Compatibility with ESP-IDF 5.4.x, 5.5.x and master (#541)

* Compatibility with ESP-IDF 4.x, 5.x and master

* Run main CI againzst released ESP-IDF
This commit is contained in:
ivmarkov 2025-08-13 09:02:33 +03:00 committed by GitHub
parent 1eba80d6ae
commit a67bf2fd3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 160 additions and 84 deletions

View File

@ -24,7 +24,7 @@ rustflags = ["--cfg", "espidf_time64"]
[env]
ESP_IDF_SDKCONFIG_DEFAULTS = ".github/configs/sdkconfig.defaults"
ESP_IDF_VERSION = "v5.3.2"
ESP_IDF_VERSION = "v5.4.2"
[unstable]
build-std = ["std", "panic_abort"]

View File

@ -27,9 +27,11 @@ jobs:
- xtensa-esp32s2-espidf
- xtensa-esp32s3-espidf
idf-version:
- release/v4.4
- release/v5.2
- v5.1.6
- v5.2.5
- v5.3.3
- v5.4.2
- v5.5
steps:
- name: Setup | Checkout
uses: actions/checkout@v3

View File

@ -5,12 +5,20 @@
//! If your board doesn't have on-board LEDs don't forget to add an appropriate resistor.
//!
use esp_idf_hal::gpio::*;
use esp_idf_hal::peripherals::Peripherals;
use esp_idf_hal::task::*;
use esp_idf_hal::timer::*;
#![allow(unexpected_cfgs)]
#[cfg(esp_idf_version_at_least_6_0_0)]
fn main() {
panic!("Timer not yet available when building against ESP-IDF 6.0+")
}
#[cfg(not(esp_idf_version_at_least_6_0_0))]
fn main() -> anyhow::Result<()> {
use esp_idf_hal::gpio::*;
use esp_idf_hal::peripherals::Peripherals;
use esp_idf_hal::task::*;
use esp_idf_hal::timer::*;
esp_idf_hal::sys::link_patches();
let peripherals = Peripherals::take()?;

View File

@ -1,9 +1,16 @@
use esp_idf_hal::peripherals::*;
use esp_idf_hal::sys::EspError;
use esp_idf_hal::task::*;
use esp_idf_hal::timer::*;
#![allow(unexpected_cfgs)]
#[cfg(esp_idf_version_at_least_6_0_0)]
fn main() {
panic!("Timer not yet available when building against ESP-IDF 6.0+")
}
#[cfg(not(esp_idf_version_at_least_6_0_0))]
fn main() -> Result<(), esp_idf_hal::sys::EspError> {
use esp_idf_hal::peripherals::*;
use esp_idf_hal::task::*;
use esp_idf_hal::timer::*;
fn main() -> Result<(), EspError> {
// It is necessary to call this function once. Otherwise some patches to the runtime
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
esp_idf_hal::sys::link_patches();

View File

@ -1,11 +1,18 @@
use std::num::NonZeroU32;
#![allow(unexpected_cfgs)]
use esp_idf_hal::peripherals::*;
use esp_idf_hal::sys::EspError;
use esp_idf_hal::task::notification::Notification;
use esp_idf_hal::timer::*;
#[cfg(esp_idf_version_at_least_6_0_0)]
fn main() {
panic!("Timer not yet available when building against ESP-IDF 6.0+")
}
#[cfg(not(esp_idf_version_at_least_6_0_0))]
fn main() -> Result<(), esp_idf_hal::sys::EspError> {
use std::num::NonZeroU32;
use esp_idf_hal::peripherals::*;
use esp_idf_hal::task::notification::Notification;
use esp_idf_hal::timer::*;
fn main() -> Result<(), EspError> {
// It is necessary to call this function once. Otherwise some patches to the runtime
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
esp_idf_hal::sys::link_patches();

View File

@ -27,11 +27,22 @@ pub trait Adc: Send {
// NOTE: Will be changed to an enum once C-style enums are usable as const generics
pub mod attenuation {
pub use esp_idf_sys::{
adc_atten_t, adc_atten_t_ADC_ATTEN_DB_0, adc_atten_t_ADC_ATTEN_DB_11,
adc_atten_t_ADC_ATTEN_DB_11 as adc_atten_t_ADC_ATTEN_DB_12, adc_atten_t_ADC_ATTEN_DB_2_5,
adc_atten_t, adc_atten_t_ADC_ATTEN_DB_0, adc_atten_t_ADC_ATTEN_DB_2_5,
adc_atten_t_ADC_ATTEN_DB_6,
};
#[cfg(esp_idf_version_at_least_6_0_0)]
pub use esp_idf_sys::adc_atten_t_ADC_ATTEN_DB_12;
#[cfg(esp_idf_version_at_least_6_0_0)]
#[allow(non_upper_case_globals)]
pub const adc_atten_t_ADC_ATTEN_DB_11: adc_atten_t = adc_atten_t_ADC_ATTEN_DB_12;
#[cfg(not(esp_idf_version_at_least_6_0_0))]
pub use esp_idf_sys::adc_atten_t_ADC_ATTEN_DB_11;
#[cfg(not(esp_idf_version_at_least_6_0_0))]
#[allow(non_upper_case_globals)]
pub const adc_atten_t_ADC_ATTEN_DB_12: adc_atten_t = adc_atten_t_ADC_ATTEN_DB_11;
pub const NONE: adc_atten_t = adc_atten_t_ADC_ATTEN_DB_0;
pub const DB_2_5: adc_atten_t = adc_atten_t_ADC_ATTEN_DB_2_5;
pub const DB_6: adc_atten_t = adc_atten_t_ADC_ATTEN_DB_6;
@ -73,6 +84,25 @@ impl Default for Resolution {
}
}
#[cfg(esp_idf_version_at_least_6_0_0)]
impl From<Resolution> for adc_bitwidth_t {
fn from(resolution: Resolution) -> Self {
match resolution {
#[cfg(esp32)]
Resolution::Resolution9Bit => adc_bitwidth_t_ADC_BITWIDTH_9,
#[cfg(esp32)]
Resolution::Resolution10Bit => adc_bitwidth_t_ADC_BITWIDTH_10,
#[cfg(esp32)]
Resolution::Resolution11Bit => adc_bitwidth_t_ADC_BITWIDTH_11,
#[cfg(any(esp32, esp32s3, esp32c3, esp32c2, esp32h2, esp32c5, esp32c6, esp32p4))]
Resolution::Resolution12Bit => adc_bitwidth_t_ADC_BITWIDTH_12,
#[cfg(esp32s2)]
Resolution::Resolution13Bit => adc_bitwidth_t_ADC_BITWIDTH_13,
}
}
}
#[cfg(not(esp_idf_version_at_least_6_0_0))]
impl From<Resolution> for adc_bits_width_t {
fn from(resolution: Resolution) -> Self {
match resolution {
@ -464,19 +494,19 @@ impl DirectConverter {
#[cfg(any(esp32c3, esp32s2, esp32c2, esp32h2, esp32c5, esp32c6, esp32p4))]
let mv = match attenuation {
adc_atten_t_ADC_ATTEN_DB_0 => 750,
adc_atten_t_ADC_ATTEN_DB_2_5 => 1050,
adc_atten_t_ADC_ATTEN_DB_6 => 1300,
adc_atten_t_ADC_ATTEN_DB_11 => 2500,
attenuation::NONE => 750,
attenuation::DB_2_5 => 1050,
attenuation::DB_6 => 1300,
attenuation::DB_12 => 2500,
other => panic!("Unknown attenuation: {other}"),
};
#[cfg(esp32s3)]
let mv = match attenuation {
adc_atten_t_ADC_ATTEN_DB_0 => 950,
adc_atten_t_ADC_ATTEN_DB_2_5 => 1250,
adc_atten_t_ADC_ATTEN_DB_6 => 1750,
adc_atten_t_ADC_ATTEN_DB_11 => 3100,
attenuation::NONE => 950,
attenuation::DB_2_5 => 1250,
attenuation::DB_6 => 1750,
attenuation::DB_12 => 3100,
other => panic!("Unknown attenuation: {other}"),
};
@ -609,7 +639,8 @@ pub mod oneshot {
unit_id: u8,
chan: adc_channel_t,
atten: adc_atten_t,
bitwidth: adc_bits_width_t,
#[cfg(esp_idf_version_at_least_6_0_0)] bitwidth: adc_bitwidth_t,
#[cfg(not(esp_idf_version_at_least_6_0_0))] bitwidth: adc_bits_width_t,
calibration: config::Calibration,
) -> Result<Self, EspError> {
match calibration {
@ -634,11 +665,7 @@ pub mod oneshot {
// then we wouuld not need the ugliness for the esp32c6
let cal_config = adc_cali_curve_fitting_config_t {
unit_id: unit_id as u32,
#[cfg(all(
esp_idf_version_major = "5",
not(esp_idf_version_minor = "0"),
not(all(esp_idf_version_minor = "1", esp_idf_version_patch = "0"))
))]
#[cfg(esp_idf_version_at_least_5_1_1)]
chan,
atten,
bitwidth,

View File

@ -157,24 +157,7 @@ pub mod config {
tseg_1: timing_segment_1,
tseg_2: timing_segment_2,
sjw: synchronization_jump_width,
#[cfg(any(
esp_idf_version_major = "4",
esp_idf_version = "5.0",
esp_idf_version = "5.1",
esp_idf_version = "5.2",
esp_idf_version = "5.3",
esp_idf_version = "5.4"
))]
triple_sampling,
#[cfg(not(any(
esp_idf_version_major = "4",
esp_idf_version = "5.0",
esp_idf_version = "5.1",
esp_idf_version = "5.2",
esp_idf_version = "5.3",
esp_idf_version = "5.4"
)))]
__bindgen_anon_1: twai_timing_config_t__bindgen_ty_1 { triple_sampling },
..Default::default()
},
}

View File

@ -26,9 +26,14 @@ const APB_TICK_PERIOD_NS: u32 = 1_000_000_000 / 80_000_000;
const XTAL_TICK_PERIOD_NS: u32 = 1_000_000_000 / 40_000_000;
#[cfg(all(esp32c2, esp_idf_xtal_freq_26))]
const XTAL_TICK_PERIOD_NS: u32 = 1_000_000_000 / 26_000_000;
#[cfg(not(esp_idf_version_at_least_6_0_0))]
#[cfg(not(any(esp32, esp32s2, esp32c2)))]
const XTAL_TICK_PERIOD_NS: u32 = 1_000_000_000 / XTAL_CLK_FREQ;
// TODO: Below is probably not correct
#[cfg(esp_idf_version_at_least_6_0_0)]
#[cfg(not(any(esp32, esp32s2, esp32c2)))]
const XTAL_TICK_PERIOD_NS: u32 = 1_000_000_000 / 40_000_000;
#[derive(Copy, Clone, Debug)]
pub struct APBTickType(::core::ffi::c_int);
impl From<Duration> for APBTickType {

View File

@ -119,7 +119,7 @@ pub(super) mod config {
/// The division from MCLK to BCLK. This is used only in I2S target (slave) mode. This should not be smaller
/// than TDM_BCLK_DIV_MIN (8). Increase this field if the target device is not able to transmit data in time.
#[cfg(all(esp_idf_version_major = "5", not(esp_idf_version_minor = "0")))]
#[cfg(esp_idf_version_at_least_5_1_0)]
bclk_div: u32,
}
@ -129,10 +129,7 @@ pub(super) mod config {
impl TdmClkConfig {
/// Create a TDM clock configuration with the specified rate (in Hz), clock source, and MCLK multiple of
/// the sample rate.
#[cfg(any(
esp_idf_version_major = "4",
all(esp_idf_version_major = "5", esp_idf_version_minor = "0")
))]
#[cfg(not(esp_idf_version_at_least_5_1_0))]
#[inline(always)]
pub fn new(sample_rate_hz: u32, clk_src: ClockSource, mclk_multiple: MclkMultiple) -> Self {
Self {
@ -144,7 +141,7 @@ pub(super) mod config {
/// Create a TDM clock configuration with the specified rate (in Hz), clock source, and MCLK multiple of
/// the sample rate.
#[cfg(all(esp_idf_version_major = "5", not(esp_idf_version_minor = "0")))]
#[cfg(esp_idf_version_at_least_5_1_0)]
#[inline(always)]
pub fn new(sample_rate_hz: u32, clk_src: ClockSource, mclk_multiple: MclkMultiple) -> Self {
Self {
@ -161,10 +158,7 @@ pub(super) mod config {
/// # Note
/// Set the mclk_multiple to [`MclkMultiple::M384`] when using 24-bit data width. Otherwise, the sample rate
/// might be imprecise since the BCLK division is not an integer.
#[cfg(any(
esp_idf_version_major = "4",
all(esp_idf_version_major = "5", esp_idf_version_minor = "0")
))]
#[cfg(not(esp_idf_version_at_least_5_1_0))]
#[inline(always)]
pub fn from_sample_rate_hz(rate: u32) -> Self {
Self {
@ -180,7 +174,7 @@ pub(super) mod config {
/// # Note
/// Set the mclk_multiple to [MclkMultiple::M384] when using 24-bit data width. Otherwise, the sample rate
/// might be imprecise since the BCLK division is not an integer.
#[cfg(all(esp_idf_version_major = "5", not(esp_idf_version_minor = "0")))]
#[cfg(esp_idf_version_at_least_5_1_0)]
#[inline(always)]
pub fn from_sample_rate_hz(rate: u32) -> Self {
Self {
@ -206,7 +200,7 @@ pub(super) mod config {
}
/// Set the MCLK to BCLK division on this TDM clock configuration.
#[cfg(all(esp_idf_version_major = "5", not(esp_idf_version_minor = "0")))]
#[cfg(esp_idf_version_at_least_5_1_0)]
#[inline(always)]
pub fn bclk_div(mut self, bclk_div: u32) -> Self {
self.bclk_div = bclk_div;
@ -214,7 +208,7 @@ pub(super) mod config {
}
/// Convert to the ESP-IDF SDK `i2s_tdm_clk_config_t` representation.
#[cfg(all(esp_idf_version_major = "5", esp_idf_version_minor = "0"))]
#[cfg(not(esp_idf_version_at_least_5_1_0))]
#[inline(always)]
pub(crate) fn as_sdk(&self) -> i2s_tdm_clk_config_t {
i2s_tdm_clk_config_t {
@ -225,7 +219,7 @@ pub(super) mod config {
}
/// Convert to the ESP-IDF SDK `i2s_tdm_clk_config_t` representation.
#[cfg(all(esp_idf_version_major = "5", not(esp_idf_version_minor = "0")))]
#[cfg(esp_idf_version_at_least_5_1_0)]
#[allow(clippy::needless_update)]
#[inline(always)]
pub(crate) fn as_sdk(&self) -> i2s_tdm_clk_config_t {

View File

@ -119,9 +119,9 @@ where
#[cfg(not(esp_idf_version_major = "4"))]
duty_resolution: config.resolution.timer_bits(),
freq_hz: config.frequency.into(),
#[cfg(any(esp_idf_version_major = "4", esp_idf_version_minor = "0"))]
#[cfg(not(esp_idf_version_at_least_5_1_0))]
clk_cfg: ledc_clk_cfg_t_LEDC_AUTO_CLK,
#[cfg(not(any(esp_idf_version_major = "4", esp_idf_version_minor = "0")))]
#[cfg(esp_idf_version_at_least_5_1_0)]
clk_cfg: soc_periph_ledc_clk_src_legacy_t_LEDC_AUTO_CLK,
#[cfg(not(any(
esp_idf_version_major = "4",

View File

@ -64,6 +64,7 @@ pub mod sys;
pub mod task;
#[cfg(all(esp_idf_soc_temp_sensor_supported, esp_idf_version_major = "5"))]
pub mod temp_sensor;
#[cfg(not(esp_idf_version_at_least_6_0_0))]
pub mod timer;
pub mod uart;
#[cfg(all(

View File

@ -24,6 +24,7 @@ use crate::spi;
use crate::task::watchdog;
#[cfg(all(esp_idf_soc_temp_sensor_supported, esp_idf_version_major = "5"))]
use crate::temp_sensor;
#[cfg(not(esp_idf_version_at_least_6_0_0))]
use crate::timer;
use crate::uart;
#[cfg(all(
@ -93,11 +94,15 @@ pub struct Peripherals {
#[cfg(all(esp_idf_soc_temp_sensor_supported, esp_idf_version_major = "5"))]
pub temp_sensor: temp_sensor::TempSensor,
// TODO: Check the timer story for c2, h2, c5, c6, and p4
#[cfg(not(esp_idf_version_at_least_6_0_0))]
pub timer00: timer::TIMER00,
#[cfg(not(esp_idf_version_at_least_6_0_0))]
#[cfg(any(esp32, esp32s2, esp32s3))]
pub timer01: timer::TIMER01,
#[cfg(not(esp_idf_version_at_least_6_0_0))]
#[cfg(not(esp32c2))]
pub timer10: timer::TIMER10,
#[cfg(not(esp_idf_version_at_least_6_0_0))]
#[cfg(any(esp32, esp32s2, esp32s3))]
pub timer11: timer::TIMER11,
#[cfg(any(
@ -197,11 +202,15 @@ impl Peripherals {
sdmmc1: sd::mmc::SDMMC1::new(),
#[cfg(all(esp_idf_soc_temp_sensor_supported, esp_idf_version_major = "5"))]
temp_sensor: temp_sensor::TempSensor::new(),
#[cfg(not(esp_idf_version_at_least_6_0_0))]
timer00: timer::TIMER00::new(),
#[cfg(not(esp_idf_version_at_least_6_0_0))]
#[cfg(any(esp32, esp32s2, esp32s3))]
timer01: timer::TIMER01::new(),
#[cfg(not(esp_idf_version_at_least_6_0_0))]
#[cfg(not(esp32c2))]
timer10: timer::TIMER10::new(),
#[cfg(not(esp_idf_version_at_least_6_0_0))]
#[cfg(any(esp32, esp32s2, esp32s3))]
timer11: timer::TIMER11::new(),
#[cfg(any(

View File

@ -102,7 +102,7 @@ impl From<esp_reset_reason_t> for ResetReason {
esp_reset_reason_t_ESP_RST_USB => Self::USBPeripheral,
#[cfg(not(any(
esp_idf_version_major = "4",
all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
esp_idf_version = "5.0",
esp_idf_version_full = "5.1.0",
esp_idf_version_full = "5.1.1",
esp_idf_version_full = "5.1.2",
@ -111,24 +111,24 @@ impl From<esp_reset_reason_t> for ResetReason {
esp_reset_reason_t_ESP_RST_JTAG => Self::JTAG,
#[cfg(not(any(
esp_idf_version_major = "4",
all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
esp_idf_version = "5.0",
esp_idf_version = "5.1",
esp_idf_version_full = "5.2.0",
esp_idf_version_full = "5.2.1",
)))]
esp_reset_reason_t_ESP_RST_EFUSE => Self::EfuseError,
#[cfg(not(any(
esp_idf_version_major = "4",
all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
esp_idf_version = "5.0",
esp_idf_version = "5.1",
esp_idf_version_full = "5.2.0",
esp_idf_version_full = "5.2.1",
)))]
esp_reset_reason_t_ESP_RST_PWR_GLITCH => Self::PowerGlitch,
#[cfg(not(any(
esp_idf_version_major = "4",
all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
esp_idf_version = "5.0",
esp_idf_version = "5.1",
esp_idf_version_full = "5.2.0",
esp_idf_version_full = "5.2.1",
)))]

View File

@ -275,6 +275,8 @@ mod sdcard {
all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
)))] // For ESP-IDF v5.2 and later
set_input_delay: None,
#[cfg(esp_idf_version_at_least_6_0_0)]
set_input_delayline: None,
command_timeout_ms: configuration.command_timeout_ms as _,
#[cfg(not(any(
esp_idf_version_major = "4",
@ -283,12 +285,7 @@ mod sdcard {
all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
)))] // For ESP-IDF v5.3 and later
dma_aligned_buffer: core::ptr::null_mut(),
#[cfg(not(any(
esp_idf_version_major = "4",
all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
)))] // For ESP-IDF v5.3 and later
#[cfg(all(esp_idf_version_at_least_5_3_0, not(esp_idf_version_at_least_6_0_0)))] // For ESP-IDF v5.3 until v6.0
get_dma_info: Some(sdspi_host_get_dma_info),
#[cfg(not(any(
esp_idf_version_major = "4",

