Merge branch 'feature/add_esp32p4_esp_system_support' into 'master'

system: added p4 base support for system related parts

See merge request espressif/esp-idf!24850
This commit is contained in:
Armando (Dou Yiwen) 2023-07-25 16:50:40 +08:00
commit 6bc9a39010
40 changed files with 2071 additions and 40 deletions

View File

@ -25,6 +25,9 @@ extern "C" {
// Forces data into DRAM instead of flash
#define DRAM_ATTR _SECTION_ATTR_IMPL(".dram1", __COUNTER__)
// Forces code into TCM instead of flash
#define TCM_IRAM_ATTR _SECTION_ATTR_IMPL(".tcm.text", __COUNTER__)
// IRAM can only be accessed as an 8-bit memory on ESP32, when CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY is set
#define IRAM_8BIT_ACCESSIBLE (CONFIG_IDF_TARGET_ESP32 && CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY)

View File

@ -41,3 +41,15 @@ entries:
[sections:extram_bss]
entries:
.ext_ram.bss+
[sections:tcm_text]
entries:
.tcm.text+
[sections:tcm_data]
entries:
.tcm.data+
[sections:tcm_bss]
entries:
.tcm.bss+

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -16,6 +16,9 @@
#include "soc/pcr_reg.h"
#define SYSTEM_CPU_PER_CONF_REG PCR_CPU_WAITI_CONF_REG
#define SYSTEM_CPU_WAIT_MODE_FORCE_ON PCR_CPU_WAIT_MODE_FORCE_ON
#elif CONFIG_IDF_TARGET_ESP32P4
#include "soc/lp_clkrst_reg.h"
#include "soc/pmu_reg.h"
#else
#include "soc/rtc_cntl_reg.h"
#endif
@ -45,6 +48,10 @@ void esp_cpu_stall(int core_id)
{
assert(core_id >= 0 && core_id < SOC_CPU_CORES_NUM);
#if SOC_CPU_CORES_NUM > 1 // We don't allow stalling of the current core
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7848
REG_SET_FIELD(PMU_CPU_SW_STALL_REG, core_id ? PMU_HPCORE1_SW_STALL_CODE : PMU_HPCORE0_SW_STALL_CODE, 0x86);
#else
/*
We need to write the value "0x86" to stall a particular core. The write location is split into two separate
bit fields named "c0" and "c1", and the two fields are located in different registers. Each core has its own pair of
@ -62,13 +69,18 @@ void esp_cpu_stall(int core_id)
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2 << rtc_cntl_c0_s);
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, rtc_cntl_c1_m);
SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21 << rtc_cntl_c1_s);
#endif
#endif // CONFIG_IDF_TARGET_ESP32P4
#endif // SOC_CPU_CORES_NUM > 1
}
void esp_cpu_unstall(int core_id)
{
assert(core_id >= 0 && core_id < SOC_CPU_CORES_NUM);
#if SOC_CPU_CORES_NUM > 1 // We don't allow stalling of the current core
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7848
REG_SET_FIELD(PMU_CPU_SW_STALL_REG, core_id ? PMU_HPCORE1_SW_STALL_CODE : PMU_HPCORE0_SW_STALL_CODE, 0);
#else
/*
We need to write clear the value "0x86" to unstall a particular core. The location of this value is split into
two separate bit fields named "c0" and "c1", and the two fields are located in different registers. Each core has
@ -82,11 +94,19 @@ void esp_cpu_unstall(int core_id)
int rtc_cntl_c1_m = (core_id == 0) ? RTC_CNTL_SW_STALL_PROCPU_C1_M : RTC_CNTL_SW_STALL_APPCPU_C1_M;
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, rtc_cntl_c0_m);
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, rtc_cntl_c1_m);
#endif
#endif // CONFIG_IDF_TARGET_ESP32P4
#endif // SOC_CPU_CORES_NUM > 1
}
void esp_cpu_reset(int core_id)
{
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7848
if (core_id == 0)
REG_SET_BIT(LP_CLKRST_HPCPU_RESET_CTRL0_REG, LP_CLKRST_HPCORE0_SW_RESET);
else
REG_SET_BIT(LP_CLKRST_HPCPU_RESET_CTRL0_REG, LP_CLKRST_HPCORE1_SW_RESET);
#else
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2// TODO: IDF-5645
SET_PERI_REG_MASK(LP_AON_CPUCORE0_CFG_REG, LP_AON_CPU_CORE0_SW_RESET);
#else
@ -103,6 +123,7 @@ void esp_cpu_reset(int core_id)
#endif // SOC_CPU_CORES_NUM > 1
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, rtc_cntl_rst_m);
#endif
#endif // CONFIG_IDF_TARGET_ESP32P4
}
void esp_cpu_wait_for_intr(void)
@ -110,12 +131,15 @@ void esp_cpu_wait_for_intr(void)
#if __XTENSA__
xt_utils_wait_for_intr();
#else
//TODO: IDF-7848
#if !CONFIG_IDF_TARGET_ESP32P4
// TODO: IDF-5645 (better to implement with ll) C6 register names converted in the #include section at the top
if (esp_cpu_dbgr_is_attached() && DPORT_REG_GET_BIT(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPU_WAIT_MODE_FORCE_ON) == 0) {
/* when SYSTEM_CPU_WAIT_MODE_FORCE_ON is disabled in WFI mode SBA access to memory does not work for debugger,
so do not enter that mode when debugger is connected */
return;
}
#endif
rv_utils_wait_for_intr();
#endif // __XTENSA__
}
@ -143,6 +167,10 @@ static bool is_intr_num_resv(int intr_num)
reserved |= BIT(0) | BIT(3) | BIT(4) | BIT(7);
#endif
#if SOC_INT_CLIC_SUPPORTED
//TODO: IDF-7795
return false;
#endif
if (reserved & BIT(intr_num)) {
return true;
}
@ -438,8 +466,31 @@ exit:
ret = xt_utils_compare_and_set(addr, compare_value, new_value);
}
return ret;
#else // __XTENSA__
//TODO: IDF-7771
#else // __riscv
#if SOC_CPU_CORES_NUM > 1
/* We use lr.w and sc.w pair for riscv TAS. lr.w will read the memory and register a cpu lock signal
* The state of the lock signal is internal to core, and it is not possible for another core to
* interface. sc.w will assert the address is registered. Then write memory and release the lock
* signal. During the lr.w and sc.w time, if other core acquires the same address, will wait
*/
volatile uint32_t old_value = 0xB33FFFFF;
volatile int error = 1;
__asm__ __volatile__(
"0: lr.w %0, 0(%2) \n"
" bne %0, %3, 1f \n"
" sc.w %1, %4, 0(%2) \n"
" bnez %1, 0b \n"
"1: \n"
: "+r" (old_value), "+r" (error)
: "r" (addr), "r" (compare_value), "r" (new_value)
);
return (old_value == compare_value);
#else
// Single core targets don't have atomic CAS instruction. So access method is the same for internal and external RAM
return rv_utils_compare_and_set(addr, compare_value, new_value);
#endif
#endif
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -233,6 +233,20 @@ FORCE_INLINE_ATTR void esp_cpu_intr_set_ivt_addr(const void *ivt_addr)
#endif
}
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7863
//"MTVT is only implemented in RISC-V arch"
/**
* @brief Set the base address of the current CPU's Interrupt Vector Table (MTVT)
*
* @param ivt_addr Interrupt Vector Table's base address
*/
FORCE_INLINE_ATTR void esp_cpu_intr_set_mtvt_addr(const void *mtvt_addr)
{
rv_utils_set_mtvt((uint32_t)mtvt_addr);
}
#endif //#if CONFIG_IDF_TARGET_ESP32P4
#if SOC_CPU_HAS_FLEXIBLE_INTC
/**
* @brief Set the interrupt type of a particular interrupt
@ -550,6 +564,16 @@ FORCE_INLINE_ATTR intptr_t esp_cpu_get_call_addr(intptr_t return_address)
*/
bool esp_cpu_compare_and_set(volatile uint32_t *addr, uint32_t compare_value, uint32_t new_value);
#if SOC_BRANCH_PREDICTOR_SUPPORTED
/**
* @brief Enable branch prediction
*/
FORCE_INLINE_ATTR void esp_cpu_branch_prediction_enable(void)
{
rv_utils_en_branch_predictor();
}
#endif //#if SOC_BRANCH_PREDICTOR_SUPPORTED
#ifdef __cplusplus
}
#endif

View File

@ -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
*/
@ -13,8 +13,13 @@
#if __XTENSA__
#include "xtensa/xtruntime.h"
#include "xt_utils.h"
#else
#include "riscv/rv_utils.h"
#endif
//TODO: IDF-7771, P4, see jira to know what changed and what need to be checked
#ifdef __cplusplus
extern "C" {
#endif
@ -72,11 +77,18 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l
esp_cpu_cycle_count_t start_count;
assert(lock);
#if __XTENSA__
irq_status = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL);
// Note: The core IDs are the full 32 bit (CORE_ID_REGVAL_PRO/CORE_ID_REGVAL_APP) values
core_id = xt_utils_get_raw_core_id();
other_core_id = CORE_ID_REGVAL_XOR_SWAP ^ core_id;
#else //__riscv
irq_status = rv_utils_set_intlevel(RVHAL_EXCM_LEVEL);
core_id = rv_utils_get_core_id();
other_core_id = 1 - core_id;
#endif
/* lock->owner should be one of SPINLOCK_FREE, CORE_ID_REGVAL_PRO,
* CORE_ID_REGVAL_APP:
@ -89,7 +101,11 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l
if (lock->owner == core_id) {
assert(lock->count > 0 && lock->count < 0xFF); // Bad count value implies memory corruption
lock->count++;
#if __XTENSA__
XTOS_RESTORE_INTLEVEL(irq_status);
#else
rv_utils_restore_intlevel(irq_status);
#endif
return true;
}
@ -126,7 +142,11 @@ exit:
assert(lock->count < 0xFF); // Bad count value implies memory corruption
}
#if __XTENSA__
XTOS_RESTORE_INTLEVEL(irq_status);
#else
rv_utils_restore_intlevel(irq_status);
#endif
return lock_set;
#else // !CONFIG_FREERTOS_UNICORE
@ -154,9 +174,15 @@ static inline void __attribute__((always_inline)) spinlock_release(spinlock_t *l
uint32_t core_id;
assert(lock);
#if __XTENSA__
irq_status = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL);
core_id = xt_utils_get_raw_core_id();
#else
irq_status = rv_utils_set_intlevel(RVHAL_EXCM_LEVEL);
core_id = rv_utils_get_core_id();
#endif
assert(core_id == lock->owner); // This is a lock that we didn't acquire, or the lock is corrupt
lock->count--;
@ -166,8 +192,12 @@ static inline void __attribute__((always_inline)) spinlock_release(spinlock_t *l
assert(lock->count < 0x100); // Indicates memory corruption
}
#if __XTENSA__
XTOS_RESTORE_INTLEVEL(irq_status);
#endif
#else
rv_utils_restore_intlevel(irq_status);
#endif //#if __XTENSA__
#endif //#if !CONFIG_FREERTOS_UNICORE && !BOOTLOADER_BUILD
}
#ifdef __cplusplus

View File

@ -101,6 +101,7 @@ menu "ESP System Settings"
default y if IDF_TARGET_ESP32S3
default y if IDF_TARGET_ESP32C6
default n if IDF_TARGET_ESP32H2 # IDF-5667
default y if IDF_TARGET_ESP32P4
depends on SOC_RTC_FAST_MEM_SUPPORTED
config ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
@ -316,6 +317,7 @@ menu "ESP System Settings"
default 20 if IDF_TARGET_ESP32C2
default 21 if IDF_TARGET_ESP32C3
default 16 if IDF_TARGET_ESP32C6
default 37 if IDF_TARGET_ESP32P4
default 24 if IDF_TARGET_ESP32H2
default 43
help
@ -333,6 +335,7 @@ menu "ESP System Settings"
default 19 if IDF_TARGET_ESP32C2
default 20 if IDF_TARGET_ESP32C3
default 17 if IDF_TARGET_ESP32C6
default 38 if IDF_TARGET_ESP32P4
default 23 if IDF_TARGET_ESP32H2
default 44
help
@ -596,6 +599,7 @@ menu "IPC (Inter-Processor Call)"
config ESP_IPC_ISR_ENABLE
bool
default n if IDF_TARGET_ESP32P4 # TODO: IDF-7769
default y if !FREERTOS_UNICORE
help
The IPC ISR feature is similar to the IPC feature except that the callback function is executed in the

View File

@ -22,6 +22,8 @@ entries:
rtc_data -> rtc_data
rtc_rodata -> rtc_data
rtc_bss -> rtc_bss
tcm_text -> tcm_text
tcm_data -> tcm_data
[scheme:rtc]
entries:
@ -44,6 +46,14 @@ entries:
entries:
text -> iram0_text
[scheme:tcm]
entries:
text -> tcm_text
data -> tcm_data
rodata -> tcm_data
bss -> tcm_bss
common -> tcm_bss
[mapping:default]
archive: *
entries:

View File

@ -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
*/
@ -24,6 +24,9 @@
#else
#include "soc/system_reg.h"
#endif
#if CONFIG_IDF_TARGET_ESP32P4
#include "soc/hp_system_reg.h"
#endif
#define REASON_YIELD BIT(0)
#define REASON_FREQ_SWITCH BIT(1)
@ -66,6 +69,12 @@ static void IRAM_ATTR esp_crosscore_isr(void *arg) {
} else {
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_1_REG, 0);
}
#elif CONFIG_IDF_TARGET_ESP32P4
if (esp_cpu_get_core_id() == 0) {
WRITE_PERI_REG(HP_SYSTEM_CPU_INT_FROM_CPU_0_REG, 0);
} else {
WRITE_PERI_REG(HP_SYSTEM_CPU_INT_FROM_CPU_1_REG, 0);
}
#elif CONFIG_IDF_TARGET_ARCH_RISCV
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0);
#endif
@ -147,6 +156,12 @@ static void IRAM_ATTR esp_crosscore_int_send(int core_id, uint32_t reason_mask)
} else {
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_1_REG, SYSTEM_CPU_INTR_FROM_CPU_1);
}
#elif CONFIG_IDF_TARGET_ESP32P4
if (core_id==0) {
WRITE_PERI_REG(HP_SYSTEM_CPU_INT_FROM_CPU_0_REG, HP_SYSTEM_CPU_INT_FROM_CPU_0);
} else {
WRITE_PERI_REG(HP_SYSTEM_CPU_INT_FROM_CPU_1_REG, HP_SYSTEM_CPU_INT_FROM_CPU_1);
}
#elif CONFIG_IDF_TARGET_ARCH_RISCV
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, SYSTEM_CPU_INTR_FROM_CPU_0);
#endif

