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.
 
 
 
 
 

1387 lines
59 KiB

  1. /*
  2. *********************************************************************************************************
  3. * uC/OS-II
  4. * The Real-Time Kernel
  5. *
  6. * Copyright 1992-2021 Silicon Laboratories Inc. www.silabs.com
  7. *
  8. * SPDX-License-Identifier: APACHE-2.0
  9. *
  10. * This software is subject to an open source license and is distributed by
  11. * Silicon Laboratories Inc. pursuant to the terms of the Apache License,
  12. * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
  13. *
  14. *********************************************************************************************************
  15. */
  16. /*
  17. *********************************************************************************************************
  18. *
  19. * TASK MANAGEMENT
  20. *
  21. * Filename : os_task.c
  22. * Version : V2.93.01
  23. *********************************************************************************************************
  24. */
  25. #ifndef OS_TASK_C
  26. #define OS_TASK_C
  27. #define MICRIUM_SOURCE
  28. #ifndef OS_MASTER_FILE
  29. #include <ucos_ii.h>
  30. #endif
  31. /*
  32. *********************************************************************************************************
  33. * CHANGE PRIORITY OF A TASK
  34. *
  35. * Description: This function allows you to change the priority of a task dynamically. Note that the new
  36. * priority MUST be available.
  37. *
  38. * Arguments : oldp is the old priority
  39. *
  40. * newp is the new priority
  41. *
  42. * Returns : OS_ERR_NONE is the call was successful
  43. * OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed
  44. * (i.e. >= OS_LOWEST_PRIO)
  45. * OS_ERR_PRIO_EXIST if the new priority already exist.
  46. * OS_ERR_PRIO there is no task with the specified OLD priority (i.e. the OLD task does
  47. * not exist.
  48. * OS_ERR_TASK_NOT_EXIST if the task is assigned to a Mutex PIP.
  49. *********************************************************************************************************
  50. */
  51. #if OS_TASK_CHANGE_PRIO_EN > 0u
  52. INT8U OSTaskChangePrio (INT8U oldprio,
  53. INT8U newprio)
  54. {
  55. #if (OS_EVENT_EN)
  56. OS_EVENT *pevent;
  57. #if (OS_EVENT_MULTI_EN > 0u)
  58. OS_EVENT **pevents;
  59. #endif
  60. #endif
  61. OS_TCB *ptcb;
  62. INT8U y_new;
  63. INT8U x_new;
  64. INT8U y_old;
  65. OS_PRIO bity_new;
  66. OS_PRIO bitx_new;
  67. OS_PRIO bity_old;
  68. OS_PRIO bitx_old;
  69. #if OS_CRITICAL_METHOD == 3u
  70. OS_CPU_SR cpu_sr = 0u; /* Storage for CPU status register */
  71. #endif
  72. #if OS_ARG_CHK_EN > 0u
  73. if (oldprio >= OS_LOWEST_PRIO) {
  74. if (oldprio != OS_PRIO_SELF) {
  75. return (OS_ERR_PRIO_INVALID);
  76. }
  77. }
  78. if (newprio >= OS_LOWEST_PRIO) {
  79. return (OS_ERR_PRIO_INVALID);
  80. }
  81. #endif
  82. OS_ENTER_CRITICAL();
  83. if (OSTCBPrioTbl[newprio] != (OS_TCB *)0) { /* New priority must not already exist */
  84. OS_EXIT_CRITICAL();
  85. return (OS_ERR_PRIO_EXIST);
  86. }
  87. if (oldprio == OS_PRIO_SELF) { /* See if changing self */
  88. oldprio = OSTCBCur->OSTCBPrio; /* Yes, get priority */
  89. }
  90. ptcb = OSTCBPrioTbl[oldprio];
  91. if (ptcb == (OS_TCB *)0) { /* Does task to change exist? */
  92. OS_EXIT_CRITICAL(); /* No, can't change its priority! */
  93. return (OS_ERR_PRIO);
  94. }
  95. if (ptcb == OS_TCB_RESERVED) { /* Is task assigned to Mutex */
  96. OS_EXIT_CRITICAL(); /* No, can't change its priority! */
  97. return (OS_ERR_TASK_NOT_EXIST);
  98. }
  99. #if OS_LOWEST_PRIO <= 63u
  100. y_new = (INT8U)(newprio >> 3u); /* Yes, compute new TCB fields */
  101. x_new = (INT8U)(newprio & 0x07u);
  102. #else
  103. y_new = (INT8U)((INT8U)(newprio >> 4u) & 0x0Fu);
  104. x_new = (INT8U)(newprio & 0x0Fu);
  105. #endif
  106. bity_new = (OS_PRIO)(1uL << y_new);
  107. bitx_new = (OS_PRIO)(1uL << x_new);
  108. OSTCBPrioTbl[oldprio] = (OS_TCB *)0; /* Remove TCB from old priority */
  109. OSTCBPrioTbl[newprio] = ptcb; /* Place pointer to TCB @ new priority */
  110. y_old = ptcb->OSTCBY;
  111. bity_old = ptcb->OSTCBBitY;
  112. bitx_old = ptcb->OSTCBBitX;
  113. if ((OSRdyTbl[y_old] & bitx_old) != 0u) { /* If task is ready make it not */
  114. OSRdyTbl[y_old] &= (OS_PRIO)~bitx_old;
  115. if (OSRdyTbl[y_old] == 0u) {
  116. OSRdyGrp &= (OS_PRIO)~bity_old;
  117. }
  118. OSRdyGrp |= bity_new; /* Make new priority ready to run */
  119. OSRdyTbl[y_new] |= bitx_new;
  120. OS_TRACE_TASK_READY(ptcb);
  121. }
  122. #if (OS_EVENT_EN)
  123. pevent = ptcb->OSTCBEventPtr;
  124. if (pevent != (OS_EVENT *)0) {
  125. pevent->OSEventTbl[y_old] &= (OS_PRIO)~bitx_old; /* Remove old task prio from wait list */
  126. if (pevent->OSEventTbl[y_old] == 0u) {
  127. pevent->OSEventGrp &= (OS_PRIO)~bity_old;
  128. }
  129. pevent->OSEventGrp |= bity_new; /* Add new task prio to wait list */
  130. pevent->OSEventTbl[y_new] |= bitx_new;
  131. }
  132. #if (OS_EVENT_MULTI_EN > 0u)
  133. if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) {
  134. pevents = ptcb->OSTCBEventMultiPtr;
  135. pevent = *pevents;
  136. while (pevent != (OS_EVENT *)0) {
  137. pevent->OSEventTbl[y_old] &= (OS_PRIO)~bitx_old; /* Remove old task prio from wait lists */
  138. if (pevent->OSEventTbl[y_old] == 0u) {
  139. pevent->OSEventGrp &= (OS_PRIO)~bity_old;
  140. }
  141. pevent->OSEventGrp |= bity_new; /* Add new task prio to wait lists */
  142. pevent->OSEventTbl[y_new] |= bitx_new;
  143. pevents++;
  144. pevent = *pevents;
  145. }
  146. }
  147. #endif
  148. #endif
  149. ptcb->OSTCBPrio = newprio; /* Set new task priority */
  150. ptcb->OSTCBY = y_new;
  151. ptcb->OSTCBX = x_new;
  152. ptcb->OSTCBBitY = bity_new;
  153. ptcb->OSTCBBitX = bitx_new;
  154. OS_EXIT_CRITICAL();
  155. if (OSRunning == OS_TRUE) {
  156. OS_Sched(); /* Find new highest priority task */
  157. }
  158. return (OS_ERR_NONE);
  159. }
  160. #endif
  161. /*
  162. *********************************************************************************************************
  163. * CREATE A TASK
  164. *
  165. * Description: This function is used to have uC/OS-II manage the execution of a task. Tasks can either
  166. * be created prior to the start of multitasking or by a running task. A task cannot be
  167. * created by an ISR.
  168. *
  169. * Arguments : task is a pointer to the task's code
  170. *
  171. * p_arg is a pointer to an optional data area which can be used to pass parameters to
  172. * the task when the task first executes. Where the task is concerned it thinks
  173. * it was invoked and passed the argument 'p_arg' as follows:
  174. *
  175. * void Task (void *p_arg)
  176. * {
  177. * for (;;) {
  178. * Task code;
  179. * }
  180. * }
  181. *
  182. * ptos is a pointer to the task's top of stack. If the configuration constant
  183. * OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
  184. * memory to low memory). 'pstk' will thus point to the highest (valid) memory
  185. * location of the stack. If OS_STK_GROWTH is set to 0, 'pstk' will point to the
  186. * lowest memory location of the stack and the stack will grow with increasing
  187. * memory locations.
  188. *
  189. * prio is the task's priority. A unique priority MUST be assigned to each task and the
  190. * lower the number, the higher the priority.
  191. *
  192. * Returns : OS_ERR_NONE if the function was successful.
  193. * OS_ERR_PRIO_EXIST if the task priority already exist
  194. * (each task MUST have a unique priority).
  195. * OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum
  196. * allowed (i.e. >= OS_LOWEST_PRIO)
  197. * OS_ERR_TASK_CREATE_ISR if you tried to create a task from an ISR.
  198. * OS_ERR_ILLEGAL_CREATE_RUN_TIME if you tried to create a task after safety critical
  199. * operation started.
  200. *********************************************************************************************************
  201. */
  202. #if OS_TASK_CREATE_EN > 0u
  203. INT8U OSTaskCreate (void (*task)(void *p_arg),
  204. void *p_arg,
  205. OS_STK *ptos,
  206. INT8U prio)
  207. {
  208. OS_STK *psp;
  209. INT8U err;
  210. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  211. OS_CPU_SR cpu_sr = 0u;
  212. #endif
  213. #ifdef OS_SAFETY_CRITICAL_IEC61508
  214. if (OSSafetyCriticalStartFlag == OS_TRUE) {
  215. OS_SAFETY_CRITICAL_EXCEPTION();
  216. return (OS_ERR_ILLEGAL_CREATE_RUN_TIME);
  217. }
  218. #endif
  219. #if OS_ARG_CHK_EN > 0u
  220. if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */
  221. return (OS_ERR_PRIO_INVALID);
  222. }
  223. #endif
  224. OS_ENTER_CRITICAL();
  225. if (OSIntNesting > 0u) { /* Make sure we don't create the task from within an ISR */
  226. OS_EXIT_CRITICAL();
  227. return (OS_ERR_TASK_CREATE_ISR);
  228. }
  229. if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */
  230. OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... */
  231. /* ... the same thing until task is created. */
  232. OS_EXIT_CRITICAL();
  233. psp = OSTaskStkInit(task, p_arg, ptos, 0u); /* Initialize the task's stack */
  234. err = OS_TCBInit(prio, psp, (OS_STK *)0, 0u, 0u, (void *)0, 0u);
  235. if (err == OS_ERR_NONE) {
  236. OS_TRACE_TASK_CREATE(OSTCBPrioTbl[prio]);
  237. if (OSRunning == OS_TRUE) { /* Find highest priority task if multitasking has started */
  238. OS_Sched();
  239. }
  240. } else {
  241. OS_TRACE_TASK_CREATE_FAILED(OSTCBPrioTbl[prio]);
  242. OS_ENTER_CRITICAL();
  243. OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others */
  244. OS_EXIT_CRITICAL();
  245. }
  246. return (err);
  247. }
  248. OS_EXIT_CRITICAL();
  249. return (OS_ERR_PRIO_EXIST);
  250. }
  251. #endif
  252. /*
  253. *********************************************************************************************************
  254. * CREATE A TASK (Extended Version)
  255. *
  256. * Description: This function is used to have uC/OS-II manage the execution of a task. Tasks can either
  257. * be created prior to the start of multitasking or by a running task. A task cannot be
  258. * created by an ISR. This function is similar to OSTaskCreate() except that it allows
  259. * additional information about a task to be specified.
  260. *
  261. * Arguments : task is a pointer to the task's code
  262. *
  263. * p_arg is a pointer to an optional data area which can be used to pass parameters to
  264. * the task when the task first executes. Where the task is concerned it thinks
  265. * it was invoked and passed the argument 'p_arg' as follows:
  266. *
  267. * void Task (void *p_arg)
  268. * {
  269. * for (;;) {
  270. * Task code;
  271. * }
  272. * }
  273. *
  274. * ptos is a pointer to the task's top of stack. If the configuration constant
  275. * OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
  276. * memory to low memory). 'ptos' will thus point to the highest (valid) memory
  277. * location of the stack. If OS_STK_GROWTH is set to 0, 'ptos' will point to the
  278. * lowest memory location of the stack and the stack will grow with increasing
  279. * memory locations. 'ptos' MUST point to a valid 'free' data item.
  280. *
  281. * prio is the task's priority. A unique priority MUST be assigned to each task and the
  282. * lower the number, the higher the priority.
  283. *
  284. * id is the task's ID (0..65535)
  285. *
  286. * pbos is a pointer to the task's bottom of stack. If the configuration constant
  287. * OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
  288. * memory to low memory). 'pbos' will thus point to the LOWEST (valid) memory
  289. * location of the stack. If OS_STK_GROWTH is set to 0, 'pbos' will point to the
  290. * HIGHEST memory location of the stack and the stack will grow with increasing
  291. * memory locations. 'pbos' MUST point to a valid 'free' data item.
  292. *
  293. * stk_size is the size of the stack in number of elements. If OS_STK is set to INT8U,
  294. * 'stk_size' corresponds to the number of bytes available. If OS_STK is set to
  295. * INT16U, 'stk_size' contains the number of 16-bit entries available. Finally, if
  296. * OS_STK is set to INT32U, 'stk_size' contains the number of 32-bit entries
  297. * available on the stack.
  298. *
  299. * pext is a pointer to a user supplied memory location which is used as a TCB extension.
  300. * For example, this user memory can hold the contents of floating-point registers
  301. * during a context switch, the time each task takes to execute, the number of times
  302. * the task has been switched-in, etc.
  303. *
  304. * opt contains additional information (or options) about the behavior of the task. The
  305. * LOWER 8-bits are reserved by uC/OS-II while the upper 8 bits can be application
  306. * specific. See OS_TASK_OPT_??? in uCOS-II.H. Current choices are:
  307. *
  308. * OS_TASK_OPT_STK_CHK Stack checking to be allowed for the task
  309. * OS_TASK_OPT_STK_CLR Clear the stack when the task is created
  310. * OS_TASK_OPT_SAVE_FP If the CPU has floating-point registers, save them
  311. * during a context switch.
  312. *
  313. * Returns : OS_ERR_NONE if the function was successful.
  314. * OS_ERR_PRIO_EXIST if the task priority already exist
  315. * (each task MUST have a unique priority).
  316. * OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum
  317. * allowed (i.e. > OS_LOWEST_PRIO)
  318. * OS_ERR_TASK_CREATE_ISR if you tried to create a task from an ISR.
  319. * OS_ERR_ILLEGAL_CREATE_RUN_TIME if you tried to create a task after safety critical
  320. * operation started.
  321. *********************************************************************************************************
  322. */
  323. #if OS_TASK_CREATE_EXT_EN > 0u
  324. INT8U OSTaskCreateExt (void (*task)(void *p_arg),
  325. void *p_arg,
  326. OS_STK *ptos,
  327. INT8U prio,
  328. INT16U id,
  329. OS_STK *pbos,
  330. INT32U stk_size,
  331. void *pext,
  332. INT16U opt)
  333. {
  334. OS_STK *psp;
  335. INT8U err;
  336. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  337. OS_CPU_SR cpu_sr = 0u;
  338. #endif
  339. #ifdef OS_SAFETY_CRITICAL_IEC61508
  340. if (OSSafetyCriticalStartFlag == OS_TRUE) {
  341. OS_SAFETY_CRITICAL_EXCEPTION();
  342. return (OS_ERR_ILLEGAL_CREATE_RUN_TIME);
  343. }
  344. #endif
  345. #if OS_ARG_CHK_EN > 0u
  346. if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */
  347. return (OS_ERR_PRIO_INVALID);
  348. }
  349. #endif
  350. OS_ENTER_CRITICAL();
  351. if (OSIntNesting > 0u) { /* Make sure we don't create the task from within an ISR */
  352. OS_EXIT_CRITICAL();
  353. return (OS_ERR_TASK_CREATE_ISR);
  354. }
  355. if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */
  356. OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... */
  357. /* ... the same thing until task is created. */
  358. OS_EXIT_CRITICAL();
  359. #if (OS_TASK_STAT_STK_CHK_EN > 0u)
  360. OS_TaskStkClr(pbos, stk_size, opt); /* Clear the task stack (if needed) */
  361. #endif
  362. psp = OSTaskStkInit(task, p_arg, ptos, opt); /* Initialize the task's stack */
  363. err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt);
  364. if (err == OS_ERR_NONE) {
  365. OS_TRACE_TASK_CREATE(OSTCBPrioTbl[prio]);
  366. if (OSRunning == OS_TRUE) { /* Find HPT if multitasking has started */
  367. OS_Sched();
  368. }
  369. } else {
  370. OS_ENTER_CRITICAL();
  371. OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Make this priority avail. to others */
  372. OS_EXIT_CRITICAL();
  373. }
  374. return (err);
  375. }
  376. OS_EXIT_CRITICAL();
  377. return (OS_ERR_PRIO_EXIST);
  378. }
  379. #endif
  380. /*
  381. *********************************************************************************************************
  382. * DELETE A TASK
  383. *
  384. * Description: This function allows you to delete a task. The calling task can delete itself by
  385. * its own priority number. The deleted task is returned to the dormant state and can be
  386. * re-activated by creating the deleted task again.
  387. *
  388. * Arguments : prio is the priority of the task to delete. Note that you can explicitly delete
  389. * the current task without knowing its priority level by setting 'prio' to
  390. * OS_PRIO_SELF.
  391. *
  392. * Returns : OS_ERR_NONE if the call is successful
  393. * OS_ERR_ILLEGAL_DEL_RUN_TIME if you tried to delete a task after safety critical operation
  394. * started.
  395. * OS_ERR_TASK_DEL_IDLE if you attempted to delete uC/OS-II's idle task
  396. * OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed
  397. * (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  398. * OS_ERR_TASK_DEL if the task is assigned to a Mutex PIP.
  399. * OS_ERR_TASK_NOT_EXIST if the task you want to delete does not exist.
  400. * OS_ERR_TASK_DEL_ISR if you tried to delete a task from an ISR
  401. *
  402. * Notes : 1) To reduce interrupt latency, OSTaskDel() 'disables' the task:
  403. * a) by making it not ready
  404. * b) by removing it from any wait lists
  405. * c) by preventing OSTimeTick() from making the task ready to run.
  406. * The task can then be 'unlinked' from the miscellaneous structures in uC/OS-II.
  407. * 2) The function OS_Dummy() is called after OS_EXIT_CRITICAL() because, on most processors,
  408. * the next instruction following the enable interrupt instruction is ignored.
  409. * 3) An ISR cannot delete a task.
  410. * 4) The lock nesting counter is incremented because, for a brief instant, if the current
  411. * task is being deleted, the current task would not be able to be rescheduled because it
  412. * is removed from the ready list. Incrementing the nesting counter prevents another task
  413. * from being schedule. This means that an ISR would return to the current task which is
  414. * being deleted. The rest of the deletion would thus be able to be completed.
  415. *********************************************************************************************************
  416. */
  417. #if OS_TASK_DEL_EN > 0u
  418. INT8U OSTaskDel (INT8U prio)
  419. {
  420. #if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
  421. OS_FLAG_NODE *pnode;
  422. #endif
  423. OS_TCB *ptcb;
  424. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  425. OS_CPU_SR cpu_sr = 0u;
  426. #endif
  427. #ifdef OS_SAFETY_CRITICAL_IEC61508
  428. if (OSSafetyCriticalStartFlag == OS_TRUE) {
  429. OS_SAFETY_CRITICAL_EXCEPTION();
  430. return (OS_ERR_ILLEGAL_DEL_RUN_TIME);
  431. }
  432. #endif
  433. if (OSIntNesting > 0u) { /* See if trying to delete from ISR */
  434. return (OS_ERR_TASK_DEL_ISR);
  435. }
  436. if (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to delete idle task */
  437. return (OS_ERR_TASK_DEL_IDLE);
  438. }
  439. #if OS_ARG_CHK_EN > 0u
  440. if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */
  441. if (prio != OS_PRIO_SELF) {
  442. return (OS_ERR_PRIO_INVALID);
  443. }
  444. }
  445. #endif
  446. OS_ENTER_CRITICAL();
  447. if (prio == OS_PRIO_SELF) { /* See if requesting to delete self */
  448. prio = OSTCBCur->OSTCBPrio; /* Set priority to delete to current */
  449. }
  450. ptcb = OSTCBPrioTbl[prio];
  451. if (ptcb == (OS_TCB *)0) { /* Task to delete must exist */
  452. OS_EXIT_CRITICAL();
  453. return (OS_ERR_TASK_NOT_EXIST);
  454. }
  455. if (ptcb == OS_TCB_RESERVED) { /* Must not be assigned to Mutex */
  456. OS_EXIT_CRITICAL();
  457. return (OS_ERR_TASK_DEL);
  458. }
  459. OSRdyTbl[ptcb->OSTCBY] &= (OS_PRIO)~ptcb->OSTCBBitX;
  460. OS_TRACE_TASK_SUSPENDED(ptcb);
  461. if (OSRdyTbl[ptcb->OSTCBY] == 0u) { /* Make task not ready */
  462. OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
  463. }
  464. #if (OS_EVENT_EN)
  465. if (ptcb->OSTCBEventPtr != (OS_EVENT *)0) {
  466. OS_EventTaskRemove(ptcb, ptcb->OSTCBEventPtr); /* Remove this task from any event wait list */
  467. }
  468. #if (OS_EVENT_MULTI_EN > 0u)
  469. if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) { /* Remove this task from any events' wait lists*/
  470. OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr);
  471. }
  472. #endif
  473. #endif
  474. #if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
  475. pnode = ptcb->OSTCBFlagNode;
  476. if (pnode != (OS_FLAG_NODE *)0) { /* If task is waiting on event flag */
  477. OS_FlagUnlink(pnode); /* Remove from wait list */
  478. }
  479. #endif
  480. ptcb->OSTCBDly = 0u; /* Prevent OSTimeTick() from updating */
  481. ptcb->OSTCBStat = OS_STAT_RDY; /* Prevent task from being resumed */
  482. ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
  483. if (OSLockNesting < 255u) { /* Make sure we don't context switch */
  484. OSLockNesting++;
  485. }
  486. OS_EXIT_CRITICAL(); /* Enabling INT. ignores next instruc. */
  487. OS_Dummy(); /* ... Dummy ensures that INTs will be */
  488. OS_ENTER_CRITICAL(); /* ... disabled HERE! */
  489. if (OSLockNesting > 0u) { /* Remove context switch lock */
  490. OSLockNesting--;
  491. }
  492. OSTaskDelHook(ptcb); /* Call user defined hook */
  493. #if OS_TASK_CREATE_EXT_EN > 0u
  494. #if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
  495. OS_TLS_TaskDel(ptcb); /* Call TLS hook */
  496. #endif
  497. #endif
  498. OSTaskCtr--; /* One less task being managed */
  499. OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Clear old priority entry */
  500. if (ptcb->OSTCBPrev == (OS_TCB *)0) { /* Remove from TCB chain */
  501. ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0;
  502. OSTCBList = ptcb->OSTCBNext;
  503. } else {
  504. ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;
  505. ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;
  506. }
  507. ptcb->OSTCBNext = OSTCBFreeList; /* Return TCB to free TCB list */
  508. OSTCBFreeList = ptcb;
  509. #if OS_TASK_NAME_EN > 0u
  510. ptcb->OSTCBTaskName = (INT8U *)(void *)"?";
  511. #endif
  512. OS_EXIT_CRITICAL();
  513. if (OSRunning == OS_TRUE) {
  514. OS_Sched(); /* Find new highest priority task */
  515. }
  516. return (OS_ERR_NONE);
  517. }
  518. #endif
  519. /*
  520. *********************************************************************************************************
  521. * REQUEST THAT A TASK DELETE ITSELF
  522. *
  523. * Description: This function is used to:
  524. * a) notify a task to delete itself.
  525. * b) to see if a task requested that the current task delete itself.
  526. * This function is a little tricky to understand. Basically, you have a task that needs
  527. * to be deleted however, this task has resources that it has allocated (memory buffers,
  528. * semaphores, mailboxes, queues etc.). The task cannot be deleted otherwise these
  529. * resources would not be freed. The requesting task calls OSTaskDelReq() to indicate that
  530. * the task needs to be deleted. Deleting of the task is however, deferred to the task to
  531. * be deleted. For example, suppose that task #10 needs to be deleted. The requesting task
  532. * example, task #5, would call OSTaskDelReq(10). When task #10 gets to execute, it calls
  533. * this function by specifying OS_PRIO_SELF and monitors the returned value. If the return
  534. * value is OS_ERR_TASK_DEL_REQ, another task requested a task delete. Task #10 would look like
  535. * this:
  536. *
  537. * void Task(void *p_arg)
  538. * {
  539. * .
  540. * .
  541. * while (1) {
  542. * OSTimeDly(1);
  543. * if (OSTaskDelReq(OS_PRIO_SELF) == OS_ERR_TASK_DEL_REQ) {
  544. * Release any owned resources;
  545. * De-allocate any dynamic memory;
  546. * OSTaskDel(OS_PRIO_SELF);
  547. * }
  548. * }
  549. * }
  550. *
  551. * Arguments : prio is the priority of the task to request the delete from
  552. *
  553. * Returns : OS_ERR_NONE if the task exist and the request has been registered
  554. * OS_ERR_ILLEGAL_DEL_RUN_TIME if you tried to delete a task after safety critical operation
  555. * started.
  556. * OS_ERR_TASK_NOT_EXIST if the task has been deleted. This allows the caller to know
  557. * whether the request has been executed.
  558. * OS_ERR_TASK_DEL if the task is assigned to a Mutex.
  559. * OS_ERR_TASK_DEL_IDLE if you requested to delete uC/OS-II's idle task
  560. * OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed
  561. * (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  562. * OS_ERR_TASK_DEL_REQ if a task (possibly another task) requested that the running
  563. * task be deleted.
  564. *********************************************************************************************************
  565. */
  566. #if OS_TASK_DEL_EN > 0u
  567. INT8U OSTaskDelReq (INT8U prio)
  568. {
  569. INT8U stat;
  570. OS_TCB *ptcb;
  571. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  572. OS_CPU_SR cpu_sr = 0u;
  573. #endif
  574. #ifdef OS_SAFETY_CRITICAL_IEC61508
  575. if (OSSafetyCriticalStartFlag == OS_TRUE) {
  576. OS_SAFETY_CRITICAL_EXCEPTION();
  577. return (OS_ERR_ILLEGAL_DEL_RUN_TIME);
  578. }
  579. #endif
  580. if (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to delete idle task */
  581. return (OS_ERR_TASK_DEL_IDLE);
  582. }
  583. #if OS_ARG_CHK_EN > 0u
  584. if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */
  585. if (prio != OS_PRIO_SELF) {
  586. return (OS_ERR_PRIO_INVALID);
  587. }
  588. }
  589. #endif
  590. if (prio == OS_PRIO_SELF) { /* See if a task is requesting to ... */
  591. OS_ENTER_CRITICAL(); /* ... this task to delete itself */
  592. stat = OSTCBCur->OSTCBDelReq; /* Return request status to caller */
  593. OS_EXIT_CRITICAL();
  594. return (stat);
  595. }
  596. OS_ENTER_CRITICAL();
  597. ptcb = OSTCBPrioTbl[prio];
  598. if (ptcb == (OS_TCB *)0) { /* Task to delete must exist */
  599. OS_EXIT_CRITICAL();
  600. return (OS_ERR_TASK_NOT_EXIST); /* Task must already be deleted */
  601. }
  602. if (ptcb == OS_TCB_RESERVED) { /* Must NOT be assigned to a Mutex */
  603. OS_EXIT_CRITICAL();
  604. return (OS_ERR_TASK_DEL);
  605. }
  606. ptcb->OSTCBDelReq = OS_ERR_TASK_DEL_REQ; /* Set flag indicating task to be DEL. */
  607. OS_EXIT_CRITICAL();
  608. return (OS_ERR_NONE);
  609. }
  610. #endif
  611. /*
  612. *********************************************************************************************************
  613. * GET THE NAME OF A TASK
  614. *
  615. * Description: This function is called to obtain the name of a task.
  616. *
  617. * Arguments : prio is the priority of the task that you want to obtain the name from.
  618. *
  619. * pname is a pointer to a pointer to an ASCII string that will receive the name of the task.
  620. *
  621. * perr is a pointer to an error code that can contain one of the following values:
  622. *
  623. * OS_ERR_NONE if the requested task is resumed
  624. * OS_ERR_TASK_NOT_EXIST if the task has not been created or is assigned to a Mutex
  625. * OS_ERR_PRIO_INVALID if you specified an invalid priority:
  626. * A higher value than the idle task or not OS_PRIO_SELF.
  627. * OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname'
  628. * OS_ERR_NAME_GET_ISR You called this function from an ISR
  629. *
  630. *
  631. * Returns : The length of the string or 0 if the task does not exist.
  632. *********************************************************************************************************
  633. */
  634. #if OS_TASK_NAME_EN > 0u
  635. INT8U OSTaskNameGet (INT8U prio,
  636. INT8U **pname,
  637. INT8U *perr)
  638. {
  639. OS_TCB *ptcb;
  640. INT8U len;
  641. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  642. OS_CPU_SR cpu_sr = 0u;
  643. #endif
  644. #ifdef OS_SAFETY_CRITICAL
  645. if (perr == (INT8U *)0) {
  646. OS_SAFETY_CRITICAL_EXCEPTION();
  647. return (0u);
  648. }
  649. #endif
  650. #if OS_ARG_CHK_EN > 0u
  651. if (prio > OS_LOWEST_PRIO) { /* Task priority valid ? */
  652. if (prio != OS_PRIO_SELF) {
  653. *perr = OS_ERR_PRIO_INVALID; /* No */
  654. return (0u);
  655. }
  656. }
  657. if (pname == (INT8U **)0) { /* Is 'pname' a NULL pointer? */
  658. *perr = OS_ERR_PNAME_NULL; /* Yes */
  659. return (0u);
  660. }
  661. #endif
  662. if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
  663. *perr = OS_ERR_NAME_GET_ISR;
  664. return (0u);
  665. }
  666. OS_ENTER_CRITICAL();
  667. if (prio == OS_PRIO_SELF) { /* See if caller desires it's own name */
  668. prio = OSTCBCur->OSTCBPrio;
  669. }
  670. ptcb = OSTCBPrioTbl[prio];
  671. if (ptcb == (OS_TCB *)0) { /* Does task exist? */
  672. OS_EXIT_CRITICAL(); /* No */
  673. *perr = OS_ERR_TASK_NOT_EXIST;
  674. return (0u);
  675. }
  676. if (ptcb == OS_TCB_RESERVED) { /* Task assigned to a Mutex? */
  677. OS_EXIT_CRITICAL(); /* Yes */
  678. *perr = OS_ERR_TASK_NOT_EXIST;
  679. return (0u);
  680. }
  681. *pname = ptcb->OSTCBTaskName;
  682. len = OS_StrLen(*pname);
  683. OS_EXIT_CRITICAL();
  684. *perr = OS_ERR_NONE;
  685. return (len);
  686. }
  687. #endif
  688. /*
  689. *********************************************************************************************************
  690. * ASSIGN A NAME TO A TASK
  691. *
  692. * Description: This function is used to set the name of a task.
  693. *
  694. * Arguments : prio is the priority of the task that you want the assign a name to.
  695. *
  696. * pname is a pointer to an ASCII string that contains the name of the task.
  697. *
  698. * perr is a pointer to an error code that can contain one of the following values:
  699. *
  700. * OS_ERR_NONE if the requested task is resumed
  701. * OS_ERR_TASK_NOT_EXIST if the task has not been created or is assigned to a Mutex
  702. * OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname'
  703. * OS_ERR_PRIO_INVALID if you specified an invalid priority:
  704. * A higher value than the idle task or not OS_PRIO_SELF.
  705. * OS_ERR_NAME_SET_ISR if you called this function from an ISR
  706. *
  707. * Returns : None
  708. *********************************************************************************************************
  709. */
  710. #if OS_TASK_NAME_EN > 0u
  711. void OSTaskNameSet (INT8U prio,
  712. INT8U *pname,
  713. INT8U *perr)
  714. {
  715. OS_TCB *ptcb;
  716. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  717. OS_CPU_SR cpu_sr = 0u;
  718. #endif
  719. #ifdef OS_SAFETY_CRITICAL
  720. if (perr == (INT8U *)0) {
  721. OS_SAFETY_CRITICAL_EXCEPTION();
  722. return;
  723. }
  724. #endif
  725. #if OS_ARG_CHK_EN > 0u
  726. if (prio > OS_LOWEST_PRIO) { /* Task priority valid ? */
  727. if (prio != OS_PRIO_SELF) {
  728. *perr = OS_ERR_PRIO_INVALID; /* No */
  729. return;
  730. }
  731. }
  732. if (pname == (INT8U *)0) { /* Is 'pname' a NULL pointer? */
  733. *perr = OS_ERR_PNAME_NULL; /* Yes */
  734. return;
  735. }
  736. #endif
  737. if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
  738. *perr = OS_ERR_NAME_SET_ISR;
  739. return;
  740. }
  741. OS_ENTER_CRITICAL();
  742. if (prio == OS_PRIO_SELF) { /* See if caller desires to set it's own name */
  743. prio = OSTCBCur->OSTCBPrio;
  744. }
  745. ptcb = OSTCBPrioTbl[prio];
  746. if (ptcb == (OS_TCB *)0) { /* Does task exist? */
  747. OS_EXIT_CRITICAL(); /* No */
  748. *perr = OS_ERR_TASK_NOT_EXIST;
  749. return;
  750. }
  751. if (ptcb == OS_TCB_RESERVED) { /* Task assigned to a Mutex? */
  752. OS_EXIT_CRITICAL(); /* Yes */
  753. *perr = OS_ERR_TASK_NOT_EXIST;
  754. return;
  755. }
  756. ptcb->OSTCBTaskName = pname;
  757. OS_TRACE_TASK_NAME_SET(ptcb);
  758. OS_EXIT_CRITICAL();
  759. *perr = OS_ERR_NONE;
  760. }
  761. #endif
  762. /*
  763. *********************************************************************************************************
  764. * RESUME A SUSPENDED TASK
  765. *
  766. * Description: This function is called to resume a previously suspended task. This is the only call that
  767. * will remove an explicit task suspension.
  768. *
  769. * Arguments : prio is the priority of the task to resume.
  770. *
  771. * Returns : OS_ERR_NONE if the requested task is resumed
  772. * OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed
  773. * (i.e. >= OS_LOWEST_PRIO)
  774. * OS_ERR_TASK_RESUME_PRIO if the task to resume does not exist
  775. * OS_ERR_TASK_NOT_EXIST if the task is assigned to a Mutex PIP
  776. * OS_ERR_TASK_NOT_SUSPENDED if the task to resume has not been suspended
  777. *********************************************************************************************************
  778. */
  779. #if OS_TASK_SUSPEND_EN > 0u
  780. INT8U OSTaskResume (INT8U prio)
  781. {
  782. OS_TCB *ptcb;
  783. #if OS_CRITICAL_METHOD == 3u /* Storage for CPU status register */
  784. OS_CPU_SR cpu_sr = 0u;
  785. #endif
  786. #if OS_ARG_CHK_EN > 0u
  787. if (prio >= OS_LOWEST_PRIO) { /* Make sure task priority is valid */
  788. return (OS_ERR_PRIO_INVALID);
  789. }
  790. #endif
  791. OS_ENTER_CRITICAL();
  792. ptcb = OSTCBPrioTbl[prio];
  793. if (ptcb == (OS_TCB *)0) { /* Task to suspend must exist */
  794. OS_EXIT_CRITICAL();
  795. return (OS_ERR_TASK_RESUME_PRIO);
  796. }
  797. if (ptcb == OS_TCB_RESERVED) { /* See if assigned to Mutex */
  798. OS_EXIT_CRITICAL();
  799. return (OS_ERR_TASK_NOT_EXIST);
  800. }
  801. if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != OS_STAT_RDY) { /* Task must be suspended */
  802. ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_SUSPEND; /* Remove suspension */
  803. if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) == OS_STAT_RDY) { /* See if task is now ready */
  804. if (ptcb->OSTCBDly == 0u) {
  805. OSRdyGrp |= ptcb->OSTCBBitY; /* Yes, Make task ready to run */
  806. OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
  807. OS_TRACE_TASK_READY(ptcb);
  808. OS_EXIT_CRITICAL();
  809. if (OSRunning == OS_TRUE) {
  810. OS_TRACE_TASK_RESUME(ptcb);
  811. OS_Sched(); /* Find new highest priority task */
  812. }
  813. } else {
  814. OS_EXIT_CRITICAL();
  815. }
  816. } else { /* Must be pending on event */
  817. OS_EXIT_CRITICAL();
  818. }
  819. return (OS_ERR_NONE);
  820. }
  821. OS_EXIT_CRITICAL();
  822. return (OS_ERR_TASK_NOT_SUSPENDED);
  823. }
  824. #endif
  825. /*
  826. *********************************************************************************************************
  827. * STACK CHECKING
  828. *
  829. * Description: This function is called to check the amount of free memory left on the specified task's
  830. * stack.
  831. *
  832. * Arguments : prio is the task priority
  833. *
  834. * p_stk_data is a pointer to a data structure of type OS_STK_DATA.
  835. *
  836. * Returns : OS_ERR_NONE upon success
  837. * OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed
  838. * (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  839. * OS_ERR_TASK_NOT_EXIST if the desired task has not been created or is assigned to a Mutex PIP
  840. * OS_ERR_TASK_OPT if you did NOT specified OS_TASK_OPT_STK_CHK when the task was created
  841. * OS_ERR_PDATA_NULL if 'p_stk_data' is a NULL pointer
  842. *********************************************************************************************************
  843. */
  844. #if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
  845. INT8U OSTaskStkChk (INT8U prio,
  846. OS_STK_DATA *p_stk_data)
  847. {
  848. OS_TCB *ptcb;
  849. OS_STK *pchk;
  850. INT32U nfree;
  851. INT32U size;
  852. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  853. OS_CPU_SR cpu_sr = 0u;
  854. #endif
  855. #if OS_ARG_CHK_EN > 0u
  856. if (prio > OS_LOWEST_PRIO) { /* Make sure task priority is valid */
  857. if (prio != OS_PRIO_SELF) {
  858. return (OS_ERR_PRIO_INVALID);
  859. }
  860. }
  861. if (p_stk_data == (OS_STK_DATA *)0) { /* Validate 'p_stk_data' */
  862. return (OS_ERR_PDATA_NULL);
  863. }
  864. #endif
  865. p_stk_data->OSFree = 0u; /* Assume failure, set to 0 size */
  866. p_stk_data->OSUsed = 0u;
  867. OS_ENTER_CRITICAL();
  868. if (prio == OS_PRIO_SELF) { /* See if check for SELF */
  869. prio = OSTCBCur->OSTCBPrio;
  870. }
  871. ptcb = OSTCBPrioTbl[prio];
  872. if (ptcb == (OS_TCB *)0) { /* Make sure task exist */
  873. OS_EXIT_CRITICAL();
  874. return (OS_ERR_TASK_NOT_EXIST);
  875. }
  876. if (ptcb == OS_TCB_RESERVED) {
  877. OS_EXIT_CRITICAL();
  878. return (OS_ERR_TASK_NOT_EXIST);
  879. }
  880. if ((ptcb->OSTCBOpt & OS_TASK_OPT_STK_CHK) == 0u) { /* Make sure stack checking option is set */
  881. OS_EXIT_CRITICAL();
  882. return (OS_ERR_TASK_OPT);
  883. }
  884. nfree = 0u;
  885. size = ptcb->OSTCBStkSize;
  886. pchk = ptcb->OSTCBStkBottom;
  887. OS_EXIT_CRITICAL();
  888. #if OS_STK_GROWTH == 1u
  889. while (*pchk++ == (OS_STK)0) { /* Compute the number of zero entries on the stk */
  890. nfree++;
  891. }
  892. #else
  893. while (*pchk-- == (OS_STK)0) {
  894. nfree++;
  895. }
  896. #endif
  897. p_stk_data->OSFree = nfree; /* Store number of free entries on the stk */
  898. p_stk_data->OSUsed = size - nfree; /* Compute number of entries used on the stk */
  899. return (OS_ERR_NONE);
  900. }
  901. #endif
  902. /*
  903. *********************************************************************************************************
  904. * SUSPEND A TASK
  905. *
  906. * Description: This function is called to suspend a task. The task can be the calling task if the
  907. * priority passed to OSTaskSuspend() is the priority of the calling task or OS_PRIO_SELF.
  908. *
  909. * Arguments : prio is the priority of the task to suspend. If you specify OS_PRIO_SELF, the
  910. * calling task will suspend itself and rescheduling will occur.
  911. *
  912. * Returns : OS_ERR_NONE if the requested task is suspended
  913. * OS_ERR_TASK_SUSPEND_IDLE if you attempted to suspend the idle task which is not allowed.
  914. * OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed
  915. * (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  916. * OS_ERR_TASK_SUSPEND_PRIO if the task to suspend does not exist
  917. * OS_ERR_TASK_NOT_EXIST if the task is assigned to a Mutex PIP
  918. *
  919. * Note : You should use this function with great care. If you suspend a task that is waiting for
  920. * an event (i.e. a message, a semaphore, a queue ...) you will prevent this task from
  921. * running when the event arrives.
  922. *********************************************************************************************************
  923. */
  924. #if OS_TASK_SUSPEND_EN > 0u
  925. INT8U OSTaskSuspend (INT8U prio)
  926. {
  927. BOOLEAN self;
  928. OS_TCB *ptcb;
  929. INT8U y;
  930. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  931. OS_CPU_SR cpu_sr = 0u;
  932. #endif
  933. #if OS_ARG_CHK_EN > 0u
  934. if (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to suspend idle task */
  935. return (OS_ERR_TASK_SUSPEND_IDLE);
  936. }
  937. if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */
  938. if (prio != OS_PRIO_SELF) {
  939. return (OS_ERR_PRIO_INVALID);
  940. }
  941. }
  942. #endif
  943. OS_ENTER_CRITICAL();
  944. if (prio == OS_PRIO_SELF) { /* See if suspend SELF */
  945. prio = OSTCBCur->OSTCBPrio;
  946. self = OS_TRUE;
  947. } else if (prio == OSTCBCur->OSTCBPrio) { /* See if suspending self */
  948. self = OS_TRUE;
  949. } else {
  950. self = OS_FALSE; /* No suspending another task */
  951. }
  952. ptcb = OSTCBPrioTbl[prio];
  953. if (ptcb == (OS_TCB *)0) { /* Task to suspend must exist */
  954. OS_EXIT_CRITICAL();
  955. return (OS_ERR_TASK_SUSPEND_PRIO);
  956. }
  957. if (ptcb == OS_TCB_RESERVED) { /* See if assigned to Mutex */
  958. OS_EXIT_CRITICAL();
  959. return (OS_ERR_TASK_NOT_EXIST);
  960. }
  961. y = ptcb->OSTCBY;
  962. OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; /* Make task not ready */
  963. if (OSRdyTbl[y] == 0u) {
  964. OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
  965. }
  966. ptcb->OSTCBStat |= OS_STAT_SUSPEND; /* Status of task is 'SUSPENDED' */
  967. OS_EXIT_CRITICAL();
  968. OS_TRACE_TASK_SUSPEND(ptcb);
  969. OS_TRACE_TASK_SUSPENDED(ptcb);
  970. if (self == OS_TRUE) { /* Context switch only if SELF */
  971. OS_Sched(); /* Find new highest priority task */
  972. }
  973. return (OS_ERR_NONE);
  974. }
  975. #endif
  976. /*
  977. *********************************************************************************************************
  978. * QUERY A TASK
  979. *
  980. * Description: This function is called to obtain a copy of the desired task's TCB.
  981. *
  982. * Arguments : prio is the priority of the task to obtain information from.
  983. *
  984. * p_task_data is a pointer to where the desired task's OS_TCB will be stored.
  985. *
  986. * Returns : OS_ERR_NONE if the requested task is suspended
  987. * OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed
  988. * (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
  989. * OS_ERR_PRIO if the desired task has not been created
  990. * OS_ERR_TASK_NOT_EXIST if the task is assigned to a Mutex PIP
  991. * OS_ERR_PDATA_NULL if 'p_task_data' is a NULL pointer
  992. *********************************************************************************************************
  993. */
  994. #if OS_TASK_QUERY_EN > 0u
  995. INT8U OSTaskQuery (INT8U prio,
  996. OS_TCB *p_task_data)
  997. {
  998. OS_TCB *ptcb;
  999. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  1000. OS_CPU_SR cpu_sr = 0u;
  1001. #endif
  1002. #if OS_ARG_CHK_EN > 0u
  1003. if (prio > OS_LOWEST_PRIO) { /* Task priority valid ? */
  1004. if (prio != OS_PRIO_SELF) {
  1005. return (OS_ERR_PRIO_INVALID);
  1006. }
  1007. }
  1008. if (p_task_data == (OS_TCB *)0) { /* Validate 'p_task_data' */
  1009. return (OS_ERR_PDATA_NULL);
  1010. }
  1011. #endif
  1012. OS_ENTER_CRITICAL();
  1013. if (prio == OS_PRIO_SELF) { /* See if suspend SELF */
  1014. prio = OSTCBCur->OSTCBPrio;
  1015. }
  1016. ptcb = OSTCBPrioTbl[prio];
  1017. if (ptcb == (OS_TCB *)0) { /* Task to query must exist */
  1018. OS_EXIT_CRITICAL();
  1019. return (OS_ERR_PRIO);
  1020. }
  1021. if (ptcb == OS_TCB_RESERVED) { /* Task to query must not be assigned to a Mutex */
  1022. OS_EXIT_CRITICAL();
  1023. return (OS_ERR_TASK_NOT_EXIST);
  1024. }
  1025. /* Copy TCB into user storage area */
  1026. OS_MemCopy((INT8U *)p_task_data, (INT8U *)ptcb, sizeof(OS_TCB));
  1027. OS_EXIT_CRITICAL();
  1028. return (OS_ERR_NONE);
  1029. }
  1030. #endif
  1031. /*
  1032. *********************************************************************************************************
  1033. * GET THE CURRENT VALUE OF A TASK REGISTER
  1034. *
  1035. * Description: This function is called to obtain the current value of a task register. Task registers
  1036. * are application specific and can be used to store task specific values such as 'error
  1037. * numbers' (i.e. errno), statistics, etc. Each task register can hold a 32-bit value.
  1038. *
  1039. * Arguments : prio is the priority of the task you want to get the task register from. If you
  1040. * specify OS_PRIO_SELF then the task register of the current task will be obtained.
  1041. *
  1042. * id is the 'id' of the desired task register. Note that the 'id' must be less
  1043. * than OS_TASK_REG_TBL_SIZE
  1044. *
  1045. * perr is a pointer to a variable that will hold an error code related to this call.
  1046. *
  1047. * OS_ERR_NONE if the call was successful
  1048. * OS_ERR_PRIO_INVALID if you specified an invalid priority
  1049. * OS_ERR_ID_INVALID if the 'id' is not between 0 and OS_TASK_REG_TBL_SIZE-1
  1050. *
  1051. * Returns : The current value of the task's register or 0 if an error is detected.
  1052. *
  1053. * Note(s) : The maximum number of task variables is 254
  1054. *********************************************************************************************************
  1055. */
  1056. #if OS_TASK_REG_TBL_SIZE > 0u
  1057. INT32U OSTaskRegGet (INT8U prio,
  1058. INT8U id,
  1059. INT8U *perr)
  1060. {
  1061. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  1062. OS_CPU_SR cpu_sr = 0u;
  1063. #endif
  1064. INT32U value;
  1065. OS_TCB *ptcb;
  1066. #ifdef OS_SAFETY_CRITICAL
  1067. if (perr == (INT8U *)0) {
  1068. OS_SAFETY_CRITICAL_EXCEPTION();
  1069. return (0u);
  1070. }
  1071. #endif
  1072. #if OS_ARG_CHK_EN > 0u
  1073. if (prio >= OS_LOWEST_PRIO) {
  1074. if (prio != OS_PRIO_SELF) {
  1075. *perr = OS_ERR_PRIO_INVALID;
  1076. return (0u);
  1077. }
  1078. }
  1079. if (id >= OS_TASK_REG_TBL_SIZE) {
  1080. *perr = OS_ERR_ID_INVALID;
  1081. return (0u);
  1082. }
  1083. #endif
  1084. OS_ENTER_CRITICAL();
  1085. if (prio == OS_PRIO_SELF) { /* See if need to get register from current task */
  1086. ptcb = OSTCBCur;
  1087. } else {
  1088. ptcb = OSTCBPrioTbl[prio];
  1089. }
  1090. value = ptcb->OSTCBRegTbl[id];
  1091. OS_EXIT_CRITICAL();
  1092. *perr = OS_ERR_NONE;
  1093. return (value);
  1094. }
  1095. #endif
  1096. /*
  1097. ************************************************************************************************************************
  1098. * ALLOCATE THE NEXT AVAILABLE TASK REGISTER ID
  1099. *
  1100. * Description: This function is called to obtain a task register ID. This function thus allows task registers IDs to be
  1101. * allocated dynamically instead of statically.
  1102. *
  1103. * Arguments : p_err is a pointer to a variable that will hold an error code related to this call.
  1104. *
  1105. * OS_ERR_NONE if the call was successful
  1106. * OS_ERR_NO_MORE_ID_AVAIL if you are attempting to assign more task register IDs than you
  1107. * have available through OS_TASK_REG_TBL_SIZE.
  1108. *
  1109. * Returns : The next available task register 'id' or OS_TASK_REG_TBL_SIZE if an error is detected.
  1110. ************************************************************************************************************************
  1111. */
  1112. #if OS_TASK_REG_TBL_SIZE > 0u
  1113. INT8U OSTaskRegGetID (INT8U *perr)
  1114. {
  1115. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  1116. OS_CPU_SR cpu_sr = 0u;
  1117. #endif
  1118. INT8U id;
  1119. #ifdef OS_SAFETY_CRITICAL
  1120. if (perr == (INT8U *)0) {
  1121. OS_SAFETY_CRITICAL_EXCEPTION();
  1122. return ((INT8U)OS_TASK_REG_TBL_SIZE);
  1123. }
  1124. #endif
  1125. OS_ENTER_CRITICAL();
  1126. if (OSTaskRegNextAvailID >= OS_TASK_REG_TBL_SIZE) { /* See if we exceeded the number of IDs available */
  1127. *perr = OS_ERR_NO_MORE_ID_AVAIL; /* Yes, cannot allocate more task register IDs */
  1128. OS_EXIT_CRITICAL();
  1129. return ((INT8U)OS_TASK_REG_TBL_SIZE);
  1130. }
  1131. id = OSTaskRegNextAvailID; /* Assign the next available ID */
  1132. OSTaskRegNextAvailID++; /* Increment available ID for next request */
  1133. OS_EXIT_CRITICAL();
  1134. *perr = OS_ERR_NONE;
  1135. return (id);
  1136. }
  1137. #endif
  1138. /*
  1139. *********************************************************************************************************
  1140. * SET THE CURRENT VALUE OF A TASK VARIABLE
  1141. *
  1142. * Description: This function is called to change the current value of a task register. Task registers
  1143. * are application specific and can be used to store task specific values such as 'error
  1144. * numbers' (i.e. errno), statistics, etc. Each task register can hold a 32-bit value.
  1145. *
  1146. * Arguments : prio is the priority of the task you want to set the task register for. If you
  1147. * specify OS_PRIO_SELF then the task register of the current task will be obtained.
  1148. *
  1149. * id is the 'id' of the desired task register. Note that the 'id' must be less
  1150. * than OS_TASK_REG_TBL_SIZE
  1151. *
  1152. * value is the desired value for the task register.
  1153. *
  1154. * perr is a pointer to a variable that will hold an error code related to this call.
  1155. *
  1156. * OS_ERR_NONE if the call was successful
  1157. * OS_ERR_PRIO_INVALID if you specified an invalid priority
  1158. * OS_ERR_ID_INVALID if the 'id' is not between 0 and OS_TASK_REG_TBL_SIZE-1
  1159. *
  1160. * Returns : The current value of the task's variable or 0 if an error is detected.
  1161. *
  1162. * Note(s) : The maximum number of task variables is 254
  1163. *********************************************************************************************************
  1164. */
  1165. #if OS_TASK_REG_TBL_SIZE > 0u
  1166. void OSTaskRegSet (INT8U prio,
  1167. INT8U id,
  1168. INT32U value,
  1169. INT8U *perr)
  1170. {
  1171. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  1172. OS_CPU_SR cpu_sr = 0u;
  1173. #endif
  1174. OS_TCB *ptcb;
  1175. #ifdef OS_SAFETY_CRITICAL
  1176. if (perr == (INT8U *)0) {
  1177. OS_SAFETY_CRITICAL_EXCEPTION();
  1178. return;
  1179. }
  1180. #endif
  1181. #if OS_ARG_CHK_EN > 0u
  1182. if (prio >= OS_LOWEST_PRIO) {
  1183. if (prio != OS_PRIO_SELF) {
  1184. *perr = OS_ERR_PRIO_INVALID;
  1185. return;
  1186. }
  1187. }
  1188. if (id >= OS_TASK_REG_TBL_SIZE) {
  1189. *perr = OS_ERR_ID_INVALID;
  1190. return;
  1191. }
  1192. #endif
  1193. OS_ENTER_CRITICAL();
  1194. if (prio == OS_PRIO_SELF) { /* See if need to get register from current task */
  1195. ptcb = OSTCBCur;
  1196. } else {
  1197. ptcb = OSTCBPrioTbl[prio];
  1198. }
  1199. ptcb->OSTCBRegTbl[id] = value;
  1200. OS_EXIT_CRITICAL();
  1201. *perr = OS_ERR_NONE;
  1202. }
  1203. #endif
  1204. /*
  1205. *********************************************************************************************************
  1206. * CATCH ACCIDENTAL TASK RETURN
  1207. *
  1208. * Description: This function is called if a task accidentally returns without deleting itself. In other
  1209. * words, a task should either be an infinite loop or delete itself if it's done.
  1210. *
  1211. * Arguments : none
  1212. *
  1213. * Returns : none
  1214. *
  1215. * Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it.
  1216. *********************************************************************************************************
  1217. */
  1218. void OS_TaskReturn (void)
  1219. {
  1220. OSTaskReturnHook(OSTCBCur); /* Call hook to let user decide on what to do */
  1221. #if OS_TASK_DEL_EN > 0u
  1222. (void)OSTaskDel(OS_PRIO_SELF); /* Delete task if it accidentally returns! */
  1223. #else
  1224. for (;;) {
  1225. OSTimeDly(OS_TICKS_PER_SEC);
  1226. }
  1227. #endif
  1228. }
  1229. /*
  1230. *********************************************************************************************************
  1231. * CLEAR TASK STACK
  1232. *
  1233. * Description: This function is used to clear the stack of a task (i.e. write all zeros)
  1234. *
  1235. * Arguments : pbos is a pointer to the task's bottom of stack. If the configuration constant
  1236. * OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
  1237. * memory to low memory). 'pbos' will thus point to the lowest (valid) memory
  1238. * location of the stack. If OS_STK_GROWTH is set to 0, 'pbos' will point to the
  1239. * highest memory location of the stack and the stack will grow with increasing
  1240. * memory locations. 'pbos' MUST point to a valid 'free' data item.
  1241. *
  1242. * size is the number of 'stack elements' to clear.
  1243. *
  1244. * opt contains additional information (or options) about the behavior of the task. The
  1245. * LOWER 8-bits are reserved by uC/OS-II while the upper 8 bits can be application
  1246. * specific. See OS_TASK_OPT_??? in uCOS-II.H.
  1247. *
  1248. * Returns : none
  1249. *********************************************************************************************************
  1250. */
  1251. #if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
  1252. void OS_TaskStkClr (OS_STK *pbos,
  1253. INT32U size,
  1254. INT16U opt)
  1255. {
  1256. if ((opt & OS_TASK_OPT_STK_CHK) != 0x0000u) { /* See if stack checking has been enabled */
  1257. if ((opt & OS_TASK_OPT_STK_CLR) != 0x0000u) { /* See if stack needs to be cleared */
  1258. #if OS_STK_GROWTH == 1u
  1259. while (size > 0u) { /* Stack grows from HIGH to LOW memory */
  1260. size--;
  1261. *pbos++ = (OS_STK)0; /* Clear from bottom of stack and up! */
  1262. }
  1263. #else
  1264. while (size > 0u) { /* Stack grows from LOW to HIGH memory */
  1265. size--;
  1266. *pbos-- = (OS_STK)0; /* Clear from bottom of stack and down */
  1267. }
  1268. #endif
  1269. }
  1270. }
  1271. }
  1272. #endif
  1273. #endif /* OS_TASK_C */