mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
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:
commit
6bc9a39010
@ -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)
|
||||
|
||||
|
@ -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+
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
441
components/esp_system/ld/esp32p4/sections.ld.in
Normal file
441
components/esp_system/ld/esp32p4/sections.ld.in
Normal 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.")
|
@ -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[] = {
|
||||
|
@ -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();
|
||||
|
@ -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})
|
43
components/esp_system/port/soc/esp32p4/Kconfig.cache
Normal file
43
components/esp_system/port/soc/esp32p4/Kconfig.cache
Normal 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
|
61
components/esp_system/port/soc/esp32p4/cache_err_int.c
Normal file
61
components/esp_system/port/soc/esp32p4/cache_err_int.c
Normal 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;
|
||||
}
|
277
components/esp_system/port/soc/esp32p4/clk.c
Normal file
277
components/esp_system/port/soc/esp32p4/clk.c
Normal 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
|
||||
}
|
110
components/esp_system/port/soc/esp32p4/reset_reason.c
Normal file
110
components/esp_system/port/soc/esp32p4/reset_reason.c
Normal 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);
|
||||
}
|
143
components/esp_system/port/soc/esp32p4/system_internal.c
Normal file
143
components/esp_system/port/soc/esp32p4/system_internal.c
Normal 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) {
|
||||
;
|
||||
}
|
||||
}
|
@ -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"
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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. ***************************/
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user