View File

@ -575,6 +575,7 @@ impl<'d> SpiDriver<'d> {
let max_transfer_sz = config.dma.max_transfer_size();
let dma_chan: spi_dma_chan_t = config.dma.into();
#[cfg(not(esp_idf_version_at_least_6_0_0))]
#[allow(clippy::needless_update)]
let bus_config = spi_bus_config_t {
flags: SPICOMMON_BUSFLAG_MASTER,
@ -605,6 +606,41 @@ impl<'d> SpiDriver<'d> {
..Default::default()
};
#[cfg(esp_idf_version_at_least_6_0_0)]
#[allow(clippy::needless_update)]
let bus_config = spi_bus_config_t {
__bindgen_anon_1: spi_bus_config_t__bindgen_ty_1 {
__bindgen_anon_1: spi_bus_config_t__bindgen_ty_1__bindgen_ty_1 {
sclk_io_num: sclk.unwrap_or(-1),
data4_io_num: -1,
data5_io_num: -1,
data6_io_num: -1,
data7_io_num: -1,
__bindgen_anon_1: spi_bus_config_t__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1 {
mosi_io_num: sdo.unwrap_or(-1),
//data0_io_num: -1,
},
__bindgen_anon_2: spi_bus_config_t__bindgen_ty_1__bindgen_ty_1__bindgen_ty_2 {
miso_io_num: sdi.unwrap_or(-1),
//data1_io_num: -1,
},
__bindgen_anon_3: spi_bus_config_t__bindgen_ty_1__bindgen_ty_1__bindgen_ty_3 {
quadwp_io_num: data2.unwrap_or(-1),
//data2_io_num: -1,
},
__bindgen_anon_4: spi_bus_config_t__bindgen_ty_1__bindgen_ty_1__bindgen_ty_4 {
quadhd_io_num: data3.unwrap_or(-1),
//data3_io_num: -1,
},
},
},
flags: SPICOMMON_BUSFLAG_MASTER,
max_transfer_sz: max_transfer_sz as i32,
intr_flags: InterruptType::to_native(config.intr_flags) as _,
..Default::default()
};
esp!(unsafe { spi_bus_initialize(host, &bus_config, dma_chan) })?;
Ok(max_transfer_sz)

View File

@ -395,9 +395,9 @@ pub mod thread {
pin_to_core: conf.pin_to_core.map(Into::into).unwrap_or(NO_AFFINITY as _),
#[cfg(not(any(
esp_idf_version_major = "4",
all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
esp_idf_version = "5.0",
esp_idf_version = "5.1",
esp_idf_version = "5.2",
)))] // ESP-IDF 5.3 and later
stack_alloc_caps: conf.stack_alloc_caps.as_u32(),
}