Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ jobs:
- v5.3.4
- v5.4.3
- v5.5.3
- v6.0
steps:
- name: Setup | Checkout
uses: actions/checkout@v3
Expand All @@ -59,31 +60,31 @@ jobs:
env:
ESP_IDF_VERSION: ${{ matrix.idf-version }}
ESP_IDF_SDKCONFIG_DEFAULTS: "${{ github.workspace }}/.github/configs/sdkconfig.defaults"
RUSTFLAGS: "${{ matrix.idf-version != 'release/v4.4' && '--cfg espidf_time64' || matrix.idf-version == 'release/v4.4' && '--cfg espidf_time32' }}"
RUSTFLAGS: "${{ startsWith(matrix.idf-version, 'v4') && '--cfg espidf_time32' || '--cfg espidf_time64' }}"
run: cargo clippy --features experimental --no-deps --target ${{ matrix.target }} -Zbuild-std=std,panic_abort -- -Dwarnings

- name: Build | Compile, all
if: matrix.target != 'riscv32imac-esp-espidf' || matrix.idf-version != 'release/v4.4'
env:
ESP_IDF_VERSION: ${{ matrix.idf-version }}
ESP_IDF_SDKCONFIG_DEFAULTS: "${{ github.workspace }}/.github/configs/sdkconfig.defaults"
RUSTFLAGS: "${{ matrix.idf-version != 'release/v4.4' && '--cfg espidf_time64' || matrix.idf-version == 'release/v4.4' && '--cfg espidf_time32' }}"
RUSTFLAGS: "${{ startsWith(matrix.idf-version, 'v4') && '--cfg espidf_time32' || '--cfg espidf_time64' }}"
run: cargo build --target ${{ matrix.target }} --features nightly,experimental,critical-section,embassy-sync -Zbuild-std=std,panic_abort

- name: Build | Compile, no_std
if: matrix.target != 'riscv32imac-esp-espidf' || matrix.idf-version != 'release/v4.4'
env:
ESP_IDF_VERSION: ${{ matrix.idf-version }}
ESP_IDF_SDKCONFIG_DEFAULTS: "${{ github.workspace }}/.github/configs/sdkconfig.defaults"
RUSTFLAGS: "${{ matrix.idf-version != 'release/v4.4' && '--cfg espidf_time64' || matrix.idf-version == 'release/v4.4' && '--cfg espidf_time32' }}"
RUSTFLAGS: "${{ startsWith(matrix.idf-version, 'v4') && '--cfg espidf_time32' || '--cfg espidf_time64' }}"
run: cargo build --no-default-features --features experimental --target ${{ matrix.target }} -Zbuild-std=std,panic_abort

- name: Build | Compile, no_std, alloc
if: matrix.target != 'riscv32imac-esp-espidf' || matrix.idf-version != 'release/v4.4'
env:
ESP_IDF_VERSION: ${{ matrix.idf-version }}
ESP_IDF_SDKCONFIG_DEFAULTS: "${{ github.workspace }}/.github/configs/sdkconfig.defaults"
RUSTFLAGS: "${{ matrix.idf-version != 'release/v4.4' && '--cfg espidf_time64' || matrix.idf-version == 'release/v4.4' && '--cfg espidf_time32' }}"
RUSTFLAGS: "${{ startsWith(matrix.idf-version, 'v4') && '--cfg espidf_time32' || '--cfg espidf_time64' }}"
run: cargo build --features alloc --no-default-features --features experimental --target ${{ matrix.target }} -Zbuild-std=std,panic_abort

- name: Setup | ldproxy
Expand All @@ -98,13 +99,13 @@ jobs:
env:
ESP_IDF_VERSION: ${{ matrix.idf-version }}
ESP_IDF_SDKCONFIG_DEFAULTS: "${{ github.workspace }}/.github/configs/sdkconfig.defaults"
RUSTFLAGS: "${{ matrix.idf-version != 'release/v4.4' && '--cfg espidf_time64' || matrix.idf-version == 'release/v4.4' && '--cfg espidf_time32' }}"
RUSTFLAGS: "${{ startsWith(matrix.idf-version, 'v4') && '--cfg espidf_time32' || '--cfg espidf_time64' }}"
run: cargo clippy --examples --target ${{ matrix.target }} -Zbuild-std=std,panic_abort -- -Dwarnings

