Save local changes (4 yrs later)

This commit is contained in:
Attila Body 2025-05-26 21:27:40 +02:00
parent 4e9d7b1334
commit 8111d591cb
Signed by: abody
GPG key ID: BD0C6214E68FB5CF
60 changed files with 2039 additions and 279 deletions

View file

@ -1,6 +1,5 @@
/* --------------------------------------------------------------------------
* Portions Copyright © 2019 STMicroelectronics International N.V. All rights reserved.
* Copyright (c) 2013-2019 Arm Limited. All rights reserved.
* Copyright (c) 2013-2020 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
@ -24,13 +23,16 @@
#include <string.h>
#include "cmsis_os2.h" // ::CMSIS:RTOS2
#include "cmsis_compiler.h"
#include "cmsis_compiler.h" // Compiler agnostic definitions
#include "FreeRTOS.h" // ARM.FreeRTOS::RTOS:Core
#include "task.h" // ARM.FreeRTOS::RTOS:Core
#include "event_groups.h" // ARM.FreeRTOS::RTOS:Event Groups
#include "semphr.h" // ARM.FreeRTOS::RTOS:Core
#include "freertos_mpool.h" // osMemoryPool definitions
#include "freertos_os2.h" // Configuration check and setup
/*---------------------------------------------------------------------------*/
#ifndef __ARM_ARCH_6M__
#define __ARM_ARCH_6M__ 0
@ -73,7 +75,9 @@
#define IS_IRQ_MODE() (__get_IPSR() != 0U)
#endif
#define IS_IRQ() (IS_IRQ_MODE() || (IS_IRQ_MASKED() && (KernelState == osKernelRunning)))
#define IS_IRQ() IS_IRQ_MODE()
#define SVCall_IRQ_NBR (IRQn_Type) -5 /* SVCall_IRQ_NBR added as SV_Call handler name is not the same for CM0 and for all other CMx */
/* Limits */
#define MAX_BITS_TASK_NOTIFY 31U
@ -108,7 +112,7 @@ static osKernelState_t KernelState = osKernelInactive;
definition configHEAP_5_REGIONS as parameter. Overriding configHEAP_5_REGIONS
is possible by defining it globally or in FreeRTOSConfig.h.
*/
#if defined(USE_FREERTOS_HEAP_5)
#if defined(USE_FreeRTOS_HEAP_5)
#if (configAPPLICATION_ALLOCATED_HEAP == 0)
/*
FreeRTOS heap is not defined by the application.
@ -138,7 +142,7 @@ static osKernelState_t KernelState = osKernelInactive;
*/
#define HEAP_5_REGION_SETUP 0
#endif /* configAPPLICATION_ALLOCATED_HEAP */
#endif /* USE_FREERTOS_HEAP_5 */
#endif /* USE_FreeRTOS_HEAP_5 */
#if defined(SysTick)
#undef SysTick_Handler
@ -151,6 +155,7 @@ extern void xPortSysTickHandler (void);
/*
SysTick handler implementation that also clears overflow flag.
*/
#if (USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION == 0)
void SysTick_Handler (void) {
/* Clear overflow flag */
SysTick->CTRL;
@ -160,6 +165,7 @@ void SysTick_Handler (void) {
xPortSysTickHandler();
}
}
#endif
#endif /* SysTick */
/*
@ -170,16 +176,23 @@ __STATIC_INLINE void SVC_Setup (void) {
/* Service Call interrupt might be configured before kernel start */
/* and when its priority is lower or equal to BASEPRI, svc intruction */
/* causes a Hard Fault. */
/*
* the call below has introduced a regression compared to revious release
* The issue was logged under:https://github.com/ARM-software/CMSIS-FreeRTOS/issues/35
* until it is correctly fixed, the code below is commented
*/
/* NVIC_SetPriority (SVCall_IRQn, 0U); */
NVIC_SetPriority (SVCall_IRQ_NBR, 0U);
#endif
}
/*
Function macro used to retrieve semaphore count from ISR
*/
#ifndef uxSemaphoreGetCountFromISR
#define uxSemaphoreGetCountFromISR( xSemaphore ) uxQueueMessagesWaitingFromISR( ( QueueHandle_t ) ( xSemaphore ) )
#endif
/* Get OS Tick count value */
static uint32_t OS_Tick_GetCount (void);
/* Get OS Tick overflow status */
static uint32_t OS_Tick_GetOverflow (void);
/* Get OS Tick interval */
static uint32_t OS_Tick_GetInterval (void);
/*---------------------------------------------------------------------------*/
osStatus_t osKernelInitialize (void) {
@ -190,7 +203,10 @@ osStatus_t osKernelInitialize (void) {
}
else {
if (KernelState == osKernelInactive) {
#if defined(USE_FREERTOS_HEAP_5) && (HEAP_5_REGION_SETUP == 1)
#if defined(USE_TRACE_EVENT_RECORDER)
EvrFreeRTOSSetup(0U);
#endif
#if defined(USE_FreeRTOS_HEAP_5) && (HEAP_5_REGION_SETUP == 1)
vPortDefineHeapRegions (configHEAP_5_REGIONS);
#endif
KernelState = osKernelReady;
@ -380,6 +396,22 @@ uint32_t osKernelGetTickFreq (void) {
return (configTICK_RATE_HZ);
}
/* Get OS Tick count value */
static uint32_t OS_Tick_GetCount (void) {
uint32_t load = SysTick->LOAD;
return (load - SysTick->VAL);
}
/* Get OS Tick overflow status */
static uint32_t OS_Tick_GetOverflow (void) {
return ((SysTick->CTRL >> 16) & 1U);
}
/* Get OS Tick interval */
static uint32_t OS_Tick_GetInterval (void) {
return (SysTick->LOAD + 1U);
}
uint32_t osKernelGetSysTimerCount (void) {
uint32_t irqmask = IS_IRQ_MASKED();
TickType_t ticks;
@ -388,8 +420,14 @@ uint32_t osKernelGetSysTimerCount (void) {
__disable_irq();
ticks = xTaskGetTickCount();
val = OS_Tick_GetCount();
if (OS_Tick_GetOverflow() != 0U) {
val = OS_Tick_GetCount();
ticks++;
}
val += ticks * OS_Tick_GetInterval();
val = ticks * ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
if (irqmask == 0U) {
__enable_irq();
}
@ -452,14 +490,18 @@ osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAtt
}
if (mem == 1) {
hTask = xTaskCreateStatic ((TaskFunction_t)func, name, stack, argument, prio, (StackType_t *)attr->stack_mem,
(StaticTask_t *)attr->cb_mem);
#if (configSUPPORT_STATIC_ALLOCATION == 1)
hTask = xTaskCreateStatic ((TaskFunction_t)func, name, stack, argument, prio, (StackType_t *)attr->stack_mem,
(StaticTask_t *)attr->cb_mem);
#endif
}
else {
if (mem == 0) {
if (xTaskCreate ((TaskFunction_t)func, name, (uint16_t)stack, argument, prio, &hTask) != pdPASS) {
hTask = NULL;
}
#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
if (xTaskCreate ((TaskFunction_t)func, name, (uint16_t)stack, argument, prio, &hTask) != pdPASS) {
hTask = NULL;
}
#endif
}
}
}
@ -517,7 +559,7 @@ uint32_t osThreadGetStackSpace (osThreadId_t thread_id) {
if (IS_IRQ() || (hTask == NULL)) {
sz = 0U;
} else {
sz = (uint32_t)uxTaskGetStackHighWaterMark (hTask);
sz = (uint32_t)(uxTaskGetStackHighWaterMark(hTask) * sizeof(StackType_t));
}
return (sz);
@ -548,7 +590,7 @@ osPriority_t osThreadGetPriority (osThreadId_t thread_id) {
if (IS_IRQ() || (hTask == NULL)) {
prio = osPriorityError;
} else {
prio = (osPriority_t)uxTaskPriorityGet (hTask);
prio = (osPriority_t)((int32_t)uxTaskPriorityGet (hTask));
}
return (prio);
@ -567,6 +609,7 @@ osStatus_t osThreadYield (void) {
return (stat);
}
#if (configUSE_OS2_THREAD_SUSPEND_RESUME == 1)
osStatus_t osThreadSuspend (osThreadId_t thread_id) {
TaskHandle_t hTask = (TaskHandle_t)thread_id;
osStatus_t stat;
@ -602,6 +645,7 @@ osStatus_t osThreadResume (osThreadId_t thread_id) {
return (stat);
}
#endif /* (configUSE_OS2_THREAD_SUSPEND_RESUME == 1) */
__NO_RETURN void osThreadExit (void) {
#ifndef USE_FreeRTOS_HEAP_1
@ -651,6 +695,7 @@ uint32_t osThreadGetCount (void) {
return (count);
}
#if (configUSE_OS2_THREAD_ENUMERATE == 1)
uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items) {
uint32_t i, count;
TaskStatus_t *task;
@ -678,7 +723,9 @@ uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items) {
return (count);
}
#endif /* (configUSE_OS2_THREAD_ENUMERATE == 1) */
#if (configUSE_OS2_THREAD_FLAGS == 1)
uint32_t osThreadFlagsSet (osThreadId_t thread_id, uint32_t flags) {
TaskHandle_t hTask = (TaskHandle_t)thread_id;
uint32_t rflags;
@ -829,6 +876,7 @@ uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout)
/* Return flags before clearing */
return (rflags);
}
#endif /* (configUSE_OS2_THREAD_FLAGS == 1) */
osStatus_t osDelay (uint32_t ticks) {
osStatus_t stat;
@ -876,6 +924,7 @@ osStatus_t osDelayUntil (uint32_t ticks) {
}
/*---------------------------------------------------------------------------*/
#if (configUSE_OS2_TIMER == 1)
static void TimerCallback (TimerHandle_t hTimer) {
TimerCallback_t *callb;
@ -932,13 +981,21 @@ osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument,
}
if (mem == 1) {
hTimer = xTimerCreateStatic (name, 1, reload, callb, TimerCallback, (StaticTimer_t *)attr->cb_mem);
#if (configSUPPORT_STATIC_ALLOCATION == 1)
hTimer = xTimerCreateStatic (name, 1, reload, callb, TimerCallback, (StaticTimer_t *)attr->cb_mem);
#endif
}
else {
if (mem == 0) {
hTimer = xTimerCreate (name, 1, reload, callb, TimerCallback);
#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
hTimer = xTimerCreate (name, 1, reload, callb, TimerCallback);
#endif
}
}
if ((hTimer == NULL) && (callb != NULL)) {
vPortFree (callb);
}
}
}
@ -1046,6 +1103,7 @@ osStatus_t osTimerDelete (osTimerId_t timer_id) {
return (stat);
}
#endif /* (configUSE_OS2_TIMER == 1) */
/*---------------------------------------------------------------------------*/
@ -1073,11 +1131,15 @@ osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr) {
}
if (mem == 1) {
#if (configSUPPORT_STATIC_ALLOCATION == 1)
hEventGroup = xEventGroupCreateStatic (attr->cb_mem);
#endif
}
else {
if (mem == 0) {
hEventGroup = xEventGroupCreate();
#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
hEventGroup = xEventGroupCreate();
#endif
}
}
}
@ -1094,6 +1156,11 @@ uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags) {
rflags = (uint32_t)osErrorParameter;
}
else if (IS_IRQ()) {
#if (configUSE_OS2_EVENTFLAGS_FROM_ISR == 0)
(void)yield;
/* Enable timers and xTimerPendFunctionCall function to support osEventFlagsSet from ISR */
rflags = (uint32_t)osErrorResource;
#else
yield = pdFALSE;
if (xEventGroupSetBitsFromISR (hEventGroup, (EventBits_t)flags, &yield) == pdFAIL) {
@ -1102,6 +1169,7 @@ uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags) {
rflags = flags;
portYIELD_FROM_ISR (yield);
}
#endif
}
else {
rflags = xEventGroupSetBits (hEventGroup, (EventBits_t)flags);
@ -1118,11 +1186,16 @@ uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags) {
rflags = (uint32_t)osErrorParameter;
}
else if (IS_IRQ()) {
#if (configUSE_OS2_EVENTFLAGS_FROM_ISR == 0)
/* Enable timers and xTimerPendFunctionCall function to support osEventFlagsSet from ISR */
rflags = (uint32_t)osErrorResource;
#else
rflags = xEventGroupGetBitsFromISR (hEventGroup);
if (xEventGroupClearBitsFromISR (hEventGroup, (EventBits_t)flags) == pdFAIL) {
rflags = (uint32_t)osErrorResource;
}
#endif
}
else {
rflags = xEventGroupClearBits (hEventGroup, (EventBits_t)flags);
@ -1176,7 +1249,7 @@ uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t opti
rflags = xEventGroupWaitBits (hEventGroup, (EventBits_t)flags, exit_clr, wait_all, (TickType_t)timeout);
if (options & osFlagsWaitAll) {
if (flags != rflags) {
if ((flags & rflags) != flags) {
if (timeout > 0U) {
rflags = (uint32_t)osErrorTimeout;
} else {
@ -1221,6 +1294,7 @@ osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id) {
}
/*---------------------------------------------------------------------------*/
#if (configUSE_OS2_MUTEX == 1)
osMutexId_t osMutexNew (const osMutexAttr_t *attr) {
SemaphoreHandle_t hMutex;
@ -1264,20 +1338,28 @@ osMutexId_t osMutexNew (const osMutexAttr_t *attr) {
}
if (mem == 1) {
if (rmtx != 0U) {
hMutex = xSemaphoreCreateRecursiveMutexStatic (attr->cb_mem);
}
else {
hMutex = xSemaphoreCreateMutexStatic (attr->cb_mem);
}
#if (configSUPPORT_STATIC_ALLOCATION == 1)
if (rmtx != 0U) {
#if (configUSE_RECURSIVE_MUTEXES == 1)
hMutex = xSemaphoreCreateRecursiveMutexStatic (attr->cb_mem);
#endif
}
else {
hMutex = xSemaphoreCreateMutexStatic (attr->cb_mem);
}
#endif
}
else {
if (mem == 0) {
if (rmtx != 0U) {
hMutex = xSemaphoreCreateRecursiveMutex ();
} else {
hMutex = xSemaphoreCreateMutex ();
}
#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
if (rmtx != 0U) {
#if (configUSE_RECURSIVE_MUTEXES == 1)
hMutex = xSemaphoreCreateRecursiveMutex ();
#endif
} else {
hMutex = xSemaphoreCreateMutex ();
}
#endif
}
}
@ -1320,6 +1402,7 @@ osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) {
}
else {
if (rmtx != 0U) {
#if (configUSE_RECURSIVE_MUTEXES == 1)
if (xSemaphoreTakeRecursive (hMutex, timeout) != pdPASS) {
if (timeout != 0U) {
stat = osErrorTimeout;
@ -1327,6 +1410,7 @@ osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) {
stat = osErrorResource;
}
}
#endif
}
else {
if (xSemaphoreTake (hMutex, timeout) != pdPASS) {
@ -1361,9 +1445,11 @@ osStatus_t osMutexRelease (osMutexId_t mutex_id) {
}
else {
if (rmtx != 0U) {
#if (configUSE_RECURSIVE_MUTEXES == 1)
if (xSemaphoreGiveRecursive (hMutex) != pdPASS) {
stat = osErrorResource;
}
#endif
}
else {
if (xSemaphoreGive (hMutex) != pdPASS) {
@ -1416,6 +1502,7 @@ osStatus_t osMutexDelete (osMutexId_t mutex_id) {
return (stat);
}
#endif /* (configUSE_OS2_MUTEX == 1) */
/*---------------------------------------------------------------------------*/
@ -1448,10 +1535,14 @@ osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, cons
if (mem != -1) {
if (max_count == 1U) {
if (mem == 1) {
hSemaphore = xSemaphoreCreateBinaryStatic ((StaticSemaphore_t *)attr->cb_mem);
#if (configSUPPORT_STATIC_ALLOCATION == 1)
hSemaphore = xSemaphoreCreateBinaryStatic ((StaticSemaphore_t *)attr->cb_mem);
#endif
}
else {
hSemaphore = xSemaphoreCreateBinary();
#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
hSemaphore = xSemaphoreCreateBinary();
#endif
}
if ((hSemaphore != NULL) && (initial_count != 0U)) {
@ -1463,10 +1554,14 @@ osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, cons
}
else {
if (mem == 1) {
hSemaphore = xSemaphoreCreateCountingStatic (max_count, initial_count, (StaticSemaphore_t *)attr->cb_mem);
#if (configSUPPORT_STATIC_ALLOCATION == 1)
hSemaphore = xSemaphoreCreateCountingStatic (max_count, initial_count, (StaticSemaphore_t *)attr->cb_mem);
#endif
}
else {
hSemaphore = xSemaphoreCreateCounting (max_count, initial_count);
#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
hSemaphore = xSemaphoreCreateCounting (max_count, initial_count);
#endif
}
}
@ -1624,11 +1719,15 @@ osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, con
}
if (mem == 1) {
hQueue = xQueueCreateStatic (msg_count, msg_size, attr->mq_mem, attr->cb_mem);
#if (configSUPPORT_STATIC_ALLOCATION == 1)
hQueue = xQueueCreateStatic (msg_count, msg_size, attr->mq_mem, attr->cb_mem);
#endif
}
else {
if (mem == 0) {
hQueue = xQueueCreate (msg_count, msg_size);
#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
hQueue = xQueueCreate (msg_count, msg_size);
#endif
}
}
@ -1842,6 +1941,463 @@ osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id) {
return (stat);
}
/*---------------------------------------------------------------------------*/
#ifdef FREERTOS_MPOOL_H_
/* Static memory pool functions */
static void FreeBlock (MemPool_t *mp, void *block);
static void *AllocBlock (MemPool_t *mp);
static void *CreateBlock (MemPool_t *mp);
osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) {
MemPool_t *mp;
const char *name;
int32_t mem_cb, mem_mp;
uint32_t sz;
if (IS_IRQ()) {
mp = NULL;
}
else if ((block_count == 0U) || (block_size == 0U)) {
mp = NULL;
}
else {
mp = NULL;
sz = MEMPOOL_ARR_SIZE (block_count, block_size);
name = NULL;
mem_cb = -1;
mem_mp = -1;
if (attr != NULL) {
if (attr->name != NULL) {
name = attr->name;
}
if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(MemPool_t))) {
/* Static control block is provided */
mem_cb = 1;
}
else if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
/* Allocate control block memory on heap */
mem_cb = 0;
}
if ((attr->mp_mem == NULL) && (attr->mp_size == 0U)) {
/* Allocate memory array on heap */
mem_mp = 0;
}
else {
if (attr->mp_mem != NULL) {
/* Check if array is 4-byte aligned */
if (((uint32_t)attr->mp_mem & 3U) == 0U) {
/* Check if array big enough */
if (attr->mp_size >= sz) {
/* Static memory pool array is provided */
mem_mp = 1;
}
}
}
}
}
else {
/* Attributes not provided, allocate memory on heap */
mem_cb = 0;
mem_mp = 0;
}
if (mem_cb == 0) {
mp = pvPortMalloc (sizeof(MemPool_t));
} else {
mp = attr->cb_mem;
}
if (mp != NULL) {
/* Create a semaphore (max count == initial count == block_count) */
#if (configSUPPORT_STATIC_ALLOCATION == 1)
mp->sem = xSemaphoreCreateCountingStatic (block_count, block_count, &mp->mem_sem);
#elif (configSUPPORT_DYNAMIC_ALLOCATION == 1)
mp->sem = xSemaphoreCreateCounting (block_count, block_count);
#else
mp->sem == NULL;
#endif
if (mp->sem != NULL) {
/* Setup memory array */
if (mem_mp == 0) {
mp->mem_arr = pvPortMalloc (sz);
} else {
mp->mem_arr = attr->mp_mem;
}
}
}
if ((mp != NULL) && (mp->mem_arr != NULL)) {
/* Memory pool can be created */
mp->head = NULL;
mp->mem_sz = sz;
mp->name = name;
mp->bl_sz = block_size;
mp->bl_cnt = block_count;
mp->n = 0U;
/* Set heap allocated memory flags */
mp->status = MPOOL_STATUS;
if (mem_cb == 0) {
/* Control block on heap */
mp->status |= 1U;
}
if (mem_mp == 0) {
/* Memory array on heap */
mp->status |= 2U;
}
}
else {
/* Memory pool cannot be created, release allocated resources */
if ((mem_cb == 0) && (mp != NULL)) {
/* Free control block memory */
vPortFree (mp);
}
mp = NULL;
}
}
return (mp);
}
const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id) {
MemPool_t *mp = (osMemoryPoolId_t)mp_id;
const char *p;
if (IS_IRQ()) {
p = NULL;
}
else if (mp_id == NULL) {
p = NULL;
}
else {
p = mp->name;
}
return (p);
}
void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
MemPool_t *mp;
void *block;
uint32_t isrm;
if (mp_id == NULL) {
/* Invalid input parameters */
block = NULL;
}
else {
block = NULL;
mp = (MemPool_t *)mp_id;
if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS) {
if (IS_IRQ()) {
if (timeout == 0U) {
if (xSemaphoreTakeFromISR (mp->sem, NULL) == pdTRUE) {
if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS) {
isrm = taskENTER_CRITICAL_FROM_ISR();
/* Get a block from the free-list */
block = AllocBlock(mp);
if (block == NULL) {
/* List of free blocks is empty, 'create' new block */
block = CreateBlock(mp);
}
taskEXIT_CRITICAL_FROM_ISR(isrm);
}
}
}
}
else {
if (xSemaphoreTake (mp->sem, (TickType_t)timeout) == pdTRUE) {
if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS) {
taskENTER_CRITICAL();
/* Get a block from the free-list */
block = AllocBlock(mp);
if (block == NULL) {
/* List of free blocks is empty, 'create' new block */
block = CreateBlock(mp);
}
taskEXIT_CRITICAL();
}
}
}
}
}
return (block);
}
osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
MemPool_t *mp;
osStatus_t stat;
uint32_t isrm;
BaseType_t yield;
if ((mp_id == NULL) || (block == NULL)) {
/* Invalid input parameters */
stat = osErrorParameter;
}
else {
mp = (MemPool_t *)mp_id;
if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
/* Invalid object status */
stat = osErrorResource;
}
else if ((block < (void *)&mp->mem_arr[0]) || (block > (void*)&mp->mem_arr[mp->mem_sz-1])) {
/* Block pointer outside of memory array area */
stat = osErrorParameter;
}
else {
stat = osOK;
if (IS_IRQ()) {
if (uxSemaphoreGetCountFromISR (mp->sem) == mp->bl_cnt) {
stat = osErrorResource;
}
else {
isrm = taskENTER_CRITICAL_FROM_ISR();
/* Add block to the list of free blocks */
FreeBlock(mp, block);
taskEXIT_CRITICAL_FROM_ISR(isrm);
yield = pdFALSE;
xSemaphoreGiveFromISR (mp->sem, &yield);
portYIELD_FROM_ISR (yield);
}
}
else {
if (uxSemaphoreGetCount (mp->sem) == mp->bl_cnt) {
stat = osErrorResource;
}
else {
taskENTER_CRITICAL();
/* Add block to the list of free blocks */
FreeBlock(mp, block);
taskEXIT_CRITICAL();
xSemaphoreGive (mp->sem);
}
}
}
}
return (stat);
}
uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
MemPool_t *mp;
uint32_t n;
if (mp_id == NULL) {
/* Invalid input parameters */
n = 0U;
}
else {
mp = (MemPool_t *)mp_id;
if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
/* Invalid object status */
n = 0U;
}
else {
n = mp->bl_cnt;
}
}
/* Return maximum number of memory blocks */
return (n);
}
uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
MemPool_t *mp;
uint32_t sz;
if (mp_id == NULL) {
/* Invalid input parameters */
sz = 0U;
}
else {
mp = (MemPool_t *)mp_id;
if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
/* Invalid object status */
sz = 0U;
}
else {
sz = mp->bl_sz;
}
}
/* Return memory block size in bytes */
return (sz);
}
uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
MemPool_t *mp;
uint32_t n;
if (mp_id == NULL) {
/* Invalid input parameters */
n = 0U;
}
else {
mp = (MemPool_t *)mp_id;
if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
/* Invalid object status */
n = 0U;
}
else {
if (IS_IRQ()) {
n = uxSemaphoreGetCountFromISR (mp->sem);
} else {
n = uxSemaphoreGetCount (mp->sem);
}
n = mp->bl_cnt - n;
}
}
/* Return number of memory blocks used */
return (n);
}
uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
MemPool_t *mp;
uint32_t n;
if (mp_id == NULL) {
/* Invalid input parameters */
n = 0U;
}
else {
mp = (MemPool_t *)mp_id;
if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
/* Invalid object status */
n = 0U;
}
else {
if (IS_IRQ()) {
n = uxSemaphoreGetCountFromISR (mp->sem);
} else {
n = uxSemaphoreGetCount (mp->sem);
}
}
}
/* Return number of memory blocks available */
return (n);
}
osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id) {
MemPool_t *mp;
osStatus_t stat;
if (mp_id == NULL) {
/* Invalid input parameters */
stat = osErrorParameter;
}
else if (IS_IRQ()) {
stat = osErrorISR;
}
else {
mp = (MemPool_t *)mp_id;
taskENTER_CRITICAL();
/* Invalidate control block status */
mp->status = mp->status & 3U;
/* Wake-up tasks waiting for pool semaphore */
while (xSemaphoreGive (mp->sem) == pdTRUE);
mp->head = NULL;
mp->bl_sz = 0U;
mp->bl_cnt = 0U;
if ((mp->status & 2U) != 0U) {
/* Memory pool array allocated on heap */
vPortFree (mp->mem_arr);
}
if ((mp->status & 1U) != 0U) {
/* Memory pool control block allocated on heap */
vPortFree (mp);
}
taskEXIT_CRITICAL();
stat = osOK;
}
return (stat);
}
/*
Create new block given according to the current block index.
*/
static void *CreateBlock (MemPool_t *mp) {
MemPoolBlock_t *p = NULL;
if (mp->n < mp->bl_cnt) {
/* Unallocated blocks exist, set pointer to new block */
p = (void *)(mp->mem_arr + (mp->bl_sz * mp->n));
/* Increment block index */
mp->n += 1U;
}
return (p);
}
/*
Allocate a block by reading the list of free blocks.
*/
static void *AllocBlock (MemPool_t *mp) {
MemPoolBlock_t *p = NULL;
if (mp->head != NULL) {
/* List of free block exists, get head block */
p = mp->head;
/* Head block is now next on the list */
mp->head = p->next;
}
return (p);
}
/*
Free block by putting it to the list of free blocks.
*/
static void FreeBlock (MemPool_t *mp, void *block) {
MemPoolBlock_t *p = block;
/* Store current head into block memory space */
p->next = mp->head;
/* Store current block as new head */
mp->head = p;
}
#endif /* FREERTOS_MPOOL_H_ */
/*---------------------------------------------------------------------------*/
/* Callback function prototypes */
@ -1886,28 +2442,25 @@ __WEAK void vApplicationDaemonTaskStartupHook (void){}
__WEAK void vApplicationStackOverflowHook (TaskHandle_t xTask, signed char *pcTaskName) {
(void)xTask;
(void)pcTaskName;
configASSERT(0);
}
#endif
/*---------------------------------------------------------------------------*/
#if (configSUPPORT_STATIC_ALLOCATION == 1)
/* External Idle and Timer task static memory allocation functions */
extern void vApplicationGetIdleTaskMemory (StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize);
extern void vApplicationGetTimerTaskMemory (StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize);
/* Idle task control block and stack */
static StaticTask_t Idle_TCB;
static StackType_t Idle_Stack[configMINIMAL_STACK_SIZE];
/* Timer task control block and stack */
static StaticTask_t Timer_TCB;
static StackType_t Timer_Stack[configTIMER_TASK_STACK_DEPTH];
/*
vApplicationGetIdleTaskMemory gets called when configSUPPORT_STATIC_ALLOCATION
equals to 1 and is required for static memory allocation support.
*/
void vApplicationGetIdleTaskMemory (StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) {
__WEAK void vApplicationGetIdleTaskMemory (StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) {
/* Idle task control block and stack */
static StaticTask_t Idle_TCB;
static StackType_t Idle_Stack[configMINIMAL_STACK_SIZE];
*ppxIdleTaskTCBBuffer = &Idle_TCB;
*ppxIdleTaskStackBuffer = &Idle_Stack[0];
*pulIdleTaskStackSize = (uint32_t)configMINIMAL_STACK_SIZE;
@ -1917,8 +2470,13 @@ void vApplicationGetIdleTaskMemory (StaticTask_t **ppxIdleTaskTCBBuffer, StackTy
vApplicationGetTimerTaskMemory gets called when configSUPPORT_STATIC_ALLOCATION
equals to 1 and is required for static memory allocation support.
*/
void vApplicationGetTimerTaskMemory (StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) {
__WEAK void vApplicationGetTimerTaskMemory (StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) {
/* Timer task control block and stack */
static StaticTask_t Timer_TCB;
static StackType_t Timer_Stack[configTIMER_TASK_STACK_DEPTH];
*ppxTimerTaskTCBBuffer = &Timer_TCB;
*ppxTimerTaskStackBuffer = &Timer_Stack[0];
*pulTimerTaskStackSize = (uint32_t)configTIMER_TASK_STACK_DEPTH;
}
#endif

View file

@ -0,0 +1,63 @@
/* --------------------------------------------------------------------------
* Copyright (c) 2013-2020 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Name: freertos_mpool.h
* Purpose: CMSIS RTOS2 wrapper for FreeRTOS
*
*---------------------------------------------------------------------------*/
#ifndef FREERTOS_MPOOL_H_
#define FREERTOS_MPOOL_H_
#include <stdint.h>
#include "FreeRTOS.h"
#include "semphr.h"
/* Memory Pool implementation definitions */
#define MPOOL_STATUS 0x5EED0000U
/* Memory Block header */
typedef struct {
void *next; /* Pointer to next block */
} MemPoolBlock_t;
/* Memory Pool control block */
typedef struct MemPoolDef_t {
MemPoolBlock_t *head; /* Pointer to head block */
SemaphoreHandle_t sem; /* Pool semaphore handle */
uint8_t *mem_arr; /* Pool memory array */
uint32_t mem_sz; /* Pool memory array size */
const char *name; /* Pointer to name string */
uint32_t bl_sz; /* Size of a single block */
uint32_t bl_cnt; /* Number of blocks */
uint32_t n; /* Block allocation index */
volatile uint32_t status; /* Object status flags */
#if (configSUPPORT_STATIC_ALLOCATION == 1)
StaticSemaphore_t mem_sem; /* Semaphore object memory */
#endif
} MemPool_t;
/* No need to hide static object type, just align to coding style */
#define StaticMemPool_t MemPool_t
/* Define memory pool control block size */
#define MEMPOOL_CB_SIZE (sizeof(StaticMemPool_t))
/* Define size of the byte array required to create count of blocks of given size */
#define MEMPOOL_ARR_SIZE(bl_count, bl_size) (((((bl_size) + (4 - 1)) / 4) * 4)*(bl_count))
#endif /* FREERTOS_MPOOL_H_ */

View file

@ -0,0 +1,310 @@
/* --------------------------------------------------------------------------
* Copyright (c) 2013-2020 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Name: freertos_os2.h
* Purpose: CMSIS RTOS2 wrapper for FreeRTOS
*
*---------------------------------------------------------------------------*/
#ifndef FREERTOS_OS2_H_
#define FREERTOS_OS2_H_
#include <string.h>
#include <stdint.h>
#include "FreeRTOS.h" // ARM.FreeRTOS::RTOS:Core
#include CMSIS_device_header
/*
CMSIS-RTOS2 FreeRTOS image size optimization definitions.
Note: Definitions configUSE_OS2 can be used to optimize FreeRTOS image size when
certain functionality is not required when using CMSIS-RTOS2 API.
In general optimization decisions are left to the tool chain but in cases
when coding style prevents it to optimize the code following optional
definitions can be used.
*/
/*
Option to exclude CMSIS-RTOS2 functions osThreadSuspend and osThreadResume from
the application image.
*/
#ifndef configUSE_OS2_THREAD_SUSPEND_RESUME
#define configUSE_OS2_THREAD_SUSPEND_RESUME 1
#endif
/*
Option to exclude CMSIS-RTOS2 function osThreadEnumerate from the application image.
*/
#ifndef configUSE_OS2_THREAD_ENUMERATE
#define configUSE_OS2_THREAD_ENUMERATE 1
#endif
/*
Option to disable CMSIS-RTOS2 function osEventFlagsSet and osEventFlagsClear
operation from ISR.
*/
#ifndef configUSE_OS2_EVENTFLAGS_FROM_ISR
#define configUSE_OS2_EVENTFLAGS_FROM_ISR 1
#endif
/*
Option to exclude CMSIS-RTOS2 Thread Flags API functions from the application image.
*/
#ifndef configUSE_OS2_THREAD_FLAGS
#define configUSE_OS2_THREAD_FLAGS configUSE_TASK_NOTIFICATIONS
#endif
/*
Option to exclude CMSIS-RTOS2 Timer API functions from the application image.
*/
#ifndef configUSE_OS2_TIMER
#define configUSE_OS2_TIMER configUSE_TIMERS
#endif
/*
Option to exclude CMSIS-RTOS2 Mutex API functions from the application image.
*/
#ifndef configUSE_OS2_MUTEX
#define configUSE_OS2_MUTEX configUSE_MUTEXES
#endif
/*
CMSIS-RTOS2 FreeRTOS configuration check (FreeRTOSConfig.h).
Note: CMSIS-RTOS API requires functions included by using following definitions.
In case if certain API function is not used compiler will optimize it away.
*/
#if (INCLUDE_xSemaphoreGetMutexHolder == 0)
/*
CMSIS-RTOS2 function osMutexGetOwner uses FreeRTOS function xSemaphoreGetMutexHolder. In case if
osMutexGetOwner is not used in the application image, compiler will optimize it away.
Set #define INCLUDE_xSemaphoreGetMutexHolder 1 to fix this error.
*/
#error "Definition INCLUDE_xSemaphoreGetMutexHolder must equal 1 to implement Mutex Management API."
#endif
#if (INCLUDE_vTaskDelay == 0)
/*
CMSIS-RTOS2 function osDelay uses FreeRTOS function vTaskDelay. In case if
osDelay is not used in the application image, compiler will optimize it away.
Set #define INCLUDE_vTaskDelay 1 to fix this error.
*/
#error "Definition INCLUDE_vTaskDelay must equal 1 to implement Generic Wait Functions API."
#endif
#if (INCLUDE_vTaskDelayUntil == 0)
/*
CMSIS-RTOS2 function osDelayUntil uses FreeRTOS function vTaskDelayUntil. In case if
osDelayUntil is not used in the application image, compiler will optimize it away.
Set #define INCLUDE_vTaskDelayUntil 1 to fix this error.
*/
#error "Definition INCLUDE_vTaskDelayUntil must equal 1 to implement Generic Wait Functions API."
#endif
#if (INCLUDE_vTaskDelete == 0)
/*
CMSIS-RTOS2 function osThreadTerminate and osThreadExit uses FreeRTOS function
vTaskDelete. In case if they are not used in the application image, compiler
will optimize them away.
Set #define INCLUDE_vTaskDelete 1 to fix this error.
*/
#error "Definition INCLUDE_vTaskDelete must equal 1 to implement Thread Management API."
#endif
#if (INCLUDE_xTaskGetCurrentTaskHandle == 0)
/*
CMSIS-RTOS2 API uses FreeRTOS function xTaskGetCurrentTaskHandle to implement
functions osThreadGetId, osThreadFlagsClear and osThreadFlagsGet. In case if these
functions are not used in the application image, compiler will optimize them away.
Set #define INCLUDE_xTaskGetCurrentTaskHandle 1 to fix this error.
*/
#error "Definition INCLUDE_xTaskGetCurrentTaskHandle must equal 1 to implement Thread Management API."
#endif
#if (INCLUDE_xTaskGetSchedulerState == 0)
/*
CMSIS-RTOS2 API uses FreeRTOS function xTaskGetSchedulerState to implement Kernel
tick handling and therefore it is vital that xTaskGetSchedulerState is included into
the application image.
Set #define INCLUDE_xTaskGetSchedulerState 1 to fix this error.
*/
#error "Definition INCLUDE_xTaskGetSchedulerState must equal 1 to implement Kernel Information and Control API."
#endif
#if (INCLUDE_uxTaskGetStackHighWaterMark == 0)
/*
CMSIS-RTOS2 function osThreadGetStackSpace uses FreeRTOS function uxTaskGetStackHighWaterMark.
In case if osThreadGetStackSpace is not used in the application image, compiler will
optimize it away.
Set #define INCLUDE_uxTaskGetStackHighWaterMark 1 to fix this error.
*/
#error "Definition INCLUDE_uxTaskGetStackHighWaterMark must equal 1 to implement Thread Management API."
#endif
#if (INCLUDE_uxTaskPriorityGet == 0)
/*
CMSIS-RTOS2 function osThreadGetPriority uses FreeRTOS function uxTaskPriorityGet. In case if
osThreadGetPriority is not used in the application image, compiler will optimize it away.
Set #define INCLUDE_uxTaskPriorityGet 1 to fix this error.
*/
#error "Definition INCLUDE_uxTaskPriorityGet must equal 1 to implement Thread Management API."
#endif
#if (INCLUDE_vTaskPrioritySet == 0)
/*
CMSIS-RTOS2 function osThreadSetPriority uses FreeRTOS function vTaskPrioritySet. In case if
osThreadSetPriority is not used in the application image, compiler will optimize it away.
Set #define INCLUDE_vTaskPrioritySet 1 to fix this error.
*/
#error "Definition INCLUDE_vTaskPrioritySet must equal 1 to implement Thread Management API."
#endif
#if (INCLUDE_eTaskGetState == 0)
/*
CMSIS-RTOS2 API uses FreeRTOS function vTaskDelayUntil to implement functions osThreadGetState
and osThreadTerminate. In case if these functions are not used in the application image,
compiler will optimize them away.
Set #define INCLUDE_eTaskGetState 1 to fix this error.
*/
#error "Definition INCLUDE_eTaskGetState must equal 1 to implement Thread Management API."
#endif
#if (INCLUDE_vTaskSuspend == 0)
/*
CMSIS-RTOS2 API uses FreeRTOS functions vTaskSuspend and vTaskResume to implement
functions osThreadSuspend and osThreadResume. In case if these functions are not
used in the application image, compiler will optimize them away.
Set #define INCLUDE_vTaskSuspend 1 to fix this error.
Alternatively, if the application does not use osThreadSuspend and
osThreadResume they can be excluded from the image code by setting:
#define configUSE_OS2_THREAD_SUSPEND_RESUME 0 (in FreeRTOSConfig.h)
*/
#if (configUSE_OS2_THREAD_SUSPEND_RESUME == 1)
#error "Definition INCLUDE_vTaskSuspend must equal 1 to implement Kernel Information and Control API."
#endif
#endif
#if (INCLUDE_xTimerPendFunctionCall == 0)
/*
CMSIS-RTOS2 function osEventFlagsSet and osEventFlagsClear, when called from
the ISR, call FreeRTOS functions xEventGroupSetBitsFromISR and
xEventGroupClearBitsFromISR which are only enabled if timers are operational and
xTimerPendFunctionCall in enabled.
Set #define INCLUDE_xTimerPendFunctionCall 1 and #define configUSE_TIMERS 1
to fix this error.
Alternatively, if the application does not use osEventFlagsSet and osEventFlagsClear
from the ISR their operation from ISR can be restricted by setting:
#define configUSE_OS2_EVENTFLAGS_FROM_ISR 0 (in FreeRTOSConfig.h)
*/
#if (configUSE_OS2_EVENTFLAGS_FROM_ISR == 1)
#error "Definition INCLUDE_xTimerPendFunctionCall must equal 1 to implement Event Flags API."
#endif
#endif
#if (configUSE_TIMERS == 0)
/*
CMSIS-RTOS2 Timer Management API functions use FreeRTOS timer functions to implement
timer management. In case if these functions are not used in the application image,
compiler will optimize them away.
Set #define configUSE_TIMERS 1 to fix this error.
Alternatively, if the application does not use timer functions they can be
excluded from the image code by setting:
#define configUSE_OS2_TIMER 0 (in FreeRTOSConfig.h)
*/
#if (configUSE_OS2_TIMER == 1)
#error "Definition configUSE_TIMERS must equal 1 to implement Timer Management API."
#endif
#endif
#if (configUSE_MUTEXES == 0)
/*
CMSIS-RTOS2 Mutex Management API functions use FreeRTOS mutex functions to implement
mutex management. In case if these functions are not used in the application image,
compiler will optimize them away.
Set #define configUSE_MUTEXES 1 to fix this error.
Alternatively, if the application does not use mutex functions they can be
excluded from the image code by setting:
#define configUSE_OS2_MUTEX 0 (in FreeRTOSConfig.h)
*/
#if (configUSE_OS2_MUTEX == 1)
#error "Definition configUSE_MUTEXES must equal 1 to implement Mutex Management API."
#endif
#endif
#if (configUSE_COUNTING_SEMAPHORES == 0)
/*
CMSIS-RTOS2 Memory Pool functions use FreeRTOS function xSemaphoreCreateCounting
to implement memory pools. In case if these functions are not used in the application image,
compiler will optimize them away.
Set #define configUSE_COUNTING_SEMAPHORES 1 to fix this error.
*/
#error "Definition configUSE_COUNTING_SEMAPHORES must equal 1 to implement Memory Pool API."
#endif
#if (configUSE_TASK_NOTIFICATIONS == 0)
/*
CMSIS-RTOS2 Thread Flags API functions use FreeRTOS Task Notification functions to implement
thread flag management. In case if these functions are not used in the application image,
compiler will optimize them away.
Set #define configUSE_TASK_NOTIFICATIONS 1 to fix this error.
Alternatively, if the application does not use thread flags functions they can be
excluded from the image code by setting:
#define configUSE_OS2_THREAD_FLAGS 0 (in FreeRTOSConfig.h)
*/
#if (configUSE_OS2_THREAD_FLAGS == 1)
#error "Definition configUSE_TASK_NOTIFICATIONS must equal 1 to implement Thread Flags API."
#endif
#endif
#if (configUSE_TRACE_FACILITY == 0)
/*
CMSIS-RTOS2 function osThreadEnumerate requires FreeRTOS function uxTaskGetSystemState
which is only enabled if configUSE_TRACE_FACILITY == 1.
Set #define configUSE_TRACE_FACILITY 1 to fix this error.
Alternatively, if the application does not use osThreadEnumerate it can be
excluded from the image code by setting:
#define configUSE_OS2_THREAD_ENUMERATE 0 (in FreeRTOSConfig.h)
*/
#if (configUSE_OS2_THREAD_ENUMERATE == 1)
#error "Definition configUSE_TRACE_FACILITY must equal 1 to implement osThreadEnumerate."
#endif
#endif
#if (configUSE_16_BIT_TICKS == 1)
/*
CMSIS-RTOS2 wrapper for FreeRTOS relies on 32-bit tick timer which is also optimal on
a 32-bit CPU architectures.
Set #define configUSE_16_BIT_TICKS 0 to fix this error.
*/
#error "Definition configUSE_16_BIT_TICKS must be zero to implement CMSIS-RTOS2 API."
#endif
#if (configMAX_PRIORITIES != 56)
/*
CMSIS-RTOS2 defines 56 different priorities (see osPriority_t) and portable CMSIS-RTOS2
implementation should implement the same number of priorities.
Set #define configMAX_PRIORITIES 56 to fix this error.
*/
#error "Definition configMAX_PRIORITIES must equal 56 to implement Thread Management API."
#endif
#if (configUSE_PORT_OPTIMISED_TASK_SELECTION != 0)
/*
CMSIS-RTOS2 requires handling of 56 different priorities (see osPriority_t) while FreeRTOS port
optimised selection for Cortex core only handles 32 different priorities.
Set #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 to fix this error.
*/
#error "Definition configUSE_PORT_OPTIMISED_TASK_SELECTION must be zero to implement Thread Management API."
#endif
#endif /* FREERTOS_OS2_H_ */