Merge branch 'bugfix/freertos_smp_build_test_failures' into 'master'

freertos-smp: Fix build test issues for s2, s3, c3 with FreeRTOS SMP enabled

See merge request espressif/esp-idf!18564
This commit is contained in:
Sudeep Mohanty 2022-06-17 19:53:54 +08:00
commit 089d88da77
6 changed files with 152 additions and 27 deletions

View File

@ -259,15 +259,6 @@ Default values for trace macros added by ESP-IDF and are not part of Vanilla Fre
#define configTASKLIST_INCLUDE_COREID 1
#endif
#ifndef __ASSEMBLER__
#if CONFIG_APPTRACE_SV_ENABLE
extern uint32_t port_switch_flag[];
#define os_task_switch_is_pended(_cpu_) (port_switch_flag[_cpu_])
#else
#define os_task_switch_is_pended(_cpu_) (false)
#endif
#endif
// ---------------------- Features -------------------------
/* These currently aren't required, but could be useful additions in the future */

View File

@ -238,6 +238,9 @@ static inline BaseType_t xPortInIsrContext(void)
return xPortCheckIfInISR();
}
// Added for backward compatibility with IDF
#define xPortInterruptedFromISRContext() xPortInIsrContext()
// ---------------------- Spinlocks ------------------------
/**
@ -279,21 +282,25 @@ static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t comp
/*
IDF style critical sections which are orthogonal to FreeRTOS critical sections. However, on single core, the IDF style
critical sections simply disable interrupts, thus we discard the lock and timeout arguments.
Note: The IDF Style critical sections are named differently to their counterparts present in the xtensa port as few IDF
examples such as esp_zigbee_gateway, when compiled for RISC-V targets, have a reference to vPortEnterCritical()
and vPortExitCritical() from precompiled libraries (.a) thereby failing linking.
*/
void vPortEnterCriticalIDF(void);
void vPortExitCriticalIDF(void);
void vPortEnterCritical(void);
void vPortExitCritical(void);
//IDF task critical sections
#define portTRY_ENTER_CRITICAL(lock, timeout) {((void) lock; (void) timeout; vPortEnterCriticalIDF(); pdPASS;)}
#define portENTER_CRITICAL_IDF(lock) ({(void) lock; vPortEnterCriticalIDF();})
#define portEXIT_CRITICAL_IDF(lock) ({(void) lock; vPortExitCriticalIDF();})
#define portTRY_ENTER_CRITICAL(lock, timeout) {((void) lock; (void) timeout; vPortEnterCritical(); pdPASS;)}
#define portENTER_CRITICAL_IDF(lock) ({(void) lock; vPortEnterCritical();})
#define portEXIT_CRITICAL_IDF(lock) ({(void) lock; vPortExitCritical();})
//IDF ISR critical sections
#define portTRY_ENTER_CRITICAL_ISR(lock, timeout) {((void) lock; (void) timeout; vPortEnterCriticalIDF(); pdPASS;)}
#define portENTER_CRITICAL_ISR(lock) ({(void) lock; vPortEnterCriticalIDF();})
#define portEXIT_CRITICAL_ISR(lock) ({(void) lock; vPortExitCriticalIDF();})
#define portTRY_ENTER_CRITICAL_ISR(lock, timeout) {((void) lock; (void) timeout; vPortEnterCritical(); pdPASS;)}
#define portENTER_CRITICAL_ISR(lock) ({(void) lock; vPortEnterCritical();})
#define portEXIT_CRITICAL_ISR(lock) ({(void) lock; vPortExitCritical();})
//IDF safe critical sections (they're the same)
#define portENTER_CRITICAL_SAFE(lock) ({(void) lock; vPortEnterCriticalIDF();})
#define portEXIT_CRITICAL_SAFE(lock) ({(void) lock; vPortExitCriticalIDF();})
#define portENTER_CRITICAL_SAFE(lock) ({(void) lock; vPortEnterCritical();})
#define portEXIT_CRITICAL_SAFE(lock) ({(void) lock; vPortExitCritical();})
// ---------------------- Yielding -------------------------
@ -307,6 +314,9 @@ static inline bool IRAM_ATTR xPortCanYield(void)
return (threshold <= 1);
}
// Added for backward compatibility with IDF
#define portYIELD_WITHIN_API() vTaskYieldWithinAPI()
// ----------------------- System --------------------------
void vPortSetStackWatchpoint(void *pxStackStart);
@ -329,7 +339,7 @@ void vPortSetStackWatchpoint(void *pxStackStart);
// --------------------- App-Trace -------------------------
#if CONFIG_APPTRACE_SV_ENABLE
extern int xPortSwitchFlag;
extern volatile BaseType_t xPortSwitchFlag;
#define os_task_switch_is_pended(_cpu_) (xPortSwitchFlag)
#else
#define os_task_switch_is_pended(_cpu_) (false)

