os_task.c 55 KB

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