View File

@ -24,6 +24,8 @@
#include "esp_private/esp_pmu.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/rtc.h"
#endif
#include "esp_log.h"
#include "esp_rom_sys.h"

View File

@ -20,7 +20,7 @@
extern "C" {
#endif
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32P4
/**
* This macro also helps users switching between spinlock declarations/definitions for multi-/single core environments
* if the macros below aren't sufficient.

View File

@ -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
*/

View File

@ -0,0 +1,131 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* ESP32-P4 Linker Script Memory Layout
* This file describes the memory layout (memory blocks) by virtual memory addresses.
* This linker script is passed through the C preprocessor to include configuration options.
* Please use preprocessor features sparingly!
* Restrict to simple macros with numeric values, and/or #if/#endif blocks.
*/
#include "sdkconfig.h"
#include "ld.common"
/**
* physical memory is mapped twice to the vritual address (IRAM and DRAM).
* `I_D_SRAM_OFFSET` is the offset between the two locations of the same physical memory
*/
#define SRAM_IRAM_START 0x4ff00000
#define SRAM_DRAM_START 0x4ff00000
#define I_D_SRAM_OFFSET (SRAM_IRAM_START - SRAM_DRAM_START)
#define SRAM_DRAM_END 0x4ff30bd0 - I_D_SRAM_OFFSET /* 2nd stage bootloader iram_loader_seg start address */
#define SRAM_IRAM_ORG (SRAM_IRAM_START)
#define SRAM_DRAM_ORG (SRAM_DRAM_START)
#define I_D_SRAM_SIZE SRAM_DRAM_END - SRAM_DRAM_ORG
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
/**
* TODO: IDF-7890
*/
#define IDROM_SEG_SIZE (CONFIG_MMU_PAGE_SIZE << 10)
#endif
#define DRAM0_0_SEG_LEN I_D_SRAM_SIZE
MEMORY
{
/**
* All these values assume the flash cache is on, and have the blocks this uses subtracted from the length
* of the various regions. The 'data access port' dram/drom regions map to the same iram/irom regions but
* are connected to the data port of the CPU and eg allow byte-wise access.
*/
/* TCM */
tcm_idram_seg (RX) : org = 0x30100000, len = 0x2000
/* IRAM for PRO CPU. */
iram0_0_seg (RX) : org = SRAM_IRAM_ORG, len = I_D_SRAM_SIZE
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
/* Flash mapped instruction data */
irom_seg (RX) : org = 0x40000020, len = IDROM_SEG_SIZE - 0x20
/**
* (0x20 offset above is a convenience for the app binary image generation.
* Flash cache has 64KB pages. The .bin file which is flashed to the chip
* has a 0x18 byte file header, and each segment has a 0x08 byte segment
* header. Setting this offset makes it simple to meet the flash cache MMU's
* constraint that (paddr % 64KB == vaddr % 64KB).)
*/
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
/**
* Shared data RAM, excluding memory reserved for ROM bss/data/stack.
* Enabling Bluetooth & Trace Memory features in menuconfig will decrease the amount of RAM available.
*/
dram0_0_seg (RW) : org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
/* Flash mapped constant data */
drom_seg (R) : org = 0x40000020, len = IDROM_SEG_SIZE - 0x20
/* (See irom_seg for meaning of 0x20 offset in the above.) */
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
/**
* lp ram memory (RWX). Persists over deep sleep. // TODO: IDF-5667
*/
#if CONFIG_ULP_COPROC_ENABLED
lp_ram_seg(RW) : org = 0x50108000 + CONFIG_ULP_COPROC_RESERVE_MEM,
len = 0x8000 - CONFIG_ULP_COPROC_RESERVE_MEM
#else
lp_ram_seg(RW) : org = 0x50108000 , len = 0x8000
#endif // CONFIG_ULP_COPROC_ENABLED
}
/* Heap ends at top of dram0_0_seg */
_heap_end = 0x50000000;
_data_seg_org = ORIGIN(rtc_data_seg);
/**
* The lines below define location alias for .rtc.data section
* P4 has no distinguished LP(RTC) fast and slow memory sections, instead, there is a unified LP_RAM section
* Thus, the following region segments are not configurable like on other targets
*/
REGION_ALIAS("rtc_iram_seg", lp_ram_seg );
REGION_ALIAS("rtc_data_seg", rtc_iram_seg );
REGION_ALIAS("rtc_slow_seg", rtc_iram_seg );
REGION_ALIAS("rtc_data_location", rtc_iram_seg );
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
REGION_ALIAS("default_code_seg", irom_seg);
#else
REGION_ALIAS("default_code_seg", iram0_0_seg);
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
REGION_ALIAS("default_rodata_seg", drom_seg);
#else
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
/**
* If rodata default segment is placed in `drom_seg`, then flash's first rodata section must
* also be first in the segment.
*/
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg),
".flash_rodata_dummy section must be placed at the beginning of the rodata segment.")
#endif
#if CONFIG_ESP_SYSTEM_USE_EH_FRAME
ASSERT ((__eh_frame_end > __eh_frame), "Error: eh_frame size is null!");
ASSERT ((__eh_frame_hdr_end > __eh_frame_hdr), "Error: eh_frame_hdr size is null!");
#endif

View File

