soc: esp32s3: add esp32s3_appcpu for AMP support

Adds esp32s3_appcpu SoC and update default esp32s3 SoC
to support AMP feature.

Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
This commit is contained in:
Sylvio Alves 2023-08-30 17:10:01 -03:00 committed by Carles Cufí
commit bdda8ac48e
16 changed files with 769 additions and 30 deletions

View file

@ -328,6 +328,11 @@ static void esp32_clock_perip_init(void)
#if defined(CONFIG_SOC_SERIES_ESP32S3)
static void esp32_clock_perip_init(void)
{
#if defined(CONFIG_SOC_ESP32S3_APPCPU)
/* skip APPCPU configuration */
return;
#endif
uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0;
uint32_t common_perip_clk1 = 0;

View file

@ -54,9 +54,17 @@ IRAM_ATTR static void esp32_ipm_isr(const struct device *dev)
/* clear interrupt flag */
if (core_id == 0) {
#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32_NET)
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, 0);
#elif defined(CONFIG_SOC_SERIES_ESP32S3)
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0);
#endif
} else {
#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32_NET)
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_1_REG, 0);
#elif defined(CONFIG_SOC_SERIES_ESP32S3)
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_1_REG, 0);
#endif
}
/* first of all take the own of the shared memory */
@ -130,12 +138,21 @@ static int esp32_ipm_send(const struct device *dev, int wait, uint32_t id,
memcpy(dev_data->shm.app_cpu_shm, data, size);
atomic_set(&dev_data->control->lock, ESP32_IPM_LOCK_FREE_VAL);
LOG_DBG("Generating interrupt on remote CPU 1 from CPU 0");
#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32_NET)
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_1_REG, DPORT_CPU_INTR_FROM_CPU_1);
#elif defined(CONFIG_SOC_SERIES_ESP32S3)
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_1_REG, SYSTEM_CPU_INTR_FROM_CPU_1);
#endif
} else {
memcpy(dev_data->shm.pro_cpu_shm, data, size);
atomic_set(&dev_data->control->lock, ESP32_IPM_LOCK_FREE_VAL);
LOG_DBG("Generating interrupt on remote CPU 0 from CPU 1");
#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32_NET)
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, DPORT_CPU_INTR_FROM_CPU_0);
#elif defined(CONFIG_SOC_SERIES_ESP32S3)
WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, SYSTEM_CPU_INTR_FROM_CPU_0);
#endif
}
irq_unlock(key);
@ -217,7 +234,6 @@ static int esp32_ipm_init(const struct device *dev)
NULL);
LOG_DBG("Waiting CPU0 to sync");
while (!atomic_cas(&data->control->lock,
ESP32_IPM_LOCK_FREE_VAL, data->this_core_id))
;

View file

@ -13,7 +13,7 @@
#include <errno.h>
#include <soc.h>
#include <zephyr/drivers/uart.h>
#if defined(CONFIG_SOC_ESP32C3)
#if defined(CONFIG_SOC_SERIES_ESP32C3)
#include <zephyr/drivers/interrupt_controller/intc_esp32c3.h>
#else
#include <zephyr/drivers/interrupt_controller/intc_esp32.h>
@ -22,7 +22,7 @@
#include <zephyr/sys/util.h>
#include <esp_attr.h>
#ifdef CONFIG_SOC_ESP32C3
#ifdef CONFIG_SOC_SERIES_ESP32C3
#define ISR_HANDLER isr_handler_t
#else
#define ISR_HANDLER intr_handler_t

View file

