From 10e8d2bd018c7811c149270299e41f6aa49b6385 Mon Sep 17 00:00:00 2001 From: wisp3rwind <17089248+wisp3rwind@users.noreply.github.com> Date: Wed, 15 Jan 2025 11:10:27 +0100 Subject: [PATCH 1/2] rmt: consolidate listen_interrupt() calls such that they reduce to a single load/modify/store operation --- esp-hal/src/rmt.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/esp-hal/src/rmt.rs b/esp-hal/src/rmt.rs index 59d832630e9..ffbbc626780 100644 --- a/esp-hal/src/rmt.rs +++ b/esp-hal/src/rmt.rs @@ -1326,8 +1326,7 @@ pub trait TxChannelAsync: TxChannelInternal { } Self::clear_interrupts(); - Self::listen_interrupt(Event::End); - Self::listen_interrupt(Event::Error); + Self::listen_interrupt(Event::End | Event::Error); Self::send_raw(data, false, 0)?; RmtTxFuture::new(self).await; @@ -1389,8 +1388,7 @@ pub trait RxChannelAsync: RxChannelInternal { } Self::clear_interrupts(); - Self::listen_interrupt(Event::End); - Self::listen_interrupt(Event::Error); + Self::listen_interrupt(Event::End | Event::Error); Self::start_receive_raw(); RmtRxFuture::new(self).await; From f4f901f68913cf217fce6b796a176a4324eaeb49 Mon Sep 17 00:00:00 2001 From: wisp3rwind <17089248+wisp3rwind@users.noreply.github.com> Date: Wed, 15 Jan 2025 11:11:24 +0100 Subject: [PATCH 2/2] rmt: avoid EnumSet::iter for better codegen with optlevel=s This iterator generates relatively complex code, which is not reliably reduced to the intended simple memory access, even if the `events` argument is constant at compile time. Rather, the loop might be retained, which is inefficient and leads to much larger code. Tested on riscv using cargo objdump, with the following cargo profile [profile.release] codegen-units = 1 debug = true debug-assertions = false incremental = false lto = 'fat' opt-level = 3|'s' overflow-checks = false --- esp-hal/src/rmt.rs | 56 ++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/esp-hal/src/rmt.rs b/esp-hal/src/rmt.rs index ffbbc626780..80420b60e98 100644 --- a/esp-hal/src/rmt.rs +++ b/esp-hal/src/rmt.rs @@ -1912,12 +1912,14 @@ mod chip_specific { fn enable_listen_interrupt(events: enumset::EnumSet<$crate::rmt::Event>, enable: bool) { let rmt = unsafe { &*crate::peripherals::RMT::PTR }; rmt.int_ena().modify(|_, w| { - for event in events { - match event { - $crate::rmt::Event::Error => w.[< ch $ch_num _tx_err >]().bit(enable), - $crate::rmt::Event::End => w.[< ch $ch_num _tx_end >]().bit(enable), - $crate::rmt::Event::Threshold => w.[< ch $ch_num _tx_thr_event >]().bit(enable), - }; + if events.contains($crate::rmt::Event::Error) { + w.[< ch $ch_num _tx_err >]().bit(enable); + } + if events.contains($crate::rmt::Event::End) { + w.[< ch $ch_num _tx_end >]().bit(enable); + } + if events.contains($crate::rmt::Event::Threshold) { + w.[< ch $ch_num _tx_thr_event >]().bit(enable); } w }); @@ -2030,12 +2032,14 @@ mod chip_specific { fn enable_listen_interrupt(events: enumset::EnumSet<$crate::rmt::Event>, enable: bool) { let rmt = unsafe { &*crate::peripherals::RMT::PTR }; rmt.int_ena().modify(|_, w| { - for event in events { - match event { - $crate::rmt::Event::Error => w.[< ch $ch_num _rx_err >]().bit(enable), - $crate::rmt::Event::End => w.[< ch $ch_num _rx_end >]().bit(enable), - $crate::rmt::Event::Threshold => w.[< ch $ch_num _rx_thr_event >]().bit(enable), - }; + if events.contains($crate::rmt::Event::Error) { + w.[< ch $ch_num _rx_err >]().bit(enable); + } + if events.contains($crate::rmt::Event::End) { + w.[< ch $ch_num _rx_end >]().bit(enable); + } + if events.contains($crate::rmt::Event::Threshold) { + w.[< ch $ch_num _rx_thr_event >]().bit(enable); } w }); @@ -2256,12 +2260,14 @@ mod chip_specific { fn enable_listen_interrupt(events: enumset::EnumSet<$crate::rmt::Event>, enable: bool) { let rmt = unsafe { &*crate::peripherals::RMT::PTR }; rmt.int_ena().modify(|_,w| { - for event in events { - match event { - $crate::rmt::Event::Error => w.[< ch $ch_num _err >]().bit(enable), - $crate::rmt::Event::End => w.[< ch $ch_num _tx_end >]().bit(enable), - $crate::rmt::Event::Threshold => w.[< ch $ch_num _tx_thr_event >]().bit(enable), - }; + if events.contains($crate::rmt::Event::Error) { + w.[< ch $ch_num _err >]().bit(enable); + } + if events.contains($crate::rmt::Event::End) { + w.[< ch $ch_num _tx_end >]().bit(enable); + } + if events.contains($crate::rmt::Event::Threshold) { + w.[< ch $ch_num _tx_thr_event >]().bit(enable); } w }); @@ -2379,12 +2385,14 @@ mod chip_specific { fn enable_listen_interrupt(events: enumset::EnumSet<$crate::rmt::Event>, enable: bool) { let rmt = unsafe { &*crate::peripherals::RMT::PTR }; rmt.int_ena().modify(|_, w| { - for event in events { - match event { - $crate::rmt::Event::Error => w.[< ch $ch_num _err >]().bit(enable), - $crate::rmt::Event::End => w.[< ch $ch_num _rx_end >]().bit(enable), - $crate::rmt::Event::Threshold => w.[< ch $ch_num _tx_thr_event >]().bit(enable), - }; + if events.contains($crate::rmt::Event::Error) { + w.[< ch $ch_num _err >]().bit(enable); + } + if events.contains($crate::rmt::Event::End) { + w.[< ch $ch_num _rx_end >]().bit(enable); + } + if events.contains($crate::rmt::Event::Threshold) { + w.[< ch $ch_num _tx_thr_event >]().bit(enable); } w });