Low Jitter and Latency on signal trigger using WFI / WFE on STM32F405
It seems the concept of Events is far simpler than what I assumed from reading the documentation. It is really confusing and not very clear. An event turns out to simply be (on an STM32F4xx) a signal which can wake up the CPU from sleep. This signal is completely independent of Interrupts. You can configure any EXTI to generate an event. And that's basically it; when configured, it will wake up the MCU from WFE, and not generate an IRQ request (unless you explicitly enable EXTI IRQ as well).

So, the reason it did not work, was first that I did not fully understand how it was supposed to work. Secondly "libopencm3" enables BOTH IRQ and Events for EXTI lines (there is no way to enable one or the other), further adding to my confusion. What works is as follows:


Configure EXTI Line Source
Set EXTI Line Trigger type
Enable Event for EXTI line (do not enable EXTI IRQ nor EXTU IRQ in NVIC)
Disable Global Interrupt (Or else interrupts will also wake up WFE)
WFE


When the EXTI then triggers, the code will continue from the next line after the WFE instruction.

When it comes to speed, it was not as impressive as I hoped, but not too bad either. It seems waking up from a WFE takes approximately 12 cycles from when the event happens until I can update an output. There is a 2 cycle delay on GPIO input and output, and it takes 2 cycles to write to it (as the data is pre-loaded before the WFE call), meaning 6 cycles is used outside of the WFE call. This leaves approximately 6 cycles delay, solely due to WFE. (This is approximate, and was measured with a 40 Mhz oscilloscope).

Comparing this to a Polling Loop, the polling loop was in fact not that much faster on average. However, the Polling results in a quite noticeable jitter on the output, meaning for consistent timing the WFE approach is far superior.

Finally, according to the same guide as mentioned in the original post, it should take 12 cycles to service an interrupt. However, this figure is far from what I observe on my scope (closer to 20 cycles). In addition, a comparable number of cycles would be wasted on IRQ exit, meaning it will be both slower to respond and I can do less operations pr. trigger.