- name: Build | Examples
if: matrix.target != 'riscv32imac-esp-espidf' || matrix.idf-version != 'release/v4.4'
env:
ESP_IDF_VERSION: ${{ matrix.idf-version }}
ESP_IDF_SDKCONFIG_DEFAULTS: "${{ github.workspace }}/.github/configs/sdkconfig.defaults"
RUSTFLAGS: "${{ matrix.idf-version != 'release/v4.4' && '--cfg espidf_time64' || matrix.idf-version == 'release/v4.4' && '--cfg espidf_time32' }}"
RUSTFLAGS: "${{ startsWith(matrix.idf-version, 'v4') && '--cfg espidf_time32' || '--cfg espidf_time64' }}"
run: cargo build --examples --target ${{ matrix.target }} -Zbuild-std=std,panic_abort
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [master] - 2026-03-26

### Breaking
- Dropped support for RGB/BGR666 format on ESP-IDF 6.0.

### Added
- Basic compatibility for ESP-IDF release 6.0.

## [0.46.2] - 2026-03-10

### Fixed
Expand Down
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ atomic-waker = { version = "1.1.1", default-features = false }
embassy-sync = "0.7"
embedded-graphics-core = { version = "0.4", optional = true }

[patch.crates-io]
esp-idf-sys = { git = "https://github.com/mh0pe/esp-idf-sys", branch = "esp-idf-v6-support" }

[build-dependencies]
embuild = "0.33"

Expand Down
78 changes: 61 additions & 17 deletions src/lcd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ pub mod config {
pub(crate) dbi_config: esp_lcd_dbi_io_config_t,
pub(crate) dpi_config: esp_lcd_dpi_panel_config_t,
pixel_format: PixelFormat,
// In IDF >=6.0, use_dma2d was removed from dpi_config.flags; we store it here
// and call esp_lcd_dpi_panel_enable_dma2d() after panel creation instead.
#[cfg(esp_idf_version_at_least_6_0_0)]
pub(super) use_dma2d: bool,
}

