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

  • So something is happening when you get interrupt for P0.09 that is blocking all other interrupts at that level and below. If you increase the interrupt priority to APP_PRIORITY_HIGH you should see that the the BLE event also does not show. Could you verify this?

    I am not sure how I can help you further without having a look at your code.

  • I set it the priority of gpiote level to APP_IRQ_PRIORITY_HIGH, and the BLE is still working (I see BLE_GAP_EVT_CONNECTED and BLE_GAP_EVT_DISCONNECTED, and also read and write requests). But I noticed something interesting : The interrupt on P0.09 is active when the pin is low, and then the problem described above happens. But on a BLE disconnection event, I send an I2C command to a IC that sets the P0.09 high, and then the other interrupts are working even if the disconnection comes after the interrupt, and they works until P0.09 goes low again. So it seems to be link to the fact that P0.09 is low, but I can't understand why. In you opinion what piece of my code is missing to permit you to help me further ?

  • Can you try to set the accuracy to high on P0.09:

    .hi_accuracy = true
    

    And see if you still have the same problem?

  • I tried it and the problem disappears with this configuration. But unfornutately the power consumption of the device is way too high in this case (about 1mA during advertising, 1.25mA connected). According to this result, do you know a solution which permit me to keep .hi_accuracy = false ?

  • I totally understand that it is not acceptable to have that high current consumption, this was just to narrow down the possible causes for the problem.

    I think I know what is the cause of the problem now. It is probably in how the sense and port event mechanism works. As described in the Reference Manual chapter 14 - GPIO, each pin has a separate DETECT signal that is set high when the pin sense the correct level. All DETECT signals are combined into a common DETECT signal that is used to trigger the PORT event. When using .hi_accuracy = false this mechanism is used. The problem is that the DETECT signal is not cleared unless no pins are sensing the correct level. This is why it works after you set the P0.09 pin manually to high and not before.

    I thought the gpiote driver had a way of avoiding this, but after checking more thoroughly this is only the case if the sense is set to NRF_GPIOTE_POLARITY_TOGGLE. Then the sense bit will be flipped in the interrupt, thereby clearing the DETECT signal for that pin.

    One way to fix your problem is to configure the sense to NRF_GPIOTE_POLARITY_TOGGLE, but then you need to check in some way if the pin went from high to low or low to high. You can do this by checking the pin input value with nrf_gpio_pin_read(uint32_t pin_number).

    I will talk to the developers if we can improve the gpiote driver such that this is not a problem in the future.

Related