mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-04 13:14:32 +02:00
feat(freertos): base support on p4
This commit is contained in:
committed by
Armando (Dou Yiwen)
parent
e11b154c99
commit
48ee1ba36e
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*
|
*
|
||||||
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeRTOS Kernel V10.4.3
|
* FreeRTOS Kernel V10.4.3
|
||||||
@@ -160,6 +160,8 @@ BaseType_t xPortInterruptedFromISRContext(void);
|
|||||||
* @note [refactor-todo] Refactor critical section API so that this is no longer required
|
* @note [refactor-todo] Refactor critical section API so that this is no longer required
|
||||||
* ------------------------------------------------------ */
|
* ------------------------------------------------------ */
|
||||||
|
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
/**
|
/**
|
||||||
* @brief Spinlock object
|
* @brief Spinlock object
|
||||||
* Owner:
|
* Owner:
|
||||||
@@ -178,6 +180,11 @@ typedef struct {
|
|||||||
uint32_t owner;
|
uint32_t owner;
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
} portMUX_TYPE;
|
} portMUX_TYPE;
|
||||||
|
|
||||||
|
#else
|
||||||
|
typedef spinlock_t portMUX_TYPE; /**< Spinlock type used by FreeRTOS critical sections */
|
||||||
|
#endif
|
||||||
|
|
||||||
/**< Spinlock initializer */
|
/**< Spinlock initializer */
|
||||||
#define portMUX_INITIALIZER_UNLOCKED { \
|
#define portMUX_INITIALIZER_UNLOCKED { \
|
||||||
.owner = portMUX_FREE_VAL, \
|
.owner = portMUX_FREE_VAL, \
|
||||||
@@ -199,7 +206,12 @@ typedef struct {
|
|||||||
* - Simply disable interrupts
|
* - Simply disable interrupts
|
||||||
* - Can be nested
|
* - Can be nested
|
||||||
*/
|
*/
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
void vPortEnterCritical(void);
|
void vPortEnterCritical(void);
|
||||||
|
#else
|
||||||
|
void vPortEnterCritical(portMUX_TYPE *mux);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Exit a critical section
|
* @brief Exit a critical section
|
||||||
@@ -207,7 +219,12 @@ void vPortEnterCritical(void);
|
|||||||
* - Reenables interrupts
|
* - Reenables interrupts
|
||||||
* - Can be nested
|
* - Can be nested
|
||||||
*/
|
*/
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
void vPortExitCritical(void);
|
void vPortExitCritical(void);
|
||||||
|
#else
|
||||||
|
void vPortExitCritical(portMUX_TYPE *mux);
|
||||||
|
#endif
|
||||||
|
|
||||||
// ---------------------- Yielding -------------------------
|
// ---------------------- Yielding -------------------------
|
||||||
|
|
||||||
@@ -320,6 +337,8 @@ FORCE_INLINE_ATTR BaseType_t xPortGetCoreID(void)
|
|||||||
|
|
||||||
// ------------------ Critical Sections --------------------
|
// ------------------ Critical Sections --------------------
|
||||||
|
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
#define portENTER_CRITICAL(mux) {(void)mux; vPortEnterCritical();}
|
#define portENTER_CRITICAL(mux) {(void)mux; vPortEnterCritical();}
|
||||||
#define portEXIT_CRITICAL(mux) {(void)mux; vPortExitCritical();}
|
#define portEXIT_CRITICAL(mux) {(void)mux; vPortExitCritical();}
|
||||||
#define portTRY_ENTER_CRITICAL(mux, timeout) ({ \
|
#define portTRY_ENTER_CRITICAL(mux, timeout) ({ \
|
||||||
@@ -328,6 +347,17 @@ FORCE_INLINE_ATTR BaseType_t xPortGetCoreID(void)
|
|||||||
BaseType_t ret = pdPASS; \
|
BaseType_t ret = pdPASS; \
|
||||||
ret; \
|
ret; \
|
||||||
})
|
})
|
||||||
|
#else
|
||||||
|
#define portENTER_CRITICAL(mux) {vPortEnterCritical(mux);}
|
||||||
|
#define portEXIT_CRITICAL(mux) {vPortExitCritical(mux);}
|
||||||
|
#define portTRY_ENTER_CRITICAL(mux, timeout) ({ \
|
||||||
|
(void)timeout; \
|
||||||
|
vPortEnterCritical(mux); \
|
||||||
|
BaseType_t ret = pdPASS; \
|
||||||
|
ret; \
|
||||||
|
})
|
||||||
|
#endif
|
||||||
|
|
||||||
//In single-core RISC-V, we can use the same critical section API
|
//In single-core RISC-V, we can use the same critical section API
|
||||||
#define portENTER_CRITICAL_ISR(mux) portENTER_CRITICAL(mux)
|
#define portENTER_CRITICAL_ISR(mux) portENTER_CRITICAL(mux)
|
||||||
#define portEXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL(mux)
|
#define portEXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL(mux)
|
||||||
@@ -350,6 +380,10 @@ FORCE_INLINE_ATTR BaseType_t xPortGetCoreID(void)
|
|||||||
})
|
})
|
||||||
#define portTRY_ENTER_CRITICAL_SAFE(mux, timeout) portENTER_CRITICAL_SAFE(mux, timeout)
|
#define portTRY_ENTER_CRITICAL_SAFE(mux, timeout) portENTER_CRITICAL_SAFE(mux, timeout)
|
||||||
|
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32P4
|
||||||
|
#define portCHECK_IF_IN_ISR() xPortInIsrContext()
|
||||||
|
#endif
|
||||||
// ---------------------- Yielding -------------------------
|
// ---------------------- Yielding -------------------------
|
||||||
|
|
||||||
#define portYIELD() vPortYield()
|
#define portYIELD() vPortYield()
|
||||||
@@ -428,7 +462,13 @@ extern void vPortCleanUpTCB ( void *pxTCB );
|
|||||||
|
|
||||||
FORCE_INLINE_ATTR bool xPortCanYield(void)
|
FORCE_INLINE_ATTR bool xPortCanYield(void)
|
||||||
{
|
{
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#if SOC_INT_CLIC_SUPPORTED
|
||||||
|
uint32_t threshold = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG + 0x10000 * xPortGetCoreID());
|
||||||
|
threshold = threshold >> (24 + (8 - NLBITS));
|
||||||
|
#else
|
||||||
uint32_t threshold = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG);
|
uint32_t threshold = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG);
|
||||||
|
#endif
|
||||||
/* when enter critical code, FreeRTOS will mask threshold to RVHAL_EXCM_LEVEL
|
/* when enter critical code, FreeRTOS will mask threshold to RVHAL_EXCM_LEVEL
|
||||||
* and exit critical code, will recover threshold value (1). so threshold <= 1
|
* and exit critical code, will recover threshold value (1). so threshold <= 1
|
||||||
* means not in critical code
|
* means not in critical code
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*
|
*
|
||||||
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeRTOS Kernel V10.4.3
|
* FreeRTOS Kernel V10.4.3
|
||||||
@@ -56,6 +56,10 @@
|
|||||||
#include "portmacro.h"
|
#include "portmacro.h"
|
||||||
#include "port_systick.h"
|
#include "port_systick.h"
|
||||||
#include "esp_memory_utils.h"
|
#include "esp_memory_utils.h"
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32P4
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#include "soc/hp_system_reg.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
_Static_assert(portBYTE_ALIGNMENT == 16, "portBYTE_ALIGNMENT must be set to 16");
|
_Static_assert(portBYTE_ALIGNMENT == 16, "portBYTE_ALIGNMENT must be set to 16");
|
||||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||||
@@ -74,6 +78,8 @@ _Static_assert(offsetof( StaticTask_t, pxDummy8 ) == PORT_OFFSET_PX_END_OF_STACK
|
|||||||
*
|
*
|
||||||
* ------------------------------------------------------------------------------------------------------------------ */
|
* ------------------------------------------------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
/**
|
/**
|
||||||
* @brief A variable is used to keep track of the critical section nesting.
|
* @brief A variable is used to keep track of the critical section nesting.
|
||||||
* @note This variable has to be stored as part of the task context and must be initialized to a non zero value
|
* @note This variable has to be stored as part of the task context and must be initialized to a non zero value
|
||||||
@@ -88,6 +94,25 @@ BaseType_t xPortSwitchFlag = 0;
|
|||||||
__attribute__((aligned(16))) StackType_t xIsrStack[configISR_STACK_SIZE];
|
__attribute__((aligned(16))) StackType_t xIsrStack[configISR_STACK_SIZE];
|
||||||
StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK)));
|
StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK)));
|
||||||
|
|
||||||
|
#else
|
||||||
|
/* uxCriticalNesting will be increased by 1 each time one processor is entering a critical section
|
||||||
|
* and will be decreased by 1 each time one processor is exiting a critical section
|
||||||
|
*/
|
||||||
|
volatile UBaseType_t uxCriticalNesting[portNUM_PROCESSORS] = {0};
|
||||||
|
volatile UBaseType_t uxSavedInterruptState[portNUM_PROCESSORS] = {0};
|
||||||
|
volatile BaseType_t uxSchedulerRunning[portNUM_PROCESSORS] = {0};
|
||||||
|
volatile UBaseType_t uxInterruptNesting[portNUM_PROCESSORS] = {0};
|
||||||
|
volatile BaseType_t xPortSwitchFlag[portNUM_PROCESSORS] = {0};
|
||||||
|
/* core0 interrupt stack space */
|
||||||
|
__attribute__((aligned(16))) static StackType_t xIsrStack[configISR_STACK_SIZE];
|
||||||
|
/* core1 interrupt stack space */
|
||||||
|
__attribute__((aligned(16))) static StackType_t xIsrStack1[configISR_STACK_SIZE];
|
||||||
|
/* core0 interrupt stack top, passed to sp */
|
||||||
|
StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK)));
|
||||||
|
/* core1 interrupt stack top, passed to sp */
|
||||||
|
StackType_t *xIsrStackTop1 = &xIsrStack1[0] + (configISR_STACK_SIZE & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK)));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------ FreeRTOS Portable --------------------------------------------------
|
/* ------------------------------------------------ FreeRTOS Portable --------------------------------------------------
|
||||||
@@ -97,11 +122,19 @@ StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOIN
|
|||||||
|
|
||||||
// ----------------- Scheduler Start/End -------------------
|
// ----------------- Scheduler Start/End -------------------
|
||||||
|
|
||||||
|
//TODO: IDF-7566
|
||||||
BaseType_t xPortStartScheduler(void)
|
BaseType_t xPortStartScheduler(void)
|
||||||
{
|
{
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
uxInterruptNesting = 0;
|
uxInterruptNesting = 0;
|
||||||
uxCriticalNesting = 0;
|
uxCriticalNesting = 0;
|
||||||
uxSchedulerRunning = 0;
|
uxSchedulerRunning = 0;
|
||||||
|
#else
|
||||||
|
BaseType_t coreID = xPortGetCoreID();
|
||||||
|
uxInterruptNesting[coreID] = 0;
|
||||||
|
uxCriticalNesting[coreID] = 0;
|
||||||
|
uxSchedulerRunning[coreID] = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Setup the hardware to generate the tick. */
|
/* Setup the hardware to generate the tick. */
|
||||||
vPortSetupTimer();
|
vPortSetupTimer();
|
||||||
@@ -312,15 +345,26 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC
|
|||||||
|
|
||||||
// --------------------- Interrupts ------------------------
|
// --------------------- Interrupts ------------------------
|
||||||
|
|
||||||
|
//TODO: IDF-7566
|
||||||
BaseType_t xPortInIsrContext(void)
|
BaseType_t xPortInIsrContext(void)
|
||||||
{
|
{
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
return uxInterruptNesting;
|
return uxInterruptNesting;
|
||||||
|
#else
|
||||||
|
BaseType_t coreID = xPortGetCoreID();
|
||||||
|
return uxInterruptNesting[coreID];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void)
|
BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void)
|
||||||
{
|
{
|
||||||
/* For single core, this can be the same as xPortInIsrContext() because reading it is atomic */
|
/* For single core, this can be the same as xPortInIsrContext() because reading it is atomic */
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
return uxInterruptNesting;
|
return uxInterruptNesting;
|
||||||
|
#else
|
||||||
|
BaseType_t coreID = xPortGetCoreID();
|
||||||
|
return uxInterruptNesting[coreID];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------- Spinlocks ------------------------
|
// ---------------------- Spinlocks ------------------------
|
||||||
@@ -329,6 +373,8 @@ BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void)
|
|||||||
|
|
||||||
// ------------------ Critical Sections --------------------
|
// ------------------ Critical Sections --------------------
|
||||||
|
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
void vPortEnterCritical(void)
|
void vPortEnterCritical(void)
|
||||||
{
|
{
|
||||||
BaseType_t state = portSET_INTERRUPT_MASK_FROM_ISR();
|
BaseType_t state = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
@@ -349,15 +395,52 @@ void vPortExitCritical(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
void vPortEnterCritical(portMUX_TYPE *mux)
|
||||||
|
{
|
||||||
|
BaseType_t coreID = xPortGetCoreID();
|
||||||
|
BaseType_t state = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
|
||||||
|
spinlock_acquire((spinlock_t *)mux, SPINLOCK_WAIT_FOREVER);
|
||||||
|
uxCriticalNesting[coreID]++;
|
||||||
|
|
||||||
|
if (uxCriticalNesting[coreID] == 1) {
|
||||||
|
uxSavedInterruptState[coreID] = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vPortExitCritical(portMUX_TYPE *mux)
|
||||||
|
{
|
||||||
|
spinlock_release((spinlock_t *)mux);
|
||||||
|
|
||||||
|
BaseType_t coreID = xPortGetCoreID();
|
||||||
|
if (uxCriticalNesting[coreID] > 0) {
|
||||||
|
uxCriticalNesting[coreID]--;
|
||||||
|
if (uxCriticalNesting[coreID] == 0) {
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptState[coreID]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// ---------------------- Yielding -------------------------
|
// ---------------------- Yielding -------------------------
|
||||||
|
|
||||||
|
//TODO: IDF-7566
|
||||||
int vPortSetInterruptMask(void)
|
int vPortSetInterruptMask(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||||
ret = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG);
|
ret = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG);
|
||||||
|
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, RVHAL_EXCM_LEVEL);
|
REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, RVHAL_EXCM_LEVEL);
|
||||||
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
||||||
|
#else
|
||||||
|
#define RVHAL_EXCM_THRESHOLD_VALUE (((RVHAL_EXCM_LEVEL << (8 - NLBITS)) | 0x1f) << CLIC_CPU_INT_THRESH_S)
|
||||||
|
|
||||||
|
REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, RVHAL_EXCM_THRESHOLD_VALUE);
|
||||||
|
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* In theory, this function should not return immediately as there is a
|
* In theory, this function should not return immediately as there is a
|
||||||
* delay between the moment we mask the interrupt threshold register and
|
* delay between the moment we mask the interrupt threshold register and
|
||||||
@@ -395,6 +478,8 @@ void vPortClearInterruptMask(int mask)
|
|||||||
asm volatile ( "nop" );
|
asm volatile ( "nop" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
void vPortYield(void)
|
void vPortYield(void)
|
||||||
{
|
{
|
||||||
if (uxInterruptNesting) {
|
if (uxInterruptNesting) {
|
||||||
@@ -423,6 +508,37 @@ void vPortYieldFromISR( void )
|
|||||||
xPortSwitchFlag = 1;
|
xPortSwitchFlag = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
void vPortYield(void)
|
||||||
|
{
|
||||||
|
BaseType_t coreID = xPortGetCoreID();
|
||||||
|
if (uxInterruptNesting[coreID]) {
|
||||||
|
vPortYieldFromISR();
|
||||||
|
} else {
|
||||||
|
esp_crosscore_int_send_yield(coreID);
|
||||||
|
/* There are 3-4 instructions of latency between triggering the software
|
||||||
|
interrupt and the CPU interrupt happening. Make sure it happened before
|
||||||
|
we return, otherwise vTaskDelay() may return and execute 1-2
|
||||||
|
instructions before the delay actually happens.
|
||||||
|
|
||||||
|
(We could use the WFI instruction here, but there is a chance that
|
||||||
|
the interrupt will happen while evaluating the other two conditions
|
||||||
|
for an instant yield, and if that happens then the WFI would be
|
||||||
|
waiting for the next interrupt to occur...)
|
||||||
|
*/
|
||||||
|
while (uxSchedulerRunning[coreID] && uxCriticalNesting[coreID] == 0 && REG_READ(HP_SYSTEM_CPU_INT_FROM_CPU_0_REG + 4*coreID) != 0) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vPortYieldFromISR( void )
|
||||||
|
{
|
||||||
|
traceISR_EXIT_TO_SCHEDULER();
|
||||||
|
BaseType_t coreID = xPortGetCoreID();
|
||||||
|
uxSchedulerRunning[coreID] = 1;
|
||||||
|
xPortSwitchFlag[coreID] = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void vPortYieldOtherCore(BaseType_t coreid)
|
void vPortYieldOtherCore(BaseType_t coreid)
|
||||||
{
|
{
|
||||||
esp_crosscore_int_send_yield(coreid);
|
esp_crosscore_int_send_yield(coreid);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -12,6 +12,10 @@
|
|||||||
.global uxInterruptNesting
|
.global uxInterruptNesting
|
||||||
.global uxSchedulerRunning
|
.global uxSchedulerRunning
|
||||||
.global xIsrStackTop
|
.global xIsrStackTop
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32P4
|
||||||
|
//TODO: IDF-7566
|
||||||
|
.global xIsrStackTop1
|
||||||
|
#endif
|
||||||
.global pxCurrentTCB
|
.global pxCurrentTCB
|
||||||
.global vTaskSwitchContext
|
.global vTaskSwitchContext
|
||||||
.global xPortSwitchFlag
|
.global xPortSwitchFlag
|
||||||
@@ -35,18 +39,40 @@
|
|||||||
.global rtos_int_enter
|
.global rtos_int_enter
|
||||||
.type rtos_int_enter, @function
|
.type rtos_int_enter, @function
|
||||||
rtos_int_enter:
|
rtos_int_enter:
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32P4
|
||||||
|
/* needs jira for p4 */
|
||||||
|
/* preserve the return address */
|
||||||
|
mv t1, ra
|
||||||
|
mv t2, a0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
/* scheduler not enabled, jump directly to ISR handler */
|
/* scheduler not enabled, jump directly to ISR handler */
|
||||||
lw t0, uxSchedulerRunning
|
lw t0, uxSchedulerRunning
|
||||||
beq t0,zero, rtos_enter_end
|
beq t0,zero, rtos_enter_end
|
||||||
|
#else
|
||||||
|
/* scheduler not enabled, jump directly to ISR handler */
|
||||||
|
csrr t6, mhartid /* t6 = coreID */
|
||||||
|
slli t6, t6, 2 /* t6 = coreID * 4 */
|
||||||
|
la t0, uxSchedulerRunning /* t0 = &uxSchedulerRunning */
|
||||||
|
add t0, t0, t6 /* t0 = &uxSchedulerRunning[coreID] */
|
||||||
|
lw t0, (t0) /* t0 = uxSchedulerRunning[coreID] */
|
||||||
|
beq t0,zero, rtos_enter_end
|
||||||
|
#endif
|
||||||
|
|
||||||
/* increments the ISR nesting count */
|
/* increments the ISR nesting count */
|
||||||
la t3, uxInterruptNesting
|
la t3, uxInterruptNesting
|
||||||
lw t4, 0x0(t3)
|
#if CONFIG_IDF_TARGET_ESP32P4
|
||||||
addi t5,t4,1
|
//TODO: IDF-7566
|
||||||
sw t5, 0x0(t3)
|
add t3, t3, t6
|
||||||
|
#endif
|
||||||
|
lw t4, 0x0(t3)
|
||||||
|
addi t5,t4,1
|
||||||
|
sw t5, 0x0(t3)
|
||||||
|
|
||||||
/* If reached here from another low-prio ISR, skip stack pushing to TCB */
|
/* If reached here from another low-prio ISR, skip stack pushing to TCB */
|
||||||
bne t4,zero, rtos_enter_end
|
bne t4,zero, rtos_enter_end
|
||||||
|
|
||||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||||
/* esp_hw_stack_guard_monitor_stop(); */
|
/* esp_hw_stack_guard_monitor_stop(); */
|
||||||
@@ -54,9 +80,21 @@ rtos_int_enter:
|
|||||||
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
|
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
|
||||||
|
|
||||||
/* Save current TCB and load the ISR stack */
|
/* Save current TCB and load the ISR stack */
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
lw t0, pxCurrentTCB
|
lw t0, pxCurrentTCB
|
||||||
sw sp, 0x0(t0)
|
sw sp, 0x0(t0)
|
||||||
lw sp, xIsrStackTop
|
lw sp, xIsrStackTop
|
||||||
|
#else
|
||||||
|
la t0, pxCurrentTCB /* t0 = &pxCurrentTCB */
|
||||||
|
add t0, t0, t6 /* t0 = &pxCurrentTCB[coreID] */
|
||||||
|
lw t0, (t0) /* t0 = pxCurrentTCB[coreID] */
|
||||||
|
sw t2, 0x0(t0)
|
||||||
|
lw sp, xIsrStackTop
|
||||||
|
csrr t6, mhartid
|
||||||
|
beq t6, zero, rtos_enter_end
|
||||||
|
lw sp, xIsrStackTop1
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||||
/* esp_hw_stack_guard_set_bounds(xIsrStack, xIsrStackTop); */
|
/* esp_hw_stack_guard_set_bounds(xIsrStack, xIsrStackTop); */
|
||||||
@@ -67,6 +105,10 @@ rtos_int_enter:
|
|||||||
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
|
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
|
||||||
|
|
||||||
rtos_enter_end:
|
rtos_enter_end:
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32P4
|
||||||
|
/* needs jira for p4 */
|
||||||
|
mv ra, t1
|
||||||
|
#endif
|
||||||
ret
|
ret
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,11 +118,25 @@ rtos_enter_end:
|
|||||||
.type rtos_int_exit, @function
|
.type rtos_int_exit, @function
|
||||||
rtos_int_exit:
|
rtos_int_exit:
|
||||||
/* may skip RTOS aware interrupt since scheduler was not started */
|
/* may skip RTOS aware interrupt since scheduler was not started */
|
||||||
|
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
lw t0, uxSchedulerRunning
|
lw t0, uxSchedulerRunning
|
||||||
|
#else
|
||||||
|
csrr t1, mhartid
|
||||||
|
slli t1, t1, 2
|
||||||
|
la t0, uxSchedulerRunning /* t0 = &uxSchedulerRunning */
|
||||||
|
add t0, t0, t1 /* t0 = &uxSchedulerRunning[coreID] */
|
||||||
|
lw t0, (t0)
|
||||||
|
#endif
|
||||||
beq t0,zero, rtos_exit_end
|
beq t0,zero, rtos_exit_end
|
||||||
|
|
||||||
/* update nesting interrupts counter */
|
/* update nesting interrupts counter */
|
||||||
la t2, uxInterruptNesting
|
la t2, uxInterruptNesting
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32P4
|
||||||
|
//TODO: IDF-7566
|
||||||
|
add t2, t2, t1
|
||||||
|
#endif
|
||||||
lw t3, 0x0(t2)
|
lw t3, 0x0(t2)
|
||||||
|
|
||||||
/* Already zero, protect against underflow */
|
/* Already zero, protect against underflow */
|
||||||
@@ -95,6 +151,10 @@ isr_skip_decrement:
|
|||||||
|
|
||||||
/* Schedule the next task if a yield is pending */
|
/* Schedule the next task if a yield is pending */
|
||||||
la t0, xPortSwitchFlag
|
la t0, xPortSwitchFlag
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32P4
|
||||||
|
//TODO: IDF-7566
|
||||||
|
add t0, t0, t1
|
||||||
|
#endif
|
||||||
lw t2, 0x0(t0)
|
lw t2, 0x0(t0)
|
||||||
beq t2, zero, no_switch
|
beq t2, zero, no_switch
|
||||||
|
|
||||||
@@ -108,11 +168,19 @@ isr_skip_decrement:
|
|||||||
|
|
||||||
/* Clears the switch pending flag */
|
/* Clears the switch pending flag */
|
||||||
la t0, xPortSwitchFlag
|
la t0, xPortSwitchFlag
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32P4
|
||||||
|
//TODO: IDF-7566
|
||||||
|
/* c routine vTaskSwitchContext may change the temp registers, so we read again */
|
||||||
|
csrr t3, mhartid
|
||||||
|
slli t3, t3, 2
|
||||||
|
add t0, t0, t3
|
||||||
|
#endif
|
||||||
mv t2, zero
|
mv t2, zero
|
||||||
sw t2, 0x0(t0)
|
sw t2, 0x0(t0)
|
||||||
|
|
||||||
no_switch:
|
no_switch:
|
||||||
|
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4 //TODO: IDF-7566
|
||||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||||
/* esp_hw_stack_guard_monitor_stop(); */
|
/* esp_hw_stack_guard_monitor_stop(); */
|
||||||
ESP_HW_STACK_GUARD_MONITOR_STOP_CPU0
|
ESP_HW_STACK_GUARD_MONITOR_STOP_CPU0
|
||||||
@@ -133,5 +201,16 @@ no_switch:
|
|||||||
ESP_HW_STACK_GUARD_MONITOR_START_CPU0
|
ESP_HW_STACK_GUARD_MONITOR_START_CPU0
|
||||||
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
|
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
|
||||||
|
|
||||||
|
#else
|
||||||
|
/* Recover the stack of next task and prepare to exit : */
|
||||||
|
la a0, pxCurrentTCB
|
||||||
|
/* We may come here from a branch, so we re-cal here */
|
||||||
|
csrr t3, mhartid
|
||||||
|
slli t3, t3, 2
|
||||||
|
add a0, a0, t3 /* a0 = &pxCurrentTCB[coreID] */
|
||||||
|
lw a0, (a0) /* a0 = pxCurrentTCB[coreID] */
|
||||||
|
lw a0, 0x0(a0) /* a0 = previous sp */
|
||||||
|
#endif //#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
|
|
||||||
rtos_exit_end:
|
rtos_exit_end:
|
||||||
ret
|
ret
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*
|
*
|
||||||
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -185,6 +185,8 @@
|
|||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
|
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
|
||||||
{ \
|
{ \
|
||||||
UBaseType_t uxTopPriority; \
|
UBaseType_t uxTopPriority; \
|
||||||
@@ -194,6 +196,17 @@
|
|||||||
configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
|
configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
|
||||||
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[ 0 ], &( pxReadyTasksLists[ uxTopPriority ] ) ); \
|
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[ 0 ], &( pxReadyTasksLists[ uxTopPriority ] ) ); \
|
||||||
} /* taskSELECT_HIGHEST_PRIORITY_TASK() */
|
} /* taskSELECT_HIGHEST_PRIORITY_TASK() */
|
||||||
|
#else
|
||||||
|
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
|
||||||
|
{ \
|
||||||
|
UBaseType_t uxTopPriority; \
|
||||||
|
\
|
||||||
|
/* Find the highest priority list that contains ready tasks. */ \
|
||||||
|
portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
|
||||||
|
configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
|
||||||
|
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[ xPortGetCoreID() ], &( pxReadyTasksLists[ uxTopPriority ] ) ); \
|
||||||
|
} /* taskSELECT_HIGHEST_PRIORITY_TASK() */
|
||||||
|
#endif
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@@ -30,6 +30,7 @@ menu "FreeRTOS"
|
|||||||
# Todo: Replace with CONFIG_NUM_CORES (IDF-4986)
|
# Todo: Replace with CONFIG_NUM_CORES (IDF-4986)
|
||||||
bool "Run FreeRTOS only on first core"
|
bool "Run FreeRTOS only on first core"
|
||||||
default "y" if IDF_TARGET_ESP32S2 || IDF_TARGET_LINUX
|
default "y" if IDF_TARGET_ESP32S2 || IDF_TARGET_LINUX
|
||||||
|
default "y" if IDF_TARGET_ESP32P4 #TODO: IDF-7566
|
||||||
select ESP_SYSTEM_SINGLE_CORE_MODE
|
select ESP_SYSTEM_SINGLE_CORE_MODE
|
||||||
help
|
help
|
||||||
This version of FreeRTOS normally takes control of all cores of the CPU. Select this if you only want
|
This version of FreeRTOS normally takes control of all cores of the CPU. Select this if you only want
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -111,10 +111,19 @@ void esp_startup_start_app_other_cores(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait for CPU0 to start FreeRTOS before progressing
|
// Wait for CPU0 to start FreeRTOS before progressing
|
||||||
|
//TODO: IDF-7566
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
extern volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS];
|
extern volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS];
|
||||||
while (port_xSchedulerRunning[0] == 0) {
|
while (port_xSchedulerRunning[0] == 0) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
extern volatile unsigned uxSchedulerRunning[portNUM_PROCESSORS];
|
||||||
|
while (uxSchedulerRunning[0] == 0) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if CONFIG_APPTRACE_ENABLE
|
#if CONFIG_APPTRACE_ENABLE
|
||||||
// [refactor-todo] move to esp_system initialization
|
// [refactor-todo] move to esp_system initialization
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -64,7 +64,17 @@ void vSystimerSetup(void)
|
|||||||
/* Systimer HAL layer object */
|
/* Systimer HAL layer object */
|
||||||
static systimer_hal_context_t systimer_hal;
|
static systimer_hal_context_t systimer_hal;
|
||||||
/* set system timer interrupt vector */
|
/* set system timer interrupt vector */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: IDF-7487
|
||||||
|
* ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE is renamed to ETS_SYSTIMER_TARGET0_INTR_SOURCE.
|
||||||
|
* It's said that this interrupt is never an edge type, for previous all chips. You may need to check this and unify the name.
|
||||||
|
*/
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
||||||
ESP_ERROR_CHECK(esp_intr_alloc(ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE + cpuid, ESP_INTR_FLAG_IRAM | level, SysTickIsrHandler, &systimer_hal, NULL));
|
ESP_ERROR_CHECK(esp_intr_alloc(ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE + cpuid, ESP_INTR_FLAG_IRAM | level, SysTickIsrHandler, &systimer_hal, NULL));
|
||||||
|
#else
|
||||||
|
ESP_ERROR_CHECK(esp_intr_alloc(ETS_SYSTIMER_TARGET0_INTR_SOURCE + cpuid, ESP_INTR_FLAG_IRAM | level, SysTickIsrHandler, &systimer_hal, NULL));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (cpuid == 0) {
|
if (cpuid == 0) {
|
||||||
periph_module_enable(PERIPH_SYSTIMER_MODULE);
|
periph_module_enable(PERIPH_SYSTIMER_MODULE);
|
||||||
|
Reference in New Issue
Block a user