This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to toggle the GPIO sense field?

So now that I understand the problem with overlapping asserted events on the GPIO port, I can't figure out the correct way to reset the sense field in the GPIOTE_IRQHandler correctly.

I have initialized a couple of input pins like so:


NRF_GPIO->PIN_CNF[PIN_GPIO_REED2] = 
    (GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos)
    | (NRF_GPIO_PIN_PULLUP << GPIO_PIN_CNF_PULL_Pos)
    | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
    | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);    
	
NRF_GPIO->PIN_CNF[PIN_GPIO_REED1] = 
    (GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos)
    | (NRF_GPIO_PIN_PULLUP << GPIO_PIN_CNF_PULL_Pos)
    | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
    | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);

And the interrupt handler is


void GPIOTE_IRQHandler(void)
{
    if (NRF_GPIOTE->EVENTS_PORT != 0) {
        NRF_GPIOTE->EVENTS_PORT = 0;
		
	if (!nrf_gpio_pin_read(PIN_GPIO_REED1))
	{
	    //first reed switch activated - do stuff
	}
	if (!nrf_gpio_pin_read(PIN_GPIO_REED2))
	{
	    //second reed switch activated - do other stuff
	}
		
	//I lose events if these assertions overlap
    }
}

What additions are necessary to properly toggle the sense field so that the overlapping assertions don't result in lost events?

I don't understand under what conditions each pin's sense value should be toggled appropriately.

  • For those of us that don't think the solution is immediately obvious, I'll share some code that seems to get it to behave...

    This is for a single IO. The app_gpiote code has more clever stuff that doesn't really make clear what needs to be done... at least to me. I guess an explanation is that overlapping GPIO port events cannot occur if the current pin level is the same as the current sense setting.

  • volatile bool reed2asserted = false;
    void GPIOTE_IRQHandler(void)
    {
      if (NRF_GPIOTE->EVENTS_PORT != 0)
      {
        NRF_GPIOTE->EVENTS_PORT = 0;
    	
        if (nrf_gpio_pin_read(PIN_GPIO_REED2) && reed2asserted)
        {
          nrf_gpio_pin_toggle(LED1);
          reed2asserted = !reed2asserted;
          NRF_GPIO->PIN_CNF[PIN_GPIO_REED2] = 
            (GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos)
            | (NRF_GPIO_PIN_PULLUP << GPIO_PIN_CNF_PULL_Pos)
            | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
            | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);    
        }
        else if (!nrf_gpio_pin_read(PIN_GPIO_REED2) && !reed2asserted)
        {
          nrf_gpio_pin_toggle(LED1);
          reed2asserted = !reed2asserted;
          NRF_GPIO->PIN_CNF[PIN_GPIO_REED2] = 
            (GPIO_PIN_CNF_SENSE_High << GPIO_PIN_CNF_SENSE_Pos)
            | (NRF_GPIO_PIN_PULLUP << GPIO_PIN_CNF_PULL_Pos)
            | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
            | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);    
        }
      }
    }
    
Related