This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

S130 GPIO Interrupt

Hi

I'm trying to catch the GPIOTE_IRQn interrupt, while the device is in system off. Not enabling the SD130 V2 the interrrupt is caught once, and then not anymore... But I'm having problems keeping it running while the softdevice is active.

I'm using the following code:

Version 1:

        static void init_wakeup_interrupt(){
    ret_code_t ret_code;
    
    ret_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(ret_code);
    
    nrf_drv_gpiote_in_config_t config =
    {
           .sense = NRF_GPIOTE_POLARITY_HITOLO,
           .pull = NRF_GPIO_PIN_NOPULL,
           .is_watcher = false,
           .hi_accuracy = false
     };
    
     nrf_drv_gpiote_in_init(13, &config, gpiote_wakeup_handler);
     nrf_drv_gpiote_in_event_enable(13, true);
}

Version 2:

    static void init_wakeup_interrupt(){

	NRF_GPIO->PIN_CNF[13] = (GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos)
							| (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
							| (GPIO_PIN_CNF_PULL_Disabled << 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_GPIOTE->CONFIG[0] = (GPIOTE_INTENSET_IN0_Set << GPIOTE_INTENSET_IN0_Pos)
							| (10 << GPIOTE_CONFIG_PSEL_Pos)
							| ((GPIOTE_CONFIG_POLARITY_HiToLo | GPIOTE_CONFIG_POLARITY_LoToHi) << GPIOTE_CONFIG_POLARITY_Pos);

	NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Set << GPIOTE_INTENSET_PORT_Pos;

//	NVIC_EnableIRQ(GPIOTE_IRQn);
	sd_nvic_SetPriority(GPIOTE_IRQn, 1);
	sd_nvic_EnableIRQ(GPIOTE_IRQn);
}

void GPIOTE_IRQHandler(void)
{
  // Event causing the interrupt must be cleared
  if ((NRF_GPIOTE->EVENTS_PORT != 0))
  {
    NRF_GPIOTE->EVENTS_PORT = 0;
  }
  // Active low.
  if (nrf_gpio_pin_read(13) == 0)
  {
	  NRF_LOG_PRINTF("GPIO >> NRF_GPIOTE_POLARITY_HITOLO : %d\r\n", 13);
  } else {
	  NRF_LOG_PRINTF("GPIO >> NRF_GPIOTE_POLARITY_LOTOHI : %d\r\n", 13);
  }
}


int main() {
	ble_stack_init();
	init_wakeup_interrupt();
}

Both cases don't work as expected...

Any help is appreciated

Parents
  • Version 1)

    to get hi_accuracy callbacks you need to set .hi_accuracy = true;
    Then instead of PORT event IN_EVENT is used which will force the HFCLK ON.

    Version2)

    1. GPIOTE->CONFIG[0] does not have any settings for GPIOTE_INTENSET_IN0_Set.

    2. PORT events are active by default you do not need to enable them. You just need to enable its interrupt if you want your ISR to be called on PORT events.

    3. You are configuing pin 13 in GPIO and pin 10 in GPIOTE? I am not sure what you are trying to do.

    4. This is very important. You are trying to read the pin inside the GPIOTE_IRQHandler. The handler itself have latency on ARM core + the interrupt forwarding mechanism by MBR and softdevice adds up the latency. So when you are reading the GPIO pin inside the handler, the state of the pin is not necessarily the same as the condition that triggered the PORT event. I would change version 2) as below

       static void init_wakeup_interrupt(){
      
       NRF_GPIO->PIN_CNF[13] = (GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos)
                               | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
                               | (GPIO_PIN_CNF_PULL_Disabled << 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_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Set << GPIOTE_INTENSET_PORT_Pos;
      

      // NVIC_EnableIRQ(GPIOTE_IRQn); sd_nvic_SetPriority(GPIOTE_IRQn, 1); sd_nvic_EnableIRQ(GPIOTE_IRQn); }

      void GPIOTE_IRQHandler(void) { // Event causing the interrupt must be cleared if ((NRF_GPIOTE->EVENTS_PORT != 0)) { NRF_GPIOTE->EVENTS_PORT = 0; NRF_LOG_PRINTF("GPIO >> LOW : %d\r\n", 13); } else { NRF_LOG_PRINTF("GPIO >> HIGH : %d\r\n", 13); } }

Reply
  • Version 1)

    to get hi_accuracy callbacks you need to set .hi_accuracy = true;
    Then instead of PORT event IN_EVENT is used which will force the HFCLK ON.

    Version2)

    1. GPIOTE->CONFIG[0] does not have any settings for GPIOTE_INTENSET_IN0_Set.

    2. PORT events are active by default you do not need to enable them. You just need to enable its interrupt if you want your ISR to be called on PORT events.

    3. You are configuing pin 13 in GPIO and pin 10 in GPIOTE? I am not sure what you are trying to do.

    4. This is very important. You are trying to read the pin inside the GPIOTE_IRQHandler. The handler itself have latency on ARM core + the interrupt forwarding mechanism by MBR and softdevice adds up the latency. So when you are reading the GPIO pin inside the handler, the state of the pin is not necessarily the same as the condition that triggered the PORT event. I would change version 2) as below

       static void init_wakeup_interrupt(){
      
       NRF_GPIO->PIN_CNF[13] = (GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos)
                               | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
                               | (GPIO_PIN_CNF_PULL_Disabled << 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_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Set << GPIOTE_INTENSET_PORT_Pos;
      

      // NVIC_EnableIRQ(GPIOTE_IRQn); sd_nvic_SetPriority(GPIOTE_IRQn, 1); sd_nvic_EnableIRQ(GPIOTE_IRQn); }

      void GPIOTE_IRQHandler(void) { // Event causing the interrupt must be cleared if ((NRF_GPIOTE->EVENTS_PORT != 0)) { NRF_GPIOTE->EVENTS_PORT = 0; NRF_LOG_PRINTF("GPIO >> LOW : %d\r\n", 13); } else { NRF_LOG_PRINTF("GPIO >> HIGH : %d\r\n", 13); } }

Children
Related