@ -0,0 +1,441 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* Default entry point */
ENTRY(call_start_cpu0);
SECTIONS
{
/**
* RTC fast memory holds RTC wake stub code,
* including from any source file named rtc_wake_stub*.c
*/
.rtc.text :
{
. = ALIGN(4);
_rtc_fast_start = ABSOLUTE(.);
mapping[rtc_text]
*rtc_wake_stub*.*(.literal .text .literal.* .text.*)
*(.rtc_text_end_test)
/* 16B padding for possible CPU prefetch and 4B alignment for PMS split lines */
. += _esp_memprot_prefetch_pad_size;
. = ALIGN(4);
_rtc_text_end = ABSOLUTE(.);
} > lp_ram_seg
/**
* This section located in RTC FAST Memory area.
* It holds data marked with RTC_FAST_ATTR attribute.
* See the file "esp_attr.h" for more information.
*/
.rtc.force_fast :
{
. = ALIGN(4);
_rtc_force_fast_start = ABSOLUTE(.);
mapping[rtc_force_fast]
*(.rtc.force_fast .rtc.force_fast.*)
. = ALIGN(4) ;
_rtc_force_fast_end = ABSOLUTE(.);
} > lp_ram_seg
/**
* RTC data section holds RTC wake stub
* data/rodata, including from any source file
* named rtc_wake_stub*.c and the data marked with
* RTC_DATA_ATTR, RTC_RODATA_ATTR attributes.
*/
.rtc.data :
{
_rtc_data_start = ABSOLUTE(.);
mapping[rtc_data]
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
_rtc_data_end = ABSOLUTE(.);
} > lp_ram_seg
/* RTC bss, from any source file named rtc_wake_stub*.c */
.rtc.bss (NOLOAD) :
{
_rtc_bss_start = ABSOLUTE(.);
*rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*)
*rtc_wake_stub*.*(COMMON)
mapping[rtc_bss]
_rtc_bss_end = ABSOLUTE(.);
} > lp_ram_seg
/**
* This section holds data that should not be initialized at power up
* and will be retained during deep sleep.
* User data marked with RTC_NOINIT_ATTR will be placed
* into this section. See the file "esp_attr.h" for more information.
*/
.rtc_noinit (NOLOAD):
{
. = ALIGN(4);
_rtc_noinit_start = ABSOLUTE(.);
*(.rtc_noinit .rtc_noinit.*)
. = ALIGN(4) ;
_rtc_noinit_end = ABSOLUTE(.);
} > lp_ram_seg
/**
* This section located in RTC SLOW Memory area.
* It holds data marked with RTC_SLOW_ATTR attribute.
* See the file "esp_attr.h" for more information.
*/
.rtc.force_slow :
{
. = ALIGN(4);
_rtc_force_slow_start = ABSOLUTE(.);
*(.rtc.force_slow .rtc.force_slow.*)
. = ALIGN(4) ;
_rtc_force_slow_end = ABSOLUTE(.);
} > lp_ram_seg
/* Get size of rtc slow data based on rtc_data_location alias */
_rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
? (_rtc_force_slow_end - _rtc_data_start)
: (_rtc_force_slow_end - _rtc_force_slow_start);
_rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
? (_rtc_force_fast_end - _rtc_fast_start)
: (_rtc_noinit_end - _rtc_fast_start);
ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)),
"RTC_SLOW segment data does not fit.")
ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)),
"RTC_FAST segment data does not fit.")
.tcm.text :
{
/* Code marked as running out of TCM */
_tcm_text_start = ABSOLUTE(.);
mapping[tcm_text]
_tcm_text_end = ABSOLUTE(.);
} > tcm_idram_seg
.tcm.data :
{
_tcm_data_start = ABSOLUTE(.);
mapping[tcm_data]
_tcm_data_end = ABSOLUTE(.);
. = ALIGN(4);
} > tcm_idram_seg
.iram0.text :
{
_iram_start = ABSOLUTE(.);
/* Vectors go to start of IRAM */
ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned");
KEEP(*(.exception_vectors.text));
. = ALIGN(4);
_invalid_pc_placeholder = ABSOLUTE(.);
/* Code marked as running out of IRAM */
_iram_text_start = ABSOLUTE(.);
mapping[iram0_text]
} > iram0_0_seg
/* Marks the end of IRAM code segment */
.iram0.text_end (NOLOAD) :
{
/* ESP32-C6 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */
. += _esp_memprot_prefetch_pad_size;
. = ALIGN(_esp_memprot_align_size);
/* iram_end_test section exists for use by memprot unit tests only */
*(.iram_end_test)
_iram_text_end = ABSOLUTE(.);
} > iram0_0_seg
.iram0.data :
{
. = ALIGN(16);
_iram_data_start = ABSOLUTE(.);
mapping[iram0_data]
_iram_data_end = ABSOLUTE(.);
} > iram0_0_seg
.iram0.bss (NOLOAD) :
{
. = ALIGN(16);
_iram_bss_start = ABSOLUTE(.);
mapping[iram0_bss]
_iram_bss_end = ABSOLUTE(.);
. = ALIGN(16);
_iram_end = ABSOLUTE(.);
} > iram0_0_seg
/**
* This section is required to skip .iram0.text area because iram0_0_seg and
* dram0_0_seg reflect the same address space on different buses.
*/
.dram0.dummy (NOLOAD):
{
. = ORIGIN(dram0_0_seg) + _iram_end - _iram_start;
} > dram0_0_seg
.dram0.data :
{
_data_start = ABSOLUTE(.);
*(.gnu.linkonce.d.*)
*(.data1)
__global_pointer$ = . + 0x800;
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
mapping[dram0_data]
_data_end = ABSOLUTE(.);
. = ALIGN(4);
} > dram0_0_seg
/**
* This section holds data that should not be initialized at power up.
* The section located in Internal SRAM memory region. The macro _NOINIT
* can be used as attribute to place data into this section.
* See the "esp_attr.h" file for more information.
*/
.noinit (NOLOAD):
{
. = ALIGN(4);
_noinit_start = ABSOLUTE(.);
*(.noinit .noinit.*)
. = ALIGN(4) ;
_noinit_end = ABSOLUTE(.);
} > dram0_0_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_bss_start = ABSOLUTE(.);
mapping[dram0_bss]
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.share.mem)
*(.gnu.linkonce.b.*)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} > dram0_0_seg
ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.")
.flash.text :
{
_stext = .;
_instruction_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.text start, this can be used for mmu driver to maintain virtual address */
_text_start = ABSOLUTE(.);
mapping[flash_text]
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += _esp_flash_mmap_prefetch_pad_size;
_text_end = ABSOLUTE(.);
_instruction_reserved_end = ABSOLUTE(.); /* This is a symbol marking the flash.text end, this can be used for mmu driver to maintain virtual address */
_etext = .;
/**
* Similar to _iram_start, this symbol goes here so it is
* resolved by addr2line in preference to the first symbol in
* the flash.text segment.
*/
_flash_cache_start = ABSOLUTE(0);
} > default_code_seg
/**
* This dummy section represents the .flash.text section but in default_rodata_seg.
* Thus, it must have its alignment and (at least) its size.
*/
.flash_rodata_dummy (NOLOAD):
{
_flash_rodata_dummy_start = .;
/* Start at the same alignment constraint than .flash.text */
. = ALIGN(ALIGNOF(.flash.text));
/* Create an empty gap as big as .flash.text section */
. = . + SIZEOF(.flash.text);
/* Prepare the alignment of the section above. Few bytes (0x20) must be
* added for the mapping header. */
. = ALIGN(_esp_mmu_block_size) + 0x20;
} > default_rodata_seg
.flash.appdesc : ALIGN(0x10)
{
_rodata_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.rodata start, this can be used for mmu driver to maintain virtual address */
_rodata_start = ABSOLUTE(.);
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
/* Create an empty gap within this section. Thanks to this, the end of this
* section will match .flash.rodata's begin address. Thus, both sections
* will be merged when creating the final bin image. */
. = ALIGN(ALIGNOF(.flash.rodata));
} > default_rodata_seg
.flash.rodata : ALIGN(0x10)
{
_flash_rodata_start = ABSOLUTE(.);
mapping[flash_rodata]
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
*(.gnu.linkonce.r.*)
*(.rodata1)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table .gcc_except_table.*)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
. = (. + 7) & ~ 3;
/*
* C++ constructor and destructor tables
* Don't include anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt.
*
* RISC-V gcc is configured with --enable-initfini-array so it emits an .init_array section instead.
* But the init_priority sections will be sorted for iteration in ascending order during startup.
* The rest of the init_array sections is sorted for iteration in descending order during startup, however.
* Hence a different section is generated for the init_priority functions which is iterated in
* ascending order during startup. The corresponding code can be found in startup.c.
*/
__init_priority_array_start = ABSOLUTE(.);
KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*))
__init_priority_array_end = ABSOLUTE(.);
__init_array_start = ABSOLUTE(.);
KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.*(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
/* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */
soc_reserved_memory_region_start = ABSOLUTE(.);
KEEP (*(.reserved_memory_address))
soc_reserved_memory_region_end = ABSOLUTE(.);
/* System init functions registered via ESP_SYSTEM_INIT_FN */
_esp_system_init_fn_array_start = ABSOLUTE(.);
KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
_esp_system_init_fn_array_end = ABSOLUTE(.);
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_thread_local_start = ABSOLUTE(.);
*(.tdata)
*(.tdata.*)
*(.tbss)
*(.tbss.*)
_thread_local_end = ABSOLUTE(.);
. = ALIGN(ALIGNOF(.eh_frame));
} > default_rodata_seg
/* Keep this section shall be at least aligned on 4 */
.eh_frame : ALIGN(8)
{
__eh_frame = ABSOLUTE(.);
KEEP (*(.eh_frame))
__eh_frame_end = ABSOLUTE(.);
/* Guarantee that this section and the next one will be merged by making
* them adjacent. */
. = ALIGN(ALIGNOF(.eh_frame_hdr));
} > default_rodata_seg
/* To avoid any exception in C++ exception frame unwinding code, this section
* shall be aligned on 8. */
.eh_frame_hdr : ALIGN(8)
{
__eh_frame_hdr = ABSOLUTE(.);
KEEP (*(.eh_frame_hdr))
__eh_frame_hdr_end = ABSOLUTE(.);
} > default_rodata_seg
/*
This section is a place where we dump all the rodata which aren't used at runtime,
so as to avoid binary size increase
*/
.flash.rodata_noload (NOLOAD) :
{
/*
This is a symbol marking the flash.rodata end, this can be used for mmu driver to maintain virtual address
We don't need to include the noload rodata in this section
*/
_rodata_reserved_end = ABSOLUTE(.);
. = ALIGN (4);
mapping[rodata_noload]
} > default_rodata_seg
/* Marks the end of data, bss and possibly rodata */
.dram0.heap_start (NOLOAD) :
{
. = ALIGN (16);
_heap_start = ABSOLUTE(.);
} > dram0_0_seg
}
ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
"IRAM0 segment data does not fit.")
ASSERT(((_heap_start - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
"DRAM segment data does not fit.")

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -8,10 +8,15 @@
#include "spi_flash_mmap.h"
#if CONFIG_IDF_TARGET_ESP32P4
#include "soc/cache_reg.h"
#else
#include "soc/extmem_reg.h"
#endif
#include "esp_private/panic_internal.h"
#include "esp_private/panic_reason.h"
#include "riscv/rvruntime-frames.h"
#include "riscv/rv_utils.h"
#include "esp_private/cache_err_int.h"
#include "soc/timer_periph.h"
@ -80,7 +85,7 @@ static inline bool test_and_print_register_bits(const uint32_t status,
*/
static inline void print_cache_err_details(const void *frame)
{
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 // ESP32C6-TODO, ESP32H2-TODO: IDF-5657
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 // ESP32P4-TODO, ESP32C6-TODO, ESP32H2-TODO: IDF-5657
/* Define the array that contains the status (bits) to test on the register
* EXTMEM_CORE0_ACS_CACHE_INT_ST_REG. each bit is accompanied by a small
* message.
@ -344,7 +349,7 @@ void panic_soc_fill_info(void *f, panic_info_t *info)
void panic_arch_fill_info(void *frame, panic_info_t *info)
{
RvExcFrame *regs = (RvExcFrame *) frame;
info->core = 0;
info->core = rv_utils_get_core_id();
info->exception = PANIC_EXCEPTION_FAULT;
static const char *reason[] = {

View File

@ -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
*/
@ -61,6 +61,11 @@
#include "esp32c2/rom/cache.h"
#include "esp32c2/rom/rtc.h"
#include "esp32c2/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rtc.h"
#include "soc/hp_sys_clkrst_reg.h"
#include "soc/interrupt_core0_reg.h"
#include "soc/interrupt_core1_reg.h"
#endif
#include "esp_private/esp_mmu_map_private.h"
@ -115,6 +120,9 @@ extern int _rodata_reserved_start;
extern int _rodata_reserved_end;
extern int _vector_table;
#if SOC_INT_CLIC_SUPPORTED
extern int _mtvt_table;
#endif
static const char *TAG = "cpu_start";
@ -140,7 +148,15 @@ static void core_intr_matrix_clear(void)
uint32_t core_id = esp_cpu_get_core_id();
for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) {
#if CONFIG_IDF_TARGET_ESP32P4
if (core_id == 0) {
REG_WRITE(INTERRUPT_CORE0_LP_RTC_INT_MAP_REG + 4 * i, 0);
} else {
REG_WRITE(INTERRUPT_CORE1_LP_RTC_INT_MAP_REG + 4 * i, 0);
}
#else
esp_rom_route_intr_matrix(core_id, i, ETS_INVALID_INUM);
#endif
}
}
@ -152,7 +168,37 @@ void startup_resume_other_cores(void)
void IRAM_ATTR call_start_cpu1(void)
{
#ifdef __riscv
// Configure the global pointer register
// (This should be the first thing IDF app does, as any other piece of code could be
// relaxed by the linker to access something relative to __global_pointer$)
__asm__ __volatile__ (
".option push\n"
".option norelax\n"
"la gp, __global_pointer$\n"
".option pop"
);
#endif //#ifdef __riscv
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7770
//set mstatus.fs=2'b01, floating-point unit in the initialization state
asm volatile(
"li t0, 0x2000\n"
"csrrs t0, mstatus, t0\n"
:::"t0"
);
#endif //#if CONFIG_IDF_TARGET_ESP32P4
#if SOC_BRANCH_PREDICTOR_SUPPORTED
esp_cpu_branch_prediction_enable();
#endif //#if SOC_BRANCH_PREDICTOR_SUPPORTED
esp_cpu_intr_set_ivt_addr(&_vector_table);
#if SOC_INT_CLIC_SUPPORTED
//TODO: IDF-7863
esp_cpu_intr_set_mtvt_addr(&_mtvt_table);
#endif
ets_set_appcpu_boot_addr(0);
@ -169,6 +215,8 @@ void IRAM_ATTR call_start_cpu1(void)
#if CONFIG_IDF_TARGET_ESP32
DPORT_REG_SET_BIT(DPORT_APP_CPU_RECORD_CTRL_REG, DPORT_APP_CPU_PDEBUG_ENABLE | DPORT_APP_CPU_RECORD_ENABLE);
DPORT_REG_CLR_BIT(DPORT_APP_CPU_RECORD_CTRL_REG, DPORT_APP_CPU_RECORD_ENABLE);
#elif CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7688
#else
REG_WRITE(ASSIST_DEBUG_CORE_1_RCD_PDEBUGENABLE_REG, 1);
REG_WRITE(ASSIST_DEBUG_CORE_1_RCD_RECORDING_REG, 1);
@ -240,6 +288,13 @@ static void start_other_core(void)
REG_SET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETING);
REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETING);
}
#elif CONFIG_IDF_TARGET_ESP32P4
if (!REG_GET_BIT(HP_SYS_CLKRST_SOC_CLK_CTRL0_REG, HP_SYS_CLKRST_REG_CORE1_CPU_CLK_EN)) {
REG_SET_BIT(HP_SYS_CLKRST_SOC_CLK_CTRL0_REG, HP_SYS_CLKRST_REG_CORE1_CPU_CLK_EN);
}
if(REG_GET_BIT(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_CORE1_GLOBAL)){
REG_CLR_BIT(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_CORE1_GLOBAL);
}
#endif
ets_set_appcpu_boot_addr((uint32_t)call_start_cpu1);
@ -250,10 +305,13 @@ static void start_other_core(void)
for (int i = 0; i < SOC_CPU_CORES_NUM; i++) {
cpus_up &= s_cpu_up[i];
}
//TODO: IDF-7891, check mixing logs
esp_rom_delay_us(100);
}
}
#if !CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7692
// This function is needed to make the multicore app runnable on a unicore bootloader (built with FREERTOS UNICORE).
// It does some cache settings for other CPUs.
void IRAM_ATTR do_multicore_settings(void)
@ -284,6 +342,7 @@ void IRAM_ATTR do_multicore_settings(void)
cache_hal_enable(CACHE_TYPE_ALL);
#endif
}
#endif //#if !CONFIG_IDF_TARGET_ESP32P4
#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
/*
@ -317,8 +376,25 @@ void IRAM_ATTR call_start_cpu0(void)
);
#endif
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7770
//set mstatus.fs=2'b01, floating-point unit in the initialization state
asm volatile(
"li t0, 0x2000\n"
"csrrs t0, mstatus, t0\n"
:::"t0"
);
#endif //#if CONFIG_IDF_TARGET_ESP32P4
#if SOC_BRANCH_PREDICTOR_SUPPORTED
esp_cpu_branch_prediction_enable();
#endif
// Move exception vectors to IRAM
esp_cpu_intr_set_ivt_addr(&_vector_table);
#if SOC_INT_CLIC_SUPPORTED
//TODO: IDF-7863
esp_cpu_intr_set_mtvt_addr(&_mtvt_table);
#endif
rst_reas[0] = esp_rom_get_reset_reason(0);
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
@ -345,8 +421,11 @@ void IRAM_ATTR call_start_cpu0(void)
ESP_EARLY_LOGI(TAG, "Unicore app");
#else
ESP_EARLY_LOGI(TAG, "Multicore app");
#if !CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7692
// It helps to fix missed cache settings for other cores. It happens when bootloader is unicore.
do_multicore_settings();
#endif //#if !CONFIG_IDF_TARGET_ESP32P4
#endif
#endif // !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
@ -404,6 +483,11 @@ void IRAM_ATTR call_start_cpu0(void)
Cache_Resume_DCache(0);
#endif // CONFIG_IDF_TARGET_ESP32S3
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7516, add cache init API
extern void esp_config_llc_mode(void);
esp_config_llc_mode();
#endif
if (esp_efuse_check_errors() != ESP_OK) {
esp_restart();
}
@ -591,10 +675,12 @@ void IRAM_ATTR call_start_cpu0(void)
#endif
#endif
#if !CONFIG_IDF_TARGET_ESP32P4 //TODO: IDF-7529
// Need to unhold the IOs that were hold right before entering deep sleep, which are used as wakeup pins
if (rst_reas[0] == RESET_REASON_CORE_DEEP_SLEEP) {
esp_deep_sleep_wakeup_io_reset();
}
#endif //#if !CONFIG_IDF_TARGET_ESP32P4
#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
esp_cache_err_int_init();

View File

@ -0,0 +1,11 @@
set(srcs "clk.c"
"reset_reason.c"
"system_internal.c"
"cache_err_int.c"
"../../arch/riscv/expression_with_stack.c"
"../../arch/riscv/panic_arch.c"
"../../arch/riscv/debug_stubs.c")
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})
target_sources(${COMPONENT_LIB} PRIVATE ${srcs})

View File

@ -0,0 +1,43 @@
menu "Cache config"
choice ESP32P4_L2_CACHE_SIZE
prompt "L2 cache size"
default ESP32P4_L2_CACHE_128KB
help
L2 cache size to be set on application startup.
config ESP32P4_L2_CACHE_128KB
bool "128KB"
config ESP32P4_L2_CACHE_256KB
bool "256KB"
config ESP32P4_L2_CACHE_512KB
bool "512KB"
endchoice
config ESP32P4_L2_CACHE_SIZE
hex
default 0x20000 if ESP32P4_L2_CACHE_128KB
default 0x40000 if ESP32P4_L2_CACHE_256KB
default 0x80000 if ESP32P4_L2_CACHE_512KB
choice ESP32P4_L2_CACHE_LINE_SIZE
prompt "L2 cache line size"
default ESP32P4_L2_CACHE_LINE_64B if ESP32P4_L2_CACHE_128KB
default ESP32P4_L2_CACHE_LINE_64B if ESP32P4_L2_CACHE_256KB
default ESP32P4_L2_CACHE_LINE_128B if ESP32P4_L2_CACHE_512KB
help
L2 cache line size to be set on application startup.
config ESP32P4_L2_CACHE_LINE_64B
bool "64 Bytes"
depends on ESP32P4_L2_CACHE_128KB || ESP32P4_L2_CACHE_256KB
config ESP32P4_L2_CACHE_LINE_128B
bool "128 Bytes"
endchoice
config ESP32P4_L2_CACHE_LINE_SIZE
int
default 64 if ESP32P4_L2_CACHE_LINE_64B
default 128 if ESP32P4_L2_CACHE_LINE_128B
endmenu # Cache config

View File

@ -0,0 +1,61 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
The cache has an interrupt that can be raised as soon as an access to a cached
region (flash) is done without the cache being enabled. We use that here
to panic the CPU, which from a debugging perspective is better than grabbing bad
data from the bus.
*/
#include "esp_rom_sys.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_intr_alloc.h"
#include "soc/periph_defs.h"
#include "riscv/interrupt.h"
#include "hal/cache_ll.h"
static const char *TAG = "CACHE_ERR";
//TODO: IDF-7515
void esp_cache_err_int_init(void)
{
const uint32_t core_id = 0;
/* Disable cache interrupts if enabled. */
ESP_INTR_DISABLE(ETS_CACHEERR_INUM);
/**
* Bind all cache errors to ETS_CACHEERR_INUM interrupt. we will deal with
* them in handler by different types
*
* On ESP32P4 boards, the cache is a shared one but buses are still
* distinct. So, we have an bus0 and a bus1 sharing the same cache.
* This error can occur if a bus performs a request but the cache
* is disabled.
*/
esp_rom_route_intr_matrix(core_id, ETS_CACHE_INTR_SOURCE, ETS_CACHEERR_INUM);
/* Set the type and priority to cache error interrupts. */
esprv_intc_int_set_type(ETS_CACHEERR_INUM, INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK);
/* On the hardware side, start by clearing all the bits reponsible for cache access error */
cache_ll_l1_clear_access_error_intr(0, CACHE_LL_L1_ACCESS_EVENT_MASK);
/* Then enable cache access error interrupts. */
cache_ll_l1_enable_access_error_intr(0, CACHE_LL_L1_ACCESS_EVENT_MASK);
/* Enable the interrupts for cache error. */
ESP_INTR_ENABLE(ETS_CACHEERR_INUM);
}
int IRAM_ATTR esp_cache_err_get_cpuid(void)
{
//TODO: IDF-7515
//Should return hart ID according to the cache error
return 0;
}

