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

GPIO/GPIOTE interrupts not triggered at every event

Hi,

My goal is to generate a GPIO or GPIOTE interrupt and inside the ISR sample 8-bits from GPIO.

I tried modifying two sample projects to achieve this, the NRFX and the button projects, but I got similar results from both. I started by toggling a pin inside the ISR to check if the ISR is triggered for every event and I found that it is not happening for higher frequencies.

See some examples below of various input frequencies to the GPIOTE pin and toggling another pin in the GPIOTE_ISR.

2 MHz input signal

500 kHz input signal

100 kHz input signal

50 kHz input signal

10 kHz input signal

Is this an expected result? Can it be improved?

Thank you.

  • Also, my application requires that the pin p1.15 be the one configured to trigger the GPIOTE IN interrupts. At the NRFX example when I modified the input pin at the .overlay file I noticed that no interrupt was triggered at all. I tried modifying some values at the IRQ_CONNECT() function without any success. What should I change to generate interrupts from events at the p1.15 pin?

  • Hi,

    With high frequencies you will not have time for many instructions in the ISR before you run out of time. So without having seen your code I expect that is the problem. What is the end goal here? Doing things in SW this rapidly does not generally seem like a good idea (and if you are able to do wat you want here, you would not be able to do much else if anything as the CPU is more or less always busy handling the GPIOTE interrupts.

    Regarding using a different pin you can for instance make an overlay where you map the sw0 alias to something else, and that should work out of the box. How have you selected another pin?

  • Hi.

    With high frequencies you will not have time for many instructions in the ISR before you run out of time. So without having seen your code I expect that is the problem. What is the end goal here? Doing things in SW this rapidly does not generally seem like a good idea (and if you are able to do wat you want here, you would not be able to do much else if anything as the CPU is more or less always busy handling the GPIOTE interrupts.

    So, what is seen in the pictures above is expected and can not be improved by adjusting the configurations?

    This is how I changed the pin:

    &button0 {
        gpios = <&gpio1 15 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    };
    I noticed that if I use the preassigned pin (p0.23) the interrupt is triggered, but if I change the pin as above and connect the signal to p1.15 the GPIOTE ISR is not called.
  • I tried to change the INPUT_PIN via the .overlay file using other pins from the P0 port and the interrupt was triggered, but I couldn't trigger interrupts using any pin from the P1 port. Is there something I need to change in the project to be able to use pins from port P1 as input?

  • Ah, I did not notice this before, but the nrfx sample does not handle GPIO pins from port 1. When yo use a pin from port 1, the pin number should be 32 + the P1 pin. So for instance, P1.15 is pin 47. This is normally handled more elegantly when using the Zephyr GPIO API, but when using nrfx directly that is not the case. You can for instance to it like this, though:

    Specify the pin in an overlay file like you have before:

    &button0 {
    	gpios = <&gpio1 15 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    };

    Then you can check the port and add 32 as needed as shown in this diff from the nrfx sample in nRF Connect SDK 1.9.1:

    diff --git a/samples/boards/nrf/nrfx/src/main.c b/samples/boards/nrf/nrfx/src/main.c
    index 5c2f2a6b55..64e60d6534 100644
    --- a/samples/boards/nrf/nrfx/src/main.c
    +++ b/samples/boards/nrf/nrfx/src/main.c
    @@ -17,9 +17,10 @@
     #include <logging/log.h>
     LOG_MODULE_REGISTER(nrfx_sample, LOG_LEVEL_INF);
     
    -#define INPUT_PIN	DT_GPIO_PIN(DT_ALIAS(sw0), gpios)
     #define OUTPUT_PIN	DT_GPIO_PIN(DT_ALIAS(led0), gpios)
     
    +uint32_t m_input_pin;
    +
     static void button_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
     {
     	LOG_INF("GPIO input event callback");
    @@ -27,7 +28,15 @@ static void button_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
     
     void main(void)
     {
    -	LOG_INF("nrfx_gpiote sample on %s", CONFIG_BOARD);
    +	if (strcmp(DT_GPIO_LABEL(DT_ALIAS(sw0), gpios), "GPIO_1") == 0) {
    +		m_input_pin = 32 + DT_GPIO_PIN(DT_ALIAS(sw0), gpios);
    +	}
    +	else {
    +		m_input_pin = DT_GPIO_PIN(DT_ALIAS(sw0), gpios);
    +	}
    +
    +	LOG_INF("nrfx_gpiote sample on %s. Input pin is: %u", CONFIG_BOARD, m_input_pin);
    +
     
     	nrfx_err_t err;
     
    @@ -56,7 +65,7 @@ void main(void)
     	/* Initialize input pin to generate event on high to low transition
     	 * (falling edge) and call button_handler()
     	 */
    -	err = nrfx_gpiote_in_init(INPUT_PIN, &in_config, button_handler);
    +	err = nrfx_gpiote_in_init(m_input_pin, &in_config, button_handler);
     	if (err != NRFX_SUCCESS) {
     		LOG_ERR("nrfx_gpiote_in_init error: %08x", err);
     		return;
    @@ -77,7 +86,7 @@ void main(void)
     		return;
     	}
     
    -	nrfx_gpiote_in_event_enable(INPUT_PIN, true);
    +	nrfx_gpiote_in_event_enable(m_input_pin, true);
     	nrfx_gpiote_out_task_enable(OUTPUT_PIN);
     
     	LOG_INF("nrfx_gpiote initialized");
    @@ -100,7 +109,7 @@ void main(void)
     	 * the button is pressed, the LED pin will be toggled.
     	 */
     	nrfx_gppi_channel_endpoints_setup(channel,
    -		nrfx_gpiote_in_event_addr_get(INPUT_PIN),
    +		nrfx_gpiote_in_event_addr_get(m_input_pin),
     		nrfx_gpiote_out_task_addr_get(OUTPUT_PIN));
     
     	/* Enable (D)PPI channel. */
    

    (I have kept the output pin as is here, but you can change that as well). 

Related