训练营PLSR题目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2823 lines
112 KiB

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