View File

@ -0,0 +1,277 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <sys/cdefs.h>
#include <sys/time.h>
#include <sys/param.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_clk_internal.h"
#include "esp32p4/rom/ets_sys.h"
#include "esp32p4/rom/uart.h"
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/rtc_periph.h"
#include "soc/i2s_reg.h"
#include "esp_cpu.h"
#include "hal/wdt_hal.h"
#include "esp_private/esp_modem_clock.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/esp_clk.h"
#include "esp_private/esp_pmu.h"
#include "esp_rom_uart.h"
#include "esp_rom_sys.h"
/* Number of cycles to wait from the 32k XTAL oscillator to consider it running.
* Larger values increase startup delay. Smaller values may cause false positive
* detection (i.e. oscillator runs for a few cycles and then stops).
*/
#define SLOW_CLK_CAL_CYCLES CONFIG_RTC_CLK_CAL_CYCLES
#define MHZ (1000000)
static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src);
static const char *TAG = "clk";
__attribute__((weak)) void esp_clk_init(void)
{
#if SOC_PMU_SUPPORTED
pmu_init();
#endif //SOC_PMU_SUPPORTED
assert(rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_40M);
rtc_clk_8m_enable(true);
rtc_clk_fast_src_set(SOC_RTC_FAST_CLK_SRC_RC_FAST);
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
// WDT uses a SLOW_CLK clock source. After a function select_rtc_slow_clk a frequency of this source can changed.
// If the frequency changes from 150kHz to 32kHz, then the timeout set for the WDT will increase 4.6 times.
// Therefore, for the time of frequency change, set a new lower timeout value (1.6 sec).
// This prevents excessive delay before resetting in case the supply voltage is drawdown.
// (If frequency is changed from 150kHz to 32kHz then WDT timeout will increased to 1.6sec * 150/32 = 7.5 sec).
wdt_hal_context_t rtc_wdt_ctx = RWDT_HAL_CONTEXT_DEFAULT();
uint32_t stage_timeout_ticks = (uint32_t)(1600ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
wdt_hal_feed(&rtc_wdt_ctx);
//Bootloader has enabled RTC WDT until now. We're only modifying timeout, so keep the stage and timeout action the same
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
#endif
#if defined(CONFIG_RTC_CLK_SRC_EXT_CRYS)
select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_XTAL32K);
#elif defined(CONFIG_RTC_CLK_SRC_EXT_OSC)
select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_OSC_SLOW);
#elif defined(CONFIG_RTC_CLK_SRC_INT_RC32K)
select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_RC32K);
#else
select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_RC_SLOW);
#endif
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
// After changing a frequency WDT timeout needs to be set for new frequency.
stage_timeout_ticks = (uint32_t)((uint64_t)CONFIG_BOOTLOADER_WDT_TIME_MS * rtc_clk_slow_freq_get_hz() / 1000);
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
wdt_hal_feed(&rtc_wdt_ctx);
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
#endif
rtc_cpu_freq_config_t old_config, new_config;
rtc_clk_cpu_freq_get_config(&old_config);
const uint32_t old_freq_mhz = old_config.freq_mhz;
const uint32_t new_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ;
bool res = rtc_clk_cpu_freq_mhz_to_config(new_freq_mhz, &new_config);
assert(res);
// Wait for UART TX to finish, otherwise some UART output will be lost
// when switching APB frequency
esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
if (res) {
rtc_clk_cpu_freq_set_config(&new_config);
}
// Re calculate the ccount to make time calculation correct.
esp_cpu_set_cycle_count( (uint64_t)esp_cpu_get_cycle_count() * new_freq_mhz / old_freq_mhz );
}
static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src)
{
uint32_t cal_val = 0;
/* number of times to repeat 32k XTAL calibration
* before giving up and switching to the internal RC
*/
int retry_32k_xtal = 3;
do {
if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K || rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
/* 32k XTAL oscillator needs to be enabled and running before it can
* be used. Hardware doesn't have a direct way of checking if the
* oscillator is running. Here we use rtc_clk_cal function to count
* the number of main XTAL cycles in the given number of 32k XTAL
* oscillator cycles. If the 32k XTAL has not started up, calibration
* will time out, returning 0.
*/
ESP_EARLY_LOGD(TAG, "waiting for 32k oscillator to start up");
rtc_cal_sel_t cal_sel = 0;
if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
rtc_clk_32k_enable(true);
cal_sel = RTC_CAL_32K_XTAL;
} else if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
rtc_clk_32k_enable_external();
cal_sel = RTC_CAL_32K_OSC_SLOW;
}
// When SLOW_CLK_CAL_CYCLES is set to 0, clock calibration will not be performed at startup.
if (SLOW_CLK_CAL_CYCLES > 0) {
cal_val = rtc_clk_cal(cal_sel, SLOW_CLK_CAL_CYCLES);
if (cal_val == 0) {
if (retry_32k_xtal-- > 0) {
continue;
}
ESP_EARLY_LOGW(TAG, "32 kHz clock not found, switching to internal 150 kHz oscillator");
rtc_slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC_SLOW;
}
}
} else if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) {
rtc_clk_rc32k_enable(true);
}
rtc_clk_slow_src_set(rtc_slow_clk_src);
if (SLOW_CLK_CAL_CYCLES > 0) {
/* TODO: 32k XTAL oscillator has some frequency drift at startup.
* Improve calibration routine to wait until the frequency is stable.
*/
cal_val = rtc_clk_cal(RTC_CAL_RTC_MUX, SLOW_CLK_CAL_CYCLES);
} else {
const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL;
cal_val = (uint32_t) (cal_dividend / rtc_clk_slow_freq_get_hz());
}
} while (cal_val == 0);
ESP_EARLY_LOGD(TAG, "RTC_SLOW_CLK calibration value: %d", cal_val);
esp_clk_slowclk_cal_set(cal_val);
}
void rtc_clk_select_rtc_slow_clk(void)
{
select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_XTAL32K);
}
/* This function is not exposed as an API at this point.
* All peripheral clocks are default enabled after chip is powered on.
* This function disables some peripheral clocks when cpu starts.
* These peripheral clocks are enabled when the peripherals are initialized
* and disabled when they are de-initialized.
*/
__attribute__((weak)) void esp_perip_clk_init(void)
{
modem_clock_domain_pmu_state_icg_map_init();
ESP_EARLY_LOGW(TAG, "esp_perip_clk_init() has not been implemented yet");
#if 0 // TODO: IDF-5658
uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0;
uint32_t common_perip_clk1 = 0;
soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0);
/* For reason that only reset CPU, do not disable the clocks
* that have been enabled before reset.
*/
if (rst_reason == RESET_REASON_CPU0_MWDT0 || rst_reason == RESET_REASON_CPU0_SW ||
rst_reason == RESET_REASON_CPU0_RTC_WDT || rst_reason == RESET_REASON_CPU0_MWDT1) {
common_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN0_REG);
hwcrypto_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN1_REG);
wifi_bt_sdio_clk = ~READ_PERI_REG(SYSTEM_WIFI_CLK_EN_REG);
} else {
common_perip_clk = SYSTEM_WDG_CLK_EN |
SYSTEM_I2S0_CLK_EN |
#if CONFIG_ESP_CONSOLE_UART_NUM != 0
SYSTEM_UART_CLK_EN |
#endif
#if CONFIG_ESP_CONSOLE_UART_NUM != 1
SYSTEM_UART1_CLK_EN |
#endif
SYSTEM_SPI2_CLK_EN |
SYSTEM_I2C_EXT0_CLK_EN |
SYSTEM_UHCI0_CLK_EN |
SYSTEM_RMT_CLK_EN |
SYSTEM_LEDC_CLK_EN |
SYSTEM_TIMERGROUP1_CLK_EN |
SYSTEM_SPI3_CLK_EN |
SYSTEM_SPI4_CLK_EN |
SYSTEM_TWAI_CLK_EN |
SYSTEM_I2S1_CLK_EN |
SYSTEM_SPI2_DMA_CLK_EN |
SYSTEM_SPI3_DMA_CLK_EN;
common_perip_clk1 = 0;
hwcrypto_perip_clk = SYSTEM_CRYPTO_AES_CLK_EN |
SYSTEM_CRYPTO_SHA_CLK_EN |
SYSTEM_CRYPTO_RSA_CLK_EN;
wifi_bt_sdio_clk = SYSTEM_WIFI_CLK_WIFI_EN |
SYSTEM_WIFI_CLK_BT_EN_M |
SYSTEM_WIFI_CLK_UNUSED_BIT5 |
SYSTEM_WIFI_CLK_UNUSED_BIT12;
}
//Reset the communication peripherals like I2C, SPI, UART, I2S and bring them to known state.
common_perip_clk |= SYSTEM_I2S0_CLK_EN |
#if CONFIG_ESP_CONSOLE_UART_NUM != 0
SYSTEM_UART_CLK_EN |
#endif
#if CONFIG_ESP_CONSOLE_UART_NUM != 1
SYSTEM_UART1_CLK_EN |
#endif
SYSTEM_SPI2_CLK_EN |
SYSTEM_I2C_EXT0_CLK_EN |
SYSTEM_UHCI0_CLK_EN |
SYSTEM_RMT_CLK_EN |
SYSTEM_UHCI1_CLK_EN |
SYSTEM_SPI3_CLK_EN |
SYSTEM_SPI4_CLK_EN |
SYSTEM_I2C_EXT1_CLK_EN |
SYSTEM_I2S1_CLK_EN |
SYSTEM_SPI2_DMA_CLK_EN |
SYSTEM_SPI3_DMA_CLK_EN;
common_perip_clk1 = 0;
/* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock,
* the current is not reduced when disable I2S clock.
*/
// TOCK(check replacement)
// REG_SET_FIELD(I2S_CLKM_CONF_REG(0), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL);
// REG_SET_FIELD(I2S_CLKM_CONF_REG(1), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL);
/* Disable some peripheral clocks. */
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, common_perip_clk);
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, common_perip_clk);
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, common_perip_clk1);
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, common_perip_clk1);
/* Disable hardware crypto clocks. */
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, hwcrypto_perip_clk);
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, hwcrypto_perip_clk);
/* Disable WiFi/BT/SDIO clocks. */
CLEAR_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, wifi_bt_sdio_clk);
SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_EN);
/* Set WiFi light sleep clock source to RTC slow clock */
REG_SET_FIELD(SYSTEM_BT_LPCK_DIV_INT_REG, SYSTEM_BT_LPCK_DIV_NUM, 0);
CLEAR_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_8M);
SET_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_RTC_SLOW);
/* Enable RNG clock. */
periph_module_enable(PERIPH_RNG_MODULE);
#endif
}

