cmsis_rtthread.c 46 KB

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