From bbd40b85c0eb7a3dd1bb0055db4fcd22e884a3cd Mon Sep 17 00:00:00 2001 From: Sylvio Alves Date: Mon, 2 Jan 2023 09:15:18 -0300 Subject: [PATCH] soc: esp32s3: add base source content This brings esp32s3 linker, DTS and all necessary files to allow the soc support. Signed-off-by: Sylvio Alves --- dts/xtensa/espressif/esp32s3.dtsi | 154 +++++ soc/xtensa/esp32s3/CMakeLists.txt | 83 +++ soc/xtensa/esp32s3/Kconfig.defconfig | 44 ++ soc/xtensa/esp32s3/Kconfig.soc | 266 ++++++++ soc/xtensa/esp32s3/include/_soc_inthandlers.h | 371 ++++++++++ soc/xtensa/esp32s3/linker.ld | 643 ++++++++++++++++++ soc/xtensa/esp32s3/loader.c | 96 +++ soc/xtensa/esp32s3/newlib_fix.c | 22 + soc/xtensa/esp32s3/pinctrl_soc.h | 78 +++ soc/xtensa/esp32s3/soc.c | 243 +++++++ soc/xtensa/esp32s3/soc.h | 72 ++ west.yml | 2 +- 12 files changed, 2073 insertions(+), 1 deletion(-) create mode 100644 dts/xtensa/espressif/esp32s3.dtsi create mode 100644 soc/xtensa/esp32s3/CMakeLists.txt create mode 100644 soc/xtensa/esp32s3/Kconfig.defconfig create mode 100644 soc/xtensa/esp32s3/Kconfig.soc create mode 100644 soc/xtensa/esp32s3/include/_soc_inthandlers.h create mode 100644 soc/xtensa/esp32s3/linker.ld create mode 100644 soc/xtensa/esp32s3/loader.c create mode 100644 soc/xtensa/esp32s3/newlib_fix.c create mode 100644 soc/xtensa/esp32s3/pinctrl_soc.h create mode 100644 soc/xtensa/esp32s3/soc.c create mode 100644 soc/xtensa/esp32s3/soc.h diff --git a/dts/xtensa/espressif/esp32s3.dtsi b/dts/xtensa/espressif/esp32s3.dtsi new file mode 100644 index 00000000000..069a49e962c --- /dev/null +++ b/dts/xtensa/espressif/esp32s3.dtsi @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include + +/ { + chosen { + zephyr,flash-controller = &flash; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <0>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <1>; + }; + + }; + + pinctrl: pin-controller { + compatible = "espressif,esp32-pinctrl"; + status = "okay"; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + sram0: memory@3fc88000 { + compatible = "mmio-sram"; + reg = <0x3fc88000 0x77FFF>; + }; + + intc: interrupt-controller@600c2000 { + #interrupt-cells = <1>; + compatible = "espressif,esp32-intc"; + interrupt-controller; + reg = <0x600c2000 0x1000>; + status = "okay"; + }; + + rtc: rtc@60021000 { + compatible = "espressif,esp32-rtc"; + reg = <0x60021000 0x2000>; + xtal-freq = ; + #clock-cells = <1>; + status = "okay"; + + rtc_timer: rtc_timer { + compatible = "espressif,esp32-rtc-timer"; + slow-clk-freq = ; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; + }; + }; + + flash: flash-controller@60002000 { + compatible = "espressif,esp32-flash-controller"; + reg = <0x60002000 0x1000>; + /* interrupts = <3 0>; */ + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + reg = <0 0x800000>; + erase-block-size = <4096>; + write-block-size = <4>; + }; + }; + + uart0: uart@60000000 { + compatible = "espressif,esp32-uart"; + reg = <0x60000000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART0_MODULE>; + status = "disabled"; + }; + + uart1: uart@60010000 { + compatible = "espressif,esp32-uart"; + reg = <0x60010000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART1_MODULE>; + status = "disabled"; + }; + + uart2: uart@6002e000 { + compatible = "espressif,esp32-uart"; + reg = <0x6002e000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART2_MODULE>; + status = "disabled"; + }; + + gpio: gpio { + compatible = "simple-bus"; + gpio-map-mask = <0xffffffe0 0xffffffc0>; + gpio-map-pass-thru = <0x1f 0x3f>; + gpio-map = < + 0x00 0x0 &gpio0 0x0 0x0 + 0x20 0x0 &gpio1 0x0 0x0 + >; + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio0: gpio@60004000 { + compatible = "espressif,esp32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x60004000 0x800>; + interrupts = ; + interrupt-parent = <&intc>; + ngpios = <32>; + }; + + gpio1: gpio@60004800 { + compatible = "espressif,esp32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x60004800 0x800>; + interrupts = ; + interrupt-parent = <&intc>; + ngpios = <13>; + }; + }; + + }; +}; diff --git a/soc/xtensa/esp32s3/CMakeLists.txt b/soc/xtensa/esp32s3/CMakeLists.txt new file mode 100644 index 00000000000..2feca8a7e74 --- /dev/null +++ b/soc/xtensa/esp32s3/CMakeLists.txt @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources( + soc.c + loader.c + ) + +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") + +if(CONFIG_BOOTLOADER_ESP_IDF) + include(ExternalProject) + + ## we use hello-world project, but I think any can be used. + set(espidf_components_dir ${ESP_IDF_PATH}/components) + set(espidf_prefix ${CMAKE_BINARY_DIR}/esp-idf) + set(espidf_build_dir ${espidf_prefix}/build) + + ExternalProject_Add( + EspIdfBootloader + PREFIX ${espidf_prefix} + SOURCE_DIR ${espidf_components_dir}/bootloader/subproject + BINARY_DIR ${espidf_build_dir}/bootloader + CONFIGURE_COMMAND + ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} + -S ${espidf_components_dir}/bootloader/subproject + -B ${espidf_build_dir}/bootloader -DSDKCONFIG=${espidf_build_dir}/sdkconfig + -DIDF_PATH=${ESP_IDF_PATH} -DIDF_TARGET=${CONFIG_SOC} + -DPYTHON_DEPS_CHECKED=1 + -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} + -DCMAKE_ASM_COMPILER=${CMAKE_ASM_COMPILER} + -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} + -DPYTHON=${PYTHON_EXECUTABLE} + BUILD_COMMAND + ${CMAKE_COMMAND} --build . + INSTALL_COMMAND "" # This particular build system has no install command + ) + + ExternalProject_Add( + EspPartitionTable + SOURCE_DIR ${espidf_components_dir}/partition_table + BINARY_DIR ${espidf_build_dir} + CONFIGURE_COMMAND "" + BUILD_COMMAND + ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/components/partition_table/gen_esp32part.py -q + --offset 0x8000 --flash-size ${esptoolpy_flashsize}MB ${ESP_IDF_PATH}/components/partition_table/partitions_singleapp.csv ${espidf_build_dir}/partitions_singleapp.bin + INSTALL_COMMAND "" + ) + + if(CONFIG_BUILD_OUTPUT_BIN) + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/components/esptool_py/esptool/esptool.py + ARGS --chip esp32s3 elf2image --flash_mode dio --flash_freq 40m --flash_size ${esptoolpy_flashsize}MB + -o ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin + ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.elf) + endif() + + set_property(TARGET bintools PROPERTY disassembly_flag_inline_source) + + add_dependencies(app EspIdfBootloader EspPartitionTable) + + board_finalize_runner_args(esp32 "--esp-flash-bootloader=${espidf_build_dir}/bootloader/bootloader.bin") + + board_finalize_runner_args(esp32 "--esp-flash-partition_table=${espidf_build_dir}/partitions_singleapp.bin") + + board_finalize_runner_args(esp32 "--esp-partition-table-address=0x8000") + +endif() + +board_finalize_runner_args(esp32 "--esp-boot-address=${boot_off}") + +board_finalize_runner_args(esp32 "--esp-app-address=${img_0_off}") diff --git a/soc/xtensa/esp32s3/Kconfig.defconfig b/soc/xtensa/esp32s3/Kconfig.defconfig new file mode 100644 index 00000000000..b20609d27c0 --- /dev/null +++ b/soc/xtensa/esp32s3/Kconfig.defconfig @@ -0,0 +1,44 @@ +# ESP32 board configuration + +# Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_ESP32S3 + +if BOOTLOADER_MCUBOOT + config HAS_FLASH_LOAD_OFFSET + default y + + config MCUBOOT_GENERATE_UNSIGNED_IMAGE + default y + + config MCUBOOT_GENERATE_CONFIRMED_IMAGE + default y + + config ROM_START_OFFSET + default 0x20 + + config HAS_DYNAMIC_DEVICE_HANDLES + default y +endif + +config SOC + default "esp32s3" + +config SOC_TOOLCHAIN_NAME + string + default "espressif_esp32s3" + +config HEAP_MEM_POOL_SIZE + default 32768 + +config MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE + default n + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency) + +config XTENSA_CCOUNT_HZ + default SYS_CLOCK_HW_CYCLES_PER_SEC + +endif diff --git a/soc/xtensa/esp32s3/Kconfig.soc b/soc/xtensa/esp32s3/Kconfig.soc new file mode 100644 index 00000000000..9c8dee0ade8 --- /dev/null +++ b/soc/xtensa/esp32s3/Kconfig.soc @@ -0,0 +1,266 @@ +# Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_ESP32S3 + bool "ESP32S3" + select XTENSA + select CLOCK_CONTROL + select DYNAMIC_INTERRUPTS + select ARCH_SUPPORTS_COREDUMP + select PINCTRL + select XIP + select HAS_ESPRESSIF_HAL + +if SOC_ESP32S3 + +config IDF_TARGET_ESP32S3 + bool "ESP32S3 as target board" + default y + +config ESPTOOLPY_FLASHFREQ_80M + bool + default y + +config FLASH_SIZE + int + default $(dt_node_reg_size_int,/soc/flash-controller@60002000/flash@0,0) + +config FLASH_BASE_ADDRESS + hex + default $(dt_node_reg_addr_hex,/soc/flash-controller@60002000/flash@0) + +choice ESP32S3_RTC_CLK_SRC + prompt "RTC clock source" + default ESP32S3_RTC_CLK_SRC_INT_RC + help + Choose which clock is used as RTC clock source. + + config ESP32S3_RTC_CLK_SRC_INT_RC + bool "Internal 150kHz RC oscillator" + config ESP32S3_RTC_CLK_SRC_EXT_CRYS + bool "External 32kHz crystal" + select ESP_SYSTEM_RTC_EXT_XTAL + config ESP32S3_RTC_CLK_SRC_EXT_OSC + bool "External 32kHz oscillator at 32K_XP pin" + select ESP_SYSTEM_RTC_EXT_OSC + config ESP32S3_RTC_CLK_SRC_INT_8MD256 + bool "Internal 8MHz oscillator, divided by 256 (~32kHz)" +endchoice + +config ESP32S3_RTC_CLK_CAL_CYCLES + int "Number of cycles for RTC_SLOW_CLK calibration" + default 3000 if ESP32S3_RTC_CLK_SRC_EXT_CRYS || ESP32S3_RTC_CLK_SRC_EXT_OSC || ESP32S3_RTC_CLK_SRC_INT_8MD256 + default 1024 if ESP32S3_RTC_CLK_SRC_INT_RC + range 0 27000 if ESP32S3_RTC_CLK_SRC_EXT_CRYS || ESP32S3_RTC_CLK_SRC_EXT_OSC || ESP32S3_RTC_CLK_SRC_INT_8MD256 + range 0 32766 if ESP32S3_RTC_CLK_SRC_INT_RC + help + When the startup code initializes RTC_SLOW_CLK, it can perform + calibration by comparing the RTC_SLOW_CLK frequency with main XTAL + frequency. This option sets the number of RTC_SLOW_CLK cycles measured + by the calibration routine. Higher numbers increase calibration + precision, which may be important for applications which spend a lot of + time in deep sleep. Lower numbers reduce startup time. + + When this option is set to 0, clock calibration will not be performed at + startup, and approximate clock frequencies will be assumed: + + - 150000 Hz if internal RC oscillator is used as clock source. For this use value 1024. + - 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more. + In case more value will help improve the definition of the launch of the crystal. + If the crystal could not start, it will be switched to internal RC. + +choice ESP32_UNIVERSAL_MAC_ADDRESSES + bool "Number of universally administered (by IEEE) MAC address" + default ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR + help + Configure the number of universally administered (by IEEE) MAC addresses. + During initialization, MAC addresses for each network interface are generated or + derived from a single base MAC address. If the number of universal MAC addresses is four, + all four interfaces (WiFi station, WiFi softap, Bluetooth and Ethernet) receive a universally + administered MAC address. These are generated sequentially by adding 0, 1, 2 and 3 (respectively) + to the final octet of the base MAC address. If the number of universal MAC addresses is two, + only two interfaces (WiFi station and Bluetooth) receive a universally administered MAC address. + These are generated sequentially by adding 0 and 1 (respectively) to the base MAC address. + The remaining two interfaces (WiFi softap and Ethernet) receive local MAC addresses. + These are derived from the universal WiFi station and Bluetooth MAC addresses, respectively. + When using the default (Espressif-assigned) base MAC address, either setting can be used. + When using a custom universal MAC address range, the correct setting will depend on the + allocation of MAC addresses in this range (either 2 or 4 per device.) + +config ESP32_UNIVERSAL_MAC_ADDRESSES_TWO + bool "Two" + select ESP_MAC_ADDR_UNIVERSE_WIFI_STA + select ESP_MAC_ADDR_UNIVERSE_BT + +config ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR + bool "Four" + select ESP_MAC_ADDR_UNIVERSE_WIFI_STA + select ESP_MAC_ADDR_UNIVERSE_WIFI_AP + select ESP_MAC_ADDR_UNIVERSE_BT + select ESP_MAC_ADDR_UNIVERSE_ETH + +endchoice # ESP32_UNIVERSAL_MAC_ADDRESSES + +config ESP_MAC_ADDR_UNIVERSE_WIFI_AP + bool + +config ESP_MAC_ADDR_UNIVERSE_WIFI_STA + bool + +config ESP_MAC_ADDR_UNIVERSE_BT + bool + +config ESP_MAC_ADDR_UNIVERSE_ETH + bool + +config ESP32_UNIVERSAL_MAC_ADDRESSES + int + default 2 if ESP32_UNIVERSAL_MAC_ADDRESSES_TWO + default 4 if ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR + +config ESP32_PHY_MAX_WIFI_TX_POWER + int "Max WiFi/BLE TX power (dBm)" + range 10 20 + default 20 + help + Set maximum transmit power for WiFi radio. Actual transmit power for high + data rates may be lower than this setting. + +config ESP32_PHY_MAX_TX_POWER + int + default ESP32_PHY_MAX_WIFI_TX_POWER + +menu "Cache config" + +choice ESP32S3_INSTRUCTION_CACHE_SIZE + prompt "Instruction cache size" + default ESP32S3_INSTRUCTION_CACHE_16KB + help + Instruction cache size to be set on application startup. + If you use 16KB instruction cache rather than 32KB instruction cache, + then the other 16KB will be managed by heap allocator. + + config ESP32S3_INSTRUCTION_CACHE_16KB + bool "16KB" + config ESP32S3_INSTRUCTION_CACHE_32KB + bool "32KB" +endchoice + +config ESP32S3_INSTRUCTION_CACHE_SIZE + hex + default 0x4000 if ESP32S3_INSTRUCTION_CACHE_16KB + default 0x8000 if ESP32S3_INSTRUCTION_CACHE_32KB + +choice ESP32S3_ICACHE_ASSOCIATED_WAYS + prompt "Instruction cache associated ways" + default ESP32S3_INSTRUCTION_CACHE_8WAYS + help + Instruction cache associated ways to be set on application startup. + + config ESP32S3_INSTRUCTION_CACHE_4WAYS + bool "4 ways" + config ESP32S3_INSTRUCTION_CACHE_8WAYS + bool "8 ways" +endchoice + +config ESP32S3_ICACHE_ASSOCIATED_WAYS + int + default 4 if ESP32S3_INSTRUCTION_CACHE_4WAYS + default 8 if ESP32S3_INSTRUCTION_CACHE_8WAYS + +choice ESP32S3_INSTRUCTION_CACHE_LINE_SIZE + prompt "Instruction cache line size" + default ESP32S3_INSTRUCTION_CACHE_LINE_32B + help + Instruction cache line size to be set on application startup. + + config ESP32S3_INSTRUCTION_CACHE_LINE_16B + bool "16 Bytes" + depends on ESP32S3_INSTRUCTION_CACHE_16KB + config ESP32S3_INSTRUCTION_CACHE_LINE_32B + bool "32 Bytes" +endchoice + +config ESP32S3_INSTRUCTION_CACHE_LINE_SIZE + int + default 16 if ESP32S3_INSTRUCTION_CACHE_LINE_16B + default 32 if ESP32S3_INSTRUCTION_CACHE_LINE_32B + +config ESP32S3_INSTRUCTION_CACHE_WRAP + bool "Define instruction cache wrap mode" + help + If enabled, instruction cache will use wrap mode to read spi flash or spi ram. + The wrap length equals to ESP32S3_INSTRUCTION_CACHE_LINE_SIZE. + However, it depends on complex conditions. + +choice ESP32S3_DATA_CACHE_SIZE + prompt "Data cache size" + default ESP32S3_DATA_CACHE_32KB + help + Data cache size to be set on application startup. + If you use 32KB data cache rather than 64KB data cache, + the other 32KB will be added to the heap. + + config ESP32S3_DATA_CACHE_16KB + bool "16KB" + config ESP32S3_DATA_CACHE_32KB + bool "32KB" + config ESP32S3_DATA_CACHE_64KB + bool "64KB" +endchoice + +config ESP32S3_DATA_CACHE_SIZE + hex + # For 16KB the actual configuration is 32kb cache, but 16kb will be reserved for heap at startup + default 0x8000 if ESP32S3_DATA_CACHE_16KB + default 0x8000 if ESP32S3_DATA_CACHE_32KB + default 0x10000 if ESP32S3_DATA_CACHE_64KB + +choice ESP32S3_DCACHE_ASSOCIATED_WAYS + prompt "Data cache associated ways" + default ESP32S3_DATA_CACHE_8WAYS + help + Data cache associated ways to be set on application startup. + + config ESP32S3_DATA_CACHE_4WAYS + bool "4 ways" + config ESP32S3_DATA_CACHE_8WAYS + bool "8 ways" +endchoice + +config ESP32S3_DCACHE_ASSOCIATED_WAYS + int + default 4 if ESP32S3_DATA_CACHE_4WAYS + default 8 if ESP32S3_DATA_CACHE_8WAYS + +choice ESP32S3_DATA_CACHE_LINE_SIZE + prompt "Data cache line size" + default ESP32S3_DATA_CACHE_LINE_32B + help + Data cache line size to be set on application startup. + + config ESP32S3_DATA_CACHE_LINE_16B + bool "16 Bytes" + depends on ESP32S3_DATA_CACHE_16KB || ESP32S3_DATA_CACHE_32KB + config ESP32S3_DATA_CACHE_LINE_32B + bool "32 Bytes" + config ESP32S3_DATA_CACHE_LINE_64B + bool "64 Bytes" +endchoice + +config ESP32S3_DATA_CACHE_LINE_SIZE + int + default 16 if ESP32S3_DATA_CACHE_LINE_16B + default 32 if ESP32S3_DATA_CACHE_LINE_32B + default 64 if ESP32S3_DATA_CACHE_LINE_64B + +config ESP32S3_DATA_CACHE_WRAP + bool "Define data cache wrap mode" + help + If enabled, data cache will use wrap mode to read spi flash or spi ram. + The wrap length equals to ESP32S3_DATA_CACHE_LINE_SIZE. + However, it depends on complex conditions. + +endmenu # Cache config + +endif # SOC_ESP32S3 diff --git a/soc/xtensa/esp32s3/include/_soc_inthandlers.h b/soc/xtensa/esp32s3/include/_soc_inthandlers.h new file mode 100644 index 00000000000..6980643e71d --- /dev/null +++ b/soc/xtensa/esp32s3/include/_soc_inthandlers.h @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + * + * Functions here are designed to produce efficient code to + * search an Xtensa bitmask of interrupts, inspecting only those bits + * declared to be associated with a given interrupt level. Each + * dispatcher will handle exactly one flagged interrupt, in numerical + * order (low bits first) and will return a mask of that bit that can + * then be cleared by the calling code. Unrecognized bits for the + * level will invoke an error handler. + */ + +#include +#include +#include + +#if !defined(XCHAL_INT0_LEVEL) || XCHAL_INT0_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT1_LEVEL) || XCHAL_INT1_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT2_LEVEL) || XCHAL_INT2_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT3_LEVEL) || XCHAL_INT3_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT4_LEVEL) || XCHAL_INT4_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT5_LEVEL) || XCHAL_INT5_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT6_LEVEL) || XCHAL_INT6_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT7_LEVEL) || XCHAL_INT7_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT8_LEVEL) || XCHAL_INT8_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT9_LEVEL) || XCHAL_INT9_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT10_LEVEL) || XCHAL_INT10_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT12_LEVEL) || XCHAL_INT12_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT13_LEVEL) || XCHAL_INT13_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT17_LEVEL) || XCHAL_INT17_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT18_LEVEL) || XCHAL_INT18_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT11_LEVEL) || XCHAL_INT11_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT15_LEVEL) || XCHAL_INT15_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT22_LEVEL) || XCHAL_INT22_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT23_LEVEL) || XCHAL_INT23_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT27_LEVEL) || XCHAL_INT27_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT29_LEVEL) || XCHAL_INT29_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT14_LEVEL) || XCHAL_INT14_LEVEL != 7 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT16_LEVEL) || XCHAL_INT16_LEVEL != 5 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT26_LEVEL) || XCHAL_INT26_LEVEL != 5 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT31_LEVEL) || XCHAL_INT31_LEVEL != 5 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT19_LEVEL) || XCHAL_INT19_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT20_LEVEL) || XCHAL_INT20_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT21_LEVEL) || XCHAL_INT21_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT24_LEVEL) || XCHAL_INT24_LEVEL != 4 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT25_LEVEL) || XCHAL_INT25_LEVEL != 4 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT28_LEVEL) || XCHAL_INT28_LEVEL != 4 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT30_LEVEL) || XCHAL_INT30_LEVEL != 4 +#error core-isa.h interrupt level does not match dispatcher! +#endif + +static inline int _xtensa_handle_one_int1(unsigned int mask) +{ + int irq; + + if (mask & 0x7f) { + if (mask & 0x7) { + if (mask & BIT(0)) { + mask = BIT(0); + irq = 0; + goto handle_irq; + } + if (mask & BIT(1)) { + mask = BIT(1); + irq = 1; + goto handle_irq; + } + if (mask & BIT(2)) { + mask = BIT(2); + irq = 2; + goto handle_irq; + } + } else { + if (mask & 0x18) { + if (mask & BIT(3)) { + mask = BIT(3); + irq = 3; + goto handle_irq; + } + if (mask & BIT(4)) { + mask = BIT(4); + irq = 4; + goto handle_irq; + } + } else { + if (mask & BIT(5)) { + mask = BIT(5); + irq = 5; + goto handle_irq; + } + if (mask & BIT(6)) { + mask = BIT(6); + irq = 6; + goto handle_irq; + } + } + } + } else { + if (mask & 0x780) { + if (mask & 0x180) { + if (mask & BIT(7)) { + mask = BIT(7); + irq = 7; + goto handle_irq; + } + if (mask & BIT(8)) { + mask = BIT(8); + irq = 8; + goto handle_irq; + } + } else { + if (mask & BIT(9)) { + mask = BIT(9); + irq = 9; + goto handle_irq; + } + if (mask & BIT(10)) { + mask = BIT(10); + irq = 10; + goto handle_irq; + } + } + } else { + if (mask & 0x3000) { + if (mask & BIT(12)) { + mask = BIT(12); + irq = 12; + goto handle_irq; + } + if (mask & BIT(13)) { + mask = BIT(13); + irq = 13; + goto handle_irq; + } + } else { + if (mask & BIT(17)) { + mask = BIT(17); + irq = 17; + goto handle_irq; + } + if (mask & BIT(18)) { + mask = BIT(18); + irq = 18; + goto handle_irq; + } + } + } + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int3(unsigned int mask) +{ + int irq; + + if (mask & 0x408800) { + if (mask & BIT(11)) { + mask = BIT(11); + irq = 11; + goto handle_irq; + } + if (mask & BIT(15)) { + mask = BIT(15); + irq = 15; + goto handle_irq; + } + if (mask & BIT(22)) { + mask = BIT(22); + irq = 22; + goto handle_irq; + } + } else { + if (mask & BIT(23)) { + mask = BIT(23); + irq = 23; + goto handle_irq; + } + if (mask & BIT(27)) { + mask = BIT(27); + irq = 27; + goto handle_irq; + } + if (mask & BIT(29)) { + mask = BIT(29); + irq = 29; + goto handle_irq; + } + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int7(unsigned int mask) +{ + int irq; + + if (mask & BIT(14)) { + mask = BIT(14); + irq = 14; + goto handle_irq; + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int5(unsigned int mask) +{ + int irq; + + if (mask & BIT(16)) { + mask = BIT(16); + irq = 16; + goto handle_irq; + } + if (mask & BIT(26)) { + mask = BIT(26); + irq = 26; + goto handle_irq; + } + if (mask & BIT(31)) { + mask = BIT(31); + irq = 31; + goto handle_irq; + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int2(unsigned int mask) +{ + int irq; + + if (mask & BIT(19)) { + mask = BIT(19); + irq = 19; + goto handle_irq; + } + if (mask & BIT(20)) { + mask = BIT(20); + irq = 20; + goto handle_irq; + } + if (mask & BIT(21)) { + mask = BIT(21); + irq = 21; + goto handle_irq; + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int4(unsigned int mask) +{ + int irq; + + if (mask & 0x3000000) { + if (mask & BIT(24)) { + mask = BIT(24); + irq = 24; + goto handle_irq; + } + if (mask & BIT(25)) { + mask = BIT(25); + irq = 25; + goto handle_irq; + } + } else { + if (mask & BIT(28)) { + mask = BIT(28); + irq = 28; + goto handle_irq; + } + if (mask & BIT(30)) { + mask = BIT(30); + irq = 30; + goto handle_irq; + } + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int0(unsigned int mask) +{ + return 0; +} +static inline int _xtensa_handle_one_int6(unsigned int mask) +{ + return 0; +} diff --git a/soc/xtensa/esp32s3/linker.ld b/soc/xtensa/esp32s3/linker.ld new file mode 100644 index 00000000000..bad03af67b8 --- /dev/null +++ b/soc/xtensa/esp32s3/linker.ld @@ -0,0 +1,643 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Linker command/script file + * + * Linker script for the Xtensa platform. + */ + +#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 I_D_SRAM_SIZE (SRAM_DRAM_END - SRAM_DRAM_START) + +#define ICACHE_SIZE 0x8000 +#define SRAM_IRAM_ORG (SRAM_IRAM_START + CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE) +#define SRAM_IRAM_SIZE (I_D_SRAM_SIZE + ICACHE_SIZE - CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE) + +#define DCACHE_SIZE 0x10000 +#define SRAM_DRAM_ORG (SRAM_DRAM_START) + +#define DRAM0_0_SEG_LEN I_D_SRAM_SIZE + +#define FLASH_CODE_REGION irom0_0_seg +#define RODATA_REGION drom0_0_seg +#define IRAM_REGION iram0_0_seg +#define RAMABLE_REGION dram0_0_seg +#define ROMABLE_REGION ROM + +#ifdef CONFIG_FLASH_SIZE +#define FLASH_SIZE CONFIG_FLASH_SIZE +#else +#define FLASH_SIZE 0x800000 +#endif + +#ifdef CONFIG_BOOTLOADER_ESP_IDF + +#define IROM_SEG_ORG 0x42000020 +#define IROM_SEG_LEN FLASH_SIZE-0x20 +#define IROM_SEG_ALIGN 0x4 + +#else + +#define IROM_SEG_ORG 0x42000000 +#define IROM_SEG_LEN FLASH_SIZE +#define IROM_SEG_ALIGN 0x10000 + +#endif + +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 + 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. + * Additional load header of 0x20 bytes are appended to the image. + * Hence, an offset of 0x40 is added to DROM segment origin. + */ + drom0_0_seg(R): org = 0x3C000040, len = FLASH_SIZE - 0x40 + + /** + * RTC fast memory (executable). Persists over deep sleep. + */ + rtc_iram_seg(RWX): org = 0x600fe000, len = 0x2000 + + /** + * RTC fast memory (same block as above), viewed from data bus + */ + rtc_data_seg(RW): org = 0x600fe000, len = 0x2000 + + /** + * RTC slow memory (data accessible). Persists over deep sleep. + */ + rtc_slow_seg(RW): org = 0x50000000, len = 0x2000 + +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 +#endif +} + +/* Default entry point: */ +ENTRY(CONFIG_KERNEL_ENTRY) + +_diram_i_start = 0x40378000; + +SECTIONS +{ + /* Reserve space for MCUboot header in the binary */ + .mcuboot_header : + { + QUAD(0x0) + QUAD(0x0) + QUAD(0x0) + QUAD(0x0) + } > mcuboot_hdr + .metadata : + { + /* Magic byte for load header */ + LONG(0xace637d3) + + /* Application entry point address */ + KEEP(*(.entry_addr)) + + /* IRAM metadata: + * - Destination address (VMA) for IRAM region + * - Flash offset (LMA) for start of IRAM region + * - Size of IRAM region + */ + LONG(ADDR(.iram0.vectors)) + LONG(LOADADDR(.iram0.vectors)) + LONG(LOADADDR(_TEXT_SECTION_NAME) + SIZEOF(_TEXT_SECTION_NAME) - LOADADDR(.iram0.vectors)) + + /* DRAM metadata: + * - Destination address (VMA) for DRAM region + * - Flash offset (LMA) for start of DRAM region + * - Size of DRAM region + */ + LONG(ADDR(.dram0.data)) + LONG(LOADADDR(.dram0.data)) + LONG(LOADADDR(.dram0.end) + SIZEOF(.dram0.end) - LOADADDR(.dram0.data)) + } > metadata + +#include + + /* RTC fast memory holds RTC wake stub code, + including from any source file named rtc_wake_stub*.c + */ + .rtc.text : + { + . = ALIGN(4); + _rtc_text_start = ABSOLUTE(.); + *(.rtc.literal .rtc.text) + *(.rtc.entry.text) + *rtc_wake_stub*.*(.literal .text .literal.* .text.*) + _rtc_text_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_iram_seg, ROMABLE_REGION) + + /** + * This section is required to skip rtc.text area because rtc_iram_seg and + * rtc_data_seg are reflect the same address space on different buses. + */ + .rtc.dummy : + { + _rtc_dummy_start = ABSOLUTE(.); + _rtc_fast_start = ABSOLUTE(.); + . = SIZEOF(.rtc.text); + _rtc_dummy_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_data_seg, ROMABLE_REGION) + + /** + * 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(.); + + *(.rtc.force_fast .rtc.force_fast.*) + . = ALIGN(4) ; + _rtc_force_fast_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_data_seg, ROMABLE_REGION) + + /** + * 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(.); + *(.rtc.data) + *(.rtc.rodata) + *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) + _rtc_data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) + + /* RTC bss, from any source file named rtc_wake_stub*.c */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.*) + *rtc_wake_stub*.*(COMMON) + + *(.rtc.data) + *(.rtc.rodata) + + _rtc_bss_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) + + /* RTC bss, from any source file named rtc_wake_stub*.c */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.*) + *rtc_wake_stub*.*(COMMON) + + _rtc_bss_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) + + /** + * 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(.); + } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) + + /** + * 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(.); + } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) + + /* Get size of rtc slow data based on rtc_data_location alias */ + _rtc_slow_length = (_rtc_force_slow_end - _rtc_data_start); + _rtc_fast_length = (_rtc_force_fast_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.") + +/* Send .iram0 code to iram */ + .iram0.vectors : ALIGN(4) + { + _iram_start = ABSOLUTE(.); + /* 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) + _init_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_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.*) + *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: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.*) + *libgcov.a:(.literal .text .literal.* .text.*) + + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + _image_dram_start = LOADADDR(.dram0.data); + _image_dram_size = LOADADDR(.dram0.end) + SIZEOF(.dram0.end) - _image_dram_start; + _image_dram_vaddr = ADDR(.dram0.data); + + /** + * 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) + MAX(_iram_end - _iram_start, 0); + } GROUP_LINK_IN(RAMABLE_REGION) + + #include + + .dram0.data : + { + __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: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.*) + + KEEP(*(.jcr)) + *(.dram1 .dram1.*) + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_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 = .; + __data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),) + { + . = ALIGN(4); + *(.noinit .noinit.*) + . = ALIGN(4) ; + } GROUP_LINK_IN(RAMABLE_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.") + + .flash.text : + { + _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. + */ + _flash_cache_start = ABSOLUTE(0); + } GROUP_DATA_LINK_IN(FLASH_CODE_REGION, ROMABLE_REGION) + + /** + * 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(0x10000) + 0x20; + _rodata_reserved_start = .; + } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) + + .flash.appdesc : ALIGN(0x10) + { + _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 .flah.rodata's begin address. Thus, both sections + * will be merged when creating the final bin image. */ + . = ALIGN(ALIGNOF(_RODATA_SECTION_NAME)); + } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) + +SECTION_PROLOGUE(_RODATA_SECTION_NAME,,ALIGN(0x10)) + { + __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(RODATA_REGION, ROMABLE_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) > RODATA_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(0x10)) + { + . = ALIGN(4); + _image_rodata_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) + + _image_iram_start = LOADADDR(.iram0.vectors); + _image_iram_size = LOADADDR(_TEXT_SECTION_NAME) + SIZEOF(_TEXT_SECTION_NAME) - _image_iram_start; + _image_iram_vaddr = ADDR(.iram0.vectors); + + /* Marks the end of IRAM code segment */ + .iram0.text_end (NOLOAD) : + { + /* ESP32-S3 memprot requires 16B padding for possible CPU prefetch and 256B alignment for PMS split lines */ + . = ALIGN(16); + _iram_text_end = ABSOLUTE(.); + } GROUP_LINK_IN(IRAM_REGION) + + .iram0.data : + { + . = ALIGN(16); + *(.iram.data) + *(.iram.data*) + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + .iram0.bss (NOLOAD) : + { + . = ALIGN(16); + *(.iram.bss) + *(.iram.bss*) + + . = ALIGN(16); + _iram_end = ABSOLUTE(.); + } GROUP_LINK_IN(IRAM_REGION) + + _image_irom_start = LOADADDR(.flash.text); + _image_irom_size = LOADADDR(.flash.text) + SIZEOF(.flash.text) - _image_irom_start; + _image_irom_vaddr = ADDR(.flash.text); + +#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.*)) + } + +#ifdef CONFIG_GEN_ISR_TABLES +#include +#endif + +} + +ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), + "IRAM0 segment data does not fit.") diff --git a/soc/xtensa/esp32s3/loader.c b/soc/xtensa/esp32s3/loader.c new file mode 100644 index 00000000000..cf3fafc5317 --- /dev/null +++ b/soc/xtensa/esp32s3/loader.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_BOOTLOADER_MCUBOOT +#define HDR_ATTR __attribute__((section(".entry_addr"))) __attribute__((used)) + +extern uint32_t _image_irom_start, _image_irom_size, _image_irom_vaddr; +extern uint32_t _image_drom_start, _image_drom_size, _image_drom_vaddr; + +void __start(void); + +static HDR_ATTR void (*_entry_point)(void) = &__start; + +static int map_rom_segments(void) +{ + int rc = 0; + size_t _partition_offset = FIXED_PARTITION_OFFSET(slot0_partition); + uint32_t _app_irom_start = _partition_offset + + (uint32_t)&_image_irom_start; + uint32_t _app_irom_size = (uint32_t)&_image_irom_size; + uint32_t _app_irom_vaddr = (uint32_t)&_image_irom_vaddr; + + uint32_t _app_drom_start = _partition_offset + + (uint32_t)&_image_drom_start; + uint32_t _app_drom_size = (uint32_t)&_image_drom_size; + uint32_t _app_drom_vaddr = (uint32_t)&_image_drom_vaddr; + + Cache_Read_Disable(0); + Cache_Flush(0); + /* Clear the MMU entries that are already set up, + * so the new app only has the mappings it creates. + */ + for (int i = 0; i < DPORT_FLASH_MMU_TABLE_SIZE; i++) { + DPORT_PRO_FLASH_MMU_TABLE[i] = + DPORT_FLASH_MMU_TABLE_INVALID_VAL; + } + + uint32_t drom_vaddr_addr_aligned = _app_drom_vaddr & MMU_FLASH_MASK; + uint32_t drom_page_count = bootloader_cache_pages_to_map(_app_drom_size, + _app_drom_vaddr); + rc = cache_flash_mmu_set(0, 0, drom_vaddr_addr_aligned, _app_drom_start + & MMU_FLASH_MASK, 64, drom_page_count); + rc |= cache_flash_mmu_set(1, 0, drom_vaddr_addr_aligned, _app_drom_start + & MMU_FLASH_MASK, 64, drom_page_count); + + uint32_t irom_vaddr_addr_aligned = _app_irom_vaddr & MMU_FLASH_MASK; + uint32_t irom_page_count = bootloader_cache_pages_to_map(_app_irom_size, + _app_irom_vaddr); + rc |= cache_flash_mmu_set(0, 0, irom_vaddr_addr_aligned, _app_irom_start + & MMU_FLASH_MASK, 64, irom_page_count); + rc |= cache_flash_mmu_set(1, 0, irom_vaddr_addr_aligned, _app_irom_start + & MMU_FLASH_MASK, 64, irom_page_count); + + DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, + (DPORT_PRO_CACHE_MASK_IRAM0) | + (DPORT_PRO_CACHE_MASK_IRAM1 & 0) | + (DPORT_PRO_CACHE_MASK_IROM0 & 0) | + DPORT_PRO_CACHE_MASK_DROM0 | + DPORT_PRO_CACHE_MASK_DRAM1); + + DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, + (DPORT_APP_CACHE_MASK_IRAM0) | + (DPORT_APP_CACHE_MASK_IRAM1 & 0) | + (DPORT_APP_CACHE_MASK_IROM0 & 0) | + DPORT_APP_CACHE_MASK_DROM0 | + DPORT_APP_CACHE_MASK_DRAM1); + + esp_rom_Cache_Read_Enable(0); + return rc; +} +#endif + +void __start(void) +{ +#ifdef CONFIG_BOOTLOADER_MCUBOOT + int err = map_rom_segments(); + + if (err != 0) { + ets_printf("Failed to setup XIP, aborting\n"); + abort(); + } +#endif + __esp_platform_start(); +} diff --git a/soc/xtensa/esp32s3/newlib_fix.c b/soc/xtensa/esp32s3/newlib_fix.c new file mode 100644 index 00000000000..b0a0efcc4e6 --- /dev/null +++ b/soc/xtensa/esp32s3/newlib_fix.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019, Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include + +int __weak _gettimeofday_r(struct _reent *r, struct timeval *__tp, void *__tzp) +{ + ARG_UNUSED(r); + ARG_UNUSED(__tp); + ARG_UNUSED(__tzp); + + return -1; +} diff --git a/soc/xtensa/esp32s3/pinctrl_soc.h b/soc/xtensa/esp32s3/pinctrl_soc.h new file mode 100644 index 00000000000..d5b84606508 --- /dev/null +++ b/soc/xtensa/esp32s3/pinctrl_soc.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * ESP32S3 SoC specific helpers for pinctrl driver + */ + +#ifndef ZEPHYR_SOC_XTENSA_ESP32S3_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_XTENSA_ESP32S3_PINCTRL_SOC_H_ + +#include +#include + +#include + +/** @cond INTERNAL_HIDDEN */ + +/** Type for ESP32 pin. */ +struct pinctrl_soc_pin { + /** Pinmux settings (pin, direction and signal). */ + uint32_t pinmux; + /** Pincfg settings (bias). */ + uint32_t pincfg; +}; + +typedef struct pinctrl_soc_pin pinctrl_soc_pin_t; + +/** + * @brief Utility macro to initialize pinmux field in #pinctrl_pin_t. + * + * @param node_id Node identifier. + */ +#define Z_PINCTRL_ESP32_PINMUX_INIT(node_id, prop, idx) \ + DT_PROP_BY_IDX(node_id, prop, idx) + +/** + * @brief Utility macro to initialize pincfg field in #pinctrl_pin_t. + * + * @param node_id Node identifier. + */ +#define Z_PINCTRL_ESP32_PINCFG_INIT(node_id) \ + (((ESP32_NO_PULL * DT_PROP(node_id, bias_disable)) << ESP32_PIN_BIAS_SHIFT) | \ + ((ESP32_PULL_UP * DT_PROP(node_id, bias_pull_up)) << ESP32_PIN_BIAS_SHIFT) | \ + ((ESP32_PULL_DOWN * DT_PROP(node_id, bias_pull_down)) << ESP32_PIN_BIAS_SHIFT) | \ + ((ESP32_PUSH_PULL * DT_PROP(node_id, drive_push_pull)) << ESP32_PIN_DRV_SHIFT) | \ + ((ESP32_OPEN_DRAIN * DT_PROP(node_id, drive_open_drain)) << ESP32_PIN_DRV_SHIFT) | \ + ((ESP32_PIN_OUT_HIGH * DT_PROP(node_id, output_high)) << ESP32_PIN_OUT_SHIFT) | \ + ((ESP32_PIN_OUT_LOW * DT_PROP(node_id, output_low)) << ESP32_PIN_OUT_SHIFT)) + +/** + * @brief Utility macro to initialize each pin. + * + * @param node_id Node identifier. + * @param prop Property name. + * @param idx Property entry index. + */ +#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ + { .pinmux = Z_PINCTRL_ESP32_PINMUX_INIT(node_id, prop, idx), \ + .pincfg = Z_PINCTRL_ESP32_PINCFG_INIT(node_id) }, + +/** + * @brief Utility macro to initialize state pins contained in a given property. + * + * @param node_id Node identifier. + * @param prop Property name describing state pins. + */ +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + {DT_FOREACH_CHILD_VARGS(DT_PHANDLE(node_id, prop), \ + DT_FOREACH_PROP_ELEM, pinmux, \ + Z_PINCTRL_STATE_PIN_INIT)} + +/** @endcond */ + +#endif /* ZEPHYR_SOC_XTENSA_ESP32S3_PINCTRL_SOC_H_ */ diff --git a/soc/xtensa/esp32s3/soc.c b/soc/xtensa/esp32s3/soc.c new file mode 100644 index 00000000000..21491600882 --- /dev/null +++ b/soc/xtensa/esp32s3/soc.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Include esp-idf headers first to avoid redefining BIT() macro */ +#include "soc.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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" +#include + +extern void z_cstart(void); +extern void rom_config_instruction_cache_mode(uint32_t cfg_cache_size, + uint8_t cfg_cache_ways, uint8_t cfg_cache_line_size); +extern void rom_config_data_cache_mode(uint32_t cfg_cache_size, + uint8_t cfg_cache_ways, uint8_t cfg_cache_line_size); +extern void Cache_Set_IDROM_MMU_Info(uint32_t instr_page_num, uint32_t rodata_page_num, + uint32_t rodata_start, uint32_t rodata_end, int i_off, int ro_off); +extern uint32_t Cache_Set_IDROM_MMU_Size(uint32_t irom_size, uint32_t drom_size); +extern int _rodata_reserved_start; +extern int _rodata_reserved_end; + +/* + * This is written in C rather than assembly since, during the port bring up, + * Zephyr is being booted by the Espressif bootloader. With it, the C stack + * is already set up. + */ +void IRAM_ATTR __esp_platform_start(void) +{ + extern uint32_t _init_start; + + /* Move the exception vector table to IRAM. */ + __asm__ __volatile__ ( + "wsr %0, vecbase" + : + : "r"(&_init_start)); + + z_bss_zero(); + + /* + * Configure the mode of instruction cache : + * cache size, cache associated ways, cache line size. + */ + rom_config_instruction_cache_mode(CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE, + CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS, + CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE); + + /* configure the mode of data: cache size, cache line size.*/ + Cache_Suspend_DCache(); + rom_config_data_cache_mode(CONFIG_ESP32S3_DATA_CACHE_SIZE, + CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS, + CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE); + Cache_Resume_DCache(0); + + /* Configure the Cache MMU size for instruction and rodata in flash. */ + uint32_t rodata_start_align = (uint32_t)&_rodata_reserved_start & ~(MMU_PAGE_SIZE - 1); + uint32_t cache_mmu_irom_size = ((rodata_start_align - SOC_DROM_LOW) / MMU_PAGE_SIZE) + * sizeof(uint32_t); + uint32_t cache_mmu_drom_size = (((uint32_t)&_rodata_reserved_end - rodata_start_align + + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE) * sizeof(uint32_t); + + Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size); + Cache_Set_IDROM_MMU_Info(cache_mmu_irom_size / sizeof(uint32_t), + cache_mmu_drom_size / sizeof(uint32_t), (uint32_t)&_rodata_reserved_start, + (uint32_t)&_rodata_reserved_end, 0, 0); + +#if CONFIG_ESP32S3_DATA_CACHE_16KB + Cache_Invalidate_DCache_All(); + Cache_Occupy_Addr(SOC_DROM_LOW, 0x4000); +#endif + + /* 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[0])); + + /* ESP-IDF/MCUboot 2nd stage bootloader enables RTC WDT to check on startup sequence + * related issues in application. Hence disable that as we are about to start + * Zephyr environment. + */ + wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL}; + + wdt_hal_write_protect_disable(&rtc_wdt_ctx); + wdt_hal_disable(&rtc_wdt_ctx); + wdt_hal_feed(&rtc_wdt_ctx); + wdt_hal_write_protect_enable(&rtc_wdt_ctx); + + esp_clk_init(); + + esp_timer_early_init(); + + 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) +{ + if (c == '\n') { + esp_rom_uart_tx_one_char('\r'); + } + esp_rom_uart_tx_one_char(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(); + + const uint32_t core_id = cpu_hal_get_core_id(); +#if CONFIG_SMP + const uint32_t other_core_id = (core_id == 0) ? 1 : 0; + + soc_ll_reset_core(other_core_id); + soc_ll_stall_core(other_core_id); +#endif + + /* 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(); + + /* Reset CPUs */ + if (core_id == 0) { + /* Running on PRO CPU: APP CPU is stalled. Can reset both CPUs. */ + soc_ll_reset_core(1); + soc_ll_reset_core(0); + } else { + /* 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/soc/xtensa/esp32s3/soc.h b/soc/xtensa/esp32s3/soc.h new file mode 100644 index 00000000000..7643d2a027b --- /dev/null +++ b/soc/xtensa/esp32s3/soc.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __SOC_H__ +#define __SOC_H__ +#include +#include +#include +#include +#include +#include "esp32s3/rom/cache.h" +#include +#include "soc/extmem_reg.h" +#include "soc/cache_memory.h" +#include "hal/cpu_hal.h" +#include "hal/cpu_types.h" +#include + +#include +#include +#include + +#include +#include + +void __esp_platform_start(void); + +static inline void esp32_set_mask32(uint32_t v, uint32_t mem_addr) +{ + sys_write32(sys_read32(mem_addr) | v, mem_addr); +} + +static inline void esp32_clear_mask32(uint32_t v, uint32_t mem_addr) +{ + sys_write32(sys_read32(mem_addr) & ~v, mem_addr); +} + +static inline uint32_t esp_core_id(void) +{ + uint32_t id; + + __asm__ volatile ( + "rsr.prid %0\n" + "extui %0,%0,13,1" : "=r" (id)); + return id; +} + +extern void esp_rom_intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num); + +extern int esp_rom_gpio_matrix_in(uint32_t gpio, uint32_t signal_index, + bool inverted); +extern int esp_rom_gpio_matrix_out(uint32_t gpio, uint32_t signal_index, + bool out_inverted, + bool out_enabled_inverted); + +extern void esp_rom_uart_attach(void); +extern void esp_rom_uart_tx_wait_idle(uint8_t uart_no); +extern int esp_rom_uart_tx_one_char(uint8_t chr); +extern int esp_rom_uart_rx_one_char(uint8_t *chr); +extern void esp_rom_uart_set_clock_baudrate(uint8_t uart_no, uint32_t clock_hz, uint32_t baud_rate); + +extern void esp_rom_ets_set_appcpu_boot_addr(void *addr); +void esp_appcpu_start(void *entry_point); + +/* ROM functions which read/write internal i2c control bus for PLL, APLL */ +extern uint8_t esp_rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add); +extern void esp_rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data); + +#endif /* __SOC_H__ */ diff --git a/west.yml b/west.yml index e3f6f1afe87..6c865dd3689 100644 --- a/west.yml +++ b/west.yml @@ -57,7 +57,7 @@ manifest: groups: - hal - name: hal_espressif - revision: 73e7af1e2ed64571ce49ff9f07dc02690b9f2df5 + revision: a06af2476671160f19e813c86570a17541f3b07e path: modules/hal/espressif west-commands: west/west-commands.yml groups: