cmsis_os2.c 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924
  1. /* --------------------------------------------------------------------------
  2. * Portions Copyright © 2019 STMicroelectronics International N.V. All rights reserved.
  3. * Copyright (c) 2013-2019 Arm Limited. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the License); you may
  8. * not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * Name: cmsis_os2.c
  20. * Purpose: CMSIS RTOS2 wrapper for FreeRTOS
  21. *
  22. *---------------------------------------------------------------------------*/
  23. #include <string.h>
  24. #include "cmsis_os2.h" // ::CMSIS:RTOS2
  25. #include "cmsis_compiler.h"
  26. #include "FreeRTOS.h" // ARM.FreeRTOS::RTOS:Core
  27. #include "task.h" // ARM.FreeRTOS::RTOS:Core
  28. #include "event_groups.h" // ARM.FreeRTOS::RTOS:Event Groups
  29. #include "semphr.h" // ARM.FreeRTOS::RTOS:Core
  30. /*---------------------------------------------------------------------------*/
  31. #ifndef __ARM_ARCH_6M__
  32. #define __ARM_ARCH_6M__ 0
  33. #endif
  34. #ifndef __ARM_ARCH_7M__
  35. #define __ARM_ARCH_7M__ 0
  36. #endif
  37. #ifndef __ARM_ARCH_7EM__
  38. #define __ARM_ARCH_7EM__ 0
  39. #endif
  40. #ifndef __ARM_ARCH_8M_MAIN__
  41. #define __ARM_ARCH_8M_MAIN__ 0
  42. #endif
  43. #ifndef __ARM_ARCH_7A__
  44. #define __ARM_ARCH_7A__ 0
  45. #endif
  46. #if ((__ARM_ARCH_7M__ == 1U) || \
  47. (__ARM_ARCH_7EM__ == 1U) || \
  48. (__ARM_ARCH_8M_MAIN__ == 1U))
  49. #define IS_IRQ_MASKED() ((__get_PRIMASK() != 0U) || (__get_BASEPRI() != 0U))
  50. #elif (__ARM_ARCH_6M__ == 1U)
  51. #define IS_IRQ_MASKED() (__get_PRIMASK() != 0U)
  52. #elif (__ARM_ARCH_7A__ == 1U)
  53. /* CPSR mask bits */
  54. #define CPSR_MASKBIT_I 0x80U
  55. #define IS_IRQ_MASKED() ((__get_CPSR() & CPSR_MASKBIT_I) != 0U)
  56. #else
  57. #define IS_IRQ_MASKED() (__get_PRIMASK() != 0U)
  58. #endif
  59. #if (__ARM_ARCH_7A__ == 1U)
  60. /* CPSR mode bitmasks */
  61. #define CPSR_MODE_USER 0x10U
  62. #define CPSR_MODE_SYSTEM 0x1FU
  63. #define IS_IRQ_MODE() ((__get_mode() != CPSR_MODE_USER) && (__get_mode() != CPSR_MODE_SYSTEM))
  64. #else
  65. #define IS_IRQ_MODE() (__get_IPSR() != 0U)
  66. #endif
  67. #define IS_IRQ() (IS_IRQ_MODE() || (IS_IRQ_MASKED() && (KernelState == osKernelRunning)))
  68. /* Limits */
  69. #define MAX_BITS_TASK_NOTIFY 31U
  70. #define MAX_BITS_EVENT_GROUPS 24U
  71. #define THREAD_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_TASK_NOTIFY) - 1U))
  72. #define EVENT_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_EVENT_GROUPS) - 1U))
  73. /* Kernel version and identification string definition (major.minor.rev: mmnnnrrrr dec) */
  74. #define KERNEL_VERSION (((uint32_t)tskKERNEL_VERSION_MAJOR * 10000000UL) | \
  75. ((uint32_t)tskKERNEL_VERSION_MINOR * 10000UL) | \
  76. ((uint32_t)tskKERNEL_VERSION_BUILD * 1UL))
  77. #define KERNEL_ID ("FreeRTOS " tskKERNEL_VERSION_NUMBER)
  78. /* Timer callback information structure definition */
  79. typedef struct {
  80. osTimerFunc_t func;
  81. void *arg;
  82. } TimerCallback_t;
  83. /* Kernel initialization state */
  84. static osKernelState_t KernelState = osKernelInactive;
  85. /*
  86. Heap region definition used by heap_5 variant
  87. Define configAPPLICATION_ALLOCATED_HEAP as nonzero value in FreeRTOSConfig.h if
  88. heap regions are already defined and vPortDefineHeapRegions is called in application.
  89. Otherwise vPortDefineHeapRegions will be called by osKernelInitialize using
  90. definition configHEAP_5_REGIONS as parameter. Overriding configHEAP_5_REGIONS
  91. is possible by defining it globally or in FreeRTOSConfig.h.
  92. */
  93. #if defined(USE_FREERTOS_HEAP_5)
  94. #if (configAPPLICATION_ALLOCATED_HEAP == 0)
  95. /*
  96. FreeRTOS heap is not defined by the application.
  97. Single region of size configTOTAL_HEAP_SIZE (defined in FreeRTOSConfig.h)
  98. is provided by default. Define configHEAP_5_REGIONS to provide custom
  99. HeapRegion_t array.
  100. */
  101. #define HEAP_5_REGION_SETUP 1
  102. #ifndef configHEAP_5_REGIONS
  103. #define configHEAP_5_REGIONS xHeapRegions
  104. static uint8_t ucHeap[configTOTAL_HEAP_SIZE];
  105. static HeapRegion_t xHeapRegions[] = {
  106. { ucHeap, configTOTAL_HEAP_SIZE },
  107. { NULL, 0 }
  108. };
  109. #else
  110. /* Global definition is provided to override default heap array */
  111. extern HeapRegion_t configHEAP_5_REGIONS[];
  112. #endif
  113. #else
  114. /*
  115. The application already defined the array used for the FreeRTOS heap and
  116. called vPortDefineHeapRegions to initialize heap.
  117. */
  118. #define HEAP_5_REGION_SETUP 0
  119. #endif /* configAPPLICATION_ALLOCATED_HEAP */
  120. #endif /* USE_FREERTOS_HEAP_5 */
  121. #if defined(SysTick)
  122. #undef SysTick_Handler
  123. /* CMSIS SysTick interrupt handler prototype */
  124. extern void SysTick_Handler (void);
  125. /* FreeRTOS tick timer interrupt handler prototype */
  126. extern void xPortSysTickHandler (void);
  127. /*
  128. SysTick handler implementation that also clears overflow flag.
  129. */
  130. void SysTick_Handler (void) {
  131. /* Clear overflow flag */
  132. SysTick->CTRL;
  133. if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
  134. /* Call tick handler */
  135. xPortSysTickHandler();
  136. }
  137. }
  138. #endif /* SysTick */
  139. /*
  140. Setup SVC to reset value.
  141. */
  142. __STATIC_INLINE void SVC_Setup (void) {
  143. #if (__ARM_ARCH_7A__ == 0U)
  144. /* Service Call interrupt might be configured before kernel start */
  145. /* and when its priority is lower or equal to BASEPRI, svc intruction */
  146. /* causes a Hard Fault. */
  147. /*
  148. * the call below has introduced a regression compared to revious release
  149. * The issue was logged under:https://github.com/ARM-software/CMSIS-FreeRTOS/issues/35
  150. * until it is correctly fixed, the code below is commented
  151. */
  152. /* NVIC_SetPriority (SVCall_IRQn, 0U); */
  153. #endif
  154. }
  155. /*---------------------------------------------------------------------------*/
  156. osStatus_t osKernelInitialize (void) {
  157. osStatus_t stat;
  158. if (IS_IRQ()) {
  159. stat = osErrorISR;
  160. }
  161. else {
  162. if (KernelState == osKernelInactive) {
  163. #if defined(USE_FREERTOS_HEAP_5) && (HEAP_5_REGION_SETUP == 1)
  164. vPortDefineHeapRegions (configHEAP_5_REGIONS);
  165. #endif
  166. KernelState = osKernelReady;
  167. stat = osOK;
  168. } else {
  169. stat = osError;
  170. }
  171. }
  172. return (stat);
  173. }
  174. osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size) {
  175. if (version != NULL) {
  176. /* Version encoding is major.minor.rev: mmnnnrrrr dec */
  177. version->api = KERNEL_VERSION;
  178. version->kernel = KERNEL_VERSION;
  179. }
  180. if ((id_buf != NULL) && (id_size != 0U)) {
  181. if (id_size > sizeof(KERNEL_ID)) {
  182. id_size = sizeof(KERNEL_ID);
  183. }
  184. memcpy(id_buf, KERNEL_ID, id_size);
  185. }
  186. return (osOK);
  187. }
  188. osKernelState_t osKernelGetState (void) {
  189. osKernelState_t state;
  190. switch (xTaskGetSchedulerState()) {
  191. case taskSCHEDULER_RUNNING:
  192. state = osKernelRunning;
  193. break;
  194. case taskSCHEDULER_SUSPENDED:
  195. state = osKernelLocked;
  196. break;
  197. case taskSCHEDULER_NOT_STARTED:
  198. default:
  199. if (KernelState == osKernelReady) {
  200. state = osKernelReady;
  201. } else {
  202. state = osKernelInactive;
  203. }
  204. break;
  205. }
  206. return (state);
  207. }
  208. osStatus_t osKernelStart (void) {
  209. osStatus_t stat;
  210. if (IS_IRQ()) {
  211. stat = osErrorISR;
  212. }
  213. else {
  214. if (KernelState == osKernelReady) {
  215. /* Ensure SVC priority is at the reset value */
  216. SVC_Setup();
  217. /* Change state to enable IRQ masking check */
  218. KernelState = osKernelRunning;
  219. /* Start the kernel scheduler */
  220. vTaskStartScheduler();
  221. stat = osOK;
  222. } else {
  223. stat = osError;
  224. }
  225. }
  226. return (stat);
  227. }
  228. int32_t osKernelLock (void) {
  229. int32_t lock;
  230. if (IS_IRQ()) {
  231. lock = (int32_t)osErrorISR;
  232. }
  233. else {
  234. switch (xTaskGetSchedulerState()) {
  235. case taskSCHEDULER_SUSPENDED:
  236. lock = 1;
  237. break;
  238. case taskSCHEDULER_RUNNING:
  239. vTaskSuspendAll();
  240. lock = 0;
  241. break;
  242. case taskSCHEDULER_NOT_STARTED:
  243. default:
  244. lock = (int32_t)osError;
  245. break;
  246. }
  247. }
  248. return (lock);
  249. }
  250. int32_t osKernelUnlock (void) {
  251. int32_t lock;
  252. if (IS_IRQ()) {
  253. lock = (int32_t)osErrorISR;
  254. }
  255. else {
  256. switch (xTaskGetSchedulerState()) {
  257. case taskSCHEDULER_SUSPENDED:
  258. lock = 1;
  259. if (xTaskResumeAll() != pdTRUE) {
  260. if (xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) {
  261. lock = (int32_t)osError;
  262. }
  263. }
  264. break;
  265. case taskSCHEDULER_RUNNING:
  266. lock = 0;
  267. break;
  268. case taskSCHEDULER_NOT_STARTED:
  269. default:
  270. lock = (int32_t)osError;
  271. break;
  272. }
  273. }
  274. return (lock);
  275. }
  276. int32_t osKernelRestoreLock (int32_t lock) {
  277. if (IS_IRQ()) {
  278. lock = (int32_t)osErrorISR;
  279. }
  280. else {
  281. switch (xTaskGetSchedulerState()) {
  282. case taskSCHEDULER_SUSPENDED:
  283. case taskSCHEDULER_RUNNING:
  284. if (lock == 1) {
  285. vTaskSuspendAll();
  286. }
  287. else {
  288. if (lock != 0) {
  289. lock = (int32_t)osError;
  290. }
  291. else {
  292. if (xTaskResumeAll() != pdTRUE) {
  293. if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) {
  294. lock = (int32_t)osError;
  295. }
  296. }
  297. }
  298. }
  299. break;
  300. case taskSCHEDULER_NOT_STARTED:
  301. default:
  302. lock = (int32_t)osError;
  303. break;
  304. }
  305. }
  306. return (lock);
  307. }
  308. uint32_t osKernelGetTickCount (void) {
  309. TickType_t ticks;
  310. if (IS_IRQ()) {
  311. ticks = xTaskGetTickCountFromISR();
  312. } else {
  313. ticks = xTaskGetTickCount();
  314. }
  315. return (ticks);
  316. }
  317. uint32_t osKernelGetTickFreq (void) {
  318. return (configTICK_RATE_HZ);
  319. }
  320. uint32_t osKernelGetSysTimerCount (void) {
  321. uint32_t irqmask = IS_IRQ_MASKED();
  322. TickType_t ticks;
  323. uint32_t val;
  324. __disable_irq();
  325. ticks = xTaskGetTickCount();
  326. val = ticks * ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
  327. if (irqmask == 0U) {
  328. __enable_irq();
  329. }
  330. return (val);
  331. }
  332. uint32_t osKernelGetSysTimerFreq (void) {
  333. return (configCPU_CLOCK_HZ);
  334. }
  335. /*---------------------------------------------------------------------------*/
  336. osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr) {
  337. const char *name;
  338. uint32_t stack;
  339. TaskHandle_t hTask;
  340. UBaseType_t prio;
  341. int32_t mem;
  342. hTask = NULL;
  343. if (!IS_IRQ() && (func != NULL)) {
  344. stack = configMINIMAL_STACK_SIZE;
  345. prio = (UBaseType_t)osPriorityNormal;
  346. name = NULL;
  347. mem = -1;
  348. if (attr != NULL) {
  349. if (attr->name != NULL) {
  350. name = attr->name;
  351. }
  352. if (attr->priority != osPriorityNone) {
  353. prio = (UBaseType_t)attr->priority;
  354. }
  355. if ((prio < osPriorityIdle) || (prio > osPriorityISR) || ((attr->attr_bits & osThreadJoinable) == osThreadJoinable)) {
  356. return (NULL);
  357. }
  358. if (attr->stack_size > 0U) {
  359. /* In FreeRTOS stack is not in bytes, but in sizeof(StackType_t) which is 4 on ARM ports. */
  360. /* Stack size should be therefore 4 byte aligned in order to avoid division caused side effects */
  361. stack = attr->stack_size / sizeof(StackType_t);
  362. }
  363. if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticTask_t)) &&
  364. (attr->stack_mem != NULL) && (attr->stack_size > 0U)) {
  365. mem = 1;
  366. }
  367. else {
  368. if ((attr->cb_mem == NULL) && (attr->cb_size == 0U) && (attr->stack_mem == NULL)) {
  369. mem = 0;
  370. }
  371. }
  372. }
  373. else {
  374. mem = 0;
  375. }
  376. if (mem == 1) {
  377. hTask = xTaskCreateStatic ((TaskFunction_t)func, name, stack, argument, prio, (StackType_t *)attr->stack_mem,
  378. (StaticTask_t *)attr->cb_mem);
  379. }
  380. else {
  381. if (mem == 0) {
  382. if (xTaskCreate ((TaskFunction_t)func, name, (uint16_t)stack, argument, prio, &hTask) != pdPASS) {
  383. hTask = NULL;
  384. }
  385. }
  386. }
  387. }
  388. return ((osThreadId_t)hTask);
  389. }
  390. const char *osThreadGetName (osThreadId_t thread_id) {
  391. TaskHandle_t hTask = (TaskHandle_t)thread_id;
  392. const char *name;
  393. if (IS_IRQ() || (hTask == NULL)) {
  394. name = NULL;
  395. } else {
  396. name = pcTaskGetName (hTask);
  397. }
  398. return (name);
  399. }
  400. osThreadId_t osThreadGetId (void) {
  401. osThreadId_t id;
  402. id = (osThreadId_t)xTaskGetCurrentTaskHandle();
  403. return (id);
  404. }
  405. osThreadState_t osThreadGetState (osThreadId_t thread_id) {
  406. TaskHandle_t hTask = (TaskHandle_t)thread_id;
  407. osThreadState_t state;
  408. if (IS_IRQ() || (hTask == NULL)) {
  409. state = osThreadError;
  410. }
  411. else {
  412. switch (eTaskGetState (hTask)) {
  413. case eRunning: state = osThreadRunning; break;
  414. case eReady: state = osThreadReady; break;
  415. case eBlocked:
  416. case eSuspended: state = osThreadBlocked; break;
  417. case eDeleted: state = osThreadTerminated; break;
  418. case eInvalid:
  419. default: state = osThreadError; break;
  420. }
  421. }
  422. return (state);
  423. }
  424. uint32_t osThreadGetStackSpace (osThreadId_t thread_id) {
  425. TaskHandle_t hTask = (TaskHandle_t)thread_id;
  426. uint32_t sz;
  427. if (IS_IRQ() || (hTask == NULL)) {
  428. sz = 0U;
  429. } else {
  430. sz = (uint32_t)uxTaskGetStackHighWaterMark (hTask);
  431. }
  432. return (sz);
  433. }
  434. osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority) {
  435. TaskHandle_t hTask = (TaskHandle_t)thread_id;
  436. osStatus_t stat;
  437. if (IS_IRQ()) {
  438. stat = osErrorISR;
  439. }
  440. else if ((hTask == NULL) || (priority < osPriorityIdle) || (priority > osPriorityISR)) {
  441. stat = osErrorParameter;
  442. }
  443. else {
  444. stat = osOK;
  445. vTaskPrioritySet (hTask, (UBaseType_t)priority);
  446. }
  447. return (stat);
  448. }
  449. osPriority_t osThreadGetPriority (osThreadId_t thread_id) {
  450. TaskHandle_t hTask = (TaskHandle_t)thread_id;
  451. osPriority_t prio;
  452. if (IS_IRQ() || (hTask == NULL)) {
  453. prio = osPriorityError;
  454. } else {
  455. prio = (osPriority_t)uxTaskPriorityGet (hTask);
  456. }
  457. return (prio);
  458. }
  459. osStatus_t osThreadYield (void) {
  460. osStatus_t stat;
  461. if (IS_IRQ()) {
  462. stat = osErrorISR;
  463. } else {
  464. stat = osOK;
  465. taskYIELD();
  466. }
  467. return (stat);
  468. }
  469. osStatus_t osThreadSuspend (osThreadId_t thread_id) {
  470. TaskHandle_t hTask = (TaskHandle_t)thread_id;
  471. osStatus_t stat;
  472. if (IS_IRQ()) {
  473. stat = osErrorISR;
  474. }
  475. else if (hTask == NULL) {
  476. stat = osErrorParameter;
  477. }
  478. else {
  479. stat = osOK;
  480. vTaskSuspend (hTask);
  481. }
  482. return (stat);
  483. }
  484. osStatus_t osThreadResume (osThreadId_t thread_id) {
  485. TaskHandle_t hTask = (TaskHandle_t)thread_id;
  486. osStatus_t stat;
  487. if (IS_IRQ()) {
  488. stat = osErrorISR;
  489. }
  490. else if (hTask == NULL) {
  491. stat = osErrorParameter;
  492. }
  493. else {
  494. stat = osOK;
  495. vTaskResume (hTask);
  496. }
  497. return (stat);
  498. }
  499. __NO_RETURN void osThreadExit (void) {
  500. #ifndef USE_FreeRTOS_HEAP_1
  501. vTaskDelete (NULL);
  502. #endif
  503. for (;;);
  504. }
  505. osStatus_t osThreadTerminate (osThreadId_t thread_id) {
  506. TaskHandle_t hTask = (TaskHandle_t)thread_id;
  507. osStatus_t stat;
  508. #ifndef USE_FreeRTOS_HEAP_1
  509. eTaskState tstate;
  510. if (IS_IRQ()) {
  511. stat = osErrorISR;
  512. }
  513. else if (hTask == NULL) {
  514. stat = osErrorParameter;
  515. }
  516. else {
  517. tstate = eTaskGetState (hTask);
  518. if (tstate != eDeleted) {
  519. stat = osOK;
  520. vTaskDelete (hTask);
  521. } else {
  522. stat = osErrorResource;
  523. }
  524. }
  525. #else
  526. stat = osError;
  527. #endif
  528. return (stat);
  529. }
  530. uint32_t osThreadGetCount (void) {
  531. uint32_t count;
  532. if (IS_IRQ()) {
  533. count = 0U;
  534. } else {
  535. count = uxTaskGetNumberOfTasks();
  536. }
  537. return (count);
  538. }
  539. uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items) {
  540. uint32_t i, count;
  541. TaskStatus_t *task;
  542. if (IS_IRQ() || (thread_array == NULL) || (array_items == 0U)) {
  543. count = 0U;
  544. } else {
  545. vTaskSuspendAll();
  546. count = uxTaskGetNumberOfTasks();
  547. task = pvPortMalloc (count * sizeof(TaskStatus_t));
  548. if (task != NULL) {
  549. count = uxTaskGetSystemState (task, count, NULL);
  550. for (i = 0U; (i < count) && (i < array_items); i++) {
  551. thread_array[i] = (osThreadId_t)task[i].xHandle;
  552. }
  553. count = i;
  554. }
  555. (void)xTaskResumeAll();
  556. vPortFree (task);
  557. }
  558. return (count);
  559. }
  560. uint32_t osThreadFlagsSet (osThreadId_t thread_id, uint32_t flags) {
  561. TaskHandle_t hTask = (TaskHandle_t)thread_id;
  562. uint32_t rflags;
  563. BaseType_t yield;
  564. if ((hTask == NULL) || ((flags & THREAD_FLAGS_INVALID_BITS) != 0U)) {
  565. rflags = (uint32_t)osErrorParameter;
  566. }
  567. else {
  568. rflags = (uint32_t)osError;
  569. if (IS_IRQ()) {
  570. yield = pdFALSE;
  571. (void)xTaskNotifyFromISR (hTask, flags, eSetBits, &yield);
  572. (void)xTaskNotifyAndQueryFromISR (hTask, 0, eNoAction, &rflags, NULL);
  573. portYIELD_FROM_ISR (yield);
  574. }
  575. else {
  576. (void)xTaskNotify (hTask, flags, eSetBits);
  577. (void)xTaskNotifyAndQuery (hTask, 0, eNoAction, &rflags);
  578. }
  579. }
  580. /* Return flags after setting */
  581. return (rflags);
  582. }
  583. uint32_t osThreadFlagsClear (uint32_t flags) {
  584. TaskHandle_t hTask;
  585. uint32_t rflags, cflags;
  586. if (IS_IRQ()) {
  587. rflags = (uint32_t)osErrorISR;
  588. }
  589. else if ((flags & THREAD_FLAGS_INVALID_BITS) != 0U) {
  590. rflags = (uint32_t)osErrorParameter;
  591. }
  592. else {
  593. hTask = xTaskGetCurrentTaskHandle();
  594. if (xTaskNotifyAndQuery (hTask, 0, eNoAction, &cflags) == pdPASS) {
  595. rflags = cflags;
  596. cflags &= ~flags;
  597. if (xTaskNotify (hTask, cflags, eSetValueWithOverwrite) != pdPASS) {
  598. rflags = (uint32_t)osError;
  599. }
  600. }
  601. else {
  602. rflags = (uint32_t)osError;
  603. }
  604. }
  605. /* Return flags before clearing */
  606. return (rflags);
  607. }
  608. uint32_t osThreadFlagsGet (void) {
  609. TaskHandle_t hTask;
  610. uint32_t rflags;
  611. if (IS_IRQ()) {
  612. rflags = (uint32_t)osErrorISR;
  613. }
  614. else {
  615. hTask = xTaskGetCurrentTaskHandle();
  616. if (xTaskNotifyAndQuery (hTask, 0, eNoAction, &rflags) != pdPASS) {
  617. rflags = (uint32_t)osError;
  618. }
  619. }
  620. return (rflags);
  621. }
  622. uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout) {
  623. uint32_t rflags, nval;
  624. uint32_t clear;
  625. TickType_t t0, td, tout;
  626. BaseType_t rval;
  627. if (IS_IRQ()) {
  628. rflags = (uint32_t)osErrorISR;
  629. }
  630. else if ((flags & THREAD_FLAGS_INVALID_BITS) != 0U) {
  631. rflags = (uint32_t)osErrorParameter;
  632. }
  633. else {
  634. if ((options & osFlagsNoClear) == osFlagsNoClear) {
  635. clear = 0U;
  636. } else {
  637. clear = flags;
  638. }
  639. rflags = 0U;
  640. tout = timeout;
  641. t0 = xTaskGetTickCount();
  642. do {
  643. rval = xTaskNotifyWait (0, clear, &nval, tout);
  644. if (rval == pdPASS) {
  645. rflags &= flags;
  646. rflags |= nval;
  647. if ((options & osFlagsWaitAll) == osFlagsWaitAll) {
  648. if ((flags & rflags) == flags) {
  649. break;
  650. } else {
  651. if (timeout == 0U) {
  652. rflags = (uint32_t)osErrorResource;
  653. break;
  654. }
  655. }
  656. }
  657. else {
  658. if ((flags & rflags) != 0) {
  659. break;
  660. } else {
  661. if (timeout == 0U) {
  662. rflags = (uint32_t)osErrorResource;
  663. break;
  664. }
  665. }
  666. }
  667. /* Update timeout */
  668. td = xTaskGetTickCount() - t0;
  669. if (td > tout) {
  670. tout = 0;
  671. } else {
  672. tout -= td;
  673. }
  674. }
  675. else {
  676. if (timeout == 0) {
  677. rflags = (uint32_t)osErrorResource;
  678. } else {
  679. rflags = (uint32_t)osErrorTimeout;
  680. }
  681. }
  682. }
  683. while (rval != pdFAIL);
  684. }
  685. /* Return flags before clearing */
  686. return (rflags);
  687. }
  688. osStatus_t osDelay (uint32_t ticks) {
  689. osStatus_t stat;
  690. if (IS_IRQ()) {
  691. stat = osErrorISR;
  692. }
  693. else {
  694. stat = osOK;
  695. if (ticks != 0U) {
  696. vTaskDelay(ticks);
  697. }
  698. }
  699. return (stat);
  700. }
  701. osStatus_t osDelayUntil (uint32_t ticks) {
  702. TickType_t tcnt, delay;
  703. osStatus_t stat;
  704. if (IS_IRQ()) {
  705. stat = osErrorISR;
  706. }
  707. else {
  708. stat = osOK;
  709. tcnt = xTaskGetTickCount();
  710. /* Determine remaining number of ticks to delay */
  711. delay = (TickType_t)ticks - tcnt;
  712. /* Check if target tick has not expired */
  713. if((delay != 0U) && (0 == (delay >> (8 * sizeof(TickType_t) - 1)))) {
  714. vTaskDelayUntil (&tcnt, delay);
  715. }
  716. else
  717. {
  718. /* No delay or already expired */
  719. stat = osErrorParameter;
  720. }
  721. }
  722. return (stat);
  723. }
  724. /*---------------------------------------------------------------------------*/
  725. static void TimerCallback (TimerHandle_t hTimer) {
  726. TimerCallback_t *callb;
  727. callb = (TimerCallback_t *)pvTimerGetTimerID (hTimer);
  728. if (callb != NULL) {
  729. callb->func (callb->arg);
  730. }
  731. }
  732. osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr) {
  733. const char *name;
  734. TimerHandle_t hTimer;
  735. TimerCallback_t *callb;
  736. UBaseType_t reload;
  737. int32_t mem;
  738. hTimer = NULL;
  739. if (!IS_IRQ() && (func != NULL)) {
  740. /* Allocate memory to store callback function and argument */
  741. callb = pvPortMalloc (sizeof(TimerCallback_t));
  742. if (callb != NULL) {
  743. callb->func = func;
  744. callb->arg = argument;
  745. if (type == osTimerOnce) {
  746. reload = pdFALSE;
  747. } else {
  748. reload = pdTRUE;
  749. }
  750. mem = -1;
  751. name = NULL;
  752. if (attr != NULL) {
  753. if (attr->name != NULL) {
  754. name = attr->name;
  755. }
  756. if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticTimer_t))) {
  757. mem = 1;
  758. }
  759. else {
  760. if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
  761. mem = 0;
  762. }
  763. }
  764. }
  765. else {
  766. mem = 0;
  767. }
  768. if (mem == 1) {
  769. hTimer = xTimerCreateStatic (name, 1, reload, callb, TimerCallback, (StaticTimer_t *)attr->cb_mem);
  770. }
  771. else {
  772. if (mem == 0) {
  773. hTimer = xTimerCreate (name, 1, reload, callb, TimerCallback);
  774. }
  775. }
  776. }
  777. }
  778. return ((osTimerId_t)hTimer);
  779. }
  780. const char *osTimerGetName (osTimerId_t timer_id) {
  781. TimerHandle_t hTimer = (TimerHandle_t)timer_id;
  782. const char *p;
  783. if (IS_IRQ() || (hTimer == NULL)) {
  784. p = NULL;
  785. } else {
  786. p = pcTimerGetName (hTimer);
  787. }
  788. return (p);
  789. }
  790. osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks) {
  791. TimerHandle_t hTimer = (TimerHandle_t)timer_id;
  792. osStatus_t stat;
  793. if (IS_IRQ()) {
  794. stat = osErrorISR;
  795. }
  796. else if (hTimer == NULL) {
  797. stat = osErrorParameter;
  798. }
  799. else {
  800. if (xTimerChangePeriod (hTimer, ticks, 0) == pdPASS) {
  801. stat = osOK;
  802. } else {
  803. stat = osErrorResource;
  804. }
  805. }
  806. return (stat);
  807. }
  808. osStatus_t osTimerStop (osTimerId_t timer_id) {
  809. TimerHandle_t hTimer = (TimerHandle_t)timer_id;
  810. osStatus_t stat;
  811. if (IS_IRQ()) {
  812. stat = osErrorISR;
  813. }
  814. else if (hTimer == NULL) {
  815. stat = osErrorParameter;
  816. }
  817. else {
  818. if (xTimerIsTimerActive (hTimer) == pdFALSE) {
  819. stat = osErrorResource;
  820. }
  821. else {
  822. if (xTimerStop (hTimer, 0) == pdPASS) {
  823. stat = osOK;
  824. } else {
  825. stat = osError;
  826. }
  827. }
  828. }
  829. return (stat);
  830. }
  831. uint32_t osTimerIsRunning (osTimerId_t timer_id) {
  832. TimerHandle_t hTimer = (TimerHandle_t)timer_id;
  833. uint32_t running;
  834. if (IS_IRQ() || (hTimer == NULL)) {
  835. running = 0U;
  836. } else {
  837. running = (uint32_t)xTimerIsTimerActive (hTimer);
  838. }
  839. return (running);
  840. }
  841. osStatus_t osTimerDelete (osTimerId_t timer_id) {
  842. TimerHandle_t hTimer = (TimerHandle_t)timer_id;
  843. osStatus_t stat;
  844. #ifndef USE_FreeRTOS_HEAP_1
  845. TimerCallback_t *callb;
  846. if (IS_IRQ()) {
  847. stat = osErrorISR;
  848. }
  849. else if (hTimer == NULL) {
  850. stat = osErrorParameter;
  851. }
  852. else {
  853. callb = (TimerCallback_t *)pvTimerGetTimerID (hTimer);
  854. if (xTimerDelete (hTimer, 0) == pdPASS) {
  855. vPortFree (callb);
  856. stat = osOK;
  857. } else {
  858. stat = osErrorResource;
  859. }
  860. }
  861. #else
  862. stat = osError;
  863. #endif
  864. return (stat);
  865. }
  866. /*---------------------------------------------------------------------------*/
  867. osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr) {
  868. EventGroupHandle_t hEventGroup;
  869. int32_t mem;
  870. hEventGroup = NULL;
  871. if (!IS_IRQ()) {
  872. mem = -1;
  873. if (attr != NULL) {
  874. if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticEventGroup_t))) {
  875. mem = 1;
  876. }
  877. else {
  878. if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
  879. mem = 0;
  880. }
  881. }
  882. }
  883. else {
  884. mem = 0;
  885. }
  886. if (mem == 1) {
  887. hEventGroup = xEventGroupCreateStatic (attr->cb_mem);
  888. }
  889. else {
  890. if (mem == 0) {
  891. hEventGroup = xEventGroupCreate();
  892. }
  893. }
  894. }
  895. return ((osEventFlagsId_t)hEventGroup);
  896. }
  897. uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags) {
  898. EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
  899. uint32_t rflags;
  900. BaseType_t yield;
  901. if ((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
  902. rflags = (uint32_t)osErrorParameter;
  903. }
  904. else if (IS_IRQ()) {
  905. yield = pdFALSE;
  906. if (xEventGroupSetBitsFromISR (hEventGroup, (EventBits_t)flags, &yield) == pdFAIL) {
  907. rflags = (uint32_t)osErrorResource;
  908. } else {
  909. rflags = flags;
  910. portYIELD_FROM_ISR (yield);
  911. }
  912. }
  913. else {
  914. rflags = xEventGroupSetBits (hEventGroup, (EventBits_t)flags);
  915. }
  916. return (rflags);
  917. }
  918. uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags) {
  919. EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
  920. uint32_t rflags;
  921. if ((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
  922. rflags = (uint32_t)osErrorParameter;
  923. }
  924. else if (IS_IRQ()) {
  925. rflags = xEventGroupGetBitsFromISR (hEventGroup);
  926. if (xEventGroupClearBitsFromISR (hEventGroup, (EventBits_t)flags) == pdFAIL) {
  927. rflags = (uint32_t)osErrorResource;
  928. }
  929. }
  930. else {
  931. rflags = xEventGroupClearBits (hEventGroup, (EventBits_t)flags);
  932. }
  933. return (rflags);
  934. }
  935. uint32_t osEventFlagsGet (osEventFlagsId_t ef_id) {
  936. EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
  937. uint32_t rflags;
  938. if (ef_id == NULL) {
  939. rflags = 0U;
  940. }
  941. else if (IS_IRQ()) {
  942. rflags = xEventGroupGetBitsFromISR (hEventGroup);
  943. }
  944. else {
  945. rflags = xEventGroupGetBits (hEventGroup);
  946. }
  947. return (rflags);
  948. }
  949. uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout) {
  950. EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
  951. BaseType_t wait_all;
  952. BaseType_t exit_clr;
  953. uint32_t rflags;
  954. if ((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
  955. rflags = (uint32_t)osErrorParameter;
  956. }
  957. else if (IS_IRQ()) {
  958. rflags = (uint32_t)osErrorISR;
  959. }
  960. else {
  961. if (options & osFlagsWaitAll) {
  962. wait_all = pdTRUE;
  963. } else {
  964. wait_all = pdFAIL;
  965. }
  966. if (options & osFlagsNoClear) {
  967. exit_clr = pdFAIL;
  968. } else {
  969. exit_clr = pdTRUE;
  970. }
  971. rflags = xEventGroupWaitBits (hEventGroup, (EventBits_t)flags, exit_clr, wait_all, (TickType_t)timeout);
  972. if (options & osFlagsWaitAll) {
  973. if (flags != rflags) {
  974. if (timeout > 0U) {
  975. rflags = (uint32_t)osErrorTimeout;
  976. } else {
  977. rflags = (uint32_t)osErrorResource;
  978. }
  979. }
  980. }
  981. else {
  982. if ((flags & rflags) == 0U) {
  983. if (timeout > 0U) {
  984. rflags = (uint32_t)osErrorTimeout;
  985. } else {
  986. rflags = (uint32_t)osErrorResource;
  987. }
  988. }
  989. }
  990. }
  991. return (rflags);
  992. }
  993. osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id) {
  994. EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
  995. osStatus_t stat;
  996. #ifndef USE_FreeRTOS_HEAP_1
  997. if (IS_IRQ()) {
  998. stat = osErrorISR;
  999. }
  1000. else if (hEventGroup == NULL) {
  1001. stat = osErrorParameter;
  1002. }
  1003. else {
  1004. stat = osOK;
  1005. vEventGroupDelete (hEventGroup);
  1006. }
  1007. #else
  1008. stat = osError;
  1009. #endif
  1010. return (stat);
  1011. }
  1012. /*---------------------------------------------------------------------------*/
  1013. osMutexId_t osMutexNew (const osMutexAttr_t *attr) {
  1014. SemaphoreHandle_t hMutex;
  1015. uint32_t type;
  1016. uint32_t rmtx;
  1017. int32_t mem;
  1018. #if (configQUEUE_REGISTRY_SIZE > 0)
  1019. const char *name;
  1020. #endif
  1021. hMutex = NULL;
  1022. if (!IS_IRQ()) {
  1023. if (attr != NULL) {
  1024. type = attr->attr_bits;
  1025. } else {
  1026. type = 0U;
  1027. }
  1028. if ((type & osMutexRecursive) == osMutexRecursive) {
  1029. rmtx = 1U;
  1030. } else {
  1031. rmtx = 0U;
  1032. }
  1033. if ((type & osMutexRobust) != osMutexRobust) {
  1034. mem = -1;
  1035. if (attr != NULL) {
  1036. if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticSemaphore_t))) {
  1037. mem = 1;
  1038. }
  1039. else {
  1040. if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
  1041. mem = 0;
  1042. }
  1043. }
  1044. }
  1045. else {
  1046. mem = 0;
  1047. }
  1048. if (mem == 1) {
  1049. if (rmtx != 0U) {
  1050. hMutex = xSemaphoreCreateRecursiveMutexStatic (attr->cb_mem);
  1051. }
  1052. else {
  1053. hMutex = xSemaphoreCreateMutexStatic (attr->cb_mem);
  1054. }
  1055. }
  1056. else {
  1057. if (mem == 0) {
  1058. if (rmtx != 0U) {
  1059. hMutex = xSemaphoreCreateRecursiveMutex ();
  1060. } else {
  1061. hMutex = xSemaphoreCreateMutex ();
  1062. }
  1063. }
  1064. }
  1065. #if (configQUEUE_REGISTRY_SIZE > 0)
  1066. if (hMutex != NULL) {
  1067. if (attr != NULL) {
  1068. name = attr->name;
  1069. } else {
  1070. name = NULL;
  1071. }
  1072. vQueueAddToRegistry (hMutex, name);
  1073. }
  1074. #endif
  1075. if ((hMutex != NULL) && (rmtx != 0U)) {
  1076. hMutex = (SemaphoreHandle_t)((uint32_t)hMutex | 1U);
  1077. }
  1078. }
  1079. }
  1080. return ((osMutexId_t)hMutex);
  1081. }
  1082. osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) {
  1083. SemaphoreHandle_t hMutex;
  1084. osStatus_t stat;
  1085. uint32_t rmtx;
  1086. hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
  1087. rmtx = (uint32_t)mutex_id & 1U;
  1088. stat = osOK;
  1089. if (IS_IRQ()) {
  1090. stat = osErrorISR;
  1091. }
  1092. else if (hMutex == NULL) {
  1093. stat = osErrorParameter;
  1094. }
  1095. else {
  1096. if (rmtx != 0U) {
  1097. if (xSemaphoreTakeRecursive (hMutex, timeout) != pdPASS) {
  1098. if (timeout != 0U) {
  1099. stat = osErrorTimeout;
  1100. } else {
  1101. stat = osErrorResource;
  1102. }
  1103. }
  1104. }
  1105. else {
  1106. if (xSemaphoreTake (hMutex, timeout) != pdPASS) {
  1107. if (timeout != 0U) {
  1108. stat = osErrorTimeout;
  1109. } else {
  1110. stat = osErrorResource;
  1111. }
  1112. }
  1113. }
  1114. }
  1115. return (stat);
  1116. }
  1117. osStatus_t osMutexRelease (osMutexId_t mutex_id) {
  1118. SemaphoreHandle_t hMutex;
  1119. osStatus_t stat;
  1120. uint32_t rmtx;
  1121. hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
  1122. rmtx = (uint32_t)mutex_id & 1U;
  1123. stat = osOK;
  1124. if (IS_IRQ()) {
  1125. stat = osErrorISR;
  1126. }
  1127. else if (hMutex == NULL) {
  1128. stat = osErrorParameter;
  1129. }
  1130. else {
  1131. if (rmtx != 0U) {
  1132. if (xSemaphoreGiveRecursive (hMutex) != pdPASS) {
  1133. stat = osErrorResource;
  1134. }
  1135. }
  1136. else {
  1137. if (xSemaphoreGive (hMutex) != pdPASS) {
  1138. stat = osErrorResource;
  1139. }
  1140. }
  1141. }
  1142. return (stat);
  1143. }
  1144. osThreadId_t osMutexGetOwner (osMutexId_t mutex_id) {
  1145. SemaphoreHandle_t hMutex;
  1146. osThreadId_t owner;
  1147. hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
  1148. if (IS_IRQ() || (hMutex == NULL)) {
  1149. owner = NULL;
  1150. } else {
  1151. owner = (osThreadId_t)xSemaphoreGetMutexHolder (hMutex);
  1152. }
  1153. return (owner);
  1154. }
  1155. osStatus_t osMutexDelete (osMutexId_t mutex_id) {
  1156. osStatus_t stat;
  1157. #ifndef USE_FreeRTOS_HEAP_1
  1158. SemaphoreHandle_t hMutex;
  1159. hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
  1160. if (IS_IRQ()) {
  1161. stat = osErrorISR;
  1162. }
  1163. else if (hMutex == NULL) {
  1164. stat = osErrorParameter;
  1165. }
  1166. else {
  1167. #if (configQUEUE_REGISTRY_SIZE > 0)
  1168. vQueueUnregisterQueue (hMutex);
  1169. #endif
  1170. stat = osOK;
  1171. vSemaphoreDelete (hMutex);
  1172. }
  1173. #else
  1174. stat = osError;
  1175. #endif
  1176. return (stat);
  1177. }
  1178. /*---------------------------------------------------------------------------*/
  1179. osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr) {
  1180. SemaphoreHandle_t hSemaphore;
  1181. int32_t mem;
  1182. #if (configQUEUE_REGISTRY_SIZE > 0)
  1183. const char *name;
  1184. #endif
  1185. hSemaphore = NULL;
  1186. if (!IS_IRQ() && (max_count > 0U) && (initial_count <= max_count)) {
  1187. mem = -1;
  1188. if (attr != NULL) {
  1189. if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticSemaphore_t))) {
  1190. mem = 1;
  1191. }
  1192. else {
  1193. if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
  1194. mem = 0;
  1195. }
  1196. }
  1197. }
  1198. else {
  1199. mem = 0;
  1200. }
  1201. if (mem != -1) {
  1202. if (max_count == 1U) {
  1203. if (mem == 1) {
  1204. hSemaphore = xSemaphoreCreateBinaryStatic ((StaticSemaphore_t *)attr->cb_mem);
  1205. }
  1206. else {
  1207. hSemaphore = xSemaphoreCreateBinary();
  1208. }
  1209. if ((hSemaphore != NULL) && (initial_count != 0U)) {
  1210. if (xSemaphoreGive (hSemaphore) != pdPASS) {
  1211. vSemaphoreDelete (hSemaphore);
  1212. hSemaphore = NULL;
  1213. }
  1214. }
  1215. }
  1216. else {
  1217. if (mem == 1) {
  1218. hSemaphore = xSemaphoreCreateCountingStatic (max_count, initial_count, (StaticSemaphore_t *)attr->cb_mem);
  1219. }
  1220. else {
  1221. hSemaphore = xSemaphoreCreateCounting (max_count, initial_count);
  1222. }
  1223. }
  1224. #if (configQUEUE_REGISTRY_SIZE > 0)
  1225. if (hSemaphore != NULL) {
  1226. if (attr != NULL) {
  1227. name = attr->name;
  1228. } else {
  1229. name = NULL;
  1230. }
  1231. vQueueAddToRegistry (hSemaphore, name);
  1232. }
  1233. #endif
  1234. }
  1235. }
  1236. return ((osSemaphoreId_t)hSemaphore);
  1237. }
  1238. osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout) {
  1239. SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
  1240. osStatus_t stat;
  1241. BaseType_t yield;
  1242. stat = osOK;
  1243. if (hSemaphore == NULL) {
  1244. stat = osErrorParameter;
  1245. }
  1246. else if (IS_IRQ()) {
  1247. if (timeout != 0U) {
  1248. stat = osErrorParameter;
  1249. }
  1250. else {
  1251. yield = pdFALSE;
  1252. if (xSemaphoreTakeFromISR (hSemaphore, &yield) != pdPASS) {
  1253. stat = osErrorResource;
  1254. } else {
  1255. portYIELD_FROM_ISR (yield);
  1256. }
  1257. }
  1258. }
  1259. else {
  1260. if (xSemaphoreTake (hSemaphore, (TickType_t)timeout) != pdPASS) {
  1261. if (timeout != 0U) {
  1262. stat = osErrorTimeout;
  1263. } else {
  1264. stat = osErrorResource;
  1265. }
  1266. }
  1267. }
  1268. return (stat);
  1269. }
  1270. osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id) {
  1271. SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
  1272. osStatus_t stat;
  1273. BaseType_t yield;
  1274. stat = osOK;
  1275. if (hSemaphore == NULL) {
  1276. stat = osErrorParameter;
  1277. }
  1278. else if (IS_IRQ()) {
  1279. yield = pdFALSE;
  1280. if (xSemaphoreGiveFromISR (hSemaphore, &yield) != pdTRUE) {
  1281. stat = osErrorResource;
  1282. } else {
  1283. portYIELD_FROM_ISR (yield);
  1284. }
  1285. }
  1286. else {
  1287. if (xSemaphoreGive (hSemaphore) != pdPASS) {
  1288. stat = osErrorResource;
  1289. }
  1290. }
  1291. return (stat);
  1292. }
  1293. uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id) {
  1294. SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
  1295. uint32_t count;
  1296. if (hSemaphore == NULL) {
  1297. count = 0U;
  1298. }
  1299. else if (IS_IRQ()) {
  1300. count = uxQueueMessagesWaitingFromISR (hSemaphore);
  1301. } else {
  1302. count = (uint32_t)uxSemaphoreGetCount (hSemaphore);
  1303. }
  1304. return (count);
  1305. }
  1306. osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id) {
  1307. SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
  1308. osStatus_t stat;
  1309. #ifndef USE_FreeRTOS_HEAP_1
  1310. if (IS_IRQ()) {
  1311. stat = osErrorISR;
  1312. }
  1313. else if (hSemaphore == NULL) {
  1314. stat = osErrorParameter;
  1315. }
  1316. else {
  1317. #if (configQUEUE_REGISTRY_SIZE > 0)
  1318. vQueueUnregisterQueue (hSemaphore);
  1319. #endif
  1320. stat = osOK;
  1321. vSemaphoreDelete (hSemaphore);
  1322. }
  1323. #else
  1324. stat = osError;
  1325. #endif
  1326. return (stat);
  1327. }
  1328. /*---------------------------------------------------------------------------*/
  1329. osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) {
  1330. QueueHandle_t hQueue;
  1331. int32_t mem;
  1332. #if (configQUEUE_REGISTRY_SIZE > 0)
  1333. const char *name;
  1334. #endif
  1335. hQueue = NULL;
  1336. if (!IS_IRQ() && (msg_count > 0U) && (msg_size > 0U)) {
  1337. mem = -1;
  1338. if (attr != NULL) {
  1339. if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticQueue_t)) &&
  1340. (attr->mq_mem != NULL) && (attr->mq_size >= (msg_count * msg_size))) {
  1341. mem = 1;
  1342. }
  1343. else {
  1344. if ((attr->cb_mem == NULL) && (attr->cb_size == 0U) &&
  1345. (attr->mq_mem == NULL) && (attr->mq_size == 0U)) {
  1346. mem = 0;
  1347. }
  1348. }
  1349. }
  1350. else {
  1351. mem = 0;
  1352. }
  1353. if (mem == 1) {
  1354. hQueue = xQueueCreateStatic (msg_count, msg_size, attr->mq_mem, attr->cb_mem);
  1355. }
  1356. else {
  1357. if (mem == 0) {
  1358. hQueue = xQueueCreate (msg_count, msg_size);
  1359. }
  1360. }
  1361. #if (configQUEUE_REGISTRY_SIZE > 0)
  1362. if (hQueue != NULL) {
  1363. if (attr != NULL) {
  1364. name = attr->name;
  1365. } else {
  1366. name = NULL;
  1367. }
  1368. vQueueAddToRegistry (hQueue, name);
  1369. }
  1370. #endif
  1371. }
  1372. return ((osMessageQueueId_t)hQueue);
  1373. }
  1374. osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
  1375. QueueHandle_t hQueue = (QueueHandle_t)mq_id;
  1376. osStatus_t stat;
  1377. BaseType_t yield;
  1378. (void)msg_prio; /* Message priority is ignored */
  1379. stat = osOK;
  1380. if (IS_IRQ()) {
  1381. if ((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) {
  1382. stat = osErrorParameter;
  1383. }
  1384. else {
  1385. yield = pdFALSE;
  1386. if (xQueueSendToBackFromISR (hQueue, msg_ptr, &yield) != pdTRUE) {
  1387. stat = osErrorResource;
  1388. } else {
  1389. portYIELD_FROM_ISR (yield);
  1390. }
  1391. }
  1392. }
  1393. else {
  1394. if ((hQueue == NULL) || (msg_ptr == NULL)) {
  1395. stat = osErrorParameter;
  1396. }
  1397. else {
  1398. if (xQueueSendToBack (hQueue, msg_ptr, (TickType_t)timeout) != pdPASS) {
  1399. if (timeout != 0U) {
  1400. stat = osErrorTimeout;
  1401. } else {
  1402. stat = osErrorResource;
  1403. }
  1404. }
  1405. }
  1406. }
  1407. return (stat);
  1408. }
  1409. osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
  1410. QueueHandle_t hQueue = (QueueHandle_t)mq_id;
  1411. osStatus_t stat;
  1412. BaseType_t yield;
  1413. (void)msg_prio; /* Message priority is ignored */
  1414. stat = osOK;
  1415. if (IS_IRQ()) {
  1416. if ((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) {
  1417. stat = osErrorParameter;
  1418. }
  1419. else {
  1420. yield = pdFALSE;
  1421. if (xQueueReceiveFromISR (hQueue, msg_ptr, &yield) != pdPASS) {
  1422. stat = osErrorResource;
  1423. } else {
  1424. portYIELD_FROM_ISR (yield);
  1425. }
  1426. }
  1427. }
  1428. else {
  1429. if ((hQueue == NULL) || (msg_ptr == NULL)) {
  1430. stat = osErrorParameter;
  1431. }
  1432. else {
  1433. if (xQueueReceive (hQueue, msg_ptr, (TickType_t)timeout) != pdPASS) {
  1434. if (timeout != 0U) {
  1435. stat = osErrorTimeout;
  1436. } else {
  1437. stat = osErrorResource;
  1438. }
  1439. }
  1440. }
  1441. }
  1442. return (stat);
  1443. }
  1444. uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id) {
  1445. StaticQueue_t *mq = (StaticQueue_t *)mq_id;
  1446. uint32_t capacity;
  1447. if (mq == NULL) {
  1448. capacity = 0U;
  1449. } else {
  1450. /* capacity = pxQueue->uxLength */
  1451. capacity = mq->uxDummy4[1];
  1452. }
  1453. return (capacity);
  1454. }
  1455. uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id) {
  1456. StaticQueue_t *mq = (StaticQueue_t *)mq_id;
  1457. uint32_t size;
  1458. if (mq == NULL) {
  1459. size = 0U;
  1460. } else {
  1461. /* size = pxQueue->uxItemSize */
  1462. size = mq->uxDummy4[2];
  1463. }
  1464. return (size);
  1465. }
  1466. uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id) {
  1467. QueueHandle_t hQueue = (QueueHandle_t)mq_id;
  1468. UBaseType_t count;
  1469. if (hQueue == NULL) {
  1470. count = 0U;
  1471. }
  1472. else if (IS_IRQ()) {
  1473. count = uxQueueMessagesWaitingFromISR (hQueue);
  1474. }
  1475. else {
  1476. count = uxQueueMessagesWaiting (hQueue);
  1477. }
  1478. return ((uint32_t)count);
  1479. }
  1480. uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id) {
  1481. StaticQueue_t *mq = (StaticQueue_t *)mq_id;
  1482. uint32_t space;
  1483. uint32_t isrm;
  1484. if (mq == NULL) {
  1485. space = 0U;
  1486. }
  1487. else if (IS_IRQ()) {
  1488. isrm = taskENTER_CRITICAL_FROM_ISR();
  1489. /* space = pxQueue->uxLength - pxQueue->uxMessagesWaiting; */
  1490. space = mq->uxDummy4[1] - mq->uxDummy4[0];
  1491. taskEXIT_CRITICAL_FROM_ISR(isrm);
  1492. }
  1493. else {
  1494. space = (uint32_t)uxQueueSpacesAvailable ((QueueHandle_t)mq);
  1495. }
  1496. return (space);
  1497. }
  1498. osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id) {
  1499. QueueHandle_t hQueue = (QueueHandle_t)mq_id;
  1500. osStatus_t stat;
  1501. if (IS_IRQ()) {
  1502. stat = osErrorISR;
  1503. }
  1504. else if (hQueue == NULL) {
  1505. stat = osErrorParameter;
  1506. }
  1507. else {
  1508. stat = osOK;
  1509. (void)xQueueReset (hQueue);
  1510. }
  1511. return (stat);
  1512. }
  1513. osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id) {
  1514. QueueHandle_t hQueue = (QueueHandle_t)mq_id;
  1515. osStatus_t stat;
  1516. #ifndef USE_FreeRTOS_HEAP_1
  1517. if (IS_IRQ()) {
  1518. stat = osErrorISR;
  1519. }
  1520. else if (hQueue == NULL) {
  1521. stat = osErrorParameter;
  1522. }
  1523. else {
  1524. #if (configQUEUE_REGISTRY_SIZE > 0)
  1525. vQueueUnregisterQueue (hQueue);
  1526. #endif
  1527. stat = osOK;
  1528. vQueueDelete (hQueue);
  1529. }
  1530. #else
  1531. stat = osError;
  1532. #endif
  1533. return (stat);
  1534. }
  1535. /*---------------------------------------------------------------------------*/
  1536. /* Callback function prototypes */
  1537. extern void vApplicationIdleHook (void);
  1538. extern void vApplicationTickHook (void);
  1539. extern void vApplicationMallocFailedHook (void);
  1540. extern void vApplicationDaemonTaskStartupHook (void);
  1541. extern void vApplicationStackOverflowHook (TaskHandle_t xTask, signed char *pcTaskName);
  1542. /**
  1543. Dummy implementation of the callback function vApplicationIdleHook().
  1544. */
  1545. #if (configUSE_IDLE_HOOK == 1)
  1546. __WEAK void vApplicationIdleHook (void){}
  1547. #endif
  1548. /**
  1549. Dummy implementation of the callback function vApplicationTickHook().
  1550. */
  1551. #if (configUSE_TICK_HOOK == 1)
  1552. __WEAK void vApplicationTickHook (void){}
  1553. #endif
  1554. /**
  1555. Dummy implementation of the callback function vApplicationMallocFailedHook().
  1556. */
  1557. #if (configUSE_MALLOC_FAILED_HOOK == 1)
  1558. __WEAK void vApplicationMallocFailedHook (void){}
  1559. #endif
  1560. /**
  1561. Dummy implementation of the callback function vApplicationDaemonTaskStartupHook().
  1562. */
  1563. #if (configUSE_DAEMON_TASK_STARTUP_HOOK == 1)
  1564. __WEAK void vApplicationDaemonTaskStartupHook (void){}
  1565. #endif
  1566. /**
  1567. Dummy implementation of the callback function vApplicationStackOverflowHook().
  1568. */
  1569. #if (configCHECK_FOR_STACK_OVERFLOW > 0)
  1570. __WEAK void vApplicationStackOverflowHook (TaskHandle_t xTask, signed char *pcTaskName) {
  1571. (void)xTask;
  1572. (void)pcTaskName;
  1573. }
  1574. #endif
  1575. /*---------------------------------------------------------------------------*/
  1576. /* External Idle and Timer task static memory allocation functions */
  1577. extern void vApplicationGetIdleTaskMemory (StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize);
  1578. extern void vApplicationGetTimerTaskMemory (StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize);
  1579. /* Idle task control block and stack */
  1580. static StaticTask_t Idle_TCB;
  1581. static StackType_t Idle_Stack[configMINIMAL_STACK_SIZE];
  1582. /* Timer task control block and stack */
  1583. static StaticTask_t Timer_TCB;
  1584. static StackType_t Timer_Stack[configTIMER_TASK_STACK_DEPTH];
  1585. /*
  1586. vApplicationGetIdleTaskMemory gets called when configSUPPORT_STATIC_ALLOCATION
  1587. equals to 1 and is required for static memory allocation support.
  1588. */
  1589. void vApplicationGetIdleTaskMemory (StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) {
  1590. *ppxIdleTaskTCBBuffer = &Idle_TCB;
  1591. *ppxIdleTaskStackBuffer = &Idle_Stack[0];
  1592. *pulIdleTaskStackSize = (uint32_t)configMINIMAL_STACK_SIZE;
  1593. }
  1594. /*
  1595. vApplicationGetTimerTaskMemory gets called when configSUPPORT_STATIC_ALLOCATION
  1596. equals to 1 and is required for static memory allocation support.
  1597. */
  1598. void vApplicationGetTimerTaskMemory (StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) {
  1599. *ppxTimerTaskTCBBuffer = &Timer_TCB;
  1600. *ppxTimerTaskStackBuffer = &Timer_Stack[0];
  1601. *pulTimerTaskStackSize = (uint32_t)configTIMER_TASK_STACK_DEPTH;
  1602. }