Measuring CPU load
⚓ Rust 📅 2026-03-19 👤 surdeus 👁️ 2I wanted to measure the CPU utilization under embassy. I found this blog on the subject:
The loop calling executor.poll() and cortex_m::asm::wfe() worked nicely, but with one flaw:
Any interrupt that wakes up the wfe() will happen between the two calls to Instant::now() to get the time stamps, and so will be counted as idle time. I'd like to measure also any time spent in interrupt handlers. There's a later example that switches to using wfi() instead of wfe() and doing so in a critical section. The problem with that is that if the interrupt you are waiting for just happened before wfi(), you block until some later interrupt that might be some time away. This messes up all of the timers. Use of wfi() seems to be inherently racy this way and so it is not actually usable.
It seems that this is why arm has the wfe instruction. It atomically checks and clears this event flag. It seems that any waker calls the pender which for arm, issues the SEV instruction to set the event flag. That way, any interrupt that tried to wake a task that happens right before calling WFE makes it not block and you go around the loop to execute the task. WFE only blocks when no interrupt tried to wake a task during that loop. The problem is, when I try to do this within a critical section, it hangs.
I think this is because with interrupts disabled, nothing ever executes SEV to set the event flag, so WFE never wakes up. It looks like ARM has a "System Control Register" with a SEVONPEND flag that causes the interrupt to set the event flag, even though it only becomes pending and is blocked by the critical section. This looks like it should solve my problem, but I don't see this register in the cortex_m crate, so how do I set this flag?
1 post - 1 participant
🏷️ Rust_feed