impl LcdConfig {
Expand Down Expand Up @@ -150,10 +154,13 @@ pub mod config {

let color_format: lcd_color_format_t = pixel_format.to_color_format();
let esp_timing: esp_lcd_video_timing_t = video_timing.into();
let use_dma2d = true;

#[cfg_attr(esp_idf_version_at_least_6_0_0, allow(unused_mut))]
let mut dpi_config = esp_lcd_dpi_panel_config_t {
virtual_channel: 0,
dpi_clk_src: soc_periph_mipi_dsi_dpi_clk_src_t_MIPI_DSI_DPI_CLK_SRC_DEFAULT,
#[cfg(not(esp_idf_version_at_least_6_0_0))]
pixel_format: pixel_format.to_rgb_pixel_format(),
in_color_format: color_format,
out_color_format: color_format,
Expand All @@ -162,13 +169,16 @@ pub mod config {
dpi_clock_freq_mhz: dpi_clock_freq_mhz as _,
..unsafe { core::mem::zeroed() }
};
dpi_config.flags.set_use_dma2d(1);
#[cfg(not(esp_idf_version_at_least_6_0_0))]
dpi_config.flags.set_use_dma2d(use_dma2d as u32);

Self {
bus_config,
dbi_config,
dpi_config,
pixel_format,
#[cfg(esp_idf_version_at_least_6_0_0)]
use_dma2d,
}
}

Expand Down Expand Up @@ -229,7 +239,15 @@ pub mod config {
/// Enable or disable DMA2D for pixel data transfer (default: enabled)
#[must_use]
pub fn use_dma2d(mut self, use_dma2d: bool) -> Self {
self.dpi_config.flags.set_use_dma2d(use_dma2d as u32);
#[cfg(not(esp_idf_version_at_least_6_0_0))]
{
self.dpi_config.flags.set_use_dma2d(use_dma2d as u32);
}
#[cfg(esp_idf_version_at_least_6_0_0)]
{
self.use_dma2d = use_dma2d;
}

self
}

Expand Down Expand Up @@ -263,6 +281,8 @@ pub mod config {
dbi_config: self.dbi_config,
dpi_config: self.dpi_config,
pixel_format: self.pixel_format,
#[cfg(esp_idf_version_at_least_6_0_0)]
use_dma2d: self.use_dma2d,
}
}
}
Expand All @@ -288,7 +308,14 @@ pub mod config {
let mut panel_config: esp_lcd_panel_dev_config_t = unsafe { core::mem::zeroed() };

panel_config.bits_per_pixel = bits_per_pixel;
panel_config.__bindgen_anon_1.rgb_ele_order = rgb_order.into();
#[cfg(not(esp_idf_version_at_least_6_0_0))]
{
panel_config.__bindgen_anon_1.rgb_ele_order = rgb_order.into();
}
#[cfg(esp_idf_version_at_least_6_0_0)]
{
panel_config.rgb_ele_order = rgb_order.into();
}

panel_config
}
Expand Down Expand Up @@ -389,9 +416,11 @@ pub mod config {
Rgb565,
/// 16-bit RGB format with BGR component order
Bgr565,
/// 18-bit RGB format with RGB component order
/// 18-bit RGB format with RGB component order (IDF < 6.0 only)
#[cfg(not(esp_idf_version_at_least_6_0_0))]
Rgb666,
/// 18-bit RGB format with BGR component order
/// 18-bit RGB format with BGR component order (IDF < 6.0 only)
#[cfg(not(esp_idf_version_at_least_6_0_0))]
Bgr666,
}

Expand All @@ -401,34 +430,35 @@ pub mod config {
match self {
PixelFormat::Rgb888 | PixelFormat::Bgr888 => 24,
PixelFormat::Rgb565 | PixelFormat::Bgr565 => 16,
#[cfg(not(esp_idf_version_at_least_6_0_0))]
PixelFormat::Rgb666 | PixelFormat::Bgr666 => 18,
}
}

/// Get the bytes per pixel for this format
pub const fn bytes_per_pixel(&self) -> usize {
match self {
PixelFormat::Rgb888
| PixelFormat::Bgr888
| PixelFormat::Rgb666
| PixelFormat::Bgr666 => 3,
PixelFormat::Rgb888 | PixelFormat::Bgr888 => 3,
PixelFormat::Rgb565 | PixelFormat::Bgr565 => 2,
#[cfg(not(esp_idf_version_at_least_6_0_0))]
PixelFormat::Rgb666 | PixelFormat::Bgr666 => 3,
}
}

/// Get the RGB element order for this format
pub const fn rgb_element_order(&self) -> RgbElementOrder {
match self {
PixelFormat::Rgb888 | PixelFormat::Rgb565 | PixelFormat::Rgb666 => {
RgbElementOrder::Rgb
}
PixelFormat::Bgr888 | PixelFormat::Bgr565 | PixelFormat::Bgr666 => {
RgbElementOrder::Bgr
}
PixelFormat::Rgb888 | PixelFormat::Rgb565 => RgbElementOrder::Rgb,
PixelFormat::Bgr888 | PixelFormat::Bgr565 => RgbElementOrder::Bgr,
#[cfg(not(esp_idf_version_at_least_6_0_0))]
PixelFormat::Rgb666 => RgbElementOrder::Rgb,
#[cfg(not(esp_idf_version_at_least_6_0_0))]
PixelFormat::Bgr666 => RgbElementOrder::Bgr,
}
}

/// Convert to `lcd_color_rgb_pixel_format_t`
/// Convert to `lcd_color_rgb_pixel_format_t` (IDF < 6.0 only)
#[cfg(not(esp_idf_version_at_least_6_0_0))]
pub fn to_rgb_pixel_format(&self) -> lcd_color_rgb_pixel_format_t {
match self {
PixelFormat::Rgb888 | PixelFormat::Bgr888 => {
Expand All @@ -452,6 +482,7 @@ pub mod config {
PixelFormat::Rgb565 | PixelFormat::Bgr565 => {
lcd_color_format_t_LCD_COLOR_FMT_RGB565
}
#[cfg(not(esp_idf_version_at_least_6_0_0))]
PixelFormat::Rgb666 | PixelFormat::Bgr666 => {
lcd_color_format_t_LCD_COLOR_FMT_RGB666
}
Expand Down Expand Up @@ -821,7 +852,10 @@ impl<'d, S: DpiPanelState> LcdDriver<'d, S> {
/// Requires that `set_control_panel()` has been called first.
pub fn set_display_off(&self, off: bool) -> Result<(), EspError> {
let panel = self.require_control_panel()?;
unsafe { esp!(esp_lcd_panel_disp_off(panel, off)) }
#[cfg(not(esp_idf_version_at_least_6_0_0))]
return unsafe { esp!(esp_lcd_panel_disp_off(panel, off)) };
#[cfg(esp_idf_version_at_least_6_0_0)]
return unsafe { esp!(esp_lcd_panel_disp_on_off(panel, !off)) };
}

/// Enter or exit sleep mode (low power mode)
Expand Down Expand Up @@ -935,6 +969,16 @@ impl<'d> LcdDriver<'d, NoDpiPanel> {
// self drops here, cleaning up bus + DBI IO + control panel
}

// In IDF 6.0, use_dma2d was removed from dpi_config flags; call API instead
#[cfg(esp_idf_version_at_least_6_0_0)]
if self.config.use_dma2d {
if let Err(e) = esp!(esp_lcd_dpi_panel_enable_dma2d(panel_handle)) {
let _ = esp_lcd_panel_del(panel_handle);
let _ = Box::from_raw(dpi_config_ptr);
return Err(e);
}
}

let handle = match NonNull::new(panel_handle as *mut c_void) {
Some(h) => h,
None => {
Expand Down
32 changes: 31 additions & 1 deletion src/pcnt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
//! - Maximum number of units: [`SOC_PCNT_UNITS_PER_GROUP`]
//! - Maximum number of channels per unit: [`SOC_PCNT_CHANNELS_PER_UNIT`]
//! - Maximum number of extra watchpoints: [`SOC_PCNT_THRES_POINT_PER_UNIT`]
//!
//! These 3 constants disappeared in ESP-IDF 6.0, as they were required by the
//! pcnt-legacy API which was removed.
//! The API rejects additional `new_*` calls beyond the maximum number of supported
//! channels. We do hardcode the maximum to 2 if alloc is not enabled, though.

use core::marker::PhantomData;
#[cfg(feature = "alloc")]
Expand All @@ -63,10 +68,20 @@ use core::ptr;

#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
#[cfg(not(feature = "alloc"))]
use heapless::Vec;

use esp_idf_sys::*;

// SOC_PCNT_CHANNELS_PER_UNIT was removed in IDF 6.0; the value is 2 for all supported chips,
// and we support more channels in the alloc case.
#[cfg(esp_idf_version_at_least_6_0_0)]
const PCNT_CHANNELS_PER_UNIT: usize = 2;
#[cfg(not(esp_idf_version_at_least_6_0_0))]
const PCNT_CHANNELS_PER_UNIT: usize = SOC_PCNT_CHANNELS_PER_UNIT as usize;

use crate::gpio::InputPin;
#[cfg(feature = "alloc")]
use crate::interrupt;
Expand Down Expand Up @@ -166,6 +181,11 @@ pub mod config {
impl From<&UnitConfig> for pcnt_unit_config_t {
fn from(value: &UnitConfig) -> Self {
pcnt_unit_config_t {
// TODO: Do we want to make this configurable?
// Most chips have only 1 option (APB==DEFAULT), but
// esp32h4 supports XTAL(==DEFAULT) or RC_FAST.
#[cfg(esp_idf_version_at_least_6_0_0)]
clk_src: soc_periph_pcnt_clk_src_t_PCNT_CLK_SRC_DEFAULT,
low_limit: value.low_limit,
high_limit: value.high_limit,
intr_priority: value.intr_priority,
Expand Down Expand Up @@ -573,7 +593,10 @@ struct DelegateUserData<'d> {
/// that have to be added with [`PcntUnitDriver::add_channel`].
pub struct PcntUnitDriver<'d> {
handle: pcnt_unit_handle_t,
channels: Vec<PcntChannel<'d>, { SOC_PCNT_CHANNELS_PER_UNIT as usize }>,
#[cfg(feature = "alloc")]
channels: alloc::vec::Vec<PcntChannel<'d>>,
#[cfg(not(feature = "alloc"))]
channels: Vec<PcntChannel<'d>, PCNT_CHANNELS_PER_UNIT>,
#[cfg(feature = "alloc")]
user_data: Option<Pin<Box<DelegateUserData<'d>>>>,
_p: PhantomData<&'d mut ()>,
Expand All @@ -596,6 +619,9 @@ impl<'d> PcntUnitDriver<'d> {

Ok(Self {
handle,
#[cfg(feature = "alloc")] // Pre-allocate to usual maximum size
channels: Vec::with_capacity(PCNT_CHANNELS_PER_UNIT),
#[cfg(not(feature = "alloc"))] // Fixed size
channels: Vec::new(),
#[cfg(feature = "alloc")]
user_data: None,
Expand Down Expand Up @@ -785,6 +811,10 @@ impl<'d> PcntUnitDriver<'d> {
level_pin: Option<impl InputPin + 'd>,
config: &ChannelConfig,
) -> Result<&mut PcntChannel<'d>, EspError> {
#[cfg(feature = "alloc")]
self.channels
.push(unsafe { PcntChannel::new(self.handle, edge_pin, level_pin, config)? });
#[cfg(not(feature = "alloc"))]
self.channels
.push(unsafe { PcntChannel::new(self.handle, edge_pin, level_pin, config)? })
.expect("Not enough channels available.");
Expand Down
11 changes: 10 additions & 1 deletion src/sleep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,19 @@ pub mod gpio {
pub fn configure_deep(pin: PinId, level: Level) -> Result<(), EspError> {
let mask = 1 << pin;
let mode = match level {
#[cfg(not(esp_idf_version_at_least_6_0_0))]
Level::Low => esp_deepsleep_gpio_wake_up_mode_t_ESP_GPIO_WAKEUP_GPIO_LOW,
#[cfg(not(esp_idf_version_at_least_6_0_0))]
Level::High => esp_deepsleep_gpio_wake_up_mode_t_ESP_GPIO_WAKEUP_GPIO_HIGH,
#[cfg(esp_idf_version_at_least_6_0_0)]
Level::Low => esp_sleep_gpio_wake_up_mode_t_ESP_GPIO_WAKEUP_GPIO_LOW,
#[cfg(esp_idf_version_at_least_6_0_0)]
Level::High => esp_sleep_gpio_wake_up_mode_t_ESP_GPIO_WAKEUP_GPIO_HIGH,
};
esp!(unsafe { esp_deep_sleep_enable_gpio_wakeup(mask, mode) })
#[cfg(not(esp_idf_version_at_least_6_0_0))]
return esp!(unsafe { esp_deep_sleep_enable_gpio_wakeup(mask, mode) });
#[cfg(esp_idf_version_at_least_6_0_0)]
return esp!(unsafe { esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown(mask, mode) });
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,10 +282,10 @@ impl<'d> TimerDriver<'d> {
{
config.allow_pd as _
},
// The `backup_before_sleep` field is deprecated, and will be removed in 6.1
// The `backup_before_sleep` field was removed in IDF 6.0
#[cfg(all(
esp_idf_version_at_least_5_3_0,
not(esp_idf_version_at_least_6_1_0)
not(esp_idf_version_at_least_6_0_0)
))]
{
false as _
Expand Down
Loading
Loading