mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/freertos_smp_port_local_storage' into 'master'
freertos: Disable portUSING_MPU_WRAPPERS Closes IDF-4563 See merge request espressif/esp-idf!17409
This commit is contained in:
commit
fc9c6a6cfb
@ -196,7 +196,7 @@ This file get's pulled into assembly sources. Therefore, some includes need to b
|
|||||||
#elif CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY
|
#elif CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY
|
||||||
#define configCHECK_FOR_STACK_OVERFLOW 2
|
#define configCHECK_FOR_STACK_OVERFLOW 2
|
||||||
#endif
|
#endif
|
||||||
#define configRECORD_STACK_HIGH_ADDRESS 1
|
#define configRECORD_STACK_HIGH_ADDRESS 1 // This must be set as the port requires TCB.pxEndOfStack
|
||||||
|
|
||||||
// ------------------- Run-time Stats ----------------------
|
// ------------------- Run-time Stats ----------------------
|
||||||
|
|
||||||
|
@ -247,54 +247,6 @@ static inline BaseType_t __attribute__((always_inline)) xPortGetCoreID( void )
|
|||||||
return (BaseType_t) cpu_hal_get_core_id();
|
return (BaseType_t) cpu_hal_get_core_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------ Misc ---------------------------------------------------------
|
|
||||||
* - Miscellaneous porting macros
|
|
||||||
* - These are not part of the FreeRTOS porting interface, but are used by other FreeRTOS dependent components
|
|
||||||
* - [refactor-todo] Remove dependency on MPU wrappers by modifying TCB
|
|
||||||
* ------------------------------------------------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
// -------------------- Co-Processor -----------------------
|
|
||||||
|
|
||||||
// When coprocessors are defined, we maintain a pointer to coprocessors area.
|
|
||||||
// We currently use a hack: redefine field xMPU_SETTINGS in TCB block as a structure that can hold:
|
|
||||||
// MPU wrappers, coprocessor area pointer, trace code structure, and more if needed.
|
|
||||||
// The field is normally used for memory protection. FreeRTOS should create another general purpose field.
|
|
||||||
typedef struct {
|
|
||||||
#if XCHAL_CP_NUM > 0
|
|
||||||
volatile StackType_t *coproc_area; // Pointer to coprocessor save area; MUST BE FIRST
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if portUSING_MPU_WRAPPERS
|
|
||||||
// Define here mpu_settings, which is port dependent
|
|
||||||
int mpu_setting; // Just a dummy example here; MPU not ported to Xtensa yet
|
|
||||||
#endif
|
|
||||||
} xMPU_SETTINGS;
|
|
||||||
|
|
||||||
// Main hack to use MPU_wrappers even when no MPU is defined (warning: mpu_setting should not be accessed; otherwise move this above xMPU_SETTINGS)
|
|
||||||
#if (XCHAL_CP_NUM > 0) && !portUSING_MPU_WRAPPERS // If MPU wrappers not used, we still need to allocate coproc area
|
|
||||||
#undef portUSING_MPU_WRAPPERS
|
|
||||||
#define portUSING_MPU_WRAPPERS 1 // Enable it to allocate coproc area
|
|
||||||
#define MPU_WRAPPERS_H // Override mpu_wrapper.h to disable unwanted code
|
|
||||||
#define PRIVILEGED_FUNCTION
|
|
||||||
#define PRIVILEGED_DATA
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void _xt_coproc_release(volatile void *coproc_sa_base);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The structures and methods of manipulating the MPU are contained within the
|
|
||||||
* port layer.
|
|
||||||
*
|
|
||||||
* Fills the xMPUSettings structure with the memory region information
|
|
||||||
* contained in xRegions.
|
|
||||||
*/
|
|
||||||
#if( portUSING_MPU_WRAPPERS == 1 )
|
|
||||||
struct xMEMORY_REGION;
|
|
||||||
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION *const xRegions, StackType_t *pxBottomOfStack, uint32_t usStackDepth ) PRIVILEGED_FUNCTION;
|
|
||||||
void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------ IDF Compatibility --------------------------------------------------
|
/* ------------------------------------------------ IDF Compatibility --------------------------------------------------
|
||||||
* - These macros and functions need to be defined for IDF to compile
|
* - These macros and functions need to be defined for IDF to compile
|
||||||
* ------------------------------------------------------------------------------------------------------------------ */
|
* ------------------------------------------------------------------------------------------------------------------ */
|
||||||
|
@ -437,17 +437,19 @@ static void vPortTaskWrapper(TaskFunction_t pxCode, void *pvParameters)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const DRAM_ATTR uint32_t offset_pxEndOfStack = offsetof(StaticTask_t, pxDummy8);
|
||||||
|
const DRAM_ATTR uint32_t offset_uxCoreAffinityMask = offsetof(StaticTask_t, uxDummy25);
|
||||||
|
const DRAM_ATTR uint32_t offset_cpsa = XT_CP_SIZE;
|
||||||
|
|
||||||
#if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
|
#if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
|
||||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||||
StackType_t * pxEndOfStack,
|
StackType_t * pxEndOfStack,
|
||||||
TaskFunction_t pxCode,
|
TaskFunction_t pxCode,
|
||||||
void * pvParameters,
|
void * pvParameters )
|
||||||
BaseType_t xRunPrivileged )
|
|
||||||
#else
|
#else
|
||||||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||||
TaskFunction_t pxCode,
|
TaskFunction_t pxCode,
|
||||||
void * pvParameters,
|
void * pvParameters )
|
||||||
BaseType_t xRunPrivileged )
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
StackType_t *sp, *tp;
|
StackType_t *sp, *tp;
|
||||||
@ -624,34 +626,3 @@ void vApplicationMinimalIdleHook( void )
|
|||||||
esp_vApplicationIdleHook(); //Run IDF style hooks
|
esp_vApplicationIdleHook(); //Run IDF style hooks
|
||||||
}
|
}
|
||||||
#endif // CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
|
#endif // CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
|
||||||
|
|
||||||
/* ---------------------------------------------- Misc Implementations -------------------------------------------------
|
|
||||||
*
|
|
||||||
* ------------------------------------------------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
// -------------------- Co-Processor -----------------------
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Used to set coprocessor area in stack. Current hack is to reuse MPU pointer for coprocessor area.
|
|
||||||
*/
|
|
||||||
#if portUSING_MPU_WRAPPERS
|
|
||||||
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION *const xRegions, StackType_t *pxBottomOfStack, uint32_t usStackDepth )
|
|
||||||
{
|
|
||||||
#if XCHAL_CP_NUM > 0
|
|
||||||
xMPUSettings->coproc_area = ( StackType_t * ) ( ( uint32_t ) ( pxBottomOfStack + usStackDepth - 1 ));
|
|
||||||
xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) xMPUSettings->coproc_area ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
|
|
||||||
xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( uint32_t ) xMPUSettings->coproc_area - XT_CP_SIZE ) & ~0xf );
|
|
||||||
|
|
||||||
|
|
||||||
/* NOTE: we cannot initialize the coprocessor save area here because FreeRTOS is going to
|
|
||||||
* clear the stack area after we return. This is done in pxPortInitialiseStack().
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings )
|
|
||||||
{
|
|
||||||
/* If task has live floating point registers somewhere, release them */
|
|
||||||
_xt_coproc_release( xMPUSettings->coproc_area );
|
|
||||||
}
|
|
||||||
#endif /* portUSING_MPU_WRAPPERS */
|
|
||||||
|
@ -32,9 +32,34 @@
|
|||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#define TOPOFSTACK_OFFS 0x00 /* StackType_t *pxTopOfStack */
|
#define TOPOFSTACK_OFFS 0x00 /* StackType_t *pxTopOfStack */
|
||||||
#define CP_TOPOFSTACK_OFFS 0x04 /* xMPU_SETTINGS.coproc_area */
|
|
||||||
|
|
||||||
.extern pxCurrentTCBs
|
.extern pxCurrentTCBs
|
||||||
|
.extern offset_pxEndOfStack
|
||||||
|
.extern offset_cpsa
|
||||||
|
|
||||||
|
/*
|
||||||
|
Macro to get a task's coprocessor save area (CPSA) from its TCB
|
||||||
|
|
||||||
|
Entry:
|
||||||
|
- reg_A contains a pointer to the TCB
|
||||||
|
Exit:
|
||||||
|
- reg_A contains a pointer to the CPSA
|
||||||
|
- reg_B destroyed
|
||||||
|
*/
|
||||||
|
.macro get_cpsa_from_tcb reg_A reg_B
|
||||||
|
// Get TCB.pxEndOfStack from reg_A
|
||||||
|
movi \reg_B, offset_pxEndOfStack /* Move &offset_pxEndOfStack into reg_B */
|
||||||
|
l32i \reg_B, \reg_B, 0 /* Load offset_pxEndOfStack into reg_B */
|
||||||
|
add \reg_A, \reg_A, \reg_B /* Calculate &pxEndOfStack to reg_A (&TCB + offset_pxEndOfStack) */
|
||||||
|
l32i \reg_A, \reg_A, 0 /* Load TCB.pxEndOfStack into reg_A */
|
||||||
|
//Offset to start of coproc save area
|
||||||
|
movi \reg_B, offset_cpsa /* Move &offset_cpsa into reg_B */
|
||||||
|
l32i \reg_B, \reg_B, 0 /* Load offset_cpsa into reg_B */
|
||||||
|
sub \reg_A, \reg_A, \reg_B /* Subtract offset_cpsa from pxEndOfStack to get to start of CP save area (unaligned) */
|
||||||
|
//Align down start of CP save area to 16 byte boundary
|
||||||
|
movi \reg_B, ~(0xF)
|
||||||
|
and \reg_A, \reg_A, \reg_B /* Align CPSA pointer to 16 bytes */
|
||||||
|
.endm
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
@ -135,23 +160,19 @@ _frxt_int_enter:
|
|||||||
mull a2, a4, a2
|
mull a2, a4, a2
|
||||||
add a1, a1, a2 /* for current proc */
|
add a1, a1, a2 /* for current proc */
|
||||||
|
|
||||||
#ifdef CONFIG_FREERTOS_FPU_IN_ISR
|
#if CONFIG_FREERTOS_FPU_IN_ISR && XCHAL_CP_NUM > 0
|
||||||
#if XCHAL_CP_NUM > 0
|
|
||||||
rsr a3, CPENABLE /* Restore thread scope CPENABLE */
|
rsr a3, CPENABLE /* Restore thread scope CPENABLE */
|
||||||
addi sp, sp,-4 /* ISR will manage FPU coprocessor by forcing */
|
addi sp, sp,-4 /* ISR will manage FPU coprocessor by forcing */
|
||||||
s32i a3, a1, 0 /* its trigger */
|
s32i a3, a1, 0 /* its trigger */
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
.Lnested:
|
.Lnested:
|
||||||
1:
|
1:
|
||||||
#ifdef CONFIG_FREERTOS_FPU_IN_ISR
|
#if CONFIG_FREERTOS_FPU_IN_ISR && XCHAL_CP_NUM > 0
|
||||||
#if XCHAL_CP_NUM > 0
|
|
||||||
movi a3, 0 /* whilst ISRs pending keep CPENABLE exception active */
|
movi a3, 0 /* whilst ISRs pending keep CPENABLE exception active */
|
||||||
wsr a3, CPENABLE
|
wsr a3, CPENABLE
|
||||||
rsync
|
rsync
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
mov a0, a12 /* restore return addr and return */
|
mov a0, a12 /* restore return addr and return */
|
||||||
ret
|
ret
|
||||||
@ -189,14 +210,12 @@ _frxt_int_exit:
|
|||||||
s32i a2, a3, 0 /* save nesting count */
|
s32i a2, a3, 0 /* save nesting count */
|
||||||
bnez a2, .Lnesting /* !=0 after decr so still nested */
|
bnez a2, .Lnesting /* !=0 after decr so still nested */
|
||||||
|
|
||||||
#ifdef CONFIG_FREERTOS_FPU_IN_ISR
|
#if CONFIG_FREERTOS_FPU_IN_ISR && XCHAL_CP_NUM > 0
|
||||||
#if XCHAL_CP_NUM > 0
|
|
||||||
l32i a3, sp, 0 /* Grab last CPENABLE before leave ISR */
|
l32i a3, sp, 0 /* Grab last CPENABLE before leave ISR */
|
||||||
addi sp, sp, 4
|
addi sp, sp, 4
|
||||||
wsr a3, CPENABLE
|
wsr a3, CPENABLE
|
||||||
rsync /* ensure CPENABLE was modified */
|
rsync /* ensure CPENABLE was modified */
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
movi a2, pxCurrentTCBs
|
movi a2, pxCurrentTCBs
|
||||||
addx4 a2, a4, a2
|
addx4 a2, a4, a2
|
||||||
@ -474,11 +493,11 @@ _frxt_dispatch:
|
|||||||
|
|
||||||
#if XCHAL_CP_NUM > 0
|
#if XCHAL_CP_NUM > 0
|
||||||
/* Restore CPENABLE from task's co-processor save area. */
|
/* Restore CPENABLE from task's co-processor save area. */
|
||||||
movi a3, pxCurrentTCBs /* cp_state = */
|
movi a2, pxCurrentTCBs /* cp_state = */
|
||||||
getcoreid a2
|
getcoreid a3
|
||||||
addx4 a3, a2, a3
|
addx4 a2, a3, a2
|
||||||
l32i a3, a3, 0
|
l32i a2, a2, 0
|
||||||
l32i a2, a3, CP_TOPOFSTACK_OFFS /* StackType_t *pxStack; */
|
get_cpsa_from_tcb a2, a3 /* After this, pointer to CP save area is in a2, a3 is destroyed */
|
||||||
l16ui a3, a2, XT_CPENABLE /* CPENABLE = cp_state->cpenable; */
|
l16ui a3, a2, XT_CPENABLE /* CPENABLE = cp_state->cpenable; */
|
||||||
wsr a3, CPENABLE
|
wsr a3, CPENABLE
|
||||||
#endif
|
#endif
|
||||||
@ -573,7 +592,7 @@ vPortYield:
|
|||||||
|
|
||||||
#if XCHAL_CP_NUM > 0
|
#if XCHAL_CP_NUM > 0
|
||||||
/* Clear CPENABLE, also in task's co-processor state save area. */
|
/* Clear CPENABLE, also in task's co-processor state save area. */
|
||||||
l32i a2, a2, CP_TOPOFSTACK_OFFS /* a2 = pxCurrentTCBs->cp_state */
|
get_cpsa_from_tcb a2, a3 /* After this, pointer to CP save area is in a2, a3 is destroyed */
|
||||||
movi a3, 0
|
movi a3, 0
|
||||||
wsr a3, CPENABLE
|
wsr a3, CPENABLE
|
||||||
beqz a2, 1f
|
beqz a2, 1f
|
||||||
@ -614,12 +633,12 @@ vPortYieldFromInt:
|
|||||||
|
|
||||||
#if XCHAL_CP_NUM > 0
|
#if XCHAL_CP_NUM > 0
|
||||||
/* Save CPENABLE in task's co-processor save area, and clear CPENABLE. */
|
/* Save CPENABLE in task's co-processor save area, and clear CPENABLE. */
|
||||||
movi a3, pxCurrentTCBs /* cp_state = */
|
movi a2, pxCurrentTCBs /* cp_state = */
|
||||||
getcoreid a2
|
getcoreid a3
|
||||||
addx4 a3, a2, a3
|
addx4 a2, a3, a2
|
||||||
l32i a3, a3, 0
|
l32i a2, a2, 0
|
||||||
|
|
||||||
l32i a2, a3, CP_TOPOFSTACK_OFFS
|
get_cpsa_from_tcb a2, a3 /* After this, pointer to CP save area is in a2, a3 is destroyed */
|
||||||
|
|
||||||
rsr a3, CPENABLE
|
rsr a3, CPENABLE
|
||||||
s16i a3, a2, XT_CPENABLE /* cp_state->cpenable = CPENABLE; */
|
s16i a3, a2, XT_CPENABLE /* cp_state->cpenable = CPENABLE; */
|
||||||
@ -673,7 +692,7 @@ _frxt_task_coproc_state:
|
|||||||
l32i a15, a15, 0 /* && pxCurrentTCBs != 0) { */
|
l32i a15, a15, 0 /* && pxCurrentTCBs != 0) { */
|
||||||
|
|
||||||
beqz a15, 2f
|
beqz a15, 2f
|
||||||
l32i a15, a15, CP_TOPOFSTACK_OFFS
|
get_cpsa_from_tcb a15, a3 /* After this, pointer to CP save area is in a15, a3 is destroyed */
|
||||||
ret
|
ret
|
||||||
|
|
||||||
1: movi a15, 0
|
1: movi a15, 0
|
||||||
|
@ -107,8 +107,8 @@
|
|||||||
Define for workaround: pin no-cpu-affinity tasks to a cpu when fpu is used.
|
Define for workaround: pin no-cpu-affinity tasks to a cpu when fpu is used.
|
||||||
Please change this when the tcb structure is changed
|
Please change this when the tcb structure is changed
|
||||||
*/
|
*/
|
||||||
#define TASKTCB_XCOREID_OFFSET (0x38+configMAX_TASK_NAME_LEN+3)&~3
|
|
||||||
.extern pxCurrentTCBs
|
.extern pxCurrentTCBs
|
||||||
|
.extern offset_uxCoreAffinityMask
|
||||||
|
|
||||||
/*
|
/*
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
@ -908,35 +908,34 @@ _xt_coproc_exc:
|
|||||||
|
|
||||||
/* Get co-processor state save area of new owner thread. */
|
/* Get co-processor state save area of new owner thread. */
|
||||||
call0 XT_RTOS_CP_STATE /* a15 = new owner's save area */
|
call0 XT_RTOS_CP_STATE /* a15 = new owner's save area */
|
||||||
|
#if CONFIG_FREERTOS_FPU_IN_ISR
|
||||||
#ifndef CONFIG_FREERTOS_FPU_IN_ISR
|
beqz a15, .L_skip_core_pin /* CP used in ISR, skip task pinning */
|
||||||
beqz a15, .L_goto_invalid
|
#else
|
||||||
|
beqz a15, .L_goto_invalid /* not in a thread (invalid) */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*When FPU in ISR is enabled we could deal with zeroed a15 */
|
/* CP operations are incompatible with unpinned tasks. Thus we pin the task
|
||||||
|
to the current running core. */
|
||||||
|
movi a2, pxCurrentTCBs
|
||||||
|
getcoreid a3 /* a3 = current core ID */
|
||||||
|
addx4 a2, a3, a2
|
||||||
|
l32i a2, a2, 0 /* a2 = start of pxCurrentTCBs[cpuid] */
|
||||||
|
movi a4, offset_uxCoreAffinityMask
|
||||||
|
l32i a4, a4, 0 /* a4 = offset_uxCoreAffinityMask */
|
||||||
|
add a2, a2, a4 /* a2 = &TCB.uxCoreAffinityMask */
|
||||||
|
ssl a3 /* Use core ID as shift amount */
|
||||||
|
movi a4, 1
|
||||||
|
sll a4, a4 /* a4 = uxCoreAffinityMask = (1 << core ID) */
|
||||||
|
s32i a4, a2, 0 /* Store affinity mask to TCB.uxCoreAffinityMask */
|
||||||
|
#if CONFIG_FREERTOS_FPU_IN_ISR
|
||||||
|
.L_skip_core_pin:
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Enable the co-processor's bit in CPENABLE. */
|
/* Enable the co-processor's bit in CPENABLE. */
|
||||||
movi a0, _xt_coproc_mask
|
movi a0, _xt_coproc_mask
|
||||||
rsr a4, CPENABLE /* a4 = CPENABLE */
|
rsr a4, CPENABLE /* a4 = CPENABLE */
|
||||||
addx4 a0, a5, a0 /* a0 = &_xt_coproc_mask[n] */
|
addx4 a0, a5, a0 /* a0 = &_xt_coproc_mask[n] */
|
||||||
l32i a0, a0, 0 /* a0 = (n << 16) | (1 << n) */
|
l32i a0, a0, 0 /* a0 = (n << 16) | (1 << n) */
|
||||||
|
|
||||||
/* FPU operations are incompatible with non-pinned tasks. If we have a FPU operation
|
|
||||||
here, to keep the entire thing from crashing, it's better to pin the task to whatever
|
|
||||||
core we're running on now. */
|
|
||||||
movi a2, pxCurrentTCBs
|
|
||||||
getcoreid a3
|
|
||||||
addx4 a2, a3, a2
|
|
||||||
l32i a2, a2, 0 /* a2 = start of pxCurrentTCBs[cpuid] */
|
|
||||||
addi a2, a2, TASKTCB_XCOREID_OFFSET /* offset to xCoreID in tcb struct */
|
|
||||||
s32i a3, a2, 0 /* store current cpuid */
|
|
||||||
|
|
||||||
/* Grab correct xt_coproc_owner_sa for this core */
|
|
||||||
movi a2, XCHAL_CP_MAX << 2
|
|
||||||
mull a2, a2, a3 /* multiply by current processor id */
|
|
||||||
movi a3, _xt_coproc_owner_sa /* a3 = base of owner array */
|
|
||||||
add a3, a3, a2 /* a3 = owner area needed for this processor */
|
|
||||||
|
|
||||||
extui a2, a0, 0, 16 /* coprocessor bitmask portion */
|
extui a2, a0, 0, 16 /* coprocessor bitmask portion */
|
||||||
or a4, a4, a2 /* a4 = CPENABLE | (1 << n) */
|
or a4, a4, a2 /* a4 = CPENABLE | (1 << n) */
|
||||||
wsr a4, CPENABLE
|
wsr a4, CPENABLE
|
||||||
@ -946,7 +945,12 @@ Keep loading _xt_coproc_owner_sa[n] atomic (=load once, then use that value
|
|||||||
everywhere): _xt_coproc_release assumes it works like this in order not to need
|
everywhere): _xt_coproc_release assumes it works like this in order not to need
|
||||||
locking.
|
locking.
|
||||||
*/
|
*/
|
||||||
|
/* Grab correct xt_coproc_owner_sa for this core */
|
||||||
|
getcoreid a3 /* a3 = current core ID */
|
||||||
|
movi a2, XCHAL_CP_MAX << 2
|
||||||
|
mull a2, a2, a3 /* multiply by current processor id */
|
||||||
|
movi a3, _xt_coproc_owner_sa /* a3 = base of owner array */
|
||||||
|
add a3, a3, a2 /* a3 = owner area needed for this processor */
|
||||||
|
|
||||||
/* Get old coprocessor owner thread (save area ptr) and assign new one. */
|
/* Get old coprocessor owner thread (save area ptr) and assign new one. */
|
||||||
addx4 a3, a5, a3 /* a3 = &_xt_coproc_owner_sa[n] */
|
addx4 a3, a5, a3 /* a3 = &_xt_coproc_owner_sa[n] */
|
||||||
|
@ -2835,13 +2835,6 @@ static BaseType_t prvCreateIdleTasks( void )
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
#if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 )
|
|
||||||
//Don't forget to pin the created IDLE tasks
|
|
||||||
vTaskCoreAffinitySet(xIdleTaskHandle[ xCoreID ], (1 << xCoreID) );
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
|
131
components/freertos/test/test_coproc.c
Normal file
131
components/freertos/test/test_coproc.c
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
|
|
||||||
|
#if CONFIG_FREERTOS_SMP && SOC_CPU_HAS_FPU
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "xtensa/xtensa_api.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "test_utils.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Note: We need to declare the float here to prevent compiler optimizing float
|
||||||
|
operations into non-float instructions.
|
||||||
|
*/
|
||||||
|
static volatile float test_float;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test coprocessor (CP) usage in task
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
- Test that CP can be used in a task (e.g., the FPU)
|
||||||
|
- Test that unpinned tasks are pinned when the CP is used
|
||||||
|
- Test that CP is properly saved in restored
|
||||||
|
- Test that CP context is properly cleaned up when task is deleted
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define COPROC_TASK_TEST_ITER 10
|
||||||
|
|
||||||
|
static void unpinned_task(void *arg)
|
||||||
|
{
|
||||||
|
// Test that task gets pinned to the current core when it uses the coprocessor
|
||||||
|
vTaskPreemptionDisable(NULL); // Disable preemption to make current core ID doesn't change
|
||||||
|
BaseType_t xCoreID = xPortGetCoreID();
|
||||||
|
TEST_ASSERT_EQUAL(tskNO_AFFINITY, vTaskCoreAffinityGet(NULL));
|
||||||
|
test_float = 1.1f;
|
||||||
|
test_float *= 2.0f;
|
||||||
|
TEST_ASSERT_EQUAL(2.2f, test_float);
|
||||||
|
TEST_ASSERT_EQUAL(1 << xCoreID, vTaskCoreAffinityGet(NULL));
|
||||||
|
vTaskPreemptionEnable(NULL);
|
||||||
|
|
||||||
|
// Delay to trigger a solicited context switch
|
||||||
|
vTaskDelay(1);
|
||||||
|
// Test that CP context was saved and restored properly
|
||||||
|
test_float *= 2.0f;
|
||||||
|
TEST_ASSERT_EQUAL(4.4f, test_float);
|
||||||
|
|
||||||
|
// Wait to be deleted
|
||||||
|
xTaskNotifyGive((TaskHandle_t)arg);
|
||||||
|
vTaskSuspend(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Test coproc usage in task", "[freertos]")
|
||||||
|
{
|
||||||
|
TaskHandle_t unity_task_handle = xTaskGetCurrentTaskHandle();
|
||||||
|
for (int i = 0; i < COPROC_TASK_TEST_ITER; i++) {
|
||||||
|
TaskHandle_t unpinned_task_handle;
|
||||||
|
xTaskCreate(unpinned_task, "unpin", 2048, (void *)unity_task_handle, UNITY_FREERTOS_PRIORITY + 1, &unpinned_task_handle);
|
||||||
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
vTaskDelete(unpinned_task_handle);
|
||||||
|
vTaskDelay(10); // Short delay to allow task memory to be freed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_FREERTOS_FPU_IN_ISR
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test coprocessor (CP) usage in ISR
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
- Test that CP can be used in an ISR
|
||||||
|
- Test that an interrupted unpinned task will not be pinned by the ISR using the CP
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SW_ISR_LEVEL_1 7
|
||||||
|
|
||||||
|
static void software_isr(void *arg)
|
||||||
|
{
|
||||||
|
(void) arg;
|
||||||
|
xt_set_intclear(1 << SW_ISR_LEVEL_1);
|
||||||
|
test_float *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unpinned_task_isr(void *arg)
|
||||||
|
{
|
||||||
|
vTaskPreemptionDisable(NULL); // Disable preemption to make current core ID doesn't change
|
||||||
|
TEST_ASSERT_EQUAL(tskNO_AFFINITY, vTaskCoreAffinityGet(NULL));
|
||||||
|
// Allocate ISR on the current core
|
||||||
|
intr_handle_t handle;
|
||||||
|
esp_err_t err = esp_intr_alloc(ETS_INTERNAL_SW0_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1, &software_isr, NULL, &handle);
|
||||||
|
TEST_ASSERT_EQUAL_HEX32(ESP_OK, err);
|
||||||
|
// Trigger the ISR
|
||||||
|
xt_set_intset(1 << SW_ISR_LEVEL_1);
|
||||||
|
// Test that task affinity hasn't changed
|
||||||
|
TEST_ASSERT_EQUAL(tskNO_AFFINITY, vTaskCoreAffinityGet(NULL));
|
||||||
|
// Free the ISR
|
||||||
|
esp_intr_free(handle);
|
||||||
|
// Wait to be deleted
|
||||||
|
vTaskPreemptionEnable(NULL);
|
||||||
|
xTaskNotifyGive((TaskHandle_t)arg);
|
||||||
|
vTaskSuspend(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Test coproc usage in ISR", "[freertos]")
|
||||||
|
{
|
||||||
|
TaskHandle_t unity_task_handle = xTaskGetCurrentTaskHandle();
|
||||||
|
for (int i = 0; i < COPROC_TASK_TEST_ITER; i++) {
|
||||||
|
// Initialize the test float
|
||||||
|
test_float = 1.1f;
|
||||||
|
// Create an unpinned task to trigger the ISR
|
||||||
|
TaskHandle_t unpinned_task_handle;
|
||||||
|
xTaskCreate(unpinned_task_isr, "unpin", 2048, (void *)unity_task_handle, UNITY_FREERTOS_PRIORITY + 1, &unpinned_task_handle);
|
||||||
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
// Check that the test float value
|
||||||
|
TEST_ASSERT_EQUAL(2.2f, test_float);
|
||||||
|
// Delete the unpinned task. Short delay to allow task memory to be freed
|
||||||
|
vTaskDelete(unpinned_task_handle);
|
||||||
|
vTaskDelay(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_FREERTOS_FPU_IN_ISR
|
||||||
|
|
||||||
|
#endif // CONFIG_FREERTOS_SMP && SOC_CPU_HAS_FPU
|
Loading…
x
Reference in New Issue
Block a user