Is there a simple example of how to enable two GPIOTE interrupts for fast timing?

I would like to monitor the states of switches sw0 and sw1 on my nrf7002dk board using GPIOTE interrupts.

Initially this is just for example purposes.

I eventually need to assign two other GPIO pins where I need to have the ability to time ~30 microsecond accuracy and I am finding that the standard Zephyr PORT interrupts not fast enough for my timing purposes.

The nrfx example that I looked at assigns just one GPIOTE pin and I am having difficulty assigning another pin. Specifically when it comes time to IRQ_CONNECT and nrfx_gpiote_in_init the second GPIO pin.

Thank you.

Parents
  • Hello,

    I've created an example that uses GPIOTE with 2 input pins. Please see attached. I may be able to expand this sample if you could describe what you are trying to monitor. Is it a signal input you want to measure on each pin as discussed in this thread:  GPIOTE + PPI SDK v2.5.2 issue + zephyr ? If so, you may need to use TIMER+PPI to accurately time signal periods.

    The Zephyr GPIO API also supports use IN events instead of PORT events if you change the triggering flag from *_LEVEL_* to _EDGE_ triggering. 

    Test sample

    hello_world_gpiote.zip

    Best regards,

    Vidar

  • Thank you Vidar.

    That example worked perfectly!

    To expand on this, I did try to use Zephyr GPIO _EDGE_ triggering in combination with the Zephyr timing functions in my pin event handlers (ie. timing_init, timing_start, timing_counter_get, timing_cycles_get), but found the values I was getting sometimes inconsistent as compared to the edge to edge times on my oscilloscope.

    Is this the wrong approach?

    Ultimately I would like to monitor the pulse widths on 4 GPIO pins where the widths can be as lows as 30 microseconds.

    Perhaps I need to move to timing with PPI. Is there an example of using PPI to get accurate GPIO edge to edge timing?

    Thanks again,

    Adam

  • Thank you Vidar,

    I switched to using GPIOTE and NRFX_GPIOTE_TRIGGER_LOTOHI for that pin and now I am seeing the correct number of low to high edges for 135KHz for roughly 2 seconds of counting.

    uart:~$ start
    started: 1970/01/01 00:00:09 UTC
    uart:~$ stop
    stopped: 1970/01/01 00:00:11 UTC
    rising_edges: 288872
    falling_edges: 0

    Clearly GPIO interrupts have too much latency.

    However, I need to capture LOTOHI and HITOLO edges and then read the timer on every interrupt. Is this also possible?

    If I change the trigger to NRFX_GPIOTE_TRIGGER_TOGGLE how will I know which edge is causing the interrupt? I suspect that calling nrfx_gpiote_in_is_set( pin ) in the pin event handler will not work.

    Best regards,

    Adam

  • Hi Adam,

    The latency will also increase as you start adding adding more signal inputs, so I think your best option may be to disable the GPIOTE interrupt after the first event. Then, use the GPIO HALs to read the pin states in a loop until the transfer is complete. The polling should happen outside of the interrupt context if you need to sample for longer periods to avoid blocking other parts of the app.

    Best regards,

    Vidar

  • Hi. I have similar problem, I try to do autobaud for my uart. I have to measure low level signal, so I need to use NRFX_GPIOTE_TRIGGER_TOGGLE. Is it possible to configure timer using PPI to start (capture) on falling edge and stop (capture) on rising?
    Best regards,
    PW  
         

  • Hi,

    You need to connect two input pins to detect raising and falling edge, where one channel is configured to detect falling edge, and the other to detect rising edge. This is because a pin can only be assigned to one GPIOTE channel at a time. Failing to do so may result in unpredictable behavior.

    The TOGGLE event will trigger on any change (falling or rising) and can still be used to measure the frequency.

Reply Children
No Data
Related