rt_CMSIS.c 66 KB

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