From ed63e2a562dd22ff92a92495dbada14f2f005a84 Mon Sep 17 00:00:00 2001 From: Glauber Maroto Ferreira Date: Fri, 9 Jul 2021 18:26:11 -0300 Subject: [PATCH] soc: esp32s2: add initial soc support files for esp32s2 by adding specific soc files for esp32s2 bring-up, such as: - linker script - soc initialization code - initial device tree source files - esp32s2 saola board support. Signed-off-by: Glauber Maroto Ferreira --- CODEOWNERS | 1 + Kconfig.zephyr | 2 +- boards/xtensa/esp32s2_saola/CMakeLists.txt | 64 +++ boards/xtensa/esp32s2_saola/Kconfig.board | 8 + boards/xtensa/esp32s2_saola/Kconfig.defconfig | 8 + boards/xtensa/esp32s2_saola/board.cmake | 3 + boards/xtensa/esp32s2_saola/doc/index.rst | 137 ++++++ boards/xtensa/esp32s2_saola/esp32s2_saola.dts | 18 + .../xtensa/esp32s2_saola/esp32s2_saola.yaml | 6 + .../esp32s2_saola/esp32s2_saola_defconfig | 16 + cmake/toolchain/espressif/generic.cmake | 15 +- dts/xtensa/espressif/esp32s2.dtsi | 35 ++ soc/xtensa/esp32s2/CMakeLists.txt | 5 + soc/xtensa/esp32s2/Kconfig.defconfig | 29 ++ soc/xtensa/esp32s2/Kconfig.soc | 69 +++ soc/xtensa/esp32s2/include/_soc_inthandlers.h | 371 ++++++++++++++++ soc/xtensa/esp32s2/linker.ld | 395 ++++++++++++++++++ soc/xtensa/esp32s2/soc.c | 198 +++++++++ soc/xtensa/esp32s2/soc.h | 40 ++ 19 files changed, 1417 insertions(+), 3 deletions(-) create mode 100644 boards/xtensa/esp32s2_saola/CMakeLists.txt create mode 100644 boards/xtensa/esp32s2_saola/Kconfig.board create mode 100644 boards/xtensa/esp32s2_saola/Kconfig.defconfig create mode 100644 boards/xtensa/esp32s2_saola/board.cmake create mode 100644 boards/xtensa/esp32s2_saola/doc/index.rst create mode 100644 boards/xtensa/esp32s2_saola/esp32s2_saola.dts create mode 100644 boards/xtensa/esp32s2_saola/esp32s2_saola.yaml create mode 100644 boards/xtensa/esp32s2_saola/esp32s2_saola_defconfig create mode 100644 dts/xtensa/espressif/esp32s2.dtsi create mode 100644 soc/xtensa/esp32s2/CMakeLists.txt create mode 100644 soc/xtensa/esp32s2/Kconfig.defconfig create mode 100644 soc/xtensa/esp32s2/Kconfig.soc create mode 100644 soc/xtensa/esp32s2/include/_soc_inthandlers.h create mode 100644 soc/xtensa/esp32s2/linker.ld create mode 100644 soc/xtensa/esp32s2/soc.c create mode 100644 soc/xtensa/esp32s2/soc.h diff --git a/CODEOWNERS b/CODEOWNERS index 949d92abe71..c55acc7e542 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -400,6 +400,7 @@ /dts/x86/ @jhedberg /dts/xtensa/xtensa.dtsi @ydamigos /dts/xtensa/intel/ @dcpleung +/dts/xtensa/espressif/ @glaubermaroto /dts/sparc/ @martin-aberg /dts/bindings/ @galak /dts/bindings/can/ @alexanderwachter diff --git a/Kconfig.zephyr b/Kconfig.zephyr index e195ed31c72..308274bddcf 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -568,7 +568,7 @@ endif # BOOTLOADER_MCUBOOT config BOOTLOADER_ESP_IDF bool "ESP-IDF bootloader support" - depends on SOC_ESP32 + depends on SOC_ESP32 || SOC_ESP32S2 help This option will trigger the compilation of the ESP-IDF bootloader inside the build folder. diff --git a/boards/xtensa/esp32s2_saola/CMakeLists.txt b/boards/xtensa/esp32s2_saola/CMakeLists.txt new file mode 100644 index 00000000000..1044915b66a --- /dev/null +++ b/boards/xtensa/esp32s2_saola/CMakeLists.txt @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: Apache-2.0 + +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} + 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 ${ESP_IDF_PATH}/components/partition_table/gen_esp32part.py -q + --offset 0x1000 --flash-size 4MB ${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 ${ESP_IDF_PATH}/components/esptool_py/esptool/esptool.py + ARGS --chip esp32s2 elf2image --flash_mode dio --flash_freq 40m + -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-boot-address=0x1000") + + board_finalize_runner_args(esp32 "--esp-partition-table-address=0x8000") + + board_finalize_runner_args(esp32 "--esp-app-address=0x10000") + +endif() diff --git a/boards/xtensa/esp32s2_saola/Kconfig.board b/boards/xtensa/esp32s2_saola/Kconfig.board new file mode 100644 index 00000000000..5accd94308a --- /dev/null +++ b/boards/xtensa/esp32s2_saola/Kconfig.board @@ -0,0 +1,8 @@ +# ESP32S2 saola board configuration + +# Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_ESP32S2_SAOLA + bool "ESP32S2 Saola Board" + depends on SOC_ESP32S2 diff --git a/boards/xtensa/esp32s2_saola/Kconfig.defconfig b/boards/xtensa/esp32s2_saola/Kconfig.defconfig new file mode 100644 index 00000000000..595bd03aa2f --- /dev/null +++ b/boards/xtensa/esp32s2_saola/Kconfig.defconfig @@ -0,0 +1,8 @@ +# ESP32S2 Saola board configuration + +# Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD + default "esp32s2_saola" + depends on BOARD_ESP32S2_SAOLA diff --git a/boards/xtensa/esp32s2_saola/board.cmake b/boards/xtensa/esp32s2_saola/board.cmake new file mode 100644 index 00000000000..71735daa671 --- /dev/null +++ b/boards/xtensa/esp32s2_saola/board.cmake @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake) diff --git a/boards/xtensa/esp32s2_saola/doc/index.rst b/boards/xtensa/esp32s2_saola/doc/index.rst new file mode 100644 index 00000000000..41d2294f334 --- /dev/null +++ b/boards/xtensa/esp32s2_saola/doc/index.rst @@ -0,0 +1,137 @@ +.. _esp32s2_saola: + +ESP32-S2 +######## + +Overview +******** + +ESP32-S2 is a highly integrated, low-power, single-core Wi-Fi Microcontroller SoC, designed to be secure and +cost-effective, with a high performance and a rich set of IO capabilities. [1]_ + +The features include the following: + +- RSA-3072-based secure boot +- AES-XTS-256-based flash encryption +- Protected private key and device secrets from software access +- Cryptographic accelerators for enhanced performance +- Protection against physical fault injection attacks +- Various peripherals: + + - 43x programmable GPIOs + - 14x configurable capacitive touch GPIOs + - USB OTG + - LCD interface + - camera interface + - SPI + - I2S + - UART + - ADC + - DAC + +System requirements +******************* + +Build Environment Setup +======================= + +Some variables must be exported into the environment prior to building this port. +Find more information at :ref:`env_vars` on how to keep this settings saved in you environment. + +.. note:: + + In case of manual toolchain installation, set :file:`ESPRESSIF_TOOLCHAIN_PATH` accordingly. + Otherwise, set toolchain path as below. If necessary. + +On Linux and macOS: + +.. code-block:: console + + export ZEPHYR_TOOLCHAIN_VARIANT="espressif" + export ESPRESSIF_TOOLCHAIN_PATH="${HOME}/.espressif/tools/xtensa-esp32s2-elf/esp-2020r3-8.4.0/xtensa-esp32s2-elf" + +On Windows: + +.. code-block:: console + + # on CMD: + set ESPRESSIF_TOOLCHAIN_PATH=%USERPROFILE%\.espressif\tools\xtensa-esp32s2-elf\esp-2020r3-8.4.0\xtensa-esp32s2-elf + set ZEPHYR_TOOLCHAIN_VARIANT=espressif + + # on PowerShell + $env:ESPRESSIF_TOOLCHAIN_PATH="$env:USERPROFILE\.espressif\tools\xtensa-esp32s2-elf\esp-2020r3-8.4.0\xtensa-esp32s2-elf" + $env:ZEPHYR_TOOLCHAIN_VARIANT="espressif" + +Finally, retrieve required submodules to build this port. This might take a while for the first time: + +.. code-block:: console + + west espressif update + +.. note:: + + It is recommended running the command above after :file:`west update` so that submodules also get updated. + +Flashing +======== + +The usual ``flash`` target will work with the ``esp32s2_saola`` board +configuration. Here is an example for the :ref:`hello_world` +application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32s2_saola + :goals: flash + +Refer to :ref:`build_an_application` and :ref:`application_run` for +more details. + +It's impossible to determine which serial port the ESP32-S2 board is +connected to, as it uses a generic RS232-USB converter. The default of +``/dev/ttyUSB0`` is provided as that's often the assigned name on a Linux +machine without any other such converters. + +The baud rate of 921600bps is recommended. If experiencing issues when +flashing, try halving the value a few times (460800, 230400, 115200, +etc). + +All flashing options are now handled by the :ref:`west` tool, including flashing +with custom options such as a different serial port. The ``west`` tool supports +specific options for the ESP32-S2 board, as listed here: + + --esp-idf-path ESP_IDF_PATH + path to ESP-IDF + --esp-device ESP_DEVICE + serial port to flash, default /dev/ttyUSB0 + --esp-baud-rate ESP_BAUD_RATE + serial baud rate, default 921600 + --esp-flash-size ESP_FLASH_SIZE + flash size, default "detect" + --esp-flash-freq ESP_FLASH_FREQ + flash frequency, default "40m" + --esp-flash-mode ESP_FLASH_MODE + flash mode, default "dio" + --esp-tool ESP_TOOL if given, complete path to espidf. default is to + search for it in [ESP_IDF_PATH]/components/esptool_py/ + esptool/esptool.py + --esp-flash-bootloader ESP_FLASH_BOOTLOADER + Bootloader image to flash + --esp-flash-partition_table ESP_FLASH_PARTITION_TABLE + Partition table to flash + +For example, to flash to ``/dev/ttyUSB2``, use the following command after +having build the application in the ``build`` directory: + + +.. code-block:: console + + west flash -d build/ --skip-rebuild --esp-device /dev/ttyUSB2 + + +References +********** + +.. [1] https://www.espressif.com/en/products/socs/esp32-s2 +.. _`ESP32S2 Technical Reference Manual`: https://espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf +.. _`ESP32S2 Datasheet`: https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf diff --git a/boards/xtensa/esp32s2_saola/esp32s2_saola.dts b/boards/xtensa/esp32s2_saola/esp32s2_saola.dts new file mode 100644 index 00000000000..56b63b1363a --- /dev/null +++ b/boards/xtensa/esp32s2_saola/esp32s2_saola.dts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + model = "esp32s2_saola"; + compatible = "espressif,esp32s2"; + + chosen { + zephyr,sram = &sram0; + }; +}; diff --git a/boards/xtensa/esp32s2_saola/esp32s2_saola.yaml b/boards/xtensa/esp32s2_saola/esp32s2_saola.yaml new file mode 100644 index 00000000000..f7581cfdb29 --- /dev/null +++ b/boards/xtensa/esp32s2_saola/esp32s2_saola.yaml @@ -0,0 +1,6 @@ +identifier: esp32s2_saola +name: ESP32-S2 +type: mcu +arch: xtensa +toolchain: + - espressif diff --git a/boards/xtensa/esp32s2_saola/esp32s2_saola_defconfig b/boards/xtensa/esp32s2_saola/esp32s2_saola_defconfig new file mode 100644 index 00000000000..3c48ed17cfa --- /dev/null +++ b/boards/xtensa/esp32s2_saola/esp32s2_saola_defconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_XTENSA_RESET_VECTOR=n + +CONFIG_BOARD_ESP32S2_SAOLA=y +CONFIG_SOC_ESP32S2=y +CONFIG_MAIN_STACK_SIZE=2048 + +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=240000000 + +CONFIG_XTENSA_USE_CORE_CRT1=n + +CONFIG_GEN_ISR_TABLES=y +CONFIG_GEN_IRQ_VECTOR_TABLE=n + +CONFIG_BOOTLOADER_ESP_IDF=y diff --git a/cmake/toolchain/espressif/generic.cmake b/cmake/toolchain/espressif/generic.cmake index 63893436aff..d418a2add89 100644 --- a/cmake/toolchain/espressif/generic.cmake +++ b/cmake/toolchain/espressif/generic.cmake @@ -10,8 +10,19 @@ set(COMPILER gcc) set(LINKER ld) set(BINTOOLS gnu) -set(CROSS_COMPILE_TARGET xtensa-esp32-elf) -set(SYSROOT_TARGET xtensa-esp32-elf) +file(GLOB toolchain_paths + LIST_DIRECTORIES true + ${TOOLCHAIN_HOME} + ) + +if(toolchain_paths) + list(GET toolchain_paths 0 soc_toolchain_path) + + get_filename_component(soc_toolchain "${soc_toolchain_path}" NAME) + + set(CROSS_COMPILE_TARGET ${soc_toolchain}) + set(SYSROOT_TARGET ${soc_toolchain}) +endif() set(CROSS_COMPILE ${TOOLCHAIN_HOME}/bin/${CROSS_COMPILE_TARGET}-) set(SYSROOT_DIR ${TOOLCHAIN_HOME}/${SYSROOT_TARGET}) diff --git a/dts/xtensa/espressif/esp32s2.dtsi b/dts/xtensa/espressif/esp32s2.dtsi new file mode 100644 index 00000000000..66991373bfe --- /dev/null +++ b/dts/xtensa/espressif/esp32s2.dtsi @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "cadence,tensilica-xtensa-lx7"; + reg = <0>; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + sram0: memory@3ffb0000 { + compatible = "mmio-sram"; + reg = <0x3ffb0000 0x50000>; + }; + }; + +}; diff --git a/soc/xtensa/esp32s2/CMakeLists.txt b/soc/xtensa/esp32s2/CMakeLists.txt new file mode 100644 index 00000000000..332416ba43b --- /dev/null +++ b/soc/xtensa/esp32s2/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources( + soc.c + ) diff --git a/soc/xtensa/esp32s2/Kconfig.defconfig b/soc/xtensa/esp32s2/Kconfig.defconfig new file mode 100644 index 00000000000..e4aa20f1801 --- /dev/null +++ b/soc/xtensa/esp32s2/Kconfig.defconfig @@ -0,0 +1,29 @@ +# ESP32S2 board configuration + +# Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_ESP32S2 + +config SOC + default "esp32s2" + +config GEN_ISR_TABLES + default y + +config GEN_IRQ_VECTOR_TABLE + default n + +config XIP + default n + +config ISR_STACK_SIZE + default 2048 + +config IRQ_OFFLOAD_INTNUM + default 7 + +config MP_NUM_CPUS + default 1 + +endif diff --git a/soc/xtensa/esp32s2/Kconfig.soc b/soc/xtensa/esp32s2/Kconfig.soc new file mode 100644 index 00000000000..a08db42701f --- /dev/null +++ b/soc/xtensa/esp32s2/Kconfig.soc @@ -0,0 +1,69 @@ +# Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_ESP32S2 + bool "ESP32S2" + select XTENSA + select ATOMIC_OPERATIONS_C + +if SOC_ESP32S2 + +config IDF_TARGET_ESP32S2 + bool "ESP32S2 as target board" + default y + +config ESPTOOLPY_FLASHFREQ_80M + bool + default y + +choice + prompt "Instruction cache line size" + default ESP32S2_INSTRUCTION_CACHE_LINE_32B + + config ESP32S2_INSTRUCTION_CACHE_LINE_16B + bool "16 Bytes" + + config ESP32S2_INSTRUCTION_CACHE_LINE_32B + bool "32 Bytes" + +endchoice + +choice + prompt "Instruction cache size" + default ESP32S2_INSTRUCTION_CACHE_8KB + + config ESP32S2_INSTRUCTION_CACHE_8KB + bool "8KB instruction cache size" + + config ESP32S2_INSTRUCTION_CACHE_16KB + bool "16KB instruction cache size" + +endchoice + +choice + prompt "Data cache size" + default ESP32S2_DATA_CACHE_0KB + + config ESP32S2_DATA_CACHE_0KB + bool "0KB data cache size" + + config ESP32S2_DATA_CACHE_8KB + bool "8KB data cache size" + + config ESP32S2_DATA_CACHE_16KB + bool "16KB data cache size" + +endchoice + +config ESP32S2_INSTRUCTION_CACHE_SIZE + hex + default 0x2000 + default 0x4000 if ESP32S2_INSTRUCTION_CACHE_16KB + +config ESP32S2_DATA_CACHE_SIZE + hex + default 0x0000 + default 0x2000 if ESP32S2_DATA_CACHE_8KB + default 0x4000 if ESP32S2_DATA_CACHE_16KB + +endif diff --git a/soc/xtensa/esp32s2/include/_soc_inthandlers.h b/soc/xtensa/esp32s2/include/_soc_inthandlers.h new file mode 100644 index 00000000000..8004406397b --- /dev/null +++ b/soc/xtensa/esp32s2/include/_soc_inthandlers.h @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2021 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/esp32s2/linker.ld b/soc/xtensa/esp32s2/linker.ld new file mode 100644 index 00000000000..760d7b6e4a3 --- /dev/null +++ b/soc/xtensa/esp32s2/linker.ld @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Linker command/script file + * + * Linker script for the esp32s2 platform. + */ + +#include +#include +#include +#include +#include + +#define RAM_IRAM_START 0x40020000 +#define RAM_DRAM_START 0x3ffb0000 + +#define DATA_RAM_END 0x3ffe0000 /* 2nd stage bootloader iram_loader_seg starts at SRAM block 14 (reclaimed after app boots) */ + +#define IRAM_ORG (RAM_IRAM_START + CONFIG_ESP32S2_INSTRUCTION_CACHE_SIZE \ + + CONFIG_ESP32S2_DATA_CACHE_SIZE) + +#define DRAM_ORG (RAM_DRAM_START + CONFIG_ESP32S2_INSTRUCTION_CACHE_SIZE \ + + CONFIG_ESP32S2_DATA_CACHE_SIZE) + +#define I_D_RAM_SIZE DATA_RAM_END - DRAM_ORG + +#define RAMABLE_REGION dram0_0_seg :dram0_0_phdr +#define ROMABLE_REGION drom0_0_seg :drom0_0_phdr +#define IRAM_REGION iram0_0_seg :iram0_0_phdr +#define FLASH_CODE_REGION irom0_0_seg :irom0_0_phdr + +MEMORY +{ + iram0_0_seg(RX): org = IRAM_ORG, len = I_D_RAM_SIZE + irom0_0_seg(RX): org = 0x40080020, len = 0x780000-0x20 + dram0_0_seg(RW): org = DRAM_ORG, len = I_D_RAM_SIZE + drom0_0_seg(R): org = 0x3f000020, len = 0x3f0000-0x20 + rtc_iram_seg(RWX): org = 0x40070000, len = 0x2000 + rtc_slow_seg(RW): org = 0x50000000, len = 0x2000 +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 +#endif +} + +PHDRS +{ + drom0_0_phdr PT_LOAD; + dram0_0_phdr PT_LOAD; + iram0_0_phdr PT_LOAD; + irom0_0_phdr PT_LOAD; +} + +/* Default entry point: */ +ENTRY(CONFIG_KERNEL_ENTRY) + +_rom_store_table = 0; + +SECTIONS +{ +#include + + /* RTC fast memory holds RTC wake stub code, + including from any source file named rtc_wake_stub*.c + */ + .rtc.text : + { + . = ALIGN(4); + *(.rtc.literal .rtc.text) + *rtc_wake_stub*.o(.literal .text .literal.* .text.*) + } >rtc_iram_seg + + /* RTC slow memory holds RTC wake stub + data/rodata, including from any source file + named rtc_wake_stub*.c + */ + .rtc.data : + { + _rtc_data_start = ABSOLUTE(.); + *(.rtc.data) + *(.rtc.rodata) + *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) + _rtc_data_end = ABSOLUTE(.); + } > rtc_slow_seg + + /* RTC bss, from any source file named rtc_wake_stub*.c */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.o(.bss .bss.*) + *rtc_wake_stub*.o(COMMON) + _rtc_bss_end = ABSOLUTE(.); + } > rtc_slow_seg + + /* Send .iram0 code to iram */ + .iram0.vectors : ALIGN(4) + { + /* Vectors go to IRAM */ + _init_start = ABSOLUTE(.); + _iram_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; + *(.*Vector.literal) + + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + _init_end = ABSOLUTE(.); + + /* This goes here, not at top of linker script, so addr2line finds it last, + and uses it in preference to the first symbol in IRAM */ + } GROUP_LINK_IN(IRAM_REGION) + + .dram0_reserved_for_iram (NOLOAD): + { + . = ORIGIN(dram0_0_seg) + _iram_end - _iram_start; + } > dram0_0_seg + + SECTION_DATA_PROLOGUE(k_objects,, ALIGN(4)) + { + Z_LINK_ITERABLE_GC_ALLOWED(k_timer); + . = ALIGN(4); + Z_LINK_ITERABLE_GC_ALLOWED(k_mem_slab); + . = ALIGN(4); + Z_LINK_ITERABLE_GC_ALLOWED(k_mem_pool); + . = ALIGN(4); + Z_LINK_ITERABLE_GC_ALLOWED(k_heap); + . = ALIGN(4); + Z_LINK_ITERABLE_GC_ALLOWED(k_mutex); + . = ALIGN(4); + Z_LINK_ITERABLE_GC_ALLOWED(k_stack); + . = ALIGN(4); + Z_LINK_ITERABLE_GC_ALLOWED(k_msgq); + . = ALIGN(4); + Z_LINK_ITERABLE_GC_ALLOWED(k_mbox); + . = ALIGN(4); + Z_LINK_ITERABLE_GC_ALLOWED(k_pipe); + . = ALIGN(4); + Z_LINK_ITERABLE_GC_ALLOWED(k_sem); + . = ALIGN(4); + Z_LINK_ITERABLE_GC_ALLOWED(k_queue); + . = ALIGN(4); + Z_LINK_ITERABLE_GC_ALLOWED(k_condvar); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + SECTION_DATA_PROLOGUE(net,, ALIGN(4)) + { + _esp_net_buf_pool_list = .; + KEEP(*(SORT_BY_NAME("._net_buf_pool.static.*"))) + +#if defined(CONFIG_NETWORKING) + Z_LINK_ITERABLE_ALIGNED(net_if, 4); + Z_LINK_ITERABLE_ALIGNED(net_if_dev, 4); + Z_LINK_ITERABLE_ALIGNED(net_l2, 4); +#endif + + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + Z_ITERABLE_SECTION_RAM(_static_thread_data, 4) + +#pragma push_macro("Z_ITERABLE_SECTION_RAM") +#pragma push_macro("Z_ITERABLE_SECTION_RAM_GC_ALLOWED") +#undef Z_ITERABLE_SECTION_RAM_GC_ALLOWED +#define Z_ITERABLE_SECTION_RAM_GC_ALLOWED(x, y) +#undef Z_ITERABLE_SECTION_RAM +#define Z_ITERABLE_SECTION_RAM(x, y) +#include +/* Restore original value for symbols referenced by `common-ram.ld` */ +_net_buf_pool_list = _esp_net_buf_pool_list; +#pragma pop_macro("Z_ITERABLE_SECTION_RAM_GC_ALLOWED") +#pragma pop_macro("Z_ITERABLE_SECTION_RAM") + +#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.*) + + . = ALIGN(4); + __esp_log_const_start = .; + KEEP(*(SORT(.log_const_*))); + __esp_log_const_end = .; + + . = ALIGN(4); + __esp_log_backends_start = .; + KEEP(*("._log_backend.*")); + __esp_log_backends_end = .; + + KEEP(*(.jcr)) + *(.dram1 .dram1.*) + _data_end = ABSOLUTE(.); + . = ALIGN(4); + } GROUP_LINK_IN(RAMABLE_REGION) + + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,ALIGN(20)) + { + _rodata_start = ABSOLUTE(.); + + __esp_shell_root_cmds_start = .; + KEEP(*(SORT(.shell_root_cmd_*))); + __esp_shell_root_cmds_end = .; + + . = ALIGN(4); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); + KEEP (*(.xt_except_table)) + KEEP (*(.gcc_except_table .gcc_except_table.*)) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + KEEP (*(.eh_frame)) + /* C++ constructor and destructor tables, properly ordered: */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); /* this table MUST be 4-byte aligned */ + _rodata_end = ABSOLUTE(.); + } GROUP_LINK_IN(ROMABLE_REGION) + +#pragma push_macro("ROMABLE_REGION") +#undef ROMABLE_REGION +/* This is to workaround limitation of `esptool` which needs single `FLASH` data segment + * which is already defined above. In case, `common-rom.ld` creates additional segments + * they will be placed in DRAM instead. */ +#define ROMABLE_REGION RAMABLE_REGION +#include +/* Restore original value for symbols referenced by `common-rom.ld` */ +__log_const_start = __esp_log_const_start; +__log_const_end = __esp_log_const_end; +__log_backends_start = __esp_log_backends_start; +__log_backends_end = __esp_log_backends_end; +__shell_root_cmds_start = __esp_shell_root_cmds_start; +__shell_root_cmds_end = __esp_shell_root_cmds_end; +#pragma pop_macro("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.*) + *libsubsys__net__l2__ethernet.a:(.literal .text .literal.* .text.*) + *libsubsys__net__lib__config.a:(.literal .text .literal.* .text.*) + *libsubsys__net__ip.a:(.literal .text .literal.* .text.*) + *libsubsys__net.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.*) + *libzephyr.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.*) + *libzephyr.a:log_output.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*) + *liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*) + *libgcov.a:(.literal .text .literal.* .text.*) + _iram_text_end = ABSOLUTE(.); + . = ALIGN(4); + _iram_end = ABSOLUTE(.); + } GROUP_LINK_IN(IRAM_REGION) + + .flash.text : + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.literal .text .literal.* .text.*) + _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_LINK_IN(FLASH_CODE_REGION) + + /* Shared RAM */ + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + . = ALIGN (8); + __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) + +#ifdef CONFIG_GEN_ISR_TABLES +#include +#endif + +#include + + SECTION_PROLOGUE(.xtensa.info, 0,) + { + *(.xtensa.info) + } + +} + +ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), + "IRAM0 segment data does not fit.") diff --git a/soc/xtensa/esp32s2/soc.c b/soc/xtensa/esp32s2/soc.c new file mode 100644 index 00000000000..c281e318a77 --- /dev/null +++ b/soc/xtensa/esp32s2/soc.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. + * + * 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 "esp_private/system_internal.h" +#include "esp32s2/rom/cache.h" +#include "soc/gpio_periph.h" +#include "hal/cpu_ll.h" +#include "esp_err.h" +#include "sys/printk.h" + +extern void z_cstart(void); +extern void z_bss_zero(void); +extern void rtc_clk_cpu_freq_set_xtal(void); + +/* + * 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 __attribute__((section(".iram1"))) __start(void) +{ + volatile uint32_t *wdt_rtc_protect = (uint32_t *)RTC_CNTL_WDTWPROTECT_REG; + volatile uint32_t *wdt_rtc_reg = (uint32_t *)RTC_CNTL_WDTCONFIG0_REG; + extern uint32_t _init_start; + + /* Move the exception vector table to IRAM. */ + __asm__ __volatile__ ( + "wsr %0, vecbase" + : + : "r"(&_init_start)); + + /* Zero out BSS */ + z_bss_zero(); + + /* + * Configure the mode of instruction cache : + * cache size, cache associated ways, cache line size. + */ + cache_size_t cache_size; + cache_ways_t cache_ways; + cache_line_size_t cache_line_size; + +#if CONFIG_ESP32S2_INSTRUCTION_CACHE_8KB + esp_rom_Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_INVALID, + CACHE_MEMORY_INVALID, CACHE_MEMORY_INVALID); + cache_size = CACHE_SIZE_8KB; +#else + esp_rom_Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_ICACHE_HIGH, + CACHE_MEMORY_INVALID, CACHE_MEMORY_INVALID); + cache_size = CACHE_SIZE_16KB; +#endif + + cache_ways = CACHE_4WAYS_ASSOC; + +#if CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_16B + cache_line_size = CACHE_LINE_SIZE_16B; +#else + cache_line_size = CACHE_LINE_SIZE_32B; +#endif + + esp_rom_Cache_Suspend_ICache(); + esp_rom_Cache_Set_ICache_Mode(cache_size, cache_ways, cache_line_size); + esp_rom_Cache_Invalidate_ICache_All(); + esp_rom_Cache_Resume_ICache(0); + +#if !CONFIG_BOOTLOADER_ESP_IDF + /* The watchdog timer is enabled in the 1st stage (ROM) bootloader. + * We're done booting, so disable it. + * If 2nd stage bootloader from IDF is enabled, then that will take + * care of this. + */ + volatile uint32_t *wdt_timg_protect = (uint32_t *)TIMG_WDTWPROTECT_REG(0); + volatile uint32_t *wdt_timg_reg = (uint32_t *)TIMG_WDTCONFIG0_REG(0); + + *wdt_rtc_protect = RTC_CNTL_WDT_WKEY_VALUE; + *wdt_rtc_reg &= ~RTC_CNTL_WDT_FLASHBOOT_MOD_EN; + *wdt_rtc_protect = 0; + *wdt_timg_protect = TIMG_WDT_WKEY_VALUE; + *wdt_timg_reg &= ~TIMG_WDT_FLASHBOOT_MOD_EN; + *wdt_timg_protect = 0; +#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])); + +#if CONFIG_BOOTLOADER_ESP_IDF + /* ESP-IDF 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_rtc_protect = RTC_CNTL_WDT_WKEY_VALUE; + *wdt_rtc_reg &= ~RTC_CNTL_WDT_EN; + *wdt_rtc_protect = 0; +#endif + + /* 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); + + /* + * Reset and stall the other CPU. + * CPU must be reset before stalling, in case it was running a s32c1i + * instruction. This would cause memory pool to be locked by arbiter + * to the stalled CPU, preventing current CPU from accessing this pool. + */ + const uint32_t core_id = cpu_ll_get_core_id(); + + /* Flush any data left in UART FIFOs */ + esp_rom_uart_tx_wait_idle(0); + esp_rom_uart_tx_wait_idle(1); + /* Disable cache */ + esp_rom_Cache_Disable_ICache(); + esp_rom_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/ethernet/sdio (bb/mac) */ + DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, + DPORT_BB_RST | DPORT_FE_RST | DPORT_MAC_RST | + DPORT_SDIO_RST | DPORT_SDIO_HOST_RST | + DPORT_EMAC_RST | DPORT_MACPWR_RST); + DPORT_REG_WRITE(DPORT_CORE_RST_EN_REG, 0); + + /* Reset timer/spi/uart */ + DPORT_SET_PERI_REG_MASK( + DPORT_PERIP_RST_EN_REG, + DPORT_TIMERS_RST | DPORT_SPI01_RST | DPORT_SPI2_RST | + DPORT_SPI3_RST | DPORT_SPI2_DMA_RST | DPORT_SPI3_DMA_RST | + DPORT_UART_RST); + DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0); + + /* Set CPU back to XTAL source, no PLL, same as hard reset */ + rtc_clk_cpu_freq_set_xtal(); + + /* Reset CPUs */ + if (core_id == 0) { + SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST_M); + } + + while (true) { + ; + } +} diff --git a/soc/xtensa/esp32s2/soc.h b/soc/xtensa/esp32s2/soc.h new file mode 100644 index 00000000000..f7b7ea89a8f --- /dev/null +++ b/soc/xtensa/esp32s2/soc.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __SOC_H__ +#define __SOC_H__ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +extern void esp_rom_uart_attach(void); +extern void esp_rom_uart_tx_wait_idle(uint8_t uart_no); +extern STATUS esp_rom_uart_tx_one_char(uint8_t chr); +extern STATUS esp_rom_uart_rx_one_char(uint8_t *chr); + +/* cache related rom functions */ +extern uint32_t esp_rom_Cache_Disable_ICache(void); +extern uint32_t esp_rom_Cache_Disable_DCache(void); + +extern void esp_rom_Cache_Allocate_SRAM(cache_layout_t sram0_layout, cache_layout_t sram1_layout, + cache_layout_t sram2_layout, cache_layout_t sram3_layout); + +extern uint32_t esp_rom_Cache_Suspend_ICache(void); + +extern void esp_rom_Cache_Set_ICache_Mode(cache_size_t cache_size, cache_ways_t ways, + cache_line_size_t cache_line_size); + +extern void esp_rom_Cache_Invalidate_ICache_All(void); +void esp_rom_Cache_Resume_ICache(uint32_t autoload); + +#endif /* __SOC_H__ */