2024-01-28 03:15 PM
Hi
Using FreeRTOS V11.0.1 and Stm32Cubeide 1.14.1 I was trying to read out the percentage information into the debugger. Unfortunately I don't get the expected behavior
As all of my tasks are either below 1% or at 1%, it does not seem correct.
I have followed the instructions in stm32CubeIDE user guide and if I make a call to
uxTaskGetSystemState
from the FreeRTOS API, i can calculate values that make more sense as the IDLE task now takes up about 99% of the time under no load.
Are there any other settings that needs to be fulfilled for this to work or are there any more needed configurations in FreeRTOS?
Best regards
Martin
2024-01-28 06:56 PM
How have you implemented portGET_RUN_TIME_COUNTER_VALUE and friends? A timer, is is running? What spped, what MCU?
I often use the cycle counter on M4 like so. In FreeRTOSConfig.h:
/* USER CODE BEGIN Includes */
/* Section where include file can be added */
#include "main.h"
#include "tracer.h"
#define configUSE_TRACE_FACILITY 1
#define configGENERATE_RUN_TIME_STATS 1
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() \
do { \
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; \
ITM->LAR = 0xC5ACCE55; \
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; \
} while(0)
#define portGET_RUN_TIME_COUNTER_VALUE() (DWT->CYCCNT)
#define configRECORD_STACK_HIGH_ADDRESS 1
/* USER CODE END Includes */
hth
KnarfB
2024-01-28 11:49 PM
Hi KnarfB and thanks for the reply.
I will dig in to my implementation and what I got later today. But I tested your variant, which I prefer since I dont need to assign a normal timer and have a timer update event interrupt that executes.
When I run with your code instead get this:
Which looks reasonable apart from the "CTR OVR" for the runtime.
Best regards
Martin
2024-01-29 06:28 AM
No idea, where the counter overflow comes from, maybe you have to add a
DWT->CYCCNT = 0;
in the init phase or the MCU clock is soo high (or tick rate so low)? Never seen that before.
Even if you use a timer, you don't have to implement an interrupt handler, but read pass the CNT counter register of a running timer for the "run time variable" (STM32CubeIDE user manual) directly, either at register level or wrapped by the __HAL_TIM_GET_COUNTER macro.
hth
KnarfB
2024-01-29 11:46 AM
I tested a bunch of ways forward. I failed to configure the CoreDebug clock so i went back to using TIM2 instead. My code currently looks like this.
In FreeRTOSconfig.h
#if configGENERATE_RUN_TIME_STATS == 1
#include "RuntimeStat.h"
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() RTOSSetupRuntimeCounter();
#define portGET_RUN_TIME_COUNTER_VALUE() RTOSGetRuntimeCounterValueFromISR()
#endif
Then in RuntimeStat.c
#define RUNTIME_STAT_USED_TIMER (TIM2)
void RTOSSetupRuntimeCounter() {
LL_TIM_InitTypeDef TIM_InitStruct = {0};
uint32_t timer_prescaler = 1u;
uTimerEnableBlockClock(RUNTIME_STAT_USED_TIMER, true);
uint32_t timer_block_frequency = uTimerGetBlockClock(RUNTIME_STAT_USED_TIMER);
timer_prescaler = __LL_TIM_CALC_PSC(timer_block_frequency, (10u * 1000u));
TIM_InitStruct.Prescaler = (uint16_t)(timer_prescaler);
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 0xFFFFFFFFu;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(RUNTIME_STAT_USED_TIMER, &TIM_InitStruct);
LL_TIM_EnableARRPreload(RUNTIME_STAT_USED_TIMER);
vEnableIrq(TIM2_IRQn, PRIORITY_TIM2_FREERTOS_RUNTIME_STAT);
// RTOS_RunTimeCounter = 0u;
LL_TIM_SetCounter(RUNTIME_STAT_USED_TIMER, 0u);
LL_TIM_EnableCounter(RUNTIME_STAT_USED_TIMER);
}
uint32_t RTOSGetRuntimeCounterValueFromISR(void) {
return RUNTIME_STAT_USED_TIMER->CNT;
}
Finally i have a custom debug terminal where i can print stuff From it I do this
uxArraySize = uxTaskGetNumberOfTasks();
if (uxArraySize > 0u) {
pxTaskStatusArray = pvPortMalloc(uxArraySize * sizeof(TaskStatus_t));
vTerminalPrintf("FreeRTOS Free/Total heap: %lu / %lu\r\n", xPortGetFreeHeapSize(), configTOTAL_HEAP_SIZE );
if (pxTaskStatusArray != NULL) {
// Generate raw status information about each task.
uint32_t total_runtime = 0u;
uxArraySize = uxTaskGetSystemState(pxTaskStatusArray, uxArraySize, &total_runtime);
vTerminalPrintf("%-15s\%-10s%-10s%-10s\r\n", "Taskname", "Stacksize", "Watermark", "PPM use");
for (uint8_t x = 0u; x < uxArraySize; x++) {
uint32_t runtime_promille = unsigned_divide_rounder((pxTaskStatusArray[x].ulRunTimeCounter * 1000u), total_runtime);
vTerminalPrintf("%-15s\%-10lu%-10lu%-10lu\r\n",
pxTaskStatusArray[x].pcTaskName,
uxTaskGetStackSize(pxTaskStatusArray[x].xHandle),
uxTaskGetStackHighWaterMark(pxTaskStatusArray[x].xHandle),
runtime_promille);
} // end for
vPortFree(pxTaskStatusArray);
}
} // end if there are any tasks at all.. there will always be tasks
// Now lets estimate the factor between the statistics timer and the freeRTOS tick
uint32_t stats = RTOSGetRuntimeCounterValueFromISR();
uint32_t tics = xTaskGetTickCount();
if (stats > tics) {
// as expected
vTerminalPrintf("Stats is %u, Tics %u. Stats is %u times faster\r\n",stats, tics, ((stats * 100u)/tics)/100u);
}
else {
vTerminalPrintf("Tics is %u, stats %u. Tics is %u times faster\r\n",tics, stats, ((tics * 100u)/stats)/100u);
}
When i then call this code after a few seconds of execution, i get this
FreeRTOS Free/Total heap: 4448 / 36864
Taskname Stacksize Watermark PPM use
Terminal 164 49 1
IDLE 12 19 995
Modbus 334 267 0
TaskTimer 164 133 0
Regul 186 169 1
Mounter 148 139 0
Logger 180 175 0
Flasher 3248 3233 1
Reson 124 117 1
Stats is 38515, Tics 3851. Stats is 10 times faster
(Something is off with the stack and high watermark values, I know.)
Nevertheless, the debugger still shows
This seems to be more of an stm32cubeide issue than a FreeRTOS issue.
2024-02-13 05:26 AM
2024-11-11 06:09 AM
This was broken by multicore support in FreeRTOS kernel, commit https://github.com/FreeRTOS/FreeRTOS-Kernel/commit/ae3a498e435cecdb25b889f2740ea99027dd0cb1.
Since data from uxTaskGetSystemState looks correct, most likely Cube IDE needs to adapt.