I have a hobby project using a STM32F405 MCU, which is intended to respond to a fast clock signal (~1Mhz) connected to Pin 1 of GPIOA. For every transition of the input (both rising and falling), I need to execute a short program which accesses address and data on the bus, and takes the appropriate action. The MCU is running at full speed (168 MHz), which gives me approximately 84 clock cycles to process each phase of the external clock.
I've looked into several approaches, and determined that using an Interrupt is not feasible. There is at least 24 clock cycles overhead of servicing an Interrupt, which would waste close to 30% of my available cycles.
The next approach is a polling loop, which works fine and only wastes 5-8 clocks. Basically the cycles needed to poll, plus GPIO latency as it runs at half the CPU speed. The main problem with this is jitter, as the change can happen at any point during the 5-8 clock cycles it takes to do a poll. So the result is that the response to the signal will have a jitter of up to 8 cycles (10%). This is doable, but I need to compensate to the varying jitter by burning off some more cycles using NOPs. This is needed in order to insure the response does not happen within the acceptable time frame.
However, reading a guide on interrupt latency, this guide claims that WFI or WFE can respond very quickly to an event or interrupt. The idea is to have the EXTI generate an interrupt or event (what ever works) on each transition of the external clock. Then I simply use __WFI() or __WFE() to wait for this event, and then immediately start processing. The guide I mention claims a wakeup from a WFI takes 4 cycles, but the point is that the number is consistent, giving me a very low number of wasted cycles and as little jitter as possible.
Now my problem is that I cannot make this work correctly at all. As mentioned, I do not want the ISR to be executed, so I disable all global interrupts before I start waiting.
First I tried WFI; Setting up the BASEPRI register to only let through interrupts of priority 1 (set it to value 2), and further set the priority of the EXTI interrupt in NVIC to 1. But if the interrupt is in fact generated by the GPIO when WFI is called, it does not wake up the CPU. I did a short test by setting the Systick IRQ Priority to 1, and this DOES wake it up. So it seems the EXTI interrupt signal is not working when WFI is called.
Finally, I've tried to use WFE instead, by setting up the EXTI line to generate an Event instead of an Interrupt. However, this exits immediately on the first call (apparently due to a unintended pending event?), and then hangs indefinitely on the second call. It does not respond to transitions of the GPIO pin.
So my questions are as follows:
- Has anyone successfully used WFI or WFE on this (or a similar) MCU for a similar purpose and made it work?
- The STM32F4 documentation does not provide any information about the time (clock cycles) it takes to wake up from a WFI/WFE (if it was working). So I don't even know if this will actually achieve my goal of a fast response and predictable jitter. Does anyone have any information on this?