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

Delay GPIOTE events (synchronize handling of external interrupts)

Good morning,

I am using nRF51 SDK v10.0.0 and I have to synchronize access to a hardware resource shared between two control flows. One flow is an interrupt handler invoked by GPIOTE (high accuracy, using the hardware registers). I can use nrf_drv_gpiote_in_event_enable() and nrf_drv_gpiote_in_event_disable() to enable or disable the interrupt handler.

My question is: Can I use these functions to delay the interrupt or will it be completely lost in this case? The GPIOTE driver documentation does not give any information about how to delay interrupts during critical sections.

Example:

  • nrf_drv_gpiote_in_init() is called
  • nrf_drv_gpiote_in_event_enable() is called
  • nrf_drv_gpiote_in_event_disable() called
  • interrupt is triggered on the disabled GPIOTE pin
  • nrf_drv_gpiote_in_event_enable() is called a bit later

Will the interrupt handler be invoked by GPIOTE in this scenario?

  • The interrupt handler should not be invoked in the scenario you describe.

    I do not have the full picture of your design, but there may be a few other ways of doing what you want. Maybe you could use a flag (or semaphore) to control the access to the common hardware resource? You would access this from critical sections. Moreover, when you get a interrupt which indicate that you need access to the hardware peripheral, you could set another flag if the hardware resource is busy at the time. Then you could check for that flag in your main loop, and handle it appropriately when set (and the hardware resource is available). Then, as soon as the hardware resource is available and there is time to run your main loop, you can do your processing.

  • This is not really an option... in the interrupt, we have to read time critical sensor data over SPI. Another SPI slave on the same interface is accessed from within the main() loop at several different locations, so moving this functionality into the interrupt handler is not possible (reading sensor data may also be disabled).

    Do you have information about the GPIOTE hardware device itself? How does the interrupt generation work there, and how are interrupts acknowledged? e.g. if GPIOTE.IN[0] is triggered, the interrupt handler is called and before it finishes GPIOTE.IN[1] is triggered. When the interrupt handler returns, will it be immediately called again? This way we might be able to trigger the SPI access from the main() loop by manually triggering a GPIOTE event. Is it possible to do this by writing GPIOTE.IN[] registers?

    Or is it possible to manually set the execution priority to APP_APP_IRQ_PRIORITY_LOW to prevent the GPIOTE interrupt to be triggered for a short time?

  • After some research, I decided to use the CMSIS NVIC_Enable/DisableIRQ() functions or the SETENA/CLRENA registers to disable the GPIOTE interrupt during main() SPI access. According to the Cortex M0 processor manual: "If a pending interrupt is enabled, the NVIC activates the interrupt based on its priority. If an interrupt is not enabled, asserting its interrupt signal changes the interrupt state to pending, but the NVIC never activates the interrupt, regardless of its priority." This is exactly what I need.

Related