os_task.c 58 KB

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