cmsis_os.c 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774
  1. /* ----------------------------------------------------------------------
  2. * $Date: 5. February 2013
  3. * $Revision: V1.02
  4. *
  5. * Project: CMSIS-RTOS API
  6. * Title: cmsis_os.c
  7. *
  8. * Version 0.02
  9. * Initial Proposal Phase
  10. * Version 0.03
  11. * osKernelStart added, optional feature: main started as thread
  12. * osSemaphores have standard behavior
  13. * osTimerCreate does not start the timer, added osTimerStart
  14. * osThreadPass is renamed to osThreadYield
  15. * Version 1.01
  16. * Support for C++ interface
  17. * - const attribute removed from the osXxxxDef_t typedef's
  18. * - const attribute added to the osXxxxDef macros
  19. * Added: osTimerDelete, osMutexDelete, osSemaphoreDelete
  20. * Added: osKernelInitialize
  21. * Version 1.02
  22. * Control functions for short timeouts in microsecond resolution:
  23. * Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec
  24. * Removed: osSignalGet
  25. *
  26. *
  27. *----------------------------------------------------------------------------
  28. *
  29. * Portions Copyright © 2016 STMicroelectronics International N.V. All rights reserved.
  30. * Portions Copyright (c) 2013 ARM LIMITED
  31. * All rights reserved.
  32. * Redistribution and use in source and binary forms, with or without
  33. * modification, are permitted provided that the following conditions are met:
  34. * - Redistributions of source code must retain the above copyright
  35. * notice, this list of conditions and the following disclaimer.
  36. * - Redistributions in binary form must reproduce the above copyright
  37. * notice, this list of conditions and the following disclaimer in the
  38. * documentation and/or other materials provided with the distribution.
  39. * - Neither the name of ARM nor the names of its contributors may be used
  40. * to endorse or promote products derived from this software without
  41. * specific prior written permission.
  42. *
  43. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  44. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  45. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  46. * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
  47. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  48. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  49. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  50. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  51. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  52. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  53. * POSSIBILITY OF SUCH DAMAGE.
  54. *---------------------------------------------------------------------------*/
  55. /**
  56. ******************************************************************************
  57. * @file cmsis_os.c
  58. * @author MCD Application Team
  59. * @date 13-July-2017
  60. * @brief CMSIS-RTOS API implementation for FreeRTOS V9.0.0
  61. ******************************************************************************
  62. * @attention
  63. *
  64. * Redistribution and use in source and binary forms, with or without
  65. * modification, are permitted, provided that the following conditions are met:
  66. *
  67. * 1. Redistribution of source code must retain the above copyright notice,
  68. * this list of conditions and the following disclaimer.
  69. * 2. Redistributions in binary form must reproduce the above copyright notice,
  70. * this list of conditions and the following disclaimer in the documentation
  71. * and/or other materials provided with the distribution.
  72. * 3. Neither the name of STMicroelectronics nor the names of other
  73. * contributors to this software may be used to endorse or promote products
  74. * derived from this software without specific written permission.
  75. * 4. This software, including modifications and/or derivative works of this
  76. * software, must execute solely and exclusively on microcontroller or
  77. * microprocessor devices manufactured by or for STMicroelectronics.
  78. * 5. Redistribution and use of this software other than as permitted under
  79. * this license is void and will automatically terminate your rights under
  80. * this license.
  81. *
  82. * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
  83. * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
  84. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  85. * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
  86. * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
  87. * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  88. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  89. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  90. * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  91. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  92. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  93. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  94. *
  95. ******************************************************************************
  96. */
  97. #include <string.h>
  98. #include "cmsis_os.h"
  99. /*
  100. * ARM Compiler 4/5
  101. */
  102. #if defined ( __CC_ARM )
  103. #define __ASM __asm
  104. #define __INLINE __inline
  105. #define __STATIC_INLINE static __inline
  106. #include "cmsis_armcc.h"
  107. /*
  108. * GNU Compiler
  109. */
  110. #elif defined ( __GNUC__ )
  111. #define __ASM __asm /*!< asm keyword for GNU Compiler */
  112. #define __INLINE inline /*!< inline keyword for GNU Compiler */
  113. #define __STATIC_INLINE static inline
  114. #include "cmsis_gcc.h"
  115. /*
  116. * IAR Compiler
  117. */
  118. #elif defined ( __ICCARM__ )
  119. #ifndef __ASM
  120. #define __ASM __asm
  121. #endif
  122. #ifndef __INLINE
  123. #define __INLINE inline
  124. #endif
  125. #ifndef __STATIC_INLINE
  126. #define __STATIC_INLINE static inline
  127. #endif
  128. #include <cmsis_iar.h>
  129. #endif
  130. extern void xPortSysTickHandler(void);
  131. /* Convert from CMSIS type osPriority to FreeRTOS priority number */
  132. static unsigned portBASE_TYPE makeFreeRtosPriority (osPriority priority)
  133. {
  134. unsigned portBASE_TYPE fpriority = tskIDLE_PRIORITY;
  135. if (priority != osPriorityError) {
  136. fpriority += (priority - osPriorityIdle);
  137. }
  138. return fpriority;
  139. }
  140. #if (INCLUDE_uxTaskPriorityGet == 1)
  141. /* Convert from FreeRTOS priority number to CMSIS type osPriority */
  142. static osPriority makeCmsisPriority (unsigned portBASE_TYPE fpriority)
  143. {
  144. osPriority priority = osPriorityError;
  145. if ((fpriority - tskIDLE_PRIORITY) <= (osPriorityRealtime - osPriorityIdle)) {
  146. priority = (osPriority)((int)osPriorityIdle + (int)(fpriority - tskIDLE_PRIORITY));
  147. }
  148. return priority;
  149. }
  150. #endif
  151. /* Determine whether we are in thread mode or handler mode. */
  152. static int inHandlerMode (void)
  153. {
  154. return __get_IPSR() != 0;
  155. }
  156. /*********************** Kernel Control Functions *****************************/
  157. /**
  158. * @brief Initialize the RTOS Kernel for creating objects.
  159. * @retval status code that indicates the execution status of the function.
  160. * @note MUST REMAIN UNCHANGED: \b osKernelInitialize shall be consistent in every CMSIS-RTOS.
  161. */
  162. osStatus osKernelInitialize (void);
  163. /**
  164. * @brief Start the RTOS Kernel with executing the specified thread.
  165. * @param thread_def thread definition referenced with \ref osThread.
  166. * @param argument pointer that is passed to the thread function as start argument.
  167. * @retval status code that indicates the execution status of the function
  168. * @note MUST REMAIN UNCHANGED: \b osKernelStart shall be consistent in every CMSIS-RTOS.
  169. */
  170. osStatus osKernelStart (void)
  171. {
  172. vTaskStartScheduler();
  173. return osOK;
  174. }
  175. /**
  176. * @brief Check if the RTOS kernel is already started
  177. * @param None
  178. * @retval (0) RTOS is not started
  179. * (1) RTOS is started
  180. * (-1) if this feature is disabled in FreeRTOSConfig.h
  181. * @note MUST REMAIN UNCHANGED: \b osKernelRunning shall be consistent in every CMSIS-RTOS.
  182. */
  183. int32_t osKernelRunning(void)
  184. {
  185. #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
  186. if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED)
  187. return 0;
  188. else
  189. return 1;
  190. #else
  191. return (-1);
  192. #endif
  193. }
  194. #if (defined (osFeature_SysTick) && (osFeature_SysTick != 0)) // System Timer available
  195. /**
  196. * @brief Get the value of the Kernel SysTick timer
  197. * @param None
  198. * @retval None
  199. * @note MUST REMAIN UNCHANGED: \b osKernelSysTick shall be consistent in every CMSIS-RTOS.
  200. */
  201. uint32_t osKernelSysTick(void)
  202. {
  203. if (inHandlerMode()) {
  204. return xTaskGetTickCountFromISR();
  205. }
  206. else {
  207. return xTaskGetTickCount();
  208. }
  209. }
  210. #endif // System Timer available
  211. /*********************** Thread Management *****************************/
  212. /**
  213. * @brief Create a thread and add it to Active Threads and set it to state READY.
  214. * @param thread_def thread definition referenced with \ref osThread.
  215. * @param argument pointer that is passed to the thread function as start argument.
  216. * @retval thread ID for reference by other functions or NULL in case of error.
  217. * @note MUST REMAIN UNCHANGED: \b osThreadCreate shall be consistent in every CMSIS-RTOS.
  218. */
  219. osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument)
  220. {
  221. TaskHandle_t handle;
  222. #if( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
  223. if((thread_def->buffer != NULL) && (thread_def->controlblock != NULL)) {
  224. handle = xTaskCreateStatic((TaskFunction_t)thread_def->pthread,(const portCHAR *)thread_def->name,
  225. thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority),
  226. thread_def->buffer, thread_def->controlblock);
  227. }
  228. else {
  229. if (xTaskCreate((TaskFunction_t)thread_def->pthread,(const portCHAR *)thread_def->name,
  230. thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority),
  231. &handle) != pdPASS) {
  232. return NULL;
  233. }
  234. }
  235. #elif( configSUPPORT_STATIC_ALLOCATION == 1 )
  236. handle = xTaskCreateStatic((TaskFunction_t)thread_def->pthread,(const portCHAR *)thread_def->name,
  237. thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority),
  238. thread_def->buffer, thread_def->controlblock);
  239. #else
  240. if (xTaskCreate((TaskFunction_t)thread_def->pthread,(const portCHAR *)thread_def->name,
  241. thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority),
  242. &handle) != pdPASS) {
  243. return NULL;
  244. }
  245. #endif
  246. return handle;
  247. }
  248. /**
  249. * @brief Return the thread ID of the current running thread.
  250. * @retval thread ID for reference by other functions or NULL in case of error.
  251. * @note MUST REMAIN UNCHANGED: \b osThreadGetId shall be consistent in every CMSIS-RTOS.
  252. */
  253. osThreadId osThreadGetId (void)
  254. {
  255. #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
  256. return xTaskGetCurrentTaskHandle();
  257. #else
  258. return NULL;
  259. #endif
  260. }
  261. /**
  262. * @brief Terminate execution of a thread and remove it from Active Threads.
  263. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
  264. * @retval status code that indicates the execution status of the function.
  265. * @note MUST REMAIN UNCHANGED: \b osThreadTerminate shall be consistent in every CMSIS-RTOS.
  266. */
  267. osStatus osThreadTerminate (osThreadId thread_id)
  268. {
  269. #if (INCLUDE_vTaskDelete == 1)
  270. vTaskDelete(thread_id);
  271. return osOK;
  272. #else
  273. return osErrorOS;
  274. #endif
  275. }
  276. /**
  277. * @brief Pass control to next thread that is in state \b READY.
  278. * @retval status code that indicates the execution status of the function.
  279. * @note MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every CMSIS-RTOS.
  280. */
  281. osStatus osThreadYield (void)
  282. {
  283. taskYIELD();
  284. return osOK;
  285. }
  286. /**
  287. * @brief Change priority of an active thread.
  288. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
  289. * @param priority new priority value for the thread function.
  290. * @retval status code that indicates the execution status of the function.
  291. * @note MUST REMAIN UNCHANGED: \b osThreadSetPriority shall be consistent in every CMSIS-RTOS.
  292. */
  293. osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority)
  294. {
  295. #if (INCLUDE_vTaskPrioritySet == 1)
  296. vTaskPrioritySet(thread_id, makeFreeRtosPriority(priority));
  297. return osOK;
  298. #else
  299. return osErrorOS;
  300. #endif
  301. }
  302. /**
  303. * @brief Get current priority of an active thread.
  304. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
  305. * @retval current priority value of the thread function.
  306. * @note MUST REMAIN UNCHANGED: \b osThreadGetPriority shall be consistent in every CMSIS-RTOS.
  307. */
  308. osPriority osThreadGetPriority (osThreadId thread_id)
  309. {
  310. #if (INCLUDE_uxTaskPriorityGet == 1)
  311. if (inHandlerMode())
  312. {
  313. return makeCmsisPriority(uxTaskPriorityGetFromISR(thread_id));
  314. }
  315. else
  316. {
  317. return makeCmsisPriority(uxTaskPriorityGet(thread_id));
  318. }
  319. #else
  320. return osPriorityError;
  321. #endif
  322. }
  323. /*********************** Generic Wait Functions *******************************/
  324. /**
  325. * @brief Wait for Timeout (Time Delay)
  326. * @param millisec time delay value
  327. * @retval status code that indicates the execution status of the function.
  328. */
  329. osStatus osDelay (uint32_t millisec)
  330. {
  331. #if INCLUDE_vTaskDelay
  332. TickType_t ticks = millisec / portTICK_PERIOD_MS;
  333. vTaskDelay(ticks ? ticks : 1); /* Minimum delay = 1 tick */
  334. return osOK;
  335. #else
  336. (void) millisec;
  337. return osErrorResource;
  338. #endif
  339. }
  340. #if (defined (osFeature_Wait) && (osFeature_Wait != 0)) /* Generic Wait available */
  341. /**
  342. * @brief Wait for Signal, Message, Mail, or Timeout
  343. * @param millisec timeout value or 0 in case of no time-out
  344. * @retval event that contains signal, message, or mail information or error code.
  345. * @note MUST REMAIN UNCHANGED: \b osWait shall be consistent in every CMSIS-RTOS.
  346. */
  347. osEvent osWait (uint32_t millisec);
  348. #endif /* Generic Wait available */
  349. /*********************** Timer Management Functions ***************************/
  350. /**
  351. * @brief Create a timer.
  352. * @param timer_def timer object referenced with \ref osTimer.
  353. * @param type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior.
  354. * @param argument argument to the timer call back function.
  355. * @retval timer ID for reference by other functions or NULL in case of error.
  356. * @note MUST REMAIN UNCHANGED: \b osTimerCreate shall be consistent in every CMSIS-RTOS.
  357. */
  358. osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument)
  359. {
  360. #if (configUSE_TIMERS == 1)
  361. #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
  362. if(timer_def->controlblock != NULL) {
  363. return xTimerCreateStatic((const char *)"",
  364. 1, // period should be filled when starting the Timer using osTimerStart
  365. (type == osTimerPeriodic) ? pdTRUE : pdFALSE,
  366. (void *) argument,
  367. (TaskFunction_t)timer_def->ptimer,
  368. (StaticTimer_t *)timer_def->controlblock);
  369. }
  370. else {
  371. return xTimerCreate((const char *)"",
  372. 1, // period should be filled when starting the Timer using osTimerStart
  373. (type == osTimerPeriodic) ? pdTRUE : pdFALSE,
  374. (void *) argument,
  375. (TaskFunction_t)timer_def->ptimer);
  376. }
  377. #elif( configSUPPORT_STATIC_ALLOCATION == 1 )
  378. return xTimerCreateStatic((const char *)"",
  379. 1, // period should be filled when starting the Timer using osTimerStart
  380. (type == osTimerPeriodic) ? pdTRUE : pdFALSE,
  381. (void *) argument,
  382. (TaskFunction_t)timer_def->ptimer,
  383. (StaticTimer_t *)timer_def->controlblock);
  384. #else
  385. return xTimerCreate((const char *)"",
  386. 1, // period should be filled when starting the Timer using osTimerStart
  387. (type == osTimerPeriodic) ? pdTRUE : pdFALSE,
  388. (void *) argument,
  389. (TaskFunction_t)timer_def->ptimer);
  390. #endif
  391. #else
  392. return NULL;
  393. #endif
  394. }
  395. /**
  396. * @brief Start or restart a timer.
  397. * @param timer_id timer ID obtained by \ref osTimerCreate.
  398. * @param millisec time delay value of the timer.
  399. * @retval status code that indicates the execution status of the function
  400. * @note MUST REMAIN UNCHANGED: \b osTimerStart shall be consistent in every CMSIS-RTOS.
  401. */
  402. osStatus osTimerStart (osTimerId timer_id, uint32_t millisec)
  403. {
  404. osStatus result = osOK;
  405. #if (configUSE_TIMERS == 1)
  406. portBASE_TYPE taskWoken = pdFALSE;
  407. TickType_t ticks = millisec / portTICK_PERIOD_MS;
  408. if (ticks == 0)
  409. ticks = 1;
  410. if (inHandlerMode())
  411. {
  412. if (xTimerChangePeriodFromISR(timer_id, ticks, &taskWoken) != pdPASS)
  413. {
  414. result = osErrorOS;
  415. }
  416. else
  417. {
  418. portEND_SWITCHING_ISR(taskWoken);
  419. }
  420. }
  421. else
  422. {
  423. if (xTimerChangePeriod(timer_id, ticks, 0) != pdPASS)
  424. result = osErrorOS;
  425. }
  426. #else
  427. result = osErrorOS;
  428. #endif
  429. return result;
  430. }
  431. /**
  432. * @brief Stop a timer.
  433. * @param timer_id timer ID obtained by \ref osTimerCreate
  434. * @retval status code that indicates the execution status of the function.
  435. * @note MUST REMAIN UNCHANGED: \b osTimerStop shall be consistent in every CMSIS-RTOS.
  436. */
  437. osStatus osTimerStop (osTimerId timer_id)
  438. {
  439. osStatus result = osOK;
  440. #if (configUSE_TIMERS == 1)
  441. portBASE_TYPE taskWoken = pdFALSE;
  442. if (inHandlerMode()) {
  443. if (xTimerStopFromISR(timer_id, &taskWoken) != pdPASS) {
  444. return osErrorOS;
  445. }
  446. portEND_SWITCHING_ISR(taskWoken);
  447. }
  448. else {
  449. if (xTimerStop(timer_id, 0) != pdPASS) {
  450. result = osErrorOS;
  451. }
  452. }
  453. #else
  454. result = osErrorOS;
  455. #endif
  456. return result;
  457. }
  458. /**
  459. * @brief Delete a timer.
  460. * @param timer_id timer ID obtained by \ref osTimerCreate
  461. * @retval status code that indicates the execution status of the function.
  462. * @note MUST REMAIN UNCHANGED: \b osTimerDelete shall be consistent in every CMSIS-RTOS.
  463. */
  464. osStatus osTimerDelete (osTimerId timer_id)
  465. {
  466. osStatus result = osOK;
  467. #if (configUSE_TIMERS == 1)
  468. if (inHandlerMode()) {
  469. return osErrorISR;
  470. }
  471. else {
  472. if ((xTimerDelete(timer_id, osWaitForever )) != pdPASS) {
  473. result = osErrorOS;
  474. }
  475. }
  476. #else
  477. result = osErrorOS;
  478. #endif
  479. return result;
  480. }
  481. /*************************** Signal Management ********************************/
  482. /**
  483. * @brief Set the specified Signal Flags of an active thread.
  484. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
  485. * @param signals specifies the signal flags of the thread that should be set.
  486. * @retval previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
  487. * @note MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS.
  488. */
  489. int32_t osSignalSet (osThreadId thread_id, int32_t signal)
  490. {
  491. #if( configUSE_TASK_NOTIFICATIONS == 1 )
  492. BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  493. uint32_t ulPreviousNotificationValue = 0;
  494. if (inHandlerMode())
  495. {
  496. if(xTaskGenericNotifyFromISR( thread_id , (uint32_t)signal, eSetBits, &ulPreviousNotificationValue, &xHigherPriorityTaskWoken ) != pdPASS )
  497. return 0x80000000;
  498. portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
  499. }
  500. else if(xTaskGenericNotify( thread_id , (uint32_t)signal, eSetBits, &ulPreviousNotificationValue) != pdPASS )
  501. return 0x80000000;
  502. return ulPreviousNotificationValue;
  503. #else
  504. (void) thread_id;
  505. (void) signal;
  506. return 0x80000000; /* Task Notification not supported */
  507. #endif
  508. }
  509. /**
  510. * @brief Clear the specified Signal Flags of an active thread.
  511. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
  512. * @param signals specifies the signal flags of the thread that shall be cleared.
  513. * @retval previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
  514. * @note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS.
  515. */
  516. int32_t osSignalClear (osThreadId thread_id, int32_t signal);
  517. /**
  518. * @brief Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
  519. * @param signals wait until all specified signal flags set or 0 for any single signal flag.
  520. * @param millisec timeout value or 0 in case of no time-out.
  521. * @retval event flag information or error code.
  522. * @note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS.
  523. */
  524. osEvent osSignalWait (int32_t signals, uint32_t millisec)
  525. {
  526. osEvent ret;
  527. #if( configUSE_TASK_NOTIFICATIONS == 1 )
  528. TickType_t ticks;
  529. ret.value.signals = 0;
  530. ticks = 0;
  531. if (millisec == osWaitForever) {
  532. ticks = portMAX_DELAY;
  533. }
  534. else if (millisec != 0) {
  535. ticks = millisec / portTICK_PERIOD_MS;
  536. if (ticks == 0) {
  537. ticks = 1;
  538. }
  539. }
  540. if (inHandlerMode())
  541. {
  542. ret.status = osErrorISR; /*Not allowed in ISR*/
  543. }
  544. else
  545. {
  546. if(xTaskNotifyWait( 0,(uint32_t) signals, (uint32_t *)&ret.value.signals, ticks) != pdTRUE)
  547. {
  548. if(ticks == 0) ret.status = osOK;
  549. else ret.status = osEventTimeout;
  550. }
  551. else if(ret.value.signals < 0)
  552. {
  553. ret.status = osErrorValue;
  554. }
  555. else ret.status = osEventSignal;
  556. }
  557. #else
  558. (void) signals;
  559. (void) millisec;
  560. ret.status = osErrorOS; /* Task Notification not supported */
  561. #endif
  562. return ret;
  563. }
  564. /**************************** Mutex Management ********************************/
  565. /**
  566. * @brief Create and Initialize a Mutex object
  567. * @param mutex_def mutex definition referenced with \ref osMutex.
  568. * @retval mutex ID for reference by other functions or NULL in case of error.
  569. * @note MUST REMAIN UNCHANGED: \b osMutexCreate shall be consistent in every CMSIS-RTOS.
  570. */
  571. osMutexId osMutexCreate (const osMutexDef_t *mutex_def)
  572. {
  573. #if ( configUSE_MUTEXES == 1)
  574. #if( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
  575. if (mutex_def->controlblock != NULL) {
  576. return xSemaphoreCreateMutexStatic( mutex_def->controlblock );
  577. }
  578. else {
  579. return xSemaphoreCreateMutex();
  580. }
  581. #elif ( configSUPPORT_STATIC_ALLOCATION == 1 )
  582. return xSemaphoreCreateMutexStatic( mutex_def->controlblock );
  583. #else
  584. return xSemaphoreCreateMutex();
  585. #endif
  586. #else
  587. return NULL;
  588. #endif
  589. }
  590. /**
  591. * @brief Wait until a Mutex becomes available
  592. * @param mutex_id mutex ID obtained by \ref osMutexCreate.
  593. * @param millisec timeout value or 0 in case of no time-out.
  594. * @retval status code that indicates the execution status of the function.
  595. * @note MUST REMAIN UNCHANGED: \b osMutexWait shall be consistent in every CMSIS-RTOS.
  596. */
  597. osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec)
  598. {
  599. TickType_t ticks;
  600. portBASE_TYPE taskWoken = pdFALSE;
  601. if (mutex_id == NULL) {
  602. return osErrorParameter;
  603. }
  604. ticks = 0;
  605. if (millisec == osWaitForever) {
  606. ticks = portMAX_DELAY;
  607. }
  608. else if (millisec != 0) {
  609. ticks = millisec / portTICK_PERIOD_MS;
  610. if (ticks == 0) {
  611. ticks = 1;
  612. }
  613. }
  614. if (inHandlerMode()) {
  615. if (xSemaphoreTakeFromISR(mutex_id, &taskWoken) != pdTRUE) {
  616. return osErrorOS;
  617. }
  618. portEND_SWITCHING_ISR(taskWoken);
  619. }
  620. else if (xSemaphoreTake(mutex_id, ticks) != pdTRUE) {
  621. return osErrorOS;
  622. }
  623. return osOK;
  624. }
  625. /**
  626. * @brief Release a Mutex that was obtained by \ref osMutexWait
  627. * @param mutex_id mutex ID obtained by \ref osMutexCreate.
  628. * @retval status code that indicates the execution status of the function.
  629. * @note MUST REMAIN UNCHANGED: \b osMutexRelease shall be consistent in every CMSIS-RTOS.
  630. */
  631. osStatus osMutexRelease (osMutexId mutex_id)
  632. {
  633. osStatus result = osOK;
  634. portBASE_TYPE taskWoken = pdFALSE;
  635. if (inHandlerMode()) {
  636. if (xSemaphoreGiveFromISR(mutex_id, &taskWoken) != pdTRUE) {
  637. return osErrorOS;
  638. }
  639. portEND_SWITCHING_ISR(taskWoken);
  640. }
  641. else if (xSemaphoreGive(mutex_id) != pdTRUE)
  642. {
  643. result = osErrorOS;
  644. }
  645. return result;
  646. }
  647. /**
  648. * @brief Delete a Mutex
  649. * @param mutex_id mutex ID obtained by \ref osMutexCreate.
  650. * @retval status code that indicates the execution status of the function.
  651. * @note MUST REMAIN UNCHANGED: \b osMutexDelete shall be consistent in every CMSIS-RTOS.
  652. */
  653. osStatus osMutexDelete (osMutexId mutex_id)
  654. {
  655. if (inHandlerMode()) {
  656. return osErrorISR;
  657. }
  658. vQueueDelete(mutex_id);
  659. return osOK;
  660. }
  661. /******************** Semaphore Management Functions **************************/
  662. #if (defined (osFeature_Semaphore) && (osFeature_Semaphore != 0))
  663. /**
  664. * @brief Create and Initialize a Semaphore object used for managing resources
  665. * @param semaphore_def semaphore definition referenced with \ref osSemaphore.
  666. * @param count number of available resources.
  667. * @retval semaphore ID for reference by other functions or NULL in case of error.
  668. * @note MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent in every CMSIS-RTOS.
  669. */
  670. osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count)
  671. {
  672. #if( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
  673. osSemaphoreId sema;
  674. if (semaphore_def->controlblock != NULL){
  675. if (count == 1) {
  676. return xSemaphoreCreateBinaryStatic( semaphore_def->controlblock );
  677. }
  678. else {
  679. #if (configUSE_COUNTING_SEMAPHORES == 1 )
  680. return xSemaphoreCreateCountingStatic( count, count, semaphore_def->controlblock );
  681. #else
  682. return NULL;
  683. #endif
  684. }
  685. }
  686. else {
  687. if (count == 1) {
  688. vSemaphoreCreateBinary(sema);
  689. return sema;
  690. }
  691. else {
  692. #if (configUSE_COUNTING_SEMAPHORES == 1 )
  693. return xSemaphoreCreateCounting(count, count);
  694. #else
  695. return NULL;
  696. #endif
  697. }
  698. }
  699. #elif ( configSUPPORT_STATIC_ALLOCATION == 1 ) // configSUPPORT_DYNAMIC_ALLOCATION == 0
  700. if(count == 1) {
  701. return xSemaphoreCreateBinaryStatic( semaphore_def->controlblock );
  702. }
  703. else
  704. {
  705. #if (configUSE_COUNTING_SEMAPHORES == 1 )
  706. return xSemaphoreCreateCountingStatic( count, count, semaphore_def->controlblock );
  707. #else
  708. return NULL;
  709. #endif
  710. }
  711. #else // configSUPPORT_STATIC_ALLOCATION == 0 && configSUPPORT_DYNAMIC_ALLOCATION == 1
  712. osSemaphoreId sema;
  713. if (count == 1) {
  714. vSemaphoreCreateBinary(sema);
  715. return sema;
  716. }
  717. else {
  718. #if (configUSE_COUNTING_SEMAPHORES == 1 )
  719. return xSemaphoreCreateCounting(count, count);
  720. #else
  721. return NULL;
  722. #endif
  723. }
  724. #endif
  725. }
  726. /**
  727. * @brief Wait until a Semaphore token becomes available
  728. * @param semaphore_id semaphore object referenced with \ref osSemaphore.
  729. * @param millisec timeout value or 0 in case of no time-out.
  730. * @retval number of available tokens, or -1 in case of incorrect parameters.
  731. * @note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
  732. */
  733. int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec)
  734. {
  735. TickType_t ticks;
  736. portBASE_TYPE taskWoken = pdFALSE;
  737. if (semaphore_id == NULL) {
  738. return osErrorParameter;
  739. }
  740. ticks = 0;
  741. if (millisec == osWaitForever) {
  742. ticks = portMAX_DELAY;
  743. }
  744. else if (millisec != 0) {
  745. ticks = millisec / portTICK_PERIOD_MS;
  746. if (ticks == 0) {
  747. ticks = 1;
  748. }
  749. }
  750. if (inHandlerMode()) {
  751. if (xSemaphoreTakeFromISR(semaphore_id, &taskWoken) != pdTRUE) {
  752. return osErrorOS;
  753. }
  754. portEND_SWITCHING_ISR(taskWoken);
  755. }
  756. else if (xSemaphoreTake(semaphore_id, ticks) != pdTRUE) {
  757. return osErrorOS;
  758. }
  759. return osOK;
  760. }
  761. /**
  762. * @brief Release a Semaphore token
  763. * @param semaphore_id semaphore object referenced with \ref osSemaphore.
  764. * @retval status code that indicates the execution status of the function.
  765. * @note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS.
  766. */
  767. osStatus osSemaphoreRelease (osSemaphoreId semaphore_id)
  768. {
  769. osStatus result = osOK;
  770. portBASE_TYPE taskWoken = pdFALSE;
  771. if (inHandlerMode()) {
  772. if (xSemaphoreGiveFromISR(semaphore_id, &taskWoken) != pdTRUE) {
  773. return osErrorOS;
  774. }
  775. portEND_SWITCHING_ISR(taskWoken);
  776. }
  777. else {
  778. if (xSemaphoreGive(semaphore_id) != pdTRUE) {
  779. result = osErrorOS;
  780. }
  781. }
  782. return result;
  783. }
  784. /**
  785. * @brief Delete a Semaphore
  786. * @param semaphore_id semaphore object referenced with \ref osSemaphore.
  787. * @retval status code that indicates the execution status of the function.
  788. * @note MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be consistent in every CMSIS-RTOS.
  789. */
  790. osStatus osSemaphoreDelete (osSemaphoreId semaphore_id)
  791. {
  792. if (inHandlerMode()) {
  793. return osErrorISR;
  794. }
  795. vSemaphoreDelete(semaphore_id);
  796. return osOK;
  797. }
  798. #endif /* Use Semaphores */
  799. /******************* Memory Pool Management Functions ***********************/
  800. #if (defined (osFeature_Pool) && (osFeature_Pool != 0))
  801. //TODO
  802. //This is a primitive and inefficient wrapper around the existing FreeRTOS memory management.
  803. //A better implementation will have to modify heap_x.c!
  804. typedef struct os_pool_cb {
  805. void *pool;
  806. uint8_t *markers;
  807. uint32_t pool_sz;
  808. uint32_t item_sz;
  809. uint32_t currentIndex;
  810. } os_pool_cb_t;
  811. /**
  812. * @brief Create and Initialize a memory pool
  813. * @param pool_def memory pool definition referenced with \ref osPool.
  814. * @retval memory pool ID for reference by other functions or NULL in case of error.
  815. * @note MUST REMAIN UNCHANGED: \b osPoolCreate shall be consistent in every CMSIS-RTOS.
  816. */
  817. osPoolId osPoolCreate (const osPoolDef_t *pool_def)
  818. {
  819. #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
  820. osPoolId thePool;
  821. int itemSize = 4 * ((pool_def->item_sz + 3) / 4);
  822. uint32_t i;
  823. /* First have to allocate memory for the pool control block. */
  824. thePool = pvPortMalloc(sizeof(os_pool_cb_t));
  825. if (thePool) {
  826. thePool->pool_sz = pool_def->pool_sz;
  827. thePool->item_sz = itemSize;
  828. thePool->currentIndex = 0;
  829. /* Memory for markers */
  830. thePool->markers = pvPortMalloc(pool_def->pool_sz);
  831. if (thePool->markers) {
  832. /* Now allocate the pool itself. */
  833. thePool->pool = pvPortMalloc(pool_def->pool_sz * itemSize);
  834. if (thePool->pool) {
  835. for (i = 0; i < pool_def->pool_sz; i++) {
  836. thePool->markers[i] = 0;
  837. }
  838. }
  839. else {
  840. vPortFree(thePool->markers);
  841. vPortFree(thePool);
  842. thePool = NULL;
  843. }
  844. }
  845. else {
  846. vPortFree(thePool);
  847. thePool = NULL;
  848. }
  849. }
  850. return thePool;
  851. #else
  852. return NULL;
  853. #endif
  854. }
  855. /**
  856. * @brief Allocate a memory block from a memory pool
  857. * @param pool_id memory pool ID obtain referenced with \ref osPoolCreate.
  858. * @retval address of the allocated memory block or NULL in case of no memory available.
  859. * @note MUST REMAIN UNCHANGED: \b osPoolAlloc shall be consistent in every CMSIS-RTOS.
  860. */
  861. void *osPoolAlloc (osPoolId pool_id)
  862. {
  863. int dummy = 0;
  864. void *p = NULL;
  865. uint32_t i;
  866. uint32_t index;
  867. if (inHandlerMode()) {
  868. dummy = portSET_INTERRUPT_MASK_FROM_ISR();
  869. }
  870. else {
  871. vPortEnterCritical();
  872. }
  873. for (i = 0; i < pool_id->pool_sz; i++) {
  874. index = pool_id->currentIndex + i;
  875. if (index >= pool_id->pool_sz) {
  876. index = 0;
  877. }
  878. if (pool_id->markers[index] == 0) {
  879. pool_id->markers[index] = 1;
  880. p = (void *)((uint32_t)(pool_id->pool) + (index * pool_id->item_sz));
  881. pool_id->currentIndex = index;
  882. break;
  883. }
  884. }
  885. if (inHandlerMode()) {
  886. portCLEAR_INTERRUPT_MASK_FROM_ISR(dummy);
  887. }
  888. else {
  889. vPortExitCritical();
  890. }
  891. return p;
  892. }
  893. /**
  894. * @brief Allocate a memory block from a memory pool and set memory block to zero
  895. * @param pool_id memory pool ID obtain referenced with \ref osPoolCreate.
  896. * @retval address of the allocated memory block or NULL in case of no memory available.
  897. * @note MUST REMAIN UNCHANGED: \b osPoolCAlloc shall be consistent in every CMSIS-RTOS.
  898. */
  899. void *osPoolCAlloc (osPoolId pool_id)
  900. {
  901. void *p = osPoolAlloc(pool_id);
  902. if (p != NULL)
  903. {
  904. memset(p, 0, sizeof(pool_id->pool_sz));
  905. }
  906. return p;
  907. }
  908. /**
  909. * @brief Return an allocated memory block back to a specific memory pool
  910. * @param pool_id memory pool ID obtain referenced with \ref osPoolCreate.
  911. * @param block address of the allocated memory block that is returned to the memory pool.
  912. * @retval status code that indicates the execution status of the function.
  913. * @note MUST REMAIN UNCHANGED: \b osPoolFree shall be consistent in every CMSIS-RTOS.
  914. */
  915. osStatus osPoolFree (osPoolId pool_id, void *block)
  916. {
  917. uint32_t index;
  918. if (pool_id == NULL) {
  919. return osErrorParameter;
  920. }
  921. if (block == NULL) {
  922. return osErrorParameter;
  923. }
  924. if (block < pool_id->pool) {
  925. return osErrorParameter;
  926. }
  927. index = (uint32_t)block - (uint32_t)(pool_id->pool);
  928. if (index % pool_id->item_sz) {
  929. return osErrorParameter;
  930. }
  931. index = index / pool_id->item_sz;
  932. if (index >= pool_id->pool_sz) {
  933. return osErrorParameter;
  934. }
  935. pool_id->markers[index] = 0;
  936. return osOK;
  937. }
  938. #endif /* Use Memory Pool Management */
  939. /******************* Message Queue Management Functions *********************/
  940. #if (defined (osFeature_MessageQ) && (osFeature_MessageQ != 0)) /* Use Message Queues */
  941. /**
  942. * @brief Create and Initialize a Message Queue
  943. * @param queue_def queue definition referenced with \ref osMessageQ.
  944. * @param thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
  945. * @retval message queue ID for reference by other functions or NULL in case of error.
  946. * @note MUST REMAIN UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS.
  947. */
  948. osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id)
  949. {
  950. (void) thread_id;
  951. #if( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
  952. if ((queue_def->buffer != NULL) && (queue_def->controlblock != NULL)) {
  953. return xQueueCreateStatic(queue_def->queue_sz, queue_def->item_sz, queue_def->buffer, queue_def->controlblock);
  954. }
  955. else {
  956. return xQueueCreate(queue_def->queue_sz, queue_def->item_sz);
  957. }
  958. #elif ( configSUPPORT_STATIC_ALLOCATION == 1 )
  959. return xQueueCreateStatic(queue_def->queue_sz, queue_def->item_sz, queue_def->buffer, queue_def->controlblock);
  960. #else
  961. return xQueueCreate(queue_def->queue_sz, queue_def->item_sz);
  962. #endif
  963. }
  964. /**
  965. * @brief Put a Message to a Queue.
  966. * @param queue_id message queue ID obtained with \ref osMessageCreate.
  967. * @param info message information.
  968. * @param millisec timeout value or 0 in case of no time-out.
  969. * @retval status code that indicates the execution status of the function.
  970. * @note MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent in every CMSIS-RTOS.
  971. */
  972. osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec)
  973. {
  974. portBASE_TYPE taskWoken = pdFALSE;
  975. TickType_t ticks;
  976. ticks = millisec / portTICK_PERIOD_MS;
  977. if (ticks == 0) {
  978. ticks = 1;
  979. }
  980. if (inHandlerMode()) {
  981. if (xQueueSendFromISR(queue_id, &info, &taskWoken) != pdTRUE) {
  982. return osErrorOS;
  983. }
  984. portEND_SWITCHING_ISR(taskWoken);
  985. }
  986. else {
  987. if (xQueueSend(queue_id, &info, ticks) != pdTRUE) {
  988. return osErrorOS;
  989. }
  990. }
  991. return osOK;
  992. }
  993. /**
  994. * @brief Get a Message or Wait for a Message from a Queue.
  995. * @param queue_id message queue ID obtained with \ref osMessageCreate.
  996. * @param millisec timeout value or 0 in case of no time-out.
  997. * @retval event information that includes status code.
  998. * @note MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS.
  999. */
  1000. osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec)
  1001. {
  1002. portBASE_TYPE taskWoken;
  1003. TickType_t ticks;
  1004. osEvent event;
  1005. event.def.message_id = queue_id;
  1006. event.value.v = 0;
  1007. if (queue_id == NULL) {
  1008. event.status = osErrorParameter;
  1009. return event;
  1010. }
  1011. taskWoken = pdFALSE;
  1012. ticks = 0;
  1013. if (millisec == osWaitForever) {
  1014. ticks = portMAX_DELAY;
  1015. }
  1016. else if (millisec != 0) {
  1017. ticks = millisec / portTICK_PERIOD_MS;
  1018. if (ticks == 0) {
  1019. ticks = 1;
  1020. }
  1021. }
  1022. if (inHandlerMode()) {
  1023. if (xQueueReceiveFromISR(queue_id, &event.value.v, &taskWoken) == pdTRUE) {
  1024. /* We have mail */
  1025. event.status = osEventMessage;
  1026. }
  1027. else {
  1028. event.status = osOK;
  1029. }
  1030. portEND_SWITCHING_ISR(taskWoken);
  1031. }
  1032. else {
  1033. if (xQueueReceive(queue_id, &event.value.v, ticks) == pdTRUE) {
  1034. /* We have mail */
  1035. event.status = osEventMessage;
  1036. }
  1037. else {
  1038. event.status = (ticks == 0) ? osOK : osEventTimeout;
  1039. }
  1040. }
  1041. return event;
  1042. }
  1043. #endif /* Use Message Queues */
  1044. /******************** Mail Queue Management Functions ***********************/
  1045. #if (defined (osFeature_MailQ) && (osFeature_MailQ != 0)) /* Use Mail Queues */
  1046. typedef struct os_mailQ_cb {
  1047. const osMailQDef_t *queue_def;
  1048. QueueHandle_t handle;
  1049. osPoolId pool;
  1050. } os_mailQ_cb_t;
  1051. /**
  1052. * @brief Create and Initialize mail queue
  1053. * @param queue_def reference to the mail queue definition obtain with \ref osMailQ
  1054. * @param thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
  1055. * @retval mail queue ID for reference by other functions or NULL in case of error.
  1056. * @note MUST REMAIN UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS.
  1057. */
  1058. osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id)
  1059. {
  1060. #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
  1061. (void) thread_id;
  1062. osPoolDef_t pool_def = {queue_def->queue_sz, queue_def->item_sz, NULL};
  1063. /* Create a mail queue control block */
  1064. *(queue_def->cb) = pvPortMalloc(sizeof(struct os_mailQ_cb));
  1065. if (*(queue_def->cb) == NULL) {
  1066. return NULL;
  1067. }
  1068. (*(queue_def->cb))->queue_def = queue_def;
  1069. /* Create a queue in FreeRTOS */
  1070. (*(queue_def->cb))->handle = xQueueCreate(queue_def->queue_sz, sizeof(void *));
  1071. if ((*(queue_def->cb))->handle == NULL) {
  1072. vPortFree(*(queue_def->cb));
  1073. return NULL;
  1074. }
  1075. /* Create a mail pool */
  1076. (*(queue_def->cb))->pool = osPoolCreate(&pool_def);
  1077. if ((*(queue_def->cb))->pool == NULL) {
  1078. //TODO: Delete queue. How to do it in FreeRTOS?
  1079. vPortFree(*(queue_def->cb));
  1080. return NULL;
  1081. }
  1082. return *(queue_def->cb);
  1083. #else
  1084. return NULL;
  1085. #endif
  1086. }
  1087. /**
  1088. * @brief Allocate a memory block from a mail
  1089. * @param queue_id mail queue ID obtained with \ref osMailCreate.
  1090. * @param millisec timeout value or 0 in case of no time-out.
  1091. * @retval pointer to memory block that can be filled with mail or NULL in case error.
  1092. * @note MUST REMAIN UNCHANGED: \b osMailAlloc shall be consistent in every CMSIS-RTOS.
  1093. */
  1094. void *osMailAlloc (osMailQId queue_id, uint32_t millisec)
  1095. {
  1096. (void) millisec;
  1097. void *p;
  1098. if (queue_id == NULL) {
  1099. return NULL;
  1100. }
  1101. p = osPoolAlloc(queue_id->pool);
  1102. return p;
  1103. }
  1104. /**
  1105. * @brief Allocate a memory block from a mail and set memory block to zero
  1106. * @param queue_id mail queue ID obtained with \ref osMailCreate.
  1107. * @param millisec timeout value or 0 in case of no time-out.
  1108. * @retval pointer to memory block that can be filled with mail or NULL in case error.
  1109. * @note MUST REMAIN UNCHANGED: \b osMailCAlloc shall be consistent in every CMSIS-RTOS.
  1110. */
  1111. void *osMailCAlloc (osMailQId queue_id, uint32_t millisec)
  1112. {
  1113. uint32_t i;
  1114. void *p = osMailAlloc(queue_id, millisec);
  1115. if (p) {
  1116. for (i = 0; i < queue_id->queue_def->item_sz; i++) {
  1117. ((uint8_t *)p)[i] = 0;
  1118. }
  1119. }
  1120. return p;
  1121. }
  1122. /**
  1123. * @brief Put a mail to a queue
  1124. * @param queue_id mail queue ID obtained with \ref osMailCreate.
  1125. * @param mail memory block previously allocated with \ref osMailAlloc or \ref osMailCAlloc.
  1126. * @retval status code that indicates the execution status of the function.
  1127. * @note MUST REMAIN UNCHANGED: \b osMailPut shall be consistent in every CMSIS-RTOS.
  1128. */
  1129. osStatus osMailPut (osMailQId queue_id, void *mail)
  1130. {
  1131. portBASE_TYPE taskWoken;
  1132. if (queue_id == NULL) {
  1133. return osErrorParameter;
  1134. }
  1135. taskWoken = pdFALSE;
  1136. if (inHandlerMode()) {
  1137. if (xQueueSendFromISR(queue_id->handle, &mail, &taskWoken) != pdTRUE) {
  1138. return osErrorOS;
  1139. }
  1140. portEND_SWITCHING_ISR(taskWoken);
  1141. }
  1142. else {
  1143. if (xQueueSend(queue_id->handle, &mail, 0) != pdTRUE) {
  1144. return osErrorOS;
  1145. }
  1146. }
  1147. return osOK;
  1148. }
  1149. /**
  1150. * @brief Get a mail from a queue
  1151. * @param queue_id mail queue ID obtained with \ref osMailCreate.
  1152. * @param millisec timeout value or 0 in case of no time-out
  1153. * @retval event that contains mail information or error code.
  1154. * @note MUST REMAIN UNCHANGED: \b osMailGet shall be consistent in every CMSIS-RTOS.
  1155. */
  1156. osEvent osMailGet (osMailQId queue_id, uint32_t millisec)
  1157. {
  1158. portBASE_TYPE taskWoken;
  1159. TickType_t ticks;
  1160. osEvent event;
  1161. event.def.mail_id = queue_id;
  1162. if (queue_id == NULL) {
  1163. event.status = osErrorParameter;
  1164. return event;
  1165. }
  1166. taskWoken = pdFALSE;
  1167. ticks = 0;
  1168. if (millisec == osWaitForever) {
  1169. ticks = portMAX_DELAY;
  1170. }
  1171. else if (millisec != 0) {
  1172. ticks = millisec / portTICK_PERIOD_MS;
  1173. if (ticks == 0) {
  1174. ticks = 1;
  1175. }
  1176. }
  1177. if (inHandlerMode()) {
  1178. if (xQueueReceiveFromISR(queue_id->handle, &event.value.p, &taskWoken) == pdTRUE) {
  1179. /* We have mail */
  1180. event.status = osEventMail;
  1181. }
  1182. else {
  1183. event.status = osOK;
  1184. }
  1185. portEND_SWITCHING_ISR(taskWoken);
  1186. }
  1187. else {
  1188. if (xQueueReceive(queue_id->handle, &event.value.p, ticks) == pdTRUE) {
  1189. /* We have mail */
  1190. event.status = osEventMail;
  1191. }
  1192. else {
  1193. event.status = (ticks == 0) ? osOK : osEventTimeout;
  1194. }
  1195. }
  1196. return event;
  1197. }
  1198. /**
  1199. * @brief Free a memory block from a mail
  1200. * @param queue_id mail queue ID obtained with \ref osMailCreate.
  1201. * @param mail pointer to the memory block that was obtained with \ref osMailGet.
  1202. * @retval status code that indicates the execution status of the function.
  1203. * @note MUST REMAIN UNCHANGED: \b osMailFree shall be consistent in every CMSIS-RTOS.
  1204. */
  1205. osStatus osMailFree (osMailQId queue_id, void *mail)
  1206. {
  1207. if (queue_id == NULL) {
  1208. return osErrorParameter;
  1209. }
  1210. return osPoolFree(queue_id->pool, mail);
  1211. }
  1212. #endif /* Use Mail Queues */
  1213. /*************************** Additional specific APIs to Free RTOS ************/
  1214. /**
  1215. * @brief Handles the tick increment
  1216. * @param none.
  1217. * @retval none.
  1218. */
  1219. void osSystickHandler(void)
  1220. {
  1221. #if (INCLUDE_xTaskGetSchedulerState == 1 )
  1222. if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
  1223. {
  1224. #endif /* INCLUDE_xTaskGetSchedulerState */
  1225. xPortSysTickHandler();
  1226. #if (INCLUDE_xTaskGetSchedulerState == 1 )
  1227. }
  1228. #endif /* INCLUDE_xTaskGetSchedulerState */
  1229. }
  1230. #if ( INCLUDE_eTaskGetState == 1 )
  1231. /**
  1232. * @brief Obtain the state of any thread.
  1233. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
  1234. * @retval the stae of the thread, states are encoded by the osThreadState enumerated type.
  1235. */
  1236. osThreadState osThreadGetState(osThreadId thread_id)
  1237. {
  1238. eTaskState ThreadState;
  1239. osThreadState result;
  1240. ThreadState = eTaskGetState(thread_id);
  1241. switch (ThreadState)
  1242. {
  1243. case eRunning :
  1244. result = osThreadRunning;
  1245. break;
  1246. case eReady :
  1247. result = osThreadReady;
  1248. break;
  1249. case eBlocked :
  1250. result = osThreadBlocked;
  1251. break;
  1252. case eSuspended :
  1253. result = osThreadSuspended;
  1254. break;
  1255. case eDeleted :
  1256. result = osThreadDeleted;
  1257. break;
  1258. default:
  1259. result = osThreadError;
  1260. }
  1261. return result;
  1262. }
  1263. #endif /* INCLUDE_eTaskGetState */
  1264. #if (INCLUDE_eTaskGetState == 1)
  1265. /**
  1266. * @brief Check if a thread is already suspended or not.
  1267. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
  1268. * @retval status code that indicates the execution status of the function.
  1269. */
  1270. osStatus osThreadIsSuspended(osThreadId thread_id)
  1271. {
  1272. if (eTaskGetState(thread_id) == eSuspended)
  1273. return osOK;
  1274. else
  1275. return osErrorOS;
  1276. }
  1277. #endif /* INCLUDE_eTaskGetState */
  1278. /**
  1279. * @brief Suspend execution of a thread.
  1280. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
  1281. * @retval status code that indicates the execution status of the function.
  1282. */
  1283. osStatus osThreadSuspend (osThreadId thread_id)
  1284. {
  1285. #if (INCLUDE_vTaskSuspend == 1)
  1286. vTaskSuspend(thread_id);
  1287. return osOK;
  1288. #else
  1289. return osErrorResource;
  1290. #endif
  1291. }
  1292. /**
  1293. * @brief Resume execution of a suspended thread.
  1294. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
  1295. * @retval status code that indicates the execution status of the function.
  1296. */
  1297. osStatus osThreadResume (osThreadId thread_id)
  1298. {
  1299. #if (INCLUDE_vTaskSuspend == 1)
  1300. if(inHandlerMode())
  1301. {
  1302. if (xTaskResumeFromISR(thread_id) == pdTRUE)
  1303. {
  1304. portYIELD_FROM_ISR(pdTRUE);
  1305. }
  1306. }
  1307. else
  1308. {
  1309. vTaskResume(thread_id);
  1310. }
  1311. return osOK;
  1312. #else
  1313. return osErrorResource;
  1314. #endif
  1315. }
  1316. /**
  1317. * @brief Suspend execution of a all active threads.
  1318. * @retval status code that indicates the execution status of the function.
  1319. */
  1320. osStatus osThreadSuspendAll (void)
  1321. {
  1322. vTaskSuspendAll();
  1323. return osOK;
  1324. }
  1325. /**
  1326. * @brief Resume execution of a all suspended threads.
  1327. * @retval status code that indicates the execution status of the function.
  1328. */
  1329. osStatus osThreadResumeAll (void)
  1330. {
  1331. if (xTaskResumeAll() == pdTRUE)
  1332. return osOK;
  1333. else
  1334. return osErrorOS;
  1335. }
  1336. /**
  1337. * @brief Delay a task until a specified time
  1338. * @param PreviousWakeTime Pointer to a variable that holds the time at which the
  1339. * task was last unblocked. PreviousWakeTime must be initialised with the current time
  1340. * prior to its first use (PreviousWakeTime = osKernelSysTick() )
  1341. * @param millisec time delay value
  1342. * @retval status code that indicates the execution status of the function.
  1343. */
  1344. osStatus osDelayUntil (uint32_t *PreviousWakeTime, uint32_t millisec)
  1345. {
  1346. #if INCLUDE_vTaskDelayUntil
  1347. TickType_t ticks = (millisec / portTICK_PERIOD_MS);
  1348. vTaskDelayUntil((TickType_t *) PreviousWakeTime, ticks ? ticks : 1);
  1349. return osOK;
  1350. #else
  1351. (void) millisec;
  1352. (void) PreviousWakeTime;
  1353. return osErrorResource;
  1354. #endif
  1355. }
  1356. /**
  1357. * @brief Abort the delay for a specific thread
  1358. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId
  1359. * @retval status code that indicates the execution status of the function.
  1360. */
  1361. osStatus osAbortDelay(osThreadId thread_id)
  1362. {
  1363. #if INCLUDE_xTaskAbortDelay
  1364. xTaskAbortDelay(thread_id);
  1365. return osOK;
  1366. #else
  1367. (void) thread_id;
  1368. return osErrorResource;
  1369. #endif
  1370. }
  1371. /**
  1372. * @brief Lists all the current threads, along with their current state
  1373. * and stack usage high water mark.
  1374. * @param buffer A buffer into which the above mentioned details
  1375. * will be written
  1376. * @retval status code that indicates the execution status of the function.
  1377. */
  1378. osStatus osThreadList (uint8_t *buffer)
  1379. {
  1380. #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) )
  1381. vTaskList((char *)buffer);
  1382. #endif
  1383. return osOK;
  1384. }
  1385. /**
  1386. * @brief Receive an item from a queue without removing the item from the queue.
  1387. * @param queue_id message queue ID obtained with \ref osMessageCreate.
  1388. * @param millisec timeout value or 0 in case of no time-out.
  1389. * @retval event information that includes status code.
  1390. */
  1391. osEvent osMessagePeek (osMessageQId queue_id, uint32_t millisec)
  1392. {
  1393. TickType_t ticks;
  1394. osEvent event;
  1395. event.def.message_id = queue_id;
  1396. if (queue_id == NULL) {
  1397. event.status = osErrorParameter;
  1398. return event;
  1399. }
  1400. ticks = 0;
  1401. if (millisec == osWaitForever) {
  1402. ticks = portMAX_DELAY;
  1403. }
  1404. else if (millisec != 0) {
  1405. ticks = millisec / portTICK_PERIOD_MS;
  1406. if (ticks == 0) {
  1407. ticks = 1;
  1408. }
  1409. }
  1410. if (xQueuePeek(queue_id, &event.value.v, ticks) == pdTRUE)
  1411. {
  1412. /* We have mail */
  1413. event.status = osEventMessage;
  1414. }
  1415. else
  1416. {
  1417. event.status = (ticks == 0) ? osOK : osEventTimeout;
  1418. }
  1419. return event;
  1420. }
  1421. /**
  1422. * @brief Get the number of messaged stored in a queue.
  1423. * @param queue_id message queue ID obtained with \ref osMessageCreate.
  1424. * @retval number of messages stored in a queue.
  1425. */
  1426. uint32_t osMessageWaiting(osMessageQId queue_id)
  1427. {
  1428. if (inHandlerMode()) {
  1429. return uxQueueMessagesWaitingFromISR(queue_id);
  1430. }
  1431. else
  1432. {
  1433. return uxQueueMessagesWaiting(queue_id);
  1434. }
  1435. }
  1436. /**
  1437. * @brief Get the available space in a message queue.
  1438. * @param queue_id message queue ID obtained with \ref osMessageCreate.
  1439. * @retval available space in a message queue.
  1440. */
  1441. uint32_t osMessageAvailableSpace(osMessageQId queue_id)
  1442. {
  1443. return uxQueueSpacesAvailable(queue_id);
  1444. }
  1445. /**
  1446. * @brief Delete a Message Queue
  1447. * @param queue_id message queue ID obtained with \ref osMessageCreate.
  1448. * @retval status code that indicates the execution status of the function.
  1449. */
  1450. osStatus osMessageDelete (osMessageQId queue_id)
  1451. {
  1452. if (inHandlerMode()) {
  1453. return osErrorISR;
  1454. }
  1455. vQueueDelete(queue_id);
  1456. return osOK;
  1457. }
  1458. /**
  1459. * @brief Create and Initialize a Recursive Mutex
  1460. * @param mutex_def mutex definition referenced with \ref osMutex.
  1461. * @retval mutex ID for reference by other functions or NULL in case of error..
  1462. */
  1463. osMutexId osRecursiveMutexCreate (const osMutexDef_t *mutex_def)
  1464. {
  1465. #if (configUSE_RECURSIVE_MUTEXES == 1)
  1466. #if( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
  1467. if (mutex_def->controlblock != NULL){
  1468. return xSemaphoreCreateRecursiveMutexStatic( mutex_def->controlblock );
  1469. }
  1470. else {
  1471. return xSemaphoreCreateRecursiveMutex();
  1472. }
  1473. #elif ( configSUPPORT_STATIC_ALLOCATION == 1 )
  1474. return xSemaphoreCreateRecursiveMutexStatic( mutex_def->controlblock );
  1475. #else
  1476. return xSemaphoreCreateRecursiveMutex();
  1477. #endif
  1478. #else
  1479. return NULL;
  1480. #endif
  1481. }
  1482. /**
  1483. * @brief Release a Recursive Mutex
  1484. * @param mutex_id mutex ID obtained by \ref osRecursiveMutexCreate.
  1485. * @retval status code that indicates the execution status of the function.
  1486. */
  1487. osStatus osRecursiveMutexRelease (osMutexId mutex_id)
  1488. {
  1489. #if (configUSE_RECURSIVE_MUTEXES == 1)
  1490. osStatus result = osOK;
  1491. if (xSemaphoreGiveRecursive(mutex_id) != pdTRUE)
  1492. {
  1493. result = osErrorOS;
  1494. }
  1495. return result;
  1496. #else
  1497. return osErrorResource;
  1498. #endif
  1499. }
  1500. /**
  1501. * @brief Release a Recursive Mutex
  1502. * @param mutex_id mutex ID obtained by \ref osRecursiveMutexCreate.
  1503. * @param millisec timeout value or 0 in case of no time-out.
  1504. * @retval status code that indicates the execution status of the function.
  1505. */
  1506. osStatus osRecursiveMutexWait (osMutexId mutex_id, uint32_t millisec)
  1507. {
  1508. #if (configUSE_RECURSIVE_MUTEXES == 1)
  1509. TickType_t ticks;
  1510. if (mutex_id == NULL)
  1511. {
  1512. return osErrorParameter;
  1513. }
  1514. ticks = 0;
  1515. if (millisec == osWaitForever)
  1516. {
  1517. ticks = portMAX_DELAY;
  1518. }
  1519. else if (millisec != 0)
  1520. {
  1521. ticks = millisec / portTICK_PERIOD_MS;
  1522. if (ticks == 0)
  1523. {
  1524. ticks = 1;
  1525. }
  1526. }
  1527. if (xSemaphoreTakeRecursive(mutex_id, ticks) != pdTRUE)
  1528. {
  1529. return osErrorOS;
  1530. }
  1531. return osOK;
  1532. #else
  1533. return osErrorResource;
  1534. #endif
  1535. }
  1536. /**
  1537. * @brief Returns the current count value of a counting semaphore
  1538. * @param semaphore_id semaphore_id ID obtained by \ref osSemaphoreCreate.
  1539. * @retval count value
  1540. */
  1541. uint32_t osSemaphoreGetCount(osSemaphoreId semaphore_id)
  1542. {
  1543. return uxSemaphoreGetCount(semaphore_id);
  1544. }