diff --git a/examples/rmt_neopixel.rs b/examples/rmt_neopixel.rs index 624fe429b..e87c1f817 100644 --- a/examples/rmt_neopixel.rs +++ b/examples/rmt_neopixel.rs @@ -29,7 +29,7 @@ fn main() -> Result<()> { // 3 seconds white at 10% brightness neopixel( - RGB { + Rgb { r: 25, g: 25, b: 25, @@ -51,7 +51,7 @@ fn main() -> Result<()> { } } -struct RGB { +struct Rgb { r: u8, g: u8, b: u8, @@ -61,7 +61,7 @@ fn ns(nanos: u64) -> Duration { Duration::from_nanos(nanos) } -fn neopixel(rgb: RGB, tx: &mut TxRmtDriver) -> Result<()> { +fn neopixel(rgb: Rgb, tx: &mut TxRmtDriver) -> Result<()> { // e.g. rgb: (1,2,4) // G R B // 7 0 7 0 7 0 @@ -85,7 +85,7 @@ fn neopixel(rgb: RGB, tx: &mut TxRmtDriver) -> Result<()> { } /// Converts hue, saturation, value to RGB -fn hsv2rgb(h: u32, s: u32, v: u32) -> Result { +fn hsv2rgb(h: u32, s: u32, v: u32) -> Result { if h > 360 || s > 100 || v > 100 { bail!("The given HSV values are not in valid range"); } @@ -99,19 +99,19 @@ fn hsv2rgb(h: u32, s: u32, v: u32) -> Result { r = c; g = x; b = 0.0; - } else if h >= 60 && h < 120 { + } else if (60..120).contains(&h) { r = x; g = c; b = 0.0; - } else if h >= 120 && h < 180 { + } else if (120..180).contains(&h) { r = 0.0; g = c; b = x; - } else if h >= 180 && h < 240 { + } else if (180..240).contains(&h) { r = 0.0; g = x; b = c; - } else if h >= 240 && h < 300 { + } else if (240..300).contains(&h) { r = x; g = 0.0; b = c; @@ -121,7 +121,7 @@ fn hsv2rgb(h: u32, s: u32, v: u32) -> Result { b = x; } - Ok(RGB { + Ok(Rgb { r: ((r + m) * 255.0) as u8, g: ((g + m) * 255.0) as u8, b: ((b + m) * 255.0) as u8, diff --git a/examples/spi_loopback.rs b/examples/spi_loopback.rs index b4be806c8..4464dca7f 100644 --- a/examples/spi_loopback.rs +++ b/examples/spi_loopback.rs @@ -32,7 +32,13 @@ fn main() -> anyhow::Result<()> { println!("Starting SPI loopback test"); - let driver = SpiDriver::new::(spi, sclk, serial_out, Some(serial_in), Dma::Disabled)?; + let driver = SpiDriver::new::( + spi, + sclk, + serial_out, + Some(serial_in), + &SpiDriverConfig::new(), + )?; let config_1 = config::Config::new().baudrate(26.MHz().into()); let mut device_1 = SpiDeviceDriver::new(&driver, Some(cs_1), &config_1)?; diff --git a/examples/spi_st7789.rs b/examples/spi_st7789.rs index 861d7edbf..43d01bb27 100644 --- a/examples/spi_st7789.rs +++ b/examples/spi_st7789.rs @@ -52,8 +52,15 @@ fn main() -> anyhow::Result<()> { .baudrate(26.MHz().into()) .data_mode(MODE_3); - let device = - SpiDeviceDriver::new_single(spi, sclk, sda, Some(sdi), Dma::Disabled, Some(cs), &config)?; + let device = SpiDeviceDriver::new_single( + spi, + sclk, + sda, + Some(sdi), + Some(cs), + &SpiDriverConfig::new(), + &config, + )?; // display interface abstraction from SPI and DC let di = SPIInterfaceNoCS::new(device, dc); diff --git a/src/can.rs b/src/can.rs index c20daeaf9..f72876429 100644 --- a/src/can.rs +++ b/src/can.rs @@ -36,6 +36,7 @@ use esp_idf_sys::*; use crate::delay::{BLOCK, NON_BLOCK}; use crate::gpio::*; +use crate::interrupt::IntrFlags; use crate::peripheral::{Peripheral, PeripheralRef}; crate::embedded_hal_error!(CanError, embedded_can::Error, embedded_can::ErrorKind); @@ -49,8 +50,11 @@ crate::embedded_hal_error!( pub type CanConfig = config::Config; pub mod config { + use enumset::EnumSet; use esp_idf_sys::*; + use crate::interrupt::IntrFlags; + /// CAN timing #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum Timing { @@ -433,7 +437,7 @@ pub mod config { } } - #[derive(Debug, Copy, Clone, Default)] + #[derive(Debug, Clone)] pub struct Config { pub timing: Timing, pub filter: Filter, @@ -441,14 +445,19 @@ pub mod config { pub rx_queue_len: u32, pub mode: Mode, pub alerts: Alerts, + pub intr_flags: EnumSet, } impl Config { pub fn new() -> Self { - Config { + Self { + timing: Default::default(), + filter: Default::default(), tx_queue_len: 5, rx_queue_len: 5, - ..Default::default() + mode: Default::default(), + alerts: Default::default(), + intr_flags: EnumSet::::empty(), } } @@ -464,25 +473,41 @@ pub mod config { self } + #[must_use] pub fn tx_queue_len(mut self, tx_queue_len: u32) -> Self { self.tx_queue_len = tx_queue_len; self } + #[must_use] pub fn rx_queue_len(mut self, rx_queue_len: u32) -> Self { self.rx_queue_len = rx_queue_len; self } + #[must_use] pub fn mode(mut self, mode: Mode) -> Self { self.mode = mode; self } + #[must_use] pub fn alerts(mut self, alerts: Alerts) -> Self { self.alerts = alerts; self } + + #[must_use] + pub fn intr_flags(mut self, flags: EnumSet) -> Self { + self.intr_flags = flags; + self + } + } + + impl Default for Config { + fn default() -> Self { + Self::new() + } } } @@ -510,7 +535,7 @@ impl<'d> CanDriver<'d> { rx_queue_len: config.rx_queue_len, alerts_enabled: config.alerts.into(), clkout_divider: 0, - intr_flags: ESP_INTR_FLAG_LEVEL1 as i32, + intr_flags: IntrFlags::to_native(config.intr_flags) as _, }; let timing_config = config.timing.into(); diff --git a/src/gpio.rs b/src/gpio.rs index 181182b9f..690106d9d 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -1319,22 +1319,33 @@ impl UnsafeCallback { } } -#[cfg(all(not(feature = "riscv-ulp-hal"), feature = "alloc"))] +#[cfg(not(feature = "riscv-ulp-hal"))] +static ISR_ALLOC_FLAGS: core::sync::atomic::AtomicU32 = core::sync::atomic::AtomicU32::new(0); + +#[cfg(not(feature = "riscv-ulp-hal"))] static ISR_SERVICE_ENABLED: core::sync::atomic::AtomicBool = core::sync::atomic::AtomicBool::new(false); -#[cfg(all(not(feature = "riscv-ulp-hal"), feature = "alloc"))] +#[cfg(not(feature = "riscv-ulp-hal"))] static ISR_SERVICE_ENABLED_CS: crate::task::CriticalSection = crate::task::CriticalSection::new(); -#[cfg(all(not(feature = "riscv-ulp-hal"), feature = "alloc"))] -fn enable_isr_service() -> Result<(), EspError> { +#[cfg(not(feature = "riscv-ulp-hal"))] +pub fn init_isr_alloc_flags(flags: enumset::EnumSet) { + ISR_ALLOC_FLAGS.store( + crate::interrupt::IntrFlags::to_native(flags), + core::sync::atomic::Ordering::SeqCst, + ); +} + +#[cfg(not(feature = "riscv-ulp-hal"))] +pub fn enable_isr_service() -> Result<(), EspError> { use core::sync::atomic::Ordering; if !ISR_SERVICE_ENABLED.load(Ordering::SeqCst) { let _guard = ISR_SERVICE_ENABLED_CS.enter(); if !ISR_SERVICE_ENABLED.load(Ordering::SeqCst) { - esp!(unsafe { gpio_install_isr_service(0) })?; + esp!(unsafe { gpio_install_isr_service(ISR_ALLOC_FLAGS.load(Ordering::SeqCst) as _) })?; ISR_SERVICE_ENABLED.store(true, Ordering::SeqCst); } diff --git a/src/i2c.rs b/src/i2c.rs index 875f75956..f8452d972 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -7,6 +7,7 @@ use esp_idf_sys::*; use crate::delay::*; use crate::gpio::*; +use crate::interrupt::IntrFlags; use crate::peripheral::Peripheral; use crate::units::*; @@ -36,16 +37,19 @@ pub type I2cSlaveConfig = config::SlaveConfig; /// I2C configuration pub mod config { + use enumset::EnumSet; + use super::APBTickType; - use crate::units::*; + use crate::{interrupt::IntrFlags, units::*}; /// I2C Master configuration - #[derive(Copy, Clone)] + #[derive(Debug, Clone)] pub struct Config { pub baudrate: Hertz, pub sda_pullup_enabled: bool, pub scl_pullup_enabled: bool, pub timeout: Option, + pub intr_flags: EnumSet, } impl Config { @@ -76,6 +80,12 @@ pub mod config { self.timeout = Some(timeout); self } + + #[must_use] + pub fn intr_flags(mut self, flags: EnumSet) -> Self { + self.intr_flags = flags; + self + } } impl Default for Config { @@ -85,18 +95,20 @@ pub mod config { sda_pullup_enabled: true, scl_pullup_enabled: true, timeout: None, + intr_flags: EnumSet::::empty(), } } } /// I2C Slave configuration #[cfg(not(esp32c2))] - #[derive(Copy, Clone)] + #[derive(Debug, Clone)] pub struct SlaveConfig { pub sda_pullup_enabled: bool, pub scl_pullup_enabled: bool, pub rx_buf_len: usize, pub tx_buf_len: usize, + pub intr_flags: EnumSet, } #[cfg(not(esp32c2))] @@ -128,6 +140,12 @@ pub mod config { self.tx_buf_len = len; self } + + #[must_use] + pub fn intr_flags(mut self, flags: EnumSet) -> Self { + self.intr_flags = flags; + self + } } #[cfg(not(esp32c2))] @@ -138,6 +156,7 @@ pub mod config { scl_pullup_enabled: true, rx_buf_len: 0, tx_buf_len: 0, + intr_flags: EnumSet::::empty(), } } } @@ -188,8 +207,8 @@ impl<'d> I2cDriver<'d> { i2c_mode_t_I2C_MODE_MASTER, 0, // Not used in master mode 0, // Not used in master mode - 0, - ) // TODO: set flags + IntrFlags::to_native(config.intr_flags) as _, + ) })?; if let Some(timeout) = config.timeout { @@ -460,7 +479,7 @@ impl<'d> I2cSlaveDriver<'d> { i2c_mode_t_I2C_MODE_SLAVE, config.rx_buf_len, config.tx_buf_len, - 0, // TODO: set flags + IntrFlags::to_native(config.intr_flags) as _, ) })?; diff --git a/src/interrupt.rs b/src/interrupt.rs index 460c0515d..f5c7669ee 100644 --- a/src/interrupt.rs +++ b/src/interrupt.rs @@ -1,7 +1,82 @@ use core::sync::atomic::{AtomicU64, Ordering}; +use enumset::{EnumSet, EnumSetType}; use esp_idf_sys::*; +/// Interrupt allocation flags. +/// These flags can be used to specify which interrupt qualities the code calling esp_intr_alloc* needs. +#[derive(Debug, EnumSetType)] +pub enum IntrFlags { + // Accept a Level 1 interrupt vector (lowest priority) + Level1, + // Accept a Level 2 interrupt vector. + Level2, + // Accept a Level 3 interrupt vector. + Level3, + // Accept a Level 4 interrupt vector. + Level4, + // Accept a Level 5 interrupt vector. + Level5, + // Accept a Level 6 interrupt vector. + Level6, + // Accept a Level 7 interrupt vector (highest priority) + Nmi, + // Interrupt can be shared between ISRs. + Shared, + // Edge-triggered interrupt. + Edge, + // ISR can be called if cache is disabled. + // Must be used with a proper option *_ISR_IN_IRAM in SDKCONFIG + Iram, + // Return with this interrupt disabled. + IntrDisabled, + // Low and medium prio interrupts. These can be handled in C. + LowMed, + // High level interrupts. Need to be handled in assembly. + High, +} + +impl IntrFlags { + pub fn levels(&self) -> EnumSet { + Self::Level1 + | Self::Level2 + | Self::Level3 + | Self::Level4 + | Self::Level5 + | Self::Level6 + | Self::Nmi + } + + pub(crate) fn to_native(flags: EnumSet) -> u32 { + let mut uflags: u32 = 0; + for flag in flags { + uflags |= u32::from(flag); + } + + uflags + } +} + +impl From for u32 { + fn from(flag: IntrFlags) -> Self { + match flag { + IntrFlags::Level1 => esp_idf_sys::ESP_INTR_FLAG_LEVEL1, + IntrFlags::Level2 => esp_idf_sys::ESP_INTR_FLAG_LEVEL2, + IntrFlags::Level3 => esp_idf_sys::ESP_INTR_FLAG_LEVEL3, + IntrFlags::Level4 => esp_idf_sys::ESP_INTR_FLAG_LEVEL4, + IntrFlags::Level5 => esp_idf_sys::ESP_INTR_FLAG_LEVEL5, + IntrFlags::Level6 => esp_idf_sys::ESP_INTR_FLAG_LEVEL6, + IntrFlags::Nmi => esp_idf_sys::ESP_INTR_FLAG_NMI, + IntrFlags::Shared => esp_idf_sys::ESP_INTR_FLAG_SHARED, + IntrFlags::Edge => esp_idf_sys::ESP_INTR_FLAG_EDGE, + IntrFlags::Iram => esp_idf_sys::ESP_INTR_FLAG_IRAM, + IntrFlags::IntrDisabled => esp_idf_sys::ESP_INTR_FLAG_INTRDISABLED, + IntrFlags::LowMed => esp_idf_sys::ESP_INTR_FLAG_LOWMED, + IntrFlags::High => esp_idf_sys::ESP_INTR_FLAG_HIGH, + } + } +} + pub(crate) static CS: IsrCriticalSection = IsrCriticalSection::new(); /// Returns true if the currently active core is executing an ISR request diff --git a/src/pcnt.rs b/src/pcnt.rs index d5049b178..96e21d2d6 100644 --- a/src/pcnt.rs +++ b/src/pcnt.rs @@ -515,6 +515,8 @@ impl Drop for PcntDriver<'_> { } } +static ISR_ALLOC_FLAGS: core::sync::AtomicU32 = core::sync::atomic::AtomicU32::new(0); + #[cfg(feature = "alloc")] static ISR_SERVICE_ENABLED: core::sync::atomic::AtomicBool = core::sync::atomic::AtomicBool::new(false); @@ -522,6 +524,13 @@ static ISR_SERVICE_ENABLED: core::sync::atomic::AtomicBool = #[cfg(feature = "alloc")] static PCNT_CS: crate::task::CriticalSection = crate::task::CriticalSection::new(); +pub fn init_isr_alloc_flags(flags: enumset::EnumSet) { + ISR_ALLOC_FLAGS.store( + crate::interrupt::IntrFlags::to_native(flags), + core::sync::atomic::Ordering::SeqCst, + ); +} + #[cfg(feature = "alloc")] fn enable_isr_service() -> Result<(), EspError> { use core::sync::atomic::Ordering; @@ -530,7 +539,7 @@ fn enable_isr_service() -> Result<(), EspError> { let _cs = PCNT_CS.enter(); if !ISR_SERVICE_ENABLED.load(Ordering::SeqCst) { - esp!(unsafe { pcnt_isr_service_install(0) })?; + esp!(unsafe { pcnt_isr_service_install(ISR_ALLOC_FLAGS.load(Ordering::SeqCst) as _) })?; ISR_SERVICE_ENABLED.store(true, Ordering::SeqCst); } diff --git a/src/rmt.rs b/src/rmt.rs index 76d19c136..696c06dfa 100644 --- a/src/rmt.rs +++ b/src/rmt.rs @@ -64,6 +64,7 @@ use esp_idf_sys::*; use crate::gpio::InputPin; use crate::gpio::OutputPin; +use crate::interrupt::IntrFlags; use crate::peripheral::Peripheral; use crate::units::Hertz; @@ -250,10 +251,14 @@ pub type RxRmtConfig = config::ReceiveConfig; /// /// ``` pub mod config { + use enumset::EnumSet; use esp_idf_sys::{EspError, ESP_ERR_INVALID_ARG}; use super::PinState; - use crate::units::{FromValueType, Hertz}; + use crate::{ + interrupt::IntrFlags, + units::{FromValueType, Hertz}, + }; /// A percentage from 0 to 100%, used to specify the duty percentage in [`CarrierConfig`]. #[derive(Debug, Copy, Clone, Eq, PartialEq)] @@ -292,16 +297,19 @@ pub mod config { } } + #[must_use] pub fn frequency(mut self, hz: Hertz) -> Self { self.frequency = hz; self } + #[must_use] pub fn carrier_level(mut self, state: PinState) -> Self { self.carrier_level = state; self } + #[must_use] pub fn duty_percent(mut self, duty: DutyPercent) -> Self { self.duty_percent = duty; self @@ -329,6 +337,7 @@ pub mod config { } /// Used when creating a [`Transmit`][crate::rmt::Transmit] instance. + #[derive(Debug, Clone)] pub struct TransmitConfig { pub clock_divider: u8, pub mem_block_num: u8, @@ -344,6 +353,8 @@ pub mod config { /// When set, RMT channel will take REF_TICK or XTAL as source clock. The benefit is, RMT /// channel can continue work even when APB clock is changing. pub aware_dfs: bool, + + pub intr_flags: EnumSet, } impl TransmitConfig { @@ -355,38 +366,51 @@ pub mod config { looping: Loop::None, carrier: None, idle: Some(PinState::Low), + intr_flags: EnumSet::::empty(), } } + #[must_use] pub fn aware_dfs(mut self, enable: bool) -> Self { self.aware_dfs = enable; self } + #[must_use] pub fn mem_block_num(mut self, mem_block_num: u8) -> Self { self.mem_block_num = mem_block_num; self } + #[must_use] pub fn clock_divider(mut self, divider: u8) -> Self { self.clock_divider = divider; self } + #[must_use] pub fn looping(mut self, looping: Loop) -> Self { self.looping = looping; self } + #[must_use] pub fn carrier(mut self, carrier: Option) -> Self { self.carrier = carrier; self } + #[must_use] pub fn idle(mut self, idle: Option) -> Self { self.idle = idle; self } + + #[must_use] + pub fn intr_flags(mut self, flags: EnumSet) -> Self { + self.intr_flags = flags; + self + } } impl Default for TransmitConfig { @@ -397,6 +421,7 @@ pub mod config { } /// Used when creating a [`Receive`][crate::rmt::Receive] instance. + #[derive(Debug, Clone)] pub struct ReceiveConfig { pub clock_divider: u8, pub mem_block_num: u8, @@ -404,6 +429,7 @@ pub mod config { pub filter_ticks_thresh: u8, pub filter_en: bool, pub carrier: Option, + pub intr_flags: EnumSet, } impl ReceiveConfig { @@ -411,35 +437,47 @@ pub mod config { Self::default() } + #[must_use] pub fn clock_divider(mut self, divider: u8) -> Self { self.clock_divider = divider; self } + #[must_use] pub fn mem_block_num(mut self, mem_block_num: u8) -> Self { self.mem_block_num = mem_block_num; self } + #[must_use] pub fn idle_threshold(mut self, threshold: u16) -> Self { self.idle_threshold = threshold; self } + #[must_use] pub fn filter_ticks_thresh(mut self, threshold: u8) -> Self { self.filter_ticks_thresh = threshold; self } + #[must_use] pub fn filter_en(mut self, enable: bool) -> Self { self.filter_en = enable; self } + #[must_use] pub fn carrier(mut self, carrier: Option) -> Self { self.carrier = carrier; self } + + #[must_use] + pub fn intr_flags(mut self, flags: EnumSet) -> Self { + self.intr_flags = flags; + self + } } impl Default for ReceiveConfig { @@ -452,6 +490,7 @@ pub mod config { filter_ticks_thresh: 100, // 100 microseconds, pulses less than this will be ignored filter_en: true, carrier: None, + intr_flags: EnumSet::::empty(), } } } @@ -520,7 +559,11 @@ impl<'d> TxRmtDriver<'d> { unsafe { esp!(rmt_config(&sys_config))?; - esp!(rmt_driver_install(C::channel(), 0, 0))?; + esp!(rmt_driver_install( + C::channel(), + 0, + IntrFlags::to_native(config.intr_flags) as _ + ))?; } Ok(Self { @@ -943,7 +986,7 @@ impl<'d> RxRmtDriver<'d> { #[cfg(not(any(esp32, esp32c2)))] let carrier = config.carrier.unwrap_or_default(); - let config = rmt_config_t { + let sys_config = rmt_config_t { rmt_mode: rmt_mode_t_RMT_MODE_RX, channel: C::channel(), gpio_num: pin.pin(), @@ -968,8 +1011,12 @@ impl<'d> RxRmtDriver<'d> { }; unsafe { - esp!(rmt_config(&config))?; - esp!(rmt_driver_install(C::channel(), ring_buf_size * 4, 0))?; + esp!(rmt_config(&sys_config))?; + esp!(rmt_driver_install( + C::channel(), + ring_buf_size * 4, + IntrFlags::to_native(config.intr_flags) as _ + ))?; } Ok(Self { diff --git a/src/spi.rs b/src/spi.rs index 8fe335be5..b4d20467a 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -45,6 +45,7 @@ use esp_idf_sys::*; use crate::delay::{Ets, BLOCK}; use crate::gpio::{AnyOutputPin, InputPin, Level, Output, OutputPin, PinDriver}; +use crate::interrupt::IntrFlags; use crate::peripheral::Peripheral; use crate::task::CriticalSection; @@ -96,13 +97,17 @@ impl Dma { } } +pub type SpiDriverConfig = config::DriverConfig; pub type SpiConfig = config::Config; /// SPI configuration pub mod config { - use crate::units::*; + use crate::{interrupt::IntrFlags, units::*}; + use enumset::EnumSet; use esp_idf_sys::*; + use super::Dma; + pub struct V02Type(pub T); impl From> for embedded_hal::spi::Polarity { @@ -137,7 +142,7 @@ pub mod config { } /// Specify the communication mode with the device - #[derive(Copy, Clone)] + #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum Duplex { /// Full duplex is the default Full, @@ -158,7 +163,7 @@ pub mod config { } /// Specifies the order in which the bits of data should be transfered/received - #[derive(Copy, Clone)] + #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum BitOrder { /// Most significant bit first (default) MsbFirst, @@ -181,8 +186,42 @@ pub mod config { } } + /// SPI Driver configuration + #[derive(Debug, Clone)] + pub struct DriverConfig { + pub dma: Dma, + pub intr_flags: EnumSet, + } + + impl DriverConfig { + pub fn new() -> Self { + Default::default() + } + + #[must_use] + pub fn dma(mut self, dma: Dma) -> Self { + self.dma = dma; + self + } + + #[must_use] + pub fn intr_flags(mut self, intr_flags: EnumSet) -> Self { + self.intr_flags = intr_flags; + self + } + } + + impl Default for DriverConfig { + fn default() -> Self { + Self { + dma: Dma::Disabled, + intr_flags: EnumSet::::empty(), + } + } + } + /// SPI Device configuration - #[derive(Copy, Clone)] + #[derive(Debug, Clone)] pub struct Config { pub baudrate: Hertz, pub data_mode: embedded_hal::spi::Mode, @@ -214,26 +253,31 @@ pub mod config { self } + #[must_use] pub fn write_only(mut self, write_only: bool) -> Self { self.write_only = write_only; self } + #[must_use] pub fn duplex(mut self, duplex: Duplex) -> Self { self.duplex = duplex; self } + #[must_use] pub fn bit_order(mut self, bit_order: BitOrder) -> Self { self.bit_order = bit_order; self } + #[must_use] pub fn cs_active_high(mut self) -> Self { self.cs_active_high = true; self } + #[must_use] pub fn input_delay_ns(mut self, input_delay_ns: i32) -> Self { self.input_delay_ns = input_delay_ns; self @@ -476,9 +520,9 @@ impl<'d> SpiDriver<'d> { sclk: impl Peripheral

+ 'd, sdo: impl Peripheral

+ 'd, sdi: Option + 'd>, - dma: Dma, + config: &config::DriverConfig, ) -> Result { - let max_transfer_size = Self::new_internal(SPI1::device(), sclk, sdo, sdi, dma)?; + let max_transfer_size = Self::new_internal(SPI1::device(), sclk, sdo, sdi, config)?; Ok(Self { host: SPI1::device() as _, @@ -493,9 +537,9 @@ impl<'d> SpiDriver<'d> { sclk: impl Peripheral

+ 'd, sdo: impl Peripheral

+ 'd, sdi: Option + 'd>, - dma: Dma, + config: &config::DriverConfig, ) -> Result { - let max_transfer_size = Self::new_internal(SPI::device(), sclk, sdo, sdi, dma)?; + let max_transfer_size = Self::new_internal(SPI::device(), sclk, sdo, sdi, config)?; Ok(Self { host: SPI::device() as _, @@ -513,14 +557,15 @@ impl<'d> SpiDriver<'d> { sclk: impl Peripheral

+ 'd, sdo: impl Peripheral

+ 'd, sdi: Option + 'd>, - dma: Dma, + config: &config::DriverConfig, ) -> Result { crate::into_ref!(sclk, sdo); let sdi = sdi.map(|sdi| sdi.into_ref()); - let max_transfer_sz = dma.max_transfer_size(); - let dma_chan: spi_dma_chan_t = dma.into(); + let max_transfer_sz = config.dma.max_transfer_size(); + let dma_chan: spi_dma_chan_t = config.dma.into(); + #[allow(clippy::needless_update)] #[cfg(not(esp_idf_version = "4.3"))] let bus_config = spi_bus_config_t { flags: SPICOMMON_BUSFLAG_MASTER, @@ -547,9 +592,11 @@ impl<'d> SpiDriver<'d> { //data3_io_num: -1, }, max_transfer_sz: max_transfer_sz as i32, + intr_flags: IntrFlags::to_native(config.intr_flags) as _, ..Default::default() }; + #[allow(clippy::needless_update)] #[cfg(esp_idf_version = "4.3")] let bus_config = spi_bus_config_t { flags: SPICOMMON_BUSFLAG_MASTER, @@ -561,6 +608,7 @@ impl<'d> SpiDriver<'d> { quadhd_io_num: -1, max_transfer_sz: max_transfer_sz as i32, + intr_flags: config.intr_flags.into() as _, ..Default::default() }; @@ -594,11 +642,15 @@ impl<'d> SpiDeviceDriver<'d, SpiDriver<'d>> { sclk: impl Peripheral

+ 'd, sdo: impl Peripheral

+ 'd, sdi: Option + 'd>, - dma: Dma, cs: Option + 'd>, + bus_config: &config::DriverConfig, config: &config::Config, ) -> Result { - Self::new(SpiDriver::new_spi1(spi, sclk, sdo, sdi, dma)?, cs, config) + Self::new( + SpiDriver::new_spi1(spi, sclk, sdo, sdi, bus_config)?, + cs, + config, + ) } pub fn new_single( @@ -606,11 +658,11 @@ impl<'d> SpiDeviceDriver<'d, SpiDriver<'d>> { sclk: impl Peripheral

+ 'd, sdo: impl Peripheral

+ 'd, sdi: Option + 'd>, - dma: Dma, cs: Option + 'd>, + bus_config: &config::DriverConfig, config: &config::Config, ) -> Result { - Self::new(SpiDriver::new(spi, sclk, sdo, sdi, dma)?, cs, config) + Self::new(SpiDriver::new(spi, sclk, sdo, sdi, bus_config)?, cs, config) } } diff --git a/src/uart.rs b/src/uart.rs index bfca3ee68..6aca7d8e6 100644 --- a/src/uart.rs +++ b/src/uart.rs @@ -44,6 +44,7 @@ use core::sync::atomic::{AtomicU8, Ordering}; use crate::delay::NON_BLOCK; use crate::gpio::*; +use crate::interrupt::IntrFlags; use crate::units::*; use esp_idf_sys::*; @@ -56,7 +57,8 @@ pub type UartConfig = config::Config; /// UART configuration pub mod config { - use crate::units::*; + use crate::{interrupt::IntrFlags, units::*}; + use enumset::EnumSet; use esp_idf_sys::*; /// Number of data bits @@ -299,7 +301,7 @@ pub mod config { } /// UART configuration - #[derive(Debug, Copy, Clone)] + #[derive(Debug, Clone)] pub struct Config { pub baudrate: Hertz, pub data_bits: DataBits, @@ -308,6 +310,7 @@ pub mod config { pub flow_control: FlowControl, pub flow_control_rts_threshold: u8, pub source_clock: SourceClock, + pub intr_flags: EnumSet, } impl Config { @@ -383,6 +386,7 @@ pub mod config { flow_control: FlowControl::None, flow_control_rts_threshold: 122, source_clock: SourceClock::default(), + intr_flags: EnumSet::::empty(), } } } @@ -934,6 +938,7 @@ fn new_common( }; esp!(unsafe { uart_param_config(UART::port(), &uart_config) })?; + esp!(unsafe { uart_intr_config(UART::port(), IntrFlags::to_native(config.intr_flags) as _) })?; esp!(unsafe { uart_set_pin(