]> begriffs open source - cmsis-freertos/blob - CMSIS/RTOS2/FreeRTOS/Source/cmsis_os2.c
Enable full static memory allocation for timer object (#48)
[cmsis-freertos] / CMSIS / RTOS2 / FreeRTOS / Source / cmsis_os2.c
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
23 #include <string.h>
24
25 #include "cmsis_os2.h"                  // ::CMSIS:RTOS2
26 #include "cmsis_compiler.h"             // Compiler agnostic definitions
27 #include "os_tick.h"                    // OS Tick API
28
29 #include "FreeRTOS.h"                   // ARM.FreeRTOS::RTOS:Core
30 #include "task.h"                       // ARM.FreeRTOS::RTOS:Core
31 #include "event_groups.h"               // ARM.FreeRTOS::RTOS:Event Groups
32 #include "semphr.h"                     // ARM.FreeRTOS::RTOS:Core
33 #include "timers.h"                     // ARM.FreeRTOS::RTOS:Timers
34
35 #include "freertos_mpool.h"             // osMemoryPool definitions
36 #include "freertos_os2.h"               // Configuration check and setup
37
38 /*---------------------------------------------------------------------------*/
39 #ifndef __ARM_ARCH_6M__
40   #define __ARM_ARCH_6M__         0
41 #endif
42 #ifndef __ARM_ARCH_7M__
43   #define __ARM_ARCH_7M__         0
44 #endif
45 #ifndef __ARM_ARCH_7EM__
46   #define __ARM_ARCH_7EM__        0
47 #endif
48 #ifndef __ARM_ARCH_8M_MAIN__
49   #define __ARM_ARCH_8M_MAIN__    0
50 #endif
51 #ifndef __ARM_ARCH_7A__
52   #define __ARM_ARCH_7A__         0
53 #endif
54
55 #if   ((__ARM_ARCH_7M__      == 1U) || \
56        (__ARM_ARCH_7EM__     == 1U) || \
57        (__ARM_ARCH_8M_MAIN__ == 1U))
58 #define IS_IRQ_MASKED()           ((__get_PRIMASK() != 0U) || (__get_BASEPRI() != 0U))
59 #elif  (__ARM_ARCH_6M__      == 1U)
60 #define IS_IRQ_MASKED()           (__get_PRIMASK() != 0U)
61 #elif (__ARM_ARCH_7A__       == 1U)
62 /* CPSR mask bits */
63 #define CPSR_MASKBIT_I            0x80U
64
65 #define IS_IRQ_MASKED()           ((__get_CPSR() & CPSR_MASKBIT_I) != 0U)
66 #else
67 #define IS_IRQ_MASKED()           (__get_PRIMASK() != 0U)
68 #endif
69
70 #if    (__ARM_ARCH_7A__      == 1U)
71 /* CPSR mode bitmasks */
72 #define CPSR_MODE_USER            0x10U
73 #define CPSR_MODE_SYSTEM          0x1FU
74
75 #define IS_IRQ_MODE()             ((__get_mode() != CPSR_MODE_USER) && (__get_mode() != CPSR_MODE_SYSTEM))
76 #else
77 #define IS_IRQ_MODE()             (__get_IPSR() != 0U)
78 #endif
79
80 /* Limits */
81 #define MAX_BITS_TASK_NOTIFY      31U
82 #define MAX_BITS_EVENT_GROUPS     24U
83
84 #define THREAD_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_TASK_NOTIFY)  - 1U))
85 #define EVENT_FLAGS_INVALID_BITS  (~((1UL << MAX_BITS_EVENT_GROUPS) - 1U))
86
87 /* Kernel version and identification string definition (major.minor.rev: mmnnnrrrr dec) */
88 #define KERNEL_VERSION            (((uint32_t)tskKERNEL_VERSION_MAJOR * 10000000UL) | \
89                                    ((uint32_t)tskKERNEL_VERSION_MINOR *    10000UL) | \
90                                    ((uint32_t)tskKERNEL_VERSION_BUILD *        1UL))
91
92 #define KERNEL_ID                 ("FreeRTOS " tskKERNEL_VERSION_NUMBER)
93
94 /* Timer callback information structure definition */
95 typedef struct {
96   osTimerFunc_t func;
97   void         *arg;
98 } TimerCallback_t;
99
100 /* Kernel initialization state */
101 static osKernelState_t KernelState = osKernelInactive;
102
103 /*
104   Heap region definition used by heap_5 variant
105
106   Define configAPPLICATION_ALLOCATED_HEAP as nonzero value in FreeRTOSConfig.h if
107   heap regions are already defined and vPortDefineHeapRegions is called in application.
108
109   Otherwise vPortDefineHeapRegions will be called by osKernelInitialize using
110   definition configHEAP_5_REGIONS as parameter. Overriding configHEAP_5_REGIONS
111   is possible by defining it globally or in FreeRTOSConfig.h.
112 */
113 #if defined(USE_FreeRTOS_HEAP_5)
114 #if (configAPPLICATION_ALLOCATED_HEAP == 0)
115   /*
116     FreeRTOS heap is not defined by the application.
117     Single region of size configTOTAL_HEAP_SIZE (defined in FreeRTOSConfig.h)
118     is provided by default. Define configHEAP_5_REGIONS to provide custom
119     HeapRegion_t array.
120   */
121   #define HEAP_5_REGION_SETUP   1
122   
123   #ifndef configHEAP_5_REGIONS
124     #define configHEAP_5_REGIONS xHeapRegions
125
126     static uint8_t ucHeap[configTOTAL_HEAP_SIZE];
127
128     static HeapRegion_t xHeapRegions[] = {
129       { ucHeap, configTOTAL_HEAP_SIZE },
130       { NULL,   0                     }
131     };
132   #else
133     /* Global definition is provided to override default heap array */
134     extern HeapRegion_t configHEAP_5_REGIONS[];
135   #endif
136 #else
137   /*
138     The application already defined the array used for the FreeRTOS heap and
139     called vPortDefineHeapRegions to initialize heap.
140   */
141   #define HEAP_5_REGION_SETUP   0
142 #endif /* configAPPLICATION_ALLOCATED_HEAP */
143 #endif /* USE_FreeRTOS_HEAP_5 */
144
145 #if defined(SysTick)
146 #undef SysTick_Handler
147
148 /* CMSIS SysTick interrupt handler prototype */
149 extern void SysTick_Handler     (void);
150 /* FreeRTOS tick timer interrupt handler prototype */
151 extern void xPortSysTickHandler (void);
152
153 /*
154   SysTick handler implementation that also clears overflow flag.
155 */
156 void SysTick_Handler (void) {
157   /* Clear overflow flag */
158   SysTick->CTRL;
159
160   if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
161     /* Call tick handler */
162     xPortSysTickHandler();
163   }
164 }
165 #endif /* SysTick */
166
167 /*
168   Setup SVC to reset value.
169 */
170 __STATIC_INLINE void SVC_Setup (void) {
171 #if (__ARM_ARCH_7A__ == 0U)
172   /* Service Call interrupt might be configured before kernel start     */
173   /* and when its priority is lower or equal to BASEPRI, svc intruction */
174   /* causes a Hard Fault.                                               */
175   NVIC_SetPriority (SVCall_IRQn, 0U);
176 #endif
177 }
178
179 /*
180   Function macro used to retrieve semaphore count from ISR
181 */
182 #ifndef uxSemaphoreGetCountFromISR
183 #define uxSemaphoreGetCountFromISR( xSemaphore ) uxQueueMessagesWaitingFromISR( ( QueueHandle_t ) ( xSemaphore ) )
184 #endif
185
186 /*
187   Determine if CPU executes from interrupt context or if interrupts are masked.
188 */
189 __STATIC_INLINE uint32_t IRQ_Context (void) {
190   uint32_t irq;
191   BaseType_t state;
192
193   irq = 0U;
194
195   if (IS_IRQ_MODE()) {
196     /* Called from interrupt context */
197     irq = 1U;
198   }
199   else {
200     /* Get FreeRTOS scheduler state */
201     state = xTaskGetSchedulerState();
202
203     if (state != taskSCHEDULER_NOT_STARTED) {
204       /* Scheduler was started */
205       if (IS_IRQ_MASKED()) {
206         /* Interrupts are masked */
207         irq = 1U;
208       }
209     }
210   }
211
212   /* Return context, 0: thread context, 1: IRQ context */
213   return (irq);
214 }
215
216
217 /* ==== Kernel Management Functions ==== */
218
219 /*
220   Initialize the RTOS Kernel.
221 */
222 osStatus_t osKernelInitialize (void) {
223   osStatus_t stat;
224   BaseType_t state;
225
226   if (IRQ_Context() != 0U) {
227     stat = osErrorISR;
228   }
229   else {
230     state = xTaskGetSchedulerState();
231
232     /* Initialize if scheduler not started and not initialized before */
233     if ((state == taskSCHEDULER_NOT_STARTED) && (KernelState == osKernelInactive)) {
234       #if defined(USE_TRACE_EVENT_RECORDER)
235         /* Initialize the trace macro debugging output channel */
236         EvrFreeRTOSSetup(0U);
237       #endif
238       #if defined(USE_FreeRTOS_HEAP_5) && (HEAP_5_REGION_SETUP == 1)
239         /* Initialize the memory regions when using heap_5 variant */
240         vPortDefineHeapRegions (configHEAP_5_REGIONS);
241       #endif
242       KernelState = osKernelReady;
243       stat = osOK;
244     } else {
245       stat = osError;
246     }
247   }
248
249   /* Return execution status */
250   return (stat);
251 }
252
253 /*
254   Get RTOS Kernel Information.
255 */
256 osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size) {
257
258   if (version != NULL) {
259     /* Version encoding is major.minor.rev: mmnnnrrrr dec */
260     version->api    = KERNEL_VERSION;
261     version->kernel = KERNEL_VERSION;
262   }
263
264   if ((id_buf != NULL) && (id_size != 0U)) {
265     /* Buffer for retrieving identification string is provided */
266     if (id_size > sizeof(KERNEL_ID)) {
267       id_size = sizeof(KERNEL_ID);
268     }
269     /* Copy kernel identification string into provided buffer */
270     memcpy(id_buf, KERNEL_ID, id_size);
271   }
272
273   /* Return execution status */
274   return (osOK);
275 }
276
277 /*
278   Get the current RTOS Kernel state.
279 */
280 osKernelState_t osKernelGetState (void) {
281   osKernelState_t state;
282
283   switch (xTaskGetSchedulerState()) {
284     case taskSCHEDULER_RUNNING:
285       state = osKernelRunning;
286       break;
287
288     case taskSCHEDULER_SUSPENDED:
289       state = osKernelLocked;
290       break;
291
292     case taskSCHEDULER_NOT_STARTED:
293     default:
294       if (KernelState == osKernelReady) {
295         /* Ready, osKernelInitialize was already called */
296         state = osKernelReady;
297       } else {
298         /* Not initialized */
299         state = osKernelInactive;
300       }
301       break;
302   }
303
304   /* Return current state */
305   return (state);
306 }
307
308 /*
309   Start the RTOS Kernel scheduler.
310 */
311 osStatus_t osKernelStart (void) {
312   osStatus_t stat;
313   BaseType_t state;
314
315   if (IRQ_Context() != 0U) {
316     stat = osErrorISR;
317   }
318   else {
319     state = xTaskGetSchedulerState();
320
321     /* Start scheduler if initialized and not started before */
322     if ((state == taskSCHEDULER_NOT_STARTED) && (KernelState == osKernelReady)) {
323       /* Ensure SVC priority is at the reset value */
324       SVC_Setup();
325       /* Change state to ensure correct API flow */
326       KernelState = osKernelRunning;
327       /* Start the kernel scheduler */
328       vTaskStartScheduler();
329       stat = osOK;
330     } else {
331       stat = osError;
332     }
333   }
334
335   /* Return execution status */
336   return (stat);
337 }
338
339 /*
340   Lock the RTOS Kernel scheduler.
341 */
342 int32_t osKernelLock (void) {
343   int32_t lock;
344
345   if (IRQ_Context() != 0U) {
346     lock = (int32_t)osErrorISR;
347   }
348   else {
349     switch (xTaskGetSchedulerState()) {
350       case taskSCHEDULER_SUSPENDED:
351         lock = 1;
352         break;
353
354       case taskSCHEDULER_RUNNING:
355         vTaskSuspendAll();
356         lock = 0;
357         break;
358
359       case taskSCHEDULER_NOT_STARTED:
360       default:
361         lock = (int32_t)osError;
362         break;
363     }
364   }
365
366   /* Return previous lock state */
367   return (lock);
368 }
369
370 /*
371   Unlock the RTOS Kernel scheduler.
372 */
373 int32_t osKernelUnlock (void) {
374   int32_t lock;
375
376   if (IRQ_Context() != 0U) {
377     lock = (int32_t)osErrorISR;
378   }
379   else {
380     switch (xTaskGetSchedulerState()) {
381       case taskSCHEDULER_SUSPENDED:
382         lock = 1;
383
384         if (xTaskResumeAll() != pdTRUE) {
385           if (xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) {
386             lock = (int32_t)osError;
387           }
388         }
389         break;
390
391       case taskSCHEDULER_RUNNING:
392         lock = 0;
393         break;
394
395       case taskSCHEDULER_NOT_STARTED:
396       default:
397         lock = (int32_t)osError;
398         break;
399     }
400   }
401
402   /* Return previous lock state */
403   return (lock);
404 }
405
406 /*
407   Restore the RTOS Kernel scheduler lock state.
408 */
409 int32_t osKernelRestoreLock (int32_t lock) {
410
411   if (IRQ_Context() != 0U) {
412     lock = (int32_t)osErrorISR;
413   }
414   else {
415     switch (xTaskGetSchedulerState()) {
416       case taskSCHEDULER_SUSPENDED:
417       case taskSCHEDULER_RUNNING:
418         if (lock == 1) {
419           vTaskSuspendAll();
420         }
421         else {
422           if (lock != 0) {
423             lock = (int32_t)osError;
424           }
425           else {
426             if (xTaskResumeAll() != pdTRUE) {
427               if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) {
428                 lock = (int32_t)osError;
429               }
430             }
431           }
432         }
433         break;
434
435       case taskSCHEDULER_NOT_STARTED:
436       default:
437         lock = (int32_t)osError;
438         break;
439     }
440   }
441
442   /* Return new lock state */
443   return (lock);
444 }
445
446 /*
447   Get the RTOS kernel tick count.
448 */
449 uint32_t osKernelGetTickCount (void) {
450   TickType_t ticks;
451
452   if (IRQ_Context() != 0U) {
453     ticks = xTaskGetTickCountFromISR();
454   } else {
455     ticks = xTaskGetTickCount();
456   }
457
458   /* Return kernel tick count */
459   return (ticks);
460 }
461
462 /*
463   Get the RTOS kernel tick frequency.
464 */
465 uint32_t osKernelGetTickFreq (void) {
466   /* Return frequency in hertz */
467   return (configTICK_RATE_HZ);
468 }
469
470 /*
471   Get the RTOS kernel system timer count.
472 */
473 uint32_t osKernelGetSysTimerCount (void) {
474   uint32_t irqmask = IS_IRQ_MASKED();
475   TickType_t ticks;
476   uint32_t val;
477
478   __disable_irq();
479
480   ticks = xTaskGetTickCount();
481   val   = OS_Tick_GetCount();
482
483   /* Update tick count and timer value when timer overflows */
484   if (OS_Tick_GetOverflow() != 0U) {
485     val = OS_Tick_GetCount();
486     ticks++;
487   }
488   val += ticks * OS_Tick_GetInterval();
489
490   if (irqmask == 0U) {
491     __enable_irq();
492   }
493
494   /* Return system timer count */
495   return (val);
496 }
497
498 /*
499   Get the RTOS kernel system timer frequency.
500 */
501 uint32_t osKernelGetSysTimerFreq (void) {
502   /* Return frequency in hertz */
503   return (configCPU_CLOCK_HZ);
504 }
505
506
507 /* ==== Thread Management Functions ==== */
508
509 /*
510   Create a thread and add it to Active Threads.
511
512   Limitations:
513   - The memory for control block and stack must be provided in the osThreadAttr_t
514     structure in order to allocate object statically.
515   - Attribute osThreadJoinable is not supported, NULL is returned if used.
516 */
517 osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr) {
518   const char *name;
519   uint32_t stack;
520   TaskHandle_t hTask;
521   UBaseType_t prio;
522   int32_t mem;
523
524   hTask = NULL;
525
526   if ((IRQ_Context() == 0U) && (func != NULL)) {
527     stack = configMINIMAL_STACK_SIZE;
528     prio  = (UBaseType_t)osPriorityNormal;
529
530     name = NULL;
531     mem  = -1;
532
533     if (attr != NULL) {
534       if (attr->name != NULL) {
535         name = attr->name;
536       }
537       if (attr->priority != osPriorityNone) {
538         prio = (UBaseType_t)attr->priority;
539       }
540
541       if ((prio < osPriorityIdle) || (prio > osPriorityISR) || ((attr->attr_bits & osThreadJoinable) == osThreadJoinable)) {
542         /* Invalid priority or unsupported osThreadJoinable attribute used */
543         return (NULL);
544       }
545
546       if (attr->stack_size > 0U) {
547         /* In FreeRTOS stack is not in bytes, but in sizeof(StackType_t) which is 4 on ARM ports.       */
548         /* Stack size should be therefore 4 byte aligned in order to avoid division caused side effects */
549         stack = attr->stack_size / sizeof(StackType_t);
550       }
551
552       if ((attr->cb_mem    != NULL) && (attr->cb_size    >= sizeof(StaticTask_t)) &&
553           (attr->stack_mem != NULL) && (attr->stack_size >  0U)) {
554         /* The memory for control block and stack is provided, use static object */
555         mem = 1;
556       }
557       else {
558         if ((attr->cb_mem == NULL) && (attr->cb_size == 0U) && (attr->stack_mem == NULL)) {
559           /* Control block and stack memory will be allocated from the dynamic pool */
560           mem = 0;
561         }
562       }
563     }
564     else {
565       mem = 0;
566     }
567
568     if (mem == 1) {
569       #if (configSUPPORT_STATIC_ALLOCATION == 1)
570         hTask = xTaskCreateStatic ((TaskFunction_t)func, name, stack, argument, prio, (StackType_t  *)attr->stack_mem,
571                                                                                       (StaticTask_t *)attr->cb_mem);
572       #endif
573     }
574     else {
575       if (mem == 0) {
576         #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
577           if (xTaskCreate ((TaskFunction_t)func, name, (uint16_t)stack, argument, prio, &hTask) != pdPASS) {
578             hTask = NULL;
579           }
580         #endif
581       }
582     }
583   }
584
585   /* Return thread ID */
586   return ((osThreadId_t)hTask);
587 }
588
589 /*
590   Get name of a thread.
591 */
592 const char *osThreadGetName (osThreadId_t thread_id) {
593   TaskHandle_t hTask = (TaskHandle_t)thread_id;
594   const char *name;
595
596   if ((IRQ_Context() != 0U) || (hTask == NULL)) {
597     name = NULL;
598   } else {
599     name = pcTaskGetName (hTask);
600   }
601
602   /* Return name as null-terminated string */
603   return (name);
604 }
605
606 /*
607   Return the thread ID of the current running thread.
608 */
609 osThreadId_t osThreadGetId (void) {
610   osThreadId_t id;
611
612   id = (osThreadId_t)xTaskGetCurrentTaskHandle();
613
614   /* Return thread ID */
615   return (id);
616 }
617
618 /*
619   Get current thread state of a thread.
620 */
621 osThreadState_t osThreadGetState (osThreadId_t thread_id) {
622   TaskHandle_t hTask = (TaskHandle_t)thread_id;
623   osThreadState_t state;
624
625   if ((IRQ_Context() != 0U) || (hTask == NULL)) {
626     state = osThreadError;
627   }
628   else {
629     switch (eTaskGetState (hTask)) {
630       case eRunning:   state = osThreadRunning;    break;
631       case eReady:     state = osThreadReady;      break;
632       case eBlocked:
633       case eSuspended: state = osThreadBlocked;    break;
634       case eDeleted:   state = osThreadTerminated; break;
635       case eInvalid:
636       default:         state = osThreadError;      break;
637     }
638   }
639
640   /* Return current thread state */
641   return (state);
642 }
643
644 /*
645   Get available stack space of a thread based on stack watermark recording during execution.
646 */
647 uint32_t osThreadGetStackSpace (osThreadId_t thread_id) {
648   TaskHandle_t hTask = (TaskHandle_t)thread_id;
649   uint32_t sz;
650
651   if ((IRQ_Context() != 0U) || (hTask == NULL)) {
652     sz = 0U;
653   } else {
654     sz = (uint32_t)(uxTaskGetStackHighWaterMark(hTask) * sizeof(StackType_t));
655   }
656
657   /* Return remaining stack space in bytes */
658   return (sz);
659 }
660
661 /*
662   Change priority of a thread.
663 */
664 osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority) {
665   TaskHandle_t hTask = (TaskHandle_t)thread_id;
666   osStatus_t stat;
667
668   if (IRQ_Context() != 0U) {
669     stat = osErrorISR;
670   }
671   else if ((hTask == NULL) || (priority < osPriorityIdle) || (priority > osPriorityISR)) {
672     stat = osErrorParameter;
673   }
674   else {
675     stat = osOK;
676     vTaskPrioritySet (hTask, (UBaseType_t)priority);
677   }
678
679   /* Return execution status */
680   return (stat);
681 }
682
683 /*
684   Get current priority of a thread.
685 */
686 osPriority_t osThreadGetPriority (osThreadId_t thread_id) {
687   TaskHandle_t hTask = (TaskHandle_t)thread_id;
688   osPriority_t prio;
689
690   if ((IRQ_Context() != 0U) || (hTask == NULL)) {
691     prio = osPriorityError;
692   } else {
693     prio = (osPriority_t)((int32_t)uxTaskPriorityGet (hTask));
694   }
695
696   /* Return current thread priority */
697   return (prio);
698 }
699
700 /*
701   Pass control to next thread that is in state READY.
702 */
703 osStatus_t osThreadYield (void) {
704   osStatus_t stat;
705
706   if (IRQ_Context() != 0U) {
707     stat = osErrorISR;
708   } else {
709     stat = osOK;
710     taskYIELD();
711   }
712
713   /* Return execution status */
714   return (stat);
715 }
716
717 #if (configUSE_OS2_THREAD_SUSPEND_RESUME == 1)
718 /*
719   Suspend execution of a thread.
720 */
721 osStatus_t osThreadSuspend (osThreadId_t thread_id) {
722   TaskHandle_t hTask = (TaskHandle_t)thread_id;
723   osStatus_t stat;
724
725   if (IRQ_Context() != 0U) {
726     stat = osErrorISR;
727   }
728   else if (hTask == NULL) {
729     stat = osErrorParameter;
730   }
731   else {
732     stat = osOK;
733     vTaskSuspend (hTask);
734   }
735
736   /* Return execution status */
737   return (stat);
738 }
739
740 /*
741   Resume execution of a thread.
742 */
743 osStatus_t osThreadResume (osThreadId_t thread_id) {
744   TaskHandle_t hTask = (TaskHandle_t)thread_id;
745   osStatus_t stat;
746
747   if (IRQ_Context() != 0U) {
748     stat = osErrorISR;
749   }
750   else if (hTask == NULL) {
751     stat = osErrorParameter;
752   }
753   else {
754     stat = osOK;
755     vTaskResume (hTask);
756   }
757
758   /* Return execution status */
759   return (stat);
760 }
761 #endif /* (configUSE_OS2_THREAD_SUSPEND_RESUME == 1) */
762
763 /*
764   Terminate execution of current running thread.
765 */
766 __NO_RETURN void osThreadExit (void) {
767 #ifndef USE_FreeRTOS_HEAP_1
768   vTaskDelete (NULL);
769 #endif
770   for (;;);
771 }
772
773 /*
774   Terminate execution of a thread.
775 */
776 osStatus_t osThreadTerminate (osThreadId_t thread_id) {
777   TaskHandle_t hTask = (TaskHandle_t)thread_id;
778   osStatus_t stat;
779 #ifndef USE_FreeRTOS_HEAP_1
780   eTaskState tstate;
781
782   if (IRQ_Context() != 0U) {
783     stat = osErrorISR;
784   }
785   else if (hTask == NULL) {
786     stat = osErrorParameter;
787   }
788   else {
789     tstate = eTaskGetState (hTask);
790
791     if (tstate != eDeleted) {
792       stat = osOK;
793       vTaskDelete (hTask);
794     } else {
795       stat = osErrorResource;
796     }
797   }
798 #else
799   stat = osError;
800 #endif
801
802   /* Return execution status */
803   return (stat);
804 }
805
806 /*
807   Get number of active threads.
808 */
809 uint32_t osThreadGetCount (void) {
810   uint32_t count;
811
812   if (IRQ_Context() != 0U) {
813     count = 0U;
814   } else {
815     count = uxTaskGetNumberOfTasks();
816   }
817
818   /* Return number of active threads */
819   return (count);
820 }
821
822 #if (configUSE_OS2_THREAD_ENUMERATE == 1)
823 /*
824   Enumerate active threads.
825 */
826 uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items) {
827   uint32_t i, count;
828   TaskStatus_t *task;
829
830   if ((IRQ_Context() != 0U) || (thread_array == NULL) || (array_items == 0U)) {
831     count = 0U;
832   } else {
833     vTaskSuspendAll();
834
835     /* Allocate memory on heap to temporarily store TaskStatus_t information */
836     count = uxTaskGetNumberOfTasks();
837     task  = pvPortMalloc (count * sizeof(TaskStatus_t));
838
839     if (task != NULL) {
840       /* Retrieve task status information */
841       count = uxTaskGetSystemState (task, count, NULL);
842
843       /* Copy handles from task status array into provided thread array */
844       for (i = 0U; (i < count) && (i < array_items); i++) {
845         thread_array[i] = (osThreadId_t)task[i].xHandle;
846       }
847       count = i;
848     }
849     (void)xTaskResumeAll();
850
851     vPortFree (task);
852   }
853
854   /* Return number of enumerated threads */
855   return (count);
856 }
857 #endif /* (configUSE_OS2_THREAD_ENUMERATE == 1) */
858
859
860 /* ==== Thread Flags Functions ==== */
861
862 #if (configUSE_OS2_THREAD_FLAGS == 1)
863 /*
864   Set the specified Thread Flags of a thread.
865 */
866 uint32_t osThreadFlagsSet (osThreadId_t thread_id, uint32_t flags) {
867   TaskHandle_t hTask = (TaskHandle_t)thread_id;
868   uint32_t rflags;
869   BaseType_t yield;
870
871   if ((hTask == NULL) || ((flags & THREAD_FLAGS_INVALID_BITS) != 0U)) {
872     rflags = (uint32_t)osErrorParameter;
873   }
874   else {
875     rflags = (uint32_t)osError;
876
877     if (IRQ_Context() != 0U) {
878       yield = pdFALSE;
879
880       (void)xTaskNotifyFromISR (hTask, flags, eSetBits, &yield);
881       (void)xTaskNotifyAndQueryFromISR (hTask, 0, eNoAction, &rflags, NULL);
882
883       portYIELD_FROM_ISR (yield);
884     }
885     else {
886       (void)xTaskNotify (hTask, flags, eSetBits);
887       (void)xTaskNotifyAndQuery (hTask, 0, eNoAction, &rflags);
888     }
889   }
890   /* Return flags after setting */
891   return (rflags);
892 }
893
894 /*
895   Clear the specified Thread Flags of current running thread.
896 */
897 uint32_t osThreadFlagsClear (uint32_t flags) {
898   TaskHandle_t hTask;
899   uint32_t rflags, cflags;
900
901   if (IRQ_Context() != 0U) {
902     rflags = (uint32_t)osErrorISR;
903   }
904   else if ((flags & THREAD_FLAGS_INVALID_BITS) != 0U) {
905     rflags = (uint32_t)osErrorParameter;
906   }
907   else {
908     hTask = xTaskGetCurrentTaskHandle();
909
910     if (xTaskNotifyAndQuery (hTask, 0, eNoAction, &cflags) == pdPASS) {
911       rflags = cflags;
912       cflags &= ~flags;
913
914       if (xTaskNotify (hTask, cflags, eSetValueWithOverwrite) != pdPASS) {
915         rflags = (uint32_t)osError;
916       }
917     }
918     else {
919       rflags = (uint32_t)osError;
920     }
921   }
922
923   /* Return flags before clearing */
924   return (rflags);
925 }
926
927 /*
928   Get the current Thread Flags of current running thread.
929 */
930 uint32_t osThreadFlagsGet (void) {
931   TaskHandle_t hTask;
932   uint32_t rflags;
933
934   if (IRQ_Context() != 0U) {
935     rflags = (uint32_t)osErrorISR;
936   }
937   else {
938     hTask = xTaskGetCurrentTaskHandle();
939
940     if (xTaskNotifyAndQuery (hTask, 0, eNoAction, &rflags) != pdPASS) {
941       rflags = (uint32_t)osError;
942     }
943   }
944
945   /* Return current flags */
946   return (rflags);
947 }
948
949 /*
950   Wait for one or more Thread Flags of the current running thread to become signaled.
951 */
952 uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout) {
953   uint32_t rflags, nval;
954   uint32_t clear;
955   TickType_t t0, td, tout;
956   BaseType_t rval;
957
958   if (IRQ_Context() != 0U) {
959     rflags = (uint32_t)osErrorISR;
960   }
961   else if ((flags & THREAD_FLAGS_INVALID_BITS) != 0U) {
962     rflags = (uint32_t)osErrorParameter;
963   }
964   else {
965     if ((options & osFlagsNoClear) == osFlagsNoClear) {
966       clear = 0U;
967     } else {
968       clear = flags;
969     }
970
971     rflags = 0U;
972     tout   = timeout;
973
974     t0 = xTaskGetTickCount();
975     do {
976       rval = xTaskNotifyWait (0, clear, &nval, tout);
977
978       if (rval == pdPASS) {
979         rflags &= flags;
980         rflags |= nval;
981
982         if ((options & osFlagsWaitAll) == osFlagsWaitAll) {
983           if ((flags & rflags) == flags) {
984             break;
985           } else {
986             if (timeout == 0U) {
987               rflags = (uint32_t)osErrorResource;
988               break;
989             }
990           }
991         }
992         else {
993           if ((flags & rflags) != 0) {
994             break;
995           } else {
996             if (timeout == 0U) {
997               rflags = (uint32_t)osErrorResource;
998               break;
999             }
1000           }
1001         }
1002
1003         /* Update timeout */
1004         td = xTaskGetTickCount() - t0;
1005
1006         if (td > tout) {
1007           tout  = 0;
1008         } else {
1009           tout -= td;
1010         }
1011       }
1012       else {
1013         if (timeout == 0) {
1014           rflags = (uint32_t)osErrorResource;
1015         } else {
1016           rflags = (uint32_t)osErrorTimeout;
1017         }
1018       }
1019     }
1020     while (rval != pdFAIL);
1021   }
1022
1023   /* Return flags before clearing */
1024   return (rflags);
1025 }
1026 #endif /* (configUSE_OS2_THREAD_FLAGS == 1) */
1027
1028
1029 /* ==== Generic Wait Functions ==== */
1030
1031 /*
1032   Wait for Timeout (Time Delay).
1033 */
1034 osStatus_t osDelay (uint32_t ticks) {
1035   osStatus_t stat;
1036
1037   if (IRQ_Context() != 0U) {
1038     stat = osErrorISR;
1039   }
1040   else {
1041     stat = osOK;
1042
1043     if (ticks != 0U) {
1044       vTaskDelay(ticks);
1045     }
1046   }
1047
1048   /* Return execution status */
1049   return (stat);
1050 }
1051
1052 /*
1053   Wait until specified time.
1054 */
1055 osStatus_t osDelayUntil (uint32_t ticks) {
1056   TickType_t tcnt, delay;
1057   osStatus_t stat;
1058
1059   if (IRQ_Context() != 0U) {
1060     stat = osErrorISR;
1061   }
1062   else {
1063     stat = osOK;
1064     tcnt = xTaskGetTickCount();
1065
1066     /* Determine remaining number of ticks to delay */
1067     delay = (TickType_t)ticks - tcnt;
1068
1069     /* Check if target tick has not expired */
1070     if((delay != 0U) && (0 == (delay >> (8 * sizeof(TickType_t) - 1)))) {
1071       vTaskDelayUntil (&tcnt, delay);
1072     }
1073     else
1074     {
1075       /* No delay or already expired */
1076       stat = osErrorParameter;
1077     }
1078   }
1079
1080   /* Return execution status */
1081   return (stat);
1082 }
1083
1084
1085 /* ==== Timer Management Functions ==== */
1086
1087 #if (configUSE_OS2_TIMER == 1)
1088
1089 static void TimerCallback (TimerHandle_t hTimer) {
1090   TimerCallback_t *callb;
1091
1092   /* Retrieve pointer to callback function and argument */
1093   callb = (TimerCallback_t *)pvTimerGetTimerID (hTimer);
1094
1095   /* Remove dynamic allocation flag */
1096   callb = (TimerCallback_t *)((uint32_t)callb & ~1U);
1097
1098   if (callb != NULL) {
1099     callb->func (callb->arg);
1100   }
1101 }
1102
1103 /*
1104   Create and Initialize a timer.
1105 */
1106 osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr) {
1107   const char *name;
1108   TimerHandle_t hTimer;
1109   TimerCallback_t *callb;
1110   UBaseType_t reload;
1111   int32_t mem;
1112   uint32_t callb_dyn;
1113
1114   hTimer = NULL;
1115
1116   if ((IRQ_Context() == 0U) && (func != NULL)) {
1117     callb     = NULL;
1118     callb_dyn = 0U;
1119
1120     #if (configSUPPORT_STATIC_ALLOCATION == 1)
1121       /* Static memory allocation is available: check if memory for control block */
1122       /* is provided and if it also contains space for callback and its argument  */
1123       if ((attr != NULL) && (attr->cb_mem != NULL)) {
1124         if (attr->cb_size >= (sizeof(StaticTimer_t) + sizeof(TimerCallback_t))) {
1125           callb = (TimerCallback_t *)((uint32_t)attr->cb_mem + sizeof(StaticTimer_t));
1126         }
1127       }
1128     #endif
1129
1130     #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
1131       /* Dynamic memory allocation is available: if memory for callback and */
1132       /* its argument is not provided, allocate it from dynamic memory pool */
1133       if (callb == NULL) {
1134         callb = (TimerCallback_t *)pvPortMalloc (sizeof(TimerCallback_t));
1135
1136         if (callb != NULL) {
1137           /* Callback memory was allocated from dynamic pool, set flag */
1138           callb_dyn = 1U;
1139         }
1140       }
1141     #endif
1142
1143     if (callb != NULL) {
1144       callb->func = func;
1145       callb->arg  = argument;
1146
1147       if (type == osTimerOnce) {
1148         reload = pdFALSE;
1149       } else {
1150         reload = pdTRUE;
1151       }
1152
1153       mem  = -1;
1154       name = NULL;
1155
1156       if (attr != NULL) {
1157         if (attr->name != NULL) {
1158           name = attr->name;
1159         }
1160
1161         if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticTimer_t))) {
1162           /* The memory for control block is provided, use static object */
1163           mem = 1;
1164         }
1165         else {
1166           if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
1167             /* Control block will be allocated from the dynamic pool */
1168             mem = 0;
1169           }
1170         }
1171       }
1172       else {
1173         mem = 0;
1174       }
1175       /* Store callback memory dynamic allocation flag */
1176       callb = (TimerCallback_t *)((uint32_t)callb | callb_dyn);
1177       /*
1178         TimerCallback function is always provided as a callback and is used to call application
1179         specified function with its argument both stored in structure callb.
1180       */
1181       if (mem == 1) {
1182         #if (configSUPPORT_STATIC_ALLOCATION == 1)
1183           hTimer = xTimerCreateStatic (name, 1, reload, callb, TimerCallback, (StaticTimer_t *)attr->cb_mem);
1184         #endif
1185       }
1186       else {
1187         if (mem == 0) {
1188           #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
1189             hTimer = xTimerCreate (name, 1, reload, callb, TimerCallback);
1190           #endif
1191         }
1192       }
1193
1194       #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
1195       if ((hTimer == NULL) && (callb != NULL) && (callb_dyn == 1U)) {
1196         /* Failed to create a timer, release allocated resources */
1197         callb = (TimerCallback_t *)((uint32_t)callb & ~1U);
1198
1199         vPortFree (callb);
1200       }
1201       #endif
1202     }
1203   }
1204
1205   /* Return timer ID */
1206   return ((osTimerId_t)hTimer);
1207 }
1208
1209 /*
1210   Get name of a timer.
1211 */
1212 const char *osTimerGetName (osTimerId_t timer_id) {
1213   TimerHandle_t hTimer = (TimerHandle_t)timer_id;
1214   const char *p;
1215
1216   if ((IRQ_Context() != 0U) || (hTimer == NULL)) {
1217     p = NULL;
1218   } else {
1219     p = pcTimerGetName (hTimer);
1220   }
1221
1222   /* Return name as null-terminated string */
1223   return (p);
1224 }
1225
1226 /*
1227   Start or restart a timer.
1228 */
1229 osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks) {
1230   TimerHandle_t hTimer = (TimerHandle_t)timer_id;
1231   osStatus_t stat;
1232
1233   if (IRQ_Context() != 0U) {
1234     stat = osErrorISR;
1235   }
1236   else if (hTimer == NULL) {
1237     stat = osErrorParameter;
1238   }
1239   else {
1240     if (xTimerChangePeriod (hTimer, ticks, 0) == pdPASS) {
1241       stat = osOK;
1242     } else {
1243       stat = osErrorResource;
1244     }
1245   }
1246
1247   /* Return execution status */
1248   return (stat);
1249 }
1250
1251 /*
1252   Stop a timer.
1253 */
1254 osStatus_t osTimerStop (osTimerId_t timer_id) {
1255   TimerHandle_t hTimer = (TimerHandle_t)timer_id;
1256   osStatus_t stat;
1257
1258   if (IRQ_Context() != 0U) {
1259     stat = osErrorISR;
1260   }
1261   else if (hTimer == NULL) {
1262     stat = osErrorParameter;
1263   }
1264   else {
1265     if (xTimerIsTimerActive (hTimer) == pdFALSE) {
1266       stat = osErrorResource;
1267     }
1268     else {
1269       if (xTimerStop (hTimer, 0) == pdPASS) {
1270         stat = osOK;
1271       } else {
1272         stat = osError;
1273       }
1274     }
1275   }
1276
1277   /* Return execution status */
1278   return (stat);
1279 }
1280
1281 /*
1282   Check if a timer is running.
1283 */
1284 uint32_t osTimerIsRunning (osTimerId_t timer_id) {
1285   TimerHandle_t hTimer = (TimerHandle_t)timer_id;
1286   uint32_t running;
1287
1288   if ((IRQ_Context() != 0U) || (hTimer == NULL)) {
1289     running = 0U;
1290   } else {
1291     running = (uint32_t)xTimerIsTimerActive (hTimer);
1292   }
1293
1294   /* Return 0: not running, 1: running */
1295   return (running);
1296 }
1297
1298 /*
1299   Delete a timer.
1300 */
1301 osStatus_t osTimerDelete (osTimerId_t timer_id) {
1302   TimerHandle_t hTimer = (TimerHandle_t)timer_id;
1303   osStatus_t stat;
1304 #ifndef USE_FreeRTOS_HEAP_1
1305 #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
1306   TimerCallback_t *callb;
1307 #endif
1308
1309   if (IRQ_Context() != 0U) {
1310     stat = osErrorISR;
1311   }
1312   else if (hTimer == NULL) {
1313     stat = osErrorParameter;
1314   }
1315   else {
1316     #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
1317     callb = (TimerCallback_t *)pvTimerGetTimerID (hTimer);
1318     #endif
1319
1320     if (xTimerDelete (hTimer, 0) == pdPASS) {
1321       #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
1322         if ((uint32_t)callb & 1U) {
1323           /* Callback memory was allocated from dynamic pool, clear flag */
1324           callb = (TimerCallback_t *)((uint32_t)callb & ~1U);
1325
1326           /* Return allocated memory to dynamic pool */
1327           vPortFree (callb);
1328         }
1329       #endif
1330       stat = osOK;
1331     } else {
1332       stat = osErrorResource;
1333     }
1334   }
1335 #else
1336   stat = osError;
1337 #endif
1338
1339   /* Return execution status */
1340   return (stat);
1341 }
1342 #endif /* (configUSE_OS2_TIMER == 1) */
1343
1344
1345 /* ==== Event Flags Management Functions ==== */
1346
1347 /*
1348   Create and Initialize an Event Flags object.
1349
1350   Limitations:
1351   - Event flags are limited to 24 bits.
1352 */
1353 osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr) {
1354   EventGroupHandle_t hEventGroup;
1355   int32_t mem;
1356
1357   hEventGroup = NULL;
1358
1359   if (IRQ_Context() == 0U) {
1360     mem = -1;
1361
1362     if (attr != NULL) {
1363       if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticEventGroup_t))) {
1364         /* The memory for control block is provided, use static object */
1365         mem = 1;
1366       }
1367       else {
1368         if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
1369           /* Control block will be allocated from the dynamic pool */
1370           mem = 0;
1371         }
1372       }
1373     }
1374     else {
1375       mem = 0;
1376     }
1377
1378     if (mem == 1) {
1379       #if (configSUPPORT_STATIC_ALLOCATION == 1)
1380       hEventGroup = xEventGroupCreateStatic (attr->cb_mem);
1381       #endif
1382     }
1383     else {
1384       if (mem == 0) {
1385         #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
1386           hEventGroup = xEventGroupCreate();
1387         #endif
1388       }
1389     }
1390   }
1391
1392   /* Return event flags ID */
1393   return ((osEventFlagsId_t)hEventGroup);
1394 }
1395
1396 /*
1397   Set the specified Event Flags.
1398
1399   Limitations:
1400   - Event flags are limited to 24 bits.
1401 */
1402 uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags) {
1403   EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
1404   uint32_t rflags;
1405   BaseType_t yield;
1406
1407   if ((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
1408     rflags = (uint32_t)osErrorParameter;
1409   }
1410   else if (IRQ_Context() != 0U) {
1411   #if (configUSE_OS2_EVENTFLAGS_FROM_ISR == 0)
1412     (void)yield;
1413     /* Enable timers and xTimerPendFunctionCall function to support osEventFlagsSet from ISR */
1414     rflags = (uint32_t)osErrorResource;
1415   #else
1416     yield = pdFALSE;
1417
1418     if (xEventGroupSetBitsFromISR (hEventGroup, (EventBits_t)flags, &yield) == pdFAIL) {
1419       rflags = (uint32_t)osErrorResource;
1420     } else {
1421       rflags = flags;
1422       portYIELD_FROM_ISR (yield);
1423     }
1424   #endif
1425   }
1426   else {
1427     rflags = xEventGroupSetBits (hEventGroup, (EventBits_t)flags);
1428   }
1429
1430   /* Return event flags after setting */
1431   return (rflags);
1432 }
1433
1434 /*
1435   Clear the specified Event Flags.
1436
1437   Limitations:
1438   - Event flags are limited to 24 bits.
1439 */
1440 uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags) {
1441   EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
1442   uint32_t rflags;
1443
1444   if ((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
1445     rflags = (uint32_t)osErrorParameter;
1446   }
1447   else if (IRQ_Context() != 0U) {
1448   #if (configUSE_OS2_EVENTFLAGS_FROM_ISR == 0)
1449     /* Enable timers and xTimerPendFunctionCall function to support osEventFlagsSet from ISR */
1450     rflags = (uint32_t)osErrorResource;
1451   #else
1452     rflags = xEventGroupGetBitsFromISR (hEventGroup);
1453
1454     if (xEventGroupClearBitsFromISR (hEventGroup, (EventBits_t)flags) == pdFAIL) {
1455       rflags = (uint32_t)osErrorResource;
1456     }
1457     else {
1458       /* xEventGroupClearBitsFromISR only registers clear operation in the timer command queue. */
1459       /* Yield is required here otherwise clear operation might not execute in the right order. */
1460       /* See https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/93 for more info.               */
1461       portYIELD_FROM_ISR (pdTRUE);
1462     }
1463   #endif
1464   }
1465   else {
1466     rflags = xEventGroupClearBits (hEventGroup, (EventBits_t)flags);
1467   }
1468
1469   /* Return event flags before clearing */
1470   return (rflags);
1471 }
1472
1473 /*
1474   Get the current Event Flags.
1475
1476   Limitations:
1477   - Event flags are limited to 24 bits.
1478 */
1479 uint32_t osEventFlagsGet (osEventFlagsId_t ef_id) {
1480   EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
1481   uint32_t rflags;
1482
1483   if (ef_id == NULL) {
1484     rflags = 0U;
1485   }
1486   else if (IRQ_Context() != 0U) {
1487     rflags = xEventGroupGetBitsFromISR (hEventGroup);
1488   }
1489   else {
1490     rflags = xEventGroupGetBits (hEventGroup);
1491   }
1492
1493   /* Return current event flags */
1494   return (rflags);
1495 }
1496
1497 /*
1498   Wait for one or more Event Flags to become signaled.
1499
1500   Limitations:
1501   - Event flags are limited to 24 bits.
1502   - osEventFlagsWait cannot be called from an ISR.
1503 */
1504 uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout) {
1505   EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
1506   BaseType_t wait_all;
1507   BaseType_t exit_clr;
1508   uint32_t rflags;
1509
1510   if ((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
1511     rflags = (uint32_t)osErrorParameter;
1512   }
1513   else if (IRQ_Context() != 0U) {
1514     rflags = (uint32_t)osErrorISR;
1515   }
1516   else {
1517     if (options & osFlagsWaitAll) {
1518       wait_all = pdTRUE;
1519     } else {
1520       wait_all = pdFAIL;
1521     }
1522
1523     if (options & osFlagsNoClear) {
1524       exit_clr = pdFAIL;
1525     } else {
1526       exit_clr = pdTRUE;
1527     }
1528
1529     rflags = xEventGroupWaitBits (hEventGroup, (EventBits_t)flags, exit_clr, wait_all, (TickType_t)timeout);
1530
1531     if (options & osFlagsWaitAll) {
1532       if ((flags & rflags) != flags) {
1533         if (timeout > 0U) {
1534           rflags = (uint32_t)osErrorTimeout;
1535         } else {
1536           rflags = (uint32_t)osErrorResource;
1537         }
1538       }
1539     }
1540     else {
1541       if ((flags & rflags) == 0U) {
1542         if (timeout > 0U) {
1543           rflags = (uint32_t)osErrorTimeout;
1544         } else {
1545           rflags = (uint32_t)osErrorResource;
1546         }
1547       }
1548     }
1549   }
1550
1551   /* Return event flags before clearing */
1552   return (rflags);
1553 }
1554
1555 /*
1556   Delete an Event Flags object.
1557 */
1558 osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id) {
1559   EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
1560   osStatus_t stat;
1561
1562 #ifndef USE_FreeRTOS_HEAP_1
1563   if (IRQ_Context() != 0U) {
1564     stat = osErrorISR;
1565   }
1566   else if (hEventGroup == NULL) {
1567     stat = osErrorParameter;
1568   }
1569   else {
1570     stat = osOK;
1571     vEventGroupDelete (hEventGroup);
1572   }
1573 #else
1574   stat = osError;
1575 #endif
1576
1577   /* Return execution status */
1578   return (stat);
1579 }
1580
1581
1582 /* ==== Mutex Management Functions ==== */
1583
1584 #if (configUSE_OS2_MUTEX == 1)
1585 /*
1586   Create and Initialize a Mutex object.
1587
1588   Limitations:
1589   - Priority inherit protocol is used by default, osMutexPrioInherit attribute is ignored.
1590   - Robust mutex is not supported, NULL is returned if used.
1591 */
1592 osMutexId_t osMutexNew (const osMutexAttr_t *attr) {
1593   SemaphoreHandle_t hMutex;
1594   uint32_t type;
1595   uint32_t rmtx;
1596   int32_t  mem;
1597
1598   hMutex = NULL;
1599
1600   if (IRQ_Context() == 0U) {
1601     if (attr != NULL) {
1602       type = attr->attr_bits;
1603     } else {
1604       type = 0U;
1605     }
1606
1607     if ((type & osMutexRecursive) == osMutexRecursive) {
1608       rmtx = 1U;
1609     } else {
1610       rmtx = 0U;
1611     }
1612
1613     if ((type & osMutexRobust) != osMutexRobust) {
1614       mem = -1;
1615
1616       if (attr != NULL) {
1617         if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticSemaphore_t))) {
1618           /* The memory for control block is provided, use static object */
1619           mem = 1;
1620         }
1621         else {
1622           if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
1623             /* Control block will be allocated from the dynamic pool */
1624             mem = 0;
1625           }
1626         }
1627       }
1628       else {
1629         mem = 0;
1630       }
1631
1632       if (mem == 1) {
1633         #if (configSUPPORT_STATIC_ALLOCATION == 1)
1634           if (rmtx != 0U) {
1635             #if (configUSE_RECURSIVE_MUTEXES == 1)
1636             hMutex = xSemaphoreCreateRecursiveMutexStatic (attr->cb_mem);
1637             #endif
1638           }
1639           else {
1640             hMutex = xSemaphoreCreateMutexStatic (attr->cb_mem);
1641           }
1642         #endif
1643       }
1644       else {
1645         if (mem == 0) {
1646           #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
1647             if (rmtx != 0U) {
1648               #if (configUSE_RECURSIVE_MUTEXES == 1)
1649               hMutex = xSemaphoreCreateRecursiveMutex ();
1650               #endif
1651             } else {
1652               hMutex = xSemaphoreCreateMutex ();
1653             }
1654           #endif
1655         }
1656       }
1657
1658       #if (configQUEUE_REGISTRY_SIZE > 0)
1659       if (hMutex != NULL) {
1660         if ((attr != NULL) && (attr->name != NULL)) {
1661           /* Only non-NULL name objects are added to the Queue Registry */
1662           vQueueAddToRegistry (hMutex, attr->name);
1663         }
1664       }
1665       #endif
1666
1667       if ((hMutex != NULL) && (rmtx != 0U)) {
1668         /* Set LSB as 'recursive mutex flag' */
1669         hMutex = (SemaphoreHandle_t)((uint32_t)hMutex | 1U);
1670       }
1671     }
1672   }
1673
1674   /* Return mutex ID */
1675   return ((osMutexId_t)hMutex);
1676 }
1677
1678 /*
1679   Acquire a Mutex or timeout if it is locked.
1680 */
1681 osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) {
1682   SemaphoreHandle_t hMutex;
1683   osStatus_t stat;
1684   uint32_t rmtx;
1685
1686   hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
1687
1688   /* Extract recursive mutex flag */
1689   rmtx = (uint32_t)mutex_id & 1U;
1690
1691   stat = osOK;
1692
1693   if (IRQ_Context() != 0U) {
1694     stat = osErrorISR;
1695   }
1696   else if (hMutex == NULL) {
1697     stat = osErrorParameter;
1698   }
1699   else {
1700     if (rmtx != 0U) {
1701       #if (configUSE_RECURSIVE_MUTEXES == 1)
1702       if (xSemaphoreTakeRecursive (hMutex, timeout) != pdPASS) {
1703         if (timeout != 0U) {
1704           stat = osErrorTimeout;
1705         } else {
1706           stat = osErrorResource;
1707         }
1708       }
1709       #endif
1710     }
1711     else {
1712       if (xSemaphoreTake (hMutex, timeout) != pdPASS) {
1713         if (timeout != 0U) {
1714           stat = osErrorTimeout;
1715         } else {
1716           stat = osErrorResource;
1717         }
1718       }
1719     }
1720   }
1721
1722   /* Return execution status */
1723   return (stat);
1724 }
1725
1726 /*
1727   Release a Mutex that was acquired by osMutexAcquire.
1728 */
1729 osStatus_t osMutexRelease (osMutexId_t mutex_id) {
1730   SemaphoreHandle_t hMutex;
1731   osStatus_t stat;
1732   uint32_t rmtx;
1733
1734   hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
1735
1736   /* Extract recursive mutex flag */
1737   rmtx = (uint32_t)mutex_id & 1U;
1738
1739   stat = osOK;
1740
1741   if (IRQ_Context() != 0U) {
1742     stat = osErrorISR;
1743   }
1744   else if (hMutex == NULL) {
1745     stat = osErrorParameter;
1746   }
1747   else {
1748     if (rmtx != 0U) {
1749       #if (configUSE_RECURSIVE_MUTEXES == 1)
1750       if (xSemaphoreGiveRecursive (hMutex) != pdPASS) {
1751         stat = osErrorResource;
1752       }
1753       #endif
1754     }
1755     else {
1756       if (xSemaphoreGive (hMutex) != pdPASS) {
1757         stat = osErrorResource;
1758       }
1759     }
1760   }
1761
1762   /* Return execution status */
1763   return (stat);
1764 }
1765
1766 /*
1767   Get Thread which owns a Mutex object.
1768 */
1769 osThreadId_t osMutexGetOwner (osMutexId_t mutex_id) {
1770   SemaphoreHandle_t hMutex;
1771   osThreadId_t owner;
1772
1773   hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
1774
1775   if ((IRQ_Context() != 0U) || (hMutex == NULL)) {
1776     owner = NULL;
1777   } else {
1778     owner = (osThreadId_t)xSemaphoreGetMutexHolder (hMutex);
1779   }
1780
1781   /* Return owner thread ID */
1782   return (owner);
1783 }
1784
1785 /*
1786   Delete a Mutex object.
1787 */
1788 osStatus_t osMutexDelete (osMutexId_t mutex_id) {
1789   osStatus_t stat;
1790 #ifndef USE_FreeRTOS_HEAP_1
1791   SemaphoreHandle_t hMutex;
1792
1793   hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
1794
1795   if (IRQ_Context() != 0U) {
1796     stat = osErrorISR;
1797   }
1798   else if (hMutex == NULL) {
1799     stat = osErrorParameter;
1800   }
1801   else {
1802     #if (configQUEUE_REGISTRY_SIZE > 0)
1803     vQueueUnregisterQueue (hMutex);
1804     #endif
1805     stat = osOK;
1806     vSemaphoreDelete (hMutex);
1807   }
1808 #else
1809   stat = osError;
1810 #endif
1811
1812   /* Return execution status */
1813   return (stat);
1814 }
1815 #endif /* (configUSE_OS2_MUTEX == 1) */
1816
1817
1818 /* ==== Semaphore Management Functions ==== */
1819
1820 /*
1821   Create and Initialize a Semaphore object.
1822 */
1823 osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr) {
1824   SemaphoreHandle_t hSemaphore;
1825   int32_t mem;
1826
1827   hSemaphore = NULL;
1828
1829   if ((IRQ_Context() == 0U) && (max_count > 0U) && (initial_count <= max_count)) {
1830     mem = -1;
1831
1832     if (attr != NULL) {
1833       if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticSemaphore_t))) {
1834         /* The memory for control block is provided, use static object */
1835         mem = 1;
1836       }
1837       else {
1838         if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
1839           /* Control block will be allocated from the dynamic pool */
1840           mem = 0;
1841         }
1842       }
1843     }
1844     else {
1845       mem = 0;
1846     }
1847
1848     if (mem != -1) {
1849       if (max_count == 1U) {
1850         if (mem == 1) {
1851           #if (configSUPPORT_STATIC_ALLOCATION == 1)
1852             hSemaphore = xSemaphoreCreateBinaryStatic ((StaticSemaphore_t *)attr->cb_mem);
1853           #endif
1854         }
1855         else {
1856           #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
1857             hSemaphore = xSemaphoreCreateBinary();
1858           #endif
1859         }
1860
1861         if ((hSemaphore != NULL) && (initial_count != 0U)) {
1862           if (xSemaphoreGive (hSemaphore) != pdPASS) {
1863             vSemaphoreDelete (hSemaphore);
1864             hSemaphore = NULL;
1865           }
1866         }
1867       }
1868       else {
1869         if (mem == 1) {
1870           #if (configSUPPORT_STATIC_ALLOCATION == 1)
1871             hSemaphore = xSemaphoreCreateCountingStatic (max_count, initial_count, (StaticSemaphore_t *)attr->cb_mem);
1872           #endif
1873         }
1874         else {
1875           #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
1876             hSemaphore = xSemaphoreCreateCounting (max_count, initial_count);
1877           #endif
1878         }
1879       }
1880       
1881       #if (configQUEUE_REGISTRY_SIZE > 0)
1882       if (hSemaphore != NULL) {
1883         if ((attr != NULL) && (attr->name != NULL)) {
1884           /* Only non-NULL name objects are added to the Queue Registry */
1885           vQueueAddToRegistry (hSemaphore, attr->name);
1886         }
1887       }
1888       #endif
1889     }
1890   }
1891
1892   /* Return semaphore ID */
1893   return ((osSemaphoreId_t)hSemaphore);
1894 }
1895
1896 /*
1897   Acquire a Semaphore token or timeout if no tokens are available.
1898 */
1899 osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout) {
1900   SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
1901   osStatus_t stat;
1902   BaseType_t yield;
1903
1904   stat = osOK;
1905
1906   if (hSemaphore == NULL) {
1907     stat = osErrorParameter;
1908   }
1909   else if (IRQ_Context() != 0U) {
1910     if (timeout != 0U) {
1911       stat = osErrorParameter;
1912     }
1913     else {
1914       yield = pdFALSE;
1915
1916       if (xSemaphoreTakeFromISR (hSemaphore, &yield) != pdPASS) {
1917         stat = osErrorResource;
1918       } else {
1919         portYIELD_FROM_ISR (yield);
1920       }
1921     }
1922   }
1923   else {
1924     if (xSemaphoreTake (hSemaphore, (TickType_t)timeout) != pdPASS) {
1925       if (timeout != 0U) {
1926         stat = osErrorTimeout;
1927       } else {
1928         stat = osErrorResource;
1929       }
1930     }
1931   }
1932
1933   /* Return execution status */
1934   return (stat);
1935 }
1936
1937 /*
1938   Release a Semaphore token up to the initial maximum count.
1939 */
1940 osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id) {
1941   SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
1942   osStatus_t stat;
1943   BaseType_t yield;
1944
1945   stat = osOK;
1946
1947   if (hSemaphore == NULL) {
1948     stat = osErrorParameter;
1949   }
1950   else if (IRQ_Context() != 0U) {
1951     yield = pdFALSE;
1952
1953     if (xSemaphoreGiveFromISR (hSemaphore, &yield) != pdTRUE) {
1954       stat = osErrorResource;
1955     } else {
1956       portYIELD_FROM_ISR (yield);
1957     }
1958   }
1959   else {
1960     if (xSemaphoreGive (hSemaphore) != pdPASS) {
1961       stat = osErrorResource;
1962     }
1963   }
1964
1965   /* Return execution status */
1966   return (stat);
1967 }
1968
1969 /*
1970   Get current Semaphore token count.
1971 */
1972 uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id) {
1973   SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
1974   uint32_t count;
1975
1976   if (hSemaphore == NULL) {
1977     count = 0U;
1978   }
1979   else if (IRQ_Context() != 0U) {
1980     count = uxQueueMessagesWaitingFromISR (hSemaphore);
1981   } else {
1982     count = (uint32_t)uxSemaphoreGetCount (hSemaphore);
1983   }
1984
1985   /* Return number of tokens */
1986   return (count);
1987 }
1988
1989 /*
1990   Delete a Semaphore object.
1991 */
1992 osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id) {
1993   SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
1994   osStatus_t stat;
1995
1996 #ifndef USE_FreeRTOS_HEAP_1
1997   if (IRQ_Context() != 0U) {
1998     stat = osErrorISR;
1999   }
2000   else if (hSemaphore == NULL) {
2001     stat = osErrorParameter;
2002   }
2003   else {
2004     #if (configQUEUE_REGISTRY_SIZE > 0)
2005     vQueueUnregisterQueue (hSemaphore);
2006     #endif
2007
2008     stat = osOK;
2009     vSemaphoreDelete (hSemaphore);
2010   }
2011 #else
2012   stat = osError;
2013 #endif
2014
2015   /* Return execution status */
2016   return (stat);
2017 }
2018
2019
2020 /* ==== Message Queue Management Functions ==== */
2021
2022 /*
2023   Create and Initialize a Message Queue object.
2024
2025   Limitations:
2026   - The memory for control block and and message data must be provided in the
2027     osThreadAttr_t structure in order to allocate object statically.
2028 */
2029 osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) {
2030   QueueHandle_t hQueue;
2031   int32_t mem;
2032
2033   hQueue = NULL;
2034
2035   if ((IRQ_Context() == 0U) && (msg_count > 0U) && (msg_size > 0U)) {
2036     mem = -1;
2037
2038     if (attr != NULL) {
2039       if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticQueue_t)) &&
2040           (attr->mq_mem != NULL) && (attr->mq_size >= (msg_count * msg_size))) {
2041         /* The memory for control block and message data is provided, use static object */
2042         mem = 1;
2043       }
2044       else {
2045         if ((attr->cb_mem == NULL) && (attr->cb_size == 0U) &&
2046             (attr->mq_mem == NULL) && (attr->mq_size == 0U)) {
2047           /* Control block will be allocated from the dynamic pool */
2048           mem = 0;
2049         }
2050       }
2051     }
2052     else {
2053       mem = 0;
2054     }
2055
2056     if (mem == 1) {
2057       #if (configSUPPORT_STATIC_ALLOCATION == 1)
2058         hQueue = xQueueCreateStatic (msg_count, msg_size, attr->mq_mem, attr->cb_mem);
2059       #endif
2060     }
2061     else {
2062       if (mem == 0) {
2063         #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
2064           hQueue = xQueueCreate (msg_count, msg_size);
2065         #endif
2066       }
2067     }
2068
2069     #if (configQUEUE_REGISTRY_SIZE > 0)
2070     if (hQueue != NULL) {
2071       if ((attr != NULL) && (attr->name != NULL)) {
2072         /* Only non-NULL name objects are added to the Queue Registry */
2073         vQueueAddToRegistry (hQueue, attr->name);
2074       }
2075     }
2076     #endif
2077
2078   }
2079
2080   /* Return message queue ID */
2081   return ((osMessageQueueId_t)hQueue);
2082 }
2083
2084 /*
2085   Put a Message into a Queue or timeout if Queue is full.
2086
2087   Limitations:
2088   - Message priority is ignored
2089 */
2090 osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
2091   QueueHandle_t hQueue = (QueueHandle_t)mq_id;
2092   osStatus_t stat;
2093   BaseType_t yield;
2094
2095   (void)msg_prio; /* Message priority is ignored */
2096
2097   stat = osOK;
2098
2099   if (IRQ_Context() != 0U) {
2100     if ((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) {
2101       stat = osErrorParameter;
2102     }
2103     else {
2104       yield = pdFALSE;
2105
2106       if (xQueueSendToBackFromISR (hQueue, msg_ptr, &yield) != pdTRUE) {
2107         stat = osErrorResource;
2108       } else {
2109         portYIELD_FROM_ISR (yield);
2110       }
2111     }
2112   }
2113   else {
2114     if ((hQueue == NULL) || (msg_ptr == NULL)) {
2115       stat = osErrorParameter;
2116     }
2117     else {
2118       if (xQueueSendToBack (hQueue, msg_ptr, (TickType_t)timeout) != pdPASS) {
2119         if (timeout != 0U) {
2120           stat = osErrorTimeout;
2121         } else {
2122           stat = osErrorResource;
2123         }
2124       }
2125     }
2126   }
2127
2128   /* Return execution status */
2129   return (stat);
2130 }
2131
2132 /*
2133   Get a Message from a Queue or timeout if Queue is empty.
2134
2135   Limitations:
2136   - Message priority is ignored
2137 */
2138 osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
2139   QueueHandle_t hQueue = (QueueHandle_t)mq_id;
2140   osStatus_t stat;
2141   BaseType_t yield;
2142
2143   (void)msg_prio; /* Message priority is ignored */
2144
2145   stat = osOK;
2146
2147   if (IRQ_Context() != 0U) {
2148     if ((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) {
2149       stat = osErrorParameter;
2150     }
2151     else {
2152       yield = pdFALSE;
2153
2154       if (xQueueReceiveFromISR (hQueue, msg_ptr, &yield) != pdPASS) {
2155         stat = osErrorResource;
2156       } else {
2157         portYIELD_FROM_ISR (yield);
2158       }
2159     }
2160   }
2161   else {
2162     if ((hQueue == NULL) || (msg_ptr == NULL)) {
2163       stat = osErrorParameter;
2164     }
2165     else {
2166       if (xQueueReceive (hQueue, msg_ptr, (TickType_t)timeout) != pdPASS) {
2167         if (timeout != 0U) {
2168           stat = osErrorTimeout;
2169         } else {
2170           stat = osErrorResource;
2171         }
2172       }
2173     }
2174   }
2175
2176   /* Return execution status */
2177   return (stat);
2178 }
2179
2180 /*
2181   Get maximum number of messages in a Message Queue.
2182 */
2183 uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id) {
2184   StaticQueue_t *mq = (StaticQueue_t *)mq_id;
2185   uint32_t capacity;
2186
2187   if (mq == NULL) {
2188     capacity = 0U;
2189   } else {
2190     /* capacity = pxQueue->uxLength */
2191     capacity = mq->uxDummy4[1];
2192   }
2193
2194   /* Return maximum number of messages */
2195   return (capacity);
2196 }
2197
2198 /*
2199   Get maximum message size in a Message Queue.
2200 */
2201 uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id) {
2202   StaticQueue_t *mq = (StaticQueue_t *)mq_id;
2203   uint32_t size;
2204
2205   if (mq == NULL) {
2206     size = 0U;
2207   } else {
2208     /* size = pxQueue->uxItemSize */
2209     size = mq->uxDummy4[2];
2210   }
2211
2212   /* Return maximum message size */
2213   return (size);
2214 }
2215
2216 /*
2217   Get number of queued messages in a Message Queue.
2218 */
2219 uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id) {
2220   QueueHandle_t hQueue = (QueueHandle_t)mq_id;
2221   UBaseType_t count;
2222
2223   if (hQueue == NULL) {
2224     count = 0U;
2225   }
2226   else if (IRQ_Context() != 0U) {
2227     count = uxQueueMessagesWaitingFromISR (hQueue);
2228   }
2229   else {
2230     count = uxQueueMessagesWaiting (hQueue);
2231   }
2232
2233   /* Return number of queued messages */
2234   return ((uint32_t)count);
2235 }
2236
2237 /*
2238   Get number of available slots for messages in a Message Queue.
2239 */
2240 uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id) {
2241   StaticQueue_t *mq = (StaticQueue_t *)mq_id;
2242   uint32_t space;
2243   uint32_t isrm;
2244
2245   if (mq == NULL) {
2246     space = 0U;
2247   }
2248   else if (IRQ_Context() != 0U) {
2249     isrm = taskENTER_CRITICAL_FROM_ISR();
2250
2251     /* space = pxQueue->uxLength - pxQueue->uxMessagesWaiting; */
2252     space = mq->uxDummy4[1] - mq->uxDummy4[0];
2253
2254     taskEXIT_CRITICAL_FROM_ISR(isrm);
2255   }
2256   else {
2257     space = (uint32_t)uxQueueSpacesAvailable ((QueueHandle_t)mq);
2258   }
2259
2260   /* Return number of available slots */
2261   return (space);
2262 }
2263
2264 /*
2265   Reset a Message Queue to initial empty state.
2266 */
2267 osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id) {
2268   QueueHandle_t hQueue = (QueueHandle_t)mq_id;
2269   osStatus_t stat;
2270
2271   if (IRQ_Context() != 0U) {
2272     stat = osErrorISR;
2273   }
2274   else if (hQueue == NULL) {
2275     stat = osErrorParameter;
2276   }
2277   else {
2278     stat = osOK;
2279     (void)xQueueReset (hQueue);
2280   }
2281
2282   /* Return execution status */
2283   return (stat);
2284 }
2285
2286 /*
2287   Delete a Message Queue object.
2288 */
2289 osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id) {
2290   QueueHandle_t hQueue = (QueueHandle_t)mq_id;
2291   osStatus_t stat;
2292
2293 #ifndef USE_FreeRTOS_HEAP_1
2294   if (IRQ_Context() != 0U) {
2295     stat = osErrorISR;
2296   }
2297   else if (hQueue == NULL) {
2298     stat = osErrorParameter;
2299   }
2300   else {
2301     #if (configQUEUE_REGISTRY_SIZE > 0)
2302     vQueueUnregisterQueue (hQueue);
2303     #endif
2304
2305     stat = osOK;
2306     vQueueDelete (hQueue);
2307   }
2308 #else
2309   stat = osError;
2310 #endif
2311
2312   /* Return execution status */
2313   return (stat);
2314 }
2315
2316
2317 /* ==== Memory Pool Management Functions ==== */
2318
2319 #ifdef FREERTOS_MPOOL_H_
2320 /* Static memory pool functions */
2321 static void  FreeBlock   (MemPool_t *mp, void *block);
2322 static void *AllocBlock  (MemPool_t *mp);
2323 static void *CreateBlock (MemPool_t *mp);
2324
2325 /*
2326   Create and Initialize a Memory Pool object.
2327 */
2328 osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) {
2329   MemPool_t *mp;
2330   const char *name;
2331   int32_t mem_cb, mem_mp;
2332   uint32_t sz;
2333
2334   if (IRQ_Context() != 0U) {
2335     mp = NULL;
2336   }
2337   else if ((block_count == 0U) || (block_size == 0U)) {
2338     mp = NULL;
2339   }
2340   else {
2341     mp = NULL;
2342     sz = MEMPOOL_ARR_SIZE (block_count, block_size);
2343
2344     name = NULL;
2345     mem_cb = -1;
2346     mem_mp = -1;
2347
2348     if (attr != NULL) {
2349       if (attr->name != NULL) {
2350         name = attr->name;
2351       }
2352
2353       if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(MemPool_t))) {
2354         /* Static control block is provided */
2355         mem_cb = 1;
2356       }
2357       else if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
2358         /* Allocate control block memory on heap */
2359         mem_cb = 0;
2360       }
2361
2362       if ((attr->mp_mem == NULL) && (attr->mp_size == 0U)) {
2363         /* Allocate memory array on heap */
2364           mem_mp = 0;
2365       }
2366       else {
2367         if (attr->mp_mem != NULL) {
2368           /* Check if array is 4-byte aligned */
2369           if (((uint32_t)attr->mp_mem & 3U) == 0U) {
2370             /* Check if array big enough */
2371             if (attr->mp_size >= sz) {
2372               /* Static memory pool array is provided */
2373               mem_mp = 1;
2374             }
2375           }
2376         }
2377       }
2378     }
2379     else {
2380       /* Attributes not provided, allocate memory on heap */
2381       mem_cb = 0;
2382       mem_mp = 0;
2383     }
2384
2385     if (mem_cb == 0) {
2386       mp = pvPortMalloc (sizeof(MemPool_t));
2387     } else {
2388       mp = attr->cb_mem;
2389     }
2390
2391     if (mp != NULL) {
2392       /* Create a semaphore (max count == initial count == block_count) */
2393       #if (configSUPPORT_STATIC_ALLOCATION == 1)
2394         mp->sem = xSemaphoreCreateCountingStatic (block_count, block_count, &mp->mem_sem);
2395       #elif (configSUPPORT_DYNAMIC_ALLOCATION == 1)
2396         mp->sem = xSemaphoreCreateCounting (block_count, block_count);
2397       #else
2398         mp->sem = NULL;
2399       #endif
2400
2401       if (mp->sem != NULL) {
2402         /* Setup memory array */
2403         if (mem_mp == 0) {
2404           mp->mem_arr = pvPortMalloc (sz);
2405         } else {
2406           mp->mem_arr = attr->mp_mem;
2407         }
2408       }
2409     }
2410
2411     if ((mp != NULL) && (mp->mem_arr != NULL)) {
2412       /* Memory pool can be created */
2413       mp->head    = NULL;
2414       mp->mem_sz  = sz;
2415       mp->name    = name;
2416       mp->bl_sz   = block_size;
2417       mp->bl_cnt  = block_count;
2418       mp->n       = 0U;
2419
2420       /* Set heap allocated memory flags */
2421       mp->status = MPOOL_STATUS;
2422
2423       if (mem_cb == 0) {
2424         /* Control block on heap */
2425         mp->status |= 1U;
2426       }
2427       if (mem_mp == 0) {
2428         /* Memory array on heap */
2429         mp->status |= 2U;
2430       }
2431     }
2432     else {
2433       /* Memory pool cannot be created, release allocated resources */
2434       if ((mem_cb == 0) && (mp != NULL)) {
2435         /* Free control block memory */
2436         vPortFree (mp);
2437       }
2438       mp = NULL;
2439     }
2440   }
2441
2442   /* Return memory pool ID */
2443   return (mp);
2444 }
2445
2446 /*
2447   Get name of a Memory Pool object.
2448 */
2449 const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id) {
2450   MemPool_t *mp = (osMemoryPoolId_t)mp_id;
2451   const char *p;
2452
2453   if (IRQ_Context() != 0U) {
2454     p = NULL;
2455   }
2456   else if (mp_id == NULL) {
2457     p = NULL;
2458   }
2459   else {
2460     p = mp->name;
2461   }
2462
2463   /* Return name as null-terminated string */
2464   return (p);
2465 }
2466
2467 /*
2468   Allocate a memory block from a Memory Pool.
2469 */
2470 void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
2471   MemPool_t *mp;
2472   void *block;
2473   uint32_t isrm;
2474
2475   if (mp_id == NULL) {
2476     /* Invalid input parameters */
2477     block = NULL;
2478   }
2479   else {
2480     block = NULL;
2481
2482     mp = (MemPool_t *)mp_id;
2483
2484     if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS) {
2485       if (IRQ_Context() != 0U) {
2486         if (timeout == 0U) {
2487           if (xSemaphoreTakeFromISR (mp->sem, NULL) == pdTRUE) {
2488             if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS) {
2489               isrm  = taskENTER_CRITICAL_FROM_ISR();
2490
2491               /* Get a block from the free-list */
2492               block = AllocBlock(mp);
2493
2494               if (block == NULL) {
2495                 /* List of free blocks is empty, 'create' new block */
2496                 block = CreateBlock(mp);
2497               }
2498
2499               taskEXIT_CRITICAL_FROM_ISR(isrm);
2500             }
2501           }
2502         }
2503       }
2504       else {
2505         if (xSemaphoreTake (mp->sem, (TickType_t)timeout) == pdTRUE) {
2506           if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS) {
2507             taskENTER_CRITICAL();
2508
2509             /* Get a block from the free-list */
2510             block = AllocBlock(mp);
2511
2512             if (block == NULL) {
2513               /* List of free blocks is empty, 'create' new block */
2514               block = CreateBlock(mp);
2515             }
2516
2517             taskEXIT_CRITICAL();
2518           }
2519         }
2520       }
2521     }
2522   }
2523
2524   /* Return memory block address */
2525   return (block);
2526 }
2527
2528 /*
2529   Return an allocated memory block back to a Memory Pool.
2530 */
2531 osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
2532   MemPool_t *mp;
2533   osStatus_t stat;
2534   uint32_t isrm;
2535   BaseType_t yield;
2536
2537   if ((mp_id == NULL) || (block == NULL)) {
2538     /* Invalid input parameters */
2539     stat = osErrorParameter;
2540   }
2541   else {
2542     mp = (MemPool_t *)mp_id;
2543
2544     if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
2545       /* Invalid object status */
2546       stat = osErrorResource;
2547     }
2548     else if ((block < (void *)&mp->mem_arr[0]) || (block > (void*)&mp->mem_arr[mp->mem_sz-1])) {
2549       /* Block pointer outside of memory array area */
2550       stat = osErrorParameter;
2551     }
2552     else {
2553       stat = osOK;
2554
2555       if (IRQ_Context() != 0U) {
2556         if (uxSemaphoreGetCountFromISR (mp->sem) == mp->bl_cnt) {
2557           stat = osErrorResource;
2558         }
2559         else {
2560           isrm = taskENTER_CRITICAL_FROM_ISR();
2561
2562           /* Add block to the list of free blocks */
2563           FreeBlock(mp, block);
2564
2565           taskEXIT_CRITICAL_FROM_ISR(isrm);
2566
2567           yield = pdFALSE;
2568           xSemaphoreGiveFromISR (mp->sem, &yield);
2569           portYIELD_FROM_ISR (yield);
2570         }
2571       }
2572       else {
2573         if (uxSemaphoreGetCount (mp->sem) == mp->bl_cnt) {
2574           stat = osErrorResource;
2575         }
2576         else {
2577           taskENTER_CRITICAL();
2578
2579           /* Add block to the list of free blocks */
2580           FreeBlock(mp, block);
2581
2582           taskEXIT_CRITICAL();
2583
2584           xSemaphoreGive (mp->sem);
2585         }
2586       }
2587     }
2588   }
2589
2590   /* Return execution status */
2591   return (stat);
2592 }
2593
2594 /*
2595   Get maximum number of memory blocks in a Memory Pool.
2596 */
2597 uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
2598   MemPool_t *mp;
2599   uint32_t  n;
2600
2601   if (mp_id == NULL) {
2602     /* Invalid input parameters */
2603     n = 0U;
2604   }
2605   else {
2606     mp = (MemPool_t *)mp_id;
2607
2608     if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
2609       /* Invalid object status */
2610       n = 0U;
2611     }
2612     else {
2613       n = mp->bl_cnt;
2614     }
2615   }
2616
2617   /* Return maximum number of memory blocks */
2618   return (n);
2619 }
2620
2621 /*
2622   Get memory block size in a Memory Pool.
2623 */
2624 uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
2625   MemPool_t *mp;
2626   uint32_t  sz;
2627
2628   if (mp_id == NULL) {
2629     /* Invalid input parameters */
2630     sz = 0U;
2631   }
2632   else {
2633     mp = (MemPool_t *)mp_id;
2634
2635     if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
2636       /* Invalid object status */
2637       sz = 0U;
2638     }
2639     else {
2640       sz = mp->bl_sz;
2641     }
2642   }
2643
2644   /* Return memory block size in bytes */
2645   return (sz);
2646 }
2647
2648 /*
2649   Get number of memory blocks used in a Memory Pool.
2650 */
2651 uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
2652   MemPool_t *mp;
2653   uint32_t  n;
2654
2655   if (mp_id == NULL) {
2656     /* Invalid input parameters */
2657     n = 0U;
2658   }
2659   else {
2660     mp = (MemPool_t *)mp_id;
2661
2662     if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
2663       /* Invalid object status */
2664       n = 0U;
2665     }
2666     else {
2667       if (IRQ_Context() != 0U) {
2668         n = uxSemaphoreGetCountFromISR (mp->sem);
2669       } else {
2670         n = uxSemaphoreGetCount        (mp->sem);
2671       }
2672
2673       n = mp->bl_cnt - n;
2674     }
2675   }
2676
2677   /* Return number of memory blocks used */
2678   return (n);
2679 }
2680
2681 /*
2682   Get number of memory blocks available in a Memory Pool.
2683 */
2684 uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
2685   MemPool_t *mp;
2686   uint32_t  n;
2687
2688   if (mp_id == NULL) {
2689     /* Invalid input parameters */
2690     n = 0U;
2691   }
2692   else {
2693     mp = (MemPool_t *)mp_id;
2694
2695     if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
2696       /* Invalid object status */
2697       n = 0U;
2698     }
2699     else {
2700       if (IRQ_Context() != 0U) {
2701         n = uxSemaphoreGetCountFromISR (mp->sem);
2702       } else {
2703         n = uxSemaphoreGetCount        (mp->sem);
2704       }
2705     }
2706   }
2707
2708   /* Return number of memory blocks available */
2709   return (n);
2710 }
2711
2712 /*
2713   Delete a Memory Pool object.
2714 */
2715 osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id) {
2716   MemPool_t *mp;
2717   osStatus_t stat;
2718
2719   if (mp_id == NULL) {
2720     /* Invalid input parameters */
2721     stat = osErrorParameter;
2722   }
2723   else if (IRQ_Context() != 0U) {
2724     stat = osErrorISR;
2725   }
2726   else {
2727     mp = (MemPool_t *)mp_id;
2728
2729     taskENTER_CRITICAL();
2730
2731     /* Invalidate control block status */
2732     mp->status  = mp->status & 3U;
2733
2734     /* Wake-up tasks waiting for pool semaphore */
2735     while (xSemaphoreGive (mp->sem) == pdTRUE);
2736
2737     mp->head    = NULL;
2738     mp->bl_sz   = 0U;
2739     mp->bl_cnt  = 0U;
2740
2741     if ((mp->status & 2U) != 0U) {
2742       /* Memory pool array allocated on heap */
2743       vPortFree (mp->mem_arr);
2744     }
2745     if ((mp->status & 1U) != 0U) {
2746       /* Memory pool control block allocated on heap */
2747       vPortFree (mp);
2748     }
2749
2750     taskEXIT_CRITICAL();
2751
2752     stat = osOK;
2753   }
2754
2755   /* Return execution status */
2756   return (stat);
2757 }
2758
2759 /*
2760   Create new block given according to the current block index.
2761 */
2762 static void *CreateBlock (MemPool_t *mp) {
2763   MemPoolBlock_t *p = NULL;
2764
2765   if (mp->n < mp->bl_cnt) {
2766     /* Unallocated blocks exist, set pointer to new block */
2767     p = (void *)(mp->mem_arr + (mp->bl_sz * mp->n));
2768
2769     /* Increment block index */
2770     mp->n += 1U;
2771   }
2772
2773   return (p);
2774 }
2775
2776 /*
2777   Allocate a block by reading the list of free blocks.
2778 */
2779 static void *AllocBlock (MemPool_t *mp) {
2780   MemPoolBlock_t *p = NULL;
2781
2782   if (mp->head != NULL) {
2783     /* List of free block exists, get head block */
2784     p = mp->head;
2785
2786     /* Head block is now next on the list */
2787     mp->head = p->next;
2788   }
2789
2790   return (p);
2791 }
2792
2793 /*
2794   Free block by putting it to the list of free blocks.
2795 */
2796 static void FreeBlock (MemPool_t *mp, void *block) {
2797   MemPoolBlock_t *p = block;
2798
2799   /* Store current head into block memory space */
2800   p->next = mp->head;
2801
2802   /* Store current block as new head */
2803   mp->head = p;
2804 }
2805 #endif /* FREERTOS_MPOOL_H_ */
2806 /*---------------------------------------------------------------------------*/
2807
2808 /* Callback function prototypes */
2809 extern void vApplicationIdleHook (void);
2810 extern void vApplicationMallocFailedHook (void);
2811 extern void vApplicationDaemonTaskStartupHook (void);
2812
2813 /**
2814   Dummy implementation of the callback function vApplicationIdleHook().
2815 */
2816 #if (configUSE_IDLE_HOOK == 1)
2817 __WEAK void vApplicationIdleHook (void){}
2818 #endif
2819
2820 /**
2821   Dummy implementation of the callback function vApplicationTickHook().
2822 */
2823 #if (configUSE_TICK_HOOK == 1)
2824  __WEAK void vApplicationTickHook (void){}
2825 #endif
2826
2827 /**
2828   Dummy implementation of the callback function vApplicationMallocFailedHook().
2829 */
2830 #if (configUSE_MALLOC_FAILED_HOOK == 1)
2831 __WEAK void vApplicationMallocFailedHook (void) {
2832   /* Assert when malloc failed hook is enabled but no application defined function exists */
2833   configASSERT(0);
2834 }
2835 #endif
2836
2837 /**
2838   Dummy implementation of the callback function vApplicationDaemonTaskStartupHook().
2839 */
2840 #if (configUSE_DAEMON_TASK_STARTUP_HOOK == 1)
2841 __WEAK void vApplicationDaemonTaskStartupHook (void){}
2842 #endif
2843
2844 /**
2845   Dummy implementation of the callback function vApplicationStackOverflowHook().
2846 */
2847 #if (configCHECK_FOR_STACK_OVERFLOW > 0)
2848 __WEAK void vApplicationStackOverflowHook (TaskHandle_t xTask, char *pcTaskName) {
2849   (void)xTask;
2850   (void)pcTaskName;
2851
2852   /* Assert when stack overflow is enabled but no application defined function exists */
2853   configASSERT(0);
2854 }
2855 #endif
2856
2857 /*---------------------------------------------------------------------------*/
2858 #if (configSUPPORT_STATIC_ALLOCATION == 1)
2859 /*
2860   vApplicationGetIdleTaskMemory gets called when configSUPPORT_STATIC_ALLOCATION
2861   equals to 1 and is required for static memory allocation support.
2862 */
2863 __WEAK void vApplicationGetIdleTaskMemory (StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) {
2864   /* Idle task control block and stack */
2865   static StaticTask_t Idle_TCB;
2866   static StackType_t  Idle_Stack[configMINIMAL_STACK_SIZE];
2867
2868   *ppxIdleTaskTCBBuffer   = &Idle_TCB;
2869   *ppxIdleTaskStackBuffer = &Idle_Stack[0];
2870   *pulIdleTaskStackSize   = (uint32_t)configMINIMAL_STACK_SIZE;
2871 }
2872
2873 /*
2874   vApplicationGetTimerTaskMemory gets called when configSUPPORT_STATIC_ALLOCATION
2875   equals to 1 and is required for static memory allocation support.
2876 */
2877 __WEAK void vApplicationGetTimerTaskMemory (StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) {
2878   /* Timer task control block and stack */
2879   static StaticTask_t Timer_TCB;
2880   static StackType_t  Timer_Stack[configTIMER_TASK_STACK_DEPTH];
2881
2882   *ppxTimerTaskTCBBuffer   = &Timer_TCB;
2883   *ppxTimerTaskStackBuffer = &Timer_Stack[0];
2884   *pulTimerTaskStackSize   = (uint32_t)configTIMER_TASK_STACK_DEPTH;
2885 }
2886 #endif