Electronic – How to use level-triggered interrupts with STM32F1xx

armcortex-m3interruptsstm32

I'm getting conflicting info on whether I can use level-triggered (as opposed to edge-triggered) interrupts with the STM32F1xx microcontroller.

In ST's CMSIS-compliant Standard Peripheral Libraries, the trigger options
are defined in enum EXTITrigger_TypeDef, which only includes EXTI_Trigger_Rising, EXTI_Trigger_Falling, and EXTI_Trigger_Rising_Falling. (no mention of level-triggered interrupts)

According to ST's help forums here and here, one well-known user says that ST only does edge-triggered interrupts.

Also, ST's RM0008 Reference Manual doesn't make mention of level-triggered interrupts.

On the other hand:

ST's PM0056 Programming Manual, Section 4.3, states that:

The NVIC supports (...) Level and pulse detection of interrupt signals

The same document, Section 4.3.9, gives more detail about level-triggered and edge-triggered interrupts.

And the official ARM documentation, Section 4.2.9 says:

A Cortex-M3 device can support both level-sensitive and pulse interrupts.
Pulse interrupts are also described as edge-triggered interrupts.
(...) A level-sensitive interrupt is held asserted until the peripheral
deasserts the interrupt signal.

However, I cannot find any way to actually set this up. I don't mind bypassing the Standard Peripheral Libraries, but I don't even see any appropriate registers to use…

I'm my specific case, I'm interfacing to another IC via SPI. It is a complex SOC, and it drives an output pin to signal that it needs attention. It communicates with it's "driver", which is hosted on the STM32. The SOC and driver want edge-triggering.

How can I configure the STM32F1xx to use level-triggered interrupts?

Best Answer

Using an STM32F407 (which appears to have a similar EXTI approach), I have in the past attacked a similar problem by using a combination of RTOS task management and edge-triggered interrupts.

The core of it was a high priority task running at high priority to service unsolicited comms from the the SoC.

The task spent most of its time blocked, waiting for a signal generated by an edge-triggered interrupt. It also timed out periodically to check whether it had missed an interrupt edge by checking the interrupt line's level, then blocked again.

If the interrupt line remained asserted after a pass of the service routine then the level check would catch that and the service routine would execute again.