cancel
Showing results for 
Search instead for 
Did you mean: 

Cycle Counter vs SLEEP - code correct?

LCE
Principal

Heyho,

I was just trying to check awake vs sleep in my H723 application (no OS), so I wanted to make sure that my code is okay.

It's using the cycle counter to measure all the cycles when the CPU is NOT sleeping, then compares the cycle sum to the SysTicks (1 ms).

So please have a look if I did something wrong - because I was surprised about the results.

When doing audio streaming via lwIP's TCP, it's about 50% sleeping at maximum bandwidth (~50Mbit/s), when streaming is off sleep percentage goes up to 98%.

Here's where the cycle counter is recorded:

/* +++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* MSTATE_IDLE:
 * 	CPU enters SLEEP mode to make room for DMA transfers
 */
	case MSTATE_IDLE:
	{
		#if DEBUG_CPU_TIMING
			u32CycFuncStop = DWT->CYCCNT;
			u32CycFuncSum[15] = u32CycFuncStop - u32CycFuncStrtWake;
			u64CycSumFunc[15] += (uint64_t)u32CycFuncSum[15];
			if( (u32CycFuncSum[15] > u32CycFuncMax[15]) && (u32CycFuncStrtWake != 0) )
				u32CycFuncMax[15] = u32CycFuncSum[15];
			u32CycFuncCalls[15]++;
		#endif
 
		CpuSleepMode();
 
		#if DEBUG_CPU_TIMING
			u32CycFuncStrtWake = DWT->CYCCNT;
		#endif
 
		u8MainState = MSTATE_LWIP;
		break;
	}

And here's how I get the sleep / awake percentage:

float flClockkHz = (float)HAL_RCC_GetSysClockFreq() / 1E3;
uint32_t u32TickTotal = 0;
 
u32CycTickStop = HAL_GetTick();
u32TickTotal = u32CycTickStop - u32CycTickStart;
 
...
 
/* SLEEP time / percentage, using ticks since start */
uart_printf("\n\rnot SLEEPing:\n\r");
uart_printf("SysTick since cycle start / reset = %lu ms\n\r", u32TickTotal);
flVal = (float)(u64CycSumFunc[CYC_FUNC_AWAKE] / (uint64_t)1E6);
uart_printf("u64CycSumFunc = %.3f Mega cycles\n\r", flVal);
flVal /= (float)u32TickTotal;
uart_printf("-> %.3f Mcyc/tick\n\r", flVal);
uart_printf("-> %.3f Mcyc/s\n\r", (flVal * 1000.0f));
flVal *= 1E6f;
flVal /= flClockkHz;
flVal *= 100.0f;
uart_printf("-> %.2f %% AWAKE\n\r", flVal);
uart_printf("-> %.2f %% SLEEP\n\r", (float)(100.0f - flVal));

1 ACCEPTED SOLUTION

Accepted Solutions
Piranha
Chief II

There is a critical thing missing related to interrupts. Read my posts there:

https://community.st.com/s/question/0D50X0000BxxCP2SQM/processor-load-calculation-and-perhaps-display

https://community.st.com/s/question/0D53W00001VriN4SAJ/compute-cpu-load-for-a-stm32l0-a-gpio-and-a-voltmeter

There is no necessity of arrays or floating point math. Just accumulate the load and total cycles for a second. When the total cycles reach SystemCoreClock, calculate the load percentage. The period, of course, can be chosen different and the load factor can also be expressed, for example, as a 1/10000th fractions.

In addition take note that a constant like "1E3" is a number of a double type.

View solution in original post

3 REPLIES 3
Piranha
Chief II

There is a critical thing missing related to interrupts. Read my posts there:

https://community.st.com/s/question/0D50X0000BxxCP2SQM/processor-load-calculation-and-perhaps-display

https://community.st.com/s/question/0D53W00001VriN4SAJ/compute-cpu-load-for-a-stm32l0-a-gpio-and-a-voltmeter

There is no necessity of arrays or floating point math. Just accumulate the load and total cycles for a second. When the total cycles reach SystemCoreClock, calculate the load percentage. The period, of course, can be chosen different and the load factor can also be expressed, for example, as a 1/10000th fractions.

In addition take note that a constant like "1E3" is a number of a double type.

Thanks, @Piranha​ !

... and that takes another 5% from sleep time.

Doesn't really matter, but I thought my ISRs were a little faster.