@ -0,0 +1,7 @@
/*
* Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp32s3_common.dtsi"

View file

@ -58,6 +58,16 @@
reg = <0x3fc88000 0x77FFF>;
};
ipmmem0: memory@3fcbd000 {
compatible = "mmio-sram";
reg = <0x3fcbd000 0x400>;
};
shm0: memory@3fcbd400 {
compatible = "mmio-sram";
reg = <0x3fcbd400 0x4000>;
};
intc: interrupt-controller@600c2000 {
#interrupt-cells = <1>;
compatible = "espressif,esp32-intc";
@ -107,6 +117,16 @@
status = "disabled";
};
ipm0: ipm@3fcc1400 {
compatible = "espressif,esp32-ipm";
reg = <0x3fcc1400 0x8>;
status = "disabled";
shared-memory = <&ipmmem0>;
shared-memory-size = <0x400>;
interrupts = <FROM_CPU_INTR0_SOURCE FROM_CPU_INTR1_SOURCE>;
interrupt-parent = <&intc>;
};
uart0: uart@60000000 {
compatible = "espressif,esp32-uart";
reg = <0x60000000 0x1000>;

View file

@ -1,21 +1,18 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_sources(
soc.c
soc_cache.c
loader.c
)
if (CONFIG_SOC_ESP32S3_APPCPU)
zephyr_sources(soc_appcpu.c)
else()
zephyr_sources(
soc.c
soc_cache.c
loader.c
esp32s3-mp.c
)
endif()
zephyr_library_sources_ifdef(CONFIG_NEWLIB_LIBC newlib_fix.c)
# get code-partition slot0 address
dt_nodelabel(dts_partition_path NODELABEL "slot0_partition")
dt_reg_addr(img_0_off PATH ${dts_partition_path})
# get code-partition boot address
dt_nodelabel(dts_partition_path NODELABEL "boot_partition")
dt_reg_addr(boot_off PATH ${dts_partition_path})
# get flash size to use in esptool as string
math(EXPR esptoolpy_flashsize "${CONFIG_FLASH_SIZE} / 0x100000")
@ -87,8 +84,31 @@ if(CONFIG_MCUBOOT OR CONFIG_BOOTLOADER_ESP_IDF)
endif()
set_property(TARGET bintools PROPERTY disassembly_flag_inline_source)
## When building for APPCPU
if (CONFIG_SOC_ESP32S3_APPCPU)
board_finalize_runner_args(esp32 "--esp-boot-address=${boot_off}")
if(CONFIG_BUILD_OUTPUT_BIN)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
COMMAND ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/tools/esp_bin2c_array.py
ARGS -i ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin
-o ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.c
-a "esp32s3_appcpu_fw_array")
endif()
board_finalize_runner_args(esp32 "--esp-app-address=${img_0_off}")
else()
set_property(TARGET bintools PROPERTY disassembly_flag_inline_source)
# get code-partition slot0 address
dt_nodelabel(dts_partition_path NODELABEL "slot0_partition")
dt_reg_addr(img_0_off PATH ${dts_partition_path})
# get code-partition boot address
dt_nodelabel(dts_partition_path NODELABEL "boot_partition")
dt_reg_addr(boot_off PATH ${dts_partition_path})
board_finalize_runner_args(esp32 "--esp-boot-address=${boot_off}")
board_finalize_runner_args(esp32 "--esp-app-address=${img_0_off}")
endif()

View file

@ -12,5 +12,17 @@ config SOC_SERIES_ESP32S3
select XIP if !MCUBOOT
select HAS_ESPRESSIF_HAL
select CPU_HAS_FPU
config SOC_ESP32S3_PROCPU
bool "Application runs in ESP32S3 PROCPU (core 0)"
depends on SOC_SERIES_ESP32S3
help
Enable support for Espressif ESP32-S3
When this SOC is enabled, it will run application on PROCPU (core 0). It will automatically
enable AMP support by building, flashing and loading APPCPU (core 1) image if exists.
config SOC_ESP32S3_APPCPU
bool "Application runs in ESP32S3 APPCPU (core 1)"
depends on SOC_SERIES_ESP32S3
help
When this SOC is enabled, it will run application on APPCPU (core 1). It is expected that
there is another image running on PROCPU (core 0) to trigger the AMP support.

View file

@ -13,11 +13,8 @@ config SOC_TOOLCHAIN_NAME
choice SOC_PART_NUMBER
prompt "ESP32-S3 SOC Selection"
depends on SOC_SERIES_ESP32S3
# SoC with/without embedded flash
config SOC_ESP32S3
bool "ESP32S3"
config SOC_ESP32S3_R2
bool "ESP32S3_R2"
config SOC_ESP32S3_R8
@ -50,6 +47,20 @@ choice SOC_PART_NUMBER
endchoice # SOC_PART_NUMBER
config ESP32S3_APPCPU_IRAM
hex "ESP32S3 APPCPU IRAM size"
depends on SOC_ESP32S3_PROCPU || SOC_ESP32S3_APPCPU
default 0x20000
help
Defines APPCPU IRAM area in bytes.
config ESP32S3_APPCPU_DRAM
hex "ESP32S3 APPCPU DRAM size"
depends on SOC_ESP32S3_PROCPU || SOC_ESP32S3_APPCPU
default 0x10000
help
Defines APPCPU DRAM area in bytes.
choice ESP32S3_RTC_CLK_SRC
prompt "RTC clock source"
default ESP32S3_RTC_CLK_SRC_INT_RC

View file

@ -57,6 +57,14 @@
#define IROM_SEG_LEN FLASH_SIZE
#endif
#ifdef CONFIG_SOC_ESP32S3_PROCPU
#define APPCPU_IRAM_SIZE CONFIG_ESP32S3_APPCPU_IRAM
#define APPCPU_DRAM_SIZE CONFIG_ESP32S3_APPCPU_DRAM
#else
#define APPCPU_IRAM_SIZE 0x0
#define APPCPU_DRAM_SIZE 0x0
#endif
#define IROM_SEG_ALIGN 0x10000
/* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA.
@ -69,9 +77,10 @@ MEMORY
mcuboot_hdr (RX): org = 0x0, len = 0x20
metadata (RX): org = 0x20, len = 0x20
ROM (RX): org = 0x40, len = FLASH_SIZE - 0x40
iram0_0_seg(RX): org = SRAM_IRAM_ORG, len = SRAM_IRAM_SIZE
iram0_0_seg(RX): org = SRAM_IRAM_ORG, len = SRAM_IRAM_SIZE - APPCPU_IRAM_SIZE
dram0_0_seg(RW): org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN - APPCPU_DRAM_SIZE
irom0_0_seg(RX): org = IROM_SEG_ORG, len = IROM_SEG_LEN
dram0_0_seg(RW): org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN
/* DROM is the first segment placed in generated binary.
* MCUboot binary for ESP32 has image header of 0x20 bytes.
@ -86,6 +95,7 @@ MEMORY
#if defined(CONFIG_ESP_SPIRAM)
ext_ram_seg(RWX): org = EXT_RAM_ORG, len = CONFIG_ESP_SPIRAM_SIZE
#endif
/* RTC fast memory (executable). Persists over deep sleep.
*/
rtc_iram_seg(RWX): org = 0x600fe000, len = 0x2000

