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

nRF52 DK GPIOTE interrupt stops working after approx 400ms after startup.

I am using SDK 15.3, SES 4.30 and softdevice 132 with the ble_app_uart_c as the core functionality for my system.

I've read many dev support threads about this issue and most seem to point to using high accuracy with GPIOTE.  I have high accuracy enabled.  Attached is my code:

// GPIOTE is used for D_TEMP_IRQ input to know when a temperature conversion is completed
void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
  nrf_gpio_pin_toggle(LED_1); // Flash the led so we know something's happening
  get_water_temp();
}

/**
 * @brief Function for configuring: PIN_IN pin for input, 
 * and configures GPIOTE to give an interrupt on pin change. */

#define PIN_IN D_TEMP_IRQ

void gpio_init(void) {
  ret_code_t err_code;
  err_code = nrf_drv_gpiote_init();
  APP_ERROR_CHECK(err_code);

  nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);   // true = high accuracy
  in_config.pull = NRF_GPIO_PIN_NOPULL;

  err_code = nrf_drv_gpiote_in_init(PIN_IN, &in_config, in_pin_handler);
  APP_ERROR_CHECK(err_code);

  d_temp_irq_enable();
}
//  Functions to enable and disable interrupts on d_temp_irq
int d_temp_irq_enable(void) {
  nrf_drv_gpiote_in_event_enable(PIN_IN, true);
//  nrf_gpio_pin_toggle(LED_2); // Flash the led so we know something's happening
  temp_probe_irq = true;
}

uint32_t d_temp_irq_disable(void) {
  nrf_drv_gpiote_in_event_disable(PIN_IN);
//  nrf_gpio_pin_toggle(LED_1); // Flash the led so we know something's happening
  temp_probe_irq = false;
}

I have an external pullup on the d_temp_irq line that is triggering the GPIOTE.  The system is consistently shutting down the GPIOTE interrupts within the approximately 400ms time period.  This is the only GPIOTE interrupt I use.

The GPIOTE is setup early in the startup sequence via gpio_init()  in main(void) code were I immediately configure the Dallas DS18B20 temperature sensor.  The sensor is working up until the 400ms time wherein the interrupt stops working.  I'm thinking that there is other code starting afterwards that is disabling the interrupt function.

Does the soft device, timers, or other BLE functions affect the GPIOTE operation?   Here's my main(void) code:

int main(void) {
  // Initialize.
  log_init();
  app_timers_init();

  uart_init();
  pins_buttons_leds_init();   
  gpio_init();                
//  pwm_init();             

//  saadc_init();               
//  saadc_sampling_event_init(); 
  perfect_shower_init();       

  db_discovery_init();
  power_management_init();
  ble_stack_init();
  gatt_init();
  nus_c_init();
  scan_init();

  // Start execution.
  printf("BLE UART central example started.\r\n");
  NRF_LOG_INFO("BLE UART central example started.");
  scan_start();

  // Enter main loop.
  for (;;) {
    idle_state_handle();
  }
}

/

I've disabled the pwm and saadc code to see if they're causing the problem... They aren't.

