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