View file

@ -0,0 +1,372 @@
/*
* Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd.
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/devicetree.h>
#include <zephyr/linker/sections.h>
#include <zephyr/linker/linker-defs.h>
#include <zephyr/linker/linker-tool.h>
#define SRAM_IRAM_START 0x40370000
#define SRAM_DIRAM_I_START 0x40378000
#define SRAM_IRAM_END 0x403BA000
#define I_D_SRAM_OFFSET (SRAM_DIRAM_I_START - SRAM_DRAM_START)
#define SRAM_DRAM_START 0x3FC88000
#define SRAM_DRAM_END (SRAM_IRAM_END - I_D_SRAM_OFFSET)
#define IRAM_REGION iram0_0_seg
#define RAMABLE_REGION dram0_0_seg
#define ROMABLE_REGION iram0_0_seg
#define IROM_SEG_ALIGN 0x4
MEMORY
{
iram0_0_seg(RX): org = SRAM_IRAM_END - CONFIG_ESP32S3_APPCPU_IRAM, len = CONFIG_ESP32S3_APPCPU_IRAM
dram0_0_seg(RW): org = SRAM_DRAM_END - CONFIG_ESP32S3_APPCPU_DRAM, len = CONFIG_ESP32S3_APPCPU_DRAM
#ifdef CONFIG_GEN_ISR_TABLES
IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000
#endif
}
/* Default entry point: */
ENTRY(__app_cpu_start)
SECTIONS
{
#include <zephyr/linker/rel-sections.ld>
/* Send .iram0 code to iram */
.iram0.vectors : ALIGN(4)
{
/* Vectors go to IRAM */
_init_start = ABSOLUTE(.);
/* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */
. = 0x0;
KEEP(*(.WindowVectors.text));
. = 0x180;
KEEP(*(.Level2InterruptVector.text));
. = 0x1c0;
KEEP(*(.Level3InterruptVector.text));
. = 0x200;
KEEP(*(.Level4InterruptVector.text));
. = 0x240;
KEEP(*(.Level5InterruptVector.text));
. = 0x280;
KEEP(*(.DebugExceptionVector.text));
. = 0x2c0;
KEEP(*(.NMIExceptionVector.text));
. = 0x300;
KEEP(*(.KernelExceptionVector.text));
. = 0x340;
KEEP(*(.UserExceptionVector.text));
. = 0x3C0;
KEEP(*(.DoubleExceptionVector.text));
. = 0x400;
_invalid_pc_placeholder = ABSOLUTE(.);
*(.*Vector.literal)
*(.UserEnter.literal);
*(.UserEnter.text);
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
. = ALIGN (4);
_init_end = ABSOLUTE(.);
_iram_start = ABSOLUTE(.);
} GROUP_LINK_IN(IRAM_REGION)
SECTION_PROLOGUE(_TEXT_SECTION_NAME, , ALIGN(4))
{
/* Code marked as running out of IRAM */
_iram_text_start = ABSOLUTE(.);
*(.iram1 .iram1.*)
*(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text)
*libesp32.a:panic.*(.literal .text .literal.* .text.*)
*librtc.a:(.literal .text .literal.* .text.*)
*libarch__xtensa__core.a:(.literal .text .literal.* .text.*)
*libkernel.a:(.literal .text .literal.* .text.*)
*libsoc.a:rtc_*.*(.literal .text .literal.* .text.*)
*libsoc.a:cpu_util.*(.literal .text .literal.* .text.*)
*libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*)
*libdrivers__flash.a:flash_esp32.*(.literal .text .literal.* .text.*)
*libzephyr.a:windowspill_asm.*(.literal .text .literal.* .text.*)
*libzephyr.a:log_noos.*(.literal .text .literal.* .text.*)
*libdrivers__timer.a:xtensa_sys_timer.*(.literal .text .literal.* .text.*)
*libzephyr.a:systimer_hal.*(.literal .text .literal.* .text.*)
*libzephyr.a:log_core.*(.literal .text .literal.* .text.*)
*libzephyr.a:cbprintf_complete.*(.literal .text .literal.* .text.*)
*libzephyr.a:printk.*(.literal.printk .literal.vprintk .literal.char_out .text.printk .text.vprintk .text.char_out)
*libzephyr.a:log_msg.*(.literal .text .literal.* .text.*)
*libzephyr.a:log_list.*(.literal .text .literal.* .text.*)
*libdrivers__console.a:uart_console.*(.literal.console_out .text.console_out)
*libzephyr.a:log_output.*(.literal .text .literal.* .text.*)
*libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*)
*libzephyr.a:loader.*(.literal .text .literal.* .text.*)
*liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*)
*liblib__libc__newlib.a:string.*(.literal .text .literal.* .text.*)
*libc.a:*(.literal .text .literal.* .text.*)
*libphy.a:(.phyiram .phyiram.*)
*libgcov.a:(.literal .text .literal.* .text.*)
. = ALIGN(4);
_iram_end = ABSOLUTE(.);
. = ALIGN(4) + 16;
} GROUP_LINK_IN(IRAM_REGION)
SECTION_PROLOGUE(_RODATA_SECTION_NAME,,)
{
_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! */
__rodata_region_start = ABSOLUTE(.);
. = ALIGN(4);
#include <snippets-rodata.ld>
. = ALIGN(4);
*(EXCLUDE_FILE (*libarch__xtensa__core.a:* *libkernel.a:fatal.* *libkernel.a:init.* *libzephyr.a:cbprintf_complete* *libzephyr.a:log_core.* *libzephyr.a:log_backend_uart.* *libzephyr.a:log_output.* *libzephyr.a:loader.* *libdrivers__serial.a:uart_esp32.*) .rodata)
*(EXCLUDE_FILE (*libarch__xtensa__core.a:* *libkernel.a:fatal.* *libkernel.a:init.* *libzephyr.a:cbprintf_complete* *libzephyr.a:log_core.* *libzephyr.a:log_backend_uart.* *libzephyr.a:log_output.* *libzephyr.a:loader.* *libdrivers__serial.a:uart_esp32.*) .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)
. = (. + 3) & ~ 3;
__eh_frame = ABSOLUTE(.);
KEEP(*(.eh_frame))
. = (. + 7) & ~ 3;
/* 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)
. = ALIGN(4);
__rodata_region_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.*)
*(.rodata_wlog)
*(.rodata_wlog*)
_thread_local_end = ABSOLUTE(.);
_rodata_reserved_end = ABSOLUTE(.);
. = ALIGN(4);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, IRAM_REGION)
/* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA.
* Executing directly from LMA is not possible. */
#pragma push_macro("GROUP_ROM_LINK_IN")
#undef GROUP_ROM_LINK_IN
#define GROUP_ROM_LINK_IN(vregion, lregion) > RAMABLE_REGION AT > lregion
#include <zephyr/linker/common-rom/common-rom-cpp.ld>
#include <zephyr/linker/common-rom/common-rom-kernel-devices.ld>
#include <zephyr/linker/common-rom/common-rom-ztest.ld>
#include <zephyr/linker/common-rom/common-rom-net.ld>
#include <zephyr/linker/common-rom/common-rom-bt.ld>
#include <zephyr/linker/common-rom/common-rom-debug.ld>
#include <zephyr/linker/common-rom/common-rom-misc.ld>
#pragma pop_macro("GROUP_ROM_LINK_IN")
/* Create an explicit section at the end of all the data that shall be mapped into drom.
* This is used to calculate the size of the _image_drom_size variable */
SECTION_PROLOGUE(_RODATA_SECTION_END,,)
{
. = ALIGN(16);
_image_rodata_end = ABSOLUTE(.);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, IRAM_REGION)
#include <snippets-sections.ld>
.dram0.data :
{
. = ALIGN (8);
__data_start = ABSOLUTE(.);
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
/* rodata for panic handler(libarch__xtensa__core.a) and all
* dependent functions should be placed in DRAM to avoid issue
* when flash cache is disabled */
*libarch__xtensa__core.a:(.rodata .rodata.*)
*libkernel.a:fatal.*(.rodata .rodata.*)
*libkernel.a:init.*(.rodata .rodata.*)
*libzephyr.a:cbprintf_complete*(.rodata .rodata.*)
*libzephyr.a:systimer_hal.*(.rodata .rodata.*)
*libzephyr.a:log_core.*(.rodata .rodata.*)
*libzephyr.a:log_backend_uart.*(.rodata .rodata.*)
*libzephyr.a:log_output.*(.rodata .rodata.*)
*libzephyr.a:loader.*(.rodata .rodata.*)
*libdrivers__serial.a:uart_esp32.*(.rodata .rodata.*)
*libdrivers__flash.a:flash_esp32.*(.rodata .rodata.*)
KEEP(*(.jcr))
*(.dram1 .dram1.*)
. = ALIGN(4);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, IRAM_REGION)
#include <zephyr/linker/cplusplus-rom.ld>
#include <snippets-data-sections.ld>
#include <zephyr/linker/common-ram.ld>
#include <snippets-ram-sections.ld>
#include <zephyr/linker/cplusplus-ram.ld>
/* logging sections should be placed in RAM area to avoid flash cache disabled issues */
#pragma push_macro("GROUP_ROM_LINK_IN")
#undef GROUP_ROM_LINK_IN
#define GROUP_ROM_LINK_IN GROUP_DATA_LINK_IN
#include <zephyr/linker/common-rom/common-rom-logging.ld>
#pragma pop_macro("GROUP_ROM_LINK_IN")
.dram0.end :
{
. = ALIGN(4);
#include <snippets-rwdata.ld>
. = ALIGN(4);
_end = ABSOLUTE(.);
_heap_sentry = .;
. = ALIGN(4);
__data_end = ABSOLUTE(.);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, IRAM_REGION)
/* Shared RAM */
SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),)
{
. = ALIGN (8);
_bss_start = ABSOLUTE(.); /* required by bluetooth library */
__bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.share.mem)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
__bss_end = ABSOLUTE(.);
} GROUP_LINK_IN(RAMABLE_REGION)
ASSERT(((__bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.")
SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),)
{
. = ALIGN(8);
*(.noinit)
*(.noinit.*)
. = ALIGN(8) ;
} GROUP_LINK_IN(RAMABLE_REGION)
.flash.text : ALIGN(IROM_SEG_ALIGN)
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.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)
*(.literal .text .literal.* .text.*)
/* 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
*/
. += 16;
_text_end = ABSOLUTE(.);
_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.
*/
. = ALIGN(4);
_flash_cache_start = ABSOLUTE(0);
} GROUP_LINK_IN(IRAM_REGION)
#ifdef CONFIG_GEN_ISR_TABLES
#include <zephyr/linker/intlist.ld>
#endif
#include <zephyr/linker/debug-sections.ld>
.xtensa.info 0 : { *(.xtensa.info) }
.xt.insn 0 :
{
KEEP (*(.xt.insn))
KEEP (*(.gnu.linkonce.x.*))
}
.xt.prop 0 :
{
KEEP (*(.xt.prop))
KEEP (*(.xt.prop.*))
KEEP (*(.gnu.linkonce.prop.*))
}
.xt.lit 0 :
{
KEEP (*(.xt.lit))
KEEP (*(.xt.lit.*))
KEEP (*(.gnu.linkonce.p.*))
}
.xt.profile_range 0 :
{
KEEP (*(.xt.profile_range))
KEEP (*(.gnu.linkonce.profile_range.*))
}
.xt.profile_ranges 0 :
{
KEEP (*(.xt.profile_ranges))
KEEP (*(.gnu.linkonce.xt.profile_ranges.*))
}
.xt.profile_files 0 :
{
KEEP (*(.xt.profile_files))
KEEP (*(.gnu.linkonce.xt.profile_files.*))
}
}
ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
"IRAM0 segment data does not fit.")

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/device.h>
#include <zephyr/kernel.h>
#include <zephyr/spinlock.h>
#include <zephyr/kernel_structs.h>
#include <soc.h>
#include <esp_cpu.h>
#include <hal/soc_hal.h>
#include <hal/soc_ll.h>
#include <zephyr/drivers/interrupt_controller/intc_esp32.h>
static struct k_spinlock loglock;
void smp_log(const char *msg)
{
while (*msg) {
esp_rom_uart_tx_one_char(*msg++);
}
esp_rom_uart_tx_one_char('\r');
esp_rom_uart_tx_one_char('\n');
}
void esp_appcpu_start(void *entry_point)
{
soc_ll_unstall_core(1);
if (!REG_GET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_CLKGATE_EN)) {
REG_SET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_CLKGATE_EN);
REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RUNSTALL);
REG_SET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETTING);
REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETTING);
}
esp_rom_ets_set_appcpu_boot_addr((void *)entry_point);
ets_delay_us(50000);
smp_log("ESP32S3: CPU1 start sequence complete");
}