Parents
  • Can you search through your code if you may be calling nrf_drv_gpiote_init() somewhere else? Can you set a breakpoint shortly after init the GPIOTE module and read out the GPIOTE peripheral registers and compare when it doesn't work? Also, check out if the GPIO pin configuration may have been reconfigured by other functionality in the code.

    To view peripheral registers in breakpoints you can check out this reply (replace RADIO with GPIOTE in your case):
    https://devzone.nordicsemi.com/f/nordic-q-a/56344/dynamic-switching-of-prefixes-not-working-with-esb/229153#229153 

    Best regards,
    Kenneth

  • Hi Kenneth,

    I've attached the GPIOTE registers here:

    Register values while WORKING (first 400ms after startup)

    Register values while NOT working... (after the initial 400ms)

    GPIOTE Registers - NOT working

    I believe that I've deactivated all button functionality.  From what I can tell, there are no other calls to nrf_drv_gpiote_init().  No other calls in any other files are being linked in.

    Please advise.

  • Hi Kenneth,

    Still no resolution on my end.

    I think you can trick the system if you change line 927 to have an internal pullup, you should be able to manually trigger the gpiote interrupt with a ground wire on P0.25 on P4 of the dev board. It is set for a LoToHi transition on this pin. Also comment-out the init function void perfect_shower_init(void) at line 1255.

    In a nutshell, what I am trying to do is to run the Dallas ds18B20 temperature sensor continuously.  It takes 172ms per conversion so I can't use a delay function so I set up it's OneWire pin as an interrupt on pin P0.25.  This pin will be held low by the DS18B20 while the conversion takes place then an external pullup resistor on our board pulls it high.  (Hence the internal pullup requirement.)  When an interrupt is generated the handler goes to read the temperature probe data.  First it disables the interrupt so that when I read the probe the act of reading doesn't generate more interrupts.  After the temperature data is read then another temperature conversion is immediately initiated and the interrupt is re-enabled and I go off to do other things for another 172ms. 

    The problem is that this process stops working after about 400ms.  The last activity I see on the d_temp_irq line falls in line with my perfect_shower_init() initialization routine. After this, I never get any interrupts from the GPIOTE system.  This seems to coincide with the ble_app_uart_c functions starting up.

  • You can also set up another GPIO as an output and tie it to P0.25 to toggle the interrupt to simulate the Dallas onewire function.

  • If you do this, you will need to comment out the while statement at line 1266 that checks for the presents of Dallas part.

  • Hi Kenneth,

    I am at a standstill until this problem is resolved.  Have you had any success determining what the issue could be?  Does the Softdevice use or control any GPIOTE resources that could be changing the settings that I set up during initialization?

  • Hi,

    I have tried to look at the code.

    I think it is weird that your screenshots in https://devzone.nordicsemi.com/support-private/support/243221#permalink=533441 show PORT event and not IN event since you have used  .hi_accuracy = true 

    I recommend to single step the code in nrf_drv_gpiote_in_init() to check why it doesn't run to nrf_gpiote_event_configure() in nrfx_gpiote_in_init(). Also set in_config.skip_gpio_setup = false; in gpio_init().

    I notice you have configured many gpio's in general with sense directly (not used the nrf_drv_gpiote_in_init() to configure them and at the same time set NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS to only 1). I am not sure if this is a good idea, maybe consider using nrf_drv_gpiote_in_init() for all pins you want to wakeup with sense and with the proper number of NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS to sense the wakeup on the pins.

    I think you should enable log output from nrfx_gpiote module, I think the nrfx_gpiote_irq_handler() may be executing here when failing, the question what it may be doing.

    Also check out the pin configuration NRF_GPIO->PIN_CNF[D_TEMP_IRQ] when failing and working, to see if it has changed.

    Best regards,
    Kenneth

Reply
  • Hi,

    I have tried to look at the code.

    I think it is weird that your screenshots in https://devzone.nordicsemi.com/support-private/support/243221#permalink=533441 show PORT event and not IN event since you have used  .hi_accuracy = true 

    I recommend to single step the code in nrf_drv_gpiote_in_init() to check why it doesn't run to nrf_gpiote_event_configure() in nrfx_gpiote_in_init(). Also set in_config.skip_gpio_setup = false; in gpio_init().

    I notice you have configured many gpio's in general with sense directly (not used the nrf_drv_gpiote_in_init() to configure them and at the same time set NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS to only 1). I am not sure if this is a good idea, maybe consider using nrf_drv_gpiote_in_init() for all pins you want to wakeup with sense and with the proper number of NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS to sense the wakeup on the pins.

    I think you should enable log output from nrfx_gpiote module, I think the nrfx_gpiote_irq_handler() may be executing here when failing, the question what it may be doing.

    Also check out the pin configuration NRF_GPIO->PIN_CNF[D_TEMP_IRQ] when failing and working, to see if it has changed.

    Best regards,
    Kenneth

Children
Related