1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-24 22:13:52 +01:00

cpu/esp32/periph: add ESP32-H2 support

This commit is contained in:
Gunar Schorcht 2025-04-18 19:00:05 +02:00
parent 3019928ccc
commit 06f0c2cf09
10 changed files with 381 additions and 52 deletions

View File

@ -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 <gunar@schorcht.net>
*
* @}
*/
#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");

View File

@ -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 */

View File

@ -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

View File

@ -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 <gunar@schorcht.net>
* @}
*/
#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 */
};

View File

@ -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();

View File

@ -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 */

View File

@ -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 */

View File

@ -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,

View File

@ -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)

View File

@ -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
};