cmsis_rtthread.c 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294
  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 (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 ((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. result = rt_event_recv(&(event_cb->event), flags, (rt_uint8_t)rt_options, timeout, &rt_recv);
  1163. if (RT_EOK == result)
  1164. return rt_recv;
  1165. else if (-RT_ETIMEOUT == result)
  1166. {
  1167. if (0U == timeout)
  1168. return osFlagsErrorResource;
  1169. else
  1170. return osFlagsErrorTimeout;
  1171. }
  1172. else
  1173. return osFlagsErrorUnknown;
  1174. }
  1175. /// Delete an Event Flags object.
  1176. /// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
  1177. /// \return status code that indicates the execution status of the function.
  1178. osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id)
  1179. {
  1180. event_cb_t *event_cb = (event_cb_t *)ef_id;
  1181. /* Check parameters */
  1182. if (RT_NULL == event_cb)
  1183. {
  1184. return osErrorParameter;
  1185. }
  1186. rt_event_detach(&(event_cb->event));
  1187. if (event_cb->flags & MALLOC_CB)
  1188. rt_free(event_cb);
  1189. return osOK;
  1190. }
  1191. #endif
  1192. #ifdef RT_USING_MUTEX
  1193. // ==== Mutex Management Functions ====
  1194. /// Create and Initialize a Mutex object.
  1195. /// \param[in] attr mutex attributes; NULL: default values.
  1196. /// \return mutex ID for reference by other functions or NULL in case of error.
  1197. osMutexId_t osMutexNew(const osMutexAttr_t *attr)
  1198. {
  1199. char name[RT_NAME_MAX];
  1200. mutex_cb_t *mutex_cb;
  1201. static rt_uint16_t mutex_number = 0U;
  1202. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  1203. {
  1204. rt_snprintf(name, sizeof(name), "mutex%02d", mutex_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. mutex_cb = rt_malloc(sizeof(mutex_cb_t));
  1211. if (RT_NULL == mutex_cb)
  1212. return RT_NULL;
  1213. rt_memset(mutex_cb, 0, sizeof(mutex_cb_t));
  1214. mutex_cb->flags |= MALLOC_CB;
  1215. }
  1216. else
  1217. {
  1218. if (attr->cb_size >= sizeof(mutex_cb_t))
  1219. {
  1220. mutex_cb = attr->cb_mem;
  1221. mutex_cb->flags = 0;
  1222. }
  1223. else
  1224. return RT_NULL;
  1225. }
  1226. if ((RT_NULL == attr) || (0 == attr->attr_bits))
  1227. {
  1228. mutex_cb->flags |= osMutexRecursive;
  1229. }
  1230. else
  1231. mutex_cb->flags |= attr->attr_bits;
  1232. rt_mutex_init(&(mutex_cb->mutex), name, RT_IPC_FLAG_FIFO);
  1233. return mutex_cb;
  1234. }
  1235. /// Get name of a Mutex object.
  1236. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1237. /// \return name as NULL terminated string.
  1238. const char *osMutexGetName(osMutexId_t mutex_id)
  1239. {
  1240. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1241. /* Check parameters */
  1242. if ((RT_NULL == mutex_cb) || (rt_object_get_type(&mutex_cb->mutex.parent.parent) != RT_Object_Class_Mutex))
  1243. {
  1244. return RT_NULL;
  1245. }
  1246. return mutex_cb->mutex.parent.parent.name;
  1247. }
  1248. /// Acquire a Mutex or timeout if it is locked.
  1249. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1250. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1251. /// \return status code that indicates the execution status of the function.
  1252. osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout)
  1253. {
  1254. rt_err_t result;
  1255. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1256. /* Check parameters */
  1257. if (RT_NULL == mutex_cb)
  1258. {
  1259. return osErrorParameter;
  1260. }
  1261. rt_enter_critical();
  1262. if ((mutex_cb->mutex.owner == rt_thread_self()) && !(mutex_cb->flags & osMutexRecursive))
  1263. {
  1264. rt_exit_critical();
  1265. return osError;
  1266. }
  1267. rt_exit_critical();
  1268. result = rt_mutex_take(&(mutex_cb->mutex), timeout);
  1269. if (RT_EOK == result)
  1270. return osOK;
  1271. else if (-RT_ETIMEOUT == result)
  1272. {
  1273. if (0U == timeout)
  1274. return osErrorResource;
  1275. else
  1276. return osErrorTimeout;
  1277. }
  1278. else
  1279. return osError;
  1280. }
  1281. /// Release a Mutex that was acquired by \ref osMutexAcquire.
  1282. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1283. /// \return status code that indicates the execution status of the function.
  1284. osStatus_t osMutexRelease(osMutexId_t mutex_id)
  1285. {
  1286. rt_err_t result;
  1287. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1288. /* Check parameters */
  1289. if (RT_NULL == mutex_cb)
  1290. {
  1291. return osErrorParameter;
  1292. }
  1293. result = rt_mutex_release(&(mutex_cb->mutex));
  1294. if (RT_EOK == result)
  1295. return osOK;
  1296. else
  1297. return osErrorResource;
  1298. }
  1299. /// Get Thread which owns a Mutex object.
  1300. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1301. /// \return thread ID of owner thread or NULL when mutex was not acquired.
  1302. osThreadId_t osMutexGetOwner(osMutexId_t mutex_id)
  1303. {
  1304. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1305. /* Check parameters */
  1306. if ((RT_NULL == mutex_cb) || (rt_object_get_type(&mutex_cb->mutex.parent.parent) != RT_Object_Class_Mutex))
  1307. {
  1308. return RT_NULL;
  1309. }
  1310. return mutex_cb->mutex.owner;
  1311. }
  1312. /// Delete a Mutex object.
  1313. /// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
  1314. /// \return status code that indicates the execution status of the function.
  1315. osStatus_t osMutexDelete(osMutexId_t mutex_id)
  1316. {
  1317. mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id;
  1318. /* Check parameters */
  1319. if (RT_NULL == mutex_cb)
  1320. {
  1321. return osErrorParameter;
  1322. }
  1323. rt_mutex_detach(&(mutex_cb->mutex));
  1324. if (mutex_cb->flags & MALLOC_CB)
  1325. rt_free(mutex_cb);
  1326. return osOK;
  1327. }
  1328. #endif
  1329. #ifdef RT_USING_SEMAPHORE
  1330. osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr)
  1331. {
  1332. char name[RT_NAME_MAX];
  1333. sem_cb_t *sem_cb;
  1334. static rt_uint16_t semaphore_number = 0U;
  1335. /* Check parameters */
  1336. if ((0U == max_count) || (initial_count > max_count))
  1337. {
  1338. return RT_NULL;
  1339. }
  1340. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  1341. {
  1342. rt_snprintf(name, sizeof(name), "sem%02d", semaphore_number++);
  1343. }
  1344. else
  1345. rt_snprintf(name, sizeof(name), "%s", attr->name);
  1346. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  1347. {
  1348. sem_cb = rt_malloc(sizeof(sem_cb_t));
  1349. if (RT_NULL == sem_cb)
  1350. return RT_NULL;
  1351. rt_memset(sem_cb, 0, sizeof(sem_cb_t));
  1352. sem_cb->flags |= MALLOC_CB;
  1353. }
  1354. else
  1355. {
  1356. if (attr->cb_size >= sizeof(sem_cb_t))
  1357. {
  1358. sem_cb = attr->cb_mem;
  1359. sem_cb->flags = 0;
  1360. }
  1361. else
  1362. return RT_NULL;
  1363. }
  1364. rt_sem_init(&(sem_cb->sem), name, initial_count, RT_IPC_FLAG_FIFO);
  1365. return sem_cb;
  1366. }
  1367. /// Get name of a Semaphore object.
  1368. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1369. /// \return name as NULL terminated string.
  1370. const char *osSemaphoreGetName(osSemaphoreId_t semaphore_id)
  1371. {
  1372. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1373. /* Check parameters */
  1374. if ((RT_NULL == sem_cb) || (rt_object_get_type(&sem_cb->sem.parent.parent) != RT_Object_Class_Semaphore))
  1375. {
  1376. return RT_NULL;
  1377. }
  1378. return sem_cb->sem.parent.parent.name;
  1379. }
  1380. /// Acquire a Semaphore token or timeout if no tokens are available.
  1381. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1382. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1383. /// \return status code that indicates the execution status of the function.
  1384. osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout)
  1385. {
  1386. rt_err_t result;
  1387. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1388. /* Check parameters */
  1389. if (RT_NULL == sem_cb)
  1390. {
  1391. return osErrorParameter;
  1392. }
  1393. result = rt_sem_take(&(sem_cb->sem), timeout);
  1394. if (RT_EOK == result)
  1395. return osOK;
  1396. else if (-RT_ETIMEOUT == result)
  1397. {
  1398. if (0U == timeout)
  1399. return osErrorResource;
  1400. else
  1401. return osErrorTimeout;
  1402. }
  1403. else
  1404. return osError;
  1405. }
  1406. /// Release a Semaphore token that was acquired by \ref osSemaphoreAcquire.
  1407. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1408. /// \return status code that indicates the execution status of the function.
  1409. osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)
  1410. {
  1411. rt_err_t result;
  1412. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1413. /* Check parameters */
  1414. if (RT_NULL == sem_cb)
  1415. {
  1416. return osErrorParameter;
  1417. }
  1418. result = rt_sem_release(&(sem_cb->sem));
  1419. if (RT_EOK == result)
  1420. return osOK;
  1421. else
  1422. return osError;
  1423. }
  1424. /// Get current Semaphore token count.
  1425. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1426. /// \return number of tokens available.
  1427. uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id)
  1428. {
  1429. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1430. /* Check parameters */
  1431. if ((RT_NULL == sem_cb) || (rt_object_get_type(&sem_cb->sem.parent.parent) != RT_Object_Class_Semaphore))
  1432. {
  1433. return 0U;
  1434. }
  1435. return sem_cb->sem.value;
  1436. }
  1437. /// Delete a Semaphore object.
  1438. /// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
  1439. /// \return status code that indicates the execution status of the function.
  1440. osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id)
  1441. {
  1442. sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id;
  1443. /* Check parameters */
  1444. if (RT_NULL == sem_cb)
  1445. {
  1446. return osErrorParameter;
  1447. }
  1448. rt_sem_detach(&(sem_cb->sem));
  1449. if (sem_cb->flags & MALLOC_CB)
  1450. rt_free(sem_cb);
  1451. return osOK;
  1452. }
  1453. #endif
  1454. #ifdef RT_USING_MEMPOOL
  1455. // ==== Memory Pool Management Functions ====
  1456. /// Create and Initialize a Memory Pool object.
  1457. /// \param[in] block_count maximum number of memory blocks in memory pool.
  1458. /// \param[in] block_size memory block size in bytes.
  1459. /// \param[in] attr memory pool attributes; NULL: default values.
  1460. /// \return memory pool ID for reference by other functions or NULL in case of error.
  1461. osMemoryPoolId_t osMemoryPoolNew(uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr)
  1462. {
  1463. char name[RT_NAME_MAX];
  1464. void *mp_addr;
  1465. rt_uint32_t mp_size;
  1466. mempool_cb_t *mempool_cb;
  1467. static rt_uint16_t memory_pool_number = 0U;
  1468. /* Check parameters */
  1469. if ((0U == block_count) || (0U == block_size))
  1470. {
  1471. return RT_NULL;
  1472. }
  1473. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  1474. {
  1475. rt_snprintf(name, sizeof(name), "mp%02d", memory_pool_number++);
  1476. }
  1477. else
  1478. rt_snprintf(name, sizeof(name), "%s", attr->name);
  1479. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  1480. {
  1481. mempool_cb = rt_malloc(sizeof(mempool_cb_t));
  1482. if (RT_NULL == mempool_cb)
  1483. return RT_NULL;
  1484. rt_memset(mempool_cb, 0, sizeof(mempool_cb_t));
  1485. mempool_cb->flags |= MALLOC_CB;
  1486. }
  1487. else
  1488. {
  1489. if (attr->cb_size >= sizeof(mempool_cb_t))
  1490. {
  1491. mempool_cb = attr->cb_mem;
  1492. mempool_cb->flags = 0;
  1493. }
  1494. else
  1495. return RT_NULL;
  1496. }
  1497. if ((RT_NULL == attr) || (RT_NULL == attr->mp_mem))
  1498. {
  1499. block_size = RT_ALIGN(block_size, RT_ALIGN_SIZE);
  1500. mp_size = (block_size + sizeof(rt_uint8_t *)) * block_count;
  1501. mp_addr = rt_malloc((block_size + sizeof(rt_uint8_t *)) * block_count);
  1502. if (RT_NULL == mp_addr)
  1503. {
  1504. if (mempool_cb->flags & MALLOC_CB)
  1505. rt_free(mempool_cb);
  1506. return RT_NULL;
  1507. }
  1508. mempool_cb->flags |= MALLOC_MEM;
  1509. }
  1510. else
  1511. {
  1512. mp_addr = (void *)(attr->mp_mem);
  1513. mp_size = attr->mp_size;
  1514. }
  1515. rt_mp_init(&(mempool_cb->mp), name, mp_addr, mp_size, block_size);
  1516. return mempool_cb;
  1517. }
  1518. /// Get name of a Memory Pool object.
  1519. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1520. /// \return name as NULL terminated string.
  1521. const char *osMemoryPoolGetName(osMemoryPoolId_t mp_id)
  1522. {
  1523. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1524. /* Check parameters */
  1525. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1526. {
  1527. return RT_NULL;
  1528. }
  1529. return mempool_cb->mp.parent.name;
  1530. }
  1531. /// Allocate a memory block from a Memory Pool.
  1532. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1533. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1534. /// \return address of the allocated memory block or NULL in case of no memory is available.
  1535. void *osMemoryPoolAlloc(osMemoryPoolId_t mp_id, uint32_t timeout)
  1536. {
  1537. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1538. /* Check parameters */
  1539. if (RT_NULL == mempool_cb)
  1540. {
  1541. return RT_NULL;
  1542. }
  1543. return rt_mp_alloc(&(mempool_cb->mp), timeout);
  1544. }
  1545. /// Return an allocated memory block back to a Memory Pool.
  1546. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1547. /// \param[in] block address of the allocated memory block to be returned to the memory pool.
  1548. /// \return status code that indicates the execution status of the function.
  1549. osStatus_t osMemoryPoolFree(osMemoryPoolId_t mp_id, void *block)
  1550. {
  1551. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1552. /* Check parameters */
  1553. if (RT_NULL == mempool_cb)
  1554. {
  1555. return osErrorParameter;
  1556. }
  1557. rt_mp_free(block);
  1558. return osOK;
  1559. }
  1560. /// Get maximum number of memory blocks in a Memory Pool.
  1561. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1562. /// \return maximum number of memory blocks.
  1563. uint32_t osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id)
  1564. {
  1565. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1566. /* Check parameters */
  1567. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1568. {
  1569. return 0U;
  1570. }
  1571. return mempool_cb->mp.block_total_count;
  1572. }
  1573. /// Get memory block size in a Memory Pool.
  1574. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1575. /// \return memory block size in bytes.
  1576. uint32_t osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id)
  1577. {
  1578. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1579. /* Check parameters */
  1580. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1581. {
  1582. return 0U;
  1583. }
  1584. return mempool_cb->mp.block_size;
  1585. }
  1586. /// Get number of memory blocks used in a Memory Pool.
  1587. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1588. /// \return number of memory blocks used.
  1589. uint32_t osMemoryPoolGetCount(osMemoryPoolId_t mp_id)
  1590. {
  1591. rt_size_t used_blocks;
  1592. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1593. /* Check parameters */
  1594. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1595. {
  1596. return 0U;
  1597. }
  1598. used_blocks = mempool_cb->mp.block_total_count - mempool_cb->mp.block_free_count;
  1599. return (uint32_t)used_blocks;
  1600. }
  1601. /// Get number of memory blocks available in a Memory Pool.
  1602. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1603. /// \return number of memory blocks available.
  1604. uint32_t osMemoryPoolGetSpace(osMemoryPoolId_t mp_id)
  1605. {
  1606. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1607. /* Check parameters */
  1608. if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool))
  1609. {
  1610. return 0U;
  1611. }
  1612. return mempool_cb->mp.block_free_count;
  1613. }
  1614. /// Delete a Memory Pool object.
  1615. /// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
  1616. /// \return status code that indicates the execution status of the function.
  1617. osStatus_t osMemoryPoolDelete(osMemoryPoolId_t mp_id)
  1618. {
  1619. mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id;
  1620. /* Check parameters */
  1621. if (RT_NULL == mempool_cb)
  1622. {
  1623. return osErrorParameter;
  1624. }
  1625. rt_mp_detach(&(mempool_cb->mp));
  1626. if (mempool_cb->flags & MALLOC_CB)
  1627. rt_free(mempool_cb);
  1628. if (mempool_cb->flags & MALLOC_MEM)
  1629. rt_free(mempool_cb->mp.start_address);
  1630. return osOK;
  1631. }
  1632. #endif
  1633. #ifdef RT_USING_MESSAGEQUEUE
  1634. // ==== Message Queue Management Functions ====
  1635. /// Create and Initialize a Message Queue object.
  1636. /// \param[in] msg_count maximum number of messages in queue.
  1637. /// \param[in] msg_size maximum message size in bytes.
  1638. /// \param[in] attr message queue attributes; NULL: default values.
  1639. /// \return message queue ID for reference by other functions or NULL in case of error.
  1640. osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr)
  1641. {
  1642. char name[RT_NAME_MAX];
  1643. mq_cb_t *mq_cb;
  1644. void *mq_addr;
  1645. rt_uint32_t mq_size;
  1646. static rt_uint16_t mq_number = 0U;
  1647. /* Check parameters */
  1648. if ((0U == msg_count) || (0U == msg_size))
  1649. {
  1650. return RT_NULL;
  1651. }
  1652. if ((RT_NULL == attr) || (RT_NULL == attr->name))
  1653. {
  1654. rt_snprintf(name, sizeof(name), "mq%02d", mq_number++);
  1655. }
  1656. else
  1657. rt_snprintf(name, sizeof(name), "%s", attr->name);
  1658. if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem))
  1659. {
  1660. mq_cb = rt_malloc(sizeof(mq_cb_t));
  1661. if (RT_NULL == mq_cb)
  1662. return RT_NULL;
  1663. rt_memset(mq_cb, 0, sizeof(mq_cb_t));
  1664. mq_cb->flags |= MALLOC_CB;
  1665. }
  1666. else
  1667. {
  1668. if (attr->cb_size >= sizeof(mq_cb_t))
  1669. {
  1670. mq_cb = attr->cb_mem;
  1671. mq_cb->flags = 0;
  1672. }
  1673. else
  1674. return RT_NULL;
  1675. }
  1676. mq_cb->init_msg_size = msg_size;
  1677. if ((RT_NULL == attr) || (RT_NULL == attr->mq_mem))
  1678. {
  1679. register rt_size_t msg_align_size;
  1680. /* get correct message size */
  1681. msg_align_size = RT_ALIGN(msg_size, RT_ALIGN_SIZE);
  1682. mq_size = (msg_align_size + sizeof(struct rt_mq_message)) * msg_count;
  1683. mq_addr = rt_malloc(mq_size);
  1684. if (RT_NULL == mq_addr)
  1685. {
  1686. if (mq_cb->flags & MALLOC_CB)
  1687. rt_free(mq_cb);
  1688. return RT_NULL;
  1689. }
  1690. rt_memset(mq_addr, 0, sizeof(mq_size));
  1691. mq_cb->flags |= MALLOC_MEM;
  1692. }
  1693. else
  1694. {
  1695. mq_addr = (void *)(attr->mq_mem);
  1696. mq_size = attr->mq_size;
  1697. }
  1698. rt_mq_init(&(mq_cb->mq), name, mq_addr, msg_size, mq_size, RT_IPC_FLAG_FIFO);
  1699. return mq_cb;
  1700. }
  1701. /// Get name of a Message Queue object.
  1702. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1703. /// \return name as NULL terminated string.
  1704. const char *osMessageQueueGetName(osMessageQueueId_t mq_id)
  1705. {
  1706. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1707. /* Check parameters */
  1708. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1709. {
  1710. return RT_NULL;
  1711. }
  1712. return mq_cb->mq.parent.parent.name;
  1713. }
  1714. /// Put a Message into a Queue or timeout if Queue is full.
  1715. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1716. /// \param[in] msg_ptr pointer to buffer with message to put into a queue.
  1717. /// \param[in] msg_prio message priority.
  1718. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1719. /// \return status code that indicates the execution status of the function.
  1720. osStatus_t osMessageQueuePut(osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout)
  1721. {
  1722. rt_err_t result;
  1723. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1724. /* Check parameters */
  1725. if (RT_NULL == mq_cb || (RT_NULL == msg_ptr))
  1726. {
  1727. return osErrorParameter;
  1728. }
  1729. result = rt_mq_send(&(mq_cb->mq), (void *)msg_ptr, mq_cb->init_msg_size);
  1730. if (RT_EOK == result)
  1731. return osOK;
  1732. else if (-RT_EFULL == result)
  1733. return osErrorResource;
  1734. else
  1735. return osError;
  1736. }
  1737. /// Get a Message from a Queue or timeout if Queue is empty.
  1738. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1739. /// \param[out] msg_ptr pointer to buffer for message to get from a queue.
  1740. /// \param[out] msg_prio pointer to buffer for message priority or NULL.
  1741. /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
  1742. /// \return status code that indicates the execution status of the function.
  1743. #if defined(RT_VERSION_CHECK) && (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 0, 1))
  1744. osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout)
  1745. {
  1746. rt_ssize_t result = 0;
  1747. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1748. /* Check parameters */
  1749. if (RT_NULL == mq_cb || (RT_NULL == msg_ptr))
  1750. {
  1751. return osErrorParameter;
  1752. }
  1753. result = rt_mq_recv(&(mq_cb->mq), msg_ptr, mq_cb->init_msg_size, timeout);
  1754. if (result > 0)
  1755. {
  1756. return osOK;
  1757. }
  1758. else
  1759. {
  1760. return osError;
  1761. }
  1762. }
  1763. #else /* legacy version macros (<5.0.1) */
  1764. osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout)
  1765. {
  1766. rt_err_t result;
  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. result = rt_mq_recv(&(mq_cb->mq), msg_ptr, mq_cb->init_msg_size, timeout);
  1774. if (RT_EOK == result)
  1775. return osOK;
  1776. else if (-RT_ETIMEOUT == result)
  1777. {
  1778. if (0U == timeout)
  1779. return osErrorResource;
  1780. return osErrorTimeout;
  1781. }
  1782. else
  1783. return osError;
  1784. }
  1785. #endif
  1786. /// Get maximum number of messages in a Message Queue.
  1787. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1788. /// \return maximum number of messages.
  1789. uint32_t osMessageQueueGetCapacity(osMessageQueueId_t mq_id)
  1790. {
  1791. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1792. /* Check parameters */
  1793. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1794. {
  1795. return 0U;
  1796. }
  1797. return mq_cb->mq.max_msgs;
  1798. }
  1799. /// Get maximum message size in a Memory Pool.
  1800. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1801. /// \return maximum message size in bytes.
  1802. uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t mq_id)
  1803. {
  1804. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1805. /* Check parameters */;
  1806. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1807. {
  1808. return 0U;
  1809. }
  1810. return mq_cb->mq.msg_size;
  1811. }
  1812. /// Get number of queued messages in a Message Queue.
  1813. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1814. /// \return number of queued messages.
  1815. uint32_t osMessageQueueGetCount(osMessageQueueId_t mq_id)
  1816. {
  1817. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1818. /* Check parameters */;
  1819. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1820. {
  1821. return 0U;
  1822. }
  1823. return mq_cb->mq.entry;
  1824. }
  1825. /// Get number of available slots for messages in a Message Queue.
  1826. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1827. /// \return number of available slots for messages.
  1828. uint32_t osMessageQueueGetSpace(osMessageQueueId_t mq_id)
  1829. {
  1830. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1831. /* Check parameters */;
  1832. if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue))
  1833. {
  1834. return 0U;
  1835. }
  1836. return (mq_cb->mq.max_msgs - mq_cb->mq.entry);
  1837. }
  1838. /// Reset a Message Queue to initial empty state.
  1839. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1840. /// \return status code that indicates the execution status of the function.
  1841. osStatus_t osMessageQueueReset(osMessageQueueId_t mq_id)
  1842. {
  1843. rt_err_t result;
  1844. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1845. /* Check parameters */;
  1846. if (RT_NULL == mq_cb)
  1847. {
  1848. return osErrorParameter;
  1849. }
  1850. result = rt_mq_control(&(mq_cb->mq), RT_IPC_CMD_RESET, RT_NULL);
  1851. if (RT_EOK == result)
  1852. return osOK;
  1853. else
  1854. return osError;
  1855. }
  1856. /// Delete a Message Queue object.
  1857. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew.
  1858. /// \return status code that indicates the execution status of the function.
  1859. osStatus_t osMessageQueueDelete(osMessageQueueId_t mq_id)
  1860. {
  1861. mq_cb_t *mq_cb = (mq_cb_t *)mq_id;
  1862. /* Check parameters */;
  1863. if (RT_NULL == mq_cb)
  1864. {
  1865. return osErrorParameter;
  1866. }
  1867. rt_mq_detach(&(mq_cb->mq));
  1868. if (mq_cb->flags & MALLOC_CB)
  1869. rt_free(mq_cb);
  1870. if (mq_cb->flags & MALLOC_MEM)
  1871. rt_free(mq_cb->mq.msg_pool);
  1872. return osOK;
  1873. }
  1874. #endif