cmsis_rtthread.c 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331
  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. }
  633. else
  634. return osError;
  635. return osOK;
  636. }
  637. /// Terminate execution of current running thread.
  638. __NO_RETURN void osThreadExit(void)
  639. {
  640. rt_thread_t self = rt_thread_self();
  641. rt_thread_control(self, RT_THREAD_CTRL_CLOSE, RT_NULL);
  642. RT_ASSERT(0);
  643. while(1);
  644. }
  645. /// Terminate execution of a thread.
  646. /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
  647. /// \return status code that indicates the execution status of the function.
  648. osStatus_t osThreadTerminate(osThreadId_t thread_id)
  649. {
  650. thread_cb_t *thread_cb;
  651. thread_cb = (thread_cb_t *)(rt_thread_self()->user_data);
  652. /* Check parameters */
  653. if (RT_NULL == thread_cb)
  654. {
  655. return osErrorParameter;
  656. }
  657. rt_thread_detach(&(thread_cb->thread));
  658. rt_schedule();
  659. return osOK;
  660. }
  661. /// Get number of active threads.
  662. /// \return number of active threads.
  663. uint32_t osThreadGetCount(void)
  664. {
  665. rt_uint32_t thread_count = 0U;
  666. struct rt_object_information *info;
  667. info = rt_object_get_information(RT_Object_Class_Thread);
  668. rt_enter_critical();
  669. thread_count = rt_list_len(&(info->object_list));
  670. rt_exit_critical();
  671. return thread_count;
  672. }
  673. /// Enumerate active threads.
  674. /// \param[out] thread_array pointer to array for retrieving thread IDs.
  675. /// \param[in] array_items maximum number of items in array for retrieving thread IDs.
  676. /// \return number of enumerated threads.
  677. uint32_t osThreadEnumerate(osThreadId_t *thread_array, uint32_t array_items)
  678. {
  679. rt_uint32_t thread_count = 0U;
  680. rt_thread_t thread;
  681. struct rt_object_information *info;
  682. struct rt_list_node *node;
  683. /* Check parameters */
  684. if ((RT_NULL == thread_array) || (0U == array_items))
  685. {
  686. return 0U;
  687. }
  688. info = rt_object_get_information(RT_Object_Class_Thread);
  689. rt_enter_critical();
  690. for (node = info->object_list.next; node != &(info->object_list); node = node->next)
  691. {
  692. thread = thread_rt_list_entry(node, rt_thread);
  693. thread_array[thread_count] = (osThreadId_t)thread;
  694. thread_count++;
  695. if (thread_count >= array_items)
  696. break;
  697. }
  698. rt_exit_critical();
  699. return thread_count;
  700. }
  701. // ==== Thread Flags Functions ====
  702. /// Set the specified Thread Flags of a thread.
  703. /// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
  704. /// \param[in] flags specifies the flags of the thread that shall be set.
  705. /// \return thread flags after setting or error code if highest bit set.
  706. uint32_t osThreadFlagsSet(osThreadId_t thread_id, uint32_t flags)
  707. {
  708. register rt_base_t status;
  709. register rt_ubase_t level;
  710. rt_bool_t need_schedule = RT_FALSE;
  711. thread_cb_t *thread_cb;
  712. rt_uint32_t return_value;
  713. thread_cb = (thread_cb_t *)(thread_id);
  714. /* Check parameters */
  715. if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread))
  716. {
  717. return osFlagsErrorParameter;
  718. }
  719. level = rt_hw_interrupt_disable();
  720. thread_cb->flag_set |= flags;
  721. return_value = thread_cb->flag_set;
  722. /* Check if Thread is waiting for Thread Flags */
  723. if (thread_cb->thread.event_info & WAITING_THREAD_FLAGS)
  724. {
  725. status = -RT_ERROR;
  726. if (thread_cb->thread.event_info & osFlagsWaitAll)
  727. {
  728. if ((thread_cb->thread.event_set & thread_cb->flag_set) == thread_cb->thread.event_set)
  729. {
  730. /* received an AND event */
  731. status = RT_EOK;
  732. }
  733. }
  734. else
  735. {
  736. if (thread_cb->thread.event_set & thread_cb->flag_set)
  737. {
  738. /* save recieved event set */
  739. thread_cb->thread.event_set &= thread_cb->flag_set;
  740. /* received an OR event */
  741. status = RT_EOK;
  742. }
  743. }
  744. /* condition is satisfied, resume thread */
  745. if (RT_EOK == status)
  746. {
  747. thread_cb->thread.event_info &= ~WAITING_THREAD_FLAGS;
  748. /* clear event */
  749. if (!(thread_cb->thread.event_info & osFlagsNoClear))
  750. thread_cb->flag_set &= ~thread_cb->thread.event_set;
  751. /* resume thread, and thread list breaks out */
  752. rt_thread_resume(rt_thread_self());
  753. need_schedule = RT_TRUE;
  754. }
  755. }
  756. rt_hw_interrupt_enable(level);
  757. if (need_schedule == RT_TRUE)
  758. rt_schedule();
  759. return return_value;
  760. }
  761. /// Clear the specified Thread Flags of current running thread.
  762. /// \param[in] flags specifies the flags of the thread that shall be cleared.
  763. /// \return thread flags before clearing or error code if highest bit set.
  764. uint32_t osThreadFlagsClear(uint32_t flags)
  765. {
  766. rt_thread_t thread = rt_thread_self();
  767. thread_cb_t *thread_cb;
  768. rt_uint32_t flag;
  769. /* Check parameters */
  770. if (RT_NULL == thread)
  771. {
  772. return osFlagsErrorParameter;
  773. }
  774. thread_cb = (thread_cb_t *)(thread->user_data);
  775. rt_enter_critical();
  776. flag = thread_cb->flag_set;
  777. thread_cb->flag_set &= ~flags;
  778. rt_exit_critical();
  779. return flag;
  780. }
  781. /// Get the current Thread Flags of current running thread.
  782. /// \return current thread flags.
  783. uint32_t osThreadFlagsGet(void)
  784. {
  785. rt_thread_t thread = rt_thread_self();
  786. thread_cb_t *thread_cb;
  787. /* Check parameters */
  788. if (RT_NULL == thread)
  789. {
  790. return osFlagsErrorParameter;
  791. }
  792. thread_cb = (thread_cb_t *)(thread->user_data);
  793. return thread_cb->flag_set;
  794. }
  795. /// Wait for one or more Thread Flags of the current running thread to become signaled.
  796. /// \param[in] flags specifies the flags to wait for.
  797. /// \param[in] options specifies flags options (osFlagsXxxx).
  798. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  799. /// \return thread flags before clearing or error code if highest bit set.
  800. uint32_t osThreadFlagsWait(uint32_t flags, uint32_t options, uint32_t timeout)
  801. {
  802. rt_uint32_t return_value;
  803. register rt_ubase_t level;
  804. register rt_base_t status = -RT_ERROR;
  805. rt_thread_t thread = rt_thread_self();
  806. thread_cb_t *thread_cb;
  807. /* Check parameters */
  808. if (RT_NULL == thread)
  809. {
  810. return osFlagsErrorParameter;
  811. }
  812. thread->error = RT_EOK;
  813. thread_cb = (thread_cb_t *)(thread->user_data);
  814. level = rt_hw_interrupt_disable();
  815. if (options & osFlagsWaitAll)
  816. {
  817. if ((thread_cb->flag_set & flags) == flags)
  818. status = RT_EOK;
  819. }
  820. else
  821. {
  822. if (thread_cb->flag_set & flags)
  823. status = RT_EOK;
  824. }
  825. if (RT_EOK == status)
  826. {
  827. return_value = thread_cb->flag_set & flags;
  828. if (!(options & osFlagsNoClear))
  829. thread_cb->flag_set &= ~flags;
  830. }
  831. else if (0U == timeout)
  832. {
  833. rt_hw_interrupt_enable(level);
  834. return osFlagsErrorResource;
  835. }
  836. else
  837. {
  838. thread->event_set = flags;
  839. thread->event_info = options | WAITING_THREAD_FLAGS;
  840. rt_thread_suspend(thread);
  841. /* if there is a waiting timeout, active thread timer */
  842. if ((timeout > 0U) && (timeout != osWaitForever))
  843. {
  844. /* reset the timeout of thread timer and start it */
  845. rt_timer_control(&(thread->thread_timer),
  846. RT_TIMER_CTRL_SET_TIME,
  847. &timeout);
  848. rt_timer_start(&(thread->thread_timer));
  849. }
  850. rt_hw_interrupt_enable(level);
  851. rt_schedule();
  852. if (thread->error != RT_EOK)
  853. {
  854. return thread->error;
  855. }
  856. level = rt_hw_interrupt_disable();
  857. return_value = thread->event_set;
  858. }
  859. rt_hw_interrupt_enable(level);
  860. return return_value;
  861. }
  862. // ==== Generic Wait Functions ====
  863. /// Wait for Timeout (Time Delay).
  864. /// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value
  865. /// \return status code that indicates the execution status of the function.
  866. osStatus_t osDelay(uint32_t ticks)
  867. {
  868. rt_thread_delay(ticks);
  869. return osOK;
  870. }
  871. /// Wait until specified time.
  872. /// \param[in] ticks absolute time in ticks
  873. /// \return status code that indicates the execution status of the function.
  874. osStatus_t osDelayUntil(uint32_t ticks)
  875. {
  876. uint64_t cur_ticks;
  877. cur_ticks = rt_tick_get();
  878. if (ticks == cur_ticks)
  879. {
  880. }
  881. else if (ticks > cur_ticks)
  882. {
  883. rt_thread_delay(ticks - cur_ticks);
  884. }
  885. else
  886. {
  887. rt_thread_delay(((rt_uint32_t) - 1) - cur_ticks + ticks);
  888. }
  889. return osOK;
  890. }
  891. // ==== Timer Management Functions ====
  892. /// Create and Initialize a timer.
  893. /// \param[in] func start address of a timer call back function.
  894. /// \param[in] type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior.
  895. /// \param[in] argument argument to the timer call back function.
  896. /// \param[in] attr timer attributes; NULL: default values.
  897. /// \return timer ID for reference by other functions or NULL in case of error.
  898. osTimerId_t osTimerNew(osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr)
  899. {
  900. timer_cb_t *timer_cb;
  901. char name[RT_NAME_MAX];
  902. static rt_uint16_t timer_number = 0U;
  903. rt_uint8_t flag = RT_TIMER_FLAG_SOFT_TIMER;
  904. /* Check parameters */
  905. if ((RT_NULL == func) || ((type != osTimerOnce) && (type != osTimerPeriodic)))
  906. {
  907. return RT_NULL;
  908. }
  909. /* RT-Thread object's name can't be NULL */
  910. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  911. rt_snprintf(name, sizeof(name), "timer%02d", timer_number++);
  912. else
  913. rt_snprintf(name, sizeof(name), "%s", attr->name);
  914. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  915. {
  916. timer_cb = rt_malloc(sizeof(timer_cb_t));
  917. if (RT_NULL == timer_cb)
  918. return RT_NULL;
  919. rt_memset(timer_cb, 0, sizeof(timer_cb_t));
  920. timer_cb->flags |= MALLOC_CB;
  921. }
  922. else
  923. {
  924. if (attr->cb_size >= sizeof(timer_cb_t))
  925. {
  926. timer_cb = attr->cb_mem;
  927. timer_cb->flags = 0;
  928. }
  929. else
  930. return RT_NULL;
  931. }
  932. if (osTimerPeriodic == type)
  933. {
  934. flag |= RT_TIMER_FLAG_PERIODIC;
  935. }
  936. rt_timer_init(&(timer_cb->timer), name, func, argument, 0, flag);
  937. return timer_cb;
  938. }
  939. /// Get name of a timer.
  940. /// \param[in] timer_id timer ID obtained by \ref osTimerNew.
  941. /// \return name as NULL terminated string.
  942. const char *osTimerGetName(osTimerId_t timer_id)
  943. {
  944. timer_cb_t *timer_cb;
  945. timer_cb = (timer_cb_t *)timer_id;
  946. /* Check parameters */
  947. if ((RT_NULL == timer_cb) || (rt_object_get_type(&timer_cb->timer.parent) != RT_Object_Class_Timer))
  948. {
  949. return RT_NULL;
  950. }
  951. return timer_cb->timer.parent.name;
  952. }
  953. /// Start or restart a timer.
  954. /// \param[in] timer_id timer ID obtained by \ref osTimerNew.
  955. /// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value of the timer.
  956. /// \return status code that indicates the execution status of the function.
  957. osStatus_t osTimerStart(osTimerId_t timer_id, uint32_t ticks)
  958. {
  959. rt_err_t result;
  960. timer_cb_t *timer_cb;
  961. timer_cb = (timer_cb_t *)timer_id;
  962. /* Check parameters */
  963. if ((RT_NULL == timer_cb) || (ticks == 0))
  964. {
  965. return osErrorParameter;
  966. }
  967. rt_timer_control(&(timer_cb->timer), RT_TIMER_CTRL_SET_TIME, &ticks);
  968. result = rt_timer_start(&(timer_cb->timer));
  969. if (RT_EOK == result)
  970. return osOK;
  971. else
  972. return osError;
  973. }
  974. /// Stop a timer.
  975. /// \param[in] timer_id timer ID obtained by \ref osTimerNew.
  976. /// \return status code that indicates the execution status of the function.
  977. osStatus_t osTimerStop(osTimerId_t timer_id)
  978. {
  979. rt_err_t result;
  980. timer_cb_t *timer_cb;
  981. timer_cb = (timer_cb_t *)timer_id;
  982. /* Check parameters */
  983. if (RT_NULL == timer_cb)
  984. {
  985. return osErrorParameter;
  986. }
  987. result = rt_timer_stop(&(timer_cb->timer));
  988. if (RT_EOK == result)
  989. return osOK;
  990. else
  991. return osError;
  992. }
  993. /// Check if a timer is running.
  994. /// \param[in] timer_id timer ID obtained by \ref osTimerNew.
  995. /// \return 0 not running, 1 running.
  996. uint32_t osTimerIsRunning(osTimerId_t timer_id)
  997. {
  998. timer_cb_t *timer_cb;
  999. timer_cb = (timer_cb_t *)timer_id;
  1000. /* Check parameters */
  1001. if ((RT_NULL == timer_cb) || (rt_object_get_type(&timer_cb->timer.parent) != RT_Object_Class_Timer))
  1002. {
  1003. return 0U;
  1004. }
  1005. if ((timer_cb->timer.parent.flag & RT_TIMER_FLAG_ACTIVATED) == 1u)
  1006. {
  1007. return 1;
  1008. }
  1009. else
  1010. return 0U;
  1011. }
  1012. /// Delete a timer.
  1013. /// \param[in] timer_id timer ID obtained by \ref osTimerNew.
  1014. /// \return status code that indicates the execution status of the function.
  1015. osStatus_t osTimerDelete(osTimerId_t timer_id)
  1016. {
  1017. timer_cb_t *timer_cb;
  1018. timer_cb = (timer_cb_t *)timer_id;
  1019. /* Check parameters */
  1020. if (RT_NULL == timer_cb)
  1021. {
  1022. return osErrorParameter;
  1023. }
  1024. rt_timer_detach(&(timer_cb->timer));
  1025. if (timer_cb->flags & MALLOC_CB)
  1026. rt_free(timer_cb);
  1027. return osOK;
  1028. }
  1029. #ifdef RT_USING_EVENT
  1030. // ==== Event Flags Management Functions ====
  1031. /// Create and Initialize an Event Flags object.
  1032. /// \param[in] attr event flags attributes; NULL: default values.
  1033. /// \return event flags ID for reference by other functions or NULL in case of error.
  1034. osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr)
  1035. {
  1036. char name[RT_NAME_MAX];
  1037. event_cb_t *event_cb;
  1038. static rt_uint16_t event_number = 0U;
  1039. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  1040. {
  1041. rt_snprintf(name, sizeof(name), "event%02d", event_number++);
  1042. }
  1043. else
  1044. rt_snprintf(name, sizeof(name), "%s", attr->name);
  1045. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  1046. {
  1047. event_cb = rt_malloc(sizeof(event_cb_t));
  1048. if (RT_NULL == event_cb)
  1049. return RT_NULL;
  1050. rt_memset(event_cb, 0, sizeof(event_cb_t));
  1051. event_cb->flags |= MALLOC_CB;
  1052. }
  1053. else
  1054. {
  1055. if (attr->cb_size >= sizeof(event_cb_t))
  1056. {
  1057. event_cb = attr->cb_mem;
  1058. event_cb->flags = 0;
  1059. }
  1060. else
  1061. return RT_NULL;
  1062. }
  1063. rt_event_init(&(event_cb->event), name, RT_IPC_FLAG_FIFO);
  1064. return event_cb;
  1065. }
  1066. /// Get name of an Event Flags object.
  1067. /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
  1068. /// \return name as NULL terminated string.
  1069. const char *osEventFlagsGetName(osEventFlagsId_t ef_id)
  1070. {
  1071. event_cb_t *event_cb = (event_cb_t *)ef_id;
  1072. /* Check parameters */
  1073. if ((RT_NULL == event_cb) || (rt_object_get_type(&event_cb->event.parent.parent) != RT_Object_Class_Event))
  1074. {
  1075. return RT_NULL;
  1076. }
  1077. return event_cb->event.parent.parent.name;
  1078. }
  1079. /// Set the specified Event Flags.
  1080. /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
  1081. /// \param[in] flags specifies the flags that shall be set.
  1082. /// \return event flags after setting or error code if highest bit set.
  1083. uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags)
  1084. {
  1085. rt_err_t result;
  1086. rt_uint32_t set_flags;
  1087. event_cb_t *event_cb = (event_cb_t *)ef_id;
  1088. /* Check parameters */
  1089. if ((RT_NULL == event_cb) || (rt_object_get_type(&event_cb->event.parent.parent) != RT_Object_Class_Event))
  1090. {
  1091. return ((uint32_t)osFlagsErrorParameter);
  1092. }
  1093. set_flags = event_cb->event.set |= flags;
  1094. result = rt_event_send(&(event_cb->event), flags);
  1095. if (RT_EOK == result)
  1096. return set_flags;
  1097. else
  1098. return osFlagsError;
  1099. }
  1100. /// Clear the specified Event Flags.
  1101. /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
  1102. /// \param[in] flags specifies the flags that shall be cleared.
  1103. /// \return event flags before clearing or error code if highest bit set.
  1104. uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags)
  1105. {
  1106. rt_uint32_t set_flags;
  1107. register rt_ubase_t level;
  1108. event_cb_t *event_cb = (event_cb_t *)ef_id;
  1109. /* Check parameters */
  1110. if ((RT_NULL == event_cb) || (rt_object_get_type(&event_cb->event.parent.parent) != RT_Object_Class_Event))
  1111. {
  1112. return ((uint32_t)osFlagsErrorParameter);
  1113. }
  1114. set_flags = event_cb->event.set;
  1115. level = rt_hw_interrupt_disable();
  1116. event_cb->event.set &= ~flags;
  1117. rt_hw_interrupt_enable(level);
  1118. return set_flags;
  1119. }
  1120. /// Get the current Event Flags.
  1121. /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
  1122. /// \return current event flags.
  1123. uint32_t osEventFlagsGet(osEventFlagsId_t ef_id)
  1124. {
  1125. event_cb_t *event_cb = (event_cb_t *)ef_id;
  1126. /* Check parameters */
  1127. if ((RT_NULL == event_cb) || (rt_object_get_type(&event_cb->event.parent.parent) != RT_Object_Class_Event))
  1128. {
  1129. return 0U;
  1130. }
  1131. return event_cb->event.set;
  1132. }
  1133. /// Wait for one or more Event Flags to become signaled.
  1134. /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
  1135. /// \param[in] flags specifies the flags to wait for.
  1136. /// \param[in] options specifies flags options (osFlagsXxxx).
  1137. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1138. /// \return event flags before clearing or error code if highest bit set.
  1139. uint32_t osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout)
  1140. {
  1141. rt_err_t result;
  1142. rt_uint32_t rt_recv;
  1143. rt_uint8_t rt_options = 0U;
  1144. event_cb_t *event_cb = (event_cb_t *)ef_id;
  1145. /* Check parameters */
  1146. if (RT_NULL == event_cb)
  1147. {
  1148. return ((uint32_t)osFlagsErrorParameter);
  1149. }
  1150. if (options & osFlagsWaitAll)
  1151. {
  1152. rt_options |= RT_EVENT_FLAG_AND;
  1153. }
  1154. else
  1155. {
  1156. rt_options |= RT_EVENT_FLAG_OR;
  1157. }
  1158. if (!(options & osFlagsNoClear))
  1159. {
  1160. rt_options |= RT_EVENT_FLAG_CLEAR;
  1161. }
  1162. if(timeout == osWaitForever)
  1163. {
  1164. timeout = RT_WAITING_FOREVER;
  1165. }
  1166. result = rt_event_recv(&(event_cb->event), flags, (rt_uint8_t)rt_options, timeout, &rt_recv);
  1167. if (RT_EOK == result)
  1168. return rt_recv;
  1169. else if (-RT_ETIMEOUT == result)
  1170. {
  1171. if (0U == timeout)
  1172. return osFlagsErrorResource;
  1173. else
  1174. return osFlagsErrorTimeout;
  1175. }
  1176. else
  1177. return osFlagsErrorUnknown;
  1178. }
  1179. /// Delete an Event Flags object.
  1180. /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
  1181. /// \return status code that indicates the execution status of the function.
  1182. osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id)
  1183. {
  1184. event_cb_t *event_cb = (event_cb_t *)ef_id;
  1185. /* Check parameters */
  1186. if (RT_NULL == event_cb)
  1187. {
  1188. return osErrorParameter;
  1189. }
  1190. rt_event_detach(&(event_cb->event));
  1191. if (event_cb->flags & MALLOC_CB)
  1192. rt_free(event_cb);
  1193. return osOK;
  1194. }
  1195. #endif
  1196. #ifdef RT_USING_MUTEX
  1197. // ==== Mutex Management Functions ====
  1198. /// Create and Initialize a Mutex object.
  1199. /// \param[in] attr mutex attributes; NULL: default values.
  1200. /// \return mutex ID for reference by other functions or NULL in case of error.
  1201. osMutexId_t osMutexNew(const osMutexAttr_t *attr)
  1202. {
  1203. char name[RT_NAME_MAX];
  1204. mutex_cb_t *mutex_cb;
  1205. static rt_uint16_t mutex_number = 0U;
  1206. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  1207. {
  1208. rt_snprintf(name, sizeof(name), "mutex%02d", mutex_number++);
  1209. }
  1210. else
  1211. rt_snprintf(name, sizeof(name), "%s", attr->name);
  1212. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  1213. {
  1214. mutex_cb = rt_malloc(sizeof(mutex_cb_t));
  1215. if (RT_NULL == mutex_cb)
  1216. return RT_NULL;
  1217. rt_memset(mutex_cb, 0, sizeof(mutex_cb_t));
  1218. mutex_cb->flags |= MALLOC_CB;
  1219. }
  1220. else
  1221. {
  1222. if (attr->cb_size >= sizeof(mutex_cb_t))
  1223. {
  1224. mutex_cb = attr->cb_mem;
  1225. mutex_cb->flags = 0;
  1226. }
  1227. else
  1228. return RT_NULL;
  1229. }
  1230. if ((RT_NULL == attr) || (0 == attr->attr_bits))
  1231. {
  1232. mutex_cb->flags |= osMutexRecursive;
  1233. }
  1234. else
  1235. mutex_cb->flags |= attr->attr_bits;
  1236. rt_mutex_init(&(mutex_cb->mutex), name, RT_IPC_FLAG_FIFO);
  1237. return mutex_cb;
  1238. }
  1239. /// Get name of a Mutex object.
  1240. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1241. /// \return name as NULL terminated string.
  1242. const char *osMutexGetName(osMutexId_t mutex_id)
  1243. {
  1244. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1245. /* Check parameters */
  1246. if ((RT_NULL == mutex_cb) || (rt_object_get_type(&mutex_cb->mutex.parent.parent) != RT_Object_Class_Mutex))
  1247. {
  1248. return RT_NULL;
  1249. }
  1250. return mutex_cb->mutex.parent.parent.name;
  1251. }
  1252. /// Acquire a Mutex or timeout if it is locked.
  1253. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1254. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1255. /// \return status code that indicates the execution status of the function.
  1256. osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout)
  1257. {
  1258. rt_err_t result;
  1259. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1260. /* Check parameters */
  1261. if (RT_NULL == mutex_cb)
  1262. {
  1263. return osErrorParameter;
  1264. }
  1265. rt_enter_critical();
  1266. if ((mutex_cb->mutex.owner == rt_thread_self()) && !(mutex_cb->flags & osMutexRecursive))
  1267. {
  1268. rt_exit_critical();
  1269. return osError;
  1270. }
  1271. rt_exit_critical();
  1272. if(timeout == osWaitForever)
  1273. {
  1274. timeout = RT_WAITING_FOREVER;
  1275. }
  1276. result = rt_mutex_take(&(mutex_cb->mutex), timeout);
  1277. if (RT_EOK == result)
  1278. return osOK;
  1279. else if (-RT_ETIMEOUT == result)
  1280. {
  1281. if (0U == timeout)
  1282. return osErrorResource;
  1283. else
  1284. return osErrorTimeout;
  1285. }
  1286. else
  1287. return osError;
  1288. }
  1289. /// Release a Mutex that was acquired by \ref osMutexAcquire.
  1290. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1291. /// \return status code that indicates the execution status of the function.
  1292. osStatus_t osMutexRelease(osMutexId_t mutex_id)
  1293. {
  1294. rt_err_t result;
  1295. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1296. /* Check parameters */
  1297. if (RT_NULL == mutex_cb)
  1298. {
  1299. return osErrorParameter;
  1300. }
  1301. result = rt_mutex_release(&(mutex_cb->mutex));
  1302. if (RT_EOK == result)
  1303. return osOK;
  1304. else
  1305. return osErrorResource;
  1306. }
  1307. /// Get Thread which owns a Mutex object.
  1308. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1309. /// \return thread ID of owner thread or NULL when mutex was not acquired.
  1310. osThreadId_t osMutexGetOwner(osMutexId_t mutex_id)
  1311. {
  1312. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1313. /* Check parameters */
  1314. if ((RT_NULL == mutex_cb) || (rt_object_get_type(&mutex_cb->mutex.parent.parent) != RT_Object_Class_Mutex))
  1315. {
  1316. return RT_NULL;
  1317. }
  1318. return mutex_cb->mutex.owner;
  1319. }
  1320. /// Delete a Mutex object.
  1321. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1322. /// \return status code that indicates the execution status of the function.
  1323. osStatus_t osMutexDelete(osMutexId_t mutex_id)
  1324. {
  1325. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1326. /* Check parameters */
  1327. if (RT_NULL == mutex_cb)
  1328. {
  1329. return osErrorParameter;
  1330. }
  1331. rt_mutex_detach(&(mutex_cb->mutex));
  1332. if (mutex_cb->flags & MALLOC_CB)
  1333. rt_free(mutex_cb);
  1334. return osOK;
  1335. }
  1336. #endif
  1337. #ifdef RT_USING_SEMAPHORE
  1338. osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr)
  1339. {
  1340. char name[RT_NAME_MAX];
  1341. sem_cb_t *sem_cb;
  1342. static rt_uint16_t semaphore_number = 0U;
  1343. /* Check parameters */
  1344. if ((0U == max_count) || (initial_count > max_count))
  1345. {
  1346. return RT_NULL;
  1347. }
  1348. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  1349. {
  1350. rt_snprintf(name, sizeof(name), "sem%02d", semaphore_number++);
  1351. }
  1352. else
  1353. rt_snprintf(name, sizeof(name), "%s", attr->name);
  1354. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  1355. {
  1356. sem_cb = rt_malloc(sizeof(sem_cb_t));
  1357. if (RT_NULL == sem_cb)
  1358. return RT_NULL;
  1359. rt_memset(sem_cb, 0, sizeof(sem_cb_t));
  1360. sem_cb->flags |= MALLOC_CB;
  1361. }
  1362. else
  1363. {
  1364. if (attr->cb_size >= sizeof(sem_cb_t))
  1365. {
  1366. sem_cb = attr->cb_mem;
  1367. sem_cb->flags = 0;
  1368. }
  1369. else
  1370. return RT_NULL;
  1371. }
  1372. rt_sem_init(&(sem_cb->sem), name, initial_count, RT_IPC_FLAG_FIFO);
  1373. return sem_cb;
  1374. }
  1375. /// Get name of a Semaphore object.
  1376. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1377. /// \return name as NULL terminated string.
  1378. const char *osSemaphoreGetName(osSemaphoreId_t semaphore_id)
  1379. {
  1380. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1381. /* Check parameters */
  1382. if ((RT_NULL == sem_cb) || (rt_object_get_type(&sem_cb->sem.parent.parent) != RT_Object_Class_Semaphore))
  1383. {
  1384. return RT_NULL;
  1385. }
  1386. return sem_cb->sem.parent.parent.name;
  1387. }
  1388. /// Acquire a Semaphore token or timeout if no tokens are available.
  1389. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1390. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1391. /// \return status code that indicates the execution status of the function.
  1392. osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout)
  1393. {
  1394. rt_err_t result;
  1395. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1396. /* Check parameters */
  1397. if (RT_NULL == sem_cb)
  1398. {
  1399. return osErrorParameter;
  1400. }
  1401. if(timeout == osWaitForever)
  1402. {
  1403. timeout = RT_WAITING_FOREVER;
  1404. }
  1405. result = rt_sem_take(&(sem_cb->sem), timeout);
  1406. if (RT_EOK == result)
  1407. return osOK;
  1408. else if (-RT_ETIMEOUT == result)
  1409. {
  1410. if (0U == timeout)
  1411. return osErrorResource;
  1412. else
  1413. return osErrorTimeout;
  1414. }
  1415. else
  1416. return osError;
  1417. }
  1418. /// Release a Semaphore token that was acquired by \ref osSemaphoreAcquire.
  1419. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1420. /// \return status code that indicates the execution status of the function.
  1421. osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)
  1422. {
  1423. rt_err_t result;
  1424. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1425. /* Check parameters */
  1426. if (RT_NULL == sem_cb)
  1427. {
  1428. return osErrorParameter;
  1429. }
  1430. result = rt_sem_release(&(sem_cb->sem));
  1431. if (RT_EOK == result)
  1432. return osOK;
  1433. else
  1434. return osError;
  1435. }
  1436. /// Get current Semaphore token count.
  1437. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1438. /// \return number of tokens available.
  1439. uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id)
  1440. {
  1441. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1442. /* Check parameters */
  1443. if ((RT_NULL == sem_cb) || (rt_object_get_type(&sem_cb->sem.parent.parent) != RT_Object_Class_Semaphore))
  1444. {
  1445. return 0U;
  1446. }
  1447. return sem_cb->sem.value;
  1448. }
  1449. /// Delete a Semaphore object.
  1450. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1451. /// \return status code that indicates the execution status of the function.
  1452. osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id)
  1453. {
  1454. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1455. /* Check parameters */
  1456. if (RT_NULL == sem_cb)
  1457. {
  1458. return osErrorParameter;
  1459. }
  1460. rt_sem_detach(&(sem_cb->sem));
  1461. if (sem_cb->flags & MALLOC_CB)
  1462. rt_free(sem_cb);
  1463. return osOK;
  1464. }
  1465. #endif
  1466. #ifdef RT_USING_MEMPOOL
  1467. // ==== Memory Pool Management Functions ====
  1468. /// Create and Initialize a Memory Pool object.
  1469. /// \param[in] block_count maximum number of memory blocks in memory pool.
  1470. /// \param[in] block_size memory block size in bytes.
  1471. /// \param[in] attr memory pool attributes; NULL: default values.
  1472. /// \return memory pool ID for reference by other functions or NULL in case of error.
  1473. osMemoryPoolId_t osMemoryPoolNew(uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr)
  1474. {
  1475. char name[RT_NAME_MAX];
  1476. void *mp_addr;
  1477. rt_uint32_t mp_size;
  1478. mempool_cb_t *mempool_cb;
  1479. static rt_uint16_t memory_pool_number = 0U;
  1480. /* Check parameters */
  1481. if ((0U == block_count) || (0U == block_size))
  1482. {
  1483. return RT_NULL;
  1484. }
  1485. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  1486. {
  1487. rt_snprintf(name, sizeof(name), "mp%02d", memory_pool_number++);
  1488. }
  1489. else
  1490. rt_snprintf(name, sizeof(name), "%s", attr->name);
  1491. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  1492. {
  1493. mempool_cb = rt_malloc(sizeof(mempool_cb_t));
  1494. if (RT_NULL == mempool_cb)
  1495. return RT_NULL;
  1496. rt_memset(mempool_cb, 0, sizeof(mempool_cb_t));
  1497. mempool_cb->flags |= MALLOC_CB;
  1498. }
  1499. else
  1500. {
  1501. if (attr->cb_size >= sizeof(mempool_cb_t))
  1502. {
  1503. mempool_cb = attr->cb_mem;
  1504. mempool_cb->flags = 0;
  1505. }
  1506. else
  1507. return RT_NULL;
  1508. }
  1509. if ((RT_NULL == attr) || (RT_NULL == attr->mp_mem))
  1510. {
  1511. block_size = RT_ALIGN(block_size, RT_ALIGN_SIZE);
  1512. mp_size = (block_size + sizeof(rt_uint8_t *)) * block_count;
  1513. mp_addr = rt_malloc((block_size + sizeof(rt_uint8_t *)) * block_count);
  1514. if (RT_NULL == mp_addr)
  1515. {
  1516. if (mempool_cb->flags & MALLOC_CB)
  1517. rt_free(mempool_cb);
  1518. return RT_NULL;
  1519. }
  1520. mempool_cb->flags |= MALLOC_MEM;
  1521. }
  1522. else
  1523. {
  1524. mp_addr = (void *)(attr->mp_mem);
  1525. mp_size = attr->mp_size;
  1526. }
  1527. rt_mp_init(&(mempool_cb->mp), name, mp_addr, mp_size, block_size);
  1528. return mempool_cb;
  1529. }
  1530. /// Get name of a Memory Pool object.
  1531. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1532. /// \return name as NULL terminated string.
  1533. const char *osMemoryPoolGetName(osMemoryPoolId_t mp_id)
  1534. {
  1535. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1536. /* Check parameters */
  1537. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1538. {
  1539. return RT_NULL;
  1540. }
  1541. return mempool_cb->mp.parent.name;
  1542. }
  1543. /// Allocate a memory block from a Memory Pool.
  1544. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1545. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1546. /// \return address of the allocated memory block or NULL in case of no memory is available.
  1547. void *osMemoryPoolAlloc(osMemoryPoolId_t mp_id, uint32_t timeout)
  1548. {
  1549. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1550. /* Check parameters */
  1551. if (RT_NULL == mempool_cb)
  1552. {
  1553. return RT_NULL;
  1554. }
  1555. if(timeout == osWaitForever)
  1556. {
  1557. timeout = RT_WAITING_FOREVER;
  1558. }
  1559. return rt_mp_alloc(&(mempool_cb->mp), timeout);
  1560. }
  1561. /// Return an allocated memory block back to a Memory Pool.
  1562. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1563. /// \param[in] block address of the allocated memory block to be returned to the memory pool.
  1564. /// \return status code that indicates the execution status of the function.
  1565. osStatus_t osMemoryPoolFree(osMemoryPoolId_t mp_id, void *block)
  1566. {
  1567. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1568. /* Check parameters */
  1569. if (RT_NULL == mempool_cb)
  1570. {
  1571. return osErrorParameter;
  1572. }
  1573. rt_mp_free(block);
  1574. return osOK;
  1575. }
  1576. /// Get maximum number of memory blocks in a Memory Pool.
  1577. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1578. /// \return maximum number of memory blocks.
  1579. uint32_t osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id)
  1580. {
  1581. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1582. /* Check parameters */
  1583. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1584. {
  1585. return 0U;
  1586. }
  1587. return mempool_cb->mp.block_total_count;
  1588. }
  1589. /// Get memory block size in a Memory Pool.
  1590. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1591. /// \return memory block size in bytes.
  1592. uint32_t osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id)
  1593. {
  1594. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1595. /* Check parameters */
  1596. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1597. {
  1598. return 0U;
  1599. }
  1600. return mempool_cb->mp.block_size;
  1601. }
  1602. /// Get number of memory blocks used in a Memory Pool.
  1603. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1604. /// \return number of memory blocks used.
  1605. uint32_t osMemoryPoolGetCount(osMemoryPoolId_t mp_id)
  1606. {
  1607. rt_size_t used_blocks;
  1608. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1609. /* Check parameters */
  1610. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1611. {
  1612. return 0U;
  1613. }
  1614. used_blocks = mempool_cb->mp.block_total_count - mempool_cb->mp.block_free_count;
  1615. return (uint32_t)used_blocks;
  1616. }
  1617. /// Get number of memory blocks available in a Memory Pool.
  1618. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1619. /// \return number of memory blocks available.
  1620. uint32_t osMemoryPoolGetSpace(osMemoryPoolId_t mp_id)
  1621. {
  1622. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1623. /* Check parameters */
  1624. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1625. {
  1626. return 0U;
  1627. }
  1628. return mempool_cb->mp.block_free_count;
  1629. }
  1630. /// Delete a Memory Pool object.
  1631. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1632. /// \return status code that indicates the execution status of the function.
  1633. osStatus_t osMemoryPoolDelete(osMemoryPoolId_t mp_id)
  1634. {
  1635. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1636. /* Check parameters */
  1637. if (RT_NULL == mempool_cb)
  1638. {
  1639. return osErrorParameter;
  1640. }
  1641. rt_mp_detach(&(mempool_cb->mp));
  1642. if (mempool_cb->flags & MALLOC_CB)
  1643. rt_free(mempool_cb);
  1644. if (mempool_cb->flags & MALLOC_MEM)
  1645. rt_free(mempool_cb->mp.start_address);
  1646. return osOK;
  1647. }
  1648. #endif
  1649. #ifdef RT_USING_MESSAGEQUEUE
  1650. // ==== Message Queue Management Functions ====
  1651. /// Create and Initialize a Message Queue object.
  1652. /// \param[in] msg_count maximum number of messages in queue.
  1653. /// \param[in] msg_size maximum message size in bytes.
  1654. /// \param[in] attr message queue attributes; NULL: default values.
  1655. /// \return message queue ID for reference by other functions or NULL in case of error.
  1656. osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr)
  1657. {
  1658. char name[RT_NAME_MAX];
  1659. mq_cb_t *mq_cb;
  1660. void *mq_addr;
  1661. rt_uint32_t mq_size;
  1662. static rt_uint16_t mq_number = 0U;
  1663. /* Check parameters */
  1664. if ((0U == msg_count) || (0U == msg_size))
  1665. {
  1666. return RT_NULL;
  1667. }
  1668. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  1669. {
  1670. rt_snprintf(name, sizeof(name), "mq%02d", mq_number++);
  1671. }
  1672. else
  1673. rt_snprintf(name, sizeof(name), "%s", attr->name);
  1674. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  1675. {
  1676. mq_cb = rt_malloc(sizeof(mq_cb_t));
  1677. if (RT_NULL == mq_cb)
  1678. return RT_NULL;
  1679. rt_memset(mq_cb, 0, sizeof(mq_cb_t));
  1680. mq_cb->flags |= MALLOC_CB;
  1681. }
  1682. else
  1683. {
  1684. if (attr->cb_size >= sizeof(mq_cb_t))
  1685. {
  1686. mq_cb = attr->cb_mem;
  1687. mq_cb->flags = 0;
  1688. }
  1689. else
  1690. return RT_NULL;
  1691. }
  1692. mq_cb->init_msg_size = msg_size;
  1693. if ((RT_NULL == attr) || (RT_NULL == attr->mq_mem))
  1694. {
  1695. register rt_size_t msg_align_size;
  1696. /* get correct message size */
  1697. msg_align_size = RT_ALIGN(msg_size, RT_ALIGN_SIZE);
  1698. mq_size = (msg_align_size + sizeof(struct rt_mq_message)) * msg_count;
  1699. mq_addr = rt_malloc(mq_size);
  1700. if (RT_NULL == mq_addr)
  1701. {
  1702. if (mq_cb->flags & MALLOC_CB)
  1703. rt_free(mq_cb);
  1704. return RT_NULL;
  1705. }
  1706. rt_memset(mq_addr, 0, sizeof(mq_size));
  1707. mq_cb->flags |= MALLOC_MEM;
  1708. }
  1709. else
  1710. {
  1711. mq_addr = (void *)(attr->mq_mem);
  1712. mq_size = attr->mq_size;
  1713. }
  1714. rt_mq_init(&(mq_cb->mq), name, mq_addr, msg_size, mq_size, RT_IPC_FLAG_FIFO);
  1715. return mq_cb;
  1716. }
  1717. /// Get name of a Message Queue object.
  1718. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1719. /// \return name as NULL terminated string.
  1720. const char *osMessageQueueGetName(osMessageQueueId_t mq_id)
  1721. {
  1722. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1723. /* Check parameters */
  1724. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1725. {
  1726. return RT_NULL;
  1727. }
  1728. return mq_cb->mq.parent.parent.name;
  1729. }
  1730. /// Put a Message into a Queue or timeout if Queue is full.
  1731. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1732. /// \param[in] msg_ptr pointer to buffer with message to put into a queue.
  1733. /// \param[in] msg_prio message priority.
  1734. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1735. /// \return status code that indicates the execution status of the function.
  1736. osStatus_t osMessageQueuePut(osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout)
  1737. {
  1738. rt_err_t result;
  1739. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1740. /* Check parameters */
  1741. if (RT_NULL == mq_cb || (RT_NULL == msg_ptr))
  1742. {
  1743. return osErrorParameter;
  1744. }
  1745. if(timeout == osWaitForever)
  1746. {
  1747. timeout = RT_WAITING_FOREVER;
  1748. }
  1749. result = rt_mq_send_wait(&(mq_cb->mq), (void *)msg_ptr, mq_cb->init_msg_size, timeout);
  1750. if (RT_EOK == result)
  1751. return osOK;
  1752. else if (-RT_EFULL == result)
  1753. return osErrorResource;
  1754. else
  1755. return osError;
  1756. }
  1757. /// Get a Message from a Queue or timeout if Queue is empty.
  1758. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1759. /// \param[out] msg_ptr pointer to buffer for message to get from a queue.
  1760. /// \param[out] msg_prio pointer to buffer for message priority or NULL.
  1761. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1762. /// \return status code that indicates the execution status of the function.
  1763. #if defined(RT_VERSION_CHECK) && (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 0, 1))
  1764. osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout)
  1765. {
  1766. rt_ssize_t result = 0;
  1767. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1768. /* Check parameters */
  1769. if (RT_NULL == mq_cb || (RT_NULL == msg_ptr))
  1770. {
  1771. return osErrorParameter;
  1772. }
  1773. if(timeout == osWaitForever)
  1774. {
  1775. timeout = RT_WAITING_FOREVER;
  1776. }
  1777. result = rt_mq_recv(&(mq_cb->mq), msg_ptr, mq_cb->init_msg_size, timeout);
  1778. if (result > 0)
  1779. {
  1780. return osOK;
  1781. }
  1782. else
  1783. {
  1784. return osError;
  1785. }
  1786. }
  1787. #else /* legacy version macros (<5.0.1) */
  1788. osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout)
  1789. {
  1790. rt_err_t result;
  1791. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1792. /* Check parameters */
  1793. if (RT_NULL == mq_cb || (RT_NULL == msg_ptr))
  1794. {
  1795. return osErrorParameter;
  1796. }
  1797. if(timeout == osWaitForever)
  1798. {
  1799. timeout = RT_WAITING_FOREVER;
  1800. }
  1801. result = rt_mq_recv(&(mq_cb->mq), msg_ptr, mq_cb->init_msg_size, timeout);
  1802. if (RT_EOK == result)
  1803. return osOK;
  1804. else if (-RT_ETIMEOUT == result)
  1805. {
  1806. if (0U == timeout)
  1807. return osErrorResource;
  1808. return osErrorTimeout;
  1809. }
  1810. else
  1811. return osError;
  1812. }
  1813. #endif
  1814. /// Get maximum number of messages in a Message Queue.
  1815. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1816. /// \return maximum number of messages.
  1817. uint32_t osMessageQueueGetCapacity(osMessageQueueId_t mq_id)
  1818. {
  1819. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1820. /* Check parameters */
  1821. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1822. {
  1823. return 0U;
  1824. }
  1825. return mq_cb->mq.max_msgs;
  1826. }
  1827. /// Get maximum message size in a Memory Pool.
  1828. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1829. /// \return maximum message size in bytes.
  1830. uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t mq_id)
  1831. {
  1832. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1833. /* Check parameters */;
  1834. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1835. {
  1836. return 0U;
  1837. }
  1838. return mq_cb->mq.msg_size;
  1839. }
  1840. /// Get number of queued messages in a Message Queue.
  1841. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1842. /// \return number of queued messages.
  1843. uint32_t osMessageQueueGetCount(osMessageQueueId_t mq_id)
  1844. {
  1845. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1846. /* Check parameters */;
  1847. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1848. {
  1849. return 0U;
  1850. }
  1851. return mq_cb->mq.entry;
  1852. }
  1853. /// Get number of available slots for messages in a Message Queue.
  1854. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1855. /// \return number of available slots for messages.
  1856. uint32_t osMessageQueueGetSpace(osMessageQueueId_t mq_id)
  1857. {
  1858. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1859. /* Check parameters */;
  1860. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1861. {
  1862. return 0U;
  1863. }
  1864. return (mq_cb->mq.max_msgs - mq_cb->mq.entry);
  1865. }
  1866. /// Reset a Message Queue to initial empty state.
  1867. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1868. /// \return status code that indicates the execution status of the function.
  1869. osStatus_t osMessageQueueReset(osMessageQueueId_t mq_id)
  1870. {
  1871. rt_err_t result;
  1872. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1873. /* Check parameters */;
  1874. if (RT_NULL == mq_cb)
  1875. {
  1876. return osErrorParameter;
  1877. }
  1878. result = rt_mq_control(&(mq_cb->mq), RT_IPC_CMD_RESET, RT_NULL);
  1879. if (RT_EOK == result)
  1880. return osOK;
  1881. else
  1882. return osError;
  1883. }
  1884. /// Delete a Message Queue object.
  1885. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1886. /// \return status code that indicates the execution status of the function.
  1887. osStatus_t osMessageQueueDelete(osMessageQueueId_t mq_id)
  1888. {
  1889. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1890. /* Check parameters */;
  1891. if (RT_NULL == mq_cb)
  1892. {
  1893. return osErrorParameter;
  1894. }
  1895. rt_mq_detach(&(mq_cb->mq));
  1896. if (mq_cb->flags & MALLOC_CB)
  1897. rt_free(mq_cb);
  1898. if (mq_cb->flags & MALLOC_MEM)
  1899. rt_free(mq_cb->mq.msg_pool);
  1900. return osOK;
  1901. }
  1902. #endif