LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
os_task.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 * TASK MANAGEMENT
10 *
11 * File : OS_TASK.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_task__c = "$Id: $";
38 #endif
39 
40 /*
41 ************************************************************************************************************************
42 * CHANGE PRIORITY OF A TASK
43 *
44 * Description: This function allows you to change the priority of a task dynamically. Note that the new
45 * priority MUST be available.
46 *
47 * Arguments : p_tcb is the TCB of the tack to change the priority for
48 *
49 * prio_new is the new priority
50 *
51 * p_err is a pointer to an error code returned by this function:
52 *
53 * OS_ERR_NONE is the call was successful
54 * OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed
55 * (i.e. >= (OS_CFG_PRIO_MAX-1))
56 * OS_ERR_STATE_INVALID if the task is in an invalid state
57 * OS_ERR_TASK_CHANGE_PRIO_ISR if you tried to change the task's priority from an ISR
58 ************************************************************************************************************************
59 */
60 
61 #if OS_CFG_TASK_CHANGE_PRIO_EN > 0u
62 void OSTaskChangePrio (OS_TCB *p_tcb,
63  OS_PRIO prio_new,
64  OS_ERR *p_err)
65 {
66  CPU_BOOLEAN self;
67  CPU_SR_ALLOC();
68 
69 
70 
71 #ifdef OS_SAFETY_CRITICAL
72  if (p_err == (OS_ERR *)0) {
73  OS_SAFETY_CRITICAL_EXCEPTION();
74  return;
75  }
76 #endif
77 
78 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
79  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* ---------- CANNOT CREATE A TASK FROM AN ISR ---------- */
81  return;
82  }
83 #endif
84 
85 #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
86  if (prio_new == 0) { /* Cannot set to IntQueue Task priority */
87  *p_err = OS_ERR_PRIO_INVALID;
88  return;
89  }
90 #endif
91 
92  if (prio_new >= (OS_CFG_PRIO_MAX - 1u)) { /* Cannot set to Idle Task priority */
93  *p_err = OS_ERR_PRIO_INVALID;
94  return;
95  }
96 
97  if (p_tcb == (OS_TCB *)0) { /* See if want to change priority of 'self' */
99  p_tcb = OSTCBCurPtr;
101  self = DEF_TRUE;
102  } else {
103  self = DEF_FALSE;
104  }
105 
107  switch (p_tcb->TaskState) {
108  case OS_TASK_STATE_RDY:
109  OS_RdyListRemove(p_tcb); /* Remove from current priority */
110  p_tcb->Prio = prio_new; /* Set new task priority */
111  OS_PrioInsert(p_tcb->Prio);
112  if (self == DEF_TRUE) {
113  OS_RdyListInsertHead(p_tcb);
114  } else {
115  OS_RdyListInsertTail(p_tcb);
116  }
117  break;
118 
119  case OS_TASK_STATE_DLY: /* Nothing to do except change the priority in the OS_TCB */
122  p_tcb->Prio = prio_new; /* Set new task priority */
123  break;
124 
125  case OS_TASK_STATE_PEND:
129  switch (p_tcb->PendOn) { /* What to do depends on what we are pending on */
130  case OS_TASK_PEND_ON_TASK_Q: /* Nothing to do except change the priority in the OS_TCB */
133  p_tcb->Prio = prio_new; /* Set new task priority */
134  break;
135 
138  case OS_TASK_PEND_ON_Q:
139  case OS_TASK_PEND_ON_SEM:
140  OS_PendListChangePrio(p_tcb,
141  prio_new);
142  break;
143 
144  default:
145  break;
146  }
147  break;
148 
149  default:
151  *p_err = OS_ERR_STATE_INVALID;
152  return;
153  }
154 
156 
157  OSSched(); /* Run highest priority task ready */
158 
159  *p_err = OS_ERR_NONE;
160 }
161 #endif
162 
163 /*$PAGE*/
164 /*
165 ************************************************************************************************************************
166 * CREATE A TASK
167 *
168 * Description: This function is used to have uC/OS-III manage the execution of a task. Tasks can either be created
169 * prior to the start of multitasking or by a running task. A task cannot be created by an ISR.
170 *
171 * Arguments : p_tcb is a pointer to the task's TCB
172 *
173 * p_name is a pointer to an ASCII string to provide a name to the task.
174 *
175 * p_task is a pointer to the task's code
176 *
177 * p_arg is a pointer to an optional data area which can be used to pass parameters to
178 * the task when the task first executes. Where the task is concerned it thinks
179 * it was invoked and passed the argument 'p_arg' as follows:
180 *
181 * void Task (void *p_arg)
182 * {
183 * for (;;) {
184 * Task code;
185 * }
186 * }
187 *
188 * prio is the task's priority. A unique priority MUST be assigned to each task and the
189 * lower the number, the higher the priority.
190 *
191 * p_stk_base is a pointer to the base address of the stack (i.e. low address).
192 *
193 * stk_limit is the number of stack elements to set as 'watermark' limit for the stack. This value
194 * represents the number of CPU_STK entries left before the stack is full. For example,
195 * specifying 10% of the 'stk_size' value indicates that the stack limit will be reached
196 * when the stack reaches 90% full.
197 *
198 * stk_size is the size of the stack in number of elements. If CPU_STK is set to CPU_INT08U,
199 * 'stk_size' corresponds to the number of bytes available. If CPU_STK is set to
200 * CPU_INT16U, 'stk_size' contains the number of 16-bit entries available. Finally, if
201 * CPU_STK is set to CPU_INT32U, 'stk_size' contains the number of 32-bit entries
202 * available on the stack.
203 *
204 * q_size is the maximum number of messages that can be sent to the task
205 *
206 * time_quanta amount of time (in ticks) for time slice when round-robin between tasks. Specify 0 to use
207 * the default.
208 *
209 * p_ext is a pointer to a user supplied memory location which is used as a TCB extension.
210 * For example, this user memory can hold the contents of floating-point registers
211 * during a context switch, the time each task takes to execute, the number of times
212 * the task has been switched-in, etc.
213 *
214 * opt contains additional information (or options) about the behavior of the task.
215 * See OS_OPT_TASK_xxx in OS.H. Current choices are:
216 *
217 * OS_OPT_TASK_NONE No option selected
218 * OS_OPT_TASK_STK_CHK Stack checking to be allowed for the task
219 * OS_OPT_TASK_STK_CLR Clear the stack when the task is created
220 * OS_OPT_TASK_SAVE_FP If the CPU has floating-point registers, save them
221 * during a context switch.
222 * OS_OPT_TASK_NO_TLS If the caller doesn't want or need TLS (Thread Local
223 * Storage) support for the task. If you do not include this
224 * option, TLS will be supported by default.
225 *
226 * p_err is a pointer to an error code that will be set during this call. The value pointer
227 * to by 'p_err' can be:
228 *
229 * OS_ERR_NONE if the function was successful.
230 * OS_ERR_ILLEGAL_CREATE_RUN_TIME if you are trying to create the task after you called
231 * OSSafetyCriticalStart().
232 * OS_ERR_NAME if 'p_name' is a NULL pointer
233 * OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum
234 * allowed (i.e. >= OS_CFG_PRIO_MAX-1) or,
235 * if OS_CFG_ISR_POST_DEFERRED_EN is set to 1 and you tried
236 * to use priority 0 which is reserved.
237 * OS_ERR_STK_INVALID if you specified a NULL pointer for 'p_stk_base'
238 * OS_ERR_STK_SIZE_INVALID if you specified zero for the 'stk_size'
239 * OS_ERR_STK_LIMIT_INVALID if you specified a 'stk_limit' greater than or equal
240 * to 'stk_size'
241 * OS_ERR_TASK_CREATE_ISR if you tried to create a task from an ISR.
242 * OS_ERR_TASK_INVALID if you specified a NULL pointer for 'p_task'
243 * OS_ERR_TCB_INVALID if you specified a NULL pointer for 'p_tcb'
244 *
245 * Returns : A pointer to the TCB of the task created. This pointer must be used as an ID (i.e handle) to the task.
246 ************************************************************************************************************************
247 */
248 /*$PAGE*/
249 void OSTaskCreate (OS_TCB *p_tcb,
250  CPU_CHAR *p_name,
251  OS_TASK_PTR p_task,
252  void *p_arg,
253  OS_PRIO prio,
254  CPU_STK *p_stk_base,
255  CPU_STK_SIZE stk_limit,
256  CPU_STK_SIZE stk_size,
257  OS_MSG_QTY q_size,
258  OS_TICK time_quanta,
259  void *p_ext,
260  OS_OPT opt,
261  OS_ERR *p_err)
262 {
263  CPU_STK_SIZE i;
264 #if OS_CFG_TASK_REG_TBL_SIZE > 0u
265  OS_REG_ID reg_nbr;
266 #endif
267 #if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
268  OS_TLS_ID id;
269 #endif
270 
271  CPU_STK *p_sp;
272  CPU_STK *p_stk_limit;
273  CPU_SR_ALLOC();
274 
275 
276 
277 #ifdef OS_SAFETY_CRITICAL
278  if (p_err == (OS_ERR *)0) {
279  OS_SAFETY_CRITICAL_EXCEPTION();
280  return;
281  }
282 #endif
283 
284 #ifdef OS_SAFETY_CRITICAL_IEC61508
285  if (OSSafetyCriticalStartFlag == DEF_TRUE) {
287  return;
288  }
289 #endif
290 
291 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
292  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* ---------- CANNOT CREATE A TASK FROM AN ISR ---------- */
293  *p_err = OS_ERR_TASK_CREATE_ISR;
294  return;
295  }
296 #endif
297 
298 #if OS_CFG_ARG_CHK_EN > 0u /* ---------------- VALIDATE ARGUMENTS ------------------ */
299  if (p_tcb == (OS_TCB *)0) { /* User must supply a valid OS_TCB */
300  *p_err = OS_ERR_TCB_INVALID;
301  return;
302  }
303  if (p_task == (OS_TASK_PTR)0) { /* User must supply a valid task */
304  *p_err = OS_ERR_TASK_INVALID;
305  return;
306  }
307  if (p_stk_base == (CPU_STK *)0) { /* User must supply a valid stack base address */
308  *p_err = OS_ERR_STK_INVALID;
309  return;
310  }
311  if (stk_size < OSCfg_StkSizeMin) { /* User must supply a valid minimum stack size */
312  *p_err = OS_ERR_STK_SIZE_INVALID;
313  return;
314  }
315  if (stk_limit >= stk_size) { /* User must supply a valid stack limit */
316  *p_err = OS_ERR_STK_LIMIT_INVALID;
317  return;
318  }
319  if (prio >= OS_CFG_PRIO_MAX) { /* Priority must be within 0 and OS_CFG_PRIO_MAX-1 */
320  *p_err = OS_ERR_PRIO_INVALID;
321  return;
322  }
323 #endif
324 
325 #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
326  if (prio == (OS_PRIO)0) {
327  if (p_tcb != &OSIntQTaskTCB) {
328  *p_err = OS_ERR_PRIO_INVALID; /* Not allowed to use priority 0 */
329  return;
330  }
331  }
332 #endif
333 
334  if (prio == (OS_CFG_PRIO_MAX - 1u)) {
335  if (p_tcb != &OSIdleTaskTCB) {
336  *p_err = OS_ERR_PRIO_INVALID; /* Not allowed to use same priority as idle task */
337  return;
338  }
339  }
340 
341  OS_TaskInitTCB(p_tcb); /* Initialize the TCB to default values */
342 
343  *p_err = OS_ERR_NONE;
344  /* --------------- CLEAR THE TASK'S STACK --------------- */
345  if ((opt & OS_OPT_TASK_STK_CHK) != (OS_OPT)0) { /* See if stack checking has been enabled */
346  if ((opt & OS_OPT_TASK_STK_CLR) != (OS_OPT)0) { /* See if stack needs to be cleared */
347  p_sp = p_stk_base;
348  for (i = 0u; i < stk_size; i++) { /* Stack grows from HIGH to LOW memory */
349  *p_sp = (CPU_STK)0; /* Clear from bottom of stack and up! */
350  p_sp++;
351  }
352  }
353  }
354  /* ------- INITIALIZE THE STACK FRAME OF THE TASK ------- */
355 #if (CPU_CFG_STK_GROWTH == CPU_STK_GROWTH_HI_TO_LO)
356  p_stk_limit = p_stk_base + stk_limit;
357 #else
358  p_stk_limit = p_stk_base + (stk_size - 1u) - stk_limit;
359 #endif
360 
361  p_sp = OSTaskStkInit(p_task,
362  p_arg,
363  p_stk_base,
364  p_stk_limit,
365  stk_size,
366  opt);
367 
368  /* -------------- INITIALIZE THE TCB FIELDS ------------- */
369  p_tcb->TaskEntryAddr = p_task; /* Save task entry point address */
370  p_tcb->TaskEntryArg = p_arg; /* Save task entry argument */
371 
372  p_tcb->NamePtr = p_name; /* Save task name */
373 
374  p_tcb->Prio = prio; /* Save the task's priority */
375 
376  p_tcb->StkPtr = p_sp; /* Save the new top-of-stack pointer */
377  p_tcb->StkLimitPtr = p_stk_limit; /* Save the stack limit pointer */
378 
379  p_tcb->TimeQuanta = time_quanta; /* Save the #ticks for time slice (0 means not sliced) */
380 #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
381  if (time_quanta == (OS_TICK)0) {
382  p_tcb->TimeQuantaCtr = OSSchedRoundRobinDfltTimeQuanta;
383  } else {
384  p_tcb->TimeQuantaCtr = time_quanta;
385  }
386 #endif
387  p_tcb->ExtPtr = p_ext; /* Save pointer to TCB extension */
388  p_tcb->StkBasePtr = p_stk_base; /* Save pointer to the base address of the stack */
389  p_tcb->StkSize = stk_size; /* Save the stack size (in number of CPU_STK elements) */
390  p_tcb->Opt = opt; /* Save task options */
391 
392 #if OS_CFG_TASK_REG_TBL_SIZE > 0u
393  for (reg_nbr = 0u; reg_nbr < OS_CFG_TASK_REG_TBL_SIZE; reg_nbr++) {
394  p_tcb->RegTbl[reg_nbr] = (OS_REG)0;
395  }
396 #endif
397 
398 #if OS_CFG_TASK_Q_EN > 0u
399  OS_MsgQInit(&p_tcb->MsgQ, /* Initialize the task's message queue */
400  q_size);
401 #else
402  (void)&q_size;
403 #endif
404 
405  OSTaskCreateHook(p_tcb); /* Call user defined hook */
406 
407 #if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
408  for (id = 0u; id < OS_CFG_TLS_TBL_SIZE; id++) {
409  p_tcb->TLS_Tbl[id] = (OS_TLS)0;
410  }
411  OS_TLS_TaskCreate(p_tcb); /* Call TLS hook */
412 #endif
413  /* --------------- ADD TASK TO READY LIST --------------- */
415  OS_PrioInsert(p_tcb->Prio);
416  OS_RdyListInsertTail(p_tcb);
417 
418 #if OS_CFG_DBG_EN > 0u
419  OS_TaskDbgListAdd(p_tcb);
420 #endif
421 
422  OSTaskQty++; /* Increment the #tasks counter */
423 
424  if (OSRunning != OS_STATE_OS_RUNNING) { /* Return if multitasking has not started */
426  return;
427  }
428 
430 
431  OSSched();
432 }
433 
434 /*$PAGE*/
435 /*
436 ************************************************************************************************************************
437 * DELETE A TASK
438 *
439 * Description: This function allows you to delete a task. The calling task can delete itself by specifying a NULL
440 * pointer for 'p_tcb'. The deleted task is returned to the dormant state and can be re-activated by
441 * creating the deleted task again.
442 *
443 * Arguments : p_tcb is the TCB of the tack to delete
444 *
445 * p_err is a pointer to an error code returned by this function:
446 *
447 * OS_ERR_NONE if the call is successful
448 * OS_ERR_STATE_INVALID if the state of the task is invalid
449 * OS_ERR_TASK_DEL_IDLE if you attempted to delete uC/OS-III's idle task
450 * OS_ERR_TASK_DEL_INVALID if you attempted to delete uC/OS-III's ISR handler task
451 * OS_ERR_TASK_DEL_ISR if you tried to delete a task from an ISR
452 *
453 * Note(s) : 1) 'p_err' gets set to OS_ERR_NONE before OSSched() to allow the returned error code to be monitored even
454 * for a task that is deleting itself. In this case, 'p_err' MUST point to a global variable that can be
455 * accessed by another task.
456 ************************************************************************************************************************
457 */
458 
459 #if OS_CFG_TASK_DEL_EN > 0u
460 void OSTaskDel (OS_TCB *p_tcb,
461  OS_ERR *p_err)
462 {
463  CPU_SR_ALLOC();
464 
465 
466 
467 #ifdef OS_SAFETY_CRITICAL
468  if (p_err == (OS_ERR *)0) {
469  OS_SAFETY_CRITICAL_EXCEPTION();
470  return;
471  }
472 #endif
473 
474 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
475  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to delete from ISR */
476  *p_err = OS_ERR_TASK_DEL_ISR;
477  return;
478  }
479 #endif
480 
481  if (p_tcb == &OSIdleTaskTCB) { /* Not allowed to delete the idle task */
482  *p_err = OS_ERR_TASK_DEL_IDLE;
483  return;
484  }
485 
486 #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
487  if (p_tcb == &OSIntQTaskTCB) { /* Cannot delete the ISR handler task */
488  *p_err = OS_ERR_TASK_DEL_INVALID;
489  return;
490  }
491 #endif
492 
493  if (p_tcb == (OS_TCB *)0) { /* Delete 'Self'? */
495  p_tcb = OSTCBCurPtr; /* Yes. */
497  }
498 
500  switch (p_tcb->TaskState) {
501  case OS_TASK_STATE_RDY:
502  OS_RdyListRemove(p_tcb);
503  break;
504 
506  break;
507 
508  case OS_TASK_STATE_DLY: /* Task is only delayed, not on any wait list */
510  OS_TickListRemove(p_tcb);
511  break;
512 
513  case OS_TASK_STATE_PEND:
517  OS_TickListRemove(p_tcb);
518  switch (p_tcb->PendOn) { /* See what we are pending on */
520  case OS_TASK_PEND_ON_TASK_Q: /* There is no wait list for these two */
522  break;
523 
524  case OS_TASK_PEND_ON_FLAG: /* Remove from wait list */
527  case OS_TASK_PEND_ON_Q:
528  case OS_TASK_PEND_ON_SEM:
529  OS_PendListRemove(p_tcb);
530  break;
531 
532  default:
533  break;
534  }
535  break;
536 
537  default:
539  *p_err = OS_ERR_STATE_INVALID;
540  return;
541  }
542 
543 #if OS_CFG_TASK_Q_EN > 0u
544  (void)OS_MsgQFreeAll(&p_tcb->MsgQ); /* Free task's message queue messages */
545 #endif
546 
547  OSTaskDelHook(p_tcb); /* Call user defined hook */
548 
549 #if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
550  OS_TLS_TaskDel(p_tcb); /* Call TLS hook */
551 #endif
552 
553 #if OS_CFG_DBG_EN > 0u
554  OS_TaskDbgListRemove(p_tcb);
555 #endif
556  OSTaskQty--; /* One less task being managed */
557 
558  OS_TaskInitTCB(p_tcb); /* Initialize the TCB to default values */
559  p_tcb->TaskState = (OS_STATE)OS_TASK_STATE_DEL; /* Indicate that the task was deleted */
560 
562 
563  *p_err = OS_ERR_NONE; /* See Note #1. */
564 
565  OSSched(); /* Find new highest priority task */
566 }
567 #endif
568 
569 /*$PAGE*/
570 /*
571 ************************************************************************************************************************
572 * FLUSH TASK's QUEUE
573 *
574 * Description: This function is used to flush the task's internal message queue.
575 *
576 * Arguments : p_tcb is a pointer to the task's OS_TCB. Specifying a NULL pointer indicates that you wish to
577 * flush the message queue of the calling task.
578 *
579 * p_err is a pointer to a variable that will contain an error code returned by this function.
580 *
581 * OS_ERR_NONE upon success
582 * OS_ERR_FLUSH_ISR if you called this function from an ISR
583 *
584 * Returns : The number of entries freed from the queue
585 *
586 * Note(s) : 1) You should use this function with great care because, when to flush the queue, you LOOSE the
587 * references to what the queue entries are pointing to and thus, you could cause 'memory leaks'. In
588 * other words, the data you are pointing to that's being referenced by the queue entries should, most
589 * likely, need to be de-allocated (i.e. freed).
590 ************************************************************************************************************************
591 */
592 
593 #if OS_CFG_TASK_Q_EN > 0u
594 OS_MSG_QTY OSTaskQFlush (OS_TCB *p_tcb,
595  OS_ERR *p_err)
596 {
597  OS_MSG_QTY entries;
598  CPU_SR_ALLOC();
599 
600 
601 
602 #ifdef OS_SAFETY_CRITICAL
603  if (p_err == (OS_ERR *)0) {
604  OS_SAFETY_CRITICAL_EXCEPTION();
605  return ((OS_MSG_QTY)0);
606  }
607 #endif
608 
609 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
610  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't flush a message queue from an ISR */
611  *p_err = OS_ERR_FLUSH_ISR;
612  return ((OS_MSG_QTY)0);
613  }
614 #endif
615 
616  if (p_tcb == (OS_TCB *)0) { /* Flush message queue of calling task? */
618  p_tcb = OSTCBCurPtr;
620  }
621 
623  entries = OS_MsgQFreeAll(&p_tcb->MsgQ); /* Return all OS_MSGs to the OS_MSG pool */
625  *p_err = OS_ERR_NONE;
626  return (entries);
627 }
628 #endif
629 
630 /*$PAGE*/
631 /*
632 ************************************************************************************************************************
633 * WAIT FOR A MESSAGE
634 *
635 * Description: This function causes the current task to wait for a message to be posted to it.
636 *
637 * Arguments : timeout is an optional timeout period (in clock ticks). If non-zero, your task will wait for a
638 * message to arrive up to the amount of time specified by this argument.
639 * If you specify 0, however, your task will wait forever or, until a message arrives.
640 *
641 * opt determines whether the user wants to block if the task's queue is empty or not:
642 *
643 * OS_OPT_PEND_BLOCKING
644 * OS_OPT_PEND_NON_BLOCKING
645 *
646 * p_msg_size is a pointer to a variable that will receive the size of the message
647 *
648 * p_ts is a pointer to a variable that will receive the timestamp of when the message was
649 * received. If you pass a NULL pointer (i.e. (CPU_TS *)0) then you will not get the
650 * timestamp. In other words, passing a NULL pointer is valid and indicates that you don't
651 * need the timestamp.
652 *
653 * p_err is a pointer to where an error message will be deposited. Possible error
654 * messages are:
655 *
656 * OS_ERR_NONE The call was successful and your task received a message.
657 * OS_ERR_PEND_ABORT
658 * OS_ERR_PEND_ISR If you called this function from an ISR and the result
659 * OS_ERR_PEND_WOULD_BLOCK If you specified non-blocking but the queue was not empty
660 * OS_ERR_Q_EMPTY
661 * OS_ERR_SCHED_LOCKED If the scheduler is locked
662 * OS_ERR_TIMEOUT A message was not received within the specified timeout
663 * would lead to a suspension.
664 *
665 * Returns : A pointer to the message received or a NULL pointer upon error.
666 *
667 * Note(s) : 1) It is possible to receive NULL pointers when there are no errors.
668 ************************************************************************************************************************
669 */
670 
671 #if OS_CFG_TASK_Q_EN > 0u
672 void *OSTaskQPend (OS_TICK timeout,
673  OS_OPT opt,
674  OS_MSG_SIZE *p_msg_size,
675  CPU_TS *p_ts,
676  OS_ERR *p_err)
677 {
678  OS_MSG_Q *p_msg_q;
679  void *p_void;
680  CPU_SR_ALLOC();
681 
682 
683 
684 #ifdef OS_SAFETY_CRITICAL
685  if (p_err == (OS_ERR *)0) {
686  OS_SAFETY_CRITICAL_EXCEPTION();
687  return ((void *)0);
688  }
689 #endif
690 
691 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
692  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't Pend from an ISR */
693  *p_err = OS_ERR_PEND_ISR;
694  return ((void *)0);
695  }
696 #endif
697 
698 #if OS_CFG_ARG_CHK_EN > 0u /* ---------------- VALIDATE ARGUMENTS ------------------ */
699  if (p_msg_size == (OS_MSG_SIZE *)0) { /* User must supply a valid destination for msg size */
700  *p_err = OS_ERR_PTR_INVALID;
701  return ((void *)0);
702  }
703  switch (opt) { /* User must supply a valid option */
706  break;
707 
708  default:
709  *p_err = OS_ERR_OPT_INVALID;
710  return ((void *)0);
711  }
712 #endif
713 
714  if (p_ts != (CPU_TS *)0) {
715  *p_ts = (CPU_TS )0; /* Initialize the returned timestamp */
716  }
717 
719  p_msg_q = &OSTCBCurPtr->MsgQ; /* Any message waiting in the message queue? */
720  p_void = OS_MsgQGet(p_msg_q,
721  p_msg_size,
722  p_ts,
723  p_err);
724  if (*p_err == OS_ERR_NONE) {
725 #if OS_CFG_TASK_PROFILE_EN > 0u
726  if (p_ts != (CPU_TS *)0) {
727  OSTCBCurPtr->MsgQPendTime = OS_TS_GET() - *p_ts;
728  if (OSTCBCurPtr->MsgQPendTimeMax < OSTCBCurPtr->MsgQPendTime) {
729  OSTCBCurPtr->MsgQPendTimeMax = OSTCBCurPtr->MsgQPendTime;
730  }
731  }
732 #endif
734  return (p_void); /* Yes, Return oldest message received */
735  }
736 
737  if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) { /* Caller wants to block if not available? */
738  *p_err = OS_ERR_PEND_WOULD_BLOCK; /* No */
740  return ((void *)0);
741  } else { /* Yes */
742  if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't block when the scheduler is locked */
744  *p_err = OS_ERR_SCHED_LOCKED;
745  return ((void *)0);
746  }
747  }
748 
749  OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT(); /* Lock the scheduler/re-enable interrupts */
750  OS_Pend((OS_PEND_DATA *)0, /* Block task pending on Message */
751  (OS_PEND_OBJ *)0,
753  (OS_TICK )timeout);
755 
756  OSSched(); /* Find the next highest priority task ready to run */
757 
759  switch (OSTCBCurPtr->PendStatus) {
760  case OS_STATUS_PEND_OK: /* Extract message from TCB (Put there by Post) */
761  p_void = OSTCBCurPtr->MsgPtr;
762  *p_msg_size = OSTCBCurPtr->MsgSize;
763  if (p_ts != (CPU_TS *)0) {
764  *p_ts = OSTCBCurPtr->TS;
765 #if OS_CFG_TASK_PROFILE_EN > 0u
766  OSTCBCurPtr->MsgQPendTime = OS_TS_GET() - OSTCBCurPtr->TS;
767  if (OSTCBCurPtr->MsgQPendTimeMax < OSTCBCurPtr->MsgQPendTime) {
768  OSTCBCurPtr->MsgQPendTimeMax = OSTCBCurPtr->MsgQPendTime;
769  }
770 #endif
771  }
772  *p_err = OS_ERR_NONE;
773  break;
774 
775  case OS_STATUS_PEND_ABORT: /* Indicate that we aborted */
776  p_void = (void *)0;
777  *p_msg_size = (OS_MSG_SIZE)0;
778  if (p_ts != (CPU_TS *)0) {
779  *p_ts = (CPU_TS )0;
780  }
781  *p_err = OS_ERR_PEND_ABORT;
782  break;
783 
784  case OS_STATUS_PEND_TIMEOUT: /* Indicate that we didn't get event within TO */
785  default:
786  p_void = (void *)0;
787  *p_msg_size = (OS_MSG_SIZE)0;
788  if (p_ts != (CPU_TS *)0) {
789  *p_ts = OSTCBCurPtr->TS;
790  }
791  *p_err = OS_ERR_TIMEOUT;
792  break;
793  }
795  return (p_void); /* Return received message */
796 }
797 #endif
798 
799 /*$PAGE*/
800 /*
801 ************************************************************************************************************************
802 * ABORT WAITING FOR A MESSAGE
803 *
804 * Description: This function aborts & readies the task specified. This function should be used to fault-abort the wait
805 * for a message, rather than to normally post the message to the task via OSTaskQPost().
806 *
807 * Arguments : p_tcb is a pointer to the task to pend abort
808 *
809 * opt provides options for this function:
810 *
811 * OS_OPT_POST_NONE No option specified
812 * OS_OPT_POST_NO_SCHED Indicates that the scheduler will not be called.
813 *
814 * p_err is a pointer to a variable that will contain an error code returned by this function.
815 *
816 * OS_ERR_NONE If the task was readied and informed of the aborted wait
817 * OS_ERR_PEND_ABORT_ISR If you called this function from an ISR
818 * OS_ERR_PEND_ABORT_NONE If task was not pending on a message and thus there is nothing to
819 * abort.
820 * OS_ERR_PEND_ABORT_SELF If you passed a NULL pointer for 'p_tcb'
821 *
822 * Returns : == DEF_FALSE if task was not waiting for a message, or upon error.
823 * == DEF_TRUE if task was waiting for a message and was readied and informed.
824 ************************************************************************************************************************
825 */
826 
827 #if (OS_CFG_TASK_Q_EN > 0u) && (OS_CFG_TASK_Q_PEND_ABORT_EN > 0u)
828 CPU_BOOLEAN OSTaskQPendAbort (OS_TCB *p_tcb,
829  OS_OPT opt,
830  OS_ERR *p_err)
831 {
832  CPU_TS ts;
833  CPU_SR_ALLOC();
834 
835 
836 
837 #ifdef OS_SAFETY_CRITICAL
838  if (p_err == (OS_ERR *)0) {
839  OS_SAFETY_CRITICAL_EXCEPTION();
840  return (DEF_FALSE);
841  }
842 #endif
843 
844 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
845  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from ISR ... */
846  *p_err = OS_ERR_PEND_ABORT_ISR; /* ... can't Pend Abort from an ISR */
847  return (DEF_FALSE);
848  }
849 #endif
850 
851 #if OS_CFG_ARG_CHK_EN > 0u /* ---------------- VALIDATE ARGUMENTS ------------------ */
852  switch (opt) { /* User must supply a valid option */
853  case OS_OPT_POST_NONE:
855  break;
856 
857  default:
858  *p_err = OS_ERR_OPT_INVALID;
859  return (DEF_FALSE);
860  }
861 #endif
862 
864 #if OS_CFG_ARG_CHK_EN > 0u
865  if ((p_tcb == (OS_TCB *)0) || /* Pend abort self? */
866  (p_tcb == OSTCBCurPtr)) {
868  *p_err = OS_ERR_PEND_ABORT_SELF; /* ... doesn't make sense */
869  return (DEF_FALSE);
870  }
871 #endif
872 
873  if (p_tcb->PendOn != OS_TASK_PEND_ON_TASK_Q) { /* Is task waiting for a message? */
874  CPU_CRITICAL_EXIT(); /* No */
875  *p_err = OS_ERR_PEND_ABORT_NONE;
876  return (DEF_FALSE);
877  }
878 
880  ts = OS_TS_GET(); /* Get timestamp of when the abort occurred */
881  OS_PendAbort((OS_PEND_OBJ *)0, /* Abort the pend */
882  p_tcb,
883  ts);
885  if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0) {
886  OSSched(); /* Run the scheduler */
887  }
888  *p_err = OS_ERR_NONE;
889  return (DEF_TRUE);
890 }
891 #endif
892 
893 /*$PAGE*/
894 /*
895 ************************************************************************************************************************
896 * POST MESSAGE TO A TASK
897 *
898 * Description: This function sends a message to a task
899 *
900 * Arguments : p_tcb is a pointer to the TCB of the task receiving a message. If you specify a NULL pointer then
901 * the message will be posted to the task's queue of the calling task. In other words, you'd be
902 * posting a message to yourself.
903 *
904 * p_void is a pointer to the message to send.
905 *
906 * msg_size is the size of the message sent (in #bytes)
907 *
908 * opt specifies whether the post will be FIFO or LIFO:
909 *
910 * OS_OPT_POST_FIFO Post at the end of the queue
911 * OS_OPT_POST_LIFO Post at the front of the queue
912 *
913 * OS_OPT_POST_NO_SCHED Do not run the scheduler after the post
914 *
915 * Note(s): 1) OS_OPT_POST_NO_SCHED can be added with one of the other options.
916 *
917 *
918 * p_err is a pointer to a variable that will hold the error code associated
919 * with the outcome of this call. Errors can be:
920 *
921 * OS_ERR_NONE The call was successful and the message was sent
922 * OS_ERR_Q_MAX If the queue is full
923 * OS_ERR_MSG_POOL_EMPTY If there are no more OS_MSGs available from the pool
924 *
925 * Returns : none
926 ************************************************************************************************************************
927 */
928 
929 #if OS_CFG_TASK_Q_EN > 0u
930 void OSTaskQPost (OS_TCB *p_tcb,
931  void *p_void,
932  OS_MSG_SIZE msg_size,
933  OS_OPT opt,
934  OS_ERR *p_err)
935 {
936  CPU_TS ts;
937 
938 
939 
940 #ifdef OS_SAFETY_CRITICAL
941  if (p_err == (OS_ERR *)0) {
942  OS_SAFETY_CRITICAL_EXCEPTION();
943  return;
944  }
945 #endif
946 
947 #if OS_CFG_ARG_CHK_EN > 0u /* ---------------- VALIDATE ARGUMENTS ------------------ */
948  switch (opt) { /* User must supply a valid option */
949  case OS_OPT_POST_FIFO:
950  case OS_OPT_POST_LIFO:
951  case OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED:
952  case OS_OPT_POST_LIFO | OS_OPT_POST_NO_SCHED:
953  break;
954 
955  default:
956  *p_err = OS_ERR_OPT_INVALID;
957  return;
958  }
959 #endif
960 
961  ts = OS_TS_GET(); /* Get timestamp */
962 
963 #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
964  if (OSIntNestingCtr > (OS_NESTING_CTR)0) {
965  OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_TASK_MSG, /* Post to ISR queue */
966  (void *)p_tcb,
967  (void *)p_void,
968  (OS_MSG_SIZE)msg_size,
969  (OS_FLAGS )0,
970  (OS_OPT )opt,
971  (CPU_TS )ts,
972  (OS_ERR *)p_err);
973  return;
974  }
975 #endif
976 
977  OS_TaskQPost(p_tcb,
978  p_void,
979  msg_size,
980  opt,
981  ts,
982  p_err);
983 }
984 #endif
985 
986 /*$PAGE*/
987 /*
988 ************************************************************************************************************************
989 * GET THE CURRENT VALUE OF A TASK REGISTER
990 *
991 * Description: This function is called to obtain the current value of a task register. Task registers are application
992 * specific and can be used to store task specific values such as 'error numbers' (i.e. errno), statistics,
993 * etc.
994 *
995 * Arguments : p_tcb is a pointer to the OS_TCB of the task you want to read the register from. If 'p_tcb' is a
996 * NULL pointer then you will get the register of the current task.
997 *
998 * id is the 'id' of the desired task variable. Note that the 'id' must be less than
999 * OS_CFG_TASK_REG_TBL_SIZE
1000 *
1001 * p_err is a pointer to a variable that will hold an error code related to this call.
1002 *
1003 * OS_ERR_NONE if the call was successful
1004 * OS_ERR_REG_ID_INVALID if the 'id' is not between 0 and OS_CFG_TASK_REG_TBL_SIZE-1
1005 *
1006 * Returns : The current value of the task's register or 0 if an error is detected.
1007 ************************************************************************************************************************
1008 */
1009 
1010 #if OS_CFG_TASK_REG_TBL_SIZE > 0u
1011 OS_REG OSTaskRegGet (OS_TCB *p_tcb,
1012  OS_REG_ID id,
1013  OS_ERR *p_err)
1014 {
1015  OS_REG value;
1016  CPU_SR_ALLOC();
1017 
1018 
1019 
1020 #ifdef OS_SAFETY_CRITICAL
1021  if (p_err == (OS_ERR *)0) {
1022  OS_SAFETY_CRITICAL_EXCEPTION();
1023  return ((OS_REG)0);
1024  }
1025 #endif
1026 
1027 #if OS_CFG_ARG_CHK_EN > 0u
1028  if (id >= OS_CFG_TASK_REG_TBL_SIZE) {
1029  *p_err = OS_ERR_REG_ID_INVALID;
1030  return ((OS_REG)0);
1031  }
1032 #endif
1033 
1035  if (p_tcb == (OS_TCB *)0) {
1036  p_tcb = OSTCBCurPtr;
1037  }
1038  value = p_tcb->RegTbl[id];
1040  *p_err = OS_ERR_NONE;
1041  return ((OS_REG)value);
1042 }
1043 #endif
1044 
1045 /*$PAGE*/
1046 /*
1047 ************************************************************************************************************************
1048 * ALLOCATE THE NEXT AVAILABLE TASK REGISTER ID
1049 *
1050 * Description: This function is called to obtain a task register ID. This function thus allows task registers IDs to be
1051 * allocated dynamically instead of statically.
1052 *
1053 * Arguments : p_err is a pointer to a variable that will hold an error code related to this call.
1054 *
1055 * OS_ERR_NONE if the call was successful
1056 * OS_ERR_NO_MORE_ID_AVAIL if you are attempting to assign more task register IDs than you
1057 * have available through OS_CFG_TASK_REG_TBL_SIZE.
1058 *
1059 * Returns : The next available task register 'id' or OS_CFG_TASK_REG_TBL_SIZE if an error is detected.
1060 ************************************************************************************************************************
1061 */
1062 
1063 #if OS_CFG_TASK_REG_TBL_SIZE > 0u
1064 OS_REG_ID OSTaskRegGetID (OS_ERR *p_err)
1065 {
1066  OS_REG_ID id;
1067  CPU_SR_ALLOC();
1068 
1069 
1070 
1071 #ifdef OS_SAFETY_CRITICAL
1072  if (p_err == (OS_ERR *)0) {
1073  OS_SAFETY_CRITICAL_EXCEPTION();
1075  }
1076 #endif
1077 
1079  if (OSTaskRegNextAvailID >= OS_CFG_TASK_REG_TBL_SIZE) { /* See if we exceeded the number of IDs available */
1080  *p_err = OS_ERR_NO_MORE_ID_AVAIL; /* Yes, cannot allocate more task register IDs */
1083  }
1084 
1085  id = OSTaskRegNextAvailID; /* Assign the next available ID */
1086  OSTaskRegNextAvailID++; /* Increment available ID for next request */
1088  *p_err = OS_ERR_NONE;
1089  return (id);
1090 }
1091 #endif
1092 
1093 /*$PAGE*/
1094 /*
1095 ************************************************************************************************************************
1096 * SET THE CURRENT VALUE OF A TASK REGISTER
1097 *
1098 * Description: This function is called to change the current value of a task register. Task registers are application
1099 * specific and can be used to store task specific values such as 'error numbers' (i.e. errno), statistics,
1100 * etc.
1101 *
1102 * Arguments : p_tcb is a pointer to the OS_TCB of the task you want to set the register for. If 'p_tcb' is a NULL
1103 * pointer then you will change the register of the current task.
1104 *
1105 * id is the 'id' of the desired task register. Note that the 'id' must be less than
1106 * OS_CFG_TASK_REG_TBL_SIZE
1107 *
1108 * value is the desired value for the task register.
1109 *
1110 * p_err is a pointer to a variable that will hold an error code related to this call.
1111 *
1112 * OS_ERR_NONE if the call was successful
1113 * OS_ERR_REG_ID_INVALID if the 'id' is not between 0 and OS_CFG_TASK_REG_TBL_SIZE-1
1114 *
1115 * Returns : none
1116 ************************************************************************************************************************
1117 */
1118 
1119 #if OS_CFG_TASK_REG_TBL_SIZE > 0u
1120 void OSTaskRegSet (OS_TCB *p_tcb,
1121  OS_REG_ID id,
1122  OS_REG value,
1123  OS_ERR *p_err)
1124 {
1125  CPU_SR_ALLOC();
1126 
1127 
1128 
1129 #ifdef OS_SAFETY_CRITICAL
1130  if (p_err == (OS_ERR *)0) {
1131  OS_SAFETY_CRITICAL_EXCEPTION();
1132  return;
1133  }
1134 #endif
1135 
1136 #if OS_CFG_ARG_CHK_EN > 0u
1137  if (id >= OS_CFG_TASK_REG_TBL_SIZE) {
1138  *p_err = OS_ERR_REG_ID_INVALID;
1139  return;
1140  }
1141 #endif
1142 
1144  if (p_tcb == (OS_TCB *)0) {
1145  p_tcb = OSTCBCurPtr;
1146  }
1147  p_tcb->RegTbl[id] = value;
1149  *p_err = OS_ERR_NONE;
1150 }
1151 #endif
1152 
1153 /*$PAGE*/
1154 /*
1155 ************************************************************************************************************************
1156 * RESUME A SUSPENDED TASK
1157 *
1158 * Description: This function is called to resume a previously suspended task. This is the only call that will remove an
1159 * explicit task suspension.
1160 *
1161 * Arguments : p_tcb Is a pointer to the task's OS_TCB to resume
1162 *
1163 * p_err Is a pointer to a variable that will contain an error code returned by this function
1164 *
1165 * OS_ERR_NONE if the requested task is resumed
1166 * OS_ERR_STATE_INVALID if the task is in an invalid state
1167 * OS_ERR_TASK_RESUME_ISR if you called this function from an ISR
1168 * OS_ERR_TASK_RESUME_SELF You cannot resume 'self'
1169 * OS_ERR_TASK_NOT_SUSPENDED if the task to resume has not been suspended
1170 *
1171 * Returns : none
1172 ************************************************************************************************************************
1173 */
1174 
1175 #if OS_CFG_TASK_SUSPEND_EN > 0u
1176 void OSTaskResume (OS_TCB *p_tcb,
1177  OS_ERR *p_err)
1178 {
1179  CPU_SR_ALLOC();
1180 
1181 
1182 
1183 #ifdef OS_SAFETY_CRITICAL
1184  if (p_err == (OS_ERR *)0) {
1185  OS_SAFETY_CRITICAL_EXCEPTION();
1186  return;
1187  }
1188 #endif
1189 
1190 #if (OS_CFG_ISR_POST_DEFERRED_EN == 0u) && \
1191  (OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u)
1192  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
1193  *p_err = OS_ERR_TASK_RESUME_ISR;
1194  return;
1195  }
1196 #endif
1197 
1198 
1200 #if OS_CFG_ARG_CHK_EN > 0u
1201  if ((p_tcb == (OS_TCB *)0) || /* We cannot resume 'self' */
1202  (p_tcb == OSTCBCurPtr)) {
1204  *p_err = OS_ERR_TASK_RESUME_SELF;
1205  return;
1206  }
1207 #endif
1209 
1210 #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
1211  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from an ISR */
1212  OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_TASK_RESUME, /* Post to ISR queue */
1213  (void *)p_tcb,
1214  (void *)0,
1215  (OS_MSG_SIZE)0,
1216  (OS_FLAGS )0,
1217  (OS_OPT )0,
1218  (CPU_TS )0,
1219  (OS_ERR *)p_err);
1220  return;
1221  }
1222 #endif
1223 
1224  OS_TaskResume(p_tcb, p_err);
1225 }
1226 #endif
1227 
1228 /*$PAGE*/
1229 /*
1230 ************************************************************************************************************************
1231 * WAIT FOR A TASK SEMAPHORE
1232 *
1233 * Description: This function is called to block the current task until a signal is sent by another task or ISR.
1234 *
1235 * Arguments : timeout is the amount of time you are will to wait for the signal
1236 *
1237 * opt determines whether the user wants to block if a semaphore post was not received:
1238 *
1239 * OS_OPT_PEND_BLOCKING
1240 * OS_OPT_PEND_NON_BLOCKING
1241 *
1242 * p_ts is a pointer to a variable that will receive the timestamp of when the semaphore was posted
1243 * or pend aborted. If you pass a NULL pointer (i.e. (CPU_TS *)0) then you will not get the
1244 * timestamp. In other words, passing a NULL pointer is valid and indicates that you don't
1245 * need the timestamp.
1246 *
1247 * p_err is a pointer to an error code that will be set by this function
1248 *
1249 * OS_ERR_NONE The call was successful and your task received a message.
1250 * OS_ERR_PEND_ABORT
1251 * OS_ERR_PEND_ISR If you called this function from an ISR and the result
1252 * OS_ERR_PEND_WOULD_BLOCK If you specified non-blocking but no signal was received
1253 * OS_ERR_SCHED_LOCKED If the scheduler is locked
1254 * OS_ERR_STATUS_INVALID If the pend status is invalid
1255 * OS_ERR_TIMEOUT A message was not received within the specified timeout
1256 * would lead to a suspension.
1257 *
1258 * Returns : The current count of signals the task received, 0 if none.
1259 ************************************************************************************************************************
1260 */
1261 
1263  OS_OPT opt,
1264  CPU_TS *p_ts,
1265  OS_ERR *p_err)
1266 {
1267  OS_SEM_CTR ctr;
1268  CPU_SR_ALLOC();
1269 
1270 
1271 
1272 #ifdef OS_SAFETY_CRITICAL
1273  if (p_err == (OS_ERR *)0) {
1274  OS_SAFETY_CRITICAL_EXCEPTION();
1275  return ((OS_SEM_CTR)0);
1276  }
1277 #endif
1278 
1279 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
1280  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
1281  *p_err = OS_ERR_PEND_ISR;
1282  return ((OS_SEM_CTR)0);
1283  }
1284 #endif
1285 
1286 #if OS_CFG_ARG_CHK_EN > 0u
1287  switch (opt) { /* Validate 'opt' */
1288  case OS_OPT_PEND_BLOCKING:
1289  case OS_OPT_PEND_NON_BLOCKING:
1290  break;
1291 
1292  default:
1293  *p_err = OS_ERR_OPT_INVALID;
1294  return ((OS_SEM_CTR)0);
1295  }
1296 #endif
1297 
1298  if (p_ts != (CPU_TS *)0) {
1299  *p_ts = (CPU_TS )0; /* Initialize the returned timestamp */
1300  }
1301 
1303  if (OSTCBCurPtr->SemCtr > (OS_SEM_CTR)0) { /* See if task already been signaled */
1304  OSTCBCurPtr->SemCtr--;
1305  ctr = OSTCBCurPtr->SemCtr;
1306  if (p_ts != (CPU_TS *)0) {
1307  *p_ts = OSTCBCurPtr->TS;
1308  }
1309 #if OS_CFG_TASK_PROFILE_EN > 0u
1310  OSTCBCurPtr->SemPendTime = OS_TS_GET() - OSTCBCurPtr->TS;
1311  if (OSTCBCurPtr->SemPendTimeMax < OSTCBCurPtr->SemPendTime) {
1312  OSTCBCurPtr->SemPendTimeMax = OSTCBCurPtr->SemPendTime;
1313  }
1314 #endif
1316  *p_err = OS_ERR_NONE;
1317  return (ctr);
1318  }
1319 
1320  if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) { /* Caller wants to block if not available? */
1322  *p_err = OS_ERR_PEND_WOULD_BLOCK; /* No */
1323  return ((OS_SEM_CTR)0);
1324  } else { /* Yes */
1325  if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't pend when the scheduler is locked */
1327  *p_err = OS_ERR_SCHED_LOCKED;
1328  return ((OS_SEM_CTR)0);
1329  }
1330  }
1331 
1332  OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT(); /* Lock the scheduler/re-enable interrupts */
1333  OS_Pend((OS_PEND_DATA *)0, /* Block task pending on Signal */
1334  (OS_PEND_OBJ *)0,
1336  (OS_TICK )timeout);
1338 
1339  OSSched(); /* Find next highest priority task ready to run */
1340 
1342  switch (OSTCBCurPtr->PendStatus) { /* See if we timed-out or aborted */
1343  case OS_STATUS_PEND_OK:
1344  if (p_ts != (CPU_TS *)0) {
1345  *p_ts = OSTCBCurPtr->TS;
1346 #if OS_CFG_TASK_PROFILE_EN > 0u
1347  OSTCBCurPtr->SemPendTime = OS_TS_GET() - OSTCBCurPtr->TS;
1348  if (OSTCBCurPtr->SemPendTimeMax < OSTCBCurPtr->SemPendTime) {
1349  OSTCBCurPtr->SemPendTimeMax = OSTCBCurPtr->SemPendTime;
1350  }
1351 #endif
1352  }
1353  *p_err = OS_ERR_NONE;
1354  break;
1355 
1356  case OS_STATUS_PEND_ABORT:
1357  if (p_ts != (CPU_TS *)0) {
1358  *p_ts = OSTCBCurPtr->TS;
1359  }
1360  *p_err = OS_ERR_PEND_ABORT; /* Indicate that we aborted */
1361  break;
1362 
1364  if (p_ts != (CPU_TS *)0) {
1365  *p_ts = (CPU_TS )0;
1366  }
1367  *p_err = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */
1368  break;
1369 
1370  default:
1371  *p_err = OS_ERR_STATUS_INVALID;
1372  break;
1373  }
1374  ctr = OSTCBCurPtr->SemCtr;
1376  return (ctr);
1377 }
1378 
1379 /*$PAGE*/
1380 /*
1381 ************************************************************************************************************************
1382 * ABORT WAITING FOR A SIGNAL
1383 *
1384 * Description: This function aborts & readies the task specified. This function should be used to fault-abort the wait
1385 * for a signal, rather than to normally post the signal to the task via OSTaskSemPost().
1386 *
1387 * Arguments : p_tcb is a pointer to the task to pend abort
1388 *
1389 * opt provides options for this function:
1390 *
1391 * OS_OPT_POST_NONE No option selected
1392 * OS_OPT_POST_NO_SCHED Indicates that the scheduler will not be called.
1393 *
1394 * p_err is a pointer to a variable that will contain an error code returned by this function.
1395 *
1396 * OS_ERR_NONE If the task was readied and informed of the aborted wait
1397 * OS_ERR_PEND_ABORT_ISR If you tried calling this function from an ISR
1398 * OS_ERR_PEND_ABORT_NONE If the task was not waiting for a signal
1399 * OS_ERR_PEND_ABORT_SELF If you attempted to pend abort the calling task. This is not
1400 * possible since the calling task cannot be pending because it's
1401 * running.
1402 *
1403 * Returns : == DEF_FALSE if task was not waiting for a message, or upon error.
1404 * == DEF_TRUE if task was waiting for a message and was readied and informed.
1405 ************************************************************************************************************************
1406 */
1407 
1408 #if OS_CFG_TASK_SEM_PEND_ABORT_EN > 0u
1409 CPU_BOOLEAN OSTaskSemPendAbort (OS_TCB *p_tcb,
1410  OS_OPT opt,
1411  OS_ERR *p_err)
1412 {
1413  CPU_TS ts;
1414  CPU_SR_ALLOC();
1415 
1416 
1417 
1418 #ifdef OS_SAFETY_CRITICAL
1419  if (p_err == (OS_ERR *)0) {
1420  OS_SAFETY_CRITICAL_EXCEPTION();
1421  return (DEF_FALSE);
1422  }
1423 #endif
1424 
1425 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
1426  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from ISR ... */
1427  *p_err = OS_ERR_PEND_ABORT_ISR; /* ... can't Pend Abort from an ISR */
1428  return (DEF_FALSE);
1429  }
1430 #endif
1431 
1432 #if OS_CFG_ARG_CHK_EN > 0u
1433  switch (opt) { /* Validate 'opt' */
1434  case OS_OPT_POST_NONE:
1435  case OS_OPT_POST_NO_SCHED:
1436  break;
1437 
1438  default:
1439  *p_err = OS_ERR_OPT_INVALID;
1440  return (DEF_FALSE);
1441  }
1442 #endif
1443 
1445  if ((p_tcb == (OS_TCB *)0) || /* Pend abort self? */
1446  (p_tcb == OSTCBCurPtr)) {
1447  CPU_CRITICAL_EXIT(); /* ... doesn't make sense! */
1448  *p_err = OS_ERR_PEND_ABORT_SELF;
1449  return (DEF_FALSE);
1450  }
1451 
1452  if (p_tcb->PendOn != OS_TASK_PEND_ON_TASK_SEM) { /* Is task waiting for a signal? */
1454  *p_err = OS_ERR_PEND_ABORT_NONE;
1455  return (DEF_FALSE);
1456  }
1458 
1460  ts = OS_TS_GET();
1461  OS_PendAbort((OS_PEND_OBJ *)0,
1462  p_tcb,
1463  ts);
1465  if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0) {
1466  OSSched(); /* Run the scheduler */
1467  }
1468  *p_err = OS_ERR_NONE;
1469  return (DEF_TRUE);
1470 }
1471 #endif
1472 
1473 /*$PAGE*/
1474 /*
1475 ************************************************************************************************************************
1476 * SIGNAL A TASK
1477 *
1478 * Description: This function is called to signal a task waiting for a signal.
1479 *
1480 * Arguments : p_tcb is the pointer to the TCB of the task to signal. A NULL pointer indicates that you are sending
1481 * a signal to yourself.
1482 *
1483 * opt determines the type of POST performed:
1484 *
1485 * OS_OPT_POST_NONE No option
1486 * OS_OPT_POST_NO_SCHED Do not call the scheduler
1487 *
1488 * p_err is a pointer to an error code returned by this function:
1489 *
1490 * OS_ERR_NONE If the requested task is signaled
1491 * OS_ERR_SEM_OVF If the post would cause the semaphore count to overflow.
1492 *
1493 * Returns : The current value of the task's signal counter or 0 if called from an ISR
1494 ************************************************************************************************************************
1495 */
1496 
1497 OS_SEM_CTR OSTaskSemPost (OS_TCB *p_tcb,
1498  OS_OPT opt,
1499  OS_ERR *p_err)
1500 {
1501  OS_SEM_CTR ctr;
1502  CPU_TS ts;
1503 
1504 
1505 
1506 #ifdef OS_SAFETY_CRITICAL
1507  if (p_err == (OS_ERR *)0) {
1508  OS_SAFETY_CRITICAL_EXCEPTION();
1509  return ((OS_SEM_CTR)0);
1510  }
1511 #endif
1512 
1513 #if OS_CFG_ARG_CHK_EN > 0u
1514  switch (opt) { /* Validate 'opt' */
1515  case OS_OPT_POST_NONE:
1516  case OS_OPT_POST_NO_SCHED:
1517  break;
1518 
1519  default:
1520  *p_err = OS_ERR_OPT_INVALID;
1521  return ((OS_SEM_CTR)0u);
1522  }
1523 #endif
1524 
1525  ts = OS_TS_GET(); /* Get timestamp */
1526 
1527 #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
1528  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from an ISR */
1529  OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_TASK_SIGNAL, /* Post to ISR queue */
1530  (void *)p_tcb,
1531  (void *)0,
1532  (OS_MSG_SIZE)0,
1533  (OS_FLAGS )0,
1534  (OS_OPT )0,
1535  (CPU_TS )ts,
1536  (OS_ERR *)p_err);
1537  return ((OS_SEM_CTR)0);
1538  }
1539 #endif
1540 
1541  ctr = OS_TaskSemPost(p_tcb,
1542  opt,
1543  ts,
1544  p_err);
1545 
1546  return (ctr);
1547 }
1548 
1549 /*$PAGE*/
1550 /*
1551 ************************************************************************************************************************
1552 * SET THE SIGNAL COUNTER OF A TASK
1553 *
1554 * Description: This function is called to clear the signal counter
1555 *
1556 * Arguments : p_tcb is the pointer to the TCB of the task to clear the counter. If you specify a NULL pointer
1557 * then the signal counter of the current task will be cleared.
1558 *
1559 * cnt is the desired value of the semaphore counter
1560 *
1561 * p_err is a pointer to an error code returned by this function
1562 *
1563 * OS_ERR_NONE if the signal counter of the requested task is cleared
1564 * OS_ERR_SET_ISR if the function was called from an ISR
1565 *
1566 * Returns : none
1567 ************************************************************************************************************************
1568 */
1569 
1570 OS_SEM_CTR OSTaskSemSet (OS_TCB *p_tcb,
1571  OS_SEM_CTR cnt,
1572  OS_ERR *p_err)
1573 {
1574  OS_SEM_CTR ctr;
1575  CPU_SR_ALLOC();
1576 
1577 
1578 
1579 #ifdef OS_SAFETY_CRITICAL
1580  if (p_err == (OS_ERR *)0) {
1581  OS_SAFETY_CRITICAL_EXCEPTION();
1582  return ((OS_SEM_CTR)0);
1583  }
1584 #endif
1585 
1586 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
1587  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
1588  *p_err = OS_ERR_SET_ISR;
1589  return ((OS_SEM_CTR)0);
1590  }
1591 #endif
1592 
1594  if (p_tcb == (OS_TCB *)0) {
1595  p_tcb = OSTCBCurPtr;
1596  }
1597  ctr = p_tcb->SemCtr;
1598  p_tcb->SemCtr = (OS_SEM_CTR)cnt;
1600  *p_err = OS_ERR_NONE;
1601  return (ctr);
1602 }
1603 
1604 /*$PAGE*/
1605 /*
1606 ************************************************************************************************************************
1607 * STACK CHECKING
1608 *
1609 * Description: This function is called to calculate the amount of free memory left on the specified task's stack.
1610 *
1611 * Arguments : p_tcb is a pointer to the TCB of the task to check. If you specify a NULL pointer then
1612 * you are specifying that you want to check the stack of the current task.
1613 *
1614 * p_free is a pointer to a variable that will receive the number of free 'entries' on the task's stack.
1615 *
1616 * p_used is a pointer to a variable that will receive the number of used 'entries' on the task's stack.
1617 *
1618 * p_err is a pointer to a variable that will contain an error code.
1619 *
1620 * OS_ERR_NONE upon success
1621 * OS_ERR_PTR_INVALID if either 'p_free' or 'p_used' are NULL pointers
1622 * OS_ERR_TASK_NOT_EXIST if the stack pointer of the task is a NULL pointer
1623 * OS_ERR_TASK_OPT if you did NOT specified OS_OPT_TASK_STK_CHK when the task
1624 * was created
1625 * OS_ERR_TASK_STK_CHK_ISR you called this function from an ISR
1626 ************************************************************************************************************************
1627 */
1628 
1629 #if OS_CFG_STAT_TASK_STK_CHK_EN > 0u
1630 void OSTaskStkChk (OS_TCB *p_tcb,
1631  CPU_STK_SIZE *p_free,
1632  CPU_STK_SIZE *p_used,
1633  OS_ERR *p_err)
1634 {
1635  CPU_STK_SIZE free_stk;
1636  CPU_STK *p_stk;
1637  CPU_SR_ALLOC();
1638 
1639 
1640 
1641 #ifdef OS_SAFETY_CRITICAL
1642  if (p_err == (OS_ERR *)0) {
1643  OS_SAFETY_CRITICAL_EXCEPTION();
1644  return;
1645  }
1646 #endif
1647 
1648 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
1649  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to check stack from ISR */
1650  *p_err = OS_ERR_TASK_STK_CHK_ISR;
1651  return;
1652  }
1653 #endif
1654 
1655 #if OS_CFG_ARG_CHK_EN > 0u
1656  if (p_free == (CPU_STK_SIZE*)0) { /* User must specify valid destinations for the sizes */
1657  *p_err = OS_ERR_PTR_INVALID;
1658  return;
1659  }
1660 
1661  if (p_used == (CPU_STK_SIZE*)0) {
1662  *p_err = OS_ERR_PTR_INVALID;
1663  return;
1664  }
1665 #endif
1666 
1668  if (p_tcb == (OS_TCB *)0) { /* Check the stack of the current task? */
1669  p_tcb = OSTCBCurPtr; /* Yes */
1670  }
1671 
1672  if (p_tcb->StkPtr == (CPU_STK*)0) { /* Make sure task exist */
1674  *p_free = (CPU_STK_SIZE)0;
1675  *p_used = (CPU_STK_SIZE)0;
1676  *p_err = OS_ERR_TASK_NOT_EXIST;
1677  return;
1678  }
1679 
1680  if ((p_tcb->Opt & OS_OPT_TASK_STK_CHK) == (OS_OPT)0) { /* Make sure stack checking option is set */
1682  *p_free = (CPU_STK_SIZE)0;
1683  *p_used = (CPU_STK_SIZE)0;
1684  *p_err = OS_ERR_TASK_OPT;
1685  return;
1686  }
1688 
1689  free_stk = 0u;
1690 #if CPU_CFG_STK_GROWTH == CPU_STK_GROWTH_HI_TO_LO
1691  p_stk = p_tcb->StkBasePtr; /* Start at the lowest memory and go up */
1692  while (*p_stk == (CPU_STK)0) { /* Compute the number of zero entries on the stk */
1693  p_stk++;
1694  free_stk++;
1695  }
1696 #else
1697  p_stk = p_tcb->StkBasePtr + p_tcb->StkSize - 1u; /* Start at the highest memory and go down */
1698  while (*p_stk == (CPU_STK)0) {
1699  free_stk++;
1700  p_stk--;
1701  }
1702 #endif
1703  *p_free = free_stk;
1704  *p_used = (p_tcb->StkSize - free_stk); /* Compute number of entries used on the stack */
1705  *p_err = OS_ERR_NONE;
1706 }
1707 #endif
1708 
1709 /*$PAGE*/
1710 /*
1711 ************************************************************************************************************************
1712 * SUSPEND A TASK
1713 *
1714 * Description: This function is called to suspend a task. The task can be the calling task if 'p_tcb' is a NULL pointer
1715 * or the pointer to the TCB of the calling task.
1716 *
1717 * Arguments : p_tcb is a pointer to the TCB to suspend.
1718 * If p_tcb is a NULL pointer then, suspend the current task.
1719 *
1720 * p_err is a pointer to a variable that will receive an error code from this function.
1721 *
1722 * OS_ERR_NONE if the requested task is suspended
1723 * OS_ERR_SCHED_LOCKED you can't suspend the current task is the scheduler is
1724 * locked
1725 * OS_ERR_TASK_SUSPEND_ISR if you called this function from an ISR
1726 * OS_ERR_TASK_SUSPEND_IDLE if you attempted to suspend the idle task which is not
1727 * allowed.
1728 * OS_ERR_TASK_SUSPEND_INT_HANDLER if you attempted to suspend the idle task which is not
1729 * allowed.
1730 *
1731 * Note(s) : 1) You should use this function with great care. If you suspend a task that is waiting for an event
1732 * (i.e. a message, a semaphore, a queue ...) you will prevent this task from running when the event
1733 * arrives.
1734 ************************************************************************************************************************
1735 */
1736 
1737 #if OS_CFG_TASK_SUSPEND_EN > 0u
1738 void OSTaskSuspend (OS_TCB *p_tcb,
1739  OS_ERR *p_err)
1740 {
1741 #ifdef OS_SAFETY_CRITICAL
1742  if (p_err == (OS_ERR *)0) {
1743  OS_SAFETY_CRITICAL_EXCEPTION();
1744  return;
1745  }
1746 #endif
1747 
1748 #if (OS_CFG_ISR_POST_DEFERRED_EN == 0u) && \
1749  (OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u)
1750  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
1751  *p_err = OS_ERR_TASK_SUSPEND_ISR;
1752  return;
1753  }
1754 #endif
1755 
1756  if (p_tcb == &OSIdleTaskTCB) { /* Make sure not suspending the idle task */
1757  *p_err = OS_ERR_TASK_SUSPEND_IDLE;
1758  return;
1759  }
1760 
1761 #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
1762  if (p_tcb == &OSIntQTaskTCB) { /* Not allowed to suspend the ISR handler task */
1764  return;
1765  }
1766 
1767  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from an ISR */
1768  OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_TASK_SUSPEND, /* Post to ISR queue */
1769  (void *)p_tcb,
1770  (void *)0,
1771  (OS_MSG_SIZE)0,
1772  (OS_FLAGS )0,
1773  (OS_OPT )0,
1774  (CPU_TS )0,
1775  (OS_ERR *)p_err);
1776  return;
1777  }
1778 #endif
1779 
1780  OS_TaskSuspend(p_tcb, p_err);
1781 }
1782 #endif
1783 
1784 /*$PAGE*/
1785 /*
1786 ************************************************************************************************************************
1787 * CHANGE A TASK'S TIME SLICE
1788 *
1789 * Description: This function is called to change the value of the task's specific time slice.
1790 *
1791 * Arguments : p_tcb is the pointer to the TCB of the task to change. If you specify an NULL pointer, the current
1792 * task is assumed.
1793 *
1794 * time_quanta is the number of ticks before the CPU is taken away when round-robin scheduling is enabled.
1795 *
1796 * p_err is a pointer to an error code returned by this function:
1797 *
1798 * OS_ERR_NONE upon success
1799 * OS_ERR_SET_ISR if you called this function from an ISR
1800 *
1801 * Returns : none
1802 ************************************************************************************************************************
1803 */
1804 
1805 #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
1806 void OSTaskTimeQuantaSet (OS_TCB *p_tcb,
1807  OS_TICK time_quanta,
1808  OS_ERR *p_err)
1809 {
1810  CPU_SR_ALLOC();
1811 
1812 
1813 
1814 #ifdef OS_SAFETY_CRITICAL
1815  if (p_err == (OS_ERR *)0) {
1816  OS_SAFETY_CRITICAL_EXCEPTION();
1817  return;
1818  }
1819 #endif
1820 
1821 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
1822  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't call this function from an ISR */
1823  *p_err = OS_ERR_SET_ISR;
1824  return;
1825  }
1826 #endif
1827 
1829  if (p_tcb == (OS_TCB *)0) {
1830  p_tcb = OSTCBCurPtr;
1831  }
1832 
1833  if (time_quanta == 0u) {
1834  p_tcb->TimeQuanta = OSSchedRoundRobinDfltTimeQuanta;
1835  } else {
1836  p_tcb->TimeQuanta = time_quanta;
1837  }
1838  if (p_tcb->TimeQuanta > p_tcb->TimeQuantaCtr) {
1839  p_tcb->TimeQuantaCtr = p_tcb->TimeQuanta;
1840  }
1842  *p_err = OS_ERR_NONE;
1843 }
1844 #endif
1845 
1846 /*$PAGE*/
1847 /*
1848 ************************************************************************************************************************
1849 * ADD/REMOVE TASK TO/FROM DEBUG LIST
1850 *
1851 * Description: These functions are called by uC/OS-III to add or remove an OS_TCB from the debug list.
1852 *
1853 * Arguments : p_tcb is a pointer to the OS_TCB to add/remove
1854 *
1855 * Returns : none
1856 *
1857 * Note(s) : These functions are INTERNAL to uC/OS-III and your application should not call it.
1858 ************************************************************************************************************************
1859 */
1860 
1861 #if OS_CFG_DBG_EN > 0u
1862 void OS_TaskDbgListAdd (OS_TCB *p_tcb)
1863 {
1864  p_tcb->DbgPrevPtr = (OS_TCB *)0;
1865  if (OSTaskDbgListPtr == (OS_TCB *)0) {
1866  p_tcb->DbgNextPtr = (OS_TCB *)0;
1867  } else {
1868  p_tcb->DbgNextPtr = OSTaskDbgListPtr;
1869  OSTaskDbgListPtr->DbgPrevPtr = p_tcb;
1870  }
1871  OSTaskDbgListPtr = p_tcb;
1872 }
1873 
1874 
1875 
1876 void OS_TaskDbgListRemove (OS_TCB *p_tcb)
1877 {
1878  OS_TCB *p_tcb_next;
1879  OS_TCB *p_tcb_prev;
1880 
1881 
1882  p_tcb_prev = p_tcb->DbgPrevPtr;
1883  p_tcb_next = p_tcb->DbgNextPtr;
1884 
1885  if (p_tcb_prev == (OS_TCB *)0) {
1886  OSTaskDbgListPtr = p_tcb_next;
1887  if (p_tcb_next != (OS_TCB *)0) {
1888  p_tcb_next->DbgPrevPtr = (OS_TCB *)0;
1889  }
1890  p_tcb->DbgNextPtr = (OS_TCB *)0;
1891 
1892  } else if (p_tcb_next == (OS_TCB *)0) {
1893  p_tcb_prev->DbgNextPtr = (OS_TCB *)0;
1894  p_tcb->DbgPrevPtr = (OS_TCB *)0;
1895 
1896  } else {
1897  p_tcb_prev->DbgNextPtr = p_tcb_next;
1898  p_tcb_next->DbgPrevPtr = p_tcb_prev;
1899  p_tcb->DbgNextPtr = (OS_TCB *)0;
1900  p_tcb->DbgPrevPtr = (OS_TCB *)0;
1901  }
1902 }
1903 #endif
1904 
1905 /*$PAGE*/
1906 /*
1907 ************************************************************************************************************************
1908 * TASK MANAGER INITIALIZATION
1909 *
1910 * Description: This function is called by OSInit() to initialize the task management.
1911 *
1912 
1913 * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
1914 *
1915 * OS_ERR_NONE the call was successful
1916 *
1917 * Returns : none
1918 *
1919 * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
1920 ************************************************************************************************************************
1921 */
1922 
1923 void OS_TaskInit (OS_ERR *p_err)
1924 {
1925 #ifdef OS_SAFETY_CRITICAL
1926  if (p_err == (OS_ERR *)0) {
1927  OS_SAFETY_CRITICAL_EXCEPTION();
1928  return;
1929  }
1930 #endif
1931 
1932 #if OS_CFG_DBG_EN > 0u
1933  OSTaskDbgListPtr = (OS_TCB *)0;
1934 #endif
1935 
1936  OSTaskQty = (OS_OBJ_QTY )0; /* Clear the number of tasks */
1937  OSTaskCtxSwCtr = (OS_CTX_SW_CTR)0; /* Clear the context switch counter */
1938 
1939  *p_err = OS_ERR_NONE;
1940 }
1941 
1942 /*$PAGE*/
1943 /*
1944 ************************************************************************************************************************
1945 * INITIALIZE TCB FIELDS
1946 *
1947 * Description: This function is called to initialize a TCB to default values
1948 *
1949 * Arguments : p_tcb is a pointer to the TCB to initialize
1950 *
1951 * Returns : none
1952 *
1953 * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
1954 ************************************************************************************************************************
1955 */
1956 
1957 void OS_TaskInitTCB (OS_TCB *p_tcb)
1958 {
1959 #if OS_CFG_TASK_REG_TBL_SIZE > 0u
1960  OS_REG_ID reg_id;
1961 #endif
1962 #if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
1963  OS_TLS_ID id;
1964 #endif
1965 #if OS_CFG_TASK_PROFILE_EN > 0u
1966  CPU_TS ts;
1967 #endif
1968 
1969 
1970  p_tcb->StkPtr = (CPU_STK *)0;
1971  p_tcb->StkLimitPtr = (CPU_STK *)0;
1972 
1973  p_tcb->ExtPtr = (void *)0;
1974 
1975  p_tcb->NextPtr = (OS_TCB *)0;
1976  p_tcb->PrevPtr = (OS_TCB *)0;
1977 
1978  p_tcb->TickNextPtr = (OS_TCB *)0;
1979  p_tcb->TickPrevPtr = (OS_TCB *)0;
1980  p_tcb->TickSpokePtr = (OS_TICK_SPOKE *)0;
1981 
1982  p_tcb->NamePtr = (CPU_CHAR *)((void *)"?Task");
1983 
1984  p_tcb->StkBasePtr = (CPU_STK *)0;
1985 
1986  p_tcb->TaskEntryAddr = (OS_TASK_PTR )0;
1987  p_tcb->TaskEntryArg = (void *)0;
1988 
1989 #if (OS_CFG_PEND_MULTI_EN > 0u)
1990  p_tcb->PendDataTblPtr = (OS_PEND_DATA *)0;
1991  p_tcb->PendDataTblEntries = (OS_OBJ_QTY )0u;
1992 #endif
1993 
1994  p_tcb->TS = (CPU_TS )0u;
1995 
1996 #if (OS_MSG_EN > 0u)
1997  p_tcb->MsgPtr = (void *)0;
1998  p_tcb->MsgSize = (OS_MSG_SIZE )0u;
1999 #endif
2000 
2001 #if OS_CFG_TASK_Q_EN > 0u
2002  OS_MsgQInit(&p_tcb->MsgQ,
2003  (OS_MSG_QTY)0u);
2004 #if OS_CFG_TASK_PROFILE_EN > 0u
2005  p_tcb->MsgQPendTime = (CPU_TS )0u;
2006  p_tcb->MsgQPendTimeMax = (CPU_TS )0u;
2007 #endif
2008 #endif
2009 
2010 #if OS_CFG_FLAG_EN > 0u
2011  p_tcb->FlagsPend = (OS_FLAGS )0u;
2012  p_tcb->FlagsOpt = (OS_OPT )0u;
2013  p_tcb->FlagsRdy = (OS_FLAGS )0u;
2014 #endif
2015 
2016 #if OS_CFG_TASK_REG_TBL_SIZE > 0u
2017  for (reg_id = 0u; reg_id < OS_CFG_TASK_REG_TBL_SIZE; reg_id++) {
2018  p_tcb->RegTbl[reg_id] = (OS_REG)0u;
2019  }
2020 #endif
2021 
2022 #if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
2023  for (id = 0u; id < OS_CFG_TLS_TBL_SIZE; id++) {
2024  p_tcb->TLS_Tbl[id] = (OS_TLS)0;
2025  }
2026 #endif
2027 
2028  p_tcb->SemCtr = (OS_SEM_CTR )0u;
2029 #if OS_CFG_TASK_PROFILE_EN > 0u
2030  p_tcb->SemPendTime = (CPU_TS )0u;
2031  p_tcb->SemPendTimeMax = (CPU_TS )0u;
2032 #endif
2033 
2034  p_tcb->StkSize = (CPU_STK_SIZE )0u;
2035 
2036 
2037 #if OS_CFG_TASK_SUSPEND_EN > 0u
2038  p_tcb->SuspendCtr = (OS_NESTING_CTR )0u;
2039 #endif
2040 
2041 #if OS_CFG_STAT_TASK_STK_CHK_EN > 0u
2042  p_tcb->StkFree = (CPU_STK_SIZE )0u;
2043  p_tcb->StkUsed = (CPU_STK_SIZE )0u;
2044 #endif
2045 
2046  p_tcb->Opt = (OS_OPT )0u;
2047 
2048  p_tcb->TickCtrPrev = (OS_TICK )OS_TICK_TH_INIT;
2049  p_tcb->TickCtrMatch = (OS_TICK )0u;
2050  p_tcb->TickRemain = (OS_TICK )0u;
2051 
2052  p_tcb->TimeQuanta = (OS_TICK )0u;
2053  p_tcb->TimeQuantaCtr = (OS_TICK )0u;
2054 
2055 #if OS_CFG_TASK_PROFILE_EN > 0u
2056  p_tcb->CPUUsage = (OS_CPU_USAGE )0u;
2057  p_tcb->CPUUsageMax = (OS_CPU_USAGE )0u;
2058  p_tcb->CtxSwCtr = (OS_CTX_SW_CTR )0u;
2059  p_tcb->CyclesDelta = (CPU_TS )0u;
2060  ts = OS_TS_GET(); /* Read the current timestamp and save */
2061  p_tcb->CyclesStart = ts;
2062  p_tcb->CyclesTotal = (OS_CYCLES )0u;
2063 #endif
2064 #ifdef CPU_CFG_INT_DIS_MEAS_EN
2065  p_tcb->IntDisTimeMax = (CPU_TS )0u;
2066 #endif
2067 #if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
2068  p_tcb->SchedLockTimeMax = (CPU_TS )0u;
2069 #endif
2070 
2071  p_tcb->PendOn = (OS_STATE )OS_TASK_PEND_ON_NOTHING;
2072  p_tcb->PendStatus = (OS_STATUS )OS_STATUS_PEND_OK;
2073  p_tcb->TaskState = (OS_STATE )OS_TASK_STATE_RDY;
2074 
2075  p_tcb->Prio = (OS_PRIO )OS_PRIO_INIT;
2076 
2077 #if OS_CFG_DBG_EN > 0u
2078  p_tcb->DbgPrevPtr = (OS_TCB *)0;
2079  p_tcb->DbgNextPtr = (OS_TCB *)0;
2080  p_tcb->DbgNamePtr = (CPU_CHAR *)((void *)" ");
2081 #endif
2082 }
2083 
2084 /*$PAGE*/
2085 /*
2086 ************************************************************************************************************************
2087 * POST MESSAGE TO A TASK
2088 *
2089 * Description: This function sends a message to a task
2090 *
2091 * Arguments : p_tcb is a pointer to the TCB of the task receiving a message. If you specify a NULL pointer then
2092 * the message will be posted to the task's queue of the calling task. In other words, you'd be
2093 * posting a message to yourself.
2094 *
2095 * p_void is a pointer to the message to send.
2096 *
2097 * msg_size is the size of the message sent (in #bytes)
2098 *
2099 * opt specifies whether the post will be FIFO or LIFO:
2100 *
2101 * OS_OPT_POST_FIFO Post at the end of the queue
2102 * OS_OPT_POST_LIFO Post at the front of the queue
2103 *
2104 * OS_OPT_POST_NO_SCHED Do not run the scheduler after the post
2105 *
2106 * Note(s): 1) OS_OPT_POST_NO_SCHED can be added with one of the other options.
2107 *
2108 *
2109 * ts is a timestamp indicating when the post occurred.
2110 *
2111 * p_err is a pointer to a variable that will hold the error code associated
2112 * with the outcome of this call. Errors can be:
2113 *
2114 * OS_ERR_NONE The call was successful and the message was sent
2115 * OS_ERR_MSG_POOL_EMPTY If there are no more OS_MSGs available from the pool
2116 * OS_ERR_Q_MAX If the queue is full
2117 * OS_ERR_STATE_INVALID If the task is in an invalid state. This should never happen
2118 * and if it does, would be considered a system failure.
2119 *
2120 * Returns : none
2121 *
2122 * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
2123 ************************************************************************************************************************
2124 */
2125 
2126 #if OS_CFG_TASK_Q_EN > 0u
2127 void OS_TaskQPost (OS_TCB *p_tcb,
2128  void *p_void,
2129  OS_MSG_SIZE msg_size,
2130  OS_OPT opt,
2131  CPU_TS ts,
2132  OS_ERR *p_err)
2133 {
2134  CPU_SR_ALLOC();
2135 
2136 
2137 
2139  if (p_tcb == (OS_TCB *)0) { /* Post msg to 'self'? */
2140  p_tcb = OSTCBCurPtr;
2141  }
2142  *p_err = OS_ERR_NONE; /* Assume we won't have any errors */
2143  switch (p_tcb->TaskState) {
2144  case OS_TASK_STATE_RDY:
2145  case OS_TASK_STATE_DLY:
2148  OS_MsgQPut(&p_tcb->MsgQ, /* Deposit the message in the queue */
2149  p_void,
2150  msg_size,
2151  opt,
2152  ts,
2153  p_err);
2154  OS_CRITICAL_EXIT();
2155  break;
2156 
2157  case OS_TASK_STATE_PEND:
2161  if (p_tcb->PendOn == OS_TASK_PEND_ON_TASK_Q) { /* Is task waiting for a message to be sent to it? */
2162  OS_Post((OS_PEND_OBJ *)0,
2163  p_tcb,
2164  p_void,
2165  msg_size,
2166  ts);
2168  if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0u) {
2169  OSSched(); /* Run the scheduler */
2170  }
2171  } else {
2172  OS_MsgQPut(&p_tcb->MsgQ, /* No, Task is pending on something else ... */
2173  p_void, /* ... Deposit the message in the task's queue */
2174  msg_size,
2175  opt,
2176  ts,
2177  p_err);
2178  OS_CRITICAL_EXIT();
2179  }
2180  break;
2181 
2182  default:
2183  OS_CRITICAL_EXIT();
2184  *p_err = OS_ERR_STATE_INVALID;
2185  break;
2186  }
2187 }
2188 #endif
2189 
2190 /*$PAGE*/
2191 /*
2192 ************************************************************************************************************************
2193 * RESUME A SUSPENDED TASK
2194 *
2195 * Description: This function is called to resume a previously suspended task. This is the only call that will remove an
2196 * explicit task suspension.
2197 *
2198 * Arguments : p_tcb Is a pointer to the task's OS_TCB to resume
2199 *
2200 * p_err Is a pointer to a variable that will contain an error code returned by this function
2201 *
2202 * OS_ERR_NONE if the requested task is resumed
2203 * OS_ERR_STATE_INVALID if the task is in an invalid state
2204 * OS_ERR_TASK_RESUME_ISR if you called this function from an ISR
2205 * OS_ERR_TASK_RESUME_SELF You cannot resume 'self'
2206 * OS_ERR_TASK_NOT_SUSPENDED if the task to resume has not been suspended
2207 *
2208 * Returns : none
2209 *
2210 * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
2211 ************************************************************************************************************************
2212 */
2213 
2214 #if OS_CFG_TASK_SUSPEND_EN > 0u
2215 void OS_TaskResume (OS_TCB *p_tcb,
2216  OS_ERR *p_err)
2217 {
2218  CPU_SR_ALLOC();
2219 
2220 
2222  *p_err = OS_ERR_NONE;
2223  switch (p_tcb->TaskState) {
2224  case OS_TASK_STATE_RDY:
2225  case OS_TASK_STATE_DLY:
2226  case OS_TASK_STATE_PEND:
2229  *p_err = OS_ERR_TASK_NOT_SUSPENDED;
2230  break;
2231 
2234  p_tcb->SuspendCtr--;
2235  if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
2236  p_tcb->TaskState = OS_TASK_STATE_RDY;
2237  OS_TaskRdy(p_tcb);
2238  }
2240  break;
2241 
2243  p_tcb->SuspendCtr--;
2244  if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
2245  p_tcb->TaskState = OS_TASK_STATE_DLY;
2246  }
2248  break;
2249 
2251  p_tcb->SuspendCtr--;
2252  if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
2253  p_tcb->TaskState = OS_TASK_STATE_PEND;
2254  }
2256  break;
2257 
2259  p_tcb->SuspendCtr--;
2260  if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
2261  p_tcb->TaskState = OS_TASK_STATE_PEND_TIMEOUT;
2262  }
2264  break;
2265 
2266  default:
2268  *p_err = OS_ERR_STATE_INVALID;
2269  return;
2270  }
2271 
2272  OSSched();
2273 }
2274 #endif
2275 
2276 /*$PAGE*/
2277 /*
2278 ************************************************************************************************************************
2279 * CATCH ACCIDENTAL TASK RETURN
2280 *
2281 * Description: This function is called if a task accidentally returns without deleting itself. In other words, a task
2282 * should either be an infinite loop or delete itself if it's done.
2283 *
2284 * Arguments : none
2285 *
2286 * Returns : none
2287 *
2288 * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
2289 ************************************************************************************************************************
2290 */
2291 
2292 void OS_TaskReturn (void)
2293 {
2294  OS_ERR err;
2295 
2296 
2297 
2298  OSTaskReturnHook(OSTCBCurPtr); /* Call hook to let user decide on what to do */
2299 #if OS_CFG_TASK_DEL_EN > 0u
2300  OSTaskDel((OS_TCB *)0, /* Delete task if it accidentally returns! */
2301  (OS_ERR *)&err);
2302 #else
2303  for (;;) {
2306  (OS_ERR *)&err);
2307  }
2308 #endif
2309 }
2310 
2311 /*$PAGE*/
2312 /*
2313 ************************************************************************************************************************
2314 * SIGNAL A TASK
2315 *
2316 * Description: This function is called to signal a task waiting for a signal.
2317 *
2318 * Arguments : p_tcb is the pointer to the TCB of the task to signal. A NULL pointer indicates that you are sending
2319 * a signal to yourself.
2320 *
2321 * opt determines the type of POST performed:
2322 *
2323 * OS_OPT_POST_NONE No option
2324 *
2325 * OS_OPT_POST_NO_SCHED Do not call the scheduler
2326 *
2327 * ts is a timestamp indicating when the post occurred.
2328 *
2329 * p_err is a pointer to an error code returned by this function:
2330 *
2331 * OS_ERR_NONE If the requested task is signaled
2332 * OS_ERR_SEM_OVF If the post would cause the semaphore count to overflow.
2333 * OS_ERR_STATE_INVALID If the task is in an invalid state. This should never happen
2334 * and if it does, would be considered a system failure.
2335 *
2336 * Returns : The current value of the task's signal counter or 0 if called from an ISR
2337 *
2338 * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
2339 ************************************************************************************************************************
2340 */
2341 
2343  OS_OPT opt,
2344  CPU_TS ts,
2345  OS_ERR *p_err)
2346 {
2347  OS_SEM_CTR ctr;
2348  CPU_SR_ALLOC();
2349 
2350 
2351 
2353  if (p_tcb == (OS_TCB *)0) { /* Post signal to 'self'? */
2354  p_tcb = OSTCBCurPtr;
2355  }
2356  p_tcb->TS = ts;
2357  *p_err = OS_ERR_NONE; /* Assume we won't have any errors */
2358  switch (p_tcb->TaskState) {
2359  case OS_TASK_STATE_RDY:
2360  case OS_TASK_STATE_DLY:
2363  switch (sizeof(OS_SEM_CTR)) {
2364  case 1u:
2365  if (p_tcb->SemCtr == DEF_INT_08U_MAX_VAL) {
2366  OS_CRITICAL_EXIT();
2367  *p_err = OS_ERR_SEM_OVF;
2368  return ((OS_SEM_CTR)0);
2369  }
2370  break;
2371 
2372  case 2u:
2373  if (p_tcb->SemCtr == DEF_INT_16U_MAX_VAL) {
2374  OS_CRITICAL_EXIT();
2375  *p_err = OS_ERR_SEM_OVF;
2376  return ((OS_SEM_CTR)0);
2377  }
2378  break;
2379 
2380  case 4u:
2381  if (p_tcb->SemCtr == DEF_INT_32U_MAX_VAL) {
2382  OS_CRITICAL_EXIT();
2383  *p_err = OS_ERR_SEM_OVF;
2384  return ((OS_SEM_CTR)0);
2385  }
2386  break;
2387 
2388  default:
2389  break;
2390  }
2391  p_tcb->SemCtr++; /* Task signaled is not pending on anything */
2392  ctr = p_tcb->SemCtr;
2393  OS_CRITICAL_EXIT();
2394  break;
2395 
2396  case OS_TASK_STATE_PEND:
2400  if (p_tcb->PendOn == OS_TASK_PEND_ON_TASK_SEM) { /* Is task signaled waiting for a signal? */
2401  OS_Post((OS_PEND_OBJ *)0, /* Task is pending on signal */
2402  (OS_TCB *)p_tcb,
2403  (void *)0,
2404  (OS_MSG_SIZE )0u,
2405  (CPU_TS )ts);
2406  ctr = p_tcb->SemCtr;
2408  if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0) {
2409  OSSched(); /* Run the scheduler */
2410  }
2411  } else {
2412  switch (sizeof(OS_SEM_CTR)) {
2413  case 1u:
2414  if (p_tcb->SemCtr == DEF_INT_08U_MAX_VAL) {
2415  OS_CRITICAL_EXIT();
2416  *p_err = OS_ERR_SEM_OVF;
2417  return ((OS_SEM_CTR)0);
2418  }
2419  break;
2420 
2421  case 2u:
2422  if (p_tcb->SemCtr == DEF_INT_16U_MAX_VAL) {
2423  OS_CRITICAL_EXIT();
2424  *p_err = OS_ERR_SEM_OVF;
2425  return ((OS_SEM_CTR)0);
2426  }
2427  break;
2428 
2429  case 4u:
2430  if (p_tcb->SemCtr == DEF_INT_32U_MAX_VAL) {
2431  OS_CRITICAL_EXIT();
2432  *p_err = OS_ERR_SEM_OVF;
2433  return ((OS_SEM_CTR)0);
2434  }
2435  break;
2436 
2437  default:
2438  break;
2439  }
2440  p_tcb->SemCtr++; /* No, Task signaled is NOT pending on semaphore ... */
2441  ctr = p_tcb->SemCtr; /* ... it must be waiting on something else */
2442  OS_CRITICAL_EXIT();
2443  }
2444  break;
2445 
2446  default:
2447  OS_CRITICAL_EXIT();
2448  *p_err = OS_ERR_STATE_INVALID;
2449  ctr = (OS_SEM_CTR)0;
2450  break;
2451  }
2452  return (ctr);
2453 }
2454 
2455 /*$PAGE*/
2456 /*
2457 ************************************************************************************************************************
2458 * SUSPEND A TASK
2459 *
2460 * Description: This function is called to suspend a task. The task can be the calling task if 'p_tcb' is a NULL pointer
2461 * or the pointer to the TCB of the calling task.
2462 *
2463 * Arguments : p_tcb is a pointer to the TCB to suspend.
2464 * If p_tcb is a NULL pointer then, suspend the current task.
2465 *
2466 * p_err is a pointer to a variable that will receive an error code from this function.
2467 *
2468 * OS_ERR_NONE if the requested task is suspended
2469 * OS_ERR_SCHED_LOCKED you can't suspend the current task is the scheduler is
2470 * locked
2471 * OS_ERR_TASK_SUSPEND_ISR if you called this function from an ISR
2472 * OS_ERR_TASK_SUSPEND_IDLE if you attempted to suspend the idle task which is not
2473 * allowed.
2474 * OS_ERR_TASK_SUSPEND_INT_HANDLER if you attempted to suspend the idle task which is not
2475 * allowed.
2476 *
2477 * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it.
2478 *
2479 * 2) You should use this function with great care. If you suspend a task that is waiting for an event
2480 * (i.e. a message, a semaphore, a queue ...) you will prevent this task from running when the event
2481 * arrives.
2482 ************************************************************************************************************************
2483 */
2484 
2485 #if OS_CFG_TASK_SUSPEND_EN > 0u
2486 void OS_TaskSuspend (OS_TCB *p_tcb,
2487  OS_ERR *p_err)
2488 {
2489  CPU_SR_ALLOC();
2490 
2491 
2492 
2494  if (p_tcb == (OS_TCB *)0) { /* See if specified to suspend self */
2495  p_tcb = OSTCBCurPtr;
2496  }
2497 
2498  if (p_tcb == OSTCBCurPtr) {
2499  if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't suspend when the scheduler is locked */
2501  *p_err = OS_ERR_SCHED_LOCKED;
2502  return;
2503  }
2504  }
2505 
2506  *p_err = OS_ERR_NONE;
2507  switch (p_tcb->TaskState) {
2508  case OS_TASK_STATE_RDY:
2510  p_tcb->TaskState = OS_TASK_STATE_SUSPENDED;
2511  p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
2512  OS_RdyListRemove(p_tcb);
2514  break;
2515 
2516  case OS_TASK_STATE_DLY:
2517  p_tcb->TaskState = OS_TASK_STATE_DLY_SUSPENDED;
2518  p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
2520  break;
2521 
2522  case OS_TASK_STATE_PEND:
2523  p_tcb->TaskState = OS_TASK_STATE_PEND_SUSPENDED;
2524  p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
2526  break;
2527 
2529  p_tcb->TaskState = OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED;
2530  p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
2532  break;
2533 
2538  p_tcb->SuspendCtr++;
2540  break;
2541 
2542  default:
2544  *p_err = OS_ERR_STATE_INVALID;
2545  return;
2546  }
2547 
2548  OSSched();
2549 }
2550 #endif