diff --git a/cpu/esp32/periph/adc_arch_esp32h2.c b/cpu/esp32/periph/adc_arch_esp32h2.c new file mode 100644 index 0000000000..8cd97384fc --- /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 f327da73be..0749241176 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 294b8a37ff..6f8c727c95 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 0000000000..aba1f97971 --- /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 2faa14d860..afcc28c80f 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 fa4d8312a9..d7e80ec728 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 0a4b976fac..55f0c0ee28 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 5bd112038a..fa60d04a96 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 a4b0400645..c0ce0ca6fa 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 4e94a9b24b..f7d00cad3e 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 };