View file

@ -14,7 +14,12 @@
#include "mcuboot.ld"
#else
/* Application default linker script */
#include "default.ld"
#if defined(CONFIG_SOC_ESP32S3_APPCPU)
#include "default_appcpu.ld"
#else
#include "default.ld"
#endif
#endif /* CONFIG_MCUBOOT */

View file

@ -5,7 +5,7 @@
*/
/* Include esp-idf headers first to avoid redefining BIT() macro */
#include "soc.h"
#include <soc.h>
#include <soc/rtc_cntl_reg.h>
#include <soc/timer_group_reg.h>
#include <zephyr/drivers/interrupt_controller/intc_esp32.h>
@ -48,6 +48,45 @@ extern int _ext_ram_bss_end;
extern void z_cstart(void);
#ifdef CONFIG_SOC_ESP32S3_PROCPU
extern const unsigned char esp32s3_appcpu_fw_array[];
void IRAM_ATTR esp_start_appcpu(void)
{
esp_image_header_t *header = (esp_image_header_t *)&esp32s3_appcpu_fw_array[0];
esp_image_segment_header_t *segment =
(esp_image_segment_header_t *)&esp32s3_appcpu_fw_array[sizeof(esp_image_header_t)];
uint8_t *segment_payload;
uint32_t entry_addr = header->entry_addr;
uint32_t idx = sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t);
for (int i = 0; i < header->segment_count; i++) {
segment_payload = (uint8_t *)&esp32s3_appcpu_fw_array[idx];
if (segment->load_addr >= SOC_IRAM_LOW && segment->load_addr < SOC_IRAM_HIGH) {
/* IRAM segment only accepts 4 byte access, avoid memcpy usage here */
volatile uint32_t *src = (volatile uint32_t *)segment_payload;
volatile uint32_t *dst = (volatile uint32_t *)segment->load_addr;
for (int i = 0; i < segment->data_len / 4; i++) {
dst[i] = src[i];
}
} else if (segment->load_addr >= SOC_DRAM_LOW &&
segment->load_addr < SOC_DRAM_HIGH) {
memcpy((void *)segment->load_addr, (const void *)segment_payload,
segment->data_len);
}
idx += segment->data_len;
segment = (esp_image_segment_header_t *)&esp32s3_appcpu_fw_array[idx];
idx += sizeof(esp_image_segment_header_t);
}
esp_appcpu_start((void *)entry_addr);
}
#endif /* CONFIG_SOC_ESP32S3_PROCPU*/
#ifndef CONFIG_MCUBOOT
/*
* This function is a container for SoC patches
@ -92,7 +131,7 @@ void IRAM_ATTR __esp_platform_start(void)
* initialization code wants a valid _current before
* arch_kernel_init() is invoked.
*/
__asm__ volatile("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[0]));
__asm__ __volatile__("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[0]));
#ifdef CONFIG_MCUBOOT
/* MCUboot early initialisation. */
@ -149,6 +188,11 @@ void IRAM_ATTR __esp_platform_start(void)
esp_timer_early_init();
#if CONFIG_SOC_ESP32S3_PROCPU
/* start the ESP32S3 APP CPU */
esp_start_appcpu();
#endif
#if CONFIG_SOC_FLASH_ESP32
spi_flash_guard_set(&g_flash_guard_default_ops);
#endif

View file

@ -0,0 +1,172 @@
/*
* Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <soc.h>
#include <soc/rtc_cntl_reg.h>
#include <soc/timer_group_reg.h>
#include <zephyr/drivers/interrupt_controller/intc_esp32.h>
#include <xtensa/config/core-isa.h>
#include <xtensa/corebits.h>
#include <zephyr/kernel_structs.h>
#include <string.h>
#include <zephyr/toolchain/gcc.h>
#include <zephyr/types.h>
#include <zephyr/linker/linker-defs.h>
#include <kernel_internal.h>
#include <zephyr/sys/util.h>
#include <esp_private/system_internal.h>
#include <esp32s3/rom/cache.h>
#include <esp32s3/rom/rtc.h>
#include <soc/syscon_reg.h>
#include <hal/soc_ll.h>
#include <hal/wdt_hal.h>
#include <soc/cpu.h>
#include <soc/gpio_periph.h>
#include <esp_spi_flash.h>
#include <esp_err.h>
#include <esp_timer.h>
#include <esp_app_format.h>
#include <esp_clk_internal.h>
extern void z_cstart(void);
static void core_intr_matrix_clear(void)
{
uint32_t core_id = cpu_hal_get_core_id();
for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) {
intr_matrix_set(core_id, i, ETS_INVALID_INUM);
}
}
void IRAM_ATTR __app_cpu_start(void)
{
extern uint32_t _init_start;
extern uint32_t _bss_start;
extern uint32_t _bss_end;
/* Move the exception vector table to IRAM. */
__asm__ __volatile__("wsr %0, vecbase" : : "r"(&_init_start));
/* Zero out BSS. Clobber _bss_start to avoid memset() elision. */
z_bss_zero();
__asm__ __volatile__("" : : "g"(&__bss_start) : "memory");
/* Disable normal interrupts. */
__asm__ __volatile__("wsr %0, PS" : : "r"(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE));
/* Initialize the architecture CPU pointer. Some of the
* initialization code wants a valid _current before
* arch_kernel_init() is invoked.
*/
__asm__ __volatile__("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[1]));
core_intr_matrix_clear();
esp_intr_initialize();
/* Start Zephyr */
z_cstart();
CODE_UNREACHABLE;
}
/* Boot-time static default printk handler, possibly to be overridden later. */
int IRAM_ATTR arch_printk_char_out(int c)
{
ARG_UNUSED(c);
return 0;
}
void sys_arch_reboot(int type)
{
esp_restart_noos();
}
void IRAM_ATTR esp_restart_noos(void)
{
/* disable interrupts */
z_xt_ints_off(0xFFFFFFFF);
/* enable RTC watchdog for 1 second */
wdt_hal_context_t wdt_ctx;
uint32_t timeout_ticks = (uint32_t)(1000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
wdt_hal_init(&wdt_ctx, WDT_RWDT, 0, false);
wdt_hal_write_protect_disable(&wdt_ctx);
wdt_hal_config_stage(&wdt_ctx, WDT_STAGE0, timeout_ticks, WDT_STAGE_ACTION_RESET_SYSTEM);
wdt_hal_config_stage(&wdt_ctx, WDT_STAGE1, 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(&wdt_ctx, true);
wdt_hal_write_protect_enable(&wdt_ctx);
/* 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);
/* Flush any data left in UART FIFOs */
esp_rom_uart_tx_wait_idle(0);
esp_rom_uart_tx_wait_idle(1);
esp_rom_uart_tx_wait_idle(2);
/* Disable cache */
Cache_Disable_ICache();
Cache_Disable_DCache();
/* 2nd stage bootloader reconfigures SPI flash signals. */
/* Reset them to the defaults expected by ROM */
WRITE_PERI_REG(GPIO_FUNC0_IN_SEL_CFG_REG, 0x30);
WRITE_PERI_REG(GPIO_FUNC1_IN_SEL_CFG_REG, 0x30);
WRITE_PERI_REG(GPIO_FUNC2_IN_SEL_CFG_REG, 0x30);
WRITE_PERI_REG(GPIO_FUNC3_IN_SEL_CFG_REG, 0x30);
WRITE_PERI_REG(GPIO_FUNC4_IN_SEL_CFG_REG, 0x30);
WRITE_PERI_REG(GPIO_FUNC5_IN_SEL_CFG_REG, 0x30);
/* Reset wifi/bluetooth/ethernet/sdio (bb/mac) */
SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG,
SYSTEM_BB_RST | SYSTEM_FE_RST | SYSTEM_MAC_RST | SYSTEM_BT_RST |
SYSTEM_BTMAC_RST | SYSTEM_SDIO_RST | SYSTEM_SDIO_HOST_RST |
SYSTEM_EMAC_RST | SYSTEM_MACPWR_RST | SYSTEM_RW_BTMAC_RST |
SYSTEM_RW_BTLP_RST | SYSTEM_BLE_REG_RST | SYSTEM_PWR_REG_RST);
REG_WRITE(SYSTEM_CORE_RST_EN_REG, 0);
/* Reset timer/spi/uart */
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST |
SYSTEM_UART_RST | SYSTEM_SYSTIMER_RST);
REG_WRITE(SYSTEM_PERIP_RST_EN0_REG, 0);
/* Reset DMA */
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
REG_WRITE(SYSTEM_PERIP_RST_EN1_REG, 0);
SET_PERI_REG_MASK(SYSTEM_EDMA_CTRL_REG, SYSTEM_EDMA_RESET);
CLEAR_PERI_REG_MASK(SYSTEM_EDMA_CTRL_REG, SYSTEM_EDMA_RESET);
rtc_clk_cpu_freq_set_xtal();
/* Running on APP CPU: need to reset PRO CPU and unstall it, */
/* then reset APP CPU */
soc_ll_reset_core(0);
soc_ll_stall_core(0);
soc_ll_reset_core(1);
while (true) {
;
}
}

View file

@ -56,7 +56,7 @@
#if defined(CONFIG_BOARD_COLIBRI_IMX7D_M4) || defined(CONFIG_SOC_MK64F12) || \
defined(CONFIG_SOC_MKW41Z4) || defined(CONFIG_SOC_SERIES_ESP32S2) || \
defined(CONFIG_SOC_ESP32S3) || defined(CONFIG_SOC_SERIES_ESP32C3)
defined(CONFIG_SOC_SERIES_ESP32S3) || defined(CONFIG_SOC_SERIES_ESP32C3)
#define DEFAULT_PERIOD_CYCLE 1024
#define DEFAULT_PULSE_CYCLE 512
#define DEFAULT_PERIOD_NSEC 2000000

View file

@ -158,7 +158,7 @@ manifest:
groups:
- hal
- name: hal_espressif
revision: 80d910ca89eab9bce03f59a4ade33f1fc30ce0ad
revision: 9e4115fcbd6b737ec36488cd88c643eb7efc8b1b
path: modules/hal/espressif
west-commands: west/west-commands.yml
groups: