Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

GPIOET interrupt and PPI in S110

Hi,

I want to measure the time of two signals to calculate the speed and sent the data with BLE.  I find the SD effect the GPIOTE_interrupt sometimes, when I try to use GPIOTE and timer to calcluate the time . So I use the PPI function, connect the NRF_GPIOTE->EVENTS_IN[ ] to the NRF_TIMER2->TASKS.  But the program can not boot up with PPI and  GPIOTE_interrupt and SD.  I debugged the program. Looks it go to the "System Reset".   

If I use PPI and GPIOTE interrupt without BLE SD, it works well. I can measure the time accurately.   If I use PPI with SD and disable the interrupt, it works well. If I use the GPIOTE interrupt with SD and disable the PPI, it works well too.  

void time1_init(void)  
{

    NRF_TIMER2->MODE        = TIMER_MODE_MODE_Timer;	
    NRF_TIMER2->PRESCALER   = 4;  
    NRF_TIMER2->CC[2]       = (50000U);  
    NRF_TIMER2->INTENSET    = TIMER_INTENSET_COMPARE2_Enabled << TIMER_INTENSET_COMPARE2_Pos;		
    NRF_TIMER2->SHORTS      = (TIMER_SHORTS_COMPARE2_CLEAR_Enabled << TIMER_SHORTS_COMPARE2_CLEAR_Pos);
		NVIC_ClearPendingIRQ(TIMER2_IRQn);			
    NVIC_SetPriority(TIMER2_IRQn,3);				
		NVIC_EnableIRQ(TIMER2_IRQn);  					
	//  NRF_TIMER2->TASKS_START = 1; 
}

 void ppi_init(void)
{
    // Configure PPI channel 0 to start Timer 2 
    NRF_PPI->CH[0].EEP = (uint32_t)(&NRF_GPIOTE->EVENTS_IN[0]);
		NRF_PPI->CH[0].TEP = (uint32_t)(&NRF_TIMER2->TASKS_START);

    // Configure PPI channel 1 to capture Timer2
    NRF_PPI->CH[1].EEP = (uint32_t)(&NRF_GPIOTE->EVENTS_IN[1]);
    NRF_PPI->CH[1].TEP = (uint32_t)(&NRF_TIMER2->TASKS_CAPTURE[0]);

    // Enable only PPI channels 0 and 1.
    NRF_PPI->CHEN = (PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos) | (PPI_CHEN_CH1_Enabled << PPI_CHEN_CH1_Pos);
}

void EXIT_KEYS_Init(void)
{

		nrf_gpio_cfg_input(S1,GPIO_PIN_CNF_PULL_Pullup);
		nrf_gpio_cfg_input(S2,GPIO_PIN_CNF_PULL_Pullup);
//		NVIC_SetPriority(GPIOTE_IRQn,1);

	
    NRF_GPIOTE->CONFIG[0] =  (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)	
                           | (S1 << GPIOTE_CONFIG_PSEL_Pos)  																
                           | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);					
		NRF_GPIOTE->CONFIG[1] =  (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)
                           | (S2 << GPIOTE_CONFIG_PSEL_Pos)  
                           | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);

         NVIC_EnableIRQ(GPIOTE_IRQn);   //must disable GPIOTE interrupt or PPI
		NRF_GPIOTE->INTENSET  = GPIOTE_INTENSET_IN0_Set << GPIOTE_INTENSET_IN0_Pos;
		NRF_GPIOTE->INTENSET  = GPIOTE_INTENSET_IN1_Set << GPIOTE_INTENSET_IN1_Pos;
}

int main(void)
{
	
	uint16_t speeds;

	time1_init(); 
	EXIT_KEYS_Init(); 
	ppi_init();
    // Initialize
    leds_init();
    timers_init();
    buttons_init();
    uart_init();
	
    ble_stack_init();
    gap_params_init();
    services_init();
    advertising_init();
    conn_params_init();
    sec_params_init();
    
    simple_uart_putstring(START_STRING);	
    
    advertising_start();
	  LED_Init();
		capture_state=1;

    for (;;)
    {........}
}

I use the example  S110 \experimental\ble_app_uart. 

SofeDevices: S110  6.0.0

Board: PCA10001

IC: nRF51822 xxaa

Any idea about it? 

Parents
  • As Turbo said, you have to use the API's to assign and enable/disable PPI channels.  The SD uses PPI and thus will write over your settings.  You can set gpiote directly through the register if you wish.

    These are some of the API's.  You would find them all listed in the SD reference docs.

     sd_ppi_channel_assign
     sd_ppi_channel_enable_set
           

    You will find the PPI reserved channels on page 169 of the product spec.

  • When I send signals to the pins,  I can get the datas that I want. But  then the bluetooth will disconnect , if the phone connect the board with BLE. And I cannot connect again. Looks the GPIOTE interrupt that I add in the GPIOTE_IRQHandle in the nrf_drv_gpiote.c  cause the SD run out.  How should I use the GPIOTE interrupt  and does not affect the SD to run??

    void GPIOTE_IRQHandler(void)
    {
        uint32_t status = 0;
        uint32_t input = 0;
    //I add the GPIOTE IN[0]and[1]
    		if ((NRF_GPIOTE->EVENTS_IN[0] == 1) && (NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN0_Msk))
        {
            NRF_GPIOTE->EVENTS_IN[0] = 0; //ÖжÏʼþÇåÁã.
    				if(capture_state==1)
    				{
    					  NRF_PPI->CHENCLR = (PPI_CHEN_CH4_Enabled << PPI_CHEN_CH4_Pos) ;
    					capture_state=2; 
    					nrf_gpio_pin_clear(20); 
    				}		
    	   }
    		
    		 if ((NRF_GPIOTE->EVENTS_IN[1] == 1) && (NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN1_Msk))
        {
    				
            NRF_GPIOTE->EVENTS_IN[1] = 0; //ÖжÏʼþÇåÁã.
    				if(capture_state==2)
    				{	
    					 NRF_PPI->CHENCLR = (PPI_CHEN_CH5_Enabled << PPI_CHEN_CH5_Pos) ;
    					NRF_TIMER2->TASKS_CAPTURE[0] = 1;
    					shoot_flag=1;						
    	//				capture_time= NRF_TIMER2->CC[0];
    					nrf_gpio_pin_clear(20);
    					lock_time=10; 
    					capture_state=3;
    					NRF_TIMER2->TASKS_START = 1;					
    				}
    	//		  NRF_TIMER2->TASKS_STOP = 1;		//Í£Ö¹¶¨Ê±Æ÷
    	//		NRF_TIMER2->TASKS_CAPTURE[0] = 1;		//²¶×½ÈÎÎñ
    	//		capture_time= NRF_TIMER2->CC[0];		//»ñµÃʱ¼ä		
    	    }
    			if(capture_state==3) lock_time=10;
    //the end of my code
    
        /* collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/
        uint32_t i;
        
        //I modified the events 0-3 to 2-3
       nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_IN_2;// nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_IN_0;			//´Óʼþ0¿ªÊ¼
        uint32_t mask = (uint32_t)NRF_GPIOTE_INT_IN2_MASK;//uint32_t mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;			//ÖжÏ0±ê־λ mask±êÖ¾£¬ÆðʼµÄµØÖ·
        for (i = 2; i < NUMBER_OF_GPIO_TE; i++)//for (i = 2; i < NUMBER_OF_GPIO_TE; i++)						//0-4
        {
            if (nrf_gpiote_event_is_set(event) && nrf_gpiote_int_is_enabled(mask))			//Èç¹ûʼþÒѾ­ÉèÖã¬ÖжÏʹÄÜ£¬Çå³ý±êÖ¾£¬×´Ì¬¼Ç¼ÄÇЩÉ趨ÁËʼþ
            {
                nrf_gpiote_event_clear(event);
                status |= mask;
            }
            mask <<= 1;
            /* Incrementing to next event, utilizing the fact that events are grouped together
             * in ascending order. */
           event = (nrf_gpiote_events_t)((uint32_t)event + sizeof(uint32_t));		//ʼþµØÖ·ÒÆÎ»
        }
    
        /* collect PORT status event, if event is set read pins state. Processing is postponed to the
         * end of interrupt. */
        if (nrf_gpiote_event_is_set(NRF_GPIOTE_EVENTS_PORT))		//Èç¹û¶Ë¿ÚʼþÉ趨
        {
            nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);			//Çå³ý
            status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK;				//״̬¼Ç¼
            input = nrf_gpio_pins_read();												//Òý½Å¶ÁÈ¡
        }
    
        // Process pin events. 
        if (status & NRF_GPIOTE_INT_IN_MASK)										//ÖжÏÊäÈë±êÖ¾ÓëÖжÏÊäÈë±êÖ¾½øÐбȽϣ¬Èç¹ûÓÐÊäÈë±êÖ¾
        {
            mask = (uint32_t)NRF_GPIOTE_INT_IN2_MASK;//mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;						//´ÓIN0µÄÖжϿªÊ¼£¬ÂÖѯ4´Î
            for (i = 2; i < NUMBER_OF_GPIO_TE; i++)//for (i = 0; i < NUMBER_OF_GPIO_TE; i++)
            {
                if (mask & status)															//Èç¹ûÖжϱêÖ¾ºÍʹÄÜ״̬
                {
                    nrf_drv_gpiote_pin_t pin = nrf_gpiote_event_pin_get(i);				//		¶ÁÈ¡GPIOTE[i]¶ÔÓ¦µÄÊÇÄĸöÒý½Å
                    nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(i);			//  ¶ÁÈ¡GPIOTE[i]ÉèÖõÄÊÇʲô¼«ÐÔ 
                    nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(i);					//m_cb.handlers[channel]
                    handler(pin,polarity);											//´¦ÀíÒý½Å£¬¼«ÐÔ  
                }
                mask <<= 1;																			//ÒÆÎ»£¬´¦ÀíÏÂÒ»¸ö
            }
        }
    
        if (status & (uint32_t)NRF_GPIOTE_INT_PORT_MASK)				//Åж϶˿ڱêÖ¾ÊÇ·ñʹÄÜ
        {
            // Process port event. 												//´¦Àí¶Ë¿Úʼþ
            for (i = 0; i < GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++)
            {
                if (m_cb.port_handlers_pins[i] != PIN_NOT_USED)
                {
                    uint8_t pin_and_sense = m_cb.port_handlers_pins[i];
                    nrf_drv_gpiote_pin_t pin = (pin_and_sense & ~SENSE_FIELD_MASK);
                    nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(channel_port_get(pin));
                    if (handler)
                    {
                        nrf_gpiote_polarity_t polarity =
                                (nrf_gpiote_polarity_t)((pin_and_sense & SENSE_FIELD_MASK) >> SENSE_FIELD_POS);
                        mask = 1 << pin;
                        nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin);
                        if (((mask & input) && (sense==NRF_GPIO_PIN_SENSE_HIGH)) ||
                           (!(mask & input) && (sense==NRF_GPIO_PIN_SENSE_LOW))  )
                        {
                            if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
                            {
                                nrf_gpio_pin_sense_t next_sense = (sense == NRF_GPIO_PIN_SENSE_HIGH) ?
                                        NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
                                nrf_gpio_cfg_sense_set(pin, next_sense);
                            }
                            handler(pin, polarity);
                        }
                    }
                }
            }
        }
    }

  • So to be clear, what you are saying is that you are getting the correct timing values now but the SD stops working, correct?

    So I don't have to read through your code and guess, how many gpiote ISR's are you generating per second?

Reply Children
No Data
Related