View File

@ -0,0 +1,110 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_system.h"
#include "esp_rom_sys.h"
#include "esp_private/system_internal.h"
#include "soc/rtc_periph.h"
#include "esp32p4/rom/rtc.h"
static void esp_reset_reason_clear_hint(void);
static esp_reset_reason_t s_reset_reason;
static esp_reset_reason_t get_reset_reason(soc_reset_reason_t rtc_reset_reason, esp_reset_reason_t reset_reason_hint)
{
switch (rtc_reset_reason) {
case RESET_REASON_CHIP_POWER_ON:
return ESP_RST_POWERON;
case RESET_REASON_CPU0_SW:
case RESET_REASON_CORE_SW:
if (reset_reason_hint == ESP_RST_PANIC ||
reset_reason_hint == ESP_RST_BROWNOUT ||
reset_reason_hint == ESP_RST_TASK_WDT ||
reset_reason_hint == ESP_RST_INT_WDT) {
return reset_reason_hint;
}
return ESP_RST_SW;
case RESET_REASON_CORE_DEEP_SLEEP:
return ESP_RST_DEEPSLEEP;
case RESET_REASON_CORE_MWDT0:
return ESP_RST_TASK_WDT;
case RESET_REASON_CORE_MWDT1:
return ESP_RST_INT_WDT;
case RESET_REASON_CORE_RTC_WDT:
case RESET_REASON_SYS_RTC_WDT:
case RESET_REASON_SYS_SUPER_WDT:
case RESET_REASON_CPU0_RTC_WDT:
case RESET_REASON_CPU0_MWDT0:
case RESET_REASON_CPU0_MWDT1:
return ESP_RST_WDT;
case RESET_REASON_SYS_BROWN_OUT:
return ESP_RST_BROWNOUT;
default:
return ESP_RST_UNKNOWN;
}
}
static void __attribute__((constructor)) esp_reset_reason_init(void)
{
esp_reset_reason_t hint = esp_reset_reason_get_hint();
s_reset_reason = get_reset_reason(esp_rom_get_reset_reason(PRO_CPU_NUM), hint);
if (hint != ESP_RST_UNKNOWN) {
esp_reset_reason_clear_hint();
}
}
esp_reset_reason_t esp_reset_reason(void)
{
return s_reset_reason;
}
/* Reset reason hint is stored in RTC_RESET_CAUSE_REG, a.k.a. RTC_CNTL_STORE6_REG,
* a.k.a. RTC_ENTRY_ADDR_REG. It is safe to use this register both for the
* deep sleep wake stub entry address and for reset reason hint, since wake stub
* is only used for deep sleep reset, and in this case the reason provided by
* esp_rom_get_reset_reason is unambiguous.
*
* Same layout is used as for RTC_APB_FREQ_REG (a.k.a. RTC_CNTL_STORE5_REG):
* the value is replicated in low and high half-words. In addition to that,
* MSB is set to 1, which doesn't happen when RTC_CNTL_STORE6_REG contains
* deep sleep wake stub address.
*/
#define RST_REASON_BIT 0x80000000
#define RST_REASON_MASK 0x7FFF
#define RST_REASON_SHIFT 16
/* in IRAM, can be called from panic handler */
void IRAM_ATTR esp_reset_reason_set_hint(esp_reset_reason_t hint)
{
assert((hint & (~RST_REASON_MASK)) == 0);
uint32_t val = hint | (hint << RST_REASON_SHIFT) | RST_REASON_BIT;
REG_WRITE(RTC_RESET_CAUSE_REG, val);
}
/* in IRAM, can be called from panic handler */
esp_reset_reason_t IRAM_ATTR esp_reset_reason_get_hint(void)
{
uint32_t reset_reason_hint = REG_READ(RTC_RESET_CAUSE_REG);
uint32_t high = (reset_reason_hint >> RST_REASON_SHIFT) & RST_REASON_MASK;
uint32_t low = reset_reason_hint & RST_REASON_MASK;
if ((reset_reason_hint & RST_REASON_BIT) == 0 || high != low) {
return ESP_RST_UNKNOWN;
}
return (esp_reset_reason_t) low;
}
static inline void esp_reset_reason_clear_hint(void)
{
REG_WRITE(RTC_RESET_CAUSE_REG, 0);
}

View File

