From 31c0ed99f4a3e524dda0670ed17db9a4a59f9bbd Mon Sep 17 00:00:00 2001 From: Vladimir Umek Date: Wed, 13 Mar 2024 11:14:03 +0100 Subject: [PATCH] Add support for processor affinity to CMSIS-RTOS2 wrapper --- ARM.CMSIS-FreeRTOS.pdsc | 7 +- .../FreeRTOS/Config/ARMCM/FreeRTOSConfig.h | 21 ++++ CMSIS/RTOS2/FreeRTOS/Include/freertos_os2.h | 28 +++++- CMSIS/RTOS2/FreeRTOS/Source/cmsis_os2.c | 96 ++++++++++++++++++- 4 files changed, 143 insertions(+), 9 deletions(-) diff --git a/ARM.CMSIS-FreeRTOS.pdsc b/ARM.CMSIS-FreeRTOS.pdsc index b23762bc..d9e39744 100644 --- a/ARM.CMSIS-FreeRTOS.pdsc +++ b/ARM.CMSIS-FreeRTOS.pdsc @@ -11,6 +11,7 @@ FreeRTOS 11.0.1 Active development... + - Add support for processor affinity to CMSIS-RTOS2 wrapper - Add memory allocation configuration options to FreeRTOSConfig.h - CMSIS-RTOS2 requires CMSIS:OS Tick component - Drop support for Arm Compiler 5 @@ -20,7 +21,7 @@ - + @@ -870,7 +871,7 @@ - + CMSIS-RTOS2 implementation for Cortex-M based on FreeRTOS #define RTE_CMSIS_RTOS2 /* CMSIS-RTOS2 */ @@ -884,7 +885,7 @@ - + CMSIS-RTOS2 implementation for Cortex-A based on FreeRTOS #define RTE_CMSIS_RTOS2 /* CMSIS-RTOS2 */ diff --git a/CMSIS/RTOS2/FreeRTOS/Config/ARMCM/FreeRTOSConfig.h b/CMSIS/RTOS2/FreeRTOS/Config/ARMCM/FreeRTOSConfig.h index 7607f7a3..7eb3de4b 100644 --- a/CMSIS/RTOS2/FreeRTOS/Config/ARMCM/FreeRTOSConfig.h +++ b/CMSIS/RTOS2/FreeRTOS/Config/ARMCM/FreeRTOSConfig.h @@ -271,6 +271,27 @@ #define configMINIMAL_SECURE_STACK_SIZE ((uint32_t)128) // +// Symmetric Multiprocessing Configuration +// Enable and configure FreeRTOS for Symmetric Multiprocessing (SMP). + +// Number of processor cores +// Sets the number of available processor cores. +// Default: 1 +#define configNUMBER_OF_CORES 1 + +// Use processor core affinity +// Enables the control for task to run on specific processor cores. +// Task that has no processor affinity set may run on any available core. +// Default: 0 +#define configUSE_CORE_AFFINITY 0 + +// Use passive idle hook +// Enable callback function call on each idle task iteration. +// Callback function vApplicationPassiveIdleHook implementation is required when idle hook is enabled. +// Default: 0 +#define configUSE_PASSIVE_IDLE_HOOK 0 +// + //------------- <<< end of configuration section >>> --------------------------- /* Defines needed by FreeRTOS to implement CMSIS RTOS2 API. Do not change! */ diff --git a/CMSIS/RTOS2/FreeRTOS/Include/freertos_os2.h b/CMSIS/RTOS2/FreeRTOS/Include/freertos_os2.h index 4844b148..4eec4269 100644 --- a/CMSIS/RTOS2/FreeRTOS/Include/freertos_os2.h +++ b/CMSIS/RTOS2/FreeRTOS/Include/freertos_os2.h @@ -1,5 +1,5 @@ /* -------------------------------------------------------------------------- - * Copyright (c) 2013-2023 Arm Limited. All rights reserved. + * Copyright (c) 2013-2024 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -110,6 +110,12 @@ #define configUSE_OS2_MUTEX configUSE_MUTEXES #endif +/* + Option to exclude CMSIS-RTOS2 Processor Affinity API functions from the application image. +*/ +#ifndef configUSE_OS2_CPU_AFFINITY +#define configUSE_OS2_CPU_AFFINITY configUSE_CORE_AFFINITY +#endif /* CMSIS-RTOS2 FreeRTOS configuration check (FreeRTOSConfig.h). @@ -267,6 +273,26 @@ #endif #endif +#if (configUSE_CORE_AFFINITY == 0) + /* + CMSIS-RTOS2 Processor Affinity API functions require FreeRTOS kernel support for + Symmetric Multiprocessing (SMP). In case if this functionality is not available + and the functions are not used in the application image, compiler will optimize + them away. + Set #define configUSE_CORE_AFFINITY 1 to fix this error. + Note: SMP is only available when #define configNUMBER_OF_CORES > 1 + + Alternatively, if the application does not use processor affinity functions they + can be excluded from the image code by setting: + #define configUSE_OS2_CPU_AFFINITY 0 (in FreeRTOSConfig.h) + */ + + #if (configUSE_OS2_CPU_AFFINITY == 1) + #error "Definitions configNUMBER_OF_CORES and configUSE_CORE_AFFINITY must equal 1 to implement Processor Affinity API." + #endif +#endif + + #if (configUSE_COUNTING_SEMAPHORES == 0) /* CMSIS-RTOS2 Memory Pool functions use FreeRTOS function xSemaphoreCreateCounting diff --git a/CMSIS/RTOS2/FreeRTOS/Source/cmsis_os2.c b/CMSIS/RTOS2/FreeRTOS/Source/cmsis_os2.c index 534e2a9e..d1840d2f 100644 --- a/CMSIS/RTOS2/FreeRTOS/Source/cmsis_os2.c +++ b/CMSIS/RTOS2/FreeRTOS/Source/cmsis_os2.c @@ -521,6 +521,9 @@ osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAtt TaskHandle_t hTask; UBaseType_t prio; int32_t mem; +#if (configUSE_OS2_CPU_AFFINITY == 1) + UBaseType_t core_aff = tskNO_AFFINITY; +#endif hTask = NULL; @@ -561,6 +564,12 @@ osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAtt mem = 0; } } + + #if (configUSE_OS2_CPU_AFFINITY == 1) + if (attr->affinity_mask != 0U) { + core_aff = attr->affinity_mask; + } + #endif } else { mem = 0; @@ -568,16 +577,49 @@ osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAtt if (mem == 1) { #if (configSUPPORT_STATIC_ALLOCATION == 1) - hTask = xTaskCreateStatic ((TaskFunction_t)func, name, stack, argument, prio, (StackType_t *)attr->stack_mem, - (StaticTask_t *)attr->cb_mem); + #if (configUSE_OS2_CPU_AFFINITY == 0) + hTask = xTaskCreateStatic ((TaskFunction_t)func, + name, + stack, + argument, + prio, + (StackType_t *)attr->stack_mem, + (StaticTask_t *)attr->cb_mem); + #else + hTask = xTaskCreateStaticAffinitySet ((TaskFunction_t)func, + name, + stack, + argument, + prio, + (StackType_t *)attr->stack_mem, + (StaticTask_t *)attr->cb_mem, + core_aff); + #endif #endif } else { if (mem == 0) { #if (configSUPPORT_DYNAMIC_ALLOCATION == 1) - if (xTaskCreate ((TaskFunction_t)func, name, (configSTACK_DEPTH_TYPE)stack, argument, prio, &hTask) != pdPASS) { - hTask = NULL; - } + #if (configUSE_OS2_CPU_AFFINITY == 0) + if (xTaskCreate ((TaskFunction_t )func, + name, + (configSTACK_DEPTH_TYPE)stack, + argument, + prio, + &hTask) != pdPASS) { + hTask = NULL; + } + #else + if (xTaskCreateAffinitySet ((TaskFunction_t )func, + name, + (configSTACK_DEPTH_TYPE)stack, + argument, + prio, + core_aff, + &hTask) != pdPASS) { + hTask = NULL; + } + #endif #endif } } @@ -878,6 +920,50 @@ uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items) { } #endif /* (configUSE_OS2_THREAD_ENUMERATE == 1) */ +#if (configUSE_OS2_CPU_AFFINITY == 1) +/* + Set processor affinity mask of a thread. +*/ +osStatus_t osThreadSetAffinityMask (osThreadId_t thread_id, uint32_t affinity_mask) { + TaskHandle_t hTask = (TaskHandle_t)thread_id; + osStatus_t stat; + + if (IRQ_Context() != 0U) { + stat = osErrorISR; + } + else if (hTask == NULL) { + stat = osErrorParameter; + } + else { + stat = osOK; + vTaskCoreAffinitySet (hTask, (UBaseType_t)affinity_mask); + } + + /* Return execution status */ + return (stat); +} + +/* + Get current processor affinity mask of a thread. +*/ +uint32_t osThreadGetAffinityMask (osThreadId_t thread_id) { + TaskHandle_t hTask = (TaskHandle_t)thread_id; + UBaseType_t affinity_mask; + + if (IRQ_Context() != 0U) { + affinity_mask = 0U; + } + else if (hTask == NULL) { + affinity_mask = 0U; + } + else { + affinity_mask = vTaskCoreAffinityGet (hTask); + } + + /* Return current processor affinity mask */ + return ((uint32_t)affinity_mask); +} +#endif /* (configUSE_OS2_CPU_AFFINITY == 1) */ /* ==== Thread Flags Functions ==== */