diff --git a/boards/common/esp32h2/Kconfig b/boards/common/esp32h2/Kconfig new file mode 100644 index 000000000000..5f6cc1ba983f --- /dev/null +++ b/boards/common/esp32h2/Kconfig @@ -0,0 +1,11 @@ +# Copyright (c) 2025 Gunar Schorcht +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. + +config BOARD_COMMON_ESP32H2 + bool + select BOARD_COMMON_ESP32X + +source "$(RIOTBOARD)/common/esp32x/Kconfig" diff --git a/boards/common/esp32h2/Makefile b/boards/common/esp32h2/Makefile new file mode 100644 index 000000000000..1784a6118d3b --- /dev/null +++ b/boards/common/esp32h2/Makefile @@ -0,0 +1,5 @@ +MODULE = boards_common_esp32h2 + +DIRS = $(RIOTBOARD)/common/esp32x + +include $(RIOTBASE)/Makefile.base diff --git a/boards/common/esp32h2/Makefile.dep b/boards/common/esp32h2/Makefile.dep new file mode 100644 index 000000000000..e55438c370f1 --- /dev/null +++ b/boards/common/esp32h2/Makefile.dep @@ -0,0 +1,3 @@ +USEMODULE += boards_common_esp32h2 + +include $(RIOTBOARD)/common/esp32x/Makefile.dep diff --git a/boards/common/esp32h2/Makefile.features b/boards/common/esp32h2/Makefile.features new file mode 100644 index 000000000000..5425e793b570 --- /dev/null +++ b/boards/common/esp32h2/Makefile.features @@ -0,0 +1,3 @@ +CPU_FAM = esp32h2 + +include $(RIOTBOARD)/common/esp32x/Makefile.features diff --git a/boards/common/esp32h2/Makefile.include b/boards/common/esp32h2/Makefile.include new file mode 100644 index 000000000000..288555cce2fe --- /dev/null +++ b/boards/common/esp32h2/Makefile.include @@ -0,0 +1,3 @@ +INCLUDES += -I$(RIOTBOARD)/common/esp32h2/include + +include $(RIOTBOARD)/common/esp32x/Makefile.include diff --git a/boards/common/esp32h2/doc.md b/boards/common/esp32h2/doc.md new file mode 100644 index 000000000000..cd4505c1ea39 --- /dev/null +++ b/boards/common/esp32h2/doc.md @@ -0,0 +1,23 @@ + + +@defgroup boards_common_esp32h2 ESP32-H2 Common +@ingroup boards_common +@ingroup boards_esp32h2 +@brief Definitions and configurations that are common for all ESP32-H2 boards. + +For detailed information about the ESP32-H2, configuring and compiling RIOT +for ESP32-H2 boards, please refer to \ref esp32_riot. + +@defgroup boards_esp32h2 ESP32-H2 Boards +@ingroup boards +@brief This group of boards contains the documentation of ESP32-H2 boards. + +@note For detailed information about the ESP32-H2 SoC, the tool chain + as well as configuring and compiling RIOT for ESP32-H2 boards, + see \ref esp32_riot. diff --git a/boards/common/esp32h2/include/board_common_esp32h2.h b/boards/common/esp32h2/include/board_common_esp32h2.h new file mode 100644 index 000000000000..224690127f12 --- /dev/null +++ b/boards/common/esp32h2/include/board_common_esp32h2.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2025 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#pragma once + +/** + * @ingroup boards_common_esp32h2 + * @brief Board definitions that are common for all ESP32-H2 boards. + * + * This file contains board configurations that are valid for all ESP32-H2. + * + * For detailed information about the configuration of ESP32-H2 boards, see + * section \ref esp32_peripherals "Common Peripherals". + * + * @author Gunar Schorcht + * @file + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !DOXYGEN + +/** + * @name ztimer Configuration valid for all ESP32-H2 boards + * @{ + */ + +#if CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ == 96 +# define CONFIG_ZTIMER_USEC_ADJUST_SET 14 +# define CONFIG_ZTIMER_USEC_ADJUST_SLEEP 13 +#elif CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ == 64 +# define CONFIG_ZTIMER_USEC_ADJUST_SET 19 +# define CONFIG_ZTIMER_USEC_ADJUST_SLEEP 18 +#elif CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ == 48 +# define CONFIG_ZTIMER_USEC_ADJUST_SET 34 +# define CONFIG_ZTIMER_USEC_ADJUST_SLEEP 32 +#elif CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ == 32 +# define CONFIG_ZTIMER_USEC_ADJUST_SET 32 +# define CONFIG_ZTIMER_USEC_ADJUST_SLEEP 33 +#elif CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ == 16 +# define CONFIG_ZTIMER_USEC_ADJUST_SET 129 +# define CONFIG_ZTIMER_USEC_ADJUST_SLEEP 135 +#else +# error "Invalid CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ value" +#endif + +/** @} */ + +#endif /* !DOXYGEN */ + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +/** @} */ diff --git a/boards/common/esp32h2/include/periph_conf_common_esp32h2.h b/boards/common/esp32h2/include/periph_conf_common_esp32h2.h new file mode 100644 index 000000000000..e2de86fdd5fe --- /dev/null +++ b/boards/common/esp32h2/include/periph_conf_common_esp32h2.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2025 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#pragma once + +/** + * @ingroup boards_common_esp32h2 + * @brief Common peripheral configurations for ESP32-H2 boards + * + * This file contains the peripheral configurations that are valid for all + * ESP32-H2 boards. + * + * For detailed information about the peripheral configuration for ESP32-H2 + * boards, see section \ref esp32_peripherals "Common Peripherals". + * + * @author Gunar Schorcht + * @file + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name UART configuration + * @{ + */ +#ifndef UART0_TXD +# define UART0_TXD (GPIO24) /**< TxD of UART_DEV(0) used on all ESP32-H2 boards */ +#endif + +#ifndef UART0_RXD +# define UART0_RXD (GPIO23) /**< RxD of UART_DEV(0) used on all ESP32-H2 boards */ +#endif +/** @} */ + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +/** @} */ diff --git a/boards/common/esp32x/include/board_common.h b/boards/common/esp32x/include/board_common.h index c986a934f7d2..4798650f8fd1 100644 --- a/boards/common/esp32x/include/board_common.h +++ b/boards/common/esp32x/include/board_common.h @@ -38,6 +38,8 @@ # include "board_common_esp32.h" #elif defined(CPU_FAM_ESP32C3) # include "board_common_esp32c3.h" +#elif defined(CPU_FAM_ESP32H2) +# include "board_common_esp32h2.h" #elif defined(CPU_FAM_ESP32S2) # include "board_common_esp32s2.h" #elif defined(CPU_FAM_ESP32S3) diff --git a/boards/common/esp32x/include/periph_conf_common.h b/boards/common/esp32x/include/periph_conf_common.h index dfb4df6447c8..42cf3d38b856 100644 --- a/boards/common/esp32x/include/periph_conf_common.h +++ b/boards/common/esp32x/include/periph_conf_common.h @@ -24,15 +24,17 @@ */ #if defined(CPU_FAM_ESP32) -#include "periph_conf_common_esp32.h" +# include "periph_conf_common_esp32.h" #elif defined(CPU_FAM_ESP32C3) -#include "periph_conf_common_esp32c3.h" +# include "periph_conf_common_esp32c3.h" +#elif defined(CPU_FAM_ESP32H2) +# include "periph_conf_common_esp32h2.h" #elif defined(CPU_FAM_ESP32S2) -#include "periph_conf_common_esp32s2.h" +# include "periph_conf_common_esp32s2.h" #elif defined(CPU_FAM_ESP32S3) -#include "periph_conf_common_esp32s3.h" +# include "periph_conf_common_esp32s3.h" #else -#error "ESP32x SoC family not supported" +# error "ESP32x SoC family not supported" #endif /* include periph_cpu.h to make it visible in any case */ diff --git a/boards/esp32h2-devkit/Kconfig b/boards/esp32h2-devkit/Kconfig new file mode 100644 index 000000000000..0630d5ebfdf6 --- /dev/null +++ b/boards/esp32h2-devkit/Kconfig @@ -0,0 +1,16 @@ +# Copyright (c) 2025 Gunar Schorcht +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. + +config BOARD + default "esp32h2-devkit" if BOARD_ESP32H2_DEVKIT + +config BOARD_ESP32H2_DEVKIT + bool + default y + select BOARD_COMMON_ESP32H2 + select CPU_MODEL_ESP32H2_MINI_1X_H4S + +source "$(RIOTBOARD)/common/esp32h2/Kconfig" diff --git a/boards/esp32h2-devkit/Makefile b/boards/esp32h2-devkit/Makefile new file mode 100644 index 000000000000..bd237085cf7a --- /dev/null +++ b/boards/esp32h2-devkit/Makefile @@ -0,0 +1,5 @@ +MODULE = board + +DIRS = $(RIOTBOARD)/common/esp32h2 + +include $(RIOTBASE)/Makefile.base diff --git a/boards/esp32h2-devkit/Makefile.dep b/boards/esp32h2-devkit/Makefile.dep new file mode 100644 index 000000000000..0ee98219c3fe --- /dev/null +++ b/boards/esp32h2-devkit/Makefile.dep @@ -0,0 +1,5 @@ +include $(RIOTBOARD)/common/esp32h2/Makefile.dep + +ifneq (,$(filter saul_default,$(USEMODULE))) + USEMODULE += saul_gpio +endif diff --git a/boards/esp32h2-devkit/Makefile.features b/boards/esp32h2-devkit/Makefile.features new file mode 100644 index 000000000000..0d4cb86f2615 --- /dev/null +++ b/boards/esp32h2-devkit/Makefile.features @@ -0,0 +1,20 @@ +CPU_MODEL = esp32h2_mini_1x_h4s + +# common board and CPU features +include $(RIOTBOARD)/common/esp32h2/Makefile.features + +# additional features provided by the board +FEATURES_PROVIDED += periph_adc +FEATURES_PROVIDED += periph_i2c +FEATURES_PROVIDED += periph_pwm +FEATURES_PROVIDED += periph_spi + +# unique features provided by the board +FEATURES_PROVIDED += esp_jtag + +FEATURES_PROVIDED += arduino_analog +FEATURES_PROVIDED += arduino_i2c +FEATURES_PROVIDED += arduino_pins +FEATURES_PROVIDED += arduino_pwm +FEATURES_PROVIDED += arduino_spi +FEATURES_PROVIDED += arduino_uart diff --git a/boards/esp32h2-devkit/Makefile.include b/boards/esp32h2-devkit/Makefile.include new file mode 100644 index 000000000000..d719a9689141 --- /dev/null +++ b/boards/esp32h2-devkit/Makefile.include @@ -0,0 +1,5 @@ +include $(RIOTBOARD)/common/esp32h2/Makefile.include + +# Only consider TTYs matching the following filter when auto-selecting the TTY +# with `MOST_RECENT_PORT=1`. +TTY_BOARD_FILTER := --driver 'cp210x' --vendor 'Silicon Labs' --model 'CP2102N USB to UART Bridge Controller' diff --git a/boards/esp32h2-devkit/doc.md b/boards/esp32h2-devkit/doc.md new file mode 100644 index 000000000000..4d8d85d7c7fc --- /dev/null +++ b/boards/esp32h2-devkit/doc.md @@ -0,0 +1,153 @@ + + +@defgroup boards_esp32h2_devkit ESP32-H2-DevKitM-1 Board +@ingroup boards_esp32h2 +@brief Support for generic ESP32-H2 boards +@author Gunar Schorcht + +\section esp32h2_devkit ESP32-H2-DevKitM-1 + +## Table of Contents {#esp32h2_devkit_toc} + +-# [Overview](#esp32h2_devkit_overview) +-# [Hardware](#esp32h2_devkit_hardware) + -# [MCU](#esp32h2_devkit_mcu) + -# [Board Configuration](#esp32h2_devkit_board_configuration) + -# [Board Pinout](#esp32h2_devkit_pinout) +-# [Flashing the Device](#esp32h2_devkit_flashing) + +## Overview {#esp32h2_devkit_overview} + +The Espressif ESP32-H2-DevKitM-1 board uses the ESP32-H2-MINI-1x module. + +Since the number of GPIOs and their possible uses on the ESP32-H2 are quite +limited, the ESP32-H2-DevKitM-1 should also work for most other ESP32-H2 boards. +Any modifications required for specific applications could be overridden by +\ref esp32_application_specific_configurations "application-specific board configuration". + +\image html "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32h2/_images/esp32-h2-devkitm-1_v1.2_callouts.png" "Espressif ESP32-H2-DevKitM-1" width=800px + +[Back to table of contents](#esp32h2_devkit_toc) + +## Hardware {#esp32h2_devkit_hardware} + +This section describes + +- the [MCU](#esp32h2_devkit_mcu), +- the default [board configuration](#esp32h2_devkit_board_configuration), +- [optional hardware configurations](#esp32h2_devkit_optional_hardware), +- the [board pinout](#esp32h2_devkit_pinout). + +[Back to table of contents](#esp32h2_devkit_toc) + +### MCU {#esp32h2_devkit_mcu} + +Most features of the board are provided by the ESP32-H2 SoC. For detailed +information about the ESP32-H2 variant (family) and ESP32x SoCs, +see section \ref esp32_mcu_esp32 "ESP32 SoC Series". + +[Back to table of contents](#esp32h2_devkit_toc) + +### Board Configuration {#esp32h2_devkit_board_configuration} + +ESP32-H2-DevKitM-1 boards have no special hardware on board with the exception +of a WS2812-compatible RGB-LED. + +All GPIOs are simply broken out for flexibility. Therefore, the board +configuration is the most flexible one which provides: + +- 5 x ADC channels at maximum +- 1 x SPI +- 1 x I2C +- 1 x UART +- 2 x PWM with 3 channels each +- 1 x RGB-LED + +Since all GPIOs are broken out, GPIOs can be used for different purposes +in different applications. For flexibility, GPIOs can be listed in multiple +peripheral configurations, but they can only be used for one peripheral +at a time. For example, GPIO1, GPIO3, GPIO4 and GPIO5 can be used as ADC +channels or as signals for SPI_DEV(0) and PWM_DEV(1). + +This is possible because GPIOs are only used for a specific peripheral +interface when either + +- the corresponding peripheral module is used, i.e. `periph_spi`, or +- the corresponding init function is called, i.e. `adc_init`, or +- the corresponding init function is called, i.e. `pwm_init` + +That is, the purpose for which a GPIO is used depends on which module +or function is used first. + +For example, if module `periph_spi` is not used, the GPIOs listed in SPI +configuration can be used for the other purposes, that is, GPIO1, GPIO4 and +GPIO5 can be used as ADC channels or PWM channels. + +The following table shows the default board configuration, which is sorted +according to the defined functionality of GPIOs. This configuration can be +overridden by \ref esp32_application_specific_configurations +"application-specific configurations". + +
+Function | GPIOs | Remarks |Configuration +:---------------|:-------|:--------|:---------------------------------- +BUTTON0 | GPIO9 | | | +ADC | GPIO1, GPIO2, GPIO3, GPIO4, GPIO5 | | see \ref esp32_adc_channels "ADC Channels" +PWM_DEV(0) | GPIO2, GPIO12, GPIO22 | - | \ref esp32_pwm_channels "PWM Channels" +PWM_DEV(1) | GPIO1, GPIO3, GPIO5 | - | \ref esp32_pwm_channels "PWM Channels" +I2C_DEV(0):SCL | GPIO10 | | \ref esp32_i2c_interfaces "I2C Interfaces" +I2C_DEV(0):SDA | GPIO11 | | \ref esp32_i2c_interfaces "I2C Interfaces" +RGB-LED | GPIO8 | supported by driver module `ws281x` | | +SPI_DEV(0):SCK | GPIO4 | SPI2_HOST (FSPI) is used | \ref esp32_spi_interfaces "SPI Interfaces" +SPI_DEV(0):MISO | GPIO5 | SPI2_HOST (FSPI) is used | \ref esp32_spi_interfaces "SPI Interfaces" +SPI_DEV(0):MOSI | GPIO0 | SPI2_HOST (FSPI) is used | \ref esp32_spi_interfaces "SPI Interfaces" +SPI_DEV(0):CS0 | GPIO1 | SPI2_HOST (FSPI) is used | \ref esp32_spi_interfaces "SPI Interfaces" +UART_DEV(0):TxD | GPIO24 | Console (configuration is fixed) | \ref esp32_uart_interfaces "UART interfaces" +UART_DEV(0):RxD | GPIO23 | Console (configuration is fixed) | \ref esp32_uart_interfaces "UART interfaces" +USB D- | GPIO26 | | | +USB D+ | GPIO26 | | | +
+\n +@note +- The configuration of ADC channels contains all ESP32-H2 GPIOs that could + be used as ADC channels. +- GPIO6 and GPIO7 are not broken out for any reason. +- GPPIO15 to GPIO21 are used for the in-package flash and are not broken out. + +For detailed information about the peripheral configurations of ESP32-H2 +boards, see section \ref esp32_peripherals "Common Peripherals". + +[Back to table of contents](#esp32h2_devkit_toc) + +### Board Pinout {#esp32h2_devkit_pinout} + +The following figures show the pinout as configured by default board +definition. + +@image html https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32h2/_images/esp32-h2-devkitm-1-v1.2_pinlayout.png "EPS32-H2-DevKitM-1 Pinout" + +The corresponding board schematics can be found: + +- [ESP32-H2-DevKitM-1 v1.2](https://dl.espressif.com/dl/schematics/esp32-h2-devkitm-1_v1.2_schematics.pdf) +- [ESP32-H2-DevKitM-1 v1.3](https://dl.espressif.com/dl/schematics/esp32-h2-devkitm-1_v1.3_schematics.pdf) + +[Back to table of contents](#esp32h2_devkit_toc) + +## Flashing the Device {#esp32h2_devkit_flashing} + +Flashing RIOT is quite easy. The board has a Micro-USB connector with +reset/boot/flash logic. Just connect the board to your host computer +and type using the programming port: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +make flash BOARD=esp32h2-devkit ... +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +For detailed information about ESP32-H2 as well as configuring and compiling +RIOT for ESP32-H2 boards, see \ref esp32_riot. + +[Back to table of contents](#esp32h2_devkit_toc) diff --git a/boards/esp32h2-devkit/include/arduino_iomap.h b/boards/esp32h2-devkit/include/arduino_iomap.h new file mode 100644 index 000000000000..16f92a46b7ea --- /dev/null +++ b/boards/esp32h2-devkit/include/arduino_iomap.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2025 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#pragma once + +/** + * @ingroup boards_esp32h2_devkit + * @{ + * + * @file + * @brief Mapping from MCU pins to Arduino pins + * + * @author Gunar Schorcht + */ + +#include "periph/gpio.h" +#include "periph/adc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Mapping of MCU pins to Arduino pins + * @{ + */ +#define ARDUINO_PIN_0 GPIO23 /**< Arduino pin 0 (RxD) */ +#define ARDUINO_PIN_1 GPIO24 /**< Arduino pin 1 (TxD) */ +#define ARDUINO_PIN_2 GPIO25 /**< Arduino pin 2 */ +#define ARDUINO_PIN_3 GPIO2 /**< Arduino pin 3 (PWM) */ +#if !defined(MODULE_ESP_RTC_TIMER_32K) +# define ARDUINO_PIN_4 GPIO13 /**< Arduino pin 4 */ +#endif +#define ARDUINO_PIN_5 GPIO12 /**< Arduino pin 5 (PWM) */ +#define ARDUINO_PIN_6 GPIO22 /**< Arduino pin 6 (PWM) */ +#define ARDUINO_PIN_7 GPIO9 /**< Arduino pin 7 (BTN0 input) */ +#define ARDUINO_PIN_8 GPIO8 /**< Arduino pin 8 (RGB output) */ +#define ARDUINO_PIN_9 GPIO3 /**< Arduino pin 9 (PWM) */ + +#define ARDUINO_PIN_10 GPIO1 /**< Arduino pin 10 (CS0 / PWM) */ +#define ARDUINO_PIN_11 GPIO5 /**< Arduino pin 11 (MOSI / PWM) */ +#define ARDUINO_PIN_12 GPIO0 /**< Arduino pin 12 (MISO) */ +#define ARDUINO_PIN_13 GPIO4 /**< Arduino pin 13 (SCK) */ + +/* analog pins as digital pins: */ +#define ARDUINO_PIN_14 GPIO1 /**< Arduino pin A0 */ +#define ARDUINO_PIN_15 GPIO2 /**< Arduino pin A1 */ +#define ARDUINO_PIN_16 GPIO3 /**< Arduino pin A2 */ +#define ARDUINO_PIN_17 GPIO4 /**< Arduino pin A3 */ + +/* I2C digital pins: */ +#define ARDUINO_PIN_18 GPIO11 /**< Arduino SDA */ +#define ARDUINO_PIN_19 GPIO10 /**< Arduino SCL */ + +#define ARDUINO_PIN_LAST 19 /**< Last Arduino pin */ +/** @} */ + +/** + * @name Aliases for analog pins + * @{ + */ +#define ARDUINO_PIN_A0 ARDUINO_PIN_14 /**< Arduino pin A0 */ +#define ARDUINO_PIN_A1 ARDUINO_PIN_15 /**< Arduino pin A1 */ +#define ARDUINO_PIN_A2 ARDUINO_PIN_16 /**< Arduino pin A2 */ +#define ARDUINO_PIN_A3 ARDUINO_PIN_17 /**< Arduino pin A3 */ + +#define ARDUINO_ANALOG_PIN_LAST 3 /**< Last analogue Arduino pin */ +/** @} */ + +/** + * @name Mapping of Arduino analog pins to RIOT ADC lines + * @{ + */ +#define ARDUINO_A0 ADC_LINE(0) /**< ADC line for Arduino pin A0 */ +#define ARDUINO_A1 ADC_LINE(1) /**< ADC line for Arduino pin A1 */ +#define ARDUINO_A2 ADC_LINE(2) /**< ADC line for Arduino pin A2 */ +#define ARDUINO_A3 ADC_LINE(3) /**< ADC line for Arduino pin A3 */ +/** @} */ + +/** + * @name Mapping of Arduino pins to RIOT PWM dev and channel pairs + * @{ + */ +#define ARDUINO_PIN_3_PWM_DEV PWM_DEV(0) /**< PWM device for Arduino pin3 */ +#define ARDUINO_PIN_3_PWM_CHAN 0 /**< PWM channel for Arduino pin3 */ + +#define ARDUINO_PIN_5_PWM_DEV PWM_DEV(0) /**< PWM device for Arduino pin5 */ +#define ARDUINO_PIN_5_PWM_CHAN 1 /**< PWM channel for Arduino pin5 */ + +#define ARDUINO_PIN_6_PWM_DEV PWM_DEV(0) /**< PWM device for Arduino pin6 */ +#define ARDUINO_PIN_6_PWM_CHAN 2 /**< PWM channel for Arduino pin6 */ + +#define ARDUINO_PIN_9_PWM_DEV PWM_DEV(1) /**< PWM device for Arduino pin9 */ +#define ARDUINO_PIN_9_PWM_CHAN 1 /**< PWM channel for Arduino pin9 */ + +#define ARDUINO_PIN_10_PWM_DEV PWM_DEV(1) /**< PWM device for Arduino pin10 */ +#define ARDUINO_PIN_10_PWM_CHAN 0 /**< PWM channel for Arduino pin10 */ + +#define ARDUINO_PIN_11_PWM_DEV PWM_DEV(1) /**< PWM device for Arduino pin11 */ +#define ARDUINO_PIN_11_PWM_CHAN 2 /**< PWM channel for Arduino pin11 */ +/** @} */ + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/boards/esp32h2-devkit/include/board.h b/boards/esp32h2-devkit/include/board.h new file mode 100644 index 000000000000..71d5e21f0a0d --- /dev/null +++ b/boards/esp32h2-devkit/include/board.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2025 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#pragma once + +/** + * @ingroup boards_esp32h2_devkit + * @brief Board definitions for ESP32-H2-DevKitM-1 boards + * @{ + * + * The board definitions in this file are valid for the Espressif + * ESP32-H2-DevKitM-1 board the ESP32-H2-MINI-1x module. + * + * Since the number of GPIOs and their possible uses on the ESP32-H2 are quite + * limited, these board definitions can also be used for most other + * ESP32-H2 boards. Any modifications required for specific applications + * can be overridden by \ref esp32_application_specific_configurations + * "application-specific board configuration". + * + * @file + * @author Gunar Schorcht + */ + +#include + +/** + * @name Button pin definitions + * @{ + */ + +/** + * @brief Default button GPIO pin definition + * + * ESP32-H2-DevKitM-1 boards have a BOOT button connected to GPIO9, which can be + * used as button during normal operation. Since the button connects GPIO9 pin + * to GND, the button signal is inverted, i.e., pressing the button will give a + * low signal. + */ +#define BTN0_PIN GPIO9 + +/** + * @brief Default button GPIO mode definition + * + * Since the GPIO of the button is not pulled up with an external resistor, the + * mode for the GPIO pin has to be GPIO_IN_PU. + */ +#define BTN0_MODE GPIO_IN_PU + +/** + * @brief Default interrupt flank definition for the button GPIO + */ +#ifndef BTN0_INT_FLANK +# define BTN0_INT_FLANK GPIO_FALLING +#endif + +/** + * @brief Definition for compatibility with previous versions + */ +#define BUTTON0_PIN BTN0_PIN + +/** @} */ + +/** + * @name LED (on-board) configuration + * + * ESP32-H2-DevKitM-1 boards have a SK68XXMINI-HS smart RGB-LED connected to + * GPIO8 on-board. The WS281x driver module `ws281x` can be used to control it. + * @{ + */ +#ifndef WS281X_PARAM_PIN +# define WS281X_PARAM_PIN (GPIO8) /**< GPIO pin connected to the data pin */ +#endif +#ifndef WS281X_PARAM_NUMOF +# define WS281X_PARAM_NUMOF (1U) /**< Number of LEDs chained */ +#endif +/** @} */ + +/* include common board definitions as last step */ +#include "board_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +/** @} */ diff --git a/boards/esp32h2-devkit/include/gpio_params.h b/boards/esp32h2-devkit/include/gpio_params.h new file mode 100644 index 000000000000..cefc80ca8f1c --- /dev/null +++ b/boards/esp32h2-devkit/include/gpio_params.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2025 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#pragma once + +/** + * @ingroup boards_esp32h2_devkit + * @brief Board specific configuration of direct mapped GPIOs + * @file + * @author Gunar Schorcht + * @{ + */ + +#include "board.h" +#include "saul/periph.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief LED and Button configuration + */ +static const saul_gpio_params_t saul_gpio_params[] = +{ + { + .name = "BOOT", + .pin = BTN0_PIN, + .mode = BTN0_MODE, + .flags = SAUL_GPIO_INVERTED + }, +}; + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/boards/esp32h2-devkit/include/periph_conf.h b/boards/esp32h2-devkit/include/periph_conf.h new file mode 100644 index 000000000000..9d6e8d5f6309 --- /dev/null +++ b/boards/esp32h2-devkit/include/periph_conf.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2025 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#pragma once + +/** + * @ingroup boards_esp32h2_devkit + * @brief Peripheral configurations for ESP32-H2-DevKit boards + * @{ + * + * The peripheral configurations in this file are valid for Espressif + * ESP32-H2-DevKitx boards that use the ESP32-H2-MINI-1x module. + * + * Since the number of GPIOs and their possible uses on the ESP32-H2 are quite + * limited, these peripheral configurations can also be used for most other + * ESP32-H2 boards. Any modifications required for specific applications + * can be overridden by \ref esp32_application_specific_configurations + * "application-specific board configuration". + * + * For detailed information about the peripheral configuration for ESP32-H2 + * boards, see section \ref esp32_peripherals "Common Peripherals". + * + * @note + * Most definitions can be overridden by an \ref esp32_application_specific_configurations + * "application-specific board configuration" if necessary. + * + * @file + * @author Gunar Schorcht + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name ADC and DAC channel configuration + * @{ + */ +/** + * @brief Declaration of GPIOs that can be used as ADC channels + * + * For generic boards, all ADC pins that are broken out are declared as ADC + * channels. + * + * @note As long as the GPIOs listed in ADC_GPIOS are not initialized as ADC + * channels with the `adc_init` function, they can be used for other + * purposes. + */ +#ifndef ADC_GPIOS +# define ADC_GPIOS { GPIO1, GPIO2, GPIO3, GPIO4, GPIO5 } +#endif +/** @} */ + +/** + * @name I2C configuration + * + * For generic boards, only one I2C interface I2C_DEV(0) is defined. + * + * The GPIOs listed in the configuration are only initialized as I2C signals + * when module `periph_i2c` is used. Otherwise they are not allocated and + * can be used for other purposes. + * + * @{ + */ +#ifndef I2C0_SPEED +# define I2C0_SPEED I2C_SPEED_FAST /**< I2C bus speed of I2C_DEV(0) */ +#endif +#ifndef I2C0_SCL +# define I2C0_SCL GPIO10 /**< SCL signal of I2C_DEV(0) */ +#endif +#ifndef I2C0_SDA +# define I2C0_SDA GPIO11 /**< SDA signal of I2C_DEV(0) */ +#endif +/** @} */ + +/** + * @name PWM channel configuration + * + * For generic boards, two PWM devices are configured. Generally, all output + * pins could be used as PWM channels. + * @{ + */ + +/** + * @brief Declaration of the channels for device PWM_DEV(0), at maximum PWM_CHANNEL_NUM_DEV_MAX. + * + * @note PWM_DEV(0) contains only GPIOs that are not used for I2C, SPI + * or UART on this board. As long as the according PWM device is not + * initialized with the `pwm_init` function, the GPIOs declared for + * this device can be used for the other purposes. + */ +#ifndef PWM0_GPIOS +# define PWM0_GPIOS { GPIO2, GPIO12, GPIO22 } +#endif + +/** + * @brief Declaration of the channels for device PWM_DEV(1), at maximum PWM_CHANNEL_NUM_DEV_MAX. + * + * @note PMW_DEV(1) contains pins that are also used by SPI_DEV(0) or as ADC + * channel. However, as long as the according PWM device is not + * initialized with the `pwm_init` function, the GPIOs declared for + * this device can be used for the other purposes. + */ +#ifndef PWM1_GPIOS +# define PWM1_GPIOS { GPIO1, GPIO3, GPIO5 } +#endif + +/** @} */ + +/** + * @name SPI configuration + * + * @note The GPIOs listed in the configuration are only initialized as SPI + * signals when the corresponding SPI interface is used for the first time + * by either calling the `spi_init_cs` function or the `spi_acquire` + * function. That is, they are not allocated as SPI signals before and can + * be used for other purposes as long as the SPI interface is not used. + * @{ + */ +#ifndef SPI0_CTRL +# define SPI0_CTRL FSPI /**< FSPI is used as SPI_DEV(0) */ +#endif +#ifndef SPI0_SCK +# define SPI0_SCK GPIO4 /**< FSPI SCK (pin FSPICLK) */ +#endif +#ifndef SPI0_MISO +# define SPI0_MISO GPIO5 /**< FSPI MISO (pin FSPIQ) */ +#endif +#ifndef SPI0_MOSI +# define SPI0_MOSI GPIO0 /**< FSPI MOSI (pin FSPID) */ +#endif +#ifndef SPI0_CS0 +# define SPI0_CS0 GPIO1 /**< FSPI CS0 (pin FSPICS0) */ +#endif +/** @} */ + +/** + * @name UART configuration + * + * ESP32-H2 provides 2 UART interfaces: + * + * UART_DEV(0) uses fixed standard configuration.
+ * UART_DEV(1) is not used.
+ * + * @{ + */ +#define UART0_TXD GPIO24 /**< direct I/O pin for UART_DEV(0) TxD, can't be changed */ +#define UART0_RXD GPIO23 /**< direct I/O pin for UART_DEV(0) RxD, can't be changed */ + +/** @} */ + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +/* include common peripheral definitions as last step */ +#include "periph_conf_common.h" + +/** @} */ diff --git a/cpu/esp32/Kconfig b/cpu/esp32/Kconfig index 6afb62a58ba4..3e86529eb9f7 100644 --- a/cpu/esp32/Kconfig +++ b/cpu/esp32/Kconfig @@ -26,14 +26,22 @@ config CPU_CORE_RV32IMC help CPU core of the ESP32x SoC is a RISC-V core. +config CPU_CORE_RV32IMAC + bool + select CPU_ARCH_RISCV + help + CPU core of the ESP32x SoC is a RISC-V core. + config CPU_CORE default "xtensa-lx6" if CPU_CORE_XTENSA_LX6 default "xtensa-lx7" if CPU_CORE_XTENSA_LX7 default "rv32imc" if CPU_CORE_RV32IMC + default "rv32imac" if CPU_CORE_RV32IMAC rsource "Kconfig.esp32x" rsource "Kconfig.esp32" rsource "Kconfig.esp32c3" +rsource "Kconfig.esp32h2" rsource "Kconfig.esp32s3" rsource "Kconfig.esp32s2" diff --git a/cpu/esp32/Kconfig.esp32h2 b/cpu/esp32/Kconfig.esp32h2 new file mode 100644 index 000000000000..68ebf779bf9d --- /dev/null +++ b/cpu/esp32/Kconfig.esp32h2 @@ -0,0 +1,104 @@ +# Copyright (c) 2025 Gunar Schorcht +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. + +config CPU_FAM_ESP32H2 + bool + select CPU_COMMON_ESP32X + select CPU_CORE_RV32IMAC + +config CPU_FAM + default "esp32h2" if CPU_FAM_ESP32H2 + +## CPU Models +config CPU_MODEL_ESP32H2_FH2S + bool + select CPU_FAM_ESP32H2 + help + ESP32-H2 CPU with 2 MB Flash + +config CPU_MODEL_ESP32H2_FH4S + bool + select CPU_FAM_ESP32H2 + help + ESP32-H2 CPU with 4 MB Flash + +## CPU Modules +config CPU_MODEL_ESP32H2_MINI_1X_H2S + bool + select CPU_MODEL_ESP32H2_FH2S + help + ESP32-H2-MINI-1-H2S or ESP32-H2-MINI-1U-H2S module with 2 MB Flash + +config CPU_MODEL_ESP32H2_MINI_1X_H4S + bool + select CPU_MODEL_ESP32H2_FH4S + help + ESP32-H2-MINI-1-H4S or ESP32-H2-MINI-1U-H4S module with 4 MB Flash + +config CPU_MODEL_ESP32H2_WROOM_02C_H2S + bool + select CPU_MODEL_ESP32H2_FH2S + help + ESP32-H2-WROOM-02C-H2S module with 2 MB Flash + +config CPU_MODEL_ESP32H2_WROOM_02C_H4S + bool + select CPU_MODEL_ESP32H2_FH4S + help + ESP32-H2-WROOM-02C-H4S module with 2 MB Flash + +## Choice +config CPU_MODEL + depends on CPU_FAM_ESP32H2 + default "esp32h2_mini_1x_h2s" if CPU_MODEL_ESP32H2_MINI_1X_H2S + default "esp32h2_mini_1x_h4s" if CPU_MODEL_ESP32H2_MINI_1X_H4S + default "esp32h2_wroom_02c_h2s" if CPU_MODEL_ESP32H2_WROOM_02C_H2S + default "esp32h2_wroom_02c_h4s" if CPU_MODEL_ESP32H2_WROOM_02C_H4S + default "esp32h2_fh2s" if CPU_MODEL_ESP32H2_FH2S + default "esp32h2_fh4s" if CPU_MODEL_ESP32H2_FH4S + +if CPU_FAM_ESP32H2 + +menu "ESP32-H2 specific configurations" + depends on HAS_ARCH_ESP32 + + # define configuration menu entries for ESP32-H2 variant (family) + + choice + bool "CPU clock frequency" + default ESP32H2_DEFAULT_CPU_FREQ_MHZ_96 + help + CPU clock frequency used (default 96 MHz). + Please note that peripherals such as I2C or SPI might not work at + the specified clock frequency if the selected CPU clock frequency + is too low. These peripherals are clocked by the APB clock, which + has a clock rate of 32 MHz for CPU clock frequencies greater than + or equal to 32 MHz, but is equal to the CPU clock frequency for + CPU clock frequencies less than 32 MHz. Thus, for SPI, the APB + clock rate must be at least five times the SPI clock rate. For the + I2C hardware implementation, the APB clock rate must be at least + 3 MHZ to use I2C in fast mode with a I2C clock rate of 400 kHz. + For the I2C software implementation, the maximum I2C clock rate + is 1/130 times the CPU clock rate. + + config ESP32H2_DEFAULT_CPU_FREQ_MHZ_16 + bool "16 MHz" + config ESP32H2_DEFAULT_CPU_FREQ_MHZ_32 + bool "32 MHz" + config ESP32H2_DEFAULT_CPU_FREQ_MHZ_48 + bool "48 MHz" + config ESP32H2_DEFAULT_CPU_FREQ_MHZ_64 + bool "64 MHz" + config ESP32H2_DEFAULT_CPU_FREQ_MHZ_96 + bool "96 MHz" + endchoice + + # import configuration menu entries that are common for all ESP32x SoCs + rsource "Kconfig.common" + +endmenu + +endif # CPU_FAM_ESP32H2 diff --git a/cpu/esp32/Makefile.features b/cpu/esp32/Makefile.features index 7ff0e3ade6e1..5e62d566d503 100644 --- a/cpu/esp32/Makefile.features +++ b/cpu/esp32/Makefile.features @@ -1,9 +1,12 @@ ifeq (esp32,$(CPU_FAM)) CPU_ARCH = xtensa CPU_CORE = xtensa-lx6 -else ifneq (,$(filter esp32c3,$(CPU_FAM))) +else ifeq (esp32c3,$(CPU_FAM)) CPU_ARCH = rv32 CPU_CORE = rv32imc +else ifeq (esp32h2,$(CPU_FAM)) + CPU_ARCH = rv32 + CPU_CORE = rv32imac else ifneq (,$(filter esp32s2 esp32s3,$(CPU_FAM))) CPU_ARCH = xtensa CPU_CORE = xtensa-lx7 @@ -17,7 +20,6 @@ include $(RIOTCPU)/esp_common/Makefile.features FEATURES_PROVIDED += arch_esp32 FEATURES_PROVIDED += esp_rmt -FEATURES_PROVIDED += esp_wifi_enterprise FEATURES_PROVIDED += periph_flashpage FEATURES_PROVIDED += periph_flashpage_in_address_space FEATURES_PROVIDED += periph_flashpage_pagewise @@ -38,6 +40,11 @@ ifeq (xtensa,$(CPU_ARCH)) FEATURES_PROVIDED += esp_hw_counter endif +ifneq (esp32h2,$(CPU_FAM)) + # ESP32-H2 doesn't have a WiFi module + FEATURES_PROVIDED += esp_wifi_enterprise +endif + ifeq (esp32,$(CPU_FAM)) FEATURES_PROVIDED += ble_nimble FEATURES_PROVIDED += ble_nimble_netif diff --git a/cpu/esp32/Makefile.include b/cpu/esp32/Makefile.include index f5780e701065..17a159bab094 100644 --- a/cpu/esp32/Makefile.include +++ b/cpu/esp32/Makefile.include @@ -19,11 +19,16 @@ else ifneq (,$(filter esp32c3 esp32s3,$(CPU_FAM))) export FLASH_FREQ ?= 80m export FLASH_SIZE ?= 2 BOOTLOADER_POS = 0x0000 -else ifneq (,$(filter esp32s2,$(CPU_FAM))) +else ifeq (esp32s2,$(CPU_FAM)) export FLASH_MODE ?= qio export FLASH_FREQ ?= 80m export FLASH_SIZE ?= 4 BOOTLOADER_POS = 0x1000 +else ifeq (esp32h2,$(CPU_FAM)) + export FLASH_MODE ?= dio + export FLASH_FREQ ?= 48m + export FLASH_SIZE ?= 2 + BOOTLOADER_POS = 0x0000 else $(error No known flash config for ESP32x SoC variant (family): $(CPU_FAM)) endif @@ -55,6 +60,11 @@ else ifeq (esp32c3,$(CPU_FAM)) # used as instruction cache via the instruction bus. RAM_LEN = 320K RAM_START_ADDR = 0x3FC80000 +else ifeq (esp32h2,$(CPU_FAM)) + # ESP32-H2 has 320 kByte RAM but the 2nd stage bootloader starts at 0x4083EFD0 + # so that there are only 258,000 byte (about 250 kByte) remaining + RAM_LEN = 250K + RAM_START_ADDR = 0x40800000 else $(error Missing ram configuration for ESP32x SoC variant (family): $(CPU_FAM)) endif @@ -168,11 +178,14 @@ ifneq (,$(filter xtensa%,$(TARGET_ARCH))) endif ifneq (,$(filter esp_ble,$(USEMODULE))) - ifeq (esp32,$(CPU_FAM)) + ifneq (,$(filter esp32 esp32h2,$(CPU_FAM))) INCLUDES += -I$(ESP32_SDK_DIR)/components/bt/include/$(CPU_FAM)/include else ifneq (,$(filter esp32s3 esp32c3,$(CPU_FAM))) INCLUDES += -I$(ESP32_SDK_DIR)/components/bt/include/esp32c3/include endif + ifeq (esp32h2,$(CPU_FAM)) + INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_hw_support/port/$(CPU_FAM)/private_include + endif endif ifneq (,$(filter esp_ble_nimble,$(USEMODULE))) @@ -252,6 +265,8 @@ CFLAGS += -DCONFIG_IDF_TARGET_$(call uppercase_and_underscore,$(CPU_FAM)) CFLAGS += -DCONFIG_IDF_TARGET=\"$(CPU_FAM)\" CFLAGS += -DESP_PLATFORM CFLAGS += -DLOG_TAG_IN_BRACKETS +CFLAGS += -DRIOT_BUILD=1 +CFLAGS += -DSOC_MMU_PAGE_SIZE=CONFIG_MMU_PAGE_SIZE # extend CFLAGS by the corresponding FLASH_FREQ ifeq (20m,$(FLASH_FREQ)) @@ -287,9 +302,11 @@ CFLAGS += -D_CONST=const # TODO no relaxation yet ifneq (,$(filter riscv%,$(TARGET_ARCH))) CFLAGS += -DCONFIG_IDF_TARGET_ARCH_RISCV - CFLAGS += -mno-relax -march=rv32imc_zicsr_zifencei -mabi=ilp32 -DRISCV_NO_RELAX + CFLAGS += -mno-relax -mabi=ilp32 -DRISCV_NO_RELAX + CFLAGS += -fno-jump-tables LDGENFLAGS += -DCONFIG_IDF_TARGET_ARCH_RISCV - LINKFLAGS += -mno-relax -march=rv32imc_zicsr_zifencei -mabi=ilp32 + LINKFLAGS += -mno-relax -mabi=ilp32 + LINKFLAGS += -T$(ESP32_SDK_DIR)/components/riscv/ld/rom.api.ld GCC_NEW_RISCV_ISA ?= $(shell echo "typedef int dont_be_pedantic;" | \ $(TARGET_ARCH)-gcc -march=rv32imac -mabi=ilp32 \ -misa-spec=2.2 -E - > /dev/null 2>&1 && \ @@ -297,6 +314,16 @@ ifneq (,$(filter riscv%,$(TARGET_ARCH))) ifeq (1,$(GCC_NEW_RISCV_ISA)) CFLAGS += -misa-spec=2.2 endif + + ifeq (esp32c3,$(CPU_FAM)) + CFLAGS += -march=rv32imc_zicsr_zifencei + LINKFLAGS += -march=rv32imc_zicsr_zifencei + else ifeq (esp32h2,$(CPU_FAM)) + CFLAGS += -march=rv32imac_zicsr_zifencei + LINKFLAGS += -march=rv32imac_zicsr_zifencei + else + $(error Missing -march option for ESP32x RISC-V SoC variant: $(CPU_FAM)) + endif endif ifneq (,$(filter xtensa%,$(TARGET_ARCH))) @@ -334,7 +361,10 @@ else ifeq (esp32c3,$(CPU_FAM)) LINKFLAGS += -T$(ESP32_SDK_DIR)/components/esp_rom/$(CPU_FAM)/ld/$(CPU_FAM).rom.bt_funcs.ld LINKFLAGS += -T$(ESP32_SDK_DIR)/components/esp_rom/$(CPU_FAM)/ld/$(CPU_FAM).rom.newlib.ld LINKFLAGS += -T$(ESP32_SDK_DIR)/components/esp_rom/$(CPU_FAM)/ld/$(CPU_FAM).rom.eco3.ld - LINKFLAGS += -T$(ESP32_SDK_DIR)/components/riscv/ld/rom.api.ld +else ifeq (esp32h2,$(CPU_FAM)) + LINKFLAGS += -T$(ESP32_SDK_DIR)/components/esp_rom/$(CPU_FAM)/ld/$(CPU_FAM).rom.newlib.ld +else + $(error Missing LINKFLAGS for ESP32x SoC variant (family): $(CPU_FAM)) endif LINKFLAGS += -nostdlib -lgcc -Wl,-gc-sections diff --git a/cpu/esp32/bootloader/Makefile b/cpu/esp32/bootloader/Makefile index 09d21bdaff3f..ed74415fc5ee 100644 --- a/cpu/esp32/bootloader/Makefile +++ b/cpu/esp32/bootloader/Makefile @@ -56,8 +56,6 @@ ESP_SDK_BOOTLOADER_SRCS = \ components/esp_hw_support/port/$(CPU_FAM)/esp_cpu_intr.c \ components/esp_hw_support/port/$(CPU_FAM)/rtc_clk.c \ components/esp_hw_support/port/$(CPU_FAM)/rtc_clk_init.c \ - components/esp_hw_support/port/$(CPU_FAM)/rtc_init.c \ - components/esp_hw_support/port/$(CPU_FAM)/rtc_sleep.c \ components/esp_hw_support/port/$(CPU_FAM)/rtc_time.c \ components/esp_rom/patches/esp_rom_crc.c \ components/esp_rom/patches/esp_rom_efuse.c \ @@ -100,7 +98,14 @@ ifneq (,$(filter xtensa%,$(TARGET_ARCH))) else endif -ifneq (,$(filter esp32,$(CPU_FAM))) +ifneq (,$(filter esp32 esp32s2 esp32s3 esp32c3,$(CPU_FAM))) + ESP_SDK_BOOTLOADER_SRCS += \ + components/esp_hw_support/port/$(CPU_FAM)/rtc_init.c \ + components/esp_hw_support/port/$(CPU_FAM)/rtc_sleep.c \ + # +endif + +ifeq (esp32,$(CPU_FAM)) ESP_SDK_BOOTLOADER_SRCS += \ components/efuse/src/efuse_controller/keys/without_key_purposes/three_key_blocks/esp_efuse_api_key.c \ components/hal/$(CPU_FAM)/cache_hal_$(CPU_FAM).c \ @@ -117,7 +122,7 @@ ifneq (,$(filter esp32,$(CPU_FAM))) components/soc/$(CPU_FAM)/sdmmc_periph.c \ components/soc/$(CPU_FAM)/touch_sensor_periph.c \ # -else ifneq (,$(filter esp32s2,$(CPU_FAM))) +else ifeq (esp32s2,$(CPU_FAM)) ESP_SDK_BOOTLOADER_SRCS += \ components/efuse/$(CPU_FAM)/esp_efuse_rtc_calib.c \ components/efuse/$(CPU_FAM)/esp_efuse_rtc_table.c \ @@ -137,7 +142,7 @@ else ifneq (,$(filter esp32s2,$(CPU_FAM))) components/soc/$(CPU_FAM)/touch_sensor_periph.c \ components/soc/$(CPU_FAM)/usb_dwc_periph.c \ # -else ifneq (,$(filter esp32s3,$(CPU_FAM))) +else ifeq (esp32s3,$(CPU_FAM)) ESP_SDK_BOOTLOADER_ASMSRC += \ components/esp_rom/patches/esp_rom_cache_writeback_$(CPU_FAM).S ESP_SDK_BOOTLOADER_SRCS += \ @@ -159,7 +164,7 @@ else ifneq (,$(filter esp32s3,$(CPU_FAM))) components/soc/$(CPU_FAM)/touch_sensor_periph.c \ components/soc/$(CPU_FAM)/usb_dwc_periph.c \ # -else ifneq (,$(filter esp32c3,$(CPU_FAM))) +else ifeq (esp32c3,$(CPU_FAM)) ESP_SDK_BOOTLOADER_SRCS += \ components/efuse/$(CPU_FAM)/esp_efuse_rtc_calib.c \ components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c \ @@ -170,6 +175,20 @@ else ifneq (,$(filter esp32c3,$(CPU_FAM))) components/soc/$(CPU_FAM)/gdma_periph.c \ components/soc/$(CPU_FAM)/temperature_sensor_periph.c \ # +else ifeq (esp32h2,$(CPU_FAM)) + ESP_SDK_BOOTLOADER_SRCS += \ + components/efuse/$(CPU_FAM)/esp_efuse_rtc_calib.c \ + components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c \ + components/esp_hw_support/port/esp32h2/pmu_init.c \ + components/esp_hw_support/port/esp32h2/pmu_param.c \ + components/esp_hw_support/port/esp32h2/pmu_sleep.c \ + components/esp_rom/patches/esp_rom_regi2c_$(CPU_FAM).c \ + components/esp_rom/patches/esp_rom_systimer.c \ + components/esp_rom/patches/esp_rom_wdt.c \ + components/hal/cache_hal.c \ + components/hal/lp_timer_hal.c \ + components/hal/wdt_hal_iram.c \ + # else $(error Missing make configuration for ESP32x SoC variant (family): $(CPU_FAM)) endif @@ -228,7 +247,6 @@ CFLAGS += -Wno-format ifneq (,$(filter riscv32%,$(TARGET_ARCH))) INCLUDES += -I$(ESP32_SDK_DIR)/components/riscv/include CFLAGS += -DCONFIG_IDF_TARGET_ARCH_RISCV - CFLAGS += -march=rv32imc_zicsr_zifencei CFLAGS += -Wno-error=format= CFLAGS += -nostartfiles GCC_NEW_RISCV_ISA ?= $(shell echo "typedef int dont_be_pedantic;" | \ @@ -238,6 +256,14 @@ ifneq (,$(filter riscv32%,$(TARGET_ARCH))) ifeq (1,$(GCC_NEW_RISCV_ISA)) CFLAGS += -misa-spec=2.2 endif + + ifeq (esp32c3,$(CPU_FAM)) + CFLAGS += -march=rv32imc_zicsr_zifencei + else ifeq (esp32h2,$(CPU_FAM)) + CFLAGS += -march=rv32imac_zicsr_zifencei + else + $(error Missing -march option for ESP32x RISC-V SoC variant: $(CPU_FAM)) + endif endif ifneq (,$(filter xtensa%,$(TARGET_ARCH))) @@ -326,6 +352,15 @@ else ifneq (,$(filter esp32c3,$(CPU_FAM))) -T$(ESP32_SDK_DIR)/components/esp_rom/$(CPU_FAM)/ld/$(CPU_FAM).rom.eco3.ld \ -T$(ESP32_SDK_DIR)/components/esp_rom/$(CPU_FAM)/ld/$(CPU_FAM).rom.eco3_bt_funcs.ld \ # +else ifneq (,$(filter esp32h2,$(CPU_FAM))) + LINKFLAGS += -nostartfiles + LINKFLAGS += --specs=nosys.specs + ESP_SDK_BOOTLOADER_ADD_LINK_FLAGS += \ + -T$(ESP32_SDK_DIR)/components/esp_rom/$(CPU_FAM)/ld/$(CPU_FAM).rom.newlib.ld \ + -T$(ESP32_SDK_DIR)/components/esp_rom/$(CPU_FAM)/ld/$(CPU_FAM).rom.version.ld \ + # +else + $(error Missing make configuration for ESP32x SoC variant (family): $(CPU_FAM)) endif # Bootloader link flags. We use the SDK source and linking files instead of the diff --git a/cpu/esp32/bootloader/sdkconfig.h b/cpu/esp32/bootloader/sdkconfig.h index 8902e481c864..5352c9e3606c 100644 --- a/cpu/esp32/bootloader/sdkconfig.h +++ b/cpu/esp32/bootloader/sdkconfig.h @@ -33,15 +33,17 @@ #include "esp_idf_ver.h" #if defined(CPU_FAM_ESP32) -#include "sdkconfig_default_esp32.h" +# include "sdkconfig_default_esp32.h" #elif defined(CPU_FAM_ESP32C3) -#include "sdkconfig_default_esp32c3.h" +# include "sdkconfig_default_esp32c3.h" +#elif defined(CPU_FAM_ESP32H2) +# include "sdkconfig_default_esp32h2.h" #elif defined(CPU_FAM_ESP32S2) -#include "sdkconfig_default_esp32s2.h" +# include "sdkconfig_default_esp32s2.h" #elif defined(CPU_FAM_ESP32S3) -#include "sdkconfig_default_esp32s3.h" +# include "sdkconfig_default_esp32s3.h" #else -#error "ESP32x family implementation missing" +# error "ESP32x family implementation missing" #endif #include "sdkconfig_default_common.h" @@ -67,11 +69,11 @@ extern "C" { * 4 = DEBUG * 5 = VERBOSE */ -#if MODULE_ESP_LOG_STARTUP -#define CONFIG_BOOTLOADER_LOG_LEVEL 3 /* INFO */ -#else -#define CONFIG_BOOTLOADER_LOG_LEVEL 0 /* NONE */ -#endif +# if MODULE_ESP_LOG_STARTUP +# define CONFIG_BOOTLOADER_LOG_LEVEL 3 /* INFO */ +# else +# define CONFIG_BOOTLOADER_LOG_LEVEL 0 /* NONE */ +# endif #endif /** @@ -81,7 +83,7 @@ extern "C" { !defined(CONFIG_FLASHMODE_DIO) && \ !defined(CONFIG_FLASHMODE_QOUT) && \ !defined(CONFIG_FLASHMODE_QIO) -#error "Flash mode not configured" +# error "Flash mode not configured" #endif /* @@ -95,17 +97,17 @@ extern "C" { * bootloader. */ #if defined(CONFIG_CONSOLE_UART_TX) && defined(CONFIG_CONSOLE_UART_RX) -#define CONFIG_ESP_CONSOLE_UART_CUSTOM 1 -#define CONFIG_ESP_CONSOLE_UART_TX_GPIO CONFIG_CONSOLE_UART_TX -#define CONFIG_ESP_CONSOLE_UART_RX_GPIO CONFIG_CONSOLE_UART_RX +# define CONFIG_ESP_CONSOLE_UART_CUSTOM 1 +# define CONFIG_ESP_CONSOLE_UART_TX_GPIO CONFIG_CONSOLE_UART_TX +# define CONFIG_ESP_CONSOLE_UART_RX_GPIO CONFIG_CONSOLE_UART_RX #else -#define CONFIG_ESP_CONSOLE_UART_DEFAULT 1 +# define CONFIG_ESP_CONSOLE_UART_DEFAULT 1 #endif #if defined(CONFIG_CONSOLE_UART_NUM) -#define CONFIG_ESP_CONSOLE_UART_NUM CONFIG_CONSOLE_UART_NUM +# define CONFIG_ESP_CONSOLE_UART_NUM CONFIG_CONSOLE_UART_NUM #else -#define CONFIG_ESP_CONSOLE_UART_NUM 0 +# define CONFIG_ESP_CONSOLE_UART_NUM 0 #endif #define CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM CONFIG_ESP_CONSOLE_UART_NUM diff --git a/cpu/esp32/bootloader/sdkconfig_default_esp32h2.h b/cpu/esp32/bootloader/sdkconfig_default_esp32h2.h new file mode 100644 index 000000000000..ca6dd99e2908 --- /dev/null +++ b/cpu/esp32/bootloader/sdkconfig_default_esp32h2.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2025 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#pragma once + +/** + * @ingroup cpu_esp32 + * @{ + * + * @file + * @brief Default SDK configuration for the ESP32-C3 SoC bootloader + * + * @author Gunar Schorcht + */ + +#ifndef DOXYGEN + +#ifdef __cplusplus +extern "C" { +#endif + +#define CONFIG_ESP32H2_REV_MIN_0 + +#ifndef CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ +# define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ 96 +#endif + +#define CONFIG_XTAL_FREQ 32 + +#define CONFIG_ESP_DEBUG_OCDAWARE 1 + +#define CONFIG_BOOTLOADER_OFFSET_IN_FLASH 0x0 +#define CONFIG_EFUSE_MAX_BLK_LEN 256 +#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0010 +#define CONFIG_MMU_PAGE_SIZE 0x8000 + +#define CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG 1 + +#ifdef __cplusplus +} +#endif + +#endif /* DOXYGEN */ +/** @} */ diff --git a/cpu/esp32/doc.txt b/cpu/esp32/doc.txt index f85a8e7ce640..0089e9376254 100644 --- a/cpu/esp32/doc.txt +++ b/cpu/esp32/doc.txt @@ -11,7 +11,7 @@ * @ingroup sys_stdio * @brief STDIO via the USB Serial/JTAG debug interface found on some ESP32 SoCs * - * Some members of the ESP32 family (ESP32-C3, ESP32-S3, ESP32-H2) provide a on-chip + * Some members of the ESP32 family (ESP32-C3, ESP32-H2, ESP32-S3) provide a on-chip * debug interface that provides a serial console and JTAG via USB. * * To route STDIO to this debug console, enable this module. @@ -71,8 +71,9 @@ This document describes the RIOT implementation for supported variants 2. [WiFi Network Interface](#esp32_wifi_network_interface) 3. [WiFi SoftAP Network Interface](#esp32_wifi_ap_network_interface) 4. [ESP-NOW Network Interface](#esp32_esp_now_network_interface) - 4. [Bluetooth Interface](#esp32_esp_bluetooth_interface) - 5. [Other Network Devices](#esp32_other_network_devices) + 5. [Bluetooth Interface](#esp32_esp_bluetooth_interface) + 6. [IEEE 802.15.4 Network Interface](#esp32_esp_ieee802154_interface) + 7. [Other Network Devices](#esp32_other_network_devices) 10. [Application-Specific Configurations](#esp32_application_specific_configurations) 1. [Make Variable `CFLAGS`](#esp32_config_make_variable) 2. [Application-Specific Board Configuration](#esp32_application_specific_board_configuration) @@ -182,9 +183,10 @@ either based on - Tensilica Xtensa 32-bit LX6 microprocessor (ESP32), - Tensilica Xtensa 32-bit LX7 microprocessor (ESP32-S2, ESP32-S3), or -- 32-bit RISC-V CPU (ESP32-C3, ESP32-H2). +- 32-bit RISC-V CPU (ESP32-C3, ESP32-C3 ESP32-H2). -At the moment, ESP32, ESP32-S2, ESP32-S3 and ESP32-C3 variants (families) are supported by RIOT-OS. +At the moment, ESP32, ESP32-S2, ESP32-S3, ESP32-C3 and ESP32-H2 +variants (families) are supported by RIOT-OS. @note Even if the used ESP32x SoC is a dual-core version, RIOT-OS uses only one core. @@ -219,7 +221,7 @@ The key features of ESP32 are: | GPIO | 34 (6 are only inputs, 18 are RTC GPIOs) | yes | | I2C | 2 | yes | | SDMMC | 2 | yes | -| SPI | 4 | yes (2) | +| SPI | 4 (2 are usable as general purpose SPI) | yes | | UART | 3 | yes | | WiFi | IEEE 802.11 b/g/n built in | yes | | Bluetooth | v4.2 BR/EDR and BLE | yes | @@ -243,7 +245,7 @@ The key features of ESP32-C3 are: | MCU | ESP32-C3 | Supported by RIOT | | ------------------|-------------------------------------------------------------------|------------------ | | Vendor | Espressif | | -| Cores | 1 32-bit RISC-V core | yes | +| Cores | 1 x 32-bit RISC-V core | yes | | FPU | - | - | | RAM | 400 KiB SRAM
8 KiB RTC SRAM | yes
yes | | ROM | 384 KiB | yes | @@ -255,7 +257,7 @@ The key features of ESP32-C3 are: | DAC | - | - | | GPIO | 22 | yes | | I2C | 1 | yes | -| SPI | 3 | yes (1) | +| SPI | 3 (1 is usable as general purpose SPI) | yes | | UART | 2 | yes | | WiFi | IEEE 802.11 b/g/n built in | yes | | Bluetooth | Bluetooth 5 (LE) | yes | @@ -270,6 +272,43 @@ The key features of ESP32-C3 are:
+### Features of The ESP32-H2 SoC variant (family) + +The key features of ESP32-H2 are: + +
+ +| MCU | ESP32-H2 | Supported by RIOT | +| ------------------|-------------------------------------------------------------------|------------------ | +| Vendor | Espressif | | +| Cores | 1 x 32-bit RISC-V core | yes | +| FPU | - | - | +| RAM | 320 KiB SRAM
4 KiB LP SRAM | yes
yes | +| ROM | 384 KiB | yes | +| Flash | 4 MiB | yes | +| Frequency | 96 MHz, 64 Mhz, 48 MHz | yes | +| Power Consumption | 17 mA @ 96 MHz
13 mA @ 64 MHz
11 mA @ 64 MHz
85 uA in light sleep mode
7 uA in deep sleep mode | yes
yes
yes
yes
yes | +| Timer | 2 x 54 bit | yes | +| ADC | 1 x SAR-ADC with up to 5 x 12 bit channels total | yes | +| DAC | - | - | +| GPIO | 28 | yes | +| I2C | 2 | yes | +| SPI | 2 (1 is usable as general purpose SPI) | yes | +| UART | 2 | yes | +| WiFi | - | - | +| Bluetooth | Bluetooth 5.3 (LE) | yes | +| IEEE 802.15.4 | 250 Kbps data rate in 2.4 GHz band with OQPSK PHY | yes | +| Ethernet | - | - | +| CAN | version 2.0 | yes | +| IR | up to 4 channels TX/RX | - | +| Motor PWM | - | no | +| LED PWM | 6 channels with 14 bit resolution in 1 channel group with 4 timers | yes | +| Crypto | Hardware acceleration of AES, SHA-2, RSA, ECC, RNG | no | +| Vcc | 3.0 - 3.6 V | | +| Documents | [Datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf)
[Technical Reference](https://www.espressif.com/sites/default/files/documentation/esp32-h2_technical_reference_manual_en.pdf) | | + +

+ ### Features of The ESP32-S2 SoC variant (family) The key features of ESP32-S2 are: @@ -291,7 +330,7 @@ The key features of ESP32-S2 are: | DAC | 2 x DAC with 8 bit | - | | GPIO | 43 (22 are RTC GPIOs) | yes | | I2C | 2 | yes | -| SPI | 4 | yes (2) | +| SPI | 4 (2 are usable as general purpose SPI) | yes | | UART | 2 | yes | | WiFi | IEEE 802.11 b/g/n built in | yes | | Bluetooth | - | - | @@ -328,7 +367,7 @@ The key features of ESP32-S3 are: | GPIO | 45 (22 are RTC GPIOs) | yes | | I2C | 2 | yes | | SDMMC | 2 | yes | -| SPI | 4 | yes (2) | +| SPI | 4 (2 are usable as general purpose SPI) | yes | | UART | 3 | yes | | WiFi | IEEE 802.11 b/g/n built in | yes | | Bluetooth | Bluetooth 5 (LE) | yes | @@ -354,6 +393,7 @@ Most common modules used by ESP32x SoC boards are: - [ESP32-WROVER](https://www.espressif.com/sites/default/files/documentation/esp32-wrover_datasheet_en.pdf) - [ESP32-C3-MINI-1](https://www.espressif.com/sites/default/files/documentation/esp32-c3-mini-1_datasheet_en.pdf) - [ESP32-C3-WROOM-02](https://www.espressif.com/sites/default/files/documentation/esp32-c3-wroom-02_datasheet_en.pdf) +- [ESP32-H2-MINI-1](https://www.espressif.com/sites/default/files/documentation/esp32-h2-mini-1_mini-1u_datasheet_en.pdf) - [ESP32-S2-MINI-1](https://www.espressif.com/sites/default/files/documentation/esp32-s2-mini-1_esp32-s2-mini-1u_datasheet_en.pdf) - [ESP32-S2-SOLO](https://www.espressif.com/sites/default/files/documentation/esp32-s2-solo_esp32-s2-solo-u_datasheet_en.pdf) - [ESP32-S2-WROOM](https://www.espressif.com/sites/default/files/documentation/esp32-s2-wroom_esp32-s2-wroom-i_datasheet_en.pdf) @@ -384,6 +424,7 @@ The RIOT-OS for ESP32x SoCs supports the following features at the moment: - ESP-NOW netdev interface - ESP WiFi netdev interface in (WPA2 Personal Mode/Enterprise Mode, SoftAP mode) - ESP Ethernet MAC (EMAC) netdev interface +- IEEE 802.15.4 HAL interface [Back to table of contents](#esp32_toc) @@ -463,9 +504,9 @@ toolchain (Debian/Ubuntu package names): The shell script `$RIOTBASE/dist/tools/esptools/install.sh` is used to install Espressif's precompiled versions of the following tools: -- ESP32 vendor toolchain (for ESP8266, ESP32, ESP32-S2, ESP32-S3 and ESP32-C3) +- ESP32 vendor toolchain - GDB for ESP32x SoCs based on Xtensa or RISC-V -- OpenOCD for ESP32 (for ESP32, ESP32-S2, ESP32-S3 and ESP32-C3) +- OpenOCD for ESP32 (for ESP32, ESP32-S2, ESP32-S3, ESP32-C3 and ESP32-H2) - QEMU for ESP32x SoCs (for ESP32, ESP32-S3 and ESP32-C3) `$RIOTBASE` defines the root directory of the RIOT repository. The shell @@ -477,7 +518,8 @@ $ dist/tools/esptools/install.sh Usage: install.sh install.sh gdb install.sh qemu - = all | esp8266 | esp32 | esp32c3 | esp32s2 | esp32s3 | gdb | openocd | qemu + = all | gdb | openocd | qemu | + esp8266 | esp32 | esp32c3 | esp32h2 | esp32s2 | esp32s3 = xtensa | riscv ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -507,7 +549,8 @@ $ . dist/tools/esptools/export.sh Usage: export.sh export.sh gdb export.sh qemu - = all | esp8266 | esp32 | esp32c3 | esp32s2 | esp32s3 | gdb | openocd | qemu + = all | gdb | openocd | qemu | + esp8266 | esp32 | esp32c3 | esp32h2 | esp32s2 | esp32s3 = xtensa | riscv ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -526,10 +569,8 @@ install it separately. The RIOT port uses the ESP flasher programme `esptool.py` as a package directly from [GitHub](https://github.com/espressif/esptool) within a virtual Python -environment. The `esptool.py` version that is available as a Python package -for your operating system does not normally work. - -The RIOT port uses the ESP flasher program `esptool.py` as package directly from [GitHub](https://github.com/espressif/esptool) within an virtual Python environment. The version of `esptool.py` available as Python package for your OS does not usually work. +environment. The `esptool.py` available as a Python package for your operating +system may not work. It is also possible to use your own version of `esptool.py` by overriding the make variable `ESPTOOL` in the command line, for example: @@ -588,9 +629,11 @@ application. These are: Module | Description --------------------|------------ +esp_ble | Enable the built-in Bluetooth LE module, see section [Bluetooth Interface](#esp32_esp_bluetooth_interface) esp_eth | Enable the Ethernet MAC (EMAC) interface as `netdev` network device, see section [Ethernet Network Interface](#esp32_ethernet_network_interface). esp_gdb | Enable the compilation with debug information for debugging with [QEMU and GDB](#esp32_qemu_mode_and_gdb) (`QEMU=1`) or via [JTAG interface with OpenOCD](#esp32_jtag_debugging). esp_i2c_hw | Use the hardware I2C implementation, see section [I2C Interfaces](#esp32_i2c_interfaces). +esp_ieee802154 | Enable the built-in IEEE 802.15.4 module, see section [IEEE 802.15.4 Interface](#esp32_esp_ieee802154_interface) esp_idf_heap | Use the ESP-IDF heap implementation, see section [ESP-IDF Heap Implementation](#esp32_esp_idf_heap_implementation). esp_log_colored | Enable colored log output, see section [Log output](#esp32_esp_log_module). esp_log_startup | Enable additional startup information, see section [Log output](#esp32_esp_log_module). @@ -724,6 +767,7 @@ For details, see: - \ref esp32_gpio_pins_esp32 "ESP32" - \ref esp32_gpio_pins_esp32c3 "ESP32-C3" +- \ref esp32_gpio_pins_esp32h2 "ESP32-H2" - \ref esp32_gpio_pins_esp32s2 "ESP32-S2" - \ref esp32_gpio_pins_esp32s3 "ESP32-S3" @@ -731,13 +775,14 @@ For details, see: ## ADC Channels {#esp32_adc_channels} -ESP32x SoCs integrate two SAR ADCs (ADC1 and ADC2). The bit width of the +ESP32x SoCs integrate up to two SAR ADCs (ADC1 and ADC2). The bit width of the ADC devices, the number of channels per device and the GPIOs that can be used as ADC channels depend on the respective ESP32x SoC family. For details, see: - \ref esp32_adc_channels_esp32 "ESP32" - \ref esp32_adc_channels_esp32c3 "ESP32-C3" +- \ref esp32_adc_channels_esp32h2 "ESP32-H2" - \ref esp32_adc_channels_esp32s2 "ESP32-S2" - \ref esp32_adc_channels_esp32s3 "ESP32-S3" @@ -780,7 +825,7 @@ Attenuation | Voltage Range | Symbol 0 dB | 0 ... 1.1V (Vref) | `ADC_ATTEN_DB_0` 2.5 / 3 dB | 0 ... 1.5V | `ADC_ATTEN_DB_2_5` 6 dB | 0 ... 2.2V | `ADC_ATTEN_DB_6` -11 / 12 dB | 0 ... 3.3V | `ADC_ATTEN_DB_11` (default) +11 / 12 dB | 0 ... 3.3V | `ADC_ATTEN_DB_12` (default)
@@ -859,6 +904,7 @@ on used ESP32x SoC family, for details see: - \ref esp32_i2c_interfaces_esp32 "ESP32" - \ref esp32_i2c_interfaces_esp32c3 "ESP32-C3" +- \ref esp32_i2c_interfaces_esp32h2 "ESP32-H2" - \ref esp32_i2c_interfaces_esp32s2 "ESP32-S2" - \ref esp32_i2c_interfaces_esp32s3 "ESP32-S3" @@ -911,6 +957,7 @@ channel depends on respective ESP32x SoC family. For details, see: - \ref esp32_pwm_channels_esp32 "ESP32" - \ref esp32_pwm_channels_esp32c3 "ESP32-C3" +- \ref esp32_pwm_channels_esp32h2 "ESP32-H2" - \ref esp32_pwm_channels_esp32s2 "ESP32-S2" - \ref esp32_pwm_channels_esp32s3 "ESP32-S3" @@ -1089,6 +1136,7 @@ on used ESP32x SoC family, for details see: - \ref esp32_spi_interfaces_esp32 "ESP32" - \ref esp32_spi_interfaces_esp32c3 "ESP32-C3" +- \ref esp32_spi_interfaces_esp32h2 "ESP32-H2" - \ref esp32_spi_interfaces_esp32s2 "ESP32-S2" - \ref esp32_spi_interfaces_esp32s3 "ESP32-S3" @@ -1133,6 +1181,7 @@ ESP32x SoC family, for details see: - \ref esp32_timers_esp32 "ESP32" - \ref esp32_timers_esp32c3 "ESP32-C3" +- \ref esp32_timers_esp32h2 "ESP32-H2" - \ref esp32_timers_esp32s2 "ESP32-S2" - \ref esp32_timers_esp32s3 "ESP32-S3" @@ -1195,6 +1244,7 @@ on used ESP32x SoC family, for details see: - \ref esp32_uart_interfaces_esp32 "ESP32" - \ref esp32_uart_interfaces_esp32c3 "ESP32-C3" +- \ref esp32_uart_interfaces_esp32h2 "ESP32-H2" - \ref esp32_uart_interfaces_esp32s2 "ESP32-S2" - \ref esp32_uart_interfaces_esp32s3 "ESP32-S3" @@ -1789,7 +1839,7 @@ The following ESP32x SoC variants (families) integrate a Bluetooth Link Controller and a Bluetooth baseband system: - ESP32 supports Bluetooth v4.2 BR/EDR and Bluetooth LE -- ESP32-C3, ESP32-S3 support Bluetooth 5 and Bluetooth mesh +- ESP32-C3, ESP32-H2, ESP32-S3 support Bluetooth 5 and Bluetooth mesh The Bluetooth interface can be used with the Bluetooth host implementation of the NimBLE package. Use one of the `nimble_*` modules for different @@ -1798,6 +1848,18 @@ implementation. Please refer to the NimBle package documentation for details. [Back to table of contents](#esp32_toc) +## IEEE 802.15.4 Network Interface {#esp32_esp_ieee802154_interface} + +ESP-H2 includes an IEEE 802.15.4 subsystem +that integrates PHY and MAC layer. + +The \ref drivers_ieee802154_hal "IEEE 802.15.4 Hardware Abstraction Layer" +driver for the IEEE 802.15.4 subsystem of ESP32x SoCs (module `esp_ieee802154`) +can be used together with RIOT's \ref net_ieee802154_submac "IEEE 802.15.4 SubMAC layer" +to use the IEEE 802.15.4 subsystem of ESP32x SoCs as network interface. + +[Back to table of contents](#esp32_toc) + ## Other Network Devices {#esp32_other_network_devices} RIOT provides a number of driver modules for different types of network @@ -1998,6 +2060,7 @@ For details, see: - \ref esp32_jtag_interface_esp32 "ESP32" - \ref esp32_jtag_interface_esp32c3 "ESP32-C3" +- \ref esp32_jtag_interface_esp32h2 "ESP32-H2" - \ref esp32_jtag_interface_esp32s2 "ESP32-S2" - \ref esp32_jtag_interface_esp32s3 "ESP32-S3" @@ -2019,6 +2082,7 @@ that can be used without additional chips. For details, see: - \ref esp32_jtag_interface_esp32 "ESP32" - \ref esp32_jtag_interface_esp32c3 "ESP32-C3" +- \ref esp32_jtag_interface_esp32h2 "ESP32-H2" - \ref esp32_jtag_interface_esp32s2 "ESP32-S2" - \ref esp32_jtag_interface_esp32s3 "ESP32-S3" @@ -2061,6 +2125,8 @@ Detailed information on how to configure the JTAG interface of the respective ESP32x SoC variant (family) can be found in ESP-IDF Programming Guide: - [ESP32](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/jtag-debugging/index.html) +- [ESP32-C3](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-guides/jtag-debugging/index.html) +- [ESP32-H2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32h2/api-guides/jtag-debugging/index.html) - [ESP32-S3](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-guides/jtag-debugging/index.html) - [ESP32-S2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-guides/jtag-debugging/index.html) - [ESP32-S3](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-guides/jtag-debugging/index.html) diff --git a/cpu/esp32/doc_esp32h2.doc.md b/cpu/esp32/doc_esp32h2.doc.md new file mode 100644 index 000000000000..d163c11d4252 --- /dev/null +++ b/cpu/esp32/doc_esp32h2.doc.md @@ -0,0 +1,213 @@ + + +@defgroup cpu_esp32_esp32h2 ESP32-H2 family +@ingroup cpu_esp32 +@brief Specific properties of ESP32-H2 variant (family) +@author Gunar Schorcht + +\section esp32_riot_esp32h2 Specific properties of ESP32-H2 variant (family) + +## GPIO pins {#esp32_gpio_pins_esp32h2} + +ESP32-H2 has 19 broken-out GPIO pins, where a subset can be used as ADC channel +and as low-power digital inputs/outputs in deep-sleep mode, the so-called +LP GPIOs. Some of them are used by special SoC components. The following +table gives a short overview. + +
+ +Pin | Type | ADC / LP | PU / PD | Special function | Remarks +-------|:-------|:----------:|:-------:|------------------|-------- +GPIO0 | In/Out | - | yes | | FSPIQ +GPIO1 | In/Out | ADC | yes | | FSPICS0 +GPIO2 | In/Out | ADC | yes | MTMS | FSPIWP, Bootstrapping +GPIO3 | In/Out | ADC | yes | MTDO | FSPIHD, Bootstrapping +GPIO4 | In/Out | ADC | yes | MTCK | FSPICLK +GPIO5 | In/Out | ADC | yes | MTDI | FSPID +GPIO8 | In/Out | LP | yes | | Bootstrapping +GPIO9 | In/Out | LP | yes | | Bootstrapping, pulled up +GPIO10 | In/Out | LP | yes | | - +GPIO11 | In/Out | LP | yes | | - +GPIO12 | In/Out | LP | yes | | - +GPIO13 | In/Out | LP | yes | XTAL_32K_P | - +GPIO14 | In/Out | LP | yes | XTAL_32K_N | - +GPIO22 | In/Out | LP | yes | | - +GPIO23 | In/Out | - | yes | UART0 RX | - +GPIO24 | In/Out | - | yes | UART0 TX | - +GPIO25 | In/Out | - | yes | | Bootstrapping +GPIO26 | In/Out | - | yes | USB D- | USB Serial / JTAG interface +GPIO27 | In/Out | - | yes | USB D+ | USB Serial / JTAG interface + +

+ +ADC: these pins can be used as ADC inputs
+LP: these pins are LP GPIOs and can be used in deep-sleep mode
+PU/PD: these pins have software configurable pull-up/pull-down functionality.
+ +GPIO2, GPIO3, GPIO8 and GPIO9 are bootstrapping pins which are used to boot +ESP32-H2 in different modes: + +
+ +GPIO9 | GPIO8 | GPIO2 | GPIO3 | Mode +:----:|:-----:|:-----:|:-----:|-------------------------------------------- +1 | X | x | x | SPI Boot mode to boot the firmware from flash (default mode) +0 | 1 | x | x | Joint Download Boot mode for flashing the firmware (standard) +0 | 0 | 1 | 0 | SPI Download Boot mode + +Other combinations are invalid. + +

+ +## ADC Channels {#esp32_adc_channels_esp32h2} + +ESP32-H2 integrates one 12-bit ADC with 5 channels in +total: GPIO1, GPIO2, GPIO3, GPIO4 and GPIO5 + +The maximum number of ADC channels #ADC_NUMOF_MAX is 5. + +## I2C Interfaces {#esp32_i2c_interfaces_esp32h2} + +ESP32-H2 has two built-in I2C interfaces. + +The following table shows the default configuration of I2C interfaces +used for ESP32-H2 boards. It can be overridden by +[application-specific configurations](#esp32_application_specific_configurations). + +
+ +Device | Signal | Pin | Symbol | Remarks +:----------|:-------|:-------|:--------------|:---------------- +I2C_DEV(0) | | | `I2C0_SPEED` | default is `I2C_SPEED_FAST` +I2C_DEV(0) | SCL | GPIO10 | `I2C0_SCL` | - +I2C_DEV(0) | SDA | GPIO11 | `I2C0_SDA` | - + +

+ +## PWM Channels {#esp32_pwm_channels_esp32h2} + +The ESP32-H2 LEDC module has 1 channel groups with 6 channels. Each of +these channels can be clocked by one of the 4 timers. + +## SPI Interfaces {#esp32_spi_interfaces_esp32h2} + +ESP32-H2 has three SPI controllers where SPI0 and SPI1 share the same bus. +They are used as interface for external memory and can only operate in memory +mode: + +- Controller SPI0 is reserved for caching external memory like Flash +- Controller SPI1 is reserved for external memory like PSRAM +- Controller SPI2 can be used as general purpose SPI (also called FSPI) + +Thus, only SPI2 (FSPI) can be used as general purpose SPI in RIOT as +SPI_DEV(0). + +The following table shows the pin configuration used for most boards, even +though it **can vary** from board to board. + +
+ +Device | Signal | Pin | Symbol | Remarks +:-------------|:------:|:-------|:-----------:|:--------------------------- +SPI_DEV(0) | SCK | GPIO4 |`SPI0_SCK` | `SPI2_HOST` (`FSPI`) +SPI_DEV(0) | MOSI | GPIO0 |`SPI0_MOSI` | `SPI2_HOST` (`FSPI`) +SPI_DEV(0) | MISO | GPIO5 |`SPI0_MISO` | `SPI2_HOST` (`FSPI`) +SPI_DEV(0) | CS0 | GPIO1 |`SPI0_CS0` | `SPI2_HOST` (`FSPI`) + +

+ +## Timers {#esp32_timers_esp32h2} + +ESP32-H2 has two timer groups with one timer each, resulting in a total of +two timers. Thus one timer with one channel can be used in RIOT +as timer device TIMER_DEV(0), because one timer is used as system timer. + +ESP32-H2 do not have CCOMPARE registers. The counter implementation can not +be used. + +## UART Interfaces {#esp32_uart_interfaces_esp32h2} + +ESP32-H2 integrates two UART interfaces. The following default pin +configuration of UART interfaces as used by a most boards can be overridden +by the application, see section [Application-Specific Configurations] +(#esp32_application_specific_configurations). + +
+ +Device |Signal|Pin |Symbol |Remarks +:-----------|:-----|:-------|:-----------|:---------------- +UART_DEV(0) | TxD | GPIO24 |`UART0_TXD` | cannot be changed +UART_DEV(0) | RxD | GPIO23 |`UART0_RXD` | cannot be changed +UART_DEV(1) | TxD | |`UART1_TXD` | optional, can be configured +UART_DEV(1) | RxD | |`UART1_RXD` | optional, can be configured + +

+ +## JTAG Interface {#esp32_jtag_interface_esp32h2} + +There are two options on how to use the JTAG interface on ESP32-H2: + +1. Using the built-in USB-to-JTAG bridge connected to an USB cable as follows: +
+ USB Signal | ESP32-H2 Pin + :--------------|:----------- + D- (white) | GPIO26 + D+ (green) | GPIO27 + V_Bus (red) | 5V + Ground (black) | GND +
+ +2. Using an external JTAG adapter connected to the JTAG interface exposed + to GPIOs as follows: +
+ JTAG Signal | ESP32-H2 Pin + :-----------|:----------- + TRST_N | CHIP_PU + TDO | GPIO3 (MTDO) + TDI | GPIO5 (MTDI) + TCK | GPIO4 (MTCK) + TMS | GPIO2 (MTMS) + GND | GND +

+ @note This option requires that the USB D- and USB D+ signals are connected + to the ESP32-H2 USB interface at GPIO18 and GPIO19. + +
+Using the built-in USB-to-JTAG bridge is the default option, i.e. the JTAG +interface of the ESP32-H2 is connected to the built-in USB-to-JTAG bridge. +To use an external JTAG adapter, the JTAG interface of the ESP32-H2 has to +be connected to the GPIOs as shown above. For this purpose eFuses have to be +burned with the following command: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +espefuse.py burn_efuse JTAG_SEL_ENABLE --port /dev/ttyUSB0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once the eFuses are burned with this command and option `JTAG_SEL_ENABLE`, +GPIO25 is used as a bootstrapping pin to choose between the two options. +If GPIO25 is HIGH when ESP32-H2 is reset, the JTAG interface is connected +to the built-in USB to JTAG bridge and the USB cable can be used for on-chip +debugging. Otherwise, the JTAG interface is exposed to GPIO2 ... GPIO5 +and an external JTAG adapter has to be used. + +Alternatively, the integrated USB-to-JTAG bridge can be permanently disabled +with the following command: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +espefuse.py burn_efuse DIS_USB_JTAG --port /dev/ttyUSB0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once the eFuses are burned with this command and option `DIS_USB_JTAG`, +the JTAG interface is always exposed to GPIO2 ... GPIO5 and an external +JTAG adapter has to be used. + +@note Burning eFuses is an irreversible operation. + +For more information about JTAG configuration for ESP32-H2, refer to the +section [Configure Other JTAG Interface] +(https://docs.espressif.com/projects/esp-idf/en/latest/esp32h2/api-guides/jtag-debugging/configure-other-jtag.html) +in the ESP-IDF documentation. diff --git a/cpu/esp32/esp-idf/common/Makefile b/cpu/esp32/esp-idf/common/Makefile index 6a3502a2b71b..bdf46fca4fe1 100644 --- a/cpu/esp32/esp-idf/common/Makefile +++ b/cpu/esp32/esp-idf/common/Makefile @@ -15,8 +15,6 @@ ESP32_SDK_SRC = \ components/esp_hw_support/periph_ctrl.c \ components/esp_hw_support/port/$(CPU_FAM)/esp_clk_tree.c \ components/esp_hw_support/port/$(CPU_FAM)/rtc_clk.c \ - components/esp_hw_support/port/$(CPU_FAM)/rtc_init.c \ - components/esp_hw_support/port/$(CPU_FAM)/rtc_sleep.c \ components/esp_hw_support/port/$(CPU_FAM)/rtc_time.c \ components/esp_hw_support/port/$(CPU_FAM)/sar_periph_ctrl.c \ components/esp_hw_support/port/esp_clk_tree_common.c \ @@ -134,13 +132,27 @@ ifneq (,$(filter riscv%,$(TARGET_ARCH))) ESP32_SDK_ASMSRC += components/riscv/vectors_intc.S endif +ifneq (,$(filter esp32 esp32s2 esp32s3 esp32c3,$(CPU_FAM))) + ESP32_SDK_SRC += components/esp_hw_support/port/$(CPU_FAM)/rtc_init.c + ESP32_SDK_SRC += components/esp_hw_support/port/$(CPU_FAM)/rtc_sleep.c +else ifneq (,$(filter esp32h2 esp32c5 esp32c6 esp32c61,$(CPU_FAM))) + ESP32_SDK_SRC += components/esp_hw_support/lowpower/port/$(CPU_FAM)/sleep_clock.c + ESP32_SDK_SRC += components/esp_hw_support/port/$(CPU_FAM)/io_mux.c + ESP32_SDK_SRC += components/esp_hw_support/port/$(CPU_FAM)/pmu_init.c + ESP32_SDK_SRC += components/esp_hw_support/port/$(CPU_FAM)/pmu_param.c + ESP32_SDK_SRC += components/esp_hw_support/port/$(CPU_FAM)/pmu_sleep.c + ESP32_SDK_SRC += components/esp_hw_support/sleep_retention.c + ESP32_SDK_SRC += components/esp_hw_support/sleep_system_peripheral.c + ESP32_SDK_SRC += components/hal/$(CPU_FAM)/modem_clock_hal.c + ESP32_SDK_SRC += components/hal/$(CPU_FAM)/pmu_hal.c + ESP32_SDK_SRC += components/soc/$(CPU_FAM)/rtc_io_periph.c +endif + ifeq (esp32,$(CPU_FAM)) ESP32_SDK_SRC += components/esp_mm/cache_esp32.c ESP32_SDK_SRC += components/esp_timer/src/esp_timer_impl_lac.c ESP32_SDK_SRC += components/hal/esp32/cache_hal_esp32.c -endif - -ifeq (esp32c3,$(CPU_FAM)) +else ifeq (esp32c3,$(CPU_FAM)) ESP32_SDK_SRC += components/esp_hw_support/lowpower/port/$(CPU_FAM)/sleep_cpu.c ESP32_SDK_SRC += components/esp_hw_support/port/$(CPU_FAM)/systimer.c ESP32_SDK_SRC += components/esp_hw_support/sleep_console.c @@ -148,9 +160,22 @@ ifeq (esp32c3,$(CPU_FAM)) ESP32_SDK_SRC += components/hal/$(CPU_FAM)/rtc_cntl_hal.c ESP32_SDK_SRC += components/hal/cache_hal.c ESP32_SDK_SRC += components/hal/systimer_hal.c -endif - -ifeq (esp32s2,$(CPU_FAM)) +else ifeq (esp32h2,$(CPU_FAM)) + ESP32_SDK_SRC += components/esp_rom/patches/esp_rom_regi2c_$(CPU_FAM).c + ESP32_SDK_SRC += components/esp_hw_support/lowpower/port/$(CPU_FAM)/sleep_cpu.c + ESP32_SDK_SRC += components/esp_hw_support/modem_clock.c + ESP32_SDK_SRC += components/esp_hw_support/port/$(CPU_FAM)/systimer.c + ESP32_SDK_SRC += components/esp_hw_support/port/pau_regdma.c + ESP32_SDK_SRC += components/esp_hw_support/port/regdma_link.c + ESP32_SDK_SRC += components/esp_hw_support/sleep_console.c + ESP32_SDK_SRC += components/esp_timer/src/esp_timer_impl_systimer.c + ESP32_SDK_SRC += components/hal/$(CPU_FAM)/pau_hal.c + ESP32_SDK_SRC += components/hal/apm_hal.c + ESP32_SDK_SRC += components/hal/cache_hal.c + ESP32_SDK_SRC += components/hal/lp_timer_hal.c + ESP32_SDK_SRC += components/hal/systimer_hal.c + ESP32_SDK_ASMSRC += components/esp_hw_support/lowpower/port/$(CPU_FAM)/sleep_cpu_asm.S +else ifeq (esp32s2,$(CPU_FAM)) ESP32_SDK_SRC += components/esp_rom/patches/esp_rom_regi2c_$(CPU_FAM).c ESP32_SDK_SRC += components/esp_hw_support/port/$(CPU_FAM)/systimer.c ESP32_SDK_SRC += components/esp_hw_support/port/$(CPU_FAM)/memprot.c @@ -160,9 +185,7 @@ ifeq (esp32s2,$(CPU_FAM)) ESP32_SDK_SRC += components/hal/brownout_hal.c ESP32_SDK_SRC += components/hal/cache_hal.c ESP32_SDK_SRC += components/hal/systimer_hal.c -endif - -ifeq (esp32s3,$(CPU_FAM)) +else ifeq (esp32s3,$(CPU_FAM)) ESP32_SDK_SRC += components/esp_hw_support/mspi_timing_tuning.c ESP32_SDK_SRC += components/esp_hw_support/port/$(CPU_FAM)/mspi_timing_config.c ESP32_SDK_SRC += components/esp_hw_support/port/$(CPU_FAM)/systimer.c @@ -174,6 +197,8 @@ ifeq (esp32s3,$(CPU_FAM)) ESP32_SDK_SRC += components/hal/cache_hal.c ESP32_SDK_SRC += components/hal/systimer_hal.c ESP32_SDK_SRC += components/spi_flash/$(CPU_FAM)/spi_flash_oct_flash_init.c +else + $(error Missing configuration for ESP32x SoC variant (family): $(CPU_FAM)) endif include $(RIOTBASE)/Makefile.base diff --git a/cpu/esp32/esp-idf/esp_idf.mk b/cpu/esp32/esp-idf/esp_idf.mk index 8ba15a9e2f62..8d34bcbad8dc 100644 --- a/cpu/esp32/esp-idf/esp_idf.mk +++ b/cpu/esp32/esp-idf/esp_idf.mk @@ -28,6 +28,11 @@ ifneq (,$(filter xtensa%,$(TARGET_ARCH))) INCLUDES += -I$(ESP32_SDK_DIR)/components/xtensa/$(CPU_FAM)/include endif +ifeq (esp32h2,$(CPU_FAM)) + INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_hw_support/include/esp_private + INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_hw_support/port/$(CPU_FAM)/private_include +endif + ifeq (esp32s3,$(CPU_FAM)) INCLUDES += -I$(ESP32_SDK_DIR)/components/spi_flash/include/spi_flash endif diff --git a/cpu/esp32/esp-idf/esp_idf_cflags.mk b/cpu/esp32/esp-idf/esp_idf_cflags.mk index 00ec2884b72b..7a048670c19f 100644 --- a/cpu/esp32/esp-idf/esp_idf_cflags.mk +++ b/cpu/esp32/esp-idf/esp_idf_cflags.mk @@ -42,16 +42,10 @@ CFLAGS += -Wno-unused-function # additional CFLAGS required for RISC-V architecture ifneq (,$(filter riscv32%,$(TARGET_ARCH))) INCLUDES += -I$(ESP32_SDK_DIR)/components/riscv/include - CFLAGS += -DCONFIG_IDF_TARGET_ARCH_RISCV - CFLAGS += -march=rv32imc CFLAGS += -Wno-error=format= CFLAGS += -nostartfiles - CFLAGS += -Wno-format - GCC_NEW_RISCV_ISA ?= $(shell echo "typedef int dont_be_pedantic;" | \ - $(TARGET_ARCH)-gcc -march=rv32imac -mabi=ilp32 \ - -misa-spec=2.2 -E - > /dev/null 2>&1 && \ - echo 1 || echo 0) - ifeq (1,$(GCC_NEW_RISCV_ISA)) - CFLAGS += -misa-spec=2.2 - endif +endif + +ifeq (esp32h2,$(CPU_FAM)) + CFLAGS += -DSOC_MMU_PAGE_SIZE=CONFIG_MMU_PAGE_SIZE endif diff --git a/cpu/esp32/esp-idf/spi_flash/Makefile b/cpu/esp32/esp-idf/spi_flash/Makefile index 1d6d96edf4fa..183337f4f639 100644 --- a/cpu/esp32/esp-idf/spi_flash/Makefile +++ b/cpu/esp32/esp-idf/spi_flash/Makefile @@ -23,19 +23,7 @@ ESP32_SDK_SRC = \ components/spi_flash/spi_flash_chip_winbond.c \ # - -ifneq (,$(filter esp32,$(CPU_FAM))) -endif - -ifneq (,$(filter esp32s2,$(CPU_FAM))) - ESP32_SDK_SRC += components/hal/spi_flash_hal_gpspi.c -endif - -ifneq (,$(filter esp32s3,$(CPU_FAM))) - ESP32_SDK_SRC += components/hal/spi_flash_hal_gpspi.c -endif - -ifneq (,$(filter esp32c3,$(CPU_FAM))) +ifneq (,$(filter esp32s2 esp32s3 esp32c3 esp32h2,$(CPU_FAM))) ESP32_SDK_SRC += components/hal/spi_flash_hal_gpspi.c endif diff --git a/cpu/esp32/include/cpu_conf.h b/cpu/esp32/include/cpu_conf.h index 01493d82079b..b401fb4b049b 100644 --- a/cpu/esp32/include/cpu_conf.h +++ b/cpu/esp32/include/cpu_conf.h @@ -22,7 +22,7 @@ */ #if !defined(__ASSEMBLER__) -#include +# include #endif /** @@ -31,9 +31,9 @@ */ /** Extra thread stack size required if newlib-nano is not used */ #ifdef MODULE_NEWLIB_NANO -#define THREAD_EXTRA_STACKSIZE (0) +# define THREAD_EXTRA_STACKSIZE (0) #else -#define THREAD_EXTRA_STACKSIZE (512) +# define THREAD_EXTRA_STACKSIZE (512) #endif /** Extra thread stack size if `printf` is used */ @@ -41,17 +41,17 @@ #ifndef THREAD_STACKSIZE_DEFAULT /** Default thread stack size */ -#define THREAD_STACKSIZE_DEFAULT (2048) +# define THREAD_STACKSIZE_DEFAULT (2048) #endif #ifndef THREAD_STACKSIZE_IDLE /** Stack size for the idle thread */ -#define THREAD_STACKSIZE_IDLE (2048) +# define THREAD_STACKSIZE_IDLE (2048) #endif #ifndef ESP_WIFI_STACKSIZE /** Stack size for the WiFi thread */ -#define ESP_WIFI_STACKSIZE (THREAD_STACKSIZE_DEFAULT + THREAD_EXTRA_STACKSIZE) +# define ESP_WIFI_STACKSIZE (THREAD_STACKSIZE_DEFAULT + THREAD_EXTRA_STACKSIZE) #endif /** @} */ @@ -100,15 +100,17 @@ extern uint8_t _fp_mmu_start; /* include ESP32x SoC specific compile time configurations */ #if defined(CPU_FAM_ESP32) -#include "cpu_conf_esp32.h" +# include "cpu_conf_esp32.h" #elif defined(CPU_FAM_ESP32C3) -#include "cpu_conf_esp32c3.h" +# include "cpu_conf_esp32c3.h" +#elif defined(CPU_FAM_ESP32H2) +# include "cpu_conf_esp32h2.h" #elif defined(CPU_FAM_ESP32S2) -#include "cpu_conf_esp32s2.h" +# include "cpu_conf_esp32s2.h" #elif defined(CPU_FAM_ESP32S3) -#include "cpu_conf_esp32s3.h" +# include "cpu_conf_esp32s3.h" #else -#error "ESP32x family implementation missing" +# error "ESP32x family implementation missing" #endif #ifdef __cplusplus diff --git a/cpu/esp32/include/cpu_conf_esp32h2.h b/cpu/esp32/include/cpu_conf_esp32h2.h new file mode 100644 index 000000000000..e32a72f55132 --- /dev/null +++ b/cpu/esp32/include/cpu_conf_esp32h2.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2025 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#pragma once + +/** + * @ingroup cpu_esp32 + * @ingroup config + * @brief Compile-time configuration macros for ESP32-H2 SoCs + * @{ + * + * @file + * @brief ESP32-H2 specific compile-time configuration + * + * @author Gunar Schorcht + */ + +#ifndef ESP_ISR_STACKSIZE +/** Stack size used in interrupt context */ +# define ESP_ISR_STACKSIZE (THREAD_STACKSIZE_DEFAULT) +#endif /* ESP_ISR_STACKSIZE */ + +/** Number of DRAM sections that can be used as heap. */ +#define NUM_HEAPS (1) + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/cpu/esp32/include/periph_cpu.h b/cpu/esp32/include/periph_cpu.h index cfe8cd707c78..9efe66560e3e 100644 --- a/cpu/esp32/include/periph_cpu.h +++ b/cpu/esp32/include/periph_cpu.h @@ -150,21 +150,18 @@ typedef enum { /* BEGIN: GPIO LL overwrites */ #if SOC_GPIO_PIN_COUNT > 32 - -#define GPIO_PORT_NUMOF 2 -#define GPIO_PORT_0 0 -#define GPIO_PORT_1 1 -#define GPIO_PORT_0_PIN_NUMOF (32) -#define GPIO_PORT_1_PIN_NUMOF (SOC_GPIO_PIN_COUNT - 32) -#define GPIO_PORT_PIN_NUMOF(p) ((p == GPIO_PORT_0) ? GPIO_PORT_0_PIN_NUMOF \ - : GPIO_PORT_1_PIN_NUMOF) +# define GPIO_PORT_NUMOF 2 +# define GPIO_PORT_0 0 +# define GPIO_PORT_1 1 +# define GPIO_PORT_0_PIN_NUMOF (32) +# define GPIO_PORT_1_PIN_NUMOF (SOC_GPIO_PIN_COUNT - 32) +# define GPIO_PORT_PIN_NUMOF(p) ((p == GPIO_PORT_0) ? GPIO_PORT_0_PIN_NUMOF \ + : GPIO_PORT_1_PIN_NUMOF) #else - -#define GPIO_PORT_NUMOF 1 -#define GPIO_PORT_0 0 -#define GPIO_PORT_0_PIN_NUMOF (SOC_GPIO_PIN_COUNT) -#define GPIO_PORT_PIN_NUMOF(p) ((p == GPIO_PORT_0) ? GPIO_PORT_0_PIN_NUMOF : 0) - +# define GPIO_PORT_NUMOF 1 +# define GPIO_PORT_0 0 +# define GPIO_PORT_0_PIN_NUMOF (SOC_GPIO_PIN_COUNT) +# define GPIO_PORT_PIN_NUMOF(p) ((p == GPIO_PORT_0) ? GPIO_PORT_0_PIN_NUMOF : 0) #endif #define HAVE_GPIO_PORT_T @@ -388,7 +385,7 @@ union gpio_conf_esp32 { * @brief Number of DAC channels that could be used at maximum. */ #if defined(SOC_DAC_SUPPORTED) || DOXYGEN -#define DAC_NUMOF_MAX (SOC_DAC_PERIPH_NUM) +# define DAC_NUMOF_MAX (SOC_DAC_PERIPH_NUM) #endif /** @} */ @@ -844,13 +841,13 @@ typedef spi_host_device_t spi_ctrl_t; * source code compatibility reasons these alias names are defined here. */ #if defined(CPU_FAM_ESP32) -#define HSPI SPI2_HOST /**< Alias name for SPI2_HOST as used in former ESP-IDF versions */ -#define VSPI SPI3_HOST /**< Alias name for SPI3_HOST as used in former ESP-IDF versions */ +# define HSPI SPI2_HOST /**< Alias name for SPI2_HOST as used in former ESP-IDF versions */ +# define VSPI SPI3_HOST /**< Alias name for SPI3_HOST as used in former ESP-IDF versions */ #elif defined(CPU_FAM_ESP32S2) -#define FSPI SPI2_HOST /**< Alias name for SPI2_HOST as used in former ESP-IDF versions */ -#define HSPI SPI3_HOST /**< Alias name for SPI3_HOST as used in former ESP-IDF versions */ +# define FSPI SPI2_HOST /**< Alias name for SPI2_HOST as used in former ESP-IDF versions */ +# define HSPI SPI3_HOST /**< Alias name for SPI3_HOST as used in former ESP-IDF versions */ #else -#define FSPI SPI2_HOST /**< Alias name for SPI2_HOST as used in former ESP-IDF versions */ +# define FSPI SPI2_HOST /**< Alias name for SPI2_HOST as used in former ESP-IDF versions */ #endif /** @@ -906,8 +903,8 @@ typedef struct { * Since one timer is used for the system time, there is one timer less than * the total number of timers. */ -#define TIMER_NUMOF (SOC_TIMER_GROUP_TOTAL_TIMERS - 1) -#define TIMER_CHANNEL_NUMOF (1) +# define TIMER_NUMOF (SOC_TIMER_GROUP_TOTAL_TIMERS - 1) +# define TIMER_CHANNEL_NUMOF (1) #endif /** Timer group used for system time */ @@ -1002,7 +999,8 @@ typedef enum { UART_PARITY_SPACE = UART_MODE_UNSUPPORTED | 1, } uart_parity_t; -#define UART_PARITY_DISABLE UART_PARITY_NONE +#define UART_PARITY_DISABLE UART_PARITY_NONE + #define HAVE_UART_PARITY_T #endif /* !DOXYGEN */ @@ -1036,19 +1034,20 @@ typedef enum { * @brief Include ESP32x family specific peripheral configuration */ #if defined(CPU_FAM_ESP32) -#include "periph_cpu_esp32.h" +# include "periph_cpu_esp32.h" #elif defined(CPU_FAM_ESP32C3) -#include "periph_cpu_esp32c3.h" +# include "periph_cpu_esp32c3.h" +#elif defined(CPU_FAM_ESP32H2) +# include "periph_cpu_esp32h2.h" #elif defined(CPU_FAM_ESP32S2) -#include "periph_cpu_esp32s2.h" +# include "periph_cpu_esp32s2.h" #elif defined(CPU_FAM_ESP32S3) -#include "periph_cpu_esp32s3.h" +# include "periph_cpu_esp32s3.h" #else -#error "ESP32x family implementation missing" +# error "ESP32x family implementation missing" #endif #ifdef MODULE_PERIPH_CAN -#include "can_esp.h" +# include "can_esp.h" #endif - /** @} */ diff --git a/cpu/esp32/include/periph_cpu_esp32h2.h b/cpu/esp32/include/periph_cpu_esp32h2.h new file mode 100644 index 000000000000..52fd2c0ed758 --- /dev/null +++ b/cpu/esp32/include/periph_cpu_esp32h2.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2025 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#pragma once + +/** + * @ingroup cpu_esp32 + * @{ + * + * @file + * @brief ESP32-H2 specific peripheral configuration + * + * @author Gunar Schorcht + */ + +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Mapping configured ESP32-H2 default clock to CLOCK_CORECLOCK define */ +#define CLOCK_CORECLOCK (1000000UL * CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ) + +/** + * @brief CPU cycles per busy wait loop + */ +#define CPU_CYCLES_PER_LOOP (4) + +/** + * @name Predefined GPIO names + * @{ + */ +#define GPIO0 (GPIO_PIN(PORT_GPIO, 0)) /**< GPIO0 */ +#define GPIO1 (GPIO_PIN(PORT_GPIO, 1)) /**< GPIO1 */ +#define GPIO2 (GPIO_PIN(PORT_GPIO, 2)) /**< GPIO2 MTMS */ +#define GPIO3 (GPIO_PIN(PORT_GPIO, 3)) /**< GPIO3 MTDO */ +#define GPIO4 (GPIO_PIN(PORT_GPIO, 4)) /**< GPIO4 MTCK */ +#define GPIO5 (GPIO_PIN(PORT_GPIO, 5)) /**< GPIO5 MTDI */ +#define GPIO6 (GPIO_PIN(PORT_GPIO, 6)) /**< GPIO6 not broken out */ +#define GPIO7 (GPIO_PIN(PORT_GPIO, 7)) /**< GPIO7 not broken out */ +#define GPIO8 (GPIO_PIN(PORT_GPIO, 8)) /**< GPIO8 */ +#define GPIO9 (GPIO_PIN(PORT_GPIO, 9)) /**< GPIO9 */ +#define GPIO10 (GPIO_PIN(PORT_GPIO, 10)) /**< GPIO10 */ +#define GPIO11 (GPIO_PIN(PORT_GPIO, 11)) /**< GPIO11 */ +#define GPIO12 (GPIO_PIN(PORT_GPIO, 12)) /**< GPIO12 */ +#define GPIO13 (GPIO_PIN(PORT_GPIO, 13)) /**< GPIO13 XTAL_32K_P */ +#define GPIO14 (GPIO_PIN(PORT_GPIO, 14)) /**< GPIO14 XTAL_32K_N */ +#define GPIO15 (GPIO_PIN(PORT_GPIO, 15)) /**< GPIO15 not broken out (internal flash) */ +#define GPIO16 (GPIO_PIN(PORT_GPIO, 16)) /**< GPIO16 not broken out (internal flash) */ +#define GPIO17 (GPIO_PIN(PORT_GPIO, 17)) /**< GPIO17 not broken out (internal flash) */ +#define GPIO18 (GPIO_PIN(PORT_GPIO, 18)) /**< GPIO18 not broken out (internal flash) */ +#define GPIO19 (GPIO_PIN(PORT_GPIO, 19)) /**< GPIO19 not broken out (internal flash) */ +#define GPIO20 (GPIO_PIN(PORT_GPIO, 20)) /**< GPIO20 not broken out (internal flash) */ +#define GPIO21 (GPIO_PIN(PORT_GPIO, 21)) /**< GPIO21 not broken out (internal flash) */ +#define GPIO22 (GPIO_PIN(PORT_GPIO, 22)) /**< GPIO22 */ +#define GPIO23 (GPIO_PIN(PORT_GPIO, 23)) /**< GPIO23 U0RXD */ +#define GPIO24 (GPIO_PIN(PORT_GPIO, 24)) /**< GPIO24 U0TXD */ +#define GPIO25 (GPIO_PIN(PORT_GPIO, 25)) /**< GPIO25 */ +#define GPIO26 (GPIO_PIN(PORT_GPIO, 26)) /**< GPIO26 */ +#define GPIO27 (GPIO_PIN(PORT_GPIO, 27)) /**< GPIO27 */ +/** @} */ + +/** + * @name ADC configuration + * + * ESP32-H2 integrates one 12-bit ADC (ADC1) with 5 channels: + * + * GPIO01, GPIO2, GPIO3, GPIO4 and GPIO5 + * + * The maximum number of ADC channels #ADC_NUMOF_MAX is 5. + */ + +/** + * @name I2C configuration + * + * ESP32-H2 has one built-in I2C interfaces. + * + * The following table shows the default configuration of I2C interfaces + * used for ESP32-H2 boards. It can be overridden by + * [application-specific configurations](#esp32_application_specific_configurations). + * + *
+ * + * Device | Signal | Pin | Symbol | Remarks + * :----------|:-------|:-------|:--------------|:---------------- + * I2C_DEV(0) | | | `#I2C0_SPEED` | default is `I2C_SPEED_FAST` + * I2C_DEV(0) | SCL | GPIO10 | `#I2C0_SCL` | - + * I2C_DEV(0) | SDA | GPIO11 | `#I2C0_SDA` | - + * + *

+ */ + +/** + * @name PWM configuration + * + * The ESP32-H2 LEDC module has 1 channel group with 6 channels. Each of + * these channels can be clocked by one of the 4 timers. This means that + * it is possible to define up to 4 PWM devices with different frequencies + * and resolutions and a total of 6 PWM channels. + */ + +/** + * @name SPI configuration + * + * ESP32-H2 has three SPI controllers where SPI0 and SPI1 share the same bus + * and can only operate in memory mode while SPI2 can be used as general + * purpose SPI: + * + * - controller SPI0 is reserved for external memories like flash and PSRAM + * - controller SPI1 is reserved for external memories like flash and PSRAM + * - controller SPI2 can be used for peripherals (also called FSPI) + * + * Thus, only SPI2 (FSPI) can be used as general purpose SPI in RIOT as + * SPI_DEV(0). + * + * The following table shows the pin configuration used by default, even + * though it **can vary** from board to board. + * + *
+ * + * Device (Alias) | Signal | Pin | Symbol | Remarks + * :-----------------------|:------:|:-------|:-----------:|:------------------- + * `SPI_HOST0`/`SPI_HOST1` | SPICS0 | - | - | reserved for Flash and PSRAM + * `SPI_HOST0`/`SPI_HOST1` | SPICLK | - | - | reserved for Flash and PSRAM + * `SPI_HOST0`/`SPI_HOST1` | SPID | - | - | reserved for Flash and PSRAM + * `SPI_HOST0`/`SPI_HOST1` | SPIQ | - | - | reserved for Flash and PSRAM + * `SPI_HOST0`/`SPI_HOST1` | SPIHD | - | - | reserved for Flash and PSRAM + * `SPI_HOST0`/`SPI_HOST1` | SPIWP | - | - | reserved for Flash and PSRAM + * `SPI_HOST2` (`FSPI`) | SCK | GPIO4 |`#SPI0_SCK` | can be used + * `SPI_HOST2` (`FSPI`) | MOSI | GPIO5 |`#SPI0_MOSI` | can be used + * `SPI_HOST2` (`FSPI`) | MISO | GPIO0 |`#SPI0_MISO` | can be used + * `SPI_HOST2` (`FSPI`) | CS0 | GPIO1 |`#SPI0_CS0` | can be used + * + *

+ */ + +/** + * @name Timer configuration depending on which implementation is used + * + * ESP32-H2 has two timer groups with one channel each. + */ + +#ifdef MODULE_ESP_HW_COUNTER +# error "Counter based timers are not supported by ESP32-H2" +#endif + +/** + * @name UART configuration + * + * ESP32-H2 integrates two UART interfaces. The following default pin + * configuration of UART interfaces as used by a most boards can be overridden + * by the application, see section [Application-Specific Configurations] + * (#esp32_application_specific_configurations). + * + *
+ * + * Device |Signal|Pin |Symbol |Remarks + * :-----------|:-----|:-------|:-----------|:---------------- + * UART_DEV(0) | TxD | GPIO24 |`#UART0_TXD`| cannot be changed + * UART_DEV(0) | RxD | GPIO23 |`#UART0_RXD`| cannot be changed + * UART_DEV(1) | TxD | - |`#UART1_TXD`| optional, can be overridden (no direct I/O) + * UART_DEV(1) | RxD | - |`#UART1_RXD`| optional, can be overridden (no direct I/O) + * + *

+ * + */ + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/cpu/esp32/include/sdkconfig.h b/cpu/esp32/include/sdkconfig.h index 7b6a5b2b186f..20d3eb96f63e 100644 --- a/cpu/esp32/include/sdkconfig.h +++ b/cpu/esp32/include/sdkconfig.h @@ -221,8 +221,8 @@ #endif -#define CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME 10 -#define CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME 50 +#define CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME 10 +#define CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME 50 #define CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME 15 /** @@ -299,6 +299,8 @@ # include "sdkconfig_esp32.h" #elif defined(CPU_FAM_ESP32C3) # include "sdkconfig_esp32c3.h" +#elif defined(CPU_FAM_ESP32H2) +# include "sdkconfig_esp32h2.h" #elif defined(CPU_FAM_ESP32S2) # include "sdkconfig_esp32s2.h" #elif defined(CPU_FAM_ESP32S3) diff --git a/cpu/esp32/include/sdkconfig_esp32h2.h b/cpu/esp32/include/sdkconfig_esp32h2.h new file mode 100644 index 000000000000..4a54c81fcc9c --- /dev/null +++ b/cpu/esp32/include/sdkconfig_esp32h2.h @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2025 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#pragma once + +/** + * @ingroup cpu_esp32 + * @{ + * + * @file + * @brief SDK configuration used by the ESP-IDF for ESP32-H2 SoC variant (family) + * + * The SDK configuration can be partially overridden by application-specific + * board configuration. + * + * @author Gunar Schorcht + */ + +#ifndef DOXYGEN + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name ESP32-H2 specific clock configuration + * @{ + */ + +/* external crystal frequency */ +#define CONFIG_XTAL_FREQ 32 + +/* Mapping of Kconfig defines to the respective enumeration values */ +#if CONFIG_ESP32H2_DEFAULT_CPU_FREQ_MHZ_16 +# define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ 16 +#elif CONFIG_ESP32H2_DEFAULT_CPU_FREQ_MHZ_32 +# define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ 32 +#elif CONFIG_ESP32H2_DEFAULT_CPU_FREQ_MHZ_48 +# define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ 48 +#elif CONFIG_ESP32H2_DEFAULT_CPU_FREQ_MHZ_64 +# define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ 64 +#elif CONFIG_ESP32H2_DEFAULT_CPU_FREQ_MHZ_96 +# define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ 96 +#endif + +/** + * @brief Defines the CPU frequency [values = 16, 32, 48, 64, 96] + */ +#ifndef CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ +# define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ 96 +#endif + +/** @} */ + +/** + * ESP32-H2 MMU configuration (DO NOT CHANGE) + */ +#ifndef CONFIG_MMU_PAGE_SIZE +# define CONFIG_MMU_PAGE_SIZE_32KB 1 +# define CONFIG_MMU_PAGE_SIZE 0x8000 +#endif + +/** + * ESP32-H2 specific RTC clock configuration + */ +#define CONFIG_RTC_CLK_CAL_CYCLES 1024 + +#ifdef MODULE_ESP_RTC_TIMER_32K +#endif + +/** + * ESP32-H2 specific EFUSE configuration + */ +#define CONFIG_EFUSE_MAX_BLK_LEN 256 +#define CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL 0 +#define CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL 99 + +/** + * ESP32-H2 specific MAC configuration + */ +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_BT 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_IEEE802154 1 +#define CONFIG_ESP32H2_UNIVERSAL_MAC_ADDRESSES 2 + +/** + * ESP32-H2 specific serial flasher config (DO NOT CHANGE) + */ +#define CONFIG_ESPTOOLPY_FLASHFREQ_64M 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ "64m" + +/** + * ESP32-H2 specific system configuration (DO NOT CHANGE) + */ +#define CONFIG_ESP32H2_REV_MIN_FULL 0 +#define CONFIG_ESP32H2_REV_MAX_FULL 99 + +#define CONFIG_ESP_TIMER_IMPL_SYSTIMER 1 +#define CONFIG_ESP_TIMER_INTERRUPT_LEVEL 1 + +#define CONFIG_ESP_DEBUG_OCDAWARE 1 + +#define CONFIG_ESP_BROWNOUT_DET 1 +#define CONFIG_ESP_BROWNOUT_DET_LVL 0 + +/** + * ESP32-H2 specific sleep configuration (DO NOT CHANGE) + */ +#define CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB 1 +#define CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND 1 +#define CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS 0 /* we realize it */ +#define CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND 1 +#define CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY 0 +#define CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP 0 + +/** + * ESP32-H2 BLE driver configuration (DO NOT CHANGE) + */ +#ifdef MODULE_ESP_BLE +# define CONFIG_BT_ALARM_MAX_NUM 50 +# define CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD 20 +# define CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM 100 +# define CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP 1 +# define CONFIG_BT_LE_50_FEATURE_SUPPORT 1 +# define CONFIG_BT_LE_ACL_BUF_COUNT 10 +# define CONFIG_BT_LE_ACL_BUF_SIZE 517 +# define CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS 1 +# define CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF 0 +# define CONFIG_BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT 1 +# define CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE 4096 +# define CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS 0 /* default 1 */ +# define CONFIG_BT_LE_DFT_TX_POWER_LEVEL_DBM_EFF 9 +# define CONFIG_BT_LE_DFT_TX_POWER_LEVEL_P9 1 +# define CONFIG_BT_LE_ENABLE_PERIODIC_ADV 1 +# define CONFIG_BT_LE_EXT_ADV_MAX_SIZE 1650 +# define CONFIG_BT_LE_EXT_ADV 1 +# define CONFIG_BT_LE_HCI_EVT_BUF_SIZE 257 +# define CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT 30 +# define CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT 8 +# define CONFIG_BT_LE_HCI_INTERFACE_USE_RAM 1 +# define CONFIG_BT_LE_LL_CFG_FEAT_LE_2M_PHY 1 +# define CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY 1 +# define CONFIG_BT_LE_LL_CFG_FEAT_LE_ENCRYPTION 1 +# define CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT 20 +# define CONFIG_BT_LE_LL_RESOLV_LIST_SIZE 4 +# define CONFIG_BT_LE_LL_SCA 60 +# define CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL 1 +# define CONFIG_BT_LE_MAX_CONNECTIONS 3 +# define CONFIG_BT_LE_MAX_EXT_ADV_INSTANCES 1 +# define CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST 5 +# define CONFIG_BT_LE_MAX_PERIODIC_SYNCS 1 +# define CONFIG_BT_LE_MSYS_1_BLOCK_COUNT 12 +# define CONFIG_BT_LE_MSYS_1_BLOCK_SIZE 256 +# define CONFIG_BT_LE_MSYS_2_BLOCK_COUNT 24 +# define CONFIG_BT_LE_MSYS_2_BLOCK_SIZE 320 +# define CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER 1 +# define CONFIG_BT_LE_PERIODIC_ADV_SYNC_TRANSFER 1 +# define CONFIG_BT_LE_SCAN_DUPL_CACHE_REFRESH_PERIOD 0 +# define CONFIG_BT_LE_SCAN_DUPL_TYPE 0 +# define CONFIG_BT_LE_SCAN_DUPL_TYPE_DEVICE 1 +# define CONFIG_BT_LE_SCAN_DUPL 1 +# define CONFIG_BT_LE_SECURITY_ENABLE 1 +# define CONFIG_BT_LE_SM_LEGACY 1 +# define CONFIG_BT_LE_SM_SC 1 +# define CONFIG_BT_LE_USE_ESP_TIMER 1 +# define CONFIG_BT_LE_WHITELIST_SIZE 12 +# define CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_DIS 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* DOXYGEN */ +/** @} */ diff --git a/cpu/esp32/irq_arch.c b/cpu/esp32/irq_arch.c index 9fcc3cb2a133..06ce7e786d44 100644 --- a/cpu/esp32/irq_arch.c +++ b/cpu/esp32/irq_arch.c @@ -63,7 +63,8 @@ static const struct intr_handle_data_t _irq_data_table[] = { #endif /* SOC_TIMER_GROUPS > 1 */ #if defined(CPU_FAM_ESP32) { ETS_TG0_LACT_LEVEL_INTR_SOURCE, CPU_INUM_SYSTIMER, 2 }, -#elif defined(CPU_FAM_ESP32S2) || defined(CPU_FAM_ESP32S3) || defined(CPU_FAM_ESP32C3) +#elif defined(CPU_FAM_ESP32S2) || defined(CPU_FAM_ESP32S3) || \ + defined(CPU_FAM_ESP32C3) || defined(CPU_FAM_ESP32H2) { ETS_SYSTIMER_TARGET2_EDGE_INTR_SOURCE, CPU_INUM_SYSTIMER, 2 }, #else # error "Platform implementation is missing" @@ -81,6 +82,7 @@ static const struct intr_handle_data_t _irq_data_table[] = { #if defined(SOC_BLE_SUPPORTED) # if defined(CPU_FAM_ESP32) || defined(CPU_FAM_ESP32S3) || defined(CPU_FAM_ESP32C3) { ETS_RWBLE_INTR_SOURCE, CPU_INUM_BLE, 2 }, +# elif defined(CPU_FAM_ESP32H2) # else # error "Platform implementation is missing" # endif @@ -95,8 +97,15 @@ static const struct intr_handle_data_t _irq_data_table[] = { { ETS_SDIO_HOST_INTR_SOURCE, CPU_INUM_SDMMC, 2 }, #endif #if defined(SOC_TWAI_SUPPORTED) +# if defined(CPU_FAM_ESP32) || defined(CPU_FAM_ESP32S3) || \ + defined(CPU_FAM_ESP32S2) || defined(CPU_FAM_ESP32C3) { ETS_TWAI_INTR_SOURCE, CPU_INUM_CAN, 1 }, -#endif +# elif defined(CPU_FAM_ESP32H2) + { ETS_TWAI0_INTR_SOURCE, CPU_INUM_CAN, 1 }, +# else +# error "Platform implementation is missing" +# endif +#endif /* SOC_TWAI_SUPPORTED */ #if defined(SOC_USB_OTG_SUPPORTED) { ETS_USB_INTR_SOURCE, CPU_INUM_USB, 1 }, #endif diff --git a/cpu/esp32/periph/adc_arch_esp32h2.c b/cpu/esp32/periph/adc_arch_esp32h2.c new file mode 100644 index 000000000000..8cd97384fc3c --- /dev/null +++ b/cpu/esp32/periph/adc_arch_esp32h2.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2025 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup cpu_esp32 + * @{ + * + * @file + * @brief Architecture-specific ADC/DAC definitions for ESP32-H2 variant (family) + * + * @author Gunar Schorcht + * + * @} + */ + +#include "board.h" + +#include "adc_arch_private.h" +#include "esp_common.h" +#include "soc/adc_channel.h" + +#define ENABLE_DEBUG 0 +#include "debug.h" + +/** + * @brief ADC hardware descriptor table (for internal use only) + * + * @note The index of entries in the table MUST correspond to the + * RTCIO GPIO number. + */ +const _adc_hw_desc_t _adc_hw[] = { + /* rtcio, gpio, adc_ctrl, adc_channel, pad_name */ + { RTCIO_GPIO(0), ADC1_CHANNEL_0_GPIO_NUM, ADC_UNIT_1, ADC_CHANNEL_0, "GPIO1" }, + { RTCIO_GPIO(1), ADC1_CHANNEL_1_GPIO_NUM, ADC_UNIT_1, ADC_CHANNEL_1, "MTMS" }, + { RTCIO_GPIO(2), ADC1_CHANNEL_2_GPIO_NUM, ADC_UNIT_1, ADC_CHANNEL_2, "MTDO" }, + { RTCIO_GPIO(3), ADC1_CHANNEL_3_GPIO_NUM, ADC_UNIT_1, ADC_CHANNEL_3, "MTCK" }, + { RTCIO_GPIO(4), ADC1_CHANNEL_4_GPIO_NUM, ADC_UNIT_1, ADC_CHANNEL_4, "MTDI" }, +}; + +/** + * @brief GPIO to RTC IO map (for internal use only) + */ +const gpio_t _gpio_rtcio_map[] = { + RTCIO_NA, /* GPIO0 */ + RTCIO_GPIO(0), /* GPIO1 */ + RTCIO_GPIO(1), /* GPIO2 */ + RTCIO_GPIO(2), /* GPIO3 */ + RTCIO_GPIO(3), /* GPIO4 */ + RTCIO_GPIO(4), /* GPIO5 */ + RTCIO_NA, /* GPIO6 */ + RTCIO_NA, /* GPIO7 */ + RTCIO_NA, /* GPIO8 */ + RTCIO_NA, /* GPIO9 */ + RTCIO_NA, /* GPIO10 */ + RTCIO_NA, /* GPIO11 */ + RTCIO_NA, /* GPIO12 */ + RTCIO_NA, /* GPIO13 */ + RTCIO_NA, /* GPIO14 */ + RTCIO_NA, /* GPIO15 */ + RTCIO_NA, /* GPIO16 */ + RTCIO_NA, /* GPIO17 */ + RTCIO_NA, /* GPIO18 */ + RTCIO_NA, /* GPIO19 */ + RTCIO_NA, /* GPIO20 */ + RTCIO_NA, /* GPIO21 */ + RTCIO_NA, /* GPIO22 */ + RTCIO_NA, /* GPIO23 */ + RTCIO_NA, /* GPIO24 */ + RTCIO_NA, /* GPIO25 */ + RTCIO_NA, /* GPIO26 */ + RTCIO_NA, /* GPIO27 */ +}; + +/** + * @brief Default voltage range of ADC results for different attenuations + * + * These values are used by function adc_get_vrange_min_max if software + * calibration doesn't work for any reason and the voltage range can't be + * determined by software. + * + * Table 5-5 in [ESP32-H2 Datasheet] + * (https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf). + */ +const int _adc_vrange_min_max[] = { + 0, 1000, /* min, max @ ADC_ATTEN_DB_0 */ + 0, 1300, /* min, max @ ADC_ATTEN_DB_2_5 */ + 0, 1900, /* min, max @ ADC_ATTEN_DB_6 */ + 0, 3300, /* min, max @ ADC_ATTEN_DB_12 */ +}; + +_Static_assert(ARRAY_SIZE(_gpio_rtcio_map) == SOC_GPIO_PIN_COUNT, + "size of _gpio_rtcio_map does not match SOC_GPIO_PIN_COUNT"); +_Static_assert(ARRAY_SIZE(_adc_vrange_min_max) == (SOC_ADC_ATTEN_NUM * 2), + "size of _adc_vrange_min_max does not match SOC_ADC_ATTEN_NUM"); diff --git a/cpu/esp32/periph/can.c b/cpu/esp32/periph/can.c index f327da73be2a..074924117643 100644 --- a/cpu/esp32/periph/can.c +++ b/cpu/esp32/periph/can.c @@ -40,6 +40,11 @@ #define CAN TWAI +#ifdef CPU_FAM_ESP32H2 +# define PERIPH_TWAI_MODULE PERIPH_TWAI0_MODULE +# define ETS_TWAI_INTR_SOURCE ETS_TWAI0_INTR_SOURCE +#endif + /** Common ESP CAN definitions */ #define ESP_CAN_INTR_MASK (0xffU) /* interrupts handled by ESP CAN */ #define ESP_CAN_CLOCK APB_CLK_FREQ /* controller main clock */ diff --git a/cpu/esp32/periph/gpio.c b/cpu/esp32/periph/gpio.c index 294b8a37ff7c..6f8c727c95c6 100644 --- a/cpu/esp32/periph/gpio.c +++ b/cpu/esp32/periph/gpio.c @@ -39,7 +39,9 @@ #include "soc/gpio_sig_map.h" #include "soc/gpio_struct.h" #include "soc/io_mux_reg.h" +#ifndef CPU_FAM_ESP32H2 #include "soc/rtc_cntl_reg.h" +#endif #include "soc/rtc_io_periph.h" #if __xtensa__ @@ -58,7 +60,7 @@ #define ENABLE_DEBUG 0 #include "debug.h" -#if SOC_PM_SUPPORT_EXT_WAKEUP +#if SOC_PM_SUPPORT_EXT1_WAKEUP #if CPU_FAM_ESP32 #define ESP_PM_WUP_PINS_ANY_HIGH ESP_EXT1_WAKEUP_ANY_HIGH #define ESP_PM_WUP_PINS_ANY_LOW -1 @@ -88,7 +90,6 @@ #endif #endif - #ifndef ESP_PM_WUP_LEVEL #define ESP_PM_WUP_LEVEL ESP_PM_WUP_PINS_ANY_HIGH #endif @@ -259,7 +260,9 @@ int gpio_init(gpio_t pin, gpio_mode_t mode) _gpio_pin_pd[pin] = cfg.pull_down_en; #if SOC_RTCIO_HOLD_SUPPORTED /* disable the RTCIO hold function for the case we come from deep sleep */ - rtc_gpio_hold_dis(pin); + if (rtc_gpio_is_valid_gpio(pin)) { + rtc_gpio_hold_dis(pin); + } #endif /* SOC_RTCIO_HOLD_SUPPORTED */ #endif /* ESP_PM_WUP_PINS */ @@ -510,6 +513,14 @@ void gpio_pm_sleep_enter(unsigned mode) /* isolating GPIO12 from external circuits is especially recommended for * ESP32-WROVER that have an external pullup on GPIO12 */ rtc_gpio_isolate(GPIO_NUM_12); +#elif CPU_FAM_ESP32H2 + /* On ESP32H2 rtc_gpio_force_hold_en_all doesn't enable the hold + * function for all RTC GPIOs, so we have to do it for each pin. */ + for (unsigned i = 0; i < SOC_GPIO_PIN_COUNT; i++) { + if (rtc_gpio_is_valid_gpio(i)) { + rtc_gpio_hold_en(i); + } + } #endif #else # error "ESP32x variant does not support hold feature in deep sleep"; @@ -589,6 +600,8 @@ void gpio_pm_sleep_enter(unsigned mode) gpio_pullup_dis(wup_pins[i]); gpio_pulldown_en(wup_pins[i]); } +#elif SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP + rtc_gpio_hold_en(wup_pins[i]); #endif } #if SOC_PM_SUPPORT_EXT1_WAKEUP diff --git a/cpu/esp32/periph/gpio_arch_esp32h2.c b/cpu/esp32/periph/gpio_arch_esp32h2.c new file mode 100644 index 000000000000..aba1f9797153 --- /dev/null +++ b/cpu/esp32/periph/gpio_arch_esp32h2.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2025 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_esp32 + * @ingroup drivers_periph_gpio + * @{ + * + * @file + * @brief Architecture-specific GPIO definitions for ESP32-H2 variant (family) + * + * @author Gunar Schorcht + * @} + */ + +#include "gpio_arch.h" +#include "soc/io_mux_reg.h" + +#if !IS_USED(MODULE_ESP_IDF_GPIO_HAL) + +/* GPIO to IOMUX register mapping (see Technical Reference, Section 6.13 IO MUX Functions List) + https://www.espressif.com/sites/default/files/documentation/esp32-h2_technical_reference_manual_en.pdf */ + +const uint32_t _gpio_to_iomux_reg[GPIO_PIN_NUMOF] = +{ + PERIPHS_IO_MUX_GPIO0_U, /* GPIO0 */ + PERIPHS_IO_MUX_GPIO1_U, /* GPIO1 */ + PERIPHS_IO_MUX_MTMS_U, /* GPIO2 */ + PERIPHS_IO_MUX_MTDO_U, /* GPIO3 */ + PERIPHS_IO_MUX_MTCK_U, /* GPIO4 */ + PERIPHS_IO_MUX_MTDI_U, /* GPIO5 */ + 0, /* GPIO6 is not available */ + 0, /* GPIO7 is not available */ + PERIPHS_IO_MUX_GPIO8_U, /* GPIO8 */ + PERIPHS_IO_MUX_GPIO9_U, /* GPIO9 */ + PERIPHS_IO_MUX_GPIO10_U, /* GPIO10 */ + PERIPHS_IO_MUX_GPIO11_U, /* GPIO11 */ + PERIPHS_IO_MUX_GPIO12_U, /* GPIO12 */ + PERIPHS_IO_MUX_XTAL_32K_P_U, /* GPIO13 used for XTAL_32K_P */ + PERIPHS_IO_MUX_XTAL_32K_N_U, /* GPIO14 used for XTAL_32K_N*/ + 0, /* GPIO15 is not available */ + 0, /* GPIO16 is not available */ + 0, /* GPIO17 is not available */ + 0, /* GPIO18 is not available */ + 0, /* GPIO19 is not available */ + 0, /* GPIO20 is not available */ + 0, /* GPIO21 is not available */ + PERIPHS_IO_MUX_GPIO22_U, /* GPIO22 */ + PERIPHS_IO_MUX_U0RXD_U, /* GPIO23 */ + PERIPHS_IO_MUX_U0TXD_U, /* GPIO24 */ + PERIPHS_IO_MUX_GPIO25_U, /* GPIO25 */ + PERIPHS_IO_MUX_GPIO26_U, /* GPIO26 */ + PERIPHS_IO_MUX_GPIO27_U, /* GPIO27 */ +}; + +#endif /* !IS_USED(MODULE_ESP_IDF_GPIO_HAL) */ + +/* Table of the usage type of each GPIO pin */ +gpio_pin_usage_t _gpio_pin_usage[GPIO_PIN_NUMOF] = { + _GPIO, /* GPIO0 */ + _GPIO, /* GPIO1 */ + _GPIO, /* GPIO2 */ + _GPIO, /* GPIO3 */ + _GPIO, /* GPIO4 */ + _GPIO, /* GPIO5 */ + _NOT_EXIST, /* GPIO6 does not exist */ + _NOT_EXIST, /* GPIO7 does not exist */ + _GPIO, /* GPIO8 */ + _GPIO, /* GPIO9 */ + _GPIO, /* GPIO10 */ + _GPIO, /* GPIO11 */ + _GPIO, /* GPIO12 */ +#if MODULE_ESP_RTC_TIMER_32K + _NOT_EXIST, /* GPIO13 is used for external 32K crystal */ + _NOT_EXIST, /* GPIO14 is used for external 32K crystal */ +#else + _GPIO, /* GPIO13 */ + _GPIO, /* GPIO14 */ +#endif + _NOT_EXIST, /* GPIO15 does not exist */ + _NOT_EXIST, /* GPIO16 does not exist */ + _NOT_EXIST, /* GPIO17 does not exist */ + _NOT_EXIST, /* GPIO18 does not exist */ + _NOT_EXIST, /* GPIO19 does not exist */ + _NOT_EXIST, /* GPIO20 does not exist */ + _NOT_EXIST, /* GPIO21 does not exist */ + _GPIO, /* GPIO22 */ + _UART, /* GPIO23 is used as direct I/O UART0 RxD */ + _UART, /* GPIO24 is used as direct I/O UART0 TxD */ + _GPIO, /* GPIO25 */ + _GPIO, /* GPIO26 could be used for builtin USB2JTAG bridge */ + _GPIO, /* GPIO27 could be used for builtin USB2JTAG bridge */ +}; diff --git a/cpu/esp32/periph/pm.c b/cpu/esp32/periph/pm.c index 2faa14d860ef..afcc28c80fe4 100644 --- a/cpu/esp32/periph/pm.c +++ b/cpu/esp32/periph/pm.c @@ -36,7 +36,9 @@ #include "rom/rtc.h" #include "rom/uart.h" #include "soc/rtc.h" -#include "soc/rtc_cntl_reg.h" +#ifndef CPU_FAM_ESP32H2 +# include "soc/rtc_cntl_reg.h" +#endif #define ENABLE_DEBUG 0 #include "debug.h" @@ -192,6 +194,7 @@ void pm_set(unsigned mode) #endif if (mode == ESP_PM_DEEP_SLEEP) { + system_wdt_stop(); esp_deep_sleep_start(); /* waking up from deep-sleep leads to a DEEPSLEEP_RESET */ UNREACHABLE(); diff --git a/cpu/esp32/periph/pwm.c b/cpu/esp32/periph/pwm.c index fa4d8312a99b..d7e80ec72899 100644 --- a/cpu/esp32/periph/pwm.c +++ b/cpu/esp32/periph/pwm.c @@ -28,11 +28,13 @@ #include "periph/pwm.h" #include "periph/gpio.h" +#include "esp_clk_tree.h" #include "esp_cpu.h" #include "esp_common.h" #include "esp_private/periph_ctrl.h" #include "esp_rom_gpio.h" #include "hal/ledc_hal.h" +#include "soc/ledc_periph.h" #include "soc/ledc_struct.h" #include "soc/rtc.h" @@ -126,9 +128,14 @@ uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res) hw_res_bit++; } + uint32_t clk_freq; + esp_clk_tree_src_get_freq_hz((soc_module_clk_t)LEDC_SCLK, + ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, + &clk_freq); + uint32_t hw_res = 1 << hw_res_bit; - uint32_t hw_ticks_max = rtc_clk_apb_freq_get(); + uint32_t hw_ticks_max = clk_freq; uint32_t hw_ticks_min = hw_ticks_max / (1 << SOC_LEDC_CLK_DIV_INT_BIT_NUM); uint32_t hw_freq_min = hw_ticks_min / (1 << SOC_LEDC_TIMER_BIT_WIDTH) + 1; @@ -139,11 +146,11 @@ uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res) } /* number of hardware ticks required, at maximum it can be APB clock */ - uint32_t hw_ticks = MIN(freq * hw_res, rtc_clk_apb_freq_get()); + uint32_t hw_ticks = MIN(freq * hw_res, clk_freq); /* - * if the number of required ticks is less than minimum ticks supported by - * the hardware supports, we have to increase the resolution. + * if the number of required ticks is less than the minimum supported by + * the hardware, we have to increase the resolution. */ while (hw_ticks < hw_ticks_min) { hw_res_bit++; @@ -153,7 +160,7 @@ uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res) /* LEDC_CLK_DIV is given in Q10.8 format */ uint32_t hw_clk_div = - ((uint64_t)rtc_clk_apb_freq_get() << SOC_LEDC_CLK_DIV_FRAC_BIT_NUM) / hw_ticks; + ((uint64_t)clk_freq << SOC_LEDC_CLK_DIV_FRAC_BIT_NUM) / hw_ticks; _DEV.freq = freq; _DEV.res = res; @@ -255,9 +262,10 @@ void pwm_poweron(pwm_t pwm) /* enable and init the module and select the right clock source */ periph_module_enable(_CFG.module); ledc_hal_init(&_DEV.hw, _CFG.group); - ledc_hal_set_slow_clk_sel(&_DEV.hw, LEDC_SLOW_CLK_APB); + ledc_ll_enable_clock(_DEV.hw.dev, true); + ledc_hal_set_slow_clk_sel(&_DEV.hw, (ledc_slow_clk_sel_t)LEDC_SCLK); #if SOC_LEDC_HAS_TIMER_SPECIFIC_MUX - ledc_hal_set_clock_source(&_DEV.hw, _CFG.timer, LEDC_APB_CLK); + ledc_hal_set_clock_source(&_DEV.hw, _CFG.timer, (ledc_clk_src_t)LEDC_SCLK); #endif /* update the timer according to determined parameters */ diff --git a/cpu/esp32/periph/rtt.c b/cpu/esp32/periph/rtt.c index 0a4b976face1..55f0c0ee28fd 100644 --- a/cpu/esp32/periph/rtt.c +++ b/cpu/esp32/periph/rtt.c @@ -34,8 +34,6 @@ #define ENABLE_DEBUG 0 #include "debug.h" -#define RTC_CLK_CAL_FRACT 19 /* fractional bits of calibration value */ - /* contains the values as given at the interface */ typedef struct { uint32_t alarm; /**< alarm value as set at the interface */ diff --git a/cpu/esp32/periph/rtt_hw_rtc.c b/cpu/esp32/periph/rtt_hw_rtc.c index 5bd112038ad1..fa60d04a96df 100644 --- a/cpu/esp32/periph/rtt_hw_rtc.c +++ b/cpu/esp32/periph/rtt_hw_rtc.c @@ -19,24 +19,26 @@ * @} */ +#include "stdint.h" + /* RIOT headers have to be included before ESP-IDF headers! */ -#include "cpu.h" #include "esp/common_macros.h" -#include "esp_common.h" #include "irq_arch.h" #include "log.h" #include "periph/rtt.h" #include "rtt_arch.h" -#include "syscalls.h" -#include "timex.h" /* ESP-IDF headers */ -#include "esp_attr.h" #include "esp_cpu.h" -#include "esp_sleep.h" #include "rom/ets_sys.h" -#include "soc/periph_defs.h" -#include "soc/rtc_cntl_struct.h" +#include "soc/rtc.h" +#include "soc/soc_caps.h" + +#if SOC_LP_TIMER_SUPPORTED +# include "hal/lp_timer_ll.h" +#else +# include "soc/rtc_cntl_struct.h" +#endif #if __xtensa__ #include "soc/dport_reg.h" @@ -46,7 +48,11 @@ #define ENABLE_DEBUG 0 #include "debug.h" -#define RTC_CLK_CAL_FRACT 19 /* fractional bits of calibration value */ +#if SOC_LP_TIMER_SUPPORTED +# define RTC_TIMER_INTR_SOURCE ETS_LP_RTC_TIMER_INTR_SOURCE +#else +# define RTC_TIMER_INTR_SOURCE ETS_RTC_CORE_INTR_SOURCE +#endif typedef struct { uint32_t alarm_set; /**< alarm set at interface */ @@ -79,7 +85,7 @@ static void _rtc_init(void) static void _rtc_poweron(void) { /* route all interrupt sources to the same RTT level type interrupt */ - intr_matrix_set(PRO_CPU_NUM, ETS_RTC_CORE_INTR_SOURCE, CPU_INUM_RTT); + intr_matrix_set(PRO_CPU_NUM, RTC_TIMER_INTR_SOURCE, CPU_INUM_RTT); /* set interrupt handler and enable the CPU interrupt */ esp_cpu_intr_set_handler(CPU_INUM_RTT, _rtc_isr, NULL); @@ -93,6 +99,106 @@ static void _rtc_poweroff(void) esp_cpu_intr_set_handler(CPU_INUM_RTT, NULL, NULL); } +static void _rtc_save_counter(void) +{ +} + +static void _rtc_restore_counter(bool in_init) +{ + (void)in_init; +} + +#if SOC_LP_TIMER_SUPPORTED + +uint64_t _rtc_get_counter(void) +{ + /* trigger timer register update */ + LP_TIMER.update.update = 1; + /* read the time from 48-bit counter and return */ + return ((uint64_t)LP_TIMER.counter[0].hi.counter_hi << 32) + + LP_TIMER.counter[0].lo.counter_lo; +} + +static void _rtc_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg) +{ + /* compute the time difference for 32.768 kHz as 32-bit value */ + uint64_t rtc_counter = _rtc_get_counter(); + uint32_t rtt_diff = alarm - rtc_counter; + + /* use computed time difference directly to set the RTC counter alarm */ + uint64_t rtc_alarm = (rtc_counter + rtt_diff) & RTT_HW_COUNTER_MAX; + + DEBUG("%s alarm=%" PRIu32 " rtt_diff=%" PRIu32 + " rtc_alarm=%" PRIu32 " @rtc=%" PRIu32 "\n", + __func__, alarm, rtt_diff, (uint32_t)rtc_alarm, (uint32_t)rtc_counter); + + /* save the alarm configuration for interrupt handling */ + _rtc_alarm.alarm_set = alarm; + _rtc_alarm.alarm_cb = cb; + _rtc_alarm.alarm_arg = arg; + + /* set the timer value */ + LP_TIMER.target[0].lo.target_lo = rtc_alarm & UINT32_MAX; + LP_TIMER.target[0].hi.target_hi = rtc_alarm >> 32; + + DEBUG("%s %08x%08x \n", __func__, + (unsigned)LP_TIMER.target[0].hi.target_hi, + (unsigned)LP_TIMER.target[0].lo.target_lo); + + /* clear and enable RTC timer interrupt */ + LP_TIMER.int_clr.alarm = 1; + LP_TIMER.int_en.alarm = 1; + + /* enable RTC timer alarm */ + LP_TIMER.target[0].hi.enable = 1; +} + +static void _rtc_clear_alarm(void) +{ + /* disable alarms first */ + LP_TIMER.target[0].hi.enable = 0; + + /* clear the bit in interrupt enable and status register */ + LP_TIMER.int_clr.alarm = 0; + LP_TIMER.int_en.alarm = 0; + + /* reset the alarm configuration for interrupt handling */ + _rtc_alarm.alarm_set = 0; + _rtc_alarm.alarm_cb = NULL; + _rtc_alarm.alarm_arg = NULL; +} + +static void IRAM _rtc_isr(void *arg) +{ + /* disable alarms first */ + LP_TIMER.target[0].hi.enable = 0; + + /* clear the bit in interrupt enable and status register */ + LP_TIMER.int_en.alarm = 0; + LP_TIMER.int_clr.alarm = 1; + + /* save the lower 32 bit of the current counter value */ + uint32_t counter = _rtc_get_counter(); + + DEBUG("%s %" PRIu32 "\n", __func__, counter); + + if (_rtc_alarm.alarm_cb) { + DEBUG("%s alarm %" PRIu32 "\n", __func__, counter); + + rtt_cb_t alarm_cb = _rtc_alarm.alarm_cb; + void *alarm_arg = _rtc_alarm.alarm_arg; + + /* clear the alarm first */ + _rtc_alarm.alarm_cb = NULL; + _rtc_alarm.alarm_arg = NULL; + + /* call the alarm handler afterwards if callback was defined */ + alarm_cb(alarm_arg); + } +} + +#else + uint64_t _rtc_get_counter(void) { /* trigger timer register update */ @@ -160,15 +266,6 @@ static void _rtc_clear_alarm(void) _rtc_alarm.alarm_arg = NULL; } -static void _rtc_save_counter(void) -{ -} - -static void _rtc_restore_counter(bool in_init) -{ - (void)in_init; -} - static void IRAM _rtc_isr(void *arg) { /* disable alarms first */ @@ -198,6 +295,8 @@ static void IRAM _rtc_isr(void *arg) } } +#endif + const rtt_hw_driver_t _rtt_hw_rtc_driver = { .init = _rtc_init, .get_counter = _rtc_get_counter, diff --git a/cpu/esp32/periph/spi.c b/cpu/esp32/periph/spi.c index a4b040064578..c0ce0ca6fa37 100644 --- a/cpu/esp32/periph/spi.c +++ b/cpu/esp32/periph/spi.c @@ -44,6 +44,7 @@ #include "driver/gpio.h" #include "esp_attr.h" +#include "esp_clk_tree.h" #include "esp_cpu.h" #include "esp_private/periph_ctrl.h" #include "esp_rom_gpio.h" @@ -68,7 +69,7 @@ struct _spi_bus_t { spi_host_device_t hostid; /* SPI hostid as used by ESP-IDF */ const spi_signal_conn_t *periph; /* SPI peripheral descriptor */ spi_hal_timing_conf_t timing; /* calculated SPI timing parameters */ - spi_clk_t clk_last; /* SPI clock speed used last time in Hz */ + spi_clk_t clk_last; /* SPI clock speed used last time in Hz */ uint8_t mode_last; /* SPI mode used last time */ bool pins_initialized; /* SPI pins initialized */ }; @@ -303,7 +304,7 @@ void IRAM_ATTR spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t cl cs = (cs == GPIO_UNDEF) ? spi_config[bus].cs : cs; /* if the CS pin used is not yet initialized, we do it now */ - if (gpio_get_pin_usage(cs) != _SPI && spi_init_cs(bus, cs) != SPI_OK) { + if ((gpio_get_pin_usage(cs) != _SPI) && (spi_init_cs(bus, cs) != SPI_OK)) { LOG_TAG_ERROR("spi", "SPI_DEV(%d) CS signal could not be initialized\n", bus); @@ -313,6 +314,9 @@ void IRAM_ATTR spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t cl /* lock the bus */ mutex_lock(&_spi[bus].lock); + /* enable peripheral output clock */ + spi_ll_enable_clock(_spi[bus].hostid, true); + /* * set SPI mode * see ESP32 Technical Reference, Section 7.4.1, Table 27 @@ -337,17 +341,22 @@ void IRAM_ATTR spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t cl /* check whether timing has to be recalculated (time consuming) */ if (clk != _spi[bus].clk_last) { - uint32_t apb_clk = rtc_clk_apb_freq_get(); + uint32_t apb_clk = 0; uint32_t clk_reg; - if (apb_clk / 5 < clk) { + spi_ll_set_clk_source(_spi[bus].periph->hw, SPI_CLK_SRC_DEFAULT); + esp_clk_tree_src_get_freq_hz((soc_module_clk_t)SPI_CLK_SRC_DEFAULT, + ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, + &apb_clk); + + if ((apb_clk / 4) < clk) { LOG_TAG_ERROR("spi", "APB clock rate (%"PRIu32" Hz) has to be at " - "least 5 times SPI clock rate (%d Hz)\n", + "least 4 times SPI clock rate (%d Hz)\n", apb_clk, clk); assert(false); } - /* duty cycle is measured in is 1/256th, 50% = 128 */ + /* duty cycle is measured in 1/256th, 50% = 128 */ int _clk = spi_ll_master_cal_clock(apb_clk, clk, 128, &clk_reg); @@ -364,7 +373,7 @@ void IRAM_ATTR spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t cl &_spi[bus].timing.clock_reg); spi_ll_apply_config(_spi[bus].periph->hw); -#if defined(CPU_FAM_ESP32C3) || defined(CPU_FAM_ESP32S3) +#if defined(CPU_FAM_ESP32C3) || defined(CPU_FAM_ESP32S3) || defined(CPU_FAM_ESP32H2) /* * If the SPI mode has been changed, the clock signal is only set to the * correct level at the beginning of the transfer on the ESP32x3. However, @@ -402,6 +411,8 @@ void IRAM_ATTR spi_release(spi_t bus) static const char* _spi_names[] = { "CSPI/FSPI", "HSPI", "VSPI" }; #elif defined(CPU_FAM_ESP32C3) static const char* _spi_names[] = { "SPI", "FSPI" }; +#elif defined(CPU_FAM_ESP32H2) +static const char* _spi_names[] = { "SPI", "FSPI" }; #elif defined(CPU_FAM_ESP32S2) static const char* _spi_names[] = { "SPI", "FSPI", "HSPI" }; #elif defined(CPU_FAM_ESP32S3) diff --git a/cpu/esp32/periph/timer.c b/cpu/esp32/periph/timer.c index 4e94a9b24b7d..f7d00cad3e31 100644 --- a/cpu/esp32/periph/timer.c +++ b/cpu/esp32/periph/timer.c @@ -64,8 +64,8 @@ /* hardware timer modules used */ /** - * ESP32 has four 64 bit hardware timers: - * two timer groups TMG0 and TMG1 with 2 timers each + * ESP32 and ESP32-S2 have four 64 bit hardware timers while ESP32-S3 has four + * 54 bit hardware timers: two timer groups TMG0 and TMG1 with 2 timers each * * TMG0, timer 0 is used for system time in us and is therefore not * available as low level timer. Timers have only one channel. Timer devices @@ -80,7 +80,7 @@ * timer device is needed. * * --- - * ESP32-C3 hast only two 54 bit hardware timers: + * ESP32-C3, ESP32-H2 have only two 54 bit hardware timers: * two timer groups TMG0 and TMG1 with 1 timer each * * TMG0, timer 0 is used for system time in us and is therefore not @@ -113,34 +113,29 @@ struct _hw_timer_desc_t { static const struct _hw_timer_desc_t _timers_desc[] = { -#if defined(CPU_FAM_ESP32) || defined(CPU_FAM_ESP32S2) || defined(CPU_FAM_ESP32S3) +#if SOC_TIMER_GROUP_TIMERS_PER_GROUP > 1 { .module = PERIPH_TIMG0_MODULE, .group = TIMER_GROUP_0, .index = TIMER_1, .int_src = ETS_TG0_T1_LEVEL_INTR_SOURCE, }, +#endif +#if SOC_TIMER_GROUPS > 1 { .module = PERIPH_TIMG1_MODULE, .group = TIMER_GROUP_1, .index = TIMER_0, .int_src = ETS_TG1_T0_LEVEL_INTR_SOURCE, }, +# if SOC_TIMER_GROUP_TIMERS_PER_GROUP > 1 { .module = PERIPH_TIMG1_MODULE, .group = TIMER_GROUP_1, .index = TIMER_1, .int_src = ETS_TG1_T1_LEVEL_INTR_SOURCE, } -#elif defined(CPU_FAM_ESP32C3) - { - .module = PERIPH_TIMG1_MODULE, - .group = TIMER_GROUP_1, - .index = TIMER_0, - .int_src = ETS_TG1_T0_LEVEL_INTR_SOURCE - }, -#else -#error "MCU implementation needed" +# endif #endif }; diff --git a/cpu/esp32/startup.c b/cpu/esp32/startup.c index 2f7a0b39f9be..b99693645c9c 100644 --- a/cpu/esp32/startup.c +++ b/cpu/esp32/startup.c @@ -57,9 +57,11 @@ #include "rom/rtc.h" #include "rom/uart.h" #include "soc/rtc.h" -#include "soc/rtc_cntl_reg.h" -#include "soc/rtc_cntl_struct.h" -#include "soc/syscon_reg.h" +#ifndef CPU_FAM_ESP32H2 +# include "soc/rtc_cntl_reg.h" +# include "soc/rtc_cntl_struct.h" +# include "soc/syscon_reg.h" +#endif #include "soc/timer_group_struct.h" #if __xtensa__ @@ -267,7 +269,7 @@ static NORETURN void IRAM system_init (void) rtc_clk_fast_freq_get() == RTC_FAST_FREQ_8M ? 8 * MHZ : esp_clk_xtal_freq()/4, rtc_clk_slow_freq_get_hz()); - LOG_STARTUP("XTAL calibration value: %d\n", esp_clk_slowclk_cal_get()); + LOG_STARTUP("RTC Slow Clock calibration value: %d\n", esp_clk_slowclk_cal_get()); LOG_STARTUP("Heap free: %u bytes\n", get_free_heap_size()); /* initialize architecture specific interrupt handling */ diff --git a/cpu/esp32/syscalls.c b/cpu/esp32/syscalls.c index e3bb2c351bf1..69150b533a12 100644 --- a/cpu/esp32/syscalls.c +++ b/cpu/esp32/syscalls.c @@ -32,6 +32,7 @@ #include "sys/lock.h" #include "timex.h" +#include "esp_clk_tree.h" #include "esp_cpu.h" #include "esp_private/periph_ctrl.h" #include "esp_rom_caps.h" @@ -43,8 +44,10 @@ #include "rom/libc_stubs.h" #include "soc/periph_defs.h" #include "soc/rtc.h" -#include "soc/rtc_cntl_reg.h" -#include "soc/rtc_cntl_struct.h" +#ifndef CPU_FAM_ESP32H2 +# include "soc/rtc_cntl_reg.h" +# include "soc/rtc_cntl_struct.h" +#endif #include "soc/timer_group_reg.h" #include "soc/timer_group_struct.h" #include "sdkconfig.h" @@ -212,6 +215,27 @@ extern int _scanf_float(struct _reent *rptr, FILE *fp, va_list *ap); +#if !defined(CPU_FAM_ESP32) && !defined(CPU_FAM_ESP32S2) +/* We need to override these functions that are used from ROM */ + +__attribute__((__noreturn__)) +static void _riot__assert_func(const char *file, int line, const char * func, + const char *failedexpr) +{ + extern __NORETURN void _assert_failure(const char *file, unsigned line); + (void)func; + (void)failedexpr; + _assert_failure(file, line); +} + +static void _riot__sinit(struct _reent *reent) +{ + /* this function should never be called from ROM */ + assert(0); +} + +#endif + static struct syscall_stub_table s_stub_table = { .__getreent = &__getreent, @@ -275,6 +299,11 @@ static struct syscall_stub_table s_stub_table = ._printf_float = NULL, ._scanf_float = NULL, #endif /* CONFIG_NEWLIB_NANO_FORMAT */ +#if !defined(CPU_FAM_ESP32) && !defined(CPU_FAM_ESP32S2) + .__assert_func = &_riot__assert_func, + .__sinit = &_riot__sinit, + ._cleanup_r = NULL, /* we don't need a cleanup of stdio */ +#endif }; timer_hal_context_t sys_timer = { @@ -406,9 +435,15 @@ void IRAM syscalls_init_arch(void) /* initialize and enable the system timer in us */ periph_module_enable(PERIPH_TIMG0_MODULE); + + uint32_t clk_freq; + esp_clk_tree_src_get_freq_hz((soc_module_clk_t)GPTIMER_CLK_SRC_DEFAULT, + ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, + &clk_freq); + timer_ll_set_clock_source(sys_timer.dev, sys_timer.timer_id, GPTIMER_CLK_SRC_DEFAULT); timer_ll_enable_clock(sys_timer.dev, sys_timer.timer_id, true); - timer_ll_set_clock_prescale(sys_timer.dev, sys_timer.timer_id, rtc_clk_apb_freq_get() / MHZ); + timer_ll_set_clock_prescale(sys_timer.dev, sys_timer.timer_id, clk_freq / MHZ); timer_ll_set_count_direction(sys_timer.dev, sys_timer.timer_id, GPTIMER_COUNT_UP); timer_ll_enable_auto_reload(sys_timer.dev, sys_timer.timer_id, false); timer_ll_enable_counter(sys_timer.dev, sys_timer.timer_id, true); @@ -425,6 +460,13 @@ void IRAM syscalls_init_arch(void) #else syscall_table_ptr = &s_stub_table; #endif + + /* we don't need a cleanup for stdio */ + _GLOBAL_REENT->__cleanup = NULL; + /* init stdio */ + _REENT_SDIDINIT(_GLOBAL_REENT) = 0; + __sinit(_GLOBAL_REENT); + _REENT_SDIDINIT(_GLOBAL_REENT) = 1; } uint32_t system_get_time(void) @@ -466,7 +508,12 @@ void system_wdt_init(void) /* initialize and disable boot watchdogs MWDT and RWDT (the prescaler for * MWDT is the APB clock in MHz to get a microsecond tick, for RWDT it is * not applicable) */ - wdt_hal_init(&mwdt, WDT_MWDT0, rtc_clk_apb_freq_get()/MHZ, true); + uint32_t clk_freq; + esp_clk_tree_src_get_freq_hz((soc_module_clk_t)GPTIMER_CLK_SRC_DEFAULT, + ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, + &clk_freq); + + wdt_hal_init(&mwdt, WDT_MWDT0, clk_freq / MHZ, true); wdt_hal_init(&rwdt, WDT_RWDT, 0, false); /* disable write protection for MWDT and RWDT */ diff --git a/cpu/esp32/vendor/ld/esp32h2/memory.ld.in b/cpu/esp32/vendor/ld/esp32h2/memory.ld.in new file mode 100644 index 000000000000..a4591890dd46 --- /dev/null +++ b/cpu/esp32/vendor/ld/esp32h2/memory.ld.in @@ -0,0 +1,118 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * ESP32-H2 Linker Script Memory Layout + * This file describes the memory layout (memory blocks) by virtual memory addresses. + * This linker script is passed through the C preprocessor to include configuration options. + * Please use preprocessor features sparingly! + * Restrict to simple macros with numeric values, and/or #if/#endif blocks. + */ + +#include "sdkconfig.h" +#include "ld.common" + +#define SRAM_SEG_START 0x40800000 +#define SRAM_SEG_END 0x4083EFD0 /* 2nd stage bootloader iram_loader_seg start address */ +#define SRAM_SEG_SIZE SRAM_SEG_END - SRAM_SEG_START + +#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS +/* + * IDRAM0_2_SEG_SIZE_DEFAULT is used when page size is 64KB + */ +#define IDRAM0_2_SEG_SIZE (CONFIG_MMU_PAGE_SIZE << 8) +#endif + +MEMORY +{ + /** + * All these values assume the flash cache is on, and have the blocks this uses subtracted from the length + * of the various regions. The 'data access port' dram/drom regions map to the same iram/irom regions but + * are connected to the data port of the CPU and eg allow byte-wise access. + */ + +#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS + /* Flash mapped instruction data */ + irom_seg (RX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 + + /** + * (0x20 offset above is a convenience for the app binary image generation. + * Flash cache has 64KB pages. The .bin file which is flashed to the chip + * has a 0x18 byte file header, and each segment has a 0x08 byte segment + * header. Setting this offset makes it simple to meet the flash cache MMU's + * constraint that (paddr % 64KB == vaddr % 64KB).) + */ +#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS + + /** + * Shared data RAM, excluding memory reserved for ROM bss/data/stack. + * Enabling Bluetooth & Trace Memory features in menuconfig will decrease the amount of RAM available. + */ + sram_seg (RWX) : org = SRAM_SEG_START, len = SRAM_SEG_SIZE + +#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS + /* Flash mapped constant data */ + drom_seg (R) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 + + /* (See irom_seg for meaning of 0x20 offset in the above.) */ +#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS + + /** + * lp ram memory (RWX). Persists over deep sleep. // ESP32H2-TODO IDF-6272 + */ + lp_ram_seg(RW) : org = 0x50000000, len = 0x1000 - RESERVE_RTC_MEM + + + /* We reduced the size of lp_ram_seg by RESERVE_RTC_MEM value. + It reserves the amount of LP memory that we use for this memory segment. + This segment is intended for keeping: + - (lower addr) rtc timer data (s_rtc_timer_retain_mem, see esp_clk.c files). + - (higher addr) bootloader rtc data (s_bootloader_retain_mem, when a Kconfig option is on). + The aim of this is to keep data that will not be moved around and have a fixed address. + */ + lp_reserved_seg(RW) : org = 0x50000000 + 0x1000 - RESERVE_RTC_MEM, len = RESERVE_RTC_MEM +} + +/* Heap ends at top of sram_seg */ +_heap_end = 0x40000000; + +_data_seg_org = ORIGIN(rtc_data_seg); + +/** + * The lines below define location alias for .rtc.data section + * As C3 only has RTC fast memory, this is not configurable like on other targets + */ +REGION_ALIAS("rtc_iram_seg", lp_ram_seg ); +REGION_ALIAS("rtc_data_seg", rtc_iram_seg ); +REGION_ALIAS("rtc_slow_seg", rtc_iram_seg ); +REGION_ALIAS("rtc_data_location", rtc_iram_seg ); +REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg ); + +#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS + REGION_ALIAS("default_code_seg", irom_seg); +#else + REGION_ALIAS("default_code_seg", sram_seg); +#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS + +#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS + REGION_ALIAS("default_rodata_seg", drom_seg); +#else + REGION_ALIAS("default_rodata_seg", sram_seg); +#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS + +/** + * If rodata default segment is placed in `drom_seg`, then flash's first rodata section must + * also be first in the segment. + */ +#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS + ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg), + ".flash_rodata_dummy section must be placed at the beginning of the rodata segment.") +#endif + +#if CONFIG_ESP_SYSTEM_USE_EH_FRAME + ASSERT ((__eh_frame_end > __eh_frame), "Error: eh_frame size is null!"); + ASSERT ((__eh_frame_hdr_end > __eh_frame_hdr), "Error: eh_frame_hdr size is null!"); +#endif diff --git a/cpu/esp32/vendor/ld/esp32h2/sections.ld.in b/cpu/esp32/vendor/ld/esp32h2/sections.ld.in new file mode 100644 index 000000000000..d1013a36590a --- /dev/null +++ b/cpu/esp32/vendor/ld/esp32h2/sections.ld.in @@ -0,0 +1,749 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "ld.common" + +/* Default entry point */ +ENTRY(call_start_cpu0); + +SECTIONS +{ + /** + * RTC fast memory holds RTC wake stub code, + * including from any source file named rtc_wake_stub*.c + */ + .rtc.text : + { + /* Align the start of RTC code region as per PMP granularity + * this ensures we do not overwrite the permissions for any potential previous + * region regardless of its end alignment + */ + ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_fast_start) + ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_text_start) + + *(.rtc.entry.text) + + *(.rtc.literal .rtc.text .rtc.text.*) + + *rtc_wake_stub*.*(.text .text.*) + *(.rtc_text_end_test) + + /* Align the end of RTC code region as per PMP granularity */ + . = ALIGN(_esp_pmp_align_size); + + _rtc_text_end = ABSOLUTE(.); + } > lp_ram_seg + + /** + * This section located in RTC FAST Memory area. + * It holds data marked with RTC_FAST_ATTR attribute. + * See the file "esp_attr.h" for more information. + */ + .rtc.force_fast : + { + ALIGNED_SYMBOL(4, _rtc_force_fast_start) + + _coredump_rtc_fast_start = ABSOLUTE(.); + *(.rtc.fast.coredump .rtc.fast.coredump.*) + _coredump_rtc_fast_end = ABSOLUTE(.); + + *(.rtc.force_fast .rtc.force_fast.*) + + ALIGNED_SYMBOL(4, _rtc_force_fast_end) + } > lp_ram_seg + + /** + * RTC data section holds RTC wake stub + * data/rodata, including from any source file + * named rtc_wake_stub*.c and the data marked with + * RTC_DATA_ATTR, RTC_RODATA_ATTR attributes. + */ + .rtc.data : + { + _rtc_data_start = ABSOLUTE(.); + + _coredump_rtc_start = ABSOLUTE(.); + *(.rtc.coredump .rtc.coredump.*) + _coredump_rtc_end = ABSOLUTE(.); + *(.rtc.data .rtc.data.*) + *(.rtc.rodata .rtc.rodata.*) + + *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) + + _rtc_data_end = ABSOLUTE(.); + } > lp_ram_seg + + /* RTC bss, from any source file named rtc_wake_stub*.c */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + + *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) + *rtc_wake_stub*.*(COMMON) + + _rtc_bss_end = ABSOLUTE(.); + /* part that saves some data for rtc periph module, this part is + only initialized at power on reset */ + _rtc_bss_rtc_start = ABSOLUTE(.); + *(.rtc.bss .rtc.bss.*) + _rtc_bss_rtc_end = ABSOLUTE(.); + } > lp_ram_seg + + /** + * This section holds data that should not be initialized at power up + * and will be retained during deep sleep. + * User data marked with RTC_NOINIT_ATTR will be placed + * into this section. See the file "esp_attr.h" for more information. + */ + .rtc_noinit (NOLOAD): + { + ALIGNED_SYMBOL(4, _rtc_noinit_start) + + *(.rtc_noinit .rtc_noinit.*) + + ALIGNED_SYMBOL(4, _rtc_noinit_end) + } > lp_ram_seg + + /** + * This section located in RTC SLOW Memory area. + * It holds data marked with RTC_SLOW_ATTR attribute. + * See the file "esp_attr.h" for more information. + */ + .rtc.force_slow : + { + ALIGNED_SYMBOL(4, _rtc_force_slow_start) + + *(.rtc.force_slow .rtc.force_slow.*) + + ALIGNED_SYMBOL(4, _rtc_force_slow_end) + } > lp_ram_seg + + /** + * This section holds RTC data that should have fixed addresses. + * The data are not initialized at power-up and are retained during deep + * sleep. + */ + .rtc_reserved (NOLOAD): + { + ALIGNED_SYMBOL(4, _rtc_reserved_start) + + /** + * New data can only be added here to ensure existing data are not moved. + * Because data have adhered to the end of the segment and code is relied + * on it. + * >> put new data here << + */ + + *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) + KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + + _rtc_reserved_end = ABSOLUTE(.); + } > rtc_reserved_seg + + _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start; + ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)), + "RTC reserved segment data does not fit.") + + /* Get size of rtc slow data based on rtc_data_location alias */ + _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) + ? (_rtc_force_slow_end - _rtc_data_start) + : (_rtc_force_slow_end - _rtc_force_slow_start); + + _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) + ? (_rtc_force_fast_end - _rtc_fast_start) + : (_rtc_noinit_end - _rtc_fast_start); + + ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)), + "RTC_SLOW segment data does not fit.") + + ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)), + "RTC_FAST segment data does not fit.") + + .iram0.text : + { + _iram_start = ABSOLUTE(.); + +#if CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS + /* Do not move this block! OpenOCD expects this to be at the beginning of IRAM. */ + KEEP(*(.ocd_stub.code)); + KEEP(*(.ocd_stub.tramp)); + . = ALIGN(0x800); + KEEP(*(.ocd_stub.data)); + KEEP(*(.ocd_stub.bss)); + KEEP(*(.ocd_stub.stack)); + KEEP(*(.ocd_stub.params)); + . = ALIGN(0x1000); + KEEP(*(.ocd_stub.scratchmem)); + ASSERT(ABSOLUTE(.) == _iram_start + 0x2000, "openocd stub memory must be ended at _iram_start + 0x2000"); +#endif + + /* Vectors go to start of IRAM */ + ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); + KEEP(*(.exception_vectors_table.text)); + KEEP(*(.exception_vectors.text)); + + ALIGNED_SYMBOL(4, _invalid_pc_placeholder) + + /* Code marked as running out of IRAM */ + _iram_text_start = ABSOLUTE(.); + + *(.iram1 .iram1.*) + + /* parts of RIOT that should run in IRAM */ + *core/*(.literal .text .literal.* .text.*) + *core_lib/*(.literal .text .literal.* .text.*) + *esp_common_periph/flash.*(.literal .text .literal.* .text.*) + *esp_common/thread_arch.*(.literal .text .literal.* .text.*) + *esp_freertos_common/*(.literal .text .literal.* .text.*) + *isrpipe/*(.literal .text .literal.* .text.*) + *stdio/stdio.*(.literal .text .literal.* .text.*) + *stdio_*/stdio*(.literal .text .literal.* .text.*) + *syscalls.*(.literal .text .literal.* .text.*) + *tsrb/*(.literal .text .literal.* .text.*) + + /* parts of ESP-IDF that should run in IRAM */ + /* find components/ -type f -name linker.lf -exec grep "(noflash)" {} \; -print */ + /* find components/ -type f -name linker.lf -exec grep "(noflash_text)" {} \; -print */ + *components/app_trace/app_trace.*(.literal .literal.* .text .text.*) + *components/app_trace/app_trace_util.*(.literal .literal.* .text .text.*) + *components/app_trace/port/port_uart.*(.literal .literal.* .text .text.*) + *components/esp_driver_gptimer/src/gptimer.*(.literal.gptimer_default_isr .text.gptimer_default_isr) + *components/esp_event/default_event_loop.*(.literal.esp_event_isr_post .text.esp_event_isr_post) + *components/esp_event/esp_event.*(.literal.esp_event_isr_post_to .text.esp_event_isr_post_to) + *components/esp_hw_support/cpu.*(.literal.esp_cpu_compare_and_set .text.esp_cpu_compare_and_set) + *components/esp_hw_support/cpu.*(.literal.esp_cpu_reset .text.esp_cpu_reset) + *components/esp_hw_support/cpu.*(.literal.esp_cpu_stall .text.esp_cpu_stall) + *components/esp_hw_support/cpu.*(.literal.esp_cpu_unstall .text.esp_cpu_unstall) + *components/esp_hw_support/cpu.*(.literal.esp_cpu_wait_for_intr .text.esp_cpu_wait_for_intr) + *components/esp_hw_support/esp_memory_utils.*(.literal .literal.* .text .text.*) + *components/esp_hw_support/gdma.*(.literal.gdma_append .text.gdma_append) + *components/esp_hw_support/gdma.*(.literal.gdma_default_rx_isr .text.gdma_default_rx_isr) + *components/esp_hw_support/gdma.*(.literal.gdma_default_tx_isr .text.gdma_default_tx_isr) + *components/esp_hw_support/gdma.*(.literal.gdma_reset .text.gdma_reset) + *components/esp_hw_support/gdma.*(.literal.gdma_start .text.gdma_start) + *components/esp_hw_support/gdma.*(.literal.gdma_stop .text.gdma_stop) + *components/esp_hw_support/mspi_timing_tuning.*(.literal .literal.* .text .text.*) + *components/esp_hw_support/periph_ctrl.*(.literal.periph_module_reset .text.periph_module_reset) + *components/esp_hw_support/*/pmu_sleep.*(.literal .literal.* .text .text.*) + *components/esp_hw_support/*/rtc_clk.*(.literal .literal.* .text .text.*) + *components/esp_hw_support/*/rtc_time.*(.literal .literal.* .text .text.*) + *components/esp_hw_support/*/sar_periph_ctrl.*(.literal.sar_periph_ctrl_power_enable .text.sar_periph_ctrl_power_enable) + *components/esp_hw_support/sleep_console.*(.literal .literal.* .text .text.*) + *components/esp_hw_support/*/systimer.*(.literal .literal.* .text .text.*) + *components/esp_mm/esp_cache.*(.literal .literal.* .text .text.*) + *components/esp_ringbuf/*(.literal .literal.* .text .text.*) + *components/esp_rom/patches/esp_rom_print.*(.literal .literal.* .text .text.*) + *components/esp_rom/patches/esp_rom_spiflash.*(.literal .literal.* .text .text.*) + *components/esp_rom/patches/esp_rom_sys.*(.literal .literal.* .text .text.*) + *components/esp_rom/patches/esp_rom_systimer.*(.literal .literal.* .text .text.*) + *components/esp_rom/patches/esp_rom_tlsf.*(.literal .literal.* .text .text.*) + *components/esp_rom/patches/esp_rom_wdt.*(.literal .literal.* .text .text.*) + *components/esp_system/esp_err.*(.literal .literal.* .text .text.*) + *components/esp_system/esp_system_chip.*(.literal.esp_system_abort .text.esp_system_abort) + *components/esp_system/image_process.*(.literal .literal.* .text .text.*) + *components/esp_system/ubsan.*(.literal .literal.* .text .text.*) + + *libclang_rt.builtins.a:_divsf3.*(.literal .literal.* .text .text.*) + *libclang_rt.builtins.a:restore.*(.literal .literal.* .text .text.*) + *libclang_rt.builtins.a:save.*(.literal .literal.* .text .text.*) + *libgcc.a:_divsf3.*(.literal .literal.* .text .text.*) + *libgcc.a:lib2funcs.*(.literal .literal.* .text .text.*) + *libgcc.a:save-restore.*(.literal .literal.* .text .text.*) + *libgcov.a:(.literal .literal.* .text .text.*) + + *components/hal/cache_hal.*(.literal .literal.* .text .text.*) + *components/hal/gdma_hal_ahb_v1.*(.literal.gdma_ahb_hal_append .text.gdma_ahb_hal_append) + *components/hal/gdma_hal_ahb_v1.*(.literal.gdma_ahb_hal_clear_intr .text.gdma_ahb_hal_clear_intr) + *components/hal/gdma_hal_ahb_v1.*(.literal.gdma_ahb_hal_get_eof_desc_addr .text.gdma_ahb_hal_get_eof_desc_addr) + *components/hal/gdma_hal_ahb_v1.*(.literal.gdma_ahb_hal_read_intr_status .text.gdma_ahb_hal_read_intr_status) + *components/hal/gdma_hal_ahb_v1.*(.literal.gdma_ahb_hal_reset .text.gdma_ahb_hal_reset) + *components/hal/gdma_hal_ahb_v1.*(.literal.gdma_ahb_hal_start_with_desc .text.gdma_ahb_hal_start_with_desc) + *components/hal/gdma_hal_ahb_v1.*(.literal.gdma_ahb_hal_stop .text.gdma_ahb_hal_stop) + *components/hal/gdma_hal_top.*(.literal.gdma_hal_append .text.gdma_hal_append) + *components/hal/gdma_hal_top.*(.literal.gdma_hal_clear_intr .text.gdma_hal_clear_intr) + *components/hal/gdma_hal_top.*(.literal.gdma_hal_get_eof_desc_addr .text.gdma_hal_get_eof_desc_addr) + *components/hal/gdma_hal_top.*(.literal.gdma_hal_read_intr_status .text.gdma_hal_read_intr_status) + *components/hal/gdma_hal_top.*(.literal.gdma_hal_reset .text.gdma_hal_reset) + *components/hal/gdma_hal_top.*(.literal.gdma_hal_start_with_desc .text.gdma_hal_start_with_desc) + *components/hal/gdma_hal_top.*(.literal.gdma_hal_stop .text.gdma_hal_stop) + *components/hal/gpio_hal.*(.literal.gpio_hal_isolate_in_sleep .text.gpio_hal_isolate_in_sleep) + *components/hal/i2c_hal_iram.*(.literal .literal.* .text .text.*) + *components/hal/ledc_hal_iram.*(.literal .literal.* .text .text.*) + *components/hal/mmu_hal.*(.literal .literal.* .text .text.*) + *components/hal/pmu_hal.*(.literal .literal.* .text .text.*) + *components/hal/spi_flash_encrypt_hal_iram.*(.literal .literal.* .text .text.*) + *components/hal/spi_flash_hal_gpspi.*(.literal .literal.* .text .text.*) + *components/hal/spi_flash_hal_iram.*(.literal .literal.* .text .text.*) + *components/hal/spi_hal_iram.*(.literal .literal.* .text .text.*) + *components/hal/spi_slave_hal_iram.*(.literal .literal.* .text .text.*) + *components/hal/timer_hal.*(.literal.timer_hal_capture_and_get_counter_value .text.timer_hal_capture_and_get_counter_value) + *components/heap/multi_heap.*(.literal._multi_heap_lock .text._multi_heap_lock) + *components/heap/multi_heap.*(.literal._multi_heap_unlock .text._multi_heap_unlock) + *components/heap/multi_heap.*(.literal.multi_heap_aligned_alloc_offs .text.multi_heap_aligned_alloc_offs) + *components/heap/multi_heap.*(.literal.multi_heap_in_rom_init .text.multi_heap_in_rom_init) + + *libieee802154.a:esp_ieee802154_ack.*(.literal.ieee802154_ack_config_pending_bit .text.ieee802154_ack_config_pending_bit) + *libieee802154.a:esp_ieee802154_dev.*(.literal.ieee802154_isr .text.ieee802154_isr) + *libieee802154.a:esp_ieee802154_dev.*(.literal.ieee802154_rx_frame_info_update .text.ieee802154_rx_frame_info_update) + *libieee802154.a:esp_ieee802154_event.*(.literal.ieee802154_inner_energy_detect_done .text.ieee802154_inner_energy_detect_done) + *libieee802154.a:esp_ieee802154_event.*(.literal.ieee802154_inner_enh_ack_generator .text.ieee802154_inner_enh_ack_generator) + *libieee802154.a:esp_ieee802154_event.*(.literal.ieee802154_inner_receive_done .text.ieee802154_inner_receive_done) + *libieee802154.a:esp_ieee802154_event.*(.literal.ieee802154_inner_receive_sfd_done .text.ieee802154_inner_receive_sfd_done) + *libieee802154.a:esp_ieee802154_event.*(.literal.ieee802154_inner_transmit_done .text.ieee802154_inner_transmit_done) + *libieee802154.a:esp_ieee802154_event.*(.literal.ieee802154_inner_transmit_failed .text.ieee802154_inner_transmit_failed) + *libieee802154.a:esp_ieee802154_event.*(.literal.ieee802154_inner_transmit_sfd_done .text.ieee802154_inner_transmit_sfd_done) + *libieee802154.a:esp_ieee802154_frame.*(.literal.ieee802154_frame_get_security_field_len .text.ieee802154_frame_get_security_field_len) + *libieee802154.a:esp_ieee802154_frame.*(.literal.ieee802154_frame_get_security_payload_offset .text.ieee802154_frame_get_security_payload_offset) + *libieee802154.a:esp_ieee802154_frame.*(.literal.ieee802154_frame_get_src_addr .text.ieee802154_frame_get_src_addr) + *libieee802154.a:esp_ieee802154_frame.*(.literal.ieee802154_frame_security_header_offset .text.ieee802154_frame_security_header_offset) + *libieee802154.a:esp_ieee802154_frame.*(.literal.is_dst_panid_present .text.is_dst_panid_present) + *libieee802154.a:esp_ieee802154_frame.*(.literal.is_src_panid_present .text.is_src_panid_present) + *libieee802154.a:esp_ieee802154_pib.*(.literal.ieee802154_pib_get_pending_mode .text.ieee802154_pib_get_pending_mode) + *libieee802154.a:esp_ieee802154_pib.*(.literal.ieee802154_pib_get_rx_when_idle .text.ieee802154_pib_get_rx_when_idle) + *libieee802154.a:esp_ieee802154_sec.*(.literal.ieee802154_sec_update .text.ieee802154_sec_update) + *libieee802154.a:esp_ieee802154_sec.*(.literal.ieee802154_transmit_security_config .text.ieee802154_transmit_security_config) + *libieee802154.a:esp_ieee802154_timer.*(.literal.ieee802154_timer0_set_threshold .text.ieee802154_timer0_set_threshold) + *libieee802154.a:esp_ieee802154_timer.*(.literal.ieee802154_timer0_start .text.ieee802154_timer0_start) + *libieee802154.a:esp_ieee802154_timer.*(.literal.ieee802154_timer0_stop .text.ieee802154_timer0_stop) + *libieee802154.a:esp_ieee802154_timer.*(.literal.ieee802154_timer1_set_threshold .text.ieee802154_timer1_set_threshold) + *libieee802154.a:esp_ieee802154_timer.*(.literal.ieee802154_timer1_start .text.ieee802154_timer1_start) + *libieee802154.a:esp_ieee802154_timer.*(.literal.ieee802154_timer1_stop .text.ieee802154_timer1_stop) + *libieee802154.a:esp_ieee802154_util.*(.literal.ieee802154_etm_channel_clear .text.ieee802154_etm_channel_clear) + + *components/log/*/log_lock.*(.literal .literal.* .text .text.*) + *components/log/*/log_timestamp.*(.literal.esp_log_early_timestamp .text.esp_log_early_timestamp) + *components/log/*/log_timestamp.*(.literal.esp_log_timestamp .text.esp_log_timestamp) + *components/log/*/log_write.*(.literal.esp_log_write .text.esp_log_write) + *components/newlib/abort.*(.literal .literal.* .text .text.*) + *components/newlib/assert.*(.literal .literal.* .text .text.*) + *components/newlib/heap.*(.literal .literal.* .text .text.*) + *components/newlib/stdatomic.*(.literal .literal.* .text .text.*) + + *components/riscv/interrupt.*(.text .text._global_interrupt_handler .text.intr_get_item .text.intr_handler_get_arg) + *components/riscv/vectors.*(.literal .literal.* .text .text.*) + + *librtc.a:(.literal .literal.* .text .text.*) + + *components/soc/lldesc.*(.literal .literal.* .text .text.*) + *components/spi_flash/flash_brownout_hook.*(.literal .literal.* .text .text.*) + *components/spi_flash/memspi_host_driver.*(.literal .literal.* .text .text.*) + *components/spi_flash/spi_flash_chip_boya.*(.literal .literal.* .text .text.*) + *components/spi_flash/spi_flash_chip_gd.*(.literal .literal.* .text .text.*) + *components/spi_flash/spi_flash_chip_generic.*(.literal .literal.* .text .text.*) + *components/spi_flash/spi_flash_chip_issi.*(.literal .literal.* .text .text.*) + *components/spi_flash/spi_flash_chip_mxic.*(.literal .literal.* .text .text.*) + *components/spi_flash/spi_flash_chip_th.*(.literal .literal.* .text .text.*) + *components/spi_flash/spi_flash_chip_winbond.*(.literal .literal.* .text .text.*) + *components/spi_flash/spi_flash_wrap.*(.literal .literal.* .text .text.*) + + } > sram_seg + + /* Marks the end of IRAM code segment */ + .iram0.text_end (NOLOAD) : + { + /* Align the end of code region as per PMP region granularity */ + . = ALIGN(_esp_pmp_align_size); + + ALIGNED_SYMBOL(4, _iram_text_end) + } > sram_seg + + .iram0.data : + { + ALIGNED_SYMBOL(16, _iram_data_start) + + *(.iram.data .iram.data.*) + _coredump_iram_start = ABSOLUTE(.); + *(.iram2.coredump .iram2.coredump.*) + _coredump_iram_end = ABSOLUTE(.); + + _iram_data_end = ABSOLUTE(.); + } > sram_seg + + .iram0.bss (NOLOAD) : + { + ALIGNED_SYMBOL(16, _iram_bss_start) + + *(.iram.bss .iram.bss.*) + + _iram_bss_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(16, _iram_end) + } > sram_seg + + .dram0.data : + { + _data_start = ABSOLUTE(.); + *(.gnu.linkonce.d.*) + *(.data1) + __global_pointer$ = . + 0x800; + *(.sdata) + *(.sdata.*) + KEEP (*(SORT(.xfa.*))) + *(.gnu.linkonce.s.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + + *(EXCLUDE_FILE(*libble_app.a *libbt.a) .data EXCLUDE_FILE(*libble_app.a *libbt.a) .data.*) + *(.dram1 .dram1.*) + _coredump_dram_start = ABSOLUTE(.); + *(.dram2.coredump .dram2.coredump.*) + _coredump_dram_end = ABSOLUTE(.); + *components/app_trace/app_trace.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/app_trace/app_trace_util.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/app_trace/port_uart.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + + . = ALIGN(4); + _bt_controller_data_start = ABSOLUTE(.); + *libble_app.a:(.data .data.*) + . = ALIGN(4); + _bt_controller_data_end = ABSOLUTE(.); + . = ALIGN(4); + _bt_data_start = ABSOLUTE(.); + *libbt.a:(.data .data.*) + . = ALIGN(4); + _bt_data_end = ABSOLUTE(.); + + *components/esp_hw_support/esp_memory_utils.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_hw_support/mspi_timing_tuning.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_hw_support/*/pmu_sleep.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_hw_support/*/rtc_clk.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_hw_support/sleep_console.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_hw_support/*/systimer.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_mm/esp_cache.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_rom/patches/esp_rom_print.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_rom/patches/esp_rom_spiflash.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_rom/patches/esp_rom_sys.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_rom/patches/esp_rom_systimer.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_rom/patches/esp_rom_tlsf.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_rom/patches/esp_rom_wdt.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_system/esp_err.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_system/port/image_process.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/esp_system/ubsan.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + + *libclang_rt.builtins.a:_divsf3.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *libclang_rt.builtins.a:restore.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *libclang_rt.builtins.a:save.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *libgcc.a:_divsf3.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *libgcc.a:save-restore.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *libgcov.a:(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *libg_nano.a:libc_a-mem*(.literal .literal.* .text .text.*) + + *components/hal/cache_hal.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/hal/i2c_hal_iram.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/hal/ledc_hal_iram.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/hal/mmu_hal.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/hal/pmu_hal.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/hal/spi_flash_encrypt_hal_iram.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/hal/spi_flash_hal_gpspi.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/hal/spi_flash_hal_iram.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/hal/spi_hal_iram.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/hal/spi_slave_hal_iram.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/log/*/log_lock.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + + *components/newlib/abort.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/newlib/assert.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/newlib/heap.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/newlib/stdatomic.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + + _nimble_data_start = ABSOLUTE(.); + *libnimble.a:(.data .data.*) + . = ALIGN(4); + _nimble_data_end = ABSOLUTE(.); + + *libphy.a:(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + + *components/soc/lldesc.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/spi_flash/flash_brownout_hook.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/spi_flash/memspi_host_driver.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/spi_flash/spi_flash_chip_boya.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/spi_flash/spi_flash_chip_gd.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/spi_flash/spi_flash_chip_generic.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/spi_flash/spi_flash_chip_issi.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/spi_flash/spi_flash_chip_mxic.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/spi_flash/spi_flash_chip_th.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/spi_flash/spi_flash_chip_winbond.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *components/spi_flash/spi_flash_wrap.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + + _data_end = ABSOLUTE(.); + } > sram_seg + + /** + * This section holds data that should not be initialized at power up. + * The section located in Internal SRAM memory region. The macro _NOINIT + * can be used as attribute to place data into this section. + * See the "esp_attr.h" file for more information. + */ + .noinit (NOLOAD): + { + ALIGNED_SYMBOL(4, _noinit_start) + + *(.noinit .noinit.*) + + ALIGNED_SYMBOL(4, _noinit_end) + } > sram_seg + + /* Shared RAM */ + .dram0.bss (NOLOAD) : + { + ALIGNED_SYMBOL(8, _bss_start) + + /** + * ldgen places all bss-related data to mapping[dram0_bss] + * (See components/esp_system/app.lf). + */ + *(EXCLUDE_FILE(*libble_app.a *libbt.a) .bss EXCLUDE_FILE(*libble_app.a *libbt.a) .bss.*) + *(.dynbss .dynsbss .gnu.linkonce.b .gnu.linkonce.b.* .gnu.linkonce.sb .gnu.linkonce.sb.* .gnu.linkonce.sb2 .gnu.linkonce.sb2.* .sbss .sbss.* .sbss2 .sbss2.* .scommon .share.mem) + *(.ext_ram.bss .ext_ram.bss.*) + *(EXCLUDE_FILE(*libble_app.a *libbt.a) COMMON) + . = ALIGN(4); + _bt_controller_bss_start = ABSOLUTE(.); + *libble_app.a:(.bss .bss.*) + . = ALIGN(4); + _bt_controller_bss_end = ABSOLUTE(.); + . = ALIGN(4); + _bt_controller_common_start = ABSOLUTE(.); + *libble_app.a:(COMMON) + . = ALIGN(4); + _bt_controller_common_end = ABSOLUTE(.); + . = ALIGN(4); + _bt_bss_start = ABSOLUTE(.); + *libbt.a:(.bss .bss.*) + . = ALIGN(4); + _bt_bss_end = ABSOLUTE(.); + . = ALIGN(4); + _bt_common_start = ABSOLUTE(.); + *libbt.a:(COMMON) + . = ALIGN(4); + _bt_common_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(8, _bss_end) + } > sram_seg + + .flash.text : + { + _stext = .; + /** + * Mark the start of flash.text. + * This can be used by the MMU driver to maintain the virtual address. + */ + _instruction_reserved_start = ABSOLUTE(.); + _text_start = ABSOLUTE(.); + + *(.literal .literal.* .text .text.*) + + *(.stub) + *(.gnu.linkonce.t.*) + *(.gnu.warning) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + + /** + * CPU will try to prefetch up to 16 bytes of of instructions. + * This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ + . += _esp_flash_mmap_prefetch_pad_size; + + _text_end = ABSOLUTE(.); + /** + * Mark the flash.text end. + * This can be used for MMU driver to maintain virtual address. + */ + _instruction_reserved_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); + } > default_code_seg + + /** + * 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 = .; + + . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); + + /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ + . = ALIGN(_esp_mmu_page_size) + 0x20; + } > default_rodata_seg + + .flash.appdesc : ALIGN(0x10) + { + /** + * Mark flash.rodata start. + * This can be used for mmu driver to maintain virtual address + */ + _rodata_reserved_start = ABSOLUTE(.); + _rodata_start = ABSOLUTE(.); + + /* !DO NOT PUT ANYTHING BEFORE THIS! */ + + /* Should be the first. App version info. */ + *(.rodata_desc .rodata_desc.*) + /* Should be the second. Custom app version info. */ + *(.rodata_custom_desc .rodata_custom_desc.*) + + /** + * Create an empty gap within this section. Thanks to this, the end of this + * section will match .flash.rodata's begin address. Thus, both sections + * will be merged when creating the final bin image. + */ + . = ALIGN(ALIGNOF(.flash.rodata)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) + + .flash.rodata : ALIGN(0x10) + { + _flash_rodata_start = ABSOLUTE(.); + + *(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*) + *(.rodata_wlog_error .rodata_wlog_error.*) + *(.rodata_wlog_info .rodata_wlog_info.*) + *(.rodata_wlog_warning .rodata_wlog_warning.*) + + KEEP (*(SORT(.roxfa.*))) + + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + /** + * C++ constructor tables. + * + * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. + * + * RISC-V gcc is configured with --enable-initfini-array so it emits + * .init_array section instead. But the init_priority sections will be + * sorted for iteration in ascending order during startup. + * The rest of the init_array sections is sorted for iteration in descending + * order during startup, however. Hence a different section is generated for + * the init_priority functions which is iterated in ascending order during + * startup. The corresponding code can be found in startup.c. + */ + ALIGNED_SYMBOL(4, __init_priority_array_start) + KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) + __init_priority_array_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, __init_array_start) + KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) + __init_array_end = ABSOLUTE(.); + + /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ + ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) + KEEP (*(.reserved_memory_address)) + soc_reserved_memory_region_end = ABSOLUTE(.); + + /* System init functions registered via ESP_SYSTEM_INIT_FN */ + ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) + _esp_system_init_fn_array_end = ABSOLUTE(.); + + _rodata_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(.eh_frame_hdr)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.rodata, .eh_frame_hdr) + + .eh_frame_hdr : + { +#if CONFIG_COMPILER_CXX_EXCEPTIONS || CONFIG_ESP_SYSTEM_USE_EH_FRAME + ALIGNED_SYMBOL(4, __eh_frame_hdr) + + KEEP (*(.eh_frame_hdr)) + + __eh_frame_hdr_end = ABSOLUTE(.); +#endif // CONFIG_COMPILER_CXX_EXCEPTIONS || CONFIG_ESP_SYSTEM_USE_EH_FRAME + + . = ALIGN(ALIGNOF(.eh_frame)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) + + .eh_frame : + { +#if CONFIG_COMPILER_CXX_EXCEPTIONS || CONFIG_ESP_SYSTEM_USE_EH_FRAME + ALIGNED_SYMBOL(4, __eh_frame) + + KEEP (*(.eh_frame)) + /** + * As we are not linking with crtend.o, which includes the CIE terminator + * (see __FRAME_END__ in libgcc sources), it is manually provided here. + */ + LONG(0); + + __eh_frame_end = ABSOLUTE(.); +#endif // CONFIG_COMPILER_CXX_EXCEPTIONS || CONFIG_ESP_SYSTEM_USE_EH_FRAME + + . = ALIGN(ALIGNOF(.flash.tdata)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) + + .flash.tdata : + { + _thread_local_data_start = ABSOLUTE(.); + + *(.tdata .tdata.* .gnu.linkonce.td.*) + + . = ALIGN(ALIGNOF(.flash.tbss)); + _thread_local_data_end = ABSOLUTE(.); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + + .flash.tbss (NOLOAD) : + { + _thread_local_bss_start = ABSOLUTE(.); + + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + + _thread_local_bss_end = ABSOLUTE(.); + } > default_rodata_seg + + /** + * This section contains all the rodata that is not used + * at runtime, helping to avoid an increase in binary size. + */ + .flash.rodata_noload (NOLOAD) : + { + /** + * This symbol marks the end of flash.rodata. It can be utilized by the MMU + * driver to maintain the virtual address. + * NOLOAD rodata may not be included in this section. + */ + _rodata_reserved_end = ADDR(.flash.tbss); + + . = ALIGN(CONFIG_MMU_PAGE_SIZE); + _fp_mmu_start = .; + _fp_mmu_end = . + CONFIG_ESP_FLASHPAGE_CAPACITY; + + _fp_mem_start = . ; + KEEP(*(SORT(.flash_writable.*))) + _fp_mem_end = . ; + . = ALIGN(4096); + _end_fw = . ; + + *(.rodata_wlog_debug .rodata_wlog_debug.*) + *(.rodata_wlog_verbose .rodata_wlog_verbose.*) + } > default_rodata_seg + + /* Marks the end of data, bss and possibly rodata */ + .dram0.heap_start (NOLOAD) : + { + ALIGNED_SYMBOL(16, _heap_start) + _sheap = ABSOLUTE(.); + } > sram_seg + + . = ORIGIN(sram_seg) + LENGTH(sram_seg); + _eheap = ABSOLUTE(.); + +#include "elf_misc.ld.in" +} diff --git a/cpu/esp_common/Makefile.dep b/cpu/esp_common/Makefile.dep index e90aefbd8831..b601a114995f 100644 --- a/cpu/esp_common/Makefile.dep +++ b/cpu/esp_common/Makefile.dep @@ -44,7 +44,9 @@ ifneq (,$(filter esp_wifi_enterprise,$(USEMODULE))) endif ifneq (,$(filter netdev_default,$(USEMODULE))) - ifneq (,$(filter lwip,$(USEMODULE))) + ifeq (esp32h2,$(CPU_FAM)) + # There is no network interface for ESP32-H2 for the moment + else ifneq (,$(filter lwip,$(USEMODULE))) # for lwip, use esp_wifi as default netdev if no other netdev is enabled ifeq (,$(filter esp_eth,$(USEMODULE))) USEMODULE += esp_wifi diff --git a/cpu/esp_common/Makefile.features b/cpu/esp_common/Makefile.features index 6180672cddd8..4a203aacda42 100644 --- a/cpu/esp_common/Makefile.features +++ b/cpu/esp_common/Makefile.features @@ -3,10 +3,7 @@ FEATURES_PROVIDED += arch_32bit FEATURES_PROVIDED += arch_esp FEATURES_PROVIDED += cpp -FEATURES_PROVIDED += esp_now FEATURES_PROVIDED += esp_spiffs -FEATURES_PROVIDED += esp_wifi -FEATURES_PROVIDED += esp_wifi_ap FEATURES_PROVIDED += libstdcpp FEATURES_PROVIDED += newlib FEATURES_PROVIDED += periph_cpuid @@ -30,8 +27,17 @@ ifeq (rv32,$(CPU_ARCH)) FEATURES_PROVIDED += arch_esp_riscv endif -# All ESP* MCUs have a peripheral network interface -FEATURES_PROVIDED += netif +ifneq (esp32h2,$(CPU_FAM)) + FEATURES_PROVIDED += esp_now + FEATURES_PROVIDED += esp_spiffs + FEATURES_PROVIDED += esp_wifi + FEATURES_PROVIDED += esp_wifi_ap +endif + +ifneq (esp32h2,$(CPU_FAM)) + # All ESP* MCUs have a peripheral network interface + FEATURES_PROVIDED += netif +endif FEATURES_CONFLICT += esp_wifi_ap:esp_now FEATURES_CONFLICT_MSG += "ESP_NOW and ESP_WIFI_AP can not be used at the same time." diff --git a/cpu/esp_common/esp-riscv/thread_arch.c b/cpu/esp_common/esp-riscv/thread_arch.c index f6a43b80c450..b5d56f64d19a 100644 --- a/cpu/esp_common/esp-riscv/thread_arch.c +++ b/cpu/esp_common/esp-riscv/thread_arch.c @@ -174,7 +174,7 @@ void IRAM_ATTR thread_yield_isr(void* arg) /* clear the interrupt first */ WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0); /* set the context switch flag (indicates that context has to be switched - is switch on exit from interrupt in rtos_int_exit */ + * on exit from interrupt in rtos_int_exit) */ sched_context_switch_request = 1; } @@ -196,12 +196,13 @@ void IRAM_ATTR thread_yield_higher(void) } else { /* otherwise trigger a software interrupt for context switch */ - WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 1); + WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, SYSTEM_CPU_INTR_FROM_CPU_0); /* small delay of 3-4 instructions required here before we return */ __asm__ volatile ( "nop" ); __asm__ volatile ( "nop" ); __asm__ volatile ( "nop" ); __asm__ volatile ( "nop" ); + __asm__ volatile ( "nop" ); } } diff --git a/cpu/esp_common/periph/i2c_sw.c b/cpu/esp_common/periph/i2c_sw.c index 6fa71cfc2cea..079723c166b3 100644 --- a/cpu/esp_common/periph/i2c_sw.c +++ b/cpu/esp_common/periph/i2c_sw.c @@ -62,7 +62,7 @@ #if defined(CPU_FAM_ESP32) || defined(CPU_FAM_ESP32S2) || defined(CPU_FAM_ESP32S3) #define GPIO_SET(lo, hi, b) if (b < 32) { GPIO.lo = BIT(b); } else { GPIO.hi.val = BIT(b-32); } #define GPIO_GET(lo, hi, b) ((b < 32) ? GPIO.lo & BIT(b) : GPIO.hi.val & BIT(b-32)) -#elif defined(CPU_FAM_ESP32C3) +#elif defined(CPU_FAM_ESP32C3) || defined(CPU_FAM_ESP32H2) #define GPIO_SET(lo, hi, b) GPIO.lo.val = BIT(b) #define GPIO_GET(lo, hi, b) GPIO.lo.val & BIT(b) #else @@ -119,6 +119,8 @@ static _i2c_bus_t _i2c_bus[I2C_NUMOF] = {}; #define I2C_CLK_CAL 62 /* clock calibration offset */ #elif defined(CPU_FAM_ESP32C3) #define I2C_CLK_CAL 32 /* clock calibration offset */ +#elif defined(CPU_FAM_ESP32H2) +#define I2C_CLK_CAL 24 /* clock calibration offset */ #elif defined(CPU_FAM_ESP32S2) #define I2C_CLK_CAL 82 /* clock calibration offset */ #elif defined(CPU_FAM_ESP32S3) diff --git a/cpu/esp_common/periph/uart.c b/cpu/esp_common/periph/uart.c index a515509b8f7c..27e22819e087 100644 --- a/cpu/esp_common/periph/uart.c +++ b/cpu/esp_common/periph/uart.c @@ -63,6 +63,7 @@ #include "esp_private/periph_ctrl.h" #include "esp_rom_gpio.h" #include "esp_rom_uart.h" +#include "hal/clk_tree_ll.h" #include "hal/uart_ll.h" #include "soc/clk_tree_defs.h" #include "soc/gpio_reg.h" @@ -73,14 +74,21 @@ #include "soc/soc_caps.h" #include "soc/uart_pins.h" +#undef UART_CLK_FREQ + +#if CPU_FAM_ESP32 || CPU_FAM_ESP32S2 || CPU_FAM_ESP32S3 || CPU_FAM_ESP32C3 /* UART_CLK_FREQ corresponds to APB_CLK_FREQ for ESP32, ESP32-S2, ESP32-S3, * ESP32-C2 and ESP32-C3, which is a fixed frequency of 80 MHz. However, * this only applies to CPU clock frequencies of 80 MHz and above. * For lower CPU clock frequencies, the APB clock corresponds to the CPU clock * frequency. Therefore, we need to determine the actual UART clock frequency * from the actual APB clock frequency. */ -#undef UART_CLK_FREQ #define UART_CLK_FREQ rtc_clk_apb_freq_get() /* APB_CLK is used */ +#elif CPU_FAM_ESP32H2 +#define UART_CLK_FREQ (CLK_LL_PLL_48M_FREQ_MHZ * MHZ) /* PLL_F48M_CLK is used */ +#else +#error "Platform implementation is missing" +#endif #endif /* defined(CPU_ESP8266) */ diff --git a/cpu/esp_common/syscalls.c b/cpu/esp_common/syscalls.c index a1a5cea8488a..13e2ae441f6b 100644 --- a/cpu/esp_common/syscalls.c +++ b/cpu/esp_common/syscalls.c @@ -460,6 +460,21 @@ void heap_caps_init(void) { } +void* heap_caps_aligned_alloc(size_t alignment, size_t size, uint32_t caps) +{ + (void)caps; + + uintptr_t raw_addr = (uintptr_t)malloc(size + alignment - 1); + uintptr_t aligned_addr = (raw_addr + (alignment - 1)) & ~(alignment - 1); + + if (!raw_addr) { + return NULL; + } + + assert(raw_addr == aligned_addr); + return (void *)aligned_addr; +} + extern uint8_t _eheap; /* end of heap (defined in ld script) */ extern uint8_t _sheap; /* start of heap (defined in ld script) */ diff --git a/dist/tools/esptools/export.sh b/dist/tools/esptools/export.sh index 86788882e22b..defd527abf40 100755 --- a/dist/tools/esptools/export.sh +++ b/dist/tools/esptools/export.sh @@ -26,7 +26,7 @@ export_arch() TARGET_ARCH="xtensa-esp-elf" ESP_GCC_RELEASE="${ESP32_GCC_RELEASE}" ;; - esp32c3) + esp32c3|esp32h2) TARGET_ARCH="riscv32-esp-elf" ESP_GCC_RELEASE="${ESP32_GCC_RELEASE}" ;; @@ -36,7 +36,7 @@ export_arch() esac TOOLS_DIR="${TOOLS_PATH}/${TARGET_ARCH}/${ESP_GCC_RELEASE}/${TARGET_ARCH}" - TOOLS_DIR_IN_PATH="$(echo $PATH | grep "${TOOLS_DIR}")" + TOOLS_DIR_IN_PATH=$(echo "$PATH" | grep "${TOOLS_DIR}") if [ ! -e "${TOOLS_DIR}" ]; then echo "${TOOLS_DIR} does not exist - please run" @@ -44,7 +44,7 @@ export_arch() return fi - if [ -z "${TOOLS_DIR_IN_PATH}" ]; then + if [ -e "${TOOLS_DIR}" ] && [ -z "${TOOLS_DIR_IN_PATH}" ]; then echo "Extending PATH by ${TOOLS_DIR}/bin" export PATH="${TOOLS_DIR}/bin:${PATH}" fi @@ -58,7 +58,7 @@ export_arch() export_openocd() { TOOLS_DIR="${TOOLS_PATH}/openocd-esp32/${ESP32_OPENOCD_VERSION}" - TOOLS_DIR_IN_PATH="$(echo $PATH | grep "${TOOLS_DIR}")" + TOOLS_DIR_IN_PATH=$(echo "$PATH" | grep "${TOOLS_DIR}") OPENOCD_DIR="${TOOLS_DIR}/openocd-esp32" if [ -e "${OPENOCD_DIR}" ] && [ -z "${TOOLS_DIR_IN_PATH}" ]; then @@ -81,7 +81,6 @@ export_qemu() # map different platform names to a unique OS name case "${PLATFORM}" in linux-amd64|linux64|Linux-x86_64|FreeBSD-amd64) - OS="linux-amd64" ;; *) echo "error: OS architecture ${PLATFORM} not supported" @@ -99,7 +98,7 @@ export_qemu() esac # qemu version depends on the version of ncurses lib - if [ "$(ldconfig -p | grep -c libncursesw.so.6)" == "0" ]; then + if [ "$(ldconfig -p | grep -c libncursesw.so.6)" = "0" ]; then ESP32_QEMU_VERSION="esp-develop-20210220" fi @@ -108,7 +107,7 @@ export_qemu() fi TOOLS_DIR="${TOOLS_PATH}/${QEMU_ARCH}/${ESP32_QEMU_VERSION}/qemu" - TOOLS_DIR_IN_PATH="$(echo $PATH | grep "${TOOLS_DIR}")" + TOOLS_DIR_IN_PATH=$(echo "$PATH" | grep "${TOOLS_DIR}") if [ -e "${TOOLS_DIR}" ] && [ -z "${TOOLS_DIR_IN_PATH}" ]; then echo "Extending PATH by ${TOOLS_DIR}/bin" @@ -133,7 +132,7 @@ export_gdb() esac TOOLS_DIR="${TOOLS_PATH}/${GDB_ARCH}/${GDB_VERSION}/${GDB_ARCH}" - TOOLS_DIR_IN_PATH="$(echo $PATH | grep "${TOOLS_DIR}")" + TOOLS_DIR_IN_PATH=$(echo "$PATH" | grep "${TOOLS_DIR}") if [ -e "${TOOLS_DIR}" ] && [ -z "${TOOLS_DIR_IN_PATH}" ]; then echo "Extending PATH by ${TOOLS_DIR}/bin" @@ -147,10 +146,11 @@ if [ -z "$1" ]; then echo "Usage: export.sh " echo " export.sh gdb " echo " export.sh qemu " - echo " = all | esp8266 | esp32 | esp32c3 | esp32s2 | esp32s3 | gdb | openocd | qemu" + echo " = all | gdb | openocd | qemu |" + echo " esp8266 | esp32 | esp32c3 | esp32h2 | esp32s2 | esp32s3" echo " = xtensa | riscv" elif [ "$1" = "all" ]; then - ARCH_ALL="esp8266 esp32 esp32c3 esp32s2 esp32s3" + ARCH_ALL="esp8266 esp32 esp32c3 esp32h2 esp32s2 esp32s3" for arch in ${ARCH_ALL}; do export_arch "$arch" done @@ -172,7 +172,7 @@ elif [ "$1" = "openocd" ]; then elif [ "$1" = "qemu" ]; then export_qemu $2 else - export_arch $1 + export_arch "$1" fi unset ESP32_GCC_RELEASE diff --git a/dist/tools/esptools/install.sh b/dist/tools/esptools/install.sh index f9d2ef3fc27c..8a28f7a21411 100755 --- a/dist/tools/esptools/install.sh +++ b/dist/tools/esptools/install.sh @@ -1,7 +1,6 @@ #!/bin/sh ESP32_GCC_RELEASE="esp-14.2.0_20241119" -ESP32_GCC_VERSION_DIR="14.2.0" ESP32_GCC_VERSION_DOWNLOAD="14.2.0_20241119" ESP8266_GCC_RELEASE="esp-5.2.0_20191018" @@ -99,7 +98,7 @@ install_arch() TARGET_ARCH="xtensa-esp-elf" ESP_GCC_RELEASE="${ESP32_GCC_RELEASE}" ;; - esp32c3) + esp32c3|esp32h2) TARGET_ARCH="riscv32-esp-elf" ESP_GCC_RELEASE="${ESP32_GCC_RELEASE}" ;; @@ -111,7 +110,7 @@ install_arch() TOOLS_DIR="${TOOLS_PATH}/${TARGET_ARCH}/${ESP_GCC_RELEASE}" if [ "$1" = "esp8266" ]; then - git clone https://github.com/gschorcht/xtensa-esp8266-elf ${TOOLS_DIR}/${TARGET_ARCH} + git clone https://github.com/gschorcht/xtensa-esp8266-elf "${TOOLS_DIR}/${TARGET_ARCH}" else URL_PATH="https://github.com/espressif/crosstool-NG/releases/download" URL_TGZ="${TARGET_ARCH}-${ESP32_GCC_VERSION_DOWNLOAD}-${OS}.tar.xz" @@ -236,11 +235,12 @@ if [ -z "$1" ]; then echo "Usage: install.sh " echo " install.sh gdb " echo " install.sh qemu " - echo " = all | esp8266 | esp32 | esp32c3 | esp32s2 | esp32s3 | gdb | openocd | qemu" + echo " = all | esptool | gdb | openocd | qemu |" + echo " esp8266 | esp32 | esp32c3 | esp32h2 | esp32s2 | esp32s3" echo " = xtensa | riscv" exit 1 elif [ "$1" = "all" ]; then - ARCH_ALL="esp8266 esp32 esp32c3 esp32s2 esp32s3" + ARCH_ALL="esp8266 esp32 esp32c3 esp32h2 esp32s2 esp32s3" for arch in ${ARCH_ALL}; do install_arch "$arch" done diff --git a/examples/networking/mqtt/paho-mqtt/Makefile.board.dep b/examples/networking/mqtt/paho-mqtt/Makefile.board.dep index 4c5dac29cd42..6897ee2bc9e0 100644 --- a/examples/networking/mqtt/paho-mqtt/Makefile.board.dep +++ b/examples/networking/mqtt/paho-mqtt/Makefile.board.dep @@ -1,7 +1,10 @@ # Put board specific dependencies here ifneq (,$(filter arch_esp,$(FEATURES_USED))) - USEMODULE += esp_wifi + ifneq (esp32h2,$(CPU_FAM)) + # ESP32-H2 doesn't have WiFi module + USEMODULE += esp_wifi + endif endif ifneq (,$(filter native native32 native64,$(BOARD))) diff --git a/pkg/esp32_sdk/patches/0031-bootloader-changes-for-esp32h2-to-compile-in-RIOT-OS.patch b/pkg/esp32_sdk/patches/0031-bootloader-changes-for-esp32h2-to-compile-in-RIOT-OS.patch new file mode 100644 index 000000000000..91f88e83c852 --- /dev/null +++ b/pkg/esp32_sdk/patches/0031-bootloader-changes-for-esp32h2-to-compile-in-RIOT-OS.patch @@ -0,0 +1,84 @@ +From b9d969975894bb635eba5caf9f7e6b00ef1258f8 Mon Sep 17 00:00:00 2001 +From: Gunar Schorcht +Date: Tue, 25 Mar 2025 14:11:15 +0100 +Subject: [PATCH 31/33] bootloader: changes for esp32h2 to compile in RIOT-OS + +--- + .../subproject/main/ld/esp32h2/bootloader.ld | 58 +++++++++---------- + 1 file changed, 29 insertions(+), 29 deletions(-) + +diff --git a/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld b/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld +index 9ae2a74d8c..ada09d06bb 100644 +--- a/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld ++++ b/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld +@@ -60,38 +60,38 @@ SECTIONS + _loader_text_start = ABSOLUTE(.); + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ +- *liblog.a:(.literal .text .literal.* .text.*) ++ *components/log/*(.literal .text .literal.* .text.*) + /* we use either libgcc or compiler-rt, so put similar entries for them here */ + *libgcc.a:(.literal .text .literal.* .text.*) + *libclang_rt.builtins.a:(.literal .text .literal.* .text.*) +- *libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable) +- *libbootloader_support.a:bootloader_efuse.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*) +- *libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) +- *libmicro-ecc.a:*.*(.literal .text .literal.* .text.*) +- *libspi_flash.a:*.*(.literal .text .literal.* .text.*) +- *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) +- *libhal.a:mmu_hal.*(.literal .text .literal.* .text.*) +- *libhal.a:cache_hal.*(.literal .text .literal.* .text.*) +- *libhal.a:efuse_hal.*(.literal .text .literal.* .text.*) +- *libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*) +- *libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*) +- *libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*) +- *libefuse.a:*.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/bootloader_clock_loader.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/bootloader_common_loader.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/bootloader_flash.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/bootloader_random.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable) ++ *components/bootloader_support/*/bootloader_efuse.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/bootloader_utility.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/bootloader_sha.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/bootloader_console_loader.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/bootloader_panic.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/bootloader_soc.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/esp_image_format.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/flash_encrypt.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/flash_encryption_secure_features.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/flash_partitions.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/secure_boot.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/secure_boot_secure_features.*(.literal .text .literal.* .text.*) ++ *components/bootloader_support/*/secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) ++ *components/*/micro-ecc/*(.literal .text .literal.* .text.*) ++ *components/spi_flash/*(.literal .text .literal.* .text.*) ++ *components/hal/wdt_hal_iram.*(.literal .text .literal.* .text.*) ++ *components/hal/mmu_hal.*(.literal .text .literal.* .text.*) ++ *components/hal/cache_hal.*(.literal .text .literal.* .text.*) ++ *components/hal/efuse_hal.*(.literal .text .literal.* .text.*) ++ *components/esp_hw_support/*/rtc_clk.*(.literal .text .literal.* .text.*) ++ *components/esp_hw_support/*/rtc_time.*(.literal .text .literal.* .text.*) ++ *components/esp_hw_support/regi2c_ctrl.*(.literal .text .literal.* .text.*) ++ *components/efuse/*(.literal .text .literal.* .text.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) +-- +2.34.1 + diff --git a/pkg/esp32_sdk/patches/0032-hal-esp32h2-gspi_flash_ll-fix-signed-unsigned-compar.patch b/pkg/esp32_sdk/patches/0032-hal-esp32h2-gspi_flash_ll-fix-signed-unsigned-compar.patch new file mode 100644 index 000000000000..2a56779fa6eb --- /dev/null +++ b/pkg/esp32_sdk/patches/0032-hal-esp32h2-gspi_flash_ll-fix-signed-unsigned-compar.patch @@ -0,0 +1,26 @@ +From 747d003d74b88b64e721e3fe9512ca2ffeaa02ee Mon Sep 17 00:00:00 2001 +From: Gunar Schorcht +Date: Mon, 31 Mar 2025 09:07:03 +0200 +Subject: [PATCH 32/33] hal/esp32h2/gspi_flash_ll: fix signed/unsigned + comparison + +--- + components/hal/esp32h2/include/hal/gpspi_flash_ll.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/components/hal/esp32h2/include/hal/gpspi_flash_ll.h b/components/hal/esp32h2/include/hal/gpspi_flash_ll.h +index 124863b7d6..4d6a5fede7 100644 +--- a/components/hal/esp32h2/include/hal/gpspi_flash_ll.h ++++ b/components/hal/esp32h2/include/hal/gpspi_flash_ll.h +@@ -85,7 +85,7 @@ static inline void gpspi_flash_ll_get_buffer_data(spi_dev_t *dev, void *buffer, + } else { + // Otherwise, slow(er) path copies word by word + int copy_len = read_len; +- for (int i = 0; i < (read_len + 3) / 4; i++) { ++ for (uint32_t i = 0; i < (read_len + 3) / 4; i++) { + int word_len = MIN(sizeof(uint32_t), copy_len); + uint32_t word = dev->data_buf[i].buf0; + memcpy(buffer, &word, word_len); +-- +2.34.1 + diff --git a/pkg/esp32_sdk/patches/0033-hal-esp32h2-spimem_flash_ll-fix-signed-unsigned-comp.patch b/pkg/esp32_sdk/patches/0033-hal-esp32h2-spimem_flash_ll-fix-signed-unsigned-comp.patch new file mode 100644 index 000000000000..61b2a3d208ea --- /dev/null +++ b/pkg/esp32_sdk/patches/0033-hal-esp32h2-spimem_flash_ll-fix-signed-unsigned-comp.patch @@ -0,0 +1,26 @@ +From 2da348f096d96e8fcd3f6263c2ba87bd6f77062f Mon Sep 17 00:00:00 2001 +From: Gunar Schorcht +Date: Mon, 31 Mar 2025 09:18:33 +0200 +Subject: [PATCH 33/33] hal/esp32h2/spimem_flash_ll: fix signed/unsigned + comparison + +--- + components/hal/esp32h2/include/hal/spimem_flash_ll.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/components/hal/esp32h2/include/hal/spimem_flash_ll.h b/components/hal/esp32h2/include/hal/spimem_flash_ll.h +index caf551023f..a0906434fb 100644 +--- a/components/hal/esp32h2/include/hal/spimem_flash_ll.h ++++ b/components/hal/esp32h2/include/hal/spimem_flash_ll.h +@@ -334,7 +334,7 @@ static inline void spimem_flash_ll_get_buffer_data(spi_mem_dev_t *dev, void *buf + } else { + // Otherwise, slow(er) path copies word by word + int copy_len = read_len; +- for (int i = 0; i < (read_len + 3) / 4; i++) { ++ for (uint32_t i = 0; i < (read_len + 3) / 4; i++) { + int word_len = MIN(sizeof(uint32_t), copy_len); + uint32_t word = dev->data_buf[i]; + memcpy(buffer, &word, word_len); +-- +2.34.1 +