@ -0,0 +1,143 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "sdkconfig.h"
#include "esp_system.h"
#include "esp_private/system_internal.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_rom_sys.h"
#include "riscv/rv_utils.h"
#include "esp_rom_uart.h"
#include "soc/gpio_reg.h"
#include "esp_cpu.h"
#include "soc/rtc.h"
#include "esp_private/rtc_clk.h"
#include "soc/rtc_periph.h"
#include "soc/uart_reg.h"
#include "hal/wdt_hal.h"
#include "esp_private/cache_err_int.h"
#include "esp32p4/rom/cache.h"
#include "esp32p4/rom/rtc.h"
#include "soc/hp_sys_clkrst_reg.h"
#include "soc/lp_clkrst_reg.h"
#include "soc/hp_system_reg.h"
void IRAM_ATTR esp_system_reset_modules_on_exit(void)
{
// Flush any data left in UART FIFOs
esp_rom_uart_tx_wait_idle(0);
esp_rom_uart_tx_wait_idle(1);
// Set Peripheral clk rst
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_TIMERGRP0);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_TIMERGRP1);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_STIMER);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_DUAL_MSPI_AXI);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART0_CORE);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART1_CORE);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART2_CORE);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART3_CORE);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART4_CORE);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_GDMA);
// Clear Peripheral clk rst
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_TIMERGRP0);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_TIMERGRP1);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_STIMER);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_DUAL_MSPI_AXI);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART0_CORE);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART1_CORE);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART2_CORE);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART3_CORE);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART4_CORE);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_GDMA);
}
/* "inner" restart function for after RTOS, interrupts & anything else on this
* core are already stopped. Stalls other core, resets hardware,
* triggers restart.
*/
void IRAM_ATTR esp_restart_noos(void)
{
// Disable interrupts
rv_utils_intr_global_disable();
// Enable RTC watchdog for 1 second
wdt_hal_context_t rtc_wdt_ctx;
wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false);
uint32_t stage_timeout_ticks = (uint32_t)(1000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_SYSTEM);
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE1, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
//Enable flash boot mode so that flash booting after restart is protected by the RTC WDT.
wdt_hal_set_flashboot_en(&rtc_wdt_ctx, true);
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
const uint32_t core_id = esp_cpu_get_core_id();
#if !CONFIG_FREERTOS_UNICORE
const uint32_t other_core_id = (core_id == 0) ? 1 : 0;
esp_cpu_reset(other_core_id);
esp_cpu_stall(other_core_id);
#endif
// Disable TG0/TG1 watchdogs
wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
wdt_hal_write_protect_disable(&wdt0_context);
wdt_hal_disable(&wdt0_context);
wdt_hal_write_protect_enable(&wdt0_context);
wdt_hal_context_t wdt1_context = {.inst = WDT_MWDT1, .mwdt_dev = &TIMERG1};
wdt_hal_write_protect_disable(&wdt1_context);
wdt_hal_disable(&wdt1_context);
wdt_hal_write_protect_enable(&wdt1_context);
// Disable cache
Cache_Disable_L2_Cache();
esp_system_reset_modules_on_exit();
// Set CPU back to XTAL source, no PLL, same as hard reset
#if !CONFIG_IDF_ENV_FPGA
rtc_clk_cpu_freq_set_xtal();
#endif
#if !CONFIG_FREERTOS_UNICORE
// clear entry point for APP CPU
ets_set_appcpu_boot_addr(0);
#endif
#if CONFIG_SPIRAM_INSTRUCTIONS_RODATA
//TODO: IDF-7556
// disable remap if enabled in menuconfig
REG_CLR_BIT(HP_SYS_HP_PSRAM_FLASH_ADDR_INTERCHANGE_REG, HP_SYS_HP_PSRAM_FLASH_ADDR_INTERCHANGE_DMA | HP_SYS_HP_PSRAM_FLASH_ADDR_INTERCHANGE_CPU);
#endif
// Reset CPUs
if (core_id == 0) {
// Running on PRO CPU: APP CPU is stalled. Can reset both CPUs.
#if !CONFIG_FREERTOS_UNICORE
esp_cpu_reset(1);
#endif
esp_cpu_reset(0);
}
#if !CONFIG_FREERTOS_UNICORE
else {
// Running on APP CPU: need to reset PRO CPU and unstall it,
// then reset APP CPU
esp_cpu_reset(0);
esp_cpu_unstall(0);
esp_cpu_reset(1);
}
#endif
while (true) {
;
}
}

View File

@ -27,6 +27,8 @@
#include "esp32c6/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rtc.h"
#endif
#include "esp_private/startup_internal.h"

View File

@ -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
*/

View File

@ -37,6 +37,8 @@
#include "esp32c6/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rtc.h"
#endif
#include "sdkconfig.h"

View File

@ -192,9 +192,16 @@ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler)
#endif
| ESP_INTR_FLAG_IRAM;
#if !CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7486
esp_err_t err = esp_intr_alloc(ETS_SYSTIMER_TARGET2_EDGE_INTR_SOURCE, isr_flags,
&timer_alarm_isr, NULL,
&s_timer_interrupt_handle[(ISR_HANDLERS == 1) ? 0 : xPortGetCoreID()]);
#else
esp_err_t err = esp_intr_alloc(ETS_SYSTIMER_TARGET2_INTR_SOURCE, isr_flags,
&timer_alarm_isr, NULL,
&s_timer_interrupt_handle[(ISR_HANDLERS == 1) ? 0 : xPortGetCoreID()]);
#endif
if (err != ESP_OK) {
ESP_EARLY_LOGE(TAG, "esp_intr_alloc failed (0x%x)", err);
return err;

View File

@ -36,6 +36,8 @@
#include "esp32c6/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/ets_sys.h"
#endif
/* We abuse 'timer_arg' field of ETSTimer structure to hold a pointer to esp_timer */

View File

@ -31,6 +31,8 @@
#include "esp32c6/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rtc.h"
#endif
__attribute__((unused)) static const char* TAG = "system_time";

View File

@ -3,7 +3,7 @@
*
* 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
@ -160,6 +160,8 @@ BaseType_t xPortInterruptedFromISRContext(void);
* @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
* Owner:
@ -178,6 +180,11 @@ typedef struct {
uint32_t owner;
uint32_t count;
} portMUX_TYPE;
#else
typedef spinlock_t portMUX_TYPE; /**< Spinlock type used by FreeRTOS critical sections */
#endif
/**< Spinlock initializer */
#define portMUX_INITIALIZER_UNLOCKED { \
.owner = portMUX_FREE_VAL, \
@ -199,7 +206,12 @@ typedef struct {
* - Simply disable interrupts
* - Can be nested
*/
//TODO: IDF-7566
#if !CONFIG_IDF_TARGET_ESP32P4
void vPortEnterCritical(void);
#else
void vPortEnterCritical(portMUX_TYPE *mux);
#endif
/**
* @brief Exit a critical section
@ -207,7 +219,12 @@ void vPortEnterCritical(void);
* - Reenables interrupts
* - Can be nested
*/
//TODO: IDF-7566
#if !CONFIG_IDF_TARGET_ESP32P4
void vPortExitCritical(void);
#else
void vPortExitCritical(portMUX_TYPE *mux);
#endif
// ---------------------- Yielding -------------------------
@ -320,6 +337,8 @@ FORCE_INLINE_ATTR BaseType_t xPortGetCoreID(void)
// ------------------ Critical Sections --------------------
//TODO: IDF-7566
#if !CONFIG_IDF_TARGET_ESP32P4
#define portENTER_CRITICAL(mux) {(void)mux; vPortEnterCritical();}
#define portEXIT_CRITICAL(mux) {(void)mux; vPortExitCritical();}
#define portTRY_ENTER_CRITICAL(mux, timeout) ({ \
@ -328,6 +347,17 @@ FORCE_INLINE_ATTR BaseType_t xPortGetCoreID(void)
BaseType_t ret = pdPASS; \
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
#define portENTER_CRITICAL_ISR(mux) portENTER_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)
//TODO: IDF-7566
#if CONFIG_IDF_TARGET_ESP32P4
#define portCHECK_IF_IN_ISR() xPortInIsrContext()
#endif
// ---------------------- Yielding -------------------------
#define portYIELD() vPortYield()
@ -428,7 +462,13 @@ extern void vPortCleanUpTCB ( void *pxTCB );
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);
#endif
/* when enter critical code, FreeRTOS will mask threshold to RVHAL_EXCM_LEVEL
* and exit critical code, will recover threshold value (1). so threshold <= 1
* means not in critical code

View File

@ -3,7 +3,7 @@
*
* 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
@ -56,6 +56,10 @@
#include "portmacro.h"
#include "port_systick.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");
#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.
* @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];
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 --------------------------------------------------
@ -97,11 +122,19 @@ StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOIN
// ----------------- Scheduler Start/End -------------------
//TODO: IDF-7566
BaseType_t xPortStartScheduler(void)
{
#if !CONFIG_IDF_TARGET_ESP32P4
uxInterruptNesting = 0;
uxCriticalNesting = 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. */
vPortSetupTimer();
@ -312,15 +345,26 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC
// --------------------- Interrupts ------------------------
//TODO: IDF-7566
BaseType_t xPortInIsrContext(void)
{
#if !CONFIG_IDF_TARGET_ESP32P4
return uxInterruptNesting;
#else
BaseType_t coreID = xPortGetCoreID();
return uxInterruptNesting[coreID];
#endif
}
BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void)
{
/* For single core, this can be the same as xPortInIsrContext() because reading it is atomic */
#if !CONFIG_IDF_TARGET_ESP32P4
return uxInterruptNesting;
#else
BaseType_t coreID = xPortGetCoreID();
return uxInterruptNesting[coreID];
#endif
}
// ---------------------- Spinlocks ------------------------
@ -329,6 +373,8 @@ BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void)
// ------------------ Critical Sections --------------------
//TODO: IDF-7566
#if !CONFIG_IDF_TARGET_ESP32P4
void vPortEnterCritical(void)
{
BaseType_t state = portSET_INTERRUPT_MASK_FROM_ISR();
@ -349,15 +395,62 @@ 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 -------------------------
//TODO: IDF-7566
int vPortSetInterruptMask(void)
{
int ret;
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
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);
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);
/**
* TODO: IDF-7898
* Here is an issue that,
* 1. Set the CLIC_INT_THRESH_REG to mask off interrupts whose level is lower than `intlevel`.
* 2. Set MSTATUS_MIE (global interrupt), then program may jump to interrupt vector.
* 3. The register value change in Step 1 may happen during Step 2.
*
* To prevent this, here a fence is used
*/
rv_utils_memory_barrier();
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
#endif
/**
* In theory, this function should not return immediately as there is a
* delay between the moment we mask the interrupt threshold register and
@ -395,6 +488,8 @@ void vPortClearInterruptMask(int mask)
asm volatile ( "nop" );
}
//TODO: IDF-7566
#if !CONFIG_IDF_TARGET_ESP32P4
void vPortYield(void)
{
if (uxInterruptNesting) {
@ -423,6 +518,37 @@ void vPortYieldFromISR( void )
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)
{
esp_crosscore_int_send_yield(coreid);

View File

@ -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
*/
@ -12,6 +12,10 @@
.global uxInterruptNesting
.global uxSchedulerRunning
.global xIsrStackTop
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7566
.global xIsrStackTop1
#endif
.global pxCurrentTCB
.global vTaskSwitchContext
.global xPortSwitchFlag
@ -35,18 +39,40 @@
.global rtos_int_enter
.type rtos_int_enter, @function
rtos_int_enter:
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7861
/* 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 */
lw t0, uxSchedulerRunning
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 */
la t3, uxInterruptNesting
lw t4, 0x0(t3)
addi t5,t4,1
sw t5, 0x0(t3)
la t3, uxInterruptNesting
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7566
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 */
bne t4,zero, rtos_enter_end
bne t4,zero, rtos_enter_end
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
/* esp_hw_stack_guard_monitor_stop(); */
@ -54,9 +80,21 @@ rtos_int_enter:
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
/* Save current TCB and load the ISR stack */
//TODO: IDF-7566
#if !CONFIG_IDF_TARGET_ESP32P4
lw t0, pxCurrentTCB
sw sp, 0x0(t0)
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
/* esp_hw_stack_guard_set_bounds(xIsrStack, xIsrStackTop); */
@ -67,6 +105,10 @@ rtos_int_enter:
#endif /* CONFIG_ESP_SYSTEM_HW_STACK_GUARD */
rtos_enter_end:
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7861
mv ra, t1
#endif
ret
/**
@ -76,11 +118,25 @@ rtos_enter_end:
.type rtos_int_exit, @function
rtos_int_exit:
/* may skip RTOS aware interrupt since scheduler was not started */
//TODO: IDF-7566
#if !CONFIG_IDF_TARGET_ESP32P4
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
/* update nesting interrupts counter */
la t2, uxInterruptNesting
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7566
add t2, t2, t1
#endif
lw t3, 0x0(t2)
/* Already zero, protect against underflow */
@ -95,6 +151,10 @@ isr_skip_decrement:
/* Schedule the next task if a yield is pending */
la t0, xPortSwitchFlag
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7566
add t0, t0, t1
#endif
lw t2, 0x0(t0)
beq t2, zero, no_switch
@ -108,11 +168,19 @@ isr_skip_decrement:
/* Clears the switch pending flag */
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
sw t2, 0x0(t0)
no_switch:
#if !CONFIG_IDF_TARGET_ESP32P4 //TODO: IDF-7566
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
/* esp_hw_stack_guard_monitor_stop(); */
ESP_HW_STACK_GUARD_MONITOR_STOP_CPU0
@ -133,5 +201,16 @@ no_switch:
ESP_HW_STACK_GUARD_MONITOR_START_CPU0
#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:
ret

