cmsis_rtthread.c 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-04-12 misonyo the first version
  9. * 2019-04-04 misonyo fix some bugs
  10. */
  11. #include <cmsis_os2.h>
  12. #include "cmsis_rtthread.h"
  13. #include <board.h>
  14. #include <os_tick.h>
  15. #include <rthw.h>
  16. #define KERNEL_Id "RT-Thread" ///< Kernel identification string
  17. #define DEFAULT_STACK_SIZE 512
  18. #define DEFAULT_TICK 5
  19. #define WAITING_THREAD_FLAGS 0x08
  20. #define MALLOC_CB 0x10
  21. #define MALLOC_STACK 0x04
  22. #define MALLOC_MEM 0x02
  23. static osKernelState_t kernel_state = osKernelInactive;
  24. static void thread_cleanup(rt_thread_t thread)
  25. {
  26. thread_cb_t *thread_cb;
  27. thread_cb = (thread_cb_t *)(thread->user_data);
  28. /* clear cleanup function */
  29. thread->cleanup = RT_NULL;
  30. if (thread_cb->flags & osThreadJoinable)
  31. {
  32. rt_sem_release(thread_cb->joinable_sem);
  33. }
  34. else
  35. {
  36. if (thread_cb->flags & MALLOC_STACK)
  37. rt_free(thread_cb->thread.stack_addr);
  38. if (thread_cb->flags & MALLOC_CB)
  39. rt_free(thread_cb);
  40. }
  41. }
  42. // ==== Kernel Management Functions ====
  43. // ==== Helper functions ====
  44. /// Block Kernel (disable: thread switching, time tick, post ISR processing).
  45. #ifdef SysTick
  46. static volatile uint8_t blocked; ///< Blocked
  47. static uint8_t pendSV; ///< Pending SV
  48. /// Get Pending SV (Service Call) Flag
  49. /// \return Pending SV Flag
  50. __STATIC_INLINE uint8_t GetPendSV (void)
  51. {
  52. return ((uint8_t)((SCB->ICSR & (SCB_ICSR_PENDSVSET_Msk)) >> 24));
  53. }
  54. /// Clear Pending SV (Service Call) Flag
  55. __STATIC_INLINE void ClrPendSV (void)
  56. {
  57. SCB->ICSR = SCB_ICSR_PENDSVCLR_Msk;
  58. }
  59. /// Set Pending SV (Service Call) Flag
  60. __STATIC_INLINE void SetPendSV (void)
  61. {
  62. SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
  63. }
  64. /// Block Kernel (disable: thread switching, time tick, post ISR processing).
  65. static void KernelBlock (void)
  66. {
  67. OS_Tick_Disable();
  68. blocked = 1U;
  69. __DSB();
  70. if (GetPendSV() != 0U)
  71. {
  72. ClrPendSV();
  73. pendSV = 1U;
  74. }
  75. }
  76. /// Unblock Kernel
  77. static void KernelUnblock (void)
  78. {
  79. blocked = 0U;
  80. __DSB();
  81. if (pendSV != 0U)
  82. {
  83. pendSV = 0U;
  84. SetPendSV();
  85. }
  86. OS_Tick_Enable();
  87. }
  88. #endif
  89. /// Initialize the RTOS Kernel.
  90. /// \return status code that indicates the execution status of the function.
  91. osStatus_t osKernelInitialize(void)
  92. {
  93. kernel_state = osKernelReady;
  94. return osOK;
  95. }
  96. /// Get RTOS Kernel Information.
  97. /// \param[out] version pointer to buffer for retrieving version information.
  98. /// \param[out] id_buf pointer to buffer for retrieving kernel identification string.
  99. /// \param[in] id_size size of buffer for kernel identification string.
  100. /// \return status code that indicates the execution status of the function.
  101. osStatus_t osKernelGetInfo(osVersion_t *version, char *id_buf, uint32_t id_size)
  102. {
  103. if ((RT_NULL == version) || (RT_NULL == id_buf) || id_size < sizeof(KERNEL_Id))
  104. return osErrorParameter;
  105. version->api = KERNEL_VERSION;
  106. version->kernel = KERNEL_VERSION;
  107. id_size = sizeof(KERNEL_Id);
  108. rt_strncpy(id_buf, KERNEL_Id, id_size);
  109. return osOK;
  110. }
  111. /// Get the current RTOS Kernel state.
  112. /// \return current RTOS Kernel state.
  113. osKernelState_t osKernelGetState(void)
  114. {
  115. return kernel_state;
  116. }
  117. /// Start the RTOS Kernel scheduler.
  118. /// \return status code that indicates the execution status of the function.
  119. osStatus_t osKernelStart(void)
  120. {
  121. osStatus_t state;
  122. if (osKernelReady == kernel_state)
  123. {
  124. kernel_state = osKernelRunning;
  125. state = osOK;
  126. }
  127. else
  128. {
  129. state = osError;
  130. }
  131. return state;
  132. }
  133. /// Lock the RTOS Kernel scheduler.
  134. /// \return previous lock state (1 - locked, 0 - not locked, error code if negative).
  135. int32_t osKernelLock(void)
  136. {
  137. rt_uint16_t level;
  138. level = rt_critical_level();
  139. rt_enter_critical();
  140. kernel_state = osKernelLocked;
  141. if (level)
  142. {
  143. return 1;
  144. }
  145. else
  146. {
  147. return 0;
  148. }
  149. }
  150. /// Unlock the RTOS Kernel scheduler.
  151. /// \return previous lock state (1 - locked, 0 - not locked, error code if negative).
  152. int32_t osKernelUnlock(void)
  153. {
  154. rt_uint16_t level;
  155. level = rt_critical_level();
  156. if (0U == level)
  157. {
  158. return 0;
  159. }
  160. else
  161. {
  162. rt_exit_critical();
  163. if (1u == level)
  164. kernel_state = osKernelRunning;
  165. return 1;
  166. }
  167. }
  168. /// Restore the RTOS Kernel scheduler lock state.
  169. /// \param[in] lock lock state obtained by \ref osKernelLock or \ref osKernelUnlock.
  170. /// \return new lock state (1 - locked, 0 - not locked, error code if negative).
  171. int32_t osKernelRestoreLock(int32_t lock)
  172. {
  173. if (1u == lock)
  174. {
  175. osKernelLock();
  176. return 1;
  177. }
  178. else
  179. {
  180. osKernelUnlock();
  181. return 0;
  182. }
  183. }
  184. /// Get the RTOS kernel tick count.
  185. /// \return RTOS kernel current tick count.
  186. uint32_t osKernelGetTickCount(void)
  187. {
  188. return (uint32_t)rt_tick_get();
  189. }
  190. /// Get the RTOS kernel tick frequency.
  191. /// \return frequency of the kernel tick.
  192. uint32_t osKernelGetTickFreq(void)
  193. {
  194. return RT_TICK_PER_SECOND;
  195. }
  196. /// The function returns the current RTOS kernel system timer as a 32-bit value.
  197. /// \return RTOS kernel current system timer count as 32-bit value
  198. #ifdef SysTick
  199. uint32_t osKernelGetSysTimerCount(void)
  200. {
  201. uint32_t irqmask ;
  202. rt_tick_t ticks;
  203. uint32_t val;
  204. irqmask = rt_hw_interrupt_disable();
  205. ticks = rt_tick_get();
  206. val = OS_Tick_GetCount();
  207. if (OS_Tick_GetOverflow() != 0U)
  208. {
  209. val = OS_Tick_GetCount();
  210. ticks++;
  211. }
  212. val += ticks * OS_Tick_GetInterval();
  213. rt_hw_interrupt_enable(irqmask);
  214. return (val);
  215. }
  216. #endif /*SysTick*/
  217. /// Get the RTOS kernel system timer frequency.
  218. /// \return frequency of the system timer.
  219. uint32_t osKernelGetSysTimerFreq(void)
  220. {
  221. return RT_TICK_PER_SECOND;
  222. }
  223. /// Suspend the RTOS Kernel scheduler.
  224. /// \return time in ticks, for how long the system can sleep or power-down.
  225. #ifdef SysTick
  226. uint32_t osKernelSuspend (void)
  227. {
  228. rt_thread_t thread;
  229. rt_timer_t timer;
  230. struct rt_object_information *info_thread;
  231. struct rt_object_information *info_timer;
  232. struct rt_list_node *node;
  233. rt_uint8_t timer_index = 0;
  234. rt_tick_t min_tick = 0;
  235. rt_tick_t cur_tick = 0;
  236. rt_tick_t temp_tick = 0;
  237. if (kernel_state != osKernelRunning)
  238. {
  239. return 0U;
  240. }
  241. info_thread = rt_object_get_information(RT_Object_Class_Thread);
  242. info_timer = rt_object_get_information(RT_Object_Class_Timer);
  243. KernelBlock();
  244. min_tick = osWaitForever;
  245. cur_tick = rt_tick_get();
  246. /*check thread delay list*/
  247. if (info_thread != NULL)
  248. {
  249. for (node = info_thread->object_list.next; node != &(info_thread->object_list); node = node->next)
  250. {
  251. thread = thread_rt_list_entry(node, rt_thread);
  252. if (thread->thread_timer.parent.flag & RT_TIMER_FLAG_ACTIVATED)
  253. {
  254. temp_tick = thread->thread_timer.timeout_tick - cur_tick;
  255. if (temp_tick < min_tick)
  256. {
  257. min_tick = temp_tick;
  258. }
  259. }
  260. }
  261. }
  262. /*check active timer list*/
  263. if (info_timer != NULL)
  264. {
  265. for (node = info_timer->object_list.next; node != &(info_timer->object_list); node = node->next)
  266. {
  267. timer = rt_list_entry(node, struct rt_timer, row[timer_index++]);
  268. if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)
  269. {
  270. temp_tick = timer->timeout_tick - cur_tick;
  271. if (temp_tick < min_tick)
  272. {
  273. min_tick = temp_tick;
  274. }
  275. }
  276. }
  277. }
  278. if (osWaitForever == min_tick)
  279. min_tick = 0U;
  280. kernel_state = osKernelSuspended;
  281. return (min_tick);
  282. }
  283. #endif /* SysTick */
  284. /// Resume the RTOS Kernel scheduler.
  285. /// \param[in] sleep_ticks time in ticks for how long the system was in sleep or power-down mode.
  286. #ifdef SysTick
  287. void osKernelResume (uint32_t sleep_ticks)
  288. {
  289. rt_tick_t delay_tick = 0;
  290. if (kernel_state != osKernelSuspended)
  291. {
  292. return;
  293. }
  294. delay_tick = (rt_tick_t)sleep_ticks;
  295. rt_enter_critical();
  296. while(delay_tick > 0)
  297. {
  298. rt_tick_increase(); /*Process Thread Delay list and Process Active Timer list*/
  299. delay_tick --;
  300. }
  301. rt_exit_critical();
  302. kernel_state = osKernelRunning;
  303. KernelUnblock();
  304. return;
  305. }
  306. #endif
  307. // ==== Thread Management Functions ====
  308. /// Create a thread and add it to Active Threads.
  309. /// \param[in] func thread function.
  310. /// \param[in] argument pointer that is passed to the thread function as start argument.
  311. /// \param[in] attr thread attributes; NULL: default values.
  312. /// \return thread ID for reference by other functions or NULL in case of error.
  313. osThreadId_t osThreadNew(osThreadFunc_t func, void *argument, const osThreadAttr_t *attr)
  314. {
  315. void *stack;
  316. rt_uint8_t rtt_prio;
  317. rt_uint32_t stack_size;
  318. thread_cb_t *thread_cb;
  319. char name[RT_NAME_MAX];
  320. static rt_uint16_t thread_number = 1U;
  321. /* Check parameters */
  322. if (RT_NULL == func)
  323. {
  324. return RT_NULL;
  325. }
  326. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  327. {
  328. thread_cb = rt_malloc(sizeof(thread_cb_t));
  329. if (RT_NULL == thread_cb)
  330. return RT_NULL;
  331. rt_memset(thread_cb, 0, sizeof(thread_cb_t));
  332. thread_cb->flags |= MALLOC_CB;
  333. }
  334. else
  335. {
  336. if (attr->cb_size >= sizeof(thread_cb_t))
  337. {
  338. thread_cb = attr->cb_mem;
  339. thread_cb->flags = 0;
  340. }
  341. else
  342. return RT_NULL;
  343. }
  344. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  345. rt_snprintf(name, sizeof(name), "th%02d", thread_number ++);
  346. else
  347. rt_snprintf(name, sizeof(name), "%s", attr->name);
  348. if ((RT_NULL == attr) || (osPriorityNone == attr->priority))
  349. {
  350. thread_cb->prio = osPriorityNormal;
  351. }
  352. else
  353. {
  354. if ((attr->priority < osPriorityIdle) || (attr->priority > osPriorityISR))
  355. return RT_NULL;
  356. thread_cb->prio = attr->priority;
  357. }
  358. if ((RT_NULL == attr) || (0U == attr->stack_size))
  359. stack_size = DEFAULT_STACK_SIZE;
  360. else
  361. stack_size = attr->stack_size;
  362. if ((RT_NULL == attr) || (RT_NULL == attr->stack_mem))
  363. {
  364. stack = rt_malloc(stack_size);
  365. if (RT_NULL == stack)
  366. {
  367. if (thread_cb->flags & MALLOC_CB)
  368. rt_free(thread_cb);
  369. return RT_NULL;
  370. }
  371. thread_cb->flags |= MALLOC_STACK;
  372. }
  373. else
  374. {
  375. stack = (void *)(attr->stack_mem);
  376. }
  377. if ((RT_NULL != attr) && (0 != attr->attr_bits))
  378. thread_cb->flags |= attr->attr_bits;
  379. rtt_prio = (osPriorityISR - thread_cb->prio) * RT_THREAD_PRIORITY_MAX / osPriorityISR;
  380. rt_thread_init(&(thread_cb->thread), name, func, argument, stack, stack_size, rtt_prio, DEFAULT_TICK);
  381. if (thread_cb->flags & osThreadJoinable)
  382. {
  383. thread_cb->joinable_sem = rt_sem_create(name, 0, RT_IPC_FLAG_FIFO);
  384. if (RT_NULL == thread_cb->joinable_sem)
  385. {
  386. if (thread_cb->flags & MALLOC_CB)
  387. rt_free(thread_cb);
  388. if (thread_cb->flags & MALLOC_STACK)
  389. rt_free(stack);
  390. return RT_NULL;
  391. }
  392. }
  393. else
  394. thread_cb->joinable_sem = RT_NULL;
  395. thread_cb->thread.cleanup = thread_cleanup;
  396. thread_cb->thread.user_data = (rt_uint32_t)thread_cb;
  397. rt_thread_startup(&(thread_cb->thread));
  398. return thread_cb;
  399. }
  400. /// Get name of a thread.
  401. /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
  402. /// \return name as NULL terminated string.
  403. const char *osThreadGetName(osThreadId_t thread_id)
  404. {
  405. thread_cb_t *thread_cb = (thread_cb_t *)thread_id;
  406. /* Check parameters */
  407. if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread))
  408. {
  409. return RT_NULL;
  410. }
  411. return THREAD_NAME(thread_cb);
  412. }
  413. /// Return the thread ID of the current running thread.
  414. /// \return thread ID for reference by other functions or NULL in case of error.
  415. osThreadId_t osThreadGetId(void)
  416. {
  417. rt_thread_t thread;
  418. thread = rt_thread_self();
  419. return (osThreadId_t)(thread->user_data);
  420. }
  421. /// Get current thread state of a thread.
  422. /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
  423. /// \return current thread state of the specified thread.
  424. osThreadState_t osThreadGetState(osThreadId_t thread_id)
  425. {
  426. osThreadState_t state;
  427. thread_cb_t *thread_cb = (thread_cb_t *)thread_id;
  428. /* Check parameters */
  429. if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread))
  430. {
  431. return osThreadError;
  432. }
  433. switch (CMSIS_RT_SCHED_CTX(thread_cb->thread).stat)
  434. {
  435. case RT_THREAD_INIT:
  436. state = osThreadInactive;
  437. break;
  438. case RT_THREAD_READY:
  439. state = osThreadReady;
  440. break;
  441. case RT_THREAD_SUSPEND:
  442. state = osThreadBlocked;
  443. break;
  444. case RT_THREAD_RUNNING:
  445. state = osThreadRunning;
  446. break;
  447. case RT_THREAD_CLOSE:
  448. state = osThreadTerminated;
  449. break;
  450. default:
  451. state = osThreadError;
  452. break;
  453. }
  454. return state;
  455. }
  456. /// Get stack size of a thread.
  457. /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
  458. /// \return stack size in bytes.
  459. uint32_t osThreadGetStackSize(osThreadId_t thread_id)
  460. {
  461. thread_cb_t *thread_cb = (thread_cb_t *)thread_id;
  462. /* Check parameters */
  463. if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread))
  464. {
  465. return 0U;
  466. }
  467. return ((uint32_t)thread_cb->thread.stack_size);
  468. }
  469. /// Get available stack space of a thread based on stack watermark recording during execution.
  470. /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
  471. /// \return remaining stack space in bytes.
  472. uint32_t osThreadGetStackSpace(osThreadId_t thread_id)
  473. {
  474. rt_uint8_t *ptr;
  475. thread_cb_t *thread_cb = (thread_cb_t *)thread_id;
  476. /* Check parameters */
  477. if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread))
  478. {
  479. return 0U;
  480. }
  481. ptr = (rt_uint8_t *)thread_cb->thread.stack_addr;
  482. while (*ptr == '#')ptr ++;
  483. return (ptr - (rt_uint8_t *)thread_cb->thread.stack_addr);
  484. }
  485. /// Change priority of a thread.
  486. /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
  487. /// \param[in] priority new priority value for the thread function.
  488. /// \return status code that indicates the execution status of the function.
  489. osStatus_t osThreadSetPriority(osThreadId_t thread_id, osPriority_t priority)
  490. {
  491. rt_uint8_t rt_priority;
  492. thread_cb_t *thread_cb = (thread_cb_t *)thread_id;
  493. // Check parameters
  494. if ((RT_NULL == thread_cb) || (priority < osPriorityIdle) || (priority > osPriorityISR))
  495. {
  496. return osErrorParameter;
  497. }
  498. thread_cb->prio = priority;
  499. rt_priority = (osPriorityISR - thread_cb->prio) * RT_THREAD_PRIORITY_MAX / osPriorityISR;
  500. rt_thread_control(&(thread_cb->thread), RT_THREAD_CTRL_CHANGE_PRIORITY, &rt_priority);
  501. return osOK;
  502. }
  503. /// Get current priority of a thread.
  504. /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
  505. /// \return current priority value of the specified thread.
  506. osPriority_t osThreadGetPriority(osThreadId_t thread_id)
  507. {
  508. thread_cb_t *thread_cb = (thread_cb_t *)thread_id;
  509. /* Check parameters */
  510. if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread))
  511. {
  512. return osPriorityError;
  513. }
  514. return (osPriority_t)thread_cb->prio;
  515. }
  516. /// Pass control to next thread that is in state \b READY.
  517. /// \return status code that indicates the execution status of the function.
  518. osStatus_t osThreadYield(void)
  519. {
  520. rt_thread_yield();
  521. return osOK;
  522. }
  523. /// Suspend execution of a thread.
  524. /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
  525. /// \return status code that indicates the execution status of the function.
  526. osStatus_t osThreadSuspend(osThreadId_t thread_id)
  527. {
  528. rt_err_t result;
  529. thread_cb_t *thread_cb = (thread_cb_t *)thread_id;
  530. /* Check parameters */
  531. if (RT_NULL == thread_cb)
  532. {
  533. return osErrorParameter;
  534. }
  535. result = rt_thread_suspend(&(thread_cb->thread));
  536. if (RT_EOK == result)
  537. return osOK;
  538. else
  539. return osError;
  540. }
  541. /// Resume execution of a thread.
  542. /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
  543. /// \return status code that indicates the execution status of the function.
  544. osStatus_t osThreadResume(osThreadId_t thread_id)
  545. {
  546. rt_err_t result;
  547. thread_cb_t *thread_cb = (thread_cb_t *)thread_id;
  548. /* Check parameters */
  549. if (RT_NULL == thread_cb)
  550. {
  551. return osErrorParameter;
  552. }
  553. result = rt_thread_resume(&(thread_cb->thread));
  554. if (RT_EOK == result)
  555. return osOK;
  556. else
  557. return osError;
  558. }
  559. /// Detach a thread (thread storage can be reclaimed when thread terminates).
  560. /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
  561. /// \return status code that indicates the execution status of the function.
  562. osStatus_t osThreadDetach(osThreadId_t thread_id)
  563. {
  564. thread_cb_t *thread_cb = (thread_cb_t *)thread_id;
  565. /* Check parameters */
  566. if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread))
  567. {
  568. return osErrorParameter;
  569. }
  570. /* Check object attributes */
  571. /*
  572. if ((thread_cb->flags & osThreadJoinable) == 0)
  573. {
  574. return osErrorResource;
  575. }
  576. */
  577. if ((CMSIS_RT_SCHED_CTX(thread_cb->thread).stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
  578. {
  579. rt_thread_detach(&(thread_cb->thread));
  580. if (thread_cb->flags & osThreadJoinable)
  581. rt_sem_delete(thread_cb->joinable_sem);
  582. if (thread_cb->flags & MALLOC_STACK)
  583. rt_free(thread_cb->thread.stack_addr);
  584. if (thread_cb->flags & MALLOC_CB)
  585. rt_free(thread_cb);
  586. }
  587. else
  588. {
  589. rt_enter_critical();
  590. /* change to detach state */
  591. thread_cb->flags &= ~osThreadJoinable;
  592. /* delete joinable semaphore */
  593. if (RT_NULL != thread_cb->joinable_sem)
  594. {
  595. rt_sem_delete(thread_cb->joinable_sem);
  596. thread_cb->joinable_sem = RT_NULL;
  597. }
  598. /* detach thread object */
  599. rt_thread_detach(&thread_cb->thread);
  600. rt_exit_critical();
  601. }
  602. return osOK;
  603. }
  604. /// Wait for specified thread to terminate.
  605. /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
  606. /// \return status code that indicates the execution status of the function.
  607. osStatus_t osThreadJoin(osThreadId_t thread_id)
  608. {
  609. rt_err_t result;
  610. thread_cb_t *thread_cb = (thread_cb_t *)thread_id;
  611. /* Check parameters */
  612. if (RT_NULL == thread_cb)
  613. {
  614. return osErrorParameter;
  615. }
  616. if (((&thread_cb->thread) == rt_thread_self()) ||
  617. (0 == (thread_cb->flags & osThreadJoinable)))
  618. {
  619. /* join self or join a detached thread*/
  620. return osErrorResource;
  621. }
  622. result = rt_sem_take(thread_cb->joinable_sem, RT_WAITING_FOREVER);
  623. if (RT_EOK == result)
  624. {
  625. /* release resource */
  626. if (thread_cb->flags & osThreadJoinable)
  627. rt_sem_delete(thread_cb->joinable_sem);
  628. if (thread_cb->flags & MALLOC_STACK)
  629. rt_free(thread_cb->thread.stack_addr);
  630. if (thread_cb->flags & MALLOC_CB)
  631. rt_free(thread_cb);
  632. return osOK;
  633. }
  634. else if (-RT_ETIMEOUT == result)
  635. {
  636. return osErrorTimeout;
  637. }
  638. else
  639. {
  640. return osError;
  641. }
  642. }
  643. /// Terminate execution of current running thread.
  644. __NO_RETURN void osThreadExit(void)
  645. {
  646. rt_thread_t self = rt_thread_self();
  647. rt_thread_control(self, RT_THREAD_CTRL_CLOSE, RT_NULL);
  648. RT_ASSERT(0);
  649. while(1);
  650. }
  651. /// Terminate execution of a thread.
  652. /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
  653. /// \return status code that indicates the execution status of the function.
  654. osStatus_t osThreadTerminate(osThreadId_t thread_id)
  655. {
  656. thread_cb_t *thread_cb;
  657. thread_cb = (thread_cb_t *)(rt_thread_self()->user_data);
  658. /* Check parameters */
  659. if (RT_NULL == thread_cb)
  660. {
  661. return osErrorParameter;
  662. }
  663. rt_thread_detach(&(thread_cb->thread));
  664. rt_schedule();
  665. return osOK;
  666. }
  667. /// Get number of active threads.
  668. /// \return number of active threads.
  669. uint32_t osThreadGetCount(void)
  670. {
  671. rt_uint32_t thread_count = 0U;
  672. struct rt_object_information *info;
  673. info = rt_object_get_information(RT_Object_Class_Thread);
  674. rt_enter_critical();
  675. thread_count = rt_list_len(&(info->object_list));
  676. rt_exit_critical();
  677. return thread_count;
  678. }
  679. /// Enumerate active threads.
  680. /// \param[out] thread_array pointer to array for retrieving thread IDs.
  681. /// \param[in] array_items maximum number of items in array for retrieving thread IDs.
  682. /// \return number of enumerated threads.
  683. uint32_t osThreadEnumerate(osThreadId_t *thread_array, uint32_t array_items)
  684. {
  685. rt_uint32_t thread_count = 0U;
  686. rt_thread_t thread;
  687. struct rt_object_information *info;
  688. struct rt_list_node *node;
  689. /* Check parameters */
  690. if ((RT_NULL == thread_array) || (0U == array_items))
  691. {
  692. return 0U;
  693. }
  694. info = rt_object_get_information(RT_Object_Class_Thread);
  695. rt_enter_critical();
  696. for (node = info->object_list.next; node != &(info->object_list); node = node->next)
  697. {
  698. thread = thread_rt_list_entry(node, rt_thread);
  699. thread_array[thread_count] = (osThreadId_t)thread;
  700. thread_count++;
  701. if (thread_count >= array_items)
  702. break;
  703. }
  704. rt_exit_critical();
  705. return thread_count;
  706. }
  707. // ==== Thread Flags Functions ====
  708. /// Set the specified Thread Flags of a thread.
  709. /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
  710. /// \param[in] flags specifies the flags of the thread that shall be set.
  711. /// \return thread flags after setting or error code if highest bit set.
  712. uint32_t osThreadFlagsSet(osThreadId_t thread_id, uint32_t flags)
  713. {
  714. register rt_base_t status;
  715. register rt_ubase_t level;
  716. rt_bool_t need_schedule = RT_FALSE;
  717. thread_cb_t *thread_cb;
  718. rt_uint32_t return_value;
  719. thread_cb = (thread_cb_t *)(thread_id);
  720. /* Check parameters */
  721. if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread))
  722. {
  723. return osFlagsErrorParameter;
  724. }
  725. level = rt_hw_interrupt_disable();
  726. thread_cb->flag_set |= flags;
  727. return_value = thread_cb->flag_set;
  728. /* Check if Thread is waiting for Thread Flags */
  729. if (thread_cb->thread.event_info & WAITING_THREAD_FLAGS)
  730. {
  731. status = -RT_ERROR;
  732. if (thread_cb->thread.event_info & osFlagsWaitAll)
  733. {
  734. if ((thread_cb->thread.event_set & thread_cb->flag_set) == thread_cb->thread.event_set)
  735. {
  736. /* received an AND event */
  737. status = RT_EOK;
  738. }
  739. }
  740. else
  741. {
  742. if (thread_cb->thread.event_set & thread_cb->flag_set)
  743. {
  744. /* save recieved event set */
  745. thread_cb->thread.event_set &= thread_cb->flag_set;
  746. /* received an OR event */
  747. status = RT_EOK;
  748. }
  749. }
  750. /* condition is satisfied, resume thread */
  751. if (RT_EOK == status)
  752. {
  753. thread_cb->thread.event_info &= ~WAITING_THREAD_FLAGS;
  754. /* clear event */
  755. if (!(thread_cb->thread.event_info & osFlagsNoClear))
  756. thread_cb->flag_set &= ~thread_cb->thread.event_set;
  757. /* resume thread, and thread list breaks out */
  758. rt_thread_resume(rt_thread_self());
  759. need_schedule = RT_TRUE;
  760. }
  761. }
  762. rt_hw_interrupt_enable(level);
  763. if (need_schedule == RT_TRUE)
  764. rt_schedule();
  765. return return_value;
  766. }
  767. /// Clear the specified Thread Flags of current running thread.
  768. /// \param[in] flags specifies the flags of the thread that shall be cleared.
  769. /// \return thread flags before clearing or error code if highest bit set.
  770. uint32_t osThreadFlagsClear(uint32_t flags)
  771. {
  772. rt_thread_t thread = rt_thread_self();
  773. thread_cb_t *thread_cb;
  774. rt_uint32_t flag;
  775. /* Check parameters */
  776. if (RT_NULL == thread)
  777. {
  778. return osFlagsErrorParameter;
  779. }
  780. thread_cb = (thread_cb_t *)(thread->user_data);
  781. rt_enter_critical();
  782. flag = thread_cb->flag_set;
  783. thread_cb->flag_set &= ~flags;
  784. rt_exit_critical();
  785. return flag;
  786. }
  787. /// Get the current Thread Flags of current running thread.
  788. /// \return current thread flags.
  789. uint32_t osThreadFlagsGet(void)
  790. {
  791. rt_thread_t thread = rt_thread_self();
  792. thread_cb_t *thread_cb;
  793. /* Check parameters */
  794. if (RT_NULL == thread)
  795. {
  796. return osFlagsErrorParameter;
  797. }
  798. thread_cb = (thread_cb_t *)(thread->user_data);
  799. return thread_cb->flag_set;
  800. }
  801. /// Wait for one or more Thread Flags of the current running thread to become signaled.
  802. /// \param[in] flags specifies the flags to wait for.
  803. /// \param[in] options specifies flags options (osFlagsXxxx).
  804. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  805. /// \return thread flags before clearing or error code if highest bit set.
  806. uint32_t osThreadFlagsWait(uint32_t flags, uint32_t options, uint32_t timeout)
  807. {
  808. rt_uint32_t return_value;
  809. register rt_ubase_t level;
  810. register rt_base_t status = -RT_ERROR;
  811. rt_thread_t thread = rt_thread_self();
  812. thread_cb_t *thread_cb;
  813. /* Check parameters */
  814. if (RT_NULL == thread)
  815. {
  816. return osFlagsErrorParameter;
  817. }
  818. thread->error = RT_EOK;
  819. thread_cb = (thread_cb_t *)(thread->user_data);
  820. level = rt_hw_interrupt_disable();
  821. if (options & osFlagsWaitAll)
  822. {
  823. if ((thread_cb->flag_set & flags) == flags)
  824. status = RT_EOK;
  825. }
  826. else
  827. {
  828. if (thread_cb->flag_set & flags)
  829. status = RT_EOK;
  830. }
  831. if (RT_EOK == status)
  832. {
  833. return_value = thread_cb->flag_set & flags;
  834. if (!(options & osFlagsNoClear))
  835. thread_cb->flag_set &= ~flags;
  836. }
  837. else if (0U == timeout)
  838. {
  839. rt_hw_interrupt_enable(level);
  840. return osFlagsErrorResource;
  841. }
  842. else
  843. {
  844. thread->event_set = flags;
  845. thread->event_info = options | WAITING_THREAD_FLAGS;
  846. rt_thread_suspend(thread);
  847. /* if there is a waiting timeout, active thread timer */
  848. if ((timeout > 0U) && (timeout != osWaitForever))
  849. {
  850. /* reset the timeout of thread timer and start it */
  851. rt_timer_control(&(thread->thread_timer),
  852. RT_TIMER_CTRL_SET_TIME,
  853. &timeout);
  854. rt_timer_start(&(thread->thread_timer));
  855. }
  856. rt_hw_interrupt_enable(level);
  857. rt_schedule();
  858. if (thread->error != RT_EOK)
  859. {
  860. return thread->error;
  861. }
  862. level = rt_hw_interrupt_disable();
  863. return_value = thread->event_set;
  864. }
  865. rt_hw_interrupt_enable(level);
  866. return return_value;
  867. }
  868. // ==== Generic Wait Functions ====
  869. /// Wait for Timeout (Time Delay).
  870. /// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value
  871. /// \return status code that indicates the execution status of the function.
  872. osStatus_t osDelay(uint32_t ticks)
  873. {
  874. rt_thread_delay(ticks);
  875. return osOK;
  876. }
  877. /// Wait until specified time.
  878. /// \param[in] ticks absolute time in ticks
  879. /// \return status code that indicates the execution status of the function.
  880. osStatus_t osDelayUntil(uint32_t ticks)
  881. {
  882. uint64_t cur_ticks;
  883. cur_ticks = rt_tick_get();
  884. if (ticks == cur_ticks)
  885. {
  886. }
  887. else if (ticks > cur_ticks)
  888. {
  889. rt_thread_delay(ticks - cur_ticks);
  890. }
  891. else
  892. {
  893. rt_thread_delay(((rt_uint32_t) - 1) - cur_ticks + ticks);
  894. }
  895. return osOK;
  896. }
  897. // ==== Timer Management Functions ====
  898. /// Create and Initialize a timer.
  899. /// \param[in] func start address of a timer call back function.
  900. /// \param[in] type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior.
  901. /// \param[in] argument argument to the timer call back function.
  902. /// \param[in] attr timer attributes; NULL: default values.
  903. /// \return timer ID for reference by other functions or NULL in case of error.
  904. osTimerId_t osTimerNew(osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr)
  905. {
  906. timer_cb_t *timer_cb;
  907. char name[RT_NAME_MAX];
  908. static rt_uint16_t timer_number = 0U;
  909. rt_uint8_t flag = RT_TIMER_FLAG_SOFT_TIMER;
  910. /* Check parameters */
  911. if ((RT_NULL == func) || ((type != osTimerOnce) && (type != osTimerPeriodic)))
  912. {
  913. return RT_NULL;
  914. }
  915. /* RT-Thread object's name can't be NULL */
  916. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  917. rt_snprintf(name, sizeof(name), "timer%02d", timer_number++);
  918. else
  919. rt_snprintf(name, sizeof(name), "%s", attr->name);
  920. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  921. {
  922. timer_cb = rt_malloc(sizeof(timer_cb_t));
  923. if (RT_NULL == timer_cb)
  924. return RT_NULL;
  925. rt_memset(timer_cb, 0, sizeof(timer_cb_t));
  926. timer_cb->flags |= MALLOC_CB;
  927. }
  928. else
  929. {
  930. if (attr->cb_size >= sizeof(timer_cb_t))
  931. {
  932. timer_cb = attr->cb_mem;
  933. timer_cb->flags = 0;
  934. }
  935. else
  936. return RT_NULL;
  937. }
  938. if (osTimerPeriodic == type)
  939. {
  940. flag |= RT_TIMER_FLAG_PERIODIC;
  941. }
  942. rt_timer_init(&(timer_cb->timer), name, func, argument, 0, flag);
  943. return timer_cb;
  944. }
  945. /// Get name of a timer.
  946. /// \param[in] timer_id timer ID obtained by \ref osTimerNew.
  947. /// \return name as NULL terminated string.
  948. const char *osTimerGetName(osTimerId_t timer_id)
  949. {
  950. timer_cb_t *timer_cb;
  951. timer_cb = (timer_cb_t *)timer_id;
  952. /* Check parameters */
  953. if ((RT_NULL == timer_cb) || (rt_object_get_type(&timer_cb->timer.parent) != RT_Object_Class_Timer))
  954. {
  955. return RT_NULL;
  956. }
  957. return timer_cb->timer.parent.name;
  958. }
  959. /// Start or restart a timer.
  960. /// \param[in] timer_id timer ID obtained by \ref osTimerNew.
  961. /// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value of the timer.
  962. /// \return status code that indicates the execution status of the function.
  963. osStatus_t osTimerStart(osTimerId_t timer_id, uint32_t ticks)
  964. {
  965. rt_err_t result;
  966. timer_cb_t *timer_cb;
  967. timer_cb = (timer_cb_t *)timer_id;
  968. /* Check parameters */
  969. if ((RT_NULL == timer_cb) || (ticks == 0))
  970. {
  971. return osErrorParameter;
  972. }
  973. rt_timer_control(&(timer_cb->timer), RT_TIMER_CTRL_SET_TIME, &ticks);
  974. result = rt_timer_start(&(timer_cb->timer));
  975. if (RT_EOK == result)
  976. return osOK;
  977. else
  978. return osError;
  979. }
  980. /// Stop a timer.
  981. /// \param[in] timer_id timer ID obtained by \ref osTimerNew.
  982. /// \return status code that indicates the execution status of the function.
  983. osStatus_t osTimerStop(osTimerId_t timer_id)
  984. {
  985. rt_err_t result;
  986. timer_cb_t *timer_cb;
  987. timer_cb = (timer_cb_t *)timer_id;
  988. /* Check parameters */
  989. if (RT_NULL == timer_cb)
  990. {
  991. return osErrorParameter;
  992. }
  993. result = rt_timer_stop(&(timer_cb->timer));
  994. if (RT_EOK == result)
  995. return osOK;
  996. else
  997. return osError;
  998. }
  999. /// Check if a timer is running.
  1000. /// \param[in] timer_id timer ID obtained by \ref osTimerNew.
  1001. /// \return 0 not running, 1 running.
  1002. uint32_t osTimerIsRunning(osTimerId_t timer_id)
  1003. {
  1004. timer_cb_t *timer_cb;
  1005. timer_cb = (timer_cb_t *)timer_id;
  1006. /* Check parameters */
  1007. if ((RT_NULL == timer_cb) || (rt_object_get_type(&timer_cb->timer.parent) != RT_Object_Class_Timer))
  1008. {
  1009. return 0U;
  1010. }
  1011. if ((timer_cb->timer.parent.flag & RT_TIMER_FLAG_ACTIVATED) == 1u)
  1012. {
  1013. return 1;
  1014. }
  1015. else
  1016. return 0U;
  1017. }
  1018. /// Delete a timer.
  1019. /// \param[in] timer_id timer ID obtained by \ref osTimerNew.
  1020. /// \return status code that indicates the execution status of the function.
  1021. osStatus_t osTimerDelete(osTimerId_t timer_id)
  1022. {
  1023. timer_cb_t *timer_cb;
  1024. timer_cb = (timer_cb_t *)timer_id;
  1025. /* Check parameters */
  1026. if (RT_NULL == timer_cb)
  1027. {
  1028. return osErrorParameter;
  1029. }
  1030. rt_timer_detach(&(timer_cb->timer));
  1031. if (timer_cb->flags & MALLOC_CB)
  1032. rt_free(timer_cb);
  1033. return osOK;
  1034. }
  1035. #ifdef RT_USING_EVENT
  1036. // ==== Event Flags Management Functions ====
  1037. /// Create and Initialize an Event Flags object.
  1038. /// \param[in] attr event flags attributes; NULL: default values.
  1039. /// \return event flags ID for reference by other functions or NULL in case of error.
  1040. osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr)
  1041. {
  1042. char name[RT_NAME_MAX];
  1043. event_cb_t *event_cb;
  1044. static rt_uint16_t event_number = 0U;
  1045. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  1046. {
  1047. rt_snprintf(name, sizeof(name), "event%02d", event_number++);
  1048. }
  1049. else
  1050. rt_snprintf(name, sizeof(name), "%s", attr->name);
  1051. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  1052. {
  1053. event_cb = rt_malloc(sizeof(event_cb_t));
  1054. if (RT_NULL == event_cb)
  1055. return RT_NULL;
  1056. rt_memset(event_cb, 0, sizeof(event_cb_t));
  1057. event_cb->flags |= MALLOC_CB;
  1058. }
  1059. else
  1060. {
  1061. if (attr->cb_size >= sizeof(event_cb_t))
  1062. {
  1063. event_cb = attr->cb_mem;
  1064. event_cb->flags = 0;
  1065. }
  1066. else
  1067. return RT_NULL;
  1068. }
  1069. rt_event_init(&(event_cb->event), name, RT_IPC_FLAG_FIFO);
  1070. return event_cb;
  1071. }
  1072. /// Get name of an Event Flags object.
  1073. /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
  1074. /// \return name as NULL terminated string.
  1075. const char *osEventFlagsGetName(osEventFlagsId_t ef_id)
  1076. {
  1077. event_cb_t *event_cb = (event_cb_t *)ef_id;
  1078. /* Check parameters */
  1079. if ((RT_NULL == event_cb) || (rt_object_get_type(&event_cb->event.parent.parent) != RT_Object_Class_Event))
  1080. {
  1081. return RT_NULL;
  1082. }
  1083. return event_cb->event.parent.parent.name;
  1084. }
  1085. /// Set the specified Event Flags.
  1086. /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
  1087. /// \param[in] flags specifies the flags that shall be set.
  1088. /// \return event flags after setting or error code if highest bit set.
  1089. uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags)
  1090. {
  1091. rt_err_t result;
  1092. rt_uint32_t set_flags;
  1093. event_cb_t *event_cb = (event_cb_t *)ef_id;
  1094. /* Check parameters */
  1095. if ((RT_NULL == event_cb) || (rt_object_get_type(&event_cb->event.parent.parent) != RT_Object_Class_Event))
  1096. {
  1097. return ((uint32_t)osFlagsErrorParameter);
  1098. }
  1099. set_flags = event_cb->event.set |= flags;
  1100. result = rt_event_send(&(event_cb->event), flags);
  1101. if (RT_EOK == result)
  1102. return set_flags;
  1103. else
  1104. return osFlagsError;
  1105. }
  1106. /// Clear the specified Event Flags.
  1107. /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
  1108. /// \param[in] flags specifies the flags that shall be cleared.
  1109. /// \return event flags before clearing or error code if highest bit set.
  1110. uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags)
  1111. {
  1112. rt_uint32_t set_flags;
  1113. register rt_ubase_t level;
  1114. event_cb_t *event_cb = (event_cb_t *)ef_id;
  1115. /* Check parameters */
  1116. if ((RT_NULL == event_cb) || (rt_object_get_type(&event_cb->event.parent.parent) != RT_Object_Class_Event))
  1117. {
  1118. return ((uint32_t)osFlagsErrorParameter);
  1119. }
  1120. set_flags = event_cb->event.set;
  1121. level = rt_hw_interrupt_disable();
  1122. event_cb->event.set &= ~flags;
  1123. rt_hw_interrupt_enable(level);
  1124. return set_flags;
  1125. }
  1126. /// Get the current Event Flags.
  1127. /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
  1128. /// \return current event flags.
  1129. uint32_t osEventFlagsGet(osEventFlagsId_t ef_id)
  1130. {
  1131. event_cb_t *event_cb = (event_cb_t *)ef_id;
  1132. /* Check parameters */
  1133. if ((RT_NULL == event_cb) || (rt_object_get_type(&event_cb->event.parent.parent) != RT_Object_Class_Event))
  1134. {
  1135. return 0U;
  1136. }
  1137. return event_cb->event.set;
  1138. }
  1139. /// Wait for one or more Event Flags to become signaled.
  1140. /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
  1141. /// \param[in] flags specifies the flags to wait for.
  1142. /// \param[in] options specifies flags options (osFlagsXxxx).
  1143. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1144. /// \return event flags before clearing or error code if highest bit set.
  1145. uint32_t osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout)
  1146. {
  1147. rt_err_t result;
  1148. rt_uint32_t rt_recv;
  1149. rt_uint8_t rt_options = 0U;
  1150. event_cb_t *event_cb = (event_cb_t *)ef_id;
  1151. /* Check parameters */
  1152. if (RT_NULL == event_cb)
  1153. {
  1154. return ((uint32_t)osFlagsErrorParameter);
  1155. }
  1156. if (options & osFlagsWaitAll)
  1157. {
  1158. rt_options |= RT_EVENT_FLAG_AND;
  1159. }
  1160. else
  1161. {
  1162. rt_options |= RT_EVENT_FLAG_OR;
  1163. }
  1164. if (!(options & osFlagsNoClear))
  1165. {
  1166. rt_options |= RT_EVENT_FLAG_CLEAR;
  1167. }
  1168. if(timeout == osWaitForever)
  1169. {
  1170. timeout = RT_WAITING_FOREVER;
  1171. }
  1172. result = rt_event_recv(&(event_cb->event), flags, (rt_uint8_t)rt_options, timeout, &rt_recv);
  1173. if (RT_EOK == result)
  1174. return rt_recv;
  1175. else if (-RT_ETIMEOUT == result)
  1176. {
  1177. if (0U == timeout)
  1178. return osFlagsErrorResource;
  1179. else
  1180. return osFlagsErrorTimeout;
  1181. }
  1182. else
  1183. return osFlagsErrorUnknown;
  1184. }
  1185. /// Delete an Event Flags object.
  1186. /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
  1187. /// \return status code that indicates the execution status of the function.
  1188. osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id)
  1189. {
  1190. event_cb_t *event_cb = (event_cb_t *)ef_id;
  1191. /* Check parameters */
  1192. if (RT_NULL == event_cb)
  1193. {
  1194. return osErrorParameter;
  1195. }
  1196. rt_event_detach(&(event_cb->event));
  1197. if (event_cb->flags & MALLOC_CB)
  1198. rt_free(event_cb);
  1199. return osOK;
  1200. }
  1201. #endif
  1202. #ifdef RT_USING_MUTEX
  1203. // ==== Mutex Management Functions ====
  1204. /// Create and Initialize a Mutex object.
  1205. /// \param[in] attr mutex attributes; NULL: default values.
  1206. /// \return mutex ID for reference by other functions or NULL in case of error.
  1207. osMutexId_t osMutexNew(const osMutexAttr_t *attr)
  1208. {
  1209. char name[RT_NAME_MAX];
  1210. mutex_cb_t *mutex_cb;
  1211. static rt_uint16_t mutex_number = 0U;
  1212. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  1213. {
  1214. rt_snprintf(name, sizeof(name), "mutex%02d", mutex_number++);
  1215. }
  1216. else
  1217. rt_snprintf(name, sizeof(name), "%s", attr->name);
  1218. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  1219. {
  1220. mutex_cb = rt_malloc(sizeof(mutex_cb_t));
  1221. if (RT_NULL == mutex_cb)
  1222. return RT_NULL;
  1223. rt_memset(mutex_cb, 0, sizeof(mutex_cb_t));
  1224. mutex_cb->flags |= MALLOC_CB;
  1225. }
  1226. else
  1227. {
  1228. if (attr->cb_size >= sizeof(mutex_cb_t))
  1229. {
  1230. mutex_cb = attr->cb_mem;
  1231. mutex_cb->flags = 0;
  1232. }
  1233. else
  1234. return RT_NULL;
  1235. }
  1236. if ((RT_NULL == attr) || (0 == attr->attr_bits))
  1237. {
  1238. mutex_cb->flags |= osMutexRecursive;
  1239. }
  1240. else
  1241. mutex_cb->flags |= attr->attr_bits;
  1242. rt_mutex_init(&(mutex_cb->mutex), name, RT_IPC_FLAG_FIFO);
  1243. return mutex_cb;
  1244. }
  1245. /// Get name of a Mutex object.
  1246. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1247. /// \return name as NULL terminated string.
  1248. const char *osMutexGetName(osMutexId_t mutex_id)
  1249. {
  1250. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1251. /* Check parameters */
  1252. if ((RT_NULL == mutex_cb) || (rt_object_get_type(&mutex_cb->mutex.parent.parent) != RT_Object_Class_Mutex))
  1253. {
  1254. return RT_NULL;
  1255. }
  1256. return mutex_cb->mutex.parent.parent.name;
  1257. }
  1258. /// Acquire a Mutex or timeout if it is locked.
  1259. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1260. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1261. /// \return status code that indicates the execution status of the function.
  1262. osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout)
  1263. {
  1264. rt_err_t result;
  1265. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1266. /* Check parameters */
  1267. if (RT_NULL == mutex_cb)
  1268. {
  1269. return osErrorParameter;
  1270. }
  1271. rt_enter_critical();
  1272. if ((mutex_cb->mutex.owner == rt_thread_self()) && !(mutex_cb->flags & osMutexRecursive))
  1273. {
  1274. rt_exit_critical();
  1275. return osError;
  1276. }
  1277. rt_exit_critical();
  1278. if(timeout == osWaitForever)
  1279. {
  1280. timeout = RT_WAITING_FOREVER;
  1281. }
  1282. result = rt_mutex_take(&(mutex_cb->mutex), timeout);
  1283. if (RT_EOK == result)
  1284. return osOK;
  1285. else if (-RT_ETIMEOUT == result)
  1286. {
  1287. if (0U == timeout)
  1288. return osErrorResource;
  1289. else
  1290. return osErrorTimeout;
  1291. }
  1292. else
  1293. return osError;
  1294. }
  1295. /// Release a Mutex that was acquired by \ref osMutexAcquire.
  1296. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1297. /// \return status code that indicates the execution status of the function.
  1298. osStatus_t osMutexRelease(osMutexId_t mutex_id)
  1299. {
  1300. rt_err_t result;
  1301. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1302. /* Check parameters */
  1303. if (RT_NULL == mutex_cb)
  1304. {
  1305. return osErrorParameter;
  1306. }
  1307. result = rt_mutex_release(&(mutex_cb->mutex));
  1308. if (RT_EOK == result)
  1309. return osOK;
  1310. else
  1311. return osErrorResource;
  1312. }
  1313. /// Get Thread which owns a Mutex object.
  1314. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1315. /// \return thread ID of owner thread or NULL when mutex was not acquired.
  1316. osThreadId_t osMutexGetOwner(osMutexId_t mutex_id)
  1317. {
  1318. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1319. /* Check parameters */
  1320. if ((RT_NULL == mutex_cb) || (rt_object_get_type(&mutex_cb->mutex.parent.parent) != RT_Object_Class_Mutex))
  1321. {
  1322. return RT_NULL;
  1323. }
  1324. return mutex_cb->mutex.owner;
  1325. }
  1326. /// Delete a Mutex object.
  1327. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1328. /// \return status code that indicates the execution status of the function.
  1329. osStatus_t osMutexDelete(osMutexId_t mutex_id)
  1330. {
  1331. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1332. /* Check parameters */
  1333. if (RT_NULL == mutex_cb)
  1334. {
  1335. return osErrorParameter;
  1336. }
  1337. rt_mutex_detach(&(mutex_cb->mutex));
  1338. if (mutex_cb->flags & MALLOC_CB)
  1339. rt_free(mutex_cb);
  1340. return osOK;
  1341. }
  1342. #endif
  1343. #ifdef RT_USING_SEMAPHORE
  1344. osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr)
  1345. {
  1346. char name[RT_NAME_MAX];
  1347. sem_cb_t *sem_cb;
  1348. static rt_uint16_t semaphore_number = 0U;
  1349. /* Check parameters */
  1350. if ((0U == max_count) || (initial_count > max_count))
  1351. {
  1352. return RT_NULL;
  1353. }
  1354. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  1355. {
  1356. rt_snprintf(name, sizeof(name), "sem%02d", semaphore_number++);
  1357. }
  1358. else
  1359. rt_snprintf(name, sizeof(name), "%s", attr->name);
  1360. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  1361. {
  1362. sem_cb = rt_malloc(sizeof(sem_cb_t));
  1363. if (RT_NULL == sem_cb)
  1364. return RT_NULL;
  1365. rt_memset(sem_cb, 0, sizeof(sem_cb_t));
  1366. sem_cb->flags |= MALLOC_CB;
  1367. }
  1368. else
  1369. {
  1370. if (attr->cb_size >= sizeof(sem_cb_t))
  1371. {
  1372. sem_cb = attr->cb_mem;
  1373. sem_cb->flags = 0;
  1374. }
  1375. else
  1376. return RT_NULL;
  1377. }
  1378. rt_sem_init(&(sem_cb->sem), name, initial_count, RT_IPC_FLAG_FIFO);
  1379. return sem_cb;
  1380. }
  1381. /// Get name of a Semaphore object.
  1382. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1383. /// \return name as NULL terminated string.
  1384. const char *osSemaphoreGetName(osSemaphoreId_t semaphore_id)
  1385. {
  1386. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1387. /* Check parameters */
  1388. if ((RT_NULL == sem_cb) || (rt_object_get_type(&sem_cb->sem.parent.parent) != RT_Object_Class_Semaphore))
  1389. {
  1390. return RT_NULL;
  1391. }
  1392. return sem_cb->sem.parent.parent.name;
  1393. }
  1394. /// Acquire a Semaphore token or timeout if no tokens are available.
  1395. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1396. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1397. /// \return status code that indicates the execution status of the function.
  1398. osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout)
  1399. {
  1400. rt_err_t result;
  1401. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1402. /* Check parameters */
  1403. if (RT_NULL == sem_cb)
  1404. {
  1405. return osErrorParameter;
  1406. }
  1407. if(timeout == osWaitForever)
  1408. {
  1409. timeout = RT_WAITING_FOREVER;
  1410. }
  1411. result = rt_sem_take(&(sem_cb->sem), timeout);
  1412. if (RT_EOK == result)
  1413. return osOK;
  1414. else if (-RT_ETIMEOUT == result)
  1415. {
  1416. if (0U == timeout)
  1417. return osErrorResource;
  1418. else
  1419. return osErrorTimeout;
  1420. }
  1421. else
  1422. return osError;
  1423. }
  1424. /// Release a Semaphore token that was acquired by \ref osSemaphoreAcquire.
  1425. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1426. /// \return status code that indicates the execution status of the function.
  1427. osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)
  1428. {
  1429. rt_err_t result;
  1430. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1431. /* Check parameters */
  1432. if (RT_NULL == sem_cb)
  1433. {
  1434. return osErrorParameter;
  1435. }
  1436. result = rt_sem_release(&(sem_cb->sem));
  1437. if (RT_EOK == result)
  1438. return osOK;
  1439. else
  1440. return osError;
  1441. }
  1442. /// Get current Semaphore token count.
  1443. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1444. /// \return number of tokens available.
  1445. uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id)
  1446. {
  1447. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1448. /* Check parameters */
  1449. if ((RT_NULL == sem_cb) || (rt_object_get_type(&sem_cb->sem.parent.parent) != RT_Object_Class_Semaphore))
  1450. {
  1451. return 0U;
  1452. }
  1453. return sem_cb->sem.value;
  1454. }
  1455. /// Delete a Semaphore object.
  1456. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1457. /// \return status code that indicates the execution status of the function.
  1458. osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id)
  1459. {
  1460. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1461. /* Check parameters */
  1462. if (RT_NULL == sem_cb)
  1463. {
  1464. return osErrorParameter;
  1465. }
  1466. rt_sem_detach(&(sem_cb->sem));
  1467. if (sem_cb->flags & MALLOC_CB)
  1468. rt_free(sem_cb);
  1469. return osOK;
  1470. }
  1471. #endif
  1472. #ifdef RT_USING_MEMPOOL
  1473. // ==== Memory Pool Management Functions ====
  1474. /// Create and Initialize a Memory Pool object.
  1475. /// \param[in] block_count maximum number of memory blocks in memory pool.
  1476. /// \param[in] block_size memory block size in bytes.
  1477. /// \param[in] attr memory pool attributes; NULL: default values.
  1478. /// \return memory pool ID for reference by other functions or NULL in case of error.
  1479. osMemoryPoolId_t osMemoryPoolNew(uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr)
  1480. {
  1481. char name[RT_NAME_MAX];
  1482. void *mp_addr;
  1483. rt_uint32_t mp_size;
  1484. mempool_cb_t *mempool_cb;
  1485. static rt_uint16_t memory_pool_number = 0U;
  1486. /* Check parameters */
  1487. if ((0U == block_count) || (0U == block_size))
  1488. {
  1489. return RT_NULL;
  1490. }
  1491. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  1492. {
  1493. rt_snprintf(name, sizeof(name), "mp%02d", memory_pool_number++);
  1494. }
  1495. else
  1496. rt_snprintf(name, sizeof(name), "%s", attr->name);
  1497. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  1498. {
  1499. mempool_cb = rt_malloc(sizeof(mempool_cb_t));
  1500. if (RT_NULL == mempool_cb)
  1501. return RT_NULL;
  1502. rt_memset(mempool_cb, 0, sizeof(mempool_cb_t));
  1503. mempool_cb->flags |= MALLOC_CB;
  1504. }
  1505. else
  1506. {
  1507. if (attr->cb_size >= sizeof(mempool_cb_t))
  1508. {
  1509. mempool_cb = attr->cb_mem;
  1510. mempool_cb->flags = 0;
  1511. }
  1512. else
  1513. return RT_NULL;
  1514. }
  1515. if ((RT_NULL == attr) || (RT_NULL == attr->mp_mem))
  1516. {
  1517. block_size = RT_ALIGN(block_size, RT_ALIGN_SIZE);
  1518. mp_size = (block_size + sizeof(rt_uint8_t *)) * block_count;
  1519. mp_addr = rt_malloc((block_size + sizeof(rt_uint8_t *)) * block_count);
  1520. if (RT_NULL == mp_addr)
  1521. {
  1522. if (mempool_cb->flags & MALLOC_CB)
  1523. rt_free(mempool_cb);
  1524. return RT_NULL;
  1525. }
  1526. mempool_cb->flags |= MALLOC_MEM;
  1527. }
  1528. else
  1529. {
  1530. mp_addr = (void *)(attr->mp_mem);
  1531. mp_size = attr->mp_size;
  1532. }
  1533. rt_mp_init(&(mempool_cb->mp), name, mp_addr, mp_size, block_size);
  1534. return mempool_cb;
  1535. }
  1536. /// Get name of a Memory Pool object.
  1537. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1538. /// \return name as NULL terminated string.
  1539. const char *osMemoryPoolGetName(osMemoryPoolId_t mp_id)
  1540. {
  1541. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1542. /* Check parameters */
  1543. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1544. {
  1545. return RT_NULL;
  1546. }
  1547. return mempool_cb->mp.parent.name;
  1548. }
  1549. /// Allocate a memory block from a Memory Pool.
  1550. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1551. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1552. /// \return address of the allocated memory block or NULL in case of no memory is available.
  1553. void *osMemoryPoolAlloc(osMemoryPoolId_t mp_id, uint32_t timeout)
  1554. {
  1555. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1556. /* Check parameters */
  1557. if (RT_NULL == mempool_cb)
  1558. {
  1559. return RT_NULL;
  1560. }
  1561. if(timeout == osWaitForever)
  1562. {
  1563. timeout = RT_WAITING_FOREVER;
  1564. }
  1565. return rt_mp_alloc(&(mempool_cb->mp), timeout);
  1566. }
  1567. /// Return an allocated memory block back to a Memory Pool.
  1568. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1569. /// \param[in] block address of the allocated memory block to be returned to the memory pool.
  1570. /// \return status code that indicates the execution status of the function.
  1571. osStatus_t osMemoryPoolFree(osMemoryPoolId_t mp_id, void *block)
  1572. {
  1573. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1574. /* Check parameters */
  1575. if (RT_NULL == mempool_cb)
  1576. {
  1577. return osErrorParameter;
  1578. }
  1579. rt_mp_free(block);
  1580. return osOK;
  1581. }
  1582. /// Get maximum number of memory blocks in a Memory Pool.
  1583. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1584. /// \return maximum number of memory blocks.
  1585. uint32_t osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id)
  1586. {
  1587. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1588. /* Check parameters */
  1589. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1590. {
  1591. return 0U;
  1592. }
  1593. return mempool_cb->mp.block_total_count;
  1594. }
  1595. /// Get memory block size in a Memory Pool.
  1596. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1597. /// \return memory block size in bytes.
  1598. uint32_t osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id)
  1599. {
  1600. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1601. /* Check parameters */
  1602. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1603. {
  1604. return 0U;
  1605. }
  1606. return mempool_cb->mp.block_size;
  1607. }
  1608. /// Get number of memory blocks used in a Memory Pool.
  1609. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1610. /// \return number of memory blocks used.
  1611. uint32_t osMemoryPoolGetCount(osMemoryPoolId_t mp_id)
  1612. {
  1613. rt_size_t used_blocks;
  1614. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1615. /* Check parameters */
  1616. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1617. {
  1618. return 0U;
  1619. }
  1620. used_blocks = mempool_cb->mp.block_total_count - mempool_cb->mp.block_free_count;
  1621. return (uint32_t)used_blocks;
  1622. }
  1623. /// Get number of memory blocks available in a Memory Pool.
  1624. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1625. /// \return number of memory blocks available.
  1626. uint32_t osMemoryPoolGetSpace(osMemoryPoolId_t mp_id)
  1627. {
  1628. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1629. /* Check parameters */
  1630. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1631. {
  1632. return 0U;
  1633. }
  1634. return mempool_cb->mp.block_free_count;
  1635. }
  1636. /// Delete a Memory Pool object.
  1637. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1638. /// \return status code that indicates the execution status of the function.
  1639. osStatus_t osMemoryPoolDelete(osMemoryPoolId_t mp_id)
  1640. {
  1641. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1642. /* Check parameters */
  1643. if (RT_NULL == mempool_cb)
  1644. {
  1645. return osErrorParameter;
  1646. }
  1647. rt_mp_detach(&(mempool_cb->mp));
  1648. if (mempool_cb->flags & MALLOC_CB)
  1649. rt_free(mempool_cb);
  1650. if (mempool_cb->flags & MALLOC_MEM)
  1651. rt_free(mempool_cb->mp.start_address);
  1652. return osOK;
  1653. }
  1654. #endif
  1655. #ifdef RT_USING_MESSAGEQUEUE
  1656. // ==== Message Queue Management Functions ====
  1657. /// Create and Initialize a Message Queue object.
  1658. /// \param[in] msg_count maximum number of messages in queue.
  1659. /// \param[in] msg_size maximum message size in bytes.
  1660. /// \param[in] attr message queue attributes; NULL: default values.
  1661. /// \return message queue ID for reference by other functions or NULL in case of error.
  1662. osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr)
  1663. {
  1664. char name[RT_NAME_MAX];
  1665. mq_cb_t *mq_cb;
  1666. void *mq_addr;
  1667. rt_uint32_t mq_size;
  1668. static rt_uint16_t mq_number = 0U;
  1669. /* Check parameters */
  1670. if ((0U == msg_count) || (0U == msg_size))
  1671. {
  1672. return RT_NULL;
  1673. }
  1674. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  1675. {
  1676. rt_snprintf(name, sizeof(name), "mq%02d", mq_number++);
  1677. }
  1678. else
  1679. rt_snprintf(name, sizeof(name), "%s", attr->name);
  1680. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  1681. {
  1682. mq_cb = rt_malloc(sizeof(mq_cb_t));
  1683. if (RT_NULL == mq_cb)
  1684. return RT_NULL;
  1685. rt_memset(mq_cb, 0, sizeof(mq_cb_t));
  1686. mq_cb->flags |= MALLOC_CB;
  1687. }
  1688. else
  1689. {
  1690. if (attr->cb_size >= sizeof(mq_cb_t))
  1691. {
  1692. mq_cb = attr->cb_mem;
  1693. mq_cb->flags = 0;
  1694. }
  1695. else
  1696. return RT_NULL;
  1697. }
  1698. mq_cb->init_msg_size = msg_size;
  1699. if ((RT_NULL == attr) || (RT_NULL == attr->mq_mem))
  1700. {
  1701. register rt_size_t msg_align_size;
  1702. /* get correct message size */
  1703. msg_align_size = RT_ALIGN(msg_size, RT_ALIGN_SIZE);
  1704. mq_size = (msg_align_size + sizeof(struct rt_mq_message)) * msg_count;
  1705. mq_addr = rt_malloc(mq_size);
  1706. if (RT_NULL == mq_addr)
  1707. {
  1708. if (mq_cb->flags & MALLOC_CB)
  1709. rt_free(mq_cb);
  1710. return RT_NULL;
  1711. }
  1712. rt_memset(mq_addr, 0, sizeof(mq_size));
  1713. mq_cb->flags |= MALLOC_MEM;
  1714. }
  1715. else
  1716. {
  1717. mq_addr = (void *)(attr->mq_mem);
  1718. mq_size = attr->mq_size;
  1719. }
  1720. rt_mq_init(&(mq_cb->mq), name, mq_addr, msg_size, mq_size, RT_IPC_FLAG_FIFO);
  1721. return mq_cb;
  1722. }
  1723. /// Get name of a Message Queue object.
  1724. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1725. /// \return name as NULL terminated string.
  1726. const char *osMessageQueueGetName(osMessageQueueId_t mq_id)
  1727. {
  1728. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1729. /* Check parameters */
  1730. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1731. {
  1732. return RT_NULL;
  1733. }
  1734. return mq_cb->mq.parent.parent.name;
  1735. }
  1736. /// Put a Message into a Queue or timeout if Queue is full.
  1737. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1738. /// \param[in] msg_ptr pointer to buffer with message to put into a queue.
  1739. /// \param[in] msg_prio message priority.
  1740. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1741. /// \return status code that indicates the execution status of the function.
  1742. osStatus_t osMessageQueuePut(osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout)
  1743. {
  1744. rt_err_t result;
  1745. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1746. /* Check parameters */
  1747. if (RT_NULL == mq_cb || (RT_NULL == msg_ptr))
  1748. {
  1749. return osErrorParameter;
  1750. }
  1751. if(timeout == osWaitForever)
  1752. {
  1753. timeout = RT_WAITING_FOREVER;
  1754. }
  1755. result = rt_mq_send_wait(&(mq_cb->mq), (void *)msg_ptr, mq_cb->init_msg_size, timeout);
  1756. if (RT_EOK == result)
  1757. return osOK;
  1758. else if (-RT_EFULL == result)
  1759. return osErrorResource;
  1760. else if (-RT_ETIMEOUT == result)
  1761. {
  1762. return osErrorTimeout;
  1763. }
  1764. else
  1765. {
  1766. return osError;
  1767. }
  1768. }
  1769. /// Get a Message from a Queue or timeout if Queue is empty.
  1770. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1771. /// \param[out] msg_ptr pointer to buffer for message to get from a queue.
  1772. /// \param[out] msg_prio pointer to buffer for message priority or NULL.
  1773. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1774. /// \return status code that indicates the execution status of the function.
  1775. #if defined(RT_VERSION_CHECK) && (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 0, 1))
  1776. osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout)
  1777. {
  1778. rt_ssize_t result = 0;
  1779. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1780. /* Check parameters */
  1781. if (RT_NULL == mq_cb || (RT_NULL == msg_ptr))
  1782. {
  1783. return osErrorParameter;
  1784. }
  1785. if(timeout == osWaitForever)
  1786. {
  1787. timeout = RT_WAITING_FOREVER;
  1788. }
  1789. result = rt_mq_recv(&(mq_cb->mq), msg_ptr, mq_cb->init_msg_size, timeout);
  1790. if (result > 0)
  1791. {
  1792. return osOK;
  1793. }
  1794. else if (-RT_ETIMEOUT == result)
  1795. {
  1796. if (0U == timeout)
  1797. return osErrorResource;
  1798. return osErrorTimeout;
  1799. }
  1800. else
  1801. return osError;
  1802. }
  1803. #else /* legacy version macros (<5.0.1) */
  1804. osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout)
  1805. {
  1806. rt_err_t result;
  1807. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1808. /* Check parameters */
  1809. if (RT_NULL == mq_cb || (RT_NULL == msg_ptr))
  1810. {
  1811. return osErrorParameter;
  1812. }
  1813. if(timeout == osWaitForever)
  1814. {
  1815. timeout = RT_WAITING_FOREVER;
  1816. }
  1817. result = rt_mq_recv(&(mq_cb->mq), msg_ptr, mq_cb->init_msg_size, timeout);
  1818. if (RT_EOK == result)
  1819. return osOK;
  1820. else if (-RT_ETIMEOUT == result)
  1821. {
  1822. if (0U == timeout)
  1823. return osErrorResource;
  1824. return osErrorTimeout;
  1825. }
  1826. else
  1827. return osError;
  1828. }
  1829. #endif
  1830. /// Get maximum number of messages in a Message Queue.
  1831. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1832. /// \return maximum number of messages.
  1833. uint32_t osMessageQueueGetCapacity(osMessageQueueId_t mq_id)
  1834. {
  1835. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1836. /* Check parameters */
  1837. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1838. {
  1839. return 0U;
  1840. }
  1841. return mq_cb->mq.max_msgs;
  1842. }
  1843. /// Get maximum message size in a Memory Pool.
  1844. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1845. /// \return maximum message size in bytes.
  1846. uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t mq_id)
  1847. {
  1848. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1849. /* Check parameters */;
  1850. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1851. {
  1852. return 0U;
  1853. }
  1854. return mq_cb->mq.msg_size;
  1855. }
  1856. /// Get number of queued messages in a Message Queue.
  1857. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1858. /// \return number of queued messages.
  1859. uint32_t osMessageQueueGetCount(osMessageQueueId_t mq_id)
  1860. {
  1861. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1862. /* Check parameters */;
  1863. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1864. {
  1865. return 0U;
  1866. }
  1867. return mq_cb->mq.entry;
  1868. }
  1869. /// Get number of available slots for messages in a Message Queue.
  1870. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1871. /// \return number of available slots for messages.
  1872. uint32_t osMessageQueueGetSpace(osMessageQueueId_t mq_id)
  1873. {
  1874. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1875. /* Check parameters */;
  1876. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1877. {
  1878. return 0U;
  1879. }
  1880. return (mq_cb->mq.max_msgs - mq_cb->mq.entry);
  1881. }
  1882. /// Reset a Message Queue to initial empty state.
  1883. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1884. /// \return status code that indicates the execution status of the function.
  1885. osStatus_t osMessageQueueReset(osMessageQueueId_t mq_id)
  1886. {
  1887. rt_err_t result;
  1888. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1889. /* Check parameters */;
  1890. if (RT_NULL == mq_cb)
  1891. {
  1892. return osErrorParameter;
  1893. }
  1894. result = rt_mq_control(&(mq_cb->mq), RT_IPC_CMD_RESET, RT_NULL);
  1895. if (RT_EOK == result)
  1896. return osOK;
  1897. else
  1898. return osError;
  1899. }
  1900. /// Delete a Message Queue object.
  1901. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1902. /// \return status code that indicates the execution status of the function.
  1903. osStatus_t osMessageQueueDelete(osMessageQueueId_t mq_id)
  1904. {
  1905. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1906. /* Check parameters */;
  1907. if (RT_NULL == mq_cb)
  1908. {
  1909. return osErrorParameter;
  1910. }
  1911. rt_mq_detach(&(mq_cb->mq));
  1912. if (mq_cb->flags & MALLOC_CB)
  1913. rt_free(mq_cb);
  1914. if (mq_cb->flags & MALLOC_MEM)
  1915. rt_free(mq_cb->mq.msg_pool);
  1916. return osOK;
  1917. }
  1918. #endif