os_stat.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. /*
  2. ************************************************************************************************************************
  3. * uC/OS-III
  4. * The Real-Time Kernel
  5. *
  6. * (c) Copyright 2009-2011; Micrium, Inc.; Weston, FL
  7. * All rights reserved. Protected by international copyright laws.
  8. *
  9. * STATISTICS MODULE
  10. *
  11. * File : OS_STAT.C
  12. * By : JJL
  13. * Version : V3.02.00
  14. *
  15. * LICENSING TERMS:
  16. * ---------------
  17. * uC/OS-III is provided in source form for FREE short-term evaluation, for educational use or
  18. * for peaceful research. If you plan or intend to use uC/OS-III in a commercial application/
  19. * product then, you need to contact Micrium to properly license uC/OS-III for its use in your
  20. * application/product. We provide ALL the source code for your convenience and to help you
  21. * experience uC/OS-III. The fact that the source is provided does NOT mean that you can use
  22. * it commercially without paying a licensing fee.
  23. *
  24. * Knowledge of the source code may NOT be used to develop a similar product.
  25. *
  26. * Please help us continue to provide the embedded community with the finest software available.
  27. * Your honesty is greatly appreciated.
  28. *
  29. * You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
  30. ************************************************************************************************************************
  31. */
  32. #include <os.h>
  33. #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
  34. const CPU_CHAR *os_stat__c = "$Id: $";
  35. #endif
  36. #if OS_CFG_STAT_TASK_EN > 0u
  37. /*
  38. ************************************************************************************************************************
  39. * RESET STATISTICS
  40. *
  41. * Description: This function is called by your application to reset the statistics.
  42. *
  43. * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
  44. *
  45. * OS_ERR_NONE
  46. *
  47. * Returns : none
  48. ************************************************************************************************************************
  49. */
  50. void OSStatReset (OS_ERR *p_err)
  51. {
  52. #if (OS_CFG_DBG_EN > 0u)
  53. OS_TCB *p_tcb;
  54. #if (OS_MSG_EN > 0u)
  55. OS_MSG_Q *p_msg_q;
  56. #endif
  57. #if (OS_CFG_Q_EN > 0u)
  58. OS_Q *p_q;
  59. #endif
  60. CPU_SR_ALLOC();
  61. #endif
  62. #ifdef OS_SAFETY_CRITICAL
  63. if (p_err == (OS_ERR *)0) {
  64. OS_SAFETY_CRITICAL_EXCEPTION();
  65. return;
  66. }
  67. #endif
  68. #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
  69. OSIntQTaskTimeMax = (CPU_TS )0; /* Reset the task execution times */
  70. OSIntQMaxNbrEntries = (OS_OBJ_QTY)0; /* Reset the queue maximum number of entries */
  71. #endif
  72. #if OS_CFG_STAT_TASK_EN > 0u
  73. OSStatTaskTimeMax = (CPU_TS)0;
  74. #endif
  75. OSTickTaskTimeMax = (CPU_TS)0;
  76. #if OS_CFG_TMR_EN > 0u
  77. OSTmrTaskTimeMax = (CPU_TS)0;
  78. #endif
  79. #ifdef CPU_CFG_INT_DIS_MEAS_EN
  80. OSIntDisTimeMax = (CPU_TS)0; /* Reset the maximum interrupt disable time */
  81. #endif
  82. #if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
  83. OSSchedLockTimeMax = (CPU_TS)0; /* Reset the maximum scheduler lock time */
  84. #endif
  85. #if OS_CFG_DBG_EN > 0u
  86. p_tcb = OSTaskDbgListPtr;
  87. while (p_tcb != (OS_TCB *)0) { /* Reset per-Task statistics */
  88. CPU_CRITICAL_ENTER();
  89. #ifdef CPU_CFG_INT_DIS_MEAS_EN
  90. p_tcb->IntDisTimeMax = (CPU_TS )0;
  91. #endif
  92. #if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
  93. p_tcb->SchedLockTimeMax = (CPU_TS )0;
  94. #endif
  95. #if OS_CFG_TASK_PROFILE_EN > 0u
  96. #if OS_CFG_TASK_Q_EN > 0u
  97. p_tcb->MsgQPendTimeMax = (CPU_TS )0;
  98. #endif
  99. p_tcb->SemPendTimeMax = (CPU_TS )0;
  100. p_tcb->CtxSwCtr = (OS_CTR )0;
  101. p_tcb->CPUUsage = (OS_CPU_USAGE)0;
  102. p_tcb->CyclesTotal = (OS_CYCLES )0;
  103. p_tcb->CyclesTotalPrev = (OS_CYCLES )0;
  104. p_tcb->CyclesStart = OS_TS_GET();
  105. #endif
  106. #if OS_CFG_TASK_Q_EN > 0u
  107. p_msg_q = &p_tcb->MsgQ;
  108. p_msg_q->NbrEntriesMax = (OS_MSG_QTY )0;
  109. #endif
  110. p_tcb = p_tcb->DbgNextPtr;
  111. CPU_CRITICAL_EXIT();
  112. }
  113. #endif
  114. OS_TickListResetPeak(); /* Reset tick wheel statistics */
  115. #if OS_CFG_TMR_EN > 0u
  116. OS_TmrResetPeak();
  117. #endif
  118. #if (OS_CFG_Q_EN > 0u) && (OS_CFG_DBG_EN > 0u)
  119. p_q = OSQDbgListPtr;
  120. while (p_q != (OS_Q *)0) { /* Reset message queues statistics */
  121. CPU_CRITICAL_ENTER();
  122. p_msg_q = &p_q->MsgQ;
  123. p_msg_q->NbrEntriesMax = (OS_MSG_QTY)0;
  124. p_q = p_q->DbgNextPtr;
  125. CPU_CRITICAL_EXIT();
  126. }
  127. #endif
  128. *p_err = OS_ERR_NONE;
  129. }
  130. /*$PAGE*/
  131. /*
  132. ************************************************************************************************************************
  133. * DETERMINE THE CPU CAPACITY
  134. *
  135. * Description: This function is called by your application to establish CPU usage by first determining how high a 32-bit
  136. * counter would count to in 1/10 second if no other tasks were to execute during that time. CPU usage is
  137. * then determined by a low priority task which keeps track of this 32-bit counter every second but this
  138. * time, with other tasks running. CPU usage is determined by:
  139. *
  140. * OS_Stat_IdleCtr
  141. * CPU Usage (%) = 100 * (1 - ------------------)
  142. * OS_Stat_IdleCtrMax
  143. *
  144. * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
  145. *
  146. * OS_ERR_NONE
  147. *
  148. * Returns : none
  149. ************************************************************************************************************************
  150. */
  151. void OSStatTaskCPUUsageInit (OS_ERR *p_err)
  152. {
  153. OS_ERR err;
  154. OS_TICK dly;
  155. CPU_SR_ALLOC();
  156. #ifdef OS_SAFETY_CRITICAL
  157. if (p_err == (OS_ERR *)0) {
  158. OS_SAFETY_CRITICAL_EXCEPTION();
  159. return;
  160. }
  161. #endif
  162. OSTimeDly((OS_TICK )2, /* Synchronize with clock tick */
  163. (OS_OPT )OS_OPT_TIME_DLY,
  164. (OS_ERR *)&err);
  165. if (err != OS_ERR_NONE) {
  166. *p_err = err;
  167. return;
  168. }
  169. CPU_CRITICAL_ENTER();
  170. OSStatTaskCtr = (OS_TICK)0; /* Clear idle counter */
  171. CPU_CRITICAL_EXIT();
  172. dly = (OS_TICK)0;
  173. if (OSCfg_TickRate_Hz > OSCfg_StatTaskRate_Hz) {
  174. dly = (OS_TICK)(OSCfg_TickRate_Hz / OSCfg_StatTaskRate_Hz);
  175. }
  176. if (dly == (OS_TICK)0) {
  177. dly = (OS_TICK)(OSCfg_TickRate_Hz / (OS_RATE_HZ)10);
  178. }
  179. OSTimeDly(dly, /* Determine MAX. idle counter value */
  180. OS_OPT_TIME_DLY,
  181. &err);
  182. CPU_CRITICAL_ENTER();
  183. OSStatTaskTimeMax = (CPU_TS)0;
  184. OSStatTaskCtrMax = OSStatTaskCtr; /* Store maximum idle counter count */
  185. OSStatTaskRdy = OS_STATE_RDY;
  186. CPU_CRITICAL_EXIT();
  187. *p_err = OS_ERR_NONE;
  188. }
  189. /*$PAGE*/
  190. /*
  191. ************************************************************************************************************************
  192. * STATISTICS TASK
  193. *
  194. * Description: This task is internal to uC/OS-III and is used to compute some statistics about the multitasking
  195. * environment. Specifically, OS_StatTask() computes the CPU usage. CPU usage is determined by:
  196. *
  197. * OSStatTaskCtr
  198. * OSStatTaskCPUUsage = 100 * (1 - ------------------) (units are in %)
  199. * OSStatTaskCtrMax
  200. *
  201. * Arguments : p_arg this pointer is not used at this time.
  202. *
  203. * Returns : none
  204. *
  205. * Note(s) : 1) This task runs at a priority level higher than the idle task.
  206. *
  207. * 2) You can disable this task by setting the configuration #define OS_CFG_STAT_TASK_EN to 0.
  208. *
  209. * 3) You MUST have at least a delay of 2/10 seconds to allow for the system to establish the maximum value
  210. * for the idle counter.
  211. *
  212. * 4) This function is INTERNAL to uC/OS-III and your application should not call it.
  213. ************************************************************************************************************************
  214. */
  215. void OS_StatTask (void *p_arg)
  216. {
  217. #if OS_CFG_DBG_EN > 0u
  218. #if OS_CFG_TASK_PROFILE_EN > 0u
  219. OS_CPU_USAGE usage;
  220. OS_CYCLES cycles_total;
  221. #endif
  222. OS_TCB *p_tcb;
  223. #endif
  224. OS_ERR err;
  225. OS_TICK dly;
  226. CPU_TS ts_start;
  227. CPU_TS ts_end;
  228. CPU_SR_ALLOC();
  229. p_arg = p_arg; /* Prevent compiler warning for not using 'p_arg' */
  230. while (OSStatTaskRdy != DEF_TRUE) {
  231. OSTimeDly(2u * OSCfg_StatTaskRate_Hz, /* Wait until statistic task is ready */
  232. OS_OPT_TIME_DLY,
  233. &err);
  234. }
  235. OSStatReset(&err); /* Reset statistics */
  236. dly = (OS_TICK)0; /* Compute statistic task sleep delay */
  237. if (OSCfg_TickRate_Hz > OSCfg_StatTaskRate_Hz) {
  238. dly = (OS_TICK)(OSCfg_TickRate_Hz / OSCfg_StatTaskRate_Hz);
  239. }
  240. if (dly == (OS_TICK)0) {
  241. dly = (OS_TICK)(OSCfg_TickRate_Hz / (OS_RATE_HZ)10);
  242. }
  243. while (DEF_ON) {
  244. ts_start = OS_TS_GET();
  245. #ifdef CPU_CFG_INT_DIS_MEAS_EN
  246. OSIntDisTimeMax = CPU_IntDisMeasMaxGet();
  247. #endif
  248. CPU_CRITICAL_ENTER(); /* ----------------- OVERALL CPU USAGE ------------------ */
  249. OSStatTaskCtrRun = OSStatTaskCtr; /* Obtain the of the stat counter for the past .1 second */
  250. OSStatTaskCtr = (OS_TICK)0; /* Reset the stat counter for the next .1 second */
  251. CPU_CRITICAL_EXIT();
  252. if (OSStatTaskCtrMax > OSStatTaskCtrRun) {
  253. if (OSStatTaskCtrMax > (OS_TICK)0) {
  254. OSStatTaskCPUUsage = (OS_CPU_USAGE)((OS_TICK)100u - 100u * OSStatTaskCtrRun / OSStatTaskCtrMax);
  255. } else {
  256. OSStatTaskCPUUsage = (OS_CPU_USAGE)100;
  257. }
  258. } else {
  259. OSStatTaskCPUUsage = (OS_CPU_USAGE)100;
  260. }
  261. OSStatTaskHook(); /* Invoke user definable hook */
  262. #if OS_CFG_DBG_EN > 0u
  263. #if OS_CFG_TASK_PROFILE_EN > 0u
  264. cycles_total = (OS_CYCLES)0;
  265. p_tcb = OSTaskDbgListPtr;
  266. while (p_tcb != (OS_TCB *)0) { /* ----------------- TOTAL CYCLES COUNT ----------------- */
  267. OS_CRITICAL_ENTER();
  268. p_tcb->CyclesTotalPrev = p_tcb->CyclesTotal; /* Save accumulated # cycles into a temp variable */
  269. p_tcb->CyclesTotal = (OS_CYCLES)0; /* Reset total cycles for task for next run */
  270. OS_CRITICAL_EXIT();
  271. cycles_total += p_tcb->CyclesTotalPrev;/* Perform sum of all task # cycles */
  272. p_tcb = p_tcb->DbgNextPtr;
  273. }
  274. #endif
  275. #if OS_CFG_TASK_PROFILE_EN > 0u
  276. cycles_total /= 100u; /* ------------- INDIVIDUAL TASK CPU USAGE -------------- */
  277. #endif
  278. p_tcb = OSTaskDbgListPtr;
  279. while (p_tcb != (OS_TCB *)0) {
  280. #if OS_CFG_TASK_PROFILE_EN > 0u /* Compute execution time of each task */
  281. if (cycles_total > (OS_CYCLES)0) {
  282. usage = (OS_CPU_USAGE)(p_tcb->CyclesTotalPrev / cycles_total);
  283. if (usage > 100u) {
  284. usage = 100u;
  285. }
  286. } else {
  287. usage = 0u;
  288. }
  289. p_tcb->CPUUsage = usage;
  290. #endif
  291. #if OS_CFG_STAT_TASK_STK_CHK_EN > 0u
  292. OSTaskStkChk( p_tcb, /* Compute stack usage of active tasks only */
  293. &p_tcb->StkFree,
  294. &p_tcb->StkUsed,
  295. &err);
  296. /*printf("%s free: %d, used : %d\r\n",
  297. p_tcb->NamePtr, p_tcb->StkFree, p_tcb->StkUsed);*/
  298. #endif
  299. p_tcb = p_tcb->DbgNextPtr;
  300. }
  301. #endif
  302. if (OSStatResetFlag == DEF_TRUE) { /* Check if need to reset statistics */
  303. OSStatResetFlag = DEF_FALSE;
  304. OSStatReset(&err);
  305. }
  306. ts_end = OS_TS_GET() - ts_start; /* Measure execution time of statistic task */
  307. if (ts_end > OSStatTaskTimeMax) {
  308. OSStatTaskTimeMax = ts_end;
  309. }
  310. OSTimeDly(dly,
  311. OS_OPT_TIME_DLY,
  312. &err);
  313. }
  314. }
  315. /*$PAGE*/
  316. /*
  317. ************************************************************************************************************************
  318. * INITIALIZE THE STATISTICS
  319. *
  320. * Description: This function is called by OSInit() to initialize the statistic task.
  321. *
  322. * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
  323. *
  324. * OS_ERR_STK_INVALID If you specified a NULL stack pointer during configuration
  325. * OS_ERR_STK_SIZE_INVALID If you didn't specify a large enough stack.
  326. * OS_ERR_PRIO_INVALID If you specified a priority for the statistic task equal to or
  327. * lower (i.e. higher number) than the idle task.
  328. * OS_ERR_xxx An error code returned by OSTaskCreate()
  329. *
  330. * Returns : none
  331. *
  332. * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
  333. ************************************************************************************************************************
  334. */
  335. void OS_StatTaskInit (OS_ERR *p_err)
  336. {
  337. #ifdef OS_SAFETY_CRITICAL
  338. if (p_err == (OS_ERR *)0) {
  339. OS_SAFETY_CRITICAL_EXCEPTION();
  340. return;
  341. }
  342. #endif
  343. OSStatTaskCtr = (OS_TICK)0;
  344. OSStatTaskCtrRun = (OS_TICK)0;
  345. OSStatTaskCtrMax = (OS_TICK)0;
  346. OSStatTaskRdy = OS_STATE_NOT_RDY; /* Statistic task is not ready */
  347. OSStatResetFlag = DEF_FALSE;
  348. /* ---------------- CREATE THE STAT TASK ---------------- */
  349. if (OSCfg_StatTaskStkBasePtr == (CPU_STK*)0) {
  350. *p_err = OS_ERR_STK_INVALID;
  351. return;
  352. }
  353. if (OSCfg_StatTaskStkSize < OSCfg_StkSizeMin) {
  354. *p_err = OS_ERR_STK_SIZE_INVALID;
  355. return;
  356. }
  357. if (OSCfg_StatTaskPrio >= (OS_CFG_PRIO_MAX - 1u)) {
  358. *p_err = OS_ERR_PRIO_INVALID;
  359. return;
  360. }
  361. OSTaskCreate((OS_TCB *)&OSStatTaskTCB,
  362. (CPU_CHAR *)((void *)"uC/OS-III Stat Task"),
  363. (OS_TASK_PTR )OS_StatTask,
  364. (void *)0,
  365. (OS_PRIO )OSCfg_StatTaskPrio,
  366. (CPU_STK *)OSCfg_StatTaskStkBasePtr,
  367. (CPU_STK_SIZE)OSCfg_StatTaskStkLimit,
  368. (CPU_STK_SIZE)OSCfg_StatTaskStkSize,
  369. (OS_MSG_QTY )0,
  370. (OS_TICK )0,
  371. (void *)0,
  372. (OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
  373. (OS_ERR *)p_err);
  374. }
  375. #endif