diff --git a/drivers/clock_control/clock_control_esp32.c b/drivers/clock_control/clock_control_esp32.c index ea8836d8d75..fba7091b871 100644 --- a/drivers/clock_control/clock_control_esp32.c +++ b/drivers/clock_control/clock_control_esp32.c @@ -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; diff --git a/drivers/ipm/ipm_esp32.c b/drivers/ipm/ipm_esp32.c index 9f7e6063519..cbe6e42d90f 100644 --- a/drivers/ipm/ipm_esp32.c +++ b/drivers/ipm/ipm_esp32.c @@ -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)) ; diff --git a/drivers/serial/serial_esp32_usb.c b/drivers/serial/serial_esp32_usb.c index 06b93e79329..14e4b798a8f 100644 --- a/drivers/serial/serial_esp32_usb.c +++ b/drivers/serial/serial_esp32_usb.c @@ -13,7 +13,7 @@ #include #include #include -#if defined(CONFIG_SOC_ESP32C3) +#if defined(CONFIG_SOC_SERIES_ESP32C3) #include #else #include @@ -22,7 +22,7 @@ #include #include -#ifdef CONFIG_SOC_ESP32C3 +#ifdef CONFIG_SOC_SERIES_ESP32C3 #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_appcpu.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_appcpu.dtsi new file mode 100644 index 00000000000..c405bfedecd --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_appcpu.dtsi @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi index a5b98a9f52b..7655b3537db 100644 --- a/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi +++ b/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi @@ -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 = ; + interrupt-parent = <&intc>; + }; + uart0: uart@60000000 { compatible = "espressif,esp32-uart"; reg = <0x60000000 0x1000>; diff --git a/soc/xtensa/espressif_esp32/esp32s3/CMakeLists.txt b/soc/xtensa/espressif_esp32/esp32s3/CMakeLists.txt index 87d71798159..dc9e86d6604 100644 --- a/soc/xtensa/espressif_esp32/esp32s3/CMakeLists.txt +++ b/soc/xtensa/espressif_esp32/esp32s3/CMakeLists.txt @@ -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() diff --git a/soc/xtensa/espressif_esp32/esp32s3/Kconfig.series b/soc/xtensa/espressif_esp32/esp32s3/Kconfig.series index 1265375c12a..6f5fcf88c17 100644 --- a/soc/xtensa/espressif_esp32/esp32s3/Kconfig.series +++ b/soc/xtensa/espressif_esp32/esp32s3/Kconfig.series @@ -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. diff --git a/soc/xtensa/espressif_esp32/esp32s3/Kconfig.soc b/soc/xtensa/espressif_esp32/esp32s3/Kconfig.soc index ac265e5edb0..b8cc95b62cb 100644 --- a/soc/xtensa/espressif_esp32/esp32s3/Kconfig.soc +++ b/soc/xtensa/espressif_esp32/esp32s3/Kconfig.soc @@ -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 diff --git a/soc/xtensa/espressif_esp32/esp32s3/default.ld b/soc/xtensa/espressif_esp32/esp32s3/default.ld index fc6a4e47d0e..c9bab6f3cad 100644 --- a/soc/xtensa/espressif_esp32/esp32s3/default.ld +++ b/soc/xtensa/espressif_esp32/esp32s3/default.ld @@ -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 diff --git a/soc/xtensa/espressif_esp32/esp32s3/default_appcpu.ld b/soc/xtensa/espressif_esp32/esp32s3/default_appcpu.ld new file mode 100644 index 00000000000..d5e0e2fe3e9 --- /dev/null +++ b/soc/xtensa/espressif_esp32/esp32s3/default_appcpu.ld @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#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 + + /* 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 + + . = 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 + #include + #include + #include + #include + #include + #include + #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 + + .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 + #include + #include + #include + #include + + /* 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 + #pragma pop_macro("GROUP_ROM_LINK_IN") + + .dram0.end : + { + . = ALIGN(4); + + #include + + . = 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 +#endif + +#include + + .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.") diff --git a/soc/xtensa/espressif_esp32/esp32s3/esp32s3-mp.c b/soc/xtensa/espressif_esp32/esp32s3/esp32s3-mp.c new file mode 100644 index 00000000000..5f20b64c27a --- /dev/null +++ b/soc/xtensa/espressif_esp32/esp32s3/esp32s3-mp.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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"); +} diff --git a/soc/xtensa/espressif_esp32/esp32s3/linker.ld b/soc/xtensa/espressif_esp32/esp32s3/linker.ld index 6cfbce9433f..9303f5a325d 100644 --- a/soc/xtensa/espressif_esp32/esp32s3/linker.ld +++ b/soc/xtensa/espressif_esp32/esp32s3/linker.ld @@ -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 */ diff --git a/soc/xtensa/espressif_esp32/esp32s3/soc.c b/soc/xtensa/espressif_esp32/esp32s3/soc.c index 617ee05aabb..ad971b907b2 100644 --- a/soc/xtensa/espressif_esp32/esp32s3/soc.c +++ b/soc/xtensa/espressif_esp32/esp32s3/soc.c @@ -5,7 +5,7 @@ */ /* Include esp-idf headers first to avoid redefining BIT() macro */ -#include "soc.h" +#include #include #include #include @@ -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 diff --git a/soc/xtensa/espressif_esp32/esp32s3/soc_appcpu.c b/soc/xtensa/espressif_esp32/esp32s3/soc_appcpu.c new file mode 100644 index 00000000000..583f0b8119a --- /dev/null +++ b/soc/xtensa/espressif_esp32/esp32s3/soc_appcpu.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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) { + ; + } +} diff --git a/tests/drivers/pwm/pwm_api/src/test_pwm.c b/tests/drivers/pwm/pwm_api/src/test_pwm.c index 28b7ea541f2..867025d99b1 100644 --- a/tests/drivers/pwm/pwm_api/src/test_pwm.c +++ b/tests/drivers/pwm/pwm_api/src/test_pwm.c @@ -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 diff --git a/west.yml b/west.yml index bed5974b0cb..d8fa2096031 100644 --- a/west.yml +++ b/west.yml @@ -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: