| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571 |
- /*
- *********************************************************************************************************
- * uC/OS-III
- * The Real-Time Kernel
- *
- * Copyright 2009-2022 Silicon Laboratories Inc. www.silabs.com
- *
- * SPDX-License-Identifier: APACHE-2.0
- *
- * This software is subject to an open source license and is distributed by
- * Silicon Laboratories Inc. pursuant to the terms of the Apache License,
- * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
- *
- *********************************************************************************************************
- */
- /*
- *********************************************************************************************************
- * STATISTICS MODULE
- *
- * File : os_stat.c
- * Version : V3.08.02
- *********************************************************************************************************
- */
- #define MICRIUM_SOURCE
- #include "os.h"
- #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
- const CPU_CHAR *os_stat__c = "$Id: $";
- #endif
- #if (OS_CFG_STAT_TASK_EN > 0u)
- /*
- ************************************************************************************************************************
- * RESET STATISTICS
- *
- * Description: This function is called by your application to reset the statistics.
- *
- * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
- *
- * OS_ERR_NONE The call succeeded
- *
- * Returns : none
- *
- * Note(s) : none
- ************************************************************************************************************************
- */
- void OSStatReset (OS_ERR *p_err)
- {
- #if (OS_CFG_DBG_EN > 0u)
- OS_TCB *p_tcb;
- #if (OS_MSG_EN > 0u)
- OS_MSG_Q *p_msg_q;
- #endif
- #if (OS_CFG_Q_EN > 0u)
- OS_Q *p_q;
- #endif
- #endif
- CPU_SR_ALLOC();
- #ifdef OS_SAFETY_CRITICAL
- if (p_err == (OS_ERR *)0) {
- OS_SAFETY_CRITICAL_EXCEPTION();
- return;
- }
- #endif
- CPU_CRITICAL_ENTER();
- #if (OS_CFG_STAT_TASK_EN > 0u)
- OSStatTaskCPUUsageMax = 0u;
- #if (OS_CFG_TS_EN > 0u)
- OSStatTaskTimeMax = 0u;
- #endif
- #endif
- #if (OS_CFG_TS_EN > 0u) && (OS_CFG_TICK_EN > 0u)
- OSTickTime = 0u;
- OSTickTimeMax = 0u;
- #endif
- #if (OS_CFG_TMR_EN > 0u)
- #if (OS_CFG_TS_EN > 0u)
- OSTmrTaskTime = 0u;
- OSTmrTaskTimeMax = 0u;
- #endif
- #endif
- #ifdef CPU_CFG_INT_DIS_MEAS_EN
- #if (OS_CFG_TS_EN > 0u)
- OSIntDisTimeMax = 0u; /* Reset the maximum interrupt disable time */
- CPU_StatReset(); /* Reset CPU-specific performance monitors. */
- #endif
- #endif
- #if (OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u)
- OSSchedLockTimeMax = 0u; /* Reset the maximum scheduler lock time */
- #endif
- #if ((OS_MSG_EN > 0u) && (OS_CFG_DBG_EN > 0u))
- OSMsgPool.NbrUsedMax = 0u;
- #endif
- CPU_CRITICAL_EXIT();
- #if (OS_CFG_DBG_EN > 0u)
- CPU_CRITICAL_ENTER();
- p_tcb = OSTaskDbgListPtr;
- CPU_CRITICAL_EXIT();
- while (p_tcb != (OS_TCB *)0) { /* Reset per-Task statistics */
- CPU_CRITICAL_ENTER();
- #ifdef CPU_CFG_INT_DIS_MEAS_EN
- p_tcb->IntDisTimeMax = 0u;
- #endif
- #if (OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u)
- p_tcb->SchedLockTimeMax = 0u;
- #endif
- #if (OS_CFG_TASK_PROFILE_EN > 0u)
- #if (OS_CFG_TASK_Q_EN > 0u)
- p_tcb->MsgQPendTimeMax = 0u;
- #endif
- p_tcb->SemPendTimeMax = 0u;
- p_tcb->CtxSwCtr = 0u;
- p_tcb->CPUUsage = 0u;
- p_tcb->CPUUsageMax = 0u;
- p_tcb->CyclesTotal = 0u;
- p_tcb->CyclesTotalPrev = 0u;
- #if (OS_CFG_TS_EN > 0u)
- p_tcb->CyclesStart = OS_TS_GET();
- #endif
- #endif
- #if (OS_CFG_TASK_Q_EN > 0u)
- p_msg_q = &p_tcb->MsgQ;
- p_msg_q->NbrEntriesMax = 0u;
- #endif
- p_tcb = p_tcb->DbgNextPtr;
- CPU_CRITICAL_EXIT();
- }
- #endif
- #if (OS_CFG_Q_EN > 0u) && (OS_CFG_DBG_EN > 0u)
- CPU_CRITICAL_ENTER();
- p_q = OSQDbgListPtr;
- CPU_CRITICAL_EXIT();
- while (p_q != (OS_Q *)0) { /* Reset message queues statistics */
- CPU_CRITICAL_ENTER();
- p_msg_q = &p_q->MsgQ;
- p_msg_q->NbrEntriesMax = 0u;
- p_q = p_q->DbgNextPtr;
- CPU_CRITICAL_EXIT();
- }
- #endif
- *p_err = OS_ERR_NONE;
- }
- /*
- ************************************************************************************************************************
- * DETERMINE THE CPU CAPACITY
- *
- * Description: This function is called by your application to establish CPU usage by first determining how high a 32-bit
- * counter would count to in 1/10 second if no other tasks were to execute during that time. CPU usage is
- * then determined by a low priority task which keeps track of this 32-bit counter every second but this
- * time, with other tasks running. CPU usage is determined by:
- *
- * OS_Stat_IdleCtr
- * CPU Usage (%) = 100 * (1 - ------------------)
- * OS_Stat_IdleCtrMax
- *
- * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
- *
- * OS_ERR_NONE The call was successful
- * OS_ERR_OS_NOT_RUNNING If uC/OS-III is not running yet
- *
- * Returns : none
- *
- * Note(s) : none
- ************************************************************************************************************************
- */
- void OSStatTaskCPUUsageInit (OS_ERR *p_err)
- {
- OS_ERR err;
- OS_TICK dly;
- CPU_SR_ALLOC();
- err = OS_ERR_NONE; /* Initialize err explicitly for static analysis. */
- #ifdef OS_SAFETY_CRITICAL
- if (p_err == (OS_ERR *)0) {
- OS_SAFETY_CRITICAL_EXCEPTION();
- return;
- }
- #endif
- #if (OS_CFG_INVALID_OS_CALLS_CHK_EN > 0u)
- if (OSRunning != OS_STATE_OS_RUNNING) { /* Is the kernel running? */
- *p_err = OS_ERR_OS_NOT_RUNNING;
- return;
- }
- #endif
- #if ((OS_CFG_TMR_EN > 0u) && (OS_CFG_TASK_SUSPEND_EN > 0u))
- OSTaskSuspend(&OSTmrTaskTCB, &err);
- if (err != OS_ERR_NONE) {
- *p_err = err;
- return;
- }
- #endif
- OSTimeDly(2u, /* Synchronize with clock tick */
- (OS_OPT )OS_OPT_TIME_DLY,
- (OS_ERR *)&err);
- if (err != OS_ERR_NONE) {
- *p_err = err;
- return;
- }
- CPU_CRITICAL_ENTER();
- OSStatTaskCtr = 0u; /* Clear idle counter */
- CPU_CRITICAL_EXIT();
- dly = 0u;
- if (OSCfg_TickRate_Hz > OSCfg_StatTaskRate_Hz) {
- dly = (OS_TICK)(OSCfg_TickRate_Hz / OSCfg_StatTaskRate_Hz);
- }
- if (dly == 0u) {
- dly = (OSCfg_TickRate_Hz / 10u);
- }
- OSTimeDly(dly, /* Determine MAX. idle counter value */
- OS_OPT_TIME_DLY,
- &err);
- #if ((OS_CFG_TMR_EN > 0u) && (OS_CFG_TASK_SUSPEND_EN > 0u))
- OSTaskResume(&OSTmrTaskTCB, &err);
- if (err != OS_ERR_NONE) {
- *p_err = err;
- return;
- }
- #endif
- CPU_CRITICAL_ENTER();
- #if (OS_CFG_TS_EN > 0u)
- OSStatTaskTimeMax = 0u;
- #endif
- OSStatTaskCtrMax = OSStatTaskCtr; /* Store maximum idle counter count */
- OSStatTaskRdy = OS_STATE_RDY;
- CPU_CRITICAL_EXIT();
- *p_err = OS_ERR_NONE;
- }
- /*
- ************************************************************************************************************************
- * STATISTICS TASK
- *
- * Description: This task is internal to uC/OS-III and is used to compute some statistics about the multitasking
- * environment. Specifically, OS_StatTask() computes the CPU usage. CPU usage is determined by:
- *
- * OSStatTaskCtr
- * OSStatTaskCPUUsage = 100 * (1 - ------------------) (units are in %)
- * OSStatTaskCtrMax
- *
- * Arguments : p_arg this pointer is not used at this time.
- *
- * Returns : none
- *
- * Note(s) : 1) This task runs at a priority level higher than the idle task.
- *
- * 2) You can disable this task by setting the configuration #define OS_CFG_STAT_TASK_EN to 0.
- *
- * 3) You MUST have at least a delay of 2/10 seconds to allow for the system to establish the maximum value
- * for the idle counter.
- *
- * 4) This function is INTERNAL to uC/OS-III and your application should not call it.
- ************************************************************************************************************************
- */
- void OS_StatTask (void *p_arg)
- {
- #if (OS_CFG_DBG_EN > 0u)
- #if (OS_CFG_TASK_PROFILE_EN > 0u)
- OS_CPU_USAGE usage;
- OS_CYCLES cycles_total;
- OS_CYCLES cycles_div;
- OS_CYCLES cycles_mult;
- OS_CYCLES cycles_max;
- #endif
- OS_TCB *p_tcb;
- #endif
- OS_TICK ctr_max;
- OS_TICK ctr_mult;
- OS_TICK ctr_div;
- OS_ERR err;
- OS_TICK dly;
- #if (OS_CFG_TS_EN > 0u)
- CPU_TS ts_start;
- #endif
- #if (OS_CFG_STAT_TASK_STK_CHK_EN > 0u) && (OS_CFG_ISR_STK_SIZE > 0u)
- CPU_STK *p_stk;
- CPU_INT32U free_stk;
- CPU_INT32U size_stk;
- #endif
- CPU_SR_ALLOC();
- (void)p_arg; /* Prevent compiler warning for not using 'p_arg' */
- while (OSStatTaskRdy != OS_TRUE) {
- OSTimeDly(2u * OSCfg_StatTaskRate_Hz, /* Wait until statistic task is ready */
- OS_OPT_TIME_DLY,
- &err);
- }
- OSStatReset(&err); /* Reset statistics */
- dly = (OS_TICK)0; /* Compute statistic task sleep delay */
- if (OSCfg_TickRate_Hz > OSCfg_StatTaskRate_Hz) {
- dly = (OSCfg_TickRate_Hz / OSCfg_StatTaskRate_Hz);
- }
- if (dly == 0u) {
- dly = (OSCfg_TickRate_Hz / 10u);
- }
- for (;;) {
- #if (OS_CFG_TS_EN > 0u)
- ts_start = OS_TS_GET();
- #ifdef CPU_CFG_INT_DIS_MEAS_EN
- OSIntDisTimeMax = CPU_IntDisMeasMaxGet();
- #endif
- #endif
- CPU_CRITICAL_ENTER(); /* ---------------- OVERALL CPU USAGE ----------------- */
- OSStatTaskCtrRun = OSStatTaskCtr; /* Obtain the of the stat counter for the past .1 second*/
- OSStatTaskCtr = 0u; /* Reset the stat counter for the next .1 second */
- CPU_CRITICAL_EXIT();
- if (OSStatTaskCtrMax > OSStatTaskCtrRun) { /* Compute CPU Usage with best resolution */
- if (OSStatTaskCtrMax < 400000u) { /* 1 to 400,000 */
- ctr_mult = 10000u;
- ctr_div = 1u;
- } else if (OSStatTaskCtrMax < 4000000u) { /* 400,000 to 4,000,000 */
- ctr_mult = 1000u;
- ctr_div = 10u;
- } else if (OSStatTaskCtrMax < 40000000u) { /* 4,000,000 to 40,000,000 */
- ctr_mult = 100u;
- ctr_div = 100u;
- } else if (OSStatTaskCtrMax < 400000000u) { /* 40,000,000 to 400,000,000 */
- ctr_mult = 10u;
- ctr_div = 1000u;
- } else { /* 400,000,000 and up */
- ctr_mult = 1u;
- ctr_div = 10000u;
- }
- ctr_max = OSStatTaskCtrMax / ctr_div;
- OSStatTaskCPUUsage = (OS_CPU_USAGE)((OS_TICK)10000u - ((ctr_mult * OSStatTaskCtrRun) / ctr_max));
- if (OSStatTaskCPUUsageMax < OSStatTaskCPUUsage) {
- OSStatTaskCPUUsageMax = OSStatTaskCPUUsage;
- }
- } else {
- OSStatTaskCPUUsage = 0u;
- }
- OSStatTaskHook(); /* Invoke user definable hook */
- #if (OS_CFG_DBG_EN > 0u)
- #if (OS_CFG_TASK_PROFILE_EN > 0u)
- cycles_total = 0u;
- CPU_CRITICAL_ENTER();
- p_tcb = OSTaskDbgListPtr;
- CPU_CRITICAL_EXIT();
- while (p_tcb != (OS_TCB *)0) { /* ---------------- TOTAL CYCLES COUNT ---------------- */
- CPU_CRITICAL_ENTER();
- p_tcb->CyclesTotalPrev = p_tcb->CyclesTotal; /* Save accumulated # cycles into a temp variable */
- p_tcb->CyclesTotal = 0u; /* Reset total cycles for task for next run */
- CPU_CRITICAL_EXIT();
- cycles_total += p_tcb->CyclesTotalPrev; /* Perform sum of all task # cycles */
- CPU_CRITICAL_ENTER();
- p_tcb = p_tcb->DbgNextPtr;
- CPU_CRITICAL_EXIT();
- }
- #endif
- #if (OS_CFG_TASK_PROFILE_EN > 0u)
- /* ------------ INDIVIDUAL TASK CPU USAGE ------------- */
- if (cycles_total > 0u) { /* 'cycles_total' scaling ... */
- if (cycles_total < 400000u) { /* 1 to 400,000 */
- cycles_mult = 10000u;
- cycles_div = 1u;
- } else if (cycles_total < 4000000u) { /* 400,000 to 4,000,000 */
- cycles_mult = 1000u;
- cycles_div = 10u;
- } else if (cycles_total < 40000000u) { /* 4,000,000 to 40,000,000 */
- cycles_mult = 100u;
- cycles_div = 100u;
- } else if (cycles_total < 400000000u) { /* 40,000,000 to 400,000,000 */
- cycles_mult = 10u;
- cycles_div = 1000u;
- } else { /* 400,000,000 and up */
- cycles_mult = 1u;
- cycles_div = 10000u;
- }
- cycles_max = cycles_total / cycles_div;
- } else {
- cycles_mult = 0u;
- cycles_max = 1u;
- }
- #endif
- CPU_CRITICAL_ENTER();
- p_tcb = OSTaskDbgListPtr;
- CPU_CRITICAL_EXIT();
- while (p_tcb != (OS_TCB *)0) {
- #if (OS_CFG_TASK_PROFILE_EN > 0u) /* Compute execution time of each task */
- usage = (OS_CPU_USAGE)(cycles_mult * p_tcb->CyclesTotalPrev / cycles_max);
- if (usage > 10000u) {
- usage = 10000u;
- }
- p_tcb->CPUUsage = usage;
- if (p_tcb->CPUUsageMax < usage) { /* Detect peak CPU usage */
- p_tcb->CPUUsageMax = usage;
- }
- #endif
- #if (OS_CFG_STAT_TASK_STK_CHK_EN > 0u)
- OSTaskStkChk( p_tcb, /* Compute stack usage of active tasks only */
- &p_tcb->StkFree,
- &p_tcb->StkUsed,
- &err);
- #endif
- CPU_CRITICAL_ENTER();
- p_tcb = p_tcb->DbgNextPtr;
- CPU_CRITICAL_EXIT();
- }
- #endif
- /*------------------ Check ISR Stack -------------------*/
- #if (OS_CFG_STAT_TASK_STK_CHK_EN > 0u) && (OS_CFG_ISR_STK_SIZE > 0u)
- free_stk = 0u;
- #if (CPU_CFG_STK_GROWTH == CPU_STK_GROWTH_HI_TO_LO)
- p_stk = OSCfg_ISRStkBasePtr; /* Start at the lowest memory and go up */
- #if (OS_CFG_TASK_STK_REDZONE_EN > 0u)
- p_stk += OS_CFG_TASK_STK_REDZONE_DEPTH;
- size_stk = OSCfg_ISRStkSize - OS_CFG_TASK_STK_REDZONE_DEPTH;
- #else
- size_stk = OSCfg_ISRStkSize;
- #endif
- while ((*p_stk == 0u) && (free_stk < size_stk)) { /* Compute the number of zero entries on the stk */
- p_stk++;
- free_stk++;
- }
- #else
- p_stk = OSCfg_ISRStkBasePtr + OSCfg_ISRStkSize - 1u;/* Start at the highest memory and go down */
- #if (OS_CFG_TASK_STK_REDZONE_EN > 0u)
- p_stk -= OS_CFG_TASK_STK_REDZONE_DEPTH;
- size_stk = OSCfg_ISRStkSize - OS_CFG_TASK_STK_REDZONE_DEPTH;
- #else
- size_stk = OSCfg_ISRStkSize;
- #endif
- while ((*p_stk == 0u) && (free_stk < size_stk)) { /* Compute the number of zero entries on the stk */
- free_stk++;
- p_stk--;
- }
- #endif
- OSISRStkFree = free_stk;
- OSISRStkUsed = OSCfg_ISRStkSize - free_stk;
- #endif
- if (OSStatResetFlag == OS_TRUE) { /* Check if need to reset statistics */
- OSStatResetFlag = OS_FALSE;
- OSStatReset(&err);
- }
- #if (OS_CFG_TS_EN > 0u)
- OSStatTaskTime = OS_TS_GET() - ts_start; /*----- Measure execution time of statistic task -------*/
- if (OSStatTaskTimeMax < OSStatTaskTime) {
- OSStatTaskTimeMax = OSStatTaskTime;
- }
- #endif
- OSTimeDly(dly,
- OS_OPT_TIME_DLY,
- &err);
- }
- }
- /*
- ************************************************************************************************************************
- * INITIALIZE THE STATISTICS
- *
- * Description: This function is called by OSInit() to initialize the statistic task.
- *
- * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
- *
- * OS_ERR_STAT_STK_INVALID If you specified a NULL stack pointer during configuration
- * OS_ERR_STAT_STK_SIZE_INVALID If you didn't specify a large enough stack.
- * OS_ERR_STAT_PRIO_INVALID If you specified a priority for the statistic task equal to or
- * lower (i.e. higher number) than the idle task.
- * OS_ERR_xxx An error code returned by OSTaskCreate()
- *
- * Returns : none
- *
- * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
- ************************************************************************************************************************
- */
- void OS_StatTaskInit (OS_ERR *p_err)
- {
- OSStatTaskCtr = 0u;
- OSStatTaskCtrRun = 0u;
- OSStatTaskCtrMax = 0u;
- OSStatTaskRdy = OS_STATE_NOT_RDY; /* Statistic task is not ready */
- OSStatResetFlag = OS_FALSE;
- #if (OS_CFG_STAT_TASK_STK_CHK_EN > 0u) && (OS_CFG_ISR_STK_SIZE > 0u)
- OSISRStkFree = 0u;
- OSISRStkUsed = 0u;
- #endif
- /* --------------- CREATE THE STAT TASK --------------- */
- if (OSCfg_StatTaskStkBasePtr == (CPU_STK *)0) {
- *p_err = OS_ERR_STAT_STK_INVALID;
- return;
- }
- if (OSCfg_StatTaskStkSize < OSCfg_StkSizeMin) {
- *p_err = OS_ERR_STAT_STK_SIZE_INVALID;
- return;
- }
- if (OSCfg_StatTaskPrio >= (OS_CFG_PRIO_MAX - 1u)) {
- *p_err = OS_ERR_STAT_PRIO_INVALID;
- return;
- }
- OSTaskCreate(&OSStatTaskTCB,
- #if (OS_CFG_DBG_EN == 0u)
- (CPU_CHAR *)0,
- #else
- (CPU_CHAR *)"uC/OS-III Stat Task",
- #endif
- OS_StatTask,
- (void *)0,
- OSCfg_StatTaskPrio,
- OSCfg_StatTaskStkBasePtr,
- OSCfg_StatTaskStkLimit,
- OSCfg_StatTaskStkSize,
- 0u,
- 0u,
- (void *)0,
- (OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
- p_err);
- }
- #endif
|