cmsis_os2.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
  1. /* --------------------------------------------------------------------------
  2. * Copyright (c) 2013-2021 Arm Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * Name: cmsis_os2.c
  19. * Purpose: CMSIS RTOS2 wrapper for FreeRTOS
  20. *
  21. *---------------------------------------------------------------------------*/
  22. #include <string.h>
  23. #include <furi/common_defines.h>
  24. #include "cmsis_os2.h" // ::CMSIS:RTOS2
  25. #include "cmsis_compiler.h" // Compiler agnostic definitions
  26. #include "FreeRTOS.h" // ARM.FreeRTOS::RTOS:Core
  27. #include "timers.h" // ARM.FreeRTOS::RTOS:Timers
  28. #include "queue.h"
  29. #include "freertos_os2.h" // Configuration check and setup
  30. #include CMSIS_device_header
  31. #ifndef CMSIS_TASK_NOTIFY_INDEX
  32. #define CMSIS_TASK_NOTIFY_INDEX 0
  33. #endif
  34. /*---------------------------------------------------------------------------*/
  35. #ifndef __ARM_ARCH_6M__
  36. #define __ARM_ARCH_6M__ 0
  37. #endif
  38. #ifndef __ARM_ARCH_7M__
  39. #define __ARM_ARCH_7M__ 0
  40. #endif
  41. #ifndef __ARM_ARCH_7EM__
  42. #define __ARM_ARCH_7EM__ 0
  43. #endif
  44. #ifndef __ARM_ARCH_8M_MAIN__
  45. #define __ARM_ARCH_8M_MAIN__ 0
  46. #endif
  47. #ifndef __ARM_ARCH_7A__
  48. #define __ARM_ARCH_7A__ 0
  49. #endif
  50. #if ((__ARM_ARCH_7M__ == 1U) || \
  51. (__ARM_ARCH_7EM__ == 1U) || \
  52. (__ARM_ARCH_8M_MAIN__ == 1U))
  53. #define IS_IRQ_MASKED() ((__get_PRIMASK() != 0U) || (__get_BASEPRI() != 0U))
  54. #elif (__ARM_ARCH_6M__ == 1U)
  55. #define IS_IRQ_MASKED() (__get_PRIMASK() != 0U)
  56. #elif (__ARM_ARCH_7A__ == 1U)
  57. /* CPSR mask bits */
  58. #define CPSR_MASKBIT_I 0x80U
  59. #define IS_IRQ_MASKED() ((__get_CPSR() & CPSR_MASKBIT_I) != 0U)
  60. #else
  61. #define IS_IRQ_MASKED() (__get_PRIMASK() != 0U)
  62. #endif
  63. #if (__ARM_ARCH_7A__ == 1U)
  64. /* CPSR mode bitmasks */
  65. #define CPSR_MODE_USER 0x10U
  66. #define CPSR_MODE_SYSTEM 0x1FU
  67. #define IS_IRQ_MODE() ((__get_mode() != CPSR_MODE_USER) && (__get_mode() != CPSR_MODE_SYSTEM))
  68. #else
  69. #define IS_IRQ_MODE() (__get_IPSR() != 0U)
  70. #endif
  71. /* Limits */
  72. #define MAX_BITS_TASK_NOTIFY 31U
  73. #define THREAD_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_TASK_NOTIFY) - 1U))
  74. /* Kernel version and identification string definition (major.minor.rev: mmnnnrrrr dec) */
  75. #define KERNEL_VERSION (((uint32_t)tskKERNEL_VERSION_MAJOR * 10000000UL) | \
  76. ((uint32_t)tskKERNEL_VERSION_MINOR * 10000UL) | \
  77. ((uint32_t)tskKERNEL_VERSION_BUILD * 1UL))
  78. #define KERNEL_ID ("FreeRTOS " tskKERNEL_VERSION_NUMBER)
  79. /* Timer callback information structure definition */
  80. typedef struct {
  81. osTimerFunc_t func;
  82. void *arg;
  83. } TimerCallback_t;
  84. /* Kernel initialization state */
  85. static osKernelState_t KernelState = osKernelInactive;
  86. /*
  87. Heap region definition used by heap_5 variant
  88. Define configAPPLICATION_ALLOCATED_HEAP as nonzero value in FreeRTOSConfig.h if
  89. heap regions are already defined and vPortDefineHeapRegions is called in application.
  90. Otherwise vPortDefineHeapRegions will be called by osKernelInitialize using
  91. definition configHEAP_5_REGIONS as parameter. Overriding configHEAP_5_REGIONS
  92. is possible by defining it globally or in FreeRTOSConfig.h.
  93. */
  94. #if defined(USE_FreeRTOS_HEAP_5)
  95. #if (configAPPLICATION_ALLOCATED_HEAP == 0)
  96. /*
  97. FreeRTOS heap is not defined by the application.
  98. Single region of size configTOTAL_HEAP_SIZE (defined in FreeRTOSConfig.h)
  99. is provided by default. Define configHEAP_5_REGIONS to provide custom
  100. HeapRegion_t array.
  101. */
  102. #define HEAP_5_REGION_SETUP 1
  103. #ifndef configHEAP_5_REGIONS
  104. #define configHEAP_5_REGIONS xHeapRegions
  105. static uint8_t ucHeap[configTOTAL_HEAP_SIZE];
  106. static HeapRegion_t xHeapRegions[] = {
  107. { ucHeap, configTOTAL_HEAP_SIZE },
  108. { NULL, 0 }
  109. };
  110. #else
  111. /* Global definition is provided to override default heap array */
  112. extern HeapRegion_t configHEAP_5_REGIONS[];
  113. #endif
  114. #else
  115. /*
  116. The application already defined the array used for the FreeRTOS heap and
  117. called vPortDefineHeapRegions to initialize heap.
  118. */
  119. #define HEAP_5_REGION_SETUP 0
  120. #endif /* configAPPLICATION_ALLOCATED_HEAP */
  121. #endif /* USE_FreeRTOS_HEAP_5 */
  122. /*
  123. Setup SVC to reset value.
  124. */
  125. __STATIC_INLINE void SVC_Setup (void) {
  126. #if (__ARM_ARCH_7A__ == 0U)
  127. /* Service Call interrupt might be configured before kernel start */
  128. /* and when its priority is lower or equal to BASEPRI, svc intruction */
  129. /* causes a Hard Fault. */
  130. NVIC_SetPriority (SVCall_IRQn, 0U);
  131. #endif
  132. }
  133. /*
  134. Function macro used to retrieve semaphore count from ISR
  135. */
  136. #ifndef uxSemaphoreGetCountFromISR
  137. #define uxSemaphoreGetCountFromISR( xSemaphore ) uxQueueMessagesWaitingFromISR( ( QueueHandle_t ) ( xSemaphore ) )
  138. #endif
  139. /*
  140. Determine if CPU executes from interrupt context or if interrupts are masked.
  141. */
  142. __STATIC_INLINE uint32_t IRQ_Context (void) {
  143. uint32_t irq;
  144. BaseType_t state;
  145. irq = 0U;
  146. if (IS_IRQ_MODE()) {
  147. /* Called from interrupt context */
  148. irq = 1U;
  149. }
  150. else {
  151. /* Get FreeRTOS scheduler state */
  152. state = xTaskGetSchedulerState();
  153. if (state != taskSCHEDULER_NOT_STARTED) {
  154. /* Scheduler was started */
  155. if (IS_IRQ_MASKED()) {
  156. /* Interrupts are masked */
  157. irq = 1U;
  158. }
  159. }
  160. }
  161. /* Return context, 0: thread context, 1: IRQ context */
  162. return (irq);
  163. }
  164. /* ==== Kernel Management Functions ==== */
  165. /*
  166. Initialize the RTOS Kernel.
  167. */
  168. osStatus_t osKernelInitialize (void) {
  169. osStatus_t stat;
  170. BaseType_t state;
  171. if (IRQ_Context() != 0U) {
  172. stat = osErrorISR;
  173. }
  174. else {
  175. state = xTaskGetSchedulerState();
  176. /* Initialize if scheduler not started and not initialized before */
  177. if ((state == taskSCHEDULER_NOT_STARTED) && (KernelState == osKernelInactive)) {
  178. #if defined(USE_TRACE_EVENT_RECORDER)
  179. /* Initialize the trace macro debugging output channel */
  180. EvrFreeRTOSSetup(0U);
  181. #endif
  182. #if defined(USE_FreeRTOS_HEAP_5) && (HEAP_5_REGION_SETUP == 1)
  183. /* Initialize the memory regions when using heap_5 variant */
  184. vPortDefineHeapRegions (configHEAP_5_REGIONS);
  185. #endif
  186. KernelState = osKernelReady;
  187. stat = osOK;
  188. } else {
  189. stat = osError;
  190. }
  191. }
  192. /* Return execution status */
  193. return (stat);
  194. }
  195. /*
  196. Get RTOS Kernel Information.
  197. */
  198. osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size) {
  199. if (version != NULL) {
  200. /* Version encoding is major.minor.rev: mmnnnrrrr dec */
  201. version->api = KERNEL_VERSION;
  202. version->kernel = KERNEL_VERSION;
  203. }
  204. if ((id_buf != NULL) && (id_size != 0U)) {
  205. /* Buffer for retrieving identification string is provided */
  206. if (id_size > sizeof(KERNEL_ID)) {
  207. id_size = sizeof(KERNEL_ID);
  208. }
  209. /* Copy kernel identification string into provided buffer */
  210. memcpy(id_buf, KERNEL_ID, id_size);
  211. }
  212. /* Return execution status */
  213. return (osOK);
  214. }
  215. /*
  216. Get the current RTOS Kernel state.
  217. */
  218. osKernelState_t osKernelGetState (void) {
  219. osKernelState_t state;
  220. switch (xTaskGetSchedulerState()) {
  221. case taskSCHEDULER_RUNNING:
  222. state = osKernelRunning;
  223. break;
  224. case taskSCHEDULER_SUSPENDED:
  225. state = osKernelLocked;
  226. break;
  227. case taskSCHEDULER_NOT_STARTED:
  228. default:
  229. if (KernelState == osKernelReady) {
  230. /* Ready, osKernelInitialize was already called */
  231. state = osKernelReady;
  232. } else {
  233. /* Not initialized */
  234. state = osKernelInactive;
  235. }
  236. break;
  237. }
  238. /* Return current state */
  239. return (state);
  240. }
  241. /*
  242. Start the RTOS Kernel scheduler.
  243. */
  244. osStatus_t osKernelStart (void) {
  245. osStatus_t stat;
  246. BaseType_t state;
  247. if (IRQ_Context() != 0U) {
  248. stat = osErrorISR;
  249. }
  250. else {
  251. state = xTaskGetSchedulerState();
  252. /* Start scheduler if initialized and not started before */
  253. if ((state == taskSCHEDULER_NOT_STARTED) && (KernelState == osKernelReady)) {
  254. /* Ensure SVC priority is at the reset value */
  255. SVC_Setup();
  256. /* Change state to ensure correct API flow */
  257. KernelState = osKernelRunning;
  258. /* Start the kernel scheduler */
  259. vTaskStartScheduler();
  260. stat = osOK;
  261. } else {
  262. stat = osError;
  263. }
  264. }
  265. /* Return execution status */
  266. return (stat);
  267. }
  268. /*
  269. Lock the RTOS Kernel scheduler.
  270. */
  271. int32_t osKernelLock (void) {
  272. int32_t lock;
  273. if (IRQ_Context() != 0U) {
  274. lock = (int32_t)osErrorISR;
  275. }
  276. else {
  277. switch (xTaskGetSchedulerState()) {
  278. case taskSCHEDULER_SUSPENDED:
  279. lock = 1;
  280. break;
  281. case taskSCHEDULER_RUNNING:
  282. vTaskSuspendAll();
  283. lock = 0;
  284. break;
  285. case taskSCHEDULER_NOT_STARTED:
  286. default:
  287. lock = (int32_t)osError;
  288. break;
  289. }
  290. }
  291. /* Return previous lock state */
  292. return (lock);
  293. }
  294. /*
  295. Unlock the RTOS Kernel scheduler.
  296. */
  297. int32_t osKernelUnlock (void) {
  298. int32_t lock;
  299. if (IRQ_Context() != 0U) {
  300. lock = (int32_t)osErrorISR;
  301. }
  302. else {
  303. switch (xTaskGetSchedulerState()) {
  304. case taskSCHEDULER_SUSPENDED:
  305. lock = 1;
  306. if (xTaskResumeAll() != pdTRUE) {
  307. if (xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) {
  308. lock = (int32_t)osError;
  309. }
  310. }
  311. break;
  312. case taskSCHEDULER_RUNNING:
  313. lock = 0;
  314. break;
  315. case taskSCHEDULER_NOT_STARTED:
  316. default:
  317. lock = (int32_t)osError;
  318. break;
  319. }
  320. }
  321. /* Return previous lock state */
  322. return (lock);
  323. }
  324. /*
  325. Restore the RTOS Kernel scheduler lock state.
  326. */
  327. int32_t osKernelRestoreLock (int32_t lock) {
  328. if (IRQ_Context() != 0U) {
  329. lock = (int32_t)osErrorISR;
  330. }
  331. else {
  332. switch (xTaskGetSchedulerState()) {
  333. case taskSCHEDULER_SUSPENDED:
  334. case taskSCHEDULER_RUNNING:
  335. if (lock == 1) {
  336. vTaskSuspendAll();
  337. }
  338. else {
  339. if (lock != 0) {
  340. lock = (int32_t)osError;
  341. }
  342. else {
  343. if (xTaskResumeAll() != pdTRUE) {
  344. if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) {
  345. lock = (int32_t)osError;
  346. }
  347. }
  348. }
  349. }
  350. break;
  351. case taskSCHEDULER_NOT_STARTED:
  352. default:
  353. lock = (int32_t)osError;
  354. break;
  355. }
  356. }
  357. /* Return new lock state */
  358. return (lock);
  359. }
  360. /*
  361. Get the RTOS kernel tick count.
  362. */
  363. uint32_t osKernelGetTickCount (void) {
  364. TickType_t ticks;
  365. if (IRQ_Context() != 0U) {
  366. ticks = xTaskGetTickCountFromISR();
  367. } else {
  368. ticks = xTaskGetTickCount();
  369. }
  370. /* Return kernel tick count */
  371. return (ticks);
  372. }
  373. /*
  374. Get the RTOS kernel tick frequency.
  375. */
  376. uint32_t osKernelGetTickFreq (void) {
  377. /* Return frequency in hertz */
  378. return (configTICK_RATE_HZ);
  379. }
  380. /*
  381. Get the RTOS kernel system timer frequency.
  382. */
  383. uint32_t osKernelGetSysTimerFreq (void) {
  384. /* Return frequency in hertz */
  385. return (configCPU_CLOCK_HZ);
  386. }
  387. /* ==== Generic Wait Functions ==== */
  388. /*
  389. Wait for Timeout (Time Delay).
  390. */
  391. osStatus_t osDelay (uint32_t ticks) {
  392. osStatus_t stat;
  393. if (IRQ_Context() != 0U) {
  394. stat = osErrorISR;
  395. }
  396. else {
  397. stat = osOK;
  398. if (ticks != 0U) {
  399. vTaskDelay(ticks);
  400. }
  401. }
  402. /* Return execution status */
  403. return (stat);
  404. }
  405. /*
  406. Wait until specified time.
  407. */
  408. osStatus_t osDelayUntil (uint32_t ticks) {
  409. TickType_t tcnt, delay;
  410. osStatus_t stat;
  411. if (IRQ_Context() != 0U) {
  412. stat = osErrorISR;
  413. }
  414. else {
  415. stat = osOK;
  416. tcnt = xTaskGetTickCount();
  417. /* Determine remaining number of ticks to delay */
  418. delay = (TickType_t)ticks - tcnt;
  419. /* Check if target tick has not expired */
  420. if((delay != 0U) && (0 == (delay >> (8 * sizeof(TickType_t) - 1)))) {
  421. if (xTaskDelayUntil (&tcnt, delay) == pdFALSE) {
  422. /* Did not delay */
  423. stat = osError;
  424. }
  425. }
  426. else
  427. {
  428. /* No delay or already expired */
  429. stat = osErrorParameter;
  430. }
  431. }
  432. /* Return execution status */
  433. return (stat);
  434. }
  435. /* ==== Timer Management Functions ==== */
  436. #if (configUSE_OS2_TIMER == 1)
  437. static void TimerCallback (TimerHandle_t hTimer) {
  438. TimerCallback_t *callb;
  439. /* Retrieve pointer to callback function and argument */
  440. callb = (TimerCallback_t *)pvTimerGetTimerID (hTimer);
  441. /* Remove dynamic allocation flag */
  442. callb = (TimerCallback_t *)((uint32_t)callb & ~1U);
  443. if (callb != NULL) {
  444. callb->func (callb->arg);
  445. }
  446. }
  447. /*
  448. Create and Initialize a timer.
  449. */
  450. osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr) {
  451. const char *name;
  452. TimerHandle_t hTimer;
  453. TimerCallback_t *callb;
  454. UBaseType_t reload;
  455. int32_t mem;
  456. uint32_t callb_dyn;
  457. hTimer = NULL;
  458. if ((IRQ_Context() == 0U) && (func != NULL)) {
  459. callb = NULL;
  460. callb_dyn = 0U;
  461. #if (configSUPPORT_STATIC_ALLOCATION == 1)
  462. /* Static memory allocation is available: check if memory for control block */
  463. /* is provided and if it also contains space for callback and its argument */
  464. if ((attr != NULL) && (attr->cb_mem != NULL)) {
  465. if (attr->cb_size >= (sizeof(StaticTimer_t) + sizeof(TimerCallback_t))) {
  466. callb = (TimerCallback_t *)((uint32_t)attr->cb_mem + sizeof(StaticTimer_t));
  467. }
  468. }
  469. #endif
  470. #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
  471. /* Dynamic memory allocation is available: if memory for callback and */
  472. /* its argument is not provided, allocate it from dynamic memory pool */
  473. if (callb == NULL) {
  474. callb = (TimerCallback_t *)pvPortMalloc (sizeof(TimerCallback_t));
  475. if (callb != NULL) {
  476. /* Callback memory was allocated from dynamic pool, set flag */
  477. callb_dyn = 1U;
  478. }
  479. }
  480. #endif
  481. if (callb != NULL) {
  482. callb->func = func;
  483. callb->arg = argument;
  484. if (type == osTimerOnce) {
  485. reload = pdFALSE;
  486. } else {
  487. reload = pdTRUE;
  488. }
  489. mem = -1;
  490. name = NULL;
  491. if (attr != NULL) {
  492. if (attr->name != NULL) {
  493. name = attr->name;
  494. }
  495. if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticTimer_t))) {
  496. /* The memory for control block is provided, use static object */
  497. mem = 1;
  498. }
  499. else {
  500. if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
  501. /* Control block will be allocated from the dynamic pool */
  502. mem = 0;
  503. }
  504. }
  505. }
  506. else {
  507. mem = 0;
  508. }
  509. /* Store callback memory dynamic allocation flag */
  510. callb = (TimerCallback_t *)((uint32_t)callb | callb_dyn);
  511. /*
  512. TimerCallback function is always provided as a callback and is used to call application
  513. specified function with its argument both stored in structure callb.
  514. */
  515. if (mem == 1) {
  516. #if (configSUPPORT_STATIC_ALLOCATION == 1)
  517. hTimer = xTimerCreateStatic (name, 1, reload, callb, TimerCallback, (StaticTimer_t *)attr->cb_mem);
  518. #endif
  519. }
  520. else {
  521. if (mem == 0) {
  522. #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
  523. hTimer = xTimerCreate (name, 1, reload, callb, TimerCallback);
  524. #endif
  525. }
  526. }
  527. #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
  528. if ((hTimer == NULL) && (callb != NULL) && (callb_dyn == 1U)) {
  529. /* Failed to create a timer, release allocated resources */
  530. callb = (TimerCallback_t *)((uint32_t)callb & ~1U);
  531. vPortFree (callb);
  532. }
  533. #endif
  534. }
  535. }
  536. /* Return timer ID */
  537. return ((osTimerId_t)hTimer);
  538. }
  539. /*
  540. Get name of a timer.
  541. */
  542. const char *osTimerGetName (osTimerId_t timer_id) {
  543. TimerHandle_t hTimer = (TimerHandle_t)timer_id;
  544. const char *p;
  545. if ((IRQ_Context() != 0U) || (hTimer == NULL)) {
  546. p = NULL;
  547. } else {
  548. p = pcTimerGetName (hTimer);
  549. }
  550. /* Return name as null-terminated string */
  551. return (p);
  552. }
  553. /*
  554. Start or restart a timer.
  555. */
  556. osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks) {
  557. TimerHandle_t hTimer = (TimerHandle_t)timer_id;
  558. osStatus_t stat;
  559. if (IRQ_Context() != 0U) {
  560. stat = osErrorISR;
  561. }
  562. else if (hTimer == NULL) {
  563. stat = osErrorParameter;
  564. }
  565. else {
  566. if (xTimerChangePeriod (hTimer, ticks, portMAX_DELAY) == pdPASS) {
  567. stat = osOK;
  568. } else {
  569. stat = osErrorResource;
  570. }
  571. }
  572. /* Return execution status */
  573. return (stat);
  574. }
  575. /*
  576. Stop a timer.
  577. */
  578. osStatus_t osTimerStop (osTimerId_t timer_id) {
  579. TimerHandle_t hTimer = (TimerHandle_t)timer_id;
  580. osStatus_t stat;
  581. if (IRQ_Context() != 0U) {
  582. stat = osErrorISR;
  583. }
  584. else if (hTimer == NULL) {
  585. stat = osErrorParameter;
  586. }
  587. else {
  588. if (xTimerIsTimerActive (hTimer) == pdFALSE) {
  589. stat = osErrorResource;
  590. }
  591. else {
  592. if (xTimerStop (hTimer, portMAX_DELAY) == pdPASS) {
  593. stat = osOK;
  594. } else {
  595. stat = osError;
  596. }
  597. }
  598. }
  599. /* Return execution status */
  600. return (stat);
  601. }
  602. /*
  603. Check if a timer is running.
  604. */
  605. uint32_t osTimerIsRunning (osTimerId_t timer_id) {
  606. TimerHandle_t hTimer = (TimerHandle_t)timer_id;
  607. uint32_t running;
  608. if ((IRQ_Context() != 0U) || (hTimer == NULL)) {
  609. running = 0U;
  610. } else {
  611. running = (uint32_t)xTimerIsTimerActive (hTimer);
  612. }
  613. /* Return 0: not running, 1: running */
  614. return (running);
  615. }
  616. /*
  617. Delete a timer.
  618. */
  619. osStatus_t osTimerDelete (osTimerId_t timer_id) {
  620. TimerHandle_t hTimer = (TimerHandle_t)timer_id;
  621. osStatus_t stat;
  622. #ifndef USE_FreeRTOS_HEAP_1
  623. #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
  624. TimerCallback_t *callb;
  625. #endif
  626. if (IRQ_Context() != 0U) {
  627. stat = osErrorISR;
  628. }
  629. else if (hTimer == NULL) {
  630. stat = osErrorParameter;
  631. }
  632. else {
  633. #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
  634. callb = (TimerCallback_t *)pvTimerGetTimerID (hTimer);
  635. #endif
  636. if (xTimerDelete (hTimer, portMAX_DELAY) == pdPASS) {
  637. #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
  638. if ((uint32_t)callb & 1U) {
  639. /* Callback memory was allocated from dynamic pool, clear flag */
  640. callb = (TimerCallback_t *)((uint32_t)callb & ~1U);
  641. /* Return allocated memory to dynamic pool */
  642. vPortFree (callb);
  643. }
  644. #endif
  645. stat = osOK;
  646. } else {
  647. stat = osErrorResource;
  648. }
  649. }
  650. #else
  651. stat = osError;
  652. #endif
  653. /* Return execution status */
  654. return (stat);
  655. }
  656. #endif /* (configUSE_OS2_TIMER == 1) */
  657. /* ==== Message Queue Management Functions ==== */
  658. /*
  659. Create and Initialize a Message Queue object.
  660. Limitations:
  661. - The memory for control block and and message data must be provided in the
  662. osThreadAttr_t structure in order to allocate object statically.
  663. */
  664. osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) {
  665. QueueHandle_t hQueue;
  666. int32_t mem;
  667. hQueue = NULL;
  668. if ((IRQ_Context() == 0U) && (msg_count > 0U) && (msg_size > 0U)) {
  669. mem = -1;
  670. if (attr != NULL) {
  671. if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticQueue_t)) &&
  672. (attr->mq_mem != NULL) && (attr->mq_size >= (msg_count * msg_size))) {
  673. /* The memory for control block and message data is provided, use static object */
  674. mem = 1;
  675. }
  676. else {
  677. if ((attr->cb_mem == NULL) && (attr->cb_size == 0U) &&
  678. (attr->mq_mem == NULL) && (attr->mq_size == 0U)) {
  679. /* Control block will be allocated from the dynamic pool */
  680. mem = 0;
  681. }
  682. }
  683. }
  684. else {
  685. mem = 0;
  686. }
  687. if (mem == 1) {
  688. #if (configSUPPORT_STATIC_ALLOCATION == 1)
  689. hQueue = xQueueCreateStatic (msg_count, msg_size, attr->mq_mem, attr->cb_mem);
  690. #endif
  691. }
  692. else {
  693. if (mem == 0) {
  694. #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
  695. hQueue = xQueueCreate (msg_count, msg_size);
  696. #endif
  697. }
  698. }
  699. #if (configQUEUE_REGISTRY_SIZE > 0)
  700. if (hQueue != NULL) {
  701. if ((attr != NULL) && (attr->name != NULL)) {
  702. /* Only non-NULL name objects are added to the Queue Registry */
  703. vQueueAddToRegistry (hQueue, attr->name);
  704. }
  705. }
  706. #endif
  707. }
  708. /* Return message queue ID */
  709. return ((osMessageQueueId_t)hQueue);
  710. }
  711. /*
  712. Put a Message into a Queue or timeout if Queue is full.
  713. Limitations:
  714. - Message priority is ignored
  715. */
  716. osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
  717. QueueHandle_t hQueue = (QueueHandle_t)mq_id;
  718. osStatus_t stat;
  719. BaseType_t yield;
  720. (void)msg_prio; /* Message priority is ignored */
  721. stat = osOK;
  722. if (IRQ_Context() != 0U) {
  723. if ((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) {
  724. stat = osErrorParameter;
  725. }
  726. else {
  727. yield = pdFALSE;
  728. if (xQueueSendToBackFromISR (hQueue, msg_ptr, &yield) != pdTRUE) {
  729. stat = osErrorResource;
  730. } else {
  731. portYIELD_FROM_ISR (yield);
  732. }
  733. }
  734. }
  735. else {
  736. if ((hQueue == NULL) || (msg_ptr == NULL)) {
  737. stat = osErrorParameter;
  738. }
  739. else {
  740. if (xQueueSendToBack (hQueue, msg_ptr, (TickType_t)timeout) != pdPASS) {
  741. if (timeout != 0U) {
  742. stat = osErrorTimeout;
  743. } else {
  744. stat = osErrorResource;
  745. }
  746. }
  747. }
  748. }
  749. /* Return execution status */
  750. return (stat);
  751. }
  752. /*
  753. Get a Message from a Queue or timeout if Queue is empty.
  754. Limitations:
  755. - Message priority is ignored
  756. */
  757. osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
  758. QueueHandle_t hQueue = (QueueHandle_t)mq_id;
  759. osStatus_t stat;
  760. BaseType_t yield;
  761. (void)msg_prio; /* Message priority is ignored */
  762. stat = osOK;
  763. if (IRQ_Context() != 0U) {
  764. if ((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) {
  765. stat = osErrorParameter;
  766. }
  767. else {
  768. yield = pdFALSE;
  769. if (xQueueReceiveFromISR (hQueue, msg_ptr, &yield) != pdPASS) {
  770. stat = osErrorResource;
  771. } else {
  772. portYIELD_FROM_ISR (yield);
  773. }
  774. }
  775. }
  776. else {
  777. if ((hQueue == NULL) || (msg_ptr == NULL)) {
  778. stat = osErrorParameter;
  779. }
  780. else {
  781. if (xQueueReceive (hQueue, msg_ptr, (TickType_t)timeout) != pdPASS) {
  782. if (timeout != 0U) {
  783. stat = osErrorTimeout;
  784. } else {
  785. stat = osErrorResource;
  786. }
  787. }
  788. }
  789. }
  790. /* Return execution status */
  791. return (stat);
  792. }
  793. /*
  794. Get maximum number of messages in a Message Queue.
  795. */
  796. uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id) {
  797. StaticQueue_t *mq = (StaticQueue_t *)mq_id;
  798. uint32_t capacity;
  799. if (mq == NULL) {
  800. capacity = 0U;
  801. } else {
  802. /* capacity = pxQueue->uxLength */
  803. capacity = mq->uxDummy4[1];
  804. }
  805. /* Return maximum number of messages */
  806. return (capacity);
  807. }
  808. /*
  809. Get maximum message size in a Message Queue.
  810. */
  811. uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id) {
  812. StaticQueue_t *mq = (StaticQueue_t *)mq_id;
  813. uint32_t size;
  814. if (mq == NULL) {
  815. size = 0U;
  816. } else {
  817. /* size = pxQueue->uxItemSize */
  818. size = mq->uxDummy4[2];
  819. }
  820. /* Return maximum message size */
  821. return (size);
  822. }
  823. /*
  824. Get number of queued messages in a Message Queue.
  825. */
  826. uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id) {
  827. QueueHandle_t hQueue = (QueueHandle_t)mq_id;
  828. UBaseType_t count;
  829. if (hQueue == NULL) {
  830. count = 0U;
  831. }
  832. else if (IRQ_Context() != 0U) {
  833. count = uxQueueMessagesWaitingFromISR (hQueue);
  834. }
  835. else {
  836. count = uxQueueMessagesWaiting (hQueue);
  837. }
  838. /* Return number of queued messages */
  839. return ((uint32_t)count);
  840. }
  841. /*
  842. Get number of available slots for messages in a Message Queue.
  843. */
  844. uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id) {
  845. StaticQueue_t *mq = (StaticQueue_t *)mq_id;
  846. uint32_t space;
  847. uint32_t isrm;
  848. if (mq == NULL) {
  849. space = 0U;
  850. }
  851. else if (IRQ_Context() != 0U) {
  852. isrm = taskENTER_CRITICAL_FROM_ISR();
  853. /* space = pxQueue->uxLength - pxQueue->uxMessagesWaiting; */
  854. space = mq->uxDummy4[1] - mq->uxDummy4[0];
  855. taskEXIT_CRITICAL_FROM_ISR(isrm);
  856. }
  857. else {
  858. space = (uint32_t)uxQueueSpacesAvailable ((QueueHandle_t)mq);
  859. }
  860. /* Return number of available slots */
  861. return (space);
  862. }
  863. /*
  864. Reset a Message Queue to initial empty state.
  865. */
  866. osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id) {
  867. QueueHandle_t hQueue = (QueueHandle_t)mq_id;
  868. osStatus_t stat;
  869. if (IRQ_Context() != 0U) {
  870. stat = osErrorISR;
  871. }
  872. else if (hQueue == NULL) {
  873. stat = osErrorParameter;
  874. }
  875. else {
  876. stat = osOK;
  877. (void)xQueueReset (hQueue);
  878. }
  879. /* Return execution status */
  880. return (stat);
  881. }
  882. /*
  883. Delete a Message Queue object.
  884. */
  885. osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id) {
  886. QueueHandle_t hQueue = (QueueHandle_t)mq_id;
  887. osStatus_t stat;
  888. #ifndef USE_FreeRTOS_HEAP_1
  889. if (IRQ_Context() != 0U) {
  890. stat = osErrorISR;
  891. }
  892. else if (hQueue == NULL) {
  893. stat = osErrorParameter;
  894. }
  895. else {
  896. #if (configQUEUE_REGISTRY_SIZE > 0)
  897. vQueueUnregisterQueue (hQueue);
  898. #endif
  899. stat = osOK;
  900. vQueueDelete (hQueue);
  901. }
  902. #else
  903. stat = osError;
  904. #endif
  905. /* Return execution status */
  906. return (stat);
  907. }
  908. /* Callback function prototypes */
  909. extern void vApplicationIdleHook (void);
  910. extern void vApplicationMallocFailedHook (void);
  911. extern void vApplicationDaemonTaskStartupHook (void);
  912. /**
  913. Dummy implementation of the callback function vApplicationIdleHook().
  914. */
  915. #if (configUSE_IDLE_HOOK == 1)
  916. __WEAK void vApplicationIdleHook (void){}
  917. #endif
  918. /**
  919. Dummy implementation of the callback function vApplicationTickHook().
  920. */
  921. #if (configUSE_TICK_HOOK == 1)
  922. __WEAK void vApplicationTickHook (void){}
  923. #endif
  924. /**
  925. Dummy implementation of the callback function vApplicationMallocFailedHook().
  926. */
  927. #if (configUSE_MALLOC_FAILED_HOOK == 1)
  928. __WEAK void vApplicationMallocFailedHook (void) {
  929. /* Assert when malloc failed hook is enabled but no application defined function exists */
  930. configASSERT(0);
  931. }
  932. #endif
  933. /**
  934. Dummy implementation of the callback function vApplicationDaemonTaskStartupHook().
  935. */
  936. #if (configUSE_DAEMON_TASK_STARTUP_HOOK == 1)
  937. __WEAK void vApplicationDaemonTaskStartupHook (void){}
  938. #endif
  939. /**
  940. Dummy implementation of the callback function vApplicationStackOverflowHook().
  941. */
  942. #if (configCHECK_FOR_STACK_OVERFLOW > 0)
  943. __WEAK void vApplicationStackOverflowHook (TaskHandle_t xTask, char *pcTaskName) {
  944. (void)xTask;
  945. (void)pcTaskName;
  946. /* Assert when stack overflow is enabled but no application defined function exists */
  947. configASSERT(0);
  948. }
  949. #endif