cmsis_rtthread.c 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558
  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. * 2022-04-27 tyustli The first version
  9. */
  10. #include <rtthread.h>
  11. #include "cmsis_os.h"
  12. #define DEFAULT_TICK (5)
  13. #define DEFAULT_THREAD_STACK_SIZE (512)
  14. #define CMSIS_MEM_ALLOC(_size) rt_malloc(_size)
  15. #define CMSIS_MEM_FREE(_ptr) rt_free(_ptr)
  16. /* cmsis to rt-thread priority map */
  17. static const rt_uint8_t priorityArrayMap[7] =
  18. {
  19. RT_THREAD_PRIORITY_MAX - 1,
  20. RT_THREAD_PRIORITY_MAX - 1 - (RT_THREAD_PRIORITY_MAX / 6),
  21. RT_THREAD_PRIORITY_MAX - 1 - (RT_THREAD_PRIORITY_MAX / 3),
  22. RT_THREAD_PRIORITY_MAX / 2,
  23. RT_THREAD_PRIORITY_MAX / 3,
  24. RT_THREAD_PRIORITY_MAX / 6,
  25. 0,
  26. };
  27. /* Convert from CMSIS type osPriority to RT-Thread priority number */
  28. static rt_uint8_t makeRttPriority(osPriority priority)
  29. {
  30. rt_uint8_t rttPriority = RT_THREAD_PRIORITY_MAX;
  31. switch (priority)
  32. {
  33. case osPriorityIdle:
  34. rttPriority = priorityArrayMap[0];
  35. break;
  36. case osPriorityLow:
  37. rttPriority = priorityArrayMap[1];
  38. break;
  39. case osPriorityBelowNormal:
  40. rttPriority = priorityArrayMap[2];
  41. break;
  42. case osPriorityNormal:
  43. rttPriority = priorityArrayMap[3];
  44. break;
  45. case osPriorityAboveNormal:
  46. rttPriority = priorityArrayMap[4];
  47. break;
  48. case osPriorityHigh:
  49. rttPriority = priorityArrayMap[5];
  50. break;
  51. case osPriorityRealtime:
  52. rttPriority = priorityArrayMap[6];
  53. break;
  54. default:
  55. break;
  56. }
  57. return rttPriority;
  58. }
  59. /* Convert from RT-Thread priority number to CMSIS type osPriority */
  60. static osPriority makeCmsisPriority(rt_uint8_t rttPriority)
  61. {
  62. osPriority priority = osPriorityError;
  63. if (rttPriority == priorityArrayMap[0])
  64. priority = osPriorityIdle;
  65. else if (rttPriority == priorityArrayMap[1])
  66. priority = osPriorityLow;
  67. else if (rttPriority == priorityArrayMap[2])
  68. priority = osPriorityBelowNormal;
  69. else if (rttPriority == priorityArrayMap[3])
  70. priority = osPriorityNormal;
  71. else if (rttPriority == priorityArrayMap[4])
  72. priority = osPriorityAboveNormal;
  73. else if (rttPriority == priorityArrayMap[5])
  74. priority = osPriorityHigh;
  75. else if (rttPriority == priorityArrayMap[6])
  76. rttPriority = osPriorityRealtime;
  77. return priority;
  78. }
  79. /* Determine whether we are in thread mode or handler mode. */
  80. static int inHandlerMode(void)
  81. {
  82. return rt_interrupt_get_nest() != 0;
  83. }
  84. /*********************** Kernel Control Functions *****************************/
  85. /**
  86. * @brief Initialize the RTOS Kernel for creating objects.
  87. * @retval status code that indicates the execution status of the function.
  88. * @note MUST REMAIN UNCHANGED: \b osKernelInitialize shall be consistent in every CMSIS-RTOS.
  89. */
  90. osStatus osKernelInitialize(void)
  91. {
  92. return osOK;
  93. }
  94. /**
  95. * @brief Start the RTOS Kernel with executing the specified thread.
  96. * @param thread_def thread definition referenced with \ref osThread.
  97. * @param argument pointer that is passed to the thread function as start argument.
  98. * @retval status code that indicates the execution status of the function
  99. * @note MUST REMAIN UNCHANGED: \b osKernelStart shall be consistent in every CMSIS-RTOS.
  100. */
  101. osStatus osKernelStart(void)
  102. {
  103. /* Cannot be called from Interrupt Service Routines */
  104. if (inHandlerMode())
  105. return osErrorISR;
  106. return osOK;
  107. }
  108. /**
  109. * @brief Check if the RTOS kernel is already started
  110. * @param None
  111. * @retval (0) RTOS is not started
  112. * (1) RTOS is started
  113. * @note MUST REMAIN UNCHANGED: \b osKernelRunning shall be consistent in every CMSIS-RTOS.
  114. */
  115. int32_t osKernelRunning(void)
  116. {
  117. if (rt_thread_self())
  118. return 1;
  119. else
  120. return 0;
  121. }
  122. /**
  123. * @brief Get the value of the Kernel SysTick timer
  124. * @param None
  125. * @retval None
  126. * @note MUST REMAIN UNCHANGED: \b osKernelSysTick shall be consistent in every CMSIS-RTOS.
  127. */
  128. uint32_t osKernelSysTick(void)
  129. {
  130. /* Cannot be called from Interrupt Service Routines */
  131. if (inHandlerMode())
  132. return 0;
  133. return rt_tick_get();
  134. }
  135. /*********************** Thread Management *****************************/
  136. typedef struct os_thread_cb
  137. {
  138. rt_thread_t thread_id;
  139. rt_event_t event_id;
  140. } os_thread_cb_t;
  141. static void thread_cleanup(struct rt_thread *tid)
  142. {
  143. if (tid->user_data)
  144. {
  145. /* delete event */
  146. rt_event_delete(((struct os_thread_cb *)(tid->user_data))->event_id);
  147. /* free mem */
  148. CMSIS_MEM_FREE((void *)(tid->user_data));
  149. tid->user_data = RT_NULL;
  150. }
  151. }
  152. /**
  153. * @brief Create a thread and add it to Active Threads and set it to state READY.
  154. * @param thread_def thread definition referenced with \ref osThread.
  155. * @param argument pointer that is passed to the thread function as start argument.
  156. * @retval thread ID for reference by other functions or NULL in case of error.
  157. * @note MUST REMAIN UNCHANGED: \b osThreadCreate shall be consistent in every CMSIS-RTOS.
  158. */
  159. osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument)
  160. {
  161. static rt_uint8_t thread_number = 0;
  162. char name[RT_NAME_MAX];
  163. rt_uint8_t rttPriority = 0;
  164. rt_uint32_t stack_size = 0;
  165. void (*entry)(void *parameter);
  166. os_thread_cb_t *thread_cb = RT_NULL;
  167. /* Cannot be called from Interrupt Service Routines */
  168. if (inHandlerMode())
  169. goto thread_create_failed;
  170. if (RT_NULL == thread_def || RT_NULL == thread_def->pthread)
  171. goto thread_create_failed;
  172. rt_snprintf(name, sizeof(name), "thread%02d", thread_number++); /* thread name */
  173. rttPriority = makeRttPriority(thread_def->tpriority); /* thread priority */
  174. entry = (void (*)(void *parameter))(thread_def->pthread); /* thread entry */
  175. stack_size = thread_def->stacksize; /* thread stack size */
  176. if (0 == thread_def->stacksize)
  177. stack_size = DEFAULT_THREAD_STACK_SIZE;
  178. thread_cb = (void *)CMSIS_MEM_ALLOC(sizeof(struct os_thread_cb));
  179. if (RT_NULL == thread_cb)
  180. goto thread_create_failed;
  181. thread_cb->thread_id = rt_thread_create(name,
  182. entry,
  183. argument,
  184. stack_size,
  185. rttPriority,
  186. DEFAULT_TICK);
  187. thread_cb->event_id = rt_event_create(name, RT_IPC_FLAG_PRIO);
  188. if (RT_NULL == thread_cb->thread_id || RT_NULL == thread_cb->event_id)
  189. goto thread_create_failed;
  190. thread_cb->thread_id->user_data = (rt_ubase_t)thread_cb;
  191. thread_cb->thread_id->cleanup = thread_cleanup; /* when thread done. event and mem must be free */
  192. /* start thread */
  193. rt_thread_startup(thread_cb->thread_id);
  194. return thread_cb;
  195. thread_create_failed:
  196. rt_kprintf("CMSIS RTOS1 %s failed\r\n", __func__);
  197. if (thread_cb)
  198. {
  199. if (thread_cb->thread_id)
  200. rt_thread_delete(thread_cb->thread_id);
  201. if (thread_cb->event_id)
  202. rt_event_delete(thread_cb->event_id);
  203. CMSIS_MEM_FREE(thread_cb);
  204. }
  205. return RT_NULL;
  206. }
  207. osStatus osThreadTerminate(osThreadId thread_id)
  208. {
  209. rt_err_t result;
  210. osStatus status;
  211. rt_thread_t thread;
  212. /* thread_id is incorrect */
  213. if (RT_NULL == thread_id)
  214. {
  215. status = osErrorParameter;
  216. goto thread_terminate_error;
  217. }
  218. thread = thread_id->thread_id;
  219. /* thread_id refers to a thread that is not an active thread. thread maybe done or has terminated*/
  220. if (rt_object_get_type((rt_object_t)thread) != RT_Object_Class_Thread)
  221. {
  222. status = osErrorResource;
  223. goto thread_terminate_error;
  224. }
  225. /* Cannot be called from Interrupt Service Routines */
  226. if (inHandlerMode())
  227. {
  228. status = osErrorISR;
  229. goto thread_terminate_error;
  230. }
  231. result = rt_thread_control(thread, RT_THREAD_CTRL_CLOSE, RT_NULL);
  232. if (result != RT_EOK)
  233. {
  234. status = osErrorOS;
  235. goto thread_terminate_error;
  236. }
  237. return osOK;
  238. thread_terminate_error:
  239. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
  240. return status;
  241. }
  242. /**
  243. * @brief Pass control to next thread that is in state \b READY.
  244. * @retval status code that indicates the execution status of the function.
  245. * @note MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every CMSIS-RTOS.
  246. */
  247. osStatus osThreadYield(void)
  248. {
  249. /* Cannot be called from Interrupt Service Routines */
  250. if (inHandlerMode())
  251. return osErrorISR;
  252. rt_thread_yield();
  253. return osOK;
  254. }
  255. /**
  256. * @brief Return the thread ID of the current running thread.
  257. * @retval thread ID for reference by other functions or NULL in case of error.
  258. * @note MUST REMAIN UNCHANGED: \b osThreadGetId shall be consistent in every CMSIS-RTOS.
  259. */
  260. osThreadId osThreadGetId(void)
  261. {
  262. rt_thread_t thread;
  263. /* Cannot be called from Interrupt Service Routines */
  264. if (inHandlerMode())
  265. return RT_NULL;
  266. thread = rt_thread_self();
  267. return (osThreadId)(thread->user_data);
  268. }
  269. /**
  270. * @brief Change priority of an active thread.
  271. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
  272. * @param priority new priority value for the thread function.
  273. * @retval status code that indicates the execution status of the function.
  274. * @note MUST REMAIN UNCHANGED: \b osThreadSetPriority shall be consistent in every CMSIS-RTOS.
  275. */
  276. osStatus osThreadSetPriority(osThreadId thread_id, osPriority priority)
  277. {
  278. osStatus status;
  279. rt_err_t result;
  280. rt_uint8_t rttPriority = 0;
  281. rt_thread_t thread;
  282. /* thread_id is incorrect */
  283. if (RT_NULL == thread_id)
  284. {
  285. status = osErrorParameter;
  286. goto set_pri_error;
  287. }
  288. /* incorrect priority value */
  289. if (osPriorityError == priority)
  290. {
  291. status = osErrorValue;
  292. goto set_pri_error;
  293. }
  294. thread = thread_id->thread_id;
  295. /* thread_id refers to a thread that is not an active thread. thread maybe done or has terminated*/
  296. if (rt_object_get_type((rt_object_t)thread) != RT_Object_Class_Thread)
  297. {
  298. status = osErrorResource;
  299. goto set_pri_error;
  300. }
  301. /* Cannot be called from Interrupt Service Routines */
  302. if (inHandlerMode())
  303. {
  304. status = osErrorISR;
  305. goto set_pri_error;
  306. }
  307. rttPriority = makeRttPriority(priority);
  308. result = rt_thread_control(thread, RT_THREAD_CTRL_CHANGE_PRIORITY, &rttPriority);
  309. if (result != RT_EOK)
  310. {
  311. status = osErrorOS;
  312. goto set_pri_error;
  313. }
  314. return osOK;
  315. set_pri_error:
  316. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
  317. return status;
  318. }
  319. /**
  320. * @brief Get current priority of an active thread.
  321. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
  322. * @retval current priority value of the thread function.
  323. * @note MUST REMAIN UNCHANGED: \b osThreadGetPriority shall be consistent in every CMSIS-RTOS.
  324. */
  325. osPriority osThreadGetPriority(osThreadId thread_id)
  326. {
  327. rt_thread_t thread;
  328. if (RT_NULL == thread_id)
  329. goto get_pri_error;
  330. thread = thread_id->thread_id;
  331. /* thread_id refers to a thread that is not an active thread. thread maybe done or has terminated*/
  332. if (rt_object_get_type((rt_object_t)thread) != RT_Object_Class_Thread)
  333. goto get_pri_error;
  334. /* Cannot be called from Interrupt Service Routines */
  335. if (inHandlerMode())
  336. goto get_pri_error;
  337. return makeCmsisPriority(thread->current_priority);
  338. get_pri_error:
  339. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__);
  340. return osPriorityError;
  341. }
  342. /*********************** Generic Wait Functions *******************************/
  343. /**
  344. * @brief Wait for Timeout (Time Delay)
  345. * @param millisec time delay value
  346. * @retval status code that indicates the execution status of the function.
  347. */
  348. osStatus osDelay(uint32_t millisec)
  349. {
  350. /* Cannot be called from Interrupt Service Routines */
  351. if (inHandlerMode())
  352. return osErrorISR;
  353. rt_thread_mdelay(millisec);
  354. return osOK;
  355. }
  356. #if (defined(osFeature_Wait) && (osFeature_Wait != 0)) /* Generic Wait available */
  357. /**
  358. * @brief Wait for Signal, Message, Mail, or Timeout
  359. * @param millisec timeout value or 0 in case of no time-out
  360. * @retval event that contains signal, message, or mail information or error code.
  361. * @note MUST REMAIN UNCHANGED: \b osWait shall be consistent in every CMSIS-RTOS.
  362. */
  363. osEvent osWait(uint32_t millisec);
  364. #endif /* Generic Wait available */
  365. /*********************** Timer Management Functions ***************************/
  366. /**
  367. * @brief Create a timer.
  368. * @param timer_def timer object referenced with \ref osTimer.
  369. * @param type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior.
  370. * @param argument argument to the timer call back function.
  371. * @retval timer ID for reference by other functions or NULL in case of error.
  372. * @note MUST REMAIN UNCHANGED: \b osTimerCreate shall be consistent in every CMSIS-RTOS.
  373. */
  374. osTimerId osTimerCreate(const osTimerDef_t *timer_def, os_timer_type type, void *argument)
  375. {
  376. rt_timer_t timer;
  377. static rt_uint16_t timer_number = 0U;
  378. rt_uint8_t flag = RT_TIMER_FLAG_SOFT_TIMER;
  379. char name[RT_NAME_MAX];
  380. void (*timeout_callback)(void *parameter);
  381. /* Cannot be called from Interrupt Service Routines */
  382. if (inHandlerMode())
  383. goto timer_create_error;
  384. if (RT_NULL == timer_def || RT_NULL == timer_def->ptimer)
  385. goto timer_create_error;
  386. if (osTimerPeriodic == type)
  387. flag |= RT_TIMER_FLAG_PERIODIC;
  388. else if (osTimerOnce == type)
  389. flag |= RT_TIMER_FLAG_ONE_SHOT;
  390. else
  391. goto timer_create_error;
  392. rt_snprintf(name, sizeof(name), "timer%02d", timer_number++); /* timer name */
  393. timeout_callback = (void (*)(void *parameter))(timer_def->ptimer); /* timeout callback */
  394. timer = rt_timer_create(name,
  395. timeout_callback,
  396. argument,
  397. 0,
  398. flag);
  399. if (RT_NULL == timer)
  400. goto timer_create_error;
  401. return (osTimerId)timer;
  402. timer_create_error:
  403. rt_kprintf("CMSIS RTOS1 %s failed\r\n", __func__);
  404. return RT_NULL;
  405. }
  406. /**
  407. * @brief Start or restart a timer.
  408. * @param timer_id timer ID obtained by \ref osTimerCreate.
  409. * @param millisec time delay value of the timer.
  410. * @retval status code that indicates the execution status of the function
  411. * @note MUST REMAIN UNCHANGED: \b osTimerStart shall be consistent in every CMSIS-RTOS.
  412. */
  413. osStatus osTimerStart(osTimerId timer_id, uint32_t millisec)
  414. {
  415. rt_err_t result;
  416. rt_tick_t ticks;
  417. osStatus status;
  418. /* timer_id is incorrect */
  419. if ((RT_NULL == timer_id))
  420. {
  421. status = osErrorParameter;
  422. goto timer_start_error;
  423. }
  424. /* Cannot be called from Interrupt Service Routines */
  425. if (inHandlerMode())
  426. {
  427. status = osErrorISR;
  428. goto timer_start_error;
  429. }
  430. ticks = rt_tick_from_millisecond(millisec);
  431. result = rt_timer_control((rt_timer_t)timer_id, RT_TIMER_CTRL_SET_TIME, &ticks);
  432. if (result != RT_EOK)
  433. {
  434. status = osErrorOS;
  435. goto timer_start_error;
  436. }
  437. result = rt_timer_start((rt_timer_t)timer_id);
  438. if (result != RT_EOK)
  439. {
  440. status = osErrorOS;
  441. goto timer_start_error;
  442. }
  443. return osOK;
  444. timer_start_error:
  445. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
  446. return status;
  447. }
  448. /**
  449. * @brief Stop a timer.
  450. * @param timer_id timer ID obtained by \ref osTimerCreate
  451. * @retval status code that indicates the execution status of the function.
  452. * @note MUST REMAIN UNCHANGED: \b osTimerStop shall be consistent in every CMSIS-RTOS.
  453. */
  454. osStatus osTimerStop(osTimerId timer_id)
  455. {
  456. rt_err_t result;
  457. rt_uint32_t timer_status;
  458. osStatus status;
  459. /* Cannot be called from Interrupt Service Routines */
  460. if (inHandlerMode())
  461. {
  462. status = osErrorISR;
  463. goto timer_stop_error;
  464. }
  465. /* timer_id is incorrect */
  466. if (RT_NULL == timer_id)
  467. {
  468. status = osErrorParameter;
  469. goto timer_stop_error;
  470. }
  471. /* the timer is not started */
  472. rt_timer_control((rt_timer_t)timer_id, RT_TIMER_CTRL_GET_STATE, &timer_status);
  473. if (RT_TIMER_FLAG_ACTIVATED != timer_status)
  474. {
  475. status = osErrorResource;
  476. goto timer_stop_error;
  477. }
  478. result = rt_timer_stop((rt_timer_t)timer_id);
  479. if (result != RT_EOK)
  480. {
  481. status = osErrorOS;
  482. goto timer_stop_error;
  483. }
  484. return osOK;
  485. timer_stop_error:
  486. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
  487. return status;
  488. }
  489. /**
  490. * @brief Delete a timer.
  491. * @param timer_id timer ID obtained by \ref osTimerCreate
  492. * @retval status code that indicates the execution status of the function.
  493. * @note MUST REMAIN UNCHANGED: \b osTimerDelete shall be consistent in every CMSIS-RTOS.
  494. */
  495. osStatus osTimerDelete(osTimerId timer_id)
  496. {
  497. rt_err_t result;
  498. osStatus status;
  499. /* timer_id is incorrect. */
  500. if (RT_NULL == timer_id)
  501. {
  502. status = osErrorParameter;
  503. goto timer_delete_error;
  504. }
  505. /* Cannot be called from Interrupt Service Routines. */
  506. if (inHandlerMode())
  507. {
  508. status = osErrorISR;
  509. goto timer_delete_error;
  510. }
  511. result = rt_timer_delete((rt_timer_t)timer_id);
  512. if (RT_EOK != result)
  513. {
  514. status = osErrorOS;
  515. goto timer_delete_error;
  516. }
  517. return osOK;
  518. timer_delete_error:
  519. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
  520. return status;
  521. }
  522. /*************************** Signal Management ********************************/
  523. /**
  524. * @brief Set the specified Signal Flags of an active thread.
  525. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
  526. * @param signals specifies the signal flags of the thread that should be set.
  527. * @retval previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
  528. * @note MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS.
  529. */
  530. int32_t osSignalSet(osThreadId thread_id, int32_t signal)
  531. {
  532. rt_event_t event;
  533. int32_t ret = 0x80000000;
  534. rt_err_t result;
  535. if (RT_NULL == thread_id)
  536. goto signal_set_error;
  537. event = thread_id->event_id;
  538. /* previous signal flags of the specified thread */
  539. rt_enter_critical();
  540. ret = event->set;
  541. rt_exit_critical();
  542. result = rt_event_send(event, signal);
  543. if (RT_EOK != result)
  544. {
  545. ret = 0x80000000;
  546. goto signal_set_error;
  547. }
  548. return ret;
  549. signal_set_error:
  550. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, ret);
  551. return 0x80000000;
  552. }
  553. /**
  554. * @brief Clear the specified Signal Flags of an active thread.
  555. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
  556. * @param signals specifies the signal flags of the thread that shall be cleared.
  557. * @retval previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
  558. * @note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS.
  559. */
  560. int32_t osSignalClear(osThreadId thread_id, int32_t signal)
  561. {
  562. rt_event_t event;
  563. int32_t ret = 0x80000000;
  564. if (RT_NULL == thread_id)
  565. goto signal_clear_error;
  566. /* Cannot be called from Interrupt Service Routines. */
  567. if (inHandlerMode())
  568. goto signal_clear_error;
  569. event = thread_id->event_id;
  570. /* previous signal flags of the specified thread */
  571. rt_enter_critical();
  572. ret = event->set;
  573. rt_exit_critical();
  574. rt_event_control(event, RT_IPC_CMD_RESET, RT_NULL);
  575. return ret;
  576. signal_clear_error:
  577. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, ret);
  578. return 0x80000000;
  579. }
  580. /**
  581. * @brief Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
  582. * @param signals wait until all specified signal flags set or 0 for any single signal flag.
  583. * @param millisec timeout value or 0 in case of no time-out.
  584. * @retval event flag information or error code.
  585. * @note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS.
  586. */
  587. osEvent osSignalWait(int32_t signals, uint32_t millisec)
  588. {
  589. osEvent event;
  590. rt_event_t recv_event;
  591. osThreadId thread_cb;
  592. rt_uint32_t recved;
  593. rt_uint32_t ticks = 0;
  594. rt_err_t result;
  595. /* Cannot be called from Interrupt Service Routines. */
  596. if (inHandlerMode())
  597. {
  598. event.status = osErrorISR;
  599. goto signal_wait_error;
  600. }
  601. /* get receive event */
  602. thread_cb = osThreadGetId();
  603. recv_event = thread_cb->event_id;
  604. /* get timeout */
  605. if (osWaitForever == millisec)
  606. ticks = RT_WAITING_FOREVER;
  607. else if (0U != millisec)
  608. ticks = rt_tick_from_millisecond(millisec);
  609. if (signals != 0)
  610. result = rt_event_recv(recv_event, signals, RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, ticks, &recved);
  611. else
  612. result = rt_event_recv(recv_event, signals, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, ticks, &recved);
  613. if (-RT_ETIMEOUT == result)
  614. {
  615. event.status = osEventTimeout;
  616. goto signal_wait_error;
  617. }
  618. else if (RT_EOK != result)
  619. {
  620. event.status = osErrorOS;
  621. goto signal_wait_error;
  622. }
  623. event.status = osEventSignal;
  624. return event;
  625. signal_wait_error:
  626. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, event.status);
  627. return event;
  628. }
  629. /**************************** Mutex Management ********************************/
  630. /**
  631. * @brief Create and Initialize a Mutex object
  632. * @param mutex_def mutex definition referenced with \ref osMutex.
  633. * @retval mutex ID for reference by other functions or NULL in case of error.
  634. * @note MUST REMAIN UNCHANGED: \b osMutexCreate shall be consistent in every CMSIS-RTOS.
  635. */
  636. osMutexId osMutexCreate(const osMutexDef_t *mutex_def)
  637. {
  638. #ifdef RT_USING_MUTEX
  639. static rt_uint16_t mutex_cnt = 0U;
  640. char name[RT_NAME_MAX];
  641. rt_mutex_t mutex;
  642. /* Cannot be called from Interrupt Service Routines. */
  643. if (inHandlerMode())
  644. goto mutex_create_failed;
  645. rt_snprintf(name, sizeof(name), "mutex%02d", mutex_cnt++); /* mutex name */
  646. mutex = rt_mutex_create(name, RT_IPC_FLAG_PRIO);
  647. if (RT_NULL == mutex)
  648. goto mutex_create_failed;
  649. return (osMutexId)mutex;
  650. mutex_create_failed:
  651. rt_kprintf("CMSIS RTOS1 %s failed\r\n", __func__);
  652. return RT_NULL;
  653. #else /* not define RT_USING_MUTEX */
  654. return RT_NULL;
  655. #endif /* RT_USING_MUTEX */
  656. }
  657. /**
  658. * @brief Wait until a Mutex becomes available
  659. * @param mutex_id mutex ID obtained by \ref osMutexCreate.
  660. * @param millisec timeout value or 0 in case of no time-out.
  661. * @retval status code that indicates the execution status of the function.
  662. * @note MUST REMAIN UNCHANGED: \b osMutexWait shall be consistent in every CMSIS-RTOS.
  663. */
  664. osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec)
  665. {
  666. rt_err_t result;
  667. osStatus status;
  668. rt_uint32_t ticks = 0;
  669. /* the parameter mutex_id is incorrect */
  670. if (RT_NULL == mutex_id)
  671. {
  672. status = osErrorParameter;
  673. goto mutex_wait_error;
  674. }
  675. /* the mutex could not be obtained when no timeout was specified */
  676. if (0 == millisec)
  677. {
  678. status = osErrorResource;
  679. goto mutex_wait_error;
  680. }
  681. /* Cannot be called from Interrupt Service Routines. */
  682. if (inHandlerMode())
  683. {
  684. status = osErrorISR;
  685. goto mutex_wait_error;
  686. }
  687. rt_enter_critical();
  688. if (((rt_mutex_t)mutex_id)->owner == rt_thread_self())
  689. {
  690. rt_exit_critical();
  691. status = osErrorOS;
  692. goto mutex_wait_error;
  693. }
  694. rt_exit_critical();
  695. if (osWaitForever == millisec)
  696. ticks = RT_WAITING_FOREVER;
  697. else if (0U != millisec)
  698. ticks = rt_tick_from_millisecond(millisec);
  699. result = rt_mutex_take((rt_mutex_t)mutex_id, ticks);
  700. if (-RT_ETIMEOUT == result)
  701. {
  702. status = osErrorTimeoutResource;
  703. goto mutex_wait_error;
  704. }
  705. else if (RT_EOK != result)
  706. {
  707. status = osErrorOS;
  708. goto mutex_wait_error;
  709. }
  710. return osOK;
  711. mutex_wait_error:
  712. rt_kprintf("CMSIS RTOS1 %s failed\r\n", __func__);
  713. return status;
  714. }
  715. /**
  716. * @brief Release a Mutex that was obtained by \ref osMutexWait
  717. * @param mutex_id mutex ID obtained by \ref osMutexCreate.
  718. * @retval status code that indicates the execution status of the function.
  719. * @note MUST REMAIN UNCHANGED: \b osMutexRelease shall be consistent in every CMSIS-RTOS.
  720. */
  721. osStatus osMutexRelease(osMutexId mutex_id)
  722. {
  723. rt_err_t result;
  724. osStatus status;
  725. /* the parameter mutex_id is incorrect */
  726. if (RT_NULL == mutex_id)
  727. {
  728. status = osErrorParameter;
  729. goto mutex_release_error;
  730. }
  731. /* Cannot be called from Interrupt Service Routines. */
  732. if (inHandlerMode())
  733. {
  734. status = osErrorISR;
  735. goto mutex_release_error;
  736. }
  737. /* the mutex was not obtained before */
  738. if (rt_object_get_type(&((rt_mutex_t)mutex_id)->parent.parent) != RT_Object_Class_Mutex)
  739. {
  740. status = osErrorResource;
  741. goto mutex_release_error;
  742. }
  743. result = rt_mutex_release((rt_mutex_t)mutex_id);
  744. if (RT_EOK != result)
  745. {
  746. status = osErrorOS;
  747. goto mutex_release_error;
  748. }
  749. return osOK;
  750. mutex_release_error:
  751. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
  752. return status;
  753. }
  754. /**
  755. * @brief Delete a Mutex
  756. * @param mutex_id mutex ID obtained by \ref osMutexCreate.
  757. * @retval status code that indicates the execution status of the function.
  758. * @note MUST REMAIN UNCHANGED: \b osMutexDelete shall be consistent in every CMSIS-RTOS.
  759. */
  760. osStatus osMutexDelete(osMutexId mutex_id)
  761. {
  762. osStatus status;
  763. rt_err_t result;
  764. /* Check parameters */
  765. if (RT_NULL == mutex_id)
  766. {
  767. status = osErrorParameter;
  768. goto mutex_delete_error;
  769. }
  770. /* Cannot be called from Interrupt Service Routines */
  771. if (inHandlerMode())
  772. {
  773. status = osErrorISR;
  774. goto mutex_delete_error;
  775. }
  776. /* all tokens have already been released */
  777. if (rt_object_get_type(&((rt_mutex_t)mutex_id)->parent.parent) != RT_Object_Class_Mutex)
  778. {
  779. status = osErrorResource;
  780. goto mutex_delete_error;
  781. }
  782. result = rt_mutex_delete((rt_mutex_t)mutex_id);
  783. if (RT_EOK != result)
  784. {
  785. status = osErrorOS;
  786. goto mutex_delete_error;
  787. }
  788. return osOK;
  789. mutex_delete_error:
  790. rt_kprintf("CMSIS RTOS1 %s failed error code is :%d\r\n", __func__, status);
  791. return status;
  792. }
  793. /******************** Semaphore Management Functions **************************/
  794. #if (defined(osFeature_Semaphore) && (osFeature_Semaphore != 0))
  795. /**
  796. * @brief Create and Initialize a Semaphore object used for managing resources
  797. * @param semaphore_def semaphore definition referenced with \ref osSemaphore.
  798. * @param count number of available resources.
  799. * @retval semaphore ID for reference by other functions or NULL in case of error.
  800. * @note MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent in every CMSIS-RTOS.
  801. */
  802. osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def, int32_t count)
  803. {
  804. #ifdef RT_USING_SEMAPHORE
  805. static rt_uint16_t sem_cnt = 0U;
  806. char name[RT_NAME_MAX];
  807. rt_sem_t sem;
  808. /* Cannot be called from Interrupt Service Routines */
  809. if (inHandlerMode())
  810. goto sem_create_error;
  811. if (count < 0 || count > osFeature_Semaphore)
  812. goto sem_create_error;
  813. rt_snprintf(name, sizeof(name), "sem%02d", sem_cnt++);
  814. sem = rt_sem_create(name, count, RT_IPC_FLAG_PRIO);
  815. if (RT_NULL == sem)
  816. goto sem_create_error;
  817. return (osSemaphoreId)sem;
  818. sem_create_error:
  819. rt_kprintf("CMSIS RTOS1 %s failed error", __func__);
  820. return RT_NULL;
  821. #else /* not defined RT_USING_SEMAPHORE */
  822. return RT_NULL;
  823. #endif /* RT_USING_SEMAPHORE */
  824. }
  825. /* get semaphore cnt */
  826. static int32_t _osSemaphoreGetCount(osSemaphoreId semaphore_id)
  827. {
  828. rt_sem_t sem_cb = (rt_sem_t)semaphore_id;
  829. /* Check parameters */
  830. if ((RT_NULL == sem_cb) || (rt_object_get_type(&sem_cb->parent.parent) != RT_Object_Class_Semaphore))
  831. return 0U;
  832. return sem_cb->value;
  833. }
  834. /**
  835. * @brief Wait until a Semaphore token becomes available
  836. * @param semaphore_id semaphore object referenced with \ref osSemaphore.
  837. * @param millisec timeout value or 0 in case of no time-out.
  838. * @retval number of available tokens, or -1 in case of incorrect parameters.
  839. * @note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
  840. */
  841. int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec)
  842. {
  843. rt_err_t result;
  844. rt_int32_t ticks = 0;
  845. if (RT_NULL == semaphore_id)
  846. goto sem_take_error;
  847. /* when millisec is set to osWaitForever the function will wait for an infinite time until the Semaphore token becomes available. */
  848. if (osWaitForever == millisec)
  849. ticks = RT_WAITING_FOREVER;
  850. else if (0U != millisec)
  851. ticks = rt_tick_from_millisecond(millisec);
  852. /* when millisec is 0, the function returns instantly */
  853. if (0 == millisec)
  854. result = rt_sem_trytake((rt_sem_t)semaphore_id);
  855. else
  856. result = rt_sem_take((rt_sem_t)semaphore_id, ticks);
  857. if (RT_EOK != result)
  858. goto sem_take_error;
  859. return _osSemaphoreGetCount(semaphore_id);
  860. sem_take_error:
  861. rt_kprintf("CMSIS RTOS1 %s failed \r\n", __func__);
  862. return 0; /* If 0 is returned, then no semaphore was available. */
  863. }
  864. /**
  865. * @brief Release a Semaphore token
  866. * @param semaphore_id semaphore object referenced with \ref osSemaphore.
  867. * @retval status code that indicates the execution status of the function.
  868. * @note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS.
  869. */
  870. osStatus osSemaphoreRelease(osSemaphoreId semaphore_id)
  871. {
  872. rt_err_t result;
  873. osStatus status;
  874. /* the parameter semaphore_id is incorrect. */
  875. if (RT_NULL == semaphore_id)
  876. {
  877. status = osErrorParameter;
  878. goto sem_release_error;
  879. }
  880. /* all tokens have already been released. */
  881. if (0 == _osSemaphoreGetCount(semaphore_id))
  882. {
  883. status = osErrorResource;
  884. goto sem_release_error;
  885. }
  886. result = rt_sem_release((rt_sem_t)semaphore_id);
  887. if (RT_EOK != result)
  888. {
  889. status = osErrorOS;
  890. goto sem_release_error;
  891. }
  892. return osOK;
  893. sem_release_error:
  894. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
  895. return status;
  896. }
  897. /**
  898. * @brief Delete a Semaphore
  899. * @param semaphore_id semaphore object referenced with \ref osSemaphore.
  900. * @retval status code that indicates the execution status of the function.
  901. * @note MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be consistent in every CMSIS-RTOS.
  902. */
  903. osStatus osSemaphoreDelete(osSemaphoreId semaphore_id)
  904. {
  905. rt_err_t result;
  906. osStatus status;
  907. /* the parameter semaphore_id is incorrect. */
  908. if (RT_NULL == semaphore_id)
  909. {
  910. status = osErrorParameter;
  911. goto sem_delete_error;
  912. }
  913. /* Cannot be called from Interrupt Service Routines */
  914. if (inHandlerMode())
  915. {
  916. status = osErrorISR;
  917. goto sem_delete_error;
  918. }
  919. /* the semaphore object could not be deleted. */
  920. if (rt_object_get_type((rt_object_t) & (((rt_sem_t)semaphore_id)->parent)) != RT_Object_Class_Semaphore)
  921. {
  922. status = osErrorResource;
  923. goto sem_delete_error;
  924. }
  925. result = rt_sem_delete((rt_sem_t)semaphore_id);
  926. if (RT_EOK != result)
  927. {
  928. status = osErrorOS;
  929. goto sem_delete_error;
  930. }
  931. return osOK;
  932. sem_delete_error:
  933. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
  934. return status;
  935. }
  936. #endif /* Use Semaphores */
  937. /******************* Memory Pool Management Functions ***********************/
  938. #if (defined(osFeature_Pool) && (osFeature_Pool != 0))
  939. /**
  940. * @brief Create and Initialize a memory pool
  941. * @param pool_def memory pool definition referenced with \ref osPool.
  942. * @retval memory pool ID for reference by other functions or NULL in case of error.
  943. * @note MUST REMAIN UNCHANGED: \b osPoolCreate shall be consistent in every CMSIS-RTOS.
  944. */
  945. osPoolId osPoolCreate(const osPoolDef_t *pool_def)
  946. {
  947. static rt_uint16_t mp_cnt = 0U;
  948. char name[RT_NAME_MAX];
  949. rt_mp_t mempool;
  950. rt_size_t block_size;
  951. /* Cannot be called from Interrupt Service Routines. */
  952. if (inHandlerMode())
  953. goto mp_create_error;
  954. if (RT_NULL == pool_def || 0 == pool_def->pool_sz || 0 == pool_def->item_sz)
  955. goto mp_create_error;
  956. rt_snprintf(name, sizeof(name), "mp%02d", mp_cnt++); /* name */
  957. block_size = RT_ALIGN(pool_def->item_sz, RT_ALIGN_SIZE); /* pool size */
  958. mempool = rt_mp_create(name, pool_def->pool_sz, block_size);
  959. if (RT_NULL == mempool)
  960. goto mp_create_error;
  961. return (osPoolId)mempool;
  962. mp_create_error:
  963. rt_kprintf("CMSIS RTOS1 %s failed\r\n", __func__);
  964. return RT_NULL;
  965. }
  966. /**
  967. * @brief Allocate a memory block from a memory pool
  968. * @param pool_id memory pool ID obtain referenced with \ref osPoolCreate.
  969. * @retval address of the allocated memory block or NULL in case of no memory available.
  970. * @note MUST REMAIN UNCHANGED: \b osPoolAlloc shall be consistent in every CMSIS-RTOS.
  971. */
  972. void *osPoolAlloc(osPoolId pool_id)
  973. {
  974. /* Check parameters */
  975. if (RT_NULL == pool_id)
  976. return RT_NULL;
  977. return rt_mp_alloc((rt_mp_t)pool_id, RT_WAITING_FOREVER);
  978. }
  979. /**
  980. * @brief Allocate a memory block from a memory pool and set memory block to zero
  981. * @param pool_id memory pool ID obtain referenced with \ref osPoolCreate.
  982. * @retval address of the allocated memory block or NULL in case of no memory available.
  983. * @note MUST REMAIN UNCHANGED: \b osPoolCAlloc shall be consistent in every CMSIS-RTOS.
  984. */
  985. void *osPoolCAlloc(osPoolId pool_id)
  986. {
  987. void *p = osPoolAlloc(pool_id);
  988. if (p != NULL)
  989. rt_memset(p, 0, ((rt_mp_t)pool_id)->block_size);
  990. return p;
  991. }
  992. /**
  993. * @brief Return an allocated memory block back to a specific memory pool
  994. * @param pool_id memory pool ID obtain referenced with \ref osPoolCreate.
  995. * @param block address of the allocated memory block that is returned to the memory pool.
  996. * @retval status code that indicates the execution status of the function.
  997. * @note MUST REMAIN UNCHANGED: \b osPoolFree shall be consistent in every CMSIS-RTOS.
  998. */
  999. osStatus osPoolFree(osPoolId pool_id, void *block)
  1000. {
  1001. osStatus status;
  1002. /* Check parameters */
  1003. if (NULL == pool_id)
  1004. {
  1005. status = osErrorParameter;
  1006. goto pool_free_error;
  1007. }
  1008. if (NULL == block)
  1009. {
  1010. status = osErrorParameter;
  1011. goto pool_free_error;
  1012. }
  1013. rt_mp_free(block);
  1014. block = RT_NULL;
  1015. return osOK;
  1016. pool_free_error:
  1017. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
  1018. return status;
  1019. }
  1020. #endif /* Use Memory Pool Management */
  1021. /******************* Message Queue Management Functions *********************/
  1022. #if (defined(osFeature_MessageQ) && (osFeature_MessageQ != 0)) /* Use Message Queues */
  1023. /**
  1024. * @brief Create and Initialize a Message Queue
  1025. * @param queue_def queue definition referenced with \ref osMessageQ.
  1026. * @param thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
  1027. * @retval message queue ID for reference by other functions or NULL in case of error.
  1028. * @note MUST REMAIN UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS.
  1029. */
  1030. osMessageQId osMessageCreate(const osMessageQDef_t *queue_def, osThreadId thread_id)
  1031. {
  1032. #ifdef RT_USING_MAILBOX
  1033. (void)thread_id;
  1034. static rt_uint16_t mailbox_cnt = 0U;
  1035. char name[RT_NAME_MAX];
  1036. rt_mailbox_t mailbox;
  1037. /* Cannot be called from Interrupt Service Routines. */
  1038. if (inHandlerMode())
  1039. goto message_create_error;
  1040. /* param error */
  1041. if (RT_NULL == queue_def || 0 == queue_def->queue_sz || sizeof(void *) != queue_def->item_sz)
  1042. goto message_create_error;
  1043. rt_snprintf(name, sizeof(name), "mailbox%02d", mailbox_cnt++);
  1044. mailbox = rt_mb_create(name, queue_def->queue_sz, RT_IPC_FLAG_PRIO);
  1045. if (mailbox == RT_NULL)
  1046. goto message_create_error;
  1047. return (osMessageQId)mailbox;
  1048. message_create_error:
  1049. rt_kprintf("CMSIS RTOS1 %s failed \r\n", __func__);
  1050. return RT_NULL;
  1051. #else /* RT_USING_MAILBOX */
  1052. return RT_NULL;
  1053. #endif /* not define RT_USING_MAILBOX */
  1054. }
  1055. /**
  1056. * @brief Put a Message to a Queue.
  1057. * @param queue_id message queue ID obtained with \ref osMessageCreate.
  1058. * @param info message information.
  1059. * @param millisec timeout value or 0 in case of no time-out.
  1060. * @retval status code that indicates the execution status of the function.
  1061. * @note MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent in every CMSIS-RTOS.
  1062. */
  1063. osStatus osMessagePut(osMessageQId queue_id, uint32_t info, uint32_t millisec)
  1064. {
  1065. rt_err_t result;
  1066. osStatus status;
  1067. rt_mailbox_t mb_cb = (rt_mailbox_t)queue_id;
  1068. rt_tick_t ticks = 0;
  1069. if (RT_NULL == queue_id)
  1070. {
  1071. /* a parameter is invalid or outside of a permitted range */
  1072. status = osErrorParameter;
  1073. goto message_put_error;
  1074. }
  1075. if (osWaitForever == millisec)
  1076. ticks = RT_WAITING_FOREVER;
  1077. else if (0U != millisec)
  1078. ticks = rt_tick_from_millisecond(millisec);
  1079. /* when millisec is 0, the function returns instantly */
  1080. if (0 == millisec)
  1081. result = rt_mb_urgent(mb_cb, info);
  1082. else
  1083. result = rt_mb_send_wait(mb_cb, info, ticks);
  1084. if (-RT_EFULL == result)
  1085. {
  1086. /* no memory in the queue was available */
  1087. status = osErrorResource;
  1088. goto message_put_error;
  1089. }
  1090. else if (-RT_ETIMEOUT == result)
  1091. {
  1092. /* no memory in the queue was available during the given time limit. */
  1093. status = osErrorTimeoutResource;
  1094. goto message_put_error;
  1095. }
  1096. if (RT_EOK != result)
  1097. {
  1098. status = osErrorOS;
  1099. goto message_put_error;
  1100. }
  1101. return osOK;
  1102. message_put_error:
  1103. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
  1104. return status;
  1105. }
  1106. /**
  1107. * @brief Get a Message or Wait for a Message from a Queue.
  1108. * @param queue_id message queue ID obtained with \ref osMessageCreate.
  1109. * @param millisec timeout value or 0 in case of no time-out.
  1110. * @retval event information that includes status code.
  1111. * @note MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS.
  1112. */
  1113. osEvent osMessageGet(osMessageQId queue_id, uint32_t millisec)
  1114. {
  1115. osEvent event;
  1116. rt_err_t result;
  1117. rt_tick_t ticks = 0;
  1118. if (RT_NULL == queue_id)
  1119. {
  1120. /* a parameter is invalid or outside of a permitted range */
  1121. event.status = osErrorParameter;
  1122. goto message_get_error;
  1123. }
  1124. event.def.message_id = queue_id;
  1125. event.value.v = 0;
  1126. if (osWaitForever == millisec)
  1127. ticks = RT_WAITING_FOREVER;
  1128. else if (0U != millisec)
  1129. ticks = rt_tick_from_millisecond(millisec);
  1130. result = rt_mb_recv((rt_mailbox_t)queue_id, &(event.value.v), ticks);
  1131. if (-RT_ETIMEOUT == result)
  1132. {
  1133. /* no message has arrived during the given timeout period */
  1134. event.status = osEventTimeout;
  1135. goto message_get_error;
  1136. }
  1137. else if (RT_EOK != result)
  1138. {
  1139. event.status = osErrorOS;
  1140. goto message_get_error;
  1141. }
  1142. /* message received, value.p contains the pointer to message */
  1143. event.status = osEventMessage;
  1144. return event;
  1145. message_get_error:
  1146. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, event.status);
  1147. return event;
  1148. }
  1149. #endif /* Use Message Queues */
  1150. /******************** Mail Queue Management Functions ***********************/
  1151. #if (defined(osFeature_MailQ) && (osFeature_MailQ != 0)) /* Use Mail Queues */
  1152. typedef struct os_mailQ_cb
  1153. {
  1154. rt_mp_t mp_id;
  1155. rt_mailbox_t mb_id;
  1156. } os_mailQ_cb_t;
  1157. /**
  1158. * @brief Create and Initialize mail queue
  1159. * @param queue_def reference to the mail queue definition obtain with \ref osMailQ
  1160. * @param thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
  1161. * @retval mail queue ID for reference by other functions or NULL in case of error.
  1162. * @note MUST REMAIN UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS.
  1163. */
  1164. osMailQId osMailCreate(const osMailQDef_t *queue_def, osThreadId thread_id)
  1165. {
  1166. #if defined(RT_USING_MEMPOOL) && defined(RT_USING_MAILBOX)
  1167. (void)thread_id;
  1168. os_mailQ_cb_t *ptr = RT_NULL;
  1169. char name[RT_NAME_MAX];
  1170. static rt_uint16_t mail_cnt = 0U;
  1171. rt_size_t block_size;
  1172. /* Cannot be called from Interrupt Service Routines. */
  1173. if (inHandlerMode())
  1174. goto mail_create_failed;
  1175. if (RT_NULL == queue_def || 0 == queue_def->queue_sz || 0 == queue_def->item_sz)
  1176. goto mail_create_failed;
  1177. rt_snprintf(name, sizeof(name), "mb%02d", mail_cnt++);
  1178. block_size = RT_ALIGN(queue_def->item_sz, RT_ALIGN_SIZE);
  1179. ptr = (void *)CMSIS_MEM_ALLOC(sizeof(struct os_mailQ_cb));
  1180. if (RT_NULL == ptr)
  1181. goto mail_create_failed;
  1182. ptr->mp_id = rt_mp_create(name, queue_def->queue_sz, block_size);
  1183. ptr->mb_id = rt_mb_create(name, queue_def->queue_sz, RT_IPC_FLAG_PRIO);
  1184. if ((RT_NULL == ptr->mp_id) || (RT_NULL == ptr->mb_id))
  1185. goto mail_create_failed;
  1186. return ptr;
  1187. mail_create_failed:
  1188. if (ptr)
  1189. CMSIS_MEM_FREE(ptr);
  1190. if (RT_NULL != ptr->mp_id)
  1191. rt_mp_delete(ptr->mp_id);
  1192. if (RT_NULL != ptr->mb_id)
  1193. rt_mb_delete(ptr->mb_id);
  1194. rt_kprintf("CMSIS RTOS1 %s failed\r\n", __func__);
  1195. return RT_NULL;
  1196. #else /* RT_USING_MEMPOOL && RT_USING_MAILBOX */
  1197. return RT_NULL;
  1198. #endif /* not define RT_USING_MEMPOOL && RT_USING_MAILBOX */
  1199. }
  1200. /**
  1201. * @brief Allocate a memory block from a mail
  1202. * @param queue_id mail queue ID obtained with \ref osMailCreate.
  1203. * @param millisec timeout value or 0 in case of no time-out.
  1204. * @retval pointer to memory block that can be filled with mail or NULL in case error.
  1205. * @note MUST REMAIN UNCHANGED: \b osMailAlloc shall be consistent in every CMSIS-RTOS.
  1206. */
  1207. void *osMailAlloc(osMailQId queue_id, uint32_t millisec)
  1208. {
  1209. os_mailQ_cb_t *ptr = (os_mailQ_cb_t *)queue_id;
  1210. void *ret = NULL;
  1211. rt_tick_t ticks = 0;
  1212. if (RT_NULL == ptr)
  1213. goto mail_alloc_error;
  1214. if (osWaitForever == millisec)
  1215. ticks = RT_WAITING_FOREVER;
  1216. else if (0U != millisec)
  1217. ticks = rt_tick_from_millisecond(millisec);
  1218. ret = rt_mp_alloc(ptr->mp_id, ticks);
  1219. if (RT_NULL == ret)
  1220. goto mail_alloc_error;
  1221. return ret;
  1222. mail_alloc_error:
  1223. rt_kprintf("CMSIS RTOS1 %s failed\r\n", __func__);
  1224. return RT_NULL;
  1225. }
  1226. /**
  1227. * @brief Allocate a memory block from a mail and set memory block to zero
  1228. * @param queue_id mail queue ID obtained with \ref osMailCreate.
  1229. * @param millisec timeout value or 0 in case of no time-out.
  1230. * @retval pointer to memory block that can be filled with mail or NULL in case error.
  1231. * @note MUST REMAIN UNCHANGED: \b osMailCAlloc shall be consistent in every CMSIS-RTOS.
  1232. */
  1233. void *osMailCAlloc(osMailQId queue_id, uint32_t millisec)
  1234. {
  1235. void *p = osMailAlloc(queue_id, millisec);
  1236. if (p)
  1237. rt_memset(p, 0, ((os_mailQ_cb_t *)queue_id)->mp_id->block_size);
  1238. return p;
  1239. }
  1240. /**
  1241. * @brief Put a mail to a queue
  1242. * @param queue_id mail queue ID obtained with \ref osMailCreate.
  1243. * @param mail memory block previously allocated with \ref osMailAlloc or \ref osMailCAlloc.
  1244. * @retval status code that indicates the execution status of the function.
  1245. * @note MUST REMAIN UNCHANGED: \b osMailPut shall be consistent in every CMSIS-RTOS.
  1246. */
  1247. osStatus osMailPut(osMailQId queue_id, void *mail)
  1248. {
  1249. osStatus status;
  1250. os_mailQ_cb_t *ptr = (os_mailQ_cb_t *)queue_id;
  1251. rt_err_t result;
  1252. if (RT_NULL == ptr)
  1253. {
  1254. status = osErrorParameter;
  1255. goto mail_put_error;
  1256. }
  1257. if (RT_NULL == mail)
  1258. {
  1259. status = osErrorValue;
  1260. goto mail_put_error;
  1261. }
  1262. result = rt_mb_send((ptr->mb_id), (rt_ubase_t)mail);
  1263. if (RT_EOK != result)
  1264. {
  1265. status = osErrorOS;
  1266. goto mail_put_error;
  1267. }
  1268. return osOK;
  1269. mail_put_error:
  1270. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
  1271. return status;
  1272. }
  1273. /**
  1274. * @brief Get a mail from a queue
  1275. * @param queue_id mail queue ID obtained with \ref osMailCreate.
  1276. * @param millisec timeout value or 0 in case of no time-out
  1277. * @retval event that contains mail information or error code.
  1278. * @note MUST REMAIN UNCHANGED: \b osMailGet shall be consistent in every CMSIS-RTOS.
  1279. */
  1280. osEvent osMailGet(osMailQId queue_id, uint32_t millisec)
  1281. {
  1282. osEvent event;
  1283. os_mailQ_cb_t *ptr = (os_mailQ_cb_t *)queue_id;
  1284. rt_err_t result;
  1285. rt_ubase_t value;
  1286. rt_tick_t ticks = 0;
  1287. if (RT_NULL == ptr)
  1288. {
  1289. event.status = osErrorParameter;
  1290. goto mail_get_error;
  1291. }
  1292. if (osWaitForever == millisec)
  1293. ticks = RT_WAITING_FOREVER;
  1294. else if (0U != millisec)
  1295. ticks = rt_tick_from_millisecond(millisec);
  1296. result = rt_mb_recv((ptr->mb_id), &value, ticks);
  1297. if (-RT_ETIMEOUT == result)
  1298. {
  1299. event.status = osEventTimeout;
  1300. goto mail_get_error;
  1301. }
  1302. else if (RT_EOK != result)
  1303. {
  1304. event.status = osErrorOS;
  1305. goto mail_get_error;
  1306. }
  1307. event.value.p = (void *)value;
  1308. event.status = osEventMail;
  1309. return event;
  1310. mail_get_error:
  1311. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, event.status);
  1312. return event;
  1313. }
  1314. /**
  1315. * @brief Free a memory block from a mail
  1316. * @param queue_id mail queue ID obtained with \ref osMailCreate.
  1317. * @param mail pointer to the memory block that was obtained with \ref osMailGet.
  1318. * @retval status code that indicates the execution status of the function.
  1319. * @note MUST REMAIN UNCHANGED: \b osMailFree shall be consistent in every CMSIS-RTOS.
  1320. */
  1321. osStatus osMailFree(osMailQId queue_id, void *mail)
  1322. {
  1323. osStatus status;
  1324. os_mailQ_cb_t *ptr = (os_mailQ_cb_t *)queue_id;
  1325. if (RT_NULL == ptr)
  1326. {
  1327. status = osErrorParameter;
  1328. goto mail_free_error;
  1329. }
  1330. if (RT_NULL == mail)
  1331. {
  1332. status = osErrorValue;
  1333. goto mail_free_error;
  1334. }
  1335. rt_mp_free(mail);
  1336. mail = RT_NULL;
  1337. return osOK;
  1338. mail_free_error:
  1339. rt_kprintf("CMSIS RTOS1 %s failed error code is : 0x%x\r\n", __func__, status);
  1340. return status;
  1341. }
  1342. #endif /* Use Mail Queues */
  1343. /****************************** end of file ******************************/