How to properly measure sleep time with DWT?

Hello everyone,

I need to measure sleep time of my Cortex-M4 processor (STM32F4xx).

I looked at DWT where I also use normal tick counter and I enabled SLEEPCNT counter.

However, I noticed that it is 8-bit register with event generation support.

Now, there is my question.

How can I know how many events was triggered with this timer if MCU sleeps for example 1 second?

Currently, I'm using like this:

before = DWT->CYCCNT; /* Read current instruction time */

__WFI(); /* Go sleep, wait interrupt */

after = DWT->CYCCNT - before; /* Get different */

The first problem I see here is that this method also measures the time when I was in interrupt and do stuff.

It would be very nice, if someone can point me to direction how to handle events from SLEEPCNT when I'm in sleep mode.

SLEEPCNT timer is working, I can get different values when I read it but it probably overlaps from 8-bits like 1000 times before MCU is awake again and I read register.

Thanks in advance.

PS: I want to create a very primitive "CPU monitor" to measure CPU load when it is active or when it sleeps.

Edit: It's funny that no one from ARM would know how to handle with their hardware. I've figure it out by now, so if anyone is interested in this, link is below.

CPU Load monitor

Parents
No Data
Reply
  • Hi,

    I went down the same rabbit hole. The DWT seems to emit events to the ITM when one of its counters overflows (I guessed based on hints in the doc)  but there seems to be no concrete documentation on that part and I found no way to get that information from the ITM.

    What could be done is to have an interrupt that has an interval < the overflow time of the counter count the overflows:

    namespace DebugCounters{
        extern uint16_t SLEEPCNTOverflowCounter;
        extern uint16_t LastSLEEPCNT;
        
        // must be called at least every 300us so that the sleepcnt can not overflow twice
        inline void SleepCounterOverflowCounter() { 
            SLEEPCNTOverflowCounter = (DWT->SLEEPCNT < LastSLEEPCNT) ? SLEEPCNTOverflowCounter+1 : SLEEPCNTOverflowCounter; 
            LastSLEEPCNT = DWT->SLEEPCNT;
        }
        
        inline uint32_t GetCycleCount(){
            return DWT->CYCCNT;
        };
        inline uint32_t GetSleepCycleCount(){
            return ((SLEEPCNTOverflowCounter*256)+DWT->SLEEPCNT)*256;
        };
    }

Children
No Data