rt_CMSIS.c 65 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180
  1. /*----------------------------------------------------------------------------
  2. * CMSIS-RTOS - RTX
  3. *----------------------------------------------------------------------------
  4. * Name: rt_CMSIS.c
  5. * Purpose: CMSIS RTOS API
  6. * Rev.: V4.82
  7. *----------------------------------------------------------------------------
  8. *
  9. * Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
  10. *
  11. * SPDX-License-Identifier: Apache-2.0
  12. *
  13. * Licensed under the Apache License, Version 2.0 (the License); you may
  14. * not use this file except in compliance with the License.
  15. * You may obtain a copy of the License at
  16. *
  17. * www.apache.org/licenses/LICENSE-2.0
  18. *
  19. * Unless required by applicable law or agreed to in writing, software
  20. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  21. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22. * See the License for the specific language governing permissions and
  23. * limitations under the License.
  24. *---------------------------------------------------------------------------*/
  25. #define __CMSIS_GENERIC
  26. #if defined (__CORTEX_M4) || defined (__CORTEX_M4F)
  27. #include "core_cm4.h"
  28. #elif defined (__CORTEX_M3)
  29. #include "core_cm3.h"
  30. #elif defined (__CORTEX_M0)
  31. #include "core_cm0.h"
  32. #else
  33. #error "Missing __CORTEX_Mx definition"
  34. #endif
  35. #include "rt_TypeDef.h"
  36. #include "RTX_Config.h"
  37. #include "rt_System.h"
  38. #include "rt_Task.h"
  39. #include "rt_Event.h"
  40. #include "rt_List.h"
  41. #include "rt_Time.h"
  42. #include "rt_Mutex.h"
  43. #include "rt_Semaphore.h"
  44. #include "rt_Mailbox.h"
  45. #include "rt_MemBox.h"
  46. #include "rt_Memory.h"
  47. #include "rt_HAL_CM.h"
  48. #define os_thread_cb OS_TCB
  49. #include "cmsis_os.h"
  50. #if (osFeature_Signals != 16)
  51. #error Invalid "osFeature_Signals" value!
  52. #endif
  53. #if (osFeature_Semaphore > 65535)
  54. #error Invalid "osFeature_Semaphore" value!
  55. #endif
  56. #if (osFeature_Wait != 0)
  57. #error osWait not supported!
  58. #endif
  59. // ==== Enumeration, structures, defines ====
  60. // Service Calls defines
  61. #if defined (__CC_ARM) /* ARM Compiler */
  62. #define __NO_RETURN __declspec(noreturn)
  63. #define osEvent_type osEvent
  64. #define osEvent_ret_status ret
  65. #define osEvent_ret_value ret
  66. #define osEvent_ret_msg ret
  67. #define osEvent_ret_mail ret
  68. #define osCallback_type osCallback
  69. #define osCallback_ret ret
  70. #define SVC_0_1(f,t,...) \
  71. __svc_indirect(0) t _##f (t(*)()); \
  72. t f (void); \
  73. __attribute__((always_inline)) \
  74. static __inline t __##f (void) { \
  75. return _##f(f); \
  76. }
  77. #define SVC_1_0(f,t,t1,...) \
  78. __svc_indirect(0) t _##f (t(*)(t1),t1); \
  79. t f (t1 a1); \
  80. __attribute__((always_inline)) \
  81. static __inline t __##f (t1 a1) { \
  82. _##f(f,a1); \
  83. }
  84. #define SVC_1_1(f,t,t1,...) \
  85. __svc_indirect(0) t _##f (t(*)(t1),t1); \
  86. t f (t1 a1); \
  87. __attribute__((always_inline)) \
  88. static __inline t __##f (t1 a1) { \
  89. return _##f(f,a1); \
  90. }
  91. #define SVC_2_1(f,t,t1,t2,...) \
  92. __svc_indirect(0) t _##f (t(*)(t1,t2),t1,t2); \
  93. t f (t1 a1, t2 a2); \
  94. __attribute__((always_inline)) \
  95. static __inline t __##f (t1 a1, t2 a2) { \
  96. return _##f(f,a1,a2); \
  97. }
  98. #define SVC_3_1(f,t,t1,t2,t3,...) \
  99. __svc_indirect(0) t _##f (t(*)(t1,t2,t3),t1,t2,t3); \
  100. t f (t1 a1, t2 a2, t3 a3); \
  101. __attribute__((always_inline)) \
  102. static __inline t __##f (t1 a1, t2 a2, t3 a3) { \
  103. return _##f(f,a1,a2,a3); \
  104. }
  105. #define SVC_4_1(f,t,t1,t2,t3,t4,...) \
  106. __svc_indirect(0) t _##f (t(*)(t1,t2,t3,t4),t1,t2,t3,t4); \
  107. t f (t1 a1, t2 a2, t3 a3, t4 a4); \
  108. __attribute__((always_inline)) \
  109. static __inline t __##f (t1 a1, t2 a2, t3 a3, t4 a4) { \
  110. return _##f(f,a1,a2,a3,a4); \
  111. }
  112. #define SVC_1_2 SVC_1_1
  113. #define SVC_1_3 SVC_1_1
  114. #define SVC_2_3 SVC_2_1
  115. #elif defined (__GNUC__) /* GNU Compiler */
  116. #define __NO_RETURN __attribute__((noreturn))
  117. typedef uint32_t __attribute__((vector_size(8))) ret64;
  118. typedef uint32_t __attribute__((vector_size(16))) ret128;
  119. #define RET_pointer __r0
  120. #define RET_int32_t __r0
  121. #define RET_uint32_t __r0
  122. #define RET_osStatus __r0
  123. #define RET_osPriority __r0
  124. #define RET_osEvent {(osStatus)__r0, {(uint32_t)__r1}, {(void *)__r2}}
  125. #define RET_osCallback {(void *)__r0, (void *)__r1}
  126. #define osEvent_type __attribute__((pcs("aapcs"))) ret128
  127. #define osEvent_ret_status (ret128){ret.status}
  128. #define osEvent_ret_value (ret128){ret.status, ret.value.v}
  129. #define osEvent_ret_msg (ret128){ret.status, ret.value.v, (uint32_t)ret.def.message_id}
  130. #define osEvent_ret_mail (ret128){ret.status, ret.value.v, (uint32_t)ret.def.mail_id}
  131. #define osCallback_type __attribute__((pcs("aapcs"))) ret64
  132. #define osCallback_ret (ret64) {(uint32_t)ret.fp, (uint32_t)ret.arg}
  133. #define SVC_ArgN(n) \
  134. register int __r##n __asm("r"#n);
  135. #define SVC_ArgR(n,t,a) \
  136. register t __r##n __asm("r"#n) = a;
  137. #define SVC_Arg0() \
  138. SVC_ArgN(0) \
  139. SVC_ArgN(1) \
  140. SVC_ArgN(2) \
  141. SVC_ArgN(3)
  142. #define SVC_Arg1(t1) \
  143. SVC_ArgR(0,t1,a1) \
  144. SVC_ArgN(1) \
  145. SVC_ArgN(2) \
  146. SVC_ArgN(3)
  147. #define SVC_Arg2(t1,t2) \
  148. SVC_ArgR(0,t1,a1) \
  149. SVC_ArgR(1,t2,a2) \
  150. SVC_ArgN(2) \
  151. SVC_ArgN(3)
  152. #define SVC_Arg3(t1,t2,t3) \
  153. SVC_ArgR(0,t1,a1) \
  154. SVC_ArgR(1,t2,a2) \
  155. SVC_ArgR(2,t3,a3) \
  156. SVC_ArgN(3)
  157. #define SVC_Arg4(t1,t2,t3,t4) \
  158. SVC_ArgR(0,t1,a1) \
  159. SVC_ArgR(1,t2,a2) \
  160. SVC_ArgR(2,t3,a3) \
  161. SVC_ArgR(3,t4,a4)
  162. #if (defined (__CORTEX_M0))
  163. #define SVC_Call(f) \
  164. __asm volatile \
  165. ( \
  166. "ldr r7,="#f"\n\t" \
  167. "mov r12,r7\n\t" \
  168. "svc 0" \
  169. : "=r" (__r0), "=r" (__r1), "=r" (__r2), "=r" (__r3) \
  170. : "r" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) \
  171. : "r7", "r12", "lr", "cc" \
  172. );
  173. #else
  174. #define SVC_Call(f) \
  175. __asm volatile \
  176. ( \
  177. "ldr r12,="#f"\n\t" \
  178. "svc 0" \
  179. : "=r" (__r0), "=r" (__r1), "=r" (__r2), "=r" (__r3) \
  180. : "r" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) \
  181. : "r12", "lr", "cc" \
  182. );
  183. #endif
  184. #define SVC_0_1(f,t,rv) \
  185. __attribute__((always_inline)) \
  186. static inline t __##f (void) { \
  187. SVC_Arg0(); \
  188. SVC_Call(f); \
  189. return (t) rv; \
  190. }
  191. #define SVC_1_0(f,t,t1) \
  192. __attribute__((always_inline)) \
  193. static inline t __##f (t1 a1) { \
  194. SVC_Arg1(t1); \
  195. SVC_Call(f); \
  196. }
  197. #define SVC_1_1(f,t,t1,rv) \
  198. __attribute__((always_inline)) \
  199. static inline t __##f (t1 a1) { \
  200. SVC_Arg1(t1); \
  201. SVC_Call(f); \
  202. return (t) rv; \
  203. }
  204. #define SVC_2_1(f,t,t1,t2,rv) \
  205. __attribute__((always_inline)) \
  206. static inline t __##f (t1 a1, t2 a2) { \
  207. SVC_Arg2(t1,t2); \
  208. SVC_Call(f); \
  209. return (t) rv; \
  210. }
  211. #define SVC_3_1(f,t,t1,t2,t3,rv) \
  212. __attribute__((always_inline)) \
  213. static inline t __##f (t1 a1, t2 a2, t3 a3) { \
  214. SVC_Arg3(t1,t2,t3); \
  215. SVC_Call(f); \
  216. return (t) rv; \
  217. }
  218. #define SVC_4_1(f,t,t1,t2,t3,t4,rv) \
  219. __attribute__((always_inline)) \
  220. static inline t __##f (t1 a1, t2 a2, t3 a3, t4 a4) { \
  221. SVC_Arg4(t1,t2,t3,t4); \
  222. SVC_Call(f); \
  223. return (t) rv; \
  224. }
  225. #define SVC_1_2 SVC_1_1
  226. #define SVC_1_3 SVC_1_1
  227. #define SVC_2_3 SVC_2_1
  228. #elif defined (__ICCARM__) /* IAR Compiler */
  229. #define __NO_RETURN __noreturn
  230. #define RET_osEvent "=r"(ret.status), "=r"(ret.value), "=r"(ret.def)
  231. #define RET_osCallback "=r"(ret.fp), "=r"(ret.arg)
  232. #define osEvent_type osEvent
  233. #define osEvent_ret_status ret
  234. #define osEvent_ret_value ret
  235. #define osEvent_ret_msg ret
  236. #define osEvent_ret_mail ret
  237. #define osCallback_type uint64_t
  238. #define osCallback_ret ((uint64_t)ret.fp | ((uint64_t)ret.arg)<<32)
  239. #define SVC_Setup(f) \
  240. __asm( \
  241. "mov r12,%0\n" \
  242. :: "r"(&f): "r12" \
  243. );
  244. #define SVC_Ret3() \
  245. __asm( \
  246. "ldr r0,[sp,#0]\n" \
  247. "ldr r1,[sp,#4]\n" \
  248. "ldr r2,[sp,#8]\n" \
  249. );
  250. #define SVC_0_1(f,t,...) \
  251. t f (void); \
  252. _Pragma("swi_number=0") __swi t _##f (void); \
  253. static inline t __##f (void) { \
  254. SVC_Setup(f); \
  255. return _##f(); \
  256. }
  257. #define SVC_1_0(f,t,t1,...) \
  258. t f (t1 a1); \
  259. _Pragma("swi_number=0") __swi t _##f (t1 a1); \
  260. static inline t __##f (t1 a1) { \
  261. SVC_Setup(f); \
  262. _##f(a1); \
  263. }
  264. #define SVC_1_1(f,t,t1,...) \
  265. t f (t1 a1); \
  266. _Pragma("swi_number=0") __swi t _##f (t1 a1); \
  267. static inline t __##f (t1 a1) { \
  268. SVC_Setup(f); \
  269. return _##f(a1); \
  270. }
  271. #define SVC_2_1(f,t,t1,t2,...) \
  272. t f (t1 a1, t2 a2); \
  273. _Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2); \
  274. static inline t __##f (t1 a1, t2 a2) { \
  275. SVC_Setup(f); \
  276. return _##f(a1,a2); \
  277. }
  278. #define SVC_3_1(f,t,t1,t2,t3,...) \
  279. t f (t1 a1, t2 a2, t3 a3); \
  280. _Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2, t3 a3); \
  281. static inline t __##f (t1 a1, t2 a2, t3 a3) { \
  282. SVC_Setup(f); \
  283. return _##f(a1,a2,a3); \
  284. }
  285. #define SVC_4_1(f,t,t1,t2,t3,t4,...) \
  286. t f (t1 a1, t2 a2, t3 a3, t4 a4); \
  287. _Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2, t3 a3, t4 a4); \
  288. static inline t __##f (t1 a1, t2 a2, t3 a3, t4 a4) { \
  289. SVC_Setup(f); \
  290. return _##f(a1,a2,a3,a4); \
  291. }
  292. #define SVC_1_2(f,t,t1,rr) \
  293. uint64_t f (t1 a1); \
  294. _Pragma("swi_number=0") __swi uint64_t _##f (t1 a1); \
  295. static inline t __##f (t1 a1) { \
  296. t ret; \
  297. SVC_Setup(f); \
  298. _##f(a1); \
  299. __asm("" : rr : :); \
  300. return ret; \
  301. }
  302. #define SVC_1_3(f,t,t1,rr) \
  303. t f (t1 a1); \
  304. void f##_ (t1 a1) { \
  305. f(a1); \
  306. SVC_Ret3(); \
  307. } \
  308. _Pragma("swi_number=0") __swi void _##f (t1 a1); \
  309. static inline t __##f (t1 a1) { \
  310. t ret; \
  311. SVC_Setup(f##_); \
  312. _##f(a1); \
  313. __asm("" : rr : :); \
  314. return ret; \
  315. }
  316. #define SVC_2_3(f,t,t1,t2,rr) \
  317. t f (t1 a1, t2 a2); \
  318. void f##_ (t1 a1, t2 a2) { \
  319. f(a1,a2); \
  320. SVC_Ret3(); \
  321. } \
  322. _Pragma("swi_number=0") __swi void _##f (t1 a1, t2 a2); \
  323. static inline t __##f (t1 a1, t2 a2) { \
  324. t ret; \
  325. SVC_Setup(f##_); \
  326. _##f(a1,a2); \
  327. __asm("" : rr : :); \
  328. return ret; \
  329. }
  330. #endif
  331. // Callback structure
  332. typedef struct {
  333. void *fp; // Function pointer
  334. void *arg; // Function argument
  335. } osCallback;
  336. // OS Section definitions
  337. #ifdef OS_SECTIONS_LINK_INFO
  338. extern const uint32_t os_section_id$$Base;
  339. extern const uint32_t os_section_id$$Limit;
  340. #endif
  341. // OS Stack Memory for Threads definitions
  342. extern uint64_t os_stack_mem[];
  343. extern const uint32_t os_stack_sz;
  344. // OS Timers external resources
  345. extern const osThreadDef_t os_thread_def_osTimerThread;
  346. extern osThreadId osThreadId_osTimerThread;
  347. extern const osMessageQDef_t os_messageQ_def_osTimerMessageQ;
  348. extern osMessageQId osMessageQId_osTimerMessageQ;
  349. // ==== Helper Functions ====
  350. /// Convert timeout in millisec to system ticks
  351. static uint16_t rt_ms2tick (uint32_t millisec) {
  352. uint32_t tick;
  353. if (millisec == 0U) { return 0x0U; } // No timeout
  354. if (millisec == osWaitForever) { return 0xFFFFU; } // Indefinite timeout
  355. if (millisec > 4000000U) { return 0xFFFEU; } // Max ticks supported
  356. tick = ((1000U * millisec) + os_clockrate - 1U) / os_clockrate;
  357. if (tick > 0xFFFEU) { return 0xFFFEU; }
  358. return (uint16_t)tick;
  359. }
  360. /// Convert Thread ID to TCB pointer
  361. static P_TCB rt_tid2ptcb (osThreadId thread_id) {
  362. P_TCB ptcb;
  363. if (thread_id == NULL) { return NULL; }
  364. if ((uint32_t)thread_id & 3U) { return NULL; }
  365. #ifdef OS_SECTIONS_LINK_INFO
  366. if ((os_section_id$$Base != 0U) && (os_section_id$$Limit != 0U)) {
  367. if (thread_id < (osThreadId)os_section_id$$Base) { return NULL; }
  368. if (thread_id >= (osThreadId)os_section_id$$Limit) { return NULL; }
  369. }
  370. #endif
  371. ptcb = thread_id;
  372. if (ptcb->cb_type != TCB) { return NULL; }
  373. return ptcb;
  374. }
  375. /// Convert ID pointer to Object pointer
  376. static void *rt_id2obj (void *id) {
  377. if ((uint32_t)id & 3U) { return NULL; }
  378. #ifdef OS_SECTIONS_LINK_INFO
  379. if ((os_section_id$$Base != 0U) && (os_section_id$$Limit != 0U)) {
  380. if (id < (void *)os_section_id$$Base) { return NULL; }
  381. if (id >= (void *)os_section_id$$Limit) { return NULL; }
  382. }
  383. #endif
  384. return id;
  385. }
  386. // ==== Kernel Control ====
  387. uint8_t os_initialized; // Kernel Initialized flag
  388. uint8_t os_running; // Kernel Running flag
  389. // Kernel Control Service Calls declarations
  390. SVC_0_1(svcKernelInitialize, osStatus, RET_osStatus)
  391. SVC_0_1(svcKernelStart, osStatus, RET_osStatus)
  392. SVC_0_1(svcKernelRunning, int32_t, RET_int32_t)
  393. SVC_0_1(svcKernelSysTick, uint32_t, RET_uint32_t)
  394. static void sysThreadError (osStatus status);
  395. osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument);
  396. osMessageQId svcMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id);
  397. // Kernel Control Service Calls
  398. /// Initialize the RTOS Kernel for creating objects
  399. osStatus svcKernelInitialize (void) {
  400. uint32_t ret;
  401. if (os_initialized == 0U) {
  402. // Init Thread Stack Memory (must be 8-byte aligned)
  403. if (((uint32_t)os_stack_mem & 7U) != 0U) { return osErrorNoMemory; }
  404. ret = rt_init_mem(os_stack_mem, os_stack_sz);
  405. if (ret != 0U) { return osErrorNoMemory; }
  406. rt_sys_init(); // RTX System Initialization
  407. }
  408. os_tsk.run->prio = 255U; // Highest priority
  409. if (os_initialized == 0U) {
  410. // Create OS Timers resources (Message Queue & Thread)
  411. osMessageQId_osTimerMessageQ = svcMessageCreate (&os_messageQ_def_osTimerMessageQ, NULL);
  412. osThreadId_osTimerThread = svcThreadCreate(&os_thread_def_osTimerThread, NULL);
  413. }
  414. sysThreadError(osOK);
  415. os_initialized = 1U;
  416. os_running = 0U;
  417. return osOK;
  418. }
  419. /// Start the RTOS Kernel
  420. osStatus svcKernelStart (void) {
  421. if (os_running) { return osOK; }
  422. rt_tsk_prio(0U, os_tsk.run->prio_base); // Restore priority
  423. if (os_tsk.run->task_id == 0xFFU) { // Idle Thread
  424. __set_PSP(os_tsk.run->tsk_stack + (8U*4U)); // Setup PSP
  425. }
  426. if (os_tsk.next == NULL) { // Force context switch
  427. os_tsk.next = os_tsk.run;
  428. os_tsk.run = NULL;
  429. }
  430. rt_sys_start();
  431. os_running = 1U;
  432. return osOK;
  433. }
  434. /// Check if the RTOS kernel is already started
  435. int32_t svcKernelRunning (void) {
  436. return (int32_t)os_running;
  437. }
  438. /// Get the RTOS kernel system timer counter
  439. uint32_t svcKernelSysTick (void) {
  440. uint32_t tick, tick0;
  441. tick = os_tick_val();
  442. if (os_tick_ovf()) {
  443. tick0 = os_tick_val();
  444. if (tick0 < tick) { tick = tick0; }
  445. tick += (os_trv + 1U) * (os_time + 1U);
  446. } else {
  447. tick += (os_trv + 1U) * os_time;
  448. }
  449. return tick;
  450. }
  451. // Kernel Control Public API
  452. /// Initialize the RTOS Kernel for creating objects
  453. osStatus osKernelInitialize (void) {
  454. if (__get_IPSR() != 0U) {
  455. return osErrorISR; // Not allowed in ISR
  456. }
  457. if ((__get_CONTROL() & 1U) == 0U) { // Privileged mode
  458. return svcKernelInitialize();
  459. } else {
  460. return __svcKernelInitialize();
  461. }
  462. }
  463. /// Start the RTOS Kernel
  464. osStatus osKernelStart (void) {
  465. uint32_t stack[8];
  466. if (__get_IPSR() != 0U) {
  467. return osErrorISR; // Not allowed in ISR
  468. }
  469. switch (__get_CONTROL() & 0x03U) {
  470. case 0x00U: // Privileged Thread mode & MSP
  471. __set_PSP((uint32_t)(stack + 8)); // Initial PSP
  472. if (os_flags & 1U) {
  473. __set_CONTROL(0x02U); // Set Privileged Thread mode & PSP
  474. } else {
  475. __set_CONTROL(0x03U); // Set Unprivileged Thread mode & PSP
  476. }
  477. __DSB();
  478. __ISB();
  479. break;
  480. case 0x01U: // Unprivileged Thread mode & MSP
  481. return osErrorOS;
  482. case 0x02U: // Privileged Thread mode & PSP
  483. if ((os_flags & 1U) == 0U) { // Unprivileged Thread mode requested
  484. __set_CONTROL(0x03U); // Set Unprivileged Thread mode & PSP
  485. __DSB();
  486. __ISB();
  487. }
  488. break;
  489. case 0x03U: // Unprivileged Thread mode & PSP
  490. if (os_flags & 1U) { return osErrorOS; } // Privileged Thread mode requested
  491. break;
  492. }
  493. return __svcKernelStart();
  494. }
  495. /// Check if the RTOS kernel is already started
  496. int32_t osKernelRunning (void) {
  497. if ((__get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) {
  498. // in ISR or Privileged
  499. return (int32_t)os_running;
  500. } else {
  501. return __svcKernelRunning();
  502. }
  503. }
  504. /// Get the RTOS kernel system timer counter
  505. uint32_t osKernelSysTick (void) {
  506. if (__get_IPSR() != 0U) { return 0U; } // Not allowed in ISR
  507. return __svcKernelSysTick();
  508. }
  509. // ==== Thread Management ====
  510. /// Set Thread Error (for Create functions which return IDs)
  511. static void sysThreadError (osStatus status) {
  512. // To Do
  513. }
  514. __NO_RETURN void osThreadExit (void);
  515. // Thread Service Calls declarations
  516. SVC_2_1(svcThreadCreate, osThreadId, const osThreadDef_t *, void *, RET_pointer)
  517. SVC_0_1(svcThreadGetId, osThreadId, RET_pointer)
  518. SVC_1_1(svcThreadTerminate, osStatus, osThreadId, RET_osStatus)
  519. SVC_0_1(svcThreadYield, osStatus, RET_osStatus)
  520. SVC_2_1(svcThreadSetPriority, osStatus, osThreadId, osPriority, RET_osStatus)
  521. SVC_1_1(svcThreadGetPriority, osPriority, osThreadId, RET_osPriority)
  522. // Thread Service Calls
  523. /// Create a thread and add it to Active Threads and set it to state READY
  524. osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument) {
  525. P_TCB ptcb;
  526. OS_TID tsk;
  527. void *stk;
  528. if ((thread_def == NULL) ||
  529. (thread_def->pthread == NULL) ||
  530. (thread_def->tpriority < osPriorityIdle) ||
  531. (thread_def->tpriority > osPriorityRealtime)) {
  532. sysThreadError(osErrorParameter);
  533. return NULL;
  534. }
  535. if (thread_def->stacksize != 0U) { // Custom stack size
  536. stk = rt_alloc_mem( // Allocate stack
  537. os_stack_mem,
  538. thread_def->stacksize
  539. );
  540. if (stk == NULL) {
  541. sysThreadError(osErrorNoMemory); // Out of memory
  542. return NULL;
  543. }
  544. } else { // Default stack size
  545. stk = NULL;
  546. }
  547. tsk = rt_tsk_create( // Create task
  548. (FUNCP)thread_def->pthread, // Task function pointer
  549. (uint32_t)
  550. (thread_def->tpriority-osPriorityIdle+1) | // Task priority
  551. (thread_def->stacksize << 8), // Task stack size in bytes
  552. stk, // Pointer to task's stack
  553. argument // Argument to the task
  554. );
  555. if (tsk == 0U) { // Invalid task ID
  556. if (stk != NULL) {
  557. rt_free_mem(os_stack_mem, stk); // Free allocated stack
  558. }
  559. sysThreadError(osErrorNoMemory); // Create task failed (Out of memory)
  560. return NULL;
  561. }
  562. ptcb = (P_TCB)os_active_TCB[tsk - 1U]; // TCB pointer
  563. *((uint32_t *)ptcb->tsk_stack + 13) = (uint32_t)osThreadExit;
  564. return ptcb;
  565. }
  566. /// Return the thread ID of the current running thread
  567. osThreadId svcThreadGetId (void) {
  568. OS_TID tsk;
  569. tsk = rt_tsk_self();
  570. if (tsk == 0U) { return NULL; }
  571. return (P_TCB)os_active_TCB[tsk - 1U];
  572. }
  573. /// Terminate execution of a thread and remove it from ActiveThreads
  574. osStatus svcThreadTerminate (osThreadId thread_id) {
  575. OS_RESULT res;
  576. P_TCB ptcb;
  577. void *stk;
  578. ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
  579. if (ptcb == NULL) {
  580. return osErrorParameter;
  581. }
  582. stk = ptcb->priv_stack ? ptcb->stack : NULL; // Private stack
  583. res = rt_tsk_delete(ptcb->task_id); // Delete task
  584. if (res == OS_R_NOK) {
  585. return osErrorResource; // Delete task failed
  586. }
  587. if (stk != NULL) {
  588. rt_free_mem(os_stack_mem, stk); // Free private stack
  589. }
  590. return osOK;
  591. }
  592. /// Pass control to next thread that is in state READY
  593. osStatus svcThreadYield (void) {
  594. rt_tsk_pass(); // Pass control to next task
  595. return osOK;
  596. }
  597. /// Change priority of an active thread
  598. osStatus svcThreadSetPriority (osThreadId thread_id, osPriority priority) {
  599. OS_RESULT res;
  600. P_TCB ptcb;
  601. ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
  602. if (ptcb == NULL) {
  603. return osErrorParameter;
  604. }
  605. if ((priority < osPriorityIdle) || (priority > osPriorityRealtime)) {
  606. return osErrorValue;
  607. }
  608. res = rt_tsk_prio( // Change task priority
  609. ptcb->task_id, // Task ID
  610. (uint8_t)(priority - osPriorityIdle + 1) // New task priority
  611. );
  612. if (res == OS_R_NOK) {
  613. return osErrorResource; // Change task priority failed
  614. }
  615. return osOK;
  616. }
  617. /// Get current priority of an active thread
  618. osPriority svcThreadGetPriority (osThreadId thread_id) {
  619. P_TCB ptcb;
  620. ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
  621. if (ptcb == NULL) {
  622. return osPriorityError;
  623. }
  624. return (osPriority)(ptcb->prio - 1 + osPriorityIdle);
  625. }
  626. // Thread Public API
  627. /// Create a thread and add it to Active Threads and set it to state READY
  628. osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument) {
  629. if (__get_IPSR() != 0U) {
  630. return NULL; // Not allowed in ISR
  631. }
  632. if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
  633. // Privileged and not running
  634. return svcThreadCreate(thread_def, argument);
  635. } else {
  636. return __svcThreadCreate(thread_def, argument);
  637. }
  638. }
  639. /// Return the thread ID of the current running thread
  640. osThreadId osThreadGetId (void) {
  641. if (__get_IPSR() != 0U) {
  642. return NULL; // Not allowed in ISR
  643. }
  644. return __svcThreadGetId();
  645. }
  646. /// Terminate execution of a thread and remove it from ActiveThreads
  647. osStatus osThreadTerminate (osThreadId thread_id) {
  648. if (__get_IPSR() != 0U) {
  649. return osErrorISR; // Not allowed in ISR
  650. }
  651. return __svcThreadTerminate(thread_id);
  652. }
  653. /// Pass control to next thread that is in state READY
  654. osStatus osThreadYield (void) {
  655. if (__get_IPSR() != 0U) {
  656. return osErrorISR; // Not allowed in ISR
  657. }
  658. return __svcThreadYield();
  659. }
  660. /// Change priority of an active thread
  661. osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority) {
  662. if (__get_IPSR() != 0U) {
  663. return osErrorISR; // Not allowed in ISR
  664. }
  665. return __svcThreadSetPriority(thread_id, priority);
  666. }
  667. /// Get current priority of an active thread
  668. osPriority osThreadGetPriority (osThreadId thread_id) {
  669. if (__get_IPSR() != 0U) {
  670. return osPriorityError; // Not allowed in ISR
  671. }
  672. return __svcThreadGetPriority(thread_id);
  673. }
  674. /// INTERNAL - Not Public
  675. /// Auto Terminate Thread on exit (used implicitly when thread exists)
  676. __NO_RETURN void osThreadExit (void) {
  677. __svcThreadTerminate(__svcThreadGetId());
  678. for (;;); // Should never come here
  679. }
  680. // ==== Generic Wait Functions ====
  681. // Generic Wait Service Calls declarations
  682. SVC_1_1(svcDelay, osStatus, uint32_t, RET_osStatus)
  683. #if osFeature_Wait != 0
  684. SVC_1_3(svcWait, os_InRegs osEvent, uint32_t, RET_osEvent)
  685. #endif
  686. // Generic Wait Service Calls
  687. /// Wait for Timeout (Time Delay)
  688. osStatus svcDelay (uint32_t millisec) {
  689. if (millisec == 0U) { return osOK; }
  690. rt_dly_wait(rt_ms2tick(millisec));
  691. return osEventTimeout;
  692. }
  693. /// Wait for Signal, Message, Mail, or Timeout
  694. #if osFeature_Wait != 0
  695. os_InRegs osEvent_type svcWait (uint32_t millisec) {
  696. osEvent ret;
  697. if (millisec == 0U) {
  698. ret.status = osOK;
  699. return osEvent_ret_status;
  700. }
  701. /* To Do: osEventSignal, osEventMessage, osEventMail */
  702. rt_dly_wait(rt_ms2tick(millisec));
  703. ret.status = osEventTimeout;
  704. return osEvent_ret_status;
  705. }
  706. #endif
  707. // Generic Wait API
  708. /// Wait for Timeout (Time Delay)
  709. osStatus osDelay (uint32_t millisec) {
  710. if (__get_IPSR() != 0U) {
  711. return osErrorISR; // Not allowed in ISR
  712. }
  713. return __svcDelay(millisec);
  714. }
  715. /// Wait for Signal, Message, Mail, or Timeout
  716. os_InRegs osEvent osWait (uint32_t millisec) {
  717. osEvent ret;
  718. #if osFeature_Wait == 0
  719. ret.status = osErrorOS;
  720. return ret;
  721. #else
  722. if (__get_IPSR() != 0U) { // Not allowed in ISR
  723. ret.status = osErrorISR;
  724. return ret;
  725. }
  726. return __svcWait(millisec);
  727. #endif
  728. }
  729. // ==== Timer Management ====
  730. // Timer definitions
  731. #define osTimerInvalid 0U
  732. #define osTimerStopped 1U
  733. #define osTimerRunning 2U
  734. // Timer structures
  735. typedef struct os_timer_cb_ { // Timer Control Block
  736. struct os_timer_cb_ *next; // Pointer to next active Timer
  737. uint8_t state; // Timer State
  738. uint8_t type; // Timer Type (Periodic/One-shot)
  739. uint16_t reserved; // Reserved
  740. uint32_t tcnt; // Timer Delay Count
  741. uint32_t icnt; // Timer Initial Count
  742. void *arg; // Timer Function Argument
  743. const osTimerDef_t *timer; // Pointer to Timer definition
  744. } os_timer_cb;
  745. // Timer variables
  746. os_timer_cb *os_timer_head; // Pointer to first active Timer
  747. // Timer Helper Functions
  748. // Insert Timer into the list sorted by time
  749. static void rt_timer_insert (os_timer_cb *pt, uint32_t tcnt) {
  750. os_timer_cb *p, *prev;
  751. prev = NULL;
  752. p = os_timer_head;
  753. while (p != NULL) {
  754. if (tcnt < p->tcnt) { break; }
  755. tcnt -= p->tcnt;
  756. prev = p;
  757. p = p->next;
  758. }
  759. pt->next = p;
  760. pt->tcnt = tcnt;
  761. if (p != NULL) {
  762. p->tcnt -= pt->tcnt;
  763. }
  764. if (prev != NULL) {
  765. prev->next = pt;
  766. } else {
  767. os_timer_head = pt;
  768. }
  769. }
  770. // Remove Timer from the list
  771. static int32_t rt_timer_remove (os_timer_cb *pt) {
  772. os_timer_cb *p, *prev;
  773. prev = NULL;
  774. p = os_timer_head;
  775. while (p != NULL) {
  776. if (p == pt) { break; }
  777. prev = p;
  778. p = p->next;
  779. }
  780. if (p == NULL) { return -1; }
  781. if (prev != NULL) {
  782. prev->next = pt->next;
  783. } else {
  784. os_timer_head = pt->next;
  785. }
  786. if (pt->next != NULL) {
  787. pt->next->tcnt += pt->tcnt;
  788. }
  789. return 0;
  790. }
  791. // Timer Service Calls declarations
  792. SVC_3_1(svcTimerCreate, osTimerId, const osTimerDef_t *, os_timer_type, void *, RET_pointer)
  793. SVC_2_1(svcTimerStart, osStatus, osTimerId, uint32_t, RET_osStatus)
  794. SVC_1_1(svcTimerStop, osStatus, osTimerId, RET_osStatus)
  795. SVC_1_1(svcTimerDelete, osStatus, osTimerId, RET_osStatus)
  796. SVC_1_2(svcTimerCall, os_InRegs osCallback, osTimerId, RET_osCallback)
  797. // Timer Management Service Calls
  798. /// Create timer
  799. osTimerId svcTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument) {
  800. os_timer_cb *pt;
  801. if ((timer_def == NULL) || (timer_def->ptimer == NULL)) {
  802. sysThreadError(osErrorParameter);
  803. return NULL;
  804. }
  805. pt = timer_def->timer;
  806. if (pt == NULL) {
  807. sysThreadError(osErrorParameter);
  808. return NULL;
  809. }
  810. if ((type != osTimerOnce) && (type != osTimerPeriodic)) {
  811. sysThreadError(osErrorValue);
  812. return NULL;
  813. }
  814. if (osThreadId_osTimerThread == NULL) {
  815. sysThreadError(osErrorResource);
  816. return NULL;
  817. }
  818. if (pt->state != osTimerInvalid){
  819. sysThreadError(osErrorResource);
  820. return NULL;
  821. }
  822. pt->next = NULL;
  823. pt->state = osTimerStopped;
  824. pt->type = (uint8_t)type;
  825. pt->arg = argument;
  826. pt->timer = timer_def;
  827. return (osTimerId)pt;
  828. }
  829. /// Start or restart timer
  830. osStatus svcTimerStart (osTimerId timer_id, uint32_t millisec) {
  831. os_timer_cb *pt;
  832. uint32_t tcnt;
  833. pt = rt_id2obj(timer_id);
  834. if (pt == NULL) {
  835. return osErrorParameter;
  836. }
  837. if (millisec == 0U) { return osErrorValue; }
  838. tcnt = (uint32_t)(((1000U * (uint64_t)millisec) + os_clockrate - 1U) / os_clockrate);
  839. switch (pt->state) {
  840. case osTimerRunning:
  841. if (rt_timer_remove(pt) != 0) {
  842. return osErrorResource;
  843. }
  844. break;
  845. case osTimerStopped:
  846. pt->state = osTimerRunning;
  847. pt->icnt = tcnt;
  848. break;
  849. default:
  850. return osErrorResource;
  851. }
  852. rt_timer_insert(pt, tcnt);
  853. return osOK;
  854. }
  855. /// Stop timer
  856. osStatus svcTimerStop (osTimerId timer_id) {
  857. os_timer_cb *pt;
  858. pt = rt_id2obj(timer_id);
  859. if (pt == NULL) {
  860. return osErrorParameter;
  861. }
  862. if (pt->state != osTimerRunning) { return osErrorResource; }
  863. pt->state = osTimerStopped;
  864. if (rt_timer_remove(pt) != 0) {
  865. return osErrorResource;
  866. }
  867. return osOK;
  868. }
  869. /// Delete timer
  870. osStatus svcTimerDelete (osTimerId timer_id) {
  871. os_timer_cb *pt;
  872. pt = rt_id2obj(timer_id);
  873. if (pt == NULL) {
  874. return osErrorParameter;
  875. }
  876. switch (pt->state) {
  877. case osTimerRunning:
  878. rt_timer_remove(pt);
  879. break;
  880. case osTimerStopped:
  881. break;
  882. default:
  883. return osErrorResource;
  884. }
  885. pt->state = osTimerInvalid;
  886. return osOK;
  887. }
  888. /// Get timer callback parameters
  889. os_InRegs osCallback_type svcTimerCall (osTimerId timer_id) {
  890. os_timer_cb *pt;
  891. osCallback ret;
  892. pt = rt_id2obj(timer_id);
  893. if (pt == NULL) {
  894. ret.fp = NULL;
  895. ret.arg = NULL;
  896. return osCallback_ret;
  897. }
  898. ret.fp = (void *)pt->timer->ptimer;
  899. ret.arg = pt->arg;
  900. return osCallback_ret;
  901. }
  902. osStatus isrMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec);
  903. /// Timer Tick (called each SysTick)
  904. void sysTimerTick (void) {
  905. os_timer_cb *pt, *p;
  906. osStatus status;
  907. p = os_timer_head;
  908. if (p == NULL) { return; }
  909. p->tcnt--;
  910. while ((p != NULL) && (p->tcnt == 0U)) {
  911. pt = p;
  912. p = p->next;
  913. os_timer_head = p;
  914. status = isrMessagePut(osMessageQId_osTimerMessageQ, (uint32_t)pt, 0U);
  915. if (status != osOK) {
  916. os_error(OS_ERR_TIMER_OVF);
  917. }
  918. if (pt->type == (uint8_t)osTimerPeriodic) {
  919. rt_timer_insert(pt, pt->icnt);
  920. } else {
  921. pt->state = osTimerStopped;
  922. }
  923. }
  924. }
  925. /// Get user timers wake-up time
  926. uint32_t sysUserTimerWakeupTime (void) {
  927. if (os_timer_head) {
  928. return os_timer_head->tcnt;
  929. }
  930. return 0xFFFFFFFFU;
  931. }
  932. /// Update user timers on resume
  933. void sysUserTimerUpdate (uint32_t sleep_time) {
  934. while ((os_timer_head != NULL) && (sleep_time != 0U)) {
  935. if (sleep_time >= os_timer_head->tcnt) {
  936. sleep_time -= os_timer_head->tcnt;
  937. os_timer_head->tcnt = 1U;
  938. sysTimerTick();
  939. } else {
  940. os_timer_head->tcnt -= sleep_time;
  941. break;
  942. }
  943. }
  944. }
  945. // Timer Management Public API
  946. /// Create timer
  947. osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument) {
  948. if (__get_IPSR() != 0U) {
  949. return NULL; // Not allowed in ISR
  950. }
  951. if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
  952. // Privileged and not running
  953. return svcTimerCreate(timer_def, type, argument);
  954. } else {
  955. return __svcTimerCreate(timer_def, type, argument);
  956. }
  957. }
  958. /// Start or restart timer
  959. osStatus osTimerStart (osTimerId timer_id, uint32_t millisec) {
  960. if (__get_IPSR() != 0U) {
  961. return osErrorISR; // Not allowed in ISR
  962. }
  963. return __svcTimerStart(timer_id, millisec);
  964. }
  965. /// Stop timer
  966. osStatus osTimerStop (osTimerId timer_id) {
  967. if (__get_IPSR() != 0U) {
  968. return osErrorISR; // Not allowed in ISR
  969. }
  970. return __svcTimerStop(timer_id);
  971. }
  972. /// Delete timer
  973. osStatus osTimerDelete (osTimerId timer_id) {
  974. if (__get_IPSR() != 0U) {
  975. return osErrorISR; // Not allowed in ISR
  976. }
  977. return __svcTimerDelete(timer_id);
  978. }
  979. /// INTERNAL - Not Public
  980. /// Get timer callback parameters (used by OS Timer Thread)
  981. os_InRegs osCallback osTimerCall (osTimerId timer_id) {
  982. return __svcTimerCall(timer_id);
  983. }
  984. // Timer Thread
  985. __NO_RETURN void osTimerThread (void const *argument) {
  986. osCallback cb;
  987. osEvent evt;
  988. for (;;) {
  989. evt = osMessageGet(osMessageQId_osTimerMessageQ, osWaitForever);
  990. if (evt.status == osEventMessage) {
  991. cb = osTimerCall(evt.value.p);
  992. if (cb.fp != NULL) {
  993. (*(os_ptimer)cb.fp)(cb.arg);
  994. }
  995. }
  996. }
  997. }
  998. // ==== Signal Management ====
  999. // Signal Service Calls declarations
  1000. SVC_2_1(svcSignalSet, int32_t, osThreadId, int32_t, RET_int32_t)
  1001. SVC_2_1(svcSignalClear, int32_t, osThreadId, int32_t, RET_int32_t)
  1002. SVC_2_3(svcSignalWait, os_InRegs osEvent, int32_t, uint32_t, RET_osEvent)
  1003. // Signal Service Calls
  1004. /// Set the specified Signal Flags of an active thread
  1005. int32_t svcSignalSet (osThreadId thread_id, int32_t signals) {
  1006. P_TCB ptcb;
  1007. int32_t sig;
  1008. ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
  1009. if (ptcb == NULL) {
  1010. return (int32_t)0x80000000U;
  1011. }
  1012. if ((uint32_t)signals & (0xFFFFFFFFU << osFeature_Signals)) {
  1013. return (int32_t)0x80000000U;
  1014. }
  1015. sig = (int32_t)ptcb->events; // Previous signal flags
  1016. rt_evt_set((uint16_t)signals, ptcb->task_id); // Set event flags
  1017. return sig;
  1018. }
  1019. /// Clear the specified Signal Flags of an active thread
  1020. int32_t svcSignalClear (osThreadId thread_id, int32_t signals) {
  1021. P_TCB ptcb;
  1022. int32_t sig;
  1023. ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
  1024. if (ptcb == NULL) {
  1025. return (int32_t)0x80000000U;
  1026. }
  1027. if ((uint32_t)signals & (0xFFFFFFFFU << osFeature_Signals)) {
  1028. return (int32_t)0x80000000U;
  1029. }
  1030. sig = (int32_t)ptcb->events; // Previous signal flags
  1031. rt_evt_clr((uint16_t)signals, ptcb->task_id); // Clear event flags
  1032. return sig;
  1033. }
  1034. /// Wait for one or more Signal Flags to become signaled for the current RUNNING thread
  1035. os_InRegs osEvent_type svcSignalWait (int32_t signals, uint32_t millisec) {
  1036. OS_RESULT res;
  1037. osEvent ret;
  1038. if ((uint32_t)signals & (0xFFFFFFFFU << osFeature_Signals)) {
  1039. ret.status = osErrorValue;
  1040. return osEvent_ret_status;
  1041. }
  1042. if (signals != 0) { // Wait for all specified signals
  1043. res = rt_evt_wait((uint16_t)signals, rt_ms2tick(millisec), __TRUE);
  1044. } else { // Wait for any signal
  1045. res = rt_evt_wait(0xFFFFU, rt_ms2tick(millisec), __FALSE);
  1046. }
  1047. if (res == OS_R_EVT) {
  1048. ret.status = osEventSignal;
  1049. ret.value.signals = (signals != 0) ? signals : (int32_t)os_tsk.run->waits;
  1050. } else {
  1051. ret.status = (millisec != 0U) ? osEventTimeout : osOK;
  1052. ret.value.signals = 0;
  1053. }
  1054. return osEvent_ret_value;
  1055. }
  1056. // Signal ISR Calls
  1057. /// Set the specified Signal Flags of an active thread
  1058. int32_t isrSignalSet (osThreadId thread_id, int32_t signals) {
  1059. P_TCB ptcb;
  1060. int32_t sig;
  1061. ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
  1062. if (ptcb == NULL) {
  1063. return (int32_t)0x80000000U;
  1064. }
  1065. if ((uint32_t)signals & (0xFFFFFFFFU << osFeature_Signals)) {
  1066. return (int32_t)0x80000000U;
  1067. }
  1068. sig = (int32_t)ptcb->events; // Previous signal flags
  1069. isr_evt_set((uint16_t)signals, ptcb->task_id);// Set event flags
  1070. return sig;
  1071. }
  1072. // Signal Public API
  1073. /// Set the specified Signal Flags of an active thread
  1074. int32_t osSignalSet (osThreadId thread_id, int32_t signals) {
  1075. if (__get_IPSR() != 0U) { // in ISR
  1076. return isrSignalSet(thread_id, signals);
  1077. } else { // in Thread
  1078. return __svcSignalSet(thread_id, signals);
  1079. }
  1080. }
  1081. /// Clear the specified Signal Flags of an active thread
  1082. int32_t osSignalClear (osThreadId thread_id, int32_t signals) {
  1083. if (__get_IPSR() != 0U) {
  1084. return (int32_t)0x80000000U; // Not allowed in ISR
  1085. }
  1086. return __svcSignalClear(thread_id, signals);
  1087. }
  1088. /// Wait for one or more Signal Flags to become signaled for the current RUNNING thread
  1089. os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec) {
  1090. osEvent ret;
  1091. if (__get_IPSR() != 0U) { // Not allowed in ISR
  1092. ret.status = osErrorISR;
  1093. return ret;
  1094. }
  1095. return __svcSignalWait(signals, millisec);
  1096. }
  1097. // ==== Mutex Management ====
  1098. // Mutex Service Calls declarations
  1099. SVC_1_1(svcMutexCreate, osMutexId, const osMutexDef_t *, RET_pointer)
  1100. SVC_2_1(svcMutexWait, osStatus, osMutexId, uint32_t, RET_osStatus)
  1101. SVC_1_1(svcMutexRelease, osStatus, osMutexId, RET_osStatus)
  1102. SVC_1_1(svcMutexDelete, osStatus, osMutexId, RET_osStatus)
  1103. // Mutex Service Calls
  1104. /// Create and Initialize a Mutex object
  1105. osMutexId svcMutexCreate (const osMutexDef_t *mutex_def) {
  1106. OS_ID mut;
  1107. if (mutex_def == NULL) {
  1108. sysThreadError(osErrorParameter);
  1109. return NULL;
  1110. }
  1111. mut = mutex_def->mutex;
  1112. if (mut == NULL) {
  1113. sysThreadError(osErrorParameter);
  1114. return NULL;
  1115. }
  1116. if (((P_MUCB)mut)->cb_type != 0U) {
  1117. sysThreadError(osErrorParameter);
  1118. return NULL;
  1119. }
  1120. rt_mut_init(mut); // Initialize Mutex
  1121. return mut;
  1122. }
  1123. /// Wait until a Mutex becomes available
  1124. osStatus svcMutexWait (osMutexId mutex_id, uint32_t millisec) {
  1125. OS_ID mut;
  1126. OS_RESULT res;
  1127. mut = rt_id2obj(mutex_id);
  1128. if (mut == NULL) {
  1129. return osErrorParameter;
  1130. }
  1131. if (((P_MUCB)mut)->cb_type != MUCB) {
  1132. return osErrorParameter;
  1133. }
  1134. res = rt_mut_wait(mut, rt_ms2tick(millisec)); // Wait for Mutex
  1135. if (res == OS_R_TMO) {
  1136. return ((millisec != 0U) ? osErrorTimeoutResource : osErrorResource);
  1137. }
  1138. if (res == OS_R_NOK) {
  1139. return osErrorResource;
  1140. }
  1141. return osOK;
  1142. }
  1143. /// Release a Mutex that was obtained with osMutexWait
  1144. osStatus svcMutexRelease (osMutexId mutex_id) {
  1145. OS_ID mut;
  1146. OS_RESULT res;
  1147. mut = rt_id2obj(mutex_id);
  1148. if (mut == NULL) {
  1149. return osErrorParameter;
  1150. }
  1151. if (((P_MUCB)mut)->cb_type != MUCB) {
  1152. return osErrorParameter;
  1153. }
  1154. res = rt_mut_release(mut); // Release Mutex
  1155. if (res == OS_R_NOK) {
  1156. return osErrorResource; // Thread not owner or Zero Counter
  1157. }
  1158. return osOK;
  1159. }
  1160. /// Delete a Mutex that was created by osMutexCreate
  1161. osStatus svcMutexDelete (osMutexId mutex_id) {
  1162. OS_ID mut;
  1163. mut = rt_id2obj(mutex_id);
  1164. if (mut == NULL) {
  1165. return osErrorParameter;
  1166. }
  1167. if (((P_MUCB)mut)->cb_type != MUCB) {
  1168. return osErrorParameter;
  1169. }
  1170. rt_mut_delete(mut); // Release Mutex
  1171. return osOK;
  1172. }
  1173. // Mutex Public API
  1174. /// Create and Initialize a Mutex object
  1175. osMutexId osMutexCreate (const osMutexDef_t *mutex_def) {
  1176. if (__get_IPSR() != 0U) {
  1177. return NULL; // Not allowed in ISR
  1178. }
  1179. if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
  1180. // Privileged and not running
  1181. return svcMutexCreate(mutex_def);
  1182. } else {
  1183. return __svcMutexCreate(mutex_def);
  1184. }
  1185. }
  1186. /// Wait until a Mutex becomes available
  1187. osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec) {
  1188. if (__get_IPSR() != 0U) {
  1189. return osErrorISR; // Not allowed in ISR
  1190. }
  1191. return __svcMutexWait(mutex_id, millisec);
  1192. }
  1193. /// Release a Mutex that was obtained with osMutexWait
  1194. osStatus osMutexRelease (osMutexId mutex_id) {
  1195. if (__get_IPSR() != 0U) {
  1196. return osErrorISR; // Not allowed in ISR
  1197. }
  1198. return __svcMutexRelease(mutex_id);
  1199. }
  1200. /// Delete a Mutex that was created by osMutexCreate
  1201. osStatus osMutexDelete (osMutexId mutex_id) {
  1202. if (__get_IPSR() != 0U) {
  1203. return osErrorISR; // Not allowed in ISR
  1204. }
  1205. return __svcMutexDelete(mutex_id);
  1206. }
  1207. // ==== Semaphore Management ====
  1208. // Semaphore Service Calls declarations
  1209. SVC_2_1(svcSemaphoreCreate, osSemaphoreId, const osSemaphoreDef_t *, int32_t, RET_pointer)
  1210. SVC_2_1(svcSemaphoreWait, int32_t, osSemaphoreId, uint32_t, RET_int32_t)
  1211. SVC_1_1(svcSemaphoreRelease, osStatus, osSemaphoreId, RET_osStatus)
  1212. SVC_1_1(svcSemaphoreDelete, osStatus, osSemaphoreId, RET_osStatus)
  1213. // Semaphore Service Calls
  1214. /// Create and Initialize a Semaphore object
  1215. osSemaphoreId svcSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count) {
  1216. OS_ID sem;
  1217. if (semaphore_def == NULL) {
  1218. sysThreadError(osErrorParameter);
  1219. return NULL;
  1220. }
  1221. sem = semaphore_def->semaphore;
  1222. if (sem == NULL) {
  1223. sysThreadError(osErrorParameter);
  1224. return NULL;
  1225. }
  1226. if (((P_SCB)sem)->cb_type != 0U) {
  1227. sysThreadError(osErrorParameter);
  1228. return NULL;
  1229. }
  1230. if (count > osFeature_Semaphore) {
  1231. sysThreadError(osErrorValue);
  1232. return NULL;
  1233. }
  1234. rt_sem_init(sem, (uint16_t)count); // Initialize Semaphore
  1235. return sem;
  1236. }
  1237. /// Wait until a Semaphore becomes available
  1238. int32_t svcSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) {
  1239. OS_ID sem;
  1240. OS_RESULT res;
  1241. sem = rt_id2obj(semaphore_id);
  1242. if (sem == NULL) {
  1243. return -1;
  1244. }
  1245. if (((P_SCB)sem)->cb_type != SCB) {
  1246. return -1;
  1247. }
  1248. res = rt_sem_wait(sem, rt_ms2tick(millisec)); // Wait for Semaphore
  1249. if (res == OS_R_TMO) { return 0; } // Timeout
  1250. return (int32_t)(((P_SCB)sem)->tokens + 1U);
  1251. }
  1252. /// Release a Semaphore
  1253. osStatus svcSemaphoreRelease (osSemaphoreId semaphore_id) {
  1254. OS_ID sem;
  1255. sem = rt_id2obj(semaphore_id);
  1256. if (sem == NULL) {
  1257. return osErrorParameter;
  1258. }
  1259. if (((P_SCB)sem)->cb_type != SCB) {
  1260. return osErrorParameter;
  1261. }
  1262. if ((int32_t)((P_SCB)sem)->tokens == osFeature_Semaphore) {
  1263. return osErrorResource;
  1264. }
  1265. rt_sem_send(sem); // Release Semaphore
  1266. return osOK;
  1267. }
  1268. /// Delete a Semaphore that was created by osSemaphoreCreate
  1269. osStatus svcSemaphoreDelete (osSemaphoreId semaphore_id) {
  1270. OS_ID sem;
  1271. sem = rt_id2obj(semaphore_id);
  1272. if (sem == NULL) {
  1273. return osErrorParameter;
  1274. }
  1275. if (((P_SCB)sem)->cb_type != SCB) {
  1276. return osErrorParameter;
  1277. }
  1278. rt_sem_delete(sem); // Delete Semaphore
  1279. return osOK;
  1280. }
  1281. // Semaphore ISR Calls
  1282. /// Release a Semaphore
  1283. osStatus isrSemaphoreRelease (osSemaphoreId semaphore_id) {
  1284. OS_ID sem;
  1285. sem = rt_id2obj(semaphore_id);
  1286. if (sem == NULL) {
  1287. return osErrorParameter;
  1288. }
  1289. if (((P_SCB)sem)->cb_type != SCB) {
  1290. return osErrorParameter;
  1291. }
  1292. if ((int32_t)((P_SCB)sem)->tokens == osFeature_Semaphore) {
  1293. return osErrorResource;
  1294. }
  1295. isr_sem_send(sem); // Release Semaphore
  1296. return osOK;
  1297. }
  1298. // Semaphore Public API
  1299. /// Create and Initialize a Semaphore object
  1300. osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count) {
  1301. if (__get_IPSR() != 0U) {
  1302. return NULL; // Not allowed in ISR
  1303. }
  1304. if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
  1305. // Privileged and not running
  1306. return svcSemaphoreCreate(semaphore_def, count);
  1307. } else {
  1308. return __svcSemaphoreCreate(semaphore_def, count);
  1309. }
  1310. }
  1311. /// Wait until a Semaphore becomes available
  1312. int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) {
  1313. if (__get_IPSR() != 0U) {
  1314. return -1; // Not allowed in ISR
  1315. }
  1316. return __svcSemaphoreWait(semaphore_id, millisec);
  1317. }
  1318. /// Release a Semaphore
  1319. osStatus osSemaphoreRelease (osSemaphoreId semaphore_id) {
  1320. if (__get_IPSR() != 0U) { // in ISR
  1321. return isrSemaphoreRelease(semaphore_id);
  1322. } else { // in Thread
  1323. return __svcSemaphoreRelease(semaphore_id);
  1324. }
  1325. }
  1326. /// Delete a Semaphore that was created by osSemaphoreCreate
  1327. osStatus osSemaphoreDelete (osSemaphoreId semaphore_id) {
  1328. if (__get_IPSR() != 0U) {
  1329. return osErrorISR; // Not allowed in ISR
  1330. }
  1331. return __svcSemaphoreDelete(semaphore_id);
  1332. }
  1333. // ==== Memory Management Functions ====
  1334. // Memory Management Helper Functions
  1335. // Clear Memory Box (Zero init)
  1336. static void rt_clr_box (void *box_mem, void *box) {
  1337. uint32_t *p, n;
  1338. if ((box_mem != NULL) && (box != NULL)) {
  1339. p = box;
  1340. for (n = ((P_BM)box_mem)->blk_size; n; n -= 4U) {
  1341. *p++ = 0U;
  1342. }
  1343. }
  1344. }
  1345. // Memory Management Service Calls declarations
  1346. SVC_1_1(svcPoolCreate, osPoolId, const osPoolDef_t *, RET_pointer)
  1347. SVC_1_1(sysPoolAlloc, void *, osPoolId, RET_pointer)
  1348. SVC_2_1(sysPoolFree, osStatus, osPoolId, void *, RET_osStatus)
  1349. // Memory Management Service & ISR Calls
  1350. /// Create and Initialize memory pool
  1351. osPoolId svcPoolCreate (const osPoolDef_t *pool_def) {
  1352. uint32_t blk_sz;
  1353. if ((pool_def == NULL) ||
  1354. (pool_def->pool_sz == 0U) ||
  1355. (pool_def->item_sz == 0U) ||
  1356. (pool_def->pool == NULL)) {
  1357. sysThreadError(osErrorParameter);
  1358. return NULL;
  1359. }
  1360. blk_sz = (pool_def->item_sz + 3U) & (uint32_t)~3U;
  1361. _init_box(pool_def->pool, sizeof(struct OS_BM) + (pool_def->pool_sz * blk_sz), blk_sz);
  1362. return pool_def->pool;
  1363. }
  1364. /// Allocate a memory block from a memory pool
  1365. void *sysPoolAlloc (osPoolId pool_id) {
  1366. void *mem;
  1367. if (pool_id == NULL) {
  1368. return NULL;
  1369. }
  1370. mem = rt_alloc_box(pool_id);
  1371. return mem;
  1372. }
  1373. /// Return an allocated memory block back to a specific memory pool
  1374. osStatus sysPoolFree (osPoolId pool_id, void *block) {
  1375. uint32_t res;
  1376. if (pool_id == NULL) {
  1377. return osErrorParameter;
  1378. }
  1379. res = rt_free_box(pool_id, block);
  1380. if (res != 0) {
  1381. return osErrorValue;
  1382. }
  1383. return osOK;
  1384. }
  1385. // Memory Management Public API
  1386. /// Create and Initialize memory pool
  1387. osPoolId osPoolCreate (const osPoolDef_t *pool_def) {
  1388. if (__get_IPSR() != 0U) {
  1389. return NULL; // Not allowed in ISR
  1390. }
  1391. if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
  1392. // Privileged and not running
  1393. return svcPoolCreate(pool_def);
  1394. } else {
  1395. return __svcPoolCreate(pool_def);
  1396. }
  1397. }
  1398. /// Allocate a memory block from a memory pool
  1399. void *osPoolAlloc (osPoolId pool_id) {
  1400. if ((__get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) { // in ISR or Privileged
  1401. return sysPoolAlloc(pool_id);
  1402. } else { // in Thread
  1403. return __sysPoolAlloc(pool_id);
  1404. }
  1405. }
  1406. /// Allocate a memory block from a memory pool and set memory block to zero
  1407. void *osPoolCAlloc (osPoolId pool_id) {
  1408. void *mem;
  1409. if ((__get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) { // in ISR or Privileged
  1410. mem = sysPoolAlloc(pool_id);
  1411. } else { // in Thread
  1412. mem = __sysPoolAlloc(pool_id);
  1413. }
  1414. rt_clr_box(pool_id, mem);
  1415. return mem;
  1416. }
  1417. /// Return an allocated memory block back to a specific memory pool
  1418. osStatus osPoolFree (osPoolId pool_id, void *block) {
  1419. if ((__get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) { // in ISR or Privileged
  1420. return sysPoolFree(pool_id, block);
  1421. } else { // in Thread
  1422. return __sysPoolFree(pool_id, block);
  1423. }
  1424. }
  1425. // ==== Message Queue Management Functions ====
  1426. // Message Queue Management Service Calls declarations
  1427. SVC_2_1(svcMessageCreate, osMessageQId, const osMessageQDef_t *, osThreadId, RET_pointer)
  1428. SVC_3_1(svcMessagePut, osStatus, osMessageQId, uint32_t, uint32_t, RET_osStatus)
  1429. SVC_2_3(svcMessageGet, os_InRegs osEvent, osMessageQId, uint32_t, RET_osEvent)
  1430. // Message Queue Service Calls
  1431. /// Create and Initialize Message Queue
  1432. osMessageQId svcMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id) {
  1433. if ((queue_def == NULL) ||
  1434. (queue_def->queue_sz == 0U) ||
  1435. (queue_def->pool == NULL)) {
  1436. sysThreadError(osErrorParameter);
  1437. return NULL;
  1438. }
  1439. if (((P_MCB)queue_def->pool)->cb_type != 0U) {
  1440. sysThreadError(osErrorParameter);
  1441. return NULL;
  1442. }
  1443. rt_mbx_init(queue_def->pool, (uint16_t)(4U*(queue_def->queue_sz + 4U)));
  1444. return queue_def->pool;
  1445. }
  1446. /// Put a Message to a Queue
  1447. osStatus svcMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
  1448. OS_RESULT res;
  1449. if (queue_id == NULL) {
  1450. return osErrorParameter;
  1451. }
  1452. if (((P_MCB)queue_id)->cb_type != MCB) {
  1453. return osErrorParameter;
  1454. }
  1455. res = rt_mbx_send(queue_id, (void *)info, rt_ms2tick(millisec));
  1456. if (res == OS_R_TMO) {
  1457. return ((millisec != 0U) ? osErrorTimeoutResource : osErrorResource);
  1458. }
  1459. return osOK;
  1460. }
  1461. /// Get a Message or Wait for a Message from a Queue
  1462. os_InRegs osEvent_type svcMessageGet (osMessageQId queue_id, uint32_t millisec) {
  1463. OS_RESULT res;
  1464. osEvent ret;
  1465. if (queue_id == NULL) {
  1466. ret.status = osErrorParameter;
  1467. return osEvent_ret_status;
  1468. }
  1469. if (((P_MCB)queue_id)->cb_type != MCB) {
  1470. ret.status = osErrorParameter;
  1471. return osEvent_ret_status;
  1472. }
  1473. res = rt_mbx_wait(queue_id, &ret.value.p, rt_ms2tick(millisec));
  1474. if (res == OS_R_TMO) {
  1475. ret.status = (millisec != 0U) ? osEventTimeout : osOK;
  1476. return osEvent_ret_value;
  1477. }
  1478. ret.status = osEventMessage;
  1479. return osEvent_ret_value;
  1480. }
  1481. // Message Queue ISR Calls
  1482. /// Put a Message to a Queue
  1483. osStatus isrMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
  1484. if ((queue_id == NULL) || (millisec != 0U)) {
  1485. return osErrorParameter;
  1486. }
  1487. if (((P_MCB)queue_id)->cb_type != MCB) {
  1488. return osErrorParameter;
  1489. }
  1490. if (rt_mbx_check(queue_id) == 0U) { // Check if Queue is full
  1491. return osErrorResource;
  1492. }
  1493. isr_mbx_send(queue_id, (void *)info);
  1494. return osOK;
  1495. }
  1496. /// Get a Message or Wait for a Message from a Queue
  1497. os_InRegs osEvent isrMessageGet (osMessageQId queue_id, uint32_t millisec) {
  1498. OS_RESULT res;
  1499. osEvent ret;
  1500. if ((queue_id == NULL) || (millisec != 0U)) {
  1501. ret.status = osErrorParameter;
  1502. return ret;
  1503. }
  1504. if (((P_MCB)queue_id)->cb_type != MCB) {
  1505. ret.status = osErrorParameter;
  1506. return ret;
  1507. }
  1508. res = isr_mbx_receive(queue_id, &ret.value.p);
  1509. if (res != OS_R_MBX) {
  1510. ret.status = osOK;
  1511. return ret;
  1512. }
  1513. ret.status = osEventMessage;
  1514. return ret;
  1515. }
  1516. // Message Queue Management Public API
  1517. /// Create and Initialize Message Queue
  1518. osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id) {
  1519. if (__get_IPSR() != 0U) {
  1520. return NULL; // Not allowed in ISR
  1521. }
  1522. if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
  1523. // Privileged and not running
  1524. return svcMessageCreate(queue_def, thread_id);
  1525. } else {
  1526. return __svcMessageCreate(queue_def, thread_id);
  1527. }
  1528. }
  1529. /// Put a Message to a Queue
  1530. osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
  1531. if (__get_IPSR() != 0U) { // in ISR
  1532. return isrMessagePut(queue_id, info, millisec);
  1533. } else { // in Thread
  1534. return __svcMessagePut(queue_id, info, millisec);
  1535. }
  1536. }
  1537. /// Get a Message or Wait for a Message from a Queue
  1538. os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec) {
  1539. if (__get_IPSR() != 0U) { // in ISR
  1540. return isrMessageGet(queue_id, millisec);
  1541. } else { // in Thread
  1542. return __svcMessageGet(queue_id, millisec);
  1543. }
  1544. }
  1545. // ==== Mail Queue Management Functions ====
  1546. // Mail Queue Management Service Calls declarations
  1547. SVC_2_1(svcMailCreate, osMailQId, const osMailQDef_t *, osThreadId, RET_pointer)
  1548. SVC_3_1(sysMailAlloc, void *, osMailQId, uint32_t, uint32_t, RET_pointer)
  1549. SVC_3_1(sysMailFree, osStatus, osMailQId, void *, uint32_t, RET_osStatus)
  1550. // Mail Queue Management Service & ISR Calls
  1551. /// Create and Initialize mail queue
  1552. osMailQId svcMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id) {
  1553. uint32_t blk_sz;
  1554. P_MCB pmcb;
  1555. void *pool;
  1556. if ((queue_def == NULL) ||
  1557. (queue_def->queue_sz == 0U) ||
  1558. (queue_def->item_sz == 0U) ||
  1559. (queue_def->pool == NULL)) {
  1560. sysThreadError(osErrorParameter);
  1561. return NULL;
  1562. }
  1563. pmcb = *(((void **)queue_def->pool) + 0);
  1564. pool = *(((void **)queue_def->pool) + 1);
  1565. if ((pool == NULL) || (pmcb == NULL) || (pmcb->cb_type != 0U)) {
  1566. sysThreadError(osErrorParameter);
  1567. return NULL;
  1568. }
  1569. blk_sz = (queue_def->item_sz + 3U) & (uint32_t)~3U;
  1570. _init_box(pool, sizeof(struct OS_BM) + (queue_def->queue_sz * blk_sz), blk_sz);
  1571. rt_mbx_init(pmcb, (uint16_t)(4U*(queue_def->queue_sz + 4U)));
  1572. return queue_def->pool;
  1573. }
  1574. /// Allocate a memory block from a mail
  1575. void *sysMailAlloc (osMailQId queue_id, uint32_t millisec, uint32_t isr) {
  1576. P_MCB pmcb;
  1577. void *pool;
  1578. void *mem;
  1579. if (queue_id == NULL) {
  1580. return NULL;
  1581. }
  1582. pmcb = *(((void **)queue_id) + 0);
  1583. pool = *(((void **)queue_id) + 1);
  1584. if ((pool == NULL) || (pmcb == NULL)) {
  1585. return NULL;
  1586. }
  1587. if ((isr != 0U) && (millisec != 0U)) {
  1588. return NULL;
  1589. }
  1590. mem = rt_alloc_box(pool);
  1591. if ((mem == NULL) && (millisec != 0U)) {
  1592. // Put Task to sleep when Memory not available
  1593. if (pmcb->p_lnk != NULL) {
  1594. rt_put_prio((P_XCB)pmcb, os_tsk.run);
  1595. } else {
  1596. pmcb->p_lnk = os_tsk.run;
  1597. os_tsk.run->p_lnk = NULL;
  1598. os_tsk.run->p_rlnk = (P_TCB)pmcb;
  1599. // Task is waiting to allocate a message
  1600. pmcb->state = 3U;
  1601. }
  1602. rt_block(rt_ms2tick(millisec), WAIT_MBX);
  1603. }
  1604. return mem;
  1605. }
  1606. /// Free a memory block from a mail
  1607. osStatus sysMailFree (osMailQId queue_id, void *mail, uint32_t isr) {
  1608. P_MCB pmcb;
  1609. P_TCB ptcb;
  1610. void *pool;
  1611. void *mem;
  1612. uint32_t res;
  1613. if (queue_id == NULL) {
  1614. return osErrorParameter;
  1615. }
  1616. pmcb = *(((void **)queue_id) + 0);
  1617. pool = *(((void **)queue_id) + 1);
  1618. if ((pmcb == NULL) || (pool == NULL)) {
  1619. return osErrorParameter;
  1620. }
  1621. res = rt_free_box(pool, mail);
  1622. if (res != 0U) {
  1623. return osErrorValue;
  1624. }
  1625. if ((pmcb->p_lnk != NULL) && (pmcb->state == 3U)) {
  1626. // Task is waiting to allocate a message
  1627. if (isr != 0U) {
  1628. rt_psq_enq (pmcb, (U32)pool);
  1629. rt_psh_req ();
  1630. } else {
  1631. mem = rt_alloc_box(pool);
  1632. if (mem != NULL) {
  1633. ptcb = rt_get_first((P_XCB)pmcb);
  1634. rt_ret_val(ptcb, (U32)mem);
  1635. rt_rmv_dly(ptcb);
  1636. rt_dispatch(ptcb);
  1637. }
  1638. }
  1639. }
  1640. return osOK;
  1641. }
  1642. // Mail Queue Management Public API
  1643. /// Create and Initialize mail queue
  1644. osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id) {
  1645. if (__get_IPSR() != 0U) {
  1646. return NULL; // Not allowed in ISR
  1647. }
  1648. if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
  1649. // Privileged and not running
  1650. return svcMailCreate(queue_def, thread_id);
  1651. } else {
  1652. return __svcMailCreate(queue_def, thread_id);
  1653. }
  1654. }
  1655. /// Allocate a memory block from a mail
  1656. void *osMailAlloc (osMailQId queue_id, uint32_t millisec) {
  1657. if (__get_IPSR() != 0U) { // in ISR
  1658. return sysMailAlloc(queue_id, millisec, 1U);
  1659. } else { // in Thread
  1660. return __sysMailAlloc(queue_id, millisec, 0U);
  1661. }
  1662. }
  1663. /// Allocate a memory block from a mail and set memory block to zero
  1664. void *osMailCAlloc (osMailQId queue_id, uint32_t millisec) {
  1665. void *pool;
  1666. void *mem;
  1667. if (__get_IPSR() != 0U) { // in ISR
  1668. mem = sysMailAlloc(queue_id, millisec, 1U);
  1669. } else { // in Thread
  1670. mem = __sysMailAlloc(queue_id, millisec, 0U);
  1671. }
  1672. pool = *(((void **)queue_id) + 1);
  1673. rt_clr_box(pool, mem);
  1674. return mem;
  1675. }
  1676. /// Free a memory block from a mail
  1677. osStatus osMailFree (osMailQId queue_id, void *mail) {
  1678. if (__get_IPSR() != 0U) { // in ISR
  1679. return sysMailFree(queue_id, mail, 1U);
  1680. } else { // in Thread
  1681. return __sysMailFree(queue_id, mail, 0U);
  1682. }
  1683. }
  1684. /// Put a mail to a queue
  1685. osStatus osMailPut (osMailQId queue_id, void *mail) {
  1686. if (queue_id == NULL) {
  1687. return osErrorParameter;
  1688. }
  1689. if (mail == NULL) {
  1690. return osErrorValue;
  1691. }
  1692. return osMessagePut(*((void **)queue_id), (uint32_t)mail, 0U);
  1693. }
  1694. /// Get a mail from a queue
  1695. os_InRegs osEvent osMailGet (osMailQId queue_id, uint32_t millisec) {
  1696. osEvent ret;
  1697. if (queue_id == NULL) {
  1698. ret.status = osErrorParameter;
  1699. return ret;
  1700. }
  1701. ret = osMessageGet(*((void **)queue_id), millisec);
  1702. if (ret.status == osEventMessage) ret.status = osEventMail;
  1703. return ret;
  1704. }
  1705. // ==== RTX Extensions ====
  1706. // Service Calls declarations
  1707. SVC_0_1(rt_suspend, uint32_t, RET_uint32_t)
  1708. SVC_1_0(rt_resume, void, uint32_t)
  1709. // Public API
  1710. /// Suspends the OS task scheduler
  1711. uint32_t os_suspend (void) {
  1712. return __rt_suspend();
  1713. }
  1714. /// Resumes the OS task scheduler
  1715. void os_resume (uint32_t sleep_time) {
  1716. __rt_resume(sleep_time);
  1717. }