mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(freertos/smp): Update ports to support Amazon FreeRTOS v11.0.1
- vTaskPreemptionDisable()/vTaskPreemptionEnable() are no longer available in single-core builds. - xTaskIncrementTick() calls must now be wrapped by critical section - Minimal Idle Task renamed to Passive Idle Task - Port critical section APIs updated
This commit is contained in:
parent
888678d102
commit
83c686c744
@ -6,7 +6,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
@ -110,15 +110,16 @@ BaseType_t xPortCheckIfInISR(void);
|
||||
|
||||
// ------------------ Critical Sections --------------------
|
||||
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
/*
|
||||
These are always called with interrupts already disabled. We simply need to get/release the spinlocks
|
||||
*/
|
||||
|
||||
extern portMUX_TYPE port_xTaskLock;
|
||||
extern portMUX_TYPE port_xISRLock;
|
||||
|
||||
void vPortTakeLock( portMUX_TYPE *lock );
|
||||
void vPortReleaseLock( portMUX_TYPE *lock );
|
||||
#endif /* configNUMBER_OF_CORES > 1 */
|
||||
|
||||
// ---------------------- Yielding -------------------------
|
||||
|
||||
@ -151,18 +152,9 @@ void vPortCleanUpTCB ( void *pxTCB );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() xPortSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vPortClearInterruptMask(0)
|
||||
#define portRESTORE_INTERRUPTS(x) vPortClearInterruptMask(x)
|
||||
|
||||
// ------------------ Critical Sections --------------------
|
||||
|
||||
#define portGET_TASK_LOCK() vPortTakeLock(&port_xTaskLock)
|
||||
#define portRELEASE_TASK_LOCK() vPortReleaseLock(&port_xTaskLock)
|
||||
#define portGET_ISR_LOCK() vPortTakeLock(&port_xISRLock)
|
||||
#define portRELEASE_ISR_LOCK() vPortReleaseLock(&port_xISRLock)
|
||||
|
||||
//Critical sections used by FreeRTOS SMP
|
||||
extern void vTaskEnterCritical( void );
|
||||
extern void vTaskExitCritical( void );
|
||||
#define portENTER_CRITICAL_SMP() vTaskEnterCritical();
|
||||
#define portEXIT_CRITICAL_SMP() vTaskExitCritical();
|
||||
|
||||
@ -286,8 +278,8 @@ void vPortExitCriticalIDF(void);
|
||||
|
||||
// ---------------------- Yielding -------------------------
|
||||
|
||||
// Added for backward compatibility with IDF
|
||||
#define portYIELD_WITHIN_API() vTaskYieldWithinAPI()
|
||||
extern void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
|
||||
// ----------------------- System --------------------------
|
||||
|
||||
|
@ -298,7 +298,7 @@ void vPortYieldFromISR( void )
|
||||
|
||||
xThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
||||
|
||||
vTaskSwitchContext(xPortGetCoreID());
|
||||
vTaskSwitchContext();
|
||||
|
||||
xThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
||||
|
||||
@ -419,7 +419,7 @@ static void vPortSystemTickHandler( int sig )
|
||||
#if ( configUSE_PREEMPTION == 1 )
|
||||
if (xSwitchRequired == pdTRUE) {
|
||||
/* Select Next Task. */
|
||||
vTaskSwitchContext(xPortGetCoreID());
|
||||
vTaskSwitchContext();
|
||||
|
||||
pxThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -10,15 +10,28 @@
|
||||
|
||||
/* Macros used instead ofsetoff() for better performance of interrupt handler */
|
||||
#if CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES
|
||||
/*
|
||||
pxTopOfStack (4) +
|
||||
xStateListItem (28) +
|
||||
xEventListItem (28) +
|
||||
uxPriority (4)
|
||||
*/
|
||||
#define PORT_OFFSET_PX_STACK 0x40
|
||||
#else
|
||||
/*
|
||||
pxTopOfStack (4) +
|
||||
xStateListItem (20) +
|
||||
xEventListItem (20) +
|
||||
uxPriority (4)
|
||||
*/
|
||||
#define PORT_OFFSET_PX_STACK 0x30
|
||||
#endif /* #if CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES */
|
||||
#define PORT_OFFSET_PX_END_OF_STACK (PORT_OFFSET_PX_STACK + \
|
||||
/* void * pxDummy6 */ 4 + \
|
||||
/* BaseType_t xDummy23[ 2 ] */ 8 + \
|
||||
/* uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ] */ CONFIG_FREERTOS_MAX_TASK_NAME_LEN + \
|
||||
/* BaseType_t xDummy24 */ 4)
|
||||
|
||||
#define PORT_OFFSET_PX_END_OF_STACK ( \
|
||||
PORT_OFFSET_PX_STACK \
|
||||
+ 4 /* StackType_t * pxStack */ \
|
||||
+ CONFIG_FREERTOS_MAX_TASK_NAME_LEN /* pcTaskName[ configMAX_TASK_NAME_LEN ] */ \
|
||||
)
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
@ -102,15 +115,16 @@ BaseType_t xPortCheckIfInISR(void);
|
||||
|
||||
// ------------------ Critical Sections --------------------
|
||||
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
/*
|
||||
These are always called with interrupts already disabled. We simply need to get/release the spinlocks
|
||||
*/
|
||||
|
||||
extern portMUX_TYPE port_xTaskLock;
|
||||
extern portMUX_TYPE port_xISRLock;
|
||||
|
||||
void vPortTakeLock( portMUX_TYPE *lock );
|
||||
void vPortReleaseLock( portMUX_TYPE *lock );
|
||||
#endif /* configNUMBER_OF_CORES > 1 */
|
||||
|
||||
// ---------------------- Yielding -------------------------
|
||||
|
||||
@ -175,11 +189,12 @@ void vPortTCBPreDeleteHook( void *pxTCB );
|
||||
|
||||
// ------------------ Critical Sections --------------------
|
||||
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
#define portGET_TASK_LOCK() vPortTakeLock(&port_xTaskLock)
|
||||
#define portRELEASE_TASK_LOCK() vPortReleaseLock(&port_xTaskLock)
|
||||
#define portGET_ISR_LOCK() vPortTakeLock(&port_xISRLock)
|
||||
#define portRELEASE_ISR_LOCK() vPortReleaseLock(&port_xISRLock)
|
||||
|
||||
#endif /* configNUMBER_OF_CORES > 1 */
|
||||
|
||||
//Critical sections used by FreeRTOS SMP
|
||||
extern void vTaskEnterCritical( void );
|
||||
@ -314,8 +329,8 @@ static inline bool IRAM_ATTR xPortCanYield(void)
|
||||
return (threshold <= 1);
|
||||
}
|
||||
|
||||
// Added for backward compatibility with IDF
|
||||
#define portYIELD_WITHIN_API() vTaskYieldWithinAPI()
|
||||
// Defined even for configNUMBER_OF_CORES > 1 for IDF compatibility
|
||||
#define portYIELD_WITHIN_API() esp_crosscore_int_send_yield(xPortGetCoreID())
|
||||
|
||||
// ----------------------- System --------------------------
|
||||
|
||||
|
@ -170,6 +170,7 @@ BaseType_t xPortCheckIfInISR(void)
|
||||
|
||||
// ------------------ Critical Sections --------------------
|
||||
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
void IRAM_ATTR vPortTakeLock( portMUX_TYPE *lock )
|
||||
{
|
||||
spinlock_acquire( lock, portMUX_NO_TIMEOUT);
|
||||
@ -179,6 +180,7 @@ void IRAM_ATTR vPortReleaseLock( portMUX_TYPE *lock )
|
||||
{
|
||||
spinlock_release( lock );
|
||||
}
|
||||
#endif /* configNUMBER_OF_CORES > 1 */
|
||||
|
||||
// ---------------------- Yielding -------------------------
|
||||
|
||||
@ -486,21 +488,21 @@ void vApplicationTickHook( void )
|
||||
#endif
|
||||
|
||||
extern void esp_vApplicationIdleHook(void);
|
||||
#if CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
|
||||
#if CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK
|
||||
/*
|
||||
By default, the port uses vApplicationMinimalIdleHook() to run IDF style idle
|
||||
hooks. However, users may also want to provide their own vApplicationMinimalIdleHook().
|
||||
In this case, we use to -Wl,--wrap option to wrap the user provided vApplicationMinimalIdleHook()
|
||||
By default, the port uses vApplicationPassiveIdleHook() to run IDF style idle
|
||||
hooks. However, users may also want to provide their own vApplicationPassiveIdleHook().
|
||||
In this case, we use to -Wl,--wrap option to wrap the user provided vApplicationPassiveIdleHook()
|
||||
*/
|
||||
extern void __real_vApplicationMinimalIdleHook( void );
|
||||
void __wrap_vApplicationMinimalIdleHook( void )
|
||||
extern void __real_vApplicationPassiveIdleHook( void );
|
||||
void __wrap_vApplicationPassiveIdleHook( void )
|
||||
{
|
||||
esp_vApplicationIdleHook(); //Run IDF style hooks
|
||||
__real_vApplicationMinimalIdleHook(); //Call the user provided vApplicationMinimalIdleHook()
|
||||
__real_vApplicationPassiveIdleHook(); //Call the user provided vApplicationPassiveIdleHook()
|
||||
}
|
||||
#else // CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
|
||||
void vApplicationMinimalIdleHook( void )
|
||||
#else // CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK
|
||||
void vApplicationPassiveIdleHook( void )
|
||||
{
|
||||
esp_vApplicationIdleHook(); //Run IDF style hooks
|
||||
}
|
||||
#endif // CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
|
||||
#endif // CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK
|
||||
|
@ -7,6 +7,10 @@
|
||||
#include "portmacro.h"
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
#include "esp_private/hw_stack_guard.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
#define pxCurrentTCBs pxCurrentTCB
|
||||
#endif
|
||||
|
||||
.global uxInterruptNesting
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -100,15 +100,16 @@ BaseType_t xPortCheckIfInISR(void);
|
||||
UBaseType_t uxPortEnterCriticalFromISR( void );
|
||||
void vPortExitCriticalFromISR( UBaseType_t level );
|
||||
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
/*
|
||||
These are always called with interrupts already disabled. We simply need to get/release the spinlocks
|
||||
*/
|
||||
|
||||
extern portMUX_TYPE port_xTaskLock;
|
||||
extern portMUX_TYPE port_xISRLock;
|
||||
|
||||
void vPortTakeLock( portMUX_TYPE *lock );
|
||||
void vPortReleaseLock( portMUX_TYPE *lock );
|
||||
#endif /* configNUMBER_OF_CORES > 1 */
|
||||
|
||||
// ---------------------- Yielding -------------------------
|
||||
|
||||
@ -151,35 +152,42 @@ void vPortTCBPreDeleteHook( void *pxTCB );
|
||||
|
||||
// --------------------- Interrupts ------------------------
|
||||
|
||||
#define portDISABLE_INTERRUPTS() ({ \
|
||||
#define portSET_INTERRUPT_MASK() ({ \
|
||||
unsigned int prev_level = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); \
|
||||
portbenchmarkINTERRUPT_DISABLE(); \
|
||||
prev_level = ((prev_level >> XCHAL_PS_INTLEVEL_SHIFT) & XCHAL_PS_INTLEVEL_MASK); \
|
||||
prev_level; \
|
||||
})
|
||||
|
||||
#define portENABLE_INTERRUPTS() ({ \
|
||||
portbenchmarkINTERRUPT_RESTORE(0); \
|
||||
XTOS_SET_INTLEVEL(0); \
|
||||
})
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() portSET_INTERRUPT_MASK()
|
||||
#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK()
|
||||
|
||||
/*
|
||||
Note: XTOS_RESTORE_INTLEVEL() will overwrite entire PS register on XEA2. So we need ot make the value INTLEVEL field ourselves
|
||||
Note: XTOS_RESTORE_INTLEVEL() will overwrite entire PS register on XEA2. So we need to set the value of the INTLEVEL field ourselves
|
||||
*/
|
||||
#define portRESTORE_INTERRUPTS(x) ({ \
|
||||
#define portCLEAR_INTERRUPT_MASK(x) ({ \
|
||||
unsigned int ps_reg; \
|
||||
RSR(PS, ps_reg); \
|
||||
ps_reg = (ps_reg & ~XCHAL_PS_INTLEVEL_MASK); \
|
||||
ps_reg |= ((x << XCHAL_PS_INTLEVEL_SHIFT) & XCHAL_PS_INTLEVEL_MASK); \
|
||||
XTOS_RESTORE_INTLEVEL(ps_reg); \
|
||||
})
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portCLEAR_INTERRUPT_MASK(x)
|
||||
#define portENABLE_INTERRUPTS() ({ \
|
||||
portbenchmarkINTERRUPT_RESTORE(0); \
|
||||
XTOS_SET_INTLEVEL(0); \
|
||||
})
|
||||
|
||||
/* Compatibility */
|
||||
#define portRESTORE_INTERRUPTS(x) portCLEAR_INTERRUPT_MASK(x)
|
||||
|
||||
// ------------------ Critical Sections --------------------
|
||||
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
#define portGET_TASK_LOCK() vPortTakeLock(&port_xTaskLock)
|
||||
#define portRELEASE_TASK_LOCK() vPortReleaseLock(&port_xTaskLock)
|
||||
#define portGET_ISR_LOCK() vPortTakeLock(&port_xISRLock)
|
||||
#define portRELEASE_ISR_LOCK() vPortReleaseLock(&port_xISRLock)
|
||||
#endif /* configNUMBER_OF_CORES > 1 */
|
||||
|
||||
//Critical sections used by FreeRTOS SMP
|
||||
extern void vTaskEnterCritical( void );
|
||||
@ -195,17 +203,10 @@ extern void vTaskExitCritical( void );
|
||||
#define portEXIT_CRITICAL(...) CHOOSE_MACRO_VA_ARG(portEXIT_CRITICAL_IDF, portEXIT_CRITICAL_SMP, ##__VA_ARGS__)(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ({ \
|
||||
unsigned int cur_level; \
|
||||
RSR(PS, cur_level); \
|
||||
cur_level = (cur_level & XCHAL_PS_INTLEVEL_MASK) >> XCHAL_PS_INTLEVEL_SHIFT; \
|
||||
vTaskEnterCritical(); \
|
||||
cur_level; \
|
||||
})
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) ({ \
|
||||
vTaskExitCritical(); \
|
||||
portRESTORE_INTERRUPTS(x); \
|
||||
})
|
||||
extern UBaseType_t vTaskEnterCriticalFromISR( void );
|
||||
extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
|
||||
#define portENTER_CRITICAL_FROM_ISR() vTaskEnterCriticalFromISR()
|
||||
#define portEXIT_CRITICAL_FROM_ISR(x) vTaskExitCriticalFromISR(x)
|
||||
|
||||
// ---------------------- Yielding -------------------------
|
||||
|
||||
@ -356,8 +357,8 @@ static inline bool IRAM_ATTR xPortCanYield(void)
|
||||
return ((ps_reg & PS_INTLEVEL_MASK) == 0);
|
||||
}
|
||||
|
||||
// Added for backward compatibility with IDF
|
||||
#define portYIELD_WITHIN_API() vTaskYieldWithinAPI()
|
||||
// Defined even for configNUMBER_OF_CORES > 1 for IDF compatibility
|
||||
#define portYIELD_WITHIN_API() esp_crosscore_int_send_yield(xPortGetCoreID())
|
||||
|
||||
// ----------------------- System --------------------------
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -63,7 +63,7 @@ const DRAM_ATTR uint32_t offset_pxEndOfStack = offsetof(StaticTask_t, pxDummy8);
|
||||
const DRAM_ATTR uint32_t offset_cpsa = XT_CP_SIZE; /* Offset to start of the CPSA area on the stack. See uxInitialiseStackCPSA(). */
|
||||
#if configNUM_CORES > 1
|
||||
/* Offset to TCB_t.uxCoreAffinityMask member. Used to pin unpinned tasks that use the FPU. */
|
||||
const DRAM_ATTR uint32_t offset_uxCoreAffinityMask = offsetof(StaticTask_t, uxDummy25);
|
||||
const DRAM_ATTR uint32_t offset_uxCoreAffinityMask = offsetof(StaticTask_t, uxDummy26);
|
||||
#if configUSE_CORE_AFFINITY != 1
|
||||
#error "configUSE_CORE_AFFINITY must be 1 on multicore targets with coprocessor support"
|
||||
#endif
|
||||
@ -72,9 +72,11 @@ const DRAM_ATTR uint32_t offset_uxCoreAffinityMask = offsetof(StaticTask_t, uxDu
|
||||
|
||||
volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Indicates whether scheduler is running on a per-core basis
|
||||
unsigned int port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
//FreeRTOS SMP Locks
|
||||
portMUX_TYPE port_xTaskLock = portMUX_INITIALIZER_UNLOCKED;
|
||||
portMUX_TYPE port_xISRLock = portMUX_INITIALIZER_UNLOCKED;
|
||||
#endif /* configNUMBER_OF_CORES > 1 */
|
||||
|
||||
/* ------------------------------------------------ IDF Compatibility --------------------------------------------------
|
||||
* - These need to be defined for IDF to compile
|
||||
@ -204,6 +206,7 @@ BaseType_t xPortCheckIfInISR(void)
|
||||
|
||||
// ------------------ Critical Sections --------------------
|
||||
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
void vPortTakeLock( portMUX_TYPE *lock )
|
||||
{
|
||||
spinlock_acquire( lock, portMUX_NO_TIMEOUT);
|
||||
@ -213,6 +216,7 @@ void vPortReleaseLock( portMUX_TYPE *lock )
|
||||
{
|
||||
spinlock_release( lock );
|
||||
}
|
||||
#endif /* configNUMBER_OF_CORES > 1 */
|
||||
|
||||
// ---------------------- Yielding -------------------------
|
||||
|
||||
@ -262,7 +266,7 @@ static void vPortCleanUpCoprocArea( void *pxTCB )
|
||||
uxCoprocArea = STACKPTR_ALIGN_DOWN(16, uxCoprocArea - XT_CP_SIZE);
|
||||
|
||||
/* Extract core ID from the affinity mask */
|
||||
xTargetCoreID = ( ( StaticTask_t * ) pxTCB )->uxDummy25 ;
|
||||
xTargetCoreID = ( ( StaticTask_t * ) pxTCB )->uxDummy26;
|
||||
xTargetCoreID = ( BaseType_t ) __builtin_ffs( ( int ) xTargetCoreID );
|
||||
assert( xTargetCoreID >= 1 ); // __builtin_ffs always returns first set index + 1
|
||||
xTargetCoreID -= 1;
|
||||
@ -667,21 +671,21 @@ void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, c
|
||||
#endif
|
||||
|
||||
extern void esp_vApplicationIdleHook(void);
|
||||
#if CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
|
||||
#if CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK
|
||||
/*
|
||||
By default, the port uses vApplicationMinimalIdleHook() to run IDF style idle
|
||||
hooks. However, users may also want to provide their own vApplicationMinimalIdleHook().
|
||||
In this case, we use to -Wl,--wrap option to wrap the user provided vApplicationMinimalIdleHook()
|
||||
By default, the port uses vApplicationPassiveIdleHook() to run IDF style idle
|
||||
hooks. However, users may also want to provide their own vApplicationPassiveIdleHook().
|
||||
In this case, we use to -Wl,--wrap option to wrap the user provided vApplicationPassiveIdleHook()
|
||||
*/
|
||||
extern void __real_vApplicationMinimalIdleHook( void );
|
||||
void __wrap_vApplicationMinimalIdleHook( void )
|
||||
extern void __real_vApplicationPassiveIdleHook( void );
|
||||
void __wrap_vApplicationPassiveIdleHook( void )
|
||||
{
|
||||
esp_vApplicationIdleHook(); //Run IDF style hooks
|
||||
__real_vApplicationMinimalIdleHook(); //Call the user provided vApplicationMinimalIdleHook()
|
||||
__real_vApplicationPassiveIdleHook(); //Call the user provided vApplicationPassiveIdleHook()
|
||||
}
|
||||
#else // CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
|
||||
void vApplicationMinimalIdleHook( void )
|
||||
#else // CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK
|
||||
void vApplicationPassiveIdleHook( void )
|
||||
{
|
||||
esp_vApplicationIdleHook(); //Run IDF style hooks
|
||||
}
|
||||
#endif // CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
|
||||
#endif // CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK
|
||||
|
@ -33,6 +33,10 @@
|
||||
|
||||
#define TOPOFSTACK_OFFS 0x00 /* StackType_t *pxTopOfStack */
|
||||
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
#define pxCurrentTCBs pxCurrentTCB
|
||||
#endif
|
||||
|
||||
.extern pxCurrentTCBs
|
||||
#if XCHAL_CP_NUM > 0
|
||||
/* Offsets used to get a task's coprocessor save area (CPSA) from its TCB */
|
||||
|
@ -1,20 +1,17 @@
|
||||
# Overview
|
||||
|
||||
This document outlines some useful notes about
|
||||
|
||||
- The porting of SMP FreeRTOS to ESP-IDF
|
||||
- And the difference between IDF FreeRTOS and SMP FreeRTOS
|
||||
This document outlines some notes regarding the Amazon AMP FreeRTOS port in ESP-IDF
|
||||
|
||||
# Terminology
|
||||
|
||||
The following terms will be used in this document to avoid confusion between the different FreeRTOS versions currently in ESP-IDF
|
||||
|
||||
- SMP FreeRTOS: The SMP branch of the FreeRTOS kernel found [here](https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/smp)
|
||||
- SMP FreeRTOS: An SMP capable release of the FreeRTOS kernel described [here](https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/smp)
|
||||
- IDF FreeRTOS: The version of FreeRTOS used in mainline ESP-IDF that contained custom modifications to support SMP features specific to the ESP chips.
|
||||
|
||||
# Organization
|
||||
|
||||
This directory contains a copy of SMP FreeRTOS based off of upstream commit [8128208](https://github.com/FreeRTOS/FreeRTOS-Kernel/commit/8128208bdee1f997f83cae631b861f36aeea9b1f)
|
||||
This directory contains a copy of upstream [v11.0.1](https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/V11.0.1) FreeRTOS which is SMP capable.
|
||||
|
||||
- IDF FreeRTOS remains in `components/freertos/FreeRTOS-Kernel`
|
||||
- SMP FreeRTOS is entirely contained in `components/freertos/FreeRTOS-Kernel-SMP`
|
||||
@ -104,15 +101,15 @@ IDF FreeRTOS:
|
||||
|
||||
SMP FreeRTOS:
|
||||
|
||||
- There are now two types of idle task functions. The `prvIdleTask()` and `prvMinimalIdleTask()`
|
||||
- `prvMinimalIdleTask()` simply calls the `vApplicationMinimalIdleHook()`
|
||||
- `prvIdleTask()` calls `prvCheckTasksWaitingTermination()`, `vApplicationIdleHook()`, `vApplicationMinimalIdleHook()`, and handles tickless idle.
|
||||
- On an N core build, one `prvIdleTask()` task is created and N-1 `prvMinimalIdleTask()` tasks are created.
|
||||
- There are now two types of idle task functions. The `prvIdleTask()` and `prvPassiveIdleTask()`
|
||||
- `prvPassiveIdleTask()` simply calls the `vApplicationPassiveIdleHook()`
|
||||
- `prvIdleTask()` calls `prvCheckTasksWaitingTermination()`, `vApplicationIdleHook()`, `vApplicationPassiveIdleHook()`, and handles tickless idling.
|
||||
- On an N core build, one `prvIdleTask()` task is created and N-1 `prvPassiveIdleTask()` tasks are created.
|
||||
- The created idle tasks are all unpinned. The idle tasks are run on a "first come first serve" basis meaning when a core goes idle, it selects whatever available idle task it can run.
|
||||
|
||||
Changes Made:
|
||||
|
||||
- The `esp_vApplicationIdleHook()` is now called from `vApplicationMinimalIdleHook()` since every idle task calls the `vApplicationMinimalIdleHook()`.
|
||||
- The `esp_vApplicationIdleHook()` is now called from `vApplicationPassiveIdleHook()` since every idle task calls the `vApplicationPassiveIdleHook()`.
|
||||
- Since the idle tasks are unpinned, the task WDT has been updated to use the "User" feature. Thus, feeding the task watchdog now tracks which "core" has fed the task WDT instead of which specific idle task has fed.
|
||||
- Since `prvIdleTask()` is solely responsible for calling `prvCheckTasksWaitingTermination()` but can run on any core, multiple IDF cleanup routines are now routed through `portCLEAN_UP_TCB()`
|
||||
- FPU registers of a task are now cleaned up via `portCLEAN_UP_TCB() -> vPortCleanUpCoprocArea()` and can clean FPU save areas across cores.
|
||||
@ -169,25 +166,3 @@ IDF FreeRTOS added multiple features/APIs that are specific to IDF. For SMP Free
|
||||
- If TLSP deletion callbacks are used, `configNUM_THREAD_LOCAL_STORAGE_POINTERS` will be doubled (in order to store the callback pointers in the same array as the TLSPs themselves)
|
||||
- `vTaskSetThreadLocalStoragePointerAndDelCallback()` moved to `freertos_tasks_c_additions.h`/`idf_additions.h`
|
||||
- Deletion callbacks invoked from the main idle task via `portCLEAN_UP_TCB()`
|
||||
|
||||
### `xTaskGetCurrentTaskHandleForCPU()`
|
||||
|
||||
- Convenience function to the get current task of a particular CPU
|
||||
- Moved to `freertos_tasks_c_additions.h`/`idf_additions.h` for now
|
||||
|
||||
Todo: Check if this can be upstreamed
|
||||
|
||||
### `xTaskGetIdleTaskHandleForCPU()`
|
||||
|
||||
- Currently moved to `freertos_tasks_c_additions.h`/`idf_additions.h`
|
||||
|
||||
Todo: This needs to be deprecated as there is no longer the concept of idle tasks pinned to a particular CPU
|
||||
|
||||
### `xTaskGetAffinity()`
|
||||
|
||||
- Returns what core a task is pinned to, and not the task's affinity mask.
|
||||
- Moved to `freertos_tasks_c_additions.h`/`idf_additions.h` and simple wraps `vTaskCoreAffinityGet()`
|
||||
- If the task's affinity mask has more than one permissible core, we simply return `tskNO_AFFINITY` even if the task is not completely unpinned.
|
||||
|
||||
Todo: This needs to be deprecated and users should call `vTaskCoreAffinityGet()` instead
|
||||
|
||||
|
@ -3,6 +3,7 @@ menu "FreeRTOS"
|
||||
menu "Kernel"
|
||||
# Upstream FreeRTOS configurations go here
|
||||
|
||||
|
||||
config FREERTOS_SMP
|
||||
bool "Run the Amazon SMP FreeRTOS kernel instead (FEATURE UNDER DEVELOPMENT)"
|
||||
depends on !IDF_TARGET_ESP32P4 #TODO: IDF-8113: Enable P4 support on AMZ SMP
|
||||
@ -116,7 +117,7 @@ menu "FreeRTOS"
|
||||
- The FreeRTOS idle hook is NOT the same as the ESP-IDF Idle Hook, but both can be enabled
|
||||
simultaneously.
|
||||
|
||||
config FREERTOS_USE_MINIMAL_IDLE_HOOK
|
||||
config FREERTOS_USE_PASSIVE_IDLE_HOOK
|
||||
bool "Use FreeRTOS minimal idle hook"
|
||||
depends on FREERTOS_SMP
|
||||
default n
|
||||
@ -126,8 +127,8 @@ menu "FreeRTOS"
|
||||
|
||||
Note:
|
||||
|
||||
- The application must provide the hook function ``void vApplicationMinimalIdleHook( void );``
|
||||
- ``vApplicationMinimalIdleHook()`` is called from FreeRTOS minimal idle task(s)
|
||||
- The application must provide the hook function ``void vApplicationPassiveIdleHook( void );``
|
||||
- ``vApplicationPassiveIdleHook()`` is called from FreeRTOS minimal idle task(s)
|
||||
|
||||
config FREERTOS_USE_TICK_HOOK
|
||||
bool "configUSE_TICK_HOOK"
|
||||
|
@ -262,10 +262,11 @@
|
||||
* - All Amazon SMP FreeRTOS specific configurations
|
||||
* ------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
#if CONFIG_FREERTOS_SMP
|
||||
#if CONFIG_FREERTOS_SMP && ( CONFIG_FREERTOS_NUMBER_OF_CORES > 1 )
|
||||
#define configUSE_CORE_AFFINITY 1
|
||||
#define configRUN_MULTIPLE_PRIORITIES 1
|
||||
#define configUSE_TASK_PREEMPTION_DISABLE 1
|
||||
#endif /* CONFIG_FREERTOS_SMP */
|
||||
#endif /* CONFIG_FREERTOS_SMP && ( CONFIG_FREERTOS_NUMBER_OF_CORES > 1 ) */
|
||||
|
||||
/* -------------------------------------------------- IDF FreeRTOS -----------------------------------------------------
|
||||
* - All IDF FreeRTOS specific configurations
|
||||
|
@ -31,7 +31,7 @@
|
||||
/* ---------------- Amazon SMP FreeRTOS -------------------- */
|
||||
|
||||
#if CONFIG_FREERTOS_SMP
|
||||
#define configUSE_MINIMAL_IDLE_HOOK 0 /* Not implemented yet, TODO IDF-6654 */
|
||||
#define configUSE_PASSIVE_IDLE_HOOK 0 /* Not implemented yet, TODO IDF-6654 */
|
||||
#endif
|
||||
|
||||
/* ----------------------- System -------------------------- */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -27,15 +27,10 @@
|
||||
/* ---------------- Amazon SMP FreeRTOS -------------------- */
|
||||
|
||||
#if CONFIG_FREERTOS_SMP
|
||||
#define configUSE_CORE_AFFINITY 1
|
||||
|
||||
/* This is always enabled to call IDF style idle hooks, by can be "--Wl,--wrap"
|
||||
* if users enable CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK. */
|
||||
#define configUSE_MINIMAL_IDLE_HOOK 1
|
||||
|
||||
/* IDF Newlib supports dynamic reentrancy. We provide our own __getreent()
|
||||
* function. */
|
||||
#define configNEWLIB_REENTRANT_IS_DYNAMIC 1
|
||||
* if users enable CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK. */
|
||||
#define configUSE_PASSIVE_IDLE_HOOK 1
|
||||
#endif
|
||||
|
||||
/* ----------------------- System -------------------------- */
|
||||
@ -46,7 +41,11 @@
|
||||
* - We simply provide our own INIT and DEINIT functions
|
||||
* - We set "SET" to a blank macro since there is no need to set the reentrancy
|
||||
* pointer. All newlib functions calls __getreent. */
|
||||
#if CONFIG_FREERTOS_SMP
|
||||
#define configINIT_TLS_BLOCK( xTLSBlock, pxTopOfStack ) esp_reent_init( &( xTLSBlock ) )
|
||||
#else /* CONFIG_FREERTOS_SMP */
|
||||
#define configINIT_TLS_BLOCK( xTLSBlock ) esp_reent_init( &( xTLSBlock ) )
|
||||
#endif /* CONFIG_FREERTOS_SMP */
|
||||
#define configSET_TLS_BLOCK( xTLSBlock )
|
||||
#define configDEINIT_TLS_BLOCK( xTLSBlock ) _reclaim_reent( &( xTLSBlock ) )
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -54,15 +54,10 @@
|
||||
/* ---------------- Amazon SMP FreeRTOS -------------------- */
|
||||
|
||||
#if CONFIG_FREERTOS_SMP
|
||||
#define configUSE_CORE_AFFINITY 1
|
||||
|
||||
/* This is always enabled to call IDF style idle hooks, by can be "--Wl,--wrap"
|
||||
* if users enable CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK. */
|
||||
#define configUSE_MINIMAL_IDLE_HOOK 1
|
||||
|
||||
/* IDF Newlib supports dynamic reentrancy. We provide our own __getreent()
|
||||
* function. */
|
||||
#define configNEWLIB_REENTRANT_IS_DYNAMIC 1
|
||||
* if users enable CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK. */
|
||||
#define configUSE_PASSIVE_IDLE_HOOK 1
|
||||
#endif
|
||||
|
||||
/* ----------------------- System -------------------------- */
|
||||
@ -73,7 +68,11 @@
|
||||
* - We simply provide our own INIT and DEINIT functions
|
||||
* - We set "SET" to a blank macro since there is no need to set the reentrancy
|
||||
* pointer. All newlib functions calls __getreent. */
|
||||
#if CONFIG_FREERTOS_SMP
|
||||
#define configINIT_TLS_BLOCK( xTLSBlock, pxTopOfStack ) esp_reent_init( &( xTLSBlock ) )
|
||||
#else /* CONFIG_FREERTOS_SMP */
|
||||
#define configINIT_TLS_BLOCK( xTLSBlock ) esp_reent_init( &( xTLSBlock ) )
|
||||
#endif /* CONFIG_FREERTOS_SMP */
|
||||
#define configSET_TLS_BLOCK( xTLSBlock )
|
||||
#define configDEINIT_TLS_BLOCK( xTLSBlock ) _reclaim_reent( &( xTLSBlock ) )
|
||||
|
||||
|
@ -29,7 +29,9 @@
|
||||
*/
|
||||
_Static_assert( offsetof( StaticTask_t, pxDummy6 ) == offsetof( TCB_t, pxStack ) );
|
||||
_Static_assert( offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfStack ) );
|
||||
#if !CONFIG_IDF_TARGET_LINUX // Disabled for linux builds due to differences in types
|
||||
_Static_assert( tskNO_AFFINITY == ( BaseType_t ) CONFIG_FREERTOS_NO_AFFINITY, "CONFIG_FREERTOS_NO_AFFINITY must be the same as tskNO_AFFINITY" );
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------- Kernel Control ------------------------------------------------- */
|
||||
|
||||
|
@ -88,6 +88,8 @@ entries:
|
||||
port_common (noflash_text) # Default all functions to internal RAM
|
||||
if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
|
||||
port_common:vApplicationGetIdleTaskMemory (default)
|
||||
if FREERTOS_SMP = y && FREERTOS_UNICORE = n:
|
||||
port_common:vApplicationGetPassiveIdleTaskMemory (default)
|
||||
port_common:vApplicationGetTimerTaskMemory (default)
|
||||
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -57,6 +57,16 @@ void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
|
||||
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
|
||||
}
|
||||
|
||||
#if ( ( CONFIG_FREERTOS_SMP ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
void vApplicationGetPassiveIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,
|
||||
StackType_t ** ppxIdleTaskStackBuffer,
|
||||
uint32_t * pulIdleTaskStackSize,
|
||||
BaseType_t xPassiveIdleTaskIndex)
|
||||
{
|
||||
vApplicationGetIdleTaskMemory(ppxIdleTaskTCBBuffer, ppxIdleTaskStackBuffer, pulIdleTaskStackSize);
|
||||
}
|
||||
#endif /* ( ( CONFIG_FREERTOS_SMP ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
|
||||
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
|
||||
StackType_t **ppxTimerTaskStackBuffer,
|
||||
uint32_t *pulTimerTaskStackSize)
|
||||
|
@ -201,6 +201,7 @@ BaseType_t xPortSysTickHandler(void)
|
||||
// Call FreeRTOS Increment tick function
|
||||
BaseType_t xSwitchRequired;
|
||||
#if CONFIG_FREERTOS_SMP
|
||||
UBaseType_t uxSavedStatus = taskENTER_CRITICAL_FROM_ISR();
|
||||
// Amazon SMP FreeRTOS requires that only core 0 calls xTaskIncrementTick()
|
||||
#if ( configNUM_CORES > 1 )
|
||||
if (portGET_CORE_ID() == 0) {
|
||||
@ -211,6 +212,7 @@ BaseType_t xPortSysTickHandler(void)
|
||||
#else /* configNUM_CORES > 1 */
|
||||
xSwitchRequired = xTaskIncrementTick();
|
||||
#endif /* configNUM_CORES > 1 */
|
||||
taskEXIT_CRITICAL_FROM_ISR(uxSavedStatus);
|
||||
#else /* !CONFIG_FREERTOS_SMP */
|
||||
#if ( configNUM_CORES > 1 )
|
||||
/*
|
||||
|
@ -109,7 +109,7 @@ Expected:
|
||||
static void unpinned_task(void *arg)
|
||||
{
|
||||
// Disable scheduling/preemption to make sure the current task doesn't switch cores
|
||||
#if CONFIG_FREERTOS_SMP
|
||||
#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) )
|
||||
vTaskPreemptionDisable(NULL);
|
||||
#else
|
||||
vTaskSuspendAll();
|
||||
@ -140,7 +140,7 @@ static void unpinned_task(void *arg)
|
||||
#endif
|
||||
#endif // !CONFIG_FREERTOS_UNICORE
|
||||
// Reenable scheduling/preemption
|
||||
#if CONFIG_FREERTOS_SMP
|
||||
#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) )
|
||||
vTaskPreemptionEnable(NULL);
|
||||
#else
|
||||
xTaskResumeAll();
|
||||
|
@ -130,7 +130,7 @@ Expected:
|
||||
static void unpinned_task(void *arg)
|
||||
{
|
||||
// Disable scheduling/preemption to make sure current core ID doesn't change
|
||||
#if CONFIG_FREERTOS_SMP
|
||||
#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) )
|
||||
vTaskPreemptionDisable(NULL);
|
||||
#else
|
||||
vTaskSuspendAll();
|
||||
@ -166,7 +166,7 @@ static void unpinned_task(void *arg)
|
||||
#endif
|
||||
#endif // !CONFIG_FREERTOS_UNICORE
|
||||
// Reenable scheduling/preemption
|
||||
#if CONFIG_FREERTOS_SMP
|
||||
#if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) )
|
||||
vTaskPreemptionEnable(NULL);
|
||||
#else
|
||||
xTaskResumeAll();
|
||||
|
Loading…
Reference in New Issue
Block a user