View File

@ -38,6 +38,9 @@
#include "esp_private/pm_trace.h"
#endif //CONFIG_PM_TRACE
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
#include "esp_gdbstub.h"
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
/* ---------------------------------------------------- Variables ------------------------------------------------------
*
@ -63,7 +66,7 @@ static UBaseType_t port_uxCriticalOldInterruptStateIDF = 0;
// ------------------ Critical Sections --------------------
void vPortEnterCriticalIDF(void)
void vPortEnterCritical(void)
{
// Save current interrupt threshold and disable interrupts
UBaseType_t old_thresh = ulPortSetInterruptMask();
@ -75,7 +78,7 @@ void vPortEnterCriticalIDF(void)
}
}
void vPortExitCriticalIDF(void)
void vPortExitCritical(void)
{
if (port_uxCriticalNestingIDF > 0) {
port_uxCriticalNestingIDF--;

View File

@ -356,6 +356,9 @@ 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()
// ----------------------- System --------------------------
void vPortSetStackWatchpoint(void *pxStackStart);

View File

@ -27,6 +27,7 @@
#include "esp_task_wdt.h"
#include "esp_heap_caps_init.h"
#include "esp_freertos_hooks.h"
#include "esp_intr_alloc.h"
#if CONFIG_SPIRAM
/* Required by esp_psram_extram_reserve_dma_pool() */
#include "esp_psram.h"
@ -38,6 +39,12 @@
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
#include "esp_gdbstub.h" /* Required by esp_gdbstub_init() */
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
#ifdef CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
#include "soc/periph_defs.h"
#include "soc/system_reg.h"
#include "hal/systimer_hal.h"
#include "hal/systimer_ll.h"
#endif // CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
/*
OS state variables
@ -148,6 +155,9 @@ void vPortSetStackWatchpoint( void *pxStackStart )
// ---------------------- Tick Timer -----------------------
BaseType_t xPortSysTickHandler(void);
#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
extern void _frxt_tick_timer_init(void);
extern void _xt_tick_divisor_init(void);
@ -163,6 +173,108 @@ void vPortSetupTimer(void)
_frxt_tick_timer_init();
}
#elif CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
_Static_assert(SOC_CPU_CORES_NUM <= SOC_SYSTIMER_ALARM_NUM - 1, "the number of cores must match the number of core alarms in SYSTIMER");
void SysTickIsrHandler(void *arg);
static uint32_t s_handled_systicks[portNUM_PROCESSORS] = { 0 };
#define SYSTICK_INTR_ID (ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE)
/**
* @brief Set up the systimer peripheral to generate the tick interrupt
*
* Both timer alarms are configured in periodic mode.
* It is done at the same time so SysTicks for both CPUs occur at the same time or very close.
* Shifts a time of triggering interrupts for core 0 and core 1.
*/
void vPortSetupTimer(void)
{
unsigned cpuid = xPortGetCoreID();
#ifdef CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3
const unsigned level = ESP_INTR_FLAG_LEVEL3;
#else
const unsigned level = ESP_INTR_FLAG_LEVEL1;
#endif
/* Systimer HAL layer object */
static systimer_hal_context_t systimer_hal;
/* set system timer interrupt vector */
ESP_ERROR_CHECK(esp_intr_alloc(ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE + cpuid, ESP_INTR_FLAG_IRAM | level, SysTickIsrHandler, &systimer_hal, NULL));
if (cpuid == 0) {
systimer_hal_init(&systimer_hal);
systimer_ll_set_counter_value(systimer_hal.dev, SYSTIMER_LL_COUNTER_OS_TICK, 0);
systimer_ll_apply_counter_value(systimer_hal.dev, SYSTIMER_LL_COUNTER_OS_TICK);
for (cpuid = 0; cpuid < SOC_CPU_CORES_NUM; cpuid++) {
systimer_hal_counter_can_stall_by_cpu(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK, cpuid, false);
}
for (cpuid = 0; cpuid < portNUM_PROCESSORS; ++cpuid) {
uint32_t alarm_id = SYSTIMER_LL_ALARM_OS_TICK_CORE0 + cpuid;
/* configure the timer */
systimer_hal_connect_alarm_counter(&systimer_hal, alarm_id, SYSTIMER_LL_COUNTER_OS_TICK);
systimer_hal_set_alarm_period(&systimer_hal, alarm_id, 1000000UL / CONFIG_FREERTOS_HZ);
systimer_hal_select_alarm_mode(&systimer_hal, alarm_id, SYSTIMER_ALARM_MODE_PERIOD);
systimer_hal_counter_can_stall_by_cpu(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK, cpuid, true);
if (cpuid == 0) {
systimer_hal_enable_alarm_int(&systimer_hal, alarm_id);
systimer_hal_enable_counter(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK);
#ifndef CONFIG_FREERTOS_UNICORE
// SysTick of core 0 and core 1 are shifted by half of period
systimer_hal_counter_value_advance(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK, 1000000UL / CONFIG_FREERTOS_HZ / 2);
#endif
}
}
} else {
uint32_t alarm_id = SYSTIMER_LL_ALARM_OS_TICK_CORE0 + cpuid;
systimer_hal_enable_alarm_int(&systimer_hal, alarm_id);
}
}
/**
* @brief Systimer interrupt handler.
*
* The Systimer interrupt for SysTick works in periodic mode no need to calc the next alarm.
* If a timer interrupt is ever serviced more than one tick late, it is necessary to process multiple ticks.
*/
IRAM_ATTR void SysTickIsrHandler(void *arg)
{
uint32_t cpuid = xPortGetCoreID();
systimer_hal_context_t *systimer_hal = (systimer_hal_context_t *)arg;
#ifdef CONFIG_PM_TRACE
ESP_PM_TRACE_ENTER(TICK, cpuid);
#endif
uint32_t alarm_id = SYSTIMER_LL_ALARM_OS_TICK_CORE0 + cpuid;
do {
systimer_ll_clear_alarm_int(systimer_hal->dev, alarm_id);
uint32_t diff = systimer_hal_get_counter_value(systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK) / systimer_ll_get_alarm_period(systimer_hal->dev, alarm_id) - s_handled_systicks[cpuid];
if (diff > 0) {
if (s_handled_systicks[cpuid] == 0) {
s_handled_systicks[cpuid] = diff;
diff = 1;
} else {
s_handled_systicks[cpuid] += diff;
}
do {
xPortSysTickHandler();
} while (--diff);
}
} while (systimer_ll_is_alarm_int_fired(systimer_hal->dev, alarm_id));
#ifdef CONFIG_PM_TRACE
ESP_PM_TRACE_EXIT(TICK, cpuid);
#endif
}
#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
// --------------------- App Start-up ----------------------
static const char *TAG = "cpu_start";

View File

@ -709,11 +709,17 @@ static void prvYieldCore( BaseType_t xCoreID )
{
xYieldPendings[ xCoreID ] = pdTRUE;
}
else
{
portYIELD_CORE( xCoreID );
pxCurrentTCBs[ xCoreID ]->xTaskRunState = taskTASK_YIELDING;
}
#ifdef ESP_PLATFORM
// TODO: IDF-5256
#if ( configNUM_CORES > 1 )
else
{
portYIELD_CORE( xCoreID );
pxCurrentTCBs[ xCoreID ]->xTaskRunState = taskTASK_YIELDING;
}
#endif /* ( configNUM_CORES > 1 ) */
#endif /* ESP_PLATFORM */
}
}