View File

@ -3,7 +3,7 @@
*
* 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() \
{ \
UBaseType_t uxTopPriority; \
@ -194,6 +196,17 @@
configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[ 0 ], &( pxReadyTasksLists[ uxTopPriority ] ) ); \
} /* 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
/*-----------------------------------------------------------*/

View File

@ -30,6 +30,7 @@ menu "FreeRTOS"
# Todo: Replace with CONFIG_NUM_CORES (IDF-4986)
bool "Run FreeRTOS only on first core"
default "y" if IDF_TARGET_ESP32S2 || IDF_TARGET_LINUX
default "y" if IDF_TARGET_ESP32P4 #TODO: IDF-7566
select ESP_SYSTEM_SINGLE_CORE_MODE
help
This version of FreeRTOS normally takes control of all cores of the CPU. Select this if you only want

View File

@ -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
*/
@ -111,10 +111,19 @@ void esp_startup_start_app_other_cores(void)
}
// Wait for CPU0 to start FreeRTOS before progressing
//TODO: IDF-7566
#if !CONFIG_IDF_TARGET_ESP32P4
extern volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS];
while (port_xSchedulerRunning[0] == 0) {
;
}
#else
extern volatile unsigned uxSchedulerRunning[portNUM_PROCESSORS];
while (uxSchedulerRunning[0] == 0) {
;
}
#endif
#if CONFIG_APPTRACE_ENABLE
// [refactor-todo] move to esp_system initialization

View File

@ -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
*/
@ -64,7 +64,17 @@ void vSystimerSetup(void)
/* Systimer HAL layer object */
static systimer_hal_context_t systimer_hal;
/* 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));
#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) {
periph_module_enable(PERIPH_SYSTIMER_MODULE);

View File

@ -1,13 +1,18 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/soc.h"
/* Since riscv does not replace mcause with "pseudo_reason" as it xtensa does
* PANIC_RSN_* defined with original interrupt numbers to make it work in
* common code
*/
#define PANIC_RSN_INTWDT_CPU0 ETS_INT_WDT_INUM
//TODO: IDF-7511
#if SOC_CPU_CORES_NUM > 1
#define PANIC_RSN_INTWDT_CPU1 ETS_INT_WDT_INUM
#endif
#define PANIC_RSN_CACHEERR 3

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -24,6 +24,9 @@ extern "C" {
#define CSR_PCMR_MACHINE 0x7e1
#define CSR_PCCR_MACHINE 0x7e2
//TODO: IDF-7771
#define RVHAL_EXCM_LEVEL 4
/* --------------------------------------------------- CPU Control -----------------------------------------------------
*
* ------------------------------------------------------------------------------------------------------------------ */
@ -33,6 +36,15 @@ FORCE_INLINE_ATTR void __attribute__((always_inline)) rv_utils_wait_for_intr(voi
asm volatile ("wfi\n");
}
/* ------------------------------------------------- Memory Barrier ----------------------------------------------------
*
* ------------------------------------------------------------------------------------------------------------------ */
//TODO: IDF-7898
FORCE_INLINE_ATTR void rv_utils_memory_barrier(void)
{
asm volatile("fence iorw, iorw" : : : "memory");
}
/* -------------------------------------------------- CPU Registers ----------------------------------------------------
*
* ------------------------------------------------------------------------------------------------------------------ */
@ -57,12 +69,22 @@ FORCE_INLINE_ATTR void *rv_utils_get_sp(void)
FORCE_INLINE_ATTR uint32_t __attribute__((always_inline)) rv_utils_get_cycle_count(void)
{
#if SOC_INT_CLIC_SUPPORTED
//TODO: IDF-7848
return RV_READ_CSR(mcycle);
#else
return RV_READ_CSR(CSR_PCCR_MACHINE);
#endif
}
FORCE_INLINE_ATTR void __attribute__((always_inline)) rv_utils_set_cycle_count(uint32_t ccount)
{
#if SOC_INT_CLIC_SUPPORTED
//TODO: IDF-7848
RV_WRITE_CSR(mcycle, ccount);
#else
RV_WRITE_CSR(CSR_PCCR_MACHINE, ccount);
#endif
}
/* ------------------------------------------------- CPU Interrupts ----------------------------------------------------
@ -72,10 +94,23 @@ FORCE_INLINE_ATTR void __attribute__((always_inline)) rv_utils_set_cycle_count(u
// ---------------- Interrupt Descriptors ------------------
// --------------- Interrupt Configuration -----------------
#if SOC_INT_CLIC_SUPPORTED
//TODO: IDF-7863
FORCE_INLINE_ATTR void rv_utils_set_mtvt(uint32_t mtvt_val)
{
#define MTVT 0x307
RV_WRITE_CSR(MTVT, mtvt_val);
}
#endif
FORCE_INLINE_ATTR void rv_utils_set_mtvec(uint32_t mtvec_val)
{
#if SOC_INT_CLIC_SUPPORTED
//TODO: IDF-7863
mtvec_val |= 3;
#else
mtvec_val |= 1; // Set MODE field to treat MTVEC as a vector base address
#endif
RV_WRITE_CSR(mtvec, mtvec_val);
}
@ -97,14 +132,62 @@ FORCE_INLINE_ATTR void rv_utils_intr_disable(uint32_t intr_mask)
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
}
//TODO: IDF-7795, clic related
#if (SOC_CPU_CORES_NUM > 1)
FORCE_INLINE_ATTR void __attribute__((always_inline)) rv_utils_restore_intlevel(uint32_t restoreval)
{
REG_SET_FIELD(CLIC_INT_THRESH_REG, CLIC_CPU_INT_THRESH, ((restoreval << (8 - NLBITS))) | 0x1f);
}
FORCE_INLINE_ATTR uint32_t __attribute__((always_inline)) rv_utils_set_intlevel(uint32_t intlevel)
{
uint32_t old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
uint32_t old_thresh;
old_thresh = REG_READ(CLIC_INT_THRESH_REG);
old_thresh = old_thresh >> (24 + (8 - NLBITS));
REG_SET_FIELD(CLIC_INT_THRESH_REG, CLIC_CPU_INT_THRESH, ((intlevel << (8 - NLBITS))) | 0x1f);
/**
* TODO: IDF-7898
* Here is an issue that,
* 1. Set the CLIC_INT_THRESH_REG to mask off interrupts whose level is lower than `intlevel`.
* 2. Set MSTATUS_MIE (global interrupt), then program may jump to interrupt vector.
* 3. The register value change in Step 1 may happen during Step 2.
*
* To prevent this, here a fence is used
*/
rv_utils_memory_barrier();
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
return old_thresh;
}
#endif //#if (SOC_CPU_CORES_NUM > 1)
FORCE_INLINE_ATTR uint32_t rv_utils_intr_get_enabled_mask(void)
{
//TODO: IDF-7795
#if SOC_INT_CLIC_SUPPORTED
unsigned intr_ena_mask = 0;
unsigned intr_num;
for (intr_num = 0; intr_num < 32; intr_num++) {
if (REG_GET_BIT(CLIC_INT_CTRL_REG(intr_num + CLIC_EXT_INTR_NUM_OFFSET), CLIC_INT_IE))
intr_ena_mask |= BIT(intr_num);
}
return intr_ena_mask;
#else
return REG_READ(INTERRUPT_CORE0_CPU_INT_ENABLE_REG);
#endif
}
FORCE_INLINE_ATTR void rv_utils_intr_edge_ack(unsigned int intr_num)
{
//TODO: IDF-7795
#if SOC_INT_CLIC_SUPPORTED
REG_SET_BIT(CLIC_INT_CTRL_REG(intr_num + CLIC_EXT_INTR_NUM_OFFSET) , CLIC_INT_IP);
#else
REG_SET_BIT(INTERRUPT_CORE0_CPU_INT_CLEAR_REG, intr_num);
#endif
}
FORCE_INLINE_ATTR void rv_utils_intr_global_enable(void)
@ -229,6 +312,17 @@ FORCE_INLINE_ATTR bool rv_utils_compare_and_set(volatile uint32_t *addr, uint32_
return (old_value == compare_value);
}
#if SOC_BRANCH_PREDICTOR_SUPPORTED
FORCE_INLINE_ATTR void rv_utils_en_branch_predictor(void)
{
#define MHCR 0x7c1
#define MHCR_RS (1<<4) /* R/W, address return stack set bit */
#define MHCR_BFE (1<<5) /* R/W, allow predictive jump set bit */
#define MHCR_BTB (1<<12) /* R/W, branch target prediction enable bit */
RV_SET_CSR(MHCR, MHCR_RS|MHCR_BFE|MHCR_BTB);
}
#endif
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -11,12 +11,21 @@
#include "soc/interrupt_reg.h"
#include "riscv/csr.h"
#include "esp_attr.h"
#include "riscv/rv_utils.h"
//TODO: IDF-7795, P4, see jira to know what changed and what need to be checked
#define RV_INT_COUNT 32
static inline void assert_valid_rv_int_num(int rv_int_num)
{
#if SOC_INT_CLIC_SUPPORTED
assert(rv_int_num < RV_INT_COUNT && "Invalid CPU interrupt number");
#else
assert(rv_int_num != 0 && rv_int_num < RV_INT_COUNT && "Invalid CPU interrupt number");
#endif
}
/*************************** Software interrupt dispatcher ***************************/
@ -27,63 +36,132 @@ typedef struct {
void *arg;
} intr_handler_item_t;
#if SOC_INT_CLIC_SUPPORTED
static intr_handler_item_t s_intr_handlers_core0[48];
static intr_handler_item_t s_intr_handlers_core1[48];
#else
static intr_handler_item_t s_intr_handlers[32];
#endif
void intr_handler_set(int int_no, intr_handler_t fn, void *arg)
{
assert_valid_rv_int_num(int_no);
#if SOC_INT_CLIC_SUPPORTED
if (rv_utils_get_core_id() == 0) {
s_intr_handlers_core0[int_no + CLIC_EXT_INTR_NUM_OFFSET] = (intr_handler_item_t) {
.handler = fn,
.arg = arg,
};
} else {
s_intr_handlers_core1[int_no + CLIC_EXT_INTR_NUM_OFFSET] = (intr_handler_item_t) {
.handler = fn,
.arg = arg,
};
}
#else
s_intr_handlers[int_no] = (intr_handler_item_t) {
.handler = fn,
.arg = arg
};
#endif
}
intr_handler_t intr_handler_get(int rv_int_num)
{
#if SOC_INT_CLIC_SUPPORTED
if (rv_utils_get_core_id() == 0)
return s_intr_handlers_core0[rv_int_num + CLIC_EXT_INTR_NUM_OFFSET].handler;
else
return s_intr_handlers_core1[rv_int_num + CLIC_EXT_INTR_NUM_OFFSET].handler;
#else
return s_intr_handlers[rv_int_num].handler;
#endif
}
void *intr_handler_get_arg(int rv_int_num)
{
#if SOC_INT_CLIC_SUPPORTED
if (rv_utils_get_core_id() == 0)
return s_intr_handlers_core0[rv_int_num + CLIC_EXT_INTR_NUM_OFFSET].arg;
else
return s_intr_handlers_core1[rv_int_num + CLIC_EXT_INTR_NUM_OFFSET].arg;
#else
return s_intr_handlers[rv_int_num].arg;
#endif
}
/* called from vectors.S */
void _global_interrupt_handler(intptr_t sp, int mcause)
{
#if SOC_INT_CLIC_SUPPORTED
if (rv_utils_get_core_id() == 0) {
intr_handler_item_t it = s_intr_handlers_core0[mcause];
if (it.handler) {
(*it.handler)(it.arg);
}
} else {
intr_handler_item_t it = s_intr_handlers_core1[mcause];
if (it.handler) {
(*it.handler)(it.arg);
}
}
#else
intr_handler_item_t it = s_intr_handlers[mcause];
if (it.handler) {
(*it.handler)(it.arg);
}
#endif
}
/*************************** RISC-V interrupt enable/disable ***************************/
void intr_matrix_route(int intr_src, int intr_num)
{
#if !SOC_INT_CLIC_SUPPORTED
assert(intr_num != 0);
REG_WRITE(DR_REG_INTERRUPT_BASE + 4 * intr_src, intr_num);
#else
if (rv_utils_get_core_id() == 0)
REG_WRITE(DR_REG_INTERRUPT_CORE0_BASE + 4 * intr_src, intr_num + CLIC_EXT_INTR_NUM_OFFSET);
else
REG_WRITE(DR_REG_INTERRUPT_CORE1_BASE + 4 * intr_src, intr_num + CLIC_EXT_INTR_NUM_OFFSET);
#endif
}
// CLIC for each interrupt line provides a IE register
// this api is not used
#if !SOC_INT_CLIC_SUPPORTED
uint32_t esprv_intc_get_interrupt_unmask(void)
{
return REG_READ(INTERRUPT_CORE0_CPU_INT_ENABLE_REG);
}
#endif
/*************************** ESP-RV Interrupt Controller ***************************/
enum intr_type esprv_intc_int_get_type(int intr_num)
{
#if SOC_INT_CLIC_SUPPORTED
uint32_t intr_type_reg = REG_GET_FIELD(CLIC_INT_CTRL_REG(intr_num + CLIC_EXT_INTR_NUM_OFFSET), CLIC_INT_ATTR_TRIG);
return (intr_type_reg & 1) ? INTR_TYPE_EDGE : INTR_TYPE_LEVEL;
// May also support rising edge and falling edge.
#else
uint32_t intr_type_reg = REG_READ(INTERRUPT_CORE0_CPU_INT_TYPE_REG);
return (intr_type_reg & (1 << intr_num)) ? INTR_TYPE_EDGE : INTR_TYPE_LEVEL;
#endif
}
int esprv_intc_int_get_priority(int rv_int_num)
{
#if SOC_INT_CLIC_SUPPORTED
uint32_t intr_priority_reg = REG_GET_FIELD(CLIC_INT_CTRL_REG(rv_int_num + CLIC_EXT_INTR_NUM_OFFSET), CLIC_INT_CTL);
return (intr_priority_reg >> (8 - NLBITS));
#else
uint32_t intr_priority_reg = REG_READ(INTC_INT_PRIO_REG(rv_int_num));
return intr_priority_reg;
#endif
}
/*************************** Exception names. Used in .gdbinit file. ***************************/

