cancel
Showing results for 
Search instead for 
Did you mean: 

Untimely wakeup during WFE on stm32g431.

treguy
Associate

I have a project in which I try to sync my assembly code on a signal on a GPIO, using WFE for minimum latency and jitter.
I use a Rust HAL ony for initialisation of the clock and to put some GPIOs into input mode, and one in output mode that I use to check the timings of my assembly code with an oscilloscope.

The synchronization works (PA15 in input mode, using EXTI line 15 to send the wake-up event), but the WFE also wakes up at regular interval. Apparently every second when no debuger is connected, and maybe a bit slower when openocd / gdb is connected.

I try to understand why it does wake-up, but really can't find anything. Here are the sources of wake-up I checked:

- Interruptions:
SEVONPEND is zero

(gdb) x/t 0xE000ED10
0xe000ed10:	00000000000000000000000000000000

and if I replace the stack with $AAAAAAAAs, I see no trace of an interruption being called when the core wakes up.

- Event on EXTI lines:
EXTI_EMR1 and EXTI_EMR2 only activate Px15

(gdb) x/t 0x40010404
0x40010404:	00000000000000001000000000000000
(gdb) x/t 0x40010424
0x40010424:	00000000000000000000000000000000

and if I set EXTI_EMR1 to 0x0, the code no longer wakes up on PA15 transitions but continues to wake up regularly every second

- SEV instruction executed by other core
the stm32g431 has only one core

I know WFE is not guaranteed to not continue when no event is raised, but is there a way to understand why it does ?

thank you

3 REPLIES 3
treguy
Associate

Ok, I found the answer :

- "next" gdb command passes* a WFE, so testing with a debug interface is not the way to go
- handler being call in "handler mode" they use a different stack pointer than "thread mode" so it leave no trace on the thread mode stack.
- putting a breakpoint on every handler helped.

* : in one configuration it did, I don't know what I did. Probably disabling the debugger before the WFE and re-enabling it after would have helped.

Now  the only thing I sitll do not understand  is that this code :

 
wfe
str r0, [r1, #(GPIOB_OFFSET + GPIOx_ODR_OFFSET)]

works, has only a 1 cycle jitter (way better than the 5 cycle using the loop), BUT I see the signal rise on the GPIO only 10 cycles after the event I wait for. From what I currently understand, WFE should exit one cycle after the event and STR should take 3 cycles.

I guess the event take some time to be raised, maybe also the pipeline needs to be reloaded after the WFE, but have not found the information in the reference manuals yet.

TDK
Super User

Writes are not instant. There is a bus which carries data through the system to where it needs to go, in this case it needs to go from the CPU to AHB2 where the GPIOs are. This takes more time. When the write actually occurs, the CPU is processing other instructions. Use DSB to enforce barriers between writes if it is important that X happens before Y.

TDK_0-1767456990463.png

Having the debugger active at the same time can also disrupts timing within the system.

Toggling pins with the CPU is not a good way to get precise timing. There are a variety of peripherals such as SPI or TIM that can do this with tick-level precision.

If you feel a post has answered your question, please click "Accept as Solution".
Hateemfatima
Associate

It sounds like you’re seeing periodic WFE wakeups from a stray event source—likely the DWT/ITM, SysTick, or a debug-related event still enabled even when no interrupt fires. Double‑check SysTick, DBGMCU settings, and any peripherals that can generate events without interrupts.