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

Parents
  • 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.

Reply
  • 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.

Children
No Data
Related