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

GPIOTE Interrupt nRF51822 freezing

Hi,

I am writing a firmware for one of my custom boards which use GPIOTE to detect interrupt for 3 GPIOs inputs (P0.03, P0.06 and P0.09, both with internal pull-ups) and one pin set as an output (P0.05). Everything is working perfectly until the P0.09 pin goes low, then the device is freezing and does not respond to any interrupt.

I tried to debug this problem using RTT by asking to write a line when the P0.09 interrupt happens, but I never saw this line.

First, I initialize the gpiote module and the gpiote output on P0.05, and set it to 1 :

// Initialize the GPIOTE Peripheral
nrf_drv_gpiote_init();

// Configure P0.05 pin as output
nrf_drv_gpiote_out_config_t p5_config = GPIOTE_CONFIG_OUT_TASK_HIGH;

// Initialize P0.05 pin as output
nrf_drv_gpiote_out_init(5, &p5_config);

nrf_drv_gpiote_out_set(5);

Here as the configuration for the gpiote pins :

// Configuration for P0.06 Interrupt Pin
    nrf_drv_gpiote_in_config_t p6_config =
    {
        .sense = NRF_GPIOTE_POLARITY_LOTOHI,
        .pull = NRF_GPIO_PIN_PULLUP ,
        .is_watcher = false,
        .hi_accuracy = false
    };

    // Configuration for P0.03 Interrupt Pin
    nrf_drv_gpiote_in_config_t p3_config =
    {
        .sense = NRF_GPIOTE_POLARITY_HITOLO,
        .pull = NRF_GPIO_PIN_PULLUP ,
        .is_watcher = false,
        .hi_accuracy = false
    };

    // Configuration for the P0.09 Interrupt Pin
    nrf_drv_gpiote_in_config_t p9_config =
    {
        .sense = NRF_GPIOTE_POLARITY_HITOLO,
        .pull = NRF_GPIO_PIN_PULLUP ,
        .is_watcher = false,
        .hi_accuracy = false
    };

Then I init and enable each GPIOTE interrupt :

// Initialize P0.06 Interrupt Pin
    nrf_drv_gpiote_in_init(6, &p6_config, gpiote_evt_handler);

    // Enable Interrupts from P0.06 interrupt pin
    nrf_drv_gpiote_in_event_enable(6,true);

    // Initialize P0.03 Interrupt Pin
    nrf_drv_gpiote_in_init(3, &p3_config, gpiote_evt_handler);

    // Enable Interrupts from P0.03 interrupt pin
    nrf_drv_gpiote_in_event_enable(3,true);

    // Initialize P0.09 Interrupt Pin
    ret_code_t ret_code;
    ret_code = nrf_drv_gpiote_in_init(9, &p9_config, gpiote_evt_handler);
#if defined(NRF_LOG_USES_RTT) && (NRF_LOG_USES_RTT == 1)
    if(ret_code == NRF_SUCCESS)
			SEGGER_RTT_WriteString(0, "P0.09 GPIOTE init state : NRF_SUCCESS.\n");
    else if(ret_code == NRF_ERROR_INVALID_STATE)
			SEGGER_RTT_WriteString(0, "P0.09 GPIOTE init state : NRF_ERROR_INVALID_STATE.\n");
    else if(ret_code == NRF_ERROR_NO_MEM)
			SEGGER_RTT_WriteString(0, "P0.09 GPIOTE init state : NRF_ERROR_NO_MEM.\n");
    else
			SEGGER_RTT_printf(0, "P0.09 GPIOTE init state : %ld.\n", (uint32_t)ret_code);
#endif

    // Enable Interrupts from P0.09 interrupt pin
    nrf_drv_gpiote_in_event_enable(9,true);

With this configuration, all the GPIOs are doing perfectly their jobs excepted when the P0.09 interrupt occurs, which freezes everything. The intialization of the gpiote input for P0.09 returns NRF_SUCCESS, and the following channels are used for each GPIOTE event (returned by channel_port_alloc function during the initializiation of the gpiote pin events) :

  • P0.05 : channel 0

  • P0.06 : channel 4

  • P0.03 : channel 5

  • P0.09 : channel 6

That all the informations that seemed useful to me about this problem. I am working on a nRF51822 QFACA1, with SDK v11.0.0 and softdevice s130 nrf51 v2.0.0.

Do you have an idea of how to solve this problem ?

Best regards,

Guillaume

  • You are sure this pin is not used anywhere else in the code such that the gpio config is altered? On the DK pin P0.09 is used for uart TX, in case you are basing your code on a PCA10028 example and have not commented out uart code. To check that the gpio config is correct you can go into debug mode, stop the code when the problem happens (this will also tell you where the code is stuck), then you can check system peripherals -> gpio and the PIN_CNF[9] register. It should be the same as PIN_CNF[6] and PIN_CNF[3], except for maybe the SENSE bit.

    Does the whole device freeze or is it only the gpiote interrupt that are not working? Can you check if you encountered an error condition? Check this.

  • I set UART0_ENABLED to 0 in nrf_drv_config.h, and I excluded from build every library related to UART. Here are the different value for PIN_CNF :

    • PIN_CNF[3] = 0x0003000C
    • PIN_CNF[6] = 0x0002000C
    • PIN_CNF[9] = 0x0003000C

    So to me it fits with the configurations I sent during the initialization (Input, S0S1, pull-up, wake-up on low level).

    I tried to replace the interrupt by a timer in repeat mode with a period of 30 seconds, the same thing happens. So I think this problem is not related to the GPIOs or GPIOTE. I'll look into if I encountered an error somewhere...

  • Ole, I made a few test and I noticed that during this bug, only the gpiote interrupt and the timer are not working. The BLE works perfectly fine and I can send commands that shows that the MCU is not completely frozen when I use the gpiote interrupt, not the timer. I wonder if the code is stuck in a power_manage() function. Is it possible that it could disable the gpiote interrupt ?

  • The power_manage() function does basically the same thing as __WFE(), it puts the chip to sleep waiting for events that will wake it up. If it was stuck here nothing would work.

    My guess is that you are stuck in an interrupt at a low level. Then all interrupts at the same level or lower, including main, will not be able to execute. Interrupts at a higher level will work as usual, this will include the SoftDevice code. Check if your main code is called at all (add something after the power_manage function to indicate that this function returns).

  • Yes I noticed that the power_manage() function doesn't return in this case, but it does for BLE event, so I think you are right. But the point is that when the interrupt should occurs, an RTT command should be sent in the gpiote handler, and I have never seen this interrupt for P0.09 interrupt, but I do for P0.03 and P0.06.

Related