rtx_thread.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337
  1. /*
  2. * Copyright (c) 2013-2016 ARM Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * -----------------------------------------------------------------------------
  19. *
  20. * Project: CMSIS-RTOS RTX
  21. * Title: Thread functions
  22. *
  23. * -----------------------------------------------------------------------------
  24. */
  25. #include "rtx_lib.h"
  26. // ==== Helper functions ====
  27. /// Set Thread Flags.
  28. /// \param[in] thread thread object.
  29. /// \param[in] flags specifies the flags to set.
  30. /// \return thread flags after setting.
  31. static int32_t os_ThreadFlagsSet (os_thread_t *thread, int32_t flags) {
  32. #ifdef __NO_EXCLUSIVE_ACCESS
  33. uint32_t primask = __get_PRIMASK();
  34. #endif
  35. int32_t thread_flags;
  36. #ifdef __NO_EXCLUSIVE_ACCESS
  37. __disable_irq();
  38. thread->thread_flags |= flags;
  39. thread_flags = thread->thread_flags;
  40. if (primask == 0U) {
  41. __enable_irq();
  42. }
  43. #else
  44. thread_flags = (int32_t)os_exc_set32((uint32_t *)&thread->thread_flags, (uint32_t)flags);
  45. #endif
  46. return thread_flags;
  47. }
  48. /// Clear Thread Flags.
  49. /// \param[in] thread thread object.
  50. /// \param[in] flags specifies the flags to clear.
  51. /// \return thread flags before clearing.
  52. static int32_t os_ThreadFlagsClear (os_thread_t *thread, int32_t flags) {
  53. #ifdef __NO_EXCLUSIVE_ACCESS
  54. uint32_t primask = __get_PRIMASK();
  55. #endif
  56. int32_t thread_flags;
  57. #ifdef __NO_EXCLUSIVE_ACCESS
  58. __disable_irq();
  59. thread_flags = thread->thread_flags;
  60. thread->thread_flags &= ~flags;
  61. if (primask == 0U) {
  62. __enable_irq();
  63. }
  64. #else
  65. thread_flags = (int32_t)os_exc_clr32((uint32_t *)&thread->thread_flags, (uint32_t)flags);
  66. #endif
  67. return thread_flags;
  68. }
  69. /// Check Thread Flags.
  70. /// \param[in] thread thread object.
  71. /// \param[in] flags specifies the flags to check.
  72. /// \param[in] options specifies flags options (osFlagsXxxx).
  73. /// \return thread flags before clearing or 0 if specified flags have not been set.
  74. static int32_t os_ThreadFlagsCheck (os_thread_t *thread, int32_t flags, uint32_t options) {
  75. #ifdef __NO_EXCLUSIVE_ACCESS
  76. uint32_t primask;
  77. #endif
  78. int32_t thread_flags;
  79. if ((options & osFlagsAutoClear) != 0U) {
  80. #ifdef __NO_EXCLUSIVE_ACCESS
  81. primask = __get_PRIMASK();
  82. __disable_irq();
  83. thread_flags = thread->thread_flags;
  84. if ((((options & osFlagsWaitAll) != 0U) && ((thread_flags & flags) != flags)) ||
  85. (((options & osFlagsWaitAll) == 0U) && ((thread_flags & flags) == 0))) {
  86. thread_flags = 0;
  87. } else {
  88. thread->thread_flags &= ~flags;
  89. }
  90. if (primask == 0U) {
  91. __enable_irq();
  92. }
  93. #else
  94. if ((options & osFlagsWaitAll) != 0U) {
  95. thread_flags = (int32_t)os_exc_chk32_all((uint32_t *)&thread->thread_flags, (uint32_t)flags);
  96. } else {
  97. thread_flags = (int32_t)os_exc_chk32_any((uint32_t *)&thread->thread_flags, (uint32_t)flags);
  98. }
  99. #endif
  100. } else {
  101. thread_flags = thread->thread_flags;
  102. if ((((options & osFlagsWaitAll) != 0U) && ((thread_flags & flags) != flags)) ||
  103. (((options & osFlagsWaitAll) == 0U) && ((thread_flags & flags) == 0))) {
  104. thread_flags = 0;
  105. }
  106. }
  107. return thread_flags;
  108. }
  109. // ==== Library functions ====
  110. /// Put a Thread into specified Object list sorted by Priority (Highest at Head).
  111. /// \param[in] object generic object.
  112. /// \param[in] thread thread object.
  113. void os_ThreadListPut (volatile os_object_t *object, os_thread_t *thread) {
  114. os_thread_t *prev, *next;
  115. int32_t priority;
  116. if (thread == NULL) {
  117. return;
  118. }
  119. priority = thread->priority;
  120. prev = (os_thread_t *)(uint32_t)object;
  121. next = object->thread_list;
  122. while ((next != NULL) && (next->priority >= priority)) {
  123. prev = next;
  124. next = next->thread_next;
  125. }
  126. thread->thread_prev = prev;
  127. thread->thread_next = next;
  128. prev->thread_next = thread;
  129. if (next != NULL) {
  130. next->thread_prev = thread;
  131. }
  132. }
  133. /// Get a Thread with Highest Priority from specified Object list and remove it.
  134. /// \param[in] object generic object.
  135. /// \return thread object.
  136. os_thread_t *os_ThreadListGet (volatile os_object_t *object) {
  137. os_thread_t *thread;
  138. thread = object->thread_list;
  139. if (thread != NULL) {
  140. object->thread_list = thread->thread_next;
  141. if (thread->thread_next != NULL) {
  142. thread->thread_next->thread_prev = (os_thread_t *)(uint32_t)object;
  143. }
  144. thread->thread_prev = NULL;
  145. }
  146. return thread;
  147. }
  148. /// Re-sort a Thread in linked Object list by Priority (Highest at Head).
  149. /// \param[in] thread thread object.
  150. void os_ThreadListSort (os_thread_t *thread) {
  151. os_object_t *object;
  152. os_thread_t *thread0;
  153. // Search for object
  154. thread0 = thread;
  155. while (thread0->id == os_IdThread) {
  156. thread0 = thread0->thread_prev;
  157. if (thread0 == NULL) {
  158. return;
  159. }
  160. }
  161. object = (os_object_t *)thread0;
  162. os_ThreadListRemove(thread);
  163. os_ThreadListPut(object, thread);
  164. }
  165. /// Remove a Thread from linked Object list.
  166. /// \param[in] thread thread object.
  167. void os_ThreadListRemove (os_thread_t *thread) {
  168. if (thread->thread_prev != NULL) {
  169. thread->thread_prev->thread_next = thread->thread_next;
  170. if (thread->thread_next != NULL) {
  171. thread->thread_next->thread_prev = thread->thread_prev;
  172. }
  173. thread->thread_prev = NULL;
  174. }
  175. }
  176. /// Unlink a Thread from specified linked list.
  177. /// \param[in] thread thread object.
  178. void os_ThreadListUnlink (os_thread_t **thread_list, os_thread_t *thread) {
  179. if (thread->thread_next != NULL) {
  180. thread->thread_next->thread_prev = thread->thread_prev;
  181. }
  182. if (thread->thread_prev != NULL) {
  183. thread->thread_prev->thread_next = thread->thread_next;
  184. thread->thread_prev = NULL;
  185. } else {
  186. *thread_list = thread->thread_next;
  187. }
  188. }
  189. /// Mark a Thread as Ready and put it into Ready list (sorted by Priority).
  190. /// \param[in] thread thread object.
  191. void os_ThreadReadyPut (os_thread_t *thread) {
  192. thread->state = os_ThreadReady;
  193. os_ThreadListPut(&os_Info.thread.ready, thread);
  194. }
  195. /// Insert a Thread into the Delay list sorted by Delay (Lowest at Head).
  196. /// \param[in] thread thread object.
  197. /// \param[in] millisec delay value.
  198. void os_ThreadDelayInsert (os_thread_t *thread, uint32_t millisec) {
  199. os_thread_t *prev, *next;
  200. if (os_Info.thread.delay_list != NULL) {
  201. prev = NULL;
  202. next = os_Info.thread.delay_list;
  203. while ((next != NULL) && (next->delay <= millisec)) {
  204. millisec -= next->delay;
  205. prev = next;
  206. next = next->delay_next;
  207. }
  208. thread->delay = millisec;
  209. thread->delay_prev = prev;
  210. thread->delay_next = next;
  211. if (prev != NULL) {
  212. prev->delay_next = thread;
  213. } else {
  214. os_Info.thread.delay_list = thread;
  215. }
  216. if (next != NULL) {
  217. next->delay -= millisec;
  218. next->delay_prev = thread;
  219. }
  220. } else {
  221. os_Info.thread.delay_list = thread;
  222. thread->delay = millisec;
  223. thread->delay_prev = NULL;
  224. thread->delay_next = NULL;
  225. }
  226. }
  227. /// Remove a Thread from the Delay list.
  228. /// \param[in] thread thread object.
  229. void os_ThreadDelayRemove (os_thread_t *thread) {
  230. if ((thread->delay_prev == NULL) && (os_Info.thread.delay_list != thread)) {
  231. return;
  232. }
  233. if (thread->delay_next != NULL) {
  234. thread->delay_next->delay += thread->delay;
  235. thread->delay_next->delay_prev = thread->delay_prev;
  236. }
  237. if (thread->delay_prev != NULL) {
  238. thread->delay_prev->delay_next = thread->delay_next;
  239. thread->delay_prev = NULL;
  240. } else {
  241. os_Info.thread.delay_list = thread->delay_next;
  242. }
  243. }
  244. /// Process Thread Delay Tick (executed each System Tick).
  245. void os_ThreadDelayTick (void) {
  246. os_thread_t *thread;
  247. thread = os_Info.thread.delay_list;
  248. if (thread == NULL) {
  249. return;
  250. }
  251. thread->delay--;
  252. if (thread->delay == 0U) {
  253. do {
  254. os_ThreadListRemove(thread);
  255. os_ThreadReadyPut(thread);
  256. thread = thread->delay_next;
  257. } while ((thread != NULL) && (thread->delay == 0U));
  258. if (thread != NULL) {
  259. thread->delay_prev = NULL;
  260. }
  261. os_Info.thread.delay_list = thread;
  262. }
  263. }
  264. /// Get pointer to Thread registers (R0..R3)
  265. /// \param[in] thread thread object.
  266. /// \return pointer to registers R0-R3.
  267. uint32_t *os_ThreadRegPtr (os_thread_t *thread) {
  268. #if (__FPU_USED != 0U)
  269. if (thread->stack_frame & os_StackFrameExtended) {
  270. // Extended Stack Frame: R4-R11, S16-S31, R0-R3, R12, LR, PC, xPSR, S0-S15, FPSCR
  271. return ((uint32_t *)(thread->sp + 8U*4U + 16U*4U));
  272. } else {
  273. // Basic Stack Frame: R4-R11, R0-R3, R12, LR, PC, xPSR
  274. return ((uint32_t *)(thread->sp + 8U*4U));
  275. }
  276. #else
  277. // Stack Frame: R4-R11, R0-R3, R12, LR, PC, xPSR
  278. return ((uint32_t *)(thread->sp + 8U*4U));
  279. #endif
  280. }
  281. /// Block running Thread execution and register it as Ready to Run.
  282. /// \param[in] thread running thread object.
  283. void os_ThreadBlock (os_thread_t *thread) {
  284. os_thread_t *prev, *next;
  285. int32_t priority;
  286. thread->state = os_ThreadReady;
  287. priority = thread->priority;
  288. prev = (os_thread_t *)(uint32_t)&os_Info.thread.ready;
  289. next = prev->thread_next;
  290. while ((next != NULL) && (next->priority > priority)) {
  291. prev = next;
  292. next = next->thread_next;
  293. }
  294. thread->thread_prev = prev;
  295. thread->thread_next = next;
  296. prev->thread_next = thread;
  297. if (next != NULL) {
  298. next->thread_prev = thread;
  299. }
  300. }
  301. /// Switch to specified Thread.
  302. /// \param[in] thread thread object.
  303. void os_ThreadSwitch (os_thread_t *thread) {
  304. thread->state = os_ThreadRunning;
  305. os_Info.thread.run.next = thread;
  306. os_ThreadStackCheck();
  307. }
  308. /// Dispatch specified Thread or Ready Thread with Highest Priority.
  309. /// \param[in] thread thread object or NULL.
  310. void os_ThreadDispatch (os_thread_t *thread) {
  311. uint8_t kernel_state;
  312. os_thread_t *thread_running;
  313. kernel_state = os_KernelGetState();
  314. thread_running = os_ThreadGetRunning();
  315. if (thread == NULL) {
  316. thread = os_Info.thread.ready.thread_list;
  317. if ((kernel_state == os_KernelRunning) &&
  318. (thread_running != NULL) && (thread != NULL) &&
  319. (thread->priority > thread_running->priority)) {
  320. // Preempt running Thread
  321. os_ThreadListRemove(thread);
  322. os_ThreadBlock(thread_running);
  323. os_ThreadSwitch(thread);
  324. }
  325. } else {
  326. if ((kernel_state == os_KernelRunning) &&
  327. (thread_running != NULL) &&
  328. (thread->priority > thread_running->priority)) {
  329. // Preempt running Thread
  330. os_ThreadBlock(thread_running);
  331. os_ThreadSwitch(thread);
  332. } else {
  333. // Put Thread into Ready list
  334. os_ThreadReadyPut(thread);
  335. }
  336. }
  337. }
  338. /// Exit Thread wait state.
  339. /// \param[in] thread thread object.
  340. /// \param[in] ret_val return value.
  341. /// \param[in] dispatch dispatch flag.
  342. void os_ThreadWaitExit (os_thread_t *thread, uint32_t ret_val, bool dispatch) {
  343. uint32_t *reg;
  344. reg = os_ThreadRegPtr(thread);
  345. reg[0] = ret_val;
  346. os_ThreadDelayRemove(thread);
  347. if (dispatch) {
  348. os_ThreadDispatch(thread);
  349. } else {
  350. os_ThreadReadyPut(thread);
  351. }
  352. }
  353. /// Enter Thread wait state.
  354. /// \param[in] state new thread state.
  355. /// \param[in] millisec wait time.
  356. /// \return true - success, false - failure.
  357. bool os_ThreadWaitEnter (uint8_t state, uint32_t millisec) {
  358. os_thread_t *thread;
  359. thread = os_ThreadGetRunning();
  360. if (thread == NULL) {
  361. return false;
  362. }
  363. if (os_KernelGetState() != os_KernelRunning) {
  364. os_ThreadListRemove(thread);
  365. return false;
  366. }
  367. if (os_Info.thread.ready.thread_list == NULL) {
  368. return false;
  369. }
  370. thread->state = state;
  371. if (millisec != osWaitForever) {
  372. os_ThreadDelayInsert(thread, millisec);
  373. }
  374. thread = os_ThreadListGet(&os_Info.thread.ready);
  375. os_ThreadSwitch(thread);
  376. return true;
  377. }
  378. /// Check current running Thread Stack.
  379. void os_ThreadStackCheck (void) {
  380. os_thread_t *thread;
  381. thread = os_ThreadGetRunning();
  382. if (thread != NULL) {
  383. if ((thread->sp <= (uint32_t)thread->stack_mem) ||
  384. (*((uint32_t *)thread->stack_mem) != os_StackMagicWord)) {
  385. os_Error(os_ErrorStackUnderflow, thread);
  386. }
  387. }
  388. }
  389. /// Thread post ISR processing.
  390. /// \param[in] thread thread object.
  391. void os_ThreadPostProcess (os_thread_t *thread) {
  392. int32_t thread_flags;
  393. if ((thread->state == os_ThreadInactive) ||
  394. (thread->state == os_ThreadTerminated)) {
  395. return;
  396. }
  397. // Check if Thread is waiting for Thread Flags
  398. if (thread->state == os_ThreadWaitingThreadFlags) {
  399. thread_flags = os_ThreadFlagsCheck(thread, thread->wait_flags, thread->flags_options);
  400. if (thread_flags > 0) {
  401. os_ThreadWaitExit(thread, (uint32_t)thread_flags, false);
  402. }
  403. }
  404. }
  405. // ==== Service Calls ====
  406. // Service Calls definitions
  407. SVC0_3 (ThreadNew, osThreadId_t, os_thread_func_t, void *, const osThreadAttr_t *)
  408. SVC0_0 (ThreadGetId, osThreadId_t)
  409. SVC0_1 (ThreadGetState, osThreadState_t, osThreadId_t)
  410. SVC0_2 (ThreadSetPriority, osStatus_t, osThreadId_t, osPriority_t)
  411. SVC0_1 (ThreadGetPriority, osPriority_t, osThreadId_t)
  412. SVC0_0 (ThreadYield, osStatus_t)
  413. SVC0_1 (ThreadAbortWait, osStatus_t, osThreadId_t)
  414. SVC0_1 (ThreadSuspend, osStatus_t, osThreadId_t)
  415. SVC0_1 (ThreadResume, osStatus_t, osThreadId_t)
  416. SVC0_1 (ThreadDetach, osStatus_t, osThreadId_t)
  417. SVC0_2 (ThreadJoin, osStatus_t, osThreadId_t, void **)
  418. SVC0_1N(ThreadExit, void, void *)
  419. SVC0_1 (ThreadTerminate, osStatus_t, osThreadId_t)
  420. SVC0_2 (ThreadFlagsSet, int32_t, osThreadId_t, int32_t)
  421. SVC0_2 (ThreadFlagsClear, int32_t, osThreadId_t, int32_t)
  422. SVC0_1 (ThreadFlagsGet, int32_t, osThreadId_t)
  423. SVC0_3 (ThreadFlagsWait, int32_t, int32_t, uint32_t, uint32_t)
  424. /// Create a thread and add it to Active Threads.
  425. /// \note API identical to osThreadNew
  426. osThreadId_t os_svcThreadNew (os_thread_func_t func, void *argument, const osThreadAttr_t *attr) {
  427. os_thread_t *thread;
  428. uint32_t attr_bits;
  429. void *stack_mem;
  430. uint32_t stack_size;
  431. osPriority_t priority;
  432. uint8_t flags;
  433. const char *name;
  434. uint32_t *ptr;
  435. uint32_t n;
  436. // Check parameters
  437. if (func == NULL) {
  438. return (osThreadId_t)NULL;
  439. }
  440. // Process attributes
  441. if (attr != NULL) {
  442. name = attr->name;
  443. attr_bits = attr->attr_bits;
  444. thread = attr->cb_mem;
  445. stack_mem = attr->stack_mem;
  446. stack_size = attr->stack_size;
  447. priority = attr->priority;
  448. if (thread != NULL) {
  449. if (((uint32_t)thread & 3U) || (attr->cb_size < sizeof(os_thread_t))) {
  450. return (osThreadId_t)NULL;
  451. }
  452. } else {
  453. if (attr->cb_size != 0U) {
  454. return (osThreadId_t)NULL;
  455. }
  456. }
  457. if (stack_mem != NULL) {
  458. if (((uint32_t)stack_mem & 7U) || (stack_size == 0U)) {
  459. return (osThreadId_t)NULL;
  460. }
  461. }
  462. if ((priority < osPriorityIdle) || (priority > osPriorityISR)) {
  463. return (osThreadId_t)NULL;
  464. }
  465. } else {
  466. name = NULL;
  467. attr_bits = 0U;
  468. thread = NULL;
  469. stack_mem = NULL;
  470. stack_size = 0U;
  471. priority = osPriorityNormal;
  472. }
  473. // Check stack size
  474. if ((stack_size != 0U) && ((stack_size & 7U) || (stack_size < (64U + 8U)))) {
  475. return (osThreadId_t)NULL;
  476. }
  477. // Allocate object memory if not provided
  478. if (thread == NULL) {
  479. if (os_Info.mpi.thread != NULL) {
  480. thread = os_MemoryPoolAlloc(os_Info.mpi.thread);
  481. } else {
  482. thread = os_MemoryAlloc(os_Info.mem.cb, sizeof(os_thread_t));
  483. }
  484. if (thread == NULL) {
  485. return (osThreadId_t)NULL;
  486. }
  487. flags = os_FlagSystemObject;
  488. } else {
  489. flags = 0U;
  490. }
  491. // Allocate stack memory if not provided
  492. if (stack_mem == NULL) {
  493. if (stack_size == 0U) {
  494. stack_size = os_Config.thread_stack_size;
  495. if (os_Info.mpi.stack != NULL) {
  496. stack_mem = os_MemoryPoolAlloc(os_Info.mpi.stack);
  497. if (stack_mem != NULL) {
  498. flags |= os_ThreadFlagDefStack;
  499. }
  500. }
  501. }
  502. if (stack_mem == NULL) {
  503. stack_mem = os_MemoryAlloc(os_Info.mem.stack, stack_size);
  504. }
  505. if (stack_mem == NULL) {
  506. if (flags & os_FlagSystemObject) {
  507. if (os_Info.mpi.thread != NULL) {
  508. os_MemoryPoolFree(os_Info.mpi.thread, thread);
  509. } else {
  510. os_MemoryFree(os_Info.mem.cb, thread);
  511. }
  512. }
  513. return (osThreadId_t)NULL;
  514. }
  515. flags |= os_FlagSystemMemory;
  516. }
  517. // Initialize control block
  518. thread->id = os_IdThread;
  519. thread->state = os_ThreadReady;
  520. thread->flags = flags;
  521. thread->attr = (uint8_t)attr_bits;
  522. thread->name = name;
  523. thread->thread_next = NULL;
  524. thread->thread_prev = NULL;
  525. thread->delay_next = NULL;
  526. thread->delay_prev = NULL;
  527. thread->thread_join = NULL;
  528. thread->delay = 0U;
  529. thread->priority = (int8_t)priority;
  530. thread->priority_base = (int8_t)priority;
  531. thread->stack_frame = os_StackFrameBasic;
  532. thread->flags_options = 0U;
  533. thread->wait_flags = 0;
  534. thread->thread_flags = 0;
  535. thread->mutex_list = NULL;
  536. thread->stack_mem = stack_mem;
  537. thread->stack_size = stack_size;
  538. thread->sp = (uint32_t)stack_mem + stack_size - 64U;
  539. // Initialize stack
  540. ptr = (uint32_t *)stack_mem;
  541. *ptr++ = os_StackMagicWord;
  542. if (os_Config.flags & os_ConfigStackWatermark) {
  543. for (n = (stack_size/4U) - (16U + 1U); n; n--) {
  544. *ptr++ = os_StackFillPattern;
  545. }
  546. } else {
  547. ptr = (uint32_t *)thread->sp;
  548. }
  549. for (n = 13U; n; n--) {
  550. *ptr++ = 0U; // R4..R11, R0..R3, R12, LR
  551. }
  552. *ptr++ = (uint32_t)osThreadExit; // LR
  553. *ptr++ = (uint32_t)func; // PC
  554. *ptr++ = XPSR_INITIAL_VALUE; // xPSR
  555. *(ptr-8) = (uint32_t)argument; // R0
  556. // Register post ISR processing function
  557. os_Info.post_process.thread = os_ThreadPostProcess;
  558. os_ThreadDispatch(thread);
  559. return (osThreadId_t)thread;
  560. }
  561. /// Return the thread ID of the current running thread.
  562. /// \note API identical to osThreadGetId
  563. osThreadId_t os_svcThreadGetId (void) {
  564. os_thread_t *thread;
  565. thread = os_ThreadGetRunning();
  566. return (osThreadId_t)thread;
  567. }
  568. /// Get current thread state of a thread.
  569. /// \note API identical to osThreadGetState
  570. osThreadState_t os_svcThreadGetState (osThreadId_t thread_id) {
  571. os_thread_t *thread = (os_thread_t *)thread_id;
  572. // Check parameters
  573. if ((thread == NULL) ||
  574. (thread->id != os_IdThread)) {
  575. return osThreadError;
  576. }
  577. return ((osThreadState_t)(thread->state & os_ThreadStateMask));
  578. }
  579. /// Change priority of a thread.
  580. /// \note API identical to osThreadSetPriority
  581. osStatus_t os_svcThreadSetPriority (osThreadId_t thread_id, osPriority_t priority) {
  582. os_thread_t *thread = (os_thread_t *)thread_id;
  583. // Check parameters
  584. if ((thread == NULL) ||
  585. (thread->id != os_IdThread)) {
  586. return osErrorParameter;
  587. }
  588. if ((priority < osPriorityIdle) || (priority > osPriorityISR)) {
  589. return osErrorParameter;
  590. }
  591. // Check object state
  592. if ((thread->state == os_ThreadInactive) ||
  593. (thread->state == os_ThreadTerminated)) {
  594. return osErrorResource;
  595. }
  596. if (thread->priority != (int8_t)priority) {
  597. thread->priority = (int8_t)priority;
  598. thread->priority_base = (int8_t)priority;
  599. os_ThreadListSort(thread);
  600. os_ThreadDispatch(NULL);
  601. }
  602. return osOK;
  603. }
  604. /// Get current priority of a thread.
  605. /// \note API identical to osThreadGetPriority
  606. osPriority_t os_svcThreadGetPriority (osThreadId_t thread_id) {
  607. os_thread_t *thread = (os_thread_t *)thread_id;
  608. // Check parameters
  609. if ((thread == NULL) ||
  610. (thread->id != os_IdThread)) {
  611. return osPriorityError;
  612. }
  613. // Check object state
  614. if ((thread->state == os_ThreadInactive) ||
  615. (thread->state == os_ThreadTerminated)) {
  616. return osPriorityError;
  617. }
  618. return ((osPriority_t)thread->priority);
  619. }
  620. /// Pass control to next thread that is in state READY.
  621. /// \note API identical to osThreadYield
  622. osStatus_t os_svcThreadYield (void) {
  623. uint8_t kernel_state;
  624. os_thread_t *thread_running;
  625. os_thread_t *thread_ready;
  626. kernel_state = os_KernelGetState();
  627. thread_running = os_ThreadGetRunning();
  628. thread_ready = os_Info.thread.ready.thread_list;
  629. if ((kernel_state == os_KernelRunning) &&
  630. (thread_ready != NULL) && (thread_running != NULL) &&
  631. (thread_ready->priority == thread_running->priority)) {
  632. os_ThreadListRemove(thread_ready);
  633. os_ThreadReadyPut(thread_running);
  634. os_ThreadSwitch(thread_ready);
  635. }
  636. return osOK;
  637. }
  638. /// Abort waiting operation of a thread.
  639. /// \note API identical to osThreadAbortWait
  640. osStatus_t os_svcThreadAbortWait (osThreadId_t thread_id) {
  641. os_thread_t *thread = (os_thread_t *)thread_id;
  642. // Check parameters
  643. if ((thread == NULL) ||
  644. (thread->id != os_IdThread)) {
  645. return osErrorParameter;
  646. }
  647. // Check object state
  648. if ((thread->state & os_ThreadStateMask) != os_ThreadWaiting) {
  649. return osErrorResource;
  650. }
  651. // Wakeup Thread
  652. os_ThreadListRemove(thread);
  653. os_ThreadDelayRemove(thread);
  654. os_ThreadDispatch(thread);
  655. return osOK;
  656. }
  657. /// Suspend execution of a thread.
  658. /// \note API identical to osThreadSuspend
  659. osStatus_t os_svcThreadSuspend (osThreadId_t thread_id) {
  660. os_thread_t *thread = (os_thread_t *)thread_id;
  661. // Check parameters
  662. if ((thread == NULL) ||
  663. (thread->id != os_IdThread)) {
  664. return osErrorParameter;
  665. }
  666. // Check object state
  667. switch (thread->state & os_ThreadStateMask) {
  668. case os_ThreadRunning:
  669. if ((os_KernelGetState() != os_KernelRunning) ||
  670. (os_Info.thread.ready.thread_list == NULL)) {
  671. return osErrorResource;
  672. }
  673. os_ThreadSwitch(os_ThreadListGet(&os_Info.thread.ready));
  674. break;
  675. case os_ThreadReady:
  676. os_ThreadListRemove(thread);
  677. break;
  678. case os_ThreadWaiting:
  679. os_ThreadListRemove(thread);
  680. os_ThreadDelayRemove(thread);
  681. break;
  682. case os_ThreadSuspended:
  683. case os_ThreadInactive:
  684. case os_ThreadTerminated:
  685. default:
  686. return osErrorResource;
  687. }
  688. // Update Thread State and put it into Suspended Thread list
  689. thread->state = os_ThreadSuspended;
  690. thread->thread_prev = NULL;
  691. thread->thread_next = os_Info.thread.suspended_list;
  692. os_Info.thread.suspended_list = thread;
  693. return osOK;
  694. }
  695. /// Resume execution of a thread.
  696. /// \note API identical to osThreadResume
  697. osStatus_t os_svcThreadResume (osThreadId_t thread_id) {
  698. os_thread_t *thread = (os_thread_t *)thread_id;
  699. // Check parameters
  700. if ((thread == NULL) ||
  701. (thread->id != os_IdThread)) {
  702. return osErrorParameter;
  703. }
  704. // Check object state
  705. if (thread->state != os_ThreadSuspended) {
  706. return osErrorResource;
  707. }
  708. // Remove Thread from Suspended Thread List
  709. os_ThreadListUnlink(&os_Info.thread.suspended_list, thread);
  710. // Dispatch Thread
  711. os_ThreadDispatch(thread);
  712. return osOK;
  713. }
  714. /// Free Thread resources.
  715. /// \param[in] thread thread object.
  716. static void os_ThreadFree (os_thread_t *thread) {
  717. // Mark object as inactive
  718. thread->state = os_ThreadInactive;
  719. // Free stack memory
  720. if (thread->flags & os_FlagSystemMemory) {
  721. if (thread->flags & os_ThreadFlagDefStack) {
  722. os_MemoryPoolFree(os_Info.mpi.stack, thread->stack_mem);
  723. } else {
  724. os_MemoryFree(os_Info.mem.stack, thread->stack_mem);
  725. }
  726. }
  727. // Free object memory
  728. if (thread->flags & os_FlagSystemObject) {
  729. if (os_Info.mpi.thread != NULL) {
  730. os_MemoryPoolFree(os_Info.mpi.thread, thread);
  731. } else {
  732. os_MemoryFree(os_Info.mem.cb, thread);
  733. }
  734. }
  735. }
  736. /// Detach a thread (thread storage can be reclaimed when thread terminates).
  737. /// \note API identical to osThreadDetach
  738. osStatus_t os_svcThreadDetach (osThreadId_t thread_id) {
  739. os_thread_t *thread = (os_thread_t *)thread_id;
  740. // Check parameters
  741. if ((thread == NULL) ||
  742. (thread->id != os_IdThread)) {
  743. return osErrorParameter;
  744. }
  745. if (thread->attr & osThreadDetached) {
  746. return osErrorResource;
  747. }
  748. // Check object state
  749. if (thread->state == os_ThreadInactive) {
  750. return osErrorResource;
  751. }
  752. if (thread->state == os_ThreadTerminated) {
  753. os_ThreadListUnlink(&os_Info.thread.terminated_list, thread);
  754. os_ThreadFree(thread);
  755. } else {
  756. thread->attr |= osThreadDetached;
  757. }
  758. return osOK;
  759. }
  760. /// Wait for specified thread to terminate.
  761. /// \note API identical to osThreadJoin
  762. osStatus_t os_svcThreadJoin (osThreadId_t thread_id, void **exit_ptr) {
  763. os_thread_t *thread = (os_thread_t *)thread_id;
  764. uint32_t *reg;
  765. // Check parameters
  766. if ((thread == NULL) ||
  767. (thread->id != os_IdThread)) {
  768. return osErrorParameter;
  769. }
  770. if (thread->attr & osThreadDetached) {
  771. return osErrorResource;
  772. }
  773. // Check object state
  774. if ((thread->state == os_ThreadInactive) ||
  775. (thread->state == os_ThreadRunning)) {
  776. return osErrorResource;
  777. }
  778. if (thread->state == os_ThreadTerminated) {
  779. if ((thread->flags & os_ThreadFlagExitPtr) && (exit_ptr != NULL)) {
  780. reg = os_ThreadRegPtr(thread);
  781. *exit_ptr = (void *)reg[0];
  782. }
  783. os_ThreadListUnlink(&os_Info.thread.terminated_list, thread);
  784. os_ThreadFree(thread);
  785. } else {
  786. // Suspend current Thread
  787. if (os_ThreadWaitEnter(os_ThreadWaitingJoin, osWaitForever)) {
  788. thread->thread_join = os_ThreadGetRunning();
  789. }
  790. return osErrorResource;
  791. }
  792. return osOK;
  793. }
  794. /// Terminate execution of current running thread.
  795. /// \note API identical to osThreadExit
  796. void os_svcThreadExit (void *exit_ptr) {
  797. os_thread_t *thread;
  798. uint32_t *reg;
  799. void **ptr;
  800. thread = os_ThreadGetRunning();
  801. if (thread == NULL) {
  802. return;
  803. }
  804. // Release owned Mutexes
  805. os_MutexOwnerRelease(thread->mutex_list);
  806. // Wakeup Thread waiting to Join
  807. if (thread->thread_join != NULL) {
  808. reg = os_ThreadRegPtr(thread->thread_join);
  809. ptr = (void **)reg[1];
  810. if (ptr != NULL) {
  811. *ptr = exit_ptr;
  812. }
  813. os_ThreadWaitExit(thread->thread_join, (uint32_t)osOK, false);
  814. }
  815. // Switch to next Ready Thread
  816. if ((os_KernelGetState() != os_KernelRunning) ||
  817. (os_Info.thread.ready.thread_list == NULL)) {
  818. return;
  819. }
  820. thread->sp = __get_PSP();
  821. os_ThreadSwitch(os_ThreadListGet(&os_Info.thread.ready));
  822. os_ThreadSetRunning(NULL);
  823. if (thread->attr & osThreadDetached) {
  824. os_ThreadFree(thread);
  825. } else {
  826. // Update Thread State and put it into Terminated Thread list
  827. thread->state = os_ThreadTerminated;
  828. thread->flags |= os_ThreadFlagExitPtr;
  829. thread->thread_prev = NULL;
  830. thread->thread_next = os_Info.thread.terminated_list;
  831. os_Info.thread.terminated_list = thread;
  832. }
  833. }
  834. /// Terminate execution of a thread.
  835. /// \note API identical to osThreadTerminate
  836. osStatus_t os_svcThreadTerminate (osThreadId_t thread_id) {
  837. os_thread_t *thread = (os_thread_t *)thread_id;
  838. // Check parameters
  839. if ((thread == NULL) ||
  840. (thread->id != os_IdThread)) {
  841. return osErrorParameter;
  842. }
  843. // Check object state
  844. switch (thread->state & os_ThreadStateMask) {
  845. case os_ThreadRunning:
  846. break;
  847. case os_ThreadReady:
  848. os_ThreadListRemove(thread);
  849. break;
  850. case os_ThreadWaiting:
  851. os_ThreadListRemove(thread);
  852. os_ThreadDelayRemove(thread);
  853. break;
  854. case os_ThreadSuspended:
  855. os_ThreadListUnlink(&os_Info.thread.suspended_list, thread);
  856. break;
  857. case os_ThreadInactive:
  858. case os_ThreadTerminated:
  859. default:
  860. return osErrorResource;
  861. }
  862. // Release owned Mutexes
  863. os_MutexOwnerRelease(thread->mutex_list);
  864. // Wakeup Thread waiting to Join
  865. if (thread->thread_join != NULL) {
  866. os_ThreadWaitExit(thread->thread_join, (uint32_t)osOK, false);
  867. }
  868. // Switch to next Ready Thread when terminating running Thread
  869. if (thread->state == os_ThreadRunning) {
  870. if ((os_KernelGetState() != os_KernelRunning) ||
  871. (os_Info.thread.ready.thread_list == NULL)) {
  872. return osErrorResource;
  873. }
  874. thread->sp = __get_PSP();
  875. os_ThreadSwitch(os_ThreadListGet(&os_Info.thread.ready));
  876. os_ThreadSetRunning(NULL);
  877. } else {
  878. os_ThreadDispatch(NULL);
  879. }
  880. if (thread->attr & osThreadDetached) {
  881. os_ThreadFree(thread);
  882. } else {
  883. // Update Thread State and put it into Terminated Thread list
  884. thread->state = os_ThreadTerminated;
  885. thread->thread_prev = NULL;
  886. thread->thread_next = os_Info.thread.terminated_list;
  887. os_Info.thread.terminated_list = thread;
  888. }
  889. return osOK;
  890. }
  891. /// Set the specified Thread Flags of a thread.
  892. /// \note API identical to osThreadFlagsSet
  893. int32_t os_svcThreadFlagsSet (osThreadId_t thread_id, int32_t flags) {
  894. os_thread_t *thread = (os_thread_t *)thread_id;
  895. int32_t thread_flags;
  896. int32_t thread_flags0;
  897. // Check parameters
  898. if ((thread == NULL) ||
  899. (thread->id != os_IdThread)) {
  900. return osErrorParameter;
  901. }
  902. if ((uint32_t)flags & ~((1U << os_ThreadFlagsLimit) - 1U)) {
  903. return osErrorParameter;
  904. }
  905. // Check object state
  906. if ((thread->state == os_ThreadInactive) ||
  907. (thread->state == os_ThreadTerminated)) {
  908. return osErrorResource;
  909. }
  910. // Set Thread Flags
  911. thread_flags = os_ThreadFlagsSet(thread, flags);
  912. // Check if Thread is waiting for Thread Flags
  913. if (thread->state == os_ThreadWaitingThreadFlags) {
  914. thread_flags0 = os_ThreadFlagsCheck(thread, thread->wait_flags, thread->flags_options);
  915. if (thread_flags0 > 0) {
  916. if ((thread->flags_options & osFlagsAutoClear) != 0U) {
  917. thread_flags = thread_flags0 & ~thread->wait_flags;
  918. } else {
  919. thread_flags = thread_flags0;
  920. }
  921. os_ThreadWaitExit(thread, (uint32_t)thread_flags0, true);
  922. }
  923. }
  924. return thread_flags;
  925. }
  926. /// Clear the specified Thread Flags of a thread.
  927. /// \note API identical to osThreadFlagsClear
  928. int32_t os_svcThreadFlagsClear (osThreadId_t thread_id, int32_t flags) {
  929. os_thread_t *thread = (os_thread_t *)thread_id;
  930. // Check parameters
  931. if ((thread == NULL) ||
  932. (thread->id != os_IdThread)) {
  933. return osErrorParameter;
  934. }
  935. if ((uint32_t)flags & ~((1U << os_ThreadFlagsLimit) - 1U)) {
  936. return osErrorParameter;
  937. }
  938. // Check object state
  939. if ((thread->state == os_ThreadInactive) ||
  940. (thread->state == os_ThreadTerminated)) {
  941. return osErrorResource;
  942. }
  943. // Clear Thread Flags
  944. return os_ThreadFlagsClear(thread, flags);
  945. }
  946. /// Get the current Thread Flags of a thread.
  947. /// \note API identical to osThreadFlagsGet
  948. int32_t os_svcThreadFlagsGet (osThreadId_t thread_id) {
  949. os_thread_t *thread = (os_thread_t *)thread_id;
  950. // Check parameters
  951. if ((thread == NULL) ||
  952. (thread->id != os_IdThread)) {
  953. return 0;
  954. }
  955. // Check object state
  956. if ((thread->state == os_ThreadInactive) ||
  957. (thread->state == os_ThreadTerminated)) {
  958. return 0;
  959. }
  960. return thread->thread_flags;
  961. }
  962. /// Wait for one or more Thread Flags of the current running thread to become signaled.
  963. /// \note API identical to osThreadFlagsWait
  964. int32_t os_svcThreadFlagsWait (int32_t flags, uint32_t options, uint32_t millisec) {
  965. os_thread_t *thread;
  966. int32_t thread_flags;
  967. thread = os_ThreadGetRunning();
  968. if (thread == NULL) {
  969. return osError;
  970. }
  971. // Check parameters
  972. if ((uint32_t)flags & ~((1U << os_ThreadFlagsLimit) - 1U)) {
  973. return osErrorParameter;
  974. }
  975. // Check Thread Flags
  976. thread_flags = os_ThreadFlagsCheck(thread, flags, options);
  977. if (thread_flags > 0) {
  978. return thread_flags;
  979. }
  980. // Check if timeout is specified
  981. if (millisec != 0U) {
  982. // Store waiting flags and options
  983. thread->wait_flags = flags;
  984. thread->flags_options = (uint8_t)options;
  985. // Suspend current Thread
  986. os_ThreadWaitEnter(os_ThreadWaitingThreadFlags, millisec);
  987. return osErrorTimeout;
  988. }
  989. return osErrorResource;
  990. }
  991. // ==== ISR Calls ====
  992. /// Set the specified Thread Flags of a thread.
  993. /// \note API identical to osThreadFlagsSet
  994. __STATIC_INLINE
  995. int32_t os_isrThreadFlagsSet (osThreadId_t thread_id, int32_t flags) {
  996. os_thread_t *thread = (os_thread_t *)thread_id;
  997. int32_t thread_flags;
  998. // Check parameters
  999. if ((thread == NULL) ||
  1000. (thread->id != os_IdThread)) {
  1001. return osErrorParameter;
  1002. }
  1003. if ((uint32_t)flags & ~((1U << os_ThreadFlagsLimit) - 1U)) {
  1004. return osErrorParameter;
  1005. }
  1006. // Check object state
  1007. if ((thread->state == os_ThreadInactive) ||
  1008. (thread->state == os_ThreadTerminated)) {
  1009. return osErrorResource;
  1010. }
  1011. // Set Thread Flags
  1012. thread_flags = os_ThreadFlagsSet(thread, flags);
  1013. // Register post ISR processing
  1014. os_PostProcess((os_object_t *)thread);
  1015. return thread_flags;
  1016. }
  1017. // ==== Public API ====
  1018. /// Create a thread and add it to Active Threads.
  1019. osThreadId_t osThreadNew (os_thread_func_t func, void *argument, const osThreadAttr_t *attr) {
  1020. if (__get_IPSR() != 0U) {
  1021. return (osThreadId_t)NULL; // Not allowed in ISR
  1022. }
  1023. if ((os_KernelGetState() == os_KernelReady) && ((__get_CONTROL() & 1U) == 0U)) {
  1024. // Kernel Ready (not running) and in Privileged mode
  1025. return os_svcThreadNew(func, argument, attr);
  1026. } else {
  1027. return __svcThreadNew(func, argument, attr);
  1028. }
  1029. }
  1030. /// Return the thread ID of the current running thread.
  1031. osThreadId_t osThreadGetId (void) {
  1032. if (__get_IPSR() != 0U) {
  1033. return (osThreadId_t)NULL; // Not allowed in ISR
  1034. }
  1035. return __svcThreadGetId();
  1036. }
  1037. /// Get current thread state of a thread.
  1038. osThreadState_t osThreadGetState (osThreadId_t thread_id) {
  1039. if (__get_IPSR() != 0U) {
  1040. return osThreadError; // Not allowed in ISR
  1041. }
  1042. return __svcThreadGetState(thread_id);
  1043. }
  1044. /// Change priority of a thread.
  1045. osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority) {
  1046. if (__get_IPSR() != 0U) {
  1047. return osErrorISR; // Not allowed in ISR
  1048. }
  1049. return __svcThreadSetPriority(thread_id, priority);
  1050. }
  1051. /// Get current priority of a thread.
  1052. osPriority_t osThreadGetPriority (osThreadId_t thread_id) {
  1053. if (__get_IPSR() != 0U) {
  1054. return osPriorityError; // Not allowed in ISR
  1055. }
  1056. return __svcThreadGetPriority(thread_id);
  1057. }
  1058. /// Pass control to next thread that is in state READY.
  1059. osStatus_t osThreadYield (void) {
  1060. if (__get_IPSR() != 0U) {
  1061. return osErrorISR; // Not allowed in ISR
  1062. }
  1063. return __svcThreadYield();
  1064. }
  1065. /// Abort waiting operation of a thread.
  1066. osStatus_t osThreadAbortWait (osThreadId_t thread_id) {
  1067. if (__get_IPSR() != 0U) {
  1068. return osErrorISR; // Not allowed in ISR
  1069. }
  1070. return __svcThreadAbortWait(thread_id);
  1071. }
  1072. /// Suspend execution of a thread.
  1073. osStatus_t osThreadSuspend (osThreadId_t thread_id) {
  1074. if (__get_IPSR() != 0U) {
  1075. return osErrorISR; // Not allowed in ISR
  1076. }
  1077. return __svcThreadSuspend(thread_id);
  1078. }
  1079. /// Resume execution of a thread.
  1080. osStatus_t osThreadResume (osThreadId_t thread_id) {
  1081. if (__get_IPSR() != 0U) {
  1082. return osErrorISR; // Not allowed in ISR
  1083. }
  1084. return __svcThreadResume(thread_id);
  1085. }
  1086. /// Detach a thread (thread storage can be reclaimed when thread terminates).
  1087. osStatus_t osThreadDetach (osThreadId_t thread_id) {
  1088. if (__get_IPSR() != 0U) {
  1089. return osErrorISR; // Not allowed in ISR
  1090. }
  1091. return __svcThreadDetach(thread_id);
  1092. }
  1093. /// Wait for specified thread to terminate.
  1094. osStatus_t osThreadJoin (osThreadId_t thread_id, void **exit_ptr) {
  1095. if (__get_IPSR() != 0U) {
  1096. return osErrorISR; // Not allowed in ISR
  1097. }
  1098. return __svcThreadJoin(thread_id, exit_ptr);
  1099. }
  1100. /// Terminate execution of current running thread.
  1101. __NO_RETURN void osThreadExit (void *exit_ptr) {
  1102. __svcThreadExit(exit_ptr);
  1103. for (;;);
  1104. }
  1105. /// Terminate execution of a thread.
  1106. osStatus_t osThreadTerminate (osThreadId_t thread_id) {
  1107. if (__get_IPSR() != 0U) {
  1108. return osErrorISR; // Not allowed in ISR
  1109. }
  1110. return __svcThreadTerminate(thread_id);
  1111. }
  1112. /// Set the specified Thread Flags of a thread.
  1113. int32_t osThreadFlagsSet (osThreadId_t thread_id, int32_t flags) {
  1114. if (__get_IPSR() != 0U) { // in ISR
  1115. return os_isrThreadFlagsSet(thread_id, flags);
  1116. } else { // in Thread
  1117. return __svcThreadFlagsSet(thread_id, flags);
  1118. }
  1119. }
  1120. /// Clear the specified Thread Flags of a thread.
  1121. int32_t osThreadFlagsClear (osThreadId_t thread_id, int32_t flags) {
  1122. if (__get_IPSR() != 0U) { // in ISR
  1123. return os_svcThreadFlagsClear(thread_id, flags);
  1124. } else { // in Thread
  1125. return __svcThreadFlagsClear(thread_id, flags);
  1126. }
  1127. }
  1128. /// Get the current Thread Flags of a thread.
  1129. int32_t osThreadFlagsGet (osThreadId_t thread_id) {
  1130. if (__get_IPSR() != 0U) { // in ISR
  1131. return os_svcThreadFlagsGet(thread_id);
  1132. } else { // in Thread
  1133. return __svcThreadFlagsGet(thread_id);
  1134. }
  1135. }
  1136. /// Wait for one or more Thread Flags of the current running thread to become signaled.
  1137. int32_t osThreadFlagsWait (int32_t flags, uint32_t options, uint32_t millisec) {
  1138. if (__get_IPSR() != 0U) {
  1139. return osErrorISR; // Not allowed in ISR
  1140. }
  1141. return __svcThreadFlagsWait(flags, options, millisec);
  1142. }