View File

@ -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
*/
@ -117,12 +117,23 @@
* only uses the 24 MSBs of the MTVEC, i.e. (MTVEC & 0xffffff00).
*/
/**
* TODO: IDF-7863, P4, see jira to know what changed and what need to be checked
*/
#if SOC_INT_CLIC_SUPPORTED
.balign 0x40
#else
.balign 0x100
#endif
.global _vector_table
.type _vector_table, @function
_vector_table:
.option push
.option norvc
#if SOC_INT_CLIC_SUPPORTED
j _trap_handler
#else
j _panic_handler /* exception handler, entry 0 */
#if ETS_INT_WDT_INUM != 24
#error "ETS_INT_WDT_INUM expected to be 24"
@ -145,10 +156,41 @@ _vector_table:
.rept (ETS_MAX_INUM - ETS_ASSIST_DEBUG_INUM)
j _interrupt_handler /* remain entries are identical, all pointing to the interrupt handler */
.endr
#endif
.option pop
.size _vector_table, .-_vector_table
#if SOC_INT_CLIC_SUPPORTED
.balign 0x40
.global _mtvt_table
.type _mtvt_table, @function
_mtvt_table:
.option push
.option norvc
.rept 48
.word _interrupt_handler
.endr
.option pop
.size _mtvt_table, .-_mtvt_table
#endif
#if SOC_INT_CLIC_SUPPORTED
.type _trap_handler, @function
_trap_handler:
addi sp, sp, -RV_STK_FRMSZ
sw t0, RV_STK_T0(sp)
sw t1, RV_STK_T1(sp)
csrr t0, mcause
li t1, 0x80000000
bltu t0, t1, _panic_handler
lw t0, RV_STK_T0(sp)
lw t1, RV_STK_T1(sp)
addi sp, sp, RV_STK_FRMSZ
//ESP32P4-TODO: ETS_T1_WDT_INUM/ETS_CACHEERR_INUM/ETS_MEMPROT_ERR_INUM
j _interrupt_handler
.size _trap_handler, .-_trap_handler
#endif
/* Exception handler.*/
.type _panic_handler, @function
_panic_handler:
@ -182,6 +224,15 @@ _panic_handler:
mv a0, sp
csrr a1, mcause
/*
* MINHV[30]: CPU is fetching vector interrupt entry address or not
* MPP[29:28]: MSTATUS.MPP[1:0]
* MPIL[23:16]: interrupt level before entrering interrupt isr
*/
#if SOC_INT_CLIC_SUPPORTED
la t1, 0x80000fff
and a1, a1, t1
#endif
/* Branches instructions don't accept immediates values, so use t1 to
* store our comparator */
li t0, 0x80000000
@ -249,6 +300,12 @@ _interrupt_handler:
/* Save SP */
sw t0, RV_STK_SP(sp)
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7861
/* Before doing anythig preserve the stack pointer */
/* It will be saved in current TCB, if needed */
mv a0, sp
#endif //#if CONFIG_IDF_TARGET_ESP32P4
call rtos_int_enter
/* If this is a non-nested interrupt, SP now points to the interrupt stack */
@ -256,6 +313,7 @@ _interrupt_handler:
csrr s1, mcause
csrr s2, mstatus
#if !SOC_INT_CLIC_SUPPORTED
/* Save the interrupt threshold level */
li t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG
lw s3, 0(t0)
@ -270,6 +328,7 @@ _interrupt_handler:
addi t2, t2, 1 /* t2 = t2 +1 */
sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */
fence
#endif
li t0, 0x8
csrrs t0, mstatus, t0
@ -295,7 +354,11 @@ _interrupt_handler:
mv a0, sp /* argument 1, stack pointer */
mv a1, s1 /* argument 2, interrupt number (mcause) */
/* mask off the interrupt flag of mcause */
#if !SOC_INT_CLIC_SUPPORTED
li t0, 0x7fffffff
#else
li t0, 0x00000fff
#endif
and a1, a1, t0
jal _global_interrupt_handler
@ -305,13 +368,25 @@ _interrupt_handler:
csrrc t0, mstatus, t0
/* MIE cleared. Nested interrupts are disabled */
#if !SOC_INT_CLIC_SUPPORTED
/* restore the interrupt threshold level */
li t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG
sw s3, 0(t0)
fence
#endif
#if SOC_INT_CLIC_SUPPORTED
/* Yield to the next task is needed: */
mv a0, sp
#endif
call rtos_int_exit
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7861
/* The next (or current) stack pointer is returned in a0 */
mv sp, a0
#endif //#if CONFIG_IDF_TARGET_ESP32P4
/* restore the rest of the registers */
csrw mcause, s1
csrw mstatus, s2

View File

@ -61,9 +61,9 @@ typedef enum {
ETS_RMT_INTR_SOURCE,
ETS_I2C0_INTR_SOURCE,
ETS_I2C1_INTR_SOURCE,
ETS_TIMERGROUP0_T0_INTR_SOURCE,
ETS_TIMERGROUP0_T1_INTR_SOURCE,
ETS_TIMERGROUP0_WDT_INTR_SOURCE,
ETS_TG0_WDT_LEVEL_INTR_SOURCE,
ETS_TG1_WDT_LEVEL_INTR_SOURCE,
ETS_TG0_WDT_INTR_SOURCE,
ETS_TIMERGROUP1_T0_INTR_SOURCE,
ETS_TIMERGROUP1_T1_INTR_SOURCE,
ETS_TIMERGROUP1_WDT_INTR_SOURCE,
@ -96,10 +96,10 @@ typedef enum {
ETS_GPIO_INTR2_SOURCE,
ETS_GPIO_INTR3_SOURCE,
ETS_GPIO_PAD_COMP_INTR_SOURCE,
ETS_CPU_INT_FROM_CPU0_INTR_SOURCE,
ETS_CPU_INT_FROM_CPU1_INTR_SOURCE,
ETS_CPU_INT_FROM_CPU2_INTR_SOURCE,
ETS_CPU_INT_FROM_CPU3_INTR_SOURCE,
ETS_FROM_CPU_INTR0_SOURCE,
ETS_FROM_CPU_INTR1_SOURCE,
ETS_FROM_CPU_INTR2_SOURCE,
ETS_FROM_CPU_INTR3_SOURCE,
ETS_CACHE_INTR_SOURCE,
ETS_MSPI_INTR_SOURCE,
ETS_CSI_BRIDGE_INTR_SOURCE,

View File

@ -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
*/
@ -39,6 +39,8 @@
#include "esp32h2/rom/cache.h"
#include "soc/extmem_reg.h"
#include "soc/ext_mem_defs.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/cache.h"
#endif
#include "esp_rom_spiflash.h"
#include "hal/cache_hal.h"
@ -914,3 +916,28 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable)
return ESP_OK;
}
#endif // CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-5670
TCM_IRAM_ATTR void esp_config_llc_mode(void)
{
cache_size_t cache_size;
cache_line_size_t cache_line_size;
#if CONFIG_ESP32P4_L2_CACHE_128KB
cache_size = CACHE_SIZE_128K;
#elif CONFIG_ESP32P4_L2_CACHE_256KB
cache_size = CACHE_SIZE_256K;
#else
cache_size = CACHE_SIZE_512K;
#endif
#if CONFIG_ESP32P4_L2_CACHE_LINE_64B
cache_line_size = CACHE_LINE_SIZE_64B;
#else
cache_line_size = CACHE_LINE_SIZE_128B;
#endif
Cache_Set_L2_Cache_Mode(cache_size, 8, cache_line_size);
Cache_Invalidate_All(CACHE_MAP_L2_CACHE);
}
#endif