| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
os_stat.c
Go to the documentation of this file.
1 /*
2 ************************************************************************************************************************
3 * uC/OS-III
4 * The Real-Time Kernel
5 *
6 * (c) Copyright 2009-2012; 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.03.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
33 #define MICRIUM_SOURCE
34 #include <os.h>
35
36 #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
37 const CPU_CHAR *os_stat__c = "$Id: $";
38 #endif
39
40
41 #if OS_CFG_STAT_TASK_EN > 0u
42
43 /*
44 ************************************************************************************************************************
45 * RESET STATISTICS
46 *
47 * Description: This function is called by your application to reset the statistics.
48 *
49 * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
50 *
51 * OS_ERR_NONE
52 *
53 * Returns : none
54 ************************************************************************************************************************
55 */
56
57 void OSStatReset (OS_ERR *p_err)
58 {
59 #if (OS_CFG_DBG_EN > 0u)
60 OS_TCB *p_tcb;
61 #if (OS_MSG_EN > 0u)
62 OS_MSG_Q *p_msg_q;
63 #endif
64 #if (OS_CFG_Q_EN > 0u)
65 OS_Q *p_q;
66 #endif
67 CPU_SR_ALLOC();
68 #endif
69
70
71
72 #ifdef OS_SAFETY_CRITICAL
73 if (p_err == (OS_ERR *)0) {
74 OS_SAFETY_CRITICAL_EXCEPTION();
75 return;
76 }
77 #endif
78
79 CPU_CRITICAL_ENTER();
80 #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
81 OSIntQTaskTimeMax = (CPU_TS )0; /* Reset the task execution times */
82 OSIntQNbrEntriesMax = (OS_OBJ_QTY)0; /* Reset the queue maximum number of entries */
83 #endif
84
85 #if OS_CFG_STAT_TASK_EN > 0u
86 OSStatTaskCPUUsageMax = 0u;
87 OSStatTaskTimeMax = (CPU_TS)0;
88 #endif
89
90 OSTickTaskTimeMax = (CPU_TS)0;
91
92 #if OS_CFG_TMR_EN > 0u
93 OSTmrTaskTimeMax = (CPU_TS)0;
94 #endif
95
96 #ifdef CPU_CFG_INT_DIS_MEAS_EN
97 OSIntDisTimeMax = (CPU_TS)0; /* Reset the maximum interrupt disable time */
98 #endif
99
100 #if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
101 OSSchedLockTimeMax = (CPU_TS)0; /* Reset the maximum scheduler lock time */
102 #endif
103
104 #if OS_MSG_EN > 0u
105 OSMsgPool.NbrUsedMax = 0;
106 #endif
107 CPU_CRITICAL_EXIT();
108
109 #if OS_CFG_DBG_EN > 0u
110 CPU_CRITICAL_ENTER();
111 p_tcb = OSTaskDbgListPtr;
112 CPU_CRITICAL_EXIT();
113 while (p_tcb != (OS_TCB *)0) { /* Reset per-Task statistics */
114 CPU_CRITICAL_ENTER();
115
116 #ifdef CPU_CFG_INT_DIS_MEAS_EN
117 p_tcb->IntDisTimeMax = (CPU_TS )0;
118 #endif
119
120 #if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
121 p_tcb->SchedLockTimeMax = (CPU_TS )0;
122 #endif
123
124 #if OS_CFG_TASK_PROFILE_EN > 0u
125 #if OS_CFG_TASK_Q_EN > 0u
126 p_tcb->MsgQPendTimeMax = (CPU_TS )0;
127 #endif
128 p_tcb->SemPendTimeMax = (CPU_TS )0;
129 p_tcb->CtxSwCtr = (OS_CTR )0;
130 p_tcb->CPUUsage = (OS_CPU_USAGE)0;
131 p_tcb->CPUUsageMax = (OS_CPU_USAGE)0;
132 p_tcb->CyclesTotal = (OS_CYCLES )0;
133 p_tcb->CyclesTotalPrev = (OS_CYCLES )0;
134 p_tcb->CyclesStart = OS_TS_GET();
135 #endif
136
137 #if OS_CFG_TASK_Q_EN > 0u
138 p_msg_q = &p_tcb->MsgQ;
139 p_msg_q->NbrEntriesMax = (OS_MSG_QTY )0;
140 #endif
141 p_tcb = p_tcb->DbgNextPtr;
142 CPU_CRITICAL_EXIT();
143 }
144 #endif
145
146 #if (OS_CFG_Q_EN > 0u) && (OS_CFG_DBG_EN > 0u)
147 CPU_CRITICAL_ENTER();
148 p_q = OSQDbgListPtr;
149 CPU_CRITICAL_EXIT();
150 while (p_q != (OS_Q *)0) { /* Reset message queues statistics */
151 CPU_CRITICAL_ENTER();
152 p_msg_q = &p_q->MsgQ;
153 p_msg_q->NbrEntriesMax = (OS_MSG_QTY)0;
154 p_q = p_q->DbgNextPtr;
155 CPU_CRITICAL_EXIT();
156 }
157 #endif
158
159 OS_TickListResetPeak(); /* Reset tick wheel statistics */
160
161 #if OS_CFG_TMR_EN > 0u
162 OS_TmrResetPeak();
163 #endif
164
165
166 *p_err = OS_ERR_NONE;
167 }
168
169 /*$PAGE*/
170 /*
171 ************************************************************************************************************************
172 * DETERMINE THE CPU CAPACITY
173 *
174 * Description: This function is called by your application to establish CPU usage by first determining how high a 32-bit
175 * counter would count to in 1/10 second if no other tasks were to execute during that time. CPU usage is
176 * then determined by a low priority task which keeps track of this 32-bit counter every second but this
177 * time, with other tasks running. CPU usage is determined by:
178 *
179 * OS_Stat_IdleCtr
180 * CPU Usage (%) = 100 * (1 - ------------------)
181 * OS_Stat_IdleCtrMax
182 *
183 * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
184 *
185 * OS_ERR_NONE
186 *
187 * Returns : none
188 ************************************************************************************************************************
189 */
190
191 void OSStatTaskCPUUsageInit (OS_ERR *p_err)
192 {
193 OS_ERR err;
194 OS_TICK dly;
195 CPU_SR_ALLOC();
196
197
198
199 #ifdef OS_SAFETY_CRITICAL
200 if (p_err == (OS_ERR *)0) {
201 OS_SAFETY_CRITICAL_EXCEPTION();
202 return;
203 }
204 #endif
205
206 #if (OS_CFG_TMR_EN > 0u)
207 OSTaskSuspend(&OSTmrTaskTCB, &err);
208 if (err != OS_ERR_NONE) {
209 *p_err = err;
210 return;
211 }
212 #endif
213
214 OSTimeDly((OS_TICK )2, /* Synchronize with clock tick */
215 (OS_OPT )OS_OPT_TIME_DLY,
216 (OS_ERR *)&err);
217 if (err != OS_ERR_NONE) {
218 *p_err = err;
219 return;
220 }
221 CPU_CRITICAL_ENTER();
222 OSStatTaskCtr = (OS_TICK)0; /* Clear idle counter */
223 CPU_CRITICAL_EXIT();
224
225 dly = (OS_TICK)0;
226 if (OSCfg_TickRate_Hz > OSCfg_StatTaskRate_Hz) {
227 dly = (OS_TICK)(OSCfg_TickRate_Hz / OSCfg_StatTaskRate_Hz);
228 }
229 if (dly == (OS_TICK)0) {
230 dly = (OS_TICK)(OSCfg_TickRate_Hz / (OS_RATE_HZ)10);
231 }
232
233 OSTimeDly(dly, /* Determine MAX. idle counter value */
234 OS_OPT_TIME_DLY,
235 &err);
236
237 #if (OS_CFG_TMR_EN > 0u)
238 OSTaskResume(&OSTmrTaskTCB, &err);
239 if (err != OS_ERR_NONE) {
240 *p_err = err;
241 return;
242 }
243 #endif
244
245 CPU_CRITICAL_ENTER();
246 OSStatTaskTimeMax = (CPU_TS)0;
247
248 OSStatTaskCtrMax = OSStatTaskCtr; /* Store maximum idle counter count */
249 OSStatTaskRdy = OS_STATE_RDY;
250 CPU_CRITICAL_EXIT();
251 *p_err = OS_ERR_NONE;
252 }
253
254 /*$PAGE*/
255 /*
256 ************************************************************************************************************************
257 * STATISTICS TASK
258 *
259 * Description: This task is internal to uC/OS-III and is used to compute some statistics about the multitasking
260 * environment. Specifically, OS_StatTask() computes the CPU usage. CPU usage is determined by:
261 *
262 * OSStatTaskCtr
263 * OSStatTaskCPUUsage = 100 * (1 - ------------------) (units are in %)
264 * OSStatTaskCtrMax
265 *
266 * Arguments : p_arg this pointer is not used at this time.
267 *
268 * Returns : none
269 *
270 * Note(s) : 1) This task runs at a priority level higher than the idle task.
271 *
272 * 2) You can disable this task by setting the configuration #define OS_CFG_STAT_TASK_EN to 0.
273 *
274 * 3) You MUST have at least a delay of 2/10 seconds to allow for the system to establish the maximum value
275 * for the idle counter.
276 *
277 * 4) This function is INTERNAL to uC/OS-III and your application should not call it.
278 ************************************************************************************************************************
279 */
280
281 void OS_StatTask (void *p_arg)
282 {
283 #if OS_CFG_DBG_EN > 0u
284 #if OS_CFG_TASK_PROFILE_EN > 0u
285 OS_CPU_USAGE usage;
286 OS_CYCLES cycles_total;
287 OS_CYCLES cycles_div;
288 OS_CYCLES cycles_mult;
289 OS_CYCLES cycles_max;
290 #endif
291 OS_TCB *p_tcb;
292 #endif
293 OS_TICK ctr_max;
294 OS_TICK ctr_mult;
295 OS_TICK ctr_div;
296 OS_ERR err;
297 OS_TICK dly;
298 CPU_TS ts_start;
299 CPU_TS ts_end;
300 CPU_SR_ALLOC();
301
302
303
304 p_arg = p_arg; /* Prevent compiler warning for not using 'p_arg' */
305 while (OSStatTaskRdy != DEF_TRUE) {
306 OSTimeDly(2u * OSCfg_StatTaskRate_Hz, /* Wait until statistic task is ready */
307 OS_OPT_TIME_DLY,
308 &err);
309 }
310 OSStatReset(&err); /* Reset statistics */
311
312 dly = (OS_TICK)0; /* Compute statistic task sleep delay */
313 if (OSCfg_TickRate_Hz > OSCfg_StatTaskRate_Hz) {
314 dly = (OS_TICK)(OSCfg_TickRate_Hz / OSCfg_StatTaskRate_Hz);
315 }
316 if (dly == (OS_TICK)0) {
317 dly = (OS_TICK)(OSCfg_TickRate_Hz / (OS_RATE_HZ)10);
318 }
319
320 while (DEF_ON) {
321 ts_start = OS_TS_GET();
322 #ifdef CPU_CFG_INT_DIS_MEAS_EN
323 OSIntDisTimeMax = CPU_IntDisMeasMaxGet();
324 #endif
325
326 CPU_CRITICAL_ENTER(); /* ----------------- OVERALL CPU USAGE ------------------ */
327 OSStatTaskCtrRun = OSStatTaskCtr; /* Obtain the of the stat counter for the past .1 second */
328 OSStatTaskCtr = (OS_TICK)0; /* Reset the stat counter for the next .1 second */
329 CPU_CRITICAL_EXIT();
330
331 if (OSStatTaskCtrMax > OSStatTaskCtrRun) { /* Compute CPU Usage with best resolution */
332 if (OSStatTaskCtrMax < 400000u) { /* 1 to 400,000 */
333 ctr_mult = 10000u;
334 ctr_div = 1u;
335 } else if (OSStatTaskCtrMax < 4000000u) { /* 400,000 to 4,000,000 */
336 ctr_mult = 1000u;
337 ctr_div = 10u;
338 } else if (OSStatTaskCtrMax < 40000000u) { /* 4,000,000 to 40,000,000 */
339 ctr_mult = 100u;
340 ctr_div = 100u;
341 } else if (OSStatTaskCtrMax < 400000000u) { /* 40,000,000 to 400,000,000 */
342 ctr_mult = 10u;
343 ctr_div = 1000u;
344 } else { /* 400,000,000 and up */
345 ctr_mult = 1u;
346 ctr_div = 10000u;
347 }
348 ctr_max = OSStatTaskCtrMax / ctr_div;
349 OSStatTaskCPUUsage = (OS_CPU_USAGE)((OS_TICK)10000u - ctr_mult * OSStatTaskCtrRun / ctr_max);
350 if (OSStatTaskCPUUsageMax < OSStatTaskCPUUsage) {
351 OSStatTaskCPUUsageMax = OSStatTaskCPUUsage;
352 }
353 } else {
354 OSStatTaskCPUUsage = (OS_CPU_USAGE)10000u;
355 }
356
357 OSStatTaskHook(); /* Invoke user definable hook */
358
359
360 #if OS_CFG_DBG_EN > 0u
361 #if OS_CFG_TASK_PROFILE_EN > 0u
362 cycles_total = (OS_CYCLES)0;
363
364 CPU_CRITICAL_ENTER();
365 p_tcb = OSTaskDbgListPtr;
366 CPU_CRITICAL_EXIT();
367 while (p_tcb != (OS_TCB *)0) { /* ----------------- TOTAL CYCLES COUNT ----------------- */
368 OS_CRITICAL_ENTER();
369 p_tcb->CyclesTotalPrev = p_tcb->CyclesTotal; /* Save accumulated # cycles into a temp variable */
370 p_tcb->CyclesTotal = (OS_CYCLES)0; /* Reset total cycles for task for next run */
371 OS_CRITICAL_EXIT();
372
373 cycles_total += p_tcb->CyclesTotalPrev;/* Perform sum of all task # cycles */
374
375 CPU_CRITICAL_ENTER();
376 p_tcb = p_tcb->DbgNextPtr;
377 CPU_CRITICAL_EXIT();
378 }
379 #endif
380
381
382 #if OS_CFG_TASK_PROFILE_EN > 0u
383 /* ------------- INDIVIDUAL TASK CPU USAGE -------------- */
384 if (cycles_total > (OS_CYCLES)0u) { /* 'cycles_total' scaling ... */
385 if (cycles_total < 400000u) { /* 1 to 400,000 */
386 cycles_mult = 10000u;
387 cycles_div = 1u;
388 } else if (cycles_total < 4000000u) { /* 400,000 to 4,000,000 */
389 cycles_mult = 1000u;
390 cycles_div = 10u;
391 } else if (cycles_total < 40000000u) { /* 4,000,000 to 40,000,000 */
392 cycles_mult = 100u;
393 cycles_div = 100u;
394 } else if (cycles_total < 400000000u) { /* 40,000,000 to 400,000,000 */
395 cycles_mult = 10u;
396 cycles_div = 1000u;
397 } else { /* 400,000,000 and up */
398 cycles_mult = 1u;
399 cycles_div = 10000u;
400 }
401 cycles_max = cycles_total / cycles_div;
402 } else {
403 cycles_mult = 0u;
404 cycles_max = 1u;
405 }
406 #endif
407 CPU_CRITICAL_ENTER();
408 p_tcb = OSTaskDbgListPtr;
409 CPU_CRITICAL_EXIT();
410 while (p_tcb != (OS_TCB *)0) {
411 #if OS_CFG_TASK_PROFILE_EN > 0u /* Compute execution time of each task */
412 usage = (OS_CPU_USAGE)(cycles_mult * p_tcb->CyclesTotalPrev / cycles_max);
413 if (usage > 10000u) {
414 usage = 10000u;
415 }
416 p_tcb->CPUUsage = usage;
417 if (p_tcb->CPUUsageMax < usage) { /* Detect peak CPU usage */
418 p_tcb->CPUUsageMax = usage;
419 }
420 #endif
421
422 #if OS_CFG_STAT_TASK_STK_CHK_EN > 0u
423 OSTaskStkChk( p_tcb, /* Compute stack usage of active tasks only */
424 &p_tcb->StkFree,
425 &p_tcb->StkUsed,
426 &err);
427 #endif
428
429 CPU_CRITICAL_ENTER();
430 p_tcb = p_tcb->DbgNextPtr;
431 CPU_CRITICAL_EXIT();
432 }
433 #endif
434
435 if (OSStatResetFlag == DEF_TRUE) { /* Check if need to reset statistics */
436 OSStatResetFlag = DEF_FALSE;
437 OSStatReset(&err);
438 }
439
440 ts_end = OS_TS_GET() - ts_start; /* Measure execution time of statistic task */
441 if (OSStatTaskTimeMax < ts_end) {
442 OSStatTaskTimeMax = ts_end;
443 }
444
445 OSTimeDly(dly,
446 OS_OPT_TIME_DLY,
447 &err);
448 }
449 }
450
451 /*$PAGE*/
452 /*
453 ************************************************************************************************************************
454 * INITIALIZE THE STATISTICS
455 *
456 * Description: This function is called by OSInit() to initialize the statistic task.
457 *
458 * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
459 *
460 * OS_ERR_STK_INVALID If you specified a NULL stack pointer during configuration
461 * OS_ERR_STK_SIZE_INVALID If you didn't specify a large enough stack.
462 * OS_ERR_PRIO_INVALID If you specified a priority for the statistic task equal to or
463 * lower (i.e. higher number) than the idle task.
464 * OS_ERR_xxx An error code returned by OSTaskCreate()
465 *
466 * Returns : none
467 *
468 * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
469 ************************************************************************************************************************
470 */
471
472 void OS_StatTaskInit (OS_ERR *p_err)
473 {
474 #ifdef OS_SAFETY_CRITICAL
475 if (p_err == (OS_ERR *)0) {
476 OS_SAFETY_CRITICAL_EXCEPTION();
477 return;
478 }
479 #endif
480
481 OSStatTaskCtr = (OS_TICK)0;
482 OSStatTaskCtrRun = (OS_TICK)0;
483 OSStatTaskCtrMax = (OS_TICK)0;
484 OSStatTaskRdy = OS_STATE_NOT_RDY; /* Statistic task is not ready */
485 OSStatResetFlag = DEF_FALSE;
486
487 /* ---------------- CREATE THE STAT TASK ---------------- */
488 if (OSCfg_StatTaskStkBasePtr == (CPU_STK *)0) {
489 *p_err = OS_ERR_STAT_STK_INVALID;
490 return;
491 }
492
493 if (OSCfg_StatTaskStkSize < OSCfg_StkSizeMin) {
494 *p_err = OS_ERR_STAT_STK_SIZE_INVALID;
495 return;
496 }
497
498 if (OSCfg_StatTaskPrio >= (OS_CFG_PRIO_MAX - 1u)) {
499 *p_err = OS_ERR_STAT_PRIO_INVALID;
500 return;
501 }
502
503 OSTaskCreate((OS_TCB *)&OSStatTaskTCB,
504 (CPU_CHAR *)((void *)"uC/OS-III Stat Task"),
505 (OS_TASK_PTR )OS_StatTask,
506 (void *)0,
507 (OS_PRIO )OSCfg_StatTaskPrio,
508 (CPU_STK *)OSCfg_StatTaskStkBasePtr,
509 (CPU_STK_SIZE)OSCfg_StatTaskStkLimit,
510 (CPU_STK_SIZE)OSCfg_StatTaskStkSize,
511 (OS_MSG_QTY )0,
512 (OS_TICK )0,
513 (void *)0,
514 (OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
515 (OS_ERR *)p_err);
516 }
517
518 #endif