cmsis_rtthread.c 57 KB

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