From 967fa1b2a2b551dfac9925e46817c97c7ec711f7 Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Mon, 17 Jun 2024 20:56:40 -0600 Subject: stm32 i2c slave --- embassy-stm32/src/i2c/config.rs | 149 ++++++++++++++ embassy-stm32/src/i2c/mod.rs | 161 ++++++++++++--- embassy-stm32/src/i2c/v2.rs | 442 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 681 insertions(+), 71 deletions(-) create mode 100644 embassy-stm32/src/i2c/config.rs diff --git a/embassy-stm32/src/i2c/config.rs b/embassy-stm32/src/i2c/config.rs new file mode 100644 index 000000000..eba14f6e0 --- /dev/null +++ b/embassy-stm32/src/i2c/config.rs @@ -0,0 +1,149 @@ +use stm32_metapac::i2c::vals::Oamsk; + +use crate::gpio::Pull; + +#[repr(u8)] +#[derive(Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum AddrMask { + NOMASK, + MASK1, + MASK2, + MASK3, + MASK4, + MASK5, + MASK6, + MASK7, +} +impl From for Oamsk { + fn from(value: AddrMask) -> Self { + match value { + AddrMask::NOMASK => Oamsk::NOMASK, + AddrMask::MASK1 => Oamsk::MASK1, + AddrMask::MASK2 => Oamsk::MASK2, + AddrMask::MASK3 => Oamsk::MASK3, + AddrMask::MASK4 => Oamsk::MASK4, + AddrMask::MASK5 => Oamsk::MASK5, + AddrMask::MASK6 => Oamsk::MASK6, + AddrMask::MASK7 => Oamsk::MASK7, + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Address { + SevenBit(u8), + TenBit(u16), +} +impl From for Address { + fn from(value: u8) -> Self { + Address::SevenBit(value) + } +} +impl From for Address { + fn from(value: u16) -> Self { + assert!(value < 0x400, "Ten bit address must be less than 0x400"); + Address::TenBit(value) + } +} +impl Address { + pub(super) fn add_mode(&self) -> stm32_metapac::i2c::vals::Addmode { + match self { + Address::SevenBit(_) => stm32_metapac::i2c::vals::Addmode::BIT7, + Address::TenBit(_) => stm32_metapac::i2c::vals::Addmode::BIT10, + } + } + pub fn addr(&self) -> u16 { + match self { + Address::SevenBit(addr) => *addr as u16, + Address::TenBit(addr) => *addr, + } + } +} + +#[derive(Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct OA2 { + pub addr: u8, + pub mask: AddrMask, +} + +#[derive(Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum OwnAddresses { + OA1(Address), + OA2(OA2), + Both { oa1: Address, oa2: OA2 }, +} + +/// Slave Configuration +#[derive(Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct SlaveAddrConfig { + /// Target Address(es) + pub addr: OwnAddresses, + /// Control if the peripheral should respond to the general call address + pub general_call: bool, +} +impl SlaveAddrConfig { + pub fn new_oa1(addr: Address, general_call: bool) -> Self { + Self { + addr: OwnAddresses::OA1(addr), + general_call, + } + } + + pub fn basic(addr: Address) -> Self { + Self { + addr: OwnAddresses::OA1(addr), + general_call: false, + } + } +} + +/// I2C config +#[non_exhaustive] +#[derive(Copy, Clone)] +pub struct Config { + /// Enable internal pullup on SDA. + /// + /// Using external pullup resistors is recommended for I2C. If you do + /// have external pullups you should not enable this. + pub sda_pullup: bool, + /// Enable internal pullup on SCL. + /// + /// Using external pullup resistors is recommended for I2C. If you do + /// have external pullups you should not enable this. + pub scl_pullup: bool, + /// Timeout. + #[cfg(feature = "time")] + pub timeout: embassy_time::Duration, +} + +impl Default for Config { + fn default() -> Self { + Self { + sda_pullup: false, + scl_pullup: false, + #[cfg(feature = "time")] + timeout: embassy_time::Duration::from_millis(1000), + } + } +} + +impl Config { + pub(super) fn scl_pull_mode(&self) -> Pull { + match self.scl_pullup { + true => Pull::Up, + false => Pull::Down, + } + } + + pub(super) fn sda_pull_mode(&self) -> Pull { + match self.sda_pullup { + true => Pull::Up, + false => Pull::Down, + } + } +} diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 739e960b9..0457595d2 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -5,14 +5,18 @@ #[cfg_attr(any(i2c_v2, i2c_v3), path = "v2.rs")] mod _version; +mod config; + use core::future::Future; use core::iter; use core::marker::PhantomData; +pub use config::*; use embassy_hal_internal::{Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; #[cfg(feature = "time")] use embassy_time::{Duration, Instant}; +use mode::{Master, MasterMode, MultiMaster}; use crate::dma::ChannelAndRequest; #[cfg(gpio_v2)] @@ -108,8 +112,56 @@ impl Config { } } +/// I2C modes +pub mod mode { + trait SealedMode {} + + /// Trait for I2C master operations. + #[allow(private_bounds)] + pub trait MasterMode: SealedMode {} + + /// Mode allowing for I2C master operations. + pub struct Master; + /// Mode allowing for I2C master and slave operations. + pub struct MultiMaster; + + impl SealedMode for Master {} + impl MasterMode for Master {} + + impl SealedMode for MultiMaster {} + impl MasterMode for MultiMaster {} +} + +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// The command kind to the slave from the master +pub enum CommandKind { + /// Write to the slave + SlaveReceive, + /// Read from the slave + SlaveSend, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// The command kind to the slave from the master and the address that the slave matched +pub struct Command { + pub kind: CommandKind, + pub address: Address, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// The status of the slave send operation +pub enum SendStatus { + /// The slave send operation is done, all bytes have been sent and the master is not requesting more + Done, + /// The slave send operation is done, but there are leftover bytes that the master did not read + LeftoverBytes(usize), +} + /// I2C driver. -pub struct I2c<'d, M: Mode> { +pub struct I2c<'d, M: Mode, IM: MasterMode> { info: &'static Info, state: &'static State, kernel_clock: Hertz, @@ -120,9 +172,10 @@ pub struct I2c<'d, M: Mode> { #[cfg(feature = "time")] timeout: Duration, _phantom: PhantomData, + _phantom2: PhantomData, } -impl<'d> I2c<'d, Async> { +impl<'d> I2c<'d, Async, Master> { /// Create a new I2C driver. pub fn new( peri: impl Peripheral

+ 'd, @@ -148,7 +201,7 @@ impl<'d> I2c<'d, Async> { } } -impl<'d> I2c<'d, Blocking> { +impl<'d> I2c<'d, Blocking, Master> { /// Create a new blocking I2C driver. pub fn new_blocking( peri: impl Peripheral

+ 'd, @@ -169,7 +222,7 @@ impl<'d> I2c<'d, Blocking> { } } -impl<'d, M: Mode> I2c<'d, M> { +impl<'d, M: Mode> I2c<'d, M, Master> { /// Create a new I2C driver. fn new_inner( _peri: impl Peripheral

+ 'd, @@ -194,8 +247,10 @@ impl<'d, M: Mode> I2c<'d, M> { #[cfg(feature = "time")] timeout: config.timeout, _phantom: PhantomData, + _phantom2: PhantomData, }; this.enable_and_init(freq, config); + this } @@ -203,7 +258,9 @@ impl<'d, M: Mode> I2c<'d, M> { self.info.rcc.enable_and_reset(); self.init(freq, config); } +} +impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { fn timeout(&self) -> Timeout { Timeout { #[cfg(feature = "time")] @@ -211,8 +268,28 @@ impl<'d, M: Mode> I2c<'d, M> { } } } +impl<'d, M: Mode> I2c<'d, M, Master> { + /// Configure the I2C driver for slave operations, allowing for the driver to be used as a slave and a master (multimaster) + pub fn into_slave_multimaster(mut self, slave_addr_config: SlaveAddrConfig) -> I2c<'d, M, MultiMaster> { + let mut slave = I2c { + info: self.info, + state: self.state, + kernel_clock: self.kernel_clock, + scl: self.scl.take(), + sda: self.sda.take(), + tx_dma: self.tx_dma.take(), + rx_dma: self.rx_dma.take(), + #[cfg(feature = "time")] + timeout: self.timeout, + _phantom: PhantomData, + _phantom2: PhantomData, + }; + slave.init_slave(slave_addr_config); + slave + } +} -impl<'d, M: Mode> Drop for I2c<'d, M> { +impl<'d, M: Mode, IM: MasterMode> Drop for I2c<'d, M, IM> { fn drop(&mut self) { self.scl.as_ref().map(|x| x.set_as_disconnected()); self.sda.as_ref().map(|x| x.set_as_disconnected()); @@ -329,27 +406,39 @@ foreach_peripheral!( }; ); -impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M> { +impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> + embedded_hal_02::blocking::i2c::Read for I2c<'d, M, IM> +where + A: Into

, +{ type Error = Error; - fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_read(address, buffer) + fn read(&mut self, address: A, buffer: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_read(address.into(), buffer) } } -impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M> { +impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> + embedded_hal_02::blocking::i2c::Write for I2c<'d, M, IM> +where + A: Into
, +{ type Error = Error; - fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(address, write) + fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(address.into(), write) } } -impl<'d, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M> { +impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> + embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M, IM> +where + A: Into
, +{ type Error = Error; - fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_write_read(address, write, read) + fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_write_read(address.into(), write, read) } } @@ -369,51 +458,57 @@ impl embedded_hal_1::i2c::Error for Error { } } -impl<'d, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, M> { +impl<'d, M: Mode, IM: MasterMode> embedded_hal_1::i2c::ErrorType for I2c<'d, M, IM> { type Error = Error; } -impl<'d, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, M> { - fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_read(address, read) +impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_1::i2c::AddressMode> embedded_hal_1::i2c::I2c for I2c<'d, M, IM> +where + Address: From, +{ + fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_read(address.into(), read) } - fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(address, write) + fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(address.into(), write) } - fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_write_read(address, write, read) + fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_write_read(address.into(), write, read) } fn transaction( &mut self, - address: u8, + address: A, operations: &mut [embedded_hal_1::i2c::Operation<'_>], ) -> Result<(), Self::Error> { - self.blocking_transaction(address, operations) + self.blocking_transaction(address.into(), operations) } } -impl<'d> embedded_hal_async::i2c::I2c for I2c<'d, Async> { - async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { - self.read(address, read).await +impl<'d, IM: MasterMode, A: embedded_hal_async::i2c::AddressMode> embedded_hal_async::i2c::I2c for I2c<'d, Async, IM> +where + Address: From, +{ + async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> { + self.read(address.into(), read).await } - async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { - self.write(address, write).await + async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { + self.write(address.into(), write).await } - async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { - self.write_read(address, write, read).await + async fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { + self.write_read(address.into(), write, read).await } async fn transaction( &mut self, - address: u8, + address: A, operations: &mut [embedded_hal_1::i2c::Operation<'_>], ) -> Result<(), Self::Error> { - self.transaction(address, operations).await + self.transaction(address.into(), operations).await } } diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 8c8df79dd..c2560d819 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -2,9 +2,12 @@ use core::cmp; use core::future::poll_fn; use core::task::Poll; +use config::{Address, OwnAddresses, OA2}; use embassy_embedded_hal::SetConfig; use embassy_hal_internal::drop::OnDrop; use embedded_hal_1::i2c::Operation; +use mode::Master; +use stm32_metapac::i2c::vals::Addmode; use super::*; use crate::pac::i2c; @@ -13,17 +16,21 @@ pub(crate) unsafe fn on_interrupt() { let regs = T::info().regs; let isr = regs.isr().read(); - if isr.tcr() || isr.tc() { + if isr.tcr() || isr.tc() || isr.addr() || isr.stopf() { T::state().waker.wake(); } - // The flag can only be cleared by writting to nbytes, we won't do that here, so disable - // the interrupt + critical_section::with(|_| { - regs.cr1().modify(|w| w.set_tcie(false)); + regs.cr1().modify(|w| { + w.set_addrie(false); + // The flag can only be cleared by writting to nbytes, we won't do that here, so disable + // the interrupt + w.set_tcie(false); + }); }); } -impl<'d, M: Mode> I2c<'d, M> { +impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { self.info.regs.cr1().modify(|reg| { reg.set_pe(false); @@ -51,7 +58,7 @@ impl<'d, M: Mode> I2c<'d, M> { fn master_read( info: &'static Info, - address: u8, + address: Address, length: usize, stop: Stop, reload: bool, @@ -80,8 +87,8 @@ impl<'d, M: Mode> I2c<'d, M> { }; info.regs.cr2().modify(|w| { - w.set_sadd((address << 1 | 0) as u16); - w.set_add10(i2c::vals::Addmode::BIT7); + w.set_sadd(address.addr() << 1); + w.set_add10(address.add_mode()); w.set_dir(i2c::vals::Dir::READ); w.set_nbytes(length as u8); w.set_start(true); @@ -94,7 +101,7 @@ impl<'d, M: Mode> I2c<'d, M> { fn master_write( info: &'static Info, - address: u8, + address: Address, length: usize, stop: Stop, reload: bool, @@ -124,8 +131,8 @@ impl<'d, M: Mode> I2c<'d, M> { // START bit can be set even if the bus is BUSY or // I2C is in slave mode. info.regs.cr2().modify(|w| { - w.set_sadd((address << 1 | 0) as u16); - w.set_add10(i2c::vals::Addmode::BIT7); + w.set_sadd(address.addr() << 1); + w.set_add10(address.add_mode()); w.set_dir(i2c::vals::Dir::WRITE); w.set_nbytes(length as u8); w.set_start(true); @@ -136,14 +143,14 @@ impl<'d, M: Mode> I2c<'d, M> { Ok(()) } - fn master_continue(info: &'static Info, length: usize, reload: bool, timeout: Timeout) -> Result<(), Error> { + fn reload(info: &'static Info, length: usize, will_reload: bool, timeout: Timeout) -> Result<(), Error> { assert!(length < 256 && length > 0); while !info.regs.isr().read().tcr() { timeout.check()?; } - let reload = if reload { + let will_reload = if will_reload { i2c::vals::Reload::NOTCOMPLETED } else { i2c::vals::Reload::COMPLETED @@ -151,7 +158,7 @@ impl<'d, M: Mode> I2c<'d, M> { info.regs.cr2().modify(|w| { w.set_nbytes(length as u8); - w.set_reload(reload); + w.set_reload(will_reload); }); Ok(()) @@ -229,7 +236,13 @@ impl<'d, M: Mode> I2c<'d, M> { } } - fn read_internal(&mut self, address: u8, read: &mut [u8], restart: bool, timeout: Timeout) -> Result<(), Error> { + fn read_internal( + &mut self, + address: Address, + read: &mut [u8], + restart: bool, + timeout: Timeout, + ) -> Result<(), Error> { let completed_chunks = read.len() / 255; let total_chunks = if completed_chunks * 255 == read.len() { completed_chunks @@ -250,7 +263,7 @@ impl<'d, M: Mode> I2c<'d, M> { for (number, chunk) in read.chunks_mut(255).enumerate() { if number != 0 { - Self::master_continue(self.info, chunk.len(), number != last_chunk_idx, timeout)?; + Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; } for byte in chunk { @@ -263,7 +276,13 @@ impl<'d, M: Mode> I2c<'d, M> { Ok(()) } - fn write_internal(&mut self, address: u8, write: &[u8], send_stop: bool, timeout: Timeout) -> Result<(), Error> { + fn write_internal( + &mut self, + address: Address, + write: &[u8], + send_stop: bool, + timeout: Timeout, + ) -> Result<(), Error> { let completed_chunks = write.len() / 255; let total_chunks = if completed_chunks * 255 == write.len() { completed_chunks @@ -291,7 +310,7 @@ impl<'d, M: Mode> I2c<'d, M> { for (number, chunk) in write.chunks(255).enumerate() { if number != 0 { - Self::master_continue(self.info, chunk.len(), number != last_chunk_idx, timeout)?; + Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; } for byte in chunk { @@ -320,18 +339,18 @@ impl<'d, M: Mode> I2c<'d, M> { // Blocking public API /// Blocking read. - pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { + pub fn blocking_read(&mut self, address: Address, read: &mut [u8]) -> Result<(), Error> { self.read_internal(address, read, false, self.timeout()) // Automatic Stop } /// Blocking write. - pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { + pub fn blocking_write(&mut self, address: Address, write: &[u8]) -> Result<(), Error> { self.write_internal(address, write, true, self.timeout()) } /// Blocking write, restart, read. - pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { + pub fn blocking_write_read(&mut self, address: Address, write: &[u8], read: &mut [u8]) -> Result<(), Error> { let timeout = self.timeout(); self.write_internal(address, write, false, timeout)?; self.read_internal(address, read, true, timeout) @@ -343,7 +362,7 @@ impl<'d, M: Mode> I2c<'d, M> { /// Consecutive operations of same type are merged. See [transaction contract] for details. /// /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction - pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { + pub fn blocking_transaction(&mut self, addr: Address, operations: &mut [Operation<'_>]) -> Result<(), Error> { let _ = addr; let _ = operations; todo!() @@ -352,7 +371,7 @@ impl<'d, M: Mode> I2c<'d, M> { /// Blocking write multiple buffers. /// /// The buffers are concatenated in a single write transaction. - pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { + pub fn blocking_write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> { if write.is_empty() { return Err(Error::ZeroLengthTransfer); } @@ -385,7 +404,7 @@ impl<'d, M: Mode> I2c<'d, M> { let last_chunk_idx = total_chunks.saturating_sub(1); if idx != 0 { - if let Err(err) = Self::master_continue( + if let Err(err) = Self::reload( self.info, slice_len.min(255), (idx != last_slice_index) || (slice_len > 255), @@ -398,7 +417,7 @@ impl<'d, M: Mode> I2c<'d, M> { for (number, chunk) in slice.chunks(255).enumerate() { if number != 0 { - if let Err(err) = Self::master_continue( + if let Err(err) = Self::reload( self.info, chunk.len(), (number != last_chunk_idx) || (idx != last_slice_index), @@ -431,10 +450,10 @@ impl<'d, M: Mode> I2c<'d, M> { } } -impl<'d> I2c<'d, Async> { +impl<'d, IM: MasterMode> I2c<'d, Async, IM> { async fn write_dma_internal( &mut self, - address: u8, + address: Address, write: &[u8], first_slice: bool, last_slice: bool, @@ -482,7 +501,7 @@ impl<'d> I2c<'d, Async> { timeout, )?; } else { - Self::master_continue(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?; + Self::reload(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?; self.info.regs.cr1().modify(|w| w.set_tcie(true)); } } else if !(isr.tcr() || isr.tc()) { @@ -493,7 +512,7 @@ impl<'d> I2c<'d, Async> { } else { let last_piece = (remaining_len <= 255) && last_slice; - if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) { + if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, timeout) { return Poll::Ready(Err(e)); } self.info.regs.cr1().modify(|w| w.set_tcie(true)); @@ -519,7 +538,7 @@ impl<'d> I2c<'d, Async> { async fn read_dma_internal( &mut self, - address: u8, + address: Address, buffer: &mut [u8], restart: bool, timeout: Timeout, @@ -569,7 +588,7 @@ impl<'d> I2c<'d, Async> { } else { let last_piece = remaining_len <= 255; - if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) { + if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, timeout) { return Poll::Ready(Err(e)); } self.info.regs.cr1().modify(|w| w.set_tcie(true)); @@ -590,12 +609,11 @@ impl<'d> I2c<'d, Async> { Ok(()) } - // ========================= // Async public API /// Write. - pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { + pub async fn write(&mut self, address: Address, write: &[u8]) -> Result<(), Error> { let timeout = self.timeout(); if write.is_empty() { self.write_internal(address, write, true, timeout) @@ -609,7 +627,7 @@ impl<'d> I2c<'d, Async> { /// Write multiple buffers. /// /// The buffers are concatenated in a single write transaction. - pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { + pub async fn write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> { let timeout = self.timeout(); if write.is_empty() { @@ -632,7 +650,7 @@ impl<'d> I2c<'d, Async> { } /// Read. - pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { + pub async fn read(&mut self, address: Address, buffer: &mut [u8]) -> Result<(), Error> { let timeout = self.timeout(); if buffer.is_empty() { @@ -644,7 +662,7 @@ impl<'d> I2c<'d, Async> { } /// Write, restart, read. - pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { + pub async fn write_read(&mut self, address: Address, write: &[u8], read: &mut [u8]) -> Result<(), Error> { let timeout = self.timeout(); if write.is_empty() { @@ -669,13 +687,343 @@ impl<'d> I2c<'d, Async> { /// Consecutive operations of same type are merged. See [transaction contract] for details. /// /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction - pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { + pub async fn transaction(&mut self, addr: Address, operations: &mut [Operation<'_>]) -> Result<(), Error> { let _ = addr; let _ = operations; todo!() } } +impl<'d, M: Mode> I2c<'d, M, MultiMaster> { + pub(crate) fn init_slave(&mut self, config: SlaveAddrConfig) { + self.info.regs.cr1().modify(|reg| { + reg.set_pe(false); + }); + + self.info.regs.cr1().modify(|reg| { + reg.set_nostretch(false); + reg.set_gcen(config.general_call); + reg.set_sbc(true); + reg.set_pe(true); + }); + + self.reconfigure_addresses(config.addr); + } + + /// Configure the slave address. + pub fn reconfigure_addresses(&mut self, addresses: OwnAddresses) { + match addresses { + OwnAddresses::OA1(oa1) => self.configure_oa1(oa1), + OwnAddresses::OA2(oa2) => self.configure_oa2(oa2), + OwnAddresses::Both { oa1, oa2 } => { + self.configure_oa1(oa1); + self.configure_oa2(oa2); + } + } + } + + fn configure_oa1(&mut self, oa1: Address) { + match oa1 { + Address::SevenBit(addr) => self.info.regs.oar1().write(|reg| { + reg.set_oa1en(false); + reg.set_oa1((addr << 1) as u16); + reg.set_oa1mode(Addmode::BIT7); + reg.set_oa1en(true); + }), + Address::TenBit(addr) => self.info.regs.oar1().write(|reg| { + reg.set_oa1en(false); + reg.set_oa1(addr); + reg.set_oa1mode(Addmode::BIT10); + reg.set_oa1en(true); + }), + } + } + + fn configure_oa2(&mut self, oa2: OA2) { + self.info.regs.oar2().write(|reg| { + reg.set_oa2en(false); + reg.set_oa2msk(oa2.mask.into()); + reg.set_oa2(oa2.addr << 1); + reg.set_oa2en(true); + }); + } + + fn determine_matched_address(&self) -> Result { + let matched = self.info.regs.isr().read().addcode(); + + if matched >> 3 == 0b11110 { + // is 10-bit address and we need to get the other 8 bits from the rxdr + // we do this by doing a blocking read of 1 byte + let mut buffer = [0]; + self.slave_read_internal(&mut buffer, self.timeout())?; + Ok(Address::TenBit((matched as u16) << 6 | buffer[0] as u16)) + } else { + Ok(Address::SevenBit(matched)) + } + } +} + +impl<'d, M: Mode> I2c<'d, M, MultiMaster> { + /// # Safety + /// This function will clear the address flag which will stop the clock stretching. + /// This should only be done after the dma transfer has been set up. + fn slave_start(info: &'static Info, length: usize, reload: bool) { + assert!(length < 256); + + let reload = if reload { + i2c::vals::Reload::NOTCOMPLETED + } else { + i2c::vals::Reload::COMPLETED + }; + + info.regs.cr2().modify(|w| { + w.set_nbytes(length as u8); + w.set_reload(reload); + }); + + // clear the address flag, will stop the clock stretching. + // this should only be done after the dma transfer has been set up. + info.regs.icr().modify(|reg| reg.set_addrcf(true)); + } + + // A blocking read operation + fn slave_read_internal(&self, read: &mut [u8], timeout: Timeout) -> Result<(), Error> { + let completed_chunks = read.len() / 255; + let total_chunks = if completed_chunks * 255 == read.len() { + completed_chunks + } else { + completed_chunks + 1 + }; + let last_chunk_idx = total_chunks.saturating_sub(1); + for (number, chunk) in read.chunks_mut(255).enumerate() { + if number != 0 { + Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; + } + + for byte in chunk { + // Wait until we have received something + self.wait_rxne(timeout)?; + + *byte = self.info.regs.rxdr().read().rxdata(); + } + } + + Ok(()) + } + + // A blocking write operation + fn slave_write_internal(&mut self, write: &[u8], timeout: Timeout) -> Result<(), Error> { + let completed_chunks = write.len() / 255; + let total_chunks = if completed_chunks * 255 == write.len() { + completed_chunks + } else { + completed_chunks + 1 + }; + let last_chunk_idx = total_chunks.saturating_sub(1); + + for (number, chunk) in write.chunks(255).enumerate() { + if number != 0 { + Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; + } + + for byte in chunk { + // Wait until we are allowed to send data + // (START has been ACKed or last byte when + // through) + self.wait_txe(timeout)?; + + self.info.regs.txdr().write(|w| w.set_txdata(*byte)); + } + } + Ok(()) + } + + /// Listen for incoming I2C messages. + /// + /// The listen method is an asynchronous method but it does not require DMA to be asynchronous. + pub async fn listen(&mut self) -> Result { + let state = self.state; + self.info.regs.cr1().modify(|reg| { + reg.set_addrie(true); + }); + + poll_fn(|cx| { + state.waker.register(cx.waker()); + let isr = self.info.regs.isr().read(); + if !isr.addr() { + Poll::Pending + } else { + // we do not clear the address flag here as it will be cleared by the dma read/write + // if we clear it here the clock stretching will stop and the master will read in data before the slave is ready to send it + match isr.dir() { + i2c::vals::Dir::WRITE => Poll::Ready(Ok(Command { + kind: CommandKind::SlaveReceive, + address: self.determine_matched_address()?, + })), + i2c::vals::Dir::READ => Poll::Ready(Ok(Command { + kind: CommandKind::SlaveSend, + address: self.determine_matched_address()?, + })), + } + } + }) + .await + } + + /// Respond to a receive command. + pub fn blocking_respond_to_receive(&self, read: &mut [u8]) -> Result<(), Error> { + let timeout = self.timeout(); + self.slave_read_internal(read, timeout) + } + + /// Respond to a send command. + pub fn blocking_respond_to_send(&mut self, write: &[u8]) -> Result<(), Error> { + let timeout = self.timeout(); + self.slave_write_internal(write, timeout) + } +} + +impl<'d> I2c<'d, Async, MultiMaster> { + /// Respond to a receive command. + pub async fn respond_to_receive(&mut self, buffer: &mut [u8]) -> Result { + let timeout = self.timeout(); + timeout.with(self.read_dma_internal_slave(buffer, timeout)).await + } + + /// Respond to a send request from an I2C master. + pub async fn respond_to_send(&mut self, write: &[u8]) -> Result { + let timeout = self.timeout(); + timeout.with(self.write_dma_internal_slave(write, timeout)).await + } + + // for data reception in slave mode + async fn read_dma_internal_slave(&mut self, buffer: &mut [u8], timeout: Timeout) -> Result { + let total_len = buffer.len(); + let mut remaining_len = total_len; + + let regs = self.info.regs; + + let dma_transfer = unsafe { + regs.cr1().modify(|w| { + w.set_rxdmaen(true); + w.set_stopie(true); + w.set_tcie(true); + }); + let src = regs.rxdr().as_ptr() as *mut u8; + + self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default()) + }; + + let state = self.state; + + let on_drop = OnDrop::new(|| { + regs.cr1().modify(|w| { + w.set_rxdmaen(false); + w.set_stopie(false); + w.set_tcie(false); + }) + }); + + let total_received = poll_fn(|cx| { + state.waker.register(cx.waker()); + + let isr = regs.isr().read(); + + if remaining_len == total_len { + Self::slave_start(self.info, total_len.min(255), total_len > 255); + remaining_len = remaining_len.saturating_sub(255); + Poll::Pending + } else if isr.tcr() { + let is_last_slice = remaining_len <= 255; + if let Err(e) = Self::reload(self.info, remaining_len.min(255), !is_last_slice, timeout) { + return Poll::Ready(Err(e)); + } + remaining_len = remaining_len.saturating_sub(255); + regs.cr1().modify(|w| w.set_tcie(true)); + Poll::Pending + } else if isr.stopf() { + regs.icr().write(|reg| reg.set_stopcf(true)); + let poll = Poll::Ready(Ok(remaining_len)); + poll + } else { + Poll::Pending + } + }) + .await?; + + dma_transfer.await; + + drop(on_drop); + + Ok(total_received) + } + + async fn write_dma_internal_slave(&mut self, buffer: &[u8], timeout: Timeout) -> Result { + let total_len = buffer.len(); + let mut remaining_len = total_len; + + let mut dma_transfer = unsafe { + let regs = self.info.regs; + regs.cr1().modify(|w| { + w.set_txdmaen(true); + w.set_stopie(true); + w.set_tcie(true); + }); + let dst = regs.txdr().as_ptr() as *mut u8; + + self.tx_dma.as_mut().unwrap().write(buffer, dst, Default::default()) + }; + + let on_drop = OnDrop::new(|| { + let regs = self.info.regs; + regs.cr1().modify(|w| { + w.set_txdmaen(false); + w.set_stopie(false); + w.set_tcie(false); + }) + }); + + let state = self.state; + + let size = poll_fn(|cx| { + state.waker.register(cx.waker()); + + let isr = self.info.regs.isr().read(); + + if remaining_len == total_len { + Self::slave_start(self.info, total_len.min(255), total_len > 255); + remaining_len = remaining_len.saturating_sub(255); + Poll::Pending + } else if isr.tcr() { + let is_last_slice = remaining_len <= 255; + if let Err(e) = Self::reload(self.info, remaining_len.min(255), !is_last_slice, timeout) { + return Poll::Ready(Err(e)); + } + remaining_len = remaining_len.saturating_sub(255); + self.info.regs.cr1().modify(|w| w.set_tcie(true)); + Poll::Pending + } else if isr.stopf() { + self.info.regs.icr().write(|reg| reg.set_stopcf(true)); + if remaining_len > 0 { + dma_transfer.request_stop(); + Poll::Ready(Ok(SendStatus::LeftoverBytes(remaining_len as usize))) + } else { + Poll::Ready(Ok(SendStatus::Done)) + } + } else { + Poll::Pending + } + }) + .await?; + + dma_transfer.await; + + drop(on_drop); + + Ok(size) + } +} + /// I2C Stop Configuration /// /// Peripheral options for generating the STOP condition @@ -800,7 +1148,7 @@ impl Timings { } } -impl<'d, M: Mode> SetConfig for I2c<'d, M> { +impl<'d, M: Mode> SetConfig for I2c<'d, M, Master> { type Config = Hertz; type ConfigError = (); fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { @@ -816,3 +1164,21 @@ impl<'d, M: Mode> SetConfig for I2c<'d, M> { Ok(()) } } + +impl<'d, M: Mode> SetConfig for I2c<'d, M, MultiMaster> { + type Config = (Hertz, SlaveAddrConfig); + type ConfigError = (); + fn set_config(&mut self, (config, addr_config): &Self::Config) -> Result<(), ()> { + let timings = Timings::new(self.kernel_clock, *config); + self.info.regs.timingr().write(|reg| { + reg.set_presc(timings.prescale); + reg.set_scll(timings.scll); + reg.set_sclh(timings.sclh); + reg.set_sdadel(timings.sdadel); + reg.set_scldel(timings.scldel); + }); + self.init_slave(*addr_config); + + Ok(()) + } +} -- cgit From 49357709ed4f619144746dd04e088d78ad7f355f Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Mon, 17 Jun 2024 21:15:26 -0600 Subject: Move slave constructor to v2 module --- embassy-stm32/src/i2c/mod.rs | 20 -------------------- embassy-stm32/src/i2c/v2.rs | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 0457595d2..a5ff61f3d 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -268,26 +268,6 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { } } } -impl<'d, M: Mode> I2c<'d, M, Master> { - /// Configure the I2C driver for slave operations, allowing for the driver to be used as a slave and a master (multimaster) - pub fn into_slave_multimaster(mut self, slave_addr_config: SlaveAddrConfig) -> I2c<'d, M, MultiMaster> { - let mut slave = I2c { - info: self.info, - state: self.state, - kernel_clock: self.kernel_clock, - scl: self.scl.take(), - sda: self.sda.take(), - tx_dma: self.tx_dma.take(), - rx_dma: self.rx_dma.take(), - #[cfg(feature = "time")] - timeout: self.timeout, - _phantom: PhantomData, - _phantom2: PhantomData, - }; - slave.init_slave(slave_addr_config); - slave - } -} impl<'d, M: Mode, IM: MasterMode> Drop for I2c<'d, M, IM> { fn drop(&mut self) { diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index c2560d819..acf4b3f12 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -694,6 +694,27 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { } } +impl<'d, M: Mode> I2c<'d, M, Master> { + /// Configure the I2C driver for slave operations, allowing for the driver to be used as a slave and a master (multimaster) + pub fn into_slave_multimaster(mut self, slave_addr_config: SlaveAddrConfig) -> I2c<'d, M, MultiMaster> { + let mut slave = I2c { + info: self.info, + state: self.state, + kernel_clock: self.kernel_clock, + scl: self.scl.take(), + sda: self.sda.take(), + tx_dma: self.tx_dma.take(), + rx_dma: self.rx_dma.take(), + #[cfg(feature = "time")] + timeout: self.timeout, + _phantom: PhantomData, + _phantom2: PhantomData, + }; + slave.init_slave(slave_addr_config); + slave + } +} + impl<'d, M: Mode> I2c<'d, M, MultiMaster> { pub(crate) fn init_slave(&mut self, config: SlaveAddrConfig) { self.info.regs.cr1().modify(|reg| { -- cgit From 65c7457c01317a803817cfdfac7b66ab23adf710 Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Mon, 17 Jun 2024 21:23:24 -0600 Subject: reference the i2c mode in v1 module --- embassy-stm32/src/i2c/v1.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 28026f83c..a93a5d987 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -11,6 +11,7 @@ use embassy_embedded_hal::SetConfig; use embassy_futures::select::{select, Either}; use embassy_hal_internal::drop::OnDrop; use embedded_hal_1::i2c::Operation; +use mode::Master; use super::*; use crate::mode::Mode as PeriMode; @@ -41,7 +42,7 @@ pub unsafe fn on_interrupt() { }); } -impl<'d, M: PeriMode> I2c<'d, M> { +impl<'d, M: PeriMode> I2c<'d, M, Master> { pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { self.info.regs.cr1().modify(|reg| { reg.set_pe(false); @@ -354,7 +355,7 @@ impl<'d, M: PeriMode> I2c<'d, M> { } } -impl<'d> I2c<'d, Async> { +impl<'d> I2c<'d, Async, Master> { async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> { self.info.regs.cr2().modify(|w| { // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for @@ -800,7 +801,7 @@ impl Timings { } } -impl<'d, M: PeriMode> SetConfig for I2c<'d, M> { +impl<'d, M: PeriMode> SetConfig for I2c<'d, M, Master> { type Config = Hertz; type ConfigError = (); fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { -- cgit From 70dfbc03b0399ebeb57ba9b8ee177154325db374 Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Tue, 18 Jun 2024 10:43:34 -0600 Subject: Add more docs --- embassy-stm32/src/i2c/config.rs | 43 +++++++++++++++++++++++++++++++---------- embassy-stm32/src/i2c/mod.rs | 4 +++- embassy-stm32/src/i2c/v2.rs | 2 +- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/embassy-stm32/src/i2c/config.rs b/embassy-stm32/src/i2c/config.rs index eba14f6e0..dac7847e8 100644 --- a/embassy-stm32/src/i2c/config.rs +++ b/embassy-stm32/src/i2c/config.rs @@ -5,14 +5,23 @@ use crate::gpio::Pull; #[repr(u8)] #[derive(Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// Bits of the I2C OA2 register to mask out. pub enum AddrMask { + /// No mask NOMASK, + /// OA2\[1\] is masked and don’t care. Only OA2\[7:2\] are compared. MASK1, + /// OA2\[2:1\] are masked and don’t care. Only OA2\[7:3\] are compared. MASK2, + /// OA2\[3:1\] are masked and don’t care. Only OA2\[7:4\] are compared. MASK3, + /// OA2\[4:1\] are masked and don’t care. Only OA2\[7:5\] are compared. MASK4, + /// OA2\[5:1\] are masked and don’t care. Only OA2\[7:6\] are compared. MASK5, + /// OA2\[6:1\] are masked and don’t care. Only OA2\[7:6\] are compared. MASK6, + /// OA2\[7:1\] are masked and don’t care. No comparison is done, and all (except reserved) 7-bit received addresses are acknowledged MASK7, } impl From for Oamsk { @@ -32,8 +41,13 @@ impl From for Oamsk { #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// An I2C address. Either 7 or 10 bit. pub enum Address { + /// A 7 bit address SevenBit(u8), + /// A 10 bit address. + /// + /// When using an address to configure the Own Address, only the OA1 register can be set to a 10-bit address. TenBit(u16), } impl From for Address { @@ -54,6 +68,9 @@ impl Address { Address::TenBit(_) => stm32_metapac::i2c::vals::Addmode::BIT10, } } + /// Get the inner address as a u16. + /// + /// For 7 bit addresses, the u8 that was used to store the address is returned as a u16. pub fn addr(&self) -> u16 { match self { Address::SevenBit(addr) => *addr as u16, @@ -64,17 +81,29 @@ impl Address { #[derive(Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// The second Own Address register. pub struct OA2 { + /// The address. pub addr: u8, + /// The bit mask that will affect how the own address 2 register is compared. pub mask: AddrMask, } #[derive(Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// The Own Address(es) of the I2C peripheral. pub enum OwnAddresses { + /// Configuration for only the OA1 register. OA1(Address), + /// Configuration for only the OA2 register. OA2(OA2), - Both { oa1: Address, oa2: OA2 }, + /// Configuration for both the OA1 and OA2 registers. + Both { + /// The [Address] for the OA1 register. + oa1: Address, + /// The [OA2] configuration. + oa2: OA2, + }, } /// Slave Configuration @@ -87,16 +116,10 @@ pub struct SlaveAddrConfig { pub general_call: bool, } impl SlaveAddrConfig { - pub fn new_oa1(addr: Address, general_call: bool) -> Self { - Self { - addr: OwnAddresses::OA1(addr), - general_call, - } - } - - pub fn basic(addr: Address) -> Self { + /// Create a new slave address configuration with only the OA1 register set in 7 bit mode and the general call disabled. + pub fn basic(addr: u8) -> Self { Self { - addr: OwnAddresses::OA1(addr), + addr: OwnAddresses::OA1(Address::SevenBit(addr)), general_call: false, } } diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index a5ff61f3d..1464a6851 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -16,7 +16,7 @@ use embassy_hal_internal::{Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; #[cfg(feature = "time")] use embassy_time::{Duration, Instant}; -use mode::{Master, MasterMode, MultiMaster}; +use mode::{Master, MasterMode}; use crate::dma::ChannelAndRequest; #[cfg(gpio_v2)] @@ -146,7 +146,9 @@ pub enum CommandKind { #[cfg_attr(feature = "defmt", derive(defmt::Format))] /// The command kind to the slave from the master and the address that the slave matched pub struct Command { + /// The kind of command pub kind: CommandKind, + /// The address that the slave matched pub address: Address, } diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index acf4b3f12..86efd0da2 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -6,7 +6,7 @@ use config::{Address, OwnAddresses, OA2}; use embassy_embedded_hal::SetConfig; use embassy_hal_internal::drop::OnDrop; use embedded_hal_1::i2c::Operation; -use mode::Master; +use mode::{Master, MultiMaster}; use stm32_metapac::i2c::vals::Addmode; use super::*; -- cgit From 31f224f43c7b0fa6796b4966b310b0bbe8edd14b Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Tue, 18 Jun 2024 10:56:46 -0600 Subject: move embedded hal impl to version modules to allow for 10bit addr on v2 --- embassy-stm32/src/i2c/mod.rs | 86 ------------------------------------------- embassy-stm32/src/i2c/v1.rs | 72 +++++++++++++++++++++++++++++++++++- embassy-stm32/src/i2c/v2.rs | 88 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+), 87 deletions(-) diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 1464a6851..3303b9f4b 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -388,42 +388,6 @@ foreach_peripheral!( }; ); -impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> - embedded_hal_02::blocking::i2c::Read for I2c<'d, M, IM> -where - A: Into
, -{ - type Error = Error; - - fn read(&mut self, address: A, buffer: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_read(address.into(), buffer) - } -} - -impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> - embedded_hal_02::blocking::i2c::Write for I2c<'d, M, IM> -where - A: Into
, -{ - type Error = Error; - - fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(address.into(), write) - } -} - -impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> - embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M, IM> -where - A: Into
, -{ - type Error = Error; - - fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_write_read(address.into(), write, read) - } -} - impl embedded_hal_1::i2c::Error for Error { fn kind(&self) -> embedded_hal_1::i2c::ErrorKind { match *self { @@ -444,56 +408,6 @@ impl<'d, M: Mode, IM: MasterMode> embedded_hal_1::i2c::ErrorType for I2c<'d, M, type Error = Error; } -impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_1::i2c::AddressMode> embedded_hal_1::i2c::I2c for I2c<'d, M, IM> -where - Address: From, -{ - fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_read(address.into(), read) - } - - fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(address.into(), write) - } - - fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_write_read(address.into(), write, read) - } - - fn transaction( - &mut self, - address: A, - operations: &mut [embedded_hal_1::i2c::Operation<'_>], - ) -> Result<(), Self::Error> { - self.blocking_transaction(address.into(), operations) - } -} - -impl<'d, IM: MasterMode, A: embedded_hal_async::i2c::AddressMode> embedded_hal_async::i2c::I2c for I2c<'d, Async, IM> -where - Address: From, -{ - async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> { - self.read(address.into(), read).await - } - - async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { - self.write(address.into(), write).await - } - - async fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { - self.write_read(address.into(), write, read).await - } - - async fn transaction( - &mut self, - address: A, - operations: &mut [embedded_hal_1::i2c::Operation<'_>], - ) -> Result<(), Self::Error> { - self.transaction(address.into(), operations).await - } -} - /// Frame type in I2C transaction. /// /// This tells each method what kind of framing to use, to generate a (repeated) start condition (ST diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index a93a5d987..e98ab0290 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -298,7 +298,7 @@ impl<'d, M: PeriMode> I2c<'d, M, Master> { } /// Blocking read. - pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> { + pub fn blocking_read(&mut self, addr: Address, read: &mut [u8]) -> Result<(), Error> { self.blocking_read_timeout(addr, read, self.timeout(), FrameOptions::FirstAndLastFrame) } @@ -821,3 +821,73 @@ impl<'d, M: PeriMode> SetConfig for I2c<'d, M, Master> { Ok(()) } } + +// ======== Embedded HAL impls ======== + +impl<'d, M: PeriMode, IM: MasterMode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M, IM> { + type Error = Error; + + fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_read(address, buffer) + } +} + +impl<'d, M: PeriMode, IM: MasterMode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M, IM> { + type Error = Error; + + fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(address, write) + } +} + +impl<'d, M: PeriMode, IM: MasterMode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M, IM> { + type Error = Error; + + fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_write_read(address, write, read) + } +} + +impl<'d, M: PeriMode, IM: MasterMode> embedded_hal_1::i2c::I2c for I2c<'d, M, IM> { + fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_read(address, read) + } + + fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(address, write) + } + + fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_write_read(address, write, read) + } + + fn transaction( + &mut self, + address: u8, + operations: &mut [embedded_hal_1::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + self.blocking_transaction(address, operations) + } +} + +impl<'d, IM: MasterMode> embedded_hal_async::i2c::I2c for I2c<'d, Async, IM> { + async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { + self.read(address, read).await + } + + async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { + self.write(address, write).await + } + + async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { + self.write_read(address, write, read).await + } + + async fn transaction( + &mut self, + address: u8, + operations: &mut [embedded_hal_1::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + self.transaction(address, operations).await + } +} diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 86efd0da2..6dd7c4079 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -1203,3 +1203,91 @@ impl<'d, M: Mode> SetConfig for I2c<'d, M, MultiMaster> { Ok(()) } } + +// ======== Embedded HAL impls ======== + +impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> + embedded_hal_02::blocking::i2c::Read for I2c<'d, M, IM> +where + A: Into
, +{ + type Error = Error; + + fn read(&mut self, address: A, buffer: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_read(address.into(), buffer) + } +} + +impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> + embedded_hal_02::blocking::i2c::Write for I2c<'d, M, IM> +where + A: Into
, +{ + type Error = Error; + + fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(address.into(), write) + } +} + +impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> + embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M, IM> +where + A: Into
, +{ + type Error = Error; + + fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_write_read(address.into(), write, read) + } +} + +impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_1::i2c::AddressMode> embedded_hal_1::i2c::I2c for I2c<'d, M, IM> +where + Address: From, +{ + fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_read(address.into(), read) + } + + fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(address.into(), write) + } + + fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_write_read(address.into(), write, read) + } + + fn transaction( + &mut self, + address: A, + operations: &mut [embedded_hal_1::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + self.blocking_transaction(address.into(), operations) + } +} + +impl<'d, IM: MasterMode, A: embedded_hal_async::i2c::AddressMode> embedded_hal_async::i2c::I2c for I2c<'d, Async, IM> +where + Address: From, +{ + async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> { + self.read(address.into(), read).await + } + + async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { + self.write(address.into(), write).await + } + + async fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { + self.write_read(address.into(), write, read).await + } + + async fn transaction( + &mut self, + address: A, + operations: &mut [embedded_hal_1::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + self.transaction(address.into(), operations).await + } +} -- cgit From 98437e39ee3b62289d1d126141d8cfb150e9c03a Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Tue, 18 Jun 2024 11:05:12 -0600 Subject: move addr mask impl to be v2 only --- embassy-stm32/src/i2c/config.rs | 16 ---------------- embassy-stm32/src/i2c/v2.rs | 17 ++++++++++++++++- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/embassy-stm32/src/i2c/config.rs b/embassy-stm32/src/i2c/config.rs index dac7847e8..6f9c53f1f 100644 --- a/embassy-stm32/src/i2c/config.rs +++ b/embassy-stm32/src/i2c/config.rs @@ -1,5 +1,3 @@ -use stm32_metapac::i2c::vals::Oamsk; - use crate::gpio::Pull; #[repr(u8)] @@ -24,20 +22,6 @@ pub enum AddrMask { /// OA2\[7:1\] are masked and don’t care. No comparison is done, and all (except reserved) 7-bit received addresses are acknowledged MASK7, } -impl From for Oamsk { - fn from(value: AddrMask) -> Self { - match value { - AddrMask::NOMASK => Oamsk::NOMASK, - AddrMask::MASK1 => Oamsk::MASK1, - AddrMask::MASK2 => Oamsk::MASK2, - AddrMask::MASK3 => Oamsk::MASK3, - AddrMask::MASK4 => Oamsk::MASK4, - AddrMask::MASK5 => Oamsk::MASK5, - AddrMask::MASK6 => Oamsk::MASK6, - AddrMask::MASK7 => Oamsk::MASK7, - } - } -} #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 6dd7c4079..b6d714327 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -7,11 +7,26 @@ use embassy_embedded_hal::SetConfig; use embassy_hal_internal::drop::OnDrop; use embedded_hal_1::i2c::Operation; use mode::{Master, MultiMaster}; -use stm32_metapac::i2c::vals::Addmode; +use stm32_metapac::i2c::vals::{Addmode, Oamsk}; use super::*; use crate::pac::i2c; +impl From for Oamsk { + fn from(value: AddrMask) -> Self { + match value { + AddrMask::NOMASK => Oamsk::NOMASK, + AddrMask::MASK1 => Oamsk::MASK1, + AddrMask::MASK2 => Oamsk::MASK2, + AddrMask::MASK3 => Oamsk::MASK3, + AddrMask::MASK4 => Oamsk::MASK4, + AddrMask::MASK5 => Oamsk::MASK5, + AddrMask::MASK6 => Oamsk::MASK6, + AddrMask::MASK7 => Oamsk::MASK7, + } + } +} + pub(crate) unsafe fn on_interrupt() { let regs = T::info().regs; let isr = regs.isr().read(); -- cgit From bec0eac5aba15c38697cfedae948e0a9f3005c56 Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Tue, 18 Jun 2024 11:13:32 -0600 Subject: Fix v1 mod --- embassy-stm32/src/i2c/v1.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index e98ab0290..30964e3f4 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -42,7 +42,7 @@ pub unsafe fn on_interrupt() { }); } -impl<'d, M: PeriMode> I2c<'d, M, Master> { +impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> { pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { self.info.regs.cr1().modify(|reg| { reg.set_pe(false); @@ -298,7 +298,7 @@ impl<'d, M: PeriMode> I2c<'d, M, Master> { } /// Blocking read. - pub fn blocking_read(&mut self, addr: Address, read: &mut [u8]) -> Result<(), Error> { + pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> { self.blocking_read_timeout(addr, read, self.timeout(), FrameOptions::FirstAndLastFrame) } @@ -355,7 +355,7 @@ impl<'d, M: PeriMode> I2c<'d, M, Master> { } } -impl<'d> I2c<'d, Async, Master> { +impl<'d, IM: MasterMode> I2c<'d, Async, IM> { async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> { self.info.regs.cr2().modify(|w| { // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for -- cgit From 8b50f2a58be0e23ca451d03af7769773e3815b00 Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Tue, 18 Jun 2024 11:17:15 -0600 Subject: remove dead code when v1 --- embassy-stm32/src/i2c/config.rs | 6 ------ embassy-stm32/src/i2c/v2.rs | 9 +++++++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/embassy-stm32/src/i2c/config.rs b/embassy-stm32/src/i2c/config.rs index 6f9c53f1f..2c7676bd9 100644 --- a/embassy-stm32/src/i2c/config.rs +++ b/embassy-stm32/src/i2c/config.rs @@ -46,12 +46,6 @@ impl From for Address { } } impl Address { - pub(super) fn add_mode(&self) -> stm32_metapac::i2c::vals::Addmode { - match self { - Address::SevenBit(_) => stm32_metapac::i2c::vals::Addmode::BIT7, - Address::TenBit(_) => stm32_metapac::i2c::vals::Addmode::BIT10, - } - } /// Get the inner address as a u16. /// /// For 7 bit addresses, the u8 that was used to store the address is returned as a u16. diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index b6d714327..531358efa 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -27,6 +27,15 @@ impl From for Oamsk { } } +impl Address { + pub(super) fn add_mode(&self) -> stm32_metapac::i2c::vals::Addmode { + match self { + Address::SevenBit(_) => stm32_metapac::i2c::vals::Addmode::BIT7, + Address::TenBit(_) => stm32_metapac::i2c::vals::Addmode::BIT10, + } + } +} + pub(crate) unsafe fn on_interrupt() { let regs = T::info().regs; let isr = regs.isr().read(); -- cgit From c7b4a076cc47b5f824b39cbeae825fc108ddac2a Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Tue, 18 Jun 2024 19:05:07 -0600 Subject: add drop guard, clear interrupts, fix len return --- embassy-stm32/src/i2c/mod.rs | 33 ++++++++++++++++++++------------- embassy-stm32/src/i2c/v2.rs | 11 ++++++++--- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 3303b9f4b..82e28b3ff 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -162,19 +162,32 @@ pub enum SendStatus { LeftoverBytes(usize), } +struct I2CDropGuard<'d> { + info: &'static Info, + scl: Option>, + sda: Option>, +} +impl<'d> Drop for I2CDropGuard<'d> { + fn drop(&mut self) { + self.scl.as_ref().map(|x| x.set_as_disconnected()); + self.sda.as_ref().map(|x| x.set_as_disconnected()); + + self.info.rcc.disable(); + } +} + /// I2C driver. pub struct I2c<'d, M: Mode, IM: MasterMode> { info: &'static Info, state: &'static State, kernel_clock: Hertz, - scl: Option>, - sda: Option>, tx_dma: Option>, rx_dma: Option>, #[cfg(feature = "time")] timeout: Duration, _phantom: PhantomData, _phantom2: PhantomData, + drop_guard: I2CDropGuard<'d>, } impl<'d> I2c<'d, Async, Master> { @@ -242,14 +255,17 @@ impl<'d, M: Mode> I2c<'d, M, Master> { info: T::info(), state: T::state(), kernel_clock: T::frequency(), - scl, - sda, tx_dma, rx_dma, #[cfg(feature = "time")] timeout: config.timeout, _phantom: PhantomData, _phantom2: PhantomData, + drop_guard: I2CDropGuard { + info: T::info(), + scl, + sda, + }, }; this.enable_and_init(freq, config); @@ -271,15 +287,6 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { } } -impl<'d, M: Mode, IM: MasterMode> Drop for I2c<'d, M, IM> { - fn drop(&mut self) { - self.scl.as_ref().map(|x| x.set_as_disconnected()); - self.sda.as_ref().map(|x| x.set_as_disconnected()); - - self.info.rcc.disable() - } -} - #[derive(Copy, Clone)] struct Timeout { #[cfg(feature = "time")] diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 531358efa..a90bdd551 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -47,6 +47,8 @@ pub(crate) unsafe fn on_interrupt() { critical_section::with(|_| { regs.cr1().modify(|w| { w.set_addrie(false); + w.set_stopie(false); + w.set_tcie(false); // The flag can only be cleared by writting to nbytes, we won't do that here, so disable // the interrupt w.set_tcie(false); @@ -725,14 +727,13 @@ impl<'d, M: Mode> I2c<'d, M, Master> { info: self.info, state: self.state, kernel_clock: self.kernel_clock, - scl: self.scl.take(), - sda: self.sda.take(), tx_dma: self.tx_dma.take(), rx_dma: self.rx_dma.take(), #[cfg(feature = "time")] timeout: self.timeout, _phantom: PhantomData, _phantom2: PhantomData, + drop_guard: self.drop_guard, }; slave.init_slave(slave_addr_config); slave @@ -930,6 +931,8 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { impl<'d> I2c<'d, Async, MultiMaster> { /// Respond to a receive command. + /// + /// Returns the total number of bytes received. pub async fn respond_to_receive(&mut self, buffer: &mut [u8]) -> Result { let timeout = self.timeout(); timeout.with(self.read_dma_internal_slave(buffer, timeout)).await @@ -942,6 +945,8 @@ impl<'d> I2c<'d, Async, MultiMaster> { } // for data reception in slave mode + // + // returns the total number of bytes received async fn read_dma_internal_slave(&mut self, buffer: &mut [u8], timeout: Timeout) -> Result { let total_len = buffer.len(); let mut remaining_len = total_len; @@ -988,7 +993,7 @@ impl<'d> I2c<'d, Async, MultiMaster> { Poll::Pending } else if isr.stopf() { regs.icr().write(|reg| reg.set_stopcf(true)); - let poll = Poll::Ready(Ok(remaining_len)); + let poll = Poll::Ready(Ok(total_len - remaining_len)); poll } else { Poll::Pending -- cgit From d1f5a4c5c72787cfa7ce9e7c057714e3a272031f Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Tue, 25 Jun 2024 14:12:19 -0600 Subject: fix ci --- embassy-stm32/src/i2c/config.rs | 40 +++++++++++++++----- embassy-stm32/src/i2c/mod.rs | 84 +++++------------------------------------ embassy-stm32/src/i2c/v2.rs | 2 +- 3 files changed, 41 insertions(+), 85 deletions(-) diff --git a/embassy-stm32/src/i2c/config.rs b/embassy-stm32/src/i2c/config.rs index 2c7676bd9..daae43bcd 100644 --- a/embassy-stm32/src/i2c/config.rs +++ b/embassy-stm32/src/i2c/config.rs @@ -1,4 +1,6 @@ +#[cfg(gpio_v2)] use crate::gpio::Pull; +use crate::gpio::{AfType, OutputType, Speed}; #[repr(u8)] #[derive(Copy, Clone)] @@ -111,11 +113,13 @@ pub struct Config { /// /// Using external pullup resistors is recommended for I2C. If you do /// have external pullups you should not enable this. + #[cfg(gpio_v2)] pub sda_pullup: bool, /// Enable internal pullup on SCL. /// /// Using external pullup resistors is recommended for I2C. If you do /// have external pullups you should not enable this. + #[cfg(gpio_v2)] pub scl_pullup: bool, /// Timeout. #[cfg(feature = "time")] @@ -125,7 +129,9 @@ pub struct Config { impl Default for Config { fn default() -> Self { Self { + #[cfg(gpio_v2)] sda_pullup: false, + #[cfg(gpio_v2)] scl_pullup: false, #[cfg(feature = "time")] timeout: embassy_time::Duration::from_millis(1000), @@ -134,17 +140,31 @@ impl Default for Config { } impl Config { - pub(super) fn scl_pull_mode(&self) -> Pull { - match self.scl_pullup { - true => Pull::Up, - false => Pull::Down, - } + pub(super) fn scl_af(&self) -> AfType { + #[cfg(gpio_v1)] + return AfType::output(OutputType::OpenDrain, Speed::Medium); + #[cfg(gpio_v2)] + return AfType::output_pull( + OutputType::OpenDrain, + Speed::Medium, + match self.scl_pullup { + true => Pull::Up, + false => Pull::Down, + }, + ); } - pub(super) fn sda_pull_mode(&self) -> Pull { - match self.sda_pullup { - true => Pull::Up, - false => Pull::Down, - } + pub(super) fn sda_af(&self) -> AfType { + #[cfg(gpio_v1)] + return AfType::output(OutputType::OpenDrain, Speed::Medium); + #[cfg(gpio_v2)] + return AfType::output_pull( + OutputType::OpenDrain, + Speed::Medium, + match self.sda_pullup { + true => Pull::Up, + false => Pull::Down, + }, + ); } } diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 82e28b3ff..fed2e4714 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -19,9 +19,7 @@ use embassy_time::{Duration, Instant}; use mode::{Master, MasterMode}; use crate::dma::ChannelAndRequest; -#[cfg(gpio_v2)] -use crate::gpio::Pull; -use crate::gpio::{AfType, AnyPin, OutputType, SealedPin as _, Speed}; +use crate::gpio::{AnyPin, SealedPin as _}; use crate::interrupt::typelevel::Interrupt; use crate::mode::{Async, Blocking, Mode}; use crate::rcc::{RccInfo, SealedRccPeripheral}; @@ -48,70 +46,6 @@ pub enum Error { ZeroLengthTransfer, } -/// I2C config -#[non_exhaustive] -#[derive(Copy, Clone)] -pub struct Config { - /// Enable internal pullup on SDA. - /// - /// Using external pullup resistors is recommended for I2C. If you do - /// have external pullups you should not enable this. - #[cfg(gpio_v2)] - pub sda_pullup: bool, - /// Enable internal pullup on SCL. - /// - /// Using external pullup resistors is recommended for I2C. If you do - /// have external pullups you should not enable this. - #[cfg(gpio_v2)] - pub scl_pullup: bool, - /// Timeout. - #[cfg(feature = "time")] - pub timeout: embassy_time::Duration, -} - -impl Default for Config { - fn default() -> Self { - Self { - #[cfg(gpio_v2)] - sda_pullup: false, - #[cfg(gpio_v2)] - scl_pullup: false, - #[cfg(feature = "time")] - timeout: embassy_time::Duration::from_millis(1000), - } - } -} - -impl Config { - fn scl_af(&self) -> AfType { - #[cfg(gpio_v1)] - return AfType::output(OutputType::OpenDrain, Speed::Medium); - #[cfg(gpio_v2)] - return AfType::output_pull( - OutputType::OpenDrain, - Speed::Medium, - match self.scl_pullup { - true => Pull::Up, - false => Pull::Down, - }, - ); - } - - fn sda_af(&self) -> AfType { - #[cfg(gpio_v1)] - return AfType::output(OutputType::OpenDrain, Speed::Medium); - #[cfg(gpio_v2)] - return AfType::output_pull( - OutputType::OpenDrain, - Speed::Medium, - match self.sda_pullup { - true => Pull::Up, - false => Pull::Down, - }, - ); - } -} - /// I2C modes pub mod mode { trait SealedMode {} @@ -169,8 +103,12 @@ struct I2CDropGuard<'d> { } impl<'d> Drop for I2CDropGuard<'d> { fn drop(&mut self) { - self.scl.as_ref().map(|x| x.set_as_disconnected()); - self.sda.as_ref().map(|x| x.set_as_disconnected()); + if let Some(x) = self.scl.as_ref() { + x.set_as_disconnected() + } + if let Some(x) = self.sda.as_ref() { + x.set_as_disconnected() + } self.info.rcc.disable(); } @@ -187,7 +125,7 @@ pub struct I2c<'d, M: Mode, IM: MasterMode> { timeout: Duration, _phantom: PhantomData, _phantom2: PhantomData, - drop_guard: I2CDropGuard<'d>, + _drop_guard: I2CDropGuard<'d>, } impl<'d> I2c<'d, Async, Master> { @@ -261,7 +199,7 @@ impl<'d, M: Mode> I2c<'d, M, Master> { timeout: config.timeout, _phantom: PhantomData, _phantom2: PhantomData, - drop_guard: I2CDropGuard { + _drop_guard: I2CDropGuard { info: T::info(), scl, sda, @@ -509,9 +447,7 @@ fn operation_frames<'a, 'b: 'a>( let mut next_first_frame = true; Ok(iter::from_fn(move || { - let Some(op) = operations.next() else { - return None; - }; + let op = operations.next()?; // Is `op` first frame of its type? let first_frame = next_first_frame; diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index a90bdd551..7ca958fca 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -733,7 +733,7 @@ impl<'d, M: Mode> I2c<'d, M, Master> { timeout: self.timeout, _phantom: PhantomData, _phantom2: PhantomData, - drop_guard: self.drop_guard, + _drop_guard: self._drop_guard, }; slave.init_slave(slave_addr_config); slave -- cgit From b4eb4a3d189efe5fe3716bb5dcd6396efcfab5c3 Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Tue, 13 Aug 2024 09:45:28 -0600 Subject: remove 10 bit support --- embassy-stm32/src/i2c/mod.rs | 68 ++++++++++++++++++++++ embassy-stm32/src/i2c/v1.rs | 70 ----------------------- embassy-stm32/src/i2c/v2.rs | 132 ++++++++----------------------------------- 3 files changed, 90 insertions(+), 180 deletions(-) diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index fed2e4714..6f952b8f8 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -333,6 +333,30 @@ foreach_peripheral!( }; ); +impl<'d, M: Mode, IM: MasterMode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M, IM> { + type Error = Error; + + fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_read(address, buffer) + } +} + +impl<'d, M: Mode, IM: MasterMode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M, IM> { + type Error = Error; + + fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(address, write) + } +} + +impl<'d, M: Mode, IM: MasterMode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M, IM> { + type Error = Error; + + fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_write_read(address, write, read) + } +} + impl embedded_hal_1::i2c::Error for Error { fn kind(&self) -> embedded_hal_1::i2c::ErrorKind { match *self { @@ -353,6 +377,50 @@ impl<'d, M: Mode, IM: MasterMode> embedded_hal_1::i2c::ErrorType for I2c<'d, M, type Error = Error; } +impl<'d, M: Mode, IM: MasterMode> embedded_hal_1::i2c::I2c for I2c<'d, M, IM> { + fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_read(address, read) + } + + fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(address, write) + } + + fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_write_read(address, write, read) + } + + fn transaction( + &mut self, + address: u8, + operations: &mut [embedded_hal_1::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + self.blocking_transaction(address, operations) + } +} + +impl<'d, IM: MasterMode> embedded_hal_async::i2c::I2c for I2c<'d, Async, IM> { + async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { + self.read(address, read).await + } + + async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { + self.write(address, write).await + } + + async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { + self.write_read(address, write, read).await + } + + async fn transaction( + &mut self, + address: u8, + operations: &mut [embedded_hal_1::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + self.transaction(address, operations).await + } +} + /// Frame type in I2C transaction. /// /// This tells each method what kind of framing to use, to generate a (repeated) start condition (ST diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 30964e3f4..35f13ab46 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -821,73 +821,3 @@ impl<'d, M: PeriMode> SetConfig for I2c<'d, M, Master> { Ok(()) } } - -// ======== Embedded HAL impls ======== - -impl<'d, M: PeriMode, IM: MasterMode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M, IM> { - type Error = Error; - - fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_read(address, buffer) - } -} - -impl<'d, M: PeriMode, IM: MasterMode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M, IM> { - type Error = Error; - - fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(address, write) - } -} - -impl<'d, M: PeriMode, IM: MasterMode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M, IM> { - type Error = Error; - - fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_write_read(address, write, read) - } -} - -impl<'d, M: PeriMode, IM: MasterMode> embedded_hal_1::i2c::I2c for I2c<'d, M, IM> { - fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_read(address, read) - } - - fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(address, write) - } - - fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_write_read(address, write, read) - } - - fn transaction( - &mut self, - address: u8, - operations: &mut [embedded_hal_1::i2c::Operation<'_>], - ) -> Result<(), Self::Error> { - self.blocking_transaction(address, operations) - } -} - -impl<'d, IM: MasterMode> embedded_hal_async::i2c::I2c for I2c<'d, Async, IM> { - async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { - self.read(address, read).await - } - - async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { - self.write(address, write).await - } - - async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { - self.write_read(address, write, read).await - } - - async fn transaction( - &mut self, - address: u8, - operations: &mut [embedded_hal_1::i2c::Operation<'_>], - ) -> Result<(), Self::Error> { - self.transaction(address, operations).await - } -} diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 7ca958fca..1cc41fb5f 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -365,21 +365,21 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { // Blocking public API /// Blocking read. - pub fn blocking_read(&mut self, address: Address, read: &mut [u8]) -> Result<(), Error> { - self.read_internal(address, read, false, self.timeout()) + pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { + self.read_internal(address.into(), read, false, self.timeout()) // Automatic Stop } /// Blocking write. - pub fn blocking_write(&mut self, address: Address, write: &[u8]) -> Result<(), Error> { - self.write_internal(address, write, true, self.timeout()) + pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { + self.write_internal(address.into(), write, true, self.timeout()) } /// Blocking write, restart, read. - pub fn blocking_write_read(&mut self, address: Address, write: &[u8], read: &mut [u8]) -> Result<(), Error> { + pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { let timeout = self.timeout(); - self.write_internal(address, write, false, timeout)?; - self.read_internal(address, read, true, timeout) + self.write_internal(address.into(), write, false, timeout)?; + self.read_internal(address.into(), read, true, timeout) // Automatic Stop } @@ -388,7 +388,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { /// Consecutive operations of same type are merged. See [transaction contract] for details. /// /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction - pub fn blocking_transaction(&mut self, addr: Address, operations: &mut [Operation<'_>]) -> Result<(), Error> { + pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { let _ = addr; let _ = operations; todo!() @@ -397,7 +397,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { /// Blocking write multiple buffers. /// /// The buffers are concatenated in a single write transaction. - pub fn blocking_write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> { + pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { if write.is_empty() { return Err(Error::ZeroLengthTransfer); } @@ -409,7 +409,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { if let Err(err) = Self::master_write( self.info, - address, + address.into(), first_length.min(255), Stop::Software, (first_length > 255) || (last_slice_index != 0), @@ -639,13 +639,13 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { // Async public API /// Write. - pub async fn write(&mut self, address: Address, write: &[u8]) -> Result<(), Error> { + pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { let timeout = self.timeout(); if write.is_empty() { - self.write_internal(address, write, true, timeout) + self.write_internal(address.into(), write, true, timeout) } else { timeout - .with(self.write_dma_internal(address, write, true, true, timeout)) + .with(self.write_dma_internal(address.into(), write, true, true, timeout)) .await } } @@ -676,32 +676,32 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { } /// Read. - pub async fn read(&mut self, address: Address, buffer: &mut [u8]) -> Result<(), Error> { + pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { let timeout = self.timeout(); if buffer.is_empty() { - self.read_internal(address, buffer, false, timeout) + self.read_internal(address.into(), buffer, false, timeout) } else { - let fut = self.read_dma_internal(address, buffer, false, timeout); + let fut = self.read_dma_internal(address.into(), buffer, false, timeout); timeout.with(fut).await } } /// Write, restart, read. - pub async fn write_read(&mut self, address: Address, write: &[u8], read: &mut [u8]) -> Result<(), Error> { + pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { let timeout = self.timeout(); if write.is_empty() { - self.write_internal(address, write, false, timeout)?; + self.write_internal(address.into(), write, false, timeout)?; } else { - let fut = self.write_dma_internal(address, write, true, true, timeout); + let fut = self.write_dma_internal(address.into(), write, true, true, timeout); timeout.with(fut).await?; } if read.is_empty() { - self.read_internal(address, read, true, timeout)?; + self.read_internal(address.into(), read, true, timeout)?; } else { - let fut = self.read_dma_internal(address, read, true, timeout); + let fut = self.read_dma_internal(address.into(), read, true, timeout); timeout.with(fut).await?; } @@ -713,7 +713,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { /// Consecutive operations of same type are merged. See [transaction contract] for details. /// /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction - pub async fn transaction(&mut self, addr: Address, operations: &mut [Operation<'_>]) -> Result<(), Error> { + pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { let _ = addr; let _ = operations; todo!() @@ -1232,91 +1232,3 @@ impl<'d, M: Mode> SetConfig for I2c<'d, M, MultiMaster> { Ok(()) } } - -// ======== Embedded HAL impls ======== - -impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> - embedded_hal_02::blocking::i2c::Read for I2c<'d, M, IM> -where - A: Into
, -{ - type Error = Error; - - fn read(&mut self, address: A, buffer: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_read(address.into(), buffer) - } -} - -impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> - embedded_hal_02::blocking::i2c::Write for I2c<'d, M, IM> -where - A: Into
, -{ - type Error = Error; - - fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(address.into(), write) - } -} - -impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_02::blocking::i2c::AddressMode> - embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M, IM> -where - A: Into
, -{ - type Error = Error; - - fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_write_read(address.into(), write, read) - } -} - -impl<'d, M: Mode, IM: MasterMode, A: embedded_hal_1::i2c::AddressMode> embedded_hal_1::i2c::I2c for I2c<'d, M, IM> -where - Address: From, -{ - fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_read(address.into(), read) - } - - fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(address.into(), write) - } - - fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_write_read(address.into(), write, read) - } - - fn transaction( - &mut self, - address: A, - operations: &mut [embedded_hal_1::i2c::Operation<'_>], - ) -> Result<(), Self::Error> { - self.blocking_transaction(address.into(), operations) - } -} - -impl<'d, IM: MasterMode, A: embedded_hal_async::i2c::AddressMode> embedded_hal_async::i2c::I2c for I2c<'d, Async, IM> -where - Address: From, -{ - async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> { - self.read(address.into(), read).await - } - - async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { - self.write(address.into(), write).await - } - - async fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { - self.write_read(address.into(), write, read).await - } - - async fn transaction( - &mut self, - address: A, - operations: &mut [embedded_hal_1::i2c::Operation<'_>], - ) -> Result<(), Self::Error> { - self.transaction(address.into(), operations).await - } -} -- cgit From 50619638ee5c71110430420a04d1b3113eb91945 Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Tue, 13 Aug 2024 10:39:34 -0600 Subject: fix examples --- embassy-stm32/src/i2c/mod.rs | 3 ++- examples/stm32h7/src/bin/i2c_shared.rs | 2 +- examples/stm32l4/src/bin/spe_adin1110_http_server.rs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 6f952b8f8..c1911cd06 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -16,7 +16,8 @@ use embassy_hal_internal::{Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; #[cfg(feature = "time")] use embassy_time::{Duration, Instant}; -use mode::{Master, MasterMode}; +use mode::{MasterMode}; +pub use mode::{Master, MultiMaster}; use crate::dma::ChannelAndRequest; use crate::gpio::{AnyPin, SealedPin as _}; diff --git a/examples/stm32h7/src/bin/i2c_shared.rs b/examples/stm32h7/src/bin/i2c_shared.rs index 6f4815582..321b35a3e 100644 --- a/examples/stm32h7/src/bin/i2c_shared.rs +++ b/examples/stm32h7/src/bin/i2c_shared.rs @@ -23,7 +23,7 @@ const SHTC3_WAKEUP: [u8; 2] = [0x35, 0x17]; const SHTC3_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24]; const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98]; -static I2C_BUS: StaticCell>>> = StaticCell::new(); +static I2C_BUS: StaticCell>>> = StaticCell::new(); bind_interrupts!(struct Irqs { I2C1_EV => i2c::EventInterruptHandler; diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index bd633cecb..8f23e4083 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs @@ -60,7 +60,7 @@ pub type SpeSpiCs = ExclusiveDevice, Delay>; pub type SpeInt = exti::ExtiInput<'static>; pub type SpeRst = Output<'static>; pub type Adin1110T = ADIN1110; -pub type TempSensI2c = I2c<'static, Async>; +pub type TempSensI2c = I2c<'static, Async, i2c::Master>; static TEMP: AtomicI32 = AtomicI32::new(0); -- cgit From bfc162d43755f988c0b4963fc23386273ce02a35 Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Tue, 13 Aug 2024 10:48:30 -0600 Subject: fix rustfmt --- embassy-stm32/src/i2c/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index c1911cd06..94507eb34 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -16,7 +16,7 @@ use embassy_hal_internal::{Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; #[cfg(feature = "time")] use embassy_time::{Duration, Instant}; -use mode::{MasterMode}; +use mode::MasterMode; pub use mode::{Master, MultiMaster}; use crate::dma::ChannelAndRequest; -- cgit From fc342915e6155dec7bafa3e135da7f37a9a07f5c Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Tue, 13 Aug 2024 12:53:58 -0600 Subject: add stm32 i2c slave example --- embassy-stm32/src/i2c/mod.rs | 10 +-- embassy-stm32/src/i2c/v2.rs | 26 +++--- examples/stm32g4/src/bin/i2c_slave.rs | 149 ++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+), 18 deletions(-) create mode 100644 examples/stm32g4/src/bin/i2c_slave.rs diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 94507eb34..2ff21702b 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -70,19 +70,19 @@ pub mod mode { #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] /// The command kind to the slave from the master -pub enum CommandKind { +pub enum SlaveCommandKind { /// Write to the slave - SlaveReceive, + Write, /// Read from the slave - SlaveSend, + Read, } #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] /// The command kind to the slave from the master and the address that the slave matched -pub struct Command { +pub struct SlaveCommand { /// The kind of command - pub kind: CommandKind, + pub kind: SlaveCommandKind, /// The address that the slave matched pub address: Address, } diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 1cc41fb5f..64ccd24c7 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -887,7 +887,7 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { /// Listen for incoming I2C messages. /// /// The listen method is an asynchronous method but it does not require DMA to be asynchronous. - pub async fn listen(&mut self) -> Result { + pub async fn listen(&mut self) -> Result { let state = self.state; self.info.regs.cr1().modify(|reg| { reg.set_addrie(true); @@ -902,12 +902,12 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { // we do not clear the address flag here as it will be cleared by the dma read/write // if we clear it here the clock stretching will stop and the master will read in data before the slave is ready to send it match isr.dir() { - i2c::vals::Dir::WRITE => Poll::Ready(Ok(Command { - kind: CommandKind::SlaveReceive, + i2c::vals::Dir::WRITE => Poll::Ready(Ok(SlaveCommand { + kind: SlaveCommandKind::Write, address: self.determine_matched_address()?, })), - i2c::vals::Dir::READ => Poll::Ready(Ok(Command { - kind: CommandKind::SlaveSend, + i2c::vals::Dir::READ => Poll::Ready(Ok(SlaveCommand { + kind: SlaveCommandKind::Read, address: self.determine_matched_address()?, })), } @@ -916,30 +916,30 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { .await } - /// Respond to a receive command. - pub fn blocking_respond_to_receive(&self, read: &mut [u8]) -> Result<(), Error> { + /// Respond to a write command. + pub fn blocking_respond_to_write(&self, read: &mut [u8]) -> Result<(), Error> { let timeout = self.timeout(); self.slave_read_internal(read, timeout) } - /// Respond to a send command. - pub fn blocking_respond_to_send(&mut self, write: &[u8]) -> Result<(), Error> { + /// Respond to a read command. + pub fn blocking_respond_to_read(&mut self, write: &[u8]) -> Result<(), Error> { let timeout = self.timeout(); self.slave_write_internal(write, timeout) } } impl<'d> I2c<'d, Async, MultiMaster> { - /// Respond to a receive command. + /// Respond to a write command. /// /// Returns the total number of bytes received. - pub async fn respond_to_receive(&mut self, buffer: &mut [u8]) -> Result { + pub async fn respond_to_write(&mut self, buffer: &mut [u8]) -> Result { let timeout = self.timeout(); timeout.with(self.read_dma_internal_slave(buffer, timeout)).await } - /// Respond to a send request from an I2C master. - pub async fn respond_to_send(&mut self, write: &[u8]) -> Result { + /// Respond to a read request from an I2C master. + pub async fn respond_to_read(&mut self, write: &[u8]) -> Result { let timeout = self.timeout(); timeout.with(self.write_dma_internal_slave(write, timeout)).await } diff --git a/examples/stm32g4/src/bin/i2c_slave.rs b/examples/stm32g4/src/bin/i2c_slave.rs new file mode 100644 index 000000000..a723a0e18 --- /dev/null +++ b/examples/stm32g4/src/bin/i2c_slave.rs @@ -0,0 +1,149 @@ +//! This example shows how to use an stm32 as both a master and a slave. +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::i2c::{Address, OwnAddresses, SlaveCommandKind}; +use embassy_stm32::mode::Async; +use embassy_stm32::time::Hertz; +use embassy_stm32::{bind_interrupts, i2c, peripherals}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + I2C1_ER => i2c::ErrorInterruptHandler; + I2C1_EV => i2c::EventInterruptHandler; + I2C2_ER => i2c::ErrorInterruptHandler; + I2C2_EV => i2c::EventInterruptHandler; +}); + +const DEV_ADDR: u8 = 0x42; + +#[embassy_executor::task] +async fn device_task(mut dev: i2c::I2c<'static, Async, i2c::MultiMaster>) -> ! { + info!("Device start"); + + let mut state = 0; + + loop { + let mut buf = [0u8; 128]; + match dev.listen().await { + Ok(i2c::SlaveCommand { + kind: SlaveCommandKind::Read, + address: Address::SevenBit(DEV_ADDR), + }) => match dev.respond_to_read(&[state]).await { + Ok(i2c::SendStatus::LeftoverBytes(x)) => info!("tried to write {} extra bytes", x), + Ok(i2c::SendStatus::Done) => {} + Err(e) => error!("error while responding {}", e), + }, + Ok(i2c::SlaveCommand { + kind: SlaveCommandKind::Write, + address: Address::SevenBit(DEV_ADDR), + }) => match dev.respond_to_write(&mut buf).await { + Ok(len) => { + info!("Device received write: {}", buf[..len]); + + if match buf[0] { + // Set the state + 0xC2 => { + state = buf[1]; + true + } + // Reset State + 0xC8 => { + state = 0; + true + } + x => { + error!("Invalid Write Read {:x}", x); + false + } + } { + match dev.respond_to_read(&[state]).await { + Ok(read_status) => info!( + "This read is part of a write/read transaction. The response read status {}", + read_status + ), + Err(i2c::Error::Timeout) => { + info!("The device only performed a write and it not also do a read") + } + Err(e) => error!("error while responding {}", e), + } + } + } + Err(e) => error!("error while receiving {}", e), + }, + Ok(i2c::SlaveCommand { address, .. }) => { + defmt::unreachable!( + "The slave matched address: {}, which it was not configured for", + address + ); + } + Err(e) => error!("{}", e), + } + } +} + +#[embassy_executor::task] +async fn controller_task(mut con: i2c::I2c<'static, Async, i2c::Master>) { + info!("Controller start"); + + loop { + let mut resp_buff = [0u8; 1]; + for i in 0..10 { + match con.write_read(DEV_ADDR, &[0xC2, i], &mut resp_buff).await { + Ok(_) => { + info!("write_read response: {}", resp_buff); + defmt::assert_eq!(resp_buff[0], i); + } + Err(e) => error!("Error writing {}", e), + } + + Timer::after_millis(100).await; + } + match con.read(DEV_ADDR, &mut resp_buff).await { + Ok(_) => { + info!("read response: {}", resp_buff); + // assert that the state is the last index that was written + defmt::assert_eq!(resp_buff[0], 9); + } + Err(e) => error!("Error writing {}", e), + } + match con.write_read(DEV_ADDR, &[0xC8], &mut resp_buff).await { + Ok(_) => { + info!("write_read response: {}", resp_buff); + // assert that the state has been reset + defmt::assert_eq!(resp_buff[0], 0); + } + Err(e) => error!("Error writing {}", e), + } + Timer::after_millis(100).await; + } +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + info!("Hello World!"); + + let speed = Hertz::khz(400); + let config = i2c::Config::default(); + + let d_addr_config = i2c::SlaveAddrConfig { + addr: OwnAddresses::OA1(Address::SevenBit(DEV_ADDR)), + general_call: false, + }; + let d_sda = p.PA8; + let d_scl = p.PA9; + let device = i2c::I2c::new(p.I2C2, d_scl, d_sda, Irqs, p.DMA1_CH1, p.DMA1_CH2, speed, config) + .into_slave_multimaster(d_addr_config); + + unwrap!(spawner.spawn(device_task(device))); + + let c_sda = p.PB8; + let c_scl = p.PB7; + let controller = i2c::I2c::new(p.I2C1, c_sda, c_scl, Irqs, p.DMA1_CH3, p.DMA1_CH4, speed, config); + + unwrap!(spawner.spawn(controller_task(controller))); +} -- cgit From 54ef354d21f7a90b0ccddbe6d1a037b35baa6006 Mon Sep 17 00:00:00 2001 From: 1-rafael-1 Date: Fri, 18 Apr 2025 23:06:20 +0200 Subject: pwm: enable pull-down resistors for pins in Drop implementation --- embassy-rp/src/pwm.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/embassy-rp/src/pwm.rs b/embassy-rp/src/pwm.rs index 6dfb90fef..1e1ccc4c6 100644 --- a/embassy-rp/src/pwm.rs +++ b/embassy-rp/src/pwm.rs @@ -464,6 +464,10 @@ impl<'d> Drop for Pwm<'d> { pac::PWM.ch(self.slice).csr().write_clear(|w| w.set_en(false)); if let Some(pin) = &self.pin_a { pin.gpio().ctrl().write(|w| w.set_funcsel(31)); + // Enable pin PULL-DOWN + pin.pad_ctrl().modify(|w| { + w.set_pde(true); + }); } if let Some(pin) = &self.pin_b { pin.gpio().ctrl().write(|w| w.set_funcsel(31)); @@ -472,6 +476,10 @@ impl<'d> Drop for Pwm<'d> { pin.pad_ctrl().modify(|w| { w.set_ie(false); }); + // Enable pin PULL-DOWN + pin.pad_ctrl().modify(|w| { + w.set_pde(true); + }); } } } -- cgit From 8cf8fb324ce9063890d8912cccd02bc79fbffd1d Mon Sep 17 00:00:00 2001 From: Michael Medin Date: Thu, 24 Apr 2025 07:15:11 +0200 Subject: Add function to allow re-init rcc config for stm32 --- embassy-stm32/src/lib.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 226293a9d..0cc6886d9 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -616,3 +616,31 @@ fn init_hw(config: Config) -> Peripherals { p }) } + + +/// Re-initialize the `embassy-stm32` clock configuration with the provided configuration. +/// +/// This is useful when you need to alter the CPU clock after configuring peripherals. +/// For instance, configure an external clock via spi or i2c. +/// +/// Please not this only re-configures the rcc and the time driver (not GPIO, EXTI, etc). +/// +/// This should only be called after `init`. +#[cfg(not(feature = "_dual-core"))] +pub fn reinitialize_rcc(config: Config) { + critical_section::with(|cs| { + unsafe { + rcc::init(config.rcc); + + // must be after rcc init + #[cfg(feature = "_time-driver")] + time_driver::init(cs); + + #[cfg(feature = "low-power")] + { + crate::rcc::REFCOUNT_STOP2 = 0; + crate::rcc::REFCOUNT_STOP1 = 0; + } + } + }) +} -- cgit From f67f11534f9617279b9ff83a693aad5f7ceb4d4f Mon Sep 17 00:00:00 2001 From: Michael Medin Date: Thu, 24 Apr 2025 07:25:21 +0200 Subject: Fixed formatting --- embassy-stm32/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 0cc6886d9..cccffd4fe 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -617,7 +617,6 @@ fn init_hw(config: Config) -> Peripherals { }) } - /// Re-initialize the `embassy-stm32` clock configuration with the provided configuration. /// /// This is useful when you need to alter the CPU clock after configuring peripherals. -- cgit From 6842ced7cb858f7735bc9376db9d39386dadec58 Mon Sep 17 00:00:00 2001 From: Michael Medin Date: Thu, 24 Apr 2025 10:17:04 +0200 Subject: Fixed for cs not always used --- embassy-stm32/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index cccffd4fe..1ad30d522 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -627,13 +627,13 @@ fn init_hw(config: Config) -> Peripherals { /// This should only be called after `init`. #[cfg(not(feature = "_dual-core"))] pub fn reinitialize_rcc(config: Config) { - critical_section::with(|cs| { + critical_section::with(|_cs| { unsafe { rcc::init(config.rcc); // must be after rcc init #[cfg(feature = "_time-driver")] - time_driver::init(cs); + time_driver::init(_cs); #[cfg(feature = "low-power")] { -- cgit From b2c32a947ea724facb75f81978dfb5d3ca331ddb Mon Sep 17 00:00:00 2001 From: Michael Medin Date: Thu, 24 Apr 2025 10:54:35 +0200 Subject: Updated based on feedback --- embassy-stm32/src/lib.rs | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 1ad30d522..af7ef9fe0 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -222,6 +222,7 @@ pub(crate) use stm32_metapac as pac; use crate::interrupt::Priority; #[cfg(feature = "rt")] pub use crate::pac::NVIC_PRIO_BITS; +use critical_section::CriticalSection; /// `embassy-stm32` global configuration. #[non_exhaustive] @@ -600,17 +601,7 @@ fn init_hw(config: Config) -> Peripherals { #[cfg(feature = "exti")] exti::init(cs); - rcc::init(config.rcc); - - // must be after rcc init - #[cfg(feature = "_time-driver")] - time_driver::init(cs); - - #[cfg(feature = "low-power")] - { - crate::rcc::REFCOUNT_STOP2 = 0; - crate::rcc::REFCOUNT_STOP1 = 0; - } + init_rcc(cs, config.rcc); } p @@ -626,20 +617,23 @@ fn init_hw(config: Config) -> Peripherals { /// /// This should only be called after `init`. #[cfg(not(feature = "_dual-core"))] -pub fn reinitialize_rcc(config: Config) { - critical_section::with(|_cs| { - unsafe { - rcc::init(config.rcc); +pub fn reinit(config: rcc::Config) { + critical_section::with(|cs| init_rcc(cs, config)) +} - // must be after rcc init - #[cfg(feature = "_time-driver")] - time_driver::init(_cs); +#[cfg(not(feature = "_dual-core"))] +fn init_rcc(_cs: CriticalSection, config: rcc::Config) { + unsafe { + rcc::init(config); - #[cfg(feature = "low-power")] - { - crate::rcc::REFCOUNT_STOP2 = 0; - crate::rcc::REFCOUNT_STOP1 = 0; - } + // must be after rcc init + #[cfg(feature = "_time-driver")] + time_driver::init(_cs); + + #[cfg(feature = "low-power")] + { + crate::rcc::REFCOUNT_STOP2 = 0; + crate::rcc::REFCOUNT_STOP1 = 0; } - }) + } } -- cgit From 8661b019e609f50bd78067cc49c65a4babfead00 Mon Sep 17 00:00:00 2001 From: Michael Medin Date: Thu, 24 Apr 2025 10:57:02 +0200 Subject: Fixed formatting --- embassy-stm32/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index af7ef9fe0..b0bc7ffbb 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -213,6 +213,7 @@ macro_rules! bind_interrupts { // Reexports pub use _generated::{peripherals, Peripherals}; +use critical_section::CriticalSection; pub use embassy_hal_internal::{Peri, PeripheralType}; #[cfg(feature = "unstable-pac")] pub use stm32_metapac as pac; @@ -222,7 +223,6 @@ pub(crate) use stm32_metapac as pac; use crate::interrupt::Priority; #[cfg(feature = "rt")] pub use crate::pac::NVIC_PRIO_BITS; -use critical_section::CriticalSection; /// `embassy-stm32` global configuration. #[non_exhaustive] -- cgit From b0519d11fb0842267e0cdd36da9b84cdb0ebb23a Mon Sep 17 00:00:00 2001 From: Michael Medin Date: Thu, 24 Apr 2025 11:01:46 +0200 Subject: Possible fix for unused CS and feature selections --- embassy-stm32/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index b0bc7ffbb..466634edf 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -213,6 +213,7 @@ macro_rules! bind_interrupts { // Reexports pub use _generated::{peripherals, Peripherals}; +#[cfg(not(feature = "_dual-core"))] use critical_section::CriticalSection; pub use embassy_hal_internal::{Peri, PeripheralType}; #[cfg(feature = "unstable-pac")] -- cgit From 584066e209141ce92d882ceb6e7525c980833689 Mon Sep 17 00:00:00 2001 From: Michael Medin Date: Thu, 24 Apr 2025 11:07:15 +0200 Subject: updated cs gates for dual core --- embassy-stm32/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 466634edf..444d14f28 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -213,7 +213,6 @@ macro_rules! bind_interrupts { // Reexports pub use _generated::{peripherals, Peripherals}; -#[cfg(not(feature = "_dual-core"))] use critical_section::CriticalSection; pub use embassy_hal_internal::{Peri, PeripheralType}; #[cfg(feature = "unstable-pac")] @@ -622,7 +621,6 @@ pub fn reinit(config: rcc::Config) { critical_section::with(|cs| init_rcc(cs, config)) } -#[cfg(not(feature = "_dual-core"))] fn init_rcc(_cs: CriticalSection, config: rcc::Config) { unsafe { rcc::init(config); -- cgit From 74cb84eb4e4be75859deb6fa4896efae5345eacb Mon Sep 17 00:00:00 2001 From: Michael Medin Date: Mon, 28 Apr 2025 09:14:56 +0200 Subject: Moved functions to rcc module (this is a bit awkward as we now have two init functions in rcc: `rcc::init`and `rcc::init_rcc`) --- embassy-stm32/src/lib.rs | 32 +------------------------------- embassy-stm32/src/rcc/mod.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 444d14f28..3e84d3386 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -213,7 +213,6 @@ macro_rules! bind_interrupts { // Reexports pub use _generated::{peripherals, Peripherals}; -use critical_section::CriticalSection; pub use embassy_hal_internal::{Peri, PeripheralType}; #[cfg(feature = "unstable-pac")] pub use stm32_metapac as pac; @@ -601,38 +600,9 @@ fn init_hw(config: Config) -> Peripherals { #[cfg(feature = "exti")] exti::init(cs); - init_rcc(cs, config.rcc); + rcc::init_rcc(cs, config.rcc); } p }) } - -/// Re-initialize the `embassy-stm32` clock configuration with the provided configuration. -/// -/// This is useful when you need to alter the CPU clock after configuring peripherals. -/// For instance, configure an external clock via spi or i2c. -/// -/// Please not this only re-configures the rcc and the time driver (not GPIO, EXTI, etc). -/// -/// This should only be called after `init`. -#[cfg(not(feature = "_dual-core"))] -pub fn reinit(config: rcc::Config) { - critical_section::with(|cs| init_rcc(cs, config)) -} - -fn init_rcc(_cs: CriticalSection, config: rcc::Config) { - unsafe { - rcc::init(config); - - // must be after rcc init - #[cfg(feature = "_time-driver")] - time_driver::init(_cs); - - #[cfg(feature = "low-power")] - { - crate::rcc::REFCOUNT_STOP2 = 0; - crate::rcc::REFCOUNT_STOP1 = 0; - } - } -} diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 4f43d3748..cf88cfad6 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -34,6 +34,7 @@ pub use _version::*; use stm32_metapac::RCC; pub use crate::_generated::{mux, Clocks}; +use crate::rcc; use crate::time::Hertz; #[cfg(feature = "low-power")] @@ -369,3 +370,32 @@ pub fn enable_and_reset() { pub fn disable() { T::RCC_INFO.disable(); } + +/// Re-initialize the `embassy-stm32` clock configuration with the provided configuration. +/// +/// This is useful when you need to alter the CPU clock after configuring peripherals. +/// For instance, configure an external clock via spi or i2c. +/// +/// Please not this only re-configures the rcc and the time driver (not GPIO, EXTI, etc). +/// +/// This should only be called after `init`. +#[cfg(not(feature = "_dual-core"))] +pub fn reinit(config: Config) { + critical_section::with(|cs| init_rcc(cs, config)) +} + +fn init_rcc(_cs: CriticalSection, config: Config) { + unsafe { + init(config); + + // must be after rcc init + #[cfg(feature = "_time-driver")] + crate::time_driver::init(_cs); + + #[cfg(feature = "low-power")] + { + REFCOUNT_STOP2 = 0; + REFCOUNT_STOP1 = 0; + } + } +} -- cgit From 1d578f5a7e1fe2b676f36b1960a93af899418c91 Mon Sep 17 00:00:00 2001 From: Michael Medin Date: Mon, 28 Apr 2025 09:21:21 +0200 Subject: function needs to be pub(crate) --- embassy-stm32/src/rcc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index cf88cfad6..22bec6d1a 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -384,7 +384,7 @@ pub fn reinit(config: Config) { critical_section::with(|cs| init_rcc(cs, config)) } -fn init_rcc(_cs: CriticalSection, config: Config) { +pub(crate) fn init_rcc(_cs: CriticalSection, config: Config) { unsafe { init(config); -- cgit From a94cc79b9b5e01f7b207947a1dfa30432e508a9c Mon Sep 17 00:00:00 2001 From: Michael Medin Date: Mon, 28 Apr 2025 18:52:03 +0200 Subject: removed unused import --- embassy-stm32/src/rcc/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 22bec6d1a..3c00d5dfb 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -34,7 +34,6 @@ pub use _version::*; use stm32_metapac::RCC; pub use crate::_generated::{mux, Clocks}; -use crate::rcc; use crate::time::Hertz; #[cfg(feature = "low-power")] -- cgit From f8f9c38b2e2527c6e3b8396e06fbb18fc1ce2a1c Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Tue, 29 Apr 2025 08:49:19 -0400 Subject: add a task registry to tracing infrastructure --- embassy-executor/src/raw/mod.rs | 2 +- embassy-executor/src/raw/trace.rs | 139 +++++++++++++++++++++++++++++++++++++- embassy-executor/src/spawner.rs | 27 ++++++++ 3 files changed, 166 insertions(+), 2 deletions(-) diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 88d839e07..35c82557c 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -18,7 +18,7 @@ mod state; pub mod timer_queue; #[cfg(feature = "trace")] -mod trace; +pub mod trace; pub(crate) mod util; #[cfg_attr(feature = "turbowakers", path = "waker_turbo.rs")] mod waker; diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index aba519c8f..bdd3e4706 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -83,6 +83,129 @@ use crate::raw::{SyncExecutor, TaskRef}; +use core::cell::UnsafeCell; +use core::sync::atomic::{AtomicUsize, Ordering}; +use rtos_trace::TaskInfo; + +const MAX_TASKS: usize = 1000; + +/// Represents a task being tracked in the task registry. +/// +/// Contains the task's unique identifier and optional name. +#[derive(Clone)] +pub struct TrackedTask { + task_id: u32, + name: Option<&'static str>, +} + +/// A thread-safe registry for tracking tasks in the system. +/// +/// This registry maintains a list of active tasks with their IDs and optional names. +/// It supports registering, unregistering, and querying information about tasks. +/// The registry has a fixed capacity of `MAX_TASKS`. +pub struct TaskRegistry { + tasks: [UnsafeCell>; MAX_TASKS], + count: AtomicUsize, +} + +impl TaskRegistry { + /// Creates a new empty task registry. + /// + /// This initializes a registry that can track up to `MAX_TASKS` tasks. + pub const fn new() -> Self { + const EMPTY: UnsafeCell> = UnsafeCell::new(None); + Self { + tasks: [EMPTY; MAX_TASKS], + count: AtomicUsize::new(0), + } + } + + /// Registers a new task in the registry. + /// + /// # Arguments + /// * `task_id` - Unique identifier for the task + /// * `name` - Optional name for the task + /// + /// # Note + /// If the registry is full, the task will not be registered. + pub fn register(&self, task_id: u32, name: Option<&'static str>) { + let count = self.count.load(Ordering::Relaxed); + if count < MAX_TASKS { + for i in 0..MAX_TASKS { + unsafe { + let slot = &self.tasks[i]; + let slot_ref = &mut *slot.get(); + if slot_ref.is_none() { + *slot_ref = Some(TrackedTask { task_id, name }); + self.count.fetch_add(1, Ordering::Relaxed); + break; + } + } + } + } + } + + /// Removes a task from the registry. + /// + /// # Arguments + /// * `task_id` - Unique identifier of the task to remove + pub fn unregister(&self, task_id: u32) { + for i in 0..MAX_TASKS { + unsafe { + let slot = &self.tasks[i]; + let slot_ref = &mut *slot.get(); + if let Some(task) = slot_ref { + if task.task_id == task_id { + *slot_ref = None; + self.count.fetch_sub(1, Ordering::Relaxed); + break; + } + } + } + } + } + + /// Returns an iterator over all registered tasks. + /// + /// This allows accessing information about all tasks currently in the registry. + pub fn get_all_tasks(&self) -> impl Iterator + '_ { + (0..MAX_TASKS).filter_map(move |i| unsafe { + let slot = &self.tasks[i]; + (*slot.get()).clone() + }) + } + + /// Retrieves the name of a task with the given ID. + /// + /// # Arguments + /// * `task_id` - Unique identifier of the task + /// + /// # Returns + /// The name of the task if found and named, or `None` otherwise + pub fn get_task_name(&self, task_id: u32) -> Option<&'static str> { + for i in 0..MAX_TASKS { + unsafe { + let slot = &self.tasks[i]; + let slot_ref = &*slot.get(); + if let Some(task) = slot_ref { + if task.task_id == task_id { + return task.name; + } + } + } + } + None + } +} + +unsafe impl Sync for TaskRegistry {} +unsafe impl Send for TaskRegistry {} + +/// Global task registry instance used for tracking all tasks in the system. +/// +/// This provides a centralized registry accessible from anywhere in the application. +pub static TASK_REGISTRY: TaskRegistry = TaskRegistry::new(); + #[cfg(not(feature = "rtos-trace"))] extern "Rust" { /// This callback is called when the executor begins polling. This will always @@ -153,6 +276,8 @@ pub(crate) fn poll_start(executor: &SyncExecutor) { #[inline] pub(crate) fn task_new(executor: &SyncExecutor, task: &TaskRef) { + let task_id = task.as_ptr() as u32; + #[cfg(not(feature = "rtos-trace"))] unsafe { _embassy_trace_task_new(executor as *const _ as u32, task.as_ptr() as u32) @@ -164,10 +289,14 @@ pub(crate) fn task_new(executor: &SyncExecutor, task: &TaskRef) { #[inline] pub(crate) fn task_end(executor: *const SyncExecutor, task: &TaskRef) { + let task_id = task.as_ptr() as u32; + #[cfg(not(feature = "rtos-trace"))] unsafe { _embassy_trace_task_end(executor as u32, task.as_ptr() as u32) } + + TASK_REGISTRY.unregister(task_id); } #[inline] @@ -213,7 +342,15 @@ pub(crate) fn executor_idle(executor: &SyncExecutor) { #[cfg(feature = "rtos-trace")] impl rtos_trace::RtosTraceOSCallbacks for crate::raw::SyncExecutor { fn task_list() { - // We don't know what tasks exist, so we can't send them. + for task in TASK_REGISTRY.get_all_tasks() { + let info = rtos_trace::TaskInfo { + name: TASK_REGISTRY.get_task_name(task.task_id).unwrap(), + priority: 0, + stack_base: 0, + stack_size: 0, + }; + rtos_trace::trace::task_send_info(task.task_id, info); + } } fn time() -> u64 { const fn gcd(a: u64, b: u64) -> u64 { diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index ff243081c..ea754341b 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -5,6 +5,8 @@ use core::sync::atomic::Ordering; use core::task::Poll; use super::raw; +#[cfg(feature = "rtos-trace")] +use super::raw::trace::TASK_REGISTRY; /// Token to spawn a newly-created task in an executor. /// @@ -154,6 +156,31 @@ impl Spawner { } } + /// Spawns a new task with a specified name. + /// + /// # Arguments + /// * `name` - Static string name to associate with the task + /// * `token` - Token representing the task to spawn + /// + /// # Returns + /// Result indicating whether the spawn was successful + #[cfg(feature = "rtos-trace")] + pub fn spawn_named(&self, name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { + let task = token.raw_task; + mem::forget(token); + + match task { + Some(task) => { + let task_id = task.as_ptr() as u32; + TASK_REGISTRY.register(task_id, Some(name)); + + unsafe { self.executor.spawn(task) }; + Ok(()) + } + None => Err(SpawnError::Busy), + } + } + // Used by the `embassy_executor_macros::main!` macro to throw an error when spawn // fails. This is here to allow conditional use of `defmt::unwrap!` // without introducing a `defmt` feature in the `embassy_executor_macros` package, -- cgit From 032898adf5848da237e4bf55b8c06c2ff73cae7c Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Mon, 5 May 2025 12:14:14 -0400 Subject: add a stub implementation for spawn_named When rtos-trace is not enabled, spawn_named will use spawn instead --- embassy-executor/src/spawner.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index ea754341b..f87700be6 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -181,6 +181,13 @@ impl Spawner { } } + /// When rtos-trace is disabled, spawn_named falls back to regular spawn. +/// This maintains API compatibility while optimizing out the name parameter. + #[cfg(not(feature = "rtos-trace"))] + pub fn spawn_named(&self, _name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { + self.spawn(token) + } + // Used by the `embassy_executor_macros::main!` macro to throw an error when spawn // fails. This is here to allow conditional use of `defmt::unwrap!` // without introducing a `defmt` feature in the `embassy_executor_macros` package, -- cgit From bbffd2b3f9f27dd9c3ae3f66ac88bcd1ee1dcb93 Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Mon, 5 May 2025 12:17:03 -0400 Subject: whitespace in the documentation --- embassy-executor/src/spawner.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index f87700be6..4fc4312b9 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -182,7 +182,7 @@ impl Spawner { } /// When rtos-trace is disabled, spawn_named falls back to regular spawn. -/// This maintains API compatibility while optimizing out the name parameter. + /// This maintains API compatibility while optimizing out the name parameter. #[cfg(not(feature = "rtos-trace"))] pub fn spawn_named(&self, _name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { self.spawn(token) -- cgit From 05d52decb2a98ad5111962b71e667c692e68c23e Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Tue, 6 May 2025 09:04:21 -0400 Subject: add name to TaskHeader --- embassy-executor/src/raw/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 35c82557c..2928848b8 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -89,6 +89,8 @@ pub(crate) struct TaskHeader { /// Integrated timer queue storage. This field should not be accessed outside of the timer queue. pub(crate) timer_queue_item: timer_queue::TimerQueueItem, + #[cfg(feature = "trace")] + pub(crate) name: Option<&'static str>, } /// This is essentially a `&'static TaskStorage` where the type of the future has been erased. @@ -190,6 +192,8 @@ impl TaskStorage { poll_fn: SyncUnsafeCell::new(None), timer_queue_item: timer_queue::TimerQueueItem::new(), + #[cfg(feature = "trace")] + name: None, }, future: UninitCell::uninit(), } -- cgit From 61f0f889a0dc89410218be725a43dcd967e53003 Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Tue, 6 May 2025 09:23:39 -0400 Subject: add get/set for task name --- embassy-executor/src/raw/mod.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 2928848b8..3f4e06350 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -151,6 +151,21 @@ impl TaskRef { pub fn as_id(self) -> u32 { self.ptr.as_ptr() as u32 } + + /// Get the name for a task + #[cfg(feature = "trace")] + pub fn name(&self) -> Option<&'static str> { + self.header().name + } + + /// Set the name for a task + #[cfg(feature = "trace")] + pub fn set_name(&self, name: Option<&'static str>) { + unsafe { + let header_ptr = self.ptr.as_ptr() as *mut TaskHeader; + (*header_ptr).name = name; + } + } } /// Raw storage in which a task can be spawned. -- cgit From 54b3fb6e7a12598e0f6299c18a333060d6a3f9c7 Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Tue, 6 May 2025 09:27:19 -0400 Subject: remove name from TaskRegistry and retrieve from task header instead --- embassy-executor/src/raw/trace.rs | 33 ++++++--------------------------- embassy-executor/src/spawner.rs | 3 ++- 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index bdd3e4706..28be79cee 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -81,7 +81,7 @@ #![allow(unused)] -use crate::raw::{SyncExecutor, TaskRef}; +use crate::raw::{SyncExecutor, TaskHeader, TaskRef}; use core::cell::UnsafeCell; use core::sync::atomic::{AtomicUsize, Ordering}; @@ -95,7 +95,6 @@ const MAX_TASKS: usize = 1000; #[derive(Clone)] pub struct TrackedTask { task_id: u32, - name: Option<&'static str>, } /// A thread-safe registry for tracking tasks in the system. @@ -128,7 +127,7 @@ impl TaskRegistry { /// /// # Note /// If the registry is full, the task will not be registered. - pub fn register(&self, task_id: u32, name: Option<&'static str>) { + pub fn register(&self, task_id: u32) { let count = self.count.load(Ordering::Relaxed); if count < MAX_TASKS { for i in 0..MAX_TASKS { @@ -136,7 +135,7 @@ impl TaskRegistry { let slot = &self.tasks[i]; let slot_ref = &mut *slot.get(); if slot_ref.is_none() { - *slot_ref = Some(TrackedTask { task_id, name }); + *slot_ref = Some(TrackedTask { task_id }); self.count.fetch_add(1, Ordering::Relaxed); break; } @@ -174,28 +173,6 @@ impl TaskRegistry { (*slot.get()).clone() }) } - - /// Retrieves the name of a task with the given ID. - /// - /// # Arguments - /// * `task_id` - Unique identifier of the task - /// - /// # Returns - /// The name of the task if found and named, or `None` otherwise - pub fn get_task_name(&self, task_id: u32) -> Option<&'static str> { - for i in 0..MAX_TASKS { - unsafe { - let slot = &self.tasks[i]; - let slot_ref = &*slot.get(); - if let Some(task) = slot_ref { - if task.task_id == task_id { - return task.name; - } - } - } - } - None - } } unsafe impl Sync for TaskRegistry {} @@ -343,8 +320,10 @@ pub(crate) fn executor_idle(executor: &SyncExecutor) { impl rtos_trace::RtosTraceOSCallbacks for crate::raw::SyncExecutor { fn task_list() { for task in TASK_REGISTRY.get_all_tasks() { + let task_ref = unsafe { TaskRef::from_ptr(task.task_id as *const TaskHeader) }; + let name = task_ref.name().unwrap_or("unnamed\0"); let info = rtos_trace::TaskInfo { - name: TASK_REGISTRY.get_task_name(task.task_id).unwrap(), + name, priority: 0, stack_base: 0, stack_size: 0, diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index 4fc4312b9..40202299f 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -171,8 +171,9 @@ impl Spawner { match task { Some(task) => { + task.set_name(Some(name)); let task_id = task.as_ptr() as u32; - TASK_REGISTRY.register(task_id, Some(name)); + TASK_REGISTRY.register(task_id); unsafe { self.executor.spawn(task) }; Ok(()) -- cgit From f4e0cbb7cc476b171acd0b21448e9bbc848a616d Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Tue, 6 May 2025 09:59:27 -0400 Subject: add ID field to TaskHeader --- embassy-executor/src/raw/mod.rs | 19 +++++++++++++++++++ embassy-executor/src/spawner.rs | 1 + 2 files changed, 20 insertions(+) diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 3f4e06350..075d8a254 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -91,6 +91,8 @@ pub(crate) struct TaskHeader { pub(crate) timer_queue_item: timer_queue::TimerQueueItem, #[cfg(feature = "trace")] pub(crate) name: Option<&'static str>, + #[cfg(feature = "trace")] + pub(crate) id: u32, } /// This is essentially a `&'static TaskStorage` where the type of the future has been erased. @@ -166,6 +168,21 @@ impl TaskRef { (*header_ptr).name = name; } } + + /// Get the ID for a task + #[cfg(feature = "trace")] + pub fn id(&self) -> u32 { + self.header().id + } + + /// Set the ID for a task + #[cfg(feature = "trace")] + pub fn set_id(&self, id: u32) { + unsafe { + let header_ptr = self.ptr.as_ptr() as *mut TaskHeader; + (*header_ptr).id = id; + } + } } /// Raw storage in which a task can be spawned. @@ -209,6 +226,8 @@ impl TaskStorage { timer_queue_item: timer_queue::TimerQueueItem::new(), #[cfg(feature = "trace")] name: None, + #[cfg(feature = "trace")] + id: 0, }, future: UninitCell::uninit(), } diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index 40202299f..7f907346d 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -174,6 +174,7 @@ impl Spawner { task.set_name(Some(name)); let task_id = task.as_ptr() as u32; TASK_REGISTRY.register(task_id); + task.set_id(task_id); unsafe { self.executor.spawn(task) }; Ok(()) -- cgit From 6085916714b79a888e117a2d7223e78c9a5de9d3 Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Tue, 6 May 2025 11:47:04 -0400 Subject: use an intrusive linked list in TaskHeader to track tasks --- embassy-executor/src/raw/mod.rs | 76 ++++++++++++++- embassy-executor/src/raw/trace.rs | 190 ++++++++++++++++++-------------------- embassy-executor/src/spawner.rs | 3 - 3 files changed, 163 insertions(+), 106 deletions(-) diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 075d8a254..b4adfe01b 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -93,6 +93,78 @@ pub(crate) struct TaskHeader { pub(crate) name: Option<&'static str>, #[cfg(feature = "trace")] pub(crate) id: u32, + #[cfg(feature = "trace")] + all_tasks_next: AtomicPtr, +} + +/// A thread-safe tracker for all tasks in the system +/// +/// This struct uses an intrusive linked list approach to track all tasks +/// without additional memory allocations. It maintains a global list of +/// tasks that can be traversed to find all currently existing tasks. +#[cfg(feature = "trace")] +pub struct TaskTracker { + head: AtomicPtr, +} + +#[cfg(feature = "trace")] +impl TaskTracker { + /// Creates a new empty task tracker + /// + /// Initializes a tracker with no tasks in its list. + pub const fn new() -> Self { + Self { + head: AtomicPtr::new(core::ptr::null_mut()), + } + } + + /// Adds a task to the tracker + /// + /// This method inserts a task at the head of the intrusive linked list. + /// The operation is thread-safe and lock-free, using atomic operations + /// to ensure consistency even when called from different contexts. + /// + /// # Arguments + /// * `task` - The task reference to add to the tracker + pub fn add(&self, task: TaskRef) { + let task_ptr = task.as_ptr() as *mut TaskHeader; + + loop { + let current_head = self.head.load(Ordering::Acquire); + unsafe { + (*task_ptr).all_tasks_next.store(current_head, Ordering::Relaxed); + } + + if self + .head + .compare_exchange(current_head, task_ptr, Ordering::Release, Ordering::Relaxed) + .is_ok() + { + break; + } + } + } + + /// Performs an operation on each task in the tracker + /// + /// This method traverses the entire list of tasks and calls the provided + /// function for each task. This allows inspecting or processing all tasks + /// in the system without modifying the tracker's structure. + /// + /// # Arguments + /// * `f` - A function to call for each task in the tracker + pub fn for_each(&self, mut f: F) + where + F: FnMut(TaskRef), + { + let mut current = self.head.load(Ordering::Acquire); + while !current.is_null() { + let task = unsafe { TaskRef::from_ptr(current) }; + f(task); + + current = unsafe { (*current).all_tasks_next.load(Ordering::Acquire) }; + } + } } /// This is essentially a `&'static TaskStorage` where the type of the future has been erased. @@ -173,7 +245,7 @@ impl TaskRef { #[cfg(feature = "trace")] pub fn id(&self) -> u32 { self.header().id - } + } /// Set the ID for a task #[cfg(feature = "trace")] @@ -228,6 +300,8 @@ impl TaskStorage { name: None, #[cfg(feature = "trace")] id: 0, + #[cfg(feature = "trace")] + all_tasks_next: AtomicPtr::new(core::ptr::null_mut()), }, future: UninitCell::uninit(), } diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index 28be79cee..81c8a0024 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -81,107 +81,19 @@ #![allow(unused)] -use crate::raw::{SyncExecutor, TaskHeader, TaskRef}; +use crate::raw::{SyncExecutor, TaskHeader, TaskRef, TaskTracker}; use core::cell::UnsafeCell; use core::sync::atomic::{AtomicUsize, Ordering}; use rtos_trace::TaskInfo; -const MAX_TASKS: usize = 1000; - -/// Represents a task being tracked in the task registry. -/// -/// Contains the task's unique identifier and optional name. -#[derive(Clone)] -pub struct TrackedTask { - task_id: u32, -} - -/// A thread-safe registry for tracking tasks in the system. -/// -/// This registry maintains a list of active tasks with their IDs and optional names. -/// It supports registering, unregistering, and querying information about tasks. -/// The registry has a fixed capacity of `MAX_TASKS`. -pub struct TaskRegistry { - tasks: [UnsafeCell>; MAX_TASKS], - count: AtomicUsize, -} - -impl TaskRegistry { - /// Creates a new empty task registry. - /// - /// This initializes a registry that can track up to `MAX_TASKS` tasks. - pub const fn new() -> Self { - const EMPTY: UnsafeCell> = UnsafeCell::new(None); - Self { - tasks: [EMPTY; MAX_TASKS], - count: AtomicUsize::new(0), - } - } - - /// Registers a new task in the registry. - /// - /// # Arguments - /// * `task_id` - Unique identifier for the task - /// * `name` - Optional name for the task - /// - /// # Note - /// If the registry is full, the task will not be registered. - pub fn register(&self, task_id: u32) { - let count = self.count.load(Ordering::Relaxed); - if count < MAX_TASKS { - for i in 0..MAX_TASKS { - unsafe { - let slot = &self.tasks[i]; - let slot_ref = &mut *slot.get(); - if slot_ref.is_none() { - *slot_ref = Some(TrackedTask { task_id }); - self.count.fetch_add(1, Ordering::Relaxed); - break; - } - } - } - } - } - - /// Removes a task from the registry. - /// - /// # Arguments - /// * `task_id` - Unique identifier of the task to remove - pub fn unregister(&self, task_id: u32) { - for i in 0..MAX_TASKS { - unsafe { - let slot = &self.tasks[i]; - let slot_ref = &mut *slot.get(); - if let Some(task) = slot_ref { - if task.task_id == task_id { - *slot_ref = None; - self.count.fetch_sub(1, Ordering::Relaxed); - break; - } - } - } - } - } - - /// Returns an iterator over all registered tasks. - /// - /// This allows accessing information about all tasks currently in the registry. - pub fn get_all_tasks(&self) -> impl Iterator + '_ { - (0..MAX_TASKS).filter_map(move |i| unsafe { - let slot = &self.tasks[i]; - (*slot.get()).clone() - }) - } -} - -unsafe impl Sync for TaskRegistry {} -unsafe impl Send for TaskRegistry {} - -/// Global task registry instance used for tracking all tasks in the system. +/// Global task tracker instance /// -/// This provides a centralized registry accessible from anywhere in the application. -pub static TASK_REGISTRY: TaskRegistry = TaskRegistry::new(); +/// This static provides access to the global task tracker which maintains +/// a list of all tasks in the system. It's automatically updated by the +/// task lifecycle hooks in the trace module. +#[cfg(feature = "trace")] +pub static TASK_TRACKER: TaskTracker = TaskTracker::new(); #[cfg(not(feature = "rtos-trace"))] extern "Rust" { @@ -262,6 +174,9 @@ pub(crate) fn task_new(executor: &SyncExecutor, task: &TaskRef) { #[cfg(feature = "rtos-trace")] rtos_trace::trace::task_new(task.as_ptr() as u32); + + #[cfg(feature = "rtos-trace")] + TASK_TRACKER.add(*task); } #[inline] @@ -272,8 +187,6 @@ pub(crate) fn task_end(executor: *const SyncExecutor, task: &TaskRef) { unsafe { _embassy_trace_task_end(executor as u32, task.as_ptr() as u32) } - - TASK_REGISTRY.unregister(task_id); } #[inline] @@ -316,20 +229,93 @@ pub(crate) fn executor_idle(executor: &SyncExecutor) { rtos_trace::trace::system_idle(); } +/// Returns an iterator over all active tasks in the system +/// +/// This function provides a convenient way to iterate over all tasks +/// that are currently tracked in the system. The returned iterator +/// yields each task in the global task tracker. +/// +/// # Returns +/// An iterator that yields `TaskRef` items for each task +#[cfg(feature = "trace")] +pub fn get_all_active_tasks() -> impl Iterator + 'static { + struct TaskIterator<'a> { + tracker: &'a TaskTracker, + current: *mut TaskHeader, + } + + impl<'a> Iterator for TaskIterator<'a> { + type Item = TaskRef; + + fn next(&mut self) -> Option { + if self.current.is_null() { + return None; + } + + let task = unsafe { TaskRef::from_ptr(self.current) }; + self.current = unsafe { (*self.current).all_tasks_next.load(Ordering::Acquire) }; + + Some(task) + } + } + + TaskIterator { + tracker: &TASK_TRACKER, + current: TASK_TRACKER.head.load(Ordering::Acquire), + } +} + +/// Get all active tasks, filtered by a predicate function +#[cfg(feature = "trace")] +pub fn filter_active_tasks(predicate: F) -> impl Iterator + 'static +where + F: Fn(&TaskRef) -> bool + 'static, +{ + get_all_active_tasks().filter(move |task| predicate(task)) +} + +/// Count the number of active tasks +#[cfg(feature = "trace")] +pub fn count_active_tasks() -> usize { + let mut count = 0; + TASK_TRACKER.for_each(|_| count += 1); + count +} + +/// Perform an action on each active task +#[cfg(feature = "trace")] +pub fn with_all_active_tasks(f: F) +where + F: FnMut(TaskRef), +{ + TASK_TRACKER.for_each(f); +} + +/// Get tasks by name +#[cfg(feature = "trace")] +pub fn get_tasks_by_name(name: &'static str) -> impl Iterator + 'static { + filter_active_tasks(move |task| task.name() == Some(name)) +} + +/// Get tasks by ID +#[cfg(feature = "trace")] +pub fn get_task_by_id(id: u32) -> Option { + filter_active_tasks(move |task| task.id() == id).next() +} + #[cfg(feature = "rtos-trace")] impl rtos_trace::RtosTraceOSCallbacks for crate::raw::SyncExecutor { fn task_list() { - for task in TASK_REGISTRY.get_all_tasks() { - let task_ref = unsafe { TaskRef::from_ptr(task.task_id as *const TaskHeader) }; - let name = task_ref.name().unwrap_or("unnamed\0"); + with_all_active_tasks(|task| { + let name = task.name().unwrap_or("unnamed task\0"); let info = rtos_trace::TaskInfo { name, priority: 0, stack_base: 0, stack_size: 0, }; - rtos_trace::trace::task_send_info(task.task_id, info); - } + rtos_trace::trace::task_send_info(task.as_id(), info); + }); } fn time() -> u64 { const fn gcd(a: u64, b: u64) -> u64 { diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index 7f907346d..5e42f01bf 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -5,8 +5,6 @@ use core::sync::atomic::Ordering; use core::task::Poll; use super::raw; -#[cfg(feature = "rtos-trace")] -use super::raw::trace::TASK_REGISTRY; /// Token to spawn a newly-created task in an executor. /// @@ -173,7 +171,6 @@ impl Spawner { Some(task) => { task.set_name(Some(name)); let task_id = task.as_ptr() as u32; - TASK_REGISTRY.register(task_id); task.set_id(task_id); unsafe { self.executor.spawn(task) }; -- cgit From f2429c212e77969bacfe726cd293bf0ab5903664 Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Tue, 6 May 2025 11:54:45 -0400 Subject: fix whitespace in the imports in trace.rs --- embassy-executor/src/raw/trace.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index 81c8a0024..c0599d2c7 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -81,12 +81,13 @@ #![allow(unused)] -use crate::raw::{SyncExecutor, TaskHeader, TaskRef, TaskTracker}; - use core::cell::UnsafeCell; use core::sync::atomic::{AtomicUsize, Ordering}; + use rtos_trace::TaskInfo; +use crate::raw::{SyncExecutor, TaskHeader, TaskRef, TaskTracker}; + /// Global task tracker instance /// /// This static provides access to the global task tracker which maintains -- cgit From b3e13cc6de744a241521cff20725706a1e40ef25 Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Thu, 8 May 2025 10:58:07 -0400 Subject: make tracing API functions internal --- embassy-executor/src/raw/trace.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index c0599d2c7..503d806bd 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -239,7 +239,7 @@ pub(crate) fn executor_idle(executor: &SyncExecutor) { /// # Returns /// An iterator that yields `TaskRef` items for each task #[cfg(feature = "trace")] -pub fn get_all_active_tasks() -> impl Iterator + 'static { +fn get_all_active_tasks() -> impl Iterator + 'static { struct TaskIterator<'a> { tracker: &'a TaskTracker, current: *mut TaskHeader, @@ -285,7 +285,7 @@ pub fn count_active_tasks() -> usize { /// Perform an action on each active task #[cfg(feature = "trace")] -pub fn with_all_active_tasks(f: F) +fn with_all_active_tasks(f: F) where F: FnMut(TaskRef), { -- cgit From 8f18810ec61ce235a4c895413936e0216ed22c4f Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Thu, 8 May 2025 10:58:27 -0400 Subject: remove unused tracing API --- embassy-executor/src/raw/trace.rs | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index 503d806bd..fec3a4834 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -266,23 +266,6 @@ fn get_all_active_tasks() -> impl Iterator + 'static { } } -/// Get all active tasks, filtered by a predicate function -#[cfg(feature = "trace")] -pub fn filter_active_tasks(predicate: F) -> impl Iterator + 'static -where - F: Fn(&TaskRef) -> bool + 'static, -{ - get_all_active_tasks().filter(move |task| predicate(task)) -} - -/// Count the number of active tasks -#[cfg(feature = "trace")] -pub fn count_active_tasks() -> usize { - let mut count = 0; - TASK_TRACKER.for_each(|_| count += 1); - count -} - /// Perform an action on each active task #[cfg(feature = "trace")] fn with_all_active_tasks(f: F) @@ -292,18 +275,6 @@ where TASK_TRACKER.for_each(f); } -/// Get tasks by name -#[cfg(feature = "trace")] -pub fn get_tasks_by_name(name: &'static str) -> impl Iterator + 'static { - filter_active_tasks(move |task| task.name() == Some(name)) -} - -/// Get tasks by ID -#[cfg(feature = "trace")] -pub fn get_task_by_id(id: u32) -> Option { - filter_active_tasks(move |task| task.id() == id).next() -} - #[cfg(feature = "rtos-trace")] impl rtos_trace::RtosTraceOSCallbacks for crate::raw::SyncExecutor { fn task_list() { -- cgit From 56b5e35c60743d65aacee753d1db391c3cbeae16 Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Thu, 8 May 2025 10:58:59 -0400 Subject: change rtos-trace feature flag on tracing API to trace feature flag --- embassy-executor/src/spawner.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index 5e42f01bf..a0d246616 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -162,7 +162,7 @@ impl Spawner { /// /// # Returns /// Result indicating whether the spawn was successful - #[cfg(feature = "rtos-trace")] + #[cfg(feature = "trace")] pub fn spawn_named(&self, name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { let task = token.raw_task; mem::forget(token); @@ -182,7 +182,7 @@ impl Spawner { /// When rtos-trace is disabled, spawn_named falls back to regular spawn. /// This maintains API compatibility while optimizing out the name parameter. - #[cfg(not(feature = "rtos-trace"))] + #[cfg(not(feature = "trace"))] pub fn spawn_named(&self, _name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { self.spawn(token) } -- cgit From 8a8deb704fdd58cecf463f033cd3c3d1cc3534c7 Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Thu, 8 May 2025 11:20:22 -0400 Subject: move spawn_named into trace.rs through TraceExt trait --- embassy-executor/src/raw/trace.rs | 43 +++++++++++++++++++++++++++++++++++++++ embassy-executor/src/spawner.rs | 37 ++------------------------------- 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index fec3a4834..eb960f721 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -87,6 +87,49 @@ use core::sync::atomic::{AtomicUsize, Ordering}; use rtos_trace::TaskInfo; use crate::raw::{SyncExecutor, TaskHeader, TaskRef, TaskTracker}; +use crate::spawner::{SpawnError, SpawnToken, Spawner}; + +/// Extension trait adding tracing capabilities to the Spawner +pub trait TraceExt { + /// Spawns a new task with a specified name. + /// + /// # Arguments + /// * `name` - Static string name to associate with the task + /// * `token` - Token representing the task to spawn + /// + /// # Returns + /// Result indicating whether the spawn was successful + fn spawn_named(&self, name: &'static str, token: SpawnToken) -> Result<(), SpawnError>; +} + +#[cfg(feature = "trace")] +impl TraceExt for Spawner { + fn spawn_named(&self, name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { + let task = token.raw_task; + core::mem::forget(token); + + match task { + Some(task) => { + task.set_name(Some(name)); + let task_id = task.as_ptr() as u32; + task.set_id(task_id); + + unsafe { self.executor.spawn(task) }; + Ok(()) + } + None => Err(SpawnError::Busy), + } + } +} + +/// When trace is disabled, spawn_named falls back to regular spawn. +/// This maintains API compatibility while optimizing out the name parameter. +#[cfg(not(feature = "trace"))] +impl TraceExt for Spawner { + fn spawn_named(&self, _name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { + self.spawn(token) + } +} /// Global task tracker instance /// diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index a0d246616..6b8db4f8f 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -22,7 +22,7 @@ use super::raw; /// Once you've invoked a task function and obtained a SpawnToken, you *must* spawn it. #[must_use = "Calling a task function does nothing on its own. You must spawn the returned SpawnToken, typically with Spawner::spawn()"] pub struct SpawnToken { - raw_task: Option, + pub(crate) raw_task: Option, phantom: PhantomData<*mut S>, } @@ -103,7 +103,7 @@ impl core::error::Error for SpawnError {} /// If you want to spawn tasks from another thread, use [SendSpawner]. #[derive(Copy, Clone)] pub struct Spawner { - executor: &'static raw::Executor, + pub(crate) executor: &'static raw::Executor, not_send: PhantomData<*mut ()>, } @@ -154,39 +154,6 @@ impl Spawner { } } - /// Spawns a new task with a specified name. - /// - /// # Arguments - /// * `name` - Static string name to associate with the task - /// * `token` - Token representing the task to spawn - /// - /// # Returns - /// Result indicating whether the spawn was successful - #[cfg(feature = "trace")] - pub fn spawn_named(&self, name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { - let task = token.raw_task; - mem::forget(token); - - match task { - Some(task) => { - task.set_name(Some(name)); - let task_id = task.as_ptr() as u32; - task.set_id(task_id); - - unsafe { self.executor.spawn(task) }; - Ok(()) - } - None => Err(SpawnError::Busy), - } - } - - /// When rtos-trace is disabled, spawn_named falls back to regular spawn. - /// This maintains API compatibility while optimizing out the name parameter. - #[cfg(not(feature = "trace"))] - pub fn spawn_named(&self, _name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { - self.spawn(token) - } - // Used by the `embassy_executor_macros::main!` macro to throw an error when spawn // fails. This is here to allow conditional use of `defmt::unwrap!` // without introducing a `defmt` feature in the `embassy_executor_macros` package, -- cgit From 462d04c6d5a0fc6072cf9bdb0faa60da74ff46d2 Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Thu, 8 May 2025 13:34:32 -0400 Subject: move TaskTracker to trace --- embassy-executor/src/raw/mod.rs | 70 ------------------------------------ embassy-executor/src/raw/trace.rs | 74 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 72 deletions(-) diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index b4adfe01b..882e4605b 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -97,76 +97,6 @@ pub(crate) struct TaskHeader { all_tasks_next: AtomicPtr, } -/// A thread-safe tracker for all tasks in the system -/// -/// This struct uses an intrusive linked list approach to track all tasks -/// without additional memory allocations. It maintains a global list of -/// tasks that can be traversed to find all currently existing tasks. -#[cfg(feature = "trace")] -pub struct TaskTracker { - head: AtomicPtr, -} - -#[cfg(feature = "trace")] -impl TaskTracker { - /// Creates a new empty task tracker - /// - /// Initializes a tracker with no tasks in its list. - pub const fn new() -> Self { - Self { - head: AtomicPtr::new(core::ptr::null_mut()), - } - } - - /// Adds a task to the tracker - /// - /// This method inserts a task at the head of the intrusive linked list. - /// The operation is thread-safe and lock-free, using atomic operations - /// to ensure consistency even when called from different contexts. - /// - /// # Arguments - /// * `task` - The task reference to add to the tracker - pub fn add(&self, task: TaskRef) { - let task_ptr = task.as_ptr() as *mut TaskHeader; - - loop { - let current_head = self.head.load(Ordering::Acquire); - unsafe { - (*task_ptr).all_tasks_next.store(current_head, Ordering::Relaxed); - } - - if self - .head - .compare_exchange(current_head, task_ptr, Ordering::Release, Ordering::Relaxed) - .is_ok() - { - break; - } - } - } - - /// Performs an operation on each task in the tracker - /// - /// This method traverses the entire list of tasks and calls the provided - /// function for each task. This allows inspecting or processing all tasks - /// in the system without modifying the tracker's structure. - /// - /// # Arguments - /// * `f` - A function to call for each task in the tracker - pub fn for_each(&self, mut f: F) - where - F: FnMut(TaskRef), - { - let mut current = self.head.load(Ordering::Acquire); - while !current.is_null() { - let task = unsafe { TaskRef::from_ptr(current) }; - f(task); - - current = unsafe { (*current).all_tasks_next.load(Ordering::Acquire) }; - } - } -} - /// This is essentially a `&'static TaskStorage` where the type of the future has been erased. #[derive(Clone, Copy, PartialEq)] pub struct TaskRef { diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index eb960f721..b59da0526 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -82,11 +82,11 @@ #![allow(unused)] use core::cell::UnsafeCell; -use core::sync::atomic::{AtomicUsize, Ordering}; +use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; use rtos_trace::TaskInfo; -use crate::raw::{SyncExecutor, TaskHeader, TaskRef, TaskTracker}; +use crate::raw::{SyncExecutor, TaskHeader, TaskRef}; use crate::spawner::{SpawnError, SpawnToken, Spawner}; /// Extension trait adding tracing capabilities to the Spawner @@ -139,6 +139,76 @@ impl TraceExt for Spawner { #[cfg(feature = "trace")] pub static TASK_TRACKER: TaskTracker = TaskTracker::new(); +/// A thread-safe tracker for all tasks in the system +/// +/// This struct uses an intrusive linked list approach to track all tasks +/// without additional memory allocations. It maintains a global list of +/// tasks that can be traversed to find all currently existing tasks. +#[cfg(feature = "trace")] +pub struct TaskTracker { + head: AtomicPtr, +} + +#[cfg(feature = "trace")] +impl TaskTracker { + /// Creates a new empty task tracker + /// + /// Initializes a tracker with no tasks in its list. + pub const fn new() -> Self { + Self { + head: AtomicPtr::new(core::ptr::null_mut()), + } + } + + /// Adds a task to the tracker + /// + /// This method inserts a task at the head of the intrusive linked list. + /// The operation is thread-safe and lock-free, using atomic operations + /// to ensure consistency even when called from different contexts. + /// + /// # Arguments + /// * `task` - The task reference to add to the tracker + pub fn add(&self, task: TaskRef) { + let task_ptr = task.as_ptr() as *mut TaskHeader; + + loop { + let current_head = self.head.load(Ordering::Acquire); + unsafe { + (*task_ptr).all_tasks_next.store(current_head, Ordering::Relaxed); + } + + if self + .head + .compare_exchange(current_head, task_ptr, Ordering::Release, Ordering::Relaxed) + .is_ok() + { + break; + } + } + } + + /// Performs an operation on each task in the tracker + /// + /// This method traverses the entire list of tasks and calls the provided + /// function for each task. This allows inspecting or processing all tasks + /// in the system without modifying the tracker's structure. + /// + /// # Arguments + /// * `f` - A function to call for each task in the tracker + pub fn for_each(&self, mut f: F) + where + F: FnMut(TaskRef), + { + let mut current = self.head.load(Ordering::Acquire); + while !current.is_null() { + let task = unsafe { TaskRef::from_ptr(current) }; + f(task); + + current = unsafe { (*current).all_tasks_next.load(Ordering::Acquire) }; + } + } +} + #[cfg(not(feature = "rtos-trace"))] extern "Rust" { /// This callback is called when the executor begins polling. This will always -- cgit From 3b873bb6bb51b9bdac9272b5ec629a6ac54a89f7 Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Thu, 8 May 2025 13:40:32 -0400 Subject: implement TaskRefTrace for tracing-only fields in TaskRef --- embassy-executor/src/raw/mod.rs | 36 --------------------------- embassy-executor/src/raw/trace.rs | 52 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 36 deletions(-) diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 882e4605b..e7a27035a 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -149,42 +149,6 @@ impl TaskRef { pub(crate) fn as_ptr(self) -> *const TaskHeader { self.ptr.as_ptr() } - - /// Get the ID for a task - #[cfg(feature = "trace")] - pub fn as_id(self) -> u32 { - self.ptr.as_ptr() as u32 - } - - /// Get the name for a task - #[cfg(feature = "trace")] - pub fn name(&self) -> Option<&'static str> { - self.header().name - } - - /// Set the name for a task - #[cfg(feature = "trace")] - pub fn set_name(&self, name: Option<&'static str>) { - unsafe { - let header_ptr = self.ptr.as_ptr() as *mut TaskHeader; - (*header_ptr).name = name; - } - } - - /// Get the ID for a task - #[cfg(feature = "trace")] - pub fn id(&self) -> u32 { - self.header().id - } - - /// Set the ID for a task - #[cfg(feature = "trace")] - pub fn set_id(&self, id: u32) { - unsafe { - let header_ptr = self.ptr.as_ptr() as *mut TaskHeader; - (*header_ptr).id = id; - } - } } /// Raw storage in which a task can be spawned. diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index b59da0526..b30f23468 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -209,6 +209,58 @@ impl TaskTracker { } } +/// Extension trait for `TaskRef` that provides tracing functionality. +/// +/// This trait is only available when the `trace` feature is enabled. +/// It extends `TaskRef` with methods for accessing and modifying task identifiers +/// and names, which are useful for debugging, logging, and performance analysis. +#[cfg(feature = "trace")] +pub trait TaskRefTrace { + /// Get the ID for a task + fn as_id(self) -> u32; + + /// Get the name for a task + fn name(&self) -> Option<&'static str>; + + /// Set the name for a task + fn set_name(&self, name: Option<&'static str>); + + /// Get the ID for a task + fn id(&self) -> u32; + + /// Set the ID for a task + fn set_id(&self, id: u32); +} + +#[cfg(feature = "trace")] +impl TaskRefTrace for TaskRef { + fn as_id(self) -> u32 { + self.ptr.as_ptr() as u32 + } + + fn name(&self) -> Option<&'static str> { + self.header().name + } + + fn set_name(&self, name: Option<&'static str>) { + unsafe { + let header_ptr = self.ptr.as_ptr() as *mut TaskHeader; + (*header_ptr).name = name; + } + } + + fn id(&self) -> u32 { + self.header().id + } + + fn set_id(&self, id: u32) { + unsafe { + let header_ptr = self.ptr.as_ptr() as *mut TaskHeader; + (*header_ptr).id = id; + } + } +} + #[cfg(not(feature = "rtos-trace"))] extern "Rust" { /// This callback is called when the executor begins polling. This will always -- cgit From 194a3044acb5cd9691ced78596b9fd81e6884667 Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Thu, 8 May 2025 13:41:23 -0400 Subject: remove unused task_id --- embassy-executor/src/raw/trace.rs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index b30f23468..04e9d234f 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -216,9 +216,6 @@ impl TaskTracker { /// and names, which are useful for debugging, logging, and performance analysis. #[cfg(feature = "trace")] pub trait TaskRefTrace { - /// Get the ID for a task - fn as_id(self) -> u32; - /// Get the name for a task fn name(&self) -> Option<&'static str>; @@ -234,10 +231,6 @@ pub trait TaskRefTrace { #[cfg(feature = "trace")] impl TaskRefTrace for TaskRef { - fn as_id(self) -> u32 { - self.ptr.as_ptr() as u32 - } - fn name(&self) -> Option<&'static str> { self.header().name } @@ -331,8 +324,6 @@ pub(crate) fn poll_start(executor: &SyncExecutor) { #[inline] pub(crate) fn task_new(executor: &SyncExecutor, task: &TaskRef) { - let task_id = task.as_ptr() as u32; - #[cfg(not(feature = "rtos-trace"))] unsafe { _embassy_trace_task_new(executor as *const _ as u32, task.as_ptr() as u32) @@ -347,8 +338,6 @@ pub(crate) fn task_new(executor: &SyncExecutor, task: &TaskRef) { #[inline] pub(crate) fn task_end(executor: *const SyncExecutor, task: &TaskRef) { - let task_id = task.as_ptr() as u32; - #[cfg(not(feature = "rtos-trace"))] unsafe { _embassy_trace_task_end(executor as u32, task.as_ptr() as u32) @@ -451,7 +440,7 @@ impl rtos_trace::RtosTraceOSCallbacks for crate::raw::SyncExecutor { stack_base: 0, stack_size: 0, }; - rtos_trace::trace::task_send_info(task.as_id(), info); + rtos_trace::trace::task_send_info(task.id(), info); }); } fn time() -> u64 { -- cgit From e968c4763694d676cca6f1bd30949619dd12e962 Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Thu, 8 May 2025 14:03:03 -0400 Subject: update TraceExt trait name for Spawner --- embassy-executor/src/raw/trace.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index 04e9d234f..f55033530 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -90,7 +90,7 @@ use crate::raw::{SyncExecutor, TaskHeader, TaskRef}; use crate::spawner::{SpawnError, SpawnToken, Spawner}; /// Extension trait adding tracing capabilities to the Spawner -pub trait TraceExt { +pub trait SpawnerTraceExt { /// Spawns a new task with a specified name. /// /// # Arguments @@ -103,7 +103,7 @@ pub trait TraceExt { } #[cfg(feature = "trace")] -impl TraceExt for Spawner { +impl SpawnerTraceExt for Spawner { fn spawn_named(&self, name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { let task = token.raw_task; core::mem::forget(token); @@ -125,7 +125,7 @@ impl TraceExt for Spawner { /// When trace is disabled, spawn_named falls back to regular spawn. /// This maintains API compatibility while optimizing out the name parameter. #[cfg(not(feature = "trace"))] -impl TraceExt for Spawner { +impl SpawnerTraceExt for Spawner { fn spawn_named(&self, _name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { self.spawn(token) } -- cgit From dfaab013ebaaa4a19c06f2eb00821712ff13cf7a Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Thu, 8 May 2025 14:35:43 -0400 Subject: move SpawnerTraceExt back into Spawner --- embassy-executor/src/raw/trace.rs | 42 -------------------------------- embassy-executor/src/spawner.rs | 50 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 42 deletions(-) diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index f55033530..593f7b0ba 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -89,48 +89,6 @@ use rtos_trace::TaskInfo; use crate::raw::{SyncExecutor, TaskHeader, TaskRef}; use crate::spawner::{SpawnError, SpawnToken, Spawner}; -/// Extension trait adding tracing capabilities to the Spawner -pub trait SpawnerTraceExt { - /// Spawns a new task with a specified name. - /// - /// # Arguments - /// * `name` - Static string name to associate with the task - /// * `token` - Token representing the task to spawn - /// - /// # Returns - /// Result indicating whether the spawn was successful - fn spawn_named(&self, name: &'static str, token: SpawnToken) -> Result<(), SpawnError>; -} - -#[cfg(feature = "trace")] -impl SpawnerTraceExt for Spawner { - fn spawn_named(&self, name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { - let task = token.raw_task; - core::mem::forget(token); - - match task { - Some(task) => { - task.set_name(Some(name)); - let task_id = task.as_ptr() as u32; - task.set_id(task_id); - - unsafe { self.executor.spawn(task) }; - Ok(()) - } - None => Err(SpawnError::Busy), - } - } -} - -/// When trace is disabled, spawn_named falls back to regular spawn. -/// This maintains API compatibility while optimizing out the name parameter. -#[cfg(not(feature = "trace"))] -impl SpawnerTraceExt for Spawner { - fn spawn_named(&self, _name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { - self.spawn(token) - } -} - /// Global task tracker instance /// /// This static provides access to the global task tracker which maintains diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index 6b8db4f8f..bfb32ebcc 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -6,6 +6,9 @@ use core::task::Poll; use super::raw; +#[cfg(feature = "trace")] +use crate::raw::trace::TaskRefTrace; + /// Token to spawn a newly-created task in an executor. /// /// When calling a task function (like `#[embassy_executor::task] async fn my_task() { ... }`), the returned @@ -180,6 +183,53 @@ impl Spawner { } } +/// Extension trait adding tracing capabilities to the Spawner +/// +/// This trait provides an additional method to spawn tasks with an associated name, +/// which can be useful for debugging and tracing purposes. +pub trait SpawnerTraceExt { + /// Spawns a new task with a specified name. + /// + /// # Arguments + /// * `name` - Static string name to associate with the task + /// * `token` - Token representing the task to spawn + /// + /// # Returns + /// Result indicating whether the spawn was successful + fn spawn_named(&self, name: &'static str, token: SpawnToken) -> Result<(), SpawnError>; +} + +/// Implementation of the SpawnerTraceExt trait for Spawner when trace is enabled +#[cfg(feature = "trace")] +impl SpawnerTraceExt for Spawner { + fn spawn_named(&self, name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { + let task = token.raw_task; + core::mem::forget(token); + + match task { + Some(task) => { + // Set the name and ID when trace is enabled + task.set_name(Some(name)); + let task_id = task.as_ptr() as u32; + task.set_id(task_id); + + unsafe { self.executor.spawn(task) }; + Ok(()) + } + None => Err(SpawnError::Busy), + } + } +} + +/// Implementation of the SpawnerTraceExt trait for Spawner when trace is disabled +#[cfg(not(feature = "trace"))] +impl SpawnerTraceExt for Spawner { + fn spawn_named(&self, _name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { + // When trace is disabled, just forward to regular spawn and ignore the name + self.spawn(token) + } +} + /// Handle to spawn tasks into an executor from any thread. /// /// This Spawner can be used from any thread (it is Send), but it can -- cgit From 3ffa2e4f3f9ecbca8637ae1603194a63d55b4396 Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Thu, 8 May 2025 16:30:06 -0400 Subject: remove unnecessary trace flags --- embassy-executor/src/raw/trace.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index 593f7b0ba..6c9cfda25 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -94,7 +94,6 @@ use crate::spawner::{SpawnError, SpawnToken, Spawner}; /// This static provides access to the global task tracker which maintains /// a list of all tasks in the system. It's automatically updated by the /// task lifecycle hooks in the trace module. -#[cfg(feature = "trace")] pub static TASK_TRACKER: TaskTracker = TaskTracker::new(); /// A thread-safe tracker for all tasks in the system @@ -102,12 +101,10 @@ pub static TASK_TRACKER: TaskTracker = TaskTracker::new(); /// This struct uses an intrusive linked list approach to track all tasks /// without additional memory allocations. It maintains a global list of /// tasks that can be traversed to find all currently existing tasks. -#[cfg(feature = "trace")] pub struct TaskTracker { head: AtomicPtr, } -#[cfg(feature = "trace")] impl TaskTracker { /// Creates a new empty task tracker /// @@ -172,7 +169,6 @@ impl TaskTracker { /// This trait is only available when the `trace` feature is enabled. /// It extends `TaskRef` with methods for accessing and modifying task identifiers /// and names, which are useful for debugging, logging, and performance analysis. -#[cfg(feature = "trace")] pub trait TaskRefTrace { /// Get the name for a task fn name(&self) -> Option<&'static str>; @@ -187,7 +183,6 @@ pub trait TaskRefTrace { fn set_id(&self, id: u32); } -#[cfg(feature = "trace")] impl TaskRefTrace for TaskRef { fn name(&self) -> Option<&'static str> { self.header().name @@ -350,7 +345,6 @@ pub(crate) fn executor_idle(executor: &SyncExecutor) { /// /// # Returns /// An iterator that yields `TaskRef` items for each task -#[cfg(feature = "trace")] fn get_all_active_tasks() -> impl Iterator + 'static { struct TaskIterator<'a> { tracker: &'a TaskTracker, @@ -379,7 +373,6 @@ fn get_all_active_tasks() -> impl Iterator + 'static { } /// Perform an action on each active task -#[cfg(feature = "trace")] fn with_all_active_tasks(f: F) where F: FnMut(TaskRef), -- cgit From ebb6132f5f9c55ad4ced2602134f8e2c69135c1e Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Thu, 8 May 2025 16:31:47 -0400 Subject: rustfmt --- embassy-executor/src/spawner.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index bfb32ebcc..522d97db3 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -5,7 +5,6 @@ use core::sync::atomic::Ordering; use core::task::Poll; use super::raw; - #[cfg(feature = "trace")] use crate::raw::trace::TaskRefTrace; -- cgit From d4c378e059443dbaaaece02a0f5148db62bd4484 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 11 Apr 2025 14:28:59 -0700 Subject: Add embassy-imxrt CRC driver --- docs/pages/imxrt.adoc | 2 +- embassy-imxrt/src/crc.rs | 190 ++++++++++++++++++++++++++++++++++++++++ embassy-imxrt/src/lib.rs | 1 + examples/mimxrt6/src/bin/crc.rs | 175 ++++++++++++++++++++++++++++++++++++ 4 files changed, 367 insertions(+), 1 deletion(-) create mode 100644 embassy-imxrt/src/crc.rs create mode 100644 examples/mimxrt6/src/bin/crc.rs diff --git a/docs/pages/imxrt.adoc b/docs/pages/imxrt.adoc index adf5218e8..a84fbae03 100644 --- a/docs/pages/imxrt.adoc +++ b/docs/pages/imxrt.adoc @@ -9,5 +9,5 @@ The link: link:https://github.com/embassy-rs/embassy/tree/main/embassy-imxrt[Emb The following peripherals have a HAL implementation at present +* CRC * GPIO - diff --git a/embassy-imxrt/src/crc.rs b/embassy-imxrt/src/crc.rs new file mode 100644 index 000000000..24d6ba5bd --- /dev/null +++ b/embassy-imxrt/src/crc.rs @@ -0,0 +1,190 @@ +//! Cyclic Redundancy Check (CRC) + +use core::marker::PhantomData; + +use crate::clocks::{enable_and_reset, SysconPeripheral}; +pub use crate::pac::crc_engine::mode::CrcPolynomial as Polynomial; +use crate::{peripherals, Peri, PeripheralType}; + +/// CRC driver. +pub struct Crc<'d> { + info: Info, + _config: Config, + _lifetime: PhantomData<&'d ()>, +} + +/// CRC configuration +pub struct Config { + /// Polynomial to be used + pub polynomial: Polynomial, + + /// Reverse bit order of input? + pub reverse_in: bool, + + /// 1's complement input? + pub complement_in: bool, + + /// Reverse CRC bit order? + pub reverse_out: bool, + + /// 1's complement CRC? + pub complement_out: bool, + + /// CRC Seed + pub seed: u32, +} + +impl Config { + /// Create a new CRC config. + #[must_use] + pub fn new( + polynomial: Polynomial, + reverse_in: bool, + complement_in: bool, + reverse_out: bool, + complement_out: bool, + seed: u32, + ) -> Self { + Config { + polynomial, + reverse_in, + complement_in, + reverse_out, + complement_out, + seed, + } + } +} + +impl Default for Config { + fn default() -> Self { + Self { + polynomial: Polynomial::CrcCcitt, + reverse_in: false, + complement_in: false, + reverse_out: false, + complement_out: false, + seed: 0xffff, + } + } +} + +impl<'d> Crc<'d> { + /// Instantiates new CRC peripheral and initializes to default values. + pub fn new(_peripheral: Peri<'d, T>, config: Config) -> Self { + // enable CRC clock + enable_and_reset::(); + + let mut instance = Self { + info: T::info(), + _config: config, + _lifetime: PhantomData, + }; + + instance.reconfigure(); + instance + } + + /// Reconfigured the CRC peripheral. + fn reconfigure(&mut self) { + self.info.regs.mode().write(|w| { + w.crc_poly() + .variant(self._config.polynomial) + .bit_rvs_wr() + .variant(self._config.reverse_in) + .cmpl_wr() + .variant(self._config.complement_in) + .bit_rvs_sum() + .variant(self._config.reverse_out) + .cmpl_sum() + .variant(self._config.complement_out) + }); + + // Init CRC value + self.info + .regs + .seed() + .write(|w| unsafe { w.crc_seed().bits(self._config.seed) }); + } + + /// Feeds a byte into the CRC peripheral. Returns the computed checksum. + pub fn feed_byte(&mut self, byte: u8) -> u32 { + self.info.regs.wr_data8().write(|w| unsafe { w.bits(byte) }); + + self.info.regs.sum().read().bits() + } + + /// Feeds an slice of bytes into the CRC peripheral. Returns the computed checksum. + pub fn feed_bytes(&mut self, bytes: &[u8]) -> u32 { + let (prefix, data, suffix) = unsafe { bytes.align_to::() }; + + for b in prefix { + self.info.regs.wr_data8().write(|w| unsafe { w.bits(*b) }); + } + + for d in data { + self.info.regs.wr_data32().write(|w| unsafe { w.bits(*d) }); + } + + for b in suffix { + self.info.regs.wr_data8().write(|w| unsafe { w.bits(*b) }); + } + + self.info.regs.sum().read().bits() + } + + /// Feeds a halfword into the CRC peripheral. Returns the computed checksum. + pub fn feed_halfword(&mut self, halfword: u16) -> u32 { + self.info.regs.wr_data16().write(|w| unsafe { w.bits(halfword) }); + + self.info.regs.sum().read().bits() + } + + /// Feeds an slice of halfwords into the CRC peripheral. Returns the computed checksum. + pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u32 { + for halfword in halfwords { + self.info.regs.wr_data16().write(|w| unsafe { w.bits(*halfword) }); + } + + self.info.regs.sum().read().bits() + } + + /// Feeds a words into the CRC peripheral. Returns the computed checksum. + pub fn feed_word(&mut self, word: u32) -> u32 { + self.info.regs.wr_data32().write(|w| unsafe { w.bits(word) }); + + self.info.regs.sum().read().bits() + } + + /// Feeds an slice of words into the CRC peripheral. Returns the computed checksum. + pub fn feed_words(&mut self, words: &[u32]) -> u32 { + for word in words { + self.info.regs.wr_data32().write(|w| unsafe { w.bits(*word) }); + } + + self.info.regs.sum().read().bits() + } +} + +struct Info { + regs: crate::pac::CrcEngine, +} + +trait SealedInstance { + fn info() -> Info; +} + +/// CRC instance trait. +#[allow(private_bounds)] +pub trait Instance: SealedInstance + PeripheralType + SysconPeripheral + 'static + Send {} + +impl Instance for peripherals::CRC {} + +impl SealedInstance for peripherals::CRC { + fn info() -> Info { + // SAFETY: safe from single executor + Info { + regs: unsafe { crate::pac::CrcEngine::steal() }, + } + } +} diff --git a/embassy-imxrt/src/lib.rs b/embassy-imxrt/src/lib.rs index ad9f81e88..d8ce97f76 100644 --- a/embassy-imxrt/src/lib.rs +++ b/embassy-imxrt/src/lib.rs @@ -18,6 +18,7 @@ compile_error!( pub(crate) mod fmt; pub mod clocks; +pub mod crc; pub mod gpio; pub mod iopctl; diff --git a/examples/mimxrt6/src/bin/crc.rs b/examples/mimxrt6/src/bin/crc.rs new file mode 100644 index 000000000..005a250e5 --- /dev/null +++ b/examples/mimxrt6/src/bin/crc.rs @@ -0,0 +1,175 @@ +#![no_std] +#![no_main] + +extern crate embassy_imxrt_examples; + +use defmt::*; +use embassy_executor::Spawner; +use embassy_imxrt::crc::{Config, Crc, Polynomial}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut p = embassy_imxrt::init(Default::default()); + let data = b"123456789"; + + info!("Initializing CRC"); + + // CRC-CCITT + let mut crc = Crc::new(p.CRC.reborrow(), Default::default()); + let output = crc.feed_bytes(data); + defmt::assert_eq!(output, 0x29b1); + + // CRC16-ARC + let mut crc = Crc::new( + p.CRC.reborrow(), + Config { + polynomial: Polynomial::Crc16, + reverse_in: true, + reverse_out: true, + complement_out: false, + seed: 0, + ..Default::default() + }, + ); + let output = crc.feed_bytes(data); + defmt::assert_eq!(output, 0xbb3d); + + // CRC16-CMS + let mut crc = Crc::new( + p.CRC.reborrow(), + Config { + polynomial: Polynomial::Crc16, + reverse_in: false, + reverse_out: false, + complement_out: false, + seed: 0xffff, + ..Default::default() + }, + ); + let output = crc.feed_bytes(data); + defmt::assert_eq!(output, 0xaee7); + + // CRC16-DDS-110 + let mut crc = Crc::new( + p.CRC.reborrow(), + Config { + polynomial: Polynomial::Crc16, + reverse_in: false, + reverse_out: false, + complement_out: false, + seed: 0x800d, + ..Default::default() + }, + ); + let output = crc.feed_bytes(data); + defmt::assert_eq!(output, 0x9ecf); + + // CRC16-MAXIM-DOW + let mut crc = Crc::new( + p.CRC.reborrow(), + Config { + polynomial: Polynomial::Crc16, + reverse_in: true, + reverse_out: true, + complement_out: true, + seed: 0, + ..Default::default() + }, + ); + let output = crc.feed_bytes(data); + defmt::assert_eq!(output, 0x44c2); + + // CRC16-MODBUS + let mut crc = Crc::new( + p.CRC.reborrow(), + Config { + polynomial: Polynomial::Crc16, + reverse_in: true, + reverse_out: true, + complement_out: false, + seed: 0xffff, + ..Default::default() + }, + ); + let output = crc.feed_bytes(data); + defmt::assert_eq!(output, 0x4b37); + + // CRC32-BZIP2 + let mut crc = Crc::new( + p.CRC.reborrow(), + Config { + polynomial: Polynomial::Crc32, + reverse_in: false, + reverse_out: false, + complement_out: true, + seed: 0xffff_ffff, + ..Default::default() + }, + ); + let output = crc.feed_bytes(data); + defmt::assert_eq!(output, 0xfc89_1918); + + // CRC32-CKSUM + let mut crc = Crc::new( + p.CRC.reborrow(), + Config { + polynomial: Polynomial::Crc32, + reverse_in: false, + reverse_out: false, + complement_out: true, + seed: 0, + ..Default::default() + }, + ); + let output = crc.feed_bytes(data); + defmt::assert_eq!(output, 0x765e_7680); + + // CRC32-ISO-HDLC + let mut crc = Crc::new( + p.CRC.reborrow(), + Config { + polynomial: Polynomial::Crc32, + reverse_in: true, + reverse_out: true, + complement_out: true, + seed: 0xffff_ffff, + ..Default::default() + }, + ); + let output = crc.feed_bytes(data); + defmt::assert_eq!(output, 0xcbf4_3926); + + // CRC32-JAMCRC + let mut crc = Crc::new( + p.CRC.reborrow(), + Config { + polynomial: Polynomial::Crc32, + reverse_in: true, + reverse_out: true, + complement_out: false, + seed: 0xffff_ffff, + ..Default::default() + }, + ); + let output = crc.feed_bytes(data); + defmt::assert_eq!(output, 0x340b_c6d9); + + // CRC32-MPEG-2 + let mut crc = Crc::new( + p.CRC.reborrow(), + Config { + polynomial: Polynomial::Crc32, + reverse_in: false, + reverse_out: false, + complement_out: false, + seed: 0xffff_ffff, + ..Default::default() + }, + ); + let output = crc.feed_bytes(data); + defmt::assert_eq!(output, 0x0376_e6e7); + + info!("end program"); + cortex_m::asm::bkpt(); +} -- cgit From 8e7e4332b40707e8d36338ad8ec486320bb3538f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 11 Apr 2025 15:03:53 -0700 Subject: Add embassy-imxrt RNG driver --- docs/pages/imxrt.adoc | 2 +- embassy-imxrt/src/lib.rs | 1 + embassy-imxrt/src/rng.rs | 257 ++++++++++++++++++++++++++++++++++++++++ examples/mimxrt6/src/bin/rng.rs | 40 +++++++ 4 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 embassy-imxrt/src/rng.rs create mode 100644 examples/mimxrt6/src/bin/rng.rs diff --git a/docs/pages/imxrt.adoc b/docs/pages/imxrt.adoc index adf5218e8..9fcb6725c 100644 --- a/docs/pages/imxrt.adoc +++ b/docs/pages/imxrt.adoc @@ -10,4 +10,4 @@ The link: link:https://github.com/embassy-rs/embassy/tree/main/embassy-imxrt[Emb The following peripherals have a HAL implementation at present * GPIO - +* RNG diff --git a/embassy-imxrt/src/lib.rs b/embassy-imxrt/src/lib.rs index ad9f81e88..f728ba060 100644 --- a/embassy-imxrt/src/lib.rs +++ b/embassy-imxrt/src/lib.rs @@ -20,6 +20,7 @@ pub(crate) mod fmt; pub mod clocks; pub mod gpio; pub mod iopctl; +pub mod rng; #[cfg(feature = "_time-driver")] pub mod time_driver; diff --git a/embassy-imxrt/src/rng.rs b/embassy-imxrt/src/rng.rs new file mode 100644 index 000000000..67e7ab65d --- /dev/null +++ b/embassy-imxrt/src/rng.rs @@ -0,0 +1,257 @@ +//! True Random Number Generator (TRNG) + +use core::future::poll_fn; +use core::marker::PhantomData; +use core::task::Poll; + +use embassy_futures::block_on; +use embassy_sync::waitqueue::AtomicWaker; +use rand_core::{CryptoRng, RngCore}; + +use crate::clocks::{enable_and_reset, SysconPeripheral}; +use crate::interrupt::typelevel::Interrupt; +use crate::{interrupt, peripherals, Peri, PeripheralType}; + +static RNG_WAKER: AtomicWaker = AtomicWaker::new(); + +/// RNG ;error +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Error { + /// Seed error. + SeedError, + + /// HW Error. + HwError, + + /// Frequency Count Fail + FreqCountFail, +} + +/// RNG interrupt handler. +pub struct InterruptHandler { + _phantom: PhantomData, +} + +impl interrupt::typelevel::Handler for InterruptHandler { + unsafe fn on_interrupt() { + let regs = T::info().regs; + let int_status = regs.int_status().read(); + + if int_status.ent_val().bit_is_set() + || int_status.hw_err().bit_is_set() + || int_status.frq_ct_fail().bit_is_set() + { + regs.int_ctrl().modify(|_, w| { + w.ent_val() + .ent_val_0() + .hw_err() + .hw_err_0() + .frq_ct_fail() + .frq_ct_fail_0() + }); + RNG_WAKER.wake(); + } + } +} + +/// RNG driver. +pub struct Rng<'d> { + info: Info, + _lifetime: PhantomData<&'d ()>, +} + +impl<'d> Rng<'d> { + /// Create a new RNG driver. + pub fn new( + _inner: Peri<'d, T>, + _irq: impl interrupt::typelevel::Binding> + 'd, + ) -> Self { + enable_and_reset::(); + + let mut random = Self { + info: T::info(), + _lifetime: PhantomData, + }; + random.init(); + + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; + + random + } + + /// Reset the RNG. + pub fn reset(&mut self) { + self.info.regs.mctl().write(|w| w.rst_def().set_bit().prgm().set_bit()); + } + + /// Fill the given slice with random values. + pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + // We have a total of 16 words (512 bits) of entropy at our + // disposal. The idea here is to read all bits and copy the + // necessary bytes to the slice. + for chunk in dest.chunks_mut(64) { + self.async_fill_chunk(chunk).await?; + } + + Ok(()) + } + + async fn async_fill_chunk(&mut self, chunk: &mut [u8]) -> Result<(), Error> { + // wait for interrupt + let res = poll_fn(|cx| { + // Check if already ready. + // TODO: Is this necessary? Could we just check once after + // the waker has been registered? + if self.info.regs.int_status().read().ent_val().bit_is_set() { + return Poll::Ready(Ok(())); + } + + RNG_WAKER.register(cx.waker()); + + self.unmask_interrupts(); + + let mctl = self.info.regs.mctl().read(); + + // Check again if interrupt fired + if mctl.ent_val().bit_is_set() { + Poll::Ready(Ok(())) + } else if mctl.err().bit_is_set() { + Poll::Ready(Err(Error::HwError)) + } else if mctl.fct_fail().bit_is_set() { + Poll::Ready(Err(Error::FreqCountFail)) + } else { + Poll::Pending + } + }) + .await; + + let bits = self.info.regs.mctl().read(); + + if bits.ent_val().bit_is_set() { + let mut entropy = [0; 16]; + + for (i, item) in entropy.iter_mut().enumerate() { + *item = self.info.regs.ent(i).read().bits(); + } + + // Read MCTL after reading ENT15 + let _ = self.info.regs.mctl().read(); + + if entropy.iter().any(|e| *e == 0) { + return Err(Error::SeedError); + } + + // SAFETY: entropy is the same for input and output types in + // native endianness. + let entropy: [u8; 64] = unsafe { core::mem::transmute(entropy) }; + + // write bytes to chunk + chunk.copy_from_slice(&entropy[..chunk.len()]); + } + + res + } + + fn mask_interrupts(&mut self) { + self.info.regs.int_mask().write(|w| { + w.ent_val() + .ent_val_0() + .hw_err() + .hw_err_0() + .frq_ct_fail() + .frq_ct_fail_0() + }); + } + + fn unmask_interrupts(&mut self) { + self.info.regs.int_mask().modify(|_, w| { + w.ent_val() + .ent_val_1() + .hw_err() + .hw_err_1() + .frq_ct_fail() + .frq_ct_fail_1() + }); + } + + fn enable_interrupts(&mut self) { + self.info.regs.int_ctrl().write(|w| { + w.ent_val() + .ent_val_1() + .hw_err() + .hw_err_1() + .frq_ct_fail() + .frq_ct_fail_1() + }); + } + + fn init(&mut self) { + self.mask_interrupts(); + + // Switch TRNG to programming mode + self.info.regs.mctl().modify(|_, w| w.prgm().set_bit()); + + self.enable_interrupts(); + + // Switch TRNG to Run Mode + self.info + .regs + .mctl() + .modify(|_, w| w.trng_acc().set_bit().prgm().clear_bit()); + } +} + +impl RngCore for Rng<'_> { + fn next_u32(&mut self) -> u32 { + let mut bytes = [0u8; 4]; + block_on(self.async_fill_bytes(&mut bytes)).unwrap(); + u32::from_ne_bytes(bytes) + } + + fn next_u64(&mut self) -> u64 { + let mut bytes = [0u8; 8]; + block_on(self.async_fill_bytes(&mut bytes)).unwrap(); + u64::from_ne_bytes(bytes) + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + block_on(self.async_fill_bytes(dest)).unwrap(); + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { + self.fill_bytes(dest); + Ok(()) + } +} + +impl CryptoRng for Rng<'_> {} + +struct Info { + regs: crate::pac::Trng, +} + +trait SealedInstance { + fn info() -> Info; +} + +/// RNG instance trait. +#[allow(private_bounds)] +pub trait Instance: SealedInstance + PeripheralType + SysconPeripheral + 'static + Send { + /// Interrupt for this RNG instance. + type Interrupt: interrupt::typelevel::Interrupt; +} + +impl Instance for peripherals::RNG { + type Interrupt = crate::interrupt::typelevel::RNG; +} + +impl SealedInstance for peripherals::RNG { + fn info() -> Info { + // SAFETY: safe from single executor + Info { + regs: unsafe { crate::pac::Trng::steal() }, + } + } +} diff --git a/examples/mimxrt6/src/bin/rng.rs b/examples/mimxrt6/src/bin/rng.rs new file mode 100644 index 000000000..5f64cb96a --- /dev/null +++ b/examples/mimxrt6/src/bin/rng.rs @@ -0,0 +1,40 @@ +#![no_std] +#![no_main] + +extern crate embassy_imxrt_examples; + +use defmt::*; +use embassy_executor::Spawner; +use embassy_imxrt::rng::Rng; +use embassy_imxrt::{bind_interrupts, peripherals, rng}; +use rand::RngCore; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + RNG => rng::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_imxrt::init(Default::default()); + + info!("Initializing RNG"); + let mut rng = Rng::new(p.RNG, Irqs); + let mut buf = [0u8; 65]; + + // Async interface + unwrap!(rng.async_fill_bytes(&mut buf).await); + info!("random bytes: {:02x}", buf); + + // RngCore interface + let mut random_bytes = [0; 16]; + + let random_u32 = rng.next_u32(); + let random_u64 = rng.next_u64(); + + rng.fill_bytes(&mut random_bytes); + + info!("random_u32 {}", random_u32); + info!("random_u64 {}", random_u64); + info!("random_bytes {}", random_bytes); +} -- cgit From 90404a8e524a0d06ce35230dea7ff4d3e4d0375a Mon Sep 17 00:00:00 2001 From: ragarnoy Date: Sat, 10 May 2025 02:17:54 +0200 Subject: Add intercore communication examples for STM32H755CM4 and CM7, does not work in release for now (for some reason) --- examples/stm32h755cm4/Cargo.toml | 17 +-- examples/stm32h755cm4/src/bin/intercore.rs | 181 +++++++++++++++++++++++ examples/stm32h755cm7/Cargo.toml | 15 +- examples/stm32h755cm7/src/bin/intercore.rs | 226 +++++++++++++++++++++++++++++ 4 files changed, 415 insertions(+), 24 deletions(-) create mode 100644 examples/stm32h755cm4/src/bin/intercore.rs create mode 100644 examples/stm32h755cm7/src/bin/intercore.rs diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index 7c17bc766..c6d4996f1 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -15,8 +15,8 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defm embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" @@ -25,7 +25,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-nal-async = "0.8.0" embedded-io-async = { version = "0.6.1" } -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } rand_core = "0.6.3" critical-section = "1.1" @@ -37,13 +37,6 @@ chrono = { version = "^0.4", default-features = false } grounded = "0.2.0" # cargo build/run -[profile.dev] -codegen-units = 1 -debug = 2 -debug-assertions = true # <- -incremental = false -opt-level = 3 # <- -overflow-checks = true # <- # cargo test [profile.test] @@ -60,8 +53,8 @@ codegen-units = 1 debug = 2 debug-assertions = false # <- incremental = false -lto = 'fat' -opt-level = 3 # <- +#lto = 'fat' +#opt-level = 3 # <- overflow-checks = false # <- # cargo test --release diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs new file mode 100644 index 000000000..08cf6c7b9 --- /dev/null +++ b/examples/stm32h755cm4/src/bin/intercore.rs @@ -0,0 +1,181 @@ +#![no_std] +#![no_main] + +// IMPORTANT: This must match EXACTLY the definition in CM7! +mod shared { + use core::sync::atomic::{AtomicU32, Ordering}; + + /// Shared LED state between CM7 and CM4 cores + #[repr(C, align(4))] + pub struct SharedLedState { + // Magic number for validation + pub magic: AtomicU32, + // Counter for synchronization testing + pub counter: AtomicU32, + // LED states packed into a single atomic + pub led_states: AtomicU32, + } + + // Bit positions in led_states + pub const GREEN_LED_BIT: u32 = 0; + pub const YELLOW_LED_BIT: u32 = 1; + + impl SharedLedState { + pub const fn new() -> Self { + Self { + magic: AtomicU32::new(0xDEADBEEF), // Magic number + counter: AtomicU32::new(0), + led_states: AtomicU32::new(0), + } + } + + /// Set LED state using safe bit operations + #[inline(never)] + pub fn set_led(&self, is_green: bool, state: bool) { + let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; + + // Use bit operations to avoid complex atomic operations + let current = self.led_states.load(Ordering::SeqCst); + + let new_value = if state { + current | (1 << bit) // Set bit + } else { + current & !(1 << bit) // Clear bit + }; + + self.led_states.store(new_value, Ordering::SeqCst); + core::sync::atomic::compiler_fence(Ordering::SeqCst); + } + + /// Get LED state using safe bit operations + #[inline(never)] + pub fn get_led(&self, is_green: bool) -> bool { + let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; + + let value = self.led_states.load(Ordering::SeqCst); + core::sync::atomic::compiler_fence(Ordering::SeqCst); + + (value & (1 << bit)) != 0 + } + + /// Increment counter safely + #[inline(never)] + pub fn increment_counter(&self) -> u32 { + let current = self.counter.load(Ordering::SeqCst); + let new_value = current.wrapping_add(1); + self.counter.store(new_value, Ordering::SeqCst); + core::sync::atomic::compiler_fence(Ordering::SeqCst); + new_value + } + + /// Get counter without incrementing + #[inline(never)] + pub fn get_counter(&self) -> u32 { + let value = self.counter.load(Ordering::SeqCst); + core::sync::atomic::compiler_fence(Ordering::SeqCst); + value + } + } + + #[link_section = ".ram_d3"] + pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); + + // SRAM4 memory region constants for MPU configuration + pub const SRAM4_BASE_ADDRESS: u32 = 0x38000000; + pub const SRAM4_SIZE_LOG2: u32 = 15; // 64KB = 2^(15+1) + pub const SRAM4_REGION_NUMBER: u8 = 0; // MPU region number to use +} + +use core::mem::MaybeUninit; +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::gpio::{Level, Output, Speed}; +use embassy_stm32::SharedData; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +// Use our shared state from the module +use shared::SHARED_LED_STATE; + +#[link_section = ".ram_d3"] +static SHARED_DATA: MaybeUninit = MaybeUninit::uninit(); + +#[embassy_executor::task] +async fn blink_heartbeat(mut led: Output<'static>) { + loop { + led.toggle(); + info!("CM4 heartbeat"); + Timer::after_millis(500).await; + } +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) -> ! { + // Initialize the secondary core + let p = embassy_stm32::init_secondary(&SHARED_DATA); + info!("CM4 core initialized!"); + + // Read the magic value to ensure shared memory is accessible + let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst); + info!("CM4: Magic value = 0x{:X}", magic); + + // Initialize LEDs + let mut green_led = Output::new(p.PB0, Level::Low, Speed::Low); // LD1 + let mut yellow_led = Output::new(p.PE1, Level::Low, Speed::Low); // LD2 + let red_led = Output::new(p.PB14, Level::Low, Speed::Low); // LD3 (heartbeat) + + // Start heartbeat task + unwrap!(spawner.spawn(blink_heartbeat(red_led))); + + // Previous values for detecting changes + let mut prev_green = false; + let mut prev_yellow = false; + let mut prev_counter = 0; + + info!("CM4: Starting main loop"); + loop { + // Read values from shared memory + let green_state = SHARED_LED_STATE.get_led(true); + let yellow_state = SHARED_LED_STATE.get_led(false); + let counter = SHARED_LED_STATE.get_counter(); + + // Check for state changes + let green_changed = green_state != prev_green; + let yellow_changed = yellow_state != prev_yellow; + let counter_changed = counter != prev_counter; + + // If any state changed, log it and update LEDs + if green_changed || yellow_changed || counter_changed { + if counter_changed { + info!("CM4: Counter = {}", counter); + prev_counter = counter; + } + + // Update LED states + if green_changed { + if green_state { + green_led.set_high(); + info!("CM4: Green LED ON"); + } else { + green_led.set_low(); + info!("CM4: Green LED OFF"); + } + prev_green = green_state; + } + + if yellow_changed { + if yellow_state { + yellow_led.set_high(); + info!("CM4: Yellow LED ON"); + } else { + yellow_led.set_low(); + info!("CM4: Yellow LED OFF"); + } + prev_yellow = yellow_state; + } + } + + // Poll at a reasonable rate + Timer::after_millis(10).await; + } +} \ No newline at end of file diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index 3186929a8..06a3b06af 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -15,8 +15,8 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defm embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" @@ -25,7 +25,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-nal-async = "0.8.0" embedded-io-async = { version = "0.6.1" } -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } rand_core = "0.6.3" critical-section = "1.1" @@ -36,15 +36,6 @@ static_cell = "2" chrono = { version = "^0.4", default-features = false } grounded = "0.2.0" -# cargo build/run -[profile.dev] -codegen-units = 1 -debug = 2 -debug-assertions = true # <- -incremental = false -opt-level = 3 # <- -overflow-checks = true # <- - # cargo test [profile.test] codegen-units = 1 diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs new file mode 100644 index 000000000..154b1682b --- /dev/null +++ b/examples/stm32h755cm7/src/bin/intercore.rs @@ -0,0 +1,226 @@ +#![no_std] +#![no_main] + +mod shared { + use core::sync::atomic::{AtomicU32, Ordering}; + + /// Shared LED state between CM7 and CM4 cores + #[repr(C, align(4))] + pub struct SharedLedState { + // Magic number for validation + pub magic: AtomicU32, + // Counter for synchronization testing + pub counter: AtomicU32, + // LED states packed into a single atomic + pub led_states: AtomicU32, + } + + // Bit positions in led_states + pub const GREEN_LED_BIT: u32 = 0; + pub const YELLOW_LED_BIT: u32 = 1; + + impl SharedLedState { + pub const fn new() -> Self { + Self { + magic: AtomicU32::new(0xDEADBEEF), // Magic number + counter: AtomicU32::new(0), + led_states: AtomicU32::new(0), + } + } + + /// Set LED state using safe bit operations + #[inline(never)] + pub fn set_led(&self, is_green: bool, state: bool) { + let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; + + // Use bit operations to avoid complex atomic operations + let current = self.led_states.load(Ordering::SeqCst); + + let new_value = if state { + current | (1 << bit) // Set bit + } else { + current & !(1 << bit) // Clear bit + }; + + self.led_states.store(new_value, Ordering::SeqCst); + core::sync::atomic::compiler_fence(Ordering::SeqCst); + } + + /// Get LED state using safe bit operations + #[inline(never)] + pub fn get_led(&self, is_green: bool) -> bool { + let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; + + let value = self.led_states.load(Ordering::SeqCst); + core::sync::atomic::compiler_fence(Ordering::SeqCst); + + (value & (1 << bit)) != 0 + } + + /// Increment counter safely + #[inline(never)] + pub fn increment_counter(&self) -> u32 { + let current = self.counter.load(Ordering::SeqCst); + let new_value = current.wrapping_add(1); + self.counter.store(new_value, Ordering::SeqCst); + core::sync::atomic::compiler_fence(Ordering::SeqCst); + new_value + } + + /// Get counter without incrementing + #[inline(never)] + pub fn get_counter(&self) -> u32 { + let value = self.counter.load(Ordering::SeqCst); + core::sync::atomic::compiler_fence(Ordering::SeqCst); + value + } + } + + #[link_section = ".ram_d3"] + pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); + + // SRAM4 memory region constants for MPU configuration + pub const SRAM4_BASE_ADDRESS: u32 = 0x38000000; + pub const SRAM4_SIZE_LOG2: u32 = 15; // 64KB = 2^(15+1) + pub const SRAM4_REGION_NUMBER: u8 = 0; // MPU region number to use +} + +use core::mem::MaybeUninit; +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::{Config, SharedData}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +// Import cortex_m for MPU configuration +use cortex_m::peripheral::{MPU, SCB}; +use cortex_m::asm; + +// Use our shared state from the module +use shared::{SHARED_LED_STATE, SRAM4_BASE_ADDRESS, SRAM4_REGION_NUMBER, SRAM4_SIZE_LOG2}; + +#[link_section = ".ram_d3"] +static SHARED_DATA: MaybeUninit = MaybeUninit::uninit(); + +// Function to configure MPU with your provided settings +fn configure_mpu_non_cacheable(mpu: &mut MPU, _scb: &mut SCB) { + // Ensure all operations complete before reconfiguring MPU/caches + asm::dmb(); + unsafe { + // Disable MPU + mpu.ctrl.write(0); + + // Configure SRAM4 as non-cacheable + // Set region number (0) + mpu.rnr.write(SRAM4_REGION_NUMBER as u32); + + // Set base address (SRAM4 = 0x38000000) with VALID bit and region number + mpu.rbar.write( + SRAM4_BASE_ADDRESS | + (1 << 4) // Region number = 0 (explicit in RBAR) + ); + + // Configure region attributes: + // SIZE=15 (64KB = 2^(15+1)) + // ENABLE=1 + // AP=3 (Full access) + // TEX=1, S=1, C=0, B=0 (Normal memory, Non-cacheable, Shareable) + let rasr_value: u32 = (SRAM4_SIZE_LOG2 << 1) | // SIZE=15 (64KB) + (1 << 0) | // ENABLE=1 + (3 << 24) | // AP=3 (Full access) + (1 << 19) | // TEX=1 + (1 << 18); // S=1 (Shareable) + + mpu.rasr.write(rasr_value); + + // Enable MPU with default memory map as background + mpu.ctrl.write(1 | (1 << 2)); // MPU_ENABLE | PRIVDEFENA + } + + // Ensure changes are committed + asm::dsb(); + asm::isb(); + + info!("MPU configured - SRAM4 set as non-cacheable"); +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) -> ! { + // Configure MPU to make SRAM4 non-cacheable + { + let mut cp = cortex_m::Peripherals::take().unwrap(); + let mpu = &mut cp.MPU; + let scb = &mut cp.SCB; + + // Configure MPU without disabling caches + configure_mpu_non_cacheable(mpu, scb); + } + + // Configure the clocks + let mut config = Config::default(); + { + use embassy_stm32::rcc::*; + config.rcc.hsi = Some(HSIPrescaler::DIV1); + config.rcc.csi = true; + config.rcc.hsi48 = Some(Default::default()); + config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), + divq: Some(PllDiv::DIV8), + divr: None, + }); + config.rcc.sys = Sysclk::PLL1_P; + config.rcc.ahb_pre = AHBPrescaler::DIV2; + config.rcc.apb1_pre = APBPrescaler::DIV2; + config.rcc.apb2_pre = APBPrescaler::DIV2; + config.rcc.apb3_pre = APBPrescaler::DIV2; + config.rcc.apb4_pre = APBPrescaler::DIV2; + config.rcc.voltage_scale = VoltageScale::Scale1; + config.rcc.supply_config = SupplyConfig::DirectSMPS; + } + + // Initialize the CM7 core + let _p = embassy_stm32::init_primary(config, &SHARED_DATA); + info!("CM7 core initialized with non-cacheable SRAM4!"); + + // Read the magic value to ensure shared memory is accessible + let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst); + info!("CM7: Magic value = 0x{:X}", magic); + + // Initialize shared memory state + SHARED_LED_STATE.set_led(true, false); // Green LED off + SHARED_LED_STATE.set_led(false, false); // Yellow LED off + + // Main loop - update shared memory values + let mut green_state = false; + let mut yellow_state = false; + let mut loop_count = 0; + + info!("CM7: Starting main loop"); + loop { + // Update loop counter + loop_count += 1; + + // Update shared counter + let counter = SHARED_LED_STATE.increment_counter(); + + // Every second, toggle green LED state + if loop_count % 10 == 0 { + green_state = !green_state; + SHARED_LED_STATE.set_led(true, green_state); + info!("CM7: Counter = {}, Set green LED to {}", counter, green_state); + } + + // Every 3 seconds, toggle yellow LED state + if loop_count % 30 == 0 { + yellow_state = !yellow_state; + SHARED_LED_STATE.set_led(false, yellow_state); + info!("CM7: Counter = {}, Set yellow LED to {}", counter, yellow_state); + } + + // Wait 100ms before next cycle + Timer::after_millis(100).await; + } +} \ No newline at end of file -- cgit From cf60b110668f1650836f7d81bf41b629603ae6d6 Mon Sep 17 00:00:00 2001 From: ragarnoy Date: Sat, 10 May 2025 02:22:48 +0200 Subject: rustfmt --- examples/stm32h755cm4/src/bin/intercore.rs | 8 ++++---- examples/stm32h755cm7/src/bin/intercore.rs | 17 ++++++++--------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs index 08cf6c7b9..7b2406e76 100644 --- a/examples/stm32h755cm4/src/bin/intercore.rs +++ b/examples/stm32h755cm4/src/bin/intercore.rs @@ -120,9 +120,9 @@ async fn main(spawner: Spawner) -> ! { info!("CM4: Magic value = 0x{:X}", magic); // Initialize LEDs - let mut green_led = Output::new(p.PB0, Level::Low, Speed::Low); // LD1 - let mut yellow_led = Output::new(p.PE1, Level::Low, Speed::Low); // LD2 - let red_led = Output::new(p.PB14, Level::Low, Speed::Low); // LD3 (heartbeat) + let mut green_led = Output::new(p.PB0, Level::Low, Speed::Low); // LD1 + let mut yellow_led = Output::new(p.PE1, Level::Low, Speed::Low); // LD2 + let red_led = Output::new(p.PB14, Level::Low, Speed::Low); // LD3 (heartbeat) // Start heartbeat task unwrap!(spawner.spawn(blink_heartbeat(red_led))); @@ -178,4 +178,4 @@ async fn main(spawner: Spawner) -> ! { // Poll at a reasonable rate Timer::after_millis(10).await; } -} \ No newline at end of file +} diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs index 154b1682b..5783d05e1 100644 --- a/examples/stm32h755cm7/src/bin/intercore.rs +++ b/examples/stm32h755cm7/src/bin/intercore.rs @@ -75,7 +75,7 @@ mod shared { value } } - + #[link_section = ".ram_d3"] pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); @@ -93,8 +93,8 @@ use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; // Import cortex_m for MPU configuration -use cortex_m::peripheral::{MPU, SCB}; use cortex_m::asm; +use cortex_m::peripheral::{MPU, SCB}; // Use our shared state from the module use shared::{SHARED_LED_STATE, SRAM4_BASE_ADDRESS, SRAM4_REGION_NUMBER, SRAM4_SIZE_LOG2}; @@ -116,8 +116,7 @@ fn configure_mpu_non_cacheable(mpu: &mut MPU, _scb: &mut SCB) { // Set base address (SRAM4 = 0x38000000) with VALID bit and region number mpu.rbar.write( - SRAM4_BASE_ADDRESS | - (1 << 4) // Region number = 0 (explicit in RBAR) + SRAM4_BASE_ADDRESS | (1 << 4), // Region number = 0 (explicit in RBAR) ); // Configure region attributes: @@ -129,7 +128,7 @@ fn configure_mpu_non_cacheable(mpu: &mut MPU, _scb: &mut SCB) { (1 << 0) | // ENABLE=1 (3 << 24) | // AP=3 (Full access) (1 << 19) | // TEX=1 - (1 << 18); // S=1 (Shareable) + (1 << 18); // S=1 (Shareable) mpu.rasr.write(rasr_value); @@ -151,7 +150,7 @@ async fn main(spawner: Spawner) -> ! { let mut cp = cortex_m::Peripherals::take().unwrap(); let mpu = &mut cp.MPU; let scb = &mut cp.SCB; - + // Configure MPU without disabling caches configure_mpu_non_cacheable(mpu, scb); } @@ -190,9 +189,9 @@ async fn main(spawner: Spawner) -> ! { info!("CM7: Magic value = 0x{:X}", magic); // Initialize shared memory state - SHARED_LED_STATE.set_led(true, false); // Green LED off + SHARED_LED_STATE.set_led(true, false); // Green LED off SHARED_LED_STATE.set_led(false, false); // Yellow LED off - + // Main loop - update shared memory values let mut green_state = false; let mut yellow_state = false; @@ -223,4 +222,4 @@ async fn main(spawner: Spawner) -> ! { // Wait 100ms before next cycle Timer::after_millis(100).await; } -} \ No newline at end of file +} -- cgit From 65f67694a964b217c55b5f6eb15d2a6830ea0ec3 Mon Sep 17 00:00:00 2001 From: ragarnoy Date: Sat, 10 May 2025 02:34:33 +0200 Subject: Add #[allow(dead_code] attributes and rename spawner variable --- examples/stm32h755cm7/src/bin/intercore.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs index 5783d05e1..464357185 100644 --- a/examples/stm32h755cm7/src/bin/intercore.rs +++ b/examples/stm32h755cm7/src/bin/intercore.rs @@ -48,6 +48,7 @@ mod shared { /// Get LED state using safe bit operations #[inline(never)] + #[allow(dead_code)] pub fn get_led(&self, is_green: bool) -> bool { let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; @@ -69,6 +70,7 @@ mod shared { /// Get counter without incrementing #[inline(never)] + #[allow(dead_code)] pub fn get_counter(&self) -> u32 { let value = self.counter.load(Ordering::SeqCst); core::sync::atomic::compiler_fence(Ordering::SeqCst); @@ -144,7 +146,7 @@ fn configure_mpu_non_cacheable(mpu: &mut MPU, _scb: &mut SCB) { } #[embassy_executor::main] -async fn main(spawner: Spawner) -> ! { +async fn main(_spawner: Spawner) -> ! { // Configure MPU to make SRAM4 non-cacheable { let mut cp = cortex_m::Peripherals::take().unwrap(); -- cgit From 6b84bf5137eb9ab0dc6b4ebd049cd68f571a78a6 Mon Sep 17 00:00:00 2001 From: ragarnoy Date: Sat, 10 May 2025 02:36:36 +0200 Subject: formatting --- examples/stm32h755cm7/src/bin/intercore.rs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs index 464357185..f01d6a6b7 100644 --- a/examples/stm32h755cm7/src/bin/intercore.rs +++ b/examples/stm32h755cm7/src/bin/intercore.rs @@ -1,6 +1,17 @@ #![no_std] #![no_main] +use core::mem::MaybeUninit; + +use cortex_m::asm; +use cortex_m::peripheral::{MPU, SCB}; +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::{Config, SharedData}; +use embassy_time::Timer; +use shared::{SHARED_LED_STATE, SRAM4_BASE_ADDRESS, SRAM4_REGION_NUMBER, SRAM4_SIZE_LOG2}; +use {defmt_rtt as _, panic_probe as _}; + mod shared { use core::sync::atomic::{AtomicU32, Ordering}; @@ -87,20 +98,6 @@ mod shared { pub const SRAM4_REGION_NUMBER: u8 = 0; // MPU region number to use } -use core::mem::MaybeUninit; -use defmt::*; -use embassy_executor::Spawner; -use embassy_stm32::{Config, SharedData}; -use embassy_time::Timer; -use {defmt_rtt as _, panic_probe as _}; - -// Import cortex_m for MPU configuration -use cortex_m::asm; -use cortex_m::peripheral::{MPU, SCB}; - -// Use our shared state from the module -use shared::{SHARED_LED_STATE, SRAM4_BASE_ADDRESS, SRAM4_REGION_NUMBER, SRAM4_SIZE_LOG2}; - #[link_section = ".ram_d3"] static SHARED_DATA: MaybeUninit = MaybeUninit::uninit(); -- cgit From f52c77693e119095270df36a9acdb92130afa755 Mon Sep 17 00:00:00 2001 From: ragarnoy Date: Sat, 10 May 2025 08:41:44 +0200 Subject: formatting again --- examples/stm32h755cm4/src/bin/intercore.rs | 4 ++-- examples/stm32h755cm7/src/bin/intercore.rs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs index 7b2406e76..d38b34365 100644 --- a/examples/stm32h755cm4/src/bin/intercore.rs +++ b/examples/stm32h755cm4/src/bin/intercore.rs @@ -87,15 +87,15 @@ mod shared { } use core::mem::MaybeUninit; + use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::{Level, Output, Speed}; use embassy_stm32::SharedData; use embassy_time::Timer; -use {defmt_rtt as _, panic_probe as _}; - // Use our shared state from the module use shared::SHARED_LED_STATE; +use {defmt_rtt as _, panic_probe as _}; #[link_section = ".ram_d3"] static SHARED_DATA: MaybeUninit = MaybeUninit::uninit(); diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs index f01d6a6b7..ab5ed6364 100644 --- a/examples/stm32h755cm7/src/bin/intercore.rs +++ b/examples/stm32h755cm7/src/bin/intercore.rs @@ -2,7 +2,6 @@ #![no_main] use core::mem::MaybeUninit; - use cortex_m::asm; use cortex_m::peripheral::{MPU, SCB}; use defmt::*; -- cgit From d9befca44f3e35c14fef85744d19bbacc4a76de3 Mon Sep 17 00:00:00 2001 From: ragarnoy Date: Sat, 10 May 2025 08:45:29 +0200 Subject: dead code, formatting, ci, we're good --- examples/stm32h755cm4/src/bin/intercore.rs | 7 ++----- examples/stm32h755cm7/src/bin/intercore.rs | 1 + 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs index d38b34365..8f61c3eb2 100644 --- a/examples/stm32h755cm4/src/bin/intercore.rs +++ b/examples/stm32h755cm4/src/bin/intercore.rs @@ -31,6 +31,7 @@ mod shared { /// Set LED state using safe bit operations #[inline(never)] + #[allow(dead_code)] pub fn set_led(&self, is_green: bool, state: bool) { let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; @@ -60,6 +61,7 @@ mod shared { /// Increment counter safely #[inline(never)] + #[allow(dead_code)] pub fn increment_counter(&self) -> u32 { let current = self.counter.load(Ordering::SeqCst); let new_value = current.wrapping_add(1); @@ -79,11 +81,6 @@ mod shared { #[link_section = ".ram_d3"] pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); - - // SRAM4 memory region constants for MPU configuration - pub const SRAM4_BASE_ADDRESS: u32 = 0x38000000; - pub const SRAM4_SIZE_LOG2: u32 = 15; // 64KB = 2^(15+1) - pub const SRAM4_REGION_NUMBER: u8 = 0; // MPU region number to use } use core::mem::MaybeUninit; diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs index ab5ed6364..f01d6a6b7 100644 --- a/examples/stm32h755cm7/src/bin/intercore.rs +++ b/examples/stm32h755cm7/src/bin/intercore.rs @@ -2,6 +2,7 @@ #![no_main] use core::mem::MaybeUninit; + use cortex_m::asm; use cortex_m::peripheral::{MPU, SCB}; use defmt::*; -- cgit From 04c0bd84e6043ac35d2a20f1f4a789ccf79bb316 Mon Sep 17 00:00:00 2001 From: ragarnoy Date: Sat, 10 May 2025 10:04:34 +0200 Subject: fix release mode that was broken by lto and codegen units (there are probably things that can be done to be able to keep lto, I haven't found yet) --- examples/stm32h755cm4/Cargo.toml | 5 ++--- examples/stm32h755cm4/src/bin/intercore.rs | 8 ++++---- examples/stm32h755cm7/Cargo.toml | 3 +-- examples/stm32h755cm7/src/bin/intercore.rs | 18 +++++++++++++----- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index c6d4996f1..d2b9b1f0e 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -49,12 +49,11 @@ overflow-checks = true # <- # cargo build/run --release [profile.release] -codegen-units = 1 +codegen-units = 16 debug = 2 debug-assertions = false # <- incremental = false -#lto = 'fat' -#opt-level = 3 # <- +opt-level = 3 # <- overflow-checks = false # <- # cargo test --release diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs index 8f61c3eb2..3a66a1ecd 100644 --- a/examples/stm32h755cm4/src/bin/intercore.rs +++ b/examples/stm32h755cm4/src/bin/intercore.rs @@ -45,7 +45,7 @@ mod shared { }; self.led_states.store(new_value, Ordering::SeqCst); - core::sync::atomic::compiler_fence(Ordering::SeqCst); + core::sync::atomic::fence(Ordering::SeqCst); } /// Get LED state using safe bit operations @@ -54,7 +54,7 @@ mod shared { let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; let value = self.led_states.load(Ordering::SeqCst); - core::sync::atomic::compiler_fence(Ordering::SeqCst); + core::sync::atomic::fence(Ordering::SeqCst); (value & (1 << bit)) != 0 } @@ -66,7 +66,7 @@ mod shared { let current = self.counter.load(Ordering::SeqCst); let new_value = current.wrapping_add(1); self.counter.store(new_value, Ordering::SeqCst); - core::sync::atomic::compiler_fence(Ordering::SeqCst); + core::sync::atomic::fence(Ordering::SeqCst); new_value } @@ -74,7 +74,7 @@ mod shared { #[inline(never)] pub fn get_counter(&self) -> u32 { let value = self.counter.load(Ordering::SeqCst); - core::sync::atomic::compiler_fence(Ordering::SeqCst); + core::sync::atomic::fence(Ordering::SeqCst); value } } diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index 06a3b06af..2e34f0928 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -47,11 +47,10 @@ overflow-checks = true # <- # cargo build/run --release [profile.release] -codegen-units = 1 +codegen-units = 16 debug = 2 debug-assertions = false # <- incremental = false -lto = 'fat' opt-level = 3 # <- overflow-checks = false # <- diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs index f01d6a6b7..f1fbd29bc 100644 --- a/examples/stm32h755cm7/src/bin/intercore.rs +++ b/examples/stm32h755cm7/src/bin/intercore.rs @@ -4,7 +4,7 @@ use core::mem::MaybeUninit; use cortex_m::asm; -use cortex_m::peripheral::{MPU, SCB}; +use cortex_m::peripheral::MPU; use defmt::*; use embassy_executor::Spawner; use embassy_stm32::{Config, SharedData}; @@ -102,7 +102,7 @@ mod shared { static SHARED_DATA: MaybeUninit = MaybeUninit::uninit(); // Function to configure MPU with your provided settings -fn configure_mpu_non_cacheable(mpu: &mut MPU, _scb: &mut SCB) { +fn configure_mpu_non_cacheable(mpu: &mut MPU) { // Ensure all operations complete before reconfiguring MPU/caches asm::dmb(); unsafe { @@ -147,11 +147,19 @@ async fn main(_spawner: Spawner) -> ! { // Configure MPU to make SRAM4 non-cacheable { let mut cp = cortex_m::Peripherals::take().unwrap(); - let mpu = &mut cp.MPU; let scb = &mut cp.SCB; - // Configure MPU without disabling caches - configure_mpu_non_cacheable(mpu, scb); + scb.disable_icache(); + scb.disable_dcache(&mut cp.CPUID); + + // 2. MPU setup + configure_mpu_non_cacheable(&mut cp.MPU); + + // 3. re-enable caches + scb.enable_icache(); + scb.enable_dcache(&mut cp.CPUID); + asm::dsb(); + asm::isb(); } // Configure the clocks -- cgit From f28934cb46bd18cf362b988471266e1b7bb9927e Mon Sep 17 00:00:00 2001 From: ragarnoy Date: Sat, 10 May 2025 10:40:35 +0200 Subject: Rewrite documentation and generally improve it --- examples/stm32h755cm4/src/bin/intercore.rs | 53 +++++++++++--------- examples/stm32h755cm7/src/bin/intercore.rs | 79 +++++++++++++++--------------- 2 files changed, 71 insertions(+), 61 deletions(-) diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs index 3a66a1ecd..715df28d6 100644 --- a/examples/stm32h755cm4/src/bin/intercore.rs +++ b/examples/stm32h755cm4/src/bin/intercore.rs @@ -1,18 +1,32 @@ #![no_std] #![no_main] -// IMPORTANT: This must match EXACTLY the definition in CM7! +//! STM32H7 Secondary Core (CM4) Intercore Communication Example +//! +//! This example demonstrates reliable communication between the Cortex-M7 and +//! Cortex-M4 cores. This secondary core monitors shared memory for LED state +//! changes and updates the physical LEDs accordingly. +//! +//! The CM4 core handles: +//! - Responding to state changes from CM7 +//! - Controlling the physical green and yellow LEDs +//! - Providing visual feedback via a heartbeat on the red LED +//! +//! Usage: +//! 1. Flash this CM4 (secondary) core binary first +//! 2. Then flash the CM7 (primary) core binary +//! 3. The red LED should blink continuously as a heartbeat +//! 4. Green and yellow LEDs should toggle according to CM7 core signals + +/// Module providing shared memory constructs for intercore communication mod shared { use core::sync::atomic::{AtomicU32, Ordering}; - /// Shared LED state between CM7 and CM4 cores + /// State shared between CM7 and CM4 cores for LED control #[repr(C, align(4))] pub struct SharedLedState { - // Magic number for validation pub magic: AtomicU32, - // Counter for synchronization testing pub counter: AtomicU32, - // LED states packed into a single atomic pub led_states: AtomicU32, } @@ -23,19 +37,17 @@ mod shared { impl SharedLedState { pub const fn new() -> Self { Self { - magic: AtomicU32::new(0xDEADBEEF), // Magic number + magic: AtomicU32::new(0xDEADBEEF), counter: AtomicU32::new(0), led_states: AtomicU32::new(0), } } - /// Set LED state using safe bit operations + /// Set LED state by manipulating the appropriate bit in the led_states field #[inline(never)] #[allow(dead_code)] pub fn set_led(&self, is_green: bool, state: bool) { let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; - - // Use bit operations to avoid complex atomic operations let current = self.led_states.load(Ordering::SeqCst); let new_value = if state { @@ -48,7 +60,7 @@ mod shared { core::sync::atomic::fence(Ordering::SeqCst); } - /// Get LED state using safe bit operations + /// Get current LED state #[inline(never)] pub fn get_led(&self, is_green: bool) -> bool { let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; @@ -59,7 +71,7 @@ mod shared { (value & (1 << bit)) != 0 } - /// Increment counter safely + /// Increment counter and return new value #[inline(never)] #[allow(dead_code)] pub fn increment_counter(&self) -> u32 { @@ -70,7 +82,7 @@ mod shared { new_value } - /// Get counter without incrementing + /// Get current counter value #[inline(never)] pub fn get_counter(&self) -> u32 { let value = self.counter.load(Ordering::SeqCst); @@ -84,19 +96,18 @@ mod shared { } use core::mem::MaybeUninit; - use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::{Level, Output, Speed}; use embassy_stm32::SharedData; use embassy_time::Timer; -// Use our shared state from the module use shared::SHARED_LED_STATE; use {defmt_rtt as _, panic_probe as _}; #[link_section = ".ram_d3"] static SHARED_DATA: MaybeUninit = MaybeUninit::uninit(); +/// Task that continuously blinks the red LED as a heartbeat indicator #[embassy_executor::task] async fn blink_heartbeat(mut led: Output<'static>) { loop { @@ -112,11 +123,11 @@ async fn main(spawner: Spawner) -> ! { let p = embassy_stm32::init_secondary(&SHARED_DATA); info!("CM4 core initialized!"); - // Read the magic value to ensure shared memory is accessible + // Verify shared memory is accessible let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst); info!("CM4: Magic value = 0x{:X}", magic); - // Initialize LEDs + // Set up LEDs let mut green_led = Output::new(p.PB0, Level::Low, Speed::Low); // LD1 let mut yellow_led = Output::new(p.PE1, Level::Low, Speed::Low); // LD2 let red_led = Output::new(p.PB14, Level::Low, Speed::Low); // LD3 (heartbeat) @@ -124,31 +135,30 @@ async fn main(spawner: Spawner) -> ! { // Start heartbeat task unwrap!(spawner.spawn(blink_heartbeat(red_led))); - // Previous values for detecting changes + // Track previous values to detect changes let mut prev_green = false; let mut prev_yellow = false; let mut prev_counter = 0; info!("CM4: Starting main loop"); loop { - // Read values from shared memory + // Read current values from shared memory let green_state = SHARED_LED_STATE.get_led(true); let yellow_state = SHARED_LED_STATE.get_led(false); let counter = SHARED_LED_STATE.get_counter(); - // Check for state changes + // Detect changes let green_changed = green_state != prev_green; let yellow_changed = yellow_state != prev_yellow; let counter_changed = counter != prev_counter; - // If any state changed, log it and update LEDs + // Update LEDs and logs when values change if green_changed || yellow_changed || counter_changed { if counter_changed { info!("CM4: Counter = {}", counter); prev_counter = counter; } - // Update LED states if green_changed { if green_state { green_led.set_high(); @@ -172,7 +182,6 @@ async fn main(spawner: Spawner) -> ! { } } - // Poll at a reasonable rate Timer::after_millis(10).await; } } diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs index f1fbd29bc..530e782ab 100644 --- a/examples/stm32h755cm7/src/bin/intercore.rs +++ b/examples/stm32h755cm7/src/bin/intercore.rs @@ -1,6 +1,23 @@ #![no_std] #![no_main] +//! STM32H7 Primary Core (CM7) Intercore Communication Example +//! +//! This example demonstrates reliable communication between the Cortex-M7 and +//! Cortex-M4 cores using a shared memory region configured as non-cacheable +//! via MPU settings. +//! +//! The CM7 core handles: +//! - MPU configuration to make shared memory non-cacheable +//! - Clock initialization +//! - Toggling LED states in shared memory +//! +//! Usage: +//! 1. Flash the CM4 (secondary) core binary first +//! 2. Then flash this CM7 (primary) core binary +//! 3. The system will start with CM7 toggling LED states and CM4 responding by +//! physically toggling the LEDs + use core::mem::MaybeUninit; use cortex_m::asm; @@ -12,17 +29,15 @@ use embassy_time::Timer; use shared::{SHARED_LED_STATE, SRAM4_BASE_ADDRESS, SRAM4_REGION_NUMBER, SRAM4_SIZE_LOG2}; use {defmt_rtt as _, panic_probe as _}; +/// Module providing shared memory constructs for intercore communication mod shared { use core::sync::atomic::{AtomicU32, Ordering}; - /// Shared LED state between CM7 and CM4 cores + /// State shared between CM7 and CM4 cores for LED control #[repr(C, align(4))] pub struct SharedLedState { - // Magic number for validation pub magic: AtomicU32, - // Counter for synchronization testing pub counter: AtomicU32, - // LED states packed into a single atomic pub led_states: AtomicU32, } @@ -33,18 +48,16 @@ mod shared { impl SharedLedState { pub const fn new() -> Self { Self { - magic: AtomicU32::new(0xDEADBEEF), // Magic number + magic: AtomicU32::new(0xDEADBEEF), counter: AtomicU32::new(0), led_states: AtomicU32::new(0), } } - /// Set LED state using safe bit operations + /// Set LED state by manipulating the appropriate bit in the led_states field #[inline(never)] pub fn set_led(&self, is_green: bool, state: bool) { let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; - - // Use bit operations to avoid complex atomic operations let current = self.led_states.load(Ordering::SeqCst); let new_value = if state { @@ -57,7 +70,7 @@ mod shared { core::sync::atomic::compiler_fence(Ordering::SeqCst); } - /// Get LED state using safe bit operations + /// Get current LED state #[inline(never)] #[allow(dead_code)] pub fn get_led(&self, is_green: bool) -> bool { @@ -69,7 +82,7 @@ mod shared { (value & (1 << bit)) != 0 } - /// Increment counter safely + /// Increment counter and return new value #[inline(never)] pub fn increment_counter(&self) -> u32 { let current = self.counter.load(Ordering::SeqCst); @@ -79,7 +92,7 @@ mod shared { new_value } - /// Get counter without incrementing + /// Get current counter value #[inline(never)] #[allow(dead_code)] pub fn get_counter(&self) -> u32 { @@ -92,37 +105,29 @@ mod shared { #[link_section = ".ram_d3"] pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); - // SRAM4 memory region constants for MPU configuration + // Memory region constants for MPU configuration pub const SRAM4_BASE_ADDRESS: u32 = 0x38000000; pub const SRAM4_SIZE_LOG2: u32 = 15; // 64KB = 2^(15+1) - pub const SRAM4_REGION_NUMBER: u8 = 0; // MPU region number to use + pub const SRAM4_REGION_NUMBER: u8 = 0; } #[link_section = ".ram_d3"] static SHARED_DATA: MaybeUninit = MaybeUninit::uninit(); -// Function to configure MPU with your provided settings +/// Configure MPU to make SRAM4 region non-cacheable fn configure_mpu_non_cacheable(mpu: &mut MPU) { - // Ensure all operations complete before reconfiguring MPU/caches asm::dmb(); unsafe { // Disable MPU mpu.ctrl.write(0); // Configure SRAM4 as non-cacheable - // Set region number (0) mpu.rnr.write(SRAM4_REGION_NUMBER as u32); - // Set base address (SRAM4 = 0x38000000) with VALID bit and region number - mpu.rbar.write( - SRAM4_BASE_ADDRESS | (1 << 4), // Region number = 0 (explicit in RBAR) - ); + // Set base address with region number + mpu.rbar.write(SRAM4_BASE_ADDRESS | (1 << 4)); - // Configure region attributes: - // SIZE=15 (64KB = 2^(15+1)) - // ENABLE=1 - // AP=3 (Full access) - // TEX=1, S=1, C=0, B=0 (Normal memory, Non-cacheable, Shareable) + // Configure region attributes let rasr_value: u32 = (SRAM4_SIZE_LOG2 << 1) | // SIZE=15 (64KB) (1 << 0) | // ENABLE=1 (3 << 24) | // AP=3 (Full access) @@ -135,7 +140,6 @@ fn configure_mpu_non_cacheable(mpu: &mut MPU) { mpu.ctrl.write(1 | (1 << 2)); // MPU_ENABLE | PRIVDEFENA } - // Ensure changes are committed asm::dsb(); asm::isb(); @@ -144,25 +148,26 @@ fn configure_mpu_non_cacheable(mpu: &mut MPU) { #[embassy_executor::main] async fn main(_spawner: Spawner) -> ! { - // Configure MPU to make SRAM4 non-cacheable + // Set up MPU and cache configuration { let mut cp = cortex_m::Peripherals::take().unwrap(); let scb = &mut cp.SCB; + // First disable caches scb.disable_icache(); scb.disable_dcache(&mut cp.CPUID); - // 2. MPU setup + // Configure MPU configure_mpu_non_cacheable(&mut cp.MPU); - // 3. re-enable caches + // Re-enable caches scb.enable_icache(); scb.enable_dcache(&mut cp.CPUID); asm::dsb(); asm::isb(); } - // Configure the clocks + // Configure the clock system let mut config = Config::default(); { use embassy_stm32::rcc::*; @@ -191,42 +196,38 @@ async fn main(_spawner: Spawner) -> ! { let _p = embassy_stm32::init_primary(config, &SHARED_DATA); info!("CM7 core initialized with non-cacheable SRAM4!"); - // Read the magic value to ensure shared memory is accessible + // Verify shared memory is accessible let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst); info!("CM7: Magic value = 0x{:X}", magic); - // Initialize shared memory state + // Initialize LED states SHARED_LED_STATE.set_led(true, false); // Green LED off SHARED_LED_STATE.set_led(false, false); // Yellow LED off - // Main loop - update shared memory values + // Main loop - periodically toggle LED states let mut green_state = false; let mut yellow_state = false; let mut loop_count = 0; info!("CM7: Starting main loop"); loop { - // Update loop counter loop_count += 1; - - // Update shared counter let counter = SHARED_LED_STATE.increment_counter(); - // Every second, toggle green LED state + // Toggle green LED every second if loop_count % 10 == 0 { green_state = !green_state; SHARED_LED_STATE.set_led(true, green_state); info!("CM7: Counter = {}, Set green LED to {}", counter, green_state); } - // Every 3 seconds, toggle yellow LED state + // Toggle yellow LED every 3 seconds if loop_count % 30 == 0 { yellow_state = !yellow_state; SHARED_LED_STATE.set_led(false, yellow_state); info!("CM7: Counter = {}, Set yellow LED to {}", counter, yellow_state); } - // Wait 100ms before next cycle Timer::after_millis(100).await; } } -- cgit From ddcf13b5260c909d95b72d61131bb1c7e96d2e66 Mon Sep 17 00:00:00 2001 From: ragarnoy Date: Sat, 10 May 2025 10:42:52 +0200 Subject: nightly rustfmt really do be my bane rn --- examples/stm32h755cm4/src/bin/intercore.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs index 715df28d6..6ebf61cd4 100644 --- a/examples/stm32h755cm4/src/bin/intercore.rs +++ b/examples/stm32h755cm4/src/bin/intercore.rs @@ -96,6 +96,7 @@ mod shared { } use core::mem::MaybeUninit; + use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::{Level, Output, Speed}; -- cgit From 4567beda7b7773c8cb11f19f0f4f146c1243508d Mon Sep 17 00:00:00 2001 From: 1-rafael-1 Date: Sun, 11 May 2025 17:26:36 +0200 Subject: rp235x overclocking --- embassy-rp/src/clocks.rs | 329 ++++++++++++++++++++++++++++---- examples/rp/src/bin/overclock.rs | 8 +- examples/rp/src/bin/overclock_manual.rs | 10 +- examples/rp235x/src/bin/overclock.rs | 74 +++++++ tests/rp/src/bin/overclock.rs | 49 +++-- 5 files changed, 405 insertions(+), 65 deletions(-) create mode 100644 examples/rp235x/src/bin/overclock.rs diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 6694aab66..ea5e9362b 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -38,7 +38,7 @@ //! //! ## Examples //! -//! ### Standard 125MHz configuration +//! ### Standard 125MHz (rp2040) or 150Mhz (rp235x) configuration //! ```rust,ignore //! let config = ClockConfig::crystal(12_000_000); //! ``` @@ -136,43 +136,152 @@ pub enum PeriClkSrc { // Gpin1 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 as _ , } -/// Core voltage regulator settings for RP2040. +/// Core voltage regulator settings. /// -/// The RP2040 voltage regulator can be configured for different output voltages. +/// The voltage regulator can be configured for different output voltages. /// Higher voltages allow for higher clock frequencies but increase power consumption and heat. -#[cfg(feature = "rp2040")] #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[repr(u8)] pub enum CoreVoltage { - /// 0.80V - Suitable for lower frequencies + // RP2040 voltage levels + #[cfg(feature = "rp2040")] + /// RP2040: 0.80V V0_80 = 0b0000, - /// 0.85V + #[cfg(feature = "rp2040")] + /// RP2040: 0.85V V0_85 = 0b0110, - /// 0.90V + #[cfg(feature = "rp2040")] + /// RP2040: 0.90V V0_90 = 0b0111, - /// 0.95V + #[cfg(feature = "rp2040")] + /// RP2040: 0.95V V0_95 = 0b1000, - /// 1.00V + #[cfg(feature = "rp2040")] + /// RP2040: 1.00V V1_00 = 0b1001, - /// 1.05V + #[cfg(feature = "rp2040")] + /// RP2040: 1.05V V1_05 = 0b1010, - /// 1.10V - Default voltage level + #[cfg(feature = "rp2040")] + /// RP2040: 1.10V - Default voltage level V1_10 = 0b1011, - /// 1.15V - Required for overclocking to 133-200MHz + #[cfg(feature = "rp2040")] + /// RP2040: 1.15V - Required for overclocking to 133-200MHz V1_15 = 0b1100, - /// 1.20V + #[cfg(feature = "rp2040")] + /// RP2040: 1.20V V1_20 = 0b1101, - /// 1.25V + #[cfg(feature = "rp2040")] + /// RP2040: 1.25V V1_25 = 0b1110, - /// 1.30V + #[cfg(feature = "rp2040")] + /// RP2040: 1.30V V1_30 = 0b1111, + + // RP235x voltage levels + #[cfg(feature = "_rp235x")] + /// RP235x: 0.55V + V0_55 = 0b00000, + #[cfg(feature = "_rp235x")] + /// RP235x: 0.60V + V0_60 = 0b00001, + #[cfg(feature = "_rp235x")] + /// RP235x: 0.65V + V0_65 = 0b00010, + #[cfg(feature = "_rp235x")] + /// RP235x: 0.70V + V0_70 = 0b00011, + #[cfg(feature = "_rp235x")] + /// RP235x: 0.75V + V0_75 = 0b00100, + #[cfg(feature = "_rp235x")] + /// RP235x: 0.80V + V0_80 = 0b00101, + #[cfg(feature = "_rp235x")] + /// RP235x: 0.85V + V0_85 = 0b00110, + #[cfg(feature = "_rp235x")] + /// RP235x: 0.90V + V0_90 = 0b00111, + #[cfg(feature = "_rp235x")] + /// RP235x: 0.95V + V0_95 = 0b01000, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.00V + V1_00 = 0b01001, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.05V + V1_05 = 0b01010, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.10V - Default voltage level + V1_10 = 0b01011, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.15V + V1_15 = 0b01100, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.20V + V1_20 = 0b01101, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.25V + V1_25 = 0b01110, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.30V + V1_30 = 0b01111, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.35V + V1_35 = 0b10000, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.40V + V1_40 = 0b10001, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.50V + V1_50 = 0b10010, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.60V + V1_60 = 0b10011, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.65V + V1_65 = 0b10100, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.70V + V1_70 = 0b10101, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.80V + V1_80 = 0b10110, + #[cfg(feature = "_rp235x")] + /// RP235x: 1.90V + V1_90 = 0b10111, + #[cfg(feature = "_rp235x")] + /// RP235x: 2.00V + V2_00 = 0b11000, + #[cfg(feature = "_rp235x")] + /// RP235x: 2.35V + V2_35 = 0b11001, + #[cfg(feature = "_rp235x")] + /// RP235x: 2.50V + V2_50 = 0b11010, + #[cfg(feature = "_rp235x")] + /// RP235x: 2.65V + V2_65 = 0b11011, + #[cfg(feature = "_rp235x")] + /// RP235x: 2.80V + V2_80 = 0b11100, + #[cfg(feature = "_rp235x")] + /// RP235x: 3.00V + V3_00 = 0b11101, + #[cfg(feature = "_rp235x")] + /// RP235x: 3.15V + V3_15 = 0b11110, + #[cfg(feature = "_rp235x")] + /// RP235x: 3.30V + V3_30 = 0b11111, } -#[cfg(feature = "rp2040")] impl CoreVoltage { /// Get the recommended Brown-Out Detection (BOD) setting for this voltage. /// Sets the BOD threshold to approximately 80% of the core voltage. fn recommended_bod(self) -> u8 { + #[cfg(feature = "rp2040")] match self { CoreVoltage::V0_80 => 0b0100, // 0.645V (~81% of 0.80V) CoreVoltage::V0_85 => 0b0101, // 0.688V (~81% of 0.85V) @@ -180,12 +289,38 @@ impl CoreVoltage { CoreVoltage::V0_95 => 0b0111, // 0.774V (~81% of 0.95V) CoreVoltage::V1_00 => 0b1000, // 0.817V (~82% of 1.00V) CoreVoltage::V1_05 => 0b1000, // 0.817V (~78% of 1.05V) - CoreVoltage::V1_10 => 0b1001, // 0.860V (~78% of 1.10V) + CoreVoltage::V1_10 => 0b1001, // 0.860V (~78% of 1.10V), the default CoreVoltage::V1_15 => 0b1010, // 0.903V (~79% of 1.15V) CoreVoltage::V1_20 => 0b1011, // 0.946V (~79% of 1.20V) CoreVoltage::V1_25 => 0b1100, // 0.989V (~79% of 1.25V) CoreVoltage::V1_30 => 0b1101, // 1.032V (~79% of 1.30V) } + #[cfg(feature = "_rp235x")] + match self { + CoreVoltage::V0_55 => 0b00001, // 0.516V (~94% of 0.55V) + CoreVoltage::V0_60 => 0b00010, // 0.559V (~93% of 0.60V) + CoreVoltage::V0_65 => 0b00011, // 0.602V (~93% of 0.65V) + CoreVoltage::V0_70 => 0b00011, // 0.602V (~86% of 0.70V) + CoreVoltage::V0_75 => 0b00100, // 0.645V (~86% of 0.75V) + CoreVoltage::V0_80 => 0b00101, // 0.688V (~86% of 0.80V) + CoreVoltage::V0_85 => 0b00110, // 0.731V (~86% of 0.85V) + CoreVoltage::V0_90 => 0b00110, // 0.731V (~81% of 0.90V) + CoreVoltage::V0_95 => 0b00111, // 0.774V (~81% of 0.95V) + CoreVoltage::V1_00 => 0b01000, // 0.817V (~82% of 1.00V) + CoreVoltage::V1_05 => 0b01000, // 0.817V (~78% of 1.05V) + CoreVoltage::V1_10 => 0b01001, // 0.860V (~78% of 1.10V), the default + CoreVoltage::V1_15 => 0b01001, // 0.860V (~75% of 1.15V) + CoreVoltage::V1_20 => 0b01010, // 0.903V (~75% of 1.20V) + CoreVoltage::V1_25 => 0b01010, // 0.903V (~72% of 1.25V) + CoreVoltage::V1_30 => 0b01011, // 0.946V (~73% of 1.30V) + CoreVoltage::V1_35 => 0b01011, // 0.946V (~70% of 1.35V) + CoreVoltage::V1_40 => 0b01100, // 0.989V (~71% of 1.40V) + CoreVoltage::V1_50 => 0b01101, // 1.032V (~69% of 1.50V) + CoreVoltage::V1_60 => 0b01110, // 1.075V (~67% of 1.60V) + CoreVoltage::V1_65 => 0b01110, // 1.075V (~65% of 1.65V) + CoreVoltage::V1_70 => 0b01111, // 1.118V (~66% of 1.70V) + _ => 0b10000, // the rp2350 datasheet repeats this value for all other core voltages + } } } @@ -209,12 +344,10 @@ pub struct ClockConfig { /// RTC clock configuration. #[cfg(feature = "rp2040")] pub rtc_clk: Option, - /// Core voltage scaling (RP2040 only). Defaults to 1.10V. - #[cfg(feature = "rp2040")] + /// Core voltage scaling. Defaults to 1.10V. pub core_voltage: CoreVoltage, /// Voltage stabilization delay in microseconds. /// If not set, defaults will be used based on voltage level. - #[cfg(feature = "rp2040")] pub voltage_stabilization_delay_us: Option, // See above re gpin handling being commented out // gpin0: Option<(u32, Gpin<'static, AnyPin>)>, @@ -250,9 +383,7 @@ impl Default for ClockConfig { adc_clk: None, #[cfg(feature = "rp2040")] rtc_clk: None, - #[cfg(feature = "rp2040")] core_voltage: CoreVoltage::V1_10, - #[cfg(feature = "rp2040")] voltage_stabilization_delay_us: None, // See above re gpin handling being commented out // gpin0: None, @@ -323,9 +454,7 @@ impl ClockConfig { div_frac: 0, phase: 0, }), - #[cfg(feature = "rp2040")] core_voltage: CoreVoltage::V1_10, // Use hardware default (1.10V) - #[cfg(feature = "rp2040")] voltage_stabilization_delay_us: None, // See above re gpin handling being commented out // gpin0: None, @@ -368,9 +497,7 @@ impl ClockConfig { div_frac: 171, phase: 0, }), - #[cfg(feature = "rp2040")] core_voltage: CoreVoltage::V1_10, // Use hardware default (1.10V) - #[cfg(feature = "rp2040")] voltage_stabilization_delay_us: None, // See above re gpin handling being commented out // gpin0: None, @@ -394,12 +521,17 @@ impl ClockConfig { /// the usual 12Mhz crystal, or panic if no valid parameters can be found. /// /// # Note on core voltage: + /// + /// **For RP2040**: /// To date the only officially documented core voltages (see Datasheet section 2.15.3.1. Instances) are: /// - Up to 133MHz: V1_10 (default) /// - Above 133MHz: V1_15, but in the context of the datasheet covering reaching up to 200Mhz /// That way all other frequencies below 133MHz or above 200MHz are not explicitly documented and not covered here. /// In case You want to go below 133MHz or above 200MHz and want a different voltage, You will have to set that manually and with caution. - #[cfg(feature = "rp2040")] + /// + /// **For RP235x**: + /// At this point in time there is no official manufacturer endorsement for running the chip on other core voltages and/or other clock speeds than the defaults. + /// Using this function is experimental and may not work as expected or even damage the chip. pub fn system_freq(hz: u32) -> Self { // Start with the standard configuration from crystal() const DEFAULT_CRYSTAL_HZ: u32 = 12_000_000; @@ -407,9 +539,14 @@ impl ClockConfig { // No need to modify anything if target frequency is already 125MHz // (which is what crystal() configures by default) + #[cfg(feature = "rp2040")] if hz == 125_000_000 { return config; } + #[cfg(feature = "_rp235x")] + if hz == 150_000_000 { + return config; + } // Find optimal PLL parameters for the requested frequency let sys_pll_params = find_pll_params(DEFAULT_CRYSTAL_HZ, hz) @@ -429,6 +566,14 @@ impl ClockConfig { _ => CoreVoltage::V1_10, // Use default voltage (V1_10) }; } + #[cfg(feature = "_rp235x")] + { + config.core_voltage = match hz { + // There is no official support for running the chip on other core voltages and/or other clock speeds than the defaults. + // So for now we have not way of knowing what the voltage should be. Change this if the manufacturer provides more information. + _ => CoreVoltage::V1_10, // Use default voltage (V1_10) + }; + } config } @@ -791,7 +936,6 @@ pub struct RtcClkConfig { /// // Find parameters for 133MHz system clock from 12MHz crystal /// let pll_params = find_pll_params(12_000_000, 133_000_000).unwrap(); /// ``` -#[cfg(feature = "rp2040")] fn find_pll_params(input_hz: u32, target_hz: u32) -> Option { // Fixed reference divider for system PLL const PLL_SYS_REFDIV: u8 = 1; @@ -925,18 +1069,59 @@ pub(crate) unsafe fn init(config: ClockConfig) { }; CLOCKS.rosc.store(rosc_freq, Ordering::Relaxed); - // Set Core Voltage (RP2040 only), if we have config for it and we're not using the default - #[cfg(feature = "rp2040")] + // Set Core Voltage, if we have config for it and we're not using the default { let voltage = config.core_voltage; + + #[cfg(feature = "rp2040")] let vreg = pac::VREG_AND_CHIP_RESET; + #[cfg(feature = "_rp235x")] + let vreg = pac::POWMAN; + let current_vsel = vreg.vreg().read().vsel(); let target_vsel = voltage as u8; // If the target voltage is different from the current one, we need to change it if target_vsel != current_vsel { - // Use modify() to preserve the HIZ and EN bits - otherwise we will disable the regulator when changing voltage - vreg.vreg().modify(|w| w.set_vsel(target_vsel)); + #[cfg(feature = "rp2040")] + { + // Use modify() to preserve the HIZ and EN bits - otherwise we will disable the regulator when changing voltage + vreg.vreg().modify(|w| w.set_vsel(target_vsel)); + } + #[cfg(feature = "_rp235x")] + { + // The rp235x has a different way of controlling the voltage regulator + // Changes to the voltage regulator are protected by a password, see datasheet section 6.4 + // The password is "5AFE" (0x5AFE), it must be set in the top 16 bits of the register + + // The rp235x by default locks the voltage regulator control, so we need to unlock it first + // See datasheet section 6.3.2. Software Control + vreg.vreg_ctrl().modify(|w| { + // Add password to top 16 bits, preserving the rest, repeat below for other registers + w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); + w.set_unlock(true); + *w + }); + + // Set the voltage + vreg.vreg().modify(|w| { + w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); + w.set_vsel(target_vsel); + *w + }); + + // The rp235x has two more registers to set the voltage for low power mode + vreg.vreg_lp_entry().modify(|w| { + w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); + w.set_vsel(target_vsel); + *w + }); + vreg.vreg_lp_exit().modify(|w| { + w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); + w.set_vsel(target_vsel); + *w + }); + } // Wait for the voltage to stabilize. Use the provided delay or default based on voltage let settling_time_us = config.voltage_stabilization_delay_us.unwrap_or_else(|| { @@ -959,6 +1144,19 @@ pub(crate) unsafe fn init(config: ClockConfig) { w.set_vsel(voltage.recommended_bod()); w.set_en(true); // Enable brownout detection }); + + #[cfg(feature = "_rp235x")] + { + // The rp235x has a separate register for the BOD level in low power mode + vreg.bod_lp_entry().write(|w| { + w.set_vsel(voltage.recommended_bod()); + w.set_en(true); // Enable brownout detection + }); + vreg.bod_lp_exit().write(|w| { + w.set_vsel(voltage.recommended_bod()); + w.set_en(true); // Enable brownout detection + }); + } } } @@ -1283,6 +1481,73 @@ pub fn clk_rtc_freq() -> u16 { CLOCKS.rtc.load(Ordering::Relaxed) } +/// The core voltage of the chip. +/// +/// Returns the current core voltage or an error if the voltage register +/// contains an unknown value. +pub fn core_voltage() -> Result { + #[cfg(feature = "rp2040")] + { + let vreg = pac::VREG_AND_CHIP_RESET; + let vsel = vreg.vreg().read().vsel(); + match vsel { + 0b0000 => Ok(CoreVoltage::V0_80), + 0b0110 => Ok(CoreVoltage::V0_85), + 0b0111 => Ok(CoreVoltage::V0_90), + 0b1000 => Ok(CoreVoltage::V0_95), + 0b1001 => Ok(CoreVoltage::V1_00), + 0b1010 => Ok(CoreVoltage::V1_05), + 0b1011 => Ok(CoreVoltage::V1_10), + 0b1100 => Ok(CoreVoltage::V1_15), + 0b1101 => Ok(CoreVoltage::V1_20), + 0b1110 => Ok(CoreVoltage::V1_25), + 0b1111 => Ok(CoreVoltage::V1_30), + _ => Err("Unexpected value in register"), + } + } + + #[cfg(feature = "_rp235x")] + { + let vreg = pac::POWMAN; + let vsel = vreg.vreg().read().vsel(); + match vsel { + 0b00000 => Ok(CoreVoltage::V0_55), + 0b00001 => Ok(CoreVoltage::V0_60), + 0b00010 => Ok(CoreVoltage::V0_65), + 0b00011 => Ok(CoreVoltage::V0_70), + 0b00100 => Ok(CoreVoltage::V0_75), + 0b00101 => Ok(CoreVoltage::V0_80), + 0b00110 => Ok(CoreVoltage::V0_85), + 0b00111 => Ok(CoreVoltage::V0_90), + 0b01000 => Ok(CoreVoltage::V0_95), + 0b01001 => Ok(CoreVoltage::V1_00), + 0b01010 => Ok(CoreVoltage::V1_05), + 0b01011 => Ok(CoreVoltage::V1_10), + 0b01100 => Ok(CoreVoltage::V1_15), + 0b01101 => Ok(CoreVoltage::V1_20), + 0b01110 => Ok(CoreVoltage::V1_25), + 0b01111 => Ok(CoreVoltage::V1_30), + 0b10000 => Ok(CoreVoltage::V1_35), + 0b10001 => Ok(CoreVoltage::V1_40), + 0b10010 => Ok(CoreVoltage::V1_50), + 0b10011 => Ok(CoreVoltage::V1_60), + 0b10100 => Ok(CoreVoltage::V1_65), + 0b10101 => Ok(CoreVoltage::V1_70), + 0b10110 => Ok(CoreVoltage::V1_80), + 0b10111 => Ok(CoreVoltage::V1_90), + 0b11000 => Ok(CoreVoltage::V2_00), + 0b11001 => Ok(CoreVoltage::V2_35), + 0b11010 => Ok(CoreVoltage::V2_50), + 0b11011 => Ok(CoreVoltage::V2_65), + 0b11100 => Ok(CoreVoltage::V2_80), + 0b11101 => Ok(CoreVoltage::V3_00), + 0b11110 => Ok(CoreVoltage::V3_15), + 0b11111 => Ok(CoreVoltage::V3_30), + _ => Err("Unexpected value in register"), + } + } +} + fn start_xosc(crystal_hz: u32, delay_multiplier: u32) { let startup_delay = (((crystal_hz / 1000) * delay_multiplier) + 128) / 256; pac::XOSC.startup().write(|w| w.set_delay(startup_delay as u16)); diff --git a/examples/rp/src/bin/overclock.rs b/examples/rp/src/bin/overclock.rs index 9c78e0c9d..89147ba42 100644 --- a/examples/rp/src/bin/overclock.rs +++ b/examples/rp/src/bin/overclock.rs @@ -7,7 +7,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::clocks::{clk_sys_freq, ClockConfig}; +use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig}; use embassy_rp::config::Config; use embassy_rp::gpio::{Level, Output}; use embassy_time::{Duration, Instant, Timer}; @@ -20,15 +20,15 @@ async fn main(_spawner: Spawner) -> ! { // Set up for clock frequency of 200 MHz, setting all necessary defaults. let config = Config::new(ClockConfig::system_freq(200_000_000)); - // Show the voltage scale for verification - info!("System core voltage: {}", Debug2Format(&config.clocks.core_voltage)); - // Initialize the peripherals let p = embassy_rp::init(config); // Show CPU frequency for verification let sys_freq = clk_sys_freq(); info!("System clock frequency: {} MHz", sys_freq / 1_000_000); + // Show core voltage for verification + let core_voltage = core_voltage().unwrap(); + info!("Core voltage: {}", Debug2Format(&core_voltage)); // LED to indicate the system is running let mut led = Output::new(p.PIN_25, Level::Low); diff --git a/examples/rp/src/bin/overclock_manual.rs b/examples/rp/src/bin/overclock_manual.rs index 35160b250..88ef26a7a 100644 --- a/examples/rp/src/bin/overclock_manual.rs +++ b/examples/rp/src/bin/overclock_manual.rs @@ -7,8 +7,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::clocks; -use embassy_rp::clocks::{ClockConfig, CoreVoltage, PllConfig}; +use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage, PllConfig}; use embassy_rp::config::Config; use embassy_rp::gpio::{Level, Output}; use embassy_time::{Duration, Instant, Timer}; @@ -41,9 +40,12 @@ async fn main(_spawner: Spawner) -> ! { // Initialize with our manual overclock configuration let p = embassy_rp::init(configure_manual_overclock()); - // Verify the actual system clock frequency - let sys_freq = clocks::clk_sys_freq(); + // Show CPU frequency for verification + let sys_freq = clk_sys_freq(); info!("System clock frequency: {} MHz", sys_freq / 1_000_000); + // Show core voltage for verification + let core_voltage = core_voltage().unwrap(); + info!("Core voltage: {}", Debug2Format(&core_voltage)); // LED to indicate the system is running let mut led = Output::new(p.PIN_25, Level::Low); diff --git a/examples/rp235x/src/bin/overclock.rs b/examples/rp235x/src/bin/overclock.rs new file mode 100644 index 000000000..8713df688 --- /dev/null +++ b/examples/rp235x/src/bin/overclock.rs @@ -0,0 +1,74 @@ +//! # Overclocking the RP2350 to 200 MHz +//! +//! This example demonstrates how to configure the RP2350 to run at 200 MHz instead of the default 150 MHz. +//! +//! ## Note +//! +//! As of yet there is no official support for running the RP235x at higher clock frequencies and/or other core voltages than the default. +//! Doing so may cause unexpected behavior and/or damage the chip. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage}; +use embassy_rp::config::Config; +use embassy_rp::gpio::{Level, Output}; +use embassy_time::{Duration, Instant, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +const COUNT_TO: i64 = 10_000_000; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + // Set up for clock frequency of 200 MHz, setting all necessary defaults. + let mut config = Config::new(ClockConfig::system_freq(200_000_000)); + + // since for the rp235x there is no official support for higher clock frequencies, `system_freq()` will not set a voltage for us. + // We need to guess the core voltage, that is needed for the higher clock frequency. Going with a small increase from the default 1.1V here, based on + // what we know about the RP2040. This is not guaranteed to be correct. + config.clocks.core_voltage = CoreVoltage::V1_15; + + // Initialize the peripherals + let p = embassy_rp::init(config); + + // Show CPU frequency for verification + let sys_freq = clk_sys_freq(); + info!("System clock frequency: {} MHz", sys_freq / 1_000_000); + // Show core voltage for verification + let core_voltage = core_voltage().unwrap(); + info!("Core voltage: {}", Debug2Format(&core_voltage)); + + // LED to indicate the system is running + let mut led = Output::new(p.PIN_25, Level::Low); + + loop { + // Reset the counter at the start of measurement period + let mut counter = 0; + + // Turn LED on while counting + led.set_high(); + + let start = Instant::now(); + + // This is a busy loop that will take some time to complete + while counter < COUNT_TO { + counter += 1; + } + + let elapsed = Instant::now() - start; + + // Report the elapsed time + led.set_low(); + info!( + "At {}Mhz: Elapsed time to count to {}: {}ms", + sys_freq / 1_000_000, + counter, + elapsed.as_millis() + ); + + // Wait 2 seconds before starting the next measurement + Timer::after(Duration::from_secs(2)).await; + } +} diff --git a/tests/rp/src/bin/overclock.rs b/tests/rp/src/bin/overclock.rs index be8e85a3f..a568d7fed 100644 --- a/tests/rp/src/bin/overclock.rs +++ b/tests/rp/src/bin/overclock.rs @@ -7,14 +7,8 @@ teleprobe_meta::target!(b"rpi-pico"); teleprobe_meta::target!(b"pimoroni-pico-plus-2"); use defmt::info; -#[cfg(feature = "rp2040")] -use defmt::{assert, assert_eq}; use embassy_executor::Spawner; -use embassy_rp::clocks; -#[cfg(feature = "rp2040")] -use embassy_rp::clocks::ClockConfig; -#[cfg(feature = "rp2040")] -use embassy_rp::clocks::CoreVoltage; +use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage}; use embassy_rp::config::Config; use embassy_time::Instant; use {defmt_rtt as _, panic_probe as _}; @@ -23,23 +17,26 @@ const COUNT_TO: i64 = 10_000_000; #[embassy_executor::main] async fn main(_spawner: Spawner) { - #[cfg(feature = "rp2040")] let mut config = Config::default(); - #[cfg(not(feature = "rp2040"))] - let config = Config::default(); - // Initialize with 200MHz clock configuration for RP2040, other chips will use default clock - #[cfg(feature = "rp2040")] + // Initialize with 200MHz clock configuration + config.clocks = ClockConfig::system_freq(200_000_000); + + // if we are rp235x, we need to manually set the core voltage. rp2040 should do this automatically + #[cfg(feature = "rp235xb")] { - config.clocks = ClockConfig::system_freq(200_000_000); - let voltage = config.clocks.core_voltage; - assert!(matches!(voltage, CoreVoltage::V1_15), "Expected voltage scale V1_15"); + config.clocks.core_voltage = CoreVoltage::V1_15; } let _p = embassy_rp::init(config); + // We should be at core voltage of 1.15V + assert_eq!(core_voltage().unwrap(), CoreVoltage::V1_15, "Core voltage is not 1.15V"); + // We should be at 200MHz + assert_eq!(clk_sys_freq(), 200_000_000, "System clock frequency is not 200MHz"); + // Test the system speed - let (time_elapsed, clk_sys_freq) = { + let time_elapsed = { let mut counter = 0; let start = Instant::now(); while counter < COUNT_TO { @@ -47,24 +44,26 @@ async fn main(_spawner: Spawner) { } let elapsed = Instant::now() - start; - (elapsed.as_millis(), clocks::clk_sys_freq()) + elapsed.as_millis() }; - // Report the elapsed time, so that the compiler doesn't optimize it away for chips other than RP2040 + // Tests will fail if unused variables are detected: + // Report the elapsed time, so that the compiler doesn't optimize it away for the chip not on test info!( "At {}Mhz: Elapsed time to count to {}: {}ms", - clk_sys_freq / 1_000_000, + clk_sys_freq() / 1_000_000, COUNT_TO, time_elapsed ); + // Check if the elapsed time is within expected limits + // for rp2040 we expect about 600ms #[cfg(feature = "rp2040")] - { - // we should be at 200MHz - assert_eq!(clk_sys_freq, 200_000_000, "System clock frequency is not 200MHz"); - // At 200MHz, the time to count to 10_000_000 should be at 600ms, testing with 1% margin - assert!(time_elapsed <= 606, "Elapsed time is too long"); - } + // allow 1% error + assert!(time_elapsed < 606, "Elapsed time is too long"); + // for rp235x we expect about 450ms + #[cfg(feature = "rp235xb")] + assert!(time_elapsed < 455, "Elapsed time is too long"); cortex_m::asm::bkpt(); } -- cgit From 133500167ca53cfbc5e9268356753bc0e3f8c209 Mon Sep 17 00:00:00 2001 From: 1-rafael-1 Date: Mon, 12 May 2025 09:45:05 +0200 Subject: limit CoreVoltage eum to values up to 1.30V, because we do not support unlocking higher voltages --- embassy-rp/src/clocks.rs | 141 +++++++---------------------------------------- 1 file changed, 21 insertions(+), 120 deletions(-) diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index ea5e9362b..bcd08c204 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -140,6 +140,10 @@ pub enum PeriClkSrc { /// /// The voltage regulator can be configured for different output voltages. /// Higher voltages allow for higher clock frequencies but increase power consumption and heat. +/// +/// **Note**: For RP235x the maximum voltage is 1.30V, unless unlocked by setting unless the voltage limit +/// is disabled using the disable_voltage_limit field in the vreg_ctrl register. For lack of practical use at this +/// point in time, this is not implemented here. So the maximum voltage in this enum is 1.30V for now. #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[repr(u8)] pub enum CoreVoltage { @@ -227,54 +231,6 @@ pub enum CoreVoltage { #[cfg(feature = "_rp235x")] /// RP235x: 1.30V V1_30 = 0b01111, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.35V - V1_35 = 0b10000, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.40V - V1_40 = 0b10001, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.50V - V1_50 = 0b10010, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.60V - V1_60 = 0b10011, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.65V - V1_65 = 0b10100, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.70V - V1_70 = 0b10101, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.80V - V1_80 = 0b10110, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.90V - V1_90 = 0b10111, - #[cfg(feature = "_rp235x")] - /// RP235x: 2.00V - V2_00 = 0b11000, - #[cfg(feature = "_rp235x")] - /// RP235x: 2.35V - V2_35 = 0b11001, - #[cfg(feature = "_rp235x")] - /// RP235x: 2.50V - V2_50 = 0b11010, - #[cfg(feature = "_rp235x")] - /// RP235x: 2.65V - V2_65 = 0b11011, - #[cfg(feature = "_rp235x")] - /// RP235x: 2.80V - V2_80 = 0b11100, - #[cfg(feature = "_rp235x")] - /// RP235x: 3.00V - V3_00 = 0b11101, - #[cfg(feature = "_rp235x")] - /// RP235x: 3.15V - V3_15 = 0b11110, - #[cfg(feature = "_rp235x")] - /// RP235x: 3.30V - V3_30 = 0b11111, } impl CoreVoltage { @@ -313,13 +269,7 @@ impl CoreVoltage { CoreVoltage::V1_20 => 0b01010, // 0.903V (~75% of 1.20V) CoreVoltage::V1_25 => 0b01010, // 0.903V (~72% of 1.25V) CoreVoltage::V1_30 => 0b01011, // 0.946V (~73% of 1.30V) - CoreVoltage::V1_35 => 0b01011, // 0.946V (~70% of 1.35V) - CoreVoltage::V1_40 => 0b01100, // 0.989V (~71% of 1.40V) - CoreVoltage::V1_50 => 0b01101, // 1.032V (~69% of 1.50V) - CoreVoltage::V1_60 => 0b01110, // 1.075V (~67% of 1.60V) - CoreVoltage::V1_65 => 0b01110, // 1.075V (~65% of 1.65V) - CoreVoltage::V1_70 => 0b01111, // 1.118V (~66% of 1.70V) - _ => 0b10000, // the rp2350 datasheet repeats this value for all other core voltages + // all others: 0.946V (see CoreVoltage: we do not support setting Voltages higher than 1.30V at this point) } } } @@ -1083,45 +1033,17 @@ pub(crate) unsafe fn init(config: ClockConfig) { // If the target voltage is different from the current one, we need to change it if target_vsel != current_vsel { + // Set the voltage regulator to the target voltage #[cfg(feature = "rp2040")] - { - // Use modify() to preserve the HIZ and EN bits - otherwise we will disable the regulator when changing voltage - vreg.vreg().modify(|w| w.set_vsel(target_vsel)); - } + vreg.vreg().modify(|w| w.set_vsel(target_vsel)); #[cfg(feature = "_rp235x")] - { - // The rp235x has a different way of controlling the voltage regulator - // Changes to the voltage regulator are protected by a password, see datasheet section 6.4 - // The password is "5AFE" (0x5AFE), it must be set in the top 16 bits of the register - - // The rp235x by default locks the voltage regulator control, so we need to unlock it first - // See datasheet section 6.3.2. Software Control - vreg.vreg_ctrl().modify(|w| { - // Add password to top 16 bits, preserving the rest, repeat below for other registers - w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); - w.set_unlock(true); - *w - }); - - // Set the voltage - vreg.vreg().modify(|w| { - w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); - w.set_vsel(target_vsel); - *w - }); - - // The rp235x has two more registers to set the voltage for low power mode - vreg.vreg_lp_entry().modify(|w| { - w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); - w.set_vsel(target_vsel); - *w - }); - vreg.vreg_lp_exit().modify(|w| { - w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); - w.set_vsel(target_vsel); - *w - }); - } + // For rp235x changes to the voltage regulator are protected by a password, see datasheet section 6.4 Power Management (POWMAN) Registers + // The password is "5AFE" (0x5AFE), it must be set in the top 16 bits of the register + vreg.vreg().modify(|w| { + w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); // Set the password + w.set_vsel(target_vsel); + *w + }); // Wait for the voltage to stabilize. Use the provided delay or default based on voltage let settling_time_us = config.voltage_stabilization_delay_us.unwrap_or_else(|| { @@ -1140,23 +1062,17 @@ pub(crate) unsafe fn init(config: ClockConfig) { } // Only now set the BOD level. At this point the voltage is considered stable. + #[cfg(feature = "rp2040")] vreg.bod().write(|w| { w.set_vsel(voltage.recommended_bod()); w.set_en(true); // Enable brownout detection }); - #[cfg(feature = "_rp235x")] - { - // The rp235x has a separate register for the BOD level in low power mode - vreg.bod_lp_entry().write(|w| { - w.set_vsel(voltage.recommended_bod()); - w.set_en(true); // Enable brownout detection - }); - vreg.bod_lp_exit().write(|w| { - w.set_vsel(voltage.recommended_bod()); - w.set_en(true); // Enable brownout detection - }); - } + vreg.bod().write(|w| { + w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); // Set the password + w.set_vsel(voltage.recommended_bod()); + w.set_en(true); // Enable brownout detection + }); } } @@ -1527,23 +1443,8 @@ pub fn core_voltage() -> Result { 0b01101 => Ok(CoreVoltage::V1_20), 0b01110 => Ok(CoreVoltage::V1_25), 0b01111 => Ok(CoreVoltage::V1_30), - 0b10000 => Ok(CoreVoltage::V1_35), - 0b10001 => Ok(CoreVoltage::V1_40), - 0b10010 => Ok(CoreVoltage::V1_50), - 0b10011 => Ok(CoreVoltage::V1_60), - 0b10100 => Ok(CoreVoltage::V1_65), - 0b10101 => Ok(CoreVoltage::V1_70), - 0b10110 => Ok(CoreVoltage::V1_80), - 0b10111 => Ok(CoreVoltage::V1_90), - 0b11000 => Ok(CoreVoltage::V2_00), - 0b11001 => Ok(CoreVoltage::V2_35), - 0b11010 => Ok(CoreVoltage::V2_50), - 0b11011 => Ok(CoreVoltage::V2_65), - 0b11100 => Ok(CoreVoltage::V2_80), - 0b11101 => Ok(CoreVoltage::V3_00), - 0b11110 => Ok(CoreVoltage::V3_15), - 0b11111 => Ok(CoreVoltage::V3_30), _ => Err("Unexpected value in register"), + // see CoreVoltage: we do not support setting Voltages higher than 1.30V at this point } } } -- cgit From 3c73b497909ce5bacd16d23e54928a7f66544e09 Mon Sep 17 00:00:00 2001 From: Gerhard de Clercq <11624490+Gerharddc@users.noreply.github.com> Date: Mon, 12 May 2025 15:51:19 +0200 Subject: [embassy-usb-dfu] support function level WinUSB GUIDs This commit makes it possible to provide function level msos GUIDs to usb_dfu. This helps to ensure that composite DFU devices automatically get assigned the WinUSB driver on Windows. --- embassy-usb-dfu/src/application.rs | 16 +++++++++++++- embassy-usb-dfu/src/dfu.rs | 16 +++++++++++++- examples/boot/application/stm32wb-dfu/src/main.rs | 26 +++++++++++++++++++++-- examples/boot/bootloader/stm32wb-dfu/src/main.rs | 15 +++++++++---- 4 files changed, 65 insertions(+), 8 deletions(-) diff --git a/embassy-usb-dfu/src/application.rs b/embassy-usb-dfu/src/application.rs index 6ad07a78c..52a7ca951 100644 --- a/embassy-usb-dfu/src/application.rs +++ b/embassy-usb-dfu/src/application.rs @@ -2,7 +2,7 @@ use embassy_boot::BlockingFirmwareState; use embassy_time::{Duration, Instant}; use embassy_usb::control::{InResponse, OutResponse, Recipient, RequestType}; use embassy_usb::driver::Driver; -use embassy_usb::{Builder, Handler}; +use embassy_usb::{msos, Builder, Handler}; use embedded_storage::nor_flash::NorFlash; use crate::consts::{ @@ -130,8 +130,22 @@ pub fn usb_dfu<'d, D: Driver<'d>, MARK: DfuMarker, RST: Reset>( builder: &mut Builder<'d, D>, handler: &'d mut Control, timeout: Duration, + winusb_guids: Option<&'d [&str]>, ) { let mut func = builder.function(0x00, 0x00, 0x00); + if let Some(winusb_guids) = winusb_guids { + // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. + // Otherwise users need to do this manually using a tool like Zadig. + // + // Adding them here on the function level appears to only work for compositive devices though. + // For non-composite devices they should be placed on the device level instead. + func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); + func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( + "DeviceInterfaceGUIDs", + msos::PropertyData::RegMultiSz(winusb_guids), + )); + } + let mut iface = func.interface(); let mut alt = iface.alt_setting(USB_CLASS_APPN_SPEC, APPN_SPEC_SUBCLASS_DFU, DFU_PROTOCOL_RT, None); let timeout = timeout.as_millis() as u16; diff --git a/embassy-usb-dfu/src/dfu.rs b/embassy-usb-dfu/src/dfu.rs index a98d6ab40..83feacaf8 100644 --- a/embassy-usb-dfu/src/dfu.rs +++ b/embassy-usb-dfu/src/dfu.rs @@ -1,7 +1,7 @@ use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterError}; use embassy_usb::control::{InResponse, OutResponse, Recipient, RequestType}; use embassy_usb::driver::Driver; -use embassy_usb::{Builder, Handler}; +use embassy_usb::{msos, Builder, Handler}; use embedded_storage::nor_flash::{NorFlash, NorFlashErrorKind}; use crate::consts::{ @@ -186,8 +186,22 @@ impl<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize> Ha pub fn usb_dfu<'d, D: Driver<'d>, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize>( builder: &mut Builder<'d, D>, handler: &'d mut Control<'d, DFU, STATE, RST, BLOCK_SIZE>, + winusb_guids: Option<&'d [&str]>, ) { let mut func = builder.function(USB_CLASS_APPN_SPEC, APPN_SPEC_SUBCLASS_DFU, DFU_PROTOCOL_DFU); + if let Some(winusb_guids) = winusb_guids { + // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. + // Otherwise users need to do this manually using a tool like Zadig. + // + // Adding them here on the function level appears to only work for compositive devices though. + // For non-composite devices they should be placed on the device level instead. + func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); + func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( + "DeviceInterfaceGUIDs", + msos::PropertyData::RegMultiSz(winusb_guids), + )); + } + let mut iface = func.interface(); let mut alt = iface.alt_setting(USB_CLASS_APPN_SPEC, APPN_SPEC_SUBCLASS_DFU, DFU_PROTOCOL_DFU, None); alt.descriptor( diff --git a/examples/boot/application/stm32wb-dfu/src/main.rs b/examples/boot/application/stm32wb-dfu/src/main.rs index dda2b795b..68e9bc3f6 100644 --- a/examples/boot/application/stm32wb-dfu/src/main.rs +++ b/examples/boot/application/stm32wb-dfu/src/main.rs @@ -13,7 +13,7 @@ use embassy_stm32::usb::{self, Driver}; use embassy_stm32::{bind_interrupts, peripherals}; use embassy_sync::blocking_mutex::Mutex; use embassy_time::Duration; -use embassy_usb::Builder; +use embassy_usb::{msos, Builder}; use embassy_usb_dfu::consts::DfuAttributes; use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; use panic_reset as _; @@ -22,6 +22,9 @@ bind_interrupts!(struct Irqs { USB_LP => usb::InterruptHandler; }); +// This is a randomly generated GUID to allow clients on Windows to find our device +const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; + #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = embassy_stm32::Config::default(); @@ -54,7 +57,26 @@ async fn main(_spawner: Spawner) { &mut control_buf, ); - usb_dfu(&mut builder, &mut state, Duration::from_millis(2500)); + // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. + // Otherwise users need to do this manually using a tool like Zadig. + builder.msos_descriptor(msos::windows_version::WIN8_1, 2); + + // In the case of non-composite devices, it seems that feature headers need to be on the device level. + // (As is implemented here) + // + // For composite devices however, they should be on the function level instead. + // (This is achieved by passing a GUID to the "usb_dfu" function) + builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); + builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( + "DeviceInterfaceGUIDs", + msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), + )); + + // For non-composite devices: + usb_dfu(&mut builder, &mut state, Duration::from_millis(2500), None); + + // Or for composite devices: + // usb_dfu(&mut builder, &mut state, Duration::from_millis(2500), Some(DEVICE_INTERFACE_GUIDS)); let mut dev = builder.build(); dev.run().await diff --git a/examples/boot/bootloader/stm32wb-dfu/src/main.rs b/examples/boot/bootloader/stm32wb-dfu/src/main.rs index 28216806e..2cd7f859d 100644 --- a/examples/boot/bootloader/stm32wb-dfu/src/main.rs +++ b/examples/boot/bootloader/stm32wb-dfu/src/main.rs @@ -67,17 +67,24 @@ fn main() -> ! { // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. // Otherwise users need to do this manually using a tool like Zadig. - // - // It seems it is important for the DFU class that these headers be on the Device level. - // builder.msos_descriptor(msos::windows_version::WIN8_1, 2); + + // In the case of non-composite devices, it seems that feature headers need to be on the device level. + // (As is implemented here) + // + // For composite devices however, they should be on the function level instead. + // (This is achieved by passing a GUID to the "usb_dfu" function) builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( "DeviceInterfaceGUIDs", msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), )); - usb_dfu::<_, _, _, _, 4096>(&mut builder, &mut state); + // For non-composite devices: + usb_dfu::<_, _, _, _, 4096>(&mut builder, &mut state, None); + + // Or for composite devices: + // usb_dfu::<_, _, _, _, 4096>(&mut builder, &mut state, Some(DEVICE_INTERFACE_GUIDS)); let mut dev = builder.build(); embassy_futures::block_on(dev.run()); -- cgit From 79e452922a6b467f2e8547a6b28698ed5f409705 Mon Sep 17 00:00:00 2001 From: 1-rafael-1 Date: Mon, 12 May 2025 21:33:47 +0200 Subject: Add ClockError enum and update system_freq to return Result for error handling --- embassy-rp/src/clocks.rs | 66 +++++++++++++++++++++++++----------- examples/rp/src/bin/overclock.rs | 2 +- examples/rp235x/src/bin/overclock.rs | 2 +- tests/rp/src/bin/overclock.rs | 2 +- 4 files changed, 50 insertions(+), 22 deletions(-) diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index bcd08c204..5872ef789 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -82,6 +82,18 @@ use crate::{pac, reset, Peri}; // be very useful until we have runtime clock reconfiguration. once this // happens we can resurrect the commented-out gpin bits. +/// Clock error types. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ClockError { + /// PLL failed to lock within the timeout period. + PllLockTimedOut, + /// Could not find valid PLL parameters for system clock. + InvalidPllParameters, + /// Reading the core voltage failed due to an unexpected value in the register. + UnexpectedCoreVoltageRead, +} + struct Clocks { xosc: AtomicU32, sys: AtomicU32, @@ -144,8 +156,9 @@ pub enum PeriClkSrc { /// **Note**: For RP235x the maximum voltage is 1.30V, unless unlocked by setting unless the voltage limit /// is disabled using the disable_voltage_limit field in the vreg_ctrl register. For lack of practical use at this /// point in time, this is not implemented here. So the maximum voltage in this enum is 1.30V for now. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[repr(u8)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum CoreVoltage { // RP2040 voltage levels #[cfg(feature = "rp2040")] @@ -468,7 +481,7 @@ impl ClockConfig { /// # Returns /// /// A ClockConfig configured to achieve the requested system frequency using the - /// the usual 12Mhz crystal, or panic if no valid parameters can be found. + /// the usual 12Mhz crystal, or an error if no valid parameters can be found. /// /// # Note on core voltage: /// @@ -482,7 +495,11 @@ impl ClockConfig { /// **For RP235x**: /// At this point in time there is no official manufacturer endorsement for running the chip on other core voltages and/or other clock speeds than the defaults. /// Using this function is experimental and may not work as expected or even damage the chip. - pub fn system_freq(hz: u32) -> Self { + /// + /// # Returns + /// + /// A Result containing either the configured ClockConfig or a ClockError. + pub fn system_freq(hz: u32) -> Result { // Start with the standard configuration from crystal() const DEFAULT_CRYSTAL_HZ: u32 = 12_000_000; let mut config = Self::crystal(DEFAULT_CRYSTAL_HZ); @@ -491,16 +508,15 @@ impl ClockConfig { // (which is what crystal() configures by default) #[cfg(feature = "rp2040")] if hz == 125_000_000 { - return config; + return Ok(config); } #[cfg(feature = "_rp235x")] if hz == 150_000_000 { - return config; + return Ok(config); } // Find optimal PLL parameters for the requested frequency - let sys_pll_params = find_pll_params(DEFAULT_CRYSTAL_HZ, hz) - .unwrap_or_else(|| panic!("Could not find valid PLL parameters for system clock")); + let sys_pll_params = find_pll_params(DEFAULT_CRYSTAL_HZ, hz).ok_or(ClockError::InvalidPllParameters)?; // Replace the sys_pll configuration with our custom parameters if let Some(xosc) = &mut config.xosc { @@ -525,7 +541,7 @@ impl ClockConfig { }; } - config + Ok(config) } /// Configure with manual PLL settings for full control over system clock @@ -620,6 +636,7 @@ impl ClockConfig { #[repr(u16)] #[non_exhaustive] #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum RoscRange { /// Low range. Low = pac::rosc::vals::FreqRange::LOW.0, @@ -726,6 +743,7 @@ pub struct RefClkConfig { /// Reference clock source. #[non_exhaustive] #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum RefClkSrc { /// XOSC. Xosc, @@ -741,6 +759,7 @@ pub enum RefClkSrc { /// SYS clock source. #[non_exhaustive] #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SysClkSrc { /// REF. Ref, @@ -779,6 +798,7 @@ pub struct SysClkConfig { #[repr(u8)] #[non_exhaustive] #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum UsbClkSrc { /// PLL USB. PllUsb = ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB as _, @@ -807,6 +827,7 @@ pub struct UsbClkConfig { #[repr(u8)] #[non_exhaustive] #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum AdcClkSrc { /// PLL USB. PllUsb = ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB as _, @@ -835,6 +856,7 @@ pub struct AdcClkConfig { #[repr(u8)] #[non_exhaustive] #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg(feature = "rp2040")] pub enum RtcClkSrc { /// PLL USB. @@ -1084,14 +1106,20 @@ pub(crate) unsafe fn init(config: ClockConfig) { let pll_sys_freq = match config.sys_pll { Some(sys_pll_config) => match configure_pll(pac::PLL_SYS, config.hz, sys_pll_config) { Ok(freq) => freq, + #[cfg(feature = "defmt")] Err(e) => panic!("Failed to configure PLL_SYS: {}", e), + #[cfg(not(feature = "defmt"))] + Err(_e) => panic!("Failed to configure PLL_SYS"), }, None => 0, }; let pll_usb_freq = match config.usb_pll { Some(usb_pll_config) => match configure_pll(pac::PLL_USB, config.hz, usb_pll_config) { Ok(freq) => freq, + #[cfg(feature = "defmt")] Err(e) => panic!("Failed to configure PLL_USB: {}", e), + #[cfg(not(feature = "defmt"))] + Err(_e) => panic!("Failed to configure PLL_USB"), }, None => 0, }; @@ -1401,7 +1429,7 @@ pub fn clk_rtc_freq() -> u16 { /// /// Returns the current core voltage or an error if the voltage register /// contains an unknown value. -pub fn core_voltage() -> Result { +pub fn core_voltage() -> Result { #[cfg(feature = "rp2040")] { let vreg = pac::VREG_AND_CHIP_RESET; @@ -1418,7 +1446,7 @@ pub fn core_voltage() -> Result { 0b1101 => Ok(CoreVoltage::V1_20), 0b1110 => Ok(CoreVoltage::V1_25), 0b1111 => Ok(CoreVoltage::V1_30), - _ => Err("Unexpected value in register"), + _ => Err(ClockError::UnexpectedCoreVoltageRead), } } @@ -1443,7 +1471,7 @@ pub fn core_voltage() -> Result { 0b01101 => Ok(CoreVoltage::V1_20), 0b01110 => Ok(CoreVoltage::V1_25), 0b01111 => Ok(CoreVoltage::V1_30), - _ => Err("Unexpected value in register"), + _ => Err(ClockError::UnexpectedCoreVoltageRead), // see CoreVoltage: we do not support setting Voltages higher than 1.30V at this point } } @@ -1461,7 +1489,7 @@ fn start_xosc(crystal_hz: u32, delay_multiplier: u32) { /// PLL (Phase-Locked Loop) configuration #[inline(always)] -fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> Result { +fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> Result { // Calculate reference frequency let ref_freq = input_freq / config.refdiv as u32; @@ -1532,7 +1560,7 @@ fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> Result timeout -= 1; if timeout == 0 { // PLL failed to lock, return 0 to indicate failure - return Err("PLL failed to lock"); + return Err(ClockError::PllLockTimedOut); } } @@ -2103,21 +2131,21 @@ mod tests { { // Test automatic voltage scaling based on frequency // Under 133 MHz should use default voltage (V1_10) - let config = ClockConfig::system_freq(125_000_000); + let config = ClockConfig::system_freq(125_000_000).unwrap(); assert_eq!(config.core_voltage, CoreVoltage::V1_10); // 133-200 MHz should use V1_15 - let config = ClockConfig::system_freq(150_000_000); + let config = ClockConfig::system_freq(150_000_000).unwrap(); assert_eq!(config.core_voltage, CoreVoltage::V1_15); - let config = ClockConfig::system_freq(200_000_000); + let config = ClockConfig::system_freq(200_000_000).unwrap(); assert_eq!(config.core_voltage, CoreVoltage::V1_15); - // Above 200 MHz should use V1_25 - let config = ClockConfig::system_freq(250_000_000); + // Above 200 MHz should use V1_15 + let config = ClockConfig::system_freq(250_000_000).unwrap(); assert_eq!(config.core_voltage, CoreVoltage::V1_15); // Below 125 MHz should use V1_10 - let config = ClockConfig::system_freq(100_000_000); + let config = ClockConfig::system_freq(100_000_000).unwrap(); assert_eq!(config.core_voltage, CoreVoltage::V1_10); } } diff --git a/examples/rp/src/bin/overclock.rs b/examples/rp/src/bin/overclock.rs index 89147ba42..2706399af 100644 --- a/examples/rp/src/bin/overclock.rs +++ b/examples/rp/src/bin/overclock.rs @@ -18,7 +18,7 @@ const COUNT_TO: i64 = 10_000_000; #[embassy_executor::main] async fn main(_spawner: Spawner) -> ! { // Set up for clock frequency of 200 MHz, setting all necessary defaults. - let config = Config::new(ClockConfig::system_freq(200_000_000)); + let config = Config::new(ClockConfig::system_freq(200_000_000).unwrap()); // Initialize the peripherals let p = embassy_rp::init(config); diff --git a/examples/rp235x/src/bin/overclock.rs b/examples/rp235x/src/bin/overclock.rs index 8713df688..178fd62ca 100644 --- a/examples/rp235x/src/bin/overclock.rs +++ b/examples/rp235x/src/bin/overclock.rs @@ -23,7 +23,7 @@ const COUNT_TO: i64 = 10_000_000; #[embassy_executor::main] async fn main(_spawner: Spawner) -> ! { // Set up for clock frequency of 200 MHz, setting all necessary defaults. - let mut config = Config::new(ClockConfig::system_freq(200_000_000)); + let mut config = Config::new(ClockConfig::system_freq(200_000_000).unwrap()); // since for the rp235x there is no official support for higher clock frequencies, `system_freq()` will not set a voltage for us. // We need to guess the core voltage, that is needed for the higher clock frequency. Going with a small increase from the default 1.1V here, based on diff --git a/tests/rp/src/bin/overclock.rs b/tests/rp/src/bin/overclock.rs index a568d7fed..167a26eb2 100644 --- a/tests/rp/src/bin/overclock.rs +++ b/tests/rp/src/bin/overclock.rs @@ -20,7 +20,7 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); // Initialize with 200MHz clock configuration - config.clocks = ClockConfig::system_freq(200_000_000); + config.clocks = ClockConfig::system_freq(200_000_000).unwrap(); // if we are rp235x, we need to manually set the core voltage. rp2040 should do this automatically #[cfg(feature = "rp235xb")] -- cgit From be1b679d48b5d781f888fb97c1fed7479235019b Mon Sep 17 00:00:00 2001 From: 1-rafael-1 Date: Mon, 12 May 2025 21:42:03 +0200 Subject: Refactor CoreVoltage enum, separate for rp2040 and rp235x --- embassy-rp/src/clocks.rs | 98 +++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 56 deletions(-) diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 5872ef789..3975e7e79 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -156,93 +156,79 @@ pub enum PeriClkSrc { /// **Note**: For RP235x the maximum voltage is 1.30V, unless unlocked by setting unless the voltage limit /// is disabled using the disable_voltage_limit field in the vreg_ctrl register. For lack of practical use at this /// point in time, this is not implemented here. So the maximum voltage in this enum is 1.30V for now. +#[cfg(feature = "rp2040")] #[repr(u8)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum CoreVoltage { - // RP2040 voltage levels - #[cfg(feature = "rp2040")] - /// RP2040: 0.80V + /// 0.80V V0_80 = 0b0000, - #[cfg(feature = "rp2040")] - /// RP2040: 0.85V + /// 0.85V V0_85 = 0b0110, - #[cfg(feature = "rp2040")] - /// RP2040: 0.90V + /// 0.90V V0_90 = 0b0111, - #[cfg(feature = "rp2040")] - /// RP2040: 0.95V + /// 0.95V V0_95 = 0b1000, - #[cfg(feature = "rp2040")] - /// RP2040: 1.00V + /// 1.00V V1_00 = 0b1001, - #[cfg(feature = "rp2040")] - /// RP2040: 1.05V + /// 1.05V V1_05 = 0b1010, - #[cfg(feature = "rp2040")] - /// RP2040: 1.10V - Default voltage level + /// 1.10V - Default voltage level V1_10 = 0b1011, - #[cfg(feature = "rp2040")] - /// RP2040: 1.15V - Required for overclocking to 133-200MHz + /// 1.15V - Required for overclocking to 133-200MHz V1_15 = 0b1100, - #[cfg(feature = "rp2040")] - /// RP2040: 1.20V + /// 1.20V V1_20 = 0b1101, - #[cfg(feature = "rp2040")] - /// RP2040: 1.25V + /// 1.25V V1_25 = 0b1110, - #[cfg(feature = "rp2040")] - /// RP2040: 1.30V + /// 1.30V V1_30 = 0b1111, +} - // RP235x voltage levels - #[cfg(feature = "_rp235x")] - /// RP235x: 0.55V +/// Core voltage regulator settings. +/// +/// The voltage regulator can be configured for different output voltages. +/// Higher voltages allow for higher clock frequencies but increase power consumption and heat. +/// +/// **Note**: For RP235x the maximum voltage is 1.30V, unless unlocked by setting unless the voltage limit +/// is disabled using the disable_voltage_limit field in the vreg_ctrl register. For lack of practical use at this +/// point in time, this is not implemented here. So the maximum voltage in this enum is 1.30V for now. +#[cfg(feature = "_rp235x")] +#[repr(u8)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum CoreVoltage { + /// 0.55V V0_55 = 0b00000, - #[cfg(feature = "_rp235x")] - /// RP235x: 0.60V + /// 0.60V V0_60 = 0b00001, - #[cfg(feature = "_rp235x")] - /// RP235x: 0.65V + /// 0.65V V0_65 = 0b00010, - #[cfg(feature = "_rp235x")] - /// RP235x: 0.70V + /// 0.70V V0_70 = 0b00011, - #[cfg(feature = "_rp235x")] - /// RP235x: 0.75V + /// 0.75V V0_75 = 0b00100, - #[cfg(feature = "_rp235x")] - /// RP235x: 0.80V + /// 0.80V V0_80 = 0b00101, - #[cfg(feature = "_rp235x")] - /// RP235x: 0.85V + /// 0.85V V0_85 = 0b00110, - #[cfg(feature = "_rp235x")] - /// RP235x: 0.90V + /// 0.90V V0_90 = 0b00111, - #[cfg(feature = "_rp235x")] - /// RP235x: 0.95V + /// 0.95V V0_95 = 0b01000, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.00V + /// 1.00V V1_00 = 0b01001, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.05V + /// 1.05V V1_05 = 0b01010, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.10V - Default voltage level + /// 1.10V - Default voltage level V1_10 = 0b01011, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.15V + /// 1.15V V1_15 = 0b01100, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.20V + /// 1.20V V1_20 = 0b01101, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.25V + /// 1.25V V1_25 = 0b01110, - #[cfg(feature = "_rp235x")] - /// RP235x: 1.30V + /// 1.30V V1_30 = 0b01111, } -- cgit From abafbed0d5fba70ab5d0096b9d381577d2f880c8 Mon Sep 17 00:00:00 2001 From: 1-rafael-1 Date: Mon, 12 May 2025 21:43:17 +0200 Subject: remove Debug2Fmt from examples --- examples/rp/src/bin/overclock.rs | 2 +- examples/rp/src/bin/overclock_manual.rs | 2 +- examples/rp235x/src/bin/overclock.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/rp/src/bin/overclock.rs b/examples/rp/src/bin/overclock.rs index 2706399af..83b17308b 100644 --- a/examples/rp/src/bin/overclock.rs +++ b/examples/rp/src/bin/overclock.rs @@ -28,7 +28,7 @@ async fn main(_spawner: Spawner) -> ! { info!("System clock frequency: {} MHz", sys_freq / 1_000_000); // Show core voltage for verification let core_voltage = core_voltage().unwrap(); - info!("Core voltage: {}", Debug2Format(&core_voltage)); + info!("Core voltage: {}", core_voltage); // LED to indicate the system is running let mut led = Output::new(p.PIN_25, Level::Low); diff --git a/examples/rp/src/bin/overclock_manual.rs b/examples/rp/src/bin/overclock_manual.rs index 88ef26a7a..dea5cfb3c 100644 --- a/examples/rp/src/bin/overclock_manual.rs +++ b/examples/rp/src/bin/overclock_manual.rs @@ -45,7 +45,7 @@ async fn main(_spawner: Spawner) -> ! { info!("System clock frequency: {} MHz", sys_freq / 1_000_000); // Show core voltage for verification let core_voltage = core_voltage().unwrap(); - info!("Core voltage: {}", Debug2Format(&core_voltage)); + info!("Core voltage: {}", core_voltage); // LED to indicate the system is running let mut led = Output::new(p.PIN_25, Level::Low); diff --git a/examples/rp235x/src/bin/overclock.rs b/examples/rp235x/src/bin/overclock.rs index 178fd62ca..5fd97ef97 100644 --- a/examples/rp235x/src/bin/overclock.rs +++ b/examples/rp235x/src/bin/overclock.rs @@ -38,7 +38,7 @@ async fn main(_spawner: Spawner) -> ! { info!("System clock frequency: {} MHz", sys_freq / 1_000_000); // Show core voltage for verification let core_voltage = core_voltage().unwrap(); - info!("Core voltage: {}", Debug2Format(&core_voltage)); + info!("Core voltage: {}", core_voltage); // LED to indicate the system is running let mut led = Output::new(p.PIN_25, Level::Low); -- cgit From 1314808b3a39d856d33655504db00d799914c440 Mon Sep 17 00:00:00 2001 From: 1-rafael-1 Date: Tue, 13 May 2025 10:49:23 +0200 Subject: Changes after review: copypasted doc comment fixed and no cfg gates to panic on failing pll config in init() --- embassy-rp/src/clocks.rs | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 3975e7e79..47e71c448 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -152,11 +152,6 @@ pub enum PeriClkSrc { /// /// The voltage regulator can be configured for different output voltages. /// Higher voltages allow for higher clock frequencies but increase power consumption and heat. -/// -/// **Note**: For RP235x the maximum voltage is 1.30V, unless unlocked by setting unless the voltage limit -/// is disabled using the disable_voltage_limit field in the vreg_ctrl register. For lack of practical use at this -/// point in time, this is not implemented here. So the maximum voltage in this enum is 1.30V for now. -#[cfg(feature = "rp2040")] #[repr(u8)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -190,7 +185,7 @@ pub enum CoreVoltage { /// The voltage regulator can be configured for different output voltages. /// Higher voltages allow for higher clock frequencies but increase power consumption and heat. /// -/// **Note**: For RP235x the maximum voltage is 1.30V, unless unlocked by setting unless the voltage limit +/// **Note**: The maximum voltage is 1.30V, unless unlocked by setting unless the voltage limit /// is disabled using the disable_voltage_limit field in the vreg_ctrl register. For lack of practical use at this /// point in time, this is not implemented here. So the maximum voltage in this enum is 1.30V for now. #[cfg(feature = "_rp235x")] @@ -1092,20 +1087,14 @@ pub(crate) unsafe fn init(config: ClockConfig) { let pll_sys_freq = match config.sys_pll { Some(sys_pll_config) => match configure_pll(pac::PLL_SYS, config.hz, sys_pll_config) { Ok(freq) => freq, - #[cfg(feature = "defmt")] - Err(e) => panic!("Failed to configure PLL_SYS: {}", e), - #[cfg(not(feature = "defmt"))] - Err(_e) => panic!("Failed to configure PLL_SYS"), + Err(e) => panic!("Failed to configure PLL_SYS: {:?}", e), }, None => 0, }; let pll_usb_freq = match config.usb_pll { Some(usb_pll_config) => match configure_pll(pac::PLL_USB, config.hz, usb_pll_config) { Ok(freq) => freq, - #[cfg(feature = "defmt")] - Err(e) => panic!("Failed to configure PLL_USB: {}", e), - #[cfg(not(feature = "defmt"))] - Err(_e) => panic!("Failed to configure PLL_USB"), + Err(e) => panic!("Failed to configure PLL_USB: {:?}", e), }, None => 0, }; -- cgit From 981ef20f83ec88601818d8c55f69a1037d57b0cb Mon Sep 17 00:00:00 2001 From: 1-rafael-1 Date: Tue, 13 May 2025 10:59:11 +0200 Subject: removed one line too many --- embassy-rp/src/clocks.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 47e71c448..857877680 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -152,6 +152,7 @@ pub enum PeriClkSrc { /// /// The voltage regulator can be configured for different output voltages. /// Higher voltages allow for higher clock frequencies but increase power consumption and heat. +#[cfg(feature = "rp2040")] #[repr(u8)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -- cgit From 46e25cbc5ff62e24f86574d7ae5d872aa0c2595d Mon Sep 17 00:00:00 2001 From: Gerhard de Clercq <11624490+Gerharddc@users.noreply.github.com> Date: Tue, 13 May 2025 15:09:53 +0200 Subject: [embassy-usb-dfu] correct comment about composite devices --- embassy-usb-dfu/src/application.rs | 5 +++-- embassy-usb-dfu/src/dfu.rs | 5 +++-- examples/boot/application/stm32wb-dfu/src/main.rs | 10 ++++------ examples/boot/bootloader/stm32wb-dfu/src/main.rs | 10 ++++------ 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/embassy-usb-dfu/src/application.rs b/embassy-usb-dfu/src/application.rs index 52a7ca951..2646d100d 100644 --- a/embassy-usb-dfu/src/application.rs +++ b/embassy-usb-dfu/src/application.rs @@ -137,8 +137,9 @@ pub fn usb_dfu<'d, D: Driver<'d>, MARK: DfuMarker, RST: Reset>( // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. // Otherwise users need to do this manually using a tool like Zadig. // - // Adding them here on the function level appears to only work for compositive devices though. - // For non-composite devices they should be placed on the device level instead. + // Adding them here on the function level appears to only be needed for compositive devices. + // In addition to being on the function level, they should also be added to the device level. + // func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( "DeviceInterfaceGUIDs", diff --git a/embassy-usb-dfu/src/dfu.rs b/embassy-usb-dfu/src/dfu.rs index 83feacaf8..43a35637d 100644 --- a/embassy-usb-dfu/src/dfu.rs +++ b/embassy-usb-dfu/src/dfu.rs @@ -193,8 +193,9 @@ pub fn usb_dfu<'d, D: Driver<'d>, DFU: NorFlash, STATE: NorFlash, RST: Reset, co // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. // Otherwise users need to do this manually using a tool like Zadig. // - // Adding them here on the function level appears to only work for compositive devices though. - // For non-composite devices they should be placed on the device level instead. + // Adding them here on the function level appears to only be needed for compositive devices. + // In addition to being on the function level, they should also be added to the device level. + // func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( "DeviceInterfaceGUIDs", diff --git a/examples/boot/application/stm32wb-dfu/src/main.rs b/examples/boot/application/stm32wb-dfu/src/main.rs index 68e9bc3f6..6236dfe52 100644 --- a/examples/boot/application/stm32wb-dfu/src/main.rs +++ b/examples/boot/application/stm32wb-dfu/src/main.rs @@ -59,13 +59,11 @@ async fn main(_spawner: Spawner) { // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. // Otherwise users need to do this manually using a tool like Zadig. - builder.msos_descriptor(msos::windows_version::WIN8_1, 2); - - // In the case of non-composite devices, it seems that feature headers need to be on the device level. - // (As is implemented here) // - // For composite devices however, they should be on the function level instead. - // (This is achieved by passing a GUID to the "usb_dfu" function) + // It seems these always need to be at added at the device level for this to work and for + // composite devices they also need to be added on the function level (as shown later). + // + builder.msos_descriptor(msos::windows_version::WIN8_1, 2); builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( "DeviceInterfaceGUIDs", diff --git a/examples/boot/bootloader/stm32wb-dfu/src/main.rs b/examples/boot/bootloader/stm32wb-dfu/src/main.rs index 2cd7f859d..8cfd4daa7 100644 --- a/examples/boot/bootloader/stm32wb-dfu/src/main.rs +++ b/examples/boot/bootloader/stm32wb-dfu/src/main.rs @@ -67,13 +67,11 @@ fn main() -> ! { // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. // Otherwise users need to do this manually using a tool like Zadig. - builder.msos_descriptor(msos::windows_version::WIN8_1, 2); - - // In the case of non-composite devices, it seems that feature headers need to be on the device level. - // (As is implemented here) // - // For composite devices however, they should be on the function level instead. - // (This is achieved by passing a GUID to the "usb_dfu" function) + // It seems these always need to be at added at the device level for this to work and for + // composite devices they also need to be added on the function level (as shown later). + // + builder.msos_descriptor(msos::windows_version::WIN8_1, 2); builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( "DeviceInterfaceGUIDs", -- cgit From edcbfeb15257e93557a73b9aac3a8ee92a273e32 Mon Sep 17 00:00:00 2001 From: Marvin Gudel Date: Tue, 13 May 2025 22:36:28 +0200 Subject: Make bit-depth of I2S PIO program configurable Also the channel argument is removed, since only 2 channels are supported. --- embassy-rp/src/pio_programs/i2s.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/embassy-rp/src/pio_programs/i2s.rs b/embassy-rp/src/pio_programs/i2s.rs index b967f0160..7ceed3fa6 100644 --- a/embassy-rp/src/pio_programs/i2s.rs +++ b/embassy-rp/src/pio_programs/i2s.rs @@ -9,6 +9,10 @@ use crate::pio::{ use crate::Peri; /// This struct represents an i2s output driver program +/// +/// The sample bit-depth is set through scratch register `Y`. +/// `Y` has to be set to sample bit-depth - 2. +/// (14 = 16bit, 22 = 24bit, 30 = 32bit) pub struct PioI2sOutProgram<'d, PIO: Instance> { prg: LoadedProgram<'d, PIO>, } @@ -17,13 +21,13 @@ impl<'d, PIO: Instance> PioI2sOutProgram<'d, PIO> { /// Load the program into the given pio pub fn new(common: &mut Common<'d, PIO>) -> Self { let prg = pio::pio_asm!( - ".side_set 2", - " set x, 14 side 0b01", // side 0bWB - W = Word Clock, B = Bit Clock + ".side_set 2", // side 0bWB - W = Word Clock, B = Bit Clock + " mov x, y side 0b01", // y stores sample depth - 2 (14 = 16bit, 22 = 24bit, 30 = 32bit) "left_data:", " out pins, 1 side 0b00", " jmp x-- left_data side 0b01", " out pins 1 side 0b10", - " set x, 14 side 0b11", + " mov x, y side 0b11", "right_data:", " out pins 1 side 0b10", " jmp x-- right_data side 0b11", @@ -53,7 +57,6 @@ impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> { lr_clock_pin: Peri<'d, impl PioPin>, sample_rate: u32, bit_depth: u32, - channels: u32, program: &PioI2sOutProgram<'d, P>, ) -> Self { let data_pin = common.make_pio_pin(data_pin); @@ -64,7 +67,7 @@ impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> { let mut cfg = Config::default(); cfg.use_program(&program.prg, &[&bit_clock_pin, &left_right_clock_pin]); cfg.set_out_pins(&[&data_pin]); - let clock_frequency = sample_rate * bit_depth * channels; + let clock_frequency = sample_rate * bit_depth * 2; cfg.clock_divider = (crate::clocks::clk_sys_freq() as f64 / clock_frequency as f64 / 2.).to_fixed(); cfg.shift_out = ShiftConfig { threshold: 32, @@ -78,6 +81,11 @@ impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> { sm.set_config(&cfg); sm.set_pin_dirs(Direction::Out, &[&data_pin, &left_right_clock_pin, &bit_clock_pin]); + // Set the `y` register up to configure the sample depth + // The SM counts down to 0 and uses one clock cycle to set up the counter, + // which results in bit_depth - 2 as register value. + unsafe { sm.set_y(bit_depth - 2) }; + sm.set_enable(true); Self { dma: dma.into(), sm } -- cgit From fd9ed3924c5a7c4ef4f9bc4b8a4f934ad2bcc486 Mon Sep 17 00:00:00 2001 From: Marvin Gudel Date: Tue, 13 May 2025 22:49:35 +0200 Subject: Fix example --- examples/rp/src/bin/pio_i2s.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/rp/src/bin/pio_i2s.rs b/examples/rp/src/bin/pio_i2s.rs index 192c8f854..695a74cc3 100644 --- a/examples/rp/src/bin/pio_i2s.rs +++ b/examples/rp/src/bin/pio_i2s.rs @@ -27,7 +27,6 @@ bind_interrupts!(struct Irqs { const SAMPLE_RATE: u32 = 48_000; const BIT_DEPTH: u32 = 16; -const CHANNELS: u32 = 2; #[embassy_executor::main] async fn main(_spawner: Spawner) { @@ -50,7 +49,6 @@ async fn main(_spawner: Spawner) { left_right_clock_pin, SAMPLE_RATE, BIT_DEPTH, - CHANNELS, &program, ); -- cgit From 58383465d52b45016f88aa6af081f60d67d2b123 Mon Sep 17 00:00:00 2001 From: Marvin Gudel Date: Tue, 13 May 2025 23:30:55 +0200 Subject: Fix example for rp235x --- examples/rp235x/src/bin/pio_i2s.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/rp235x/src/bin/pio_i2s.rs b/examples/rp235x/src/bin/pio_i2s.rs index 5a4bcfcac..cfcb0221d 100644 --- a/examples/rp235x/src/bin/pio_i2s.rs +++ b/examples/rp235x/src/bin/pio_i2s.rs @@ -27,7 +27,6 @@ bind_interrupts!(struct Irqs { const SAMPLE_RATE: u32 = 48_000; const BIT_DEPTH: u32 = 16; -const CHANNELS: u32 = 2; #[embassy_executor::main] async fn main(_spawner: Spawner) { @@ -50,7 +49,6 @@ async fn main(_spawner: Spawner) { left_right_clock_pin, SAMPLE_RATE, BIT_DEPTH, - CHANNELS, &program, ); -- cgit From f41e8c45f68ca31819ea1b1eae5fbd019bf8f318 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Tue, 13 May 2025 21:55:50 -0500 Subject: mspm0: generate feature per chip + package --- ci.sh | 10 +-- embassy-mspm0/Cargo.toml | 140 +++++++++++++++++++++++++++++++++-- embassy-mspm0/README.md | 28 +++++++ embassy-mspm0/build.rs | 87 ++++++++++++++++++++-- embassy-mspm0/src/gpio.rs | 4 +- embassy-mspm0/src/int_group/g150x.rs | 51 +++++++++++++ embassy-mspm0/src/lib.rs | 17 +++-- examples/mspm0c1104/Cargo.toml | 2 +- examples/mspm0c1104/README.md | 4 +- examples/mspm0g3507/Cargo.toml | 2 +- examples/mspm0g3507/README.md | 4 +- examples/mspm0g3519/Cargo.toml | 2 +- examples/mspm0g3519/README.md | 4 +- examples/mspm0l1306/Cargo.toml | 2 +- examples/mspm0l1306/README.md | 4 +- examples/mspm0l2228/Cargo.toml | 2 +- examples/mspm0l2228/README.md | 4 +- tests/mspm0/Cargo.toml | 2 +- 18 files changed, 326 insertions(+), 43 deletions(-) create mode 100644 embassy-mspm0/README.md create mode 100644 embassy-mspm0/src/int_group/g150x.rs diff --git a/ci.sh b/ci.sh index 6e320e4d1..4e48778da 100755 --- a/ci.sh +++ b/ci.sh @@ -174,11 +174,11 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u073mb,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u083rc,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv8m.main-none-eabihf \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0c110x,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g350x,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g351x,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l130x,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l222x,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0c1104dgs20,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3507pm,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3519pz,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1306rhb,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l2228pn,defmt,time-driver-any \ --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features ''\ --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log' \ --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt' \ diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index df996ff4b..79feee0c2 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -46,14 +46,14 @@ cortex-m = "0.7.6" critical-section = "1.2.0" # mspm0-metapac = { version = "" } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-119240dd23ef5748d2a7bef219ca298d37ba604a" } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-66a55c7bf38a2201ff48c299843e741f2d537f0b" } [build-dependencies] proc-macro2 = "1.0.94" quote = "1.0.40" # mspm0-metapac = { version = "", default-features = false, features = ["metadata"] } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-119240dd23ef5748d2a7bef219ca298d37ba604a", default-features = false, features = ["metadata"] } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-66a55c7bf38a2201ff48c299843e741f2d537f0b", default-features = false, features = ["metadata"] } [features] default = ["rt"] @@ -120,14 +120,138 @@ time-driver-tima0 = ["_time-driver"] time-driver-tima1 = ["_time-driver"] #! ## Chip-selection features -#! Select your chip by specifying the model as a feature, e.g. `mspm0g350x`. +#! Select your chip by specifying the model as a feature, e.g. `mspm0g3507pm`. #! Check the `Cargo.toml` for the latest list of supported chips. #! #! **Important:** Do not forget to adapt the target chip in your toolchain, #! e.g. in `.cargo/config.toml`. -mspm0c110x = [ "mspm0-metapac/mspm0c110x" ] -mspm0g350x = [ "mspm0-metapac/mspm0g350x" ] -mspm0g351x = [ "mspm0-metapac/mspm0g351x" ] -mspm0l130x = [ "mspm0-metapac/mspm0l130x" ] -mspm0l222x = [ "mspm0-metapac/mspm0l222x" ] +mspm0c1103dgs20 = ["mspm0-metapac/mspm0c1103dgs20"] +mspm0c1103dsg = ["mspm0-metapac/mspm0c1103dsg"] +mspm0c1103dyy = ["mspm0-metapac/mspm0c1103dyy"] +mspm0c1103ruk = ["mspm0-metapac/mspm0c1103ruk"] +mspm0c1104dgs20 = ["mspm0-metapac/mspm0c1104dgs20"] +mspm0c1104dsg = ["mspm0-metapac/mspm0c1104dsg"] +mspm0c1104dyy = ["mspm0-metapac/mspm0c1104dyy"] +mspm0c1104ruk = ["mspm0-metapac/mspm0c1104ruk"] +mspm0c1104ycj = ["mspm0-metapac/mspm0c1104ycj"] +mspm0g1105dgs28 = ["mspm0-metapac/mspm0g1105dgs28"] +mspm0g1105pm = ["mspm0-metapac/mspm0g1105pm"] +mspm0g1105pt = ["mspm0-metapac/mspm0g1105pt"] +mspm0g1105rge = ["mspm0-metapac/mspm0g1105rge"] +mspm0g1105rgz = ["mspm0-metapac/mspm0g1105rgz"] +mspm0g1105rhb = ["mspm0-metapac/mspm0g1105rhb"] +mspm0g1106dgs28 = ["mspm0-metapac/mspm0g1106dgs28"] +mspm0g1106pm = ["mspm0-metapac/mspm0g1106pm"] +mspm0g1106pt = ["mspm0-metapac/mspm0g1106pt"] +mspm0g1106rge = ["mspm0-metapac/mspm0g1106rge"] +mspm0g1106rgz = ["mspm0-metapac/mspm0g1106rgz"] +mspm0g1106rhb = ["mspm0-metapac/mspm0g1106rhb"] +mspm0g1107dgs28 = ["mspm0-metapac/mspm0g1107dgs28"] +mspm0g1107pm = ["mspm0-metapac/mspm0g1107pm"] +mspm0g1107pt = ["mspm0-metapac/mspm0g1107pt"] +mspm0g1107rge = ["mspm0-metapac/mspm0g1107rge"] +mspm0g1107rgz = ["mspm0-metapac/mspm0g1107rgz"] +mspm0g1107rhb = ["mspm0-metapac/mspm0g1107rhb"] +mspm0g1107ycj = ["mspm0-metapac/mspm0g1107ycj"] +mspm0g1505pm = ["mspm0-metapac/mspm0g1505pm"] +mspm0g1505pt = ["mspm0-metapac/mspm0g1505pt"] +mspm0g1505rge = ["mspm0-metapac/mspm0g1505rge"] +mspm0g1505rgz = ["mspm0-metapac/mspm0g1505rgz"] +mspm0g1505rhb = ["mspm0-metapac/mspm0g1505rhb"] +mspm0g1506pm = ["mspm0-metapac/mspm0g1506pm"] +mspm0g1506pt = ["mspm0-metapac/mspm0g1506pt"] +mspm0g1506rge = ["mspm0-metapac/mspm0g1506rge"] +mspm0g1506rgz = ["mspm0-metapac/mspm0g1506rgz"] +mspm0g1506rhb = ["mspm0-metapac/mspm0g1506rhb"] +mspm0g1507pm = ["mspm0-metapac/mspm0g1507pm"] +mspm0g1507pt = ["mspm0-metapac/mspm0g1507pt"] +mspm0g1507rge = ["mspm0-metapac/mspm0g1507rge"] +mspm0g1507rgz = ["mspm0-metapac/mspm0g1507rgz"] +mspm0g1507rhb = ["mspm0-metapac/mspm0g1507rhb"] +mspm0g1507ycj = ["mspm0-metapac/mspm0g1507ycj"] +mspm0g1519rgz = ["mspm0-metapac/mspm0g1519rgz"] +mspm0g1519rhb = ["mspm0-metapac/mspm0g1519rhb"] +mspm0g3105dgs20 = ["mspm0-metapac/mspm0g3105dgs20"] +mspm0g3105dgs28 = ["mspm0-metapac/mspm0g3105dgs28"] +mspm0g3105rhb = ["mspm0-metapac/mspm0g3105rhb"] +mspm0g3106dgs20 = ["mspm0-metapac/mspm0g3106dgs20"] +mspm0g3106dgs28 = ["mspm0-metapac/mspm0g3106dgs28"] +mspm0g3106rhb = ["mspm0-metapac/mspm0g3106rhb"] +mspm0g3107dgs20 = ["mspm0-metapac/mspm0g3107dgs20"] +mspm0g3107dgs28 = ["mspm0-metapac/mspm0g3107dgs28"] +mspm0g3107rhb = ["mspm0-metapac/mspm0g3107rhb"] +mspm0g3505dgs28 = ["mspm0-metapac/mspm0g3505dgs28"] +mspm0g3505pm = ["mspm0-metapac/mspm0g3505pm"] +mspm0g3505pt = ["mspm0-metapac/mspm0g3505pt"] +mspm0g3505rgz = ["mspm0-metapac/mspm0g3505rgz"] +mspm0g3505rhb = ["mspm0-metapac/mspm0g3505rhb"] +mspm0g3506dgs28 = ["mspm0-metapac/mspm0g3506dgs28"] +mspm0g3506pm = ["mspm0-metapac/mspm0g3506pm"] +mspm0g3506pt = ["mspm0-metapac/mspm0g3506pt"] +mspm0g3506rgz = ["mspm0-metapac/mspm0g3506rgz"] +mspm0g3506rhb = ["mspm0-metapac/mspm0g3506rhb"] +mspm0g3507dgs28 = ["mspm0-metapac/mspm0g3507dgs28"] +mspm0g3507pm = ["mspm0-metapac/mspm0g3507pm"] +mspm0g3507pt = ["mspm0-metapac/mspm0g3507pt"] +mspm0g3507rgz = ["mspm0-metapac/mspm0g3507rgz"] +mspm0g3507rhb = ["mspm0-metapac/mspm0g3507rhb"] +mspm0g3519pm = ["mspm0-metapac/mspm0g3519pm"] +mspm0g3519pn = ["mspm0-metapac/mspm0g3519pn"] +mspm0g3519pz = ["mspm0-metapac/mspm0g3519pz"] +mspm0g3519rgz = ["mspm0-metapac/mspm0g3519rgz"] +mspm0g3519rhb = ["mspm0-metapac/mspm0g3519rhb"] +mspm0l1105dgs20 = ["mspm0-metapac/mspm0l1105dgs20"] +mspm0l1105dgs28 = ["mspm0-metapac/mspm0l1105dgs28"] +mspm0l1105dyy = ["mspm0-metapac/mspm0l1105dyy"] +mspm0l1105rge = ["mspm0-metapac/mspm0l1105rge"] +mspm0l1105rtr = ["mspm0-metapac/mspm0l1105rtr"] +mspm0l1106dgs20 = ["mspm0-metapac/mspm0l1106dgs20"] +mspm0l1106dgs28 = ["mspm0-metapac/mspm0l1106dgs28"] +mspm0l1106dyy = ["mspm0-metapac/mspm0l1106dyy"] +mspm0l1106rge = ["mspm0-metapac/mspm0l1106rge"] +mspm0l1106rhb = ["mspm0-metapac/mspm0l1106rhb"] +mspm0l1106rtr = ["mspm0-metapac/mspm0l1106rtr"] +mspm0l1227pm = ["mspm0-metapac/mspm0l1227pm"] +mspm0l1227pn = ["mspm0-metapac/mspm0l1227pn"] +mspm0l1227pt = ["mspm0-metapac/mspm0l1227pt"] +mspm0l1227rge = ["mspm0-metapac/mspm0l1227rge"] +mspm0l1227rgz = ["mspm0-metapac/mspm0l1227rgz"] +mspm0l1227rhb = ["mspm0-metapac/mspm0l1227rhb"] +mspm0l1228pm = ["mspm0-metapac/mspm0l1228pm"] +mspm0l1228pn = ["mspm0-metapac/mspm0l1228pn"] +mspm0l1228pt = ["mspm0-metapac/mspm0l1228pt"] +mspm0l1228rge = ["mspm0-metapac/mspm0l1228rge"] +mspm0l1228rgz = ["mspm0-metapac/mspm0l1228rgz"] +mspm0l1228rhb = ["mspm0-metapac/mspm0l1228rhb"] +mspm0l1303rge = ["mspm0-metapac/mspm0l1303rge"] +mspm0l1304dgs20 = ["mspm0-metapac/mspm0l1304dgs20"] +mspm0l1304dgs28 = ["mspm0-metapac/mspm0l1304dgs28"] +mspm0l1304dyy = ["mspm0-metapac/mspm0l1304dyy"] +mspm0l1304rge = ["mspm0-metapac/mspm0l1304rge"] +mspm0l1304rhb = ["mspm0-metapac/mspm0l1304rhb"] +mspm0l1304rtr = ["mspm0-metapac/mspm0l1304rtr"] +mspm0l1305dgs20 = ["mspm0-metapac/mspm0l1305dgs20"] +mspm0l1305dgs28 = ["mspm0-metapac/mspm0l1305dgs28"] +mspm0l1305dyy = ["mspm0-metapac/mspm0l1305dyy"] +mspm0l1305rge = ["mspm0-metapac/mspm0l1305rge"] +mspm0l1305rtr = ["mspm0-metapac/mspm0l1305rtr"] +mspm0l1306dgs20 = ["mspm0-metapac/mspm0l1306dgs20"] +mspm0l1306dgs28 = ["mspm0-metapac/mspm0l1306dgs28"] +mspm0l1306dyy = ["mspm0-metapac/mspm0l1306dyy"] +mspm0l1306rge = ["mspm0-metapac/mspm0l1306rge"] +mspm0l1306rhb = ["mspm0-metapac/mspm0l1306rhb"] +mspm0l1343dgs20 = ["mspm0-metapac/mspm0l1343dgs20"] +mspm0l1344dgs20 = ["mspm0-metapac/mspm0l1344dgs20"] +mspm0l1345dgs28 = ["mspm0-metapac/mspm0l1345dgs28"] +mspm0l1346dgs28 = ["mspm0-metapac/mspm0l1346dgs28"] +mspm0l2227pm = ["mspm0-metapac/mspm0l2227pm"] +mspm0l2227pn = ["mspm0-metapac/mspm0l2227pn"] +mspm0l2227pt = ["mspm0-metapac/mspm0l2227pt"] +mspm0l2227rgz = ["mspm0-metapac/mspm0l2227rgz"] +mspm0l2228pm = ["mspm0-metapac/mspm0l2228pm"] +mspm0l2228pn = ["mspm0-metapac/mspm0l2228pn"] +mspm0l2228pt = ["mspm0-metapac/mspm0l2228pt"] +mspm0l2228rgz = ["mspm0-metapac/mspm0l2228rgz"] +msps003f3pw20 = ["mspm0-metapac/msps003f3pw20"] +msps003f4pw20 = ["mspm0-metapac/msps003f4pw20"] diff --git a/embassy-mspm0/README.md b/embassy-mspm0/README.md new file mode 100644 index 000000000..b2b8934aa --- /dev/null +++ b/embassy-mspm0/README.md @@ -0,0 +1,28 @@ +# Embassy MSPM0 HAL + +The embassy-mspm0 HAL aims to provide a safe, idiomatic hardware abstraction layer for all MSPM0 and MSPS003 chips. + +* [Documentation](https://docs.embassy.dev/embassy-mspm0/) (**Important:** use docs.embassy.dev rather than docs.rs to see the specific docs for the chip you’re using!) +* [Source](https://github.com/embassy-rs/embassy/tree/main/embassy-mspm0) +* [Examples](https://github.com/embassy-rs/embassy/tree/main/examples) + +## Embedded-hal + +The `embassy-mspm0` HAL implements the traits from [embedded-hal](https://crates.io/crates/embedded-hal) (1.0) and [embedded-hal-async](https://crates.io/crates/embedded-hal-async), as well as [embedded-io](https://crates.io/crates/embedded-io) and [embedded-io-async](https://crates.io/crates/embedded-io-async). + +## A note on feature flag names + +Feature flag names for chips do not include temperature rating or distribution format. + +Usually chapter 10 of your device's datasheet will explain the device nomenclature and how to decode it. Feature names in embassy-mspm0 only use the following from device nomenclature: +- MCU platform +- Product family +- Device subfamily +- Flash memory +- Package type + +This means for a part such as `MSPM0G3507SPMR`, the feature name is `mspm0g3507pm`. This also means that `MSPM0G3507QPMRQ1` uses the feature `mspm0g3507pm`, since the Q1 parts are just qualified variants of the base G3507 with a PM (QFP-64) package. + +## Interoperability + +This crate can run on any executor. diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs index 08209df2a..409ce0621 100644 --- a/embassy-mspm0/build.rs +++ b/embassy-mspm0/build.rs @@ -7,7 +7,7 @@ use std::sync::LazyLock; use std::{env, fs}; use common::CfgSet; -use mspm0_metapac::metadata::METADATA; +use mspm0_metapac::metadata::{ALL_CHIPS, METADATA}; use proc_macro2::{Ident, Literal, Span, TokenStream}; use quote::{format_ident, quote}; @@ -24,6 +24,27 @@ fn generate_code() { cfgs.declare_all(&["gpio_pb", "gpio_pc", "int_group1"]); + let chip_name = match env::vars() + .map(|(a, _)| a) + .filter(|x| x.starts_with("CARGO_FEATURE_MSPM0") || x.starts_with("CARGO_FEATURE_MSPS")) + .get_one() + { + Ok(x) => x, + Err(GetOneError::None) => panic!("No mspm0xx/mspsxx Cargo feature enabled"), + Err(GetOneError::Multiple) => panic!("Multiple mspm0xx/mspsxx Cargo features enabled"), + } + .strip_prefix("CARGO_FEATURE_") + .unwrap() + .to_ascii_lowercase() + .replace('_', "-"); + + eprintln!("chip: {chip_name}"); + + cfgs.enable_all(&get_chip_cfgs(&chip_name)); + for chip in ALL_CHIPS { + cfgs.declare_all(&get_chip_cfgs(&chip)); + } + let mut singletons = get_singletons(&mut cfgs); time_driver(&mut singletons, &mut cfgs); @@ -44,6 +65,60 @@ fn generate_code() { rustfmt(&out_file); } +fn get_chip_cfgs(chip_name: &str) -> Vec { + let mut cfgs = Vec::new(); + + // GPIO on C110x is special as it does not belong to an interrupt group. + if chip_name.starts_with("mspm0c110") || chip_name.starts_with("msps003f") { + cfgs.push("mspm0c110x".to_string()); + } + + // Family ranges (temporary until int groups are generated) + // + // TODO: Remove this once int group stuff is generated. + if chip_name.starts_with("mspm0g110") { + cfgs.push("mspm0g110x".to_string()); + } + + if chip_name.starts_with("mspm0g150") { + cfgs.push("mspm0g150x".to_string()); + } + + if chip_name.starts_with("mspm0g310") { + cfgs.push("mspm0g310x".to_string()); + } + + if chip_name.starts_with("mspm0g350") { + cfgs.push("mspm0g350x".to_string()); + } + + if chip_name.starts_with("mspm0g351") { + cfgs.push("mspm0g351x".to_string()); + } + + if chip_name.starts_with("mspm0l110") { + cfgs.push("mspm0l110x".to_string()); + } + + if chip_name.starts_with("mspm0l122") { + cfgs.push("mspm0l122x".to_string()); + } + + if chip_name.starts_with("mspm0l130") { + cfgs.push("mspm0l130x".to_string()); + } + + if chip_name.starts_with("mspm0l134") { + cfgs.push("mspm0l134x".to_string()); + } + + if chip_name.starts_with("mspm0l222") { + cfgs.push("mspm0l222x".to_string()); + } + + cfgs +} + #[derive(Debug, Clone)] struct Singleton { name: String, @@ -146,7 +221,7 @@ fn make_valid_identifier(s: &str) -> Singleton { } fn generate_pincm_mapping() -> TokenStream { - let pincms = METADATA.pincm_mappings.iter().map(|mapping| { + let pincms = METADATA.pins.iter().map(|mapping| { let port_letter = mapping.pin.strip_prefix("P").unwrap(); let port_base = (port_letter.chars().next().unwrap() as u8 - b'A') * 32; // This assumes all ports are single letter length. @@ -174,11 +249,11 @@ fn generate_pincm_mapping() -> TokenStream { } fn generate_pin() -> TokenStream { - let pin_impls = METADATA.pincm_mappings.iter().map(|pincm_mapping| { - let name = Ident::new(&pincm_mapping.pin, Span::call_site()); - let port_letter = pincm_mapping.pin.strip_prefix("P").unwrap(); + let pin_impls = METADATA.pins.iter().map(|pin| { + let name = Ident::new(&pin.pin, Span::call_site()); + let port_letter = pin.pin.strip_prefix("P").unwrap(); let port_letter = port_letter.chars().next().unwrap(); - let pin_number = Literal::u8_unsuffixed(pincm_mapping.pin[2..].parse::().unwrap()); + let pin_number = Literal::u8_unsuffixed(pin.pin[2..].parse::().unwrap()); let port = Ident::new(&format!("Port{}", port_letter), Span::call_site()); diff --git a/embassy-mspm0/src/gpio.rs b/embassy-mspm0/src/gpio.rs index 3f895d962..3c824b0e6 100644 --- a/embassy-mspm0/src/gpio.rs +++ b/embassy-mspm0/src/gpio.rs @@ -10,7 +10,7 @@ use embassy_sync::waitqueue::AtomicWaker; use crate::pac::gpio::vals::*; use crate::pac::gpio::{self}; -#[cfg(all(feature = "rt", feature = "mspm0c110x"))] +#[cfg(all(feature = "rt", mspm0c110x))] use crate::pac::interrupt; use crate::pac::{self}; @@ -1120,7 +1120,7 @@ impl Iterator for BitIter { } // C110x has a dedicated interrupt just for GPIOA, as it does not have a GROUP1 interrupt. -#[cfg(all(feature = "rt", feature = "mspm0c110x"))] +#[cfg(all(feature = "rt", mspm0c110x))] #[interrupt] fn GPIOA() { gpioa_interrupt(); diff --git a/embassy-mspm0/src/int_group/g150x.rs b/embassy-mspm0/src/int_group/g150x.rs new file mode 100644 index 000000000..706ba2078 --- /dev/null +++ b/embassy-mspm0/src/int_group/g150x.rs @@ -0,0 +1,51 @@ +use crate::pac; +use crate::pac::interrupt; + +#[cfg(feature = "rt")] +#[interrupt] +fn GROUP0() { + use mspm0_metapac::Group0; + + let group = pac::CPUSS.int_group(0); + + // Must subtract by 1 since NO_INTR is value 0 + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = pac::Group0::try_from(iidx as u8) else { + debug!("Invalid IIDX for group 0: {}", iidx); + return; + }; + + match group { + Group0::WWDT0 => todo!("implement WWDT0"), + Group0::WWDT1 => todo!("implement WWDT1"), + Group0::DEBUGSS => todo!("implement DEBUGSS"), + Group0::FLASHCTL => todo!("implement FLASHCTL"), + Group0::SYSCTL => todo!("implement SYSCTL"), + } +} + +#[cfg(feature = "rt")] +#[interrupt] +fn GROUP1() { + use mspm0_metapac::Group1; + + let group = pac::CPUSS.int_group(1); + + // Must subtract by 1 since NO_INTR is value 0 + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = pac::Group1::try_from(iidx as u8) else { + debug!("Invalid IIDX for group 1: {}", iidx); + return; + }; + + match group { + Group1::GPIOA => crate::gpio::gpioa_interrupt(), + Group1::GPIOB => crate::gpio::gpiob_interrupt(), + Group1::COMP0 => todo!("implement COMP0"), + Group1::COMP1 => todo!("implement COMP1"), + Group1::COMP2 => todo!("implement COMP2"), + Group1::TRNG => todo!("implement TRNG"), + } +} diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index e8f5971d5..df2d83cc0 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -1,6 +1,11 @@ #![no_std] // Doc feature labels can be tested locally by running RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc #![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg_hide), doc(cfg_hide(doc, docsrs)))] +#![cfg_attr( + docsrs, + doc = "\n\n" +)] +#![doc = include_str!("../README.md")] // This mod MUST go first, so that the others see its macros. pub(crate) mod fmt; @@ -35,11 +40,11 @@ pub mod mode { mod time_driver; // Interrupt group handlers. -#[cfg_attr(feature = "mspm0c110x", path = "int_group/c110x.rs")] -#[cfg_attr(feature = "mspm0g350x", path = "int_group/g350x.rs")] -#[cfg_attr(feature = "mspm0g351x", path = "int_group/g351x.rs")] -#[cfg_attr(feature = "mspm0l130x", path = "int_group/l130x.rs")] -#[cfg_attr(feature = "mspm0l222x", path = "int_group/l222x.rs")] +#[cfg_attr(mspm0c110x, path = "int_group/c110x.rs")] +#[cfg_attr(mspm0g350x, path = "int_group/g350x.rs")] +#[cfg_attr(mspm0g351x, path = "int_group/g351x.rs")] +#[cfg_attr(mspm0l130x, path = "int_group/l130x.rs")] +#[cfg_attr(mspm0l222x, path = "int_group/l222x.rs")] mod int_group; pub(crate) mod _generated { @@ -109,7 +114,7 @@ pub fn init(_config: Config) -> Peripherals { _generated::enable_group_interrupts(cs); - #[cfg(feature = "mspm0c110x")] + #[cfg(mspm0c110x)] unsafe { use crate::_generated::interrupt::typelevel::Interrupt; crate::interrupt::typelevel::GPIOA::enable(); diff --git a/examples/mspm0c1104/Cargo.toml b/examples/mspm0c1104/Cargo.toml index ba64a578d..67b0372ab 100644 --- a/examples/mspm0c1104/Cargo.toml +++ b/examples/mspm0c1104/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0c110x", "defmt", "rt", "time-driver-any"] } +embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0c1104dgs20", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } diff --git a/examples/mspm0c1104/README.md b/examples/mspm0c1104/README.md index e5c9f961d..86b6c3918 100644 --- a/examples/mspm0c1104/README.md +++ b/examples/mspm0c1104/README.md @@ -1,4 +1,4 @@ -# Examples for MSPM0C110x family +# Examples for MSPM0C1104 Run individual examples with ``` @@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0C1104](https://www.t You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for C1104 it should be `probe-rs run --chip MSPM0C1104`. (use `probe-rs chip list` to find your chip) -* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for C1104 it should be `mspm0c1104`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. +* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0C1104 it should be `mspm0c1104dgs20`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic diff --git a/examples/mspm0g3507/Cargo.toml b/examples/mspm0g3507/Cargo.toml index f6fed091d..49baeabdf 100644 --- a/examples/mspm0g3507/Cargo.toml +++ b/examples/mspm0g3507/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g350x", "defmt", "rt", "time-driver-any"] } +embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3507pm", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } diff --git a/examples/mspm0g3507/README.md b/examples/mspm0g3507/README.md index 5e8a83212..be91dc5a0 100644 --- a/examples/mspm0g3507/README.md +++ b/examples/mspm0g3507/README.md @@ -1,4 +1,4 @@ -# Examples for MSPM0C350x family +# Examples for MSPM0M3507 Run individual examples with ``` @@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0G3507](https://www.t You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for G3507 it should be `probe-rs run --chip MSPM0G3507`. (use `probe-rs chip list` to find your chip) -* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for G3507 it should be `mspm0g3507`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. +* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0G3507 it should be `mspm0g3507pm`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic diff --git a/examples/mspm0g3519/Cargo.toml b/examples/mspm0g3519/Cargo.toml index 1662e1f8d..dfe365daf 100644 --- a/examples/mspm0g3519/Cargo.toml +++ b/examples/mspm0g3519/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g351x", "defmt", "rt", "time-driver-any"] } +embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3519pz", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } diff --git a/examples/mspm0g3519/README.md b/examples/mspm0g3519/README.md index 5034b1913..c392c9e25 100644 --- a/examples/mspm0g3519/README.md +++ b/examples/mspm0g3519/README.md @@ -1,4 +1,4 @@ -# Examples for MSPM0G351x family +# Examples for MSPM0G3519 Run individual examples with ``` @@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0G3519](https://www.t You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for G3519 it should be `probe-rs run --chip MSPM0G3519`. (use `probe-rs chip list` to find your chip) -* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for G3519 it should be `mspm0g3519`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. +* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0G3519 it should be `mspm0g3519pz`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic diff --git a/examples/mspm0l1306/Cargo.toml b/examples/mspm0l1306/Cargo.toml index 609b3f205..b0c370bb5 100644 --- a/examples/mspm0l1306/Cargo.toml +++ b/examples/mspm0l1306/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l130x", "defmt", "rt", "time-driver-any"] } +embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l1306rhb", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } diff --git a/examples/mspm0l1306/README.md b/examples/mspm0l1306/README.md index 5a55d721e..4d698e0fa 100644 --- a/examples/mspm0l1306/README.md +++ b/examples/mspm0l1306/README.md @@ -1,4 +1,4 @@ -# Examples for MSPM0L130x family +# Examples for MSPM0L1306 Run individual examples with ``` @@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0L1306](https://www.t You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L1306 it should be `probe-rs run --chip MSPM0L1306`. (use `probe-rs chip list` to find your chip) -* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for L1306 it should be `mspm0l1306`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. +* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0L1306 it should be `mspm0l1306rhb`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic diff --git a/examples/mspm0l2228/Cargo.toml b/examples/mspm0l2228/Cargo.toml index bbca011a1..d55b9e6a8 100644 --- a/examples/mspm0l2228/Cargo.toml +++ b/examples/mspm0l2228/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l222x", "defmt", "rt", "time-driver-any"] } +embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l2228pn", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } diff --git a/examples/mspm0l2228/README.md b/examples/mspm0l2228/README.md index c73fa13b6..191022258 100644 --- a/examples/mspm0l2228/README.md +++ b/examples/mspm0l2228/README.md @@ -1,4 +1,4 @@ -# Examples for MSPM0L222x family +# Examples for MSPM0L2228 Run individual examples with ``` @@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0L2228](https://www.t You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. * [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L2228 it should be `probe-rs run --chip MSPM0L2228`. (use `probe-rs chip list` to find your chip) -* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for L2228 it should be `mspm0l2228`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. +* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for LP-MSPM0L2228 it should be `mspm0l2228pn`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. * [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. * [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic diff --git a/tests/mspm0/Cargo.toml b/tests/mspm0/Cargo.toml index 0566807d7..d76aaff73 100644 --- a/tests/mspm0/Cargo.toml +++ b/tests/mspm0/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [features] -mspm0g3507 = [ "embassy-mspm0/mspm0g350x" ] +mspm0g3507 = [ "embassy-mspm0/mspm0g3507pm" ] [dependencies] teleprobe-meta = "1.1" -- cgit From 8bb25a551abbf3677a440d6f73401b88cf4de57f Mon Sep 17 00:00:00 2001 From: i509VCB Date: Tue, 13 May 2025 22:53:16 -0500 Subject: ci: build std examples on aarch64-unknown-linux-gnu --- ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci.sh b/ci.sh index 6e320e4d1..f2d461c1a 100755 --- a/ci.sh +++ b/ci.sh @@ -19,7 +19,7 @@ fi TARGET=$(rustc -vV | sed -n 's|host: ||p') BUILD_EXTRA="" -if [ $TARGET = "x86_64-unknown-linux-gnu" ]; then +if [ $TARGET = "x86_64-unknown-linux-gnu" ] || [ $TARGET = "aarch64-unknown-linux-gnu" ]; then BUILD_EXTRA="--- build --release --manifest-path examples/std/Cargo.toml --target $TARGET --artifact-dir out/examples/std" fi -- cgit From d4d10bad0bc2f2bbfbad116fb07e27eea4ac5af2 Mon Sep 17 00:00:00 2001 From: Gerhard de Clercq <11624490+Gerharddc@users.noreply.github.com> Date: Wed, 14 May 2025 09:52:46 +0200 Subject: [embassy-usb-dfu] accept closure to customise DFU function This provides a more generic interface for users to customise the DFU function instead of restricting customisation to DFU headers. --- embassy-usb-dfu/src/application.rs | 21 ++++++--------------- embassy-usb-dfu/src/dfu.rs | 21 ++++++--------------- examples/boot/application/stm32wb-dfu/src/main.rs | 14 +++++++++----- examples/boot/bootloader/stm32wb-dfu/src/main.rs | 14 +++++++++----- 4 files changed, 30 insertions(+), 40 deletions(-) diff --git a/embassy-usb-dfu/src/application.rs b/embassy-usb-dfu/src/application.rs index 2646d100d..4b7b72073 100644 --- a/embassy-usb-dfu/src/application.rs +++ b/embassy-usb-dfu/src/application.rs @@ -2,7 +2,7 @@ use embassy_boot::BlockingFirmwareState; use embassy_time::{Duration, Instant}; use embassy_usb::control::{InResponse, OutResponse, Recipient, RequestType}; use embassy_usb::driver::Driver; -use embassy_usb::{msos, Builder, Handler}; +use embassy_usb::{Builder, FunctionBuilder, Handler}; use embedded_storage::nor_flash::NorFlash; use crate::consts::{ @@ -130,22 +130,13 @@ pub fn usb_dfu<'d, D: Driver<'d>, MARK: DfuMarker, RST: Reset>( builder: &mut Builder<'d, D>, handler: &'d mut Control, timeout: Duration, - winusb_guids: Option<&'d [&str]>, + func_modifier: impl Fn(&mut FunctionBuilder<'_, 'd, D>), ) { let mut func = builder.function(0x00, 0x00, 0x00); - if let Some(winusb_guids) = winusb_guids { - // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. - // Otherwise users need to do this manually using a tool like Zadig. - // - // Adding them here on the function level appears to only be needed for compositive devices. - // In addition to being on the function level, they should also be added to the device level. - // - func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); - func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( - "DeviceInterfaceGUIDs", - msos::PropertyData::RegMultiSz(winusb_guids), - )); - } + + // Here we give users the opportunity to add their own function level MSOS headers for instance. + // This is useful when DFU functionality is part of a composite USB device. + func_modifier(&mut func); let mut iface = func.interface(); let mut alt = iface.alt_setting(USB_CLASS_APPN_SPEC, APPN_SPEC_SUBCLASS_DFU, DFU_PROTOCOL_RT, None); diff --git a/embassy-usb-dfu/src/dfu.rs b/embassy-usb-dfu/src/dfu.rs index 43a35637d..0f39d906b 100644 --- a/embassy-usb-dfu/src/dfu.rs +++ b/embassy-usb-dfu/src/dfu.rs @@ -1,7 +1,7 @@ use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterError}; use embassy_usb::control::{InResponse, OutResponse, Recipient, RequestType}; use embassy_usb::driver::Driver; -use embassy_usb::{msos, Builder, Handler}; +use embassy_usb::{Builder, FunctionBuilder, Handler}; use embedded_storage::nor_flash::{NorFlash, NorFlashErrorKind}; use crate::consts::{ @@ -186,22 +186,13 @@ impl<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize> Ha pub fn usb_dfu<'d, D: Driver<'d>, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize>( builder: &mut Builder<'d, D>, handler: &'d mut Control<'d, DFU, STATE, RST, BLOCK_SIZE>, - winusb_guids: Option<&'d [&str]>, + func_modifier: impl Fn(&mut FunctionBuilder<'_, 'd, D>), ) { let mut func = builder.function(USB_CLASS_APPN_SPEC, APPN_SPEC_SUBCLASS_DFU, DFU_PROTOCOL_DFU); - if let Some(winusb_guids) = winusb_guids { - // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. - // Otherwise users need to do this manually using a tool like Zadig. - // - // Adding them here on the function level appears to only be needed for compositive devices. - // In addition to being on the function level, they should also be added to the device level. - // - func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); - func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( - "DeviceInterfaceGUIDs", - msos::PropertyData::RegMultiSz(winusb_guids), - )); - } + + // Here we give users the opportunity to add their own function level MSOS headers for instance. + // This is useful when DFU functionality is part of a composite USB device. + func_modifier(&mut func); let mut iface = func.interface(); let mut alt = iface.alt_setting(USB_CLASS_APPN_SPEC, APPN_SPEC_SUBCLASS_DFU, DFU_PROTOCOL_DFU, None); diff --git a/examples/boot/application/stm32wb-dfu/src/main.rs b/examples/boot/application/stm32wb-dfu/src/main.rs index 6236dfe52..4d6556597 100644 --- a/examples/boot/application/stm32wb-dfu/src/main.rs +++ b/examples/boot/application/stm32wb-dfu/src/main.rs @@ -70,11 +70,15 @@ async fn main(_spawner: Spawner) { msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), )); - // For non-composite devices: - usb_dfu(&mut builder, &mut state, Duration::from_millis(2500), None); - - // Or for composite devices: - // usb_dfu(&mut builder, &mut state, Duration::from_millis(2500), Some(DEVICE_INTERFACE_GUIDS)); + usb_dfu(&mut builder, &mut state, Duration::from_millis(2500), |func| { + // You likely don't have to add these function level headers if your USB device is not composite + // (i.e. if your device does not expose another interface in addition to DFU) + func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); + func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( + "DeviceInterfaceGUIDs", + msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), + )); + }); let mut dev = builder.build(); dev.run().await diff --git a/examples/boot/bootloader/stm32wb-dfu/src/main.rs b/examples/boot/bootloader/stm32wb-dfu/src/main.rs index 8cfd4daa7..fea6f4a0d 100644 --- a/examples/boot/bootloader/stm32wb-dfu/src/main.rs +++ b/examples/boot/bootloader/stm32wb-dfu/src/main.rs @@ -78,11 +78,15 @@ fn main() -> ! { msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), )); - // For non-composite devices: - usb_dfu::<_, _, _, _, 4096>(&mut builder, &mut state, None); - - // Or for composite devices: - // usb_dfu::<_, _, _, _, 4096>(&mut builder, &mut state, Some(DEVICE_INTERFACE_GUIDS)); + usb_dfu::<_, _, _, _, 4096>(&mut builder, &mut state, |func| { + // You likely don't have to add these function level headers if your USB device is not composite + // (i.e. if your device does not expose another interface in addition to DFU) + func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); + func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( + "DeviceInterfaceGUIDs", + msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), + )); + }); let mut dev = builder.build(); embassy_futures::block_on(dev.run()); -- cgit From 2bbc2045a4a6cb1e489295d258ac0cdb6338f90a Mon Sep 17 00:00:00 2001 From: Gerhard de Clercq <11624490+Gerharddc@users.noreply.github.com> Date: Wed, 14 May 2025 09:56:28 +0200 Subject: [usb-dfu examples] Alert users to customise their WinUSB GUIDs --- examples/boot/application/stm32wb-dfu/src/main.rs | 4 +++- examples/boot/bootloader/stm32wb-dfu/src/main.rs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/boot/application/stm32wb-dfu/src/main.rs b/examples/boot/application/stm32wb-dfu/src/main.rs index 4d6556597..5e7b71f5a 100644 --- a/examples/boot/application/stm32wb-dfu/src/main.rs +++ b/examples/boot/application/stm32wb-dfu/src/main.rs @@ -22,7 +22,9 @@ bind_interrupts!(struct Irqs { USB_LP => usb::InterruptHandler; }); -// This is a randomly generated GUID to allow clients on Windows to find our device +// This is a randomly generated GUID to allow clients on Windows to find your device. +// +// N.B. update to a custom GUID for your own device! const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; #[embassy_executor::main] diff --git a/examples/boot/bootloader/stm32wb-dfu/src/main.rs b/examples/boot/bootloader/stm32wb-dfu/src/main.rs index fea6f4a0d..0b643079f 100644 --- a/examples/boot/bootloader/stm32wb-dfu/src/main.rs +++ b/examples/boot/bootloader/stm32wb-dfu/src/main.rs @@ -20,7 +20,9 @@ bind_interrupts!(struct Irqs { USB_LP => usb::InterruptHandler; }); -// This is a randomly generated GUID to allow clients on Windows to find our device +// This is a randomly generated GUID to allow clients on Windows to find your device. +// +// N.B. update to a custom GUID for your own device! const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; #[entry] -- cgit From be20c708fa7b099507c2027a8c5666b54f1e5723 Mon Sep 17 00:00:00 2001 From: jake-taf <149392739+jake-taf@users.noreply.github.com> Date: Wed, 14 May 2025 09:45:20 -0400 Subject: Interrupt Doc Comments Support adding doc comments to interrupts --- embassy-stm32/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 3e84d3386..f8d09413d 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -173,8 +173,9 @@ pub use crate::_generated::interrupt; // developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`. #[macro_export] macro_rules! bind_interrupts { - ($vis:vis struct $name:ident { + ($(#[$outer:meta])* $vis:vis struct $name:ident { $( + $(#[$inner:meta])* $(#[cfg($cond_irq:meta)])? $irq:ident => $( $(#[cfg($cond_handler:meta)])? @@ -183,12 +184,14 @@ macro_rules! bind_interrupts { )* }) => { #[derive(Copy, Clone)] + $(#[$outer])* $vis struct $name; $( #[allow(non_snake_case)] #[no_mangle] $(#[cfg($cond_irq)])? + $(#[$inner])* unsafe extern "C" fn $irq() { $( $(#[cfg($cond_handler)])? -- cgit From a71642ca01190d1a8f8bd652bd41d8a9539fe2ee Mon Sep 17 00:00:00 2001 From: Jakob Date: Wed, 14 May 2025 18:57:00 +0200 Subject: Fix compile error in adc_read doc comment code --- embassy-stm32/src/adc/g4.rs | 4 ++-- embassy-stm32/src/adc/v3.rs | 4 ++-- embassy-stm32/src/adc/v4.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs index 8ed102c1b..1fce3085a 100644 --- a/embassy-stm32/src/adc/g4.rs +++ b/embassy-stm32/src/adc/g4.rs @@ -371,8 +371,8 @@ impl<'d, T: Instance> Adc<'d, T> { /// let mut adc_pin1 = p.PA1.into(); /// let mut measurements = [0u16; 2]; /// - /// adc.read_async( - /// p.DMA1_CH2, + /// adc.read( + /// p.DMA1_CH2.reborrow(), /// [ /// (&mut *adc_pin0, SampleTime::CYCLES160_5), /// (&mut *adc_pin1, SampleTime::CYCLES160_5), diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index 1c5ad16e9..313244e19 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -272,8 +272,8 @@ impl<'d, T: Instance> Adc<'d, T> { /// let mut adc_pin1 = p.PA1.degrade_adc(); /// let mut measurements = [0u16; 2]; /// - /// adc.read_async( - /// p.DMA1_CH2, + /// adc.read( + /// p.DMA1_CH2.reborrow(), /// [ /// (&mut *adc_pin0, SampleTime::CYCLES160_5), /// (&mut *adc_pin1, SampleTime::CYCLES160_5), diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index e455b275c..39e0d51b9 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs @@ -347,8 +347,8 @@ impl<'d, T: Instance> Adc<'d, T> { /// let mut adc_pin2 = p.PA2.into(); /// let mut measurements = [0u16; 2]; /// - /// adc.read_async( - /// p.DMA2_CH0, + /// adc.read( + /// p.DMA2_CH0.reborrow(), /// [ /// (&mut *adc_pin0, SampleTime::CYCLES112), /// (&mut *adc_pin2, SampleTime::CYCLES112), -- cgit From ad091324a7da4d6b4326f6d1f8dc29e7a9844be0 Mon Sep 17 00:00:00 2001 From: Matthew Tran <0e4ef622@gmail.com> Date: Wed, 14 May 2025 22:26:55 -0500 Subject: nrf: _3v3 -> _3V3 --- embassy-nrf/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 5bce65a98..7d86e1218 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -339,7 +339,7 @@ pub mod config { /// 3.0 V _3V0 = 4, /// 3.3 V - _3v3 = 5, + _3V3 = 5, //ERASED = 7, means 1.8V } @@ -371,7 +371,7 @@ pub mod config { /// 3.0 V _3V0 = 4, /// 3.3 V - _3v3 = 5, + _3V3 = 5, //ERASED = 7, means 1.8V } -- cgit From d64ae225b30bc3a0f7a9b1277188b6e60fc97484 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 10 Apr 2025 10:39:54 -0700 Subject: Add UART and DMA drivers Both blocking and async versions are supported. Add separate examples for each mode. --- docs/pages/imxrt.adoc | 2 + embassy-imxrt/src/dma.rs | 418 +++++++++++ embassy-imxrt/src/flexcomm/mod.rs | 252 +++++++ embassy-imxrt/src/flexcomm/uart.rs | 1230 ++++++++++++++++++++++++++++++++ embassy-imxrt/src/gpio.rs | 20 +- embassy-imxrt/src/lib.rs | 26 +- examples/mimxrt6/src/bin/uart-async.rs | 87 +++ examples/mimxrt6/src/bin/uart.rs | 55 ++ 8 files changed, 2069 insertions(+), 21 deletions(-) create mode 100644 embassy-imxrt/src/dma.rs create mode 100644 embassy-imxrt/src/flexcomm/mod.rs create mode 100644 embassy-imxrt/src/flexcomm/uart.rs create mode 100644 examples/mimxrt6/src/bin/uart-async.rs create mode 100644 examples/mimxrt6/src/bin/uart.rs diff --git a/docs/pages/imxrt.adoc b/docs/pages/imxrt.adoc index bbd65e494..87867e1e0 100644 --- a/docs/pages/imxrt.adoc +++ b/docs/pages/imxrt.adoc @@ -10,5 +10,7 @@ The link: link:https://github.com/embassy-rs/embassy/tree/main/embassy-imxrt[Emb The following peripherals have a HAL implementation at present * CRC +* DMA * GPIO * RNG +* UART diff --git a/embassy-imxrt/src/dma.rs b/embassy-imxrt/src/dma.rs new file mode 100644 index 000000000..e141447f3 --- /dev/null +++ b/embassy-imxrt/src/dma.rs @@ -0,0 +1,418 @@ +//! DMA driver. + +use core::future::Future; +use core::pin::Pin; +use core::sync::atomic::{compiler_fence, Ordering}; +use core::task::{Context, Poll}; + +use embassy_hal_internal::{impl_peripheral, Peri, PeripheralType}; +use embassy_sync::waitqueue::AtomicWaker; +use pac::dma0::channel::cfg::Periphreqen; +use pac::dma0::channel::xfercfg::{Dstinc, Srcinc, Width}; + +use crate::clocks::enable_and_reset; +use crate::interrupt::InterruptExt; +use crate::peripherals::DMA0; +use crate::sealed::Sealed; +use crate::{interrupt, pac, peripherals, BitIter}; + +#[cfg(feature = "rt")] +#[interrupt] +fn DMA0() { + let reg = unsafe { crate::pac::Dma0::steal() }; + + if reg.intstat().read().activeerrint().bit() { + let err = reg.errint0().read().bits(); + + for channel in BitIter(err) { + error!("DMA error interrupt on channel {}!", channel); + reg.errint0().write(|w| unsafe { w.err().bits(1 << channel) }); + CHANNEL_WAKERS[channel as usize].wake(); + } + } + + if reg.intstat().read().activeint().bit() { + let ia = reg.inta0().read().bits(); + + for channel in BitIter(ia) { + reg.inta0().write(|w| unsafe { w.ia().bits(1 << channel) }); + CHANNEL_WAKERS[channel as usize].wake(); + } + } +} + +/// Initialize DMA controllers (DMA0 only, for now) +pub(crate) unsafe fn init() { + let sysctl0 = crate::pac::Sysctl0::steal(); + let dmactl0 = crate::pac::Dma0::steal(); + + enable_and_reset::(); + + interrupt::DMA0.disable(); + interrupt::DMA0.set_priority(interrupt::Priority::P3); + + dmactl0.ctrl().modify(|_, w| w.enable().set_bit()); + + // Set channel descriptor SRAM base address + // Descriptor base must be 1K aligned + let descriptor_base = core::ptr::addr_of!(DESCRIPTORS.descs) as u32; + dmactl0.srambase().write(|w| w.bits(descriptor_base)); + + // Ensure AHB priority it highest (M4 == DMAC0) + sysctl0.ahbmatrixprior().modify(|_, w| w.m4().bits(0)); + + interrupt::DMA0.unpend(); + interrupt::DMA0.enable(); +} + +/// DMA read. +/// +/// SAFETY: Slice must point to a valid location reachable by DMA. +pub unsafe fn read<'a, C: Channel, W: Word>(ch: Peri<'a, C>, from: *const W, to: *mut [W]) -> Transfer<'a, C> { + let count = ((to.len() / W::size() as usize) - 1) as isize; + + copy_inner( + ch, + from as *const u32, + (to as *mut u32).byte_offset(count * W::size()), + W::width(), + count, + false, + true, + true, + ) +} + +/// DMA write. +/// +/// SAFETY: Slice must point to a valid location reachable by DMA. +pub unsafe fn write<'a, C: Channel, W: Word>(ch: Peri<'a, C>, from: *const [W], to: *mut W) -> Transfer<'a, C> { + let count = ((from.len() / W::size() as usize) - 1) as isize; + + copy_inner( + ch, + (from as *const u32).byte_offset(count * W::size()), + to as *mut u32, + W::width(), + count, + true, + false, + true, + ) +} + +/// DMA copy between slices. +/// +/// SAFETY: Slices must point to locations reachable by DMA. +pub unsafe fn copy<'a, C: Channel, W: Word>(ch: Peri<'a, C>, from: &[W], to: &mut [W]) -> Transfer<'a, C> { + let from_len = from.len(); + let to_len = to.len(); + assert_eq!(from_len, to_len); + + let count = ((from_len / W::size() as usize) - 1) as isize; + + copy_inner( + ch, + from.as_ptr().byte_offset(count * W::size()) as *const u32, + to.as_mut_ptr().byte_offset(count * W::size()) as *mut u32, + W::width(), + count, + true, + true, + false, + ) +} + +fn copy_inner<'a, C: Channel>( + ch: Peri<'a, C>, + from: *const u32, + to: *mut u32, + width: Width, + count: isize, + incr_read: bool, + incr_write: bool, + periph: bool, +) -> Transfer<'a, C> { + let p = ch.regs(); + + unsafe { + DESCRIPTORS.descs[ch.number() as usize].src = from as u32; + DESCRIPTORS.descs[ch.number() as usize].dest = to as u32; + } + + compiler_fence(Ordering::SeqCst); + + p.errint0().write(|w| unsafe { w.err().bits(1 << ch.number()) }); + p.inta0().write(|w| unsafe { w.ia().bits(1 << ch.number()) }); + + p.channel(ch.number().into()).cfg().write(|w| { + unsafe { w.chpriority().bits(0) } + .periphreqen() + .variant(match periph { + false => Periphreqen::Disabled, + true => Periphreqen::Enabled, + }) + .hwtrigen() + .clear_bit() + }); + + p.intenset0().write(|w| unsafe { w.inten().bits(1 << ch.number()) }); + + p.channel(ch.number().into()).xfercfg().write(|w| { + unsafe { w.xfercount().bits(count as u16) } + .cfgvalid() + .set_bit() + .clrtrig() + .set_bit() + .reload() + .clear_bit() + .setinta() + .set_bit() + .width() + .variant(width) + .srcinc() + .variant(match incr_read { + false => Srcinc::NoIncrement, + true => Srcinc::WidthX1, + // REVISIT: what about WidthX2 and WidthX4? + }) + .dstinc() + .variant(match incr_write { + false => Dstinc::NoIncrement, + true => Dstinc::WidthX1, + // REVISIT: what about WidthX2 and WidthX4? + }) + }); + + p.enableset0().write(|w| unsafe { w.ena().bits(1 << ch.number()) }); + + p.channel(ch.number().into()) + .xfercfg() + .modify(|_, w| w.swtrig().set_bit()); + + compiler_fence(Ordering::SeqCst); + + Transfer::new(ch) +} + +/// DMA transfer driver. +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Transfer<'a, C: Channel> { + channel: Peri<'a, C>, +} + +impl<'a, C: Channel> Transfer<'a, C> { + pub(crate) fn new(channel: Peri<'a, C>) -> Self { + Self { channel } + } + + pub(crate) fn abort(&mut self) -> usize { + let p = self.channel.regs(); + + p.abort0().write(|w| w.channel(self.channel.number()).set_bit()); + while p.busy0().read().bsy().bits() & (1 << self.channel.number()) != 0 {} + + p.enableclr0() + .write(|w| unsafe { w.clr().bits(1 << self.channel.number()) }); + + let width: u8 = p + .channel(self.channel.number().into()) + .xfercfg() + .read() + .width() + .variant() + .unwrap() + .into(); + + let count = p + .channel(self.channel.number().into()) + .xfercfg() + .read() + .xfercount() + .bits() + + 1; + + usize::from(count) * usize::from(width) + } +} + +impl<'a, C: Channel> Drop for Transfer<'a, C> { + fn drop(&mut self) { + self.abort(); + } +} + +impl<'a, C: Channel> Unpin for Transfer<'a, C> {} +impl<'a, C: Channel> Future for Transfer<'a, C> { + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // Re-register the waker on each call to poll() because any calls to + // wake will deregister the waker. + CHANNEL_WAKERS[self.channel.number() as usize].register(cx.waker()); + + if self.channel.regs().active0().read().act().bits() & (1 << self.channel.number()) == 0 { + Poll::Ready(()) + } else { + Poll::Pending + } + } +} + +/// DMA channel descriptor +#[derive(Copy, Clone)] +#[repr(C)] +struct Descriptor { + reserved: u32, + src: u32, + dest: u32, + link: u32, +} + +impl Descriptor { + const fn new() -> Self { + Self { + reserved: 0, + src: 0, + dest: 0, + link: 0, + } + } +} + +#[repr(align(1024))] +struct Descriptors { + descs: [Descriptor; CHANNEL_COUNT], +} + +impl Descriptors { + const fn new() -> Self { + Self { + descs: [const { Descriptor::new() }; CHANNEL_COUNT], + } + } +} + +static mut DESCRIPTORS: Descriptors = Descriptors::new(); +static CHANNEL_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [const { AtomicWaker::new() }; CHANNEL_COUNT]; +pub(crate) const CHANNEL_COUNT: usize = 33; + +/// DMA channel interface. +#[allow(private_bounds)] +pub trait Channel: PeripheralType + Sealed + Into + Sized + 'static { + /// Channel number. + fn number(&self) -> u8; + + /// Channel registry block. + fn regs(&self) -> &'static pac::dma0::RegisterBlock { + unsafe { &*crate::pac::Dma0::ptr() } + } +} + +/// DMA word. +#[allow(private_bounds)] +pub trait Word: Sealed { + /// Transfer width. + fn width() -> Width; + + /// Size in bytes for the width. + fn size() -> isize; +} + +impl Sealed for u8 {} +impl Word for u8 { + fn width() -> Width { + Width::Bit8 + } + + fn size() -> isize { + 1 + } +} + +impl Sealed for u16 {} +impl Word for u16 { + fn width() -> Width { + Width::Bit16 + } + + fn size() -> isize { + 2 + } +} + +impl Sealed for u32 {} +impl Word for u32 { + fn width() -> Width { + Width::Bit32 + } + + fn size() -> isize { + 4 + } +} + +/// Type erased DMA channel. +pub struct AnyChannel { + number: u8, +} + +impl_peripheral!(AnyChannel); + +impl Sealed for AnyChannel {} +impl Channel for AnyChannel { + fn number(&self) -> u8 { + self.number + } +} + +macro_rules! channel { + ($name:ident, $num:expr) => { + impl Sealed for peripherals::$name {} + impl Channel for peripherals::$name { + fn number(&self) -> u8 { + $num + } + } + + impl From for crate::dma::AnyChannel { + fn from(val: peripherals::$name) -> Self { + Self { number: val.number() } + } + } + }; +} + +channel!(DMA0_CH0, 0); +channel!(DMA0_CH1, 1); +channel!(DMA0_CH2, 2); +channel!(DMA0_CH3, 3); +channel!(DMA0_CH4, 4); +channel!(DMA0_CH5, 5); +channel!(DMA0_CH6, 6); +channel!(DMA0_CH7, 7); +channel!(DMA0_CH8, 8); +channel!(DMA0_CH9, 9); +channel!(DMA0_CH10, 10); +channel!(DMA0_CH11, 11); +channel!(DMA0_CH12, 12); +channel!(DMA0_CH13, 13); +channel!(DMA0_CH14, 14); +channel!(DMA0_CH15, 15); +channel!(DMA0_CH16, 16); +channel!(DMA0_CH17, 17); +channel!(DMA0_CH18, 18); +channel!(DMA0_CH19, 19); +channel!(DMA0_CH20, 20); +channel!(DMA0_CH21, 21); +channel!(DMA0_CH22, 22); +channel!(DMA0_CH23, 23); +channel!(DMA0_CH24, 24); +channel!(DMA0_CH25, 25); +channel!(DMA0_CH26, 26); +channel!(DMA0_CH27, 27); +channel!(DMA0_CH28, 28); +channel!(DMA0_CH29, 29); +channel!(DMA0_CH30, 30); +channel!(DMA0_CH31, 31); +channel!(DMA0_CH32, 32); diff --git a/embassy-imxrt/src/flexcomm/mod.rs b/embassy-imxrt/src/flexcomm/mod.rs new file mode 100644 index 000000000..4473c9a77 --- /dev/null +++ b/embassy-imxrt/src/flexcomm/mod.rs @@ -0,0 +1,252 @@ +//! Implements Flexcomm interface wrapper for easier usage across modules + +pub mod uart; + +use paste::paste; + +use crate::clocks::{enable_and_reset, SysconPeripheral}; +use crate::peripherals::{ + FLEXCOMM0, FLEXCOMM1, FLEXCOMM14, FLEXCOMM15, FLEXCOMM2, FLEXCOMM3, FLEXCOMM4, FLEXCOMM5, FLEXCOMM6, FLEXCOMM7, +}; +use crate::{pac, PeripheralType}; + +/// clock selection option +#[derive(Copy, Clone, Debug)] +pub enum Clock { + /// SFRO + Sfro, + + /// FFRO + Ffro, + + /// `AUDIO_PLL` + AudioPll, + + /// MASTER + Master, + + /// FCn_FRG with Main clock source + FcnFrgMain, + + /// FCn_FRG with Pll clock source + FcnFrgPll, + + /// FCn_FRG with Sfro clock source + FcnFrgSfro, + + /// FCn_FRG with Ffro clock source + FcnFrgFfro, + + /// disabled + None, +} + +/// do not allow implementation of trait outside this mod +mod sealed { + /// trait does not get re-exported outside flexcomm mod, allowing us to safely expose only desired APIs + pub trait Sealed {} +} + +/// primary low-level flexcomm interface +pub(crate) trait FlexcommLowLevel: sealed::Sealed + PeripheralType + SysconPeripheral + 'static + Send { + // fetch the flexcomm register block for direct manipulation + fn reg() -> &'static pac::flexcomm0::RegisterBlock; + + // set the clock select for this flexcomm instance and remove from reset + fn enable(clk: Clock); +} + +macro_rules! impl_flexcomm { + ($($idx:expr),*) => { + $( + paste!{ + impl sealed::Sealed for crate::peripherals::[] {} + + impl FlexcommLowLevel for crate::peripherals::[] { + fn reg() -> &'static crate::pac::flexcomm0::RegisterBlock { + // SAFETY: safe from single executor, enforce + // via peripheral reference lifetime tracking + unsafe { + &*crate::pac::[]::ptr() + } + } + + fn enable(clk: Clock) { + // SAFETY: safe from single executor + let clkctl1 = unsafe { crate::pac::Clkctl1::steal() }; + + clkctl1.flexcomm($idx).fcfclksel().write(|w| match clk { + Clock::Sfro => w.sel().sfro_clk(), + Clock::Ffro => w.sel().ffro_clk(), + Clock::AudioPll => w.sel().audio_pll_clk(), + Clock::Master => w.sel().master_clk(), + Clock::FcnFrgMain => w.sel().fcn_frg_clk(), + Clock::FcnFrgPll => w.sel().fcn_frg_clk(), + Clock::FcnFrgSfro => w.sel().fcn_frg_clk(), + Clock::FcnFrgFfro => w.sel().fcn_frg_clk(), + Clock::None => w.sel().none(), // no clock? throw an error? + }); + + clkctl1.flexcomm($idx).frgclksel().write(|w| match clk { + Clock::FcnFrgMain => w.sel().main_clk(), + Clock::FcnFrgPll => w.sel().frg_pll_clk(), + Clock::FcnFrgSfro => w.sel().sfro_clk(), + Clock::FcnFrgFfro => w.sel().ffro_clk(), + _ => w.sel().none(), // not using frg ... + }); + + // todo: add support for frg div/mult + clkctl1 + .flexcomm($idx) + .frgctl() + .write(|w| + // SAFETY: unsafe only used for .bits() call + unsafe { w.mult().bits(0) }); + + enable_and_reset::<[]>(); + } + } + } + )* + } +} + +impl_flexcomm!(0, 1, 2, 3, 4, 5, 6, 7); + +// TODO: FLEXCOMM 14 is untested. Enable SPI support on FLEXCOMM14 +// Add special case FLEXCOMM14 +impl sealed::Sealed for crate::peripherals::FLEXCOMM14 {} + +impl FlexcommLowLevel for crate::peripherals::FLEXCOMM14 { + fn reg() -> &'static crate::pac::flexcomm0::RegisterBlock { + // SAFETY: safe from single executor, enforce + // via peripheral reference lifetime tracking + unsafe { &*crate::pac::Flexcomm14::ptr() } + } + + fn enable(clk: Clock) { + // SAFETY: safe from single executor + let clkctl1 = unsafe { crate::pac::Clkctl1::steal() }; + + clkctl1.fc14fclksel().write(|w| match clk { + Clock::Sfro => w.sel().sfro_clk(), + Clock::Ffro => w.sel().ffro_clk(), + Clock::AudioPll => w.sel().audio_pll_clk(), + Clock::Master => w.sel().master_clk(), + Clock::FcnFrgMain => w.sel().fcn_frg_clk(), + Clock::FcnFrgPll => w.sel().fcn_frg_clk(), + Clock::FcnFrgSfro => w.sel().fcn_frg_clk(), + Clock::FcnFrgFfro => w.sel().fcn_frg_clk(), + Clock::None => w.sel().none(), // no clock? throw an error? + }); + + clkctl1.frg14clksel().write(|w| match clk { + Clock::FcnFrgMain => w.sel().main_clk(), + Clock::FcnFrgPll => w.sel().frg_pll_clk(), + Clock::FcnFrgSfro => w.sel().sfro_clk(), + Clock::FcnFrgFfro => w.sel().ffro_clk(), + _ => w.sel().none(), // not using frg ... + }); + + // todo: add support for frg div/mult + clkctl1.frg14ctl().write(|w| + // SAFETY: unsafe only used for .bits() call + unsafe { w.mult().bits(0) }); + + enable_and_reset::(); + } +} + +// Add special case FLEXCOMM15 +impl sealed::Sealed for crate::peripherals::FLEXCOMM15 {} + +impl FlexcommLowLevel for crate::peripherals::FLEXCOMM15 { + fn reg() -> &'static crate::pac::flexcomm0::RegisterBlock { + // SAFETY: safe from single executor, enforce + // via peripheral reference lifetime tracking + unsafe { &*crate::pac::Flexcomm15::ptr() } + } + + fn enable(clk: Clock) { + // SAFETY: safe from single executor + let clkctl1 = unsafe { crate::pac::Clkctl1::steal() }; + + clkctl1.fc15fclksel().write(|w| match clk { + Clock::Sfro => w.sel().sfro_clk(), + Clock::Ffro => w.sel().ffro_clk(), + Clock::AudioPll => w.sel().audio_pll_clk(), + Clock::Master => w.sel().master_clk(), + Clock::FcnFrgMain => w.sel().fcn_frg_clk(), + Clock::FcnFrgPll => w.sel().fcn_frg_clk(), + Clock::FcnFrgSfro => w.sel().fcn_frg_clk(), + Clock::FcnFrgFfro => w.sel().fcn_frg_clk(), + Clock::None => w.sel().none(), // no clock? throw an error? + }); + clkctl1.frg15clksel().write(|w| match clk { + Clock::FcnFrgMain => w.sel().main_clk(), + Clock::FcnFrgPll => w.sel().frg_pll_clk(), + Clock::FcnFrgSfro => w.sel().sfro_clk(), + Clock::FcnFrgFfro => w.sel().ffro_clk(), + _ => w.sel().none(), // not using frg ... + }); + // todo: add support for frg div/mult + clkctl1.frg15ctl().write(|w| + // SAFETY: unsafe only used for .bits() call + unsafe { w.mult().bits(0) }); + + enable_and_reset::(); + } +} + +macro_rules! into_mode { + ($mode:ident, $($fc:ident),*) => { + paste! { + /// Sealed Mode trait + trait []: FlexcommLowLevel {} + + /// Select mode of operation + #[allow(private_bounds)] + pub trait []: [] { + /// Set mode of operation + fn []() { + Self::reg().pselid().write(|w| w.persel().[<$mode>]()); + } + } + } + + $( + paste!{ + impl [] for crate::peripherals::$fc {} + impl [] for crate::peripherals::$fc {} + } + )* + } +} + +into_mode!(usart, FLEXCOMM0, FLEXCOMM1, FLEXCOMM2, FLEXCOMM3, FLEXCOMM4, FLEXCOMM5, FLEXCOMM6, FLEXCOMM7); +into_mode!(spi, FLEXCOMM0, FLEXCOMM1, FLEXCOMM2, FLEXCOMM3, FLEXCOMM4, FLEXCOMM5, FLEXCOMM6, FLEXCOMM7, FLEXCOMM14); +into_mode!(i2c, FLEXCOMM0, FLEXCOMM1, FLEXCOMM2, FLEXCOMM3, FLEXCOMM4, FLEXCOMM5, FLEXCOMM6, FLEXCOMM7, FLEXCOMM15); + +into_mode!( + i2s_transmit, + FLEXCOMM0, + FLEXCOMM1, + FLEXCOMM2, + FLEXCOMM3, + FLEXCOMM4, + FLEXCOMM5, + FLEXCOMM6, + FLEXCOMM7 +); + +into_mode!( + i2s_receive, + FLEXCOMM0, + FLEXCOMM1, + FLEXCOMM2, + FLEXCOMM3, + FLEXCOMM4, + FLEXCOMM5, + FLEXCOMM6, + FLEXCOMM7 +); diff --git a/embassy-imxrt/src/flexcomm/uart.rs b/embassy-imxrt/src/flexcomm/uart.rs new file mode 100644 index 000000000..230b30d43 --- /dev/null +++ b/embassy-imxrt/src/flexcomm/uart.rs @@ -0,0 +1,1230 @@ +//! Universal Asynchronous Receiver Transmitter (UART) driver. + +use core::future::poll_fn; +use core::marker::PhantomData; +use core::sync::atomic::{compiler_fence, AtomicU8, Ordering}; +use core::task::Poll; + +use embassy_futures::select::{select, Either}; +use embassy_hal_internal::drop::OnDrop; +use embassy_hal_internal::{Peri, PeripheralType}; +use embassy_sync::waitqueue::AtomicWaker; +use paste::paste; + +use crate::dma::AnyChannel; +use crate::flexcomm::Clock; +use crate::gpio::{AnyPin, GpioPin as Pin}; +use crate::interrupt::typelevel::Interrupt; +use crate::iopctl::{DriveMode, DriveStrength, Inverter, IopctlPin, Pull, SlewRate}; +use crate::pac::usart0::cfg::{Clkpol, Datalen, Loop, Paritysel as Parity, Stoplen, Syncen, Syncmst}; +use crate::pac::usart0::ctl::Cc; +use crate::sealed::Sealed; +use crate::{dma, interrupt}; + +/// Driver move trait. +#[allow(private_bounds)] +pub trait Mode: Sealed {} + +/// Blocking mode. +pub struct Blocking; +impl Sealed for Blocking {} +impl Mode for Blocking {} + +/// Async mode. +pub struct Async; +impl Sealed for Async {} +impl Mode for Async {} + +/// Uart driver. +pub struct Uart<'a, M: Mode> { + tx: UartTx<'a, M>, + rx: UartRx<'a, M>, +} + +/// Uart TX driver. +pub struct UartTx<'a, M: Mode> { + info: Info, + tx_dma: Option>, + _phantom: PhantomData<(&'a (), M)>, +} + +/// Uart RX driver. +pub struct UartRx<'a, M: Mode> { + info: Info, + rx_dma: Option>, + _phantom: PhantomData<(&'a (), M)>, +} + +/// UART config +#[derive(Clone, Copy)] +pub struct Config { + /// Baudrate of the Uart + pub baudrate: u32, + /// data length + pub data_bits: Datalen, + /// Parity + pub parity: Parity, + /// Stop bits + pub stop_bits: Stoplen, + /// Polarity of the clock + pub clock_polarity: Clkpol, + /// Sync/ Async operation selection + pub operation: Syncen, + /// Sync master/slave mode selection (only applicable in sync mode) + pub sync_mode_master_select: Syncmst, + /// USART continuous Clock generation enable in synchronous master mode. + pub continuous_clock: Cc, + /// Normal/ loopback mode + pub loopback_mode: Loop, + /// Clock type + pub clock: Clock, +} + +impl Default for Config { + /// Default configuration for single channel sampling. + fn default() -> Self { + Self { + baudrate: 115_200, + data_bits: Datalen::Bit8, + parity: Parity::NoParity, + stop_bits: Stoplen::Bit1, + clock_polarity: Clkpol::FallingEdge, + operation: Syncen::AsynchronousMode, + sync_mode_master_select: Syncmst::Slave, + continuous_clock: Cc::ClockOnCharacter, + loopback_mode: Loop::Normal, + clock: crate::flexcomm::Clock::Sfro, + } + } +} + +/// Uart Errors +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Error { + /// Read error + Read, + + /// Buffer overflow + Overrun, + + /// Noise error + Noise, + + /// Framing error + Framing, + + /// Parity error + Parity, + + /// Failure + Fail, + + /// Invalid argument + InvalidArgument, + + /// Uart baud rate cannot be supported with the given clock + UnsupportedBaudrate, + + /// RX FIFO Empty + RxFifoEmpty, + + /// TX FIFO Full + TxFifoFull, + + /// TX Busy + TxBusy, +} +/// shorthand for -> `Result` +pub type Result = core::result::Result; + +impl<'a, M: Mode> UartTx<'a, M> { + fn new_inner(tx_dma: Option>) -> Self { + let uarttx = Self { + info: T::info(), + tx_dma, + _phantom: PhantomData, + }; + uarttx.info.refcnt.fetch_add(1, Ordering::Relaxed); + uarttx + } +} + +impl<'a, M: Mode> Drop for UartTx<'a, M> { + fn drop(&mut self) { + if self.info.refcnt.fetch_sub(1, Ordering::Relaxed) == 1 { + while self.info.regs.stat().read().txidle().bit_is_clear() {} + + self.info.regs.fifointenclr().modify(|_, w| { + w.txerr() + .set_bit() + .rxerr() + .set_bit() + .txlvl() + .set_bit() + .rxlvl() + .set_bit() + }); + + self.info + .regs + .fifocfg() + .modify(|_, w| w.dmatx().clear_bit().dmarx().clear_bit()); + + self.info.regs.cfg().modify(|_, w| w.enable().disabled()); + } + } +} + +impl<'a> UartTx<'a, Blocking> { + /// Create a new UART which can only send data + /// Unidirectional Uart - Tx only + pub fn new_blocking(_inner: Peri<'a, T>, tx: Peri<'a, impl TxPin>, config: Config) -> Result { + tx.as_tx(); + + let _tx = tx.into(); + Uart::::init::(Some(_tx), None, None, None, config)?; + + Ok(Self::new_inner::(None)) + } + + fn write_byte_internal(&mut self, byte: u8) -> Result<()> { + // SAFETY: unsafe only used for .bits() + self.info + .regs + .fifowr() + .write(|w| unsafe { w.txdata().bits(u16::from(byte)) }); + + Ok(()) + } + + fn blocking_write_byte(&mut self, byte: u8) -> Result<()> { + while self.info.regs.fifostat().read().txnotfull().bit_is_clear() {} + + // Prevent the compiler from reordering write_byte_internal() + // before the loop above. + compiler_fence(Ordering::Release); + + self.write_byte_internal(byte) + } + + fn write_byte(&mut self, byte: u8) -> Result<()> { + if self.info.regs.fifostat().read().txnotfull().bit_is_clear() { + Err(Error::TxFifoFull) + } else { + self.write_byte_internal(byte) + } + } + + /// Transmit the provided buffer blocking execution until done. + pub fn blocking_write(&mut self, buf: &[u8]) -> Result<()> { + for x in buf { + self.blocking_write_byte(*x)?; + } + + Ok(()) + } + + /// Transmit the provided buffer. Non-blocking version, bails out + /// if it would block. + pub fn write(&mut self, buf: &[u8]) -> Result<()> { + for x in buf { + self.write_byte(*x)?; + } + + Ok(()) + } + + /// Flush UART TX blocking execution until done. + pub fn blocking_flush(&mut self) -> Result<()> { + while self.info.regs.stat().read().txidle().bit_is_clear() {} + Ok(()) + } + + /// Flush UART TX. + pub fn flush(&mut self) -> Result<()> { + if self.info.regs.stat().read().txidle().bit_is_clear() { + Err(Error::TxBusy) + } else { + Ok(()) + } + } +} + +impl<'a, M: Mode> UartRx<'a, M> { + fn new_inner(rx_dma: Option>) -> Self { + let uartrx = Self { + info: T::info(), + rx_dma, + _phantom: PhantomData, + }; + uartrx.info.refcnt.fetch_add(1, Ordering::Relaxed); + uartrx + } +} + +impl<'a, M: Mode> Drop for UartRx<'a, M> { + fn drop(&mut self) { + if self.info.refcnt.fetch_sub(1, Ordering::Relaxed) == 1 { + while self.info.regs.stat().read().rxidle().bit_is_clear() {} + + self.info.regs.fifointenclr().modify(|_, w| { + w.txerr() + .set_bit() + .rxerr() + .set_bit() + .txlvl() + .set_bit() + .rxlvl() + .set_bit() + }); + + self.info + .regs + .fifocfg() + .modify(|_, w| w.dmatx().clear_bit().dmarx().clear_bit()); + + self.info.regs.cfg().modify(|_, w| w.enable().disabled()); + } + } +} + +impl<'a> UartRx<'a, Blocking> { + /// Create a new blocking UART which can only receive data + pub fn new_blocking(_inner: Peri<'a, T>, rx: Peri<'a, impl RxPin>, config: Config) -> Result { + rx.as_rx(); + + let _rx = rx.into(); + Uart::::init::(None, Some(_rx), None, None, config)?; + + Ok(Self::new_inner::(None)) + } +} + +impl UartRx<'_, Blocking> { + fn read_byte_internal(&mut self) -> Result { + if self.info.regs.fifostat().read().rxerr().bit_is_set() { + self.info.regs.fifocfg().modify(|_, w| w.emptyrx().set_bit()); + self.info.regs.fifostat().modify(|_, w| w.rxerr().set_bit()); + Err(Error::Read) + } else if self.info.regs.stat().read().parityerrint().bit_is_set() { + self.info.regs.stat().modify(|_, w| w.parityerrint().clear_bit_by_one()); + Err(Error::Parity) + } else if self.info.regs.stat().read().framerrint().bit_is_set() { + self.info.regs.stat().modify(|_, w| w.framerrint().clear_bit_by_one()); + Err(Error::Framing) + } else if self.info.regs.stat().read().rxnoiseint().bit_is_set() { + self.info.regs.stat().modify(|_, w| w.rxnoiseint().clear_bit_by_one()); + Err(Error::Noise) + } else { + let byte = self.info.regs.fiford().read().rxdata().bits() as u8; + Ok(byte) + } + } + + fn read_byte(&mut self) -> Result { + if self.info.regs.fifostat().read().rxnotempty().bit_is_clear() { + Err(Error::RxFifoEmpty) + } else { + self.read_byte_internal() + } + } + + fn blocking_read_byte(&mut self) -> Result { + while self.info.regs.fifostat().read().rxnotempty().bit_is_clear() {} + + // Prevent the compiler from reordering read_byte_internal() + // before the loop above. + compiler_fence(Ordering::Acquire); + + self.read_byte_internal() + } + + /// Read from UART RX. Non-blocking version, bails out if it would + /// block. + pub fn read(&mut self, buf: &mut [u8]) -> Result<()> { + for b in buf.iter_mut() { + *b = self.read_byte()?; + } + + Ok(()) + } + + /// Read from UART RX blocking execution until done. + pub fn blocking_read(&mut self, buf: &mut [u8]) -> Result<()> { + for b in buf.iter_mut() { + *b = self.blocking_read_byte()?; + } + + Ok(()) + } +} + +impl<'a, M: Mode> Uart<'a, M> { + fn init( + tx: Option>, + rx: Option>, + rts: Option>, + cts: Option>, + config: Config, + ) -> Result<()> { + T::enable(config.clock); + T::into_usart(); + + let regs = T::info().regs; + + if tx.is_some() { + regs.fifocfg().modify(|_, w| w.emptytx().set_bit().enabletx().enabled()); + + // clear FIFO error + regs.fifostat().write(|w| w.txerr().set_bit()); + } + + if rx.is_some() { + regs.fifocfg().modify(|_, w| w.emptyrx().set_bit().enablerx().enabled()); + + // clear FIFO error + regs.fifostat().write(|w| w.rxerr().set_bit()); + } + + if rts.is_some() && cts.is_some() { + regs.cfg().modify(|_, w| w.ctsen().enabled()); + } + + Self::set_baudrate_inner::(config.baudrate, config.clock)?; + Self::set_uart_config::(config); + + Ok(()) + } + + fn get_fc_freq(clock: Clock) -> Result { + match clock { + Clock::Sfro => Ok(16_000_000), + Clock::Ffro => Ok(48_000_000), + // We only support Sfro and Ffro now. + _ => Err(Error::InvalidArgument), + } + } + + fn set_baudrate_inner(baudrate: u32, clock: Clock) -> Result<()> { + // Get source clock frequency according to clock type. + let source_clock_hz = Self::get_fc_freq(clock)?; + + if baudrate == 0 { + return Err(Error::InvalidArgument); + } + + let regs = T::info().regs; + + // If synchronous master mode is enabled, only configure the BRG value. + if regs.cfg().read().syncen().is_synchronous_mode() { + // Master + if regs.cfg().read().syncmst().is_master() { + // Calculate the BRG value + let brgval = (source_clock_hz / baudrate) - 1; + + // SAFETY: unsafe only used for .bits() + regs.brg().write(|w| unsafe { w.brgval().bits(brgval as u16) }); + } + } else { + // Smaller values of OSR can make the sampling position within a + // data bit less accurate and may potentially cause more noise + // errors or incorrect data. + let (_, osr, brg) = (8..16).rev().fold( + (u32::MAX, u32::MAX, u32::MAX), + |(best_diff, best_osr, best_brg), osrval| { + // Compare source_clock_hz agaist with ((osrval + 1) * baudrate) to make sure + // (source_clock_hz / ((osrval + 1) * baudrate)) is not less than 0. + if source_clock_hz < ((osrval + 1) * baudrate) { + (best_diff, best_osr, best_brg) + } else { + let brgval = (source_clock_hz / ((osrval + 1) * baudrate)) - 1; + // We know brgval will not be less than 0 now, it should have already been a valid u32 value, + // then compare it agaist with 65535. + if brgval > 65535 { + (best_diff, best_osr, best_brg) + } else { + // Calculate the baud rate based on the BRG value + let candidate = source_clock_hz / ((osrval + 1) * (brgval + 1)); + + // Calculate the difference between the + // current baud rate and the desired baud rate + let diff = (candidate as i32 - baudrate as i32).unsigned_abs(); + + // Check if the current calculated difference is the best so far + if diff < best_diff { + (diff, osrval, brgval) + } else { + (best_diff, best_osr, best_brg) + } + } + } + }, + ); + + // Value over range + if brg > 65535 { + return Err(Error::UnsupportedBaudrate); + } + + // SAFETY: unsafe only used for .bits() + regs.osr().write(|w| unsafe { w.osrval().bits(osr as u8) }); + + // SAFETY: unsafe only used for .bits() + regs.brg().write(|w| unsafe { w.brgval().bits(brg as u16) }); + } + + Ok(()) + } + + fn set_uart_config(config: Config) { + let regs = T::info().regs; + + regs.cfg().modify(|_, w| w.enable().disabled()); + + regs.cfg().modify(|_, w| { + w.datalen() + .variant(config.data_bits) + .stoplen() + .variant(config.stop_bits) + .paritysel() + .variant(config.parity) + .loop_() + .variant(config.loopback_mode) + .syncen() + .variant(config.operation) + .clkpol() + .variant(config.clock_polarity) + }); + + regs.cfg().modify(|_, w| w.enable().enabled()); + } + + /// Split the Uart into a transmitter and receiver, which is particularly + /// useful when having two tasks correlating to transmitting and receiving. + pub fn split(self) -> (UartTx<'a, M>, UartRx<'a, M>) { + (self.tx, self.rx) + } + + /// Split the Uart into a transmitter and receiver by mutable reference, + /// which is particularly useful when having two tasks correlating to + /// transmitting and receiving. + pub fn split_ref(&mut self) -> (&mut UartTx<'a, M>, &mut UartRx<'a, M>) { + (&mut self.tx, &mut self.rx) + } +} + +impl<'a> Uart<'a, Blocking> { + /// Create a new blocking UART + pub fn new_blocking( + _inner: Peri<'a, T>, + tx: Peri<'a, impl TxPin>, + rx: Peri<'a, impl RxPin>, + config: Config, + ) -> Result { + tx.as_tx(); + rx.as_rx(); + + let tx = tx.into(); + let rx = rx.into(); + + Self::init::(Some(tx), Some(rx), None, None, config)?; + + Ok(Self { + tx: UartTx::new_inner::(None), + rx: UartRx::new_inner::(None), + }) + } + + /// Read from UART RX blocking execution until done. + pub fn blocking_read(&mut self, buf: &mut [u8]) -> Result<()> { + self.rx.blocking_read(buf) + } + + /// Read from UART RX. Non-blocking version, bails out if it would + /// block. + pub fn read(&mut self, buf: &mut [u8]) -> Result<()> { + self.rx.read(buf) + } + + /// Transmit the provided buffer blocking execution until done. + pub fn blocking_write(&mut self, buf: &[u8]) -> Result<()> { + self.tx.blocking_write(buf) + } + + /// Transmit the provided buffer. Non-blocking version, bails out + /// if it would block. + pub fn write(&mut self, buf: &[u8]) -> Result<()> { + self.tx.write(buf) + } + + /// Flush UART TX blocking execution until done. + pub fn blocking_flush(&mut self) -> Result<()> { + self.tx.blocking_flush() + } + + /// Flush UART TX. + pub fn flush(&mut self) -> Result<()> { + self.tx.flush() + } +} + +impl<'a> UartTx<'a, Async> { + /// Create a new DMA enabled UART which can only send data + pub fn new_async( + _inner: Peri<'a, T>, + tx: Peri<'a, impl TxPin>, + _irq: impl interrupt::typelevel::Binding> + 'a, + tx_dma: Peri<'a, impl TxDma>, + config: Config, + ) -> Result { + tx.as_tx(); + + let _tx = tx.into(); + Uart::::init::(Some(_tx), None, None, None, config)?; + + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; + + Ok(Self::new_inner::(Some(tx_dma.into()))) + } + + /// Transmit the provided buffer asynchronously. + pub async fn write(&mut self, buf: &[u8]) -> Result<()> { + let regs = self.info.regs; + + // Disable DMA on completion/cancellation + let _dma_guard = OnDrop::new(|| { + regs.fifocfg().modify(|_, w| w.dmatx().disabled()); + }); + + for chunk in buf.chunks(1024) { + regs.fifocfg().modify(|_, w| w.dmatx().enabled()); + + let ch = self.tx_dma.as_mut().unwrap().reborrow(); + let transfer = unsafe { dma::write(ch, chunk, regs.fifowr().as_ptr() as *mut u8) }; + + let res = select( + transfer, + poll_fn(|cx| { + UART_WAKERS[self.info.index].register(cx.waker()); + + self.info.regs.intenset().write(|w| { + w.framerren() + .set_bit() + .parityerren() + .set_bit() + .rxnoiseen() + .set_bit() + .aberren() + .set_bit() + }); + + let stat = self.info.regs.stat().read(); + + self.info.regs.stat().write(|w| { + w.framerrint() + .clear_bit_by_one() + .parityerrint() + .clear_bit_by_one() + .rxnoiseint() + .clear_bit_by_one() + .aberr() + .clear_bit_by_one() + }); + + if stat.framerrint().bit_is_set() { + Poll::Ready(Err(Error::Framing)) + } else if stat.parityerrint().bit_is_set() { + Poll::Ready(Err(Error::Parity)) + } else if stat.rxnoiseint().bit_is_set() { + Poll::Ready(Err(Error::Noise)) + } else if stat.aberr().bit_is_set() { + Poll::Ready(Err(Error::Fail)) + } else { + Poll::Pending + } + }), + ) + .await; + + match res { + Either::First(()) | Either::Second(Ok(())) => (), + Either::Second(e) => return e, + } + } + + Ok(()) + } + + /// Flush UART TX asynchronously. + pub async fn flush(&mut self) -> Result<()> { + self.wait_on( + |me| { + if me.info.regs.stat().read().txidle().bit_is_set() { + Poll::Ready(Ok(())) + } else { + Poll::Pending + } + }, + |me| { + me.info.regs.intenset().write(|w| w.txidleen().set_bit()); + }, + ) + .await + } + + /// Calls `f` to check if we are ready or not. + /// If not, `g` is called once the waker is set (to eg enable the required interrupts). + async fn wait_on(&mut self, mut f: F, mut g: G) -> U + where + F: FnMut(&mut Self) -> Poll, + G: FnMut(&mut Self), + { + poll_fn(|cx| { + // Register waker before checking condition, to ensure that wakes/interrupts + // aren't lost between f() and g() + UART_WAKERS[self.info.index].register(cx.waker()); + let r = f(self); + + if r.is_pending() { + g(self); + } + + r + }) + .await + } +} + +impl<'a> UartRx<'a, Async> { + /// Create a new DMA enabled UART which can only receive data + pub fn new_async( + _inner: Peri<'a, T>, + rx: Peri<'a, impl RxPin>, + _irq: impl interrupt::typelevel::Binding> + 'a, + rx_dma: Peri<'a, impl RxDma>, + config: Config, + ) -> Result { + rx.as_rx(); + + let _rx = rx.into(); + Uart::::init::(None, Some(_rx), None, None, config)?; + + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; + + Ok(Self::new_inner::(Some(rx_dma.into()))) + } + + /// Read from UART RX asynchronously. + pub async fn read(&mut self, buf: &mut [u8]) -> Result<()> { + let regs = self.info.regs; + + // Disable DMA on completion/cancellation + let _dma_guard = OnDrop::new(|| { + regs.fifocfg().modify(|_, w| w.dmarx().disabled()); + }); + + for chunk in buf.chunks_mut(1024) { + regs.fifocfg().modify(|_, w| w.dmarx().enabled()); + + let ch = self.rx_dma.as_mut().unwrap().reborrow(); + let transfer = unsafe { dma::read(ch, regs.fiford().as_ptr() as *const u8, chunk) }; + + let res = select( + transfer, + poll_fn(|cx| { + UART_WAKERS[self.info.index].register(cx.waker()); + + self.info.regs.intenset().write(|w| { + w.framerren() + .set_bit() + .parityerren() + .set_bit() + .rxnoiseen() + .set_bit() + .aberren() + .set_bit() + }); + + let stat = self.info.regs.stat().read(); + + self.info.regs.stat().write(|w| { + w.framerrint() + .clear_bit_by_one() + .parityerrint() + .clear_bit_by_one() + .rxnoiseint() + .clear_bit_by_one() + .aberr() + .clear_bit_by_one() + }); + + if stat.framerrint().bit_is_set() { + Poll::Ready(Err(Error::Framing)) + } else if stat.parityerrint().bit_is_set() { + Poll::Ready(Err(Error::Parity)) + } else if stat.rxnoiseint().bit_is_set() { + Poll::Ready(Err(Error::Noise)) + } else if stat.aberr().bit_is_set() { + Poll::Ready(Err(Error::Fail)) + } else { + Poll::Pending + } + }), + ) + .await; + + match res { + Either::First(()) | Either::Second(Ok(())) => (), + Either::Second(e) => return e, + } + } + + Ok(()) + } +} + +impl<'a> Uart<'a, Async> { + /// Create a new DMA enabled UART + pub fn new_async( + _inner: Peri<'a, T>, + tx: Peri<'a, impl TxPin>, + rx: Peri<'a, impl RxPin>, + _irq: impl interrupt::typelevel::Binding> + 'a, + tx_dma: Peri<'a, impl TxDma>, + rx_dma: Peri<'a, impl RxDma>, + config: Config, + ) -> Result { + tx.as_tx(); + rx.as_rx(); + + let tx = tx.into(); + let rx = rx.into(); + + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; + + Self::init::(Some(tx), Some(rx), None, None, config)?; + + Ok(Self { + tx: UartTx::new_inner::(Some(tx_dma.into())), + rx: UartRx::new_inner::(Some(rx_dma.into())), + }) + } + + /// Create a new DMA enabled UART with hardware flow control (RTS/CTS) + pub fn new_with_rtscts( + _inner: Peri<'a, T>, + tx: Peri<'a, impl TxPin>, + rx: Peri<'a, impl RxPin>, + rts: Peri<'a, impl RtsPin>, + cts: Peri<'a, impl CtsPin>, + _irq: impl interrupt::typelevel::Binding> + 'a, + tx_dma: Peri<'a, impl TxDma>, + rx_dma: Peri<'a, impl RxDma>, + config: Config, + ) -> Result { + tx.as_tx(); + rx.as_rx(); + rts.as_rts(); + cts.as_cts(); + + let tx = tx.into(); + let rx = rx.into(); + let rts = rts.into(); + let cts = cts.into(); + + Self::init::(Some(tx), Some(rx), Some(rts), Some(cts), config)?; + + Ok(Self { + tx: UartTx::new_inner::(Some(tx_dma.into())), + rx: UartRx::new_inner::(Some(rx_dma.into())), + }) + } + + /// Read from UART RX. + pub async fn read(&mut self, buf: &mut [u8]) -> Result<()> { + self.rx.read(buf).await + } + + /// Transmit the provided buffer. + pub async fn write(&mut self, buf: &[u8]) -> Result<()> { + self.tx.write(buf).await + } + + /// Flush UART TX. + pub async fn flush(&mut self) -> Result<()> { + self.tx.flush().await + } +} + +impl embedded_hal_02::serial::Read for UartRx<'_, Blocking> { + type Error = Error; + + fn read(&mut self) -> core::result::Result> { + let mut buf = [0; 1]; + + match self.read(&mut buf) { + Ok(_) => Ok(buf[0]), + Err(Error::RxFifoEmpty) => Err(nb::Error::WouldBlock), + Err(e) => Err(nb::Error::Other(e)), + } + } +} + +impl embedded_hal_02::serial::Write for UartTx<'_, Blocking> { + type Error = Error; + + fn write(&mut self, word: u8) -> core::result::Result<(), nb::Error> { + match self.write(&[word]) { + Ok(_) => Ok(()), + Err(Error::TxFifoFull) => Err(nb::Error::WouldBlock), + Err(e) => Err(nb::Error::Other(e)), + } + } + + fn flush(&mut self) -> core::result::Result<(), nb::Error> { + match self.flush() { + Ok(_) => Ok(()), + Err(Error::TxBusy) => Err(nb::Error::WouldBlock), + Err(e) => Err(nb::Error::Other(e)), + } + } +} + +impl embedded_hal_02::blocking::serial::Write for UartTx<'_, Blocking> { + type Error = Error; + + fn bwrite_all(&mut self, buffer: &[u8]) -> core::result::Result<(), Self::Error> { + self.blocking_write(buffer) + } + + fn bflush(&mut self) -> core::result::Result<(), Self::Error> { + self.blocking_flush() + } +} + +impl embedded_hal_02::serial::Read for Uart<'_, Blocking> { + type Error = Error; + + fn read(&mut self) -> core::result::Result> { + embedded_hal_02::serial::Read::read(&mut self.rx) + } +} + +impl embedded_hal_02::serial::Write for Uart<'_, Blocking> { + type Error = Error; + + fn write(&mut self, word: u8) -> core::result::Result<(), nb::Error> { + embedded_hal_02::serial::Write::write(&mut self.tx, word) + } + + fn flush(&mut self) -> core::result::Result<(), nb::Error> { + embedded_hal_02::serial::Write::flush(&mut self.tx) + } +} + +impl embedded_hal_02::blocking::serial::Write for Uart<'_, Blocking> { + type Error = Error; + + fn bwrite_all(&mut self, buffer: &[u8]) -> core::result::Result<(), Self::Error> { + self.blocking_write(buffer) + } + + fn bflush(&mut self) -> core::result::Result<(), Self::Error> { + self.blocking_flush() + } +} + +impl embedded_hal_nb::serial::Error for Error { + fn kind(&self) -> embedded_hal_nb::serial::ErrorKind { + match *self { + Self::Framing => embedded_hal_nb::serial::ErrorKind::FrameFormat, + Self::Overrun => embedded_hal_nb::serial::ErrorKind::Overrun, + Self::Parity => embedded_hal_nb::serial::ErrorKind::Parity, + Self::Noise => embedded_hal_nb::serial::ErrorKind::Noise, + _ => embedded_hal_nb::serial::ErrorKind::Other, + } + } +} + +impl embedded_hal_nb::serial::ErrorType for UartRx<'_, Blocking> { + type Error = Error; +} + +impl embedded_hal_nb::serial::ErrorType for UartTx<'_, Blocking> { + type Error = Error; +} + +impl embedded_hal_nb::serial::ErrorType for Uart<'_, Blocking> { + type Error = Error; +} + +impl embedded_hal_nb::serial::Read for UartRx<'_, Blocking> { + fn read(&mut self) -> nb::Result { + let mut buf = [0; 1]; + + match self.read(&mut buf) { + Ok(_) => Ok(buf[0]), + Err(Error::RxFifoEmpty) => Err(nb::Error::WouldBlock), + Err(e) => Err(nb::Error::Other(e)), + } + } +} + +impl embedded_hal_nb::serial::Write for UartTx<'_, Blocking> { + fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { + match self.write(&[word]) { + Ok(_) => Ok(()), + Err(Error::TxFifoFull) => Err(nb::Error::WouldBlock), + Err(e) => Err(nb::Error::Other(e)), + } + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + match self.flush() { + Ok(_) => Ok(()), + Err(Error::TxBusy) => Err(nb::Error::WouldBlock), + Err(e) => Err(nb::Error::Other(e)), + } + } +} + +impl embedded_hal_nb::serial::Read for Uart<'_, Blocking> { + fn read(&mut self) -> core::result::Result> { + embedded_hal_02::serial::Read::read(&mut self.rx) + } +} + +impl embedded_hal_nb::serial::Write for Uart<'_, Blocking> { + fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { + self.blocking_write(&[char]).map_err(nb::Error::Other) + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + self.blocking_flush().map_err(nb::Error::Other) + } +} + +struct Info { + regs: &'static crate::pac::usart0::RegisterBlock, + index: usize, + refcnt: AtomicU8, +} + +trait SealedInstance { + fn info() -> Info; + fn index() -> usize; +} + +/// UART interrupt handler. +pub struct InterruptHandler { + _phantom: PhantomData, +} + +const UART_COUNT: usize = 8; +static UART_WAKERS: [AtomicWaker; UART_COUNT] = [const { AtomicWaker::new() }; UART_COUNT]; + +impl interrupt::typelevel::Handler for InterruptHandler { + unsafe fn on_interrupt() { + let waker = &UART_WAKERS[T::index()]; + let regs = T::info().regs; + let stat = regs.intstat().read(); + + if stat.txidle().bit_is_set() + || stat.framerrint().bit_is_set() + || stat.parityerrint().bit_is_set() + || stat.rxnoiseint().bit_is_set() + || stat.aberrint().bit_is_set() + { + regs.intenclr().write(|w| { + w.txidleclr() + .set_bit() + .framerrclr() + .set_bit() + .parityerrclr() + .set_bit() + .rxnoiseclr() + .set_bit() + .aberrclr() + .set_bit() + }); + } + + waker.wake(); + } +} + +/// UART instance trait. +#[allow(private_bounds)] +pub trait Instance: crate::flexcomm::IntoUsart + SealedInstance + PeripheralType + 'static + Send { + /// Interrupt for this UART instance. + type Interrupt: interrupt::typelevel::Interrupt; +} + +macro_rules! impl_instance { + ($($n:expr),*) => { + $( + paste!{ + impl SealedInstance for crate::peripherals::[] { + fn info() -> Info { + Info { + regs: unsafe { &*crate::pac::[]::ptr() }, + index: $n, + refcnt: AtomicU8::new(0), + } + } + + #[inline] + fn index() -> usize { + $n + } + } + + impl Instance for crate::peripherals::[] { + type Interrupt = crate::interrupt::typelevel::[]; + } + } + )* + }; +} + +impl_instance!(0, 1, 2, 3, 4, 5, 6, 7); + +impl Sealed for T {} + +/// io configuration trait for Uart Tx configuration +pub trait TxPin: Pin + Sealed + PeripheralType { + /// convert the pin to appropriate function for Uart Tx usage + fn as_tx(&self); +} + +/// io configuration trait for Uart Rx configuration +pub trait RxPin: Pin + Sealed + PeripheralType { + /// convert the pin to appropriate function for Uart Rx usage + fn as_rx(&self); +} + +/// io configuration trait for Uart Cts +pub trait CtsPin: Pin + Sealed + PeripheralType { + /// convert the pin to appropriate function for Uart Cts usage + fn as_cts(&self); +} + +/// io configuration trait for Uart Rts +pub trait RtsPin: Pin + Sealed + PeripheralType { + /// convert the pin to appropriate function for Uart Rts usage + fn as_rts(&self); +} + +macro_rules! impl_pin_trait { + ($fcn:ident, $mode:ident, $($pin:ident, $fn:ident),*) => { + paste! { + $( + impl [<$mode:camel Pin>] for crate::peripherals::$pin { + fn [](&self) { + // UM11147 table 507 pg 495 + self.set_function(crate::iopctl::Function::$fn) + .set_pull(Pull::None) + .enable_input_buffer() + .set_slew_rate(SlewRate::Standard) + .set_drive_strength(DriveStrength::Normal) + .disable_analog_multiplex() + .set_drive_mode(DriveMode::PushPull) + .set_input_inverter(Inverter::Disabled); + } + } + )* + } + }; +} + +// FLEXCOMM0 +impl_pin_trait!(FLEXCOMM0, tx, PIO0_1, F1, PIO3_1, F5); +impl_pin_trait!(FLEXCOMM0, rx, PIO0_2, F1, PIO3_2, F5); +impl_pin_trait!(FLEXCOMM0, cts, PIO0_3, F1, PIO3_3, F5); +impl_pin_trait!(FLEXCOMM0, rts, PIO0_4, F1, PIO3_4, F5); + +// FLEXCOMM1 +impl_pin_trait!(FLEXCOMM1, tx, PIO0_8, F1, PIO7_26, F1); +impl_pin_trait!(FLEXCOMM1, rx, PIO0_9, F1, PIO7_27, F1); +impl_pin_trait!(FLEXCOMM1, cts, PIO0_10, F1, PIO7_28, F1); +impl_pin_trait!(FLEXCOMM1, rts, PIO0_11, F1, PIO7_29, F1); + +// FLEXCOMM2 +impl_pin_trait!(FLEXCOMM2, tx, PIO0_15, F1, PIO7_30, F5); +impl_pin_trait!(FLEXCOMM2, rx, PIO0_16, F1, PIO7_31, F5); +impl_pin_trait!(FLEXCOMM2, cts, PIO0_17, F1, PIO4_8, F5); +impl_pin_trait!(FLEXCOMM2, rts, PIO0_18, F1); + +// FLEXCOMM3 +impl_pin_trait!(FLEXCOMM3, tx, PIO0_22, F1); +impl_pin_trait!(FLEXCOMM3, rx, PIO0_23, F1); +impl_pin_trait!(FLEXCOMM3, cts, PIO0_24, F1); +impl_pin_trait!(FLEXCOMM3, rts, PIO0_25, F1); + +// FLEXCOMM4 +impl_pin_trait!(FLEXCOMM4, tx, PIO0_29, F1); +impl_pin_trait!(FLEXCOMM4, rx, PIO0_30, F1); +impl_pin_trait!(FLEXCOMM4, cts, PIO0_31, F1); +impl_pin_trait!(FLEXCOMM4, rts, PIO1_0, F1); + +// FLEXCOMM5 +impl_pin_trait!(FLEXCOMM5, tx, PIO1_4, F1, PIO3_16, F5); +impl_pin_trait!(FLEXCOMM5, rx, PIO1_5, F1, PIO3_17, F5); +impl_pin_trait!(FLEXCOMM5, cts, PIO1_6, F1, PIO3_18, F5); +impl_pin_trait!(FLEXCOMM5, rts, PIO1_7, F1, PIO3_23, F5); + +// FLEXCOMM6 +impl_pin_trait!(FLEXCOMM6, tx, PIO3_26, F1); +impl_pin_trait!(FLEXCOMM6, rx, PIO3_27, F1); +impl_pin_trait!(FLEXCOMM6, cts, PIO3_28, F1); +impl_pin_trait!(FLEXCOMM6, rts, PIO3_29, F1); + +// FLEXCOMM7 +impl_pin_trait!(FLEXCOMM7, tx, PIO4_1, F1); +impl_pin_trait!(FLEXCOMM7, rx, PIO4_2, F1); +impl_pin_trait!(FLEXCOMM7, cts, PIO4_3, F1); +impl_pin_trait!(FLEXCOMM7, rts, PIO4_4, F1); + +/// UART Tx DMA trait. +#[allow(private_bounds)] +pub trait TxDma: crate::dma::Channel {} + +/// UART Rx DMA trait. +#[allow(private_bounds)] +pub trait RxDma: crate::dma::Channel {} + +macro_rules! impl_dma { + ($fcn:ident, $mode:ident, $dma:ident) => { + paste! { + impl [<$mode Dma>] for crate::peripherals::$dma {} + } + }; +} + +impl_dma!(FLEXCOMM0, Rx, DMA0_CH0); +impl_dma!(FLEXCOMM0, Tx, DMA0_CH1); + +impl_dma!(FLEXCOMM1, Rx, DMA0_CH2); +impl_dma!(FLEXCOMM1, Tx, DMA0_CH3); + +impl_dma!(FLEXCOMM2, Rx, DMA0_CH4); +impl_dma!(FLEXCOMM2, Tx, DMA0_CH5); + +impl_dma!(FLEXCOMM3, Rx, DMA0_CH6); +impl_dma!(FLEXCOMM3, Tx, DMA0_CH7); + +impl_dma!(FLEXCOMM4, Rx, DMA0_CH8); +impl_dma!(FLEXCOMM4, Tx, DMA0_CH9); + +impl_dma!(FLEXCOMM5, Rx, DMA0_CH10); +impl_dma!(FLEXCOMM5, Tx, DMA0_CH11); + +impl_dma!(FLEXCOMM6, Rx, DMA0_CH12); +impl_dma!(FLEXCOMM6, Tx, DMA0_CH13); + +impl_dma!(FLEXCOMM7, Rx, DMA0_CH14); +impl_dma!(FLEXCOMM7, Tx, DMA0_CH15); diff --git a/embassy-imxrt/src/gpio.rs b/embassy-imxrt/src/gpio.rs index 6883c4ee0..e62fde8b1 100644 --- a/embassy-imxrt/src/gpio.rs +++ b/embassy-imxrt/src/gpio.rs @@ -13,7 +13,7 @@ use crate::clocks::enable_and_reset; use crate::iopctl::IopctlPin; pub use crate::iopctl::{AnyPin, DriveMode, DriveStrength, Function, Inverter, Pull, SlewRate}; use crate::sealed::Sealed; -use crate::{interrupt, peripherals, Peri, PeripheralType}; +use crate::{interrupt, peripherals, BitIter, Peri, PeripheralType}; // This should be unique per IMXRT package const PORT_COUNT: usize = 8; @@ -63,24 +63,6 @@ fn GPIO_INTA() { irq_handler(&GPIO_WAKERS); } -#[cfg(feature = "rt")] -struct BitIter(u32); - -#[cfg(feature = "rt")] -impl Iterator for BitIter { - type Item = u32; - - fn next(&mut self) -> Option { - match self.0.trailing_zeros() { - 32 => None, - b => { - self.0 &= !(1 << b); - Some(b) - } - } - } -} - #[cfg(feature = "rt")] fn irq_handler(port_wakers: &[Option<&PortWaker>]) { let reg = unsafe { crate::pac::Gpio::steal() }; diff --git a/embassy-imxrt/src/lib.rs b/embassy-imxrt/src/lib.rs index b1183d8fc..ad0d9e21c 100644 --- a/embassy-imxrt/src/lib.rs +++ b/embassy-imxrt/src/lib.rs @@ -19,6 +19,8 @@ pub(crate) mod fmt; pub mod clocks; pub mod crc; +pub mod dma; +pub mod flexcomm; pub mod gpio; pub mod iopctl; pub mod rng; @@ -129,14 +131,16 @@ pub fn init(config: config::Config) -> Peripherals { // before doing anything important. let peripherals = Peripherals::take(); + #[cfg(feature = "_time-driver")] + time_driver::init(config.time_interrupt_priority); + unsafe { if let Err(e) = clocks::init(config.clocks) { error!("unable to initialize Clocks for reason: {:?}", e); // Panic here? } + dma::init(); } - #[cfg(feature = "_time-driver")] - time_driver::init(config.time_interrupt_priority); gpio::init(); peripherals @@ -145,3 +149,21 @@ pub fn init(config: config::Config) -> Peripherals { pub(crate) mod sealed { pub trait Sealed {} } + +#[cfg(feature = "rt")] +struct BitIter(u32); + +#[cfg(feature = "rt")] +impl Iterator for BitIter { + type Item = u32; + + fn next(&mut self) -> Option { + match self.0.trailing_zeros() { + 32 => None, + b => { + self.0 &= !(1 << b); + Some(b) + } + } + } +} diff --git a/examples/mimxrt6/src/bin/uart-async.rs b/examples/mimxrt6/src/bin/uart-async.rs new file mode 100644 index 000000000..58e31f379 --- /dev/null +++ b/examples/mimxrt6/src/bin/uart-async.rs @@ -0,0 +1,87 @@ +#![no_std] +#![no_main] + +extern crate embassy_imxrt_examples; + +use defmt::info; +use embassy_executor::Spawner; +use embassy_imxrt::flexcomm::uart::{self, Async, Uart}; +use embassy_imxrt::{bind_interrupts, peripherals}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + FLEXCOMM2 => uart::InterruptHandler; + FLEXCOMM4 => uart::InterruptHandler; +}); + +const BUFLEN: usize = 16; + +#[embassy_executor::task] +async fn usart4_task(mut uart: Uart<'static, Async>) { + info!("RX Task"); + + loop { + let mut rx_buf = [0; BUFLEN]; + uart.read(&mut rx_buf).await.unwrap(); + info!("usart4: rx_buf {:02x}", rx_buf); + + Timer::after_millis(10).await; + + let tx_buf = [0xaa; BUFLEN]; + uart.write(&tx_buf).await.unwrap(); + info!("usart4: tx_buf {:02x}", tx_buf); + } +} + +#[embassy_executor::task] +async fn usart2_task(mut uart: Uart<'static, Async>) { + info!("TX Task"); + + loop { + let tx_buf = [0x55; BUFLEN]; + uart.write(&tx_buf).await.unwrap(); + info!("usart2: tx_buf {:02x}", tx_buf); + + Timer::after_millis(10).await; + + let mut rx_buf = [0x00; BUFLEN]; + uart.read(&mut rx_buf).await.unwrap(); + info!("usart2: rx_buf {:02x}", rx_buf); + } +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_imxrt::init(Default::default()); + + info!("UART test start"); + + let usart4 = Uart::new_with_rtscts( + p.FLEXCOMM4, + p.PIO0_29, + p.PIO0_30, + p.PIO1_0, + p.PIO0_31, + Irqs, + p.DMA0_CH9, + p.DMA0_CH8, + Default::default(), + ) + .unwrap(); + spawner.must_spawn(usart4_task(usart4)); + + let usart2 = Uart::new_with_rtscts( + p.FLEXCOMM2, + p.PIO0_15, + p.PIO0_16, + p.PIO0_18, + p.PIO0_17, + Irqs, + p.DMA0_CH5, + p.DMA0_CH4, + Default::default(), + ) + .unwrap(); + spawner.must_spawn(usart2_task(usart2)); +} diff --git a/examples/mimxrt6/src/bin/uart.rs b/examples/mimxrt6/src/bin/uart.rs new file mode 100644 index 000000000..d6a75f85d --- /dev/null +++ b/examples/mimxrt6/src/bin/uart.rs @@ -0,0 +1,55 @@ +#![no_std] +#![no_main] + +extern crate embassy_imxrt_examples; + +use defmt::info; +use embassy_executor::Spawner; +use embassy_imxrt::flexcomm::uart::{Blocking, Uart, UartRx, UartTx}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::task] +async fn usart4_task(mut uart: UartRx<'static, Blocking>) { + info!("RX Task"); + + loop { + let mut buf = [0; 8]; + + Timer::after_millis(10).await; + + uart.blocking_read(&mut buf).unwrap(); + + let s = core::str::from_utf8(&buf).unwrap(); + + info!("Received '{}'", s); + } +} + +#[embassy_executor::task] +async fn usart2_task(mut uart: UartTx<'static, Blocking>) { + info!("TX Task"); + + loop { + let buf = "Testing\0".as_bytes(); + + uart.blocking_write(buf).unwrap(); + + Timer::after_millis(10).await; + } +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_imxrt::init(Default::default()); + + info!("UART test start"); + + let usart4 = Uart::new_blocking(p.FLEXCOMM4, p.PIO0_29, p.PIO0_30, Default::default()).unwrap(); + + let (_, usart4) = usart4.split(); + spawner.must_spawn(usart4_task(usart4)); + + let usart2 = UartTx::new_blocking(p.FLEXCOMM2, p.PIO0_15, Default::default()).unwrap(); + spawner.must_spawn(usart2_task(usart2)); +} -- cgit From 117eb45fa0829239da9152b9cf54c3cf706dc76d Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Thu, 15 May 2025 17:53:31 +0200 Subject: add the possibility to document `bind_interrupts` `struct`s the `bind_interrupts` macro creates a `struct` for the interrupts. it was so far not possible to document those (except for STM32) and there was no generic documentation being generated/added either, thus the `missing_docs` lint was triggered for consumers which enabled it. with this change it is now possible to manually add a comment on the `struct` being defined in the macro invocation. to show that this works one RP example has been modified accordingly. --- embassy-imxrt/src/lib.rs | 12 ++++++++---- embassy-nrf/src/lib.rs | 12 ++++++++---- embassy-rp/src/lib.rs | 12 ++++++++---- embassy-stm32/src/lib.rs | 13 ++++++++----- examples/rp/src/bin/adc.rs | 9 ++++++--- 5 files changed, 38 insertions(+), 20 deletions(-) diff --git a/embassy-imxrt/src/lib.rs b/embassy-imxrt/src/lib.rs index b1183d8fc..5b7341fbd 100644 --- a/embassy-imxrt/src/lib.rs +++ b/embassy-imxrt/src/lib.rs @@ -54,16 +54,20 @@ pub use crate::pac::NVIC_PRIO_BITS; /// ```rust,ignore /// use embassy_imxrt::{bind_interrupts, flexspi, peripherals}; /// -/// bind_interrupts!(struct Irqs { -/// FLEXSPI_IRQ => flexspi::InterruptHandler; -/// }); +/// bind_interrupts!( +/// /// Binds the FLEXSPI interrupt. +/// struct Irqs { +/// FLEXSPI_IRQ => flexspi::InterruptHandler; +/// } +/// ); /// ``` /// // developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`. #[macro_export] macro_rules! bind_interrupts { - ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { + ($(#[$attr:meta])* $vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { #[derive(Copy, Clone)] + $(#[$attr])* $vis struct $name; $( diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 7d86e1218..0c5dd059d 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -200,9 +200,12 @@ mod chip; /// ```rust,ignore /// use embassy_nrf::{bind_interrupts, spim, peripherals}; /// -/// bind_interrupts!(struct Irqs { -/// SPIM3 => spim::InterruptHandler; -/// }); +/// bind_interrupts!( +/// /// Binds the SPIM3 interrupt. +/// struct Irqs { +/// SPIM3 => spim::InterruptHandler; +/// } +/// ); /// ``` /// /// Example of how to bind multiple interrupts in a single macro invocation: @@ -219,7 +222,7 @@ mod chip; // developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`. #[macro_export] macro_rules! bind_interrupts { - ($vis:vis struct $name:ident { + ($(#[$attr:meta])* $vis:vis struct $name:ident { $( $(#[cfg($cond_irq:meta)])? $irq:ident => $( @@ -229,6 +232,7 @@ macro_rules! bind_interrupts { )* }) => { #[derive(Copy, Clone)] + $(#[$attr])* $vis struct $name; $( diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index f549446bc..f3c5a35bb 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -160,15 +160,18 @@ embassy_hal_internal::interrupt_mod!( /// ```rust,ignore /// use embassy_rp::{bind_interrupts, usb, peripherals}; /// -/// bind_interrupts!(struct Irqs { -/// USBCTRL_IRQ => usb::InterruptHandler; -/// }); +/// bind_interrupts!( +/// /// Binds the USB Interrupts. +/// struct Irqs { +/// USBCTRL_IRQ => usb::InterruptHandler; +/// } +/// ); /// ``` /// // developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`. #[macro_export] macro_rules! bind_interrupts { - ($vis:vis struct $name:ident { + ($(#[$attr:meta])* $vis:vis struct $name:ident { $( $(#[cfg($cond_irq:meta)])? $irq:ident => $( @@ -178,6 +181,7 @@ macro_rules! bind_interrupts { )* }) => { #[derive(Copy, Clone)] + $(#[$attr])* $vis struct $name; $( diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index f8d09413d..973acc9bb 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -163,11 +163,14 @@ pub use crate::_generated::interrupt; /// ```rust,ignore /// use embassy_stm32::{bind_interrupts, i2c, peripherals}; /// -/// bind_interrupts!(struct Irqs { -/// I2C1 => i2c::EventInterruptHandler, i2c::ErrorInterruptHandler; -/// I2C2_3 => i2c::EventInterruptHandler, i2c::ErrorInterruptHandler, -/// i2c::EventInterruptHandler, i2c::ErrorInterruptHandler; -/// }); +/// bind_interrupts!( +/// /// Binds the I2C interrupts. +/// struct Irqs { +/// I2C1 => i2c::EventInterruptHandler, i2c::ErrorInterruptHandler; +/// I2C2_3 => i2c::EventInterruptHandler, i2c::ErrorInterruptHandler, +/// i2c::EventInterruptHandler, i2c::ErrorInterruptHandler; +/// } +/// ); /// ``` // developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`. diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index 1bb7c2249..015915586 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs @@ -12,9 +12,12 @@ use embassy_rp::gpio::Pull; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; -bind_interrupts!(struct Irqs { - ADC_IRQ_FIFO => InterruptHandler; -}); +bind_interrupts!( + /// Binds the ADC interrupts. + struct Irqs { + ADC_IRQ_FIFO => InterruptHandler; + } +); #[embassy_executor::main] async fn main(_spawner: Spawner) { -- cgit From 05bfbacee55207f8065b6e9bbbc0d5454e77668f Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Thu, 15 May 2025 18:36:51 +0200 Subject: `embassy-nxp`: make `defmt` optional also enable it on all dependencies (where available). this is needed because in a next commit we'll add code to `embassy-hal-internal` which uses the feature in a macro, as it expects `defmt` to be optional in all embassy HALs. this was the only HAL where that wasn't the case. note that this is a breaking change for consumers! if you wish to use `defmt` in `embassy-nxp` you now need to enable the feature. --- embassy-nxp/Cargo.toml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index cf36a67ec..031cd4aba 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -10,8 +10,11 @@ critical-section = "1.1.2" embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-sync = { version = "0.6.2", path = "../embassy-sync" } lpc55-pac = "0.5.0" -defmt = "0.3.8" +defmt = { version = "0.3.8", optional = true } [features] default = ["rt"] -rt = ["lpc55-pac/rt"] \ No newline at end of file +rt = ["lpc55-pac/rt"] + +## Enable [defmt support](https://docs.rs/defmt) and enables `defmt` debug-log messages and formatting in embassy drivers. +defmt = ["dep:defmt", "embassy-hal-internal/defmt", "embassy-sync/defmt"] -- cgit From 4a089fe2455f22f956455548816fcd96735e38d8 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Thu, 15 May 2025 17:29:23 +0200 Subject: rp: add missing `Debug` and `defmt::Format` `derive`s for ADC this doesn't cover every `struct` & co. in `embassy-rp`, but at least it adds those needed for `Adc` and `adc::Channel`. --- embassy-hal-internal/src/macros.rs | 2 ++ embassy-hal-internal/src/peripheral.rs | 2 ++ embassy-rp/src/adc.rs | 2 ++ embassy-rp/src/gpio.rs | 2 ++ 4 files changed, 8 insertions(+) diff --git a/embassy-hal-internal/src/macros.rs b/embassy-hal-internal/src/macros.rs index cd2bc3cab..ce72ded5c 100644 --- a/embassy-hal-internal/src/macros.rs +++ b/embassy-hal-internal/src/macros.rs @@ -8,6 +8,8 @@ macro_rules! peripherals_definition { $(#[$cfg])? #[allow(non_camel_case_types)] #[doc = concat!(stringify!($name), " peripheral")] + #[derive(Debug)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct $name { _private: () } $(#[$cfg])? diff --git a/embassy-hal-internal/src/peripheral.rs b/embassy-hal-internal/src/peripheral.rs index 803259bb8..b1868caf6 100644 --- a/embassy-hal-internal/src/peripheral.rs +++ b/embassy-hal-internal/src/peripheral.rs @@ -14,6 +14,8 @@ use core::ops::Deref; /// the driver code would be monomorphized two times. With Peri, the driver is generic /// over a lifetime only. `SPI4` becomes `Peri<'static, SPI4>`, and `&mut SPI4` becomes /// `Peri<'a, SPI4>`. Lifetimes don't cause monomorphization. +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Peri<'a, T: PeripheralType> { inner: T, _lifetime: PhantomData<&'a mut T>, diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs index ec0c8c46c..2db8e63d7 100644 --- a/embassy-rp/src/adc.rs +++ b/embassy-rp/src/adc.rs @@ -21,6 +21,8 @@ static WAKER: AtomicWaker = AtomicWaker::new(); #[derive(Default)] pub struct Config {} +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] enum Source<'p> { Pin(Peri<'p, AnyPin>), TempSensor(Peri<'p, ADC_TEMP_SENSOR>), diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index af0837f6a..2fb2d65c2 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs @@ -932,6 +932,8 @@ pub trait Pin: PeripheralType + Into + SealedPin + Sized + 'static { } /// Type-erased GPIO pin +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AnyPin { pin_bank: u8, } -- cgit From 466e1ee9eff2a40f562b0f970e3afcdeac017cfb Mon Sep 17 00:00:00 2001 From: Tobias Naumann Date: Fri, 16 May 2025 13:05:35 +0200 Subject: Impl Drop for stm32 Rng --- embassy-stm32/src/rng.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index 250a08a39..8fa1b3a9d 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs @@ -186,6 +186,15 @@ impl<'d, T: Instance> Rng<'d, T> { } } +impl<'d, T: Instance> Drop for Rng<'d, T> { + fn drop(&mut self) { + T::regs().cr().modify(|reg| { + reg.set_rngen(false); + }); + rcc::disable::(); + } +} + impl<'d, T: Instance> RngCore for Rng<'d, T> { fn next_u32(&mut self) -> u32 { loop { -- cgit From 1eb76eb59170f3953c390385fc572cf36536f652 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 16 May 2025 09:45:02 +0200 Subject: fix: add bank configuration doc build features --- embassy-stm32/Cargo.toml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 972307bec..873c9b6ae 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -19,16 +19,22 @@ flavors = [ { regex_feature = "stm32f1.*", target = "thumbv7m-none-eabi" }, { regex_feature = "stm32f2.*", target = "thumbv7m-none-eabi" }, { regex_feature = "stm32f3.*", target = "thumbv7em-none-eabi" }, - { regex_feature = "stm32f4.*", target = "thumbv7em-none-eabi", features = ["low-power"] }, + { regex_feature = "stm32f4[2367]..[ig]", target = "thumbv7em-none-eabi", features = ["low-power", "dual-bank"] }, + { regex_feature = "stm32f4.*", target = "thumbv7em-none-eabi", features = ["low-power", "single-bank"] }, + { regex_feature = "stm32f7[67]..[ig]", target = "thumbv7em-none-eabi", features = ["dual-bank"] }, { regex_feature = "stm32f7.*", target = "thumbv7em-none-eabi" }, { regex_feature = "stm32c0.*", target = "thumbv6m-none-eabi" }, + { regex_feature = "stm32g0...c", target = "thumbv6m-none-eabi", features = ["dual-bank"] }, { regex_feature = "stm32g0.*", target = "thumbv6m-none-eabi" }, + { regex_feature = "stm32g4[78].*", target = "thumbv7em-none-eabi", features = ["low-power", "dual-bank"] }, { regex_feature = "stm32g4.*", target = "thumbv7em-none-eabi", features = ["low-power"] }, { regex_feature = "stm32h5.*", target = "thumbv8m.main-none-eabihf", features = ["low-power"] }, { regex_feature = "stm32h7.*", target = "thumbv7em-none-eabi" }, { regex_feature = "stm32l0.*", target = "thumbv6m-none-eabi", features = ["low-power"] }, { regex_feature = "stm32l1.*", target = "thumbv7m-none-eabi" }, + { regex_feature = "stm32l4[pqrs].*", target = "thumbv7em-none-eabi", features = ["dual-bank"] }, { regex_feature = "stm32l4.*", target = "thumbv7em-none-eabi" }, + { regex_feature = "stm32l5...e", target = "thumbv8m.main-none-eabihf", features = ["low-power", "dual-bank"] }, { regex_feature = "stm32l5.*", target = "thumbv8m.main-none-eabihf", features = ["low-power"] }, { regex_feature = "stm32u0.*", target = "thumbv6m-none-eabi" }, { regex_feature = "stm32u5.*", target = "thumbv8m.main-none-eabihf" }, @@ -38,7 +44,7 @@ flavors = [ ] [package.metadata.docs.rs] -features = ["defmt", "unstable-pac", "exti", "time-driver-any", "time", "stm32h755zi-cm7"] +features = ["defmt", "unstable-pac", "exti", "time-driver-any", "time", "stm32h755zi-cm7", "single-bank"] rustdoc-args = ["--cfg", "docsrs"] [dependencies] -- cgit From e2d053e5a85bc0206b6d088f2b794211d0a46e96 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 16 May 2025 14:48:18 +0200 Subject: Fix a minor formatting issue in `README.md` --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 669fa469b..68d8460d3 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ Rust's [async/await](https://rust-lang.github.io/async-book/) allows for unprece ## Batteries included -- **Hardware Abstraction Layers - ** - HALs implement safe, idiomatic Rust APIs to use the hardware capabilities, so raw register manipulation is not needed. The Embassy project maintains HALs for select hardware, but you can still use HALs from other projects with Embassy. +- **Hardware Abstraction Layers** + - HALs implement safe, idiomatic Rust APIs to use the hardware capabilities, so raw register manipulation is not needed. The Embassy project maintains HALs for select hardware, but you can still use HALs from other projects with Embassy. - [embassy-stm32](https://docs.embassy.dev/embassy-stm32/), for all STM32 microcontroller families. - [embassy-nrf](https://docs.embassy.dev/embassy-nrf/), for the Nordic Semiconductor nRF52, nRF53, nRF54 and nRF91 series. - [embassy-rp](https://docs.embassy.dev/embassy-rp/), for the Raspberry Pi RP2040 and RP23xx microcontrollers. -- cgit From e4fc48764491f8981e4a145a72e9b6e72df8c546 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 18 May 2025 20:32:48 +0200 Subject: Add rand-core v0.9 support. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Aurélien Jacobs --- embassy-imxrt/Cargo.toml | 4 +- embassy-imxrt/src/rng.rs | 48 +++++++++++++--- embassy-nrf/Cargo.toml | 4 +- embassy-nrf/src/rng.rs | 47 +++++++++++----- embassy-rp/Cargo.toml | 4 +- embassy-rp/src/clocks.rs | 49 ++++++++++++++--- embassy-rp/src/trng.rs | 25 +++++++-- embassy-stm32/Cargo.toml | 4 +- embassy-stm32/src/rng.rs | 64 ++++++++++++++++------ examples/mimxrt6/Cargo.toml | 1 - examples/mimxrt6/src/bin/rng.rs | 7 +-- examples/nrf-rtos-trace/Cargo.toml | 1 - examples/nrf52840/Cargo.toml | 2 +- examples/nrf52840/src/bin/rng.rs | 2 +- examples/nrf5340/Cargo.toml | 1 - examples/rp/Cargo.toml | 3 +- examples/rp/src/bin/ethernet_w5500_icmp.rs | 1 - examples/rp/src/bin/ethernet_w5500_icmp_ping.rs | 1 - examples/rp/src/bin/ethernet_w5500_multisocket.rs | 1 - examples/rp/src/bin/ethernet_w5500_tcp_client.rs | 1 - examples/rp/src/bin/ethernet_w5500_tcp_server.rs | 1 - examples/rp/src/bin/ethernet_w5500_udp.rs | 1 - examples/rp/src/bin/orchestrate_tasks.rs | 1 - examples/rp/src/bin/sharing.rs | 1 - examples/rp/src/bin/spi_gc9a01.rs | 1 - examples/rp/src/bin/usb_ethernet.rs | 1 - examples/rp/src/bin/usb_hid_mouse.rs | 4 +- examples/rp/src/bin/wifi_ap_tcp_server.rs | 1 - examples/rp/src/bin/wifi_tcp_server.rs | 1 - examples/rp/src/bin/wifi_webrequest.rs | 1 - examples/rp235x/Cargo.toml | 1 - examples/rp235x/src/bin/sharing.rs | 1 - examples/rp235x/src/bin/trng.rs | 5 +- examples/std/Cargo.toml | 2 +- examples/std/src/bin/net.rs | 4 +- examples/std/src/bin/net_dns.rs | 4 +- examples/std/src/bin/net_ppp.rs | 4 +- examples/std/src/bin/net_udp.rs | 4 +- examples/std/src/bin/tcp_accept.rs | 4 +- examples/stm32f7/Cargo.toml | 1 - examples/stm32f7/src/bin/eth.rs | 1 - examples/stm32h5/Cargo.toml | 1 - examples/stm32h5/src/bin/eth.rs | 1 - examples/stm32h7/Cargo.toml | 1 - examples/stm32h7/src/bin/eth.rs | 1 - examples/stm32h7/src/bin/eth_client.rs | 1 - examples/stm32h7/src/bin/eth_client_mii.rs | 1 - examples/stm32h723/Cargo.toml | 1 - examples/stm32h742/Cargo.toml | 1 - examples/stm32h755cm4/Cargo.toml | 1 - examples/stm32h755cm7/Cargo.toml | 1 - examples/stm32h7b0/Cargo.toml | 1 - examples/stm32h7rs/Cargo.toml | 1 - examples/stm32h7rs/src/bin/eth.rs | 1 - examples/stm32l4/Cargo.toml | 1 - .../stm32l4/src/bin/spe_adin1110_http_server.rs | 1 - examples/stm32l5/Cargo.toml | 1 - examples/stm32l5/src/bin/usb_ethernet.rs | 1 - tests/rp/Cargo.toml | 1 - tests/rp/src/bin/ethernet_w5100s_perf.rs | 1 - tests/stm32/Cargo.toml | 4 +- tests/stm32/src/bin/eth.rs | 1 - tests/utils/Cargo.toml | 2 +- 63 files changed, 218 insertions(+), 122 deletions(-) mode change 100644 => 100755 examples/nrf52840/src/bin/rng.rs mode change 100644 => 100755 examples/rp/src/bin/usb_hid_mouse.rs diff --git a/embassy-imxrt/Cargo.toml b/embassy-imxrt/Cargo.toml index f16002a8d..d8cf3aaba 100644 --- a/embassy-imxrt/Cargo.toml +++ b/embassy-imxrt/Cargo.toml @@ -80,9 +80,11 @@ cortex-m = "0.7.6" critical-section = "1.1" embedded-io = { version = "0.6.1" } embedded-io-async = { version = "0.6.1" } -rand_core = "0.6.4" fixed = "1.23.1" +rand-core-06 = { package = "rand_core", version = "0.6" } +rand-core-09 = { package = "rand_core", version = "0.9" } + embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [ "unproven", ] } diff --git a/embassy-imxrt/src/rng.rs b/embassy-imxrt/src/rng.rs index 67e7ab65d..75f243df9 100644 --- a/embassy-imxrt/src/rng.rs +++ b/embassy-imxrt/src/rng.rs @@ -6,7 +6,6 @@ use core::task::Poll; use embassy_futures::block_on; use embassy_sync::waitqueue::AtomicWaker; -use rand_core::{CryptoRng, RngCore}; use crate::clocks::{enable_and_reset, SysconPeripheral}; use crate::interrupt::typelevel::Interrupt; @@ -201,32 +200,63 @@ impl<'d> Rng<'d> { .mctl() .modify(|_, w| w.trng_acc().set_bit().prgm().clear_bit()); } -} -impl RngCore for Rng<'_> { - fn next_u32(&mut self) -> u32 { + /// Generate a random u32 + pub fn blocking_next_u32(&mut self) -> u32 { let mut bytes = [0u8; 4]; block_on(self.async_fill_bytes(&mut bytes)).unwrap(); u32::from_ne_bytes(bytes) } - fn next_u64(&mut self) -> u64 { + /// Generate a random u64 + pub fn blocking_next_u64(&mut self) -> u64 { let mut bytes = [0u8; 8]; block_on(self.async_fill_bytes(&mut bytes)).unwrap(); u64::from_ne_bytes(bytes) } - fn fill_bytes(&mut self, dest: &mut [u8]) { + /// Fill a slice with random bytes. + pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) { block_on(self.async_fill_bytes(dest)).unwrap(); } +} - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { - self.fill_bytes(dest); +impl<'d> rand_core_06::RngCore for Rng<'d> { + fn next_u32(&mut self) -> u32 { + self.blocking_next_u32() + } + + fn next_u64(&mut self) -> u64 { + self.blocking_next_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.blocking_fill_bytes(dest); + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> { + self.blocking_fill_bytes(dest); Ok(()) } } -impl CryptoRng for Rng<'_> {} +impl<'d> rand_core_06::CryptoRng for Rng<'d> {} + +impl<'d> rand_core_09::RngCore for Rng<'d> { + fn next_u32(&mut self) -> u32 { + self.blocking_next_u32() + } + + fn next_u64(&mut self) -> u64 { + self.blocking_next_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.blocking_fill_bytes(dest); + } +} + +impl<'d> rand_core_09::CryptoRng for Rng<'d> {} struct Info { regs: crate::pac::Trng, diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 6ca099599..e4e143c65 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -154,6 +154,9 @@ embedded-hal-async = { version = "1.0" } embedded-io = { version = "0.6.0" } embedded-io-async = { version = "0.6.1" } +rand-core-06 = { package = "rand_core", version = "0.6" } +rand-core-09 = { package = "rand_core", version = "0.9" } + nrf-pac = "0.1.0" defmt = { version = "0.3", optional = true } @@ -162,7 +165,6 @@ log = { version = "0.4.14", optional = true } cortex-m-rt = ">=0.6.15,<0.8" cortex-m = "0.7.6" critical-section = "1.1" -rand_core = "0.6.3" fixed = "1.10.0" embedded-storage = "0.3.1" embedded-storage-async = "0.4.1" diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs index e75ffda00..7e42dc938 100644 --- a/embassy-nrf/src/rng.rs +++ b/embassy-nrf/src/rng.rs @@ -167,6 +167,21 @@ impl<'d, T: Instance> Rng<'d, T> { self.stop(); } + + /// Generate a random u32 + pub fn blocking_next_u32(&mut self) -> u32 { + let mut bytes = [0; 4]; + self.blocking_fill_bytes(&mut bytes); + // We don't care about the endianness, so just use the native one. + u32::from_ne_bytes(bytes) + } + + /// Generate a random u64 + pub fn blocking_next_u64(&mut self) -> u64 { + let mut bytes = [0; 8]; + self.blocking_fill_bytes(&mut bytes); + u64::from_ne_bytes(bytes) + } } impl<'d, T: Instance> Drop for Rng<'d, T> { @@ -180,31 +195,37 @@ impl<'d, T: Instance> Drop for Rng<'d, T> { } } -impl<'d, T: Instance> rand_core::RngCore for Rng<'d, T> { +impl<'d, T: Instance> rand_core_06::RngCore for Rng<'d, T> { fn fill_bytes(&mut self, dest: &mut [u8]) { self.blocking_fill_bytes(dest); } - fn next_u32(&mut self) -> u32 { - let mut bytes = [0; 4]; - self.blocking_fill_bytes(&mut bytes); - // We don't care about the endianness, so just use the native one. - u32::from_ne_bytes(bytes) + self.blocking_next_u32() } - fn next_u64(&mut self) -> u64 { - let mut bytes = [0; 8]; - self.blocking_fill_bytes(&mut bytes); - u64::from_ne_bytes(bytes) + self.blocking_next_u64() } - - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> { self.blocking_fill_bytes(dest); Ok(()) } } -impl<'d, T: Instance> rand_core::CryptoRng for Rng<'d, T> {} +impl<'d, T: Instance> rand_core_06::CryptoRng for Rng<'d, T> {} + +impl<'d, T: Instance> rand_core_09::RngCore for Rng<'d, T> { + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.blocking_fill_bytes(dest); + } + fn next_u32(&mut self) -> u32 { + self.blocking_next_u32() + } + fn next_u64(&mut self) -> u64 { + self.blocking_next_u64() + } +} + +impl<'d, T: Instance> rand_core_09::CryptoRng for Rng<'d, T> {} /// Peripheral static state pub(crate) struct State { diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 8fb8a50fd..849cb549a 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -157,7 +157,6 @@ embedded-io = { version = "0.6.1" } embedded-io-async = { version = "0.6.1" } embedded-storage = { version = "0.3" } embedded-storage-async = { version = "0.4.1" } -rand_core = "0.6.4" fixed = "1.28.0" rp-pac = { version = "7.0.0" } @@ -167,6 +166,9 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-hal-nb = { version = "1.0" } +rand-core-06 = { package = "rand_core", version = "0.6" } +rand-core-09 = { package = "rand_core", version = "0.9" } + pio = { version = "0.3" } rp2040-boot2 = "0.3" document-features = "0.2.10" diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 857877680..d79bffab3 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -1776,7 +1776,8 @@ impl<'d, T: GpoutPin> Drop for Gpout<'d, T> { pub struct RoscRng; impl RoscRng { - fn next_u8() -> u8 { + /// Get a random u8 + pub fn next_u8() -> u8 { let random_reg = pac::ROSC.randombit(); let mut acc = 0; for _ in 0..u8::BITS { @@ -1785,26 +1786,60 @@ impl RoscRng { } acc } + + /// Get a random u32 + pub fn next_u32(&mut self) -> u32 { + rand_core_09::impls::next_u32_via_fill(self) + } + + /// Get a random u64 + pub fn next_u64(&mut self) -> u64 { + rand_core_09::impls::next_u64_via_fill(self) + } + + /// Fill a slice with random bytes + pub fn fill_bytes(&mut self, dest: &mut [u8]) { + dest.fill_with(Self::next_u8) + } } -impl rand_core::RngCore for RoscRng { - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { - Ok(self.fill_bytes(dest)) +impl rand_core_06::RngCore for RoscRng { + fn next_u32(&mut self) -> u32 { + self.next_u32() + } + + fn next_u64(&mut self) -> u64 { + self.next_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.fill_bytes(dest); + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> { + self.fill_bytes(dest); + Ok(()) } +} + +impl rand_core_06::CryptoRng for RoscRng {} +impl rand_core_09::RngCore for RoscRng { fn next_u32(&mut self) -> u32 { - rand_core::impls::next_u32_via_fill(self) + self.next_u32() } fn next_u64(&mut self) -> u64 { - rand_core::impls::next_u64_via_fill(self) + self.next_u64() } fn fill_bytes(&mut self, dest: &mut [u8]) { - dest.fill_with(Self::next_u8) + self.fill_bytes(dest); } } +impl rand_core_09::CryptoRng for RoscRng {} + /// Enter the `DORMANT` sleep state. This will stop *all* internal clocks /// and can only be exited through resets, dormant-wake GPIO interrupts, /// and RTC interrupts. If RTC is clocked from an internal clock source diff --git a/embassy-rp/src/trng.rs b/embassy-rp/src/trng.rs index a8a0172be..a3f23c1f2 100644 --- a/embassy-rp/src/trng.rs +++ b/embassy-rp/src/trng.rs @@ -7,7 +7,6 @@ use core::task::Poll; use embassy_hal_internal::{Peri, PeripheralType}; use embassy_sync::waitqueue::AtomicWaker; -use rand_core::Error; use crate::interrupt::typelevel::{Binding, Interrupt}; use crate::peripherals::TRNG; @@ -369,7 +368,7 @@ impl<'d, T: Instance> Trng<'d, T> { } } -impl<'d, T: Instance> rand_core::RngCore for Trng<'d, T> { +impl<'d, T: Instance> rand_core_06::RngCore for Trng<'d, T> { fn next_u32(&mut self) -> u32 { self.blocking_next_u32() } @@ -379,16 +378,32 @@ impl<'d, T: Instance> rand_core::RngCore for Trng<'d, T> { } fn fill_bytes(&mut self, dest: &mut [u8]) { - self.blocking_fill_bytes(dest) + self.blocking_fill_bytes(dest); } - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> { self.blocking_fill_bytes(dest); Ok(()) } } -impl<'d, T: Instance> rand_core::CryptoRng for Trng<'d, T> {} +impl<'d, T: Instance> rand_core_06::CryptoRng for Trng<'d, T> {} + +impl<'d, T: Instance> rand_core_09::RngCore for Trng<'d, T> { + fn next_u32(&mut self) -> u32 { + self.blocking_next_u32() + } + + fn next_u64(&mut self) -> u64 { + self.blocking_next_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.blocking_fill_bytes(dest); + } +} + +impl<'d, T: Instance> rand_core_09::CryptoRng for Trng<'d, T> {} /// TRNG interrupt handler. pub struct InterruptHandler { diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 972307bec..35c1291fd 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -63,13 +63,15 @@ embedded-can = "0.4" embedded-storage = "0.3.1" embedded-storage-async = { version = "0.4.1" } +rand-core-06 = { package = "rand_core", version = "0.6" } +rand-core-09 = { package = "rand_core", version = "0.9" } + defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } cortex-m-rt = ">=0.6.15,<0.8" cortex-m = "0.7.6" futures-util = { version = "0.3.30", default-features = false } -rand_core = "0.6.3" sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index 8fa1b3a9d..312f343b9 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs @@ -7,7 +7,6 @@ use core::task::Poll; use embassy_hal_internal::PeripheralType; use embassy_sync::waitqueue::AtomicWaker; -use rand_core::{CryptoRng, RngCore}; use crate::interrupt::typelevel::Interrupt; use crate::{interrupt, pac, peripherals, rcc, Peri}; @@ -184,19 +183,9 @@ impl<'d, T: Instance> Rng<'d, T> { Ok(()) } -} - -impl<'d, T: Instance> Drop for Rng<'d, T> { - fn drop(&mut self) { - T::regs().cr().modify(|reg| { - reg.set_rngen(false); - }); - rcc::disable::(); - } -} -impl<'d, T: Instance> RngCore for Rng<'d, T> { - fn next_u32(&mut self) -> u32 { + /// Get a random u32 + pub fn next_u32(&mut self) -> u32 { loop { let sr = T::regs().sr().read(); if sr.seis() | sr.ceis() { @@ -207,13 +196,15 @@ impl<'d, T: Instance> RngCore for Rng<'d, T> { } } - fn next_u64(&mut self) -> u64 { + /// Get a random u64 + pub fn next_u64(&mut self) -> u64 { let mut rand = self.next_u32() as u64; rand |= (self.next_u32() as u64) << 32; rand } - fn fill_bytes(&mut self, dest: &mut [u8]) { + /// Fill a slice with random bytes + pub fn fill_bytes(&mut self, dest: &mut [u8]) { for chunk in dest.chunks_mut(4) { let rand = self.next_u32(); for (slot, num) in chunk.iter_mut().zip(rand.to_ne_bytes().iter()) { @@ -221,14 +212,53 @@ impl<'d, T: Instance> RngCore for Rng<'d, T> { } } } +} + +impl<'d, T: Instance> Drop for Rng<'d, T> { + fn drop(&mut self) { + T::regs().cr().modify(|reg| { + reg.set_rngen(false); + }); + rcc::disable::(); + } +} - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { +impl<'d, T: Instance> rand_core_06::RngCore for Rng<'d, T> { + fn next_u32(&mut self) -> u32 { + self.next_u32() + } + + fn next_u64(&mut self) -> u64 { + self.next_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.fill_bytes(dest); + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> { self.fill_bytes(dest); Ok(()) } } -impl<'d, T: Instance> CryptoRng for Rng<'d, T> {} +impl<'d, T: Instance> rand_core_06::CryptoRng for Rng<'d, T> {} + +impl<'d, T: Instance> rand_core_09::RngCore for Rng<'d, T> { + fn next_u32(&mut self) -> u32 { + self.next_u32() + } + + fn next_u64(&mut self) -> u64 { + self.next_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.fill_bytes(dest); + } +} + +impl<'d, T: Instance> rand_core_09::CryptoRng for Rng<'d, T> {} trait SealedInstance { fn regs() -> pac::rng::Rng; diff --git a/examples/mimxrt6/Cargo.toml b/examples/mimxrt6/Cargo.toml index b0c56f003..27c3a27dc 100644 --- a/examples/mimxrt6/Cargo.toml +++ b/examples/mimxrt6/Cargo.toml @@ -20,7 +20,6 @@ embedded-hal-async = "1.0.0" mimxrt600-fcb = "0.2.2" panic-probe = { version = "0.3", features = ["print-defmt"] } -rand = { version = "0.8.5", default-features = false } # cargo build/run [profile.dev] diff --git a/examples/mimxrt6/src/bin/rng.rs b/examples/mimxrt6/src/bin/rng.rs index 5f64cb96a..9468dd109 100644 --- a/examples/mimxrt6/src/bin/rng.rs +++ b/examples/mimxrt6/src/bin/rng.rs @@ -7,7 +7,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_imxrt::rng::Rng; use embassy_imxrt::{bind_interrupts, peripherals, rng}; -use rand::RngCore; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { @@ -29,10 +28,10 @@ async fn main(_spawner: Spawner) { // RngCore interface let mut random_bytes = [0; 16]; - let random_u32 = rng.next_u32(); - let random_u64 = rng.next_u64(); + let random_u32 = rng.blocking_next_u32(); + let random_u64 = rng.blocking_next_u64(); - rng.fill_bytes(&mut random_bytes); + rng.blocking_fill_bytes(&mut random_bytes); info!("random_u32 {}", random_u32); info!("random_u64 {}", random_u64); diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index af12212cd..ba609d889 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -23,7 +23,6 @@ embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["nrf5 cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" panic-probe = { version = "0.3" } -rand = { version = "0.8.4", default-features = false } serde = { version = "1.0.136", default-features = false } rtos-trace = "0.1.3" systemview-target = { version = "0.1.2", features = ["callbacks-app", "callbacks-os", "log", "cortex-m"] } diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 902193f3a..ff40a34af 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -25,7 +25,7 @@ static_cell = { version = "2" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" panic-probe = { version = "0.3", features = ["print-defmt"] } -rand = { version = "0.8.4", default-features = false } +rand = { version = "0.9.0", default-features = false } embedded-storage = "0.3.1" usbd-hid = "0.8.1" serde = { version = "1.0.136", default-features = false } diff --git a/examples/nrf52840/src/bin/rng.rs b/examples/nrf52840/src/bin/rng.rs old mode 100644 new mode 100755 index 326054c9a..f32d17cd9 --- a/examples/nrf52840/src/bin/rng.rs +++ b/examples/nrf52840/src/bin/rng.rs @@ -22,7 +22,7 @@ async fn main(_spawner: Spawner) { defmt::info!("Some random bytes: {:?}", bytes); // Sync API with `rand` - defmt::info!("A random number from 1 to 10: {:?}", rng.gen_range(1..=10)); + defmt::info!("A random number from 1 to 10: {:?}", rng.random_range(1..=10)); let mut bytes = [0; 1024]; rng.fill_bytes(&mut bytes).await; diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 459c43221..5c226695f 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -21,7 +21,6 @@ static_cell = "2" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" panic-probe = { version = "0.3", features = ["print-defmt"] } -rand = { version = "0.8.4", default-features = false } embedded-storage = "0.3.1" usbd-hid = "0.8.1" serde = { version = "1.0.136", default-features = false } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 45ca30e4c..aacf9846a 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -45,7 +45,6 @@ byte-slice-cast = { version = "1.2.0", default-features = false } smart-leds = "0.4.0" heapless = "0.8" usbd-hid = "0.8.1" -rand_core = "0.6.4" embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = "1.0" @@ -55,7 +54,7 @@ embedded-storage = { version = "0.3" } static_cell = "2.1" portable-atomic = { version = "1.5", features = ["critical-section"] } log = "0.4" -rand = { version = "0.8.5", default-features = false } +rand = { version = "0.9.0", default-features = false } embedded-sdmmc = "0.7.0" [profile.release] diff --git a/examples/rp/src/bin/ethernet_w5500_icmp.rs b/examples/rp/src/bin/ethernet_w5500_icmp.rs index 5c42b2dde..e434b3bbc 100644 --- a/examples/rp/src/bin/ethernet_w5500_icmp.rs +++ b/examples/rp/src/bin/ethernet_w5500_icmp.rs @@ -21,7 +21,6 @@ use embassy_rp::peripherals::SPI0; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; use embassy_time::{Delay, Instant, Timer}; use embedded_hal_bus::spi::ExclusiveDevice; -use rand::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs b/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs index 0724311f9..0ec594fd5 100644 --- a/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs +++ b/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs @@ -23,7 +23,6 @@ use embassy_rp::peripherals::SPI0; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; use embassy_time::{Delay, Duration}; use embedded_hal_bus::spi::ExclusiveDevice; -use rand::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index 2bea9fc9d..27e2f3c30 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -18,7 +18,6 @@ use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; use embassy_time::{Delay, Duration}; use embedded_hal_bus::spi::ExclusiveDevice; use embedded_io_async::Write; -use rand::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index 78d1b0b83..ba82f2a60 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -20,7 +20,6 @@ use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; use embassy_time::{Delay, Duration, Timer}; use embedded_hal_bus::spi::ExclusiveDevice; use embedded_io_async::Write; -use rand::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index 25a38c714..5c56dcafa 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -19,7 +19,6 @@ use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; use embassy_time::{Delay, Duration}; use embedded_hal_bus::spi::ExclusiveDevice; use embedded_io_async::Write; -use rand::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index 683e29222..c5fc8de1d 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -18,7 +18,6 @@ use embassy_rp::peripherals::SPI0; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; use embassy_time::Delay; use embedded_hal_bus::spi::ExclusiveDevice; -use rand::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/orchestrate_tasks.rs b/examples/rp/src/bin/orchestrate_tasks.rs index 5e2775793..c35679251 100644 --- a/examples/rp/src/bin/orchestrate_tasks.rs +++ b/examples/rp/src/bin/orchestrate_tasks.rs @@ -29,7 +29,6 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::mutex::Mutex; use embassy_sync::{channel, signal}; use embassy_time::{Duration, Timer}; -use rand::RngCore; use {defmt_rtt as _, panic_probe as _}; // Hardware resource assignment. See other examples for different ways of doing this. diff --git a/examples/rp/src/bin/sharing.rs b/examples/rp/src/bin/sharing.rs index 497c4f845..856be6ace 100644 --- a/examples/rp/src/bin/sharing.rs +++ b/examples/rp/src/bin/sharing.rs @@ -27,7 +27,6 @@ use embassy_rp::{bind_interrupts, interrupt}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::{blocking_mutex, mutex}; use embassy_time::{Duration, Ticker}; -use rand::RngCore; use static_cell::{ConstStaticCell, StaticCell}; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/spi_gc9a01.rs b/examples/rp/src/bin/spi_gc9a01.rs index 30afc253d..fdef09d4b 100644 --- a/examples/rp/src/bin/spi_gc9a01.rs +++ b/examples/rp/src/bin/spi_gc9a01.rs @@ -26,7 +26,6 @@ use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; use mipidsi::models::GC9A01; use mipidsi::options::{ColorInversion, ColorOrder}; use mipidsi::Builder; -use rand_core::RngCore; use {defmt_rtt as _, panic_probe as _}; const DISPLAY_FREQ: u32 = 64_000_000; diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 2add20bc6..171f21a75 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -17,7 +17,6 @@ use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::{Builder, Config, UsbDevice}; use embedded_io_async::Write; -use rand::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs old mode 100644 new mode 100755 index 5ee650910..4454c593c --- a/examples/rp/src/bin/usb_hid_mouse.rs +++ b/examples/rp/src/bin/usb_hid_mouse.rs @@ -85,8 +85,8 @@ async fn main(_spawner: Spawner) { _ = Timer::after_secs(1).await; let report = MouseReport { buttons: 0, - x: rng.gen_range(-100..100), // random small x movement - y: rng.gen_range(-100..100), // random small y movement + x: rng.random_range(-100..100), // random small x movement + y: rng.random_range(-100..100), // random small y movement wheel: 0, pan: 0, }; diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index e97ddb4c1..856838a8c 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs @@ -19,7 +19,6 @@ use embassy_rp::peripherals::{DMA_CH0, PIO0}; use embassy_rp::pio::{InterruptHandler, Pio}; use embassy_time::Duration; use embedded_io_async::Write; -use rand::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index 7e3c663fe..fbc957e0e 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -20,7 +20,6 @@ use embassy_rp::peripherals::{DMA_CH0, PIO0}; use embassy_rp::pio::{InterruptHandler, Pio}; use embassy_time::{Duration, Timer}; use embedded_io_async::Write; -use rand::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/wifi_webrequest.rs b/examples/rp/src/bin/wifi_webrequest.rs index f1b398b65..1efd1cd28 100644 --- a/examples/rp/src/bin/wifi_webrequest.rs +++ b/examples/rp/src/bin/wifi_webrequest.rs @@ -20,7 +20,6 @@ use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{DMA_CH0, PIO0}; use embassy_rp::pio::{InterruptHandler, Pio}; use embassy_time::{Duration, Timer}; -use rand::RngCore; use reqwless::client::{HttpClient, TlsConfig, TlsVerify}; use reqwless::request::Method; use serde::Deserialize; diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 345a915af..a247bc619 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -55,7 +55,6 @@ embedded-storage = { version = "0.3" } static_cell = "2.1" portable-atomic = { version = "1.5", features = ["critical-section"] } log = "0.4" -rand = { version = "0.8.5", default-features = false } embedded-sdmmc = "0.7.0" [profile.release] diff --git a/examples/rp235x/src/bin/sharing.rs b/examples/rp235x/src/bin/sharing.rs index 497c4f845..856be6ace 100644 --- a/examples/rp235x/src/bin/sharing.rs +++ b/examples/rp235x/src/bin/sharing.rs @@ -27,7 +27,6 @@ use embassy_rp::{bind_interrupts, interrupt}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::{blocking_mutex, mutex}; use embassy_time::{Duration, Ticker}; -use rand::RngCore; use static_cell::{ConstStaticCell, StaticCell}; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp235x/src/bin/trng.rs b/examples/rp235x/src/bin/trng.rs index ad19aef3e..100d6b104 100644 --- a/examples/rp235x/src/bin/trng.rs +++ b/examples/rp235x/src/bin/trng.rs @@ -10,7 +10,6 @@ use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::TRNG; use embassy_rp::trng::Trng; use embassy_time::Timer; -use rand::RngCore; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { @@ -33,8 +32,8 @@ async fn main(_spawner: Spawner) { info!("Random bytes async {}", &randomness); trng.blocking_fill_bytes(&mut randomness); info!("Random bytes blocking {}", &randomness); - let random_u32 = trng.next_u32(); - let random_u64 = trng.next_u64(); + let random_u32 = trng.blocking_next_u32(); + let random_u64 = trng.blocking_next_u64(); info!("Random u32 {} u64 {}", random_u32, random_u64); // Random number of blinks between 0 and 31 let blinks = random_u32 % 32; diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index f00953167..ff4b2fbbd 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -21,7 +21,7 @@ futures = { version = "0.3.17" } log = "0.4.14" nix = "0.26.2" clap = { version = "3.0.0-beta.5", features = ["derive"] } -rand_core = { version = "0.6.3", features = ["std"] } +rand_core = { version = "0.9.1", features = ["std", "os_rng"] } heapless = { version = "0.8", default-features = false } static_cell = "2" diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs index 6e50b1a01..232cf494b 100644 --- a/examples/std/src/bin/net.rs +++ b/examples/std/src/bin/net.rs @@ -9,7 +9,7 @@ use embassy_time::Duration; use embedded_io_async::Write; use heapless::Vec; use log::*; -use rand_core::{OsRng, RngCore}; +use rand_core::{OsRng, TryRngCore}; use static_cell::StaticCell; #[derive(Parser)] @@ -48,7 +48,7 @@ async fn main_task(spawner: Spawner) { // Generate random seed let mut seed = [0; 8]; - OsRng.fill_bytes(&mut seed); + OsRng.try_fill_bytes(&mut seed).unwrap(); let seed = u64::from_le_bytes(seed); // Init network stack diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs index a42c5dbb7..cf90731dd 100644 --- a/examples/std/src/bin/net_dns.rs +++ b/examples/std/src/bin/net_dns.rs @@ -5,7 +5,7 @@ use embassy_net::{Config, Ipv4Address, Ipv4Cidr, StackResources}; use embassy_net_tuntap::TunTapDevice; use heapless::Vec; use log::*; -use rand_core::{OsRng, RngCore}; +use rand_core::{OsRng, TryRngCore}; use static_cell::StaticCell; #[derive(Parser)] @@ -45,7 +45,7 @@ async fn main_task(spawner: Spawner) { // Generate random seed let mut seed = [0; 8]; - OsRng.fill_bytes(&mut seed); + OsRng.try_fill_bytes(&mut seed).unwrap(); let seed = u64::from_le_bytes(seed); // Init network stack diff --git a/examples/std/src/bin/net_ppp.rs b/examples/std/src/bin/net_ppp.rs index f667e8d4c..ac3aea6ff 100644 --- a/examples/std/src/bin/net_ppp.rs +++ b/examples/std/src/bin/net_ppp.rs @@ -23,7 +23,7 @@ use futures::io::BufReader; use heapless::Vec; use log::*; use nix::sys::termios; -use rand_core::{OsRng, RngCore}; +use rand_core::{OsRng, TryRngCore}; use static_cell::StaticCell; use crate::serial_port::SerialPort; @@ -89,7 +89,7 @@ async fn main_task(spawner: Spawner) { // Generate random seed let mut seed = [0; 8]; - OsRng.fill_bytes(&mut seed); + OsRng.try_fill_bytes(&mut seed).unwrap(); let seed = u64::from_le_bytes(seed); // Init network stack diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs index 02d4d3efb..53632a5b4 100644 --- a/examples/std/src/bin/net_udp.rs +++ b/examples/std/src/bin/net_udp.rs @@ -5,7 +5,7 @@ use embassy_net::{Config, Ipv4Address, Ipv4Cidr, StackResources}; use embassy_net_tuntap::TunTapDevice; use heapless::Vec; use log::*; -use rand_core::{OsRng, RngCore}; +use rand_core::{OsRng, TryRngCore}; use static_cell::StaticCell; #[derive(Parser)] @@ -44,7 +44,7 @@ async fn main_task(spawner: Spawner) { // Generate random seed let mut seed = [0; 8]; - OsRng.fill_bytes(&mut seed); + OsRng.try_fill_bytes(&mut seed).unwrap(); let seed = u64::from_le_bytes(seed); // Init network stack diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs index 18646a083..961c20e2d 100644 --- a/examples/std/src/bin/tcp_accept.rs +++ b/examples/std/src/bin/tcp_accept.rs @@ -7,7 +7,7 @@ use embassy_time::{Duration, Timer}; use embedded_io_async::Write as _; use heapless::Vec; use log::*; -use rand_core::{OsRng, RngCore}; +use rand_core::{OsRng, TryRngCore}; use static_cell::StaticCell; #[derive(Parser)] @@ -46,7 +46,7 @@ async fn main_task(spawner: Spawner) { // Generate random seed let mut seed = [0; 8]; - OsRng.fill_bytes(&mut seed); + OsRng.try_fill_bytes(&mut seed).unwrap(); let seed = u64::from_le_bytes(seed); // Init network stack diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 1a46931d9..94e0a80eb 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -24,7 +24,6 @@ embedded-hal = "0.2.6" panic-probe = { version = "0.3", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } nb = "1.0.0" -rand_core = "0.6.3" critical-section = "1.1" embedded-storage = "0.3.1" static_cell = "2" diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index 17ab7fc00..67a2b34bb 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs @@ -12,7 +12,6 @@ use embassy_stm32::time::Hertz; use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_time::Timer; use embedded_io_async::Write; -use rand_core::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 5631ff746..6fb14f422 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -26,7 +26,6 @@ embedded-io-async = { version = "0.6.1" } embedded-nal-async = "0.8.0" panic-probe = { version = "0.3", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } -rand_core = "0.6.3" critical-section = "1.1" micromath = "2.0.0" stm32-fmc = "0.3.0" diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 4034b552c..1d85cc1e7 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs @@ -15,7 +15,6 @@ use embassy_stm32::time::Hertz; use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_time::Timer; use embedded_io_async::Write; -use rand_core::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 2f98542bb..5035dacae 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -27,7 +27,6 @@ embedded-nal-async = "0.8.0" embedded-io-async = { version = "0.6.1" } panic-probe = { version = "0.3", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } -rand_core = "0.6.3" critical-section = "1.1" micromath = "2.0.0" stm32-fmc = "0.3.0" diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index da7aa4af5..fc14c1a70 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -11,7 +11,6 @@ use embassy_stm32::rng::Rng; use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_time::Timer; use embedded_io_async::Write; -use rand_core::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 10485109a..46301a478 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs @@ -14,7 +14,6 @@ use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_time::Timer; use embedded_io_async::Write; use embedded_nal_async::TcpConnect; -use rand_core::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/stm32h7/src/bin/eth_client_mii.rs b/examples/stm32h7/src/bin/eth_client_mii.rs index 849173615..99cd1a158 100644 --- a/examples/stm32h7/src/bin/eth_client_mii.rs +++ b/examples/stm32h7/src/bin/eth_client_mii.rs @@ -14,7 +14,6 @@ use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_time::Timer; use embedded_io_async::Write; use embedded_nal_async::TcpConnect; -use rand_core::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/stm32h723/Cargo.toml b/examples/stm32h723/Cargo.toml index 749fd78ae..f07d360b3 100644 --- a/examples/stm32h723/Cargo.toml +++ b/examples/stm32h723/Cargo.toml @@ -24,7 +24,6 @@ embedded-nal-async = "0.8.0" embedded-io-async = { version = "0.6.1" } panic-probe = { version = "0.3", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } -rand_core = "0.6.3" critical-section = "1.1" static_cell = "2" chrono = { version = "^0.4", default-features = false } diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml index e2e0094b8..3f936193c 100644 --- a/examples/stm32h742/Cargo.toml +++ b/examples/stm32h742/Cargo.toml @@ -51,7 +51,6 @@ embedded-hal = "0.2.6" panic-probe = { version = "0.3", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } nb = "1.0.0" -rand_core = "0.6.3" critical-section = "1.1" embedded-storage = "0.3.1" static_cell = "2" diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index 7c17bc766..c186ef19f 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -27,7 +27,6 @@ embedded-nal-async = "0.8.0" embedded-io-async = { version = "0.6.1" } panic-probe = { version = "0.3", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } -rand_core = "0.6.3" critical-section = "1.1" micromath = "2.0.0" stm32-fmc = "0.3.0" diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index 3186929a8..d37978e44 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -27,7 +27,6 @@ embedded-nal-async = "0.8.0" embedded-io-async = { version = "0.6.1" } panic-probe = { version = "0.3", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } -rand_core = "0.6.3" critical-section = "1.1" micromath = "2.0.0" stm32-fmc = "0.3.0" diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml index e5f2dfe86..dc8ecc684 100644 --- a/examples/stm32h7b0/Cargo.toml +++ b/examples/stm32h7b0/Cargo.toml @@ -26,7 +26,6 @@ embedded-nal-async = "0.8.0" embedded-io-async = { version = "0.6.1" } panic-probe = { version = "0.3", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } -rand_core = "0.6.3" critical-section = "1.1" micromath = "2.0.0" stm32-fmc = "0.3.0" diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml index 22d59be04..aee2703a1 100644 --- a/examples/stm32h7rs/Cargo.toml +++ b/examples/stm32h7rs/Cargo.toml @@ -26,7 +26,6 @@ embedded-nal-async = "0.8.0" embedded-io-async = { version = "0.6.1" } panic-probe = { version = "0.3", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } -rand_core = "0.6.3" critical-section = "1.1" micromath = "2.0.0" stm32-fmc = "0.3.0" diff --git a/examples/stm32h7rs/src/bin/eth.rs b/examples/stm32h7rs/src/bin/eth.rs index f2bd9575e..6d246bb09 100644 --- a/examples/stm32h7rs/src/bin/eth.rs +++ b/examples/stm32h7rs/src/bin/eth.rs @@ -11,7 +11,6 @@ use embassy_stm32::rng::Rng; use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_time::Timer; use heapless::Vec; -use rand_core::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 239bfcd79..cceec86dd 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -30,7 +30,6 @@ embedded-hal-bus = { version = "0.1", features = ["async"] } panic-probe = { version = "0.3", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } chrono = { version = "^0.4", default-features = false } -rand = { version = "0.8.5", default-features = false } static_cell = "2" micromath = "2.0.0" diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index 4a7c01f9f..354ac90b2 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs @@ -38,7 +38,6 @@ use embedded_io::Write as bWrite; use embedded_io_async::Write; use heapless::Vec; use panic_probe as _; -use rand::RngCore; use static_cell::StaticCell; bind_interrupts!(struct Irqs { diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 4c372a554..6962db7ea 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -23,7 +23,6 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" heapless = { version = "0.8", default-features = false } -rand_core = { version = "0.6.3", default-features = false } embedded-io-async = { version = "0.6.1" } static_cell = "2" diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index 809ec6ab1..6c72132c6 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs @@ -12,7 +12,6 @@ use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::{Builder, UsbDevice}; use embedded_io_async::Write; -use rand_core::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 1335aa84b..46dc820ab 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -38,7 +38,6 @@ embedded-io-async = { version = "0.6.1" } embedded-storage = { version = "0.3" } static_cell = "2" portable-atomic = { version = "1.5", features = ["critical-section"] } -rand = { version = "0.8.5", default-features = false } # bootsel not currently supported on 2350 [[bin]] diff --git a/tests/rp/src/bin/ethernet_w5100s_perf.rs b/tests/rp/src/bin/ethernet_w5100s_perf.rs index ae2adfa55..89e0ad32e 100644 --- a/tests/rp/src/bin/ethernet_w5100s_perf.rs +++ b/tests/rp/src/bin/ethernet_w5100s_perf.rs @@ -14,7 +14,6 @@ use embassy_rp::peripherals::SPI0; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; use embassy_time::Delay; use embedded_hal_bus::spi::ExclusiveDevice; -use rand::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 3a347e279..b230e619e 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -81,8 +81,8 @@ embedded-hal-async = { version = "1.0" } embedded-can = { version = "0.4" } micromath = "2.0.0" panic-probe = { version = "0.3.0", features = ["print-defmt"] } -rand_core = { version = "0.6", default-features = false } -rand_chacha = { version = "0.3", default-features = false } +rand_core = { version = "0.9.1", default-features = false } +rand_chacha = { version = "0.9.0", default-features = false } static_cell = "2" portable-atomic = { version = "1.5", features = [] } diff --git a/tests/stm32/src/bin/eth.rs b/tests/stm32/src/bin/eth.rs index a7e76fd8e..bcb362b42 100644 --- a/tests/stm32/src/bin/eth.rs +++ b/tests/stm32/src/bin/eth.rs @@ -11,7 +11,6 @@ use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; use embassy_stm32::peripherals::ETH; use embassy_stm32::rng::Rng; use embassy_stm32::{bind_interrupts, eth, peripherals, rng}; -use rand_core::RngCore; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/tests/utils/Cargo.toml b/tests/utils/Cargo.toml index 7b54a4f52..bda55ad32 100644 --- a/tests/utils/Cargo.toml +++ b/tests/utils/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -rand = "0.8" +rand = "0.9" serial = "0.4" -- cgit From ef0f29f0ede245671ffd82fcf384a9105f174c24 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 18 May 2025 20:51:15 +0200 Subject: Update defmt dependencies --- cyw43-pio/Cargo.toml | 2 +- cyw43/Cargo.toml | 2 +- docs/examples/basic/Cargo.toml | 6 +++--- docs/examples/layer-by-layer/blinky-async/Cargo.toml | 6 +++--- docs/examples/layer-by-layer/blinky-hal/Cargo.toml | 6 +++--- docs/examples/layer-by-layer/blinky-irq/Cargo.toml | 6 +++--- docs/examples/layer-by-layer/blinky-pac/Cargo.toml | 6 +++--- embassy-boot-nrf/Cargo.toml | 2 +- embassy-boot-rp/Cargo.toml | 2 +- embassy-boot-stm32/Cargo.toml | 2 +- embassy-boot/Cargo.toml | 2 +- embassy-embedded-hal/Cargo.toml | 2 +- embassy-executor/Cargo.toml | 2 +- embassy-futures/Cargo.toml | 2 +- embassy-hal-internal/Cargo.toml | 2 +- embassy-imxrt/Cargo.toml | 2 +- embassy-mspm0/Cargo.toml | 2 +- embassy-net-adin1110/Cargo.toml | 4 ++-- embassy-net-driver-channel/Cargo.toml | 2 +- embassy-net-driver/Cargo.toml | 2 +- embassy-net-enc28j60/Cargo.toml | 2 +- embassy-net-esp-hosted/Cargo.toml | 6 +++--- embassy-net-nrf91/Cargo.toml | 12 ++++++------ embassy-net-ppp/Cargo.toml | 2 +- embassy-net-wiznet/Cargo.toml | 2 +- embassy-net/Cargo.toml | 2 +- embassy-nrf/Cargo.toml | 2 +- embassy-nxp/Cargo.toml | 2 +- embassy-rp/Cargo.toml | 2 +- embassy-stm32-wpan/Cargo.toml | 2 +- embassy-stm32/Cargo.toml | 2 +- embassy-sync/Cargo.toml | 2 +- embassy-time/Cargo.toml | 2 +- embassy-usb-dfu/Cargo.toml | 2 +- embassy-usb-driver/Cargo.toml | 2 +- embassy-usb-synopsys-otg/Cargo.toml | 2 +- embassy-usb/Cargo.toml | 4 ++-- examples/boot/application/nrf/Cargo.toml | 4 ++-- examples/boot/application/rp/Cargo.toml | 6 +++--- examples/boot/application/stm32f3/Cargo.toml | 4 ++-- examples/boot/application/stm32f7/Cargo.toml | 4 ++-- examples/boot/application/stm32h7/Cargo.toml | 4 ++-- examples/boot/application/stm32l0/Cargo.toml | 4 ++-- examples/boot/application/stm32l1/Cargo.toml | 4 ++-- examples/boot/application/stm32l4/Cargo.toml | 4 ++-- examples/boot/application/stm32wb-dfu/Cargo.toml | 4 ++-- examples/boot/application/stm32wl/Cargo.toml | 4 ++-- examples/boot/bootloader/nrf/Cargo.toml | 4 ++-- examples/boot/bootloader/rp/Cargo.toml | 4 ++-- examples/boot/bootloader/stm32-dual-bank/Cargo.toml | 4 ++-- examples/boot/bootloader/stm32/Cargo.toml | 4 ++-- examples/boot/bootloader/stm32wb-dfu/Cargo.toml | 4 ++-- examples/lpc55s69/Cargo.toml | 8 ++++---- examples/mimxrt6/Cargo.toml | 6 +++--- examples/mspm0c1104/Cargo.toml | 8 ++++---- examples/mspm0g3507/Cargo.toml | 8 ++++---- examples/mspm0g3519/Cargo.toml | 8 ++++---- examples/mspm0l1306/Cargo.toml | 8 ++++---- examples/mspm0l2228/Cargo.toml | 8 ++++---- examples/nrf-rtos-trace/Cargo.toml | 2 +- examples/nrf51/Cargo.toml | 6 +++--- examples/nrf52810/Cargo.toml | 6 +++--- examples/nrf52840-rtic/Cargo.toml | 6 +++--- examples/nrf52840/Cargo.toml | 6 +++--- examples/nrf5340/Cargo.toml | 6 +++--- examples/nrf54l15/Cargo.toml | 6 +++--- examples/nrf9151/ns/Cargo.toml | 6 +++--- examples/nrf9151/s/Cargo.toml | 6 +++--- examples/nrf9160/Cargo.toml | 6 +++--- examples/rp/Cargo.toml | 6 +++--- examples/rp235x/Cargo.toml | 6 +++--- examples/stm32c0/Cargo.toml | 6 +++--- examples/stm32f0/Cargo.toml | 6 +++--- examples/stm32f1/Cargo.toml | 6 +++--- examples/stm32f2/Cargo.toml | 6 +++--- examples/stm32f3/Cargo.toml | 6 +++--- examples/stm32f334/Cargo.toml | 6 +++--- examples/stm32f4/Cargo.toml | 6 +++--- examples/stm32f469/Cargo.toml | 6 +++--- examples/stm32f7/Cargo.toml | 6 +++--- examples/stm32g0/Cargo.toml | 6 +++--- examples/stm32g4/Cargo.toml | 6 +++--- examples/stm32h5/Cargo.toml | 6 +++--- examples/stm32h7/Cargo.toml | 6 +++--- examples/stm32h723/Cargo.toml | 6 +++--- examples/stm32h735/Cargo.toml | 6 +++--- examples/stm32h742/Cargo.toml | 6 +++--- examples/stm32h755cm4/Cargo.toml | 6 +++--- examples/stm32h755cm7/Cargo.toml | 6 +++--- examples/stm32h7b0/Cargo.toml | 6 +++--- examples/stm32h7rs/Cargo.toml | 6 +++--- examples/stm32l0/Cargo.toml | 6 +++--- examples/stm32l1/Cargo.toml | 6 +++--- examples/stm32l4/Cargo.toml | 6 +++--- examples/stm32l432/Cargo.toml | 6 +++--- examples/stm32l5/Cargo.toml | 6 +++--- examples/stm32u0/Cargo.toml | 6 +++--- examples/stm32u5/Cargo.toml | 6 +++--- examples/stm32wb/Cargo.toml | 10 +++++----- examples/stm32wba/Cargo.toml | 10 +++++----- examples/stm32wl/Cargo.toml | 6 +++--- rustfmt.toml | 2 +- tests/mspm0/Cargo.toml | 2 +- tests/nrf/Cargo.toml | 6 +++--- tests/perf-client/Cargo.toml | 2 +- tests/rp/Cargo.toml | 6 +++--- tests/stm32/Cargo.toml | 6 +++--- 107 files changed, 254 insertions(+), 254 deletions(-) diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index 600caf5ed..93a2e7089 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -13,7 +13,7 @@ documentation = "https://docs.embassy.dev/cyw43-pio" cyw43 = { version = "0.3.0", path = "../cyw43" } embassy-rp = { version = "0.4.0", path = "../embassy-rp" } fixed = "1.23.1" -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/cyw43-pio-v$VERSION/cyw43-pio/src/" diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index 88d1fe506..4b58ee9c9 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -23,7 +23,7 @@ embassy-sync = { version = "0.6.2", path = "../embassy-sync"} embassy-futures = { version = "0.1.0", path = "../embassy-futures"} embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel"} -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.17", optional = true } cortex-m = "0.7.6" diff --git a/docs/examples/basic/Cargo.toml b/docs/examples/basic/Cargo.toml index 705c334a7..f5cf2b231 100644 --- a/docs/examples/basic/Cargo.toml +++ b/docs/examples/basic/Cargo.toml @@ -10,9 +10,9 @@ embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", feat embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt"] } embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } -defmt = "0.3" -defmt-rtt = "0.3" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } diff --git a/docs/examples/layer-by-layer/blinky-async/Cargo.toml b/docs/examples/layer-by-layer/blinky-async/Cargo.toml index 541eb6edf..2a6741b33 100644 --- a/docs/examples/layer-by-layer/blinky-async/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-async/Cargo.toml @@ -10,6 +10,6 @@ cortex-m-rt = "0.7" embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x", "exti"] } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3.0", features = ["print-defmt"] } +defmt = "1.0.1" +defmt-rtt = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } diff --git a/docs/examples/layer-by-layer/blinky-hal/Cargo.toml b/docs/examples/layer-by-layer/blinky-hal/Cargo.toml index dd574c3e7..9a261f804 100644 --- a/docs/examples/layer-by-layer/blinky-hal/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-hal/Cargo.toml @@ -9,6 +9,6 @@ cortex-m-rt = "0.7" cortex-m = { version = "0.7", features = ["critical-section-single-core"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x"] } -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3.0", features = ["print-defmt"] } +defmt = "1.0.1" +defmt-rtt = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } diff --git a/docs/examples/layer-by-layer/blinky-irq/Cargo.toml b/docs/examples/layer-by-layer/blinky-irq/Cargo.toml index 8733ee894..c3ec9ad1a 100644 --- a/docs/examples/layer-by-layer/blinky-irq/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-irq/Cargo.toml @@ -11,6 +11,6 @@ cortex-m = { version = "0.7", features = ["critical-section-single-core"] } cortex-m-rt = { version = "0.7" } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x", "unstable-pac"] } -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3.0", features = ["print-defmt"] } +defmt = "1.0.1" +defmt-rtt = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } diff --git a/docs/examples/layer-by-layer/blinky-pac/Cargo.toml b/docs/examples/layer-by-layer/blinky-pac/Cargo.toml index 155c41ec6..4e7e2f2ff 100644 --- a/docs/examples/layer-by-layer/blinky-pac/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-pac/Cargo.toml @@ -9,6 +9,6 @@ cortex-m = { version = "0.7", features = ["critical-section-single-core"] } cortex-m-rt = "0.7" stm32-metapac = { version = "16", features = ["stm32l475vg"] } -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3.0", features = ["print-defmt"] } +defmt = "1.0.1" +defmt-rtt = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index c3e0cb5ec..7d3e04419 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -21,7 +21,7 @@ target = "thumbv7em-none-eabi" [lib] [dependencies] -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.17", optional = true } embassy-sync = { version = "0.6.2", path = "../embassy-sync" } diff --git a/embassy-boot-rp/Cargo.toml b/embassy-boot-rp/Cargo.toml index 284ac654c..10eec774f 100644 --- a/embassy-boot-rp/Cargo.toml +++ b/embassy-boot-rp/Cargo.toml @@ -21,7 +21,7 @@ features = ["embassy-rp/rp2040"] [lib] [dependencies] -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4", optional = true } embassy-sync = { version = "0.6.2", path = "../embassy-sync" } diff --git a/embassy-boot-stm32/Cargo.toml b/embassy-boot-stm32/Cargo.toml index 7dbe7e22b..2b741cc95 100644 --- a/embassy-boot-stm32/Cargo.toml +++ b/embassy-boot-stm32/Cargo.toml @@ -21,7 +21,7 @@ target = "thumbv7em-none-eabi" [lib] [dependencies] -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4", optional = true } embassy-sync = { version = "0.6.2", path = "../embassy-sync" } diff --git a/embassy-boot/Cargo.toml b/embassy-boot/Cargo.toml index 4906da0ea..8889f1a20 100644 --- a/embassy-boot/Cargo.toml +++ b/embassy-boot/Cargo.toml @@ -24,7 +24,7 @@ features = ["defmt"] [lib] [dependencies] -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } digest = "0.10" log = { version = "0.4", optional = true } ed25519-dalek = { version = "2", default-features = false, features = ["digest"], optional = true } diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index f385963f1..f7a973a8d 100644 --- a/embassy-embedded-hal/Cargo.toml +++ b/embassy-embedded-hal/Cargo.toml @@ -35,7 +35,7 @@ embedded-storage = "0.3.1" embedded-storage-async = { version = "0.4.1" } nb = "1.0.0" -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } [dev-dependencies] critical-section = { version = "1.1.1", features = ["std"] } diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 0f69d3c8a..9f9eaa600 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -29,7 +29,7 @@ targets = ["thumbv7em-none-eabi"] features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"] [dependencies] -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } rtos-trace = { version = "0.1.3", optional = true } diff --git a/embassy-futures/Cargo.toml b/embassy-futures/Cargo.toml index 47cefa56f..0deab0165 100644 --- a/embassy-futures/Cargo.toml +++ b/embassy-futures/Cargo.toml @@ -24,5 +24,5 @@ target = "thumbv7em-none-eabi" features = ["defmt"] [dependencies] -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } diff --git a/embassy-hal-internal/Cargo.toml b/embassy-hal-internal/Cargo.toml index d5ca95ac2..cc360682e 100644 --- a/embassy-hal-internal/Cargo.toml +++ b/embassy-hal-internal/Cargo.toml @@ -28,7 +28,7 @@ prio-bits-8 = [] cortex-m = ["dep:cortex-m", "dep:critical-section"] [dependencies] -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } num-traits = { version = "0.2.14", default-features = false } diff --git a/embassy-imxrt/Cargo.toml b/embassy-imxrt/Cargo.toml index d8cf3aaba..231a80251 100644 --- a/embassy-imxrt/Cargo.toml +++ b/embassy-imxrt/Cargo.toml @@ -71,7 +71,7 @@ embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", fe embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false } embassy-futures = { version = "0.1.1", path = "../embassy-futures" } -defmt = { version = "1.0", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } nb = "1.0.0" cfg-if = "1.0.0" diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index df996ff4b..877d1ae18 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -38,7 +38,7 @@ embassy-executor = { version = "0.7.0", path = "../embassy-executor", optional = embedded-hal = { version = "1.0" } embedded-hal-async = { version = "1.0" } -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } fixed = "1.29" log = { version = "0.4.14", optional = true } cortex-m-rt = ">=0.6.15,<0.8" diff --git a/embassy-net-adin1110/Cargo.toml b/embassy-net-adin1110/Cargo.toml index 22d494b84..a620928cb 100644 --- a/embassy-net-adin1110/Cargo.toml +++ b/embassy-net-adin1110/Cargo.toml @@ -11,7 +11,7 @@ documentation = "https://docs.embassy.dev/embassy-net-adin1110" [dependencies] heapless = "0.8" -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4", default-features = false, optional = true } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } @@ -29,7 +29,7 @@ critical-section = { version = "1.1.2", features = ["std"] } futures-test = "0.3.28" [features] -defmt = [ "dep:defmt", "embedded-hal-1/defmt-03" ] +defmt = ["dep:defmt", "embedded-hal-1/defmt-03"] log = ["dep:log"] [package.metadata.embassy_docs] diff --git a/embassy-net-driver-channel/Cargo.toml b/embassy-net-driver-channel/Cargo.toml index 5165621b7..beadbf3c9 100644 --- a/embassy-net-driver-channel/Cargo.toml +++ b/embassy-net-driver-channel/Cargo.toml @@ -22,7 +22,7 @@ target = "thumbv7em-none-eabi" features = ["defmt"] [dependencies] -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } embassy-sync = { version = "0.6.2", path = "../embassy-sync" } diff --git a/embassy-net-driver/Cargo.toml b/embassy-net-driver/Cargo.toml index 97e8a0db3..34bc6c91a 100644 --- a/embassy-net-driver/Cargo.toml +++ b/embassy-net-driver/Cargo.toml @@ -22,4 +22,4 @@ target = "thumbv7em-none-eabi" features = ["defmt"] [dependencies] -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } diff --git a/embassy-net-enc28j60/Cargo.toml b/embassy-net-enc28j60/Cargo.toml index 74f94816a..b26be1420 100644 --- a/embassy-net-enc28j60/Cargo.toml +++ b/embassy-net-enc28j60/Cargo.toml @@ -16,7 +16,7 @@ embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } embassy-time = { version = "0.4.0", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } [package.metadata.embassy_docs] diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml index bab0e6d7c..0cb99e67e 100644 --- a/embassy-net-esp-hosted/Cargo.toml +++ b/embassy-net-esp-hosted/Cargo.toml @@ -10,11 +10,11 @@ repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/embassy-net-esp-hosted" [features] -defmt = [ "dep:defmt", "heapless/defmt-03" ] -log = [ "dep:log" ] +defmt = ["dep:defmt", "heapless/defmt-03"] +log = ["dep:log"] [dependencies] -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time" } diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml index 99ec5a318..de12ac36f 100644 --- a/embassy-net-nrf91/Cargo.toml +++ b/embassy-net-nrf91/Cargo.toml @@ -10,20 +10,20 @@ repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/embassy-net-nrf91" [features] -defmt = [ "dep:defmt", "heapless/defmt-03" ] -log = [ "dep:log" ] +defmt = ["dep:defmt", "heapless/defmt-03"] +log = ["dep:log"] [dependencies] -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } nrf-pac = "0.1.0" cortex-m = "0.7.7" embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-sync = { version = "0.6.2", path = "../embassy-sync"} -embassy-futures = { version = "0.1.0", path = "../embassy-futures"} -embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel"} +embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } heapless = "0.8" embedded-io = "0.6.1" diff --git a/embassy-net-ppp/Cargo.toml b/embassy-net-ppp/Cargo.toml index 2d82e2ad0..ab713fed8 100644 --- a/embassy-net-ppp/Cargo.toml +++ b/embassy-net-ppp/Cargo.toml @@ -14,7 +14,7 @@ defmt = ["dep:defmt", "ppproto/defmt"] log = ["dep:log", "ppproto/log"] [dependencies] -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } embedded-io-async = { version = "0.6.1" } diff --git a/embassy-net-wiznet/Cargo.toml b/embassy-net-wiznet/Cargo.toml index 2ad5a6f48..a06a09302 100644 --- a/embassy-net-wiznet/Cargo.toml +++ b/embassy-net-wiznet/Cargo.toml @@ -15,7 +15,7 @@ embedded-hal-async = { version = "1.0" } embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } embassy-time = { version = "0.4.0", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-wiznet-v$VERSION/embassy-net-wiznet/src/" diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index c3bf1acbc..d96481f98 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -68,7 +68,7 @@ alloc = ["smoltcp/alloc"] [dependencies] -defmt = { version = "0.3.8", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } smoltcp = { version = "0.12.0", default-features = false, features = [ diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index e4e143c65..e4f40630e 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -159,7 +159,7 @@ rand-core-09 = { package = "rand_core", version = "0.9" } nrf-pac = "0.1.0" -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } bitflags = "2.4.2" log = { version = "0.4.14", optional = true } cortex-m-rt = ">=0.6.15,<0.8" diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 031cd4aba..86a989aa7 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -10,7 +10,7 @@ critical-section = "1.1.2" embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-sync = { version = "0.6.2", path = "../embassy-sync" } lpc55-pac = "0.5.0" -defmt = { version = "0.3.8", optional = true } +defmt = { version = "1", optional = true } [features] default = ["rt"] diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 849cb549a..3c18a8f77 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -145,7 +145,7 @@ embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", fe embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal" } embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } atomic-polyfill = "1.0.1" -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } nb = "1.1.0" cfg-if = "1.0.0" diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 3bcfd11a9..81af6aedd 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -27,7 +27,7 @@ embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal" } embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver", optional=true } -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.17", optional = true } cortex-m = "0.7.6" diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 35c1291fd..d898f7ff3 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -67,7 +67,7 @@ rand-core-06 = { package = "rand_core", version = "0.6" } rand-core-09 = { package = "rand_core", version = "0.9" } -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } cortex-m-rt = ">=0.6.15,<0.8" cortex-m = "0.7.6" diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml index 92ee38ed9..65cade317 100644 --- a/embassy-sync/Cargo.toml +++ b/embassy-sync/Cargo.toml @@ -24,7 +24,7 @@ std = [] turbowakers = [] [dependencies] -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } futures-sink = { version = "0.3", default-features = false, features = [] } diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index dc144ec3c..76983d880 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml @@ -420,7 +420,7 @@ tick-hz-5_242_880_000 = ["embassy-time-driver/tick-hz-5_242_880_000"] embassy-time-driver = { version = "0.2", path = "../embassy-time-driver" } embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true} -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6" } diff --git a/embassy-usb-dfu/Cargo.toml b/embassy-usb-dfu/Cargo.toml index eba902c74..ccf8a16eb 100644 --- a/embassy-usb-dfu/Cargo.toml +++ b/embassy-usb-dfu/Cargo.toml @@ -26,7 +26,7 @@ flavors = [ features = ["defmt", "cortex-m", "dfu"] [dependencies] -defmt = { version = "0.3.5", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.17", optional = true } bitflags = "2.4.1" diff --git a/embassy-usb-driver/Cargo.toml b/embassy-usb-driver/Cargo.toml index edb6551b0..e40421649 100644 --- a/embassy-usb-driver/Cargo.toml +++ b/embassy-usb-driver/Cargo.toml @@ -19,5 +19,5 @@ target = "thumbv7em-none-eabi" features = ["defmt"] [dependencies] -defmt = { version = "0.3", optional = true } embedded-io-async = "0.6.1" +defmt = { version = "1", optional = true } diff --git a/embassy-usb-synopsys-otg/Cargo.toml b/embassy-usb-synopsys-otg/Cargo.toml index f9703a54a..98fc044ce 100644 --- a/embassy-usb-synopsys-otg/Cargo.toml +++ b/embassy-usb-synopsys-otg/Cargo.toml @@ -21,5 +21,5 @@ critical-section = "1.1" embassy-sync = { version = "0.6.2", path = "../embassy-sync" } embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } -defmt = { version = "0.3", optional = true } +defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml index 4950fbe2a..e52f4602d 100644 --- a/embassy-usb/Cargo.toml +++ b/embassy-usb/Cargo.toml @@ -51,10 +51,10 @@ embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } embassy-sync = { version = "0.6.2", path = "../embassy-sync" } embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } -defmt = { version = "0.3", optional = true } -embedded-io-async = "0.6.1" +defmt = { version = "1", optional = true } log = { version = "0.4.14", optional = true } heapless = "0.8" +embedded-io-async = "0.6.1" # for HID usbd-hid = { version = "0.8.1", optional = true } diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 4ae0e6a77..244ce9591 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -13,8 +13,8 @@ embassy-boot = { version = "0.4.0", path = "../../../../embassy-boot", features embassy-boot-nrf = { version = "0.4.0", path = "../../../../embassy-boot-nrf", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } -defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index 3c0d207d1..24f4218f1 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -12,9 +12,9 @@ embassy-rp = { version = "0.4.0", path = "../../../../embassy-rp", features = [" embassy-boot-rp = { version = "0.5.0", path = "../../../../embassy-boot-rp", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3", features = ["print-defmt"], optional = true } +defmt = "1.0.1" +defmt-rtt = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"], optional = true } panic-reset = { version = "0.1.1", optional = true } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index f32727ea8..1e209eb9c 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -12,8 +12,8 @@ embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", feature embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32" } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } -defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index d62c67742..877e239fa 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -12,8 +12,8 @@ embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", feature embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } -defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } embedded-storage = "0.3.1" diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index dd3a32e45..f28723835 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -12,8 +12,8 @@ embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", feature embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } -defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } embedded-storage = "0.3.1" diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 0b9e9b96a..f1cb55223 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -12,8 +12,8 @@ embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", feature embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } -defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 490541a2e..7c53e011d 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -12,8 +12,8 @@ embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", feature embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } -defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index c3aa31161..9f5060802 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -12,8 +12,8 @@ embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", feature embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } -defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index a89e2bb6e..d1cea8520 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -14,8 +14,8 @@ embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded embassy-usb = { version = "0.4.0", path = "../../../../embassy-usb" } embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } -defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index f4d7ae712..54331dd69 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -12,8 +12,8 @@ embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", feature embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } -defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/bootloader/nrf/Cargo.toml b/examples/boot/bootloader/nrf/Cargo.toml index 34a0553e3..4c2712718 100644 --- a/examples/boot/bootloader/nrf/Cargo.toml +++ b/examples/boot/bootloader/nrf/Cargo.toml @@ -6,8 +6,8 @@ description = "Bootloader for nRF chips" license = "MIT OR Apache-2.0" [dependencies] -defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } embassy-nrf = { path = "../../../../embassy-nrf", features = [] } embassy-boot-nrf = { path = "../../../../embassy-boot-nrf" } diff --git a/examples/boot/bootloader/rp/Cargo.toml b/examples/boot/bootloader/rp/Cargo.toml index 7c9c3c779..c57b90793 100644 --- a/examples/boot/bootloader/rp/Cargo.toml +++ b/examples/boot/bootloader/rp/Cargo.toml @@ -6,8 +6,8 @@ description = "Example bootloader for RP2040 chips" license = "MIT OR Apache-2.0" [dependencies] -defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } embassy-rp = { path = "../../../../embassy-rp", features = ["rp2040"] } embassy-boot-rp = { path = "../../../../embassy-boot-rp" } diff --git a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml index 4beb9c61c..a3ca96aec 100644 --- a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml +++ b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml @@ -6,8 +6,8 @@ description = "Example bootloader for dual-bank flash STM32 chips" license = "MIT OR Apache-2.0" [dependencies] -defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } diff --git a/examples/boot/bootloader/stm32/Cargo.toml b/examples/boot/bootloader/stm32/Cargo.toml index 9abad8636..bdefa2cb5 100644 --- a/examples/boot/bootloader/stm32/Cargo.toml +++ b/examples/boot/bootloader/stm32/Cargo.toml @@ -6,8 +6,8 @@ description = "Example bootloader for STM32 chips" license = "MIT OR Apache-2.0" [dependencies] -defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml index 01343b86b..389f43641 100644 --- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml @@ -6,8 +6,8 @@ description = "Example USB DFUbootloader for the STM32WB series of chips" license = "MIT OR Apache-2.0" [dependencies] -defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.4", optional = true } +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index f5a6e6995..30ce0b799 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml @@ -10,12 +10,12 @@ embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["rt"] embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } -panic-halt = "0.2.0" +panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = { version = "0.7.0"} -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3.2", features = ["print-defmt"] } +defmt = "1.0.1" +defmt-rtt = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } panic-semihosting = "0.6.0" [profile.release] diff --git a/examples/mimxrt6/Cargo.toml b/examples/mimxrt6/Cargo.toml index 27c3a27dc..40cc0fb44 100644 --- a/examples/mimxrt6/Cargo.toml +++ b/examples/mimxrt6/Cargo.toml @@ -7,8 +7,8 @@ license = "MIT or Apache-2.0" [dependencies] cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.3" -defmt = "1.0" -defmt-rtt = "1.0" +defmt = "1.0.1" +defmt-rtt = "1.0.0" embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } @@ -19,7 +19,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = "1.0.0" mimxrt600-fcb = "0.2.2" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } # cargo build/run [profile.dev] diff --git a/examples/mspm0c1104/Cargo.toml b/examples/mspm0c1104/Cargo.toml index ba64a578d..1498b599d 100644 --- a/examples/mspm0c1104/Cargo.toml +++ b/examples/mspm0c1104/Cargo.toml @@ -9,12 +9,12 @@ embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = [" embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } -panic-halt = "0.2.0" +panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = { version = "0.7.0"} -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3.2", features = ["print-defmt"] } +defmt = "1.0.1" +defmt-rtt = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } panic-semihosting = "0.6.0" # The chip only has 1KB of ram, so we must optimize binaries regardless diff --git a/examples/mspm0g3507/Cargo.toml b/examples/mspm0g3507/Cargo.toml index f6fed091d..78c4b3f5a 100644 --- a/examples/mspm0g3507/Cargo.toml +++ b/examples/mspm0g3507/Cargo.toml @@ -9,12 +9,12 @@ embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = [" embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } -panic-halt = "0.2.0" +panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = { version = "0.7.0"} -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3.2", features = ["print-defmt"] } +defmt = "1.0.1" +defmt-rtt = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } panic-semihosting = "0.6.0" [profile.release] diff --git a/examples/mspm0g3519/Cargo.toml b/examples/mspm0g3519/Cargo.toml index 1662e1f8d..1d191b2da 100644 --- a/examples/mspm0g3519/Cargo.toml +++ b/examples/mspm0g3519/Cargo.toml @@ -9,12 +9,12 @@ embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = [" embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } -panic-halt = "0.2.0" +panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = { version = "0.7.0"} -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3.2", features = ["print-defmt"] } +defmt = "1.0.1" +defmt-rtt = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } panic-semihosting = "0.6.0" [profile.release] diff --git a/examples/mspm0l1306/Cargo.toml b/examples/mspm0l1306/Cargo.toml index 609b3f205..e427971fe 100644 --- a/examples/mspm0l1306/Cargo.toml +++ b/examples/mspm0l1306/Cargo.toml @@ -9,12 +9,12 @@ embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = [" embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } -panic-halt = "0.2.0" +panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = { version = "0.7.0"} -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3.2", features = ["print-defmt"] } +defmt = "1.0.1" +defmt-rtt = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } panic-semihosting = "0.6.0" [profile.release] diff --git a/examples/mspm0l2228/Cargo.toml b/examples/mspm0l2228/Cargo.toml index bbca011a1..39e0e1a0c 100644 --- a/examples/mspm0l2228/Cargo.toml +++ b/examples/mspm0l2228/Cargo.toml @@ -9,12 +9,12 @@ embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = [" embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } -panic-halt = "0.2.0" +panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = { version = "0.7.0"} -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3.2", features = ["print-defmt"] } +defmt = "1.0.1" +defmt-rtt = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } panic-semihosting = "0.6.0" [profile.release] diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index ba609d889..dcbaf87f8 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -22,7 +22,7 @@ embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["nrf5 cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3" } +panic-probe = "1.0.0" serde = { version = "1.0.136", default-features = false } rtos-trace = "0.1.3" systemview-target = { version = "0.1.2", features = ["callbacks-app", "callbacks-os", "log", "cortex-m"] } diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml index 97b5b924a..91f78737f 100644 --- a/examples/nrf51/Cargo.toml +++ b/examples/nrf51/Cargo.toml @@ -9,12 +9,12 @@ embassy-executor = { version = "0.7.0", path = "../../embassy-executor", feature embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index cd59b86c3..5373278c1 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml @@ -11,14 +11,14 @@ embassy-executor = { version = "0.7.0", path = "../../embassy-executor", feature embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" fixed = "1.10.0" static_cell = { version = "2" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index ac3d2006c..2eef012b7 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml @@ -13,12 +13,12 @@ embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "d embassy-time-queue-utils = { version = "0.1", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index ff40a34af..92127a8b0 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -17,14 +17,14 @@ embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } embassy-net-esp-hosted = { version = "0.2.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } embassy-net-enc28j60 = { version = "0.2.0", path = "../../embassy-net-enc28j60", features = ["defmt"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" fixed = "1.10.0" static_cell = { version = "2" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } rand = { version = "0.9.0", default-features = false } embedded-storage = "0.3.1" usbd-hid = "0.8.1" diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 5c226695f..42d7766b7 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -14,13 +14,13 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defm embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io-async = { version = "0.6.1" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" static_cell = "2" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } embedded-storage = "0.3.1" usbd-hid = "0.8.1" serde = { version = "1.0.136", default-features = false } diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index 8848065d8..4b229d06d 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml @@ -9,9 +9,9 @@ embassy-executor = { version = "0.7.0", path = "../../embassy-executor", feature embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3", features = ["print-defmt"] } +defmt = "1.0.1" +defmt-rtt = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml index 03f38fd63..a083aa5e7 100644 --- a/examples/nrf9151/ns/Cargo.toml +++ b/examples/nrf9151/ns/Cargo.toml @@ -9,12 +9,12 @@ embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", feat embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml index ba88f6da3..ae98631ef 100644 --- a/examples/nrf9151/s/Cargo.toml +++ b/examples/nrf9151/s/Cargo.toml @@ -9,12 +9,12 @@ embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", feat embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml index a720f2d61..25aedf624 100644 --- a/examples/nrf9160/Cargo.toml +++ b/examples/nrf9160/Cargo.toml @@ -11,13 +11,13 @@ embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defm embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" heapless = "0.8" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } static_cell = { version = "2" } embedded-io = "0.6.1" embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index aacf9846a..d19dd9dc7 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -19,8 +19,8 @@ embassy-usb-logger = { version = "0.4.0", path = "../../embassy-usb-logger" } cyw43 = { version = "0.3.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { version = "0.4.0", path = "../../cyw43-pio", features = ["defmt"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" fixed = "1.23.1" fixed-macro = "1.2" @@ -36,7 +36,7 @@ assign-resources = { git = "https://github.com/adamgreig/assign-resources", rev cortex-m = { version = "0.7.6", features = ["inline-asm"] } cortex-m-rt = "0.7.0" critical-section = "1.1" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } display-interface-spi = "0.5.0" embedded-graphics = "0.8.1" mipidsi = "0.8.0" diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index a247bc619..ae64489ae 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -19,8 +19,8 @@ embassy-usb-logger = { version = "0.4.0", path = "../../embassy-usb-logger" } cyw43 = { version = "0.3.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { version = "0.4.0", path = "../../cyw43-pio", features = ["defmt"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" fixed = "1.23.1" fixed-macro = "1.2" @@ -37,7 +37,7 @@ tb6612fng = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm"] } cortex-m-rt = "0.7.0" critical-section = "1.1" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } display-interface-spi = "0.5.0" embedded-graphics = "0.8.1" mipidsi = "0.8.0" diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index 767b742f7..71f1cfda1 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml @@ -11,13 +11,13 @@ embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } [profile.release] diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index 932a97dc8..534e8c33d 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -9,9 +9,9 @@ license = "MIT OR Apache-2.0" embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "memory-x", "stm32f091rc", "time-driver-tim2", "exti", "unstable-pac"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3", features = ["print-defmt"] } +defmt = "1.0.1" +defmt-rtt = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index fe800bc80..f856d2620 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -13,13 +13,13 @@ embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["de embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } nb = "1.0.0" static_cell = "2.0.0" diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index 26be3f485..f26cbfadc 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml @@ -11,13 +11,13 @@ embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } nb = "1.0.0" diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 31bf040b0..4c1dd881f 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -13,13 +13,13 @@ embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["de embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } nb = "1.0.0" embedded-storage = "0.3.1" diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml index 5fb6d60c5..c28855b3a 100644 --- a/examples/stm32f334/Cargo.toml +++ b/examples/stm32f334/Cargo.toml @@ -12,13 +12,13 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } nb = "1.0.0" embedded-storage = "0.3.1" diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 7aa4354ca..7374f8813 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -15,8 +15,8 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defm embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" @@ -24,7 +24,7 @@ embedded-hal = "0.2.6" embedded-hal-bus = { version = "0.2", features = ["async"] } embedded-io = { version = "0.6.0" } embedded-io-async = { version = "0.6.1" } -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } futures-util = { version = "0.3.30", default-features = false } heapless = { version = "0.8", default-features = false } critical-section = "1.1" diff --git a/examples/stm32f469/Cargo.toml b/examples/stm32f469/Cargo.toml index 4d403bae8..87a3b8f75 100644 --- a/examples/stm32f469/Cargo.toml +++ b/examples/stm32f469/Cargo.toml @@ -10,13 +10,13 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [" embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "1.0.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 94e0a80eb..bce521f30 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -15,13 +15,13 @@ embedded-io-async = { version = "0.6.1" } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } nb = "1.0.0" critical-section = "1.1" diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index 319d84179..5e09b237e 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml @@ -13,13 +13,13 @@ embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["de embassy-usb = { version = "0.4.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index aa01d84e2..582553a29 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -14,14 +14,14 @@ embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defm embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } usbd-hid = "0.8.1" -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" embedded-can = { version = "0.4" } -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } static_cell = "2.0.0" diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 6fb14f422..3e022e4e5 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -14,8 +14,8 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defm embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" @@ -24,7 +24,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-io-async = { version = "0.6.1" } embedded-nal-async = "0.8.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } critical-section = "1.1" micromath = "2.0.0" diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 5035dacae..520d0c8e6 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -15,8 +15,8 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defm embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" @@ -25,7 +25,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-nal-async = "0.8.0" embedded-io-async = { version = "0.6.1" } -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } critical-section = "1.1" micromath = "2.0.0" diff --git a/examples/stm32h723/Cargo.toml b/examples/stm32h723/Cargo.toml index f07d360b3..1eb706b4d 100644 --- a/examples/stm32h723/Cargo.toml +++ b/examples/stm32h723/Cargo.toml @@ -12,8 +12,8 @@ embassy-executor = { version = "0.7.0", path = "../../embassy-executor", feature embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" @@ -22,7 +22,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-nal-async = "0.8.0" embedded-io-async = { version = "0.6.1" } -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } critical-section = "1.1" static_cell = "2" diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml index 4d31dedf1..2ce989e6f 100644 --- a/examples/stm32h735/Cargo.toml +++ b/examples/stm32h735/Cargo.toml @@ -12,12 +12,12 @@ embassy-executor = { version = "0.7.0", path = "../../embassy-executor", feature embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } embedded-graphics = { version = "0.8.1" } tinybmp = { version = "0.5" } diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml index 3f936193c..c3bf39e13 100644 --- a/examples/stm32h742/Cargo.toml +++ b/examples/stm32h742/Cargo.toml @@ -39,8 +39,8 @@ embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = [ ] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = [ "inline-asm", @@ -48,7 +48,7 @@ cortex-m = { version = "0.7.6", features = [ ] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } nb = "1.0.0" critical-section = "1.1" diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index c186ef19f..c97ac447e 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -15,8 +15,8 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defm embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" @@ -25,7 +25,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-nal-async = "0.8.0" embedded-io-async = { version = "0.6.1" } -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } critical-section = "1.1" micromath = "2.0.0" diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index d37978e44..3843d5d43 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -15,8 +15,8 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defm embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" @@ -25,7 +25,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-nal-async = "0.8.0" embedded-io-async = { version = "0.6.1" } -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } critical-section = "1.1" micromath = "2.0.0" diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml index dc8ecc684..e4f1080ac 100644 --- a/examples/stm32h7b0/Cargo.toml +++ b/examples/stm32h7b0/Cargo.toml @@ -14,8 +14,8 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defm embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" @@ -24,7 +24,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-nal-async = "0.8.0" embedded-io-async = { version = "0.6.1" } -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } critical-section = "1.1" micromath = "2.0.0" diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml index aee2703a1..58f8b1274 100644 --- a/examples/stm32h7rs/Cargo.toml +++ b/examples/stm32h7rs/Cargo.toml @@ -14,8 +14,8 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defm embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" @@ -24,7 +24,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-nal-async = "0.8.0" embedded-io-async = { version = "0.6.1" } -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } critical-section = "1.1" micromath = "2.0.0" diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 189b0e8d4..ce54ad9fb 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -11,8 +11,8 @@ embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" embedded-storage = "0.3.1" embedded-io = { version = "0.6.0" } @@ -20,7 +20,7 @@ embedded-io-async = { version = "0.6.1" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } embedded-hal = "0.2.6" static_cell = { version = "2" } diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 6066b6dc7..a780f9290 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -12,13 +12,13 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } embedded-storage = "0.3.1" diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index cceec86dd..5c4dce482 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -18,8 +18,8 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } embedded-io = { version = "0.6.0", features = ["defmt-03"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" @@ -27,7 +27,7 @@ embedded-hal = "0.2.6" embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-hal-bus = { version = "0.1", features = ["async"] } -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } chrono = { version = "^0.4", default-features = false } static_cell = "2" diff --git a/examples/stm32l432/Cargo.toml b/examples/stm32l432/Cargo.toml index e155b3e66..ac7e507de 100644 --- a/examples/stm32l432/Cargo.toml +++ b/examples/stm32l432/Cargo.toml @@ -10,8 +10,8 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = [ "defmt" ] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "tick-hz-32_768" ] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" @@ -19,7 +19,7 @@ embedded-hal = "0.2.6" embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-hal-bus = { version = "0.1", features = ["async"] } -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 6962db7ea..138276b7f 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -15,9 +15,9 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defm embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } usbd-hid = "0.8.1" -defmt = "0.3" -defmt-rtt = "0.4" -panic-probe = { version = "0.3", features = ["print-defmt"] } +defmt = "1.0.1" +defmt-rtt = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml index efcb9bf4d..86cff2321 100644 --- a/examples/stm32u0/Cargo.toml +++ b/examples/stm32u0/Cargo.toml @@ -13,13 +13,13 @@ embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["de embassy-usb = { version = "0.4.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } micromath = "2.0.0" diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index 886c5cb2e..94f77ce2f 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -13,13 +13,13 @@ embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["de embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } embedded-graphics = { version = "0.8.1" } tinybmp = { version = "0.6.0" } diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 96f66f3af..a83871d4d 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -11,15 +11,15 @@ embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", fea embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true } +embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -embedded-hal = "0.2.6" -panic-probe = { version = "0.3", features = ["print-defmt"] } +embedded-hal = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } static_cell = "2" diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml index 60b09adb4..b87ca88bf 100644 --- a/examples/stm32wba/Cargo.toml +++ b/examples/stm32wba/Cargo.toml @@ -9,15 +9,15 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true } +embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -embedded-hal = "0.2.6" -panic-probe = { version = "0.3", features = ["print-defmt"] } +embedded-hal = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } static_cell = "2" diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 6b677914e..1b6a23bed 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -12,14 +12,14 @@ embassy-executor = { version = "0.7.0", path = "../../embassy-executor", feature embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" embedded-storage = "0.3.1" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } chrono = { version = "^0.4", default-features = false } diff --git a/rustfmt.toml b/rustfmt.toml index 592ad27ff..2561562fd 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,4 +1,4 @@ group_imports = "StdExternalCrate" imports_granularity = "Module" edition = "2021" -max_width=120 +max_width = 120 diff --git a/tests/mspm0/Cargo.toml b/tests/mspm0/Cargo.toml index 0566807d7..b77747e5d 100644 --- a/tests/mspm0/Cargo.toml +++ b/tests/mspm0/Cargo.toml @@ -23,7 +23,7 @@ cortex-m = { version = "0.7.6", features = [ "inline-asm", "critical-section-sin cortex-m-rt = "0.7.0" embedded-hal = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } -panic-probe = { version = "0.3.0", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } static_cell = "2" portable-atomic = { version = "1.5", features = ["critical-section"] } diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index 410d62bdd..32087940e 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -21,12 +21,12 @@ embedded-hal-bus = { version = "0.1", features = ["async"] } static_cell = "2" perf-client = { path = "../perf-client" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } portable-atomic = { version = "1.6.0" } [features] diff --git a/tests/perf-client/Cargo.toml b/tests/perf-client/Cargo.toml index 9620972c3..e31d6361b 100644 --- a/tests/perf-client/Cargo.toml +++ b/tests/perf-client/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", ] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -defmt = "0.3" +defmt = "1.0.1" diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 46dc820ab..2c2ed73cc 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -24,8 +24,8 @@ cyw43 = { path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { path = "../../cyw43-pio", features = ["defmt"] } perf-client = { path = "../perf-client" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6" } cortex-m-rt = "0.7.0" @@ -33,7 +33,7 @@ embedded-hal = "0.2.6" embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-hal-bus = { version = "0.1", features = ["async"] } -panic-probe = { version = "0.3.0", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } embedded-io-async = { version = "0.6.1" } embedded-storage = { version = "0.3" } static_cell = "2" diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index b230e619e..6036a5a97 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -70,8 +70,8 @@ embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", opt embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } perf-client = { path = "../perf-client" } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" @@ -80,7 +80,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-can = { version = "0.4" } micromath = "2.0.0" -panic-probe = { version = "0.3.0", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } rand_core = { version = "0.9.1", default-features = false } rand_chacha = { version = "0.9.0", default-features = false } static_cell = "2" -- cgit From e0c5e93e78d48a2077578ac01d532066a638115a Mon Sep 17 00:00:00 2001 From: Tobias Naumann Date: Sun, 18 May 2025 22:09:00 +0200 Subject: Count all users of a given CAN instance and cleanup pins and RCC when the last user gets dropped --- embassy-stm32/src/can/fdcan.rs | 71 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 9 deletions(-) diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index 5467a40f1..a7815f79b 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs @@ -10,7 +10,7 @@ use embassy_sync::channel::Channel; use embassy_sync::waitqueue::AtomicWaker; use crate::can::fd::peripheral::Registers; -use crate::gpio::{AfType, OutputType, Pull, Speed}; +use crate::gpio::{AfType, OutputType, Pull, SealedPin as _, Speed}; use crate::interrupt::typelevel::Interrupt; use crate::rcc::{self, RccPeripheral}; use crate::{interrupt, peripherals, Peri}; @@ -187,13 +187,17 @@ impl<'d> CanConfigurator<'d> { rcc::enable_and_reset::(); + let info = T::info(); + let state = unsafe { T::mut_state() }; + state.tx_pin_port = Some(tx.pin_port()); + state.rx_pin_port = Some(rx.pin_port()); + (info.internal_operation)(InternalOperation::NotifySenderCreated); + (info.internal_operation)(InternalOperation::NotifyReceiverCreated); + let mut config = crate::can::fd::config::FdCanConfig::default(); config.timestamp_source = TimestampSource::Prescaler(TimestampPrescaler::_1); T::registers().into_config_mode(config); - rx.set_as_af(rx.af_num(), AfType::input(Pull::None)); - tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); - unsafe { T::IT0Interrupt::unpend(); // Not unsafe T::IT0Interrupt::enable(); @@ -204,8 +208,8 @@ impl<'d> CanConfigurator<'d> { Self { _phantom: PhantomData, config, - info: T::info(), - state: T::state(), + info, + state, properties: Properties::new(T::info()), periph_clock: T::frequency(), } @@ -265,6 +269,8 @@ impl<'d> CanConfigurator<'d> { } }); self.info.regs.into_mode(self.config, mode); + (self.info.internal_operation)(InternalOperation::NotifySenderCreated); + (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated); Can { _phantom: PhantomData, config: self.config, @@ -291,6 +297,13 @@ impl<'d> CanConfigurator<'d> { } } +impl<'d> Drop for CanConfigurator<'d> { + fn drop(&mut self) { + (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); + (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); + } +} + /// FDCAN Instance pub struct Can<'d> { _phantom: PhantomData<&'d ()>, @@ -353,6 +366,8 @@ impl<'d> Can<'d> { /// Split instance into separate portions: Tx(write), Rx(read), common properties pub fn split(self) -> (CanTx<'d>, CanRx<'d>, Properties) { + (self.info.internal_operation)(InternalOperation::NotifySenderCreated); + (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated); ( CanTx { _phantom: PhantomData, @@ -367,11 +382,15 @@ impl<'d> Can<'d> { state: self.state, _mode: self._mode, }, - self.properties, + Properties { + info: self.properties.info, + }, ) } /// Join split rx and tx portions back together pub fn join(tx: CanTx<'d>, rx: CanRx<'d>) -> Self { + (tx.info.internal_operation)(InternalOperation::NotifySenderCreated); + (tx.info.internal_operation)(InternalOperation::NotifyReceiverCreated); Can { _phantom: PhantomData, config: tx.config, @@ -401,6 +420,13 @@ impl<'d> Can<'d> { } } +impl<'d> Drop for Can<'d> { + fn drop(&mut self) { + (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); + (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); + } +} + /// User supplied buffer for RX Buffering pub type RxBuf = Channel, BUF_SIZE>; @@ -426,6 +452,8 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, tx_buf: &'static TxBuf, rx_buf: &'static RxBuf, ) -> Self { + (info.internal_operation)(InternalOperation::NotifySenderCreated); + (info.internal_operation)(InternalOperation::NotifyReceiverCreated); BufferedCan { _phantom: PhantomData, info, @@ -532,6 +560,8 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<' tx_buf: &'static TxFdBuf, rx_buf: &'static RxFdBuf, ) -> Self { + (info.internal_operation)(InternalOperation::NotifySenderCreated); + (info.internal_operation)(InternalOperation::NotifyReceiverCreated); BufferedCanFd { _phantom: PhantomData, info, @@ -627,6 +657,12 @@ impl<'d> CanRx<'d> { } } +impl<'d> Drop for CanRx<'d> { + fn drop(&mut self) { + (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); + } +} + /// FDCAN Tx only Instance pub struct CanTx<'d> { _phantom: PhantomData<&'d ()>, @@ -654,6 +690,12 @@ impl<'c, 'd> CanTx<'d> { } } +impl<'d> Drop for CanTx<'d> { + fn drop(&mut self) { + (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); + } +} + enum RxMode { NonBuffered(AtomicWaker), ClassicBuffered(super::common::ClassicBufferedRxInner), @@ -898,6 +940,8 @@ struct State { pub ns_per_timer_tick: u64, receiver_instance_count: usize, sender_instance_count: usize, + tx_pin_port: Option, + rx_pin_port: Option, pub err_waker: AtomicWaker, } @@ -909,8 +953,10 @@ impl State { tx_mode: TxMode::NonBuffered(AtomicWaker::new()), ns_per_timer_tick: 0, err_waker: AtomicWaker::new(), - receiver_instance_count: 1, - sender_instance_count: 1, + receiver_instance_count: 0, + sender_instance_count: 0, + tx_pin_port: None, + rx_pin_port: None, } } } @@ -998,6 +1044,13 @@ macro_rules! impl_fdcan { } } } + if mut_state.sender_instance_count == 0 && mut_state.receiver_instance_count == 0 { + let tx_pin = crate::gpio::AnyPin::steal(mut_state.tx_pin_port.unwrap()); + tx_pin.set_as_disconnected(); + let rx_pin = crate::gpio::AnyPin::steal(mut_state.rx_pin_port.unwrap()); + rx_pin.set_as_disconnected(); + rcc::disable::(); + } } }); } -- cgit From ef32187ed7349f3883d997b6f1590e11dbc8db81 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 19 May 2025 18:15:05 +0200 Subject: mspm0: fix build for int groups. --- ci.sh | 7 +++++ embassy-mspm0/build.rs | 4 +++ embassy-mspm0/src/int_group/g110x.rs | 47 ++++++++++++++++++++++++++++++++ embassy-mspm0/src/int_group/g151x.rs | 52 ++++++++++++++++++++++++++++++++++++ embassy-mspm0/src/int_group/g310x.rs | 48 +++++++++++++++++++++++++++++++++ embassy-mspm0/src/int_group/l11xx.rs | 25 +++++++++++++++++ embassy-mspm0/src/int_group/l12xx.rs | 49 +++++++++++++++++++++++++++++++++ embassy-mspm0/src/int_group/l130x.rs | 46 ------------------------------- embassy-mspm0/src/int_group/l13xx.rs | 46 +++++++++++++++++++++++++++++++ embassy-mspm0/src/lib.rs | 8 +++++- 10 files changed, 285 insertions(+), 47 deletions(-) create mode 100644 embassy-mspm0/src/int_group/g110x.rs create mode 100644 embassy-mspm0/src/int_group/g151x.rs create mode 100644 embassy-mspm0/src/int_group/g310x.rs create mode 100644 embassy-mspm0/src/int_group/l11xx.rs create mode 100644 embassy-mspm0/src/int_group/l12xx.rs delete mode 100644 embassy-mspm0/src/int_group/l130x.rs create mode 100644 embassy-mspm0/src/int_group/l13xx.rs diff --git a/ci.sh b/ci.sh index 2f4164998..2be84ef6b 100755 --- a/ci.sh +++ b/ci.sh @@ -179,6 +179,13 @@ cargo batch \ --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3519pz,defmt,time-driver-any \ --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1306rhb,defmt,time-driver-any \ --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l2228pn,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1345dgs28,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1106dgs28,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1228pm,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1107ycj,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3105rhb,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1505pt,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1519rhb,defmt,time-driver-any \ --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features ''\ --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log' \ --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt' \ diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs index 409ce0621..094769992 100644 --- a/embassy-mspm0/build.rs +++ b/embassy-mspm0/build.rs @@ -84,6 +84,10 @@ fn get_chip_cfgs(chip_name: &str) -> Vec { cfgs.push("mspm0g150x".to_string()); } + if chip_name.starts_with("mspm0g151") { + cfgs.push("mspm0g151x".to_string()); + } + if chip_name.starts_with("mspm0g310") { cfgs.push("mspm0g310x".to_string()); } diff --git a/embassy-mspm0/src/int_group/g110x.rs b/embassy-mspm0/src/int_group/g110x.rs new file mode 100644 index 000000000..9f8ac4d7b --- /dev/null +++ b/embassy-mspm0/src/int_group/g110x.rs @@ -0,0 +1,47 @@ +use crate::pac; +use crate::pac::interrupt; + +#[cfg(feature = "rt")] +#[interrupt] +fn GROUP0() { + use mspm0_metapac::Group0; + + let group = pac::CPUSS.int_group(0); + + // Must subtract by 1 since NO_INTR is value 0 + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = pac::Group0::try_from(iidx as u8) else { + debug!("Invalid IIDX for group 0: {}", iidx); + return; + }; + + match group { + Group0::WWDT0 => todo!("implement WWDT0"), + Group0::WWDT1 => todo!("implement WWDT1"), + Group0::DEBUGSS => todo!("implement DEBUGSS"), + Group0::FLASHCTL => todo!("implement FLASHCTL"), + Group0::SYSCTL => todo!("implement SYSCTL"), + } +} + +#[cfg(feature = "rt")] +#[interrupt] +fn GROUP1() { + use mspm0_metapac::Group1; + + let group = pac::CPUSS.int_group(1); + + // Must subtract by 1 since NO_INTR is value 0 + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = pac::Group1::try_from(iidx as u8) else { + debug!("Invalid IIDX for group 1: {}", iidx); + return; + }; + + match group { + Group1::GPIOA => crate::gpio::gpioa_interrupt(), + Group1::GPIOB => crate::gpio::gpiob_interrupt(), + } +} diff --git a/embassy-mspm0/src/int_group/g151x.rs b/embassy-mspm0/src/int_group/g151x.rs new file mode 100644 index 000000000..e785018a7 --- /dev/null +++ b/embassy-mspm0/src/int_group/g151x.rs @@ -0,0 +1,52 @@ +use crate::pac; +use crate::pac::interrupt; + +#[cfg(feature = "rt")] +#[interrupt] +fn GROUP0() { + use mspm0_metapac::Group0; + + let group = pac::CPUSS.int_group(0); + + // Must subtract by 1 since NO_INTR is value 0 + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = pac::Group0::try_from(iidx as u8) else { + debug!("Invalid IIDX for group 0: {}", iidx); + return; + }; + + match group { + Group0::WWDT0 => todo!("implement WWDT0"), + Group0::WWDT1 => todo!("implement WWDT1"), + Group0::DEBUGSS => todo!("implement DEBUGSS"), + Group0::FLASHCTL => todo!("implement FLASHCTL"), + Group0::SYSCTL => todo!("implement SYSCTL"), + } +} + +#[cfg(feature = "rt")] +#[interrupt] +fn GROUP1() { + use mspm0_metapac::Group1; + + let group = pac::CPUSS.int_group(1); + + // Must subtract by 1 since NO_INTR is value 0 + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = pac::Group1::try_from(iidx as u8) else { + debug!("Invalid IIDX for group 1: {}", iidx); + return; + }; + + match group { + Group1::GPIOA => crate::gpio::gpioa_interrupt(), + Group1::GPIOB => crate::gpio::gpiob_interrupt(), + Group1::COMP0 => todo!("implement COMP0"), + Group1::COMP1 => todo!("implement COMP1"), + Group1::COMP2 => todo!("implement COMP2"), + Group1::TRNG => todo!("implement TRNG"), + Group1::GPIOC => crate::gpio::gpioc_interrupt(), + } +} diff --git a/embassy-mspm0/src/int_group/g310x.rs b/embassy-mspm0/src/int_group/g310x.rs new file mode 100644 index 000000000..ad508d3a2 --- /dev/null +++ b/embassy-mspm0/src/int_group/g310x.rs @@ -0,0 +1,48 @@ +use crate::pac; +use crate::pac::interrupt; + +#[cfg(feature = "rt")] +#[interrupt] +fn GROUP0() { + use mspm0_metapac::Group0; + + let group = pac::CPUSS.int_group(0); + + // Must subtract by 1 since NO_INTR is value 0 + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = pac::Group0::try_from(iidx as u8) else { + debug!("Invalid IIDX for group 0: {}", iidx); + return; + }; + + match group { + Group0::WWDT0 => todo!("implement WWDT0"), + Group0::WWDT1 => todo!("implement WWDT1"), + Group0::DEBUGSS => todo!("implement DEBUGSS"), + Group0::FLASHCTL => todo!("implement FLASHCTL"), + Group0::SYSCTL => todo!("implement SYSCTL"), + } +} + +#[cfg(feature = "rt")] +#[interrupt] +fn GROUP1() { + use mspm0_metapac::Group1; + + let group = pac::CPUSS.int_group(1); + + // Must subtract by 1 since NO_INTR is value 0 + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = pac::Group1::try_from(iidx as u8) else { + debug!("Invalid IIDX for group 1: {}", iidx); + return; + }; + + match group { + Group1::GPIOA => crate::gpio::gpioa_interrupt(), + Group1::GPIOB => crate::gpio::gpiob_interrupt(), + Group1::TRNG => todo!("implement TRNG"), + } +} diff --git a/embassy-mspm0/src/int_group/l11xx.rs b/embassy-mspm0/src/int_group/l11xx.rs new file mode 100644 index 000000000..426a80c13 --- /dev/null +++ b/embassy-mspm0/src/int_group/l11xx.rs @@ -0,0 +1,25 @@ +use crate::pac; +use crate::pac::interrupt; + +#[cfg(feature = "rt")] +#[interrupt] +fn GROUP0() { + use mspm0_metapac::Group0; + + let group = pac::CPUSS.int_group(0); + + // Must subtract by 1 since NO_INTR is value 0 + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = pac::Group0::try_from(iidx as u8) else { + debug!("Invalid IIDX for group 0: {}", iidx); + return; + }; + + match group { + Group0::WWDT0 => todo!("implement WWDT0"), + Group0::DEBUGSS => todo!("implement DEBUGSS"), + Group0::FLASHCTL => todo!("implement FLASHCTL"), + Group0::SYSCTL => todo!("implement SYSCTL"), + } +} diff --git a/embassy-mspm0/src/int_group/l12xx.rs b/embassy-mspm0/src/int_group/l12xx.rs new file mode 100644 index 000000000..833771eea --- /dev/null +++ b/embassy-mspm0/src/int_group/l12xx.rs @@ -0,0 +1,49 @@ +use crate::pac; +use crate::pac::interrupt; + +#[cfg(feature = "rt")] +#[interrupt] +fn GROUP0() { + use mspm0_metapac::Group0; + + let group = pac::CPUSS.int_group(0); + + // Must subtract by 1 since NO_INTR is value 0 + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = pac::Group0::try_from(iidx as u8) else { + debug!("Invalid IIDX for group 0: {}", iidx); + return; + }; + + match group { + Group0::WWDT0 => todo!("implement WWDT0"), + Group0::DEBUGSS => todo!("implement DEBUGSS"), + Group0::FLASHCTL => todo!("implement FLASHCTL"), + Group0::SYSCTL => todo!("implement SYSCTL"), + } +} + +#[cfg(feature = "rt")] +#[interrupt] +fn GROUP1() { + use mspm0_metapac::Group1; + + let group = pac::CPUSS.int_group(1); + + // Must subtract by 1 since NO_INTR is value 0 + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = pac::Group1::try_from(iidx as u8) else { + debug!("Invalid IIDX for group 1: {}", iidx); + return; + }; + + match group { + Group1::GPIOA => crate::gpio::gpioa_interrupt(), + Group1::GPIOB => todo!("implement GPIOB"), + Group1::COMP0 => todo!("implement COMP0"), + Group1::TRNG => todo!("implement TRNG"), + Group1::GPIOC => todo!("implement GPIOC"), + } +} diff --git a/embassy-mspm0/src/int_group/l130x.rs b/embassy-mspm0/src/int_group/l130x.rs deleted file mode 100644 index 8be5adcad..000000000 --- a/embassy-mspm0/src/int_group/l130x.rs +++ /dev/null @@ -1,46 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - } -} diff --git a/embassy-mspm0/src/int_group/l13xx.rs b/embassy-mspm0/src/int_group/l13xx.rs new file mode 100644 index 000000000..8be5adcad --- /dev/null +++ b/embassy-mspm0/src/int_group/l13xx.rs @@ -0,0 +1,46 @@ +use crate::pac; +use crate::pac::interrupt; + +#[cfg(feature = "rt")] +#[interrupt] +fn GROUP0() { + use mspm0_metapac::Group0; + + let group = pac::CPUSS.int_group(0); + + // Must subtract by 1 since NO_INTR is value 0 + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = pac::Group0::try_from(iidx as u8) else { + debug!("Invalid IIDX for group 0: {}", iidx); + return; + }; + + match group { + Group0::WWDT0 => todo!("implement WWDT0"), + Group0::DEBUGSS => todo!("implement DEBUGSS"), + Group0::FLASHCTL => todo!("implement FLASHCTL"), + Group0::SYSCTL => todo!("implement SYSCTL"), + } +} + +#[cfg(feature = "rt")] +#[interrupt] +fn GROUP1() { + use mspm0_metapac::Group1; + + let group = pac::CPUSS.int_group(1); + + // Must subtract by 1 since NO_INTR is value 0 + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = pac::Group1::try_from(iidx as u8) else { + debug!("Invalid IIDX for group 1: {}", iidx); + return; + }; + + match group { + Group1::GPIOA => crate::gpio::gpioa_interrupt(), + Group1::COMP0 => todo!("implement COMP0"), + } +} diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index df2d83cc0..f129e221b 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -41,9 +41,15 @@ mod time_driver; // Interrupt group handlers. #[cfg_attr(mspm0c110x, path = "int_group/c110x.rs")] +#[cfg_attr(mspm0g110x, path = "int_group/g110x.rs")] +#[cfg_attr(mspm0g150x, path = "int_group/g150x.rs")] #[cfg_attr(mspm0g350x, path = "int_group/g350x.rs")] +#[cfg_attr(mspm0g151x, path = "int_group/g151x.rs")] #[cfg_attr(mspm0g351x, path = "int_group/g351x.rs")] -#[cfg_attr(mspm0l130x, path = "int_group/l130x.rs")] +#[cfg_attr(mspm0g310x, path = "int_group/g310x.rs")] +#[cfg_attr(mspm0l110x, path = "int_group/l11xx.rs")] +#[cfg_attr(mspm0l122x, path = "int_group/l12xx.rs")] +#[cfg_attr(any(mspm0l130x, mspm0l134x), path = "int_group/l13xx.rs")] #[cfg_attr(mspm0l222x, path = "int_group/l222x.rs")] mod int_group; -- cgit From ab5e0150d46b8b97d5ffe430b3e7a1caaae0438c Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Tue, 20 May 2025 18:48:44 +0300 Subject: update stm32-metapac --- embassy-stm32/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 413c92cce..2ab4f9960 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7251801e3273011ce28a89e8f2e45eec2e419e26" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-27ef8fba3483187e852eaf3796d827259f61e8ec" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7251801e3273011ce28a89e8f2e45eec2e419e26", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-27ef8fba3483187e852eaf3796d827259f61e8ec", default-features = false, features = ["metadata"] } [features] default = ["rt"] -- cgit From 44dce8206124359459facbb373887ca51c33c60b Mon Sep 17 00:00:00 2001 From: i509VCB Date: Tue, 20 May 2025 12:27:28 -0500 Subject: mspm0: add gpio handlers to l122x --- embassy-mspm0/src/int_group/l12xx.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-mspm0/src/int_group/l12xx.rs b/embassy-mspm0/src/int_group/l12xx.rs index 833771eea..eeb2ce70d 100644 --- a/embassy-mspm0/src/int_group/l12xx.rs +++ b/embassy-mspm0/src/int_group/l12xx.rs @@ -41,9 +41,9 @@ fn GROUP1() { match group { Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => todo!("implement GPIOB"), + Group1::GPIOB => crate::gpio::gpiob_interrupt(), Group1::COMP0 => todo!("implement COMP0"), Group1::TRNG => todo!("implement TRNG"), - Group1::GPIOC => todo!("implement GPIOC"), + Group1::GPIOC => crate::gpio::gpioc_interrupt(), } } -- cgit From 156bf00009495bbdffefd67f920919b4cd35c418 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Tue, 20 May 2025 12:35:17 -0500 Subject: mspm0: L110x has no group1 --- embassy-mspm0/src/gpio.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-mspm0/src/gpio.rs b/embassy-mspm0/src/gpio.rs index 3c824b0e6..19a6230b6 100644 --- a/embassy-mspm0/src/gpio.rs +++ b/embassy-mspm0/src/gpio.rs @@ -10,7 +10,7 @@ use embassy_sync::waitqueue::AtomicWaker; use crate::pac::gpio::vals::*; use crate::pac::gpio::{self}; -#[cfg(all(feature = "rt", mspm0c110x))] +#[cfg(all(feature = "rt", any(mspm0c110x, mspm0l110x)))] use crate::pac::interrupt; use crate::pac::{self}; @@ -1120,7 +1120,7 @@ impl Iterator for BitIter { } // C110x has a dedicated interrupt just for GPIOA, as it does not have a GROUP1 interrupt. -#[cfg(all(feature = "rt", mspm0c110x))] +#[cfg(all(feature = "rt", any(mspm0c110x, mspm0l110x)))] #[interrupt] fn GPIOA() { gpioa_interrupt(); -- cgit From e93ae32546b754ee9b54405aca81d936087ea8c7 Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Tue, 20 May 2025 21:31:32 +0300 Subject: adding eeprom constants to _generated.rs --- embassy-stm32/build.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index b00b6a7ac..b91934af3 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1922,6 +1922,47 @@ fn main() { pub const WRITE_SIZE: usize = #write_size; )); + // ======== + // Generate EEPROM constants + + let eeprom_memory_regions: Vec<&MemoryRegion> = + memory.iter().filter(|x| x.kind == MemoryRegionKind::Eeprom).collect(); + + if !eeprom_memory_regions.is_empty() { + cfgs.enable("eeprom"); + cfgs.declare("eeprom"); + + let mut sorted_eeprom_regions = eeprom_memory_regions.clone(); + sorted_eeprom_regions.sort_by_key(|r| r.address); + + let first_eeprom_address = sorted_eeprom_regions[0].address; + let mut total_eeprom_size = 0; + let mut current_expected_address = first_eeprom_address; + + for region in sorted_eeprom_regions.iter() { + if region.address != current_expected_address { + // For STM32L0 and STM32L1, EEPROM regions (if multiple) are expected to be contiguous. + // If they are not, this indicates an issue with the chip metadata or an unsupported configuration. + panic!( + "EEPROM regions for chip {} are not contiguous, which is unexpected for L0/L1 series. \ + First region: '{}' at {:#X}. Found next non-contiguous region: '{}' at {:#X}. \ + Please verify chip metadata. Embassy currently assumes contiguous EEPROM for these series.", + chip_name, sorted_eeprom_regions[0].name, first_eeprom_address, region.name, region.address + ); + } + total_eeprom_size += region.size; + current_expected_address += region.size; + } + + let eeprom_base_usize = first_eeprom_address as usize; + let total_eeprom_size_usize = total_eeprom_size as usize; + + g.extend(quote! { + pub const EEPROM_BASE: usize = #eeprom_base_usize; + pub const EEPROM_SIZE: usize = #total_eeprom_size_usize; + }); + } + // ======== // Generate macro-tables -- cgit From c9f0afa494636533c838473bcb5d27ff8f011fb7 Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Wed, 21 May 2025 00:37:46 +0300 Subject: import and re-export EEPROM_BASE and EEPROM_SIZE in flash module --- embassy-stm32/src/flash/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index adc45db9c..ab956664b 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -13,6 +13,8 @@ pub use common::*; pub use crate::_generated::flash_regions::*; pub use crate::_generated::{FLASH_BASE, FLASH_SIZE, MAX_ERASE_SIZE, WRITE_SIZE}; +#[cfg(eeprom)] +pub use crate::_generated::{EEPROM_BASE, EEPROM_SIZE}; /// Get all flash regions. pub fn get_flash_regions() -> &'static [&'static FlashRegion] { -- cgit From d335e309012020b5eab6f0d04ee63053365140ea Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Wed, 21 May 2025 00:44:24 +0300 Subject: only support eeprom for l0 and l1 --- embassy-stm32/src/flash/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index ab956664b..26f357370 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -12,9 +12,9 @@ pub use asynch::InterruptHandler; pub use common::*; pub use crate::_generated::flash_regions::*; -pub use crate::_generated::{FLASH_BASE, FLASH_SIZE, MAX_ERASE_SIZE, WRITE_SIZE}; #[cfg(eeprom)] pub use crate::_generated::{EEPROM_BASE, EEPROM_SIZE}; +pub use crate::_generated::{FLASH_BASE, FLASH_SIZE, MAX_ERASE_SIZE, WRITE_SIZE}; /// Get all flash regions. pub fn get_flash_regions() -> &'static [&'static FlashRegion] { @@ -85,7 +85,8 @@ pub enum FlashBank { /// OTP region, Otp, } - +#[cfg(all(eeprom, not(any(flash_l0, flash_l1))))] +compile_error!("The 'eeprom' cfg is enabled for a non-L0/L1 chip family. This is an unsupported configuration."); #[cfg_attr(any(flash_l0, flash_l1, flash_l4, flash_l5, flash_wl, flash_wb), path = "l.rs")] #[cfg_attr(flash_f0, path = "f0.rs")] #[cfg_attr(any(flash_f1, flash_f3), path = "f1f3.rs")] -- cgit From d23c71ea290828cbdf12b0ce64e9cd420e9038ab Mon Sep 17 00:00:00 2001 From: i509VCB Date: Tue, 20 May 2025 17:17:03 -0500 Subject: mspm0: generate interrupt group handlers --- embassy-mspm0/Cargo.toml | 4 +- embassy-mspm0/build.rs | 88 +++++++++++++++++++++++++++++++++++- embassy-mspm0/src/gpio.rs | 24 +++++++--- embassy-mspm0/src/int_group/c110x.rs | 25 ---------- embassy-mspm0/src/int_group/g110x.rs | 47 ------------------- embassy-mspm0/src/int_group/g150x.rs | 51 --------------------- embassy-mspm0/src/int_group/g151x.rs | 52 --------------------- embassy-mspm0/src/int_group/g310x.rs | 48 -------------------- embassy-mspm0/src/int_group/g350x.rs | 51 --------------------- embassy-mspm0/src/int_group/g351x.rs | 52 --------------------- embassy-mspm0/src/int_group/l11xx.rs | 25 ---------- embassy-mspm0/src/int_group/l12xx.rs | 49 -------------------- embassy-mspm0/src/int_group/l13xx.rs | 46 ------------------- embassy-mspm0/src/int_group/l222x.rs | 49 -------------------- embassy-mspm0/src/lib.rs | 14 ------ examples/mspm0c1104/build.rs | 2 + examples/mspm0g3507/build.rs | 2 + examples/mspm0g3519/build.rs | 2 + examples/mspm0l1306/build.rs | 2 + examples/mspm0l2228/build.rs | 2 + 20 files changed, 117 insertions(+), 518 deletions(-) delete mode 100644 embassy-mspm0/src/int_group/c110x.rs delete mode 100644 embassy-mspm0/src/int_group/g110x.rs delete mode 100644 embassy-mspm0/src/int_group/g150x.rs delete mode 100644 embassy-mspm0/src/int_group/g151x.rs delete mode 100644 embassy-mspm0/src/int_group/g310x.rs delete mode 100644 embassy-mspm0/src/int_group/g350x.rs delete mode 100644 embassy-mspm0/src/int_group/g351x.rs delete mode 100644 embassy-mspm0/src/int_group/l11xx.rs delete mode 100644 embassy-mspm0/src/int_group/l12xx.rs delete mode 100644 embassy-mspm0/src/int_group/l13xx.rs delete mode 100644 embassy-mspm0/src/int_group/l222x.rs diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index 1b189e05a..6f767a3c0 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -46,14 +46,14 @@ cortex-m = "0.7.6" critical-section = "1.2.0" # mspm0-metapac = { version = "" } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-66a55c7bf38a2201ff48c299843e741f2d537f0b" } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-26a6f681eda4ef120e8cb614a1631727c848590f" } [build-dependencies] proc-macro2 = "1.0.94" quote = "1.0.40" # mspm0-metapac = { version = "", default-features = false, features = ["metadata"] } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-66a55c7bf38a2201ff48c299843e741f2d537f0b", default-features = false, features = ["metadata"] } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-26a6f681eda4ef120e8cb614a1631727c848590f", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs index 094769992..6cd62895b 100644 --- a/embassy-mspm0/build.rs +++ b/embassy-mspm0/build.rs @@ -1,6 +1,7 @@ use std::cmp::Ordering; use std::collections::{BTreeSet, HashMap}; -use std::io::Write; +use std::fmt::Write; +use std::io::Write as _; use std::path::{Path, PathBuf}; use std::process::Command; use std::sync::LazyLock; @@ -16,12 +17,19 @@ mod common; fn main() { generate_code(); + interrupt_group_linker_magic(); } fn generate_code() { let mut cfgs = common::CfgSet::new(); common::set_target_cfgs(&mut cfgs); + #[cfg(any(feature = "rt"))] + println!( + "cargo:rustc-link-search={}", + PathBuf::from(env::var_os("OUT_DIR").unwrap()).display(), + ); + cfgs.declare_all(&["gpio_pb", "gpio_pc", "int_group1"]); let chip_name = match env::vars() @@ -58,6 +66,7 @@ fn generate_code() { g.extend(generate_interrupts()); g.extend(generate_peripheral_instances()); g.extend(generate_pin_trait_impls()); + g.extend(generate_groups()); let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); let out_file = out_dir.join("_generated.rs").to_string_lossy().to_string(); @@ -123,6 +132,83 @@ fn get_chip_cfgs(chip_name: &str) -> Vec { cfgs } +/// Interrupt groups use a weakly linked symbols and #[linkage = "extern_weak"] is nightly we need to +/// do some linker magic to create weak linkage. +fn interrupt_group_linker_magic() { + let mut file = String::new(); + + for group in METADATA.interrupt_groups { + for interrupt in group.interrupts.iter() { + let name = interrupt.name; + + writeln!(&mut file, "PROVIDE({name} = DefaultHandler);").unwrap(); + } + } + + let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let out_file = out_dir.join("interrupt_group.x"); + fs::write(&out_file, file).unwrap(); +} + +fn generate_groups() -> TokenStream { + let group_vectors = METADATA.interrupt_groups.iter().map(|group| { + let vectors = group.interrupts.iter().map(|interrupt| { + let fn_name = Ident::new(interrupt.name, Span::call_site()); + + quote! { + pub(crate) fn #fn_name(); + } + }); + + quote! { #(#vectors)* } + }); + + let groups = METADATA.interrupt_groups.iter().map(|group| { + let interrupt_group_name = Ident::new(group.name, Span::call_site()); + let group_enum = Ident::new(&format!("Group{}", &group.name[5..]), Span::call_site()); + let group_number = Literal::u32_unsuffixed(group.number); + + let matches = group.interrupts.iter().map(|interrupt| { + let variant = Ident::new(&interrupt.name, Span::call_site()); + + quote! { + #group_enum::#variant => unsafe { group_vectors::#variant() }, + } + }); + + quote! { + #[cfg(feature = "rt")] + #[crate::pac::interrupt] + fn #interrupt_group_name() { + use crate::pac::#group_enum; + + let group = crate::pac::CPUSS.int_group(#group_number); + // MUST subtract by 1 since 0 is NO_INTR + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = #group_enum::try_from(iidx as u8) else { + return; + }; + + match group { + #(#matches)* + } + } + } + }); + + quote! { + #(#groups)* + + #[cfg(feature = "rt")] + mod group_vectors { + extern "Rust" { + #(#group_vectors)* + } + } + } +} + #[derive(Debug, Clone)] struct Singleton { name: String, diff --git a/embassy-mspm0/src/gpio.rs b/embassy-mspm0/src/gpio.rs index 19a6230b6..738d51928 100644 --- a/embassy-mspm0/src/gpio.rs +++ b/embassy-mspm0/src/gpio.rs @@ -1119,24 +1119,36 @@ impl Iterator for BitIter { } } -// C110x has a dedicated interrupt just for GPIOA, as it does not have a GROUP1 interrupt. +// C110x and L110x have a dedicated interrupts just for GPIOA. +// +// These chips do not have a GROUP1 interrupt. #[cfg(all(feature = "rt", any(mspm0c110x, mspm0l110x)))] #[interrupt] fn GPIOA() { - gpioa_interrupt(); + irq_handler(pac::GPIOA, &PORTA_WAKERS); } -#[cfg(feature = "rt")] -pub(crate) fn gpioa_interrupt() { +// These symbols are weakly defined as DefaultHandler and are called by the interrupt group implementation. +// +// Defining these as no_mangle is required so that the linker will pick these over the default handler. + +#[cfg(all(feature = "rt", not(any(mspm0c110x, mspm0l110x))))] +#[no_mangle] +#[allow(non_snake_case)] +fn GPIOA() { irq_handler(pac::GPIOA, &PORTA_WAKERS); } #[cfg(all(feature = "rt", gpio_pb))] -pub(crate) fn gpiob_interrupt() { +#[no_mangle] +#[allow(non_snake_case)] +fn GPIOB() { irq_handler(pac::GPIOB, &PORTB_WAKERS); } #[cfg(all(feature = "rt", gpio_pc))] -pub(crate) fn gpioc_interrupt() { +#[allow(non_snake_case)] +#[no_mangle] +fn GPIOC() { irq_handler(pac::GPIOC, &PORTC_WAKERS); } diff --git a/embassy-mspm0/src/int_group/c110x.rs b/embassy-mspm0/src/int_group/c110x.rs deleted file mode 100644 index e6a9ddb99..000000000 --- a/embassy-mspm0/src/int_group/c110x.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // TODO: Decompose to direct u8 - let iidx = group.iidx().read().stat().to_bits(); - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} diff --git a/embassy-mspm0/src/int_group/g110x.rs b/embassy-mspm0/src/int_group/g110x.rs deleted file mode 100644 index 9f8ac4d7b..000000000 --- a/embassy-mspm0/src/int_group/g110x.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::WWDT1 => todo!("implement WWDT1"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - } -} diff --git a/embassy-mspm0/src/int_group/g150x.rs b/embassy-mspm0/src/int_group/g150x.rs deleted file mode 100644 index 706ba2078..000000000 --- a/embassy-mspm0/src/int_group/g150x.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::WWDT1 => todo!("implement WWDT1"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - Group1::COMP1 => todo!("implement COMP1"), - Group1::COMP2 => todo!("implement COMP2"), - Group1::TRNG => todo!("implement TRNG"), - } -} diff --git a/embassy-mspm0/src/int_group/g151x.rs b/embassy-mspm0/src/int_group/g151x.rs deleted file mode 100644 index e785018a7..000000000 --- a/embassy-mspm0/src/int_group/g151x.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::WWDT1 => todo!("implement WWDT1"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - Group1::COMP1 => todo!("implement COMP1"), - Group1::COMP2 => todo!("implement COMP2"), - Group1::TRNG => todo!("implement TRNG"), - Group1::GPIOC => crate::gpio::gpioc_interrupt(), - } -} diff --git a/embassy-mspm0/src/int_group/g310x.rs b/embassy-mspm0/src/int_group/g310x.rs deleted file mode 100644 index ad508d3a2..000000000 --- a/embassy-mspm0/src/int_group/g310x.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::WWDT1 => todo!("implement WWDT1"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - Group1::TRNG => todo!("implement TRNG"), - } -} diff --git a/embassy-mspm0/src/int_group/g350x.rs b/embassy-mspm0/src/int_group/g350x.rs deleted file mode 100644 index 706ba2078..000000000 --- a/embassy-mspm0/src/int_group/g350x.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::WWDT1 => todo!("implement WWDT1"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - Group1::COMP1 => todo!("implement COMP1"), - Group1::COMP2 => todo!("implement COMP2"), - Group1::TRNG => todo!("implement TRNG"), - } -} diff --git a/embassy-mspm0/src/int_group/g351x.rs b/embassy-mspm0/src/int_group/g351x.rs deleted file mode 100644 index e785018a7..000000000 --- a/embassy-mspm0/src/int_group/g351x.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::WWDT1 => todo!("implement WWDT1"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - Group1::COMP1 => todo!("implement COMP1"), - Group1::COMP2 => todo!("implement COMP2"), - Group1::TRNG => todo!("implement TRNG"), - Group1::GPIOC => crate::gpio::gpioc_interrupt(), - } -} diff --git a/embassy-mspm0/src/int_group/l11xx.rs b/embassy-mspm0/src/int_group/l11xx.rs deleted file mode 100644 index 426a80c13..000000000 --- a/embassy-mspm0/src/int_group/l11xx.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} diff --git a/embassy-mspm0/src/int_group/l12xx.rs b/embassy-mspm0/src/int_group/l12xx.rs deleted file mode 100644 index eeb2ce70d..000000000 --- a/embassy-mspm0/src/int_group/l12xx.rs +++ /dev/null @@ -1,49 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - Group1::TRNG => todo!("implement TRNG"), - Group1::GPIOC => crate::gpio::gpioc_interrupt(), - } -} diff --git a/embassy-mspm0/src/int_group/l13xx.rs b/embassy-mspm0/src/int_group/l13xx.rs deleted file mode 100644 index 8be5adcad..000000000 --- a/embassy-mspm0/src/int_group/l13xx.rs +++ /dev/null @@ -1,46 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - } -} diff --git a/embassy-mspm0/src/int_group/l222x.rs b/embassy-mspm0/src/int_group/l222x.rs deleted file mode 100644 index eeb2ce70d..000000000 --- a/embassy-mspm0/src/int_group/l222x.rs +++ /dev/null @@ -1,49 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - Group1::TRNG => todo!("implement TRNG"), - Group1::GPIOC => crate::gpio::gpioc_interrupt(), - } -} diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index f129e221b..7ff60e946 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -39,20 +39,6 @@ pub mod mode { #[cfg(feature = "_time-driver")] mod time_driver; -// Interrupt group handlers. -#[cfg_attr(mspm0c110x, path = "int_group/c110x.rs")] -#[cfg_attr(mspm0g110x, path = "int_group/g110x.rs")] -#[cfg_attr(mspm0g150x, path = "int_group/g150x.rs")] -#[cfg_attr(mspm0g350x, path = "int_group/g350x.rs")] -#[cfg_attr(mspm0g151x, path = "int_group/g151x.rs")] -#[cfg_attr(mspm0g351x, path = "int_group/g351x.rs")] -#[cfg_attr(mspm0g310x, path = "int_group/g310x.rs")] -#[cfg_attr(mspm0l110x, path = "int_group/l11xx.rs")] -#[cfg_attr(mspm0l122x, path = "int_group/l12xx.rs")] -#[cfg_attr(any(mspm0l130x, mspm0l134x), path = "int_group/l13xx.rs")] -#[cfg_attr(mspm0l222x, path = "int_group/l222x.rs")] -mod int_group; - pub(crate) mod _generated { #![allow(dead_code)] #![allow(unused_imports)] diff --git a/examples/mspm0c1104/build.rs b/examples/mspm0c1104/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0c1104/build.rs +++ b/examples/mspm0c1104/build.rs @@ -32,4 +32,6 @@ fn main() { println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=-Tlink.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + // You must tell cargo to link interrupt groups if the rt feature is enabled. + println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); } diff --git a/examples/mspm0g3507/build.rs b/examples/mspm0g3507/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0g3507/build.rs +++ b/examples/mspm0g3507/build.rs @@ -32,4 +32,6 @@ fn main() { println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=-Tlink.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + // You must tell cargo to link interrupt groups if the rt feature is enabled. + println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); } diff --git a/examples/mspm0g3519/build.rs b/examples/mspm0g3519/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0g3519/build.rs +++ b/examples/mspm0g3519/build.rs @@ -32,4 +32,6 @@ fn main() { println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=-Tlink.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + // You must tell cargo to link interrupt groups if the rt feature is enabled. + println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); } diff --git a/examples/mspm0l1306/build.rs b/examples/mspm0l1306/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0l1306/build.rs +++ b/examples/mspm0l1306/build.rs @@ -32,4 +32,6 @@ fn main() { println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=-Tlink.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + // You must tell cargo to link interrupt groups if the rt feature is enabled. + println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); } diff --git a/examples/mspm0l2228/build.rs b/examples/mspm0l2228/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0l2228/build.rs +++ b/examples/mspm0l2228/build.rs @@ -32,4 +32,6 @@ fn main() { println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=-Tlink.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + // You must tell cargo to link interrupt groups if the rt feature is enabled. + println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); } -- cgit From 7be84f137c4f56842b6ebd6de3538b0081d42a09 Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Wed, 21 May 2025 01:21:43 +0300 Subject: eeprom support --- embassy-stm32/src/flash/common.rs | 97 +++++++++++++++++++++++++++++++++++++++ embassy-stm32/src/flash/l.rs | 2 +- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 10023e637..81d8966e9 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -11,6 +11,9 @@ use crate::Peri; use crate::_generated::FLASH_BASE; use crate::peripherals::FLASH; +#[cfg(eeprom)] +use crate::_generated::{EEPROM_BASE, EEPROM_SIZE}; + /// Internal flash memory driver. pub struct Flash<'d, MODE = Async> { pub(crate) inner: Peri<'d, FLASH>, @@ -72,6 +75,100 @@ impl<'d, MODE> Flash<'d, MODE> { } } +#[cfg(eeprom)] +impl<'d> Flash<'d, Blocking> { + fn eeprom_base(&self) -> u32 { + EEPROM_BASE as u32 + } + + fn eeprom_size(&self) -> u32 { + EEPROM_SIZE as u32 + } + + fn check_eeprom_offset(&self, offset: u32, size: u32) -> Result<(), Error> { + if offset + size > self.eeprom_size() { + Err(Error::Size) + } else { + Ok(()) + } + } + + /// Read a byte (u8) from EEPROM at the given offset. + pub fn eeprom_read_u8(&self, offset: u32) -> Result { + self.check_eeprom_offset(offset, 1)?; + let addr = self.eeprom_base() + offset; + Ok(unsafe { core::ptr::read_volatile(addr as *const u8) }) + } + + /// Read a half-word (u16) from EEPROM at the given offset. + pub fn eeprom_read_u16(&self, offset: u32) -> Result { + if offset % 2 != 0 { + return Err(Error::Unaligned); + } + self.check_eeprom_offset(offset, 2)?; + let addr = self.eeprom_base() + offset; + Ok(unsafe { core::ptr::read_volatile(addr as *const u16) }) + } + + /// Read a word (u32) from EEPROM at the given offset. + pub fn eeprom_read_u32(&self, offset: u32) -> Result { + if offset % 4 != 0 { + return Err(Error::Unaligned); + } + self.check_eeprom_offset(offset, 4)?; + let addr = self.eeprom_base() + offset; + Ok(unsafe { core::ptr::read_volatile(addr as *const u32) }) + } + + /// Write a byte (u8) to EEPROM at the given offset. + pub fn eeprom_write_u8(&mut self, offset: u32, value: u8) -> Result<(), Error> { + self.check_eeprom_offset(offset, 1)?; + let addr = self.eeprom_base() + offset; + unsafe { + family::unlock(); + core::ptr::write_volatile(addr as *mut u8, value); + family::wait_ready_blocking()?; + family::clear_all_err(); + family::lock(); + } + Ok(()) + } + + /// Write a half-word (u16) to EEPROM at the given offset. + pub fn eeprom_write_u16(&mut self, offset: u32, value: u16) -> Result<(), Error> { + if offset % 2 != 0 { + return Err(Error::Unaligned); + } + self.check_eeprom_offset(offset, 2)?; + let addr = self.eeprom_base() + offset; + unsafe { + family::unlock(); + core::ptr::write_volatile(addr as *mut u16, value); + family::wait_ready_blocking()?; + family::clear_all_err(); + family::lock(); + } + Ok(()) + } + + /// Write a word (u32) to EEPROM at the given offset. + pub fn eeprom_write_u32(&mut self, offset: u32, value: u32) -> Result<(), Error> { + if offset % 4 != 0 { + return Err(Error::Unaligned); + } + self.check_eeprom_offset(offset, 4)?; + let addr = self.eeprom_base() + offset; + unsafe { + family::unlock(); + core::ptr::write_volatile(addr as *mut u32, value); + family::wait_ready_blocking()?; + family::clear_all_err(); + family::lock(); + } + Ok(()) + } +} + pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { if offset + bytes.len() as u32 > size { return Err(Error::Size); diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index 65cea005c..1b82704ec 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs @@ -162,7 +162,7 @@ pub(crate) unsafe fn clear_all_err() { pac::FLASH.nssr().modify(|_| {}); } -unsafe fn wait_ready_blocking() -> Result<(), Error> { +pub(crate) unsafe fn wait_ready_blocking() -> Result<(), Error> { loop { #[cfg(not(flash_l5))] { -- cgit From 8b65f9cf0f4095080297bf5c3e09334296da8076 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Tue, 20 May 2025 17:29:28 -0500 Subject: mspm0: link interrupt groups in tests --- tests/mspm0/build.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/mspm0/build.rs b/tests/mspm0/build.rs index 57b592abf..0b58fb9e9 100644 --- a/tests/mspm0/build.rs +++ b/tests/mspm0/build.rs @@ -19,6 +19,8 @@ fn main() -> Result<(), Box> { println!("cargo:rustc-link-arg-bins=-Tlink_ram.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); println!("cargo:rustc-link-arg-bins=-Tteleprobe.x"); + // You must tell cargo to link interrupt groups if the rt feature is enabled. + println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); Ok(()) } -- cgit From 6d19f2fd4cd073359f543776475c6ef6c5fddd00 Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Wed, 21 May 2025 02:43:41 +0300 Subject: nightly fmt --- embassy-stm32/src/flash/common.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 81d8966e9..fb899b813 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -9,10 +9,9 @@ use super::{ }; use crate::Peri; use crate::_generated::FLASH_BASE; -use crate::peripherals::FLASH; - #[cfg(eeprom)] use crate::_generated::{EEPROM_BASE, EEPROM_SIZE}; +use crate::peripherals::FLASH; /// Internal flash memory driver. pub struct Flash<'d, MODE = Async> { -- cgit From 21004fce0dae25a5f27b627861fad8912e7256f5 Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Wed, 21 May 2025 02:50:36 +0300 Subject: always declare eeprom --- embassy-stm32/build.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index b91934af3..bb5ef53d7 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1925,12 +1925,13 @@ fn main() { // ======== // Generate EEPROM constants + cfgs.declare("eeprom"); + let eeprom_memory_regions: Vec<&MemoryRegion> = memory.iter().filter(|x| x.kind == MemoryRegionKind::Eeprom).collect(); if !eeprom_memory_regions.is_empty() { cfgs.enable("eeprom"); - cfgs.declare("eeprom"); let mut sorted_eeprom_regions = eeprom_memory_regions.clone(); sorted_eeprom_regions.sort_by_key(|r| r.address); -- cgit From 1accd560054f4203e193c6e77baca1c448fbf1c9 Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Wed, 21 May 2025 08:30:38 +0300 Subject: new API --- embassy-stm32/src/flash/common.rs | 96 ---------------- embassy-stm32/src/flash/eeprom.rs | 224 ++++++++++++++++++++++++++++++++++++++ embassy-stm32/src/flash/mod.rs | 5 + 3 files changed, 229 insertions(+), 96 deletions(-) create mode 100644 embassy-stm32/src/flash/eeprom.rs diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index fb899b813..10023e637 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -9,8 +9,6 @@ use super::{ }; use crate::Peri; use crate::_generated::FLASH_BASE; -#[cfg(eeprom)] -use crate::_generated::{EEPROM_BASE, EEPROM_SIZE}; use crate::peripherals::FLASH; /// Internal flash memory driver. @@ -74,100 +72,6 @@ impl<'d, MODE> Flash<'d, MODE> { } } -#[cfg(eeprom)] -impl<'d> Flash<'d, Blocking> { - fn eeprom_base(&self) -> u32 { - EEPROM_BASE as u32 - } - - fn eeprom_size(&self) -> u32 { - EEPROM_SIZE as u32 - } - - fn check_eeprom_offset(&self, offset: u32, size: u32) -> Result<(), Error> { - if offset + size > self.eeprom_size() { - Err(Error::Size) - } else { - Ok(()) - } - } - - /// Read a byte (u8) from EEPROM at the given offset. - pub fn eeprom_read_u8(&self, offset: u32) -> Result { - self.check_eeprom_offset(offset, 1)?; - let addr = self.eeprom_base() + offset; - Ok(unsafe { core::ptr::read_volatile(addr as *const u8) }) - } - - /// Read a half-word (u16) from EEPROM at the given offset. - pub fn eeprom_read_u16(&self, offset: u32) -> Result { - if offset % 2 != 0 { - return Err(Error::Unaligned); - } - self.check_eeprom_offset(offset, 2)?; - let addr = self.eeprom_base() + offset; - Ok(unsafe { core::ptr::read_volatile(addr as *const u16) }) - } - - /// Read a word (u32) from EEPROM at the given offset. - pub fn eeprom_read_u32(&self, offset: u32) -> Result { - if offset % 4 != 0 { - return Err(Error::Unaligned); - } - self.check_eeprom_offset(offset, 4)?; - let addr = self.eeprom_base() + offset; - Ok(unsafe { core::ptr::read_volatile(addr as *const u32) }) - } - - /// Write a byte (u8) to EEPROM at the given offset. - pub fn eeprom_write_u8(&mut self, offset: u32, value: u8) -> Result<(), Error> { - self.check_eeprom_offset(offset, 1)?; - let addr = self.eeprom_base() + offset; - unsafe { - family::unlock(); - core::ptr::write_volatile(addr as *mut u8, value); - family::wait_ready_blocking()?; - family::clear_all_err(); - family::lock(); - } - Ok(()) - } - - /// Write a half-word (u16) to EEPROM at the given offset. - pub fn eeprom_write_u16(&mut self, offset: u32, value: u16) -> Result<(), Error> { - if offset % 2 != 0 { - return Err(Error::Unaligned); - } - self.check_eeprom_offset(offset, 2)?; - let addr = self.eeprom_base() + offset; - unsafe { - family::unlock(); - core::ptr::write_volatile(addr as *mut u16, value); - family::wait_ready_blocking()?; - family::clear_all_err(); - family::lock(); - } - Ok(()) - } - - /// Write a word (u32) to EEPROM at the given offset. - pub fn eeprom_write_u32(&mut self, offset: u32, value: u32) -> Result<(), Error> { - if offset % 4 != 0 { - return Err(Error::Unaligned); - } - self.check_eeprom_offset(offset, 4)?; - let addr = self.eeprom_base() + offset; - unsafe { - family::unlock(); - core::ptr::write_volatile(addr as *mut u32, value); - family::wait_ready_blocking()?; - family::clear_all_err(); - family::lock(); - } - Ok(()) - } -} - pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { if offset + bytes.len() as u32 > size { return Err(Error::Size); diff --git a/embassy-stm32/src/flash/eeprom.rs b/embassy-stm32/src/flash/eeprom.rs new file mode 100644 index 000000000..74aedb7c0 --- /dev/null +++ b/embassy-stm32/src/flash/eeprom.rs @@ -0,0 +1,224 @@ +use super::{family, Blocking, Error, Flash, EEPROM_BASE, EEPROM_SIZE}; + +#[cfg(eeprom)] +impl<'d> Flash<'d, Blocking> { + // --- Internal helpers --- + + fn check_eeprom_offset(&self, offset: u32, size: u32) -> Result<(), Error> { + if offset + .checked_add(size) + .filter(|&end| end <= EEPROM_SIZE as u32) + .is_some() + { + Ok(()) + } else { + Err(Error::Size) + } + } + + // --- Unlocked (unsafe, internal) functions --- + + unsafe fn eeprom_write_u8_slice_unlocked(&self, offset: u32, data: &[u8]) -> Result<(), Error> { + for (i, &byte) in data.iter().enumerate() { + let addr = EEPROM_BASE as u32 + offset + i as u32; + core::ptr::write_volatile(addr as *mut u8, byte); + family::wait_ready_blocking()?; + family::clear_all_err(); + } + Ok(()) + } + + unsafe fn eeprom_write_u16_slice_unlocked(&self, offset: u32, data: &[u16]) -> Result<(), Error> { + for (i, &value) in data.iter().enumerate() { + let addr = EEPROM_BASE as u32 + offset + i as u32 * 2; + core::ptr::write_volatile(addr as *mut u16, value); + family::wait_ready_blocking()?; + family::clear_all_err(); + } + Ok(()) + } + + unsafe fn eeprom_write_u32_slice_unlocked(&self, offset: u32, data: &[u32]) -> Result<(), Error> { + for (i, &value) in data.iter().enumerate() { + let addr = EEPROM_BASE as u32 + offset + i as u32 * 4; + core::ptr::write_volatile(addr as *mut u32, value); + family::wait_ready_blocking()?; + family::clear_all_err(); + } + Ok(()) + } + + // --- Public, safe API --- + + pub fn eeprom_write_u8(&mut self, offset: u32, value: u8) -> Result<(), Error> { + self.check_eeprom_offset(offset, 1)?; + unsafe { + family::unlock(); + } + unsafe { + self.eeprom_write_u8_slice_unlocked(offset, core::slice::from_ref(&value))?; + } + unsafe { + family::lock(); + } + Ok(()) + } + + pub fn eeprom_write_u16(&mut self, offset: u32, value: u16) -> Result<(), Error> { + if offset % 2 != 0 { + return Err(Error::Unaligned); + } + self.check_eeprom_offset(offset, 2)?; + unsafe { + family::unlock(); + } + unsafe { + self.eeprom_write_u16_slice_unlocked(offset, core::slice::from_ref(&value))?; + } + unsafe { + family::lock(); + } + Ok(()) + } + + pub fn eeprom_write_u32(&mut self, offset: u32, value: u32) -> Result<(), Error> { + if offset % 4 != 0 { + return Err(Error::Unaligned); + } + self.check_eeprom_offset(offset, 4)?; + unsafe { + family::unlock(); + } + unsafe { + self.eeprom_write_u32_slice_unlocked(offset, core::slice::from_ref(&value))?; + } + unsafe { + family::lock(); + } + Ok(()) + } + + pub fn eeprom_write_u8_slice(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> { + self.check_eeprom_offset(offset, data.len() as u32)?; + unsafe { + family::unlock(); + } + unsafe { + self.eeprom_write_u8_slice_unlocked(offset, data)?; + } + unsafe { + family::lock(); + } + Ok(()) + } + + pub fn eeprom_write_u16_slice(&mut self, offset: u32, data: &[u16]) -> Result<(), Error> { + if offset % 2 != 0 { + return Err(Error::Unaligned); + } + self.check_eeprom_offset(offset, data.len() as u32 * 2)?; + unsafe { + family::unlock(); + } + unsafe { + self.eeprom_write_u16_slice_unlocked(offset, data)?; + } + unsafe { + family::lock(); + } + Ok(()) + } + + pub fn eeprom_write_u32_slice(&mut self, offset: u32, data: &[u32]) -> Result<(), Error> { + if offset % 4 != 0 { + return Err(Error::Unaligned); + } + self.check_eeprom_offset(offset, data.len() as u32 * 4)?; + unsafe { + family::unlock(); + } + unsafe { + self.eeprom_write_u32_slice_unlocked(offset, data)?; + } + unsafe { + family::lock(); + } + Ok(()) + } + + pub fn eeprom_write(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> { + let start = offset; + let end = offset.checked_add(data.len() as u32).ok_or(Error::Size)?; + if end > EEPROM_SIZE as u32 { + return Err(Error::Size); + } + + let misalign = (start % 4) as usize; + let prefix_len = if misalign == 0 { + 0 + } else { + (4 - misalign).min(data.len()) + }; + let (prefix, rest) = data.split_at(prefix_len); + let aligned_len = (rest.len() / 4) * 4; + let (aligned, suffix) = rest.split_at(aligned_len); + + unsafe { + family::unlock(); + } + if !prefix.is_empty() { + unsafe { + self.eeprom_write_u8_slice_unlocked(start, prefix)?; + } + } + if !aligned.is_empty() { + let aligned_offset = start + prefix_len as u32; + let u32_data = unsafe { core::slice::from_raw_parts(aligned.as_ptr() as *const u32, aligned.len() / 4) }; + unsafe { + self.eeprom_write_u32_slice_unlocked(aligned_offset, u32_data)?; + } + } + if !suffix.is_empty() { + let suffix_offset = start + (prefix_len + aligned_len) as u32; + unsafe { + self.eeprom_write_u8_slice_unlocked(suffix_offset, suffix)?; + } + } + unsafe { + family::lock(); + } + Ok(()) + } + + pub fn eeprom_read_u8(&self, offset: u32) -> Result { + self.check_eeprom_offset(offset, 1)?; + let addr = EEPROM_BASE as u32 + offset; + Ok(unsafe { core::ptr::read_volatile(addr as *const u8) }) + } + + pub fn eeprom_read_u16(&self, offset: u32) -> Result { + if offset % 2 != 0 { + return Err(Error::Unaligned); + } + self.check_eeprom_offset(offset, 2)?; + let addr = EEPROM_BASE as u32 + offset; + Ok(unsafe { core::ptr::read_volatile(addr as *const u16) }) + } + + pub fn eeprom_read_u32(&self, offset: u32) -> Result { + if offset % 4 != 0 { + return Err(Error::Unaligned); + } + self.check_eeprom_offset(offset, 4)?; + let addr = EEPROM_BASE as u32 + offset; + Ok(unsafe { core::ptr::read_volatile(addr as *const u32) }) + } + + pub fn eeprom_read_slice(&self, offset: u32, buf: &mut [u8]) -> Result<(), Error> { + self.check_eeprom_offset(offset, buf.len() as u32)?; + let addr = EEPROM_BASE as u32 + offset; + let src = unsafe { core::slice::from_raw_parts(addr as *const u8, buf.len()) }; + buf.copy_from_slice(src); + Ok(()) + } +} diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index 26f357370..a3f9e00f7 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -5,11 +5,16 @@ use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind}; mod asynch; #[cfg(flash)] mod common; +#[cfg(eeprom)] +mod eeprom; #[cfg(flash_f4)] pub use asynch::InterruptHandler; #[cfg(flash)] pub use common::*; +#[cfg(eeprom)] +#[allow(unused_imports)] +pub use eeprom::*; pub use crate::_generated::flash_regions::*; #[cfg(eeprom)] -- cgit From bc265b98b7597ffb90fe4e951beee5d65c6c481f Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Wed, 21 May 2025 08:41:04 +0300 Subject: adding docs --- embassy-stm32/src/flash/eeprom.rs | 88 ++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/embassy-stm32/src/flash/eeprom.rs b/embassy-stm32/src/flash/eeprom.rs index 74aedb7c0..99c6b9c10 100644 --- a/embassy-stm32/src/flash/eeprom.rs +++ b/embassy-stm32/src/flash/eeprom.rs @@ -4,6 +4,7 @@ use super::{family, Blocking, Error, Flash, EEPROM_BASE, EEPROM_SIZE}; impl<'d> Flash<'d, Blocking> { // --- Internal helpers --- + /// Checks if the given offset and size are within the EEPROM bounds. fn check_eeprom_offset(&self, offset: u32, size: u32) -> Result<(), Error> { if offset .checked_add(size) @@ -18,6 +19,10 @@ impl<'d> Flash<'d, Blocking> { // --- Unlocked (unsafe, internal) functions --- + /// Writes a slice of bytes to EEPROM at the given offset without locking. + /// + /// # Safety + /// Caller must ensure EEPROM is unlocked and offset is valid. unsafe fn eeprom_write_u8_slice_unlocked(&self, offset: u32, data: &[u8]) -> Result<(), Error> { for (i, &byte) in data.iter().enumerate() { let addr = EEPROM_BASE as u32 + offset + i as u32; @@ -28,6 +33,10 @@ impl<'d> Flash<'d, Blocking> { Ok(()) } + /// Writes a slice of u16 values to EEPROM at the given offset without locking. + /// + /// # Safety + /// Caller must ensure EEPROM is unlocked and offset is valid and aligned. unsafe fn eeprom_write_u16_slice_unlocked(&self, offset: u32, data: &[u16]) -> Result<(), Error> { for (i, &value) in data.iter().enumerate() { let addr = EEPROM_BASE as u32 + offset + i as u32 * 2; @@ -38,6 +47,10 @@ impl<'d> Flash<'d, Blocking> { Ok(()) } + /// Writes a slice of u32 values to EEPROM at the given offset without locking. + /// + /// # Safety + /// Caller must ensure EEPROM is unlocked and offset is valid and aligned. unsafe fn eeprom_write_u32_slice_unlocked(&self, offset: u32, data: &[u32]) -> Result<(), Error> { for (i, &value) in data.iter().enumerate() { let addr = EEPROM_BASE as u32 + offset + i as u32 * 4; @@ -50,20 +63,20 @@ impl<'d> Flash<'d, Blocking> { // --- Public, safe API --- + /// Writes a single byte to EEPROM at the given offset. pub fn eeprom_write_u8(&mut self, offset: u32, value: u8) -> Result<(), Error> { self.check_eeprom_offset(offset, 1)?; unsafe { family::unlock(); - } - unsafe { self.eeprom_write_u8_slice_unlocked(offset, core::slice::from_ref(&value))?; - } - unsafe { family::lock(); } Ok(()) } + /// Writes a single 16-bit value to EEPROM at the given offset. + /// + /// Returns an error if the offset is not 2-byte aligned. pub fn eeprom_write_u16(&mut self, offset: u32, value: u16) -> Result<(), Error> { if offset % 2 != 0 { return Err(Error::Unaligned); @@ -71,16 +84,15 @@ impl<'d> Flash<'d, Blocking> { self.check_eeprom_offset(offset, 2)?; unsafe { family::unlock(); - } - unsafe { self.eeprom_write_u16_slice_unlocked(offset, core::slice::from_ref(&value))?; - } - unsafe { family::lock(); } Ok(()) } + /// Writes a single 32-bit value to EEPROM at the given offset. + /// + /// Returns an error if the offset is not 4-byte aligned. pub fn eeprom_write_u32(&mut self, offset: u32, value: u32) -> Result<(), Error> { if offset % 4 != 0 { return Err(Error::Unaligned); @@ -88,30 +100,26 @@ impl<'d> Flash<'d, Blocking> { self.check_eeprom_offset(offset, 4)?; unsafe { family::unlock(); - } - unsafe { self.eeprom_write_u32_slice_unlocked(offset, core::slice::from_ref(&value))?; - } - unsafe { family::lock(); } Ok(()) } + /// Writes a slice of bytes to EEPROM at the given offset. pub fn eeprom_write_u8_slice(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> { self.check_eeprom_offset(offset, data.len() as u32)?; unsafe { family::unlock(); - } - unsafe { self.eeprom_write_u8_slice_unlocked(offset, data)?; - } - unsafe { family::lock(); } Ok(()) } + /// Writes a slice of 16-bit values to EEPROM at the given offset. + /// + /// Returns an error if the offset is not 2-byte aligned. pub fn eeprom_write_u16_slice(&mut self, offset: u32, data: &[u16]) -> Result<(), Error> { if offset % 2 != 0 { return Err(Error::Unaligned); @@ -119,16 +127,15 @@ impl<'d> Flash<'d, Blocking> { self.check_eeprom_offset(offset, data.len() as u32 * 2)?; unsafe { family::unlock(); - } - unsafe { self.eeprom_write_u16_slice_unlocked(offset, data)?; - } - unsafe { family::lock(); } Ok(()) } + /// Writes a slice of 32-bit values to EEPROM at the given offset. + /// + /// Returns an error if the offset is not 4-byte aligned. pub fn eeprom_write_u32_slice(&mut self, offset: u32, data: &[u32]) -> Result<(), Error> { if offset % 4 != 0 { return Err(Error::Unaligned); @@ -136,23 +143,18 @@ impl<'d> Flash<'d, Blocking> { self.check_eeprom_offset(offset, data.len() as u32 * 4)?; unsafe { family::unlock(); - } - unsafe { self.eeprom_write_u32_slice_unlocked(offset, data)?; - } - unsafe { family::lock(); } Ok(()) } + /// Writes a byte slice to EEPROM at the given offset, handling alignment. + /// + /// This method will write unaligned prefix and suffix as bytes, and aligned middle as u32. pub fn eeprom_write(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> { + self.check_eeprom_offset(offset, data.len() as u32)?; let start = offset; - let end = offset.checked_add(data.len() as u32).ok_or(Error::Size)?; - if end > EEPROM_SIZE as u32 { - return Err(Error::Size); - } - let misalign = (start % 4) as usize; let prefix_len = if misalign == 0 { 0 @@ -165,37 +167,33 @@ impl<'d> Flash<'d, Blocking> { unsafe { family::unlock(); - } - if !prefix.is_empty() { - unsafe { + if !prefix.is_empty() { self.eeprom_write_u8_slice_unlocked(start, prefix)?; } - } - if !aligned.is_empty() { - let aligned_offset = start + prefix_len as u32; - let u32_data = unsafe { core::slice::from_raw_parts(aligned.as_ptr() as *const u32, aligned.len() / 4) }; - unsafe { + if !aligned.is_empty() { + let aligned_offset = start + prefix_len as u32; + let u32_data = core::slice::from_raw_parts(aligned.as_ptr() as *const u32, aligned.len() / 4); self.eeprom_write_u32_slice_unlocked(aligned_offset, u32_data)?; } - } - if !suffix.is_empty() { - let suffix_offset = start + (prefix_len + aligned_len) as u32; - unsafe { + if !suffix.is_empty() { + let suffix_offset = start + (prefix_len + aligned_len) as u32; self.eeprom_write_u8_slice_unlocked(suffix_offset, suffix)?; } - } - unsafe { family::lock(); } Ok(()) } + /// Reads a single byte from EEPROM at the given offset. pub fn eeprom_read_u8(&self, offset: u32) -> Result { self.check_eeprom_offset(offset, 1)?; let addr = EEPROM_BASE as u32 + offset; Ok(unsafe { core::ptr::read_volatile(addr as *const u8) }) } + /// Reads a single 16-bit value from EEPROM at the given offset. + /// + /// Returns an error if the offset is not 2-byte aligned. pub fn eeprom_read_u16(&self, offset: u32) -> Result { if offset % 2 != 0 { return Err(Error::Unaligned); @@ -205,6 +203,9 @@ impl<'d> Flash<'d, Blocking> { Ok(unsafe { core::ptr::read_volatile(addr as *const u16) }) } + /// Reads a single 32-bit value from EEPROM at the given offset. + /// + /// Returns an error if the offset is not 4-byte aligned. pub fn eeprom_read_u32(&self, offset: u32) -> Result { if offset % 4 != 0 { return Err(Error::Unaligned); @@ -214,6 +215,7 @@ impl<'d> Flash<'d, Blocking> { Ok(unsafe { core::ptr::read_volatile(addr as *const u32) }) } + /// Reads a slice of bytes from EEPROM at the given offset into the provided buffer. pub fn eeprom_read_slice(&self, offset: u32, buf: &mut [u8]) -> Result<(), Error> { self.check_eeprom_offset(offset, buf.len() as u32)?; let addr = EEPROM_BASE as u32 + offset; -- cgit From 437e45df2b468caf13475ffaf3d55cc4f01e2d6b Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Wed, 21 May 2025 09:44:28 +0300 Subject: make API more consistent --- embassy-stm32/src/flash/eeprom.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/flash/eeprom.rs b/embassy-stm32/src/flash/eeprom.rs index 99c6b9c10..5bccb2ecc 100644 --- a/embassy-stm32/src/flash/eeprom.rs +++ b/embassy-stm32/src/flash/eeprom.rs @@ -152,7 +152,7 @@ impl<'d> Flash<'d, Blocking> { /// Writes a byte slice to EEPROM at the given offset, handling alignment. /// /// This method will write unaligned prefix and suffix as bytes, and aligned middle as u32. - pub fn eeprom_write(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> { + pub fn eeprom_write_slice(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> { self.check_eeprom_offset(offset, data.len() as u32)?; let start = offset; let misalign = (start % 4) as usize; -- cgit From 27ca627fc83974d926630b4a1bfc9783c3c86bb9 Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Wed, 21 May 2025 09:54:19 +0300 Subject: added examples --- examples/stm32l0/src/bin/eeprom.rs | 32 ++++++++++++++++++++++++++++++++ examples/stm32l1/src/bin/eeprom.rs | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 examples/stm32l0/src/bin/eeprom.rs create mode 100644 examples/stm32l1/src/bin/eeprom.rs diff --git a/examples/stm32l0/src/bin/eeprom.rs b/examples/stm32l0/src/bin/eeprom.rs new file mode 100644 index 000000000..370246644 --- /dev/null +++ b/examples/stm32l0/src/bin/eeprom.rs @@ -0,0 +1,32 @@ +#![no_std] +#![no_main] + +use defmt::{info, unwrap}; +use embassy_executor::Spawner; +use embassy_stm32::flash::{Flash, EEPROM_BASE, EEPROM_SIZE}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + + info!("Hello Eeprom! Start: {}, Size: {}", EEPROM_BASE, EEPROM_SIZE); + + const ADDR: u32 = 0x0; + + let mut f = Flash::new_blocking(p.FLASH); + + info!("Reading..."); + let mut buf = [0u8; 8]; + unwrap!(f.eeprom_read_slice(ADDR, &mut buf)); + info!("Read: {=[u8]:x}", buf); + + info!("Writing..."); + unwrap!(f.eeprom_write_slice(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + + info!("Reading..."); + let mut buf = [0u8; 8]; + unwrap!(f.eeprom_read_slice(ADDR, &mut buf)); + info!("Read: {=[u8]:x}", buf); + assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); +} diff --git a/examples/stm32l1/src/bin/eeprom.rs b/examples/stm32l1/src/bin/eeprom.rs new file mode 100644 index 000000000..370246644 --- /dev/null +++ b/examples/stm32l1/src/bin/eeprom.rs @@ -0,0 +1,32 @@ +#![no_std] +#![no_main] + +use defmt::{info, unwrap}; +use embassy_executor::Spawner; +use embassy_stm32::flash::{Flash, EEPROM_BASE, EEPROM_SIZE}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + + info!("Hello Eeprom! Start: {}, Size: {}", EEPROM_BASE, EEPROM_SIZE); + + const ADDR: u32 = 0x0; + + let mut f = Flash::new_blocking(p.FLASH); + + info!("Reading..."); + let mut buf = [0u8; 8]; + unwrap!(f.eeprom_read_slice(ADDR, &mut buf)); + info!("Read: {=[u8]:x}", buf); + + info!("Writing..."); + unwrap!(f.eeprom_write_slice(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + + info!("Reading..."); + let mut buf = [0u8; 8]; + unwrap!(f.eeprom_read_slice(ADDR, &mut buf)); + info!("Read: {=[u8]:x}", buf); + assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); +} -- cgit From 05c511355638c3a55ab509ef9b2e30f5564b6282 Mon Sep 17 00:00:00 2001 From: RaulIQ Date: Wed, 21 May 2025 12:27:25 +0300 Subject: add waveform_up_multichannel using DMAR/DCR --- embassy-stm32/src/timer/simple_pwm.rs | 68 +++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 8fd7e8df4..c6fd169fc 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -381,6 +381,74 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { self.inner.enable_update_dma(false); } } + + /// Generate a multichannel sequence of PWM waveforms using DMA triggered by timer update events. + /// + /// This method utilizes the timer's DMA burst transfer capability to update multiple CCRx registers + /// in sequence on each update event (UEV). The data is written via the DMAR register using the + /// DMA base address (DBA) and burst length (DBL) configured in the DCR register. + /// + /// Note: + /// you will need to provide corresponding TIMx_UP DMA channel to use this method. + pub async fn waveform_up_multichannel( + &mut self, + dma: Peri<'_, impl super::UpDma>, + starting_channel: Channel, + ending_channel: Channel, + duty: &[u16], + ) { + let cr1_addr = self.inner.regs_gp16().cr1().as_ptr() as u32; + let start_ch_index = starting_channel.index(); + let end_ch_index = ending_channel.index(); + + assert!(start_ch_index <= end_ch_index); + + let ccrx_addr = self.inner.regs_gp16().ccr(start_ch_index).as_ptr() as u32; + self.inner + .regs_gp16() + .dcr() + .modify(|w| w.set_dba(((ccrx_addr - cr1_addr) / 4) as u8)); + self.inner + .regs_gp16() + .dcr() + .modify(|w| w.set_dbl((end_ch_index - start_ch_index) as u8)); + + #[allow(clippy::let_unit_value)] // eg. stm32f334 + let req = dma.request(); + + let original_update_dma_state = self.inner.get_update_dma_state(); + if !original_update_dma_state { + self.inner.enable_update_dma(true); + } + + unsafe { + #[cfg(not(any(bdma, gpdma)))] + use crate::dma::{Burst, FifoThreshold}; + use crate::dma::{Transfer, TransferOptions}; + + let dma_transfer_option = TransferOptions { + #[cfg(not(any(bdma, gpdma)))] + fifo_threshold: Some(FifoThreshold::Full), + #[cfg(not(any(bdma, gpdma)))] + mburst: Burst::Incr4, + ..Default::default() + }; + + Transfer::new_write( + dma, + req, + duty, + self.inner.regs_gp16().dmar().as_ptr() as *mut u16, + dma_transfer_option, + ) + .await + }; + + if !original_update_dma_state { + self.inner.enable_update_dma(false); + } + } + } macro_rules! impl_waveform_chx { -- cgit From d5c9d1af26e7bd0ebefafba6ae28b0bd660aa924 Mon Sep 17 00:00:00 2001 From: ragarnoy Date: Wed, 21 May 2025 12:27:56 +0200 Subject: Remove unnecessary atomic fences from intercore examples --- examples/stm32h755cm4/src/bin/intercore.rs | 6 ------ examples/stm32h755cm7/src/bin/intercore.rs | 5 ----- 2 files changed, 11 deletions(-) diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs index 6ebf61cd4..d5e3e7648 100644 --- a/examples/stm32h755cm4/src/bin/intercore.rs +++ b/examples/stm32h755cm4/src/bin/intercore.rs @@ -55,9 +55,7 @@ mod shared { } else { current & !(1 << bit) // Clear bit }; - self.led_states.store(new_value, Ordering::SeqCst); - core::sync::atomic::fence(Ordering::SeqCst); } /// Get current LED state @@ -66,8 +64,6 @@ mod shared { let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; let value = self.led_states.load(Ordering::SeqCst); - core::sync::atomic::fence(Ordering::SeqCst); - (value & (1 << bit)) != 0 } @@ -78,7 +74,6 @@ mod shared { let current = self.counter.load(Ordering::SeqCst); let new_value = current.wrapping_add(1); self.counter.store(new_value, Ordering::SeqCst); - core::sync::atomic::fence(Ordering::SeqCst); new_value } @@ -86,7 +81,6 @@ mod shared { #[inline(never)] pub fn get_counter(&self) -> u32 { let value = self.counter.load(Ordering::SeqCst); - core::sync::atomic::fence(Ordering::SeqCst); value } } diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs index 530e782ab..a4e1b5ff4 100644 --- a/examples/stm32h755cm7/src/bin/intercore.rs +++ b/examples/stm32h755cm7/src/bin/intercore.rs @@ -67,7 +67,6 @@ mod shared { }; self.led_states.store(new_value, Ordering::SeqCst); - core::sync::atomic::compiler_fence(Ordering::SeqCst); } /// Get current LED state @@ -77,8 +76,6 @@ mod shared { let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT }; let value = self.led_states.load(Ordering::SeqCst); - core::sync::atomic::compiler_fence(Ordering::SeqCst); - (value & (1 << bit)) != 0 } @@ -88,7 +85,6 @@ mod shared { let current = self.counter.load(Ordering::SeqCst); let new_value = current.wrapping_add(1); self.counter.store(new_value, Ordering::SeqCst); - core::sync::atomic::compiler_fence(Ordering::SeqCst); new_value } @@ -97,7 +93,6 @@ mod shared { #[allow(dead_code)] pub fn get_counter(&self) -> u32 { let value = self.counter.load(Ordering::SeqCst); - core::sync::atomic::compiler_fence(Ordering::SeqCst); value } } -- cgit From 0e47478f01335c735f8f27fa3a935776736e9afa Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 19 May 2025 16:38:34 +0200 Subject: nrf/rng: add Blocking/Async Mode param. This allows avoiding creating the irq handler if you're only going to use it in blocking mode. --- embassy-nrf/src/lib.rs | 24 ++++++++++++++++ embassy-nrf/src/rng.rs | 78 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 76 insertions(+), 26 deletions(-) diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 0c5dd059d..398bfed48 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -1039,3 +1039,27 @@ pub fn init(config: config::Config) -> Peripherals { peripherals } + +/// Operating modes for peripherals. +pub mod mode { + trait SealedMode {} + + /// Operating mode for a peripheral. + #[allow(private_bounds)] + pub trait Mode: SealedMode {} + + macro_rules! impl_mode { + ($name:ident) => { + impl SealedMode for $name {} + impl Mode for $name {} + }; + } + + /// Blocking mode. + pub struct Blocking; + /// Async mode. + pub struct Async; + + impl_mode!(Blocking); + impl_mode!(Async); +} diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs index 7e42dc938..9d3130e6e 100644 --- a/embassy-nrf/src/rng.rs +++ b/embassy-nrf/src/rng.rs @@ -14,6 +14,7 @@ use embassy_hal_internal::{Peri, PeripheralType}; use embassy_sync::waitqueue::WakerRegistration; use crate::interrupt::typelevel::Interrupt; +use crate::mode::{Async, Blocking, Mode}; use crate::{interrupt, pac}; /// Interrupt handler. @@ -55,11 +56,31 @@ impl interrupt::typelevel::Handler for InterruptHandl /// A wrapper around an nRF RNG peripheral. /// /// It has a non-blocking API, and a blocking api through `rand`. -pub struct Rng<'d, T: Instance> { +pub struct Rng<'d, T: Instance, M: Mode> { _peri: Peri<'d, T>, + _phantom: PhantomData, } -impl<'d, T: Instance> Rng<'d, T> { +impl<'d, T: Instance> Rng<'d, T, Blocking> { + /// Creates a new RNG driver from the `RNG` peripheral and interrupt. + /// + /// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor, + /// e.g. using `mem::forget`. + /// + /// The synchronous API is safe. + pub fn new_blocking(rng: Peri<'d, T>) -> Self { + let this = Self { + _peri: rng, + _phantom: PhantomData, + }; + + this.stop(); + + this + } +} + +impl<'d, T: Instance> Rng<'d, T, Async> { /// Creates a new RNG driver from the `RNG` peripheral and interrupt. /// /// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor, @@ -70,7 +91,10 @@ impl<'d, T: Instance> Rng<'d, T> { rng: Peri<'d, T>, _irq: impl interrupt::typelevel::Binding> + 'd, ) -> Self { - let this = Self { _peri: rng }; + let this = Self { + _peri: rng, + _phantom: PhantomData, + }; this.stop(); this.disable_irq(); @@ -81,14 +105,6 @@ impl<'d, T: Instance> Rng<'d, T> { this } - fn stop(&self) { - T::regs().tasks_stop().write_value(1) - } - - fn start(&self) { - T::regs().tasks_start().write_value(1) - } - fn enable_irq(&self) { T::regs().intenset().write(|w| w.set_valrdy(true)); } @@ -97,16 +113,6 @@ impl<'d, T: Instance> Rng<'d, T> { T::regs().intenclr().write(|w| w.set_valrdy(true)); } - /// Enable or disable the RNG's bias correction. - /// - /// Bias correction removes any bias towards a '1' or a '0' in the bits generated. - /// However, this makes the generation of numbers slower. - /// - /// Defaults to disabled. - pub fn set_bias_correction(&self, enable: bool) { - T::regs().config().write(|w| w.set_dercen(enable)) - } - /// Fill the buffer with random bytes. pub async fn fill_bytes(&mut self, dest: &mut [u8]) { if dest.is_empty() { @@ -153,6 +159,26 @@ impl<'d, T: Instance> Rng<'d, T> { // Trigger the teardown drop(on_drop); } +} + +impl<'d, T: Instance, M: Mode> Rng<'d, T, M> { + fn stop(&self) { + T::regs().tasks_stop().write_value(1) + } + + fn start(&self) { + T::regs().tasks_start().write_value(1) + } + + /// Enable or disable the RNG's bias correction. + /// + /// Bias correction removes any bias towards a '1' or a '0' in the bits generated. + /// However, this makes the generation of numbers slower. + /// + /// Defaults to disabled. + pub fn set_bias_correction(&self, enable: bool) { + T::regs().config().write(|w| w.set_dercen(enable)) + } /// Fill the buffer with random bytes, blocking version. pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) { @@ -184,7 +210,7 @@ impl<'d, T: Instance> Rng<'d, T> { } } -impl<'d, T: Instance> Drop for Rng<'d, T> { +impl<'d, T: Instance, M: Mode> Drop for Rng<'d, T, M> { fn drop(&mut self) { self.stop(); critical_section::with(|cs| { @@ -195,7 +221,7 @@ impl<'d, T: Instance> Drop for Rng<'d, T> { } } -impl<'d, T: Instance> rand_core_06::RngCore for Rng<'d, T> { +impl<'d, T: Instance, M: Mode> rand_core_06::RngCore for Rng<'d, T, M> { fn fill_bytes(&mut self, dest: &mut [u8]) { self.blocking_fill_bytes(dest); } @@ -211,9 +237,9 @@ impl<'d, T: Instance> rand_core_06::RngCore for Rng<'d, T> { } } -impl<'d, T: Instance> rand_core_06::CryptoRng for Rng<'d, T> {} +impl<'d, T: Instance, M: Mode> rand_core_06::CryptoRng for Rng<'d, T, M> {} -impl<'d, T: Instance> rand_core_09::RngCore for Rng<'d, T> { +impl<'d, T: Instance, M: Mode> rand_core_09::RngCore for Rng<'d, T, M> { fn fill_bytes(&mut self, dest: &mut [u8]) { self.blocking_fill_bytes(dest); } @@ -225,7 +251,7 @@ impl<'d, T: Instance> rand_core_09::RngCore for Rng<'d, T> { } } -impl<'d, T: Instance> rand_core_09::CryptoRng for Rng<'d, T> {} +impl<'d, T: Instance, M: Mode> rand_core_09::CryptoRng for Rng<'d, T, M> {} /// Peripheral static state pub(crate) struct State { -- cgit From 0bbde1f65964acccb52ca8913da0f99511d29336 Mon Sep 17 00:00:00 2001 From: Adam Morgan Date: Mon, 19 May 2025 16:02:20 -0600 Subject: Add support for rtc_v3h7rs --- embassy-stm32/src/rtc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index b16c6fdca..49f423f37 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -25,7 +25,7 @@ use crate::time::Hertz; ), path = "v2.rs" )] -#[cfg_attr(any(rtc_v3, rtc_v3u5, rtc_v3l5), path = "v3.rs")] +#[cfg_attr(any(rtc_v3, rtc_v3u5, rtc_v3l5, rtc_v3h7rs), path = "v3.rs")] mod _version; #[allow(unused_imports)] pub use _version::*; -- cgit From 3c025ff3772f6c20d53151a25b8cca9598bfcb2c Mon Sep 17 00:00:00 2001 From: Adam Morgan Date: Tue, 20 May 2025 09:17:38 -0600 Subject: Update stm32-metapac tag --- embassy-stm32/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 413c92cce..2ab4f9960 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7251801e3273011ce28a89e8f2e45eec2e419e26" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-27ef8fba3483187e852eaf3796d827259f61e8ec" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7251801e3273011ce28a89e8f2e45eec2e419e26", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-27ef8fba3483187e852eaf3796d827259f61e8ec", default-features = false, features = ["metadata"] } [features] default = ["rt"] -- cgit From 65a22439d587746f6311ed05af740fd0cd455644 Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Wed, 21 May 2025 11:17:59 +0200 Subject: feat(stm32-l): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/bd.rs | 18 +++++++++++------- embassy-stm32/src/rcc/hsi48.rs | 8 +++++++- embassy-stm32/src/rcc/l.rs | 17 ++++++++++++----- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs index 57aaba1c7..939c05907 100644 --- a/embassy-stm32/src/rcc/bd.rs +++ b/embassy-stm32/src/rcc/bd.rs @@ -92,6 +92,16 @@ pub struct LsConfig { } impl LsConfig { + pub const fn new() -> Self { + // on L5, just the fact that LSI is enabled makes things crash. + // TODO: investigate. + + #[cfg(not(stm32l5))] + return Self::default_lsi(); + #[cfg(stm32l5)] + return Self::off(); + } + pub const fn default_lse() -> Self { Self { rtc: RtcClockSource::LSE, @@ -124,13 +134,7 @@ impl LsConfig { impl Default for LsConfig { fn default() -> Self { - // on L5, just the fact that LSI is enabled makes things crash. - // TODO: investigate. - - #[cfg(not(stm32l5))] - return Self::default_lsi(); - #[cfg(stm32l5)] - return Self::off(); + Self::new() } } diff --git a/embassy-stm32/src/rcc/hsi48.rs b/embassy-stm32/src/rcc/hsi48.rs index efabd059f..3ea5c96c9 100644 --- a/embassy-stm32/src/rcc/hsi48.rs +++ b/embassy-stm32/src/rcc/hsi48.rs @@ -18,9 +18,15 @@ pub struct Hsi48Config { pub sync_from_usb: bool, } +impl Hsi48Config { + pub const fn new() -> Self { + Self { sync_from_usb: false } + } +} + impl Default for Hsi48Config { fn default() -> Self { - Self { sync_from_usb: false } + Self::new() } } diff --git a/embassy-stm32/src/rcc/l.rs b/embassy-stm32/src/rcc/l.rs index 863942f1a..91e6ae07e 100644 --- a/embassy-stm32/src/rcc/l.rs +++ b/embassy-stm32/src/rcc/l.rs @@ -68,9 +68,9 @@ pub struct Config { pub mux: super::mux::ClockMux, } -impl Default for Config { +impl Config { #[inline] - fn default() -> Config { + pub const fn new() -> Self { Config { hse: None, hsi: false, @@ -90,15 +90,22 @@ impl Default for Config { #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] pllsai2: None, #[cfg(crs)] - hsi48: Some(Default::default()), - ls: Default::default(), + hsi48: Some(crate::rcc::Hsi48Config::new()), + ls: crate::rcc::LsConfig::new(), #[cfg(any(stm32l0, stm32l1))] voltage_scale: VoltageScale::RANGE1, - mux: Default::default(), + mux: super::mux::ClockMux::default(), } } } +impl Default for Config { + #[inline] + fn default() -> Config { + Self::new() + } +} + #[cfg(stm32wb)] pub const WPAN_DEFAULT: Config = Config { hse: Some(Hse { -- cgit From 79b24bd35d452d162867480327e7b77296aad8c5 Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Wed, 21 May 2025 11:36:55 +0200 Subject: feat(stm32-c0): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/c0.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs index 0b749bcff..68f67af01 100644 --- a/embassy-stm32/src/rcc/c0.rs +++ b/embassy-stm32/src/rcc/c0.rs @@ -59,9 +59,9 @@ pub struct Config { pub mux: super::mux::ClockMux, } -impl Default for Config { +impl Config { #[inline] - fn default() -> Config { + pub const fn new() -> Self { Config { hsi: Some(Hsi { sys_div: HsiSysDiv::DIV4, @@ -71,12 +71,19 @@ impl Default for Config { sys: Sysclk::HSISYS, ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, - ls: Default::default(), - mux: Default::default(), + ls: crate::rcc::LsConfig::new(), + mux: super::mux::ClockMux::default(), } } } +impl Default for Config { + #[inline] + fn default() -> Config { + Self::new() + } +} + pub(crate) unsafe fn init(config: Config) { // Turn on the HSI match config.hsi { -- cgit From 4e6df1704703d69162fe91416fba6daa12eec0f4 Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Wed, 21 May 2025 11:36:55 +0200 Subject: feat(stm32-f013): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/f013.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/rcc/f013.rs b/embassy-stm32/src/rcc/f013.rs index cfa223d1f..1155b6acd 100644 --- a/embassy-stm32/src/rcc/f013.rs +++ b/embassy-stm32/src/rcc/f013.rs @@ -126,13 +126,13 @@ pub struct Config { pub ls: super::LsConfig, } -impl Default for Config { - fn default() -> Self { +impl Config { + pub const fn new() -> Self { Self { hsi: true, hse: None, #[cfg(crs)] - hsi48: Some(Default::default()), + hsi48: Some(crate::rcc::Hsi48Config::new()), sys: Sysclk::HSI, pll: None, @@ -147,7 +147,7 @@ impl Default for Config { apb1_pre: APBPrescaler::DIV1, #[cfg(not(stm32f0))] apb2_pre: APBPrescaler::DIV1, - ls: Default::default(), + ls: crate::rcc::LsConfig::new(), #[cfg(stm32f1)] // ensure ADC is not out of range by default even if APB2 is maxxed out (36mhz) @@ -163,11 +163,17 @@ impl Default for Config { #[cfg(stm32f107)] i2s3_src: I2s2src::SYS, - mux: Default::default(), + mux: super::mux::ClockMux::default(), } } } +impl Default for Config { + fn default() -> Self { + Self::new() + } +} + /// Initialize and Set the clock frequencies pub(crate) unsafe fn init(config: Config) { // Turn on the HSI -- cgit From 3fcfec7b943c3ac26668c1c168e549fe3009547e Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Wed, 21 May 2025 11:36:55 +0200 Subject: feat(stm32-f247): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/f247.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/rcc/f247.rs b/embassy-stm32/src/rcc/f247.rs index ee67f1cc0..8f2e8db5f 100644 --- a/embassy-stm32/src/rcc/f247.rs +++ b/embassy-stm32/src/rcc/f247.rs @@ -108,8 +108,8 @@ pub struct Config { pub voltage: VoltageScale, } -impl Default for Config { - fn default() -> Self { +impl Config { + pub const fn new() -> Self { Self { hsi: true, hse: None, @@ -127,15 +127,21 @@ impl Default for Config { apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, - ls: Default::default(), + ls: crate::rcc::LsConfig::new(), #[cfg(stm32f2)] voltage: VoltageScale::Range3, - mux: Default::default(), + mux: super::mux::ClockMux::default(), } } } +impl Default for Config { + fn default() -> Self { + Self::new() + } +} + pub(crate) unsafe fn init(config: Config) { // set VOS to SCALE1, if use PLL // TODO: check real clock speed before set VOS -- cgit From 26fb6eb9f65e7bf03302c26727ef7d6d940cf648 Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Wed, 21 May 2025 11:36:55 +0200 Subject: feat(stm32-g0): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/g0.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs index e391b1210..c03cbf9a8 100644 --- a/embassy-stm32/src/rcc/g0.rs +++ b/embassy-stm32/src/rcc/g0.rs @@ -97,9 +97,9 @@ pub struct Config { pub mux: super::mux::ClockMux, } -impl Default for Config { +impl Config { #[inline] - fn default() -> Config { + pub const fn new() -> Self { Config { hsi: Some(Hsi { sys_div: HsiSysDiv::DIV1, @@ -107,18 +107,25 @@ impl Default for Config { hse: None, sys: Sysclk::HSI, #[cfg(crs)] - hsi48: Some(Default::default()), + hsi48: Some(crate::rcc::Hsi48Config::new()), pll: None, ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, low_power_run: false, - ls: Default::default(), + ls: crate::rcc::LsConfig::new(), voltage_range: VoltageRange::RANGE1, - mux: Default::default(), + mux: super::mux::ClockMux::default(), } } } +impl Default for Config { + #[inline] + fn default() -> Config { + Self::new() + } +} + #[derive(Default)] pub struct PllFreq { pub pll_p: Option, -- cgit From ea243761f727fb4fe2e2a55e85d3f0ac80e6387d Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Wed, 21 May 2025 11:36:55 +0200 Subject: feat(stm32-g4): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/g4.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index d7d5c7388..e4b216450 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -91,26 +91,33 @@ pub struct Config { pub mux: super::mux::ClockMux, } -impl Default for Config { +impl Config { #[inline] - fn default() -> Config { + pub const fn new() -> Self { Config { hsi: true, hse: None, sys: Sysclk::HSI, - hsi48: Some(Default::default()), + hsi48: Some(crate::rcc::Hsi48Config::new()), pll: None, ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, low_power_run: false, - ls: Default::default(), + ls: crate::rcc::LsConfig::new(), boost: false, - mux: Default::default(), + mux: super::mux::ClockMux::default(), } } } +impl Default for Config { + #[inline] + fn default() -> Config { + Self::new() + } +} + #[derive(Default)] pub struct PllFreq { pub pll_p: Option, -- cgit From 48b36adafd0e001e5d277f480359396759a0509e Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Wed, 21 May 2025 11:36:55 +0200 Subject: feat(stm32-h): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/h.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index eaba8cefb..383f48874 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs @@ -218,13 +218,13 @@ pub struct Config { pub mux: super::mux::ClockMux, } -impl Default for Config { - fn default() -> Self { +impl Config { + pub const fn new() -> Self { Self { hsi: Some(HSIPrescaler::DIV1), hse: None, csi: false, - hsi48: Some(Default::default()), + hsi48: Some(crate::rcc::Hsi48Config::new()), sys: Sysclk::HSI, pll1: None, pll2: None, @@ -248,16 +248,22 @@ impl Default for Config { voltage_scale: VoltageScale::Scale0, #[cfg(rcc_h7rs)] voltage_scale: VoltageScale::HIGH, - ls: Default::default(), + ls: crate::rcc::LsConfig::new(), #[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468, pwr_h7rs))] supply_config: SupplyConfig::LDO, - mux: Default::default(), + mux: super::mux::ClockMux::default(), } } } +impl Default for Config { + fn default() -> Self { + Self::new() + } +} + pub(crate) unsafe fn init(config: Config) { #[cfg(any(stm32h7))] let pwr_reg = PWR.cr3(); -- cgit From da86052586b38768bdc2f709fda299ab06260cdb Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Wed, 21 May 2025 11:36:55 +0200 Subject: feat(stm32-u5): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/u5.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index 93a327be7..ff70466b9 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -97,14 +97,14 @@ pub struct Config { pub mux: super::mux::ClockMux, } -impl Default for Config { - fn default() -> Self { +impl Config { + pub const fn new() -> Self { Self { msis: Some(Msirange::RANGE_4MHZ), msik: Some(Msirange::RANGE_4MHZ), hse: None, hsi: false, - hsi48: Some(Default::default()), + hsi48: Some(crate::rcc::Hsi48Config::new()), pll1: None, pll2: None, pll3: None, @@ -114,12 +114,18 @@ impl Default for Config { apb2_pre: APBPrescaler::DIV1, apb3_pre: APBPrescaler::DIV1, voltage_range: VoltageScale::RANGE1, - ls: Default::default(), - mux: Default::default(), + ls: crate::rcc::LsConfig::new(), + mux: super::mux::ClockMux::default(), } } } +impl Default for Config { + fn default() -> Self { + Self::new() + } +} + pub(crate) unsafe fn init(config: Config) { // Set the requested power mode PWR.vosr().modify(|w| w.set_vos(config.voltage_range)); -- cgit From 576241fe2a455fff58527d9a593583fdab2d51bb Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Wed, 21 May 2025 11:36:55 +0200 Subject: feat(stm32-wba): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/wba.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index 1fee648d4..98d2dcf0e 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs @@ -37,9 +37,9 @@ pub struct Config { pub mux: super::mux::ClockMux, } -impl Default for Config { +impl Config { #[inline] - fn default() -> Config { + pub const fn new() -> Self { Config { hse: None, hsi: true, @@ -48,13 +48,20 @@ impl Default for Config { apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, apb7_pre: APBPrescaler::DIV1, - ls: Default::default(), + ls: crate::rcc::LsConfig::new(), voltage_scale: VoltageScale::RANGE2, - mux: Default::default(), + mux: super::mux::ClockMux::default(), } } } +impl Default for Config { + #[inline] + fn default() -> Config { + Self::new() + } +} + fn hsi_enable() { RCC.cr().modify(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} -- cgit From 62ffc995f179de25d3fc41b420dd0194c94df737 Mon Sep 17 00:00:00 2001 From: RaulIQ Date: Wed, 21 May 2025 16:39:41 +0300 Subject: improve waveform_up_multi_channel documentation --- embassy-stm32/src/timer/simple_pwm.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index c6fd169fc..972a3852c 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -388,9 +388,27 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// in sequence on each update event (UEV). The data is written via the DMAR register using the /// DMA base address (DBA) and burst length (DBL) configured in the DCR register. /// + /// The `duty` buffer must be structured as a flattened 2D array in row-major order, where each row + /// represents a single update event and each column corresponds to a specific timer channel (starting + /// from `starting_channel` up to and including `ending_channel`). + /// + /// For example, if using channels 1 through 4, a buffer of 4 update steps might look like: + /// + /// ```rust + /// let dma_buf: [u16; 16] = [ + /// ch1_duty_1, ch2_duty_1, ch3_duty_1, ch4_duty_1, // update 1 + /// ch1_duty_2, ch2_duty_2, ch3_duty_2, ch4_duty_2, // update 2 + /// ch1_duty_3, ch2_duty_3, ch3_duty_3, ch4_duty_3, // update 3 + /// ch1_duty_4, ch2_duty_4, ch3_duty_4, ch4_duty_4, // update 4 + /// ]; + /// ``` + /// + /// Each group of N values (where N = number of channels) is transferred on one update event, + /// updating the duty cycles of all selected channels simultaneously. + /// /// Note: /// you will need to provide corresponding TIMx_UP DMA channel to use this method. - pub async fn waveform_up_multichannel( + pub async fn waveform_up_multi_channel( &mut self, dma: Peri<'_, impl super::UpDma>, starting_channel: Channel, -- cgit From 8e93ae88995d4f6663b2ba7ce2d4987d907c0339 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 20 May 2025 10:11:30 -0700 Subject: imxrt: add button example --- examples/mimxrt6/src/bin/button.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 examples/mimxrt6/src/bin/button.rs diff --git a/examples/mimxrt6/src/bin/button.rs b/examples/mimxrt6/src/bin/button.rs new file mode 100644 index 000000000..efb7f14af --- /dev/null +++ b/examples/mimxrt6/src/bin/button.rs @@ -0,0 +1,29 @@ +#![no_std] +#![no_main] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_futures::select::{select, Either}; +use embassy_imxrt::gpio; +use {defmt_rtt as _, embassy_imxrt_examples as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_imxrt::init(Default::default()); + + let mut user1 = gpio::Input::new(p.PIO1_1, gpio::Pull::None, gpio::Inverter::Disabled); + let mut user2 = gpio::Input::new(p.PIO0_10, gpio::Pull::None, gpio::Inverter::Disabled); + + loop { + let res = select(user1.wait_for_falling_edge(), user2.wait_for_falling_edge()).await; + + match res { + Either::First(()) => { + info!("Button `USER1' pressed"); + } + Either::Second(()) => { + info!("Button `USER2' pressed"); + } + } + } +} -- cgit From 7a600fe9256a4c7c25501320da1de1fce8e1b39e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 20 May 2025 08:49:34 -0700 Subject: timer: ostimer: wait for match write ready Before writing to MATCH_L/MATCH_H registers, wait for permission to do so by pollinmg MATCH_WR_RDY bit in CTRL register. --- embassy-imxrt/src/time_driver.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/embassy-imxrt/src/time_driver.rs b/embassy-imxrt/src/time_driver.rs index c68679d3e..f127609c8 100644 --- a/embassy-imxrt/src/time_driver.rs +++ b/embassy-imxrt/src/time_driver.rs @@ -336,6 +336,10 @@ impl OsTimer { let alarm = self.alarms.borrow(cs); alarm.timestamp.set(timestamp); + // Wait until we're allowed to write to MATCH_L/MATCH_H + // registers + while os().osevent_ctrl().read().match_wr_rdy().bit_is_set() {} + let t = self.now(); if timestamp <= t { os().osevent_ctrl().modify(|_, w| w.ostimer_intena().clear_bit()); @@ -366,7 +370,8 @@ impl OsTimer { fn on_interrupt(&self) { critical_section::with(|cs| { if os().osevent_ctrl().read().ostimer_intrflag().bit_is_set() { - os().osevent_ctrl().modify(|_, w| w.ostimer_intena().clear_bit()); + os().osevent_ctrl() + .modify(|_, w| w.ostimer_intena().clear_bit().ostimer_intrflag().set_bit()); self.trigger_alarm(cs); } }); -- cgit From 966186064ebf36634e9930dd4b2d83ed675f6eb0 Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Wed, 21 May 2025 20:59:49 +0300 Subject: fix UB --- embassy-stm32/src/flash/eeprom.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/flash/eeprom.rs b/embassy-stm32/src/flash/eeprom.rs index 5bccb2ecc..68bcc6c15 100644 --- a/embassy-stm32/src/flash/eeprom.rs +++ b/embassy-stm32/src/flash/eeprom.rs @@ -154,6 +154,7 @@ impl<'d> Flash<'d, Blocking> { /// This method will write unaligned prefix and suffix as bytes, and aligned middle as u32. pub fn eeprom_write_slice(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> { self.check_eeprom_offset(offset, data.len() as u32)?; + let start = offset; let misalign = (start % 4) as usize; let prefix_len = if misalign == 0 { @@ -163,17 +164,24 @@ impl<'d> Flash<'d, Blocking> { }; let (prefix, rest) = data.split_at(prefix_len); let aligned_len = (rest.len() / 4) * 4; - let (aligned, suffix) = rest.split_at(aligned_len); + let (bytes_for_u32_write, suffix) = rest.split_at(aligned_len); unsafe { family::unlock(); if !prefix.is_empty() { self.eeprom_write_u8_slice_unlocked(start, prefix)?; } - if !aligned.is_empty() { - let aligned_offset = start + prefix_len as u32; - let u32_data = core::slice::from_raw_parts(aligned.as_ptr() as *const u32, aligned.len() / 4); - self.eeprom_write_u32_slice_unlocked(aligned_offset, u32_data)?; + if !bytes_for_u32_write.is_empty() { + let aligned_eeprom_offset = start + prefix_len as u32; + let base_eeprom_addr = EEPROM_BASE as u32 + aligned_eeprom_offset; + for (i, chunk) in bytes_for_u32_write.chunks_exact(4).enumerate() { + // Safely read a u32 from a potentially unaligned pointer into the chunk. + let value = (chunk.as_ptr() as *const u32).read_unaligned(); + let current_eeprom_addr = base_eeprom_addr + (i * 4) as u32; + core::ptr::write_volatile(current_eeprom_addr as *mut u32, value); + family::wait_ready_blocking()?; + family::clear_all_err(); + } } if !suffix.is_empty() { let suffix_offset = start + (prefix_len + aligned_len) as u32; -- cgit From e4a6d7aeddd686e47e1a26cd129e7bb646dcb0be Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Wed, 21 May 2025 21:30:23 +0300 Subject: fix: lock on early return --- embassy-stm32/src/flash/eeprom.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/embassy-stm32/src/flash/eeprom.rs b/embassy-stm32/src/flash/eeprom.rs index 68bcc6c15..cc3529eb9 100644 --- a/embassy-stm32/src/flash/eeprom.rs +++ b/embassy-stm32/src/flash/eeprom.rs @@ -1,3 +1,5 @@ +use embassy_hal_internal::drop::OnDrop; + use super::{family, Blocking, Error, Flash, EEPROM_BASE, EEPROM_SIZE}; #[cfg(eeprom)] @@ -68,8 +70,8 @@ impl<'d> Flash<'d, Blocking> { self.check_eeprom_offset(offset, 1)?; unsafe { family::unlock(); + let _on_drop = OnDrop::new(|| family::lock()); self.eeprom_write_u8_slice_unlocked(offset, core::slice::from_ref(&value))?; - family::lock(); } Ok(()) } @@ -84,8 +86,8 @@ impl<'d> Flash<'d, Blocking> { self.check_eeprom_offset(offset, 2)?; unsafe { family::unlock(); + let _on_drop = OnDrop::new(|| family::lock()); self.eeprom_write_u16_slice_unlocked(offset, core::slice::from_ref(&value))?; - family::lock(); } Ok(()) } @@ -100,8 +102,8 @@ impl<'d> Flash<'d, Blocking> { self.check_eeprom_offset(offset, 4)?; unsafe { family::unlock(); + let _on_drop = OnDrop::new(|| family::lock()); self.eeprom_write_u32_slice_unlocked(offset, core::slice::from_ref(&value))?; - family::lock(); } Ok(()) } @@ -111,8 +113,8 @@ impl<'d> Flash<'d, Blocking> { self.check_eeprom_offset(offset, data.len() as u32)?; unsafe { family::unlock(); + let _on_drop = OnDrop::new(|| family::lock()); self.eeprom_write_u8_slice_unlocked(offset, data)?; - family::lock(); } Ok(()) } @@ -127,8 +129,8 @@ impl<'d> Flash<'d, Blocking> { self.check_eeprom_offset(offset, data.len() as u32 * 2)?; unsafe { family::unlock(); + let _on_drop = OnDrop::new(|| family::lock()); self.eeprom_write_u16_slice_unlocked(offset, data)?; - family::lock(); } Ok(()) } @@ -143,8 +145,8 @@ impl<'d> Flash<'d, Blocking> { self.check_eeprom_offset(offset, data.len() as u32 * 4)?; unsafe { family::unlock(); + let _on_drop = OnDrop::new(|| family::lock()); self.eeprom_write_u32_slice_unlocked(offset, data)?; - family::lock(); } Ok(()) } @@ -154,7 +156,6 @@ impl<'d> Flash<'d, Blocking> { /// This method will write unaligned prefix and suffix as bytes, and aligned middle as u32. pub fn eeprom_write_slice(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> { self.check_eeprom_offset(offset, data.len() as u32)?; - let start = offset; let misalign = (start % 4) as usize; let prefix_len = if misalign == 0 { @@ -168,6 +169,8 @@ impl<'d> Flash<'d, Blocking> { unsafe { family::unlock(); + let _on_drop = OnDrop::new(|| family::lock()); + if !prefix.is_empty() { self.eeprom_write_u8_slice_unlocked(start, prefix)?; } @@ -187,7 +190,6 @@ impl<'d> Flash<'d, Blocking> { let suffix_offset = start + (prefix_len + aligned_len) as u32; self.eeprom_write_u8_slice_unlocked(suffix_offset, suffix)?; } - family::lock(); } Ok(()) } -- cgit From c88bc972316634da586589adcefa49bb02a2cf0f Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Wed, 21 May 2025 22:33:44 +0300 Subject: added eeprom to tests --- tests/stm32/Cargo.toml | 10 ++++++++-- tests/stm32/src/bin/eeprom.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 tests/stm32/src/bin/eeprom.rs diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 6036a5a97..5a483849c 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -19,8 +19,8 @@ stm32h563zi = ["embassy-stm32/stm32h563zi", "spi-v345", "chrono", "eth", "rng", stm32h753zi = ["embassy-stm32/stm32h753zi", "spi-v345", "chrono", "not-gpdma", "eth", "rng", "fdcan", "hash", "cryp"] stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "spi-v345", "chrono", "not-gpdma", "eth", "dac", "rng", "fdcan", "hash", "cryp"] stm32h7a3zi = ["embassy-stm32/stm32h7a3zi", "spi-v345", "not-gpdma", "rng", "fdcan"] -stm32l073rz = ["embassy-stm32/stm32l073rz", "cm0", "not-gpdma", "rng"] -stm32l152re = ["embassy-stm32/stm32l152re", "spi-v1", "chrono", "not-gpdma"] +stm32l073rz = ["embassy-stm32/stm32l073rz", "cm0", "not-gpdma", "rng", "eeprom"] +stm32l152re = ["embassy-stm32/stm32l152re", "spi-v1", "chrono", "not-gpdma", "eeprom"] stm32l496zg = ["embassy-stm32/stm32l496zg", "not-gpdma", "rng"] stm32l4a6zg = ["embassy-stm32/stm32l4a6zg", "chrono", "not-gpdma", "rng", "hash"] stm32l4r5zi = ["embassy-stm32/stm32l4r5zi", "chrono", "not-gpdma", "rng", "dual-bank"] @@ -55,6 +55,7 @@ ucpd = [] cordic = ["dep:num-traits"] dual-bank = ["embassy-stm32/dual-bank"] single-bank = ["embassy-stm32/single-bank"] +eeprom = [] cm0 = ["portable-atomic/unsafe-assume-single-core"] @@ -119,6 +120,11 @@ name = "dac_l1" path = "src/bin/dac_l1.rs" required-features = [ "stm32l152re",] +[[bin]] +name = "eeprom" +path = "src/bin/eeprom.rs" +required-features = [ "eeprom",] + [[bin]] name = "eth" path = "src/bin/eth.rs" diff --git a/tests/stm32/src/bin/eeprom.rs b/tests/stm32/src/bin/eeprom.rs new file mode 100644 index 000000000..61d249fd7 --- /dev/null +++ b/tests/stm32/src/bin/eeprom.rs @@ -0,0 +1,30 @@ +#![no_std] +#![no_main] + +// required-features: eeprom + +#[path = "../common.rs"] +mod common; + +use common::*; +use defmt::assert_eq; +use embassy_executor::Spawner; +use embassy_stm32::flash::Flash; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + // Initialize the board and obtain a Peripherals instance + let p: embassy_stm32::Peripherals = init(); + + let mut f = Flash::new_blocking(p.FLASH); + const ADDR: u32 = 0x0; + + unwrap!(f.eeprom_write_slice(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + let mut buf = [0u8; 8]; + unwrap!(f.eeprom_read_slice(ADDR, &mut buf)); + assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} -- cgit From 2f8a8e817c64dfa8d63b4a3ad43e650785698a5e Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Thu, 22 May 2025 11:41:25 +0800 Subject: embassy-sync: Update changelog --- embassy-sync/CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/embassy-sync/CHANGELOG.md b/embassy-sync/CHANGELOG.md index 2049e0f11..aacb0d6c4 100644 --- a/embassy-sync/CHANGELOG.md +++ b/embassy-sync/CHANGELOG.md @@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- Add `remove_if` to `priority_channel::{Receiver, PriorityChannel}`. +- impl `Stream` for `channel::{Receiver, Channel}`. +- Fix channels to wake senders on `clear()`. + For `Channel`, `PriorityChannel`, `PubSub`, `zerocopy_channel::Channel`. +- Allow `zerocopy_channel::Channel` to auto-implement `Sync`/`Send`. +- Add `must_use` to `MutexGuard`. +- Add a `RwLock`. +- Add `lock_mut` to `blocking_mutex::Mutex`. +- Don't select a critical-section implementation when `std` feature is enabled. +- Improve waker documentation. +- Improve `Signal` and `Watch` documentation. +- Update to defmt 1.0. This remains compatible with latest defmt 0.3. + ## 0.6.2 - 2025-01-15 - Add dynamic dispatch variant of `Pipe`. -- cgit From 5e49985ed678659e199c58c8100e3ed18d2f6227 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Thu, 22 May 2025 11:42:15 +0800 Subject: embassy-sync: bump to 0.7.0 --- cyw43/Cargo.toml | 2 +- embassy-boot-nrf/Cargo.toml | 2 +- embassy-boot-rp/Cargo.toml | 2 +- embassy-boot-stm32/Cargo.toml | 2 +- embassy-boot/Cargo.toml | 2 +- embassy-embedded-hal/Cargo.toml | 2 +- embassy-imxrt/Cargo.toml | 2 +- embassy-mspm0/Cargo.toml | 2 +- embassy-net-driver-channel/Cargo.toml | 2 +- embassy-net-esp-hosted/Cargo.toml | 2 +- embassy-net-nrf91/Cargo.toml | 2 +- embassy-net-ppp/Cargo.toml | 2 +- embassy-net/Cargo.toml | 2 +- embassy-nrf/Cargo.toml | 2 +- embassy-nxp/Cargo.toml | 2 +- embassy-rp/Cargo.toml | 2 +- embassy-stm32-wpan/Cargo.toml | 2 +- embassy-stm32/Cargo.toml | 2 +- embassy-sync/CHANGELOG.md | 2 ++ embassy-sync/Cargo.toml | 2 +- embassy-usb-dfu/Cargo.toml | 2 +- embassy-usb-logger/Cargo.toml | 2 +- embassy-usb-synopsys-otg/Cargo.toml | 2 +- embassy-usb/Cargo.toml | 2 +- examples/boot/application/nrf/Cargo.toml | 2 +- examples/boot/application/rp/Cargo.toml | 2 +- examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wb-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wl/Cargo.toml | 2 +- examples/boot/bootloader/nrf/Cargo.toml | 2 +- examples/boot/bootloader/rp/Cargo.toml | 2 +- examples/boot/bootloader/stm32-dual-bank/Cargo.toml | 2 +- examples/boot/bootloader/stm32/Cargo.toml | 2 +- examples/boot/bootloader/stm32wb-dfu/Cargo.toml | 2 +- examples/lpc55s69/Cargo.toml | 2 +- examples/mimxrt6/Cargo.toml | 2 +- examples/mspm0c1104/Cargo.toml | 2 +- examples/mspm0g3507/Cargo.toml | 2 +- examples/mspm0g3519/Cargo.toml | 2 +- examples/mspm0l1306/Cargo.toml | 2 +- examples/mspm0l2228/Cargo.toml | 2 +- examples/nrf-rtos-trace/Cargo.toml | 2 +- examples/nrf52810/Cargo.toml | 2 +- examples/nrf52840-rtic/Cargo.toml | 2 +- examples/nrf52840/Cargo.toml | 2 +- examples/nrf5340/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- examples/std/Cargo.toml | 2 +- examples/stm32c0/Cargo.toml | 2 +- examples/stm32f0/Cargo.toml | 2 +- examples/stm32f1/Cargo.toml | 2 +- examples/stm32f2/Cargo.toml | 2 +- examples/stm32f3/Cargo.toml | 2 +- examples/stm32f334/Cargo.toml | 2 +- examples/stm32f4/Cargo.toml | 2 +- examples/stm32f7/Cargo.toml | 2 +- examples/stm32g0/Cargo.toml | 2 +- examples/stm32g4/Cargo.toml | 2 +- examples/stm32h5/Cargo.toml | 2 +- examples/stm32h7/Cargo.toml | 2 +- examples/stm32h723/Cargo.toml | 2 +- examples/stm32h735/Cargo.toml | 2 +- examples/stm32h742/Cargo.toml | 2 +- examples/stm32h755cm4/Cargo.toml | 2 +- examples/stm32h755cm7/Cargo.toml | 2 +- examples/stm32h7b0/Cargo.toml | 2 +- examples/stm32h7rs/Cargo.toml | 2 +- examples/stm32l0/Cargo.toml | 2 +- examples/stm32l1/Cargo.toml | 2 +- examples/stm32l4/Cargo.toml | 2 +- examples/stm32l432/Cargo.toml | 2 +- examples/stm32l5/Cargo.toml | 2 +- examples/stm32u0/Cargo.toml | 2 +- examples/stm32u5/Cargo.toml | 2 +- examples/stm32wb/Cargo.toml | 2 +- examples/stm32wba/Cargo.toml | 2 +- examples/stm32wl/Cargo.toml | 2 +- examples/wasm/Cargo.toml | 2 +- tests/mspm0/Cargo.toml | 2 +- tests/nrf/Cargo.toml | 2 +- tests/riscv32/Cargo.toml | 2 +- tests/rp/Cargo.toml | 2 +- tests/stm32/Cargo.toml | 2 +- 89 files changed, 90 insertions(+), 88 deletions(-) diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index 4b58ee9c9..c52a653bd 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -19,7 +19,7 @@ firmware-logs = [] [dependencies] embassy-time = { version = "0.4.0", path = "../embassy-time"} -embassy-sync = { version = "0.6.2", path = "../embassy-sync"} +embassy-sync = { version = "0.7.0", path = "../embassy-sync"} embassy-futures = { version = "0.1.0", path = "../embassy-futures"} embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel"} diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index 7d3e04419..3cfaa5a80 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -24,7 +24,7 @@ target = "thumbv7em-none-eabi" defmt = { version = "1.0.1", optional = true } log = { version = "0.4.17", optional = true } -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-nrf = { version = "0.3.1", path = "../embassy-nrf", default-features = false } embassy-boot = { version = "0.4.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } diff --git a/embassy-boot-rp/Cargo.toml b/embassy-boot-rp/Cargo.toml index 10eec774f..afe5d6691 100644 --- a/embassy-boot-rp/Cargo.toml +++ b/embassy-boot-rp/Cargo.toml @@ -24,7 +24,7 @@ features = ["embassy-rp/rp2040"] defmt = { version = "1.0.1", optional = true } log = { version = "0.4", optional = true } -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-rp = { version = "0.4.0", path = "../embassy-rp", default-features = false } embassy-boot = { version = "0.4.0", path = "../embassy-boot" } embassy-time = { version = "0.4.0", path = "../embassy-time" } diff --git a/embassy-boot-stm32/Cargo.toml b/embassy-boot-stm32/Cargo.toml index 2b741cc95..a24921291 100644 --- a/embassy-boot-stm32/Cargo.toml +++ b/embassy-boot-stm32/Cargo.toml @@ -24,7 +24,7 @@ target = "thumbv7em-none-eabi" defmt = { version = "1.0.1", optional = true } log = { version = "0.4", optional = true } -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-stm32 = { version = "0.2.0", path = "../embassy-stm32", default-features = false } embassy-boot = { version = "0.4.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } diff --git a/embassy-boot/Cargo.toml b/embassy-boot/Cargo.toml index 8889f1a20..f12e8e304 100644 --- a/embassy-boot/Cargo.toml +++ b/embassy-boot/Cargo.toml @@ -29,7 +29,7 @@ digest = "0.10" log = { version = "0.4", optional = true } ed25519-dalek = { version = "2", default-features = false, features = ["digest"], optional = true } embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal" } -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embedded-storage = "0.3.1" embedded-storage-async = { version = "0.4.1" } salty = { version = "0.3", optional = true } diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index f7a973a8d..efc3173d4 100644 --- a/embassy-embedded-hal/Cargo.toml +++ b/embassy-embedded-hal/Cargo.toml @@ -24,7 +24,7 @@ default = ["time"] [dependencies] embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [ "unproven", diff --git a/embassy-imxrt/Cargo.toml b/embassy-imxrt/Cargo.toml index 231a80251..49dc8089c 100644 --- a/embassy-imxrt/Cargo.toml +++ b/embassy-imxrt/Cargo.toml @@ -63,7 +63,7 @@ mimxrt685s = ["mimxrt685s-pac", "_mimxrt685s"] mimxrt633s = ["mimxrt633s-pac", "_mimxrt633s"] [dependencies] -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.4", path = "../embassy-time", optional = true } diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index 6f767a3c0..456d302af 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -25,7 +25,7 @@ features = ["defmt", "unstable-pac", "time-driver-any", "time", "mspm0g3507"] rustdoc-args = ["--cfg", "docsrs"] [dependencies] -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } # TODO: Support other tick rates embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true, features = ["tick-hz-32_768"] } diff --git a/embassy-net-driver-channel/Cargo.toml b/embassy-net-driver-channel/Cargo.toml index beadbf3c9..c16c4be74 100644 --- a/embassy-net-driver-channel/Cargo.toml +++ b/embassy-net-driver-channel/Cargo.toml @@ -25,6 +25,6 @@ features = ["defmt"] defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml index 0cb99e67e..dea74ed65 100644 --- a/embassy-net-esp-hosted/Cargo.toml +++ b/embassy-net-esp-hosted/Cargo.toml @@ -18,7 +18,7 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-sync = { version = "0.6.2", path = "../embassy-sync"} +embassy-sync = { version = "0.7.0", path = "../embassy-sync"} embassy-futures = { version = "0.1.0", path = "../embassy-futures"} embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel"} diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml index de12ac36f..62813e546 100644 --- a/embassy-net-nrf91/Cargo.toml +++ b/embassy-net-nrf91/Cargo.toml @@ -21,7 +21,7 @@ nrf-pac = "0.1.0" cortex-m = "0.7.7" embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } diff --git a/embassy-net-ppp/Cargo.toml b/embassy-net-ppp/Cargo.toml index ab713fed8..0936626eb 100644 --- a/embassy-net-ppp/Cargo.toml +++ b/embassy-net-ppp/Cargo.toml @@ -21,7 +21,7 @@ embedded-io-async = { version = "0.6.1" } embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } ppproto = { version = "0.2.1"} -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-ppp-v$VERSION/embassy-net-ppp/src/" diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index d96481f98..526c8a4b3 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -78,7 +78,7 @@ smoltcp = { version = "0.12.0", default-features = false, features = [ embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embedded-io-async = { version = "0.6.1" } managed = { version = "0.8.0", default-features = false, features = [ "map" ] } diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index e4f40630e..47eb92697 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -143,7 +143,7 @@ _multi_wdt = [] embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false } embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 86a989aa7..426af06a0 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -8,7 +8,7 @@ cortex-m = "0.7.7" cortex-m-rt = "0.7.0" critical-section = "1.1.2" embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } lpc55-pac = "0.5.0" defmt = { version = "1", optional = true } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 3c18a8f77..5df9e154c 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -136,7 +136,7 @@ _test = [] binary-info = ["rt", "dep:rp-binary-info", "rp-binary-info?/binary-info"] [dependencies] -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time" } diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 81af6aedd..b749625aa 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -20,7 +20,7 @@ features = ["stm32wb55rg", "ble", "mac"] [dependencies] embassy-stm32 = { version = "0.2.0", path = "../embassy-stm32" } -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal" } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 2ab4f9960..034f51df9 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -48,7 +48,7 @@ features = ["defmt", "unstable-pac", "exti", "time-driver-any", "time", "stm32h7 rustdoc-args = ["--cfg", "docsrs"] [dependencies] -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } diff --git a/embassy-sync/CHANGELOG.md b/embassy-sync/CHANGELOG.md index aacb0d6c4..1770bef44 100644 --- a/embassy-sync/CHANGELOG.md +++ b/embassy-sync/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## 0.7.0 - 2025-05-22 + - Add `remove_if` to `priority_channel::{Receiver, PriorityChannel}`. - impl `Stream` for `channel::{Receiver, Channel}`. - Fix channels to wake senders on `clear()`. diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml index 65cade317..99962f9f6 100644 --- a/embassy-sync/Cargo.toml +++ b/embassy-sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-sync" -version = "0.6.2" +version = "0.7.0" edition = "2021" description = "no-std, no-alloc synchronization primitives with async support" repository = "https://github.com/embassy-rs/embassy" diff --git a/embassy-usb-dfu/Cargo.toml b/embassy-usb-dfu/Cargo.toml index ccf8a16eb..ca108c1a2 100644 --- a/embassy-usb-dfu/Cargo.toml +++ b/embassy-usb-dfu/Cargo.toml @@ -33,7 +33,7 @@ bitflags = "2.4.1" cortex-m = { version = "0.7.7", features = ["inline-asm"], optional = true } embassy-boot = { version = "0.4.0", path = "../embassy-boot" } embassy-futures = { version = "0.1.1", path = "../embassy-futures" } -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time" } embassy-usb = { version = "0.4.0", path = "../embassy-usb", default-features = false } embedded-storage = { version = "0.3.1" } diff --git a/embassy-usb-logger/Cargo.toml b/embassy-usb-logger/Cargo.toml index c670b41b6..6b8e9af47 100644 --- a/embassy-usb-logger/Cargo.toml +++ b/embassy-usb-logger/Cargo.toml @@ -16,6 +16,6 @@ target = "thumbv7em-none-eabi" [dependencies] embassy-usb = { version = "0.4.0", path = "../embassy-usb" } -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } log = "0.4" diff --git a/embassy-usb-synopsys-otg/Cargo.toml b/embassy-usb-synopsys-otg/Cargo.toml index 98fc044ce..6252feaef 100644 --- a/embassy-usb-synopsys-otg/Cargo.toml +++ b/embassy-usb-synopsys-otg/Cargo.toml @@ -18,7 +18,7 @@ target = "thumbv7em-none-eabi" [dependencies] critical-section = "1.1" -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } defmt = { version = "1.0.1", optional = true } diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml index e52f4602d..31fd1c1e0 100644 --- a/embassy-usb/Cargo.toml +++ b/embassy-usb/Cargo.toml @@ -48,7 +48,7 @@ max-handler-count-8 = [] [dependencies] embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } -embassy-sync = { version = "0.6.2", path = "../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } defmt = { version = "1", optional = true } diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 244ce9591..4d633e8a8 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } embassy-nrf = { version = "0.3.1", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index 24f4218f1..be283fb27 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } embassy-rp = { version = "0.4.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index 1e209eb9c..87f97071b 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index 877e239fa..d593a568e 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index f28723835..7653d82ed 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index f1cb55223..d1cace246 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 7c53e011d..034bf39af 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index 9f5060802..d32cbca97 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index d1cea8520..49b35f681 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index 54331dd69..e44d9859a 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } diff --git a/examples/boot/bootloader/nrf/Cargo.toml b/examples/boot/bootloader/nrf/Cargo.toml index 4c2712718..897890ca4 100644 --- a/examples/boot/bootloader/nrf/Cargo.toml +++ b/examples/boot/bootloader/nrf/Cargo.toml @@ -12,7 +12,7 @@ defmt-rtt = { version = "1.0.0", optional = true } embassy-nrf = { path = "../../../../embassy-nrf", features = [] } embassy-boot-nrf = { path = "../../../../embassy-boot-nrf" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } cortex-m-rt = { version = "0.7" } cfg-if = "1.0.0" diff --git a/examples/boot/bootloader/rp/Cargo.toml b/examples/boot/bootloader/rp/Cargo.toml index c57b90793..090a581d4 100644 --- a/examples/boot/bootloader/rp/Cargo.toml +++ b/examples/boot/bootloader/rp/Cargo.toml @@ -11,7 +11,7 @@ defmt-rtt = { version = "1.0.0", optional = true } embassy-rp = { path = "../../../../embassy-rp", features = ["rp2040"] } embassy-boot-rp = { path = "../../../../embassy-boot-rp" } -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-time = { path = "../../../../embassy-time", features = [] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml index a3ca96aec..67edc6a6c 100644 --- a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml +++ b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml @@ -15,7 +15,7 @@ cortex-m = { version = "0.7.6", features = [ "inline-asm", "critical-section-single-core", ] } -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" diff --git a/examples/boot/bootloader/stm32/Cargo.toml b/examples/boot/bootloader/stm32/Cargo.toml index bdefa2cb5..fe81b5151 100644 --- a/examples/boot/bootloader/stm32/Cargo.toml +++ b/examples/boot/bootloader/stm32/Cargo.toml @@ -12,7 +12,7 @@ defmt-rtt = { version = "1.0.0", optional = true } embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml index 389f43641..738afb6ec 100644 --- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml @@ -12,7 +12,7 @@ defmt-rtt = { version = "1.0.0", optional = true } embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } -embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index 30ce0b799..7f81e9c7f 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["rt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/mimxrt6/Cargo.toml b/examples/mimxrt6/Cargo.toml index 40cc0fb44..65cb9e3ca 100644 --- a/examples/mimxrt6/Cargo.toml +++ b/examples/mimxrt6/Cargo.toml @@ -14,7 +14,7 @@ embassy-executor = { version = "0.7.0", path = "../../embassy-executor", feature embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } embassy-imxrt = { version = "0.1.0", path = "../../embassy-imxrt", features = ["defmt", "mimxrt685s", "unstable-pac", "time", "time-driver-os-timer"] } embassy-time = { version = "0.4", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = "1.0.0" diff --git a/examples/mspm0c1104/Cargo.toml b/examples/mspm0c1104/Cargo.toml index 7d419af51..79f9c0959 100644 --- a/examples/mspm0c1104/Cargo.toml +++ b/examples/mspm0c1104/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0c1104dgs20", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/mspm0g3507/Cargo.toml b/examples/mspm0g3507/Cargo.toml index 5a02b7249..b6621c9c5 100644 --- a/examples/mspm0g3507/Cargo.toml +++ b/examples/mspm0g3507/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3507pm", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/mspm0g3519/Cargo.toml b/examples/mspm0g3519/Cargo.toml index fc647a4ce..fd0e97c01 100644 --- a/examples/mspm0g3519/Cargo.toml +++ b/examples/mspm0g3519/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3519pz", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/mspm0l1306/Cargo.toml b/examples/mspm0l1306/Cargo.toml index 6f2f33b1e..6b1125810 100644 --- a/examples/mspm0l1306/Cargo.toml +++ b/examples/mspm0l1306/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l1306rhb", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/mspm0l2228/Cargo.toml b/examples/mspm0l2228/Cargo.toml index a68b5bfe9..08dfd5ff6 100644 --- a/examples/mspm0l2228/Cargo.toml +++ b/examples/mspm0l2228/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l2228pn", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index dcbaf87f8..d9e8ca2f9 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -15,7 +15,7 @@ log = [ ] [dependencies] -embassy-sync = { version = "0.6.2", path = "../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } embassy-time = { version = "0.4.0", path = "../../embassy-time" } embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index 5373278c1..87da89efe 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index 2eef012b7..afd269f72 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" rtic = { version = "2", features = ["thumbv7-backend"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } embassy-time-queue-utils = { version = "0.1", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 92127a8b0..4140e49d2 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 42d7766b7..dc4fba4fd 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index d19dd9dc7..c8a132a5e 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal", features = ["defmt"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-rp = { version = "0.4.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index ae64489ae..c81b79ae1 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal", features = ["defmt"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-rp = { version = "0.4.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index ff4b2fbbd..63740963d 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["log"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["log"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["log", "std", ] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features=[ "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index 71f1cfda1..4cf07cef4 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32c031c6 to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index 534e8c33d..400e6b94c 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -12,7 +12,7 @@ cortex-m-rt = "0.7.0" defmt = "1.0.1" defmt-rtt = "1.0.0" panic-probe = { version = "1.0.0", features = ["print-defmt"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } static_cell = "2" diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index f856d2620..261733305 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f103c8 to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index f26cbfadc..905cffff0 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f207zg to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 4c1dd881f..f675b0be1 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f303ze to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-tim2", "exti"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml index c28855b3a..b47a81e1b 100644 --- a/examples/stm32f334/Cargo.toml +++ b/examples/stm32f334/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 7374f8813..edab9ea00 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f429zi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-tim4", "exti", "chrono"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt" ] } diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index bce521f30..c5801ea90 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f777zi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32f777zi", "memory-x", "unstable-pac", "time-driver-any", "exti", "single-bank"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index 5e09b237e..bf1e7250e 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32g0b1re to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g0b1re", "memory-x", "unstable-pac", "exti"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index 582553a29..3d2c2aa7d 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32g491re to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 3e022e4e5..f3fda7ff3 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h563zi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 520d0c8e6..27c59d980 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32h723/Cargo.toml b/examples/stm32h723/Cargo.toml index 1eb706b4d..fb219733f 100644 --- a/examples/stm32h723/Cargo.toml +++ b/examples/stm32h723/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h723zg to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h723zg", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml index 2ce989e6f..8d23c346a 100644 --- a/examples/stm32h735/Cargo.toml +++ b/examples/stm32h735/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml index c3bf39e13..31eff4379 100644 --- a/examples/stm32h742/Cargo.toml +++ b/examples/stm32h742/Cargo.toml @@ -14,7 +14,7 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "time-driver-any", "exti", ] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = [ +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = [ "defmt", ] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = [ diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index c97ac447e..71bd50d60 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h755zi-cm4 to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index 3843d5d43..8e960932a 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml index e4f1080ac..72f86e0cf 100644 --- a/examples/stm32h7b0/Cargo.toml +++ b/examples/stm32h7b0/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml index 58f8b1274..5f1ce8dfc 100644 --- a/examples/stm32h7rs/Cargo.toml +++ b/examples/stm32h7rs/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ethernet", "medium-ip", "proto-ipv4"] } diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index ce54ad9fb..3101cf7ce 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32l072cz to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32l073rz", "unstable-pac", "time-driver-any", "exti", "memory-x"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index a780f9290..a0a7916a7 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 5c4dce482..7da09e5b0 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32l4s5vi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4r5zi", "memory-x", "time-driver-any", "exti", "chrono", "dual-bank"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } diff --git a/examples/stm32l432/Cargo.toml b/examples/stm32l432/Cargo.toml index ac7e507de..c38462355 100644 --- a/examples/stm32l432/Cargo.toml +++ b/examples/stm32l432/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32l4s5vi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l432kc", "memory-x", "time-driver-any", "exti", "chrono"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = [ "defmt" ] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = [ "defmt" ] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "tick-hz-32_768" ] } defmt = "1.0.1" diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 138276b7f..3ea3bcd5c 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32l552ze to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x", "low-power", "dual-bank"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml index 86cff2321..3aa45dc79 100644 --- a/examples/stm32u0/Cargo.toml +++ b/examples/stm32u0/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32u083rc to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index 94f77ce2f..777d3ed4c 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32u5g9zj to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u5g9zj", "time-driver-any", "memory-x" ] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index a83871d4d..dbe9660e2 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32wb55rg to your chip name in both dependencies, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml index b87ca88bf..2c638f9f4 100644 --- a/examples/stm32wba/Cargo.toml +++ b/examples/stm32wba/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 1b6a23bed..5ecd77443 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32wl55jc-cm4 to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml index 3a27f913c..9e553f52b 100644 --- a/examples/wasm/Cargo.toml +++ b/examples/wasm/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" crate-type = ["cdylib"] [dependencies] -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["log"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["log"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["log", "wasm", ] } diff --git a/tests/mspm0/Cargo.toml b/tests/mspm0/Cargo.toml index 386536bee..298522d09 100644 --- a/tests/mspm0/Cargo.toml +++ b/tests/mspm0/Cargo.toml @@ -10,7 +10,7 @@ mspm0g3507 = [ "embassy-mspm0/mspm0g3507pm" ] [dependencies] teleprobe-meta = "1.1" -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = [ "defmt" ] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = [ "defmt" ] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt" ] } embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = [ "rt", "defmt", "unstable-pac", "time-driver-any" ] } diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index 32087940e..30c4223b7 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" teleprobe-meta = "1" embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt", ] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt", ] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } diff --git a/tests/riscv32/Cargo.toml b/tests/riscv32/Cargo.toml index 446326d8a..c5f6a1194 100644 --- a/tests/riscv32/Cargo.toml +++ b/tests/riscv32/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] critical-section = { version = "1.1.1", features = ["restore-state-bool"] } -embassy-sync = { version = "0.6.2", path = "../../embassy-sync" } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-riscv32", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../embassy-time" } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 2c2ed73cc..2be37f525 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -12,7 +12,7 @@ rp235xb = ["embassy-rp/rp235xb"] [dependencies] teleprobe-meta = "1.1" -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", ] } embassy-rp = { version = "0.4.0", path = "../../embassy-rp", features = [ "defmt", "unstable-pac", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 6036a5a97..e78520e40 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -61,7 +61,7 @@ cm0 = ["portable-atomic/unsafe-assume-single-core"] [dependencies] teleprobe-meta = "1" -embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "tick-hz-131_072", "defmt-timestamp-uptime"] } embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "memory-x", "time-driver-any"] } -- cgit From 43ff562b5a0327d575d2c02f299ad6d15680384e Mon Sep 17 00:00:00 2001 From: jubeormk1 Date: Thu, 22 May 2025 15:41:43 +1000 Subject: Adjustments for std examples I extended the README.md file to extend instructions for the rest of network examples I modified the tap.sh script to give ownership to the user running it and avoiding running the examples with sudo. This would help someone using a debuger. --- examples/std/README.md | 115 +++++++++++++++++++++++++++++++++++++++++++++++-- examples/std/tap.sh | 2 +- 2 files changed, 112 insertions(+), 5 deletions(-) diff --git a/examples/std/README.md b/examples/std/README.md index dcc152fc2..5d7c384ae 100644 --- a/examples/std/README.md +++ b/examples/std/README.md @@ -1,19 +1,126 @@ ## Running the `embassy-net` examples -First, create the tap99 interface. (The number was chosen to +To run `net`, `tcp_accept`, `net_udp` examples you will need a tap interface. Before running any example, create the tap99 interface. (The number was chosen to hopefully not collide with anything.) You only need to do -this once. +this once every time you reboot your computer. ```sh sudo sh tap.sh ``` -Second, have something listening there. For example `nc -lp 8000` +### `net` example + +For this example, you need to have something listening in the correct port. For example `nc -lp 8000`. Then run the example located in the `examples` folder: ```sh cd $EMBASSY_ROOT/examples/std/ -sudo cargo run --bin net -- --tap tap99 --static-ip +cargo run --bin net -- --tap tap99 --static-ip +``` +### `tcp_accept` example + +This example listen for a tcp connection. + +First run the example located in the `examples` folder: + +```sh +cd $EMBASSY_ROOT/examples/std/ +cargo run --bin tcp_accept -- --tap tap99 --static-ip +``` + +Then open a connection to the port. For example `nc 192.168.69.2 9999`. + +### `net_udp` example + +This example listen for a udp connection. + +First run the example located in the `examples` folder: + +```sh +cd $EMBASSY_ROOT/examples/std/ +cargo run --bin net_udp -- --tap tap99 --static-ip +``` + +Then open a connection to the port. For example `nc -u 192.168.69.2 9400`. + +### `net_dns` example + +This example queries a `DNS` for the IP address of `www.example.com`. + +In order to achieve this, the `tap99` interface requires configuring tap99 as a gateway device temporarily. + +For example, in Ubuntu you can do this by: + +1. Identifying your default route device. In the next example `eth0` + +```sh +ip r | grep "default" +default via 192.168.2.1 dev eth0 proto kernel metric 35 +``` + +2. Enabling temporarily IP Forwarding: + +```sh +sudo sysctl -w net.ipv4.ip_forward=1 +``` + +3. Configuring NAT to mascarade traffic from `tap99` to `eth0` + +```sh +sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE +sudo iptables -A FORWARD -i tap99 -j ACCEPT +sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +``` + +4. Then you can run the example located in the `examples` folder: + +```sh +cd $EMBASSY_ROOT/examples/std/ +cargo run --bin net_dns -- --tap tap99 --static-ip +``` + +### `net_ppp` example + +This example establish a Point-to-Point Protocol (PPP) connection that can be used, for example, for connecting to internet through a 4G modem via a serial channel. + +The example creates a PPP bridge over a virtual serial channel between `pty1` and `pty2` for the example code and a PPP server running on the same computer. + +To run this example you will need: +- ppp (pppd server) +- socat (socket CAT) + +To run the examples you may follow the next steps: + +1. Save the PPP server configuration: +```sh +sudo sh -c 'echo "myuser $(hostname) mypass 192.168.7.10" >> /etc/ppp/pap-secrets' +``` + +2. Create a files `pty1` and `pty2` and link them +```sh +cd $EMBASSY_ROOT/examples/std/ +socat -v -x PTY,link=pty1,rawer PTY,link=pty2,rawer +``` + +3. open a second terminal and start the PPP server: +```sh +cd $EMBASSY_ROOT/examples/std/ +sudo pppd $PWD/pty1 115200 192.168.7.1: ms-dns 8.8.4.4 ms-dns 8.8.8.8 nodetach debug local persist silent +``` + +4. Open a third terminal and run the example +```sh +cd $EMBASSY_ROOT/examples/std/ +RUST_LOG=trace cargo run --bin net_ppp -- --device pty2 +``` +5. Observe the output in the second and third terminal +6. Open one last terminal to interact with `net_ppp` example through the PPP connection +```sh +# ping the net_ppp client +ping 192.168.7.10 +# open an tcp connection +nc 192.168.7.10 1234 +# Type anything and observe the output in the different terminals ``` diff --git a/examples/std/tap.sh b/examples/std/tap.sh index 39d92a099..fb89d2381 100644 --- a/examples/std/tap.sh +++ b/examples/std/tap.sh @@ -1,4 +1,4 @@ -ip tuntap add name tap99 mode tap user $USER +ip tuntap add name tap99 mode tap user $SUDO_USER ip link set tap99 up ip addr add 192.168.69.100/24 dev tap99 ip -6 addr add fe80::100/64 dev tap99 -- cgit From bc80903d0affb0cff6f97b8da64d2ddb6549a5fb Mon Sep 17 00:00:00 2001 From: jubeormk1 Date: Thu, 22 May 2025 15:47:11 +1000 Subject: Added some notes for net_ppp example --- examples/std/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/std/README.md b/examples/std/README.md index 5d7c384ae..ac2c2a1a6 100644 --- a/examples/std/README.md +++ b/examples/std/README.md @@ -1,14 +1,16 @@ ## Running the `embassy-net` examples -To run `net`, `tcp_accept`, `net_udp` examples you will need a tap interface. Before running any example, create the tap99 interface. (The number was chosen to -hopefully not collide with anything.) You only need to do -this once every time you reboot your computer. +To run `net`, `tcp_accept`, `net_udp` and `net_dns` examples you will need a tap interface. Before running these examples, create the tap99 interface. (The number was chosen to +hopefully not collide with anything.) You only need to do this once every time you reboot your computer. ```sh +cd $EMBASSY_ROOT/examples/std/ sudo sh tap.sh ``` +The example `net_ppp` requires different steps that are detailed in its section. + ### `net` example For this example, you need to have something listening in the correct port. For example `nc -lp 8000`. -- cgit From 3c3c7877cd31b84fb5dcf976e05d4eab66ddeaee Mon Sep 17 00:00:00 2001 From: RaulIQ Date: Thu, 22 May 2025 10:44:38 +0300 Subject: format simple_pwm.rs with rustfmt --- embassy-stm32/src/timer/simple_pwm.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 972a3852c..d356bb4b4 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -383,11 +383,11 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { } /// Generate a multichannel sequence of PWM waveforms using DMA triggered by timer update events. - /// + /// /// This method utilizes the timer's DMA burst transfer capability to update multiple CCRx registers /// in sequence on each update event (UEV). The data is written via the DMAR register using the /// DMA base address (DBA) and burst length (DBL) configured in the DCR register. - /// + /// /// The `duty` buffer must be structured as a flattened 2D array in row-major order, where each row /// represents a single update event and each column corresponds to a specific timer channel (starting /// from `starting_channel` up to and including `ending_channel`). @@ -405,7 +405,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// Each group of N values (where N = number of channels) is transferred on one update event, /// updating the duty cycles of all selected channels simultaneously. - /// + /// /// Note: /// you will need to provide corresponding TIMx_UP DMA channel to use this method. pub async fn waveform_up_multi_channel( @@ -466,7 +466,6 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { self.inner.enable_update_dma(false); } } - } macro_rules! impl_waveform_chx { -- cgit From 967ae161a0dfe996635866b7c7139d02bc5882b9 Mon Sep 17 00:00:00 2001 From: RaulIQ Date: Thu, 22 May 2025 10:56:48 +0300 Subject: doc: update documentation to pass test --- embassy-stm32/src/timer/simple_pwm.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index d356bb4b4..f7f433154 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -394,14 +394,12 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// For example, if using channels 1 through 4, a buffer of 4 update steps might look like: /// - /// ```rust /// let dma_buf: [u16; 16] = [ /// ch1_duty_1, ch2_duty_1, ch3_duty_1, ch4_duty_1, // update 1 /// ch1_duty_2, ch2_duty_2, ch3_duty_2, ch4_duty_2, // update 2 /// ch1_duty_3, ch2_duty_3, ch3_duty_3, ch4_duty_3, // update 3 /// ch1_duty_4, ch2_duty_4, ch3_duty_4, ch4_duty_4, // update 4 /// ]; - /// ``` /// /// Each group of N values (where N = number of channels) is transferred on one update event, /// updating the duty cycles of all selected channels simultaneously. -- cgit From 9baf5fc5eb8b317c7ac86ddd7bdc7434fbe7c26c Mon Sep 17 00:00:00 2001 From: MatrixSenpai Date: Thu, 22 May 2025 10:54:24 -0500 Subject: adding compatibility with ws2812 leds that have 4 addressable lights --- embassy-rp/src/pio_programs/ws2812.rs | 71 +++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/embassy-rp/src/pio_programs/ws2812.rs b/embassy-rp/src/pio_programs/ws2812.rs index 578937e11..f257bfcdc 100644 --- a/embassy-rp/src/pio_programs/ws2812.rs +++ b/embassy-rp/src/pio_programs/ws2812.rs @@ -2,7 +2,7 @@ use embassy_time::Timer; use fixed::types::U24F8; -use smart_leds::RGB8; +use smart_leds::{RGB8, RGBW}; use crate::clocks::clk_sys_freq; use crate::dma::{AnyChannel, Channel}; @@ -50,14 +50,14 @@ impl<'a, PIO: Instance> PioWs2812Program<'a, PIO> { } } -/// Pio backed ws2812 driver +/// Pio backed RGB ws2812 driver /// Const N is the number of ws2812 leds attached to this pin -pub struct PioWs2812<'d, P: Instance, const S: usize, const N: usize> { +pub struct RgbPioWs2812<'d, P: Instance, const S: usize, const N: usize> { dma: Peri<'d, AnyChannel>, sm: StateMachine<'d, P, S>, } -impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> { +impl<'d, P: Instance, const S: usize, const N: usize> RgbPioWs2812<'d, P, S, N> { /// Configure a pio state machine to use the loaded ws2812 program. pub fn new( pio: &mut Common<'d, P>, @@ -111,3 +111,66 @@ impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> { Timer::after_micros(55).await; } } + +/// Pio backed RGBW ws2812 driver +/// This version is intended for ws2812 leds with 4 addressable lights +/// Const N is the number of ws2812 leds attached to this pin +pub struct RgbwPioWs2812<'d, P: Instance, const S: usize, const N: usize> { + dma: Peri<'d, AnyChannel>, + sm: StateMachine<'d, P, S>, +} + +impl<'d, P: Instance, const S: usize, const N: usize> RgbwPioWs2812<'d, P, S, N> { + /// Configure a pio state machine to use the loaded ws2812 program. + pub fn new( + pio: &mut Common<'d, P>, + mut sm: StateMachine<'d, P, S>, + dma: Peri<'d, impl Channel>, + pin: Peri<'d, impl PioPin>, + program: &PioWs2812Program<'d, P>, + ) -> Self { + // Setup sm0 + let mut cfg = Config::default(); + + // Pin config + let out_pin = pio.make_pio_pin(pin); + cfg.set_out_pins(&[&out_pin]); + cfg.set_set_pins(&[&out_pin]); + + cfg.use_program(&program.prg, &[&out_pin]); + + // Clock config, measured in kHz to avoid overflows + let clock_freq = U24F8::from_num(clk_sys_freq() / 1000); + let ws2812_freq = U24F8::from_num(800); + let bit_freq = ws2812_freq * CYCLES_PER_BIT; + cfg.clock_divider = clock_freq / bit_freq; + + // FIFO config + cfg.fifo_join = FifoJoin::TxOnly; + cfg.shift_out = ShiftConfig { + auto_fill: true, + threshold: 32, + direction: ShiftDirection::Left, + }; + + sm.set_config(&cfg); + sm.set_enable(true); + + Self { dma: dma.into(), sm } + } + + /// Write a buffer of [smart_leds::RGBW] to the ws2812 string + pub async fn write(&mut self, colors: &[RGBW; N]) { + // Precompute the word bytes from the colors + let mut words = [0u32; N]; + for i in 0..N { + let word = (u32::from(colors[i].g) << 24) | (u32::from(colors[i].r) << 16) | (u32::from(colors[i].b) << 8) | u32::from(colors[i].a.0); + words[i] = word; + } + + // DMA transfer + self.sm.tx().dma_push(self.dma.reborrow(), &words, false).await; + + Timer::after_micros(55).await; + } +} -- cgit From 7eaea84fb769f739f884bc0a474b518b65c126e4 Mon Sep 17 00:00:00 2001 From: MatrixSenpai Date: Thu, 22 May 2025 11:04:30 -0500 Subject: rustfmt --- embassy-rp/src/pio_programs/ws2812.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/embassy-rp/src/pio_programs/ws2812.rs b/embassy-rp/src/pio_programs/ws2812.rs index f257bfcdc..37dd1c4e0 100644 --- a/embassy-rp/src/pio_programs/ws2812.rs +++ b/embassy-rp/src/pio_programs/ws2812.rs @@ -52,12 +52,12 @@ impl<'a, PIO: Instance> PioWs2812Program<'a, PIO> { /// Pio backed RGB ws2812 driver /// Const N is the number of ws2812 leds attached to this pin -pub struct RgbPioWs2812<'d, P: Instance, const S: usize, const N: usize> { +pub struct PioWs2812<'d, P: Instance, const S: usize, const N: usize> { dma: Peri<'d, AnyChannel>, sm: StateMachine<'d, P, S>, } -impl<'d, P: Instance, const S: usize, const N: usize> RgbPioWs2812<'d, P, S, N> { +impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> { /// Configure a pio state machine to use the loaded ws2812 program. pub fn new( pio: &mut Common<'d, P>, @@ -164,7 +164,10 @@ impl<'d, P: Instance, const S: usize, const N: usize> RgbwPioWs2812<'d, P, S, N> // Precompute the word bytes from the colors let mut words = [0u32; N]; for i in 0..N { - let word = (u32::from(colors[i].g) << 24) | (u32::from(colors[i].r) << 16) | (u32::from(colors[i].b) << 8) | u32::from(colors[i].a.0); + let word = (u32::from(colors[i].g) << 24) + | (u32::from(colors[i].r) << 16) + | (u32::from(colors[i].b) << 8) + | u32::from(colors[i].a.0); words[i] = word; } -- cgit From ea36d121db8dc71ebd205040cdd4b99fe5c2086c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 22 May 2025 14:01:40 -0700 Subject: embassy-rp: implement input/output inversion RP2040/RP23xx support inversion in HW of the inputs and outputs. Implement minimal support for that. --- embassy-rp/src/gpio.rs | 38 ++++++++++++++++++++++++++++++++++++++ tests/rp/src/bin/gpio.rs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index 2fb2d65c2..9b5faac15 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs @@ -146,6 +146,12 @@ impl<'d> Input<'d> { self.pin.get_level() } + /// Configure the input logic inversion of this pin. + #[inline] + pub fn set_inversion(&mut self, invert: bool) { + self.pin.set_input_inversion(invert) + } + /// Wait until the pin is high. If it is already high, return immediately. #[inline] pub async fn wait_for_high(&mut self) { @@ -382,6 +388,12 @@ impl<'d> Output<'d> { self.pin.set_slew_rate(slew_rate) } + /// Configure the output logic inversion of this pin. + #[inline] + pub fn set_inversion(&mut self, invert: bool) { + self.pin.set_output_inversion(invert) + } + /// Set the output as high. #[inline] pub fn set_high(&mut self) { @@ -685,6 +697,30 @@ impl<'d> Flex<'d> { self.pin.sio_oe().value_xor().write_value(self.bit()) } + /// Configure the input logic inversion of this pin. + #[inline] + pub fn set_input_inversion(&mut self, invert: bool) { + self.pin.gpio().ctrl().modify(|w| { + w.set_inover(if invert { + pac::io::vals::Inover::INVERT + } else { + pac::io::vals::Inover::NORMAL + }) + }); + } + + /// Configure the output logic inversion of this pin. + #[inline] + pub fn set_output_inversion(&mut self, invert: bool) { + self.pin.gpio().ctrl().modify(|w| { + w.set_outover(if invert { + pac::io::vals::Outover::INVERT + } else { + pac::io::vals::Outover::NORMAL + }) + }); + } + /// Get whether the pin input level is high. #[inline] pub fn is_high(&self) -> bool { @@ -815,6 +851,8 @@ impl<'d> Drop for Flex<'d> { self.pin.pad_ctrl().write(|_| {}); self.pin.gpio().ctrl().write(|w| { w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL as _); + w.set_inover(pac::io::vals::Inover::NORMAL); + w.set_outover(pac::io::vals::Outover::NORMAL); }); self.pin.io().int_dormant_wake().inte(idx / 8).write_clear(|w| { w.set_edge_high(idx % 8, true); diff --git a/tests/rp/src/bin/gpio.rs b/tests/rp/src/bin/gpio.rs index 614b6317a..8bd0df8d8 100644 --- a/tests/rp/src/bin/gpio.rs +++ b/tests/rp/src/bin/gpio.rs @@ -67,6 +67,40 @@ async fn main(_spawner: Spawner) { } } + // Test input inversion + { + let mut b = Input::new(b.reborrow(), Pull::None); + b.set_inversion(true); + // no pull, the status is undefined + + let mut a = Output::new(a.reborrow(), Level::Low); + delay(); + assert!(b.is_high()); + a.set_high(); + delay(); + assert!(b.is_low()); + + b.set_inversion(false); + a.set_inversion(true); + + a.set_low(); + delay(); + assert!(b.is_high()); + + a.set_high(); + delay(); + assert!(b.is_low()); + + b.set_inversion(true); + a.set_high(); + delay(); + assert!(b.is_high()); + + a.set_high(); + delay(); + assert!(b.is_high()); + } + // Test input no pull { let b = Input::new(b.reborrow(), Pull::None); -- cgit From 2d1652c53268ef1ac36b8d7ea6be9bf31dd79586 Mon Sep 17 00:00:00 2001 From: Matthew Tran <0e4ef622@gmail.com> Date: Thu, 22 May 2025 23:53:18 -0500 Subject: nrf: Enable TEMP driver for nrf5340-net --- embassy-nrf/src/chips/nrf5340_net.rs | 3 +++ embassy-nrf/src/lib.rs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/embassy-nrf/src/chips/nrf5340_net.rs b/embassy-nrf/src/chips/nrf5340_net.rs index c2932be31..d4c3e5353 100644 --- a/embassy-nrf/src/chips/nrf5340_net.rs +++ b/embassy-nrf/src/chips/nrf5340_net.rs @@ -201,6 +201,9 @@ embassy_hal_internal::peripherals! { // EGU EGU0, + + // TEMP + TEMP, } impl_ipc!(IPC, IPC, IPC); diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 398bfed48..9d44ae7e6 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -149,7 +149,7 @@ pub mod spim; #[cfg(not(feature = "_nrf51"))] pub mod spis; #[cfg(not(feature = "_nrf54l"))] // TODO -#[cfg(not(any(feature = "_nrf5340", feature = "_nrf91")))] +#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))] pub mod temp; #[cfg(not(feature = "_nrf54l"))] // TODO pub mod timer; -- cgit From 68a45490fc1675f2171131ccbf01f690c4123f01 Mon Sep 17 00:00:00 2001 From: Gerhard de Clercq <11624490+Gerharddc@users.noreply.github.com> Date: Tue, 15 Apr 2025 20:16:09 +0200 Subject: [embassy-usb-dfu] support ed25519 verification This commit adds the ability to verify that USB DFU updates are correctly signed using ed25519. This required adding support to embassy-boot for reading from the DFU partition. --- ci.sh | 1 + embassy-boot/src/firmware_updater/asynch.rs | 11 ++++++++ embassy-boot/src/firmware_updater/blocking.rs | 11 ++++++++ embassy-usb-dfu/Cargo.toml | 5 ++++ embassy-usb-dfu/README.md | 6 ++++ embassy-usb-dfu/src/dfu.rs | 33 ++++++++++++++++++++-- examples/boot/application/stm32wb-dfu/memory.x | 8 +++--- .../boot/application/stm32wb-dfu/secrets/key.sec | 2 ++ examples/boot/bootloader/stm32wb-dfu/Cargo.toml | 1 + examples/boot/bootloader/stm32wb-dfu/README.md | 26 +++++++++++++++++ examples/boot/bootloader/stm32wb-dfu/memory.x | 8 +++--- .../bootloader/stm32wb-dfu/secrets/key.pub.short | 1 + examples/boot/bootloader/stm32wb-dfu/src/main.rs | 12 ++++++++ 13 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 examples/boot/application/stm32wb-dfu/secrets/key.sec create mode 100644 examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short diff --git a/ci.sh b/ci.sh index 2be84ef6b..dce0d7b13 100755 --- a/ci.sh +++ b/ci.sh @@ -282,6 +282,7 @@ cargo batch \ --- build --release --manifest-path examples/boot/bootloader/rp/Cargo.toml --target thumbv6m-none-eabi \ --- build --release --manifest-path examples/boot/bootloader/stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32l496zg \ --- build --release --manifest-path examples/boot/bootloader/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wb55rg \ + --- build --release --manifest-path examples/boot/bootloader/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wb55rg,verify \ --- build --release --manifest-path examples/boot/bootloader/stm32-dual-bank/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32h743zi \ --- build --release --manifest-path examples/wasm/Cargo.toml --target wasm32-unknown-unknown --artifact-dir out/examples/wasm \ --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f103c8 --artifact-dir out/tests/stm32f103c8 \ diff --git a/embassy-boot/src/firmware_updater/asynch.rs b/embassy-boot/src/firmware_updater/asynch.rs index 0dc09e18d..66e311e38 100644 --- a/embassy-boot/src/firmware_updater/asynch.rs +++ b/embassy-boot/src/firmware_updater/asynch.rs @@ -161,6 +161,17 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> { Ok(()) } + /// Read a slice of data from the DFU storage peripheral, starting the read + /// operation at the given address offset, and reading `buf.len()` bytes. + /// + /// # Errors + /// + /// Returns an error if the arguments are not aligned or out of bounds. + pub async fn read_dfu(&mut self, offset: u32, buf: &mut [u8]) -> Result<(), FirmwareUpdaterError> { + self.dfu.read(offset, buf).await?; + Ok(()) + } + /// Mark to trigger firmware swap on next boot. #[cfg(not(feature = "_verify"))] pub async fn mark_updated(&mut self) -> Result<(), FirmwareUpdaterError> { diff --git a/embassy-boot/src/firmware_updater/blocking.rs b/embassy-boot/src/firmware_updater/blocking.rs index 08062b0d0..0fedac1ea 100644 --- a/embassy-boot/src/firmware_updater/blocking.rs +++ b/embassy-boot/src/firmware_updater/blocking.rs @@ -196,6 +196,17 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE> Ok(()) } + /// Read a slice of data from the DFU storage peripheral, starting the read + /// operation at the given address offset, and reading `buf.len()` bytes. + /// + /// # Errors + /// + /// Returns an error if the arguments are not aligned or out of bounds. + pub fn read_dfu(&mut self, offset: u32, buf: &mut [u8]) -> Result<(), FirmwareUpdaterError> { + self.dfu.read(offset, buf)?; + Ok(()) + } + /// Mark to trigger firmware swap on next boot. #[cfg(not(feature = "_verify"))] pub fn mark_updated(&mut self) -> Result<(), FirmwareUpdaterError> { diff --git a/embassy-usb-dfu/Cargo.toml b/embassy-usb-dfu/Cargo.toml index ca108c1a2..8b2467bca 100644 --- a/embassy-usb-dfu/Cargo.toml +++ b/embassy-usb-dfu/Cargo.toml @@ -43,3 +43,8 @@ esp32c3-hal = { version = "0.13.0", optional = true, default-features = false } dfu = [] application = [] defmt = ["dep:defmt", "embassy-boot/defmt", "embassy-usb/defmt"] +ed25519-dalek = ["embassy-boot/ed25519-dalek", "_verify"] +ed25519-salty = ["embassy-boot/ed25519-salty", "_verify"] + +# Internal features +_verify = [] diff --git a/embassy-usb-dfu/README.md b/embassy-usb-dfu/README.md index bdd5b033a..a81b98279 100644 --- a/embassy-usb-dfu/README.md +++ b/embassy-usb-dfu/README.md @@ -4,3 +4,9 @@ An implementation of the USB DFU 1.1 protocol using embassy-boot. It has 2 compo * DFU protocol mode, enabled by the `dfu` feature. This mode corresponds to the transfer phase DFU protocol described by the USB IF. It supports DFU_DNLOAD requests if marked by the user, and will automatically reset the chip once a DFU transaction has been completed. It also responds to DFU_GETSTATUS, DFU_GETSTATE, DFU_ABORT, and DFU_CLRSTATUS with no user intervention. * DFU runtime mode, enabled by the `application feature`. This mode allows users to expose a DFU interface on their USB device, informing the host of the capability to DFU over USB, and allowing the host to reset the device into its bootloader to complete a DFU operation. Supports DFU_GETSTATUS and DFU_DETACH. When detach/reset is seen by the device as described by the standard, will write a new DFU magic number into the bootloader state in flash, and reset the system. + +## Verification + +Embassy-boot provides functionality to verify that an update binary has been correctly signed using ed25519 as described in https://embassy.dev/book/#_verification. Even though the linked procedure describes the signature being concatenated to the end of the update binary, embassy-boot does not force this and is flexible in terms of how the signature for a binary is distributed. The current implementation in embassy-usb-dfu does however assume that the signature is 64 bytes long and concatenated to the end of the update binary since this is the simplest way to make it work with the usb-dfu mechanism. I.e. embassy-usb-dfu does not currently offer the same flexibility as embassy-boot. + +To enable verification, you need to enable either the `ed25519-dalek` or the `ed25519-salty` feature with `ed25519-salty` being recommended. diff --git a/embassy-usb-dfu/src/dfu.rs b/embassy-usb-dfu/src/dfu.rs index 0f39d906b..9a2f125fb 100644 --- a/embassy-usb-dfu/src/dfu.rs +++ b/embassy-usb-dfu/src/dfu.rs @@ -19,11 +19,19 @@ pub struct Control<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_S offset: usize, buf: AlignedBuffer, reset: RST, + + #[cfg(feature = "_verify")] + public_key: &'static [u8; 32], } impl<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize> Control<'d, DFU, STATE, RST, BLOCK_SIZE> { /// Create a new DFU instance to handle DFU transfers. - pub fn new(updater: BlockingFirmwareUpdater<'d, DFU, STATE>, attrs: DfuAttributes, reset: RST) -> Self { + pub fn new( + updater: BlockingFirmwareUpdater<'d, DFU, STATE>, + attrs: DfuAttributes, + reset: RST, + #[cfg(feature = "_verify")] public_key: &'static [u8; 32], + ) -> Self { Self { updater, attrs, @@ -32,6 +40,9 @@ impl<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize> Co offset: 0, buf: AlignedBuffer([0; BLOCK_SIZE]), reset, + + #[cfg(feature = "_verify")] + public_key, } } @@ -102,7 +113,23 @@ impl<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize> Ha if final_transfer { debug!("Receiving final transfer"); - match self.updater.mark_updated() { + #[cfg(feature = "_verify")] + let update_res: Result<(), FirmwareUpdaterError> = { + const SIGNATURE_LEN: usize = 64; + + let mut signature = [0; SIGNATURE_LEN]; + let update_len = (self.offset - SIGNATURE_LEN) as u32; + + self.updater.read_dfu(update_len, &mut signature).and_then(|_| { + self.updater + .verify_and_mark_updated(self.public_key, &signature, update_len) + }) + }; + + #[cfg(not(feature = "_verify"))] + let update_res = self.updater.mark_updated(); + + match update_res { Ok(_) => { self.status = Status::Ok; self.state = State::ManifestSync; @@ -168,7 +195,7 @@ impl<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize> Ha Some(InResponse::Accepted(&buf[0..1])) } Ok(Request::Upload) if self.attrs.contains(DfuAttributes::CAN_UPLOAD) => { - //TODO: FirmwareUpdater does not provide a way of reading the active partition, can't upload. + //TODO: FirmwareUpdater provides a way of reading the active partition so we could in theory add functionality to upload firmware. Some(InResponse::Rejected) } _ => None, diff --git a/examples/boot/application/stm32wb-dfu/memory.x b/examples/boot/application/stm32wb-dfu/memory.x index ff1b800d2..f1e6b053c 100644 --- a/examples/boot/application/stm32wb-dfu/memory.x +++ b/examples/boot/application/stm32wb-dfu/memory.x @@ -1,10 +1,10 @@ MEMORY { /* NOTE 1 K = 1 KiBi = 1024 bytes */ - BOOTLOADER : ORIGIN = 0x08000000, LENGTH = 24K - BOOTLOADER_STATE : ORIGIN = 0x08006000, LENGTH = 4K - FLASH : ORIGIN = 0x08008000, LENGTH = 128K - DFU : ORIGIN = 0x08028000, LENGTH = 132K + BOOTLOADER : ORIGIN = 0x08000000, LENGTH = 48K + BOOTLOADER_STATE : ORIGIN = 0x0800C000, LENGTH = 4K + FLASH : ORIGIN = 0x0800D000, LENGTH = 120K + DFU : ORIGIN = 0x0802B000, LENGTH = 120K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 32K } diff --git a/examples/boot/application/stm32wb-dfu/secrets/key.sec b/examples/boot/application/stm32wb-dfu/secrets/key.sec new file mode 100644 index 000000000..52e7f125b --- /dev/null +++ b/examples/boot/application/stm32wb-dfu/secrets/key.sec @@ -0,0 +1,2 @@ +untrusted comment: signify secret key +RWRCSwAAAAATdHQF3B4jEIoNZrjADRp2LbjJjNdNNzKwTCe4IB6mDNq96pe53nbNxwbdCc/T4hrz7W+Kx1MwrZ0Yz5xebSK5Z0Kh/3Cdf039U5f+eoTDS2fIGbohyUbrtwKzjyE0qXI= diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml index 738afb6ec..0bb93b12e 100644 --- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml @@ -30,6 +30,7 @@ defmt = [ "embassy-usb/defmt", "embassy-usb-dfu/defmt" ] +verify = ["embassy-usb-dfu/ed25519-salty"] [profile.dev] debug = 2 diff --git a/examples/boot/bootloader/stm32wb-dfu/README.md b/examples/boot/bootloader/stm32wb-dfu/README.md index 3c5f268a0..99a7002c4 100644 --- a/examples/boot/bootloader/stm32wb-dfu/README.md +++ b/examples/boot/bootloader/stm32wb-dfu/README.md @@ -28,6 +28,32 @@ cargo objcopy --release -- -O binary fw.bin dfu-util -d c0de:cafe -w -D fw.bin ``` +### 3. Sign Updates Before Flashing (Optional) + +Currently, embassy-usb-dfu only supports a limited implementation of the generic support for ed25519-based update verfication in embassy-boot. This implementation assumes that a signature is simply concatenated to the end of an update binary. For more details, please see https://embassy.dev/book/#_verification and/or refer to the documentation for embassy-boot-dfu. + +To sign (and then verify) application updates, you will first need to generate a key pair: + +``` +signify-openbsd -G -n -p secrets/key.pub -s secrets/key.sec +tail -n1 secrets/key.pub | base64 -d -i - | dd ibs=10 skip=1 > secrets/key.pub.short +``` + +Then you will need to sign all you binaries with the private key: + +``` +cargo objcopy --release -- -O binary fw.bin +shasum -a 512 -b fw.bin | head -c128 | xxd -p -r > target/fw-hash.txt +signify-openbsd -S -s secrets/key.sec -m target/fw-hash.txt -x target/fw-hash.sig +cp fw.bin fw-signed.bin +tail -n1 target/fw-hash.sig | base64 -d -i - | dd ibs=10 skip=1 >> fw-signed.bin +dfu-util -d c0de:cafe -w -D fw-signed.bin +``` + +Finally, as shown in this example with the `verify` feature flag enabled, you then need to embed the public key into your bootloader so that it can verify update signatures. + +N.B. Please note that the exact steps above are NOT a good example of how to manage your keys securely. In a production environment, you should take great care to ensure that (at least the private key) is protected and not leaked into your version control system. + ## Troubleshooting - Make sure your device is in DFU mode before flashing diff --git a/examples/boot/bootloader/stm32wb-dfu/memory.x b/examples/boot/bootloader/stm32wb-dfu/memory.x index 858062631..77c4d2ee2 100644 --- a/examples/boot/bootloader/stm32wb-dfu/memory.x +++ b/examples/boot/bootloader/stm32wb-dfu/memory.x @@ -1,10 +1,10 @@ MEMORY { /* NOTE 1 K = 1 KiBi = 1024 bytes */ - FLASH : ORIGIN = 0x08000000, LENGTH = 24K - BOOTLOADER_STATE : ORIGIN = 0x08006000, LENGTH = 4K - ACTIVE : ORIGIN = 0x08008000, LENGTH = 128K - DFU : ORIGIN = 0x08028000, LENGTH = 132K + FLASH : ORIGIN = 0x08000000, LENGTH = 48K + BOOTLOADER_STATE : ORIGIN = 0x0800C000, LENGTH = 4K + ACTIVE : ORIGIN = 0x0800D000, LENGTH = 120K + DFU : ORIGIN = 0x0802B000, LENGTH = 120K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K } diff --git a/examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short b/examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short new file mode 100644 index 000000000..7a4de8585 --- /dev/null +++ b/examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short @@ -0,0 +1 @@ +gBpMSzKg!F!4r \ No newline at end of file diff --git a/examples/boot/bootloader/stm32wb-dfu/src/main.rs b/examples/boot/bootloader/stm32wb-dfu/src/main.rs index 0b643079f..107f243fd 100644 --- a/examples/boot/bootloader/stm32wb-dfu/src/main.rs +++ b/examples/boot/bootloader/stm32wb-dfu/src/main.rs @@ -25,6 +25,12 @@ bind_interrupts!(struct Irqs { // N.B. update to a custom GUID for your own device! const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; +// This is a randomly generated example key. +// +// N.B. Please replace with your own! +#[cfg(feature = "verify")] +static PUBLIC_SIGNING_KEY: &[u8; 32] = include_bytes!("../secrets/key.pub.short"); + #[entry] fn main() -> ! { let mut config = embassy_stm32::Config::default(); @@ -57,7 +63,13 @@ fn main() -> ! { let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 4096]; + + #[cfg(not(feature = "verify"))] let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate); + + #[cfg(feature = "verify")] + let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate, PUBLIC_SIGNING_KEY); + let mut builder = Builder::new( driver, config, -- cgit From 489c9df453b86f80f040fe1e48d89ab342e24b3a Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 23 May 2025 14:32:36 +0200 Subject: chore: temporarily disable pico tests --- ci.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci.sh b/ci.sh index 2be84ef6b..b2112328f 100755 --- a/ci.sh +++ b/ci.sh @@ -362,6 +362,8 @@ rm out/tests/pimoroni-pico-plus-2/flash rm out/tests/pimoroni-pico-plus-2/i2c # The pico2 plus doesn't have the adcs hooked up like the picoW does. rm out/tests/pimoroni-pico-plus-2/adc +# temporarily disabled, bad hardware connection. +rm -f out/tests/rpi-pico/* if [[ -z "${TELEPROBE_TOKEN-}" ]]; then echo No teleprobe token found, skipping running HIL tests -- cgit From 134d162a337d17d0ef881135812c270cef162e61 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 23 May 2025 14:53:17 +0200 Subject: chore: disable another test --- ci.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci.sh b/ci.sh index b2112328f..94bcc75ed 100755 --- a/ci.sh +++ b/ci.sh @@ -362,6 +362,9 @@ rm out/tests/pimoroni-pico-plus-2/flash rm out/tests/pimoroni-pico-plus-2/i2c # The pico2 plus doesn't have the adcs hooked up like the picoW does. rm out/tests/pimoroni-pico-plus-2/adc +# temporarily disabled +rm out/tests/pimoroni-pico-plus-2/pwm + # temporarily disabled, bad hardware connection. rm -f out/tests/rpi-pico/* -- cgit From 0f9a7a057fb7dfb2358acec9068fece82c7c7a89 Mon Sep 17 00:00:00 2001 From: Johan Anderholm Date: Sat, 30 Dec 2023 11:54:16 +0100 Subject: executor: Make state implementations and their conditions match Use u8 for state_atomics and state_critical_section since that is all that is needed. Change arm condition to "32" since that is what is used and required. --- embassy-executor/src/raw/mod.rs | 2 +- embassy-executor/src/raw/state_atomics.rs | 10 +++++----- embassy-executor/src/raw/state_critical_section.rs | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index e7a27035a..913da2e25 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -11,7 +11,7 @@ #[cfg_attr(not(target_has_atomic = "ptr"), path = "run_queue_critical_section.rs")] mod run_queue; -#[cfg_attr(all(cortex_m, target_has_atomic = "8"), path = "state_atomics_arm.rs")] +#[cfg_attr(all(cortex_m, target_has_atomic = "32"), path = "state_atomics_arm.rs")] #[cfg_attr(all(not(cortex_m), target_has_atomic = "8"), path = "state_atomics.rs")] #[cfg_attr(not(target_has_atomic = "8"), path = "state_critical_section.rs")] mod state; diff --git a/embassy-executor/src/raw/state_atomics.rs b/embassy-executor/src/raw/state_atomics.rs index b6576bfc2..e813548ae 100644 --- a/embassy-executor/src/raw/state_atomics.rs +++ b/embassy-executor/src/raw/state_atomics.rs @@ -1,4 +1,4 @@ -use core::sync::atomic::{AtomicU32, Ordering}; +use core::sync::atomic::{AtomicU8, Ordering}; #[derive(Clone, Copy)] pub(crate) struct Token(()); @@ -11,18 +11,18 @@ pub(crate) fn locked(f: impl FnOnce(Token) -> R) -> R { } /// Task is spawned (has a future) -pub(crate) const STATE_SPAWNED: u32 = 1 << 0; +pub(crate) const STATE_SPAWNED: u8 = 1 << 0; /// Task is in the executor run queue -pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 1; +pub(crate) const STATE_RUN_QUEUED: u8 = 1 << 1; pub(crate) struct State { - state: AtomicU32, + state: AtomicU8, } impl State { pub const fn new() -> State { Self { - state: AtomicU32::new(0), + state: AtomicU8::new(0), } } diff --git a/embassy-executor/src/raw/state_critical_section.rs b/embassy-executor/src/raw/state_critical_section.rs index 6b627ff79..ec08f2f58 100644 --- a/embassy-executor/src/raw/state_critical_section.rs +++ b/embassy-executor/src/raw/state_critical_section.rs @@ -4,12 +4,12 @@ pub(crate) use critical_section::{with as locked, CriticalSection as Token}; use critical_section::{CriticalSection, Mutex}; /// Task is spawned (has a future) -pub(crate) const STATE_SPAWNED: u32 = 1 << 0; +pub(crate) const STATE_SPAWNED: u8 = 1 << 0; /// Task is in the executor run queue -pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 1; +pub(crate) const STATE_RUN_QUEUED: u8 = 1 << 1; pub(crate) struct State { - state: Mutex>, + state: Mutex>, } impl State { @@ -19,11 +19,11 @@ impl State { } } - fn update(&self, f: impl FnOnce(&mut u32) -> R) -> R { + fn update(&self, f: impl FnOnce(&mut u8) -> R) -> R { critical_section::with(|cs| self.update_with_cs(cs, f)) } - fn update_with_cs(&self, cs: CriticalSection<'_>, f: impl FnOnce(&mut u32) -> R) -> R { + fn update_with_cs(&self, cs: CriticalSection<'_>, f: impl FnOnce(&mut u8) -> R) -> R { let s = self.state.borrow(cs); let mut val = s.get(); let r = f(&mut val); -- cgit From 2ed5e04fd0fa216502c20ec4571a4b553bb86f1f Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Sat, 24 May 2025 16:39:25 -0400 Subject: stm32: Expand documentation of RingBufferedUartRx. Explain to users of this driver how 'waiting for bytes' actually works, and what that may mean for latency introduced in their application. Also correct references to 'start' to be 'start_uart'. --- embassy-stm32/src/usart/ringbuffered.rs | 73 +++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index eaa9424c5..9280dbd18 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs @@ -79,7 +79,7 @@ impl<'d> RingBufferedUartRx<'d> { /// Configure and start the DMA backed UART receiver /// - /// Note: This is also done automatically by [`read()`] if required. + /// Note: This is also done automatically by `read()` if required. pub fn start_uart(&mut self) { // Clear the buffer so that it is ready to receive data compiler_fence(Ordering::SeqCst); @@ -139,14 +139,70 @@ impl<'d> RingBufferedUartRx<'d> { Ok(()) } - /// Read bytes that are readily available in the ring buffer. - /// If no bytes are currently available in the buffer the call waits until the some - /// bytes are available (at least one byte and at most half the buffer size) + /// Read bytes that are available in the ring buffer, or wait for + /// bytes to become available and return them. /// - /// Background receive is started if `start()` has not been previously called. + /// Background reception is started if necessary (if `start_uart()` had + /// not previously been called, or if an error was detected which + /// caused background reception to be stopped). /// - /// Receive in the background is terminated if an error is returned. - /// It must then manually be started again by calling `start()` or by re-calling `read()`. + /// Background reception is terminated when an error is returned. + /// It must be started again by calling `start_uart()` or by + /// calling `read()` again. + /// + /// ### Notes on 'waiting for bytes' + /// + /// Waiting for bytes operates in one of two modes, depending on + /// the behavior of the sender and the size of the buffer passed + /// to `read()`: + /// + /// - If the sender sends intermittently, the 'idle line' + /// condition will be detected when the sender stops, and any + /// bytes in the ring buffer will be returned. If there are no + /// bytes in the buffer, the check will be repeated each time the + /// 'idle line' condition is detected, so if the sender sends just + /// a single byte, it will be returned once the 'idle line' + /// condition is detected. + /// + /// - If the sender sends continuously, the call will wait until + /// the DMA controller indicates that it has written to either the + /// middle byte or last byte of the ring buffer ('half transfer' + /// or 'transfer complete', respectively). This does not indicate + /// the buffer is half-full or full, though, because the DMA + /// controller does not detect those conditions; it sends an + /// interrupt when those specific buffer addresses have been + /// written. + /// + /// In both cases this will result in variable latency due to the + /// buffering effect. For example, if the baudrate is 2400 bps, + /// and the configuration is 8 data bits, no parity bit, and one + /// stop bit, then a byte will be received every ~4.16ms. If the + /// ring buffer is 32 bytes, then a 'wait for bytes' delay may + /// have to wait for 16 bytes in the worst case, resulting in a + /// delay (latency) of ~62.46ms for the first byte in the ring + /// buffer. If the sender sends only 6 bytes and then stops, but + /// the buffer was empty when `read()` was called, then those + /// bytes may not be returned until ~24.96ms after the first byte + /// was received (time for 5 additional bytes plus the 'idle + /// frame' which triggers the 'idle line' condition). + /// + /// Applications subject to this latency must be careful if they + /// also apply timeouts during reception, as it may appear (to + /// them) that the sender has stopped sending when it did not. In + /// the example above, a 50ms timeout (12 bytes at 2400bps) might + /// seem to be reasonable to detect that the sender has stopped + /// sending, but would be falsely triggered in the worst-case + /// buffer delay scenario. + /// + /// Note: This latency is caused by the limited capabilities of + /// the STM32 DMA controller; since it cannot generate an + /// interrupt when it stores a byte into an empty ring buffer, or + /// in any other configurable conditions, it is not possible to + /// take notice of the contents of the ring buffer more quickly + /// without introducing polling. As a result the latency can be + /// reduced by calling `read()` repeatedly with smaller buffers to + /// receive the available bytes, as each call to `read()` will + /// explicitly check the ring buffer for available bytes. pub async fn read(&mut self, buf: &mut [u8]) -> Result { self.start_dma_or_check_errors()?; @@ -202,7 +258,8 @@ impl<'d> RingBufferedUartRx<'d> { }); let mut dma_init = false; - // Future which completes when there is dma is half full or full + // Future which completes when the DMA controller indicates it + // has written to the ring buffer's middle byte, or last byte let dma = poll_fn(|cx| { self.ring_buf.set_waker(cx.waker()); -- cgit From ca5fe2645dd5a969052081ab855aa88520198e12 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Sat, 24 May 2025 19:34:07 -0400 Subject: Move new documentation to RingBufferedUartRx struct. --- embassy-stm32/src/usart/ringbuffered.rs | 118 +++++++++++++++++--------------- 1 file changed, 62 insertions(+), 56 deletions(-) diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index 9280dbd18..1d4a44896 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs @@ -18,6 +18,65 @@ use crate::Peri; /// Rx-only Ring-buffered UART Driver /// /// Created with [UartRx::into_ring_buffered] +/// +/// ### Notes on 'waiting for bytes' +/// +/// The `read(buf)` (but not `read()`) and `read_exact(buf)` functions +/// may need to wait for bytes to arrive, if the ring buffer does not +/// contain enough bytes to fill the buffer passed by the caller of +/// the function, or is empty. +/// +/// Waiting for bytes operates in one of two modes, depending on +/// the behavior of the sender and the size of the buffer passed +/// to the function: +/// +/// - If the sender sends intermittently, the 'idle line' +/// condition will be detected when the sender stops, and any +/// bytes in the ring buffer will be returned. If there are no +/// bytes in the buffer, the check will be repeated each time the +/// 'idle line' condition is detected, so if the sender sends just +/// a single byte, it will be returned once the 'idle line' +/// condition is detected. +/// +/// - If the sender sends continuously, the call will wait until +/// the DMA controller indicates that it has written to either the +/// middle byte or last byte of the ring buffer ('half transfer' +/// or 'transfer complete', respectively). This does not indicate +/// the buffer is half-full or full, though, because the DMA +/// controller does not detect those conditions; it sends an +/// interrupt when those specific buffer addresses have been +/// written. +/// +/// In both cases this will result in variable latency due to the +/// buffering effect. For example, if the baudrate is 2400 bps, and +/// the configuration is 8 data bits, no parity bit, and one stop bit, +/// then a byte will be received every ~4.16ms. If the ring buffer is +/// 32 bytes, then a 'wait for bytes' delay may have to wait for 16 +/// bytes in the worst case, resulting in a delay (latency) of +/// ~62.46ms for the first byte in the ring buffer. If the sender +/// sends only 6 bytes and then stops, but the buffer was empty when +/// the read function was called, then those bytes may not be returned +/// until ~24.96ms after the first byte was received (time for 5 +/// additional bytes plus the 'idle frame' which triggers the 'idle +/// line' condition). +/// +/// Applications subject to this latency must be careful if they +/// also apply timeouts during reception, as it may appear (to +/// them) that the sender has stopped sending when it did not. In +/// the example above, a 50ms timeout (12 bytes at 2400bps) might +/// seem to be reasonable to detect that the sender has stopped +/// sending, but would be falsely triggered in the worst-case +/// buffer delay scenario. +/// +/// Note: This latency is caused by the limited capabilities of the +/// STM32 DMA controller; since it cannot generate an interrupt when +/// it stores a byte into an empty ring buffer, or in any other +/// configurable conditions, it is not possible to take notice of the +/// contents of the ring buffer more quickly without introducing +/// polling. As a result the latency can be reduced by calling the +/// read functions repeatedly with smaller buffers to receive the +/// available bytes, as each call to a read function will explicitly +/// check the ring buffer for available bytes. pub struct RingBufferedUartRx<'d> { info: &'static Info, state: &'static State, @@ -79,7 +138,8 @@ impl<'d> RingBufferedUartRx<'d> { /// Configure and start the DMA backed UART receiver /// - /// Note: This is also done automatically by `read()` if required. + /// Note: This is also done automatically by the read functions if + /// required. pub fn start_uart(&mut self) { // Clear the buffer so that it is ready to receive data compiler_fence(Ordering::SeqCst); @@ -148,61 +208,7 @@ impl<'d> RingBufferedUartRx<'d> { /// /// Background reception is terminated when an error is returned. /// It must be started again by calling `start_uart()` or by - /// calling `read()` again. - /// - /// ### Notes on 'waiting for bytes' - /// - /// Waiting for bytes operates in one of two modes, depending on - /// the behavior of the sender and the size of the buffer passed - /// to `read()`: - /// - /// - If the sender sends intermittently, the 'idle line' - /// condition will be detected when the sender stops, and any - /// bytes in the ring buffer will be returned. If there are no - /// bytes in the buffer, the check will be repeated each time the - /// 'idle line' condition is detected, so if the sender sends just - /// a single byte, it will be returned once the 'idle line' - /// condition is detected. - /// - /// - If the sender sends continuously, the call will wait until - /// the DMA controller indicates that it has written to either the - /// middle byte or last byte of the ring buffer ('half transfer' - /// or 'transfer complete', respectively). This does not indicate - /// the buffer is half-full or full, though, because the DMA - /// controller does not detect those conditions; it sends an - /// interrupt when those specific buffer addresses have been - /// written. - /// - /// In both cases this will result in variable latency due to the - /// buffering effect. For example, if the baudrate is 2400 bps, - /// and the configuration is 8 data bits, no parity bit, and one - /// stop bit, then a byte will be received every ~4.16ms. If the - /// ring buffer is 32 bytes, then a 'wait for bytes' delay may - /// have to wait for 16 bytes in the worst case, resulting in a - /// delay (latency) of ~62.46ms for the first byte in the ring - /// buffer. If the sender sends only 6 bytes and then stops, but - /// the buffer was empty when `read()` was called, then those - /// bytes may not be returned until ~24.96ms after the first byte - /// was received (time for 5 additional bytes plus the 'idle - /// frame' which triggers the 'idle line' condition). - /// - /// Applications subject to this latency must be careful if they - /// also apply timeouts during reception, as it may appear (to - /// them) that the sender has stopped sending when it did not. In - /// the example above, a 50ms timeout (12 bytes at 2400bps) might - /// seem to be reasonable to detect that the sender has stopped - /// sending, but would be falsely triggered in the worst-case - /// buffer delay scenario. - /// - /// Note: This latency is caused by the limited capabilities of - /// the STM32 DMA controller; since it cannot generate an - /// interrupt when it stores a byte into an empty ring buffer, or - /// in any other configurable conditions, it is not possible to - /// take notice of the contents of the ring buffer more quickly - /// without introducing polling. As a result the latency can be - /// reduced by calling `read()` repeatedly with smaller buffers to - /// receive the available bytes, as each call to `read()` will - /// explicitly check the ring buffer for available bytes. + /// calling a read function again. pub async fn read(&mut self, buf: &mut [u8]) -> Result { self.start_dma_or_check_errors()?; -- cgit From a860fea0a5d1a0b39fa02afd5214ee4971d6e571 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Sun, 25 May 2025 08:51:27 -0400 Subject: stm32: Assert in BufferedUart that the buffers are not empty. --- embassy-stm32/src/usart/buffered.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 06d5f7528..73ab46404 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -457,8 +457,10 @@ impl<'d> BufferedUart<'d> { info.rcc.enable_and_reset(); + assert!(!tx_buffer.is_empty()); let len = tx_buffer.len(); unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; + assert!(!rx_buffer.is_empty()); let len = rx_buffer.len(); unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; -- cgit From cb1bccfd5cf528497e3be8e0da9928854ed8e081 Mon Sep 17 00:00:00 2001 From: Ivan Li Date: Sun, 25 May 2025 21:39:23 +0800 Subject: feat(stm32): Add DAC::new_unbuffered method. Signed-off-by: Ivan Li --- embassy-stm32/src/dac/mod.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index 30046849b..d8f1f96f2 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs @@ -403,6 +403,46 @@ impl<'d, T: Instance> Dac<'d, T, Async> { Mode::NormalExternalBuffered, ) } + /// Create a new `Dac` instance with external output pins and unbuffered mode. + /// + /// This function consumes the underlying DAC peripheral and allows access to both channels. + /// The channels are configured for external output with the buffer disabled. + /// + /// The channels are enabled on creation and begin to drive their output pins. + /// Note that some methods, such as `set_trigger()` and `set_mode()`, will + /// disable the channel; you must re-enable them with `enable()`. + /// + /// By default, triggering is disabled, but it can be enabled using the `set_trigger()` + /// method on the underlying channels. + /// + /// # Arguments + /// + /// * `peri` - The DAC peripheral instance. + /// * `dma_ch1` - The DMA channel for DAC channel 1. + /// * `dma_ch2` - The DMA channel for DAC channel 2. + /// * `pin_ch1` - The GPIO pin for DAC channel 1 output. + /// * `pin_ch2` - The GPIO pin for DAC channel 2 output. + /// + /// # Returns + /// + /// A new `Dac` instance in unbuffered mode. + pub fn new_unbuffered( + peri: Peri<'d, T>, + dma_ch1: Peri<'d, impl Dma>, + dma_ch2: Peri<'d, impl Dma>, + pin_ch1: Peri<'d, impl DacPin + crate::gpio::Pin>, + pin_ch2: Peri<'d, impl DacPin + crate::gpio::Pin>, + ) -> Self { + pin_ch1.set_as_analog(); + pin_ch2.set_as_analog(); + Self::new_inner( + peri, + new_dma!(dma_ch1), + new_dma!(dma_ch2), + #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] + Mode::NormalExternalUnbuffered, + ) + } /// Create a new `Dac` instance where the external output pins are not used, /// so the DAC can only be used to generate internal signals but the GPIO -- cgit From a8b3178ceec8243e337dc8b3b320faf266eff4a7 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 26 May 2025 09:10:35 +0200 Subject: chore: bump version of embassy-boot-stm32 --- embassy-boot-stm32/Cargo.toml | 2 +- examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wb-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wl/Cargo.toml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/embassy-boot-stm32/Cargo.toml b/embassy-boot-stm32/Cargo.toml index a24921291..11ad453b8 100644 --- a/embassy-boot-stm32/Cargo.toml +++ b/embassy-boot-stm32/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-stm32" -version = "0.2.0" +version = "0.3.0" description = "Bootloader lib for STM32 chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index 87f97071b..b3466e288 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32" } +embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32" } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index d593a568e..72dbded5f 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } -embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index 7653d82ed..57fb8312c 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index d1cace246..7dbbba138 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } -embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 034bf39af..9549b2048 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index d32cbca97..03daeb0bc 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index 49b35f681..e582628aa 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } embassy-usb = { version = "0.4.0", path = "../../../../embassy-usb" } embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index e44d9859a..3ed04b472 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } -- cgit From 8fa07ac062eba0ddc3021e7f8787fce32f62cfbe Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Mon, 26 May 2025 14:43:07 +0200 Subject: fixup! feat(stm32-c0): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/c0.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs index 68f67af01..cac2a9149 100644 --- a/embassy-stm32/src/rcc/c0.rs +++ b/embassy-stm32/src/rcc/c0.rs @@ -60,7 +60,6 @@ pub struct Config { } impl Config { - #[inline] pub const fn new() -> Self { Config { hsi: Some(Hsi { @@ -78,7 +77,6 @@ impl Config { } impl Default for Config { - #[inline] fn default() -> Config { Self::new() } -- cgit From ca17b41d0dfa32150ac72187e1b05924577641cb Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Mon, 26 May 2025 14:43:21 +0200 Subject: fixup! feat(stm32-g0): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/g0.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs index c03cbf9a8..ce6398afd 100644 --- a/embassy-stm32/src/rcc/g0.rs +++ b/embassy-stm32/src/rcc/g0.rs @@ -98,7 +98,6 @@ pub struct Config { } impl Config { - #[inline] pub const fn new() -> Self { Config { hsi: Some(Hsi { @@ -120,7 +119,6 @@ impl Config { } impl Default for Config { - #[inline] fn default() -> Config { Self::new() } -- cgit From fce84bd51be5fa52e965255cabbb26d69a1edbab Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Mon, 26 May 2025 14:43:29 +0200 Subject: fixup! feat(stm32-g4): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/g4.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index e4b216450..da13e16aa 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -92,7 +92,6 @@ pub struct Config { } impl Config { - #[inline] pub const fn new() -> Self { Config { hsi: true, @@ -112,7 +111,6 @@ impl Config { } impl Default for Config { - #[inline] fn default() -> Config { Self::new() } -- cgit From 5d6b51d910462b5dc2c5b80eacd3d7199df86965 Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Mon, 26 May 2025 14:43:39 +0200 Subject: fixup! feat(stm32-l): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/l.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/embassy-stm32/src/rcc/l.rs b/embassy-stm32/src/rcc/l.rs index 91e6ae07e..81b89046e 100644 --- a/embassy-stm32/src/rcc/l.rs +++ b/embassy-stm32/src/rcc/l.rs @@ -69,7 +69,6 @@ pub struct Config { } impl Config { - #[inline] pub const fn new() -> Self { Config { hse: None, @@ -100,7 +99,6 @@ impl Config { } impl Default for Config { - #[inline] fn default() -> Config { Self::new() } -- cgit From a5a27ef52b9575edd0d25aff65f49331f676ca82 Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Mon, 26 May 2025 14:43:46 +0200 Subject: fixup! feat(stm32-wba): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/wba.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index 98d2dcf0e..b9fc4e423 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs @@ -38,7 +38,6 @@ pub struct Config { } impl Config { - #[inline] pub const fn new() -> Self { Config { hse: None, @@ -56,7 +55,6 @@ impl Config { } impl Default for Config { - #[inline] fn default() -> Config { Self::new() } -- cgit From 44c53365ad387c8d1296751080f4f8117c7d7b5c Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Mon, 26 May 2025 14:44:48 +0200 Subject: fixup! feat(stm32-l): provide a `const` constructor on `rcc::Config` --- embassy-stm32/src/rcc/bd.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs index 939c05907..e2c704405 100644 --- a/embassy-stm32/src/rcc/bd.rs +++ b/embassy-stm32/src/rcc/bd.rs @@ -92,6 +92,7 @@ pub struct LsConfig { } impl LsConfig { + /// Creates an [`LsConfig`] using the LSI when possible. pub const fn new() -> Self { // on L5, just the fact that LSI is enabled makes things crash. // TODO: investigate. -- cgit From b9f7478ada241731c52a58cab8c4caa295354467 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Mon, 26 May 2025 18:43:09 -0400 Subject: stm32: Improvements to CRC HAL. * Corrects spelling and grammar errors in documentation. * Removes non-v1 code from v1-only source file. * Adds 'read' operation for v2/v3, to be consistent with v1. * Removes 'reset' from the v2/v3 'reconfigure' operation to match the documentation (the only user is the 'new' function which already issues a reset). --- embassy-stm32/src/crc/v1.rs | 16 ++-------------- embassy-stm32/src/crc/v2v3.rs | 39 +++++++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs index a78b3c2b7..13e5263de 100644 --- a/embassy-stm32/src/crc/v1.rs +++ b/embassy-stm32/src/crc/v1.rs @@ -23,22 +23,16 @@ impl<'d> Crc<'d> { PAC_CRC.cr().write(|w| w.set_reset(true)); } - /// Feeds a word to the peripheral and returns the current CRC value + /// Feeds a word into the CRC peripheral. Returns the computed CRC. pub fn feed_word(&mut self, word: u32) -> u32 { // write a single byte to the device, and return the result - #[cfg(not(crc_v1))] - PAC_CRC.dr32().write_value(word); - #[cfg(crc_v1)] PAC_CRC.dr().write_value(word); self.read() } - /// Feed a slice of words to the peripheral and return the result. + /// Feeds a slice of words into the CRC peripheral. Returns the computed CRC. pub fn feed_words(&mut self, words: &[u32]) -> u32 { for word in words { - #[cfg(not(crc_v1))] - PAC_CRC.dr32().write_value(*word); - #[cfg(crc_v1)] PAC_CRC.dr().write_value(*word); } @@ -46,12 +40,6 @@ impl<'d> Crc<'d> { } /// Read the CRC result value. - #[cfg(not(crc_v1))] - pub fn read(&self) -> u32 { - PAC_CRC.dr32().read() - } - /// Read the CRC result value. - #[cfg(crc_v1)] pub fn read(&self) -> u32 { PAC_CRC.dr().read() } diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs index c94c9f380..d834d0971 100644 --- a/embassy-stm32/src/crc/v2v3.rs +++ b/embassy-stm32/src/crc/v2v3.rs @@ -9,7 +9,7 @@ pub struct Crc<'d> { _config: Config, } -/// CRC configuration errlr +/// CRC configuration error #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ConfigError { @@ -34,9 +34,9 @@ pub enum InputReverseConfig { None, /// Reverse bytes Byte, - /// Reverse 16-bit halfwords. + /// Reverse 16-bit halfwords Halfword, - /// Reverse 32-bit words. + /// Reverse 32-bit words Word, } @@ -127,45 +127,52 @@ impl<'d> Crc<'d> { PolySize::Width32 => vals::Polysize::POLYSIZE32, }); }); + } - self.reset(); + /// Read the CRC result value. + pub fn read(&self) -> u32 { + PAC_CRC.dr32().read() } - /// Feeds a byte into the CRC peripheral. Returns the computed checksum. + /// Feeds a byte into the CRC peripheral. Returns the computed CRC. pub fn feed_byte(&mut self, byte: u8) -> u32 { PAC_CRC.dr8().write_value(byte); - PAC_CRC.dr32().read() + self.read() } - /// Feeds an slice of bytes into the CRC peripheral. Returns the computed checksum. + /// Feeds a slice of bytes into the CRC peripheral. Returns the computed CRC. pub fn feed_bytes(&mut self, bytes: &[u8]) -> u32 { for byte in bytes { PAC_CRC.dr8().write_value(*byte); } - PAC_CRC.dr32().read() + self.read() } - /// Feeds a halfword into the CRC peripheral. Returns the computed checksum. + + /// Feeds a halfword into the CRC peripheral. Returns the computed CRC. pub fn feed_halfword(&mut self, halfword: u16) -> u32 { PAC_CRC.dr16().write_value(halfword); - PAC_CRC.dr32().read() + self.read() } - /// Feeds an slice of halfwords into the CRC peripheral. Returns the computed checksum. + + /// Feeds a slice of halfwords into the CRC peripheral. Returns the computed CRC. pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u32 { for halfword in halfwords { PAC_CRC.dr16().write_value(*halfword); } - PAC_CRC.dr32().read() + self.read() } - /// Feeds a words into the CRC peripheral. Returns the computed checksum. + + /// Feeds a word into the CRC peripheral. Returns the computed CRC. pub fn feed_word(&mut self, word: u32) -> u32 { PAC_CRC.dr32().write_value(word as u32); - PAC_CRC.dr32().read() + self.read() } - /// Feeds an slice of words into the CRC peripheral. Returns the computed checksum. + + /// Feeds a slice of words into the CRC peripheral. Returns the computed CRC. pub fn feed_words(&mut self, words: &[u32]) -> u32 { for word in words { PAC_CRC.dr32().write_value(*word as u32); } - PAC_CRC.dr32().read() + self.read() } } -- cgit From f761e4b97b533388433ac3de8063d0a1aa2dc0e0 Mon Sep 17 00:00:00 2001 From: bobsrac Date: Fri, 23 May 2025 22:01:07 -0600 Subject: nrf52840: example ieee 802.15.4 packet send/receive --- examples/nrf52840/src/bin/ieee802154_receive.rs | 38 ++++++++++++++++++++++++ examples/nrf52840/src/bin/ieee802154_send.rs | 39 +++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 examples/nrf52840/src/bin/ieee802154_receive.rs create mode 100644 examples/nrf52840/src/bin/ieee802154_send.rs diff --git a/examples/nrf52840/src/bin/ieee802154_receive.rs b/examples/nrf52840/src/bin/ieee802154_receive.rs new file mode 100644 index 000000000..ede8fca65 --- /dev/null +++ b/examples/nrf52840/src/bin/ieee802154_receive.rs @@ -0,0 +1,38 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_nrf::config::{Config, HfclkSource}; +use embassy_nrf::gpio::{Level, Output, OutputDrive}; +use embassy_nrf::radio::ieee802154::{self, Packet}; +use embassy_nrf::{peripherals, radio}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +embassy_nrf::bind_interrupts!(struct Irqs { + RADIO => radio::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = Config::default(); + config.hfclk_source = HfclkSource::ExternalXtal; + let peripherals = embassy_nrf::init(config); + + // assumes LED on P0_15 with active-high polarity + let mut gpo_led = Output::new(peripherals.P0_15, Level::Low, OutputDrive::Standard); + + let mut radio = ieee802154::Radio::new(peripherals.RADIO, Irqs); + let mut packet = Packet::new(); + + loop { + gpo_led.set_low(); + let rv = radio.receive(&mut packet).await; + gpo_led.set_high(); + match rv { + Err(_) => defmt::error!("receive() Err"), + Ok(_) => defmt::info!("receive() {:?}", *packet), + } + Timer::after_millis(100u64).await; + } +} diff --git a/examples/nrf52840/src/bin/ieee802154_send.rs b/examples/nrf52840/src/bin/ieee802154_send.rs new file mode 100644 index 000000000..7af9d1d06 --- /dev/null +++ b/examples/nrf52840/src/bin/ieee802154_send.rs @@ -0,0 +1,39 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_nrf::config::{Config, HfclkSource}; +use embassy_nrf::gpio::{Level, Output, OutputDrive}; +use embassy_nrf::radio::ieee802154::{self, Packet}; +use embassy_nrf::{peripherals, radio}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +embassy_nrf::bind_interrupts!(struct Irqs { + RADIO => radio::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = Config::default(); + config.hfclk_source = HfclkSource::ExternalXtal; + let peripherals = embassy_nrf::init(config); + + // assumes LED on P0_15 with active-high polarity + let mut gpo_led = Output::new(peripherals.P0_15, Level::Low, OutputDrive::Standard); + + let mut radio = ieee802154::Radio::new(peripherals.RADIO, Irqs); + let mut packet = Packet::new(); + + loop { + packet.copy_from_slice(&[0_u8; 16]); + gpo_led.set_high(); + let rv = radio.try_send(&mut packet).await; + gpo_led.set_low(); + match rv { + Err(_) => defmt::error!("try_send() Err"), + Ok(_) => defmt::info!("try_send() {:?}", *packet), + } + Timer::after_millis(1000u64).await; + } +} -- cgit From 035040e53cba24d7a15a055b605d50c568eb9e57 Mon Sep 17 00:00:00 2001 From: Nathan Vander Wilt Date: Tue, 27 May 2025 11:38:11 -0700 Subject: Update layer_by_layer.adoc to clarify PAC limitations proposed fix for #4226, re. https://github.com/embassy-rs/embassy/issues/4226#issuecomment-2908772500 --- docs/pages/layer_by_layer.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/layer_by_layer.adoc b/docs/pages/layer_by_layer.adoc index 7dba11b5e..0692ee4fa 100644 --- a/docs/pages/layer_by_layer.adoc +++ b/docs/pages/layer_by_layer.adoc @@ -8,7 +8,7 @@ The application we'll write is a simple 'push button, blink led' application, wh == PAC version -The PAC is the lowest API for accessing peripherals and registers, if you don't count reading/writing directly to memory addresses. It provides distinct types to make accessing peripheral registers easier, but it does not prevent you from writing unsafe code. +The PAC is the lowest API for accessing peripherals and registers, if you don't count reading/writing directly to memory addresses. It provides distinct types to make accessing peripheral registers easier, but it does little to prevent you from configuring or coordinating those registers incorrectly. Writing an application using the PAC directly is therefore not recommended, but if the functionality you want to use is not exposed in the upper layers, that's what you need to use. -- cgit From 042abc805a84d09231174e41edb0e498baaf7295 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 28 May 2025 10:36:05 +0200 Subject: feat: add support for channel peek Add support for peeking into the front of the channel if the value implements Clone. This can be useful in single-receiver situations where you don't want to remove the item from the queue until you've successfully processed it. --- embassy-sync/src/channel.rs | 78 ++++++++++++++++++++++++++++++++++++ embassy-sync/src/priority_channel.rs | 64 +++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs index 4d1fa9e39..a229c52e7 100644 --- a/embassy-sync/src/channel.rs +++ b/embassy-sync/src/channel.rs @@ -208,6 +208,16 @@ where self.channel.try_receive() } + /// Peek at the next value without removing it from the queue. + /// + /// See [`Channel::try_peek()`] + pub fn try_peek(&self) -> Result + where + T: Clone, + { + self.channel.try_peek() + } + /// Allows a poll_fn to poll until the channel is ready to receive /// /// See [`Channel::poll_ready_to_receive()`] @@ -293,6 +303,16 @@ impl<'ch, T> DynamicReceiver<'ch, T> { self.channel.try_receive_with_context(None) } + /// Peek at the next value without removing it from the queue. + /// + /// See [`Channel::try_peek()`] + pub fn try_peek(&self) -> Result + where + T: Clone, + { + self.channel.try_peek_with_context(None) + } + /// Allows a poll_fn to poll until the channel is ready to receive /// /// See [`Channel::poll_ready_to_receive()`] @@ -463,6 +483,10 @@ pub(crate) trait DynamicChannel { fn try_receive_with_context(&self, cx: Option<&mut Context<'_>>) -> Result; + fn try_peek_with_context(&self, cx: Option<&mut Context<'_>>) -> Result + where + T: Clone; + fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> Poll<()>; fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> Poll<()>; @@ -505,6 +529,31 @@ impl ChannelState { self.try_receive_with_context(None) } + fn try_peek(&mut self) -> Result + where + T: Clone, + { + self.try_peek_with_context(None) + } + + fn try_peek_with_context(&mut self, cx: Option<&mut Context<'_>>) -> Result + where + T: Clone, + { + if self.queue.is_full() { + self.senders_waker.wake(); + } + + if let Some(message) = self.queue.front() { + Ok(message.clone()) + } else { + if let Some(cx) = cx { + self.receiver_waker.register(cx.waker()); + } + Err(TryReceiveError::Empty) + } + } + fn try_receive_with_context(&mut self, cx: Option<&mut Context<'_>>) -> Result { if self.queue.is_full() { self.senders_waker.wake(); @@ -634,6 +683,13 @@ where self.lock(|c| c.try_receive_with_context(cx)) } + fn try_peek_with_context(&self, cx: Option<&mut Context<'_>>) -> Result + where + T: Clone, + { + self.lock(|c| c.try_peek_with_context(cx)) + } + /// Poll the channel for the next message pub fn poll_receive(&self, cx: &mut Context<'_>) -> Poll { self.lock(|c| c.poll_receive(cx)) @@ -722,6 +778,17 @@ where self.lock(|c| c.try_receive()) } + /// Peek at the next value without removing it from the queue. + /// + /// This method will either receive a copy of the message from the channel immediately or return + /// an error if the channel is empty. + pub fn try_peek(&self) -> Result + where + T: Clone, + { + self.lock(|c| c.try_peek()) + } + /// Returns the maximum number of elements the channel can hold. pub const fn capacity(&self) -> usize { N @@ -769,6 +836,13 @@ where Channel::try_receive_with_context(self, cx) } + fn try_peek_with_context(&self, cx: Option<&mut Context<'_>>) -> Result + where + T: Clone, + { + Channel::try_peek_with_context(self, cx) + } + fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> Poll<()> { Channel::poll_ready_to_send(self, cx) } @@ -851,6 +925,8 @@ mod tests { fn simple_send_and_receive() { let c = Channel::::new(); assert!(c.try_send(1).is_ok()); + assert_eq!(c.try_peek().unwrap(), 1); + assert_eq!(c.try_peek().unwrap(), 1); assert_eq!(c.try_receive().unwrap(), 1); } @@ -881,6 +957,8 @@ mod tests { let r = c.dyn_receiver(); assert!(s.try_send(1).is_ok()); + assert_eq!(r.try_peek().unwrap(), 1); + assert_eq!(r.try_peek().unwrap(), 1); assert_eq!(r.try_receive().unwrap(), 1); } diff --git a/embassy-sync/src/priority_channel.rs b/embassy-sync/src/priority_channel.rs index 36959204f..623c52993 100644 --- a/embassy-sync/src/priority_channel.rs +++ b/embassy-sync/src/priority_channel.rs @@ -175,6 +175,16 @@ where self.channel.try_receive() } + /// Peek at the next value without removing it from the queue. + /// + /// See [`PriorityChannel::try_peek()`] + pub fn try_peek(&self) -> Result + where + T: Clone, + { + self.channel.try_peek_with_context(None) + } + /// Allows a poll_fn to poll until the channel is ready to receive /// /// See [`PriorityChannel::poll_ready_to_receive()`] @@ -343,6 +353,31 @@ where self.try_receive_with_context(None) } + fn try_peek(&mut self) -> Result + where + T: Clone, + { + self.try_peek_with_context(None) + } + + fn try_peek_with_context(&mut self, cx: Option<&mut Context<'_>>) -> Result + where + T: Clone, + { + if self.queue.len() == self.queue.capacity() { + self.senders_waker.wake(); + } + + if let Some(message) = self.queue.peek() { + Ok(message.clone()) + } else { + if let Some(cx) = cx { + self.receiver_waker.register(cx.waker()); + } + Err(TryReceiveError::Empty) + } + } + fn try_receive_with_context(&mut self, cx: Option<&mut Context<'_>>) -> Result { if self.queue.len() == self.queue.capacity() { self.senders_waker.wake(); @@ -478,6 +513,13 @@ where self.lock(|c| c.try_receive_with_context(cx)) } + fn try_peek_with_context(&self, cx: Option<&mut Context<'_>>) -> Result + where + T: Clone, + { + self.lock(|c| c.try_peek_with_context(cx)) + } + /// Poll the channel for the next message pub fn poll_receive(&self, cx: &mut Context<'_>) -> Poll { self.lock(|c| c.poll_receive(cx)) @@ -548,6 +590,17 @@ where self.lock(|c| c.try_receive()) } + /// Peek at the next value without removing it from the queue. + /// + /// This method will either receive a copy of the message from the channel immediately or return + /// an error if the channel is empty. + pub fn try_peek(&self) -> Result + where + T: Clone, + { + self.lock(|c| c.try_peek()) + } + /// Removes elements from the channel based on the given predicate. pub fn remove_if(&self, predicate: F) where @@ -617,6 +670,13 @@ where PriorityChannel::try_receive_with_context(self, cx) } + fn try_peek_with_context(&self, cx: Option<&mut Context<'_>>) -> Result + where + T: Clone, + { + PriorityChannel::try_peek_with_context(self, cx) + } + fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> Poll<()> { PriorityChannel::poll_ready_to_send(self, cx) } @@ -705,6 +765,8 @@ mod tests { fn simple_send_and_receive() { let c = PriorityChannel::::new(); assert!(c.try_send(1).is_ok()); + assert_eq!(c.try_peek().unwrap(), 1); + assert_eq!(c.try_peek().unwrap(), 1); assert_eq!(c.try_receive().unwrap(), 1); } @@ -725,6 +787,8 @@ mod tests { let r: DynamicReceiver<'_, u32> = c.receiver().into(); assert!(s.try_send(1).is_ok()); + assert_eq!(r.try_peek().unwrap(), 1); + assert_eq!(r.try_peek().unwrap(), 1); assert_eq!(r.try_receive().unwrap(), 1); } -- cgit From 277f6f7331684a0008930a43b6705ba52873d1f5 Mon Sep 17 00:00:00 2001 From: Corey Schuhen Date: Wed, 28 May 2025 18:15:15 +1000 Subject: Make Sync capable versions of DynamicSender and DynamicReceiver. DynamicSender and DynamicReceiver, just seem to be a fat pointer to a Channel which is already protected by it's own Mutex already. In fact, you can share the Channel already betwen threads and create Dynamic*er's in the target threads. It should be safe to share the Dynamic*er's directly. Can only be used when Mutex M of channel supoorts Sync. --- embassy-sync/src/channel.rs | 106 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs index 4d1fa9e39..1b053ecad 100644 --- a/embassy-sync/src/channel.rs +++ b/embassy-sync/src/channel.rs @@ -164,6 +164,57 @@ impl<'ch, T> DynamicSender<'ch, T> { } } +/// Send-only access to a [`Channel`] without knowing channel size. +/// This version can be sent between threads but can only be created if the underlying mutex is Sync. +pub struct SendDynamicSender<'ch, T> { + pub(crate) channel: &'ch dyn DynamicChannel, +} + +impl<'ch, T> Clone for SendDynamicSender<'ch, T> { + fn clone(&self) -> Self { + *self + } +} + +impl<'ch, T> Copy for SendDynamicSender<'ch, T> {} +unsafe impl<'ch, T: Send> Send for SendDynamicSender<'ch, T> {} +unsafe impl<'ch, T: Send> Sync for SendDynamicSender<'ch, T> {} + +impl<'ch, M, T, const N: usize> From> for SendDynamicSender<'ch, T> +where + M: RawMutex + Sync + Send, +{ + fn from(s: Sender<'ch, M, T, N>) -> Self { + Self { channel: s.channel } + } +} + +impl<'ch, T> SendDynamicSender<'ch, T> { + /// Sends a value. + /// + /// See [`Channel::send()`] + pub fn send(&self, message: T) -> DynamicSendFuture<'ch, T> { + DynamicSendFuture { + channel: self.channel, + message: Some(message), + } + } + + /// Attempt to immediately send a message. + /// + /// See [`Channel::send()`] + pub fn try_send(&self, message: T) -> Result<(), TrySendError> { + self.channel.try_send_with_context(message, None) + } + + /// Allows a poll_fn to poll until the channel is ready to send + /// + /// See [`Channel::poll_ready_to_send()`] + pub fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> Poll<()> { + self.channel.poll_ready_to_send(cx) + } +} + /// Receive-only access to a [`Channel`]. pub struct Receiver<'ch, M, T, const N: usize> where @@ -317,6 +368,61 @@ where } } +/// Receive-only access to a [`Channel`] without knowing channel size. +/// This version can be sent between threads but can only be created if the underlying mutex is Sync. +pub struct SendableDynamicReceiver<'ch, T> { + pub(crate) channel: &'ch dyn DynamicChannel, +} + +impl<'ch, T> Clone for SendableDynamicReceiver<'ch, T> { + fn clone(&self) -> Self { + *self + } +} + +impl<'ch, T> Copy for SendableDynamicReceiver<'ch, T> {} +unsafe impl<'ch, T: Send> Send for SendableDynamicReceiver<'ch, T> {} +unsafe impl<'ch, T: Send> Sync for SendableDynamicReceiver<'ch, T> {} + +impl<'ch, T> SendableDynamicReceiver<'ch, T> { + /// Receive the next value. + /// + /// See [`Channel::receive()`]. + pub fn receive(&self) -> DynamicReceiveFuture<'_, T> { + DynamicReceiveFuture { channel: self.channel } + } + + /// Attempt to immediately receive the next value. + /// + /// See [`Channel::try_receive()`] + pub fn try_receive(&self) -> Result { + self.channel.try_receive_with_context(None) + } + + /// Allows a poll_fn to poll until the channel is ready to receive + /// + /// See [`Channel::poll_ready_to_receive()`] + pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> Poll<()> { + self.channel.poll_ready_to_receive(cx) + } + + /// Poll the channel for the next item + /// + /// See [`Channel::poll_receive()`] + pub fn poll_receive(&self, cx: &mut Context<'_>) -> Poll { + self.channel.poll_receive(cx) + } +} + +impl<'ch, M, T, const N: usize> From> for SendableDynamicReceiver<'ch, T> +where + M: RawMutex + Sync + Send, +{ + fn from(s: Receiver<'ch, M, T, N>) -> Self { + Self { channel: s.channel } + } +} + impl<'ch, M, T, const N: usize> futures_util::Stream for Receiver<'ch, M, T, N> where M: RawMutex, -- cgit From dfd2d31819835820ecb196cd0497d1456ba1b825 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 28 May 2025 12:35:59 +0200 Subject: docs: update changelog for embassy-sync --- embassy-sync/CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-sync/CHANGELOG.md b/embassy-sync/CHANGELOG.md index 1770bef44..89684de0c 100644 --- a/embassy-sync/CHANGELOG.md +++ b/embassy-sync/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -## 0.7.0 - 2025-05-22 +## 0.7.0 - 2025-05-28 - Add `remove_if` to `priority_channel::{Receiver, PriorityChannel}`. - impl `Stream` for `channel::{Receiver, Channel}`. @@ -21,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improve waker documentation. - Improve `Signal` and `Watch` documentation. - Update to defmt 1.0. This remains compatible with latest defmt 0.3. +- Add `peek` method on `channel` and `priority_channel`. +- Add dynamic sender and receiver that are Send + Sync for `channel`. ## 0.6.2 - 2025-01-15 -- cgit From 5a07ea5d851768223e2e41342e69d14c1afb2b2b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 9 Mar 2025 20:55:11 +0100 Subject: Add support for Cortex-A/R --- ci-nightly.sh | 1 + ci.sh | 3 ++ embassy-executor-macros/src/lib.rs | 25 +++++++++ embassy-executor-macros/src/macros/main.rs | 6 +++ embassy-executor/CHANGELOG.md | 4 ++ embassy-executor/Cargo.toml | 5 ++ embassy-executor/src/arch/cortex_ar.rs | 84 ++++++++++++++++++++++++++++++ embassy-executor/src/lib.rs | 2 + rust-toolchain-nightly.toml | 1 + rust-toolchain.toml | 3 ++ 10 files changed, 134 insertions(+) create mode 100644 embassy-executor/src/arch/cortex_ar.rs diff --git a/ci-nightly.sh b/ci-nightly.sh index c0a2482e7..d486d442c 100755 --- a/ci-nightly.sh +++ b/ci-nightly.sh @@ -21,5 +21,6 @@ cargo batch \ --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32 \ --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread \ --- build --release --manifest-path examples/nrf52840-rtic/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/nrf52840-rtic \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7a-none-eabi --features nightly,arch-cortex-ar,executor-thread \ RUSTFLAGS="$RUSTFLAGS -C target-cpu=atmega328p" cargo build --release --manifest-path embassy-executor/Cargo.toml --target avr-none -Z build-std=core,alloc --features nightly,arch-avr,avr-device/atmega328p diff --git a/ci.sh b/ci.sh index d21c1c97b..e1fdf998a 100755 --- a/ci.sh +++ b/ci.sh @@ -35,6 +35,9 @@ cargo batch \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread,executor-interrupt \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7a-none-eabi --features arch-cortex-ar,executor-thread \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7r-none-eabi --features arch-cortex-ar,executor-thread \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7r-none-eabihf --features arch-cortex-ar,executor-thread \ --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32 \ --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32,executor-thread \ --- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features defmt \ diff --git a/embassy-executor-macros/src/lib.rs b/embassy-executor-macros/src/lib.rs index 8e737db6a..962ce2e75 100644 --- a/embassy-executor-macros/src/lib.rs +++ b/embassy-executor-macros/src/lib.rs @@ -70,6 +70,31 @@ pub fn main_cortex_m(args: TokenStream, item: TokenStream) -> TokenStream { main::run(args.into(), item.into(), &main::ARCH_CORTEX_M).into() } +/// Creates a new `executor` instance and declares an application entry point for Cortex-A/R +/// spawning the corresponding function body as an async task. +/// +/// The following restrictions apply: +/// +/// * The function must accept exactly 1 parameter, an `embassy_executor::Spawner` handle that it +/// can use to spawn additional tasks. +/// * The function must be declared `async`. +/// * The function must not use generics. +/// * Only a single `main` task may be declared. +/// +/// ## Examples +/// Spawning a task: +/// +/// ``` rust +/// #[embassy_executor::main] +/// async fn main(_s: embassy_executor::Spawner) { +/// // Function body +/// } +/// ``` +#[proc_macro_attribute] +pub fn main_cortex_ar(args: TokenStream, item: TokenStream) -> TokenStream { + main::run(args.into(), item.into(), &main::ARCH_CORTEX_AR).into() +} + /// Creates a new `executor` instance and declares an architecture agnostic application entry point spawning /// the corresponding function body as an async task. /// diff --git a/embassy-executor-macros/src/macros/main.rs b/embassy-executor-macros/src/macros/main.rs index 95722b19b..a0e7b3401 100644 --- a/embassy-executor-macros/src/macros/main.rs +++ b/embassy-executor-macros/src/macros/main.rs @@ -37,6 +37,12 @@ pub static ARCH_CORTEX_M: Arch = Arch { executor_required: false, }; +pub static ARCH_CORTEX_AR: Arch = Arch { + default_entry: None, + flavor: Flavor::Standard, + executor_required: false, +}; + pub static ARCH_SPIN: Arch = Arch { default_entry: None, flavor: Flavor::Standard, diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 5d2468c58..608c67724 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -5,6 +5,10 @@ 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). +## unreleased + +- Added support for Cortex-A and Cortex-R + ## 0.7.0 - 2025-01-02 - Performance optimizations. diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 9f9eaa600..f014ccf30 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -45,6 +45,9 @@ portable-atomic = { version = "1.5", optional = true } # arch-cortex-m dependencies cortex-m = { version = "0.7.6", optional = true } +# arch-cortex-ar dependencies +cortex-ar = { version = "0.2", optional = true } + # arch-wasm dependencies wasm-bindgen = { version = "0.2.82", optional = true } js-sys = { version = "0.3", optional = true } @@ -73,6 +76,8 @@ _arch = [] # some arch was picked arch-std = ["_arch"] ## Cortex-M arch-cortex-m = ["_arch", "dep:cortex-m"] +## Cortex-A/R +arch-cortex-ar = ["_arch", "dep:cortex-ar"] ## RISC-V 32 arch-riscv32 = ["_arch"] ## WASM diff --git a/embassy-executor/src/arch/cortex_ar.rs b/embassy-executor/src/arch/cortex_ar.rs new file mode 100644 index 000000000..f9e2f3f7c --- /dev/null +++ b/embassy-executor/src/arch/cortex_ar.rs @@ -0,0 +1,84 @@ +#[cfg(feature = "executor-interrupt")] +compile_error!("`executor-interrupt` is not supported with `arch-cortex-ar`."); + +#[export_name = "__pender"] +#[cfg(any(feature = "executor-thread", feature = "executor-interrupt"))] +fn __pender(context: *mut ()) { + // `context` is always `usize::MAX` created by `Executor::run`. + let context = context as usize; + + #[cfg(feature = "executor-thread")] + // Try to make Rust optimize the branching away if we only use thread mode. + if !cfg!(feature = "executor-interrupt") || context == THREAD_PENDER { + cortex_ar::asm::sev(); + return; + } +} + +#[cfg(feature = "executor-thread")] +pub use thread::*; +#[cfg(feature = "executor-thread")] +mod thread { + pub(super) const THREAD_PENDER: usize = usize::MAX; + + use core::marker::PhantomData; + + use cortex_ar::asm::wfe; + pub use embassy_executor_macros::main_cortex_ar as main; + + use crate::{raw, Spawner}; + + /// Thread mode executor, using WFE/SEV. + /// + /// This is the simplest and most common kind of executor. It runs on + /// thread mode (at the lowest priority level), and uses the `WFE` ARM instruction + /// to sleep when it has no more work to do. When a task is woken, a `SEV` instruction + /// is executed, to make the `WFE` exit from sleep and poll the task. + /// + /// This executor allows for ultra low power consumption for chips where `WFE` + /// triggers low-power sleep without extra steps. If your chip requires extra steps, + /// you may use [`raw::Executor`] directly to program custom behavior. + pub struct Executor { + inner: raw::Executor, + not_send: PhantomData<*mut ()>, + } + + impl Executor { + /// Create a new Executor. + pub fn new() -> Self { + Self { + inner: raw::Executor::new(THREAD_PENDER as *mut ()), + not_send: PhantomData, + } + } + + /// Run the executor. + /// + /// The `init` closure is called with a [`Spawner`] that spawns tasks on + /// this executor. Use it to spawn the initial task(s). After `init` returns, + /// the executor starts running the tasks. + /// + /// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`), + /// for example by passing it as an argument to the initial tasks. + /// + /// This function requires `&'static mut self`. This means you have to store the + /// Executor instance in a place where it'll live forever and grants you mutable + /// access. There's a few ways to do this: + /// + /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe) + /// - a `static mut` (unsafe) + /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) + /// + /// This function never returns. + pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { + init(self.inner.spawner()); + + loop { + unsafe { + self.inner.poll(); + } + wfe(); + } + } + } +} diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index d6fd3d651..dfe420bab 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -26,6 +26,7 @@ macro_rules! check_at_most_one { check_at_most_one!( "arch-avr", "arch-cortex-m", + "arch-cortex-ar", "arch-riscv32", "arch-std", "arch-wasm", @@ -35,6 +36,7 @@ check_at_most_one!( #[cfg(feature = "_arch")] #[cfg_attr(feature = "arch-avr", path = "arch/avr.rs")] #[cfg_attr(feature = "arch-cortex-m", path = "arch/cortex_m.rs")] +#[cfg_attr(feature = "arch-cortex-ar", path = "arch/cortex_ar.rs")] #[cfg_attr(feature = "arch-riscv32", path = "arch/riscv32.rs")] #[cfg_attr(feature = "arch-std", path = "arch/std.rs")] #[cfg_attr(feature = "arch-wasm", path = "arch/wasm.rs")] diff --git a/rust-toolchain-nightly.toml b/rust-toolchain-nightly.toml index d803b29a0..e75ea40cc 100644 --- a/rust-toolchain-nightly.toml +++ b/rust-toolchain-nightly.toml @@ -9,4 +9,5 @@ targets = [ "thumbv8m.main-none-eabihf", "riscv32imac-unknown-none-elf", "wasm32-unknown-unknown", + "armv7a-none-eabi", ] diff --git a/rust-toolchain.toml b/rust-toolchain.toml index ca5816121..870904c3a 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -9,4 +9,7 @@ targets = [ "thumbv8m.main-none-eabihf", "riscv32imac-unknown-none-elf", "wasm32-unknown-unknown", + "armv7a-none-eabi", + "armv7r-none-eabi", + "armv7r-none-eabihf", ] -- cgit From 5730b57094d6e2da3645326596532a091b47ec86 Mon Sep 17 00:00:00 2001 From: Corey Schuhen Date: Thu, 29 May 2025 08:30:21 +1000 Subject: Rename SendableDynamicReceiver to SendDynamicReceiver --- embassy-sync/src/channel.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs index f97cb2b8e..856551417 100644 --- a/embassy-sync/src/channel.rs +++ b/embassy-sync/src/channel.rs @@ -390,21 +390,21 @@ where /// Receive-only access to a [`Channel`] without knowing channel size. /// This version can be sent between threads but can only be created if the underlying mutex is Sync. -pub struct SendableDynamicReceiver<'ch, T> { +pub struct SendDynamicReceiver<'ch, T> { pub(crate) channel: &'ch dyn DynamicChannel, } -impl<'ch, T> Clone for SendableDynamicReceiver<'ch, T> { +impl<'ch, T> Clone for SendDynamicReceiver<'ch, T> { fn clone(&self) -> Self { *self } } -impl<'ch, T> Copy for SendableDynamicReceiver<'ch, T> {} -unsafe impl<'ch, T: Send> Send for SendableDynamicReceiver<'ch, T> {} -unsafe impl<'ch, T: Send> Sync for SendableDynamicReceiver<'ch, T> {} +impl<'ch, T> Copy for SendDynamicReceiver<'ch, T> {} +unsafe impl<'ch, T: Send> Send for SendDynamicReceiver<'ch, T> {} +unsafe impl<'ch, T: Send> Sync for SendDynamicReceiver<'ch, T> {} -impl<'ch, T> SendableDynamicReceiver<'ch, T> { +impl<'ch, T> SendDynamicReceiver<'ch, T> { /// Receive the next value. /// /// See [`Channel::receive()`]. @@ -434,7 +434,7 @@ impl<'ch, T> SendableDynamicReceiver<'ch, T> { } } -impl<'ch, M, T, const N: usize> From> for SendableDynamicReceiver<'ch, T> +impl<'ch, M, T, const N: usize> From> for SendDynamicReceiver<'ch, T> where M: RawMutex + Sync + Send, { -- cgit From a4d4f62a1e0e808ec3dd93e282f517a2f8ad9fa5 Mon Sep 17 00:00:00 2001 From: Matthew Tran <0e4ef622@gmail.com> Date: Wed, 28 May 2025 22:00:25 -0500 Subject: Allow `-> impl Future` in #[task] --- embassy-executor-macros/src/macros/task.rs | 34 +++--- embassy-executor/src/lib.rs | 47 +++++++- embassy-executor/tests/test.rs | 24 ++++- embassy-executor/tests/ui.rs | 4 + embassy-executor/tests/ui/bad_return_impl_trait.rs | 9 ++ .../tests/ui/bad_return_impl_trait.stderr | 120 +++++++++++++++++++++ .../tests/ui/bad_return_impl_trait_nightly.rs | 9 ++ .../tests/ui/bad_return_impl_trait_nightly.stderr | 9 ++ 8 files changed, 239 insertions(+), 17 deletions(-) create mode 100644 embassy-executor/tests/ui/bad_return_impl_trait.rs create mode 100644 embassy-executor/tests/ui/bad_return_impl_trait.stderr create mode 100644 embassy-executor/tests/ui/bad_return_impl_trait_nightly.rs create mode 100644 embassy-executor/tests/ui/bad_return_impl_trait_nightly.stderr diff --git a/embassy-executor-macros/src/macros/task.rs b/embassy-executor-macros/src/macros/task.rs index 91d6beee8..91bf8e940 100644 --- a/embassy-executor-macros/src/macros/task.rs +++ b/embassy-executor-macros/src/macros/task.rs @@ -51,7 +51,11 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { .embassy_executor .unwrap_or(Expr::Verbatim(TokenStream::from_str("::embassy_executor").unwrap())); - if f.sig.asyncness.is_none() { + let returns_impl_trait = match &f.sig.output { + ReturnType::Type(_, ty) => matches!(**ty, Type::ImplTrait(_)), + _ => false, + }; + if f.sig.asyncness.is_none() && !returns_impl_trait { error(&mut errors, &f.sig, "task functions must be async"); } if !f.sig.generics.params.is_empty() { @@ -66,17 +70,19 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { if !f.sig.variadic.is_none() { error(&mut errors, &f.sig, "task functions must not be variadic"); } - match &f.sig.output { - ReturnType::Default => {} - ReturnType::Type(_, ty) => match &**ty { - Type::Tuple(tuple) if tuple.elems.is_empty() => {} - Type::Never(_) => {} - _ => error( - &mut errors, - &f.sig, - "task functions must either not return a value, return `()` or return `!`", - ), - }, + if f.sig.asyncness.is_some() { + match &f.sig.output { + ReturnType::Default => {} + ReturnType::Type(_, ty) => match &**ty { + Type::Tuple(tuple) if tuple.elems.is_empty() => {} + Type::Never(_) => {} + _ => error( + &mut errors, + &f.sig, + "task functions must either not return a value, return `()` or return `!`", + ), + }, + } } let mut args = Vec::new(); @@ -128,12 +134,12 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { #[cfg(feature = "nightly")] let mut task_outer_body = quote! { trait _EmbassyInternalTaskTrait { - type Fut: ::core::future::Future + 'static; + type Fut: ::core::future::Future + 'static; fn construct(#fargs) -> Self::Fut; } impl _EmbassyInternalTaskTrait for () { - type Fut = impl core::future::Future + 'static; + type Fut = impl core::future::Future + 'static; fn construct(#fargs) -> Self::Fut { #task_inner_ident(#(#full_args,)*) } diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index dfe420bab..70abfcc3a 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -65,8 +65,17 @@ pub mod _export { use crate::raw::TaskPool; + trait TaskReturnValue {} + impl TaskReturnValue for () {} + impl TaskReturnValue for Never {} + + #[diagnostic::on_unimplemented( + message = "task function futures must resolve to `()`", + note = "use `async fn` or change the return type to `impl Future`" + )] + #[allow(private_bounds)] pub trait TaskFn: Copy { - type Fut: Future + 'static; + type Fut: Future + 'static; } macro_rules! task_fn_impl { @@ -74,7 +83,7 @@ pub mod _export { impl TaskFn<($($Tn,)*)> for F where F: Copy + FnOnce($($Tn,)*) -> Fut, - Fut: Future + 'static, + Fut: Future + 'static, { type Fut = Fut; } @@ -205,4 +214,38 @@ pub mod _export { Align268435456: 268435456, Align536870912: 536870912, ); + + #[allow(dead_code)] + trait HasOutput { + type Output; + } + + impl HasOutput for fn() -> O { + type Output = O; + } + + #[allow(dead_code)] + type Never = ! as HasOutput>::Output; +} + +/// Implementation details for embassy macros. +/// Do not use. Used for macros and HALs only. Not covered by semver guarantees. +#[doc(hidden)] +#[cfg(feature = "nightly")] +pub mod _export { + pub trait TaskReturnValue {} + impl TaskReturnValue for () {} + impl TaskReturnValue for Never {} + + #[allow(dead_code)] + trait HasOutput { + type Output; + } + + impl HasOutput for fn() -> O { + type Output = O; + } + + #[allow(dead_code)] + type Never = ! as HasOutput>::Output; } diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs index 78c49c071..c7ff4554c 100644 --- a/embassy-executor/tests/test.rs +++ b/embassy-executor/tests/test.rs @@ -1,7 +1,7 @@ #![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] use std::boxed::Box; -use std::future::poll_fn; +use std::future::{poll_fn, Future}; use std::sync::{Arc, Mutex}; use std::task::Poll; @@ -73,6 +73,28 @@ fn executor_task() { ) } +#[test] +fn executor_task_rpit() { + #[task] + fn task1(trace: Trace) -> impl Future { + async move { trace.push("poll task1") } + } + + let (executor, trace) = setup(); + executor.spawner().spawn(task1(trace.clone())).unwrap(); + + unsafe { executor.poll() }; + unsafe { executor.poll() }; + + assert_eq!( + trace.get(), + &[ + "pend", // spawning a task pends the executor + "poll task1", // poll only once. + ] + ) +} + #[test] fn executor_task_self_wake() { #[task] diff --git a/embassy-executor/tests/ui.rs b/embassy-executor/tests/ui.rs index 278a4b903..ed8228e27 100644 --- a/embassy-executor/tests/ui.rs +++ b/embassy-executor/tests/ui.rs @@ -17,6 +17,10 @@ fn ui() { t.compile_fail("tests/ui/nonstatic_struct_elided.rs"); t.compile_fail("tests/ui/nonstatic_struct_generic.rs"); t.compile_fail("tests/ui/not_async.rs"); + // #[cfg(not(feature = "nightly"))] // output differs on stable and nightly + // t.compile_fail("tests/ui/bad_return_impl_trait.rs"); + #[cfg(feature = "nightly")] + t.compile_fail("tests/ui/bad_return_impl_trait_nightly.rs"); t.compile_fail("tests/ui/self_ref.rs"); t.compile_fail("tests/ui/self.rs"); t.compile_fail("tests/ui/type_error.rs"); diff --git a/embassy-executor/tests/ui/bad_return_impl_trait.rs b/embassy-executor/tests/ui/bad_return_impl_trait.rs new file mode 100644 index 000000000..baaa7dc5a --- /dev/null +++ b/embassy-executor/tests/ui/bad_return_impl_trait.rs @@ -0,0 +1,9 @@ +#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] +use core::future::Future; + +#[embassy_executor::task] +fn task() -> impl Future { + async { 5 } +} + +fn main() {} diff --git a/embassy-executor/tests/ui/bad_return_impl_trait.stderr b/embassy-executor/tests/ui/bad_return_impl_trait.stderr new file mode 100644 index 000000000..9e2df353e --- /dev/null +++ b/embassy-executor/tests/ui/bad_return_impl_trait.stderr @@ -0,0 +1,120 @@ +error[E0277]: task function futures must resolve to `()` + --> tests/ui/bad_return_impl_trait.rs:5:4 + | +4 | #[embassy_executor::task] + | ------------------------- required by a bound introduced by this call +5 | fn task() -> impl Future { + | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_size` + --> src/lib.rs + | + | pub const fn task_pool_size(_: F) -> usize + | -------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^ required by this bound in `task_pool_size` + +error[E0277]: task function futures must resolve to `()` + --> tests/ui/bad_return_impl_trait.rs:4:1 + | +4 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_size` + --> src/lib.rs + | + | pub const fn task_pool_size(_: F) -> usize + | -------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_size` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: task function futures must resolve to `()` + --> tests/ui/bad_return_impl_trait.rs:5:4 + | +4 | #[embassy_executor::task] + | ------------------------- required by a bound introduced by this call +5 | fn task() -> impl Future { + | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_align` + --> src/lib.rs + | + | pub const fn task_pool_align(_: F) -> usize + | --------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^ required by this bound in `task_pool_align` + +error[E0277]: task function futures must resolve to `()` + --> tests/ui/bad_return_impl_trait.rs:4:1 + | +4 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_align` + --> src/lib.rs + | + | pub const fn task_pool_align(_: F) -> usize + | --------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_align` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: task function futures must resolve to `()` + --> tests/ui/bad_return_impl_trait.rs:5:4 + | +4 | #[embassy_executor::task] + | ------------------------- required by a bound introduced by this call +5 | fn task() -> impl Future { + | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_new` + --> src/lib.rs + | + | pub const fn task_pool_new(_: F) -> TaskPool + | ------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^ required by this bound in `task_pool_new` + +error[E0277]: task function futures must resolve to `()` + --> tests/ui/bad_return_impl_trait.rs:4:1 + | +4 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_new` + --> src/lib.rs + | + | pub const fn task_pool_new(_: F) -> TaskPool + | ------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_new` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: task function futures must resolve to `()` + --> tests/ui/bad_return_impl_trait.rs:5:4 + | +4 | #[embassy_executor::task] + | ------------------------- required by a bound introduced by this call +5 | fn task() -> impl Future { + | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `__task_pool_get` + --> tests/ui/bad_return_impl_trait.rs:4:1 + | +4 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `__task_pool_get` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/embassy-executor/tests/ui/bad_return_impl_trait_nightly.rs b/embassy-executor/tests/ui/bad_return_impl_trait_nightly.rs new file mode 100644 index 000000000..baaa7dc5a --- /dev/null +++ b/embassy-executor/tests/ui/bad_return_impl_trait_nightly.rs @@ -0,0 +1,9 @@ +#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] +use core::future::Future; + +#[embassy_executor::task] +fn task() -> impl Future { + async { 5 } +} + +fn main() {} diff --git a/embassy-executor/tests/ui/bad_return_impl_trait_nightly.stderr b/embassy-executor/tests/ui/bad_return_impl_trait_nightly.stderr new file mode 100644 index 000000000..21e20d5c0 --- /dev/null +++ b/embassy-executor/tests/ui/bad_return_impl_trait_nightly.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `u32: TaskReturnValue` is not satisfied + --> tests/ui/bad_return_impl_trait_nightly.rs:4:1 + | +4 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskReturnValue` is not implemented for `u32` + | + = help: the following other types implement trait `TaskReturnValue`: + () + ! as _export::HasOutput>::Output -- cgit From dbff432e19b326d7cef109bc4d2a0cd51260562d Mon Sep 17 00:00:00 2001 From: Matthew Tran <0e4ef622@gmail.com> Date: Thu, 29 May 2025 05:18:16 -0500 Subject: Add test for -> impl Future --- embassy-executor/tests/test.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs index c7ff4554c..c1e7ec5d7 100644 --- a/embassy-executor/tests/test.rs +++ b/embassy-executor/tests/test.rs @@ -1,4 +1,5 @@ #![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] +#![cfg_attr(feature = "nightly", feature(never_type))] use std::boxed::Box; use std::future::{poll_fn, Future}; @@ -58,6 +59,11 @@ fn executor_task() { trace.push("poll task1") } + #[task] + async fn task2() -> ! { + panic!() + } + let (executor, trace) = setup(); executor.spawner().spawn(task1(trace.clone())).unwrap(); @@ -80,6 +86,12 @@ fn executor_task_rpit() { async move { trace.push("poll task1") } } + #[cfg(feature = "nightly")] + #[task] + fn task2() -> impl Future { + async { panic!() } + } + let (executor, trace) = setup(); executor.spawner().spawn(task1(trace.clone())).unwrap(); -- cgit From b06a708f81d208236763a121797807fd5b48aee6 Mon Sep 17 00:00:00 2001 From: Matthew Tran <0e4ef622@gmail.com> Date: Thu, 29 May 2025 05:54:25 -0500 Subject: Mention ! in diagnostic --- embassy-executor/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index 70abfcc3a..e26e8ee7d 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -70,7 +70,7 @@ pub mod _export { impl TaskReturnValue for Never {} #[diagnostic::on_unimplemented( - message = "task function futures must resolve to `()`", + message = "task futures must resolve to `()` or `!`", note = "use `async fn` or change the return type to `impl Future`" )] #[allow(private_bounds)] -- cgit From 3d617007a257b814459e6e8c8c3ee4bce77469e3 Mon Sep 17 00:00:00 2001 From: Willdew Date: Thu, 29 May 2025 23:06:01 +0200 Subject: fixed n in set_sq to be indexed correctly --- embassy-stm32/src/adc/ringbuffered_v2.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/embassy-stm32/src/adc/ringbuffered_v2.rs b/embassy-stm32/src/adc/ringbuffered_v2.rs index fabf0284b..6f69e8486 100644 --- a/embassy-stm32/src/adc/ringbuffered_v2.rs +++ b/embassy-stm32/src/adc/ringbuffered_v2.rs @@ -199,16 +199,16 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> { Sequence::Four => T::regs().sqr3().modify(|w| w.set_sq(3, channel.channel())), Sequence::Five => T::regs().sqr3().modify(|w| w.set_sq(4, channel.channel())), Sequence::Six => T::regs().sqr3().modify(|w| w.set_sq(5, channel.channel())), - Sequence::Seven => T::regs().sqr2().modify(|w| w.set_sq(6, channel.channel())), - Sequence::Eight => T::regs().sqr2().modify(|w| w.set_sq(7, channel.channel())), - Sequence::Nine => T::regs().sqr2().modify(|w| w.set_sq(8, channel.channel())), - Sequence::Ten => T::regs().sqr2().modify(|w| w.set_sq(9, channel.channel())), - Sequence::Eleven => T::regs().sqr2().modify(|w| w.set_sq(10, channel.channel())), - Sequence::Twelve => T::regs().sqr2().modify(|w| w.set_sq(11, channel.channel())), - Sequence::Thirteen => T::regs().sqr1().modify(|w| w.set_sq(12, channel.channel())), - Sequence::Fourteen => T::regs().sqr1().modify(|w| w.set_sq(13, channel.channel())), - Sequence::Fifteen => T::regs().sqr1().modify(|w| w.set_sq(14, channel.channel())), - Sequence::Sixteen => T::regs().sqr1().modify(|w| w.set_sq(15, channel.channel())), + Sequence::Seven => T::regs().sqr2().modify(|w| w.set_sq(0, channel.channel())), + Sequence::Eight => T::regs().sqr2().modify(|w| w.set_sq(1, channel.channel())), + Sequence::Nine => T::regs().sqr2().modify(|w| w.set_sq(2, channel.channel())), + Sequence::Ten => T::regs().sqr2().modify(|w| w.set_sq(3, channel.channel())), + Sequence::Eleven => T::regs().sqr2().modify(|w| w.set_sq(4, channel.channel())), + Sequence::Twelve => T::regs().sqr2().modify(|w| w.set_sq(5, channel.channel())), + Sequence::Thirteen => T::regs().sqr1().modify(|w| w.set_sq(0, channel.channel())), + Sequence::Fourteen => T::regs().sqr1().modify(|w| w.set_sq(1, channel.channel())), + Sequence::Fifteen => T::regs().sqr1().modify(|w| w.set_sq(2, channel.channel())), + Sequence::Sixteen => T::regs().sqr1().modify(|w| w.set_sq(3, channel.channel())), }; if !was_on { -- cgit From 86efdc9cc39a47269d384424dc09c4642444e357 Mon Sep 17 00:00:00 2001 From: melvdl Date: Fri, 30 May 2025 00:28:35 +0200 Subject: convert embassy-stm32::qspi::enums `Into` impls into equivalant `From` impls --- embassy-stm32/src/qspi/enums.rs | 48 ++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/embassy-stm32/src/qspi/enums.rs b/embassy-stm32/src/qspi/enums.rs index ecade9b1a..9ec4c1b43 100644 --- a/embassy-stm32/src/qspi/enums.rs +++ b/embassy-stm32/src/qspi/enums.rs @@ -9,9 +9,9 @@ pub(crate) enum QspiMode { MemoryMapped, } -impl Into for QspiMode { - fn into(self) -> u8 { - match self { +impl From for u8 { + fn from(val: QspiMode) -> Self { + match val { QspiMode::IndirectWrite => 0b00, QspiMode::IndirectRead => 0b01, QspiMode::AutoPolling => 0b10, @@ -34,9 +34,9 @@ pub enum QspiWidth { QUAD, } -impl Into for QspiWidth { - fn into(self) -> u8 { - match self { +impl From for u8 { + fn from(val: QspiWidth) -> Self { + match val { QspiWidth::NONE => 0b00, QspiWidth::SING => 0b01, QspiWidth::DUAL => 0b10, @@ -55,9 +55,9 @@ pub enum FlashSelection { Flash2, } -impl Into for FlashSelection { - fn into(self) -> bool { - match self { +impl From for bool { + fn from(val: FlashSelection) -> Self { + match val { FlashSelection::Flash1 => false, FlashSelection::Flash2 => true, } @@ -94,9 +94,9 @@ pub enum MemorySize { Other(u8), } -impl Into for MemorySize { - fn into(self) -> u8 { - match self { +impl From for u8 { + fn from(val: MemorySize) -> Self { + match val { MemorySize::_1KiB => 9, MemorySize::_2KiB => 10, MemorySize::_4KiB => 11, @@ -138,9 +138,9 @@ pub enum AddressSize { _32bit, } -impl Into for AddressSize { - fn into(self) -> u8 { - match self { +impl From for u8 { + fn from(val: AddressSize) -> Self { + match val { AddressSize::_8Bit => 0b00, AddressSize::_16Bit => 0b01, AddressSize::_24bit => 0b10, @@ -163,9 +163,9 @@ pub enum ChipSelectHighTime { _8Cycle, } -impl Into for ChipSelectHighTime { - fn into(self) -> u8 { - match self { +impl From for u8 { + fn from(val: ChipSelectHighTime) -> Self { + match val { ChipSelectHighTime::_1Cycle => 0, ChipSelectHighTime::_2Cycle => 1, ChipSelectHighTime::_3Cycle => 2, @@ -216,9 +216,9 @@ pub enum FIFOThresholdLevel { _32Bytes, } -impl Into for FIFOThresholdLevel { - fn into(self) -> u8 { - match self { +impl From for u8 { + fn from(val: FIFOThresholdLevel) -> Self { + match val { FIFOThresholdLevel::_1Bytes => 0, FIFOThresholdLevel::_2Bytes => 1, FIFOThresholdLevel::_3Bytes => 2, @@ -293,9 +293,9 @@ pub enum DummyCycles { _31, } -impl Into for DummyCycles { - fn into(self) -> u8 { - match self { +impl From for u8 { + fn from(val: DummyCycles) -> Self { + match val { DummyCycles::_0 => 0, DummyCycles::_1 => 1, DummyCycles::_2 => 2, -- cgit From eba9ddc8055da13cb02c5732e30c37d2209cfa28 Mon Sep 17 00:00:00 2001 From: Corey Schuhen Date: Thu, 29 May 2025 20:47:33 +1000 Subject: Switch to SendDynamicSender for FDCAN. --- embassy-stm32/src/can/common.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/src/can/common.rs b/embassy-stm32/src/can/common.rs index e12111910..386d4467c 100644 --- a/embassy-stm32/src/can/common.rs +++ b/embassy-stm32/src/can/common.rs @@ -1,29 +1,29 @@ -use embassy_sync::channel::{DynamicReceiver, DynamicSender}; +use embassy_sync::channel::{SendDynamicReceiver, SendDynamicSender}; use super::enums::*; use super::frame::*; pub(crate) struct ClassicBufferedRxInner { - pub rx_sender: DynamicSender<'static, Result>, + pub rx_sender: SendDynamicSender<'static, Result>, } pub(crate) struct ClassicBufferedTxInner { - pub tx_receiver: DynamicReceiver<'static, Frame>, + pub tx_receiver: SendDynamicReceiver<'static, Frame>, } #[cfg(any(can_fdcan_v1, can_fdcan_h7))] pub(crate) struct FdBufferedRxInner { - pub rx_sender: DynamicSender<'static, Result>, + pub rx_sender: SendDynamicSender<'static, Result>, } #[cfg(any(can_fdcan_v1, can_fdcan_h7))] pub(crate) struct FdBufferedTxInner { - pub tx_receiver: DynamicReceiver<'static, FdFrame>, + pub tx_receiver: SendDynamicReceiver<'static, FdFrame>, } /// Sender that can be used for sending CAN frames. pub struct BufferedSender<'ch, FRAME> { - pub(crate) tx_buf: embassy_sync::channel::DynamicSender<'ch, FRAME>, + pub(crate) tx_buf: embassy_sync::channel::SendDynamicSender<'ch, FRAME>, pub(crate) waker: fn(), pub(crate) internal_operation: fn(InternalOperation), } @@ -70,7 +70,7 @@ pub type BufferedCanSender = BufferedSender<'static, Frame>; /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. pub struct BufferedReceiver<'ch, ENVELOPE> { - pub(crate) rx_buf: embassy_sync::channel::DynamicReceiver<'ch, Result>, + pub(crate) rx_buf: embassy_sync::channel::SendDynamicReceiver<'ch, Result>, pub(crate) internal_operation: fn(InternalOperation), } -- cgit From f5658d6833cb140296a0b6f25b7eb6d16f06c520 Mon Sep 17 00:00:00 2001 From: Corey Schuhen Date: Thu, 29 May 2025 20:48:40 +1000 Subject: Put State inside a critical section mutex of RefCell. This removes the unsound code that was giving out mut&. to State --- embassy-stm32/src/can/fdcan.rs | 246 ++++++++++++++++++----------------------- 1 file changed, 108 insertions(+), 138 deletions(-) diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index a7815f79b..4495280c4 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs @@ -52,36 +52,39 @@ impl interrupt::typelevel::Handler for IT0Interrup regs.ir().write(|w| w.set_tefn(true)); } - match &T::state().tx_mode { - TxMode::NonBuffered(waker) => waker.wake(), - TxMode::ClassicBuffered(buf) => { - if !T::registers().tx_queue_is_full() { - match buf.tx_receiver.try_receive() { - Ok(frame) => { - _ = T::registers().write(&frame); + T::info().state.lock(|s| { + let state = s.borrow_mut(); + match &state.tx_mode { + TxMode::NonBuffered(waker) => waker.wake(), + TxMode::ClassicBuffered(buf) => { + if !T::registers().tx_queue_is_full() { + match buf.tx_receiver.try_receive() { + Ok(frame) => { + _ = T::registers().write(&frame); + } + Err(_) => {} } - Err(_) => {} } } - } - TxMode::FdBuffered(buf) => { - if !T::registers().tx_queue_is_full() { - match buf.tx_receiver.try_receive() { - Ok(frame) => { - _ = T::registers().write(&frame); + TxMode::FdBuffered(buf) => { + if !T::registers().tx_queue_is_full() { + match buf.tx_receiver.try_receive() { + Ok(frame) => { + _ = T::registers().write(&frame); + } + Err(_) => {} } - Err(_) => {} } } } - } - if ir.rfn(0) { - T::state().rx_mode.on_interrupt::(0); - } - if ir.rfn(1) { - T::state().rx_mode.on_interrupt::(1); - } + if ir.rfn(0) { + state.rx_mode.on_interrupt::(0, state.ns_per_timer_tick); + } + if ir.rfn(1) { + state.rx_mode.on_interrupt::(1, state.ns_per_timer_tick); + } + }); if ir.bo() { regs.ir().write(|w| w.set_bo(true)); @@ -165,7 +168,6 @@ pub struct CanConfigurator<'d> { _phantom: PhantomData<&'d ()>, config: crate::can::fd::config::FdCanConfig, info: &'static Info, - state: &'static State, /// Reference to internals. properties: Properties, periph_clock: crate::time::Hertz, @@ -188,9 +190,10 @@ impl<'d> CanConfigurator<'d> { rcc::enable_and_reset::(); let info = T::info(); - let state = unsafe { T::mut_state() }; - state.tx_pin_port = Some(tx.pin_port()); - state.rx_pin_port = Some(rx.pin_port()); + T::info().state.lock(|s| { + s.borrow_mut().tx_pin_port = Some(tx.pin_port()); + s.borrow_mut().rx_pin_port = Some(rx.pin_port()); + }); (info.internal_operation)(InternalOperation::NotifySenderCreated); (info.internal_operation)(InternalOperation::NotifyReceiverCreated); @@ -209,7 +212,6 @@ impl<'d> CanConfigurator<'d> { _phantom: PhantomData, config, info, - state, properties: Properties::new(T::info()), periph_clock: T::frequency(), } @@ -261,12 +263,8 @@ impl<'d> CanConfigurator<'d> { /// Start in mode. pub fn start(self, mode: OperatingMode) -> Can<'d> { let ns_per_timer_tick = calc_ns_per_timer_tick(self.info, self.periph_clock, self.config.frame_transmit); - critical_section::with(|_| { - let state = self.state as *const State; - unsafe { - let mut_state = state as *mut State; - (*mut_state).ns_per_timer_tick = ns_per_timer_tick; - } + self.info.state.lock(|s| { + s.borrow_mut().ns_per_timer_tick = ns_per_timer_tick; }); self.info.regs.into_mode(self.config, mode); (self.info.internal_operation)(InternalOperation::NotifySenderCreated); @@ -275,7 +273,6 @@ impl<'d> CanConfigurator<'d> { _phantom: PhantomData, config: self.config, info: self.info, - state: self.state, _mode: mode, properties: Properties::new(self.info), } @@ -309,7 +306,6 @@ pub struct Can<'d> { _phantom: PhantomData<&'d ()>, config: crate::can::fd::config::FdCanConfig, info: &'static Info, - state: &'static State, _mode: OperatingMode, properties: Properties, } @@ -323,7 +319,9 @@ impl<'d> Can<'d> { /// Flush one of the TX mailboxes. pub async fn flush(&self, idx: usize) { poll_fn(|cx| { - self.state.tx_mode.register(cx.waker()); + self.info.state.lock(|s| { + s.borrow_mut().tx_mode.register(cx.waker()); + }); if idx > 3 { panic!("Bad mailbox"); @@ -343,12 +341,12 @@ impl<'d> Can<'d> { /// can be replaced, this call asynchronously waits for a frame to be successfully /// transmitted, then tries again. pub async fn write(&mut self, frame: &Frame) -> Option { - self.state.tx_mode.write(self.info, frame).await + TxMode::write(self.info, frame).await } /// Returns the next received message frame pub async fn read(&mut self) -> Result { - self.state.rx_mode.read_classic(self.info, self.state).await + RxMode::read_classic(self.info).await } /// Queues the message to be sent but exerts backpressure. If a lower-priority @@ -356,12 +354,12 @@ impl<'d> Can<'d> { /// can be replaced, this call asynchronously waits for a frame to be successfully /// transmitted, then tries again. pub async fn write_fd(&mut self, frame: &FdFrame) -> Option { - self.state.tx_mode.write_fd(self.info, frame).await + TxMode::write_fd(self.info, frame).await } /// Returns the next received message frame pub async fn read_fd(&mut self) -> Result { - self.state.rx_mode.read_fd(self.info, self.state).await + RxMode::read_fd(self.info).await } /// Split instance into separate portions: Tx(write), Rx(read), common properties @@ -372,14 +370,12 @@ impl<'d> Can<'d> { CanTx { _phantom: PhantomData, info: self.info, - state: self.state, config: self.config, _mode: self._mode, }, CanRx { _phantom: PhantomData, info: self.info, - state: self.state, _mode: self._mode, }, Properties { @@ -395,7 +391,6 @@ impl<'d> Can<'d> { _phantom: PhantomData, config: tx.config, info: tx.info, - state: tx.state, _mode: rx._mode, properties: Properties::new(tx.info), } @@ -407,7 +402,7 @@ impl<'d> Can<'d> { tx_buf: &'static mut TxBuf, rxb: &'static mut RxBuf, ) -> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> { - BufferedCan::new(self.info, self.state, self._mode, tx_buf, rxb) + BufferedCan::new(self.info, self._mode, tx_buf, rxb) } /// Return a buffered instance of driver with CAN FD support. User must supply Buffers @@ -416,7 +411,7 @@ impl<'d> Can<'d> { tx_buf: &'static mut TxFdBuf, rxb: &'static mut RxFdBuf, ) -> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> { - BufferedCanFd::new(self.info, self.state, self._mode, tx_buf, rxb) + BufferedCanFd::new(self.info, self._mode, tx_buf, rxb) } } @@ -437,7 +432,6 @@ pub type TxBuf = Channel { _phantom: PhantomData<&'d ()>, info: &'static Info, - state: &'static State, _mode: OperatingMode, tx_buf: &'static TxBuf, rx_buf: &'static RxBuf, @@ -447,7 +441,6 @@ pub struct BufferedCan<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> { fn new( info: &'static Info, - state: &'static State, _mode: OperatingMode, tx_buf: &'static TxBuf, rx_buf: &'static RxBuf, @@ -457,7 +450,6 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, BufferedCan { _phantom: PhantomData, info, - state, _mode, tx_buf, rx_buf, @@ -473,19 +465,15 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, fn setup(self) -> Self { // We don't want interrupts being processed while we change modes. - critical_section::with(|_| { + self.info.state.lock(|s| { let rx_inner = super::common::ClassicBufferedRxInner { rx_sender: self.rx_buf.sender().into(), }; let tx_inner = super::common::ClassicBufferedTxInner { tx_receiver: self.tx_buf.receiver().into(), }; - let state = self.state as *const State; - unsafe { - let mut_state = state as *mut State; - (*mut_state).rx_mode = RxMode::ClassicBuffered(rx_inner); - (*mut_state).tx_mode = TxMode::ClassicBuffered(tx_inner); - } + s.borrow_mut().rx_mode = RxMode::ClassicBuffered(rx_inner); + s.borrow_mut().tx_mode = TxMode::ClassicBuffered(tx_inner); }); self } @@ -545,7 +533,6 @@ pub type BufferedFdCanReceiver = super::common::BufferedReceiver<'static, FdEnve pub struct BufferedCanFd<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { _phantom: PhantomData<&'d ()>, info: &'static Info, - state: &'static State, _mode: OperatingMode, tx_buf: &'static TxFdBuf, rx_buf: &'static RxFdBuf, @@ -555,7 +542,6 @@ pub struct BufferedCanFd<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> { fn new( info: &'static Info, - state: &'static State, _mode: OperatingMode, tx_buf: &'static TxFdBuf, rx_buf: &'static RxFdBuf, @@ -565,7 +551,6 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<' BufferedCanFd { _phantom: PhantomData, info, - state, _mode, tx_buf, rx_buf, @@ -581,19 +566,15 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<' fn setup(self) -> Self { // We don't want interrupts being processed while we change modes. - critical_section::with(|_| { + self.info.state.lock(|s| { let rx_inner = super::common::FdBufferedRxInner { rx_sender: self.rx_buf.sender().into(), }; let tx_inner = super::common::FdBufferedTxInner { tx_receiver: self.tx_buf.receiver().into(), }; - let state = self.state as *const State; - unsafe { - let mut_state = state as *mut State; - (*mut_state).rx_mode = RxMode::FdBuffered(rx_inner); - (*mut_state).tx_mode = TxMode::FdBuffered(tx_inner); - } + s.borrow_mut().rx_mode = RxMode::FdBuffered(rx_inner); + s.borrow_mut().tx_mode = TxMode::FdBuffered(tx_inner); }); self } @@ -641,19 +622,18 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for Buffer pub struct CanRx<'d> { _phantom: PhantomData<&'d ()>, info: &'static Info, - state: &'static State, _mode: OperatingMode, } impl<'d> CanRx<'d> { /// Returns the next received message frame pub async fn read(&mut self) -> Result { - self.state.rx_mode.read_classic(&self.info, &self.state).await + RxMode::read_classic(&self.info).await } /// Returns the next received message frame pub async fn read_fd(&mut self) -> Result { - self.state.rx_mode.read_fd(&self.info, &self.state).await + RxMode::read_fd(&self.info).await } } @@ -667,7 +647,6 @@ impl<'d> Drop for CanRx<'d> { pub struct CanTx<'d> { _phantom: PhantomData<&'d ()>, info: &'static Info, - state: &'static State, config: crate::can::fd::config::FdCanConfig, _mode: OperatingMode, } @@ -678,7 +657,7 @@ impl<'c, 'd> CanTx<'d> { /// can be replaced, this call asynchronously waits for a frame to be successfully /// transmitted, then tries again. pub async fn write(&mut self, frame: &Frame) -> Option { - self.state.tx_mode.write(self.info, frame).await + TxMode::write(self.info, frame).await } /// Queues the message to be sent but exerts backpressure. If a lower-priority @@ -686,7 +665,7 @@ impl<'c, 'd> CanTx<'d> { /// can be replaced, this call asynchronously waits for a frame to be successfully /// transmitted, then tries again. pub async fn write_fd(&mut self, frame: &FdFrame) -> Option { - self.state.tx_mode.write_fd(self.info, frame).await + TxMode::write_fd(self.info, frame).await } } @@ -712,19 +691,19 @@ impl RxMode { } } - fn on_interrupt(&self, fifonr: usize) { + fn on_interrupt(&self, fifonr: usize, ns_per_timer_tick: u64) { T::registers().regs.ir().write(|w| w.set_rfn(fifonr, true)); match self { RxMode::NonBuffered(waker) => { waker.wake(); } RxMode::ClassicBuffered(buf) => { - if let Some(result) = self.try_read::() { + if let Some(result) = self.try_read::(ns_per_timer_tick) { let _ = buf.rx_sender.try_send(result); } } RxMode::FdBuffered(buf) => { - if let Some(result) = self.try_read_fd::() { + if let Some(result) = self.try_read_fd::(ns_per_timer_tick) { let _ = buf.rx_sender.try_send(result); } } @@ -732,12 +711,12 @@ impl RxMode { } //async fn read_classic(&self) -> Result { - fn try_read(&self) -> Option> { + fn try_read(&self, ns_per_timer_tick: u64) -> Option> { if let Some((frame, ts)) = T::registers().read(0) { - let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); + let ts = T::calc_timestamp(ns_per_timer_tick, ts); Some(Ok(Envelope { ts, frame })) } else if let Some((frame, ts)) = T::registers().read(1) { - let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); + let ts = T::calc_timestamp(ns_per_timer_tick, ts); Some(Ok(Envelope { ts, frame })) } else if let Some(err) = T::registers().curr_error() { // TODO: this is probably wrong @@ -747,12 +726,12 @@ impl RxMode { } } - fn try_read_fd(&self) -> Option> { + fn try_read_fd(&self, ns_per_timer_tick: u64) -> Option> { if let Some((frame, ts)) = T::registers().read(0) { - let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); + let ts = T::calc_timestamp(ns_per_timer_tick, ts); Some(Ok(FdEnvelope { ts, frame })) } else if let Some((frame, ts)) = T::registers().read(1) { - let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); + let ts = T::calc_timestamp(ns_per_timer_tick, ts); Some(Ok(FdEnvelope { ts, frame })) } else if let Some(err) = T::registers().curr_error() { // TODO: this is probably wrong @@ -762,16 +741,12 @@ impl RxMode { } } - fn read( - &self, - info: &'static Info, - state: &'static State, - ) -> Option> { + fn read(info: &'static Info, ns_per_timer_tick: u64) -> Option> { if let Some((msg, ts)) = info.regs.read(0) { - let ts = info.calc_timestamp(state.ns_per_timer_tick, ts); + let ts = info.calc_timestamp(ns_per_timer_tick, ts); Some(Ok((msg, ts))) } else if let Some((msg, ts)) = info.regs.read(1) { - let ts = info.calc_timestamp(state.ns_per_timer_tick, ts); + let ts = info.calc_timestamp(ns_per_timer_tick, ts); Some(Ok((msg, ts))) } else if let Some(err) = info.regs.curr_error() { // TODO: this is probably wrong @@ -781,16 +756,15 @@ impl RxMode { } } - async fn read_async( - &self, - info: &'static Info, - state: &'static State, - ) -> Result<(F, Timestamp), BusError> { - //let _ = self.read::(info, state); + async fn read_async(info: &'static Info) -> Result<(F, Timestamp), BusError> { poll_fn(move |cx| { - state.err_waker.register(cx.waker()); - self.register(cx.waker()); - match self.read::<_>(info, state) { + let ns_per_timer_tick = info.state.lock(|s| { + let state = s.borrow_mut(); + state.err_waker.register(cx.waker()); + state.rx_mode.register(cx.waker()); + state.ns_per_timer_tick + }); + match RxMode::read::<_>(info, ns_per_timer_tick) { Some(result) => Poll::Ready(result), None => Poll::Pending, } @@ -798,15 +772,15 @@ impl RxMode { .await } - async fn read_classic(&self, info: &'static Info, state: &'static State) -> Result { - match self.read_async::<_>(info, state).await { + async fn read_classic(info: &'static Info) -> Result { + match RxMode::read_async::<_>(info).await { Ok((frame, ts)) => Ok(Envelope { ts, frame }), Err(e) => Err(e), } } - async fn read_fd(&self, info: &'static Info, state: &'static State) -> Result { - match self.read_async::<_>(info, state).await { + async fn read_fd(info: &'static Info) -> Result { + match RxMode::read_async::<_>(info).await { Ok((frame, ts)) => Ok(FdEnvelope { ts, frame }), Err(e) => Err(e), } @@ -835,9 +809,11 @@ impl TxMode { /// frame is dropped from the mailbox, it is returned. If no lower-priority frames /// can be replaced, this call asynchronously waits for a frame to be successfully /// transmitted, then tries again. - async fn write_generic(&self, info: &'static Info, frame: &F) -> Option { + async fn write_generic(info: &'static Info, frame: &F) -> Option { poll_fn(|cx| { - self.register(cx.waker()); + info.state.lock(|s| { + s.borrow_mut().tx_mode.register(cx.waker()); + }); if let Ok(dropped) = info.regs.write(frame) { return Poll::Ready(dropped); @@ -854,16 +830,16 @@ impl TxMode { /// frame is dropped from the mailbox, it is returned. If no lower-priority frames /// can be replaced, this call asynchronously waits for a frame to be successfully /// transmitted, then tries again. - async fn write(&self, info: &'static Info, frame: &Frame) -> Option { - self.write_generic::<_>(info, frame).await + async fn write(info: &'static Info, frame: &Frame) -> Option { + TxMode::write_generic::<_>(info, frame).await } /// Queues the message to be sent but exerts backpressure. If a lower-priority /// frame is dropped from the mailbox, it is returned. If no lower-priority frames /// can be replaced, this call asynchronously waits for a frame to be successfully /// transmitted, then tries again. - async fn write_fd(&self, info: &'static Info, frame: &FdFrame) -> Option { - self.write_generic::<_>(info, frame).await + async fn write_fd(info: &'static Info, frame: &FdFrame) -> Option { + TxMode::write_generic::<_>(info, frame).await } } @@ -961,12 +937,14 @@ impl State { } } +type SharedState = embassy_sync::blocking_mutex::Mutex>; struct Info { regs: Registers, interrupt0: crate::interrupt::Interrupt, _interrupt1: crate::interrupt::Interrupt, tx_waker: fn(), internal_operation: fn(InternalOperation), + state: SharedState, } impl Info { @@ -993,8 +971,6 @@ trait SealedInstance { fn info() -> &'static Info; fn registers() -> crate::can::fd::peripheral::Registers; - fn state() -> &'static State; - unsafe fn mut_state() -> &'static mut State; fn internal_operation(val: InternalOperation); fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp; } @@ -1019,32 +995,30 @@ macro_rules! impl_fdcan { const MSG_RAM_OFFSET: usize = $msg_ram_offset; fn internal_operation(val: InternalOperation) { - critical_section::with(|_| { - //let state = self.state as *const State; - unsafe { - //let mut_state = state as *mut State; - let mut_state = peripherals::$inst::mut_state(); - match val { - InternalOperation::NotifySenderCreated => { - mut_state.sender_instance_count += 1; - } - InternalOperation::NotifySenderDestroyed => { - mut_state.sender_instance_count -= 1; - if ( 0 == mut_state.sender_instance_count) { - (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); - } - } - InternalOperation::NotifyReceiverCreated => { - mut_state.receiver_instance_count += 1; + peripherals::$inst::info().state.lock(|s| { + let mut mut_state = s.borrow_mut(); + match val { + InternalOperation::NotifySenderCreated => { + mut_state.sender_instance_count += 1; + } + InternalOperation::NotifySenderDestroyed => { + mut_state.sender_instance_count -= 1; + if ( 0 == mut_state.sender_instance_count) { + (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); } - InternalOperation::NotifyReceiverDestroyed => { - mut_state.receiver_instance_count -= 1; - if ( 0 == mut_state.receiver_instance_count) { - (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); - } + } + InternalOperation::NotifyReceiverCreated => { + mut_state.receiver_instance_count += 1; + } + InternalOperation::NotifyReceiverDestroyed => { + mut_state.receiver_instance_count -= 1; + if ( 0 == mut_state.receiver_instance_count) { + (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); } } - if mut_state.sender_instance_count == 0 && mut_state.receiver_instance_count == 0 { + } + if mut_state.sender_instance_count == 0 && mut_state.receiver_instance_count == 0 { + unsafe { let tx_pin = crate::gpio::AnyPin::steal(mut_state.tx_pin_port.unwrap()); tx_pin.set_as_disconnected(); let rx_pin = crate::gpio::AnyPin::steal(mut_state.rx_pin_port.unwrap()); @@ -1054,26 +1028,22 @@ macro_rules! impl_fdcan { } }); } + fn info() -> &'static Info { + static INFO: Info = Info { regs: Registers{regs: crate::pac::$inst, msgram: crate::pac::$msg_ram_inst, msg_ram_offset: $msg_ram_offset}, interrupt0: crate::_generated::peripheral_interrupts::$inst::IT0::IRQ, _interrupt1: crate::_generated::peripheral_interrupts::$inst::IT1::IRQ, tx_waker: crate::_generated::peripheral_interrupts::$inst::IT0::pend, internal_operation: peripherals::$inst::internal_operation, + state: embassy_sync::blocking_mutex::Mutex::new(core::cell::RefCell::new(State::new())), }; &INFO } fn registers() -> Registers { Registers{regs: crate::pac::$inst, msgram: crate::pac::$msg_ram_inst, msg_ram_offset: Self::MSG_RAM_OFFSET} } - unsafe fn mut_state() -> &'static mut State { - static mut STATE: State = State::new(); - &mut *core::ptr::addr_of_mut!(STATE) - } - fn state() -> &'static State { - unsafe { peripherals::$inst::mut_state() } - } #[cfg(feature = "time")] fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp { -- cgit From 010744802fc4a1fda51f259cce874aac7294a79e Mon Sep 17 00:00:00 2001 From: Corey Schuhen Date: Sat, 31 May 2025 09:09:12 +1000 Subject: Remove duplicate calc_timestamp and move to 'Registers' struct. --- embassy-stm32/src/can/fd/peripheral.rs | 17 ++++++++++++ embassy-stm32/src/can/fdcan.rs | 49 +++++----------------------------- 2 files changed, 23 insertions(+), 43 deletions(-) diff --git a/embassy-stm32/src/can/fd/peripheral.rs b/embassy-stm32/src/can/fd/peripheral.rs index 4873ee444..0a22f2c91 100644 --- a/embassy-stm32/src/can/fd/peripheral.rs +++ b/embassy-stm32/src/can/fd/peripheral.rs @@ -71,6 +71,23 @@ impl Registers { } } + #[cfg(feature = "time")] + pub fn calc_timestamp(&self, ns_per_timer_tick: u64, ts_val: u16) -> Timestamp { + let now_embassy = embassy_time::Instant::now(); + if ns_per_timer_tick == 0 { + return now_embassy; + } + let cantime = { self.regs.tscv().read().tsc() }; + let delta = cantime.overflowing_sub(ts_val).0 as u64; + let ns = ns_per_timer_tick * delta as u64; + now_embassy - embassy_time::Duration::from_nanos(ns) + } + + #[cfg(not(feature = "time"))] + pub fn calc_timestamp(&self, _ns_per_timer_tick: u64, ts_val: u16) -> Timestamp { + ts_val + } + pub fn put_tx_frame(&self, bufidx: usize, header: &Header, buffer: &[u8]) { let mailbox = self.tx_buffer_element(bufidx); mailbox.reset(); diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index 4495280c4..97d22315a 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs @@ -713,10 +713,10 @@ impl RxMode { //async fn read_classic(&self) -> Result { fn try_read(&self, ns_per_timer_tick: u64) -> Option> { if let Some((frame, ts)) = T::registers().read(0) { - let ts = T::calc_timestamp(ns_per_timer_tick, ts); + let ts = T::registers().calc_timestamp(ns_per_timer_tick, ts); Some(Ok(Envelope { ts, frame })) } else if let Some((frame, ts)) = T::registers().read(1) { - let ts = T::calc_timestamp(ns_per_timer_tick, ts); + let ts = T::registers().calc_timestamp(ns_per_timer_tick, ts); Some(Ok(Envelope { ts, frame })) } else if let Some(err) = T::registers().curr_error() { // TODO: this is probably wrong @@ -728,10 +728,10 @@ impl RxMode { fn try_read_fd(&self, ns_per_timer_tick: u64) -> Option> { if let Some((frame, ts)) = T::registers().read(0) { - let ts = T::calc_timestamp(ns_per_timer_tick, ts); + let ts = T::registers().calc_timestamp(ns_per_timer_tick, ts); Some(Ok(FdEnvelope { ts, frame })) } else if let Some((frame, ts)) = T::registers().read(1) { - let ts = T::calc_timestamp(ns_per_timer_tick, ts); + let ts = T::registers().calc_timestamp(ns_per_timer_tick, ts); Some(Ok(FdEnvelope { ts, frame })) } else if let Some(err) = T::registers().curr_error() { // TODO: this is probably wrong @@ -743,10 +743,10 @@ impl RxMode { fn read(info: &'static Info, ns_per_timer_tick: u64) -> Option> { if let Some((msg, ts)) = info.regs.read(0) { - let ts = info.calc_timestamp(ns_per_timer_tick, ts); + let ts = info.regs.calc_timestamp(ns_per_timer_tick, ts); Some(Ok((msg, ts))) } else if let Some((msg, ts)) = info.regs.read(1) { - let ts = info.calc_timestamp(ns_per_timer_tick, ts); + let ts = info.regs.calc_timestamp(ns_per_timer_tick, ts); Some(Ok((msg, ts))) } else if let Some(err) = info.regs.curr_error() { // TODO: this is probably wrong @@ -947,32 +947,12 @@ struct Info { state: SharedState, } -impl Info { - #[cfg(feature = "time")] - fn calc_timestamp(&self, ns_per_timer_tick: u64, ts_val: u16) -> Timestamp { - let now_embassy = embassy_time::Instant::now(); - if ns_per_timer_tick == 0 { - return now_embassy; - } - let cantime = { self.regs.regs.tscv().read().tsc() }; - let delta = cantime.overflowing_sub(ts_val).0 as u64; - let ns = ns_per_timer_tick * delta as u64; - now_embassy - embassy_time::Duration::from_nanos(ns) - } - - #[cfg(not(feature = "time"))] - fn calc_timestamp(&self, _ns_per_timer_tick: u64, ts_val: u16) -> Timestamp { - ts_val - } -} - trait SealedInstance { const MSG_RAM_OFFSET: usize; fn info() -> &'static Info; fn registers() -> crate::can::fd::peripheral::Registers; fn internal_operation(val: InternalOperation); - fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp; } /// Instance trait @@ -1045,23 +1025,6 @@ macro_rules! impl_fdcan { Registers{regs: crate::pac::$inst, msgram: crate::pac::$msg_ram_inst, msg_ram_offset: Self::MSG_RAM_OFFSET} } - #[cfg(feature = "time")] - fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp { - let now_embassy = embassy_time::Instant::now(); - if ns_per_timer_tick == 0 { - return now_embassy; - } - let cantime = { Self::registers().regs.tscv().read().tsc() }; - let delta = cantime.overflowing_sub(ts_val).0 as u64; - let ns = ns_per_timer_tick * delta as u64; - now_embassy - embassy_time::Duration::from_nanos(ns) - } - - #[cfg(not(feature = "time"))] - fn calc_timestamp(_ns_per_timer_tick: u64, ts_val: u16) -> Timestamp { - ts_val - } - } #[allow(non_snake_case)] -- cgit From 69abc42077e6de4453d422330a9a07407a36f218 Mon Sep 17 00:00:00 2001 From: 9names <60134748+9names@users.noreply.github.com> Date: Sun, 1 Jun 2025 00:08:09 +1000 Subject: doc: add high-level embassy-boot a-b info --- docs/pages/bootloader.adoc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/pages/bootloader.adoc b/docs/pages/bootloader.adoc index 53f85d995..b0f0331aa 100644 --- a/docs/pages/bootloader.adoc +++ b/docs/pages/bootloader.adoc @@ -2,6 +2,13 @@ `embassy-boot` a lightweight bootloader supporting firmware application upgrades in a power-fail-safe way, with trial boots and rollbacks. +The update method used is referred to as an A/B partition update scheme. + +With a general-purpose OS, A/B partition update is accomplished by directly booting either the A or B partition depending on the update state. +To accomplish the same goal in a way that is portable across all microcontrollers, `embassy-boot` swaps data page by page (in both directions) between the DFU and the Active partition when a firmware update is triggered. + +Because the original Active application is moved into the DFU partition during this update, the operation can be reversed if the update is interrupted or the new firmware does not flag that it booted successfully. + +See the design section for more details on how this is implemented. + The bootloader can be used either as a library or be flashed directly if you are happy with the default configuration and capabilities. By design, the bootloader does not provide any network capabilities. Networking capabilities for fetching new firmware can be provided by the user application, using the bootloader as a library for updating the firmware, or by using the bootloader as a library and adding this capability yourself. -- cgit From 0d83fbbb57cf17186a1b8f40f57ef7a35b3e9627 Mon Sep 17 00:00:00 2001 From: Matthew Tran <0e4ef622@gmail.com> Date: Sun, 1 Jun 2025 10:32:24 -0500 Subject: Add diagnostic::on_unimplemented for nightly --- embassy-executor/src/lib.rs | 4 ++++ embassy-executor/tests/ui/bad_return_impl_trait_nightly.stderr | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index e26e8ee7d..e174a0594 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -233,6 +233,10 @@ pub mod _export { #[doc(hidden)] #[cfg(feature = "nightly")] pub mod _export { + #[diagnostic::on_unimplemented( + message = "task futures must resolve to `()` or `!`", + note = "use `async fn` or change the return type to `impl Future`" + )] pub trait TaskReturnValue {} impl TaskReturnValue for () {} impl TaskReturnValue for Never {} diff --git a/embassy-executor/tests/ui/bad_return_impl_trait_nightly.stderr b/embassy-executor/tests/ui/bad_return_impl_trait_nightly.stderr index 21e20d5c0..a51251bb8 100644 --- a/embassy-executor/tests/ui/bad_return_impl_trait_nightly.stderr +++ b/embassy-executor/tests/ui/bad_return_impl_trait_nightly.stderr @@ -1,9 +1,10 @@ -error[E0277]: the trait bound `u32: TaskReturnValue` is not satisfied +error[E0277]: task futures must resolve to `()` or `!` --> tests/ui/bad_return_impl_trait_nightly.rs:4:1 | 4 | #[embassy_executor::task] | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskReturnValue` is not implemented for `u32` | + = note: use `async fn` or change the return type to `impl Future` = help: the following other types implement trait `TaskReturnValue`: () ! as _export::HasOutput>::Output -- cgit From 3cef4f0c04a1f0f56c84950d8fd408979299fa50 Mon Sep 17 00:00:00 2001 From: Matthew Tran <0e4ef622@gmail.com> Date: Sun, 1 Jun 2025 11:42:33 -0500 Subject: Update tests --- embassy-executor/Cargo.toml | 1 + embassy-executor/tests/ui.rs | 13 +- .../tests/ui/bad_return_impl_future.rs | 9 ++ .../tests/ui/bad_return_impl_future.stderr | 120 ++++++++++++++++++ .../tests/ui/bad_return_impl_future_nightly.rs | 9 ++ .../tests/ui/bad_return_impl_future_nightly.stderr | 10 ++ embassy-executor/tests/ui/bad_return_impl_trait.rs | 9 -- .../tests/ui/bad_return_impl_trait.stderr | 120 ------------------ .../tests/ui/bad_return_impl_trait_nightly.rs | 9 -- .../tests/ui/bad_return_impl_trait_nightly.stderr | 10 -- embassy-executor/tests/ui/return_impl_send.rs | 6 + embassy-executor/tests/ui/return_impl_send.stderr | 137 +++++++++++++++++++++ .../tests/ui/return_impl_send_nightly.rs | 6 + .../tests/ui/return_impl_send_nightly.stderr | 10 ++ 14 files changed, 317 insertions(+), 152 deletions(-) create mode 100644 embassy-executor/tests/ui/bad_return_impl_future.rs create mode 100644 embassy-executor/tests/ui/bad_return_impl_future.stderr create mode 100644 embassy-executor/tests/ui/bad_return_impl_future_nightly.rs create mode 100644 embassy-executor/tests/ui/bad_return_impl_future_nightly.stderr delete mode 100644 embassy-executor/tests/ui/bad_return_impl_trait.rs delete mode 100644 embassy-executor/tests/ui/bad_return_impl_trait.stderr delete mode 100644 embassy-executor/tests/ui/bad_return_impl_trait_nightly.rs delete mode 100644 embassy-executor/tests/ui/bad_return_impl_trait_nightly.stderr create mode 100644 embassy-executor/tests/ui/return_impl_send.rs create mode 100644 embassy-executor/tests/ui/return_impl_send.stderr create mode 100644 embassy-executor/tests/ui/return_impl_send_nightly.rs create mode 100644 embassy-executor/tests/ui/return_impl_send_nightly.stderr diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index f014ccf30..2dbf2c29a 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -59,6 +59,7 @@ avr-device = { version = "0.7.0", optional = true } critical-section = { version = "1.1", features = ["std"] } trybuild = "1.0" embassy-sync = { path = "../embassy-sync" } +rustversion = "1.0.21" [features] diff --git a/embassy-executor/tests/ui.rs b/embassy-executor/tests/ui.rs index ed8228e27..c4a1a601c 100644 --- a/embassy-executor/tests/ui.rs +++ b/embassy-executor/tests/ui.rs @@ -17,10 +17,15 @@ fn ui() { t.compile_fail("tests/ui/nonstatic_struct_elided.rs"); t.compile_fail("tests/ui/nonstatic_struct_generic.rs"); t.compile_fail("tests/ui/not_async.rs"); - // #[cfg(not(feature = "nightly"))] // output differs on stable and nightly - // t.compile_fail("tests/ui/bad_return_impl_trait.rs"); - #[cfg(feature = "nightly")] - t.compile_fail("tests/ui/bad_return_impl_trait_nightly.rs"); + if rustversion::cfg!(stable) { + // output is slightly different on nightly + t.compile_fail("tests/ui/bad_return_impl_future.rs"); + t.compile_fail("tests/ui/return_impl_send.rs"); + } + if cfg!(feature = "nightly") { + t.compile_fail("tests/ui/bad_return_impl_future_nightly.rs"); + t.compile_fail("tests/ui/return_impl_send_nightly.rs"); + } t.compile_fail("tests/ui/self_ref.rs"); t.compile_fail("tests/ui/self.rs"); t.compile_fail("tests/ui/type_error.rs"); diff --git a/embassy-executor/tests/ui/bad_return_impl_future.rs b/embassy-executor/tests/ui/bad_return_impl_future.rs new file mode 100644 index 000000000..baaa7dc5a --- /dev/null +++ b/embassy-executor/tests/ui/bad_return_impl_future.rs @@ -0,0 +1,9 @@ +#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] +use core::future::Future; + +#[embassy_executor::task] +fn task() -> impl Future { + async { 5 } +} + +fn main() {} diff --git a/embassy-executor/tests/ui/bad_return_impl_future.stderr b/embassy-executor/tests/ui/bad_return_impl_future.stderr new file mode 100644 index 000000000..2980fd18b --- /dev/null +++ b/embassy-executor/tests/ui/bad_return_impl_future.stderr @@ -0,0 +1,120 @@ +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/bad_return_impl_future.rs:5:4 + | +4 | #[embassy_executor::task] + | ------------------------- required by a bound introduced by this call +5 | fn task() -> impl Future { + | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_size` + --> src/lib.rs + | + | pub const fn task_pool_size(_: F) -> usize + | -------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^ required by this bound in `task_pool_size` + +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/bad_return_impl_future.rs:4:1 + | +4 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_size` + --> src/lib.rs + | + | pub const fn task_pool_size(_: F) -> usize + | -------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_size` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/bad_return_impl_future.rs:5:4 + | +4 | #[embassy_executor::task] + | ------------------------- required by a bound introduced by this call +5 | fn task() -> impl Future { + | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_align` + --> src/lib.rs + | + | pub const fn task_pool_align(_: F) -> usize + | --------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^ required by this bound in `task_pool_align` + +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/bad_return_impl_future.rs:4:1 + | +4 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_align` + --> src/lib.rs + | + | pub const fn task_pool_align(_: F) -> usize + | --------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_align` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/bad_return_impl_future.rs:5:4 + | +4 | #[embassy_executor::task] + | ------------------------- required by a bound introduced by this call +5 | fn task() -> impl Future { + | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_new` + --> src/lib.rs + | + | pub const fn task_pool_new(_: F) -> TaskPool + | ------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^ required by this bound in `task_pool_new` + +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/bad_return_impl_future.rs:4:1 + | +4 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_new` + --> src/lib.rs + | + | pub const fn task_pool_new(_: F) -> TaskPool + | ------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_new` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/bad_return_impl_future.rs:5:4 + | +4 | #[embassy_executor::task] + | ------------------------- required by a bound introduced by this call +5 | fn task() -> impl Future { + | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `__task_pool_get` + --> tests/ui/bad_return_impl_future.rs:4:1 + | +4 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `__task_pool_get` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/embassy-executor/tests/ui/bad_return_impl_future_nightly.rs b/embassy-executor/tests/ui/bad_return_impl_future_nightly.rs new file mode 100644 index 000000000..baaa7dc5a --- /dev/null +++ b/embassy-executor/tests/ui/bad_return_impl_future_nightly.rs @@ -0,0 +1,9 @@ +#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] +use core::future::Future; + +#[embassy_executor::task] +fn task() -> impl Future { + async { 5 } +} + +fn main() {} diff --git a/embassy-executor/tests/ui/bad_return_impl_future_nightly.stderr b/embassy-executor/tests/ui/bad_return_impl_future_nightly.stderr new file mode 100644 index 000000000..73ceb989d --- /dev/null +++ b/embassy-executor/tests/ui/bad_return_impl_future_nightly.stderr @@ -0,0 +1,10 @@ +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/bad_return_impl_future_nightly.rs:4:1 + | +4 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskReturnValue` is not implemented for `u32` + | + = note: use `async fn` or change the return type to `impl Future` + = help: the following other types implement trait `TaskReturnValue`: + () + ! as _export::HasOutput>::Output diff --git a/embassy-executor/tests/ui/bad_return_impl_trait.rs b/embassy-executor/tests/ui/bad_return_impl_trait.rs deleted file mode 100644 index baaa7dc5a..000000000 --- a/embassy-executor/tests/ui/bad_return_impl_trait.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] -use core::future::Future; - -#[embassy_executor::task] -fn task() -> impl Future { - async { 5 } -} - -fn main() {} diff --git a/embassy-executor/tests/ui/bad_return_impl_trait.stderr b/embassy-executor/tests/ui/bad_return_impl_trait.stderr deleted file mode 100644 index 9e2df353e..000000000 --- a/embassy-executor/tests/ui/bad_return_impl_trait.stderr +++ /dev/null @@ -1,120 +0,0 @@ -error[E0277]: task function futures must resolve to `()` - --> tests/ui/bad_return_impl_trait.rs:5:4 - | -4 | #[embassy_executor::task] - | ------------------------- required by a bound introduced by this call -5 | fn task() -> impl Future { - | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` - | - = note: use `async fn` or change the return type to `impl Future` -note: required by a bound in `task_pool_size` - --> src/lib.rs - | - | pub const fn task_pool_size(_: F) -> usize - | -------------- required by a bound in this function - | where - | F: TaskFn, - | ^^^^^^^^^ required by this bound in `task_pool_size` - -error[E0277]: task function futures must resolve to `()` - --> tests/ui/bad_return_impl_trait.rs:4:1 - | -4 | #[embassy_executor::task] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` - | - = note: use `async fn` or change the return type to `impl Future` -note: required by a bound in `task_pool_size` - --> src/lib.rs - | - | pub const fn task_pool_size(_: F) -> usize - | -------------- required by a bound in this function - | where - | F: TaskFn, - | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_size` - = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: task function futures must resolve to `()` - --> tests/ui/bad_return_impl_trait.rs:5:4 - | -4 | #[embassy_executor::task] - | ------------------------- required by a bound introduced by this call -5 | fn task() -> impl Future { - | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` - | - = note: use `async fn` or change the return type to `impl Future` -note: required by a bound in `task_pool_align` - --> src/lib.rs - | - | pub const fn task_pool_align(_: F) -> usize - | --------------- required by a bound in this function - | where - | F: TaskFn, - | ^^^^^^^^^ required by this bound in `task_pool_align` - -error[E0277]: task function futures must resolve to `()` - --> tests/ui/bad_return_impl_trait.rs:4:1 - | -4 | #[embassy_executor::task] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` - | - = note: use `async fn` or change the return type to `impl Future` -note: required by a bound in `task_pool_align` - --> src/lib.rs - | - | pub const fn task_pool_align(_: F) -> usize - | --------------- required by a bound in this function - | where - | F: TaskFn, - | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_align` - = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: task function futures must resolve to `()` - --> tests/ui/bad_return_impl_trait.rs:5:4 - | -4 | #[embassy_executor::task] - | ------------------------- required by a bound introduced by this call -5 | fn task() -> impl Future { - | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` - | - = note: use `async fn` or change the return type to `impl Future` -note: required by a bound in `task_pool_new` - --> src/lib.rs - | - | pub const fn task_pool_new(_: F) -> TaskPool - | ------------- required by a bound in this function - | where - | F: TaskFn, - | ^^^^^^^^^ required by this bound in `task_pool_new` - -error[E0277]: task function futures must resolve to `()` - --> tests/ui/bad_return_impl_trait.rs:4:1 - | -4 | #[embassy_executor::task] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` - | - = note: use `async fn` or change the return type to `impl Future` -note: required by a bound in `task_pool_new` - --> src/lib.rs - | - | pub const fn task_pool_new(_: F) -> TaskPool - | ------------- required by a bound in this function - | where - | F: TaskFn, - | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_new` - = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: task function futures must resolve to `()` - --> tests/ui/bad_return_impl_trait.rs:5:4 - | -4 | #[embassy_executor::task] - | ------------------------- required by a bound introduced by this call -5 | fn task() -> impl Future { - | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` - | - = note: use `async fn` or change the return type to `impl Future` -note: required by a bound in `__task_pool_get` - --> tests/ui/bad_return_impl_trait.rs:4:1 - | -4 | #[embassy_executor::task] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `__task_pool_get` - = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/embassy-executor/tests/ui/bad_return_impl_trait_nightly.rs b/embassy-executor/tests/ui/bad_return_impl_trait_nightly.rs deleted file mode 100644 index baaa7dc5a..000000000 --- a/embassy-executor/tests/ui/bad_return_impl_trait_nightly.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] -use core::future::Future; - -#[embassy_executor::task] -fn task() -> impl Future { - async { 5 } -} - -fn main() {} diff --git a/embassy-executor/tests/ui/bad_return_impl_trait_nightly.stderr b/embassy-executor/tests/ui/bad_return_impl_trait_nightly.stderr deleted file mode 100644 index a51251bb8..000000000 --- a/embassy-executor/tests/ui/bad_return_impl_trait_nightly.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error[E0277]: task futures must resolve to `()` or `!` - --> tests/ui/bad_return_impl_trait_nightly.rs:4:1 - | -4 | #[embassy_executor::task] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskReturnValue` is not implemented for `u32` - | - = note: use `async fn` or change the return type to `impl Future` - = help: the following other types implement trait `TaskReturnValue`: - () - ! as _export::HasOutput>::Output diff --git a/embassy-executor/tests/ui/return_impl_send.rs b/embassy-executor/tests/ui/return_impl_send.rs new file mode 100644 index 000000000..6ddb0e722 --- /dev/null +++ b/embassy-executor/tests/ui/return_impl_send.rs @@ -0,0 +1,6 @@ +#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] + +#[embassy_executor::task] +fn task() -> impl Send {} + +fn main() {} diff --git a/embassy-executor/tests/ui/return_impl_send.stderr b/embassy-executor/tests/ui/return_impl_send.stderr new file mode 100644 index 000000000..7e3e468b8 --- /dev/null +++ b/embassy-executor/tests/ui/return_impl_send.stderr @@ -0,0 +1,137 @@ +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/return_impl_send.rs:4:4 + | +3 | #[embassy_executor::task] + | ------------------------- required by a bound introduced by this call +4 | fn task() -> impl Send {} + | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Send {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_size` + --> src/lib.rs + | + | pub const fn task_pool_size(_: F) -> usize + | -------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^ required by this bound in `task_pool_size` + +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/return_impl_send.rs:3:1 + | +3 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Send {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_size` + --> src/lib.rs + | + | pub const fn task_pool_size(_: F) -> usize + | -------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_size` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/return_impl_send.rs:4:4 + | +3 | #[embassy_executor::task] + | ------------------------- required by a bound introduced by this call +4 | fn task() -> impl Send {} + | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Send {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_align` + --> src/lib.rs + | + | pub const fn task_pool_align(_: F) -> usize + | --------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^ required by this bound in `task_pool_align` + +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/return_impl_send.rs:3:1 + | +3 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Send {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_align` + --> src/lib.rs + | + | pub const fn task_pool_align(_: F) -> usize + | --------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_align` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/return_impl_send.rs:4:4 + | +3 | #[embassy_executor::task] + | ------------------------- required by a bound introduced by this call +4 | fn task() -> impl Send {} + | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Send {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_new` + --> src/lib.rs + | + | pub const fn task_pool_new(_: F) -> TaskPool + | ------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^ required by this bound in `task_pool_new` + +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/return_impl_send.rs:3:1 + | +3 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Send {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_new` + --> src/lib.rs + | + | pub const fn task_pool_new(_: F) -> TaskPool + | ------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_new` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/return_impl_send.rs:4:4 + | +3 | #[embassy_executor::task] + | ------------------------- required by a bound introduced by this call +4 | fn task() -> impl Send {} + | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Send {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `__task_pool_get` + --> tests/ui/return_impl_send.rs:3:1 + | +3 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `__task_pool_get` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `impl Send` is not a future + --> tests/ui/return_impl_send.rs:3:1 + | +3 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `impl Send` is not a future + | + = help: the trait `Future` is not implemented for `impl Send` +note: required by a bound in `TaskPool::::_spawn_async_fn` + --> src/raw/mod.rs + | + | impl TaskPool { + | ^^^^^^ required by this bound in `TaskPool::::_spawn_async_fn` +... + | pub unsafe fn _spawn_async_fn(&'static self, future: FutFn) -> SpawnToken + | --------------- required by a bound in this associated function + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/embassy-executor/tests/ui/return_impl_send_nightly.rs b/embassy-executor/tests/ui/return_impl_send_nightly.rs new file mode 100644 index 000000000..6ddb0e722 --- /dev/null +++ b/embassy-executor/tests/ui/return_impl_send_nightly.rs @@ -0,0 +1,6 @@ +#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] + +#[embassy_executor::task] +fn task() -> impl Send {} + +fn main() {} diff --git a/embassy-executor/tests/ui/return_impl_send_nightly.stderr b/embassy-executor/tests/ui/return_impl_send_nightly.stderr new file mode 100644 index 000000000..de9ba6243 --- /dev/null +++ b/embassy-executor/tests/ui/return_impl_send_nightly.stderr @@ -0,0 +1,10 @@ +error[E0277]: `impl Send` is not a future + --> tests/ui/return_impl_send_nightly.rs:3:1 + | +3 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `impl Send` is not a future + | return type was inferred to be `impl Send` here + | + = help: the trait `Future` is not implemented for `impl Send` -- cgit From 011d7832f899a1cc836bed5d4dbb80863b774e6c Mon Sep 17 00:00:00 2001 From: Frank Stevenson Date: Tue, 3 Jun 2025 15:47:33 +0200 Subject: Use modify() for subsequent changes to RCC.cr() --- embassy-stm32/src/rcc/u5.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index ff70466b9..97eb2eb6d 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -181,7 +181,7 @@ pub(crate) unsafe fn init(config: Config) { w.set_msikrange(range); w.set_msirgsel(Msirgsel::ICSCR1); }); - RCC.cr().write(|w| { + RCC.cr().modify(|w| { w.set_msikon(true); }); while !RCC.cr().read().msikrdy() {} @@ -189,7 +189,7 @@ pub(crate) unsafe fn init(config: Config) { }); let hsi = config.hsi.then(|| { - RCC.cr().write(|w| w.set_hsion(true)); + RCC.cr().modify(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} HSI_FREQ @@ -207,7 +207,7 @@ pub(crate) unsafe fn init(config: Config) { } // Enable HSE, and wait for it to stabilize - RCC.cr().write(|w| { + RCC.cr().modify(|w| { w.set_hseon(true); w.set_hsebyp(hse.mode != HseMode::Oscillator); w.set_hseext(match hse.mode { -- cgit From 9b3b6c54210afb1c99c1b57cce700eccc49896a4 Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Tue, 3 Jun 2025 16:08:55 +0200 Subject: STM32 USB: Read data before register update --- embassy-stm32/src/usb/usb.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index 0b878915a..3e8e74a1f 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -911,6 +911,8 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { }; self.read_data_double_buffered(buf, packet_buffer)? } else { + let len = self.read_data(buf)?; + regs.epr(index).write(|w| { w.set_ep_type(convert_type(self.info.ep_type)); w.set_ea(self.info.addr.index() as _); @@ -920,7 +922,7 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { w.set_ctr_tx(true); // don't clear }); - self.read_data(buf)? + len }; trace!("READ OK, rx_len = {}", rx_len); -- cgit From 94080b38a5b8dec05210b5b1377d595b2640488c Mon Sep 17 00:00:00 2001 From: Benjamin Date: Tue, 3 Jun 2025 20:29:06 +0200 Subject: Added Option to enable HW Oversampling in STM32 V3 ADCs. Copied from adc/v4.rs and adjusted to reflect 2 to 256x oversampling + adjusted bit shifting operations --- embassy-stm32/src/adc/v3.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index 313244e19..f561f817c 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -93,6 +93,18 @@ cfg_if! { } } +/// Number of samples used for averaging. +pub enum Averaging { + Disabled, + Samples2, + Samples4, + Samples8, + Samples16, + Samples32, + Samples64, + Samples128, + Samples256, +} impl<'d, T: Instance> Adc<'d, T> { pub fn new(adc: Peri<'d, T>) -> Self { rcc::enable_and_reset::(); @@ -223,6 +235,25 @@ impl<'d, T: Instance> Adc<'d, T> { T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); } + pub fn set_averaging(&mut self, averaging: Averaging) { + let (enable, samples, right_shift) = match averaging { + Averaging::Disabled => (false, 0, 0), + Averaging::Samples2 => (true, 0, 1), + Averaging::Samples4 => (true, 1, 2), + Averaging::Samples8 => (true, 2, 3), + Averaging::Samples16 => (true, 3, 4), + Averaging::Samples32 => (true, 4, 5), + Averaging::Samples64 => (true, 5, 6), + Averaging::Samples128 => (true, 6, 7), + Averaging::Samples256 => (true, 7, 8), + }; + + T::regs().cfgr2().modify(|reg| { + reg.set_rovse(enable); + reg.set_ovsr(samples); + reg.set_ovss(right_shift); + }) + } /* /// Convert a raw sample from the `Temperature` to deg C pub fn to_degrees_centigrade(sample: u16) -> f32 { -- cgit From a912a3798d5321d099765df4e1af16158699c8d5 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Tue, 3 Jun 2025 21:04:41 +0200 Subject: Fixed variations in register access for different families --- embassy-stm32/src/adc/v3.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index f561f817c..c032113d5 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -247,9 +247,14 @@ impl<'d, T: Instance> Adc<'d, T> { Averaging::Samples128 => (true, 6, 7), Averaging::Samples256 => (true, 7, 8), }; - T::regs().cfgr2().modify(|reg| { + #[cfg(not(adc_g0))] reg.set_rovse(enable); + #[cfg(adc_g0)] + reg.set_ovse(enable); + #[cfg(any(adc_h5, adc_h7rs))] + reg.set_ovsr(samples.into()); + #[cfg(not(any(adc_h5, adc_h7rs)))] reg.set_ovsr(samples); reg.set_ovss(right_shift); }) -- cgit From adb728009ceba095d2190038ff698aaee08907a9 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Tue, 3 Jun 2025 21:10:19 +0200 Subject: adjusted for u0 as well --- embassy-stm32/src/adc/v3.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index c032113d5..7b5df80b8 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -248,9 +248,9 @@ impl<'d, T: Instance> Adc<'d, T> { Averaging::Samples256 => (true, 7, 8), }; T::regs().cfgr2().modify(|reg| { - #[cfg(not(adc_g0))] + #[cfg(not(any(adc_g0, adc_u0)))] reg.set_rovse(enable); - #[cfg(adc_g0)] + #[cfg(any(adc_g0, adc_u0))] reg.set_ovse(enable); #[cfg(any(adc_h5, adc_h7rs))] reg.set_ovsr(samples.into()); -- cgit From c10688cd40d5ffdc181446f304e833ec880b25f0 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Fri, 6 Jun 2025 13:01:11 -0400 Subject: Add public function to get current clock configuration --- embassy-stm32/src/rcc/mod.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 3733fed56..c41f81816 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -95,6 +95,15 @@ pub(crate) unsafe fn get_freqs() -> &'static Clocks { unwrap!(CLOCK_FREQS_PTR.load(core::sync::atomic::Ordering::SeqCst).as_ref()).assume_init_ref() } +/// Get the current clock configuration of the chip. +pub fn clocks<'a>(_rcc: &'a crate::Peri<'a, crate::peripherals::RCC>) -> &'a Clocks { + // Safety: the existence of a `Peri` means that `rcc::init()` + // has already been called, so `CLOCK_FREQS` must be initialized. + // The clocks could be modified again by `reinit()`, but reinit + // (for this reason) requires an exclusive reference to `Peri`. + unsafe { get_freqs() } +} + pub(crate) trait SealedRccPeripheral { fn frequency() -> Hertz; #[allow(dead_code)] @@ -381,7 +390,7 @@ pub fn disable() { /// /// This should only be called after `init`. #[cfg(not(feature = "_dual-core"))] -pub fn reinit(config: Config) { +pub fn reinit<'a>(config: Config, _rcc: &'a mut crate::Peri<'a, crate::peripherals::RCC>) { critical_section::with(|cs| init_rcc(cs, config)) } -- cgit From 358a0cd464c0798c7d6a1178b5a633f5d90ad515 Mon Sep 17 00:00:00 2001 From: Adam Newell Date: Mon, 9 Jun 2025 17:15:24 -0400 Subject: Fix MPU region enablement in stack guard installation Updated the MPU region enablement logic in the `install_stack_guard` function to correctly set the region limit by using the stack bottom address plus 256 minus one, ensuring proper memory protection configuration. See Table 235. MPU_RLAR Register in RP2350 documentation See Section 4.5 MPU_RLAR in armv8m MPU documentation --- embassy-rp/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index f3c5a35bb..94b20bce3 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -567,7 +567,7 @@ unsafe fn install_stack_guard(stack_bottom: *mut usize) -> Result<(), ()> { unsafe { core.MPU.ctrl.write(5); // enable mpu with background default map core.MPU.rbar.write(stack_bottom as u32 & !0xff); // set address - core.MPU.rlar.write(1); // enable region + core.MPU.rlar.write(((stack_bottom as usize + 255) as u32) | 1); } Ok(()) } -- cgit From 3b2dd2bad846f237c33f60013ef2a880489c55c9 Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Tue, 10 Jun 2025 15:49:31 -0600 Subject: fmt --- embassy-stm32/src/i2c/v2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 990ce7d21..48008b695 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -48,7 +48,7 @@ pub(crate) unsafe fn on_interrupt() { regs.cr1().modify(|w| { w.set_addrie(false); w.set_stopie(false); - // The flag can only be cleared by writting to nbytes, we won't do that here + // The flag can only be cleared by writting to nbytes, we won't do that here w.set_tcie(false); // Error flags are to be read in the routines, so we also don't clear them here w.set_nackie(false); -- cgit From fb711395222509c80877b8f74a267c258f03ffae Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Tue, 10 Jun 2025 15:49:31 -0600 Subject: fix name change --- embassy-stm32/src/i2c/v2.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 48008b695..35dc91c86 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -15,7 +15,7 @@ use crate::pac::i2c; impl From for Oamsk { fn from(value: AddrMask) -> Self { match value { - AddrMask::NOMASK => Oamsk::NOMASK, + AddrMask::NOMASK => Oamsk::NO_MASK, AddrMask::MASK1 => Oamsk::MASK1, AddrMask::MASK2 => Oamsk::MASK2, AddrMask::MASK3 => Oamsk::MASK3, @@ -871,7 +871,7 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { assert!(length < 256); let reload = if reload { - i2c::vals::Reload::NOTCOMPLETED + i2c::vals::Reload::NOT_COMPLETED } else { i2c::vals::Reload::COMPLETED }; @@ -1295,4 +1295,3 @@ impl<'d, M: Mode> SetConfig for I2c<'d, M, MultiMaster> { Ok(()) } } - -- cgit From 4efb3b4f3f0178b98ea25f3957393ab6977c89de Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Tue, 10 Jun 2025 15:58:02 -0600 Subject: fix ci --- examples/stm32h7/src/bin/i2c_shared.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/stm32h7/src/bin/i2c_shared.rs b/examples/stm32h7/src/bin/i2c_shared.rs index ec5757284..655ff901f 100644 --- a/examples/stm32h7/src/bin/i2c_shared.rs +++ b/examples/stm32h7/src/bin/i2c_shared.rs @@ -33,7 +33,7 @@ bind_interrupts!(struct Irqs { }); #[embassy_executor::task] -async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async>>) { +async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async, i2c::Master>>) { let mut data = [0u8; 2]; loop { @@ -50,7 +50,7 @@ async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Asyn } #[embassy_executor::task] -async fn humidity(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async>>) { +async fn humidity(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async, i2c::Master>>) { let mut data = [0u8; 6]; loop { -- cgit From 5534a3650755ba7e5d406eb5c78d4f5f0d4d3716 Mon Sep 17 00:00:00 2001 From: Alan Rosenthal Date: Tue, 10 Jun 2025 18:46:41 -0400 Subject: Add RTC example for STM32C0 Tested on STM32C0116F6 Requries: https://github.com/embassy-rs/stm32-data/pull/617 --- embassy-stm32/Cargo.toml | 4 ++-- examples/stm32c0/Cargo.toml | 3 ++- examples/stm32c0/src/bin/rtc.rs | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 examples/stm32c0/src/bin/rtc.rs diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 034f51df9..1031baa2d 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-27ef8fba3483187e852eaf3796d827259f61e8ec" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-778e3d102186ebb12a8c8b60b7cafdd15858bab3" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-27ef8fba3483187e852eaf3796d827259f61e8ec", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-778e3d102186ebb12a8c8b60b7cafdd15858bab3", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index 4cf07cef4..70a7b0895 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32c031c6 to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] } +embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } @@ -19,6 +19,7 @@ cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } +chrono = { version = "^0.4", default-features = false} [profile.release] debug = 2 diff --git a/examples/stm32c0/src/bin/rtc.rs b/examples/stm32c0/src/bin/rtc.rs new file mode 100644 index 000000000..82d8a37ba --- /dev/null +++ b/examples/stm32c0/src/bin/rtc.rs @@ -0,0 +1,35 @@ +#![no_std] +#![no_main] + +use chrono::{NaiveDate, NaiveDateTime}; +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::rtc::{Rtc, RtcConfig}; +use embassy_stm32::Config; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let config = Config::default(); + let p = embassy_stm32::init(config); + + info!("Hello World!"); + + let now = NaiveDate::from_ymd_opt(2020, 5, 15) + .unwrap() + .and_hms_opt(10, 30, 15) + .unwrap(); + + let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); + + rtc.set_datetime(now.into()).expect("datetime not set"); + + loop { + let now: NaiveDateTime = rtc.now().unwrap().into(); + + info!("{}", now.and_utc().timestamp()); + + Timer::after_millis(1000).await; + } +} -- cgit From 56d76aeb7bccfebf07f0ad5ad9da8d9d36b0865d Mon Sep 17 00:00:00 2001 From: Jakob Date: Wed, 11 Jun 2025 09:08:55 +0200 Subject: Remove incorrect addition of 1 to get_max_duty --- embassy-stm32/src/timer/complementary_pwm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 8eec6c0c7..d51b5a8fc 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -121,7 +121,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { /// /// This value depends on the configured frequency and the timer's clock rate from RCC. pub fn get_max_duty(&self) -> u16 { - self.inner.get_max_compare_value() as u16 + 1 + self.inner.get_max_compare_value() as u16 } /// Set the duty for a given channel. -- cgit From 0ee77f50aacdc39aabae1881304a7c744adc24c5 Mon Sep 17 00:00:00 2001 From: Jakob Date: Wed, 11 Jun 2025 09:24:00 +0200 Subject: Add separate case for center aligned mode --- embassy-stm32/src/timer/complementary_pwm.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index d51b5a8fc..1a840650a 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -121,7 +121,11 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { /// /// This value depends on the configured frequency and the timer's clock rate from RCC. pub fn get_max_duty(&self) -> u16 { - self.inner.get_max_compare_value() as u16 + if self.inner.get_counting_mode().is_center_aligned() { + self.inner.get_max_compare_value() as u16 + } else { + self.inner.get_max_compare_value() as u16 + 1 + } } /// Set the duty for a given channel. -- cgit From 66296f673b05f3e34a85f85f30a23a98a863b3e3 Mon Sep 17 00:00:00 2001 From: Jakob Date: Wed, 11 Jun 2025 11:34:37 +0200 Subject: Enable autoreload_preload for complementary PWM --- embassy-stm32/src/timer/complementary_pwm.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 8eec6c0c7..7807bb1bf 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -88,6 +88,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); this.inner.set_output_compare_preload(channel, true); }); + this.inner.set_autoreload_preload(true); this } -- cgit From 09967b71f509bdebaf23ab11e3c362e447722240 Mon Sep 17 00:00:00 2001 From: Jakob Date: Wed, 11 Jun 2025 11:48:39 +0200 Subject: Also update the AdvancedInstace4Channel version --- embassy-stm32/src/timer/complementary_pwm.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 1a840650a..fa6164bdd 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -175,7 +175,11 @@ impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm< } fn get_max_duty(&self) -> Self::Duty { - self.inner.get_max_compare_value() as u16 + 1 + if self.inner.get_counting_mode().is_center_aligned() { + self.inner.get_max_compare_value() as u16 + } else { + self.inner.get_max_compare_value() as u16 + 1 + } } fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { -- cgit From f2266242043c0933e6d39e922400b21d726c9be3 Mon Sep 17 00:00:00 2001 From: Annie Ehler Date: Wed, 11 Jun 2025 19:37:37 -0700 Subject: Add extra methods for the low-power interrupt timer. --- embassy-stm32/src/lptim/timer/mod.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/embassy-stm32/src/lptim/timer/mod.rs b/embassy-stm32/src/lptim/timer/mod.rs index a629be62b..f6abd4a74 100644 --- a/embassy-stm32/src/lptim/timer/mod.rs +++ b/embassy-stm32/src/lptim/timer/mod.rs @@ -82,6 +82,31 @@ impl<'d, T: Instance> Timer<'d, T> { pub fn get_max_compare_value(&self) -> u16 { T::regs().arr().read().arr() } + + /// Enable the timer interrupt. + pub fn enable_interrupt(&self) { + T::regs().dier().modify(|w| w.set_arrmie(true)); + } + + /// Disable the timer interrupt. + pub fn disable_interrupt(&self) { + T::regs().dier().modify(|w| w.set_arrmie(false)); + } + + /// Check if the timer interrupt is enabled. + pub fn is_interrupt_enabled(&self) -> bool { + T::regs().dier().read().arrmie() + } + + /// Check if the timer interrupt is pending. + pub fn is_interrupt_pending(&self) -> bool { + T::regs().isr().read().arrm() + } + + /// Clear the timer interrupt. + pub fn clear_interrupt(&self) { + T::regs().icr().write(|w| w.set_arrmcf(true)); + } } #[cfg(any(lptim_v2a, lptim_v2b))] -- cgit From 4301016f155fd26a3934fb9e7bd2920107a32910 Mon Sep 17 00:00:00 2001 From: Annie Ehler Date: Thu, 12 Jun 2025 04:11:49 +0000 Subject: Move the methods to the cfg gated impls to handle register renaming. --- embassy-stm32/src/lptim/timer/mod.rs | 75 ++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/embassy-stm32/src/lptim/timer/mod.rs b/embassy-stm32/src/lptim/timer/mod.rs index f6abd4a74..648da5940 100644 --- a/embassy-stm32/src/lptim/timer/mod.rs +++ b/embassy-stm32/src/lptim/timer/mod.rs @@ -82,31 +82,6 @@ impl<'d, T: Instance> Timer<'d, T> { pub fn get_max_compare_value(&self) -> u16 { T::regs().arr().read().arr() } - - /// Enable the timer interrupt. - pub fn enable_interrupt(&self) { - T::regs().dier().modify(|w| w.set_arrmie(true)); - } - - /// Disable the timer interrupt. - pub fn disable_interrupt(&self) { - T::regs().dier().modify(|w| w.set_arrmie(false)); - } - - /// Check if the timer interrupt is enabled. - pub fn is_interrupt_enabled(&self) -> bool { - T::regs().dier().read().arrmie() - } - - /// Check if the timer interrupt is pending. - pub fn is_interrupt_pending(&self) -> bool { - T::regs().isr().read().arrm() - } - - /// Clear the timer interrupt. - pub fn clear_interrupt(&self) { - T::regs().icr().write(|w| w.set_arrmcf(true)); - } } #[cfg(any(lptim_v2a, lptim_v2b))] @@ -140,6 +115,31 @@ impl<'d, T: Instance> Timer<'d, T> { .ccmr(0) .modify(|w| w.set_ccsel(channel.index(), direction.into())); } + + /// Enable the timer interrupt. + pub fn enable_interrupt(&self) { + T::regs().dier().modify(|w| w.set_arrmie(true)); + } + + /// Disable the timer interrupt. + pub fn disable_interrupt(&self) { + T::regs().dier().modify(|w| w.set_arrmie(false)); + } + + /// Check if the timer interrupt is enabled. + pub fn is_interrupt_enabled(&self) -> bool { + T::regs().dier().read().arrmie() + } + + /// Check if the timer interrupt is pending. + pub fn is_interrupt_pending(&self) -> bool { + T::regs().isr().read().arrm() + } + + /// Clear the timer interrupt. + pub fn clear_interrupt(&self) { + T::regs().icr().write(|w| w.set_arrmcf(true)); + } } #[cfg(not(any(lptim_v2a, lptim_v2b)))] @@ -153,4 +153,29 @@ impl<'d, T: Instance> Timer<'d, T> { pub fn get_compare_value(&self) -> u16 { T::regs().cmp().read().cmp() } + + /// Enable the timer interrupt. + pub fn enable_interrupt(&self) { + T::regs().ier().modify(|w| w.set_arrmie(true)); + } + + /// Disable the timer interrupt. + pub fn disable_interrupt(&self) { + T::regs().ier().modify(|w| w.set_arrmie(false)); + } + + /// Check if the timer interrupt is enabled. + pub fn is_interrupt_enabled(&self) -> bool { + T::regs().ier().read().arrmie() + } + + /// Check if the timer interrupt is pending. + pub fn is_interrupt_pending(&self) -> bool { + T::regs().isr().read().arrm() + } + + /// Clear the timer interrupt. + pub fn clear_interrupt(&self) { + T::regs().icr().write(|w| w.set_arrmcf(true)); + } } -- cgit From a0d17ea5ca0bd76ef4d4398c28bc8f98c4e50065 Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Mon, 16 Jun 2025 13:57:19 +0200 Subject: Remove futures-util where unnecessary --- embassy-sync/Cargo.toml | 2 +- embassy-sync/src/channel.rs | 4 ++-- embassy-sync/src/pubsub/subscriber.rs | 2 +- embassy-time/Cargo.toml | 2 +- embassy-time/src/timer.rs | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml index 99962f9f6..1e2ea8ea1 100644 --- a/embassy-sync/Cargo.toml +++ b/embassy-sync/Cargo.toml @@ -28,7 +28,7 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } futures-sink = { version = "0.3", default-features = false, features = [] } -futures-util = { version = "0.3.17", default-features = false } +futures-core = { version = "0.3.31", default-features = false } critical-section = "1.1" heapless = "0.8" cfg-if = "1.0.0" diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs index 856551417..dda91c651 100644 --- a/embassy-sync/src/channel.rs +++ b/embassy-sync/src/channel.rs @@ -443,7 +443,7 @@ where } } -impl<'ch, M, T, const N: usize> futures_util::Stream for Receiver<'ch, M, T, N> +impl<'ch, M, T, const N: usize> futures_core::Stream for Receiver<'ch, M, T, N> where M: RawMutex, { @@ -962,7 +962,7 @@ where } } -impl futures_util::Stream for Channel +impl futures_core::Stream for Channel where M: RawMutex, { diff --git a/embassy-sync/src/pubsub/subscriber.rs b/embassy-sync/src/pubsub/subscriber.rs index 6ad660cb3..649382cf1 100644 --- a/embassy-sync/src/pubsub/subscriber.rs +++ b/embassy-sync/src/pubsub/subscriber.rs @@ -115,7 +115,7 @@ impl<'a, PSB: PubSubBehavior + ?Sized, T: Clone> Unpin for Sub<'a, PSB, T> {} /// Warning: The stream implementation ignores lag results and returns all messages. /// This might miss some messages without you knowing it. -impl<'a, PSB: PubSubBehavior + ?Sized, T: Clone> futures_util::Stream for Sub<'a, PSB, T> { +impl<'a, PSB: PubSubBehavior + ?Sized, T: Clone> futures_core::Stream for Sub<'a, PSB, T> { type Item = T; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index 76983d880..2284906b0 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml @@ -427,7 +427,7 @@ embedded-hal-02 = { package = "embedded-hal", version = "0.2.6" } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } -futures-util = { version = "0.3.17", default-features = false } +futures-core = { version = "0.3.31", default-features = false } critical-section = "1.1" cfg-if = "1.0.0" diff --git a/embassy-time/src/timer.rs b/embassy-time/src/timer.rs index d1162eadd..d3f1e1621 100644 --- a/embassy-time/src/timer.rs +++ b/embassy-time/src/timer.rs @@ -2,8 +2,8 @@ use core::future::{poll_fn, Future}; use core::pin::Pin; use core::task::{Context, Poll}; -use futures_util::stream::FusedStream; -use futures_util::Stream; +use futures_core::stream::FusedStream; +use futures_core::Stream; use crate::{Duration, Instant}; -- cgit From 2613295111e47d8476e4b5b26517e7f7900a4ab8 Mon Sep 17 00:00:00 2001 From: Rob Wells Date: Mon, 16 Jun 2025 13:11:46 +0100 Subject: embassy-rp: fix rom_data module documentation Removes module doc comment markers that appeared in the generated documentation. --- embassy-rp/src/rom_data/mod.rs | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/embassy-rp/src/rom_data/mod.rs b/embassy-rp/src/rom_data/mod.rs index e5fcf8e3c..a4aba5737 100644 --- a/embassy-rp/src/rom_data/mod.rs +++ b/embassy-rp/src/rom_data/mod.rs @@ -1,29 +1,29 @@ #![cfg_attr( feature = "rp2040", doc = r" -//! Functions and data from the RPI Bootrom. -//! -//! From the [RP2040 datasheet](https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf), Section 2.8.2.1: -//! -//! > The Bootrom contains a number of public functions that provide useful -//! > RP2040 functionality that might be needed in the absence of any other code -//! > on the device, as well as highly optimized versions of certain key -//! > functionality that would otherwise have to take up space in most user -//! > binaries. +Functions and data from the RPI Bootrom. + +From the [RP2040 datasheet](https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf), Section 2.8.2.1: + +> The Bootrom contains a number of public functions that provide useful +> RP2040 functionality that might be needed in the absence of any other code +> on the device, as well as highly optimized versions of certain key +> functionality that would otherwise have to take up space in most user +> binaries. " )] #![cfg_attr( feature = "_rp235x", doc = r" -//! Functions and data from the RPI Bootrom. -//! -//! From [Section 5.4](https://rptl.io/rp2350-datasheet#section_bootrom) of the -//! RP2350 datasheet: -//! -//! > Whilst some ROM space is dedicated to the implementation of the boot -//! > sequence and USB/UART boot interfaces, the bootrom also contains public -//! > functions that provide useful RP2350 functionality that may be useful for -//! > any code or runtime running on the device +Functions and data from the RPI Bootrom. + +From [Section 5.4](https://rptl.io/rp2350-datasheet#section_bootrom) of the +RP2350 datasheet: + +> Whilst some ROM space is dedicated to the implementation of the boot +> sequence and USB/UART boot interfaces, the bootrom also contains public +> functions that provide useful RP2350 functionality that may be useful for +> any code or runtime running on the device " )] -- cgit From e155d17328b3015a38734df3b540ac0881b05d1c Mon Sep 17 00:00:00 2001 From: Anton Lazarev Date: Mon, 16 Jun 2025 17:55:29 -0700 Subject: sdmmc: set datatime during initialization --- embassy-stm32/src/sdmmc/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 6a02aae70..675d1813b 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs @@ -751,7 +751,6 @@ impl<'d, T: Instance> Sdmmc<'d, T> { Self::wait_idle(); Self::clear_interrupt_flags(); - regs.dtimer().write(|w| w.set_datatime(config.data_transfer_timeout)); regs.dlenr().write(|w| w.set_datalength(length_bytes)); #[cfg(sdmmc_v1)] @@ -789,8 +788,6 @@ impl<'d, T: Instance> Sdmmc<'d, T> { Self::wait_idle(); Self::clear_interrupt_flags(); - regs.dtimer() - .write(|w| w.set_datatime(self.config.data_transfer_timeout)); regs.dlenr().write(|w| w.set_datalength(length_bytes)); #[cfg(sdmmc_v1)] @@ -1349,6 +1346,8 @@ impl<'d, T: Instance> Sdmmc<'d, T> { #[cfg(sdmmc_v1)] w.set_bypass(_bypass); }); + regs.dtimer() + .write(|w| w.set_datatime(self.config.data_transfer_timeout)); regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); Self::cmd(common_cmd::idle(), false)?; -- cgit From 7fe4547ecb8a2838b26e6e0a902fbef3a4d22e52 Mon Sep 17 00:00:00 2001 From: Frank Stevenson Date: Tue, 17 Jun 2025 14:27:37 +0200 Subject: U5: Apply auto-calibration on MSIK and calculate frequencies for detuned LSE input --- embassy-stm32/src/rcc/u5.rs | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index 97eb2eb6d..7e5001499 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -5,7 +5,7 @@ pub use crate::pac::rcc::vals::{ Hpre as AHBPrescaler, Msirange, Msirange as MSIRange, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk, }; -use crate::pac::rcc::vals::{Hseext, Msirgsel, Pllmboost, Pllrge}; +use crate::pac::rcc::vals::{Hseext, Msipllsel, Msirgsel, Pllmboost, Pllrge}; #[cfg(all(peri_usb_otg_hs))] pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG}; use crate::pac::{FLASH, PWR, RCC}; @@ -131,7 +131,18 @@ pub(crate) unsafe fn init(config: Config) { PWR.vosr().modify(|w| w.set_vos(config.voltage_range)); while !PWR.vosr().read().vosrdy() {} - let msis = config.msis.map(|range| { + let lse_calibration_freq = match config.ls.lse { + Some(lse_config) => { + if lse_config.peripherals_clocked && (31_000..=34_000).contains(&lse_config.frequency.0) { + Some(lse_config.frequency) + } else { + None + } + } + _ => None, + }; + + let mut msis = config.msis.map(|range| { // Check MSI output per RM0456 § 11.4.10 match config.voltage_range { VoltageScale::RANGE4 => { @@ -184,8 +195,25 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().modify(|w| { w.set_msikon(true); }); + if lse_calibration_freq.is_some() { + // Enable the MSIK auto-calibration feature + RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIK)); + RCC.cr().modify(|w| w.set_msipllen(true)); + } while !RCC.cr().read().msikrdy() {} - msirange_to_hertz(range) + if let Some(freq) = lse_calibration_freq { + // Estimate frequency based on it being a fixed fractional multiple of LSE + let base = msirange_to_hertz(range).0; + let multiplier = (base + 8096) / 16384; + let msik_freq = Hertz(freq.0 * multiplier / 2); + if config.msis == config.msik { + // If MSIS and MSIK are the same range both will be auto calibrated to the same frequency + msis = Some(msik_freq) + } + msik_freq + } else { + msirange_to_hertz(range) + } }); let hsi = config.hsi.then(|| { -- cgit From d750a8b6b99d7012a1aab21ab67ba530e7a7206b Mon Sep 17 00:00:00 2001 From: Frank Stevenson Date: Tue, 17 Jun 2025 15:46:32 +0200 Subject: Make more accurate table based MSI frequency calculation based on datasheet. --- embassy-stm32/src/rcc/u5.rs | 53 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index 7e5001499..e7fe50f33 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -202,10 +202,7 @@ pub(crate) unsafe fn init(config: Config) { } while !RCC.cr().read().msikrdy() {} if let Some(freq) = lse_calibration_freq { - // Estimate frequency based on it being a fixed fractional multiple of LSE - let base = msirange_to_hertz(range).0; - let multiplier = (base + 8096) / 16384; - let msik_freq = Hertz(freq.0 * multiplier / 2); + let msik_freq = calculate_calibrated_msi_frequency(range, freq); if config.msis == config.msik { // If MSIS and MSIK are the same range both will be auto calibrated to the same frequency msis = Some(msik_freq) @@ -542,3 +539,51 @@ fn init_pll(instance: PllInstance, config: Option, input: &PllInput, voltag PllOutput { p, q, r } } + +/// Fraction structure for MSI auto-calibration +/// Represents the multiplier as numerator/denominator that LSE frequency is multiplied by +#[derive(Debug, Clone, Copy)] +struct MsiFraction { + numerator: u32, + denominator: u32, +} + +impl MsiFraction { + const fn new(numerator: u32, denominator: u32) -> Self { + Self { numerator, denominator } + } + + /// Calculate the calibrated frequency given an LSE frequency + fn calculate_frequency(&self, lse_freq: Hertz) -> Hertz { + Hertz(lse_freq.0 * self.numerator / self.denominator) + } +} + +/// Get the calibration fraction for a given MSI range +/// Based on STM32U5 datasheet table for LSE = 32.768 kHz +fn get_msi_calibration_fraction(range: Msirange) -> MsiFraction { + match range { + Msirange::RANGE_48MHZ => MsiFraction::new(1465, 1), // Range 0: 48.005 MHz + Msirange::RANGE_24MHZ => MsiFraction::new(1465, 2), // Range 1: 24.003 MHz + Msirange::RANGE_16MHZ => MsiFraction::new(1465, 3), // Range 2: 16.002 MHz + Msirange::RANGE_12MHZ => MsiFraction::new(1465, 4), // Range 3: 12.001 MHz + Msirange::RANGE_4MHZ => MsiFraction::new(122, 1), // Range 4: 3.998 MHz + Msirange::RANGE_2MHZ => MsiFraction::new(61, 1), // Range 5: 1.999 MHz + Msirange::RANGE_1_33MHZ => MsiFraction::new(122, 3), // Range 6: 1.333 MHz + Msirange::RANGE_1MHZ => MsiFraction::new(61, 2), // Range 7: 0.999 MHz + Msirange::RANGE_3_072MHZ => MsiFraction::new(94, 1), // Range 8: 3.08 MHz + Msirange::RANGE_1_536MHZ => MsiFraction::new(47, 1), // Range 9: 1.54 MHz + Msirange::RANGE_1_024MHZ => MsiFraction::new(94, 3), // Range 10: 1.027 MHz + Msirange::RANGE_768KHZ => MsiFraction::new(47, 2), // Range 11: 0.77 MHz + Msirange::RANGE_400KHZ => MsiFraction::new(12, 1), // Range 12: 393 kHz + Msirange::RANGE_200KHZ => MsiFraction::new(6, 1), // Range 13: 196.6 kHz + Msirange::RANGE_133KHZ => MsiFraction::new(4, 1), // Range 14: 131 kHz + Msirange::RANGE_100KHZ => MsiFraction::new(3, 1), // Range 15: 98.3 kHz + } +} + +/// Calculate the calibrated MSI frequency for a given range and LSE frequency +fn calculate_calibrated_msi_frequency(range: Msirange, lse_freq: Hertz) -> Hertz { + let fraction = get_msi_calibration_fraction(range); + fraction.calculate_frequency(lse_freq) +} -- cgit From 905aed45f9c15eef9bf9afa5a6b81ae345694581 Mon Sep 17 00:00:00 2001 From: Melvin Wang Date: Wed, 18 Jun 2025 15:37:05 -0700 Subject: add tests illustrating the problem --- embassy-sync/Cargo.toml | 1 + embassy-sync/tests/ui.rs | 13 +++++++++++++ embassy-sync/tests/ui/sync_impl/lazy_lock_function.rs | 15 +++++++++++++++ embassy-sync/tests/ui/sync_impl/lazy_lock_type.rs | 6 ++++++ embassy-sync/tests/ui/sync_impl/once_lock.rs | 6 ++++++ 5 files changed, 41 insertions(+) create mode 100644 embassy-sync/tests/ui.rs create mode 100644 embassy-sync/tests/ui/sync_impl/lazy_lock_function.rs create mode 100644 embassy-sync/tests/ui/sync_impl/lazy_lock_type.rs create mode 100644 embassy-sync/tests/ui/sync_impl/once_lock.rs diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml index 1e2ea8ea1..9e5c39f5e 100644 --- a/embassy-sync/Cargo.toml +++ b/embassy-sync/Cargo.toml @@ -43,3 +43,4 @@ futures-util = { version = "0.3.17", features = [ "channel", "sink" ] } # Enable critical-section implementation for std, for tests critical-section = { version = "1.1", features = ["std"] } static_cell = { version = "2" } +trybuild = "1.0.105" diff --git a/embassy-sync/tests/ui.rs b/embassy-sync/tests/ui.rs new file mode 100644 index 000000000..9ef0d4c67 --- /dev/null +++ b/embassy-sync/tests/ui.rs @@ -0,0 +1,13 @@ +// #[cfg(not(miri))] +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + + // These test cases should fail to compile since OnceLock and LazyLock should not unconditionally implement sync + // for all types. These tests are regression tests against the following issues: + // * https://github.com/embassy-rs/embassy/issues/4307 + // * https://github.com/embassy-rs/embassy/issues/3904 + t.compile_fail("tests/ui/sync_impl/lazy_lock_function.rs"); + t.compile_fail("tests/ui/sync_impl/lazy_lock_type.rs"); + t.compile_fail("tests/ui/sync_impl/once_lock.rs"); +} diff --git a/embassy-sync/tests/ui/sync_impl/lazy_lock_function.rs b/embassy-sync/tests/ui/sync_impl/lazy_lock_function.rs new file mode 100644 index 000000000..c6e6f7e64 --- /dev/null +++ b/embassy-sync/tests/ui/sync_impl/lazy_lock_function.rs @@ -0,0 +1,15 @@ +use embassy_sync::lazy_lock::LazyLock; + +fn main() { + let x = 128u8; + let x_ptr: *const u8 = core::ptr::addr_of!(x); + + let closure_capturing_non_sync_variable = || { + unsafe { + core::ptr::read(x_ptr) + } + }; + + // This should fail to compile because the closure captures a non-Sync variable: x_ptr. + let _lazy_u8: LazyLock = LazyLock::new(closure_capturing_non_sync_variable); +} diff --git a/embassy-sync/tests/ui/sync_impl/lazy_lock_type.rs b/embassy-sync/tests/ui/sync_impl/lazy_lock_type.rs new file mode 100644 index 000000000..4e1383143 --- /dev/null +++ b/embassy-sync/tests/ui/sync_impl/lazy_lock_type.rs @@ -0,0 +1,6 @@ +use embassy_sync::lazy_lock::LazyLock; + +// *mut u8 is not Sync, so LazyLock should not implement Sync for this type. This should fail to compile. +static GLOBAL: LazyLock<*mut u8> = LazyLock::new(|| core::ptr::null_mut()); + +fn main() {} diff --git a/embassy-sync/tests/ui/sync_impl/once_lock.rs b/embassy-sync/tests/ui/sync_impl/once_lock.rs new file mode 100644 index 000000000..8f50d583b --- /dev/null +++ b/embassy-sync/tests/ui/sync_impl/once_lock.rs @@ -0,0 +1,6 @@ +use embassy_sync::once_lock::OnceLock; + +// *mut u8 is not Sync, so OnceLock should not implement Sync for this type. This should fail to compile. +static GLOBAL: OnceLock<*mut u8> = OnceLock::new(); + +fn main() {} -- cgit From 051c63fea2fdb9cc9773c3bd311e6c423f3d1cd2 Mon Sep 17 00:00:00 2001 From: Melvin Wang Date: Wed, 18 Jun 2025 15:38:57 -0700 Subject: fix missing sync bounds --- embassy-sync/src/lazy_lock.rs | 7 ++++++- embassy-sync/src/once_lock.rs | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/embassy-sync/src/lazy_lock.rs b/embassy-sync/src/lazy_lock.rs index 18e3c2019..f1bd88b61 100644 --- a/embassy-sync/src/lazy_lock.rs +++ b/embassy-sync/src/lazy_lock.rs @@ -31,7 +31,12 @@ union Data { f: ManuallyDrop, } -unsafe impl Sync for LazyLock {} +unsafe impl Sync for LazyLock +where + T: Sync, + F: Sync, +{ +} impl T> LazyLock { /// Create a new uninitialized `StaticLock`. diff --git a/embassy-sync/src/once_lock.rs b/embassy-sync/src/once_lock.rs index cd05b986d..1e848685a 100644 --- a/embassy-sync/src/once_lock.rs +++ b/embassy-sync/src/once_lock.rs @@ -42,7 +42,7 @@ pub struct OnceLock { data: Cell>, } -unsafe impl Sync for OnceLock {} +unsafe impl Sync for OnceLock where T: Sync {} impl OnceLock { /// Create a new uninitialized `OnceLock`. -- cgit From 3a432920978dc48f0b4c0a8da7c118415a0708fd Mon Sep 17 00:00:00 2001 From: Melvin Wang Date: Wed, 18 Jun 2025 16:16:06 -0700 Subject: commit expected errors --- .../tests/ui/sync_impl/lazy_lock_function.rs | 12 ++++------- .../tests/ui/sync_impl/lazy_lock_function.stderr | 24 ++++++++++++++++++++++ .../tests/ui/sync_impl/lazy_lock_type.stderr | 9 ++++++++ embassy-sync/tests/ui/sync_impl/once_lock.stderr | 9 ++++++++ 4 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 embassy-sync/tests/ui/sync_impl/lazy_lock_function.stderr create mode 100644 embassy-sync/tests/ui/sync_impl/lazy_lock_type.stderr create mode 100644 embassy-sync/tests/ui/sync_impl/once_lock.stderr diff --git a/embassy-sync/tests/ui/sync_impl/lazy_lock_function.rs b/embassy-sync/tests/ui/sync_impl/lazy_lock_function.rs index c6e6f7e64..35f5587c0 100644 --- a/embassy-sync/tests/ui/sync_impl/lazy_lock_function.rs +++ b/embassy-sync/tests/ui/sync_impl/lazy_lock_function.rs @@ -3,13 +3,9 @@ use embassy_sync::lazy_lock::LazyLock; fn main() { let x = 128u8; let x_ptr: *const u8 = core::ptr::addr_of!(x); + let closure_capturing_non_sync_variable = || unsafe { core::ptr::read(x_ptr) }; - let closure_capturing_non_sync_variable = || { - unsafe { - core::ptr::read(x_ptr) - } - }; - - // This should fail to compile because the closure captures a non-Sync variable: x_ptr. - let _lazy_u8: LazyLock = LazyLock::new(closure_capturing_non_sync_variable); + check_sync(LazyLock::new(closure_capturing_non_sync_variable)); } + +fn check_sync(_lazy_lock: T) {} diff --git a/embassy-sync/tests/ui/sync_impl/lazy_lock_function.stderr b/embassy-sync/tests/ui/sync_impl/lazy_lock_function.stderr new file mode 100644 index 000000000..daf79ad28 --- /dev/null +++ b/embassy-sync/tests/ui/sync_impl/lazy_lock_function.stderr @@ -0,0 +1,24 @@ +error[E0277]: `*const u8` cannot be shared between threads safely + --> tests/ui/sync_impl/lazy_lock_function.rs:8:16 + | +6 | let closure_capturing_non_sync_variable = || unsafe { core::ptr::read(x_ptr) }; + | -- within this `{closure@$DIR/tests/ui/sync_impl/lazy_lock_function.rs:6:47: 6:49}` +7 | +8 | check_sync(LazyLock::new(closure_capturing_non_sync_variable)); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const u8` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: within `{closure@$DIR/tests/ui/sync_impl/lazy_lock_function.rs:6:47: 6:49}`, the trait `Sync` is not implemented for `*const u8` + = note: required because it appears within the type `&*const u8` +note: required because it's used within this closure + --> tests/ui/sync_impl/lazy_lock_function.rs:6:47 + | +6 | let closure_capturing_non_sync_variable = || unsafe { core::ptr::read(x_ptr) }; + | ^^ + = note: required for `embassy_sync::lazy_lock::LazyLock` to implement `Sync` +note: required by a bound in `check_sync` + --> tests/ui/sync_impl/lazy_lock_function.rs:11:18 + | +11 | fn check_sync(_lazy_lock: T) {} + | ^^^^ required by this bound in `check_sync` diff --git a/embassy-sync/tests/ui/sync_impl/lazy_lock_type.stderr b/embassy-sync/tests/ui/sync_impl/lazy_lock_type.stderr new file mode 100644 index 000000000..1ccc54c7a --- /dev/null +++ b/embassy-sync/tests/ui/sync_impl/lazy_lock_type.stderr @@ -0,0 +1,9 @@ +error[E0277]: `*mut u8` cannot be shared between threads safely + --> tests/ui/sync_impl/lazy_lock_type.rs:4:16 + | +4 | static GLOBAL: LazyLock<*mut u8> = LazyLock::new(|| core::ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^ `*mut u8` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `*mut u8` + = note: required for `embassy_sync::lazy_lock::LazyLock<*mut u8>` to implement `Sync` + = note: shared static variables must have a type that implements `Sync` diff --git a/embassy-sync/tests/ui/sync_impl/once_lock.stderr b/embassy-sync/tests/ui/sync_impl/once_lock.stderr new file mode 100644 index 000000000..e2419f844 --- /dev/null +++ b/embassy-sync/tests/ui/sync_impl/once_lock.stderr @@ -0,0 +1,9 @@ +error[E0277]: `*mut u8` cannot be shared between threads safely + --> tests/ui/sync_impl/once_lock.rs:4:16 + | +4 | static GLOBAL: OnceLock<*mut u8> = OnceLock::new(); + | ^^^^^^^^^^^^^^^^^ `*mut u8` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `*mut u8` + = note: required for `embassy_sync::once_lock::OnceLock<*mut u8>` to implement `Sync` + = note: shared static variables must have a type that implements `Sync` -- cgit From e19c3a02043077154f034da8c767b3e8e396435f Mon Sep 17 00:00:00 2001 From: Melvin Wang Date: Wed, 18 Jun 2025 16:20:50 -0700 Subject: disable ui tests in miri --- embassy-sync/tests/ui.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-sync/tests/ui.rs b/embassy-sync/tests/ui.rs index 9ef0d4c67..e8b1080d8 100644 --- a/embassy-sync/tests/ui.rs +++ b/embassy-sync/tests/ui.rs @@ -1,4 +1,4 @@ -// #[cfg(not(miri))] +#[cfg(not(miri))] #[test] fn ui() { let t = trybuild::TestCases::new(); -- cgit From be5b62bdd469dc7fd68ddb4040b4c0547e65bda8 Mon Sep 17 00:00:00 2001 From: Pietro Lorefice Date: Fri, 20 Jun 2025 10:46:33 +0200 Subject: stm32: hsem: add missing RCC initialization --- embassy-stm32/src/hsem/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/hsem/mod.rs b/embassy-stm32/src/hsem/mod.rs index 31527bcdb..f648bf861 100644 --- a/embassy-stm32/src/hsem/mod.rs +++ b/embassy-stm32/src/hsem/mod.rs @@ -3,7 +3,7 @@ use embassy_hal_internal::PeripheralType; use crate::pac; -use crate::rcc::RccPeripheral; +use crate::rcc::{self, RccPeripheral}; // TODO: This code works for all HSEM implemenations except for the STM32WBA52/4/5xx MCUs. // Those MCUs have a different HSEM implementation (Secure semaphore lock support, // Privileged / unprivileged semaphore lock support, Semaphore lock protection via semaphore attribute), @@ -80,6 +80,8 @@ pub struct HardwareSemaphore<'d, T: Instance> { impl<'d, T: Instance> HardwareSemaphore<'d, T> { /// Creates a new HardwareSemaphore instance. pub fn new(peripheral: Peri<'d, T>) -> Self { + rcc::enable_and_reset::(); + HardwareSemaphore { _peri: peripheral } } -- cgit From 59228e2ab4d70eee356400b2470190885527bbc1 Mon Sep 17 00:00:00 2001 From: Pietro Lorefice Date: Fri, 20 Jun 2025 10:47:37 +0200 Subject: stm32: hsem: fix broken CPUID detection --- embassy-stm32/src/hsem/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/hsem/mod.rs b/embassy-stm32/src/hsem/mod.rs index f648bf861..573a1851d 100644 --- a/embassy-stm32/src/hsem/mod.rs +++ b/embassy-stm32/src/hsem/mod.rs @@ -46,7 +46,7 @@ pub enum CoreId { #[inline(always)] pub fn get_current_coreid() -> CoreId { let cpuid = unsafe { cortex_m::peripheral::CPUID::PTR.read_volatile().base.read() }; - match cpuid & 0x000000F0 { + match (cpuid & 0x000000F0) >> 4 { #[cfg(any(stm32wb, stm32wl))] 0x0 => CoreId::Core1, -- cgit From 53fd571ddb4774d103340e1442efa671a3564567 Mon Sep 17 00:00:00 2001 From: John Youren <29236922+JYouren@users.noreply.github.com> Date: Fri, 20 Jun 2025 14:45:13 +0100 Subject: Only write to the flash what was read from the file The write method is given the full aligned buffer to write to flash even though it may not be fully populated. This change ensures only what has been read is written to flash. Preventing potential corrupted firmware and additional flash wear. --- examples/boot/application/rp/src/bin/a.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/boot/application/rp/src/bin/a.rs b/examples/boot/application/rp/src/bin/a.rs index ede0c07da..e6d7b3d4f 100644 --- a/examples/boot/application/rp/src/bin/a.rs +++ b/examples/boot/application/rp/src/bin/a.rs @@ -54,7 +54,7 @@ async fn main(_s: Spawner) { for chunk in APP_B.chunks(4096) { buf.0[..chunk.len()].copy_from_slice(chunk); defmt::info!("writing block at offset {}", offset); - writer.write(offset, &buf.0[..]).unwrap(); + writer.write(offset, &buf.0[..chunk.len()]).unwrap(); offset += chunk.len() as u32; } watchdog.feed(); -- cgit From f84792aaa7212a38f721ad7f2533f54970f5c298 Mon Sep 17 00:00:00 2001 From: paul fornage Date: Fri, 20 Jun 2025 07:47:30 -0700 Subject: Add syntax highlighter --- docs/index.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.adoc b/docs/index.adoc index 9c6150196..80754d5a4 100644 --- a/docs/index.adoc +++ b/docs/index.adoc @@ -5,6 +5,7 @@ :toc-placement: left :toclevels: 2 :imagesdir: images +:source-highlighter: rouge # Embassy Book -- cgit From b2dcdad51db528e1242ef7ea6028341339a9d488 Mon Sep 17 00:00:00 2001 From: Corey Schuhen Date: Sat, 21 Jun 2025 11:58:53 +1000 Subject: BXCAN: Put State inside a critical section mutex of RefCell. This removed unsound code that was giving out mut& to State This change is equiverlent to f5658d6833cb140296a0b6f25b7eb6d16f06c520 that was already done for the FDCAN driver. --- embassy-stm32/src/can/bxcan/mod.rs | 240 +++++++++++++++++-------------------- 1 file changed, 113 insertions(+), 127 deletions(-) diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs index 305666d5b..e2d1c8182 100644 --- a/embassy-stm32/src/can/bxcan/mod.rs +++ b/embassy-stm32/src/can/bxcan/mod.rs @@ -35,7 +35,9 @@ impl interrupt::typelevel::Handler for TxInterruptH v.set_rqcp(1, true); v.set_rqcp(2, true); }); - T::state().tx_mode.on_interrupt::(); + T::info().state.lock(|state| { + state.borrow().tx_mode.on_interrupt::(); + }); } } @@ -46,7 +48,9 @@ pub struct Rx0InterruptHandler { impl interrupt::typelevel::Handler for Rx0InterruptHandler { unsafe fn on_interrupt() { - T::state().rx_mode.on_interrupt::(RxFifo::Fifo0); + T::info().state.lock(|state| { + state.borrow().rx_mode.on_interrupt::(RxFifo::Fifo0); + }); } } @@ -57,7 +61,9 @@ pub struct Rx1InterruptHandler { impl interrupt::typelevel::Handler for Rx1InterruptHandler { unsafe fn on_interrupt() { - T::state().rx_mode.on_interrupt::(RxFifo::Fifo1); + T::info().state.lock(|state| { + state.borrow().rx_mode.on_interrupt::(RxFifo::Fifo1); + }); } } @@ -73,7 +79,9 @@ impl interrupt::typelevel::Handler for SceInterrup if msr_val.slaki() { msr.modify(|m| m.set_slaki(true)); - T::state().err_waker.wake(); + T::info().state.lock(|state| { + state.borrow().err_waker.wake(); + }); } else if msr_val.erri() { // Disable the interrupt, but don't acknowledge the error, so that it can be // forwarded off the bus message consumer. If we don't provide some way for @@ -83,7 +91,9 @@ impl interrupt::typelevel::Handler for SceInterrup let ier = T::regs().ier(); ier.modify(|i| i.set_errie(false)); - T::state().err_waker.wake(); + T::info().state.lock(|state| { + state.borrow().err_waker.wake(); + }); } } } @@ -157,7 +167,6 @@ impl Drop for CanConfig<'_> { pub struct Can<'d> { phantom: PhantomData<&'d ()>, info: &'static Info, - state: &'static State, periph_clock: crate::time::Hertz, } @@ -228,7 +237,6 @@ impl<'d> Can<'d> { Self { phantom: PhantomData, info: T::info(), - state: T::state(), periph_clock: T::frequency(), } } @@ -297,7 +305,9 @@ impl<'d> Can<'d> { self.info.regs.0.mcr().modify(|m| m.set_sleep(true)); poll_fn(|cx| { - self.state.err_waker.register(cx.waker()); + self.info.state.lock(|state| { + state.borrow().err_waker.register(cx.waker()); + }); if self.is_sleeping() { Poll::Ready(()) } else { @@ -351,7 +361,6 @@ impl<'d> Can<'d> { CanTx { _phantom: PhantomData, info: self.info, - state: self.state, } .flush_inner(mb) .await; @@ -367,7 +376,6 @@ impl<'d> Can<'d> { CanTx { _phantom: PhantomData, info: self.info, - state: self.state, } .flush_any_inner() .await @@ -378,7 +386,6 @@ impl<'d> Can<'d> { CanTx { _phantom: PhantomData, info: self.info, - state: self.state, } .flush_all_inner() .await @@ -406,19 +413,19 @@ impl<'d> Can<'d> { /// /// Returns a tuple of the time the message was received and the message frame pub async fn read(&mut self) -> Result { - self.state.rx_mode.read(self.info, self.state).await + RxMode::read(self.info).await } /// Attempts to read a CAN frame without blocking. /// /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. pub fn try_read(&mut self) -> Result { - self.state.rx_mode.try_read(self.info) + RxMode::try_read(self.info) } /// Waits while receive queue is empty. pub async fn wait_not_empty(&mut self) { - self.state.rx_mode.wait_not_empty(self.info, self.state).await + RxMode::wait_not_empty(self.info).await } /// Split the CAN driver into transmit and receive halves. @@ -429,12 +436,10 @@ impl<'d> Can<'d> { CanTx { _phantom: PhantomData, info: self.info, - state: self.state, }, CanRx { _phantom: PhantomData, info: self.info, - state: self.state, }, ) } @@ -515,7 +520,6 @@ impl<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_ pub struct CanTx<'d> { _phantom: PhantomData<&'d ()>, info: &'static Info, - state: &'static State, } impl<'d> CanTx<'d> { @@ -524,7 +528,9 @@ impl<'d> CanTx<'d> { /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure. pub async fn write(&mut self, frame: &Frame) -> TransmitStatus { poll_fn(|cx| { - self.state.tx_mode.register(cx.waker()); + self.info.state.lock(|state| { + state.borrow().tx_mode.register(cx.waker()); + }); if let Ok(status) = self.info.regs.transmit(frame) { return Poll::Ready(status); } @@ -549,7 +555,9 @@ impl<'d> CanTx<'d> { async fn flush_inner(&self, mb: Mailbox) { poll_fn(|cx| { - self.state.tx_mode.register(cx.waker()); + self.info.state.lock(|state| { + state.borrow().tx_mode.register(cx.waker()); + }); if self.info.regs.0.tsr().read().tme(mb.index()) { return Poll::Ready(()); } @@ -566,7 +574,9 @@ impl<'d> CanTx<'d> { async fn flush_any_inner(&self) { poll_fn(|cx| { - self.state.tx_mode.register(cx.waker()); + self.info.state.lock(|state| { + state.borrow().tx_mode.register(cx.waker()); + }); let tsr = self.info.regs.0.tsr().read(); if tsr.tme(Mailbox::Mailbox0.index()) @@ -593,7 +603,9 @@ impl<'d> CanTx<'d> { async fn flush_all_inner(&self) { poll_fn(|cx| { - self.state.tx_mode.register(cx.waker()); + self.info.state.lock(|state| { + state.borrow().tx_mode.register(cx.waker()); + }); let tsr = self.info.regs.0.tsr().read(); if tsr.tme(Mailbox::Mailbox0.index()) @@ -634,7 +646,7 @@ impl<'d> CanTx<'d> { self, txb: &'static mut TxBuf, ) -> BufferedCanTx<'d, TX_BUF_SIZE> { - BufferedCanTx::new(self.info, self.state, self, txb) + BufferedCanTx::new(self.info, self, txb) } } @@ -644,33 +656,22 @@ pub type TxBuf = Channel { info: &'static Info, - state: &'static State, _tx: CanTx<'d>, tx_buf: &'static TxBuf, } impl<'d, const TX_BUF_SIZE: usize> BufferedCanTx<'d, TX_BUF_SIZE> { - fn new(info: &'static Info, state: &'static State, _tx: CanTx<'d>, tx_buf: &'static TxBuf) -> Self { - Self { - info, - state, - _tx, - tx_buf, - } - .setup() + fn new(info: &'static Info, _tx: CanTx<'d>, tx_buf: &'static TxBuf) -> Self { + Self { info, _tx, tx_buf }.setup() } fn setup(self) -> Self { // We don't want interrupts being processed while we change modes. - critical_section::with(|_| { - let tx_inner = super::common::ClassicBufferedTxInner { - tx_receiver: self.tx_buf.receiver().into(), - }; - let state = self.state as *const State; - unsafe { - let mut_state = state as *mut State; - (*mut_state).tx_mode = TxMode::Buffered(tx_inner); - } + let tx_inner = super::common::ClassicBufferedTxInner { + tx_receiver: self.tx_buf.receiver().into(), + }; + self.info.state.lock(|state| { + state.borrow_mut().tx_mode = TxMode::Buffered(tx_inner); }); self } @@ -704,7 +705,6 @@ impl<'d, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, TX_BUF_SIZE> { pub struct CanRx<'d> { _phantom: PhantomData<&'d ()>, info: &'static Info, - state: &'static State, } impl<'d> CanRx<'d> { @@ -714,19 +714,19 @@ impl<'d> CanRx<'d> { /// /// Returns a tuple of the time the message was received and the message frame pub async fn read(&mut self) -> Result { - self.state.rx_mode.read(self.info, self.state).await + RxMode::read(self.info).await } /// Attempts to read a CAN frame without blocking. /// /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. pub fn try_read(&mut self) -> Result { - self.state.rx_mode.try_read(self.info) + RxMode::try_read(self.info) } /// Waits while receive queue is empty. pub async fn wait_not_empty(&mut self) { - self.state.rx_mode.wait_not_empty(self.info, self.state).await + RxMode::wait_not_empty(self.info).await } /// Return a buffered instance of driver. User must supply Buffers @@ -734,7 +734,7 @@ impl<'d> CanRx<'d> { self, rxb: &'static mut RxBuf, ) -> BufferedCanRx<'d, RX_BUF_SIZE> { - BufferedCanRx::new(self.info, self.state, self, rxb) + BufferedCanRx::new(self.info, self, rxb) } /// Accesses the filter banks owned by this CAN peripheral. @@ -752,33 +752,22 @@ pub type RxBuf = Channel { info: &'static Info, - state: &'static State, rx: CanRx<'d>, rx_buf: &'static RxBuf, } impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> { - fn new(info: &'static Info, state: &'static State, rx: CanRx<'d>, rx_buf: &'static RxBuf) -> Self { - BufferedCanRx { - info, - state, - rx, - rx_buf, - } - .setup() + fn new(info: &'static Info, rx: CanRx<'d>, rx_buf: &'static RxBuf) -> Self { + BufferedCanRx { info, rx, rx_buf }.setup() } fn setup(self) -> Self { // We don't want interrupts being processed while we change modes. - critical_section::with(|_| { - let rx_inner = super::common::ClassicBufferedRxInner { - rx_sender: self.rx_buf.sender().into(), - }; - let state = self.state as *const State; - unsafe { - let mut_state = state as *mut State; - (*mut_state).rx_mode = RxMode::Buffered(rx_inner); - } + let rx_inner = super::common::ClassicBufferedRxInner { + rx_sender: self.rx_buf.sender().into(), + }; + self.info.state.lock(|state| { + state.borrow_mut().rx_mode = RxMode::Buffered(rx_inner); }); self } @@ -792,7 +781,7 @@ impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> { /// /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. pub fn try_read(&mut self) -> Result { - match &self.state.rx_mode { + self.info.state.lock(|s| match &s.borrow().rx_mode { RxMode::Buffered(_) => { if let Ok(result) = self.rx_buf.try_receive() { match result { @@ -810,7 +799,7 @@ impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> { _ => { panic!("Bad Mode") } - } + }) } /// Waits while receive queue is empty. @@ -929,27 +918,30 @@ impl RxMode { } } - pub(crate) async fn read(&self, info: &Info, state: &State) -> Result { - match self { - Self::NonBuffered(waker) => { - poll_fn(|cx| { - state.err_waker.register(cx.waker()); - waker.register(cx.waker()); - match self.try_read(info) { - Ok(result) => Poll::Ready(Ok(result)), - Err(TryReadError::Empty) => Poll::Pending, - Err(TryReadError::BusError(be)) => Poll::Ready(Err(be)), + pub(crate) async fn read(info: &Info) -> Result { + poll_fn(|cx| { + info.state.lock(|state| { + let state = state.borrow(); + state.err_waker.register(cx.waker()); + match &state.rx_mode { + Self::NonBuffered(waker) => { + waker.register(cx.waker()); } - }) - .await - } - _ => { - panic!("Bad Mode") + _ => { + panic!("Bad Mode") + } + } + }); + match RxMode::try_read(info) { + Ok(result) => Poll::Ready(Ok(result)), + Err(TryReadError::Empty) => Poll::Pending, + Err(TryReadError::BusError(be)) => Poll::Ready(Err(be)), } - } + }) + .await } - pub(crate) fn try_read(&self, info: &Info) -> Result { - match self { + pub(crate) fn try_read(info: &Info) -> Result { + info.state.lock(|state| match state.borrow().rx_mode { Self::NonBuffered(_) => { let registers = &info.regs; if let Some(msg) = registers.receive_fifo(RxFifo::Fifo0) { @@ -975,25 +967,28 @@ impl RxMode { _ => { panic!("Bad Mode") } - } + }) } - pub(crate) async fn wait_not_empty(&self, info: &Info, state: &State) { - match &state.rx_mode { - Self::NonBuffered(waker) => { - poll_fn(|cx| { - waker.register(cx.waker()); - if info.regs.receive_frame_available() { - Poll::Ready(()) - } else { - Poll::Pending + pub(crate) async fn wait_not_empty(info: &Info) { + poll_fn(|cx| { + info.state.lock(|s| { + let state = s.borrow(); + match &state.rx_mode { + Self::NonBuffered(waker) => { + waker.register(cx.waker()); } - }) - .await - } - _ => { - panic!("Bad Mode") + _ => { + panic!("Bad Mode") + } + } + }); + if info.regs.receive_frame_available() { + Poll::Ready(()) + } else { + Poll::Pending } - } + }) + .await } } @@ -1008,21 +1003,24 @@ impl TxMode { tsr.tme(Mailbox::Mailbox0.index()) || tsr.tme(Mailbox::Mailbox1.index()) || tsr.tme(Mailbox::Mailbox2.index()) } pub fn on_interrupt(&self) { - match &T::state().tx_mode { - TxMode::NonBuffered(waker) => waker.wake(), - TxMode::Buffered(buf) => { - while self.buffer_free::() { - match buf.tx_receiver.try_receive() { - Ok(frame) => { - _ = Registers(T::regs()).transmit(&frame); - } - Err(_) => { - break; + T::info().state.lock(|state| { + let tx_mode = &state.borrow().tx_mode; + match tx_mode { + TxMode::NonBuffered(waker) => waker.wake(), + TxMode::Buffered(buf) => { + while self.buffer_free::() { + match buf.tx_receiver.try_receive() { + Ok(frame) => { + _ = Registers(T::regs()).transmit(&frame); + } + Err(_) => { + break; + } } } } } - } + }); } fn register(&self, arg: &core::task::Waker) { @@ -1057,6 +1055,7 @@ impl State { } } +type SharedState = embassy_sync::blocking_mutex::Mutex>; pub(crate) struct Info { regs: Registers, tx_interrupt: crate::interrupt::Interrupt, @@ -1065,6 +1064,7 @@ pub(crate) struct Info { sce_interrupt: crate::interrupt::Interrupt, tx_waker: fn(), internal_operation: fn(InternalOperation), + state: SharedState, /// The total number of filter banks available to the instance. /// @@ -1075,8 +1075,6 @@ pub(crate) struct Info { trait SealedInstance { fn info() -> &'static Info; fn regs() -> crate::pac::can::Can; - fn state() -> &'static State; - unsafe fn mut_state() -> &'static mut State; fn internal_operation(val: InternalOperation); } @@ -1136,6 +1134,7 @@ foreach_peripheral!( sce_interrupt: crate::_generated::peripheral_interrupts::$inst::SCE::IRQ, tx_waker: crate::_generated::peripheral_interrupts::$inst::TX::pend, internal_operation: peripherals::$inst::internal_operation, + state: embassy_sync::blocking_mutex::Mutex::new(core::cell::RefCell::new(State::new())), num_filter_banks: peripherals::$inst::NUM_FILTER_BANKS, }; &INFO @@ -1144,21 +1143,10 @@ foreach_peripheral!( crate::pac::$inst } - unsafe fn mut_state() -> & 'static mut State { - static mut STATE: State = State::new(); - &mut *core::ptr::addr_of_mut!(STATE) - } - fn state() -> &'static State { - unsafe { peripherals::$inst::mut_state() } - } - - fn internal_operation(val: InternalOperation) { - critical_section::with(|_| { - //let state = self.state as *const State; - unsafe { + peripherals::$inst::info().state.lock(|s| { + let mut mut_state = s.borrow_mut(); //let mut_state = state as *mut State; - let mut_state = peripherals::$inst::mut_state(); match val { InternalOperation::NotifySenderCreated => { mut_state.sender_instance_count += 1; @@ -1179,11 +1167,9 @@ foreach_peripheral!( } } } - } }); } } - impl Instance for peripherals::$inst { type TXInterrupt = crate::_generated::peripheral_interrupts::$inst::TX; type RX0Interrupt = crate::_generated::peripheral_interrupts::$inst::RX0; -- cgit From e75b344089df76aa89d7fd4463a509c0bc58de2c Mon Sep 17 00:00:00 2001 From: Tobias Naumann Date: Thu, 5 Jun 2025 15:24:29 +0200 Subject: Add TxGuard and RxGuard which impl RAII for the STM32 CAN reference counting --- embassy-stm32/src/can/common.rs | 53 +++++++++++++++++-------- embassy-stm32/src/can/fdcan.rs | 85 +++++++++++++---------------------------- 2 files changed, 64 insertions(+), 74 deletions(-) diff --git a/embassy-stm32/src/can/common.rs b/embassy-stm32/src/can/common.rs index 386d4467c..651fa12d5 100644 --- a/embassy-stm32/src/can/common.rs +++ b/embassy-stm32/src/can/common.rs @@ -25,7 +25,7 @@ pub(crate) struct FdBufferedTxInner { pub struct BufferedSender<'ch, FRAME> { pub(crate) tx_buf: embassy_sync::channel::SendDynamicSender<'ch, FRAME>, pub(crate) waker: fn(), - pub(crate) internal_operation: fn(InternalOperation), + pub(crate) tx_guard: TxGuard, } impl<'ch, FRAME> BufferedSender<'ch, FRAME> { @@ -50,28 +50,21 @@ impl<'ch, FRAME> BufferedSender<'ch, FRAME> { impl<'ch, FRAME> Clone for BufferedSender<'ch, FRAME> { fn clone(&self) -> Self { - (self.internal_operation)(InternalOperation::NotifySenderCreated); Self { tx_buf: self.tx_buf, waker: self.waker, - internal_operation: self.internal_operation, + tx_guard: TxGuard::new(self.tx_guard.internal_operation), } } } -impl<'ch, FRAME> Drop for BufferedSender<'ch, FRAME> { - fn drop(&mut self) { - (self.internal_operation)(InternalOperation::NotifySenderDestroyed); - } -} - /// Sender that can be used for sending Classic CAN frames. pub type BufferedCanSender = BufferedSender<'static, Frame>; /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. pub struct BufferedReceiver<'ch, ENVELOPE> { pub(crate) rx_buf: embassy_sync::channel::SendDynamicReceiver<'ch, Result>, - pub(crate) internal_operation: fn(InternalOperation), + pub(crate) rx_guard: RxGuard, } impl<'ch, ENVELOPE> BufferedReceiver<'ch, ENVELOPE> { @@ -106,19 +99,47 @@ impl<'ch, ENVELOPE> BufferedReceiver<'ch, ENVELOPE> { impl<'ch, ENVELOPE> Clone for BufferedReceiver<'ch, ENVELOPE> { fn clone(&self) -> Self { - (self.internal_operation)(InternalOperation::NotifyReceiverCreated); Self { rx_buf: self.rx_buf, - internal_operation: self.internal_operation, + rx_guard: RxGuard::new(self.rx_guard.internal_operation), } } } -impl<'ch, ENVELOPE> Drop for BufferedReceiver<'ch, ENVELOPE> { +/// A BufferedCanReceiver for Classic CAN frames. +pub type BufferedCanReceiver = BufferedReceiver<'static, Envelope>; + +/// Implements RAII for the internal reference counting (TX side). Each TX type should contain one +/// of these. The new method and the Drop impl will automatically call the reference counting +/// function. Like this, the reference counting function does not need to be called manually for +/// each TX type. Transceiver types (TX and RX) should contain one TxGuard and one RxGuard. +pub(crate) struct TxGuard { + internal_operation: fn(InternalOperation), +} +impl TxGuard { + pub(crate) fn new(internal_operation: fn(InternalOperation)) -> Self { + internal_operation(InternalOperation::NotifySenderCreated); + Self { internal_operation } + } +} +impl Drop for TxGuard { + fn drop(&mut self) { + (self.internal_operation)(InternalOperation::NotifySenderDestroyed); + } +} + +/// Implements RAII for the internal reference counting (RX side). See TxGuard for further doc. +pub(crate) struct RxGuard { + internal_operation: fn(InternalOperation), +} +impl RxGuard { + pub(crate) fn new(internal_operation: fn(InternalOperation)) -> Self { + internal_operation(InternalOperation::NotifyReceiverCreated); + Self { internal_operation } + } +} +impl Drop for RxGuard { fn drop(&mut self) { (self.internal_operation)(InternalOperation::NotifyReceiverDestroyed); } } - -/// A BufferedCanReceiver for Classic CAN frames. -pub type BufferedCanReceiver = BufferedReceiver<'static, Envelope>; diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index 97d22315a..2846fb44a 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs @@ -21,6 +21,7 @@ use self::fd::config::*; use self::fd::filter::*; pub use self::fd::{config, filter}; pub use super::common::{BufferedCanReceiver, BufferedCanSender}; +use super::common::{RxGuard, TxGuard}; use super::enums::*; use super::frame::*; use super::util; @@ -171,6 +172,7 @@ pub struct CanConfigurator<'d> { /// Reference to internals. properties: Properties, periph_clock: crate::time::Hertz, + raii_guards: (TxGuard, RxGuard), } impl<'d> CanConfigurator<'d> { @@ -194,8 +196,6 @@ impl<'d> CanConfigurator<'d> { s.borrow_mut().tx_pin_port = Some(tx.pin_port()); s.borrow_mut().rx_pin_port = Some(rx.pin_port()); }); - (info.internal_operation)(InternalOperation::NotifySenderCreated); - (info.internal_operation)(InternalOperation::NotifyReceiverCreated); let mut config = crate::can::fd::config::FdCanConfig::default(); config.timestamp_source = TimestampSource::Prescaler(TimestampPrescaler::_1); @@ -214,6 +214,10 @@ impl<'d> CanConfigurator<'d> { info, properties: Properties::new(T::info()), periph_clock: T::frequency(), + raii_guards: ( + TxGuard::new(info.internal_operation), + RxGuard::new(info.internal_operation), + ), } } @@ -267,14 +271,13 @@ impl<'d> CanConfigurator<'d> { s.borrow_mut().ns_per_timer_tick = ns_per_timer_tick; }); self.info.regs.into_mode(self.config, mode); - (self.info.internal_operation)(InternalOperation::NotifySenderCreated); - (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated); Can { _phantom: PhantomData, config: self.config, info: self.info, _mode: mode, properties: Properties::new(self.info), + raii_guards: self.raii_guards, } } @@ -294,13 +297,6 @@ impl<'d> CanConfigurator<'d> { } } -impl<'d> Drop for CanConfigurator<'d> { - fn drop(&mut self) { - (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); - (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); - } -} - /// FDCAN Instance pub struct Can<'d> { _phantom: PhantomData<&'d ()>, @@ -308,6 +304,7 @@ pub struct Can<'d> { info: &'static Info, _mode: OperatingMode, properties: Properties, + raii_guards: (TxGuard, RxGuard), } impl<'d> Can<'d> { @@ -364,19 +361,19 @@ impl<'d> Can<'d> { /// Split instance into separate portions: Tx(write), Rx(read), common properties pub fn split(self) -> (CanTx<'d>, CanRx<'d>, Properties) { - (self.info.internal_operation)(InternalOperation::NotifySenderCreated); - (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated); ( CanTx { _phantom: PhantomData, info: self.info, config: self.config, _mode: self._mode, + tx_guard: self.raii_guards.0, }, CanRx { _phantom: PhantomData, info: self.info, _mode: self._mode, + rx_guard: self.raii_guards.1, }, Properties { info: self.properties.info, @@ -385,14 +382,13 @@ impl<'d> Can<'d> { } /// Join split rx and tx portions back together pub fn join(tx: CanTx<'d>, rx: CanRx<'d>) -> Self { - (tx.info.internal_operation)(InternalOperation::NotifySenderCreated); - (tx.info.internal_operation)(InternalOperation::NotifyReceiverCreated); Can { _phantom: PhantomData, config: tx.config, info: tx.info, _mode: rx._mode, properties: Properties::new(tx.info), + raii_guards: (tx.tx_guard, rx.rx_guard), } } @@ -415,13 +411,6 @@ impl<'d> Can<'d> { } } -impl<'d> Drop for Can<'d> { - fn drop(&mut self) { - (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); - (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); - } -} - /// User supplied buffer for RX Buffering pub type RxBuf = Channel, BUF_SIZE>; @@ -436,6 +425,7 @@ pub struct BufferedCan<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { tx_buf: &'static TxBuf, rx_buf: &'static RxBuf, properties: Properties, + _raii_guards: (TxGuard, RxGuard), } impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> { @@ -445,8 +435,6 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, tx_buf: &'static TxBuf, rx_buf: &'static RxBuf, ) -> Self { - (info.internal_operation)(InternalOperation::NotifySenderCreated); - (info.internal_operation)(InternalOperation::NotifyReceiverCreated); BufferedCan { _phantom: PhantomData, info, @@ -454,6 +442,10 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, tx_buf, rx_buf, properties: Properties::new(info), + _raii_guards: ( + TxGuard::new(info.internal_operation), + RxGuard::new(info.internal_operation), + ), } .setup() } @@ -492,31 +484,22 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, /// Returns a sender that can be used for sending CAN frames. pub fn writer(&self) -> BufferedCanSender { - (self.info.internal_operation)(InternalOperation::NotifySenderCreated); BufferedCanSender { tx_buf: self.tx_buf.sender().into(), waker: self.info.tx_waker, - internal_operation: self.info.internal_operation, + tx_guard: TxGuard::new(self.info.internal_operation), } } /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. pub fn reader(&self) -> BufferedCanReceiver { - (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated); BufferedCanReceiver { rx_buf: self.rx_buf.receiver().into(), - internal_operation: self.info.internal_operation, + rx_guard: RxGuard::new(self.info.internal_operation), } } } -impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> { - fn drop(&mut self) { - (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); - (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); - } -} - /// User supplied buffer for RX Buffering pub type RxFdBuf = Channel, BUF_SIZE>; @@ -537,6 +520,7 @@ pub struct BufferedCanFd<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> tx_buf: &'static TxFdBuf, rx_buf: &'static RxFdBuf, properties: Properties, + _raii_guards: (TxGuard, RxGuard), } impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> { @@ -546,8 +530,6 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<' tx_buf: &'static TxFdBuf, rx_buf: &'static RxFdBuf, ) -> Self { - (info.internal_operation)(InternalOperation::NotifySenderCreated); - (info.internal_operation)(InternalOperation::NotifyReceiverCreated); BufferedCanFd { _phantom: PhantomData, info, @@ -555,6 +537,10 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<' tx_buf, rx_buf, properties: Properties::new(info), + _raii_guards: ( + TxGuard::new(info.internal_operation), + RxGuard::new(info.internal_operation), + ), } .setup() } @@ -597,7 +583,7 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<' BufferedFdCanSender { tx_buf: self.tx_buf.sender().into(), waker: self.info.tx_waker, - internal_operation: self.info.internal_operation, + tx_guard: TxGuard::new(self.info.internal_operation), } } @@ -606,23 +592,17 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<' (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated); BufferedFdCanReceiver { rx_buf: self.rx_buf.receiver().into(), - internal_operation: self.info.internal_operation, + rx_guard: RxGuard::new(self.info.internal_operation), } } } -impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> { - fn drop(&mut self) { - (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); - (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); - } -} - /// FDCAN Rx only Instance pub struct CanRx<'d> { _phantom: PhantomData<&'d ()>, info: &'static Info, _mode: OperatingMode, + rx_guard: RxGuard, } impl<'d> CanRx<'d> { @@ -637,18 +617,13 @@ impl<'d> CanRx<'d> { } } -impl<'d> Drop for CanRx<'d> { - fn drop(&mut self) { - (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); - } -} - /// FDCAN Tx only Instance pub struct CanTx<'d> { _phantom: PhantomData<&'d ()>, info: &'static Info, config: crate::can::fd::config::FdCanConfig, _mode: OperatingMode, + tx_guard: TxGuard, } impl<'c, 'd> CanTx<'d> { @@ -669,12 +644,6 @@ impl<'c, 'd> CanTx<'d> { } } -impl<'d> Drop for CanTx<'d> { - fn drop(&mut self) { - (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); - } -} - enum RxMode { NonBuffered(AtomicWaker), ClassicBuffered(super::common::ClassicBufferedRxInner), -- cgit From 8b280688e18bd92b126601d9af26d73e147edeac Mon Sep 17 00:00:00 2001 From: Corey Schuhen Date: Sat, 7 Jun 2025 17:25:15 +1000 Subject: FDCAN/BXCAN: Finish implementation of RAII instance counters. - Use DeRef in all types - Change Name of internal_operation and its enum - move into Info to avoid macro code dup --- embassy-stm32/src/can/bxcan/mod.rs | 191 ++++++++++++++++++------------------- embassy-stm32/src/can/common.rs | 108 +++++++++++++++------ embassy-stm32/src/can/enums.rs | 2 +- embassy-stm32/src/can/fdcan.rs | 163 +++++++++++++------------------ 4 files changed, 243 insertions(+), 221 deletions(-) diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs index e2d1c8182..4c0795a2a 100644 --- a/embassy-stm32/src/can/bxcan/mod.rs +++ b/embassy-stm32/src/can/bxcan/mod.rs @@ -15,9 +15,10 @@ pub use embedded_can::{ExtendedId, Id, StandardId}; use self::filter::MasterFilters; use self::registers::{Registers, RxFifo}; pub use super::common::{BufferedCanReceiver, BufferedCanSender}; +use super::common::{InfoRef, RxInfoRef, TxInfoRef}; use super::frame::{Envelope, Frame}; use super::util; -use crate::can::enums::{BusError, InternalOperation, TryReadError}; +use crate::can::enums::{BusError, RefCountOp, TryReadError}; use crate::gpio::{AfType, OutputType, Pull, Speed}; use crate::interrupt::typelevel::Interrupt; use crate::rcc::{self, RccPeripheral}; @@ -90,7 +91,6 @@ impl interrupt::typelevel::Handler for SceInterrup // an indefinite amount of time. let ier = T::regs().ier(); ier.modify(|i| i.set_errie(false)); - T::info().state.lock(|state| { state.borrow().err_waker.wake(); }); @@ -101,7 +101,7 @@ impl interrupt::typelevel::Handler for SceInterrup /// Configuration proxy returned by [`Can::modify_config`]. pub struct CanConfig<'a> { phantom: PhantomData<&'a ()>, - info: &'static Info, + info: InfoRef, periph_clock: crate::time::Hertz, } @@ -166,7 +166,7 @@ impl Drop for CanConfig<'_> { /// CAN driver pub struct Can<'d> { phantom: PhantomData<&'d ()>, - info: &'static Info, + info: InfoRef, periph_clock: crate::time::Hertz, } @@ -236,7 +236,7 @@ impl<'d> Can<'d> { Self { phantom: PhantomData, - info: T::info(), + info: InfoRef::new(T::info()), periph_clock: T::frequency(), } } @@ -256,7 +256,7 @@ impl<'d> Can<'d> { CanConfig { phantom: self.phantom, - info: self.info, + info: InfoRef::new(&self.info), periph_clock: self.periph_clock, } } @@ -305,8 +305,8 @@ impl<'d> Can<'d> { self.info.regs.0.mcr().modify(|m| m.set_sleep(true)); poll_fn(|cx| { - self.info.state.lock(|state| { - state.borrow().err_waker.register(cx.waker()); + self.info.state.lock(|s| { + s.borrow().err_waker.register(cx.waker()); }); if self.is_sleeping() { Poll::Ready(()) @@ -360,7 +360,7 @@ impl<'d> Can<'d> { pub async fn flush(&self, mb: Mailbox) { CanTx { _phantom: PhantomData, - info: self.info, + info: TxInfoRef::new(&self.info), } .flush_inner(mb) .await; @@ -375,7 +375,7 @@ impl<'d> Can<'d> { pub async fn flush_any(&self) { CanTx { _phantom: PhantomData, - info: self.info, + info: TxInfoRef::new(&self.info), } .flush_any_inner() .await @@ -385,7 +385,7 @@ impl<'d> Can<'d> { pub async fn flush_all(&self) { CanTx { _phantom: PhantomData, - info: self.info, + info: TxInfoRef::new(&self.info), } .flush_all_inner() .await @@ -413,19 +413,19 @@ impl<'d> Can<'d> { /// /// Returns a tuple of the time the message was received and the message frame pub async fn read(&mut self) -> Result { - RxMode::read(self.info).await + RxMode::read(&self.info).await } /// Attempts to read a CAN frame without blocking. /// /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. pub fn try_read(&mut self) -> Result { - RxMode::try_read(self.info) + RxMode::try_read(&self.info) } /// Waits while receive queue is empty. pub async fn wait_not_empty(&mut self) { - RxMode::wait_not_empty(self.info).await + RxMode::wait_not_empty(&self.info).await } /// Split the CAN driver into transmit and receive halves. @@ -435,11 +435,11 @@ impl<'d> Can<'d> { ( CanTx { _phantom: PhantomData, - info: self.info, + info: TxInfoRef::new(&self.info), }, CanRx { _phantom: PhantomData, - info: self.info, + info: RxInfoRef::new(&self.info), }, ) } @@ -464,7 +464,7 @@ impl<'d> Can<'d> { /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master /// peripheral instead. pub fn modify_filters(&mut self) -> MasterFilters<'_> { - unsafe { MasterFilters::new(self.info) } + unsafe { MasterFilters::new(&self.info) } } } @@ -519,7 +519,7 @@ impl<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_ /// CAN driver, transmit half. pub struct CanTx<'d> { _phantom: PhantomData<&'d ()>, - info: &'static Info, + info: TxInfoRef, } impl<'d> CanTx<'d> { @@ -528,8 +528,8 @@ impl<'d> CanTx<'d> { /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure. pub async fn write(&mut self, frame: &Frame) -> TransmitStatus { poll_fn(|cx| { - self.info.state.lock(|state| { - state.borrow().tx_mode.register(cx.waker()); + self.info.state.lock(|s| { + s.borrow().tx_mode.register(cx.waker()); }); if let Ok(status) = self.info.regs.transmit(frame) { return Poll::Ready(status); @@ -555,8 +555,8 @@ impl<'d> CanTx<'d> { async fn flush_inner(&self, mb: Mailbox) { poll_fn(|cx| { - self.info.state.lock(|state| { - state.borrow().tx_mode.register(cx.waker()); + self.info.state.lock(|s| { + s.borrow().tx_mode.register(cx.waker()); }); if self.info.regs.0.tsr().read().tme(mb.index()) { return Poll::Ready(()); @@ -574,8 +574,8 @@ impl<'d> CanTx<'d> { async fn flush_any_inner(&self) { poll_fn(|cx| { - self.info.state.lock(|state| { - state.borrow().tx_mode.register(cx.waker()); + self.info.state.lock(|s| { + s.borrow().tx_mode.register(cx.waker()); }); let tsr = self.info.regs.0.tsr().read(); @@ -603,8 +603,8 @@ impl<'d> CanTx<'d> { async fn flush_all_inner(&self) { poll_fn(|cx| { - self.info.state.lock(|state| { - state.borrow().tx_mode.register(cx.waker()); + self.info.state.lock(|s| { + s.borrow().tx_mode.register(cx.waker()); }); let tsr = self.info.regs.0.tsr().read(); @@ -646,7 +646,7 @@ impl<'d> CanTx<'d> { self, txb: &'static mut TxBuf, ) -> BufferedCanTx<'d, TX_BUF_SIZE> { - BufferedCanTx::new(self.info, self, txb) + BufferedCanTx::new(&self.info, self, txb) } } @@ -655,23 +655,30 @@ pub type TxBuf = Channel { - info: &'static Info, + info: TxInfoRef, _tx: CanTx<'d>, tx_buf: &'static TxBuf, } impl<'d, const TX_BUF_SIZE: usize> BufferedCanTx<'d, TX_BUF_SIZE> { fn new(info: &'static Info, _tx: CanTx<'d>, tx_buf: &'static TxBuf) -> Self { - Self { info, _tx, tx_buf }.setup() + Self { + info: TxInfoRef::new(info), + _tx, + tx_buf, + } + .setup() } fn setup(self) -> Self { // We don't want interrupts being processed while we change modes. - let tx_inner = super::common::ClassicBufferedTxInner { - tx_receiver: self.tx_buf.receiver().into(), - }; - self.info.state.lock(|state| { - state.borrow_mut().tx_mode = TxMode::Buffered(tx_inner); + critical_section::with(|_| { + let tx_inner = super::common::ClassicBufferedTxInner { + tx_receiver: self.tx_buf.receiver().into(), + }; + self.info.state.lock(|s| { + s.borrow_mut().tx_mode = TxMode::Buffered(tx_inner); + }); }); self } @@ -685,26 +692,18 @@ impl<'d, const TX_BUF_SIZE: usize> BufferedCanTx<'d, TX_BUF_SIZE> { /// Returns a sender that can be used for sending CAN frames. pub fn writer(&self) -> BufferedCanSender { - (self.info.internal_operation)(InternalOperation::NotifySenderCreated); BufferedCanSender { tx_buf: self.tx_buf.sender().into(), - waker: self.info.tx_waker, - internal_operation: self.info.internal_operation, + info: TxInfoRef::new(&self.info), } } } -impl<'d, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, TX_BUF_SIZE> { - fn drop(&mut self) { - (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); - } -} - /// CAN driver, receive half. #[allow(dead_code)] pub struct CanRx<'d> { _phantom: PhantomData<&'d ()>, - info: &'static Info, + info: RxInfoRef, } impl<'d> CanRx<'d> { @@ -714,19 +713,19 @@ impl<'d> CanRx<'d> { /// /// Returns a tuple of the time the message was received and the message frame pub async fn read(&mut self) -> Result { - RxMode::read(self.info).await + RxMode::read(&self.info).await } /// Attempts to read a CAN frame without blocking. /// /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. pub fn try_read(&mut self) -> Result { - RxMode::try_read(self.info) + RxMode::try_read(&self.info) } /// Waits while receive queue is empty. pub async fn wait_not_empty(&mut self) { - RxMode::wait_not_empty(self.info).await + RxMode::wait_not_empty(&self.info).await } /// Return a buffered instance of driver. User must supply Buffers @@ -734,7 +733,7 @@ impl<'d> CanRx<'d> { self, rxb: &'static mut RxBuf, ) -> BufferedCanRx<'d, RX_BUF_SIZE> { - BufferedCanRx::new(self.info, self, rxb) + BufferedCanRx::new(&self.info, self, rxb) } /// Accesses the filter banks owned by this CAN peripheral. @@ -742,7 +741,7 @@ impl<'d> CanRx<'d> { /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master /// peripheral instead. pub fn modify_filters(&mut self) -> MasterFilters<'_> { - unsafe { MasterFilters::new(self.info) } + unsafe { MasterFilters::new(&self.info) } } } @@ -751,23 +750,30 @@ pub type RxBuf = Channel { - info: &'static Info, + info: RxInfoRef, rx: CanRx<'d>, rx_buf: &'static RxBuf, } impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> { fn new(info: &'static Info, rx: CanRx<'d>, rx_buf: &'static RxBuf) -> Self { - BufferedCanRx { info, rx, rx_buf }.setup() + BufferedCanRx { + info: RxInfoRef::new(info), + rx, + rx_buf, + } + .setup() } fn setup(self) -> Self { // We don't want interrupts being processed while we change modes. - let rx_inner = super::common::ClassicBufferedRxInner { - rx_sender: self.rx_buf.sender().into(), - }; - self.info.state.lock(|state| { - state.borrow_mut().rx_mode = RxMode::Buffered(rx_inner); + critical_section::with(|_| { + let rx_inner = super::common::ClassicBufferedRxInner { + rx_sender: self.rx_buf.sender().into(), + }; + self.info.state.lock(|s| { + s.borrow_mut().rx_mode = RxMode::Buffered(rx_inner); + }); }); self } @@ -809,10 +815,9 @@ impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> { /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. pub fn reader(&self) -> BufferedCanReceiver { - (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated); BufferedCanReceiver { rx_buf: self.rx_buf.receiver().into(), - internal_operation: self.info.internal_operation, + info: RxInfoRef::new(&self.info), } } @@ -825,12 +830,6 @@ impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> { } } -impl<'d, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, RX_BUF_SIZE> { - fn drop(&mut self) { - (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); - } -} - impl Drop for Can<'_> { fn drop(&mut self) { // Cannot call `free()` because it moves the instance. @@ -1005,6 +1004,7 @@ impl TxMode { pub fn on_interrupt(&self) { T::info().state.lock(|state| { let tx_mode = &state.borrow().tx_mode; + match tx_mode { TxMode::NonBuffered(waker) => waker.wake(), TxMode::Buffered(buf) => { @@ -1062,8 +1062,7 @@ pub(crate) struct Info { rx0_interrupt: crate::interrupt::Interrupt, rx1_interrupt: crate::interrupt::Interrupt, sce_interrupt: crate::interrupt::Interrupt, - tx_waker: fn(), - internal_operation: fn(InternalOperation), + pub(crate) tx_waker: fn(), state: SharedState, /// The total number of filter banks available to the instance. @@ -1072,10 +1071,37 @@ pub(crate) struct Info { num_filter_banks: u8, } +impl Info { + pub(crate) fn adjust_reference_counter(&self, val: RefCountOp) { + self.state.lock(|s| { + let mut mut_state = s.borrow_mut(); + match val { + RefCountOp::NotifySenderCreated => { + mut_state.sender_instance_count += 1; + } + RefCountOp::NotifySenderDestroyed => { + mut_state.sender_instance_count -= 1; + if 0 == mut_state.sender_instance_count { + (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); + } + } + RefCountOp::NotifyReceiverCreated => { + mut_state.receiver_instance_count += 1; + } + RefCountOp::NotifyReceiverDestroyed => { + mut_state.receiver_instance_count -= 1; + if 0 == mut_state.receiver_instance_count { + (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); + } + } + } + }); + } +} + trait SealedInstance { fn info() -> &'static Info; fn regs() -> crate::pac::can::Can; - fn internal_operation(val: InternalOperation); } /// CAN instance trait. @@ -1133,43 +1159,16 @@ foreach_peripheral!( rx1_interrupt: crate::_generated::peripheral_interrupts::$inst::RX1::IRQ, sce_interrupt: crate::_generated::peripheral_interrupts::$inst::SCE::IRQ, tx_waker: crate::_generated::peripheral_interrupts::$inst::TX::pend, - internal_operation: peripherals::$inst::internal_operation, - state: embassy_sync::blocking_mutex::Mutex::new(core::cell::RefCell::new(State::new())), num_filter_banks: peripherals::$inst::NUM_FILTER_BANKS, + state: embassy_sync::blocking_mutex::Mutex::new(core::cell::RefCell::new(State::new())), }; &INFO } fn regs() -> crate::pac::can::Can { crate::pac::$inst } - - fn internal_operation(val: InternalOperation) { - peripherals::$inst::info().state.lock(|s| { - let mut mut_state = s.borrow_mut(); - //let mut_state = state as *mut State; - match val { - InternalOperation::NotifySenderCreated => { - mut_state.sender_instance_count += 1; - } - InternalOperation::NotifySenderDestroyed => { - mut_state.sender_instance_count -= 1; - if ( 0 == mut_state.sender_instance_count) { - (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); - } - } - InternalOperation::NotifyReceiverCreated => { - mut_state.receiver_instance_count += 1; - } - InternalOperation::NotifyReceiverDestroyed => { - mut_state.receiver_instance_count -= 1; - if ( 0 == mut_state.receiver_instance_count) { - (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); - } - } - } - }); - } } + impl Instance for peripherals::$inst { type TXInterrupt = crate::_generated::peripheral_interrupts::$inst::TX; type RX0Interrupt = crate::_generated::peripheral_interrupts::$inst::RX0; diff --git a/embassy-stm32/src/can/common.rs b/embassy-stm32/src/can/common.rs index 651fa12d5..980f33a04 100644 --- a/embassy-stm32/src/can/common.rs +++ b/embassy-stm32/src/can/common.rs @@ -24,22 +24,21 @@ pub(crate) struct FdBufferedTxInner { /// Sender that can be used for sending CAN frames. pub struct BufferedSender<'ch, FRAME> { pub(crate) tx_buf: embassy_sync::channel::SendDynamicSender<'ch, FRAME>, - pub(crate) waker: fn(), - pub(crate) tx_guard: TxGuard, + pub(crate) info: TxInfoRef, } impl<'ch, FRAME> BufferedSender<'ch, FRAME> { /// Async write frame to TX buffer. pub fn try_write(&mut self, frame: FRAME) -> Result<(), embassy_sync::channel::TrySendError> { self.tx_buf.try_send(frame)?; - (self.waker)(); + (self.info.tx_waker)(); Ok(()) } /// Async write frame to TX buffer. pub async fn write(&mut self, frame: FRAME) { self.tx_buf.send(frame).await; - (self.waker)(); + (self.info.tx_waker)(); } /// Allows a poll_fn to poll until the channel is ready to write @@ -52,8 +51,7 @@ impl<'ch, FRAME> Clone for BufferedSender<'ch, FRAME> { fn clone(&self) -> Self { Self { tx_buf: self.tx_buf, - waker: self.waker, - tx_guard: TxGuard::new(self.tx_guard.internal_operation), + info: TxInfoRef::new(&self.info), } } } @@ -64,7 +62,7 @@ pub type BufferedCanSender = BufferedSender<'static, Frame>; /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. pub struct BufferedReceiver<'ch, ENVELOPE> { pub(crate) rx_buf: embassy_sync::channel::SendDynamicReceiver<'ch, Result>, - pub(crate) rx_guard: RxGuard, + pub(crate) info: RxInfoRef, } impl<'ch, ENVELOPE> BufferedReceiver<'ch, ENVELOPE> { @@ -101,7 +99,7 @@ impl<'ch, ENVELOPE> Clone for BufferedReceiver<'ch, ENVELOPE> { fn clone(&self) -> Self { Self { rx_buf: self.rx_buf, - rx_guard: RxGuard::new(self.rx_guard.internal_operation), + info: RxInfoRef::new(&self.info), } } } @@ -109,37 +107,89 @@ impl<'ch, ENVELOPE> Clone for BufferedReceiver<'ch, ENVELOPE> { /// A BufferedCanReceiver for Classic CAN frames. pub type BufferedCanReceiver = BufferedReceiver<'static, Envelope>; -/// Implements RAII for the internal reference counting (TX side). Each TX type should contain one -/// of these. The new method and the Drop impl will automatically call the reference counting -/// function. Like this, the reference counting function does not need to be called manually for -/// each TX type. Transceiver types (TX and RX) should contain one TxGuard and one RxGuard. -pub(crate) struct TxGuard { - internal_operation: fn(InternalOperation), +/// Provides a reference to the driver internals and implements RAII for the internal reference +/// counting. Each type that can operate on the driver should contain either InfoRef +/// or the similar TxInfoRef or RxInfoRef. The new method and the Drop impl will automatically +/// call the reference counting function. Like this, the reference counting function does not +/// need to be called manually for each type. +pub(crate) struct InfoRef { + info: &'static super::Info, +} +impl InfoRef { + pub(crate) fn new(info: &'static super::Info) -> Self { + info.adjust_reference_counter(RefCountOp::NotifyReceiverCreated); + info.adjust_reference_counter(RefCountOp::NotifySenderCreated); + Self { info } + } +} + +impl Drop for InfoRef { + fn drop(&mut self) { + self.info.adjust_reference_counter(RefCountOp::NotifyReceiverDestroyed); + self.info.adjust_reference_counter(RefCountOp::NotifySenderDestroyed); + } +} + +impl core::ops::Deref for InfoRef { + type Target = &'static super::Info; + + fn deref(&self) -> &Self::Target { + &self.info + } } -impl TxGuard { - pub(crate) fn new(internal_operation: fn(InternalOperation)) -> Self { - internal_operation(InternalOperation::NotifySenderCreated); - Self { internal_operation } + +/// Provides a reference to the driver internals and implements RAII for the internal reference +/// counting for Tx only types. +/// See InfoRef for further doc. +pub(crate) struct TxInfoRef { + info: &'static super::Info, +} + +impl TxInfoRef { + pub(crate) fn new(info: &'static super::Info) -> Self { + info.adjust_reference_counter(RefCountOp::NotifySenderCreated); + Self { info } } } -impl Drop for TxGuard { + +impl Drop for TxInfoRef { fn drop(&mut self) { - (self.internal_operation)(InternalOperation::NotifySenderDestroyed); + self.info.adjust_reference_counter(RefCountOp::NotifySenderDestroyed); + } +} + +impl core::ops::Deref for TxInfoRef { + type Target = &'static super::Info; + + fn deref(&self) -> &Self::Target { + &self.info } } -/// Implements RAII for the internal reference counting (RX side). See TxGuard for further doc. -pub(crate) struct RxGuard { - internal_operation: fn(InternalOperation), +/// Provides a reference to the driver internals and implements RAII for the internal reference +/// counting for Rx only types. +/// See InfoRef for further doc. +pub(crate) struct RxInfoRef { + info: &'static super::Info, } -impl RxGuard { - pub(crate) fn new(internal_operation: fn(InternalOperation)) -> Self { - internal_operation(InternalOperation::NotifyReceiverCreated); - Self { internal_operation } + +impl RxInfoRef { + pub(crate) fn new(info: &'static super::Info) -> Self { + info.adjust_reference_counter(RefCountOp::NotifyReceiverCreated); + Self { info } } } -impl Drop for RxGuard { + +impl Drop for RxInfoRef { fn drop(&mut self) { - (self.internal_operation)(InternalOperation::NotifyReceiverDestroyed); + self.info.adjust_reference_counter(RefCountOp::NotifyReceiverDestroyed); + } +} + +impl core::ops::Deref for RxInfoRef { + type Target = &'static super::Info; + + fn deref(&self) -> &Self::Target { + &self.info } } diff --git a/embassy-stm32/src/can/enums.rs b/embassy-stm32/src/can/enums.rs index 97cb47640..6d91020fc 100644 --- a/embassy-stm32/src/can/enums.rs +++ b/embassy-stm32/src/can/enums.rs @@ -72,7 +72,7 @@ pub enum TryReadError { /// Internal Operation #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum InternalOperation { +pub enum RefCountOp { /// Notify receiver created NotifyReceiverCreated, /// Notify receiver destroyed diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index 2846fb44a..99e40ba62 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs @@ -21,7 +21,7 @@ use self::fd::config::*; use self::fd::filter::*; pub use self::fd::{config, filter}; pub use super::common::{BufferedCanReceiver, BufferedCanSender}; -use super::common::{RxGuard, TxGuard}; +use super::common::{InfoRef, RxInfoRef, TxInfoRef}; use super::enums::*; use super::frame::*; use super::util; @@ -168,11 +168,10 @@ fn calc_ns_per_timer_tick( pub struct CanConfigurator<'d> { _phantom: PhantomData<&'d ()>, config: crate::can::fd::config::FdCanConfig, - info: &'static Info, /// Reference to internals. properties: Properties, periph_clock: crate::time::Hertz, - raii_guards: (TxGuard, RxGuard), + info: InfoRef, } impl<'d> CanConfigurator<'d> { @@ -211,13 +210,9 @@ impl<'d> CanConfigurator<'d> { Self { _phantom: PhantomData, config, - info, properties: Properties::new(T::info()), periph_clock: T::frequency(), - raii_guards: ( - TxGuard::new(info.internal_operation), - RxGuard::new(info.internal_operation), - ), + info: InfoRef::new(info), } } @@ -266,7 +261,7 @@ impl<'d> CanConfigurator<'d> { /// Start in mode. pub fn start(self, mode: OperatingMode) -> Can<'d> { - let ns_per_timer_tick = calc_ns_per_timer_tick(self.info, self.periph_clock, self.config.frame_transmit); + let ns_per_timer_tick = calc_ns_per_timer_tick(&self.info, self.periph_clock, self.config.frame_transmit); self.info.state.lock(|s| { s.borrow_mut().ns_per_timer_tick = ns_per_timer_tick; }); @@ -274,10 +269,9 @@ impl<'d> CanConfigurator<'d> { Can { _phantom: PhantomData, config: self.config, - info: self.info, _mode: mode, - properties: Properties::new(self.info), - raii_guards: self.raii_guards, + properties: Properties::new(&self.info), + info: InfoRef::new(&self.info), } } @@ -301,10 +295,9 @@ impl<'d> CanConfigurator<'d> { pub struct Can<'d> { _phantom: PhantomData<&'d ()>, config: crate::can::fd::config::FdCanConfig, - info: &'static Info, _mode: OperatingMode, properties: Properties, - raii_guards: (TxGuard, RxGuard), + info: InfoRef, } impl<'d> Can<'d> { @@ -338,12 +331,12 @@ impl<'d> Can<'d> { /// can be replaced, this call asynchronously waits for a frame to be successfully /// transmitted, then tries again. pub async fn write(&mut self, frame: &Frame) -> Option { - TxMode::write(self.info, frame).await + TxMode::write(&self.info, frame).await } /// Returns the next received message frame pub async fn read(&mut self) -> Result { - RxMode::read_classic(self.info).await + RxMode::read_classic(&self.info).await } /// Queues the message to be sent but exerts backpressure. If a lower-priority @@ -351,12 +344,12 @@ impl<'d> Can<'d> { /// can be replaced, this call asynchronously waits for a frame to be successfully /// transmitted, then tries again. pub async fn write_fd(&mut self, frame: &FdFrame) -> Option { - TxMode::write_fd(self.info, frame).await + TxMode::write_fd(&self.info, frame).await } /// Returns the next received message frame pub async fn read_fd(&mut self) -> Result { - RxMode::read_fd(self.info).await + RxMode::read_fd(&self.info).await } /// Split instance into separate portions: Tx(write), Rx(read), common properties @@ -364,16 +357,14 @@ impl<'d> Can<'d> { ( CanTx { _phantom: PhantomData, - info: self.info, config: self.config, _mode: self._mode, - tx_guard: self.raii_guards.0, + info: TxInfoRef::new(&self.info), }, CanRx { _phantom: PhantomData, - info: self.info, _mode: self._mode, - rx_guard: self.raii_guards.1, + info: RxInfoRef::new(&self.info), }, Properties { info: self.properties.info, @@ -385,10 +376,9 @@ impl<'d> Can<'d> { Can { _phantom: PhantomData, config: tx.config, - info: tx.info, _mode: rx._mode, - properties: Properties::new(tx.info), - raii_guards: (tx.tx_guard, rx.rx_guard), + properties: Properties::new(&tx.info), + info: InfoRef::new(&tx.info), } } @@ -398,7 +388,7 @@ impl<'d> Can<'d> { tx_buf: &'static mut TxBuf, rxb: &'static mut RxBuf, ) -> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> { - BufferedCan::new(self.info, self._mode, tx_buf, rxb) + BufferedCan::new(&self.info, self._mode, tx_buf, rxb) } /// Return a buffered instance of driver with CAN FD support. User must supply Buffers @@ -407,7 +397,7 @@ impl<'d> Can<'d> { tx_buf: &'static mut TxFdBuf, rxb: &'static mut RxFdBuf, ) -> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> { - BufferedCanFd::new(self.info, self._mode, tx_buf, rxb) + BufferedCanFd::new(&self.info, self._mode, tx_buf, rxb) } } @@ -420,12 +410,11 @@ pub type TxBuf = Channel { _phantom: PhantomData<&'d ()>, - info: &'static Info, _mode: OperatingMode, tx_buf: &'static TxBuf, rx_buf: &'static RxBuf, properties: Properties, - _raii_guards: (TxGuard, RxGuard), + info: InfoRef, } impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> { @@ -437,15 +426,11 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, ) -> Self { BufferedCan { _phantom: PhantomData, - info, _mode, tx_buf, rx_buf, properties: Properties::new(info), - _raii_guards: ( - TxGuard::new(info.internal_operation), - RxGuard::new(info.internal_operation), - ), + info: InfoRef::new(info), } .setup() } @@ -486,8 +471,7 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, pub fn writer(&self) -> BufferedCanSender { BufferedCanSender { tx_buf: self.tx_buf.sender().into(), - waker: self.info.tx_waker, - tx_guard: TxGuard::new(self.info.internal_operation), + info: TxInfoRef::new(&self.info), } } @@ -495,7 +479,7 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, pub fn reader(&self) -> BufferedCanReceiver { BufferedCanReceiver { rx_buf: self.rx_buf.receiver().into(), - rx_guard: RxGuard::new(self.info.internal_operation), + info: RxInfoRef::new(&self.info), } } } @@ -515,12 +499,11 @@ pub type BufferedFdCanReceiver = super::common::BufferedReceiver<'static, FdEnve /// Buffered FDCAN Instance pub struct BufferedCanFd<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { _phantom: PhantomData<&'d ()>, - info: &'static Info, _mode: OperatingMode, tx_buf: &'static TxFdBuf, rx_buf: &'static RxFdBuf, properties: Properties, - _raii_guards: (TxGuard, RxGuard), + info: InfoRef, } impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> { @@ -532,15 +515,11 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<' ) -> Self { BufferedCanFd { _phantom: PhantomData, - info, _mode, tx_buf, rx_buf, properties: Properties::new(info), - _raii_guards: ( - TxGuard::new(info.internal_operation), - RxGuard::new(info.internal_operation), - ), + info: InfoRef::new(info), } .setup() } @@ -579,20 +558,17 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<' /// Returns a sender that can be used for sending CAN frames. pub fn writer(&self) -> BufferedFdCanSender { - (self.info.internal_operation)(InternalOperation::NotifySenderCreated); BufferedFdCanSender { tx_buf: self.tx_buf.sender().into(), - waker: self.info.tx_waker, - tx_guard: TxGuard::new(self.info.internal_operation), + info: TxInfoRef::new(&self.info), } } /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. pub fn reader(&self) -> BufferedFdCanReceiver { - (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated); BufferedFdCanReceiver { rx_buf: self.rx_buf.receiver().into(), - rx_guard: RxGuard::new(self.info.internal_operation), + info: RxInfoRef::new(&self.info), } } } @@ -600,9 +576,8 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<' /// FDCAN Rx only Instance pub struct CanRx<'d> { _phantom: PhantomData<&'d ()>, - info: &'static Info, _mode: OperatingMode, - rx_guard: RxGuard, + info: RxInfoRef, } impl<'d> CanRx<'d> { @@ -620,10 +595,9 @@ impl<'d> CanRx<'d> { /// FDCAN Tx only Instance pub struct CanTx<'d> { _phantom: PhantomData<&'d ()>, - info: &'static Info, config: crate::can::fd::config::FdCanConfig, _mode: OperatingMode, - tx_guard: TxGuard, + info: TxInfoRef, } impl<'c, 'd> CanTx<'d> { @@ -632,7 +606,7 @@ impl<'c, 'd> CanTx<'d> { /// can be replaced, this call asynchronously waits for a frame to be successfully /// transmitted, then tries again. pub async fn write(&mut self, frame: &Frame) -> Option { - TxMode::write(self.info, frame).await + TxMode::write(&self.info, frame).await } /// Queues the message to be sent but exerts backpressure. If a lower-priority @@ -640,7 +614,7 @@ impl<'c, 'd> CanTx<'d> { /// can be replaced, this call asynchronously waits for a frame to be successfully /// transmitted, then tries again. pub async fn write_fd(&mut self, frame: &FdFrame) -> Option { - TxMode::write_fd(self.info, frame).await + TxMode::write_fd(&self.info, frame).await } } @@ -907,21 +881,56 @@ impl State { } type SharedState = embassy_sync::blocking_mutex::Mutex>; -struct Info { +pub(crate) struct Info { regs: Registers, interrupt0: crate::interrupt::Interrupt, _interrupt1: crate::interrupt::Interrupt, - tx_waker: fn(), - internal_operation: fn(InternalOperation), + pub(crate) tx_waker: fn(), state: SharedState, } +impl Info { + pub(crate) fn adjust_reference_counter(&self, val: RefCountOp) { + self.state.lock(|s| { + let mut mut_state = s.borrow_mut(); + match val { + RefCountOp::NotifySenderCreated => { + mut_state.sender_instance_count += 1; + } + RefCountOp::NotifySenderDestroyed => { + mut_state.sender_instance_count -= 1; + if 0 == mut_state.sender_instance_count { + (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); + } + } + RefCountOp::NotifyReceiverCreated => { + mut_state.receiver_instance_count += 1; + } + RefCountOp::NotifyReceiverDestroyed => { + mut_state.receiver_instance_count -= 1; + if 0 == mut_state.receiver_instance_count { + (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); + } + } + } + if mut_state.sender_instance_count == 0 && mut_state.receiver_instance_count == 0 { + unsafe { + let tx_pin = crate::gpio::AnyPin::steal(mut_state.tx_pin_port.unwrap()); + tx_pin.set_as_disconnected(); + let rx_pin = crate::gpio::AnyPin::steal(mut_state.rx_pin_port.unwrap()); + rx_pin.set_as_disconnected(); + self.interrupt0.disable(); + } + } + }); + } +} + trait SealedInstance { const MSG_RAM_OFFSET: usize; fn info() -> &'static Info; fn registers() -> crate::can::fd::peripheral::Registers; - fn internal_operation(val: InternalOperation); } /// Instance trait @@ -943,41 +952,6 @@ macro_rules! impl_fdcan { impl SealedInstance for peripherals::$inst { const MSG_RAM_OFFSET: usize = $msg_ram_offset; - fn internal_operation(val: InternalOperation) { - peripherals::$inst::info().state.lock(|s| { - let mut mut_state = s.borrow_mut(); - match val { - InternalOperation::NotifySenderCreated => { - mut_state.sender_instance_count += 1; - } - InternalOperation::NotifySenderDestroyed => { - mut_state.sender_instance_count -= 1; - if ( 0 == mut_state.sender_instance_count) { - (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); - } - } - InternalOperation::NotifyReceiverCreated => { - mut_state.receiver_instance_count += 1; - } - InternalOperation::NotifyReceiverDestroyed => { - mut_state.receiver_instance_count -= 1; - if ( 0 == mut_state.receiver_instance_count) { - (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); - } - } - } - if mut_state.sender_instance_count == 0 && mut_state.receiver_instance_count == 0 { - unsafe { - let tx_pin = crate::gpio::AnyPin::steal(mut_state.tx_pin_port.unwrap()); - tx_pin.set_as_disconnected(); - let rx_pin = crate::gpio::AnyPin::steal(mut_state.rx_pin_port.unwrap()); - rx_pin.set_as_disconnected(); - rcc::disable::(); - } - } - }); - } - fn info() -> &'static Info { static INFO: Info = Info { @@ -985,7 +959,6 @@ macro_rules! impl_fdcan { interrupt0: crate::_generated::peripheral_interrupts::$inst::IT0::IRQ, _interrupt1: crate::_generated::peripheral_interrupts::$inst::IT1::IRQ, tx_waker: crate::_generated::peripheral_interrupts::$inst::IT0::pend, - internal_operation: peripherals::$inst::internal_operation, state: embassy_sync::blocking_mutex::Mutex::new(core::cell::RefCell::new(State::new())), }; &INFO -- cgit From 9cb5c6d001bff9615417d8b0999c9cd33fff79d6 Mon Sep 17 00:00:00 2001 From: jake-taf <149392739+jake-taf@users.noreply.github.com> Date: Mon, 23 Jun 2025 10:30:09 -0400 Subject: Fix issues #4333 Allow configs to be used in this macro --- embassy-stm32/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 973acc9bb..06c91ef97 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -178,7 +178,7 @@ pub use crate::_generated::interrupt; macro_rules! bind_interrupts { ($(#[$outer:meta])* $vis:vis struct $name:ident { $( - $(#[$inner:meta])* + $(#[doc = $doc:literal])* $(#[cfg($cond_irq:meta)])? $irq:ident => $( $(#[cfg($cond_handler:meta)])? @@ -194,7 +194,7 @@ macro_rules! bind_interrupts { #[allow(non_snake_case)] #[no_mangle] $(#[cfg($cond_irq)])? - $(#[$inner])* + $(#[doc = $doc])* unsafe extern "C" fn $irq() { $( $(#[cfg($cond_handler)])? -- cgit From 5da6e31a3e4a1175ddf34e1ebdf83a8d685ea521 Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Tue, 24 Jun 2025 16:19:33 +0200 Subject: Correct esp-hal link --- docs/pages/overview.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/overview.adoc b/docs/pages/overview.adoc index acd757795..18eaaeb75 100644 --- a/docs/pages/overview.adoc +++ b/docs/pages/overview.adoc @@ -30,7 +30,7 @@ The Embassy project maintains HALs for select hardware, but you can still use HA * link:https://docs.embassy.dev/embassy-nrf/[embassy-nrf], for the Nordic Semiconductor nRF52, nRF53, nRF91 series. * link:https://docs.embassy.dev/embassy-rp/[embassy-rp], for the Raspberry Pi RP2040 as well as RP235x microcontroller. * link:https://docs.embassy.dev/embassy-mspm0/[embassy-mspm0], for the Texas Instruments MSPM0 microcontrollers. -* link:https://github.com/esp-rs[esp-rs], for the Espressif Systems ESP32 series of chips. +* link:https://github.com/esp-rs/esp-hal[esp-hal], for the Espressif Systems ESP32 series of chips. * link:https://github.com/ch32-rs/ch32-hal[ch32-hal], for the WCH 32-bit RISC-V(CH32V) series of chips. * link:https://github.com/AlexCharlton/mpfs-hal[mpfs-hal], for the Microchip PolarFire SoC. * link:https://github.com/py32-rs/py32-hal[py32-hal], for the Puya Semiconductor PY32 series of chips. -- cgit From cbf61765f166edd7377e148291c102c61903efe8 Mon Sep 17 00:00:00 2001 From: Thomas Giesel Date: Mon, 9 Jun 2025 21:15:25 +0200 Subject: Generate pins for new opamp pin naming scheme The new code implements the corresponding traits for the common opamp pin naming scheme of all families, which is VINPx/VINMx. The same pin must not be used for multiple channels for the same opamp. For example, if VINM0 and VINM1 of the same opamp were assigned to the same pin, the channel would not be unique, meaning that the traits would be implemented in a conflicting manner. --- embassy-stm32/Cargo.toml | 4 ++-- embassy-stm32/build.rs | 33 +++++++++++++-------------------- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 034f51df9..4ee43e600 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-27ef8fba3483187e852eaf3796d827259f61e8ec" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8a502cec14512a6b833beb8f6e15f4a7b5ee7c06" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-27ef8fba3483187e852eaf3796d827259f61e8ec", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8a502cec14512a6b833beb8f6e15f4a7b5ee7c06", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index bb5ef53d7..8143c9a23 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1402,31 +1402,24 @@ fn main() { } if regs.kind == "opamp" { - if pin.signal.starts_with("VP") { - // Impl NonInvertingPin for the VP* signals (VP0, VP1, VP2, etc) - let peri = format_ident!("{}", p.name); - let pin_name = format_ident!("{}", pin.pin); - let ch: u8 = pin.signal.strip_prefix("VP").unwrap().parse().unwrap(); - - g.extend(quote! { - impl_opamp_vp_pin!( #peri, #pin_name, #ch); - }) - } else if pin.signal.starts_with("VINM") { - // Impl NonInvertingPin for the VINM* signals ( VINM0, VINM1, etc) - // STM32G4 - let peri = format_ident!("{}", p.name); - let pin_name = format_ident!("{}", pin.pin); - let ch: Result = pin.signal.strip_prefix("VINM").unwrap().parse(); - - if let Ok(ch) = ch { + let peri = format_ident!("{}", p.name); + let pin_name = format_ident!("{}", pin.pin); + if let Some(ch_str) = pin.signal.strip_prefix("VINP") { + // Impl NonInvertingPin for VINP0, VINP1 etc. + if let Ok(ch) = ch_str.parse::() { + g.extend(quote! { + impl_opamp_vp_pin!( #peri, #pin_name, #ch ); + }); + } + } else if let Some(ch_str) = pin.signal.strip_prefix("VINM") { + // Impl InvertingPin for VINM0, VINM1 etc. + if let Ok(ch) = ch_str.parse::() { g.extend(quote! { impl_opamp_vn_pin!( #peri, #pin_name, #ch); - }) + }); } } else if pin.signal == "VOUT" { // Impl OutputPin for the VOUT pin - let peri = format_ident!("{}", p.name); - let pin_name = format_ident!("{}", pin.pin); g.extend(quote! { impl_opamp_vout_pin!( #peri, #pin_name ); }) -- cgit From ca14f5452959bb23499f057ca78cf21e0e69dccd Mon Sep 17 00:00:00 2001 From: Thomas Giesel Date: Wed, 25 Jun 2025 21:06:39 +0200 Subject: Adapt opamp driver to new opamp IP version numbers --- embassy-stm32/src/opamp.rs | 56 +++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs index 2eb2e61c1..0467dbce3 100644 --- a/embassy-stm32/src/opamp.rs +++ b/embassy-stm32/src/opamp.rs @@ -7,7 +7,7 @@ use crate::pac::opamp::vals::*; use crate::Peri; /// Performs a busy-wait delay for a specified number of microseconds. -#[cfg(opamp_g4)] +#[cfg(opamp_v5)] fn blocking_delay_ms(ms: u32) { #[cfg(feature = "time")] embassy_time::block_for(embassy_time::Duration::from_millis(ms as u64)); @@ -23,13 +23,13 @@ pub enum OpAmpGain { Mul4, Mul8, Mul16, - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] Mul32, - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] Mul64, } -#[cfg(opamp_g4)] +#[cfg(opamp_v5)] enum OpAmpDifferentialPair { P, N, @@ -53,7 +53,7 @@ pub struct OpAmpOutput<'d, T: Instance> { /// OpAmp internal outputs, wired directly to ADC inputs. /// /// This struct can be used as an ADC input. -#[cfg(opamp_g4)] +#[cfg(opamp_v5)] pub struct OpAmpInternalOutput<'d, T: Instance> { _inner: &'d OpAmp<'d, T>, } @@ -67,8 +67,8 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// Create a new driver instance. /// /// Does not enable the opamp, but does set the speed mode on some families. - pub fn new(opamp: Peri<'d, T>, #[cfg(opamp_g4)] speed: OpAmpSpeed) -> Self { - #[cfg(opamp_g4)] + pub fn new(opamp: Peri<'d, T>, #[cfg(opamp_v5)] speed: OpAmpSpeed) -> Self { + #[cfg(opamp_v5)] T::regs().csr().modify(|w| { w.set_opahsm(speed == OpAmpSpeed::HighSpeed); }); @@ -94,15 +94,15 @@ impl<'d, T: Instance> OpAmp<'d, T> { in_pin.set_as_analog(); out_pin.set_as_analog(); - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] let vm_sel = VmSel::OUTPUT; - #[cfg(not(opamp_g4))] + #[cfg(not(opamp_v5))] let vm_sel = VmSel::from_bits(0b11); T::regs().csr().modify(|w| { w.set_vp_sel(VpSel::from_bits(in_pin.channel())); w.set_vm_sel(vm_sel); - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] w.set_opaintoen(false); w.set_opampen(true); }); @@ -129,12 +129,12 @@ impl<'d, T: Instance> OpAmp<'d, T> { in_pin.set_as_analog(); out_pin.set_as_analog(); - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] let vm_sel = VmSel::PGA; - #[cfg(not(opamp_g4))] + #[cfg(not(opamp_v5))] let vm_sel = VmSel::from_bits(0b10); - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] let pga_gain = match gain { OpAmpGain::Mul2 => PgaGain::GAIN2, OpAmpGain::Mul4 => PgaGain::GAIN4, @@ -143,7 +143,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { OpAmpGain::Mul32 => PgaGain::GAIN32, OpAmpGain::Mul64 => PgaGain::GAIN64, }; - #[cfg(not(opamp_g4))] + #[cfg(not(opamp_v5))] let pga_gain = PgaGain::from_bits(match gain { OpAmpGain::Mul2 => 0b00, OpAmpGain::Mul4 => 0b01, @@ -155,7 +155,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { w.set_vp_sel(VpSel::from_bits(in_pin.channel())); w.set_vm_sel(vm_sel); w.set_pga_gain(pga_gain); - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] w.set_opaintoen(false); w.set_opampen(true); }); @@ -170,7 +170,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// preventing it being used elsewhere. The `OpAmpOutput` can then be /// directly used as an ADC input. The opamp will be disabled when the /// [`OpAmpOutput`] is dropped. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn buffer_dac(&mut self, out_pin: Peri<'_, impl OutputPin + crate::gpio::Pin>) -> OpAmpOutput<'_, T> { out_pin.set_as_analog(); @@ -194,7 +194,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// /// The returned `OpAmpInternalOutput` struct may be used as an ADC input. /// The opamp output will be disabled when it is dropped. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn buffer_int( &mut self, pin: Peri<'_, impl NonInvertingPin + crate::gpio::Pin>, @@ -204,7 +204,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { T::regs().csr().modify(|w| { w.set_vp_sel(VpSel::from_bits(pin.channel())); w.set_vm_sel(VmSel::OUTPUT); - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] w.set_opaintoen(true); w.set_opampen(true); }); @@ -220,7 +220,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// /// The returned `OpAmpInternalOutput` struct may be used as an ADC input. /// The opamp output will be disabled when it is dropped. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn pga_int( &mut self, pin: Peri<'_, impl NonInvertingPin + crate::gpio::Pin>, @@ -257,7 +257,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// /// The returned `OpAmpInternalOutput` struct may be used as an ADC /// input. The opamp output will be disabled when it is dropped. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn standalone_dac_int( &mut self, m_pin: Peri<'_, impl InvertingPin + crate::gpio::Pin>, @@ -285,7 +285,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// The output pin is held within the returned [`OpAmpOutput`] struct, /// preventing it being used elsewhere. The opamp will be disabled when /// the [`OpAmpOutput`] is dropped. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn standalone_dac_ext( &mut self, m_pin: Peri<'_, impl InvertingPin + crate::gpio::Pin>, @@ -315,7 +315,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// The output pin is held within the returned [`OpAmpOutput`] struct, /// preventing it being used elsewhere. The opamp will be disabled when /// the [`OpAmpOutput`] is dropped. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn standalone_ext( &mut self, p_pin: Peri<'d, impl NonInvertingPin + crate::gpio::Pin>, @@ -346,7 +346,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// /// The returned `OpAmpOutput` struct may be used as an ADC /// input. The opamp output will be disabled when it is dropped. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn standalone_int( &mut self, p_pin: Peri<'d, impl NonInvertingPin + crate::gpio::Pin>, @@ -374,7 +374,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// while for high-speed mode, only the P differential pair is calibrated. /// /// Calibrating a differential pair requires waiting 12ms in the worst case (binary method). - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn calibrate(&mut self) { T::regs().csr().modify(|w| { w.set_opampen(true); @@ -403,7 +403,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// The calibration range is from 0 to 31. /// /// The result is stored in the OPAMP_CSR register. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] fn calibrate_differential_pair(&mut self, pair: OpAmpDifferentialPair) { let mut low = 0; let mut high = 31; @@ -460,7 +460,7 @@ impl<'d, T: Instance> Drop for OpAmpOutput<'d, T> { } } -#[cfg(opamp_g4)] +#[cfg(opamp_v5)] impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> { fn drop(&mut self) { T::regs().csr().modify(|w| { @@ -545,7 +545,7 @@ foreach_peripheral!( }; ); -#[cfg(opamp_g4)] +#[cfg(opamp_v5)] macro_rules! impl_opamp_internal_output { ($inst:ident, $adc:ident, $ch:expr) => { foreach_adc!( @@ -567,7 +567,7 @@ macro_rules! impl_opamp_internal_output { }; } -#[cfg(opamp_g4)] +#[cfg(opamp_v5)] foreach_peripheral!( (opamp, OPAMP1) => { impl_opamp_internal_output!(OPAMP1, ADC1, 13); -- cgit From 51675e9bc767080b0e9c47f106ad3ef4251f9d8b Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Wed, 25 Jun 2025 19:22:18 -0700 Subject: Added STM32WBA6XXX devices as features Added 2 wba6 features to cargo batch in ci.sh WIP Added default RTC rust version for undefined peripherals Added missing generated RTC peripheral to be handled by rtc/v3.rs Reordered cfg_attrs in rtc/mod.rs --- ci.sh | 2 ++ embassy-stm32/Cargo.toml | 22 ++++++++++++++++++++-- embassy-stm32/src/rtc/mod.rs | 2 +- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/ci.sh b/ci.sh index e1fdf998a..33152e559 100755 --- a/ci.sh +++ b/ci.sh @@ -169,6 +169,8 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h562ag,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba50ke,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba55ug,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba62cg,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba65ri,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u5f9zj,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u5g9nj,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb35ce,defmt,exti,time-driver-any,time \ diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 4ee43e600..552113a79 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8a502cec14512a6b833beb8f6e15f4a7b5ee7c06" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-0069be7389d0378d826003304d72a13008f3ebce" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8a502cec14512a6b833beb8f6e15f4a7b5ee7c06", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-0069be7389d0378d826003304d72a13008f3ebce", default-features = false, features = ["metadata"] } [features] default = ["rt"] @@ -1634,6 +1634,24 @@ stm32wba55he = [ "stm32-metapac/stm32wba55he" ] stm32wba55hg = [ "stm32-metapac/stm32wba55hg" ] stm32wba55ue = [ "stm32-metapac/stm32wba55ue" ] stm32wba55ug = [ "stm32-metapac/stm32wba55ug" ] +stm32wba62cg = [ "stm32-metapac/stm32wba62cg" ] +stm32wba62ci = [ "stm32-metapac/stm32wba62ci" ] +stm32wba62mg = [ "stm32-metapac/stm32wba62mg" ] +stm32wba62mi = [ "stm32-metapac/stm32wba62mi" ] +stm32wba62pg = [ "stm32-metapac/stm32wba62pg" ] +stm32wba62pi = [ "stm32-metapac/stm32wba62pi" ] +stm32wba63cg = [ "stm32-metapac/stm32wba63cg" ] +stm32wba63ci = [ "stm32-metapac/stm32wba63ci" ] +stm32wba64cg = [ "stm32-metapac/stm32wba64cg" ] +stm32wba64ci = [ "stm32-metapac/stm32wba64ci" ] +stm32wba65cg = [ "stm32-metapac/stm32wba65cg" ] +stm32wba65ci = [ "stm32-metapac/stm32wba65ci" ] +stm32wba65mg = [ "stm32-metapac/stm32wba65mg" ] +stm32wba65mi = [ "stm32-metapac/stm32wba65mi" ] +stm32wba65pg = [ "stm32-metapac/stm32wba65pg" ] +stm32wba65pi = [ "stm32-metapac/stm32wba65pi" ] +stm32wba65rg = [ "stm32-metapac/stm32wba65rg" ] +stm32wba65ri = [ "stm32-metapac/stm32wba65ri" ] stm32wl54cc-cm4 = [ "stm32-metapac/stm32wl54cc-cm4", "_dual-core", "_core-cm4" ] stm32wl54cc-cm0p = [ "stm32-metapac/stm32wl54cc-cm0p", "_dual-core", "_core-cm0p" ] stm32wl54jc-cm4 = [ "stm32-metapac/stm32wl54jc-cm4", "_dual-core", "_core-cm4" ] diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 49f423f37..2c5aaca35 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -25,7 +25,7 @@ use crate::time::Hertz; ), path = "v2.rs" )] -#[cfg_attr(any(rtc_v3, rtc_v3u5, rtc_v3l5, rtc_v3h7rs), path = "v3.rs")] +#[cfg_attr(any(rtc_v3, rtc_v3u5, rtc_v3l5, rtc_v3h7rs, rtc_v3c0), path = "v3.rs")] mod _version; #[allow(unused_imports)] pub use _version::*; -- cgit From f0e3ca9ee4efcb4a9618983190068d866631fa28 Mon Sep 17 00:00:00 2001 From: Kevin Lannen Date: Mon, 23 Jun 2025 22:03:43 -0600 Subject: STM32H7RS Examples: Add OPI functionality to the XSPI example Cleans up the SPI and OPI commands to match the datasheet for the flash used on the Nucleo board Creates a separate impl for OPI operations --- examples/stm32h7rs/src/bin/xspi_memory_mapped.rs | 850 ++++++++++++++++++----- 1 file changed, 677 insertions(+), 173 deletions(-) diff --git a/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs b/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs index 88d914180..59045ca2e 100644 --- a/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs +++ b/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs @@ -3,7 +3,8 @@ //! For Nucleo STM32H7S3L8 MB1737, has MX25UW25645GXDI00 //! -//! TODO: Currently this only uses single SPI, pending flash chip documentation for octo SPI. + +use core::cmp::min; use defmt::info; use embassy_executor::Spawner; @@ -52,14 +53,16 @@ async fn main(_spawner: Spawner) { fifo_threshold: FIFOThresholdLevel::_4Bytes, memory_type: MemoryType::Macronix, delay_hold_quarter_cycle: true, - // memory_type: MemoryType::Micron, - // delay_hold_quarter_cycle: false, device_size: MemorySize::_32MiB, chip_select_high_time: ChipSelectHighTime::_2Cycle, free_running_clock: false, clock_mode: false, wrap_size: WrapSize::None, - // 300mhz / (4+1) = 60mhz. Unsure the limit, need to find a MX25UW25645GXDI00 datasheet. + // 300 MHz clock / (3 + 1) = 75 MHz. This is above the max for READ instructions so the + // FAST READ must be used. The nucleo board's flash can run at up to 133 MHz in SPI mode + // and 200 MHz in OPI mode. This clock prescaler must be even otherwise the clock will not + // have symmetric high and low times. + // The clock can also be fed by one of the PLLs to allow for more flexible clock rates. clock_prescaler: 3, sample_shifting: false, chip_select_boundary: 0, @@ -71,28 +74,41 @@ async fn main(_spawner: Spawner) { // Not necessary, but recommended if using XIP cor.SCB.enable_icache(); + // Note: Enabling data cache can cause issues with DMA transfers. cor.SCB.enable_dcache(&mut cor.CPUID); let xspi = embassy_stm32::xspi::Xspi::new_blocking_xspi( p.XSPI2, p.PN6, p.PN2, p.PN3, p.PN4, p.PN5, p.PN8, p.PN9, p.PN10, p.PN11, p.PN1, spi_config, ); - let mut flash = FlashMemory::new(xspi).await; + let mut flash = SpiFlashMemory::new(xspi); let flash_id = flash.read_id(); info!("FLASH ID: {=[u8]:x}", flash_id); - let mut wr_buf = [0u8; 8]; - for i in 0..8 { - wr_buf[i] = 0x90 + i as u8; - } - let mut rd_buf = [0u8; 8]; - flash.erase_sector(0).await; - flash.write_memory(0, &wr_buf, true).await; - flash.read_memory(0, &mut rd_buf, true); - info!("WRITE BUF: {=[u8]:#X}", wr_buf); - info!("READ BUF: {=[u8]:#X}", rd_buf); - flash.enable_mm().await; + // Erase the first sector + flash.erase_sector(0); + + // Write some data into the flash. This writes more than one page to test that functionality. + let mut wr_buf = [0u8; 512]; + let base_number: u8 = 0x90; + for i in 0..512 { + wr_buf[i] = base_number.wrapping_add(i as u8); + } + flash.write_memory(0, &wr_buf); + + // Read the data back and verify it. + let mut rd_buf = [0u8; 512]; + let start_time = embassy_time::Instant::now(); + flash.read_memory(0, &mut rd_buf); + let elapsed = start_time.elapsed(); + info!("Read 512 bytes in {} us in SPI mode", elapsed.as_micros()); + info!("WRITE BUF: {=[u8]:#X}", wr_buf[0..32]); + info!("READ BUF: {=[u8]:#X}", rd_buf[0..32]); + + assert_eq!(wr_buf, rd_buf, "Read buffer does not match write buffer"); + + flash.enable_mm(); info!("Enabled memory mapped mode"); let first_u32 = unsafe { *(0x70000000 as *const u32) }; @@ -103,10 +119,53 @@ async fn main(_spawner: Spawner) { assert_eq!(second_u32, 0x97969594); info!("second_u32 {:08x}", first_u32); - flash.disable_mm().await; + flash.disable_mm(); info!("Disabled memory mapped mode"); + let flash_id = flash.read_id(); + info!("FLASH ID: {=[u8]:x}", flash_id); + + let mut flash = flash.into_octo(); + + Timer::after_millis(100).await; + + let flash_id = flash.read_id(); + info!("FLASH ID in OPI mode: {=[u8]:x}", flash_id); + + flash.erase_sector(0); + + let mut rd_buf = [0u8; 512]; + flash.read_memory(0, &mut rd_buf); + info!("READ BUF after erase: {=[u8]:#X}", rd_buf[0..32]); + + assert_eq!(rd_buf, [0xFF; 512], "Read buffer is not all 0xFF after erase"); + + flash.write_memory(0, &wr_buf); + let start = embassy_time::Instant::now(); + flash.read_memory(0, &mut rd_buf); + let elapsed = start.elapsed(); + info!("Read 512 bytes in {} us in OPI mode", elapsed.as_micros()); + info!("READ BUF after write: {=[u8]:#X}", rd_buf[0..32]); + assert_eq!(wr_buf, rd_buf, "Read buffer does not match write buffer in OPI mode"); + + flash.enable_mm(); + info!("Enabled memory mapped mode in OPI mode"); + let first_u32 = unsafe { *(0x70000000 as *const u32) }; + assert_eq!(first_u32, 0x93929190); + info!("first_u32 {:08x}", first_u32); + let second_u32 = unsafe { *(0x70000004 as *const u32) }; + assert_eq!(second_u32, 0x97969594); + info!("second_u32 {:08x}", first_u32); + flash.disable_mm(); + info!("Disabled memory mapped mode in OPI mode"); + + // Reset back to SPI mode + let mut flash = flash.into_spi(); + let flash_id = flash.read_id(); + info!("FLASH ID back in SPI mode: {=[u8]:x}", flash_id); + info!("DONE"); + // Output pin PE3 let mut led = Output::new(p.PE3, Level::Low, Speed::Low); @@ -116,80 +175,268 @@ async fn main(_spawner: Spawner) { } } -const MEMORY_PAGE_SIZE: usize = 8; - -const CMD_READ: u8 = 0x0B; -const _CMD_QUAD_READ: u8 = 0x6B; - -const CMD_WRITE_PG: u8 = 0x02; -const _CMD_QUAD_WRITE_PG: u8 = 0x32; - -const CMD_READ_ID: u8 = 0x9F; -const CMD_READ_ID_OCTO: u16 = 0x9F60; +const MEMORY_PAGE_SIZE: usize = 256; -const CMD_ENABLE_RESET: u8 = 0x66; -const CMD_RESET: u8 = 0x99; - -const CMD_WRITE_ENABLE: u8 = 0x06; - -const CMD_CHIP_ERASE: u8 = 0xC7; -const CMD_SECTOR_ERASE: u8 = 0x20; -const CMD_BLOCK_ERASE_32K: u8 = 0x52; -const CMD_BLOCK_ERASE_64K: u8 = 0xD8; - -const CMD_READ_SR: u8 = 0x05; -const CMD_READ_CR: u8 = 0x35; - -const CMD_WRITE_SR: u8 = 0x01; -const CMD_WRITE_CR: u8 = 0x31; +/// Implementation of access to flash chip using SPI. +/// +/// Chip commands are hardcoded as it depends on used chip. +/// This targets a MX25UW25645GXDI00. +pub struct SpiFlashMemory { + xspi: Xspi<'static, I, Blocking>, +} -/// Implementation of access to flash chip. +/// Implementation of access to flash chip using Octo SPI. /// /// Chip commands are hardcoded as it depends on used chip. /// This targets a MX25UW25645GXDI00. -pub struct FlashMemory { +pub struct OpiFlashMemory { xspi: Xspi<'static, I, Blocking>, } -impl FlashMemory { - pub async fn new(xspi: Xspi<'static, I, Blocking>) -> Self { - let mut memory = Self { xspi }; +/// SPI mode commands for MX25UW25645G flash memory +#[allow(dead_code)] +#[repr(u8)] +enum SpiCommand { + // Array access commands + /// Read data bytes using 3-byte address (up to 50 MHz) + Read3B = 0x03, + /// Fast read data bytes using 3-byte address with 8 dummy cycles (up to 133 MHz) + FastRead3B = 0x0B, + /// Program 1-256 bytes of data using 3-byte address + PageProgram3B = 0x02, + /// Erase 4KB sector using 3-byte address + SectorErase3B = 0x20, + /// Erase 64KB block using 3-byte address + BlockErase3B = 0xD8, + /// Read data bytes using 4-byte address (up to 50 MHz) + Read4B = 0x13, + /// Fast read data bytes using 4-byte address with 8 dummy cycles (up to 133 MHz) + FastRead4B = 0x0C, + /// Program 1-256 bytes of data using 4-byte address + PageProgram4B = 0x12, + /// Erase 4KB sector using 4-byte address + SectorErase4B = 0x21, + /// Erase 64KB block using 4-byte address + BlockErase4B = 0xDC, + /// Erase entire chip (only if no blocks are protected) + ChipErase = 0x60, + + // Write Buffer Access commands + /// Read data from the 256-byte page buffer + ReadBuffer = 0x25, + /// Initialize write-to-buffer sequence, clears buffer and writes initial data + WriteBufferInitial = 0x22, + /// Continue writing data to buffer (used between WRBI and WRCF) + WriteBufferContinue = 0x24, + /// Confirm write operation, programs buffer contents to flash array + WriteBufferConfirm = 0x31, + + // Device operation commands + /// Set Write Enable Latch (WEL) bit, required before write/program/erase operations + WriteEnable = 0x06, + /// Clear Write Enable Latch (WEL) bit + WriteDisable = 0x04, + /// Select write protection mode (BP mode or Advanced Sector Protection) + WriteProtectSelection = 0x68, + /// Suspend ongoing program or erase operation to allow read access + ProgramEraseSuspend = 0xB0, + /// Resume suspended program or erase operation + ProgramEraseResume = 0x30, + /// Enter deep power-down mode for minimum power consumption + DeepPowerDown = 0xB9, + /// Exit deep power-down mode and return to standby + ReleaseFromDeepPowerDown = 0xAB, + /// No operation, can terminate Reset Enable command + NoOperation = 0x00, + /// Enable reset operation (must precede Reset Memory command) + ResetEnable = 0x66, + /// Reset device to power-on state (requires prior Reset Enable) + ResetMemory = 0x99, + /// Protect all sectors using Dynamic Protection Bits (DPB) + GangBlockLock = 0x7E, + /// Unprotect all sectors by clearing Dynamic Protection Bits (DPB) + GangBlockUnlock = 0x98, + + // Register Access commands + /// Read 3-byte device identification (manufacturer ID + device ID) + ReadIdentification = 0x9F, + /// Read Serial Flash Discoverable Parameters (SFDP) table + ReadSFDP = 0x5A, + /// Read 8-bit Status Register (WIP, WEL, BP bits, etc.) + ReadStatusRegister = 0x05, + /// Read 8-bit Configuration Register (ODS, TB, PBE bits) + ReadConfigurationRegister = 0x15, + /// Write Status and/or Configuration Register (1-2 bytes) + WriteStatusConfigurationRegister = 0x01, + /// Read Configuration Register 2 from specified 4-byte address + ReadConfigurationRegister2 = 0x71, + /// Write Configuration Register 2 to specified 4-byte address + WriteConfigurationRegister2 = 0x72, + /// Read 8-bit Security Register (protection status, suspend bits) + ReadSecurityRegister = 0x2B, + /// Write Security Register to set customer lock-down bit + WriteSecurityRegister = 0x2F, + /// Read 32-bit Fast Boot Register (boot address and configuration) + ReadFastBootRegister = 0x16, + /// Write 32-bit Fast Boot Register + WriteFastBootRegister = 0x17, + /// Erase Fast Boot Register (disable fast boot feature) + EraseFastBootRegister = 0x18, + /// Set burst/wrap length for read operations (16/32/64 bytes) + SetBurstLength = 0xC0, + /// Enter 8K-bit secured OTP mode for programming unique identifiers + EnterSecuredOTP = 0xB1, + /// Exit secured OTP mode and return to main array access + ExitSecuredOTP = 0xC1, + /// Write Lock Register to control SPB protection mode + WriteLockRegister = 0x2C, + /// Read Lock Register status + ReadLockRegister = 0x2D, + /// Program Solid Protection Bit (SPB) for specified sector/block + WriteSPB = 0xE3, + /// Erase all Solid Protection Bits (SPB) + EraseSPB = 0xE4, + /// Read Solid Protection Bit (SPB) status for specified sector/block + ReadSPB = 0xE2, + /// Write Dynamic Protection Bit (DPB) for specified sector + WriteDPB = 0xE1, + /// Read Dynamic Protection Bit (DPB) status for specified sector + ReadDPB = 0xE0, + /// Read 64-bit password register (only in Solid Protection mode) + ReadPassword = 0x27, + /// Write 64-bit password register + WritePassword = 0x28, + /// Unlock SPB operations using 64-bit password + PasswordUnlock = 0x29, +} - memory.reset_memory().await; - memory.enable_octo(); - memory - } +/// OPI mode commands for MX25UW25645G flash memory +#[allow(dead_code)] +#[repr(u16)] +enum OpiCommand { + // Array access commands + /// Read data using 8 I/O lines in STR mode with configurable dummy cycles (up to 200 MHz) + OctaRead = 0xEC13, + /// Read data using 8 I/O lines in DTR mode with configurable dummy cycles (up to 200 MHz) + OctaDTRRead = 0xEE11, + /// Program 1-256 bytes using 4-byte address and 8 I/O lines + PageProgram4B = 0x12ED, + /// Erase 4KB sector using 4-byte address + SectorErase4B = 0x21DE, + /// Erase 64KB block using 4-byte address + BlockErase4B = 0xDC23, + /// Erase entire chip (only if no blocks are protected) + ChipErase = 0x609F, + + // Write Buffer Access commands + /// Read data from the 256-byte page buffer using 4-byte address + ReadBuffer = 0x25DA, + /// Initialize interruptible write-to-buffer sequence with 4-byte address + WriteBufferInitial = 0x22DD, + /// Continue writing data to buffer during interruptible sequence + WriteBufferContinue = 0x24DB, + /// Confirm and execute write operation from buffer to flash array + WriteBufferConfirm = 0x31CE, + + // Device operation commands + /// Set Write Enable Latch (WEL) bit, required before write/program/erase operations + WriteEnable = 0x06F9, + /// Clear Write Enable Latch (WEL) bit, aborts write-to-buffer sequence + WriteDisable = 0x04FB, + /// Select write protection mode (BP mode or Advanced Sector Protection) - OTP bit + WriteProtectSelection = 0x6897, + /// Suspend ongoing program or erase operation to allow read from other banks + ProgramEraseSuspend = 0xB04F, + /// Resume suspended program or erase operation + ProgramEraseResume = 0x30CF, + /// Enter deep power-down mode for minimum power consumption + DeepPowerDown = 0xB946, + /// Exit deep power-down mode and return to standby + ReleaseFromDeepPowerDown = 0xAB54, + /// No operation, can terminate Reset Enable command + NoOperation = 0x00FF, + /// Enable reset operation (must precede Reset Memory command) + ResetEnable = 0x6699, + /// Reset device to power-on state, clears volatile settings + ResetMemory = 0x9966, + /// Protect all sectors using Dynamic Protection Bits (DPB) + GangBlockLock = 0x7E81, + /// Unprotect all sectors by clearing Dynamic Protection Bits (DPB) + GangBlockUnlock = 0x9867, + + // Register Access commands + /// Read 3-byte device identification with 4-byte dummy address + ReadIdentification = 0x9F60, + /// Read Serial Flash Discoverable Parameters (SFDP) table with 4-byte address + ReadSFDP = 0x5AA5, + /// Read 8-bit Status Register with 4-byte dummy address + ReadStatusRegister = 0x05FA, + /// Read 8-bit Configuration Register with specific address (00000001h) + ReadConfigurationRegister = 0x15EA, + /// Write 8-bit Status Register with specific address (00000000h) or Configuration Register with address (00000001h) + WriteStatusConfigurationRegister = 0x01FE, + /// Read Configuration Register 2 from specified 4-byte address + ReadConfigurationRegister2 = 0x718E, + /// Write Configuration Register 2 to specified 4-byte address + WriteConfigurationRegister2 = 0x728D, + /// Read 8-bit Security Register with 4-byte dummy address + ReadSecurityRegister = 0x2BD4, + /// Write Security Register to set customer lock-down bit + WriteSecurityRegister = 0x2FD0, + /// Set burst/wrap length for read operations with 4-byte dummy address + SetBurstLength = 0xC03F, + /// Read 32-bit Fast Boot Register with 4-byte dummy address + ReadFastBootRegister = 0x16E9, + /// Write 32-bit Fast Boot Register with 4-byte dummy address + WriteFastBootRegister = 0x17E8, + /// Erase Fast Boot Register (disable fast boot feature) + EraseFastBootRegister = 0x18E7, + /// Enter 8K-bit secured OTP mode for programming unique identifiers + EnterSecuredOTP = 0xB14E, + /// Exit secured OTP mode and return to main array access + ExitSecuredOTP = 0xC13E, + /// Write Lock Register to control SPB protection mode with 4-byte dummy address + WriteLockRegister = 0x2CD3, + /// Read Lock Register status with 4-byte dummy address + ReadLockRegister = 0x2DD2, + /// Program Solid Protection Bit (SPB) for specified 4-byte address + WriteSPB = 0xE31C, + /// Erase all Solid Protection Bits (SPB) + EraseSPB = 0xE41B, + /// Read Solid Protection Bit (SPB) status for specified 4-byte address + ReadSPB = 0xE21D, + /// Write Dynamic Protection Bit (DPB) for specified 4-byte address + WriteDPB = 0xE11E, + /// Read Dynamic Protection Bit (DPB) status for specified 4-byte address + ReadDPB = 0xE01F, + /// Read 64-bit password register with 4-byte dummy address and 20 dummy cycles + ReadPassword = 0x27D8, + /// Write 64-bit password register with 4-byte dummy address + WritePassword = 0x28D7, + /// Unlock SPB operations using 64-bit password with 4-byte dummy address + PasswordUnlock = 0x29D6, +} - async fn qpi_mode(&mut self) { - // Enter qpi mode - self.exec_command(0x38).await; +impl SpiFlashMemory { + pub fn new(xspi: Xspi<'static, I, Blocking>) -> Self { + let mut memory = Self { xspi }; - // Set read param - let transaction = TransferConfig { - iwidth: XspiWidth::QUAD, - dwidth: XspiWidth::QUAD, - instruction: Some(0xC0), - ..Default::default() - }; - self.enable_write().await; - self.xspi.blocking_write(&[0x30_u8], transaction).unwrap(); - self.wait_write_finish(); + memory.reset_memory(); + memory } - pub async fn disable_mm(&mut self) { + pub fn disable_mm(&mut self) { self.xspi.disable_memory_mapped_mode(); } - pub async fn enable_mm(&mut self) { - self.qpi_mode().await; - + pub fn enable_mm(&mut self) { let read_config = TransferConfig { iwidth: XspiWidth::SING, isize: AddressSize::_8bit, adwidth: XspiWidth::SING, - adsize: AddressSize::_24bit, + adsize: AddressSize::_32bit, dwidth: XspiWidth::SING, - instruction: Some(CMD_READ as u32), + instruction: Some(SpiCommand::FastRead4B as u32), dummy: DummyCycles::_8, ..Default::default() }; @@ -198,42 +445,28 @@ impl FlashMemory { iwidth: XspiWidth::SING, isize: AddressSize::_8bit, adwidth: XspiWidth::SING, - adsize: AddressSize::_24bit, + adsize: AddressSize::_32bit, dwidth: XspiWidth::SING, - instruction: Some(CMD_WRITE_PG as u32), + instruction: Some(SpiCommand::PageProgram4B as u32), dummy: DummyCycles::_0, ..Default::default() }; self.xspi.enable_memory_mapped_mode(read_config, write_config).unwrap(); } - fn enable_octo(&mut self) { - let cr = self.read_cr(); - // info!("Read cr: {:x}", cr); - self.write_cr(cr | 0x02); - // info!("Read cr after writing: {:x}", cr); + fn into_octo(mut self) -> OpiFlashMemory { + self.enable_opi_mode(); + OpiFlashMemory { xspi: self.xspi } } - pub fn disable_octo(&mut self) { - let cr = self.read_cr(); - self.write_cr(cr & (!(0x02))); - } - - async fn exec_command_4(&mut self, cmd: u8) { - let transaction = TransferConfig { - iwidth: XspiWidth::QUAD, - adwidth: XspiWidth::NONE, - // adsize: AddressSize::_24bit, - dwidth: XspiWidth::NONE, - instruction: Some(cmd as u32), - address: None, - dummy: DummyCycles::_0, - ..Default::default() - }; - self.xspi.blocking_command(&transaction).unwrap(); + fn enable_opi_mode(&mut self) { + let cr2_0 = self.read_cr2(0); + info!("Read CR2 at 0x0: {:x}", cr2_0); + self.enable_write(); + self.write_cr2(0, cr2_0 | 0x01); // Set bit 0 to enable octo SPI in STR } - async fn exec_command(&mut self, cmd: u8) { + fn exec_command(&mut self, cmd: u8) { let transaction = TransferConfig { iwidth: XspiWidth::SING, adwidth: XspiWidth::NONE, @@ -248,16 +481,14 @@ impl FlashMemory { self.xspi.blocking_command(&transaction).unwrap(); } - pub async fn reset_memory(&mut self) { - self.exec_command_4(CMD_ENABLE_RESET).await; - self.exec_command_4(CMD_RESET).await; - self.exec_command(CMD_ENABLE_RESET).await; - self.exec_command(CMD_RESET).await; + pub fn reset_memory(&mut self) { + self.exec_command(SpiCommand::ResetEnable as u8); + self.exec_command(SpiCommand::ResetMemory as u8); self.wait_write_finish(); } - pub async fn enable_write(&mut self) { - self.exec_command(CMD_WRITE_ENABLE).await; + pub fn enable_write(&mut self) { + self.exec_command(SpiCommand::WriteEnable as u8); } pub fn read_id(&mut self) -> [u8; 3] { @@ -266,92 +497,64 @@ impl FlashMemory { iwidth: XspiWidth::SING, isize: AddressSize::_8bit, adwidth: XspiWidth::NONE, - // adsize: AddressSize::_24bit, dwidth: XspiWidth::SING, - instruction: Some(CMD_READ_ID as u32), + instruction: Some(SpiCommand::ReadIdentification as u32), ..Default::default() }; - // info!("Reading id: 0x{:X}", transaction.instruction); self.xspi.blocking_read(&mut buffer, transaction).unwrap(); buffer } - pub fn read_id_8(&mut self) -> [u8; 3] { - let mut buffer = [0; 3]; - let transaction: TransferConfig = TransferConfig { - iwidth: XspiWidth::OCTO, - isize: AddressSize::_16bit, - adwidth: XspiWidth::OCTO, - address: Some(0), - adsize: AddressSize::_32bit, - dwidth: XspiWidth::OCTO, - instruction: Some(CMD_READ_ID_OCTO as u32), - dummy: DummyCycles::_4, - ..Default::default() - }; - info!("Reading id: {:#X}", transaction.instruction); - self.xspi.blocking_read(&mut buffer, transaction).unwrap(); - buffer - } - - pub fn read_memory(&mut self, addr: u32, buffer: &mut [u8], use_dma: bool) { + pub fn read_memory(&mut self, addr: u32, buffer: &mut [u8]) { let transaction = TransferConfig { iwidth: XspiWidth::SING, adwidth: XspiWidth::SING, - adsize: AddressSize::_24bit, + adsize: AddressSize::_32bit, dwidth: XspiWidth::SING, - instruction: Some(CMD_READ as u32), + instruction: Some(SpiCommand::FastRead4B as u32), dummy: DummyCycles::_8, - // dwidth: XspiWidth::QUAD, - // instruction: Some(CMD_QUAD_READ as u32), - // dummy: DummyCycles::_8, address: Some(addr), ..Default::default() }; - if use_dma { - self.xspi.blocking_read(buffer, transaction).unwrap(); - } else { - self.xspi.blocking_read(buffer, transaction).unwrap(); - } + + self.xspi.blocking_read(buffer, transaction).unwrap(); } fn wait_write_finish(&mut self) { while (self.read_sr() & 0x01) != 0 {} } - async fn perform_erase(&mut self, addr: u32, cmd: u8) { + fn perform_erase(&mut self, addr: u32, cmd: u8) { let transaction = TransferConfig { iwidth: XspiWidth::SING, adwidth: XspiWidth::SING, - adsize: AddressSize::_24bit, + adsize: AddressSize::_32bit, dwidth: XspiWidth::NONE, instruction: Some(cmd as u32), address: Some(addr), dummy: DummyCycles::_0, ..Default::default() }; - self.enable_write().await; + self.enable_write(); self.xspi.blocking_command(&transaction).unwrap(); self.wait_write_finish(); } - pub async fn erase_sector(&mut self, addr: u32) { - self.perform_erase(addr, CMD_SECTOR_ERASE).await; + pub fn erase_sector(&mut self, addr: u32) { + self.perform_erase(addr, SpiCommand::SectorErase4B as u8); } - pub async fn erase_block_32k(&mut self, addr: u32) { - self.perform_erase(addr, CMD_BLOCK_ERASE_32K).await; + pub fn erase_block_64k(&mut self, addr: u32) { + self.perform_erase(addr, SpiCommand::BlockErase4B as u8); } - pub async fn erase_block_64k(&mut self, addr: u32) { - self.perform_erase(addr, CMD_BLOCK_ERASE_64K).await; - } - - pub async fn erase_chip(&mut self) { - self.exec_command(CMD_CHIP_ERASE).await; + pub fn erase_chip(&mut self) { + self.enable_write(); + self.exec_command(SpiCommand::ChipErase as u8); + self.wait_write_finish(); } - async fn write_page(&mut self, addr: u32, buffer: &[u8], len: usize, use_dma: bool) { + fn write_page(&mut self, addr: u32, buffer: &[u8], len: usize) { assert!( (len as u32 + (addr & 0x000000ff)) <= MEMORY_PAGE_SIZE as u32, "write_page(): page write length exceeds page boundary (len = {}, addr = {:X}", @@ -361,48 +564,43 @@ impl FlashMemory { let transaction = TransferConfig { iwidth: XspiWidth::SING, - adsize: AddressSize::_24bit, + adsize: AddressSize::_32bit, adwidth: XspiWidth::SING, dwidth: XspiWidth::SING, - instruction: Some(CMD_WRITE_PG as u32), - // dwidth: XspiWidth::QUAD, - // instruction: Some(CMD_QUAD_WRITE_PG as u32), + instruction: Some(SpiCommand::PageProgram4B as u32), address: Some(addr), dummy: DummyCycles::_0, ..Default::default() }; - self.enable_write().await; - if use_dma { - self.xspi.blocking_write(buffer, transaction).unwrap(); - } else { - self.xspi.blocking_write(buffer, transaction).unwrap(); - } + self.enable_write(); + self.xspi.blocking_write(buffer, transaction).unwrap(); self.wait_write_finish(); } - pub async fn write_memory(&mut self, addr: u32, buffer: &[u8], use_dma: bool) { + pub fn write_memory(&mut self, addr: u32, buffer: &[u8]) { let mut left = buffer.len(); let mut place = addr; let mut chunk_start = 0; while left > 0 { let max_chunk_size = MEMORY_PAGE_SIZE - (place & 0x000000ff) as usize; - let chunk_size = if left >= max_chunk_size { max_chunk_size } else { left }; + let chunk_size = min(max_chunk_size, left); let chunk = &buffer[chunk_start..(chunk_start + chunk_size)]; - self.write_page(place, chunk, chunk_size, use_dma).await; + self.write_page(place, chunk, chunk_size); place += chunk_size as u32; left -= chunk_size; chunk_start += chunk_size; } } + // Note: read_register cannot be used to read the configuration register 2 since there is an + // address required for that read. fn read_register(&mut self, cmd: u8) -> u8 { let mut buffer = [0; 1]; let transaction: TransferConfig = TransferConfig { iwidth: XspiWidth::SING, isize: AddressSize::_8bit, adwidth: XspiWidth::NONE, - adsize: AddressSize::_24bit, dwidth: XspiWidth::SING, instruction: Some(cmd as u32), address: None, @@ -410,39 +608,345 @@ impl FlashMemory { ..Default::default() }; self.xspi.blocking_read(&mut buffer, transaction).unwrap(); - // info!("Read w25q64 register: 0x{:x}", buffer[0]); buffer[0] } - fn write_register(&mut self, cmd: u8, value: u8) { - let buffer = [value; 1]; + pub fn read_sr(&mut self) -> u8 { + self.read_register(SpiCommand::ReadStatusRegister as u8) + } + + pub fn read_cr(&mut self) -> u8 { + self.read_register(SpiCommand::ReadConfigurationRegister as u8) + } + + pub fn write_sr_cr(&mut self, sr: u8, cr: u8) { + let buffer = [sr, cr]; let transaction: TransferConfig = TransferConfig { iwidth: XspiWidth::SING, isize: AddressSize::_8bit, - instruction: Some(cmd as u32), - adsize: AddressSize::_24bit, + instruction: Some(SpiCommand::WriteStatusConfigurationRegister as u32), adwidth: XspiWidth::NONE, dwidth: XspiWidth::SING, address: None, dummy: DummyCycles::_0, ..Default::default() }; + self.enable_write(); + self.xspi.blocking_write(&buffer, transaction).unwrap(); + self.wait_write_finish(); + } + + pub fn read_cr2(&mut self, address: u32) -> u8 { + let mut buffer = [0; 1]; + let transaction: TransferConfig = TransferConfig { + iwidth: XspiWidth::SING, + isize: AddressSize::_8bit, + instruction: Some(SpiCommand::ReadConfigurationRegister2 as u32), + adsize: AddressSize::_32bit, + adwidth: XspiWidth::SING, + dwidth: XspiWidth::SING, + address: Some(address), + dummy: DummyCycles::_0, + ..Default::default() + }; + self.xspi.blocking_read(&mut buffer, transaction).unwrap(); + buffer[0] + } + + pub fn write_cr2(&mut self, address: u32, value: u8) { + let buffer = [value; 1]; + let transaction: TransferConfig = TransferConfig { + iwidth: XspiWidth::SING, + isize: AddressSize::_8bit, + instruction: Some(SpiCommand::WriteConfigurationRegister2 as u32), + adsize: AddressSize::_32bit, + adwidth: XspiWidth::SING, + dwidth: XspiWidth::SING, + address: Some(address), + dummy: DummyCycles::_0, + ..Default::default() + }; self.xspi.blocking_write(&buffer, transaction).unwrap(); + self.wait_write_finish(); + } +} + +impl OpiFlashMemory { + pub fn into_spi(mut self) -> SpiFlashMemory { + self.disable_opi_mode(); + SpiFlashMemory { xspi: self.xspi } + } + + /// Disable OPI mode and return to SPI + pub fn disable_opi_mode(&mut self) { + // Clear SOPI and DOPI bits in CR2 volatile register + let cr2_0 = self.read_cr2(0x00000000); + self.write_cr2(0x00000000, cr2_0 & 0xFC); // Clear bits 0 and 1 + } + + /// Enable memory-mapped mode for OPI + pub fn enable_mm(&mut self) { + let read_config = TransferConfig { + iwidth: XspiWidth::OCTO, + isize: AddressSize::_16bit, // 2-byte command for OPI + adwidth: XspiWidth::OCTO, + adsize: AddressSize::_32bit, + dwidth: XspiWidth::OCTO, + instruction: Some(OpiCommand::OctaRead as u32), + dummy: DummyCycles::_20, // Default dummy cycles for OPI + ..Default::default() + }; + + let write_config = TransferConfig { + iwidth: XspiWidth::OCTO, + isize: AddressSize::_16bit, + adwidth: XspiWidth::OCTO, + adsize: AddressSize::_32bit, + dwidth: XspiWidth::OCTO, + instruction: Some(OpiCommand::PageProgram4B as u32), + dummy: DummyCycles::_0, + ..Default::default() + }; + + self.xspi.enable_memory_mapped_mode(read_config, write_config).unwrap(); + } + + pub fn disable_mm(&mut self) { + self.xspi.disable_memory_mapped_mode(); + } + + /// Execute OPI command (2-byte command) + fn exec_command(&mut self, cmd: OpiCommand) { + let transaction = TransferConfig { + iwidth: XspiWidth::OCTO, + isize: AddressSize::_16bit, // 2-byte command + adwidth: XspiWidth::NONE, + dwidth: XspiWidth::NONE, + instruction: Some(cmd as u32), + address: None, + dummy: DummyCycles::_0, + ..Default::default() + }; + self.xspi.blocking_command(&transaction).unwrap(); + } + + /// Reset memory using OPI commands + pub fn reset_memory(&mut self) { + self.exec_command(OpiCommand::ResetEnable); + self.exec_command(OpiCommand::ResetMemory); + self.wait_write_finish(); } + /// Enable write using OPI command + pub fn enable_write(&mut self) { + self.exec_command(OpiCommand::WriteEnable); + } + + /// Read device ID in OPI mode + pub fn read_id(&mut self) -> [u8; 3] { + let mut buffer = [0; 3]; + let transaction = TransferConfig { + iwidth: XspiWidth::OCTO, + isize: AddressSize::_16bit, + adwidth: XspiWidth::OCTO, + adsize: AddressSize::_32bit, + dwidth: XspiWidth::OCTO, + instruction: Some(OpiCommand::ReadIdentification as u32), + address: Some(0x00000000), // Dummy address required + dummy: DummyCycles::_4, + ..Default::default() + }; + self.xspi.blocking_read(&mut buffer, transaction).unwrap(); + buffer + } + + /// Read memory using OPI mode + pub fn read_memory(&mut self, addr: u32, buffer: &mut [u8]) { + let transaction = TransferConfig { + iwidth: XspiWidth::OCTO, + isize: AddressSize::_16bit, + adwidth: XspiWidth::OCTO, + adsize: AddressSize::_32bit, + dwidth: XspiWidth::OCTO, + instruction: Some(OpiCommand::OctaRead as u32), + address: Some(addr), + dummy: DummyCycles::_20, // Default for 200MHz operation + ..Default::default() + }; + self.xspi.blocking_read(buffer, transaction).unwrap(); + } + + /// Wait for write completion using OPI status read + fn wait_write_finish(&mut self) { + while (self.read_sr() & 0x01) != 0 {} + } + + /// Perform erase operation using OPI command + fn perform_erase(&mut self, addr: u32, cmd: OpiCommand) { + let transaction = TransferConfig { + iwidth: XspiWidth::OCTO, + isize: AddressSize::_16bit, + adwidth: XspiWidth::OCTO, + adsize: AddressSize::_32bit, + dwidth: XspiWidth::NONE, + instruction: Some(cmd as u32), + address: Some(addr), + dummy: DummyCycles::_0, + ..Default::default() + }; + self.enable_write(); + self.xspi.blocking_command(&transaction).unwrap(); + self.wait_write_finish(); + } + + /// Erase 4KB sector using OPI + pub fn erase_sector(&mut self, addr: u32) { + self.perform_erase(addr, OpiCommand::SectorErase4B); + } + + /// Erase 64KB block using OPI + pub fn erase_block_64k(&mut self, addr: u32) { + self.perform_erase(addr, OpiCommand::BlockErase4B); + } + + /// Erase entire chip using OPI + pub fn erase_chip(&mut self) { + self.enable_write(); + self.exec_command(OpiCommand::ChipErase); + self.wait_write_finish(); + } + + /// Write single page using OPI + fn write_page(&mut self, addr: u32, buffer: &[u8], len: usize) { + assert!( + (len as u32 + (addr & 0x000000ff)) <= MEMORY_PAGE_SIZE as u32, + "write_page(): page write length exceeds page boundary (len = {}, addr = {:X})", + len, + addr + ); + + let transaction = TransferConfig { + iwidth: XspiWidth::OCTO, + isize: AddressSize::_16bit, + adwidth: XspiWidth::OCTO, + adsize: AddressSize::_32bit, + dwidth: XspiWidth::OCTO, + instruction: Some(OpiCommand::PageProgram4B as u32), + address: Some(addr), + dummy: DummyCycles::_0, + ..Default::default() + }; + self.enable_write(); + self.xspi.blocking_write(buffer, transaction).unwrap(); + self.wait_write_finish(); + } + + /// Write memory using OPI (handles page boundaries) + pub fn write_memory(&mut self, addr: u32, buffer: &[u8]) { + let mut left = buffer.len(); + let mut place = addr; + let mut chunk_start = 0; + + while left > 0 { + let max_chunk_size = MEMORY_PAGE_SIZE - (place & 0x000000ff) as usize; + let chunk_size = min(max_chunk_size, left); + let chunk = &buffer[chunk_start..(chunk_start + chunk_size)]; + self.write_page(place, chunk, chunk_size); + place += chunk_size as u32; + left -= chunk_size; + chunk_start += chunk_size; + } + } + + /// Read register using OPI mode + fn read_register(&mut self, cmd: OpiCommand, dummy_addr: u32, dummy_cycles: DummyCycles) -> u8 { + let mut buffer = [0; 1]; + let transaction = TransferConfig { + iwidth: XspiWidth::OCTO, + isize: AddressSize::_16bit, + adwidth: XspiWidth::OCTO, + adsize: AddressSize::_32bit, + dwidth: XspiWidth::OCTO, + instruction: Some(cmd as u32), + address: Some(dummy_addr), + dummy: dummy_cycles, + ..Default::default() + }; + self.xspi.blocking_read(&mut buffer, transaction).unwrap(); + buffer[0] + } + + /// Read Status Register using OPI pub fn read_sr(&mut self) -> u8 { - self.read_register(CMD_READ_SR) + self.read_register( + OpiCommand::ReadStatusRegister, + 0x00000000, // Dummy address + DummyCycles::_4, + ) } + /// Read Configuration Register using OPI pub fn read_cr(&mut self) -> u8 { - self.read_register(CMD_READ_CR) + self.read_register( + OpiCommand::ReadConfigurationRegister, + 0x00000001, // Address for CR + DummyCycles::_4, + ) } - pub fn write_sr(&mut self, value: u8) { - self.write_register(CMD_WRITE_SR, value); + /// Write Status/Configuration Register using OPI + pub fn write_sr_cr(&mut self, sr: u8, cr: u8) { + let transaction = TransferConfig { + iwidth: XspiWidth::OCTO, + isize: AddressSize::_16bit, + adwidth: XspiWidth::OCTO, + adsize: AddressSize::_32bit, + dwidth: XspiWidth::OCTO, + instruction: Some(OpiCommand::WriteStatusConfigurationRegister as u32), + address: Some(0x00000000), + dummy: DummyCycles::_0, + ..Default::default() + }; + + self.enable_write(); + self.xspi.blocking_write(&[sr, cr], transaction).unwrap(); + self.wait_write_finish(); + } + + /// Read Configuration Register 2 using OPI + pub fn read_cr2(&mut self, address: u32) -> u8 { + let mut buffer = [0; 1]; + let transaction = TransferConfig { + iwidth: XspiWidth::OCTO, + isize: AddressSize::_16bit, + adwidth: XspiWidth::OCTO, + adsize: AddressSize::_32bit, + dwidth: XspiWidth::OCTO, + instruction: Some(OpiCommand::ReadConfigurationRegister2 as u32), + address: Some(address), + dummy: DummyCycles::_4, + ..Default::default() + }; + self.xspi.blocking_read(&mut buffer, transaction).unwrap(); + buffer[0] } - pub fn write_cr(&mut self, value: u8) { - self.write_register(CMD_WRITE_CR, value); + /// Write Configuration Register 2 using OPI + pub fn write_cr2(&mut self, address: u32, value: u8) { + let transaction = TransferConfig { + iwidth: XspiWidth::OCTO, + isize: AddressSize::_16bit, + adwidth: XspiWidth::OCTO, + adsize: AddressSize::_32bit, + dwidth: XspiWidth::OCTO, + instruction: Some(OpiCommand::WriteConfigurationRegister2 as u32), + address: Some(address), + dummy: DummyCycles::_0, + ..Default::default() + }; + + self.enable_write(); + self.xspi.blocking_write(&[value], transaction).unwrap(); + self.wait_write_finish(); } } -- cgit From 3e78f8a108c031f992116808b66c5e6c760c2c9e Mon Sep 17 00:00:00 2001 From: melvdl Date: Thu, 26 Jun 2025 19:35:19 +0200 Subject: stm32: generify timer channels --- embassy-stm32/build.rs | 36 ++++----- embassy-stm32/src/timer/complementary_pwm.rs | 72 ++++++++--------- embassy-stm32/src/timer/input_capture.rs | 67 ++++++++-------- embassy-stm32/src/timer/low_level.rs | 38 ++++----- embassy-stm32/src/timer/mod.rs | 111 +++++++++++++++++++++------ embassy-stm32/src/timer/one_pulse.rs | 88 ++++++++++++--------- embassy-stm32/src/timer/pwm_input.rs | 32 ++++---- embassy-stm32/src/timer/qei.rs | 10 ++- embassy-stm32/src/timer/simple_pwm.rs | 80 +++++++++---------- 9 files changed, 297 insertions(+), 237 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 8143c9a23..192688149 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1090,21 +1090,21 @@ fn main() { (("fmc", "CLK"), quote!(crate::fmc::ClkPin)), (("fmc", "BA0"), quote!(crate::fmc::BA0Pin)), (("fmc", "BA1"), quote!(crate::fmc::BA1Pin)), - (("timer", "CH1"), quote!(crate::timer::Channel1Pin)), - (("timer", "CH1N"), quote!(crate::timer::Channel1ComplementaryPin)), - (("timer", "CH2"), quote!(crate::timer::Channel2Pin)), - (("timer", "CH2N"), quote!(crate::timer::Channel2ComplementaryPin)), - (("timer", "CH3"), quote!(crate::timer::Channel3Pin)), - (("timer", "CH3N"), quote!(crate::timer::Channel3ComplementaryPin)), - (("timer", "CH4"), quote!(crate::timer::Channel4Pin)), - (("timer", "CH4N"), quote!(crate::timer::Channel4ComplementaryPin)), + (("timer", "CH1"), quote!(crate::timer::TimerPin)), + (("timer", "CH1N"), quote!(crate::timer::TimerComplementaryPin)), + (("timer", "CH2"), quote!(crate::timer::TimerPin)), + (("timer", "CH2N"), quote!(crate::timer::TimerComplementaryPin)), + (("timer", "CH3"), quote!(crate::timer::TimerPin)), + (("timer", "CH3N"), quote!(crate::timer::TimerComplementaryPin)), + (("timer", "CH4"), quote!(crate::timer::TimerPin)), + (("timer", "CH4N"), quote!(crate::timer::TimerComplementaryPin)), (("timer", "ETR"), quote!(crate::timer::ExternalTriggerPin)), - (("timer", "BKIN"), quote!(crate::timer::BreakInputPin)), - (("timer", "BKIN_COMP1"), quote!(crate::timer::BreakInputComparator1Pin)), - (("timer", "BKIN_COMP2"), quote!(crate::timer::BreakInputComparator2Pin)), - (("timer", "BKIN2"), quote!(crate::timer::BreakInput2Pin)), - (("timer", "BKIN2_COMP1"), quote!(crate::timer::BreakInput2Comparator1Pin)), - (("timer", "BKIN2_COMP2"), quote!(crate::timer::BreakInput2Comparator2Pin)), + (("timer", "BKIN"), quote!(crate::timer::BreakInputPin)), + (("timer", "BKIN_COMP1"), quote!(crate::timer::BreakInputComparator1Pin)), + (("timer", "BKIN_COMP2"), quote!(crate::timer::BreakInputComparator2Pin)), + (("timer", "BKIN2"), quote!(crate::timer::BreakInputPin)), + (("timer", "BKIN2_COMP1"), quote!(crate::timer::BreakInput2Comparator1Pin)), + (("timer", "BKIN2_COMP2"), quote!(crate::timer::BreakInput2Comparator2Pin)), (("hrtim", "CHA1"), quote!(crate::hrtim::ChannelAPin)), (("hrtim", "CHA2"), quote!(crate::hrtim::ChannelAComplementaryPin)), (("hrtim", "CHB1"), quote!(crate::hrtim::ChannelBPin)), @@ -1475,10 +1475,10 @@ fn main() { (("hash", "IN"), quote!(crate::hash::Dma)), (("cryp", "IN"), quote!(crate::cryp::DmaIn)), (("cryp", "OUT"), quote!(crate::cryp::DmaOut)), - (("timer", "CH1"), quote!(crate::timer::Ch1Dma)), - (("timer", "CH2"), quote!(crate::timer::Ch2Dma)), - (("timer", "CH3"), quote!(crate::timer::Ch3Dma)), - (("timer", "CH4"), quote!(crate::timer::Ch4Dma)), + (("timer", "CH1"), quote!(crate::timer::Dma)), + (("timer", "CH2"), quote!(crate::timer::Dma)), + (("timer", "CH3"), quote!(crate::timer::Dma)), + (("timer", "CH4"), quote!(crate::timer::Dma)), (("cordic", "WRITE"), quote!(crate::cordic::WriteDma)), // FIXME: stm32u5a crash on Cordic driver (("cordic", "READ"), quote!(crate::cordic::ReadDma)), // FIXME: stm32u5a crash on Cordic driver ] diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 8eec6c0c7..4600dd1a3 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -5,14 +5,12 @@ use core::marker::PhantomData; use stm32_metapac::timer::vals::Ckd; use super::low_level::{CountingMode, OutputPolarity, Timer}; -use super::simple_pwm::{Ch1, Ch2, Ch3, Ch4, PwmPin}; -use super::{ - AdvancedInstance4Channel, Channel, Channel1ComplementaryPin, Channel2ComplementaryPin, Channel3ComplementaryPin, - Channel4ComplementaryPin, -}; +use super::simple_pwm::PwmPin; +use super::{AdvancedInstance4Channel, Ch1, Ch2, Ch3, Ch4, TimerChannel, TimerComplementaryPin}; use crate::gpio::{AnyPin, OutputType}; use crate::time::Hertz; use crate::timer::low_level::OutputCompareMode; +use crate::timer::Channel; use crate::Peri; /// Complementary PWM pin wrapper. @@ -23,32 +21,23 @@ pub struct ComplementaryPwmPin<'d, T, C> { phantom: PhantomData<(T, C)>, } -macro_rules! complementary_channel_impl { - ($new_chx:ident, $channel:ident, $pin_trait:ident) => { - impl<'d, T: AdvancedInstance4Channel> ComplementaryPwmPin<'d, T, $channel> { - #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")] - pub fn $new_chx(pin: Peri<'d, impl $pin_trait>, output_type: OutputType) -> Self { - critical_section::with(|_| { - pin.set_low(); - pin.set_as_af( - pin.af_num(), - crate::gpio::AfType::output(output_type, crate::gpio::Speed::VeryHigh), - ); - }); - ComplementaryPwmPin { - _pin: pin.into(), - phantom: PhantomData, - } - } +impl<'d, T: AdvancedInstance4Channel, C: Channel> ComplementaryPwmPin<'d, T, C> { + /// Create a new complementary PWM pin instance. + pub fn new(pin: Peri<'d, impl TimerComplementaryPin>, output_type: OutputType) -> Self { + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af( + pin.af_num(), + crate::gpio::AfType::output(output_type, crate::gpio::Speed::VeryHigh), + ); + }); + ComplementaryPwmPin { + _pin: pin.into(), + phantom: PhantomData, } - }; + } } -complementary_channel_impl!(new_ch1, Ch1, Channel1ComplementaryPin); -complementary_channel_impl!(new_ch2, Ch2, Channel2ComplementaryPin); -complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin); -complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin); - /// PWM driver with support for standard and complementary outputs. pub struct ComplementaryPwm<'d, T: AdvancedInstance4Channel> { inner: Timer<'d, T>, @@ -82,24 +71,29 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { this.inner.enable_outputs(); - [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] - .iter() - .for_each(|&channel| { - this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); - this.inner.set_output_compare_preload(channel, true); - }); + [ + TimerChannel::Ch1, + TimerChannel::Ch2, + TimerChannel::Ch3, + TimerChannel::Ch4, + ] + .iter() + .for_each(|&channel| { + this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); + this.inner.set_output_compare_preload(channel, true); + }); this } /// Enable the given channel. - pub fn enable(&mut self, channel: Channel) { + pub fn enable(&mut self, channel: TimerChannel) { self.inner.enable_channel(channel, true); self.inner.enable_complementary_channel(channel, true); } /// Disable the given channel. - pub fn disable(&mut self, channel: Channel) { + pub fn disable(&mut self, channel: TimerChannel) { self.inner.enable_complementary_channel(channel, false); self.inner.enable_channel(channel, false); } @@ -127,13 +121,13 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { /// Set the duty for a given channel. /// /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. - pub fn set_duty(&mut self, channel: Channel, duty: u16) { + pub fn set_duty(&mut self, channel: TimerChannel, duty: u16) { assert!(duty <= self.get_max_duty()); self.inner.set_compare_value(channel, duty as _) } /// Set the output polarity for a given channel. - pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { + pub fn set_polarity(&mut self, channel: TimerChannel, polarity: OutputPolarity) { self.inner.set_output_polarity(channel, polarity); self.inner.set_complementary_output_polarity(channel, polarity); } @@ -148,7 +142,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { } impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { - type Channel = Channel; + type Channel = TimerChannel; type Time = Hertz; type Duty = u16; diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index ec8b1ddf1..da567d504 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -6,14 +6,12 @@ use core::pin::Pin; use core::task::{Context, Poll}; use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer}; -use super::{ - CaptureCompareInterruptHandler, Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, - GeneralInstance4Channel, -}; +use super::{CaptureCompareInterruptHandler, GeneralInstance4Channel, TimerChannel, TimerPin}; pub use super::{Ch1, Ch2, Ch3, Ch4}; use crate::gpio::{AfType, AnyPin, Pull}; use crate::interrupt::typelevel::{Binding, Interrupt}; use crate::time::Hertz; +use crate::timer::Channel; use crate::Peri; /// Capture pin wrapper. @@ -23,27 +21,17 @@ pub struct CapturePin<'d, T, C> { _pin: Peri<'d, AnyPin>, phantom: PhantomData<(T, C)>, } - -macro_rules! channel_impl { - ($new_chx:ident, $channel:ident, $pin_trait:ident) => { - impl<'d, T: GeneralInstance4Channel> CapturePin<'d, T, $channel> { - #[doc = concat!("Create a new ", stringify!($channel), " capture pin instance.")] - pub fn $new_chx(pin: Peri<'d, impl $pin_trait>, pull: Pull) -> Self { - pin.set_as_af(pin.af_num(), AfType::input(pull)); - CapturePin { - _pin: pin.into(), - phantom: PhantomData, - } - } +impl<'d, T: GeneralInstance4Channel, C: Channel> CapturePin<'d, T, C> { + /// Create a new capture pin instance. + pub fn new(pin: Peri<'d, impl TimerPin>, pull: Pull) -> Self { + pin.set_as_af(pin.af_num(), AfType::input(pull)); + CapturePin { + _pin: pin.into(), + phantom: PhantomData, } - }; + } } -channel_impl!(new_ch1, Ch1, Channel1Pin); -channel_impl!(new_ch2, Ch2, Channel2Pin); -channel_impl!(new_ch3, Ch3, Channel3Pin); -channel_impl!(new_ch4, Ch4, Channel4Pin); - /// Input capture driver. pub struct InputCapture<'d, T: GeneralInstance4Channel> { inner: Timer<'d, T>, @@ -80,41 +68,46 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { } /// Enable the given channel. - pub fn enable(&mut self, channel: Channel) { + pub fn enable(&mut self, channel: TimerChannel) { self.inner.enable_channel(channel, true); } /// Disable the given channel. - pub fn disable(&mut self, channel: Channel) { + pub fn disable(&mut self, channel: TimerChannel) { self.inner.enable_channel(channel, false); } /// Check whether given channel is enabled - pub fn is_enabled(&self, channel: Channel) -> bool { + pub fn is_enabled(&self, channel: TimerChannel) -> bool { self.inner.get_channel_enable_state(channel) } /// Set the input capture mode for a given channel. - pub fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { + pub fn set_input_capture_mode(&mut self, channel: TimerChannel, mode: InputCaptureMode) { self.inner.set_input_capture_mode(channel, mode); } /// Set input TI selection. - pub fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) { + pub fn set_input_ti_selection(&mut self, channel: TimerChannel, tisel: InputTISelection) { self.inner.set_input_ti_selection(channel, tisel) } /// Get capture value for a channel. - pub fn get_capture_value(&self, channel: Channel) -> u32 { + pub fn get_capture_value(&self, channel: TimerChannel) -> u32 { self.inner.get_capture_value(channel) } /// Get input interrupt. - pub fn get_input_interrupt(&self, channel: Channel) -> bool { + pub fn get_input_interrupt(&self, channel: TimerChannel) -> bool { self.inner.get_input_interrupt(channel) } - fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture { + fn new_future( + &self, + channel: TimerChannel, + mode: InputCaptureMode, + tisel: InputTISelection, + ) -> InputCaptureFuture { // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.5 // or ST RM0008 (STM32F103) chapter 15.3.5 Input capture mode self.inner.set_input_ti_selection(channel, tisel); @@ -131,37 +124,37 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { } /// Asynchronously wait until the pin sees a rising edge. - pub async fn wait_for_rising_edge(&mut self, channel: Channel) -> u32 { + pub async fn wait_for_rising_edge(&mut self, channel: TimerChannel) -> u32 { self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Normal) .await } /// Asynchronously wait until the pin sees a falling edge. - pub async fn wait_for_falling_edge(&mut self, channel: Channel) -> u32 { + pub async fn wait_for_falling_edge(&mut self, channel: TimerChannel) -> u32 { self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Normal) .await } /// Asynchronously wait until the pin sees any edge. - pub async fn wait_for_any_edge(&mut self, channel: Channel) -> u32 { + pub async fn wait_for_any_edge(&mut self, channel: TimerChannel) -> u32 { self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Normal) .await } /// Asynchronously wait until the (alternate) pin sees a rising edge. - pub async fn wait_for_rising_edge_alternate(&mut self, channel: Channel) -> u32 { + pub async fn wait_for_rising_edge_alternate(&mut self, channel: TimerChannel) -> u32 { self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Alternate) .await } /// Asynchronously wait until the (alternate) pin sees a falling edge. - pub async fn wait_for_falling_edge_alternate(&mut self, channel: Channel) -> u32 { + pub async fn wait_for_falling_edge_alternate(&mut self, channel: TimerChannel) -> u32 { self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Alternate) .await } /// Asynchronously wait until the (alternate) pin sees any edge. - pub async fn wait_for_any_edge_alternate(&mut self, channel: Channel) -> u32 { + pub async fn wait_for_any_edge_alternate(&mut self, channel: TimerChannel) -> u32 { self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Alternate) .await } @@ -169,7 +162,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { #[must_use = "futures do nothing unless you `.await` or poll them"] struct InputCaptureFuture { - channel: Channel, + channel: TimerChannel, phantom: PhantomData, } diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index dc8ceb725..bfdbcf968 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -503,7 +503,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set input capture filter. - pub fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) { + pub fn set_input_capture_filter(&self, channel: TimerChannel, icf: vals::FilterValue) { let raw_channel = channel.index(); self.regs_gp16() .ccmr_input(raw_channel / 2) @@ -511,22 +511,22 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Clear input interrupt. - pub fn clear_input_interrupt(&self, channel: Channel) { + pub fn clear_input_interrupt(&self, channel: TimerChannel) { self.regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false)); } /// Get input interrupt. - pub fn get_input_interrupt(&self, channel: Channel) -> bool { + pub fn get_input_interrupt(&self, channel: TimerChannel) -> bool { self.regs_gp16().sr().read().ccif(channel.index()) } /// Enable input interrupt. - pub fn enable_input_interrupt(&self, channel: Channel, enable: bool) { + pub fn enable_input_interrupt(&self, channel: TimerChannel, enable: bool) { self.regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable)); } /// Set input capture prescaler. - pub fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) { + pub fn set_input_capture_prescaler(&self, channel: TimerChannel, factor: u8) { let raw_channel = channel.index(); self.regs_gp16() .ccmr_input(raw_channel / 2) @@ -534,7 +534,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set input TI selection. - pub fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) { + pub fn set_input_ti_selection(&self, channel: TimerChannel, tisel: InputTISelection) { let raw_channel = channel.index(); self.regs_gp16() .ccmr_input(raw_channel / 2) @@ -542,7 +542,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set input capture mode. - pub fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) { + pub fn set_input_capture_mode(&self, channel: TimerChannel, mode: InputCaptureMode) { self.regs_gp16().ccer().modify(|r| match mode { InputCaptureMode::Rising => { r.set_ccnp(channel.index(), false); @@ -560,7 +560,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set output compare mode. - pub fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) { + pub fn set_output_compare_mode(&self, channel: TimerChannel, mode: OutputCompareMode) { let raw_channel: usize = channel.index(); self.regs_gp16() .ccmr_output(raw_channel / 2) @@ -568,24 +568,24 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set output polarity. - pub fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { + pub fn set_output_polarity(&self, channel: TimerChannel, polarity: OutputPolarity) { self.regs_gp16() .ccer() .modify(|w| w.set_ccp(channel.index(), polarity.into())); } /// Enable/disable a channel. - pub fn enable_channel(&self, channel: Channel, enable: bool) { + pub fn enable_channel(&self, channel: TimerChannel, enable: bool) { self.regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable)); } /// Get enable/disable state of a channel - pub fn get_channel_enable_state(&self, channel: Channel) -> bool { + pub fn get_channel_enable_state(&self, channel: TimerChannel) -> bool { self.regs_gp16().ccer().read().cce(channel.index()) } /// Set compare value for a channel. - pub fn set_compare_value(&self, channel: Channel, value: u32) { + pub fn set_compare_value(&self, channel: TimerChannel, value: u32) { match T::BITS { TimerBits::Bits16 => { let value = unwrap!(u16::try_from(value)); @@ -599,7 +599,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Get compare value for a channel. - pub fn get_compare_value(&self, channel: Channel) -> u32 { + pub fn get_compare_value(&self, channel: TimerChannel) -> u32 { match T::BITS { TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32, #[cfg(not(stm32l0))] @@ -608,12 +608,12 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Get capture value for a channel. - pub fn get_capture_value(&self, channel: Channel) -> u32 { + pub fn get_capture_value(&self, channel: TimerChannel) -> u32 { self.get_compare_value(channel) } /// Set output compare preload. - pub fn set_output_compare_preload(&self, channel: Channel, preload: bool) { + pub fn set_output_compare_preload(&self, channel: TimerChannel, preload: bool) { let channel_index = channel.index(); self.regs_gp16() .ccmr_output(channel_index / 2) @@ -631,12 +631,12 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Get capture compare DMA enable state - pub fn get_cc_dma_enable_state(&self, channel: Channel) -> bool { + pub fn get_cc_dma_enable_state(&self, channel: TimerChannel) -> bool { self.regs_gp16().dier().read().ccde(channel.index()) } /// Set capture compare DMA enable state - pub fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) { + pub fn set_cc_dma_enable_state(&self, channel: TimerChannel, ccde: bool) { self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) } @@ -713,14 +713,14 @@ impl<'d, T: AdvancedInstance4Channel> Timer<'d, T> { } /// Set complementary output polarity. - pub fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { + pub fn set_complementary_output_polarity(&self, channel: TimerChannel, polarity: OutputPolarity) { self.regs_advanced() .ccer() .modify(|w| w.set_ccnp(channel.index(), polarity.into())); } /// Enable/disable a complementary channel. - pub fn enable_complementary_channel(&self, channel: Channel, enable: bool) { + pub fn enable_complementary_channel(&self, channel: TimerChannel, enable: bool) { self.regs_advanced() .ccer() .modify(|w| w.set_ccne(channel.index(), enable)); diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index b29382fc8..362d95e25 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -19,7 +19,7 @@ use crate::rcc::RccPeripheral; /// Timer channel. #[derive(Clone, Copy)] -pub enum Channel { +pub enum TimerChannel { /// Channel 1. Ch1, /// Channel 2. @@ -30,14 +30,14 @@ pub enum Channel { Ch4, } -impl Channel { +impl TimerChannel { /// Get the channel index (0..3) pub fn index(&self) -> usize { match self { - Channel::Ch1 => 0, - Channel::Ch2 => 1, - Channel::Ch3 => 2, - Channel::Ch4 => 3, + TimerChannel::Ch1 => 0, + TimerChannel::Ch2 => 1, + TimerChannel::Ch3 => 2, + TimerChannel::Ch4 => 3, } } } @@ -51,6 +51,80 @@ pub enum Ch3 {} /// Channel 4 marker type. pub enum Ch4 {} +/// Timer channel trait. +#[allow(private_bounds)] +pub trait Channel: SealedChannel { + /// The runtime channel. + const CHANNEL: TimerChannel; +} + +trait SealedChannel {} + +impl Channel for Ch1 { + const CHANNEL: TimerChannel = TimerChannel::Ch1; +} + +impl Channel for Ch2 { + const CHANNEL: TimerChannel = TimerChannel::Ch2; +} + +impl Channel for Ch3 { + const CHANNEL: TimerChannel = TimerChannel::Ch3; +} + +impl Channel for Ch4 { + const CHANNEL: TimerChannel = TimerChannel::Ch4; +} + +impl SealedChannel for Ch1 {} +impl SealedChannel for Ch2 {} +impl SealedChannel for Ch3 {} +impl SealedChannel for Ch4 {} + +/// Timer break input. +#[derive(Clone, Copy)] +pub enum BkIn { + /// Break input 1. + BkIn1, + /// Break input 2. + BkIn2, +} + +impl BkIn { + /// Get the channel index (0..3) + pub fn index(&self) -> usize { + match self { + BkIn::BkIn1 => 0, + BkIn::BkIn2 => 1, + } + } +} + +/// Break input 1 marker type. +pub enum BkIn1 {} +/// Break input 2 marker type. +pub enum BkIn2 {} + +/// Timer channel trait. +#[allow(private_bounds)] +pub trait BreakInput: SealedBreakInput { + /// The runtim timer channel. + const INPUT: BkIn; +} + +trait SealedBreakInput {} + +impl BreakInput for BkIn1 { + const INPUT: BkIn = BkIn::BkIn1; +} + +impl BreakInput for BkIn2 { + const INPUT: BkIn = BkIn::BkIn2; +} + +impl SealedBreakInput for BkIn1 {} +impl SealedBreakInput for BkIn2 {} + /// Amount of bits of a timer. #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -149,33 +223,20 @@ pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + Ad /// Advanced 16-bit timer with 4 channels instance. pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {} -pin_trait!(Channel1Pin, GeneralInstance4Channel); -pin_trait!(Channel2Pin, GeneralInstance4Channel); -pin_trait!(Channel3Pin, GeneralInstance4Channel); -pin_trait!(Channel4Pin, GeneralInstance4Channel); +pin_trait!(TimerPin, GeneralInstance4Channel, Channel); pin_trait!(ExternalTriggerPin, GeneralInstance4Channel); -pin_trait!(Channel1ComplementaryPin, AdvancedInstance4Channel); -pin_trait!(Channel2ComplementaryPin, AdvancedInstance4Channel); -pin_trait!(Channel3ComplementaryPin, AdvancedInstance4Channel); -pin_trait!(Channel4ComplementaryPin, AdvancedInstance4Channel); - -pin_trait!(BreakInputPin, AdvancedInstance4Channel); -pin_trait!(BreakInput2Pin, AdvancedInstance4Channel); +pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, Channel); -pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel); -pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel); +pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput); -pin_trait!(BreakInput2Comparator1Pin, AdvancedInstance4Channel); -pin_trait!(BreakInput2Comparator2Pin, AdvancedInstance4Channel); +pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel, BreakInput); +pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput); // Update Event trigger DMA for every timer dma_trait!(UpDma, BasicInstance); -dma_trait!(Ch1Dma, GeneralInstance4Channel); -dma_trait!(Ch2Dma, GeneralInstance4Channel); -dma_trait!(Ch3Dma, GeneralInstance4Channel); -dma_trait!(Ch4Dma, GeneralInstance4Channel); +dma_trait!(Dma, GeneralInstance4Channel, Channel); #[allow(unused)] macro_rules! impl_core_timer { diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs index 933165ef9..47c1d7f49 100644 --- a/embassy-stm32/src/timer/one_pulse.rs +++ b/embassy-stm32/src/timer/one_pulse.rs @@ -9,9 +9,7 @@ use core::task::{Context, Poll}; use super::low_level::{ CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource, }; -use super::{ - CaptureCompareInterruptHandler, Channel, Channel1Pin, Channel2Pin, ExternalTriggerPin, GeneralInstance4Channel, -}; +use super::{CaptureCompareInterruptHandler, ExternalTriggerPin, GeneralInstance4Channel, TimerChannel, TimerPin}; pub use super::{Ch1, Ch2}; use crate::gpio::{AfType, AnyPin, Pull}; use crate::interrupt::typelevel::{Binding, Interrupt}; @@ -48,24 +46,40 @@ pub struct TriggerPin<'d, T, C> { phantom: PhantomData<(T, C)>, } -macro_rules! channel_impl { - ($new_chx:ident, $channel:ident, $pin_trait:ident) => { - impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, $channel> { - #[doc = concat!("Create a new ", stringify!($channel), " trigger pin instance.")] - pub fn $new_chx(pin: Peri<'d, impl $pin_trait>, pull: Pull) -> Self { - pin.set_as_af(pin.af_num(), AfType::input(pull)); - TriggerPin { - _pin: pin.into(), - phantom: PhantomData, - } - } +// TODO: Generify trigger inputs + +impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ch1> { + /// "Create a new Ch1 trigger pin instance. + pub fn new_ch1(pin: Peri<'d, impl TimerPin>, pull: Pull) -> Self { + pin.set_as_af(pin.af_num(), AfType::input(pull)); + TriggerPin { + _pin: pin.into(), + phantom: PhantomData, } - }; + } } -channel_impl!(new_ch1, Ch1, Channel1Pin); -channel_impl!(new_ch2, Ch2, Channel2Pin); -channel_impl!(new_ext, Ext, ExternalTriggerPin); +impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ch2> { + /// "Create a new Ch2 trigger pin instance. + pub fn new_ch2(pin: Peri<'d, impl TimerPin>, pull: Pull) -> Self { + pin.set_as_af(pin.af_num(), AfType::input(pull)); + TriggerPin { + _pin: pin.into(), + phantom: PhantomData, + } + } +} + +impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ext> { + /// "Create a new EXT trigger pin instance. + pub fn new_ext(pin: Peri<'d, impl ExternalTriggerPin>, pull: Pull) -> Self { + pin.set_as_af(pin.af_num(), AfType::input(pull)); + TriggerPin { + _pin: pin.into(), + phantom: PhantomData, + } + } +} /// One pulse driver. /// @@ -91,9 +105,9 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { this.inner.set_trigger_source(TriggerSource::TI1F_ED); this.inner - .set_input_ti_selection(Channel::Ch1, InputTISelection::Normal); + .set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal); this.inner - .set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER); + .set_input_capture_filter(TimerChannel::Ch1, FilterValue::NO_FILTER); this.new_inner(freq, pulse_end, counting_mode); this @@ -116,10 +130,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { this.inner.set_trigger_source(TriggerSource::TI1FP1); this.inner - .set_input_ti_selection(Channel::Ch1, InputTISelection::Normal); + .set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal); this.inner - .set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER); - this.inner.set_input_capture_mode(Channel::Ch1, capture_mode); + .set_input_capture_filter(TimerChannel::Ch1, FilterValue::NO_FILTER); + this.inner.set_input_capture_mode(TimerChannel::Ch1, capture_mode); this.new_inner(freq, pulse_end, counting_mode); this @@ -142,10 +156,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { this.inner.set_trigger_source(TriggerSource::TI2FP2); this.inner - .set_input_ti_selection(Channel::Ch2, InputTISelection::Normal); + .set_input_ti_selection(TimerChannel::Ch2, InputTISelection::Normal); this.inner - .set_input_capture_filter(Channel::Ch2, FilterValue::NO_FILTER); - this.inner.set_input_capture_mode(Channel::Ch2, capture_mode); + .set_input_capture_filter(TimerChannel::Ch2, FilterValue::NO_FILTER); + this.inner.set_input_capture_mode(TimerChannel::Ch2, capture_mode); this.new_inner(freq, pulse_end, counting_mode); this @@ -217,7 +231,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// Get a single channel /// /// If you need to use multiple channels, use [`Self::split`]. - pub fn channel(&mut self, channel: Channel) -> OnePulseChannel<'_, T> { + pub fn channel(&mut self, channel: TimerChannel) -> OnePulseChannel<'_, T> { OnePulseChannel { inner: unsafe { self.inner.clone_unchecked() }, channel, @@ -230,7 +244,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch1(&mut self) -> OnePulseChannel<'_, T> { - self.channel(Channel::Ch1) + self.channel(TimerChannel::Ch1) } /// Channel 2 @@ -239,7 +253,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch2(&mut self) -> OnePulseChannel<'_, T> { - self.channel(Channel::Ch2) + self.channel(TimerChannel::Ch2) } /// Channel 3 @@ -248,7 +262,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch3(&mut self) -> OnePulseChannel<'_, T> { - self.channel(Channel::Ch3) + self.channel(TimerChannel::Ch3) } /// Channel 4 @@ -257,7 +271,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch4(&mut self) -> OnePulseChannel<'_, T> { - self.channel(Channel::Ch4) + self.channel(TimerChannel::Ch4) } /// Splits a [`OnePulse`] into four output channels. @@ -276,10 +290,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { }; OnePulseChannels { - ch1: ch(Channel::Ch1), - ch2: ch(Channel::Ch2), - ch3: ch(Channel::Ch3), - ch4: ch(Channel::Ch4), + ch1: ch(TimerChannel::Ch1), + ch2: ch(TimerChannel::Ch2), + ch3: ch(TimerChannel::Ch3), + ch4: ch(TimerChannel::Ch4), } } } @@ -303,7 +317,7 @@ pub struct OnePulseChannels<'d, T: GeneralInstance4Channel> { /// configuration is shared with all four channels. pub struct OnePulseChannel<'d, T: GeneralInstance4Channel> { inner: ManuallyDrop>, - channel: Channel, + channel: TimerChannel, } impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> { @@ -350,7 +364,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> { #[must_use = "futures do nothing unless you `.await` or poll them"] struct OnePulseFuture { - channel: Channel, + channel: TimerChannel, phantom: PhantomData, } diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index 98b798634..3f9e5f651 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -1,33 +1,33 @@ //! PWM Input driver. use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource}; -use super::{Channel, Channel1Pin, Channel2Pin, GeneralInstance4Channel}; +use super::{Ch1, Ch2, GeneralInstance4Channel, TimerChannel, TimerPin}; use crate::gpio::{AfType, Pull}; use crate::time::Hertz; use crate::Peri; /// PWM Input driver. pub struct PwmInput<'d, T: GeneralInstance4Channel> { - channel: Channel, + channel: TimerChannel, inner: Timer<'d, T>, } impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { /// Create a new PWM input driver. - pub fn new(tim: Peri<'d, T>, pin: Peri<'d, impl Channel1Pin>, pull: Pull, freq: Hertz) -> Self { + pub fn new(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); - Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2) + Self::new_inner(tim, freq, TimerChannel::Ch1, TimerChannel::Ch2) } /// Create a new PWM input driver. - pub fn new_alt(tim: Peri<'d, T>, pin: Peri<'d, impl Channel2Pin>, pull: Pull, freq: Hertz) -> Self { + pub fn new_alt(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); - Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1) + Self::new_inner(tim, freq, TimerChannel::Ch2, TimerChannel::Ch1) } - fn new_inner(tim: Peri<'d, T>, freq: Hertz, ch1: Channel, ch2: Channel) -> Self { + fn new_inner(tim: Peri<'d, T>, freq: Hertz, ch1: TimerChannel, ch2: TimerChannel) -> Self { let mut inner = Timer::new(tim); inner.set_counting_mode(CountingMode::EdgeAlignedUp); @@ -44,8 +44,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { inner.set_input_capture_mode(ch2, InputCaptureMode::Falling); inner.set_trigger_source(match ch1 { - Channel::Ch1 => TriggerSource::TI1FP1, - Channel::Ch2 => TriggerSource::TI2FP2, + TimerChannel::Ch1 => TriggerSource::TI1FP1, + TimerChannel::Ch2 => TriggerSource::TI2FP2, _ => panic!("Invalid channel for PWM input"), }); @@ -58,19 +58,19 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { /// Enable the given channel. pub fn enable(&mut self) { - self.inner.enable_channel(Channel::Ch1, true); - self.inner.enable_channel(Channel::Ch2, true); + self.inner.enable_channel(TimerChannel::Ch1, true); + self.inner.enable_channel(TimerChannel::Ch2, true); } /// Disable the given channel. pub fn disable(&mut self) { - self.inner.enable_channel(Channel::Ch1, false); - self.inner.enable_channel(Channel::Ch2, false); + self.inner.enable_channel(TimerChannel::Ch1, false); + self.inner.enable_channel(TimerChannel::Ch2, false); } /// Check whether given channel is enabled pub fn is_enabled(&self) -> bool { - self.inner.get_channel_enable_state(Channel::Ch1) + self.inner.get_channel_enable_state(TimerChannel::Ch1) } /// Get the period tick count @@ -81,8 +81,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { /// Get the pulse width tick count pub fn get_width_ticks(&self) -> u32 { self.inner.get_capture_value(match self.channel { - Channel::Ch1 => Channel::Ch2, - Channel::Ch2 => Channel::Ch1, + TimerChannel::Ch1 => TimerChannel::Ch2, + TimerChannel::Ch2 => TimerChannel::Ch1, _ => panic!("Invalid channel for PWM input"), }) } diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index f3c81667c..bc7e71290 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -6,7 +6,7 @@ use stm32_metapac::timer::vals; use super::low_level::Timer; pub use super::{Ch1, Ch2}; -use super::{Channel1Pin, Channel2Pin, GeneralInstance4Channel}; +use super::{GeneralInstance4Channel, TimerPin}; use crate::gpio::{AfType, AnyPin, Pull}; use crate::Peri; @@ -24,11 +24,13 @@ pub struct QeiPin<'d, T, Channel> { phantom: PhantomData<(T, Channel)>, } +// TODO: generify QEI channels + macro_rules! channel_impl { ($new_chx:ident, $channel:ident, $pin_trait:ident) => { impl<'d, T: GeneralInstance4Channel> QeiPin<'d, T, $channel> { #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")] - pub fn $new_chx(pin: Peri<'d, impl $pin_trait>) -> Self { + pub fn $new_chx(pin: Peri<'d, impl $pin_trait>) -> Self { critical_section::with(|_| { pin.set_low(); pin.set_as_af(pin.af_num(), AfType::input(Pull::None)); @@ -42,8 +44,8 @@ macro_rules! channel_impl { }; } -channel_impl!(new_ch1, Ch1, Channel1Pin); -channel_impl!(new_ch2, Ch2, Channel2Pin); +channel_impl!(new_ch1, Ch1, TimerPin); +channel_impl!(new_ch2, Ch2, TimerPin); /// Quadrature decoder driver. pub struct Qei<'d, T: GeneralInstance4Channel> { diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index f7f433154..02835c379 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -4,22 +4,13 @@ use core::marker::PhantomData; use core::mem::ManuallyDrop; use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer}; -use super::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance4Channel, TimerBits}; +use super::{Ch1, Ch2, Ch3, Ch4, GeneralInstance4Channel, TimerBits, TimerChannel, TimerPin}; #[cfg(gpio_v2)] use crate::gpio::Pull; use crate::gpio::{AfType, AnyPin, OutputType, Speed}; use crate::time::Hertz; use crate::Peri; -/// Channel 1 marker type. -pub enum Ch1 {} -/// Channel 2 marker type. -pub enum Ch2 {} -/// Channel 3 marker type. -pub enum Ch3 {} -/// Channel 4 marker type. -pub enum Ch4 {} - /// PWM pin wrapper. /// /// This wraps a pin to make it usable with PWM. @@ -47,7 +38,7 @@ macro_rules! channel_impl { ($new_chx:ident, $new_chx_with_config:ident, $channel:ident, $pin_trait:ident) => { impl<'d, T: GeneralInstance4Channel> PwmPin<'d, T, $channel> { #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")] - pub fn $new_chx(pin: Peri<'d, impl $pin_trait>, output_type: OutputType) -> Self { + pub fn $new_chx(pin: Peri<'d, impl $pin_trait>, output_type: OutputType) -> Self { critical_section::with(|_| { pin.set_low(); pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh)); @@ -59,7 +50,7 @@ macro_rules! channel_impl { } #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance with config.")] - pub fn $new_chx_with_config(pin: Peri<'d, impl $pin_trait>, pin_config: PwmPinConfig) -> Self { + pub fn $new_chx_with_config(pin: Peri<'d, impl $pin_trait>, pin_config: PwmPinConfig) -> Self { critical_section::with(|_| { pin.set_low(); pin.set_as_af( @@ -79,10 +70,10 @@ macro_rules! channel_impl { }; } -channel_impl!(new_ch1, new_ch1_with_config, Ch1, Channel1Pin); -channel_impl!(new_ch2, new_ch2_with_config, Ch2, Channel2Pin); -channel_impl!(new_ch3, new_ch3_with_config, Ch3, Channel3Pin); -channel_impl!(new_ch4, new_ch4_with_config, Ch4, Channel4Pin); +channel_impl!(new_ch1, new_ch1_with_config, Ch1, TimerPin); +channel_impl!(new_ch2, new_ch2_with_config, Ch2, TimerPin); +channel_impl!(new_ch3, new_ch3_with_config, Ch3, TimerPin); +channel_impl!(new_ch4, new_ch4_with_config, Ch4, TimerPin); /// A single channel of a pwm, obtained from [`SimplePwm::split`], /// [`SimplePwm::channel`], [`SimplePwm::ch1`], etc. @@ -91,7 +82,7 @@ channel_impl!(new_ch4, new_ch4_with_config, Ch4, Channel4Pin); /// the frequency configuration is shared with all four channels. pub struct SimplePwmChannel<'d, T: GeneralInstance4Channel> { timer: ManuallyDrop>, - channel: Channel, + channel: TimerChannel, } // TODO: check for RMW races @@ -216,13 +207,18 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details this.inner.start(); - [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] - .iter() - .for_each(|&channel| { - this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); + [ + TimerChannel::Ch1, + TimerChannel::Ch2, + TimerChannel::Ch3, + TimerChannel::Ch4, + ] + .iter() + .for_each(|&channel| { + this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); - this.inner.set_output_compare_preload(channel, true); - }); + this.inner.set_output_compare_preload(channel, true); + }); this } @@ -230,7 +226,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// Get a single channel /// /// If you need to use multiple channels, use [`Self::split`]. - pub fn channel(&mut self, channel: Channel) -> SimplePwmChannel<'_, T> { + pub fn channel(&mut self, channel: TimerChannel) -> SimplePwmChannel<'_, T> { SimplePwmChannel { timer: unsafe { self.inner.clone_unchecked() }, channel, @@ -243,7 +239,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch1(&mut self) -> SimplePwmChannel<'_, T> { - self.channel(Channel::Ch1) + self.channel(TimerChannel::Ch1) } /// Channel 2 @@ -252,7 +248,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch2(&mut self) -> SimplePwmChannel<'_, T> { - self.channel(Channel::Ch2) + self.channel(TimerChannel::Ch2) } /// Channel 3 @@ -261,7 +257,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch3(&mut self) -> SimplePwmChannel<'_, T> { - self.channel(Channel::Ch3) + self.channel(TimerChannel::Ch3) } /// Channel 4 @@ -270,7 +266,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch4(&mut self) -> SimplePwmChannel<'_, T> { - self.channel(Channel::Ch4) + self.channel(TimerChannel::Ch4) } /// Splits a [`SimplePwm`] into four pwm channels. @@ -292,10 +288,10 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { }; SimplePwmChannels { - ch1: ch(Channel::Ch1), - ch2: ch(Channel::Ch2), - ch3: ch(Channel::Ch3), - ch4: ch(Channel::Ch4), + ch1: ch(TimerChannel::Ch1), + ch2: ch(TimerChannel::Ch2), + ch3: ch(TimerChannel::Ch3), + ch4: ch(TimerChannel::Ch4), } } @@ -326,7 +322,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// Note: /// you will need to provide corresponding TIMx_UP DMA channel to use this method. - pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma>, channel: Channel, duty: &[u16]) { + pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma>, channel: TimerChannel, duty: &[u16]) { #[allow(clippy::let_unit_value)] // eg. stm32f334 let req = dma.request(); @@ -409,8 +405,8 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { pub async fn waveform_up_multi_channel( &mut self, dma: Peri<'_, impl super::UpDma>, - starting_channel: Channel, - ending_channel: Channel, + starting_channel: TimerChannel, + ending_channel: TimerChannel, duty: &[u16], ) { let cr1_addr = self.inner.regs_gp16().cr1().as_ptr() as u32; @@ -470,13 +466,13 @@ macro_rules! impl_waveform_chx { ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => { impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// Generate a sequence of PWM waveform - pub async fn $fn_name(&mut self, dma: Peri<'_, impl super::$dma_ch>, duty: &[u16]) { + pub async fn $fn_name(&mut self, dma: Peri<'_, impl super::$dma_ch>, duty: &[u16]) { use crate::pac::timer::vals::Ccds; #[allow(clippy::let_unit_value)] // eg. stm32f334 let req = dma.request(); - let cc_channel = Channel::$cc_ch; + let cc_channel = TimerChannel::$cc_ch; let original_duty_state = self.channel(cc_channel).current_duty_cycle(); let original_enable_state = self.channel(cc_channel).is_enabled(); @@ -562,10 +558,10 @@ macro_rules! impl_waveform_chx { }; } -impl_waveform_chx!(waveform_ch1, Ch1Dma, Ch1); -impl_waveform_chx!(waveform_ch2, Ch2Dma, Ch2); -impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3); -impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4); +impl_waveform_chx!(waveform_ch1, Dma, Ch1); +impl_waveform_chx!(waveform_ch2, Dma, Ch2); +impl_waveform_chx!(waveform_ch3, Dma, Ch3); +impl_waveform_chx!(waveform_ch4, Dma, Ch4); impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> { type Error = core::convert::Infallible; @@ -603,7 +599,7 @@ impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::SetDutyCycle for Simpl } impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> { - type Channel = Channel; + type Channel = TimerChannel; type Time = Hertz; type Duty = u32; -- cgit From 3bc2113651dc9c9b92fb789544f50aa296fba2e1 Mon Sep 17 00:00:00 2001 From: Nicholas Fasching <91689117+njfdev@users.noreply.github.com> Date: Thu, 26 Jun 2025 16:32:09 -0400 Subject: Fix Release and Dev Profiles Being Backwards in rp235x Examples --- examples/rp235x/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index c81b79ae1..1346a75a2 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -57,9 +57,9 @@ portable-atomic = { version = "1.5", features = ["critical-section"] } log = "0.4" embedded-sdmmc = "0.7.0" -[profile.release] +[profile.dev] debug = 2 -[profile.dev] +[profile.release] lto = true opt-level = "z" -- cgit From 1623d4e639a54f21678381b54fd6d444309dab0a Mon Sep 17 00:00:00 2001 From: melvdl Date: Thu, 26 Jun 2025 22:55:12 +0200 Subject: stm32: generify timer::one_pulse and timer::qei pin constructors --- embassy-stm32/src/timer/one_pulse.rs | 88 ++++++++++++++++++++++++++---------- embassy-stm32/src/timer/qei.rs | 42 +++++++++-------- 2 files changed, 86 insertions(+), 44 deletions(-) diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs index 47c1d7f49..e89ad8390 100644 --- a/embassy-stm32/src/timer/one_pulse.rs +++ b/embassy-stm32/src/timer/one_pulse.rs @@ -7,7 +7,7 @@ use core::pin::Pin; use core::task::{Context, Poll}; use super::low_level::{ - CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource, + CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource as Ts, }; use super::{CaptureCompareInterruptHandler, ExternalTriggerPin, GeneralInstance4Channel, TimerChannel, TimerPin}; pub use super::{Ch1, Ch2}; @@ -46,33 +46,71 @@ pub struct TriggerPin<'d, T, C> { phantom: PhantomData<(T, C)>, } -// TODO: Generify trigger inputs +trait SealedTriggerSource {} -impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ch1> { - /// "Create a new Ch1 trigger pin instance. - pub fn new_ch1(pin: Peri<'d, impl TimerPin>, pull: Pull) -> Self { - pin.set_as_af(pin.af_num(), AfType::input(pull)); - TriggerPin { - _pin: pin.into(), - phantom: PhantomData, - } +/// Marker trait for a trigger source. +#[expect(private_bounds)] +pub trait TriggerSource: SealedTriggerSource {} + +impl TriggerSource for Ch1 {} +impl TriggerSource for Ch2 {} +impl TriggerSource for Ext {} + +impl SealedTriggerSource for Ch1 {} +impl SealedTriggerSource for Ch2 {} +impl SealedTriggerSource for Ext {} + +trait SealedTimerTriggerPin: crate::gpio::Pin {} + +/// Marker trait for a trigger pin. +#[expect(private_bounds)] +// TODO: find better naming scheme than prefixing all pin traits with "Timer". +// The trait name cannot conflict with the corresponding type's name. +// Applies to other timer submodules as well. +pub trait TimerTriggerPin: SealedTimerTriggerPin { + /// Get the AF number needed to use this pin as a trigger source. + fn af_num(&self) -> u8; +} + +impl TimerTriggerPin for P +where + T: GeneralInstance4Channel, + P: TimerPin, + C: super::Channel + TriggerSource, +{ + fn af_num(&self) -> u8 { + TimerPin::af_num(self) } } -impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ch2> { - /// "Create a new Ch2 trigger pin instance. - pub fn new_ch2(pin: Peri<'d, impl TimerPin>, pull: Pull) -> Self { - pin.set_as_af(pin.af_num(), AfType::input(pull)); - TriggerPin { - _pin: pin.into(), - phantom: PhantomData, - } +impl TimerTriggerPin for P +where + T: GeneralInstance4Channel, + P: ExternalTriggerPin, +{ + fn af_num(&self) -> u8 { + ExternalTriggerPin::af_num(self) } } -impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ext> { - /// "Create a new EXT trigger pin instance. - pub fn new_ext(pin: Peri<'d, impl ExternalTriggerPin>, pull: Pull) -> Self { +impl SealedTimerTriggerPin for P +where + T: GeneralInstance4Channel, + P: TimerPin, + C: super::Channel + TriggerSource, +{ +} + +impl SealedTimerTriggerPin for P +where + T: GeneralInstance4Channel, + P: ExternalTriggerPin, +{ +} + +impl<'d, T: GeneralInstance4Channel, C: TriggerSource> TriggerPin<'d, T, C> { + /// "Create a new Ch1 trigger pin instance. + pub fn new(pin: Peri<'d, impl TimerTriggerPin>, pull: Pull) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); TriggerPin { _pin: pin.into(), @@ -103,7 +141,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { ) -> Self { let mut this = Self { inner: Timer::new(tim) }; - this.inner.set_trigger_source(TriggerSource::TI1F_ED); + this.inner.set_trigger_source(Ts::TI1F_ED); this.inner .set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal); this.inner @@ -128,7 +166,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { ) -> Self { let mut this = Self { inner: Timer::new(tim) }; - this.inner.set_trigger_source(TriggerSource::TI1FP1); + this.inner.set_trigger_source(Ts::TI1FP1); this.inner .set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal); this.inner @@ -154,7 +192,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { ) -> Self { let mut this = Self { inner: Timer::new(tim) }; - this.inner.set_trigger_source(TriggerSource::TI2FP2); + this.inner.set_trigger_source(Ts::TI2FP2); this.inner .set_input_ti_selection(TimerChannel::Ch2, InputTISelection::Normal); this.inner @@ -186,7 +224,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { // No filtering r.set_etf(FilterValue::NO_FILTER); }); - this.inner.set_trigger_source(TriggerSource::ETRF); + this.inner.set_trigger_source(Ts::ETRF); this.new_inner(freq, pulse_end, counting_mode); this diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index bc7e71290..657052cfa 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -8,6 +8,7 @@ use super::low_level::Timer; pub use super::{Ch1, Ch2}; use super::{GeneralInstance4Channel, TimerPin}; use crate::gpio::{AfType, AnyPin, Pull}; +use crate::timer::Channel; use crate::Peri; /// Counting direction @@ -24,28 +25,31 @@ pub struct QeiPin<'d, T, Channel> { phantom: PhantomData<(T, Channel)>, } -// TODO: generify QEI channels - -macro_rules! channel_impl { - ($new_chx:ident, $channel:ident, $pin_trait:ident) => { - impl<'d, T: GeneralInstance4Channel> QeiPin<'d, T, $channel> { - #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")] - pub fn $new_chx(pin: Peri<'d, impl $pin_trait>) -> Self { - critical_section::with(|_| { - pin.set_low(); - pin.set_as_af(pin.af_num(), AfType::input(Pull::None)); - }); - QeiPin { - _pin: pin.into(), - phantom: PhantomData, - } - } +impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> { + /// Create a new QEI pin instance. + pub fn new(pin: Peri<'d, impl TimerPin>) -> Self { + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af(pin.af_num(), AfType::input(Pull::None)); + }); + QeiPin { + _pin: pin.into(), + phantom: PhantomData, } - }; + } } -channel_impl!(new_ch1, Ch1, TimerPin); -channel_impl!(new_ch2, Ch2, TimerPin); +trait SealedQeiChannel: Channel {} + +/// Marker trait for a timer channel eligible for use with QEI. +#[expect(private_bounds)] +pub trait QeiChannel: SealedQeiChannel {} + +impl QeiChannel for Ch1 {} +impl QeiChannel for Ch2 {} + +impl SealedQeiChannel for Ch1 {} +impl SealedQeiChannel for Ch2 {} /// Quadrature decoder driver. pub struct Qei<'d, T: GeneralInstance4Channel> { -- cgit From cbd24bf2eece65a787fc085c255e9b2932ea73e3 Mon Sep 17 00:00:00 2001 From: melvdl Date: Fri, 27 Jun 2025 01:04:47 +0200 Subject: stm32: fix timer break input 2 trait name in build script --- embassy-stm32/build.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 192688149..13fc23e54 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1103,8 +1103,8 @@ fn main() { (("timer", "BKIN_COMP1"), quote!(crate::timer::BreakInputComparator1Pin)), (("timer", "BKIN_COMP2"), quote!(crate::timer::BreakInputComparator2Pin)), (("timer", "BKIN2"), quote!(crate::timer::BreakInputPin)), - (("timer", "BKIN2_COMP1"), quote!(crate::timer::BreakInput2Comparator1Pin)), - (("timer", "BKIN2_COMP2"), quote!(crate::timer::BreakInput2Comparator2Pin)), + (("timer", "BKIN2_COMP1"), quote!(crate::timer::BreakInputComparator1Pin)), + (("timer", "BKIN2_COMP2"), quote!(crate::timer::BreakInputComparator2Pin)), (("hrtim", "CHA1"), quote!(crate::hrtim::ChannelAPin)), (("hrtim", "CHA2"), quote!(crate::hrtim::ChannelAComplementaryPin)), (("hrtim", "CHB1"), quote!(crate::hrtim::ChannelBPin)), -- cgit From 6f88c2c73caa63a6e534130f4a064cb95d3e9d7d Mon Sep 17 00:00:00 2001 From: melvdl Date: Fri, 27 Jun 2025 01:08:28 +0200 Subject: stm32: rename timer channel trait; replace impls via macro with impls generic over timer channels --- embassy-stm32/src/timer/complementary_pwm.rs | 33 ++-- embassy-stm32/src/timer/input_capture.rs | 41 ++-- embassy-stm32/src/timer/low_level.rs | 38 ++-- embassy-stm32/src/timer/mod.rs | 48 ++--- embassy-stm32/src/timer/one_pulse.rs | 44 ++--- embassy-stm32/src/timer/pwm_input.rs | 28 +-- embassy-stm32/src/timer/qei.rs | 4 +- embassy-stm32/src/timer/simple_pwm.rs | 279 ++++++++++++--------------- 8 files changed, 241 insertions(+), 274 deletions(-) diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 4600dd1a3..a450705a2 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -6,11 +6,11 @@ use stm32_metapac::timer::vals::Ckd; use super::low_level::{CountingMode, OutputPolarity, Timer}; use super::simple_pwm::PwmPin; -use super::{AdvancedInstance4Channel, Ch1, Ch2, Ch3, Ch4, TimerChannel, TimerComplementaryPin}; +use super::{AdvancedInstance4Channel, Ch1, Ch2, Ch3, Ch4, Channel, TimerComplementaryPin}; use crate::gpio::{AnyPin, OutputType}; use crate::time::Hertz; use crate::timer::low_level::OutputCompareMode; -use crate::timer::Channel; +use crate::timer::TimerChannel; use crate::Peri; /// Complementary PWM pin wrapper. @@ -21,7 +21,7 @@ pub struct ComplementaryPwmPin<'d, T, C> { phantom: PhantomData<(T, C)>, } -impl<'d, T: AdvancedInstance4Channel, C: Channel> ComplementaryPwmPin<'d, T, C> { +impl<'d, T: AdvancedInstance4Channel, C: TimerChannel> ComplementaryPwmPin<'d, T, C> { /// Create a new complementary PWM pin instance. pub fn new(pin: Peri<'d, impl TimerComplementaryPin>, output_type: OutputType) -> Self { critical_section::with(|_| { @@ -71,29 +71,24 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { this.inner.enable_outputs(); - [ - TimerChannel::Ch1, - TimerChannel::Ch2, - TimerChannel::Ch3, - TimerChannel::Ch4, - ] - .iter() - .for_each(|&channel| { - this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); - this.inner.set_output_compare_preload(channel, true); - }); + [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] + .iter() + .for_each(|&channel| { + this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); + this.inner.set_output_compare_preload(channel, true); + }); this } /// Enable the given channel. - pub fn enable(&mut self, channel: TimerChannel) { + pub fn enable(&mut self, channel: Channel) { self.inner.enable_channel(channel, true); self.inner.enable_complementary_channel(channel, true); } /// Disable the given channel. - pub fn disable(&mut self, channel: TimerChannel) { + pub fn disable(&mut self, channel: Channel) { self.inner.enable_complementary_channel(channel, false); self.inner.enable_channel(channel, false); } @@ -121,13 +116,13 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { /// Set the duty for a given channel. /// /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. - pub fn set_duty(&mut self, channel: TimerChannel, duty: u16) { + pub fn set_duty(&mut self, channel: Channel, duty: u16) { assert!(duty <= self.get_max_duty()); self.inner.set_compare_value(channel, duty as _) } /// Set the output polarity for a given channel. - pub fn set_polarity(&mut self, channel: TimerChannel, polarity: OutputPolarity) { + pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { self.inner.set_output_polarity(channel, polarity); self.inner.set_complementary_output_polarity(channel, polarity); } @@ -142,7 +137,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { } impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { - type Channel = TimerChannel; + type Channel = Channel; type Time = Hertz; type Duty = u16; diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index da567d504..49e22b10f 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -6,12 +6,12 @@ use core::pin::Pin; use core::task::{Context, Poll}; use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer}; -use super::{CaptureCompareInterruptHandler, GeneralInstance4Channel, TimerChannel, TimerPin}; +use super::{CaptureCompareInterruptHandler, GeneralInstance4Channel, Channel, TimerPin}; pub use super::{Ch1, Ch2, Ch3, Ch4}; use crate::gpio::{AfType, AnyPin, Pull}; use crate::interrupt::typelevel::{Binding, Interrupt}; use crate::time::Hertz; -use crate::timer::Channel; +use crate::timer::TimerChannel; use crate::Peri; /// Capture pin wrapper. @@ -21,7 +21,7 @@ pub struct CapturePin<'d, T, C> { _pin: Peri<'d, AnyPin>, phantom: PhantomData<(T, C)>, } -impl<'d, T: GeneralInstance4Channel, C: Channel> CapturePin<'d, T, C> { +impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> { /// Create a new capture pin instance. pub fn new(pin: Peri<'d, impl TimerPin>, pull: Pull) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); @@ -68,46 +68,41 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { } /// Enable the given channel. - pub fn enable(&mut self, channel: TimerChannel) { + pub fn enable(&mut self, channel: Channel) { self.inner.enable_channel(channel, true); } /// Disable the given channel. - pub fn disable(&mut self, channel: TimerChannel) { + pub fn disable(&mut self, channel: Channel) { self.inner.enable_channel(channel, false); } /// Check whether given channel is enabled - pub fn is_enabled(&self, channel: TimerChannel) -> bool { + pub fn is_enabled(&self, channel: Channel) -> bool { self.inner.get_channel_enable_state(channel) } /// Set the input capture mode for a given channel. - pub fn set_input_capture_mode(&mut self, channel: TimerChannel, mode: InputCaptureMode) { + pub fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { self.inner.set_input_capture_mode(channel, mode); } /// Set input TI selection. - pub fn set_input_ti_selection(&mut self, channel: TimerChannel, tisel: InputTISelection) { + pub fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) { self.inner.set_input_ti_selection(channel, tisel) } /// Get capture value for a channel. - pub fn get_capture_value(&self, channel: TimerChannel) -> u32 { + pub fn get_capture_value(&self, channel: Channel) -> u32 { self.inner.get_capture_value(channel) } /// Get input interrupt. - pub fn get_input_interrupt(&self, channel: TimerChannel) -> bool { + pub fn get_input_interrupt(&self, channel: Channel) -> bool { self.inner.get_input_interrupt(channel) } - fn new_future( - &self, - channel: TimerChannel, - mode: InputCaptureMode, - tisel: InputTISelection, - ) -> InputCaptureFuture { + fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture { // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.5 // or ST RM0008 (STM32F103) chapter 15.3.5 Input capture mode self.inner.set_input_ti_selection(channel, tisel); @@ -124,37 +119,37 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { } /// Asynchronously wait until the pin sees a rising edge. - pub async fn wait_for_rising_edge(&mut self, channel: TimerChannel) -> u32 { + pub async fn wait_for_rising_edge(&mut self, channel: Channel) -> u32 { self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Normal) .await } /// Asynchronously wait until the pin sees a falling edge. - pub async fn wait_for_falling_edge(&mut self, channel: TimerChannel) -> u32 { + pub async fn wait_for_falling_edge(&mut self, channel: Channel) -> u32 { self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Normal) .await } /// Asynchronously wait until the pin sees any edge. - pub async fn wait_for_any_edge(&mut self, channel: TimerChannel) -> u32 { + pub async fn wait_for_any_edge(&mut self, channel: Channel) -> u32 { self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Normal) .await } /// Asynchronously wait until the (alternate) pin sees a rising edge. - pub async fn wait_for_rising_edge_alternate(&mut self, channel: TimerChannel) -> u32 { + pub async fn wait_for_rising_edge_alternate(&mut self, channel: Channel) -> u32 { self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Alternate) .await } /// Asynchronously wait until the (alternate) pin sees a falling edge. - pub async fn wait_for_falling_edge_alternate(&mut self, channel: TimerChannel) -> u32 { + pub async fn wait_for_falling_edge_alternate(&mut self, channel: Channel) -> u32 { self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Alternate) .await } /// Asynchronously wait until the (alternate) pin sees any edge. - pub async fn wait_for_any_edge_alternate(&mut self, channel: TimerChannel) -> u32 { + pub async fn wait_for_any_edge_alternate(&mut self, channel: Channel) -> u32 { self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Alternate) .await } @@ -162,7 +157,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { #[must_use = "futures do nothing unless you `.await` or poll them"] struct InputCaptureFuture { - channel: TimerChannel, + channel: Channel, phantom: PhantomData, } diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index bfdbcf968..dc8ceb725 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -503,7 +503,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set input capture filter. - pub fn set_input_capture_filter(&self, channel: TimerChannel, icf: vals::FilterValue) { + pub fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) { let raw_channel = channel.index(); self.regs_gp16() .ccmr_input(raw_channel / 2) @@ -511,22 +511,22 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Clear input interrupt. - pub fn clear_input_interrupt(&self, channel: TimerChannel) { + pub fn clear_input_interrupt(&self, channel: Channel) { self.regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false)); } /// Get input interrupt. - pub fn get_input_interrupt(&self, channel: TimerChannel) -> bool { + pub fn get_input_interrupt(&self, channel: Channel) -> bool { self.regs_gp16().sr().read().ccif(channel.index()) } /// Enable input interrupt. - pub fn enable_input_interrupt(&self, channel: TimerChannel, enable: bool) { + pub fn enable_input_interrupt(&self, channel: Channel, enable: bool) { self.regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable)); } /// Set input capture prescaler. - pub fn set_input_capture_prescaler(&self, channel: TimerChannel, factor: u8) { + pub fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) { let raw_channel = channel.index(); self.regs_gp16() .ccmr_input(raw_channel / 2) @@ -534,7 +534,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set input TI selection. - pub fn set_input_ti_selection(&self, channel: TimerChannel, tisel: InputTISelection) { + pub fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) { let raw_channel = channel.index(); self.regs_gp16() .ccmr_input(raw_channel / 2) @@ -542,7 +542,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set input capture mode. - pub fn set_input_capture_mode(&self, channel: TimerChannel, mode: InputCaptureMode) { + pub fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) { self.regs_gp16().ccer().modify(|r| match mode { InputCaptureMode::Rising => { r.set_ccnp(channel.index(), false); @@ -560,7 +560,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set output compare mode. - pub fn set_output_compare_mode(&self, channel: TimerChannel, mode: OutputCompareMode) { + pub fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) { let raw_channel: usize = channel.index(); self.regs_gp16() .ccmr_output(raw_channel / 2) @@ -568,24 +568,24 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set output polarity. - pub fn set_output_polarity(&self, channel: TimerChannel, polarity: OutputPolarity) { + pub fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { self.regs_gp16() .ccer() .modify(|w| w.set_ccp(channel.index(), polarity.into())); } /// Enable/disable a channel. - pub fn enable_channel(&self, channel: TimerChannel, enable: bool) { + pub fn enable_channel(&self, channel: Channel, enable: bool) { self.regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable)); } /// Get enable/disable state of a channel - pub fn get_channel_enable_state(&self, channel: TimerChannel) -> bool { + pub fn get_channel_enable_state(&self, channel: Channel) -> bool { self.regs_gp16().ccer().read().cce(channel.index()) } /// Set compare value for a channel. - pub fn set_compare_value(&self, channel: TimerChannel, value: u32) { + pub fn set_compare_value(&self, channel: Channel, value: u32) { match T::BITS { TimerBits::Bits16 => { let value = unwrap!(u16::try_from(value)); @@ -599,7 +599,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Get compare value for a channel. - pub fn get_compare_value(&self, channel: TimerChannel) -> u32 { + pub fn get_compare_value(&self, channel: Channel) -> u32 { match T::BITS { TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32, #[cfg(not(stm32l0))] @@ -608,12 +608,12 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Get capture value for a channel. - pub fn get_capture_value(&self, channel: TimerChannel) -> u32 { + pub fn get_capture_value(&self, channel: Channel) -> u32 { self.get_compare_value(channel) } /// Set output compare preload. - pub fn set_output_compare_preload(&self, channel: TimerChannel, preload: bool) { + pub fn set_output_compare_preload(&self, channel: Channel, preload: bool) { let channel_index = channel.index(); self.regs_gp16() .ccmr_output(channel_index / 2) @@ -631,12 +631,12 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Get capture compare DMA enable state - pub fn get_cc_dma_enable_state(&self, channel: TimerChannel) -> bool { + pub fn get_cc_dma_enable_state(&self, channel: Channel) -> bool { self.regs_gp16().dier().read().ccde(channel.index()) } /// Set capture compare DMA enable state - pub fn set_cc_dma_enable_state(&self, channel: TimerChannel, ccde: bool) { + pub fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) { self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) } @@ -713,14 +713,14 @@ impl<'d, T: AdvancedInstance4Channel> Timer<'d, T> { } /// Set complementary output polarity. - pub fn set_complementary_output_polarity(&self, channel: TimerChannel, polarity: OutputPolarity) { + pub fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { self.regs_advanced() .ccer() .modify(|w| w.set_ccnp(channel.index(), polarity.into())); } /// Enable/disable a complementary channel. - pub fn enable_complementary_channel(&self, channel: TimerChannel, enable: bool) { + pub fn enable_complementary_channel(&self, channel: Channel, enable: bool) { self.regs_advanced() .ccer() .modify(|w| w.set_ccne(channel.index(), enable)); diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 362d95e25..7062f5f4c 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -19,7 +19,7 @@ use crate::rcc::RccPeripheral; /// Timer channel. #[derive(Clone, Copy)] -pub enum TimerChannel { +pub enum Channel { /// Channel 1. Ch1, /// Channel 2. @@ -30,14 +30,14 @@ pub enum TimerChannel { Ch4, } -impl TimerChannel { +impl Channel { /// Get the channel index (0..3) pub fn index(&self) -> usize { match self { - TimerChannel::Ch1 => 0, - TimerChannel::Ch2 => 1, - TimerChannel::Ch3 => 2, - TimerChannel::Ch4 => 3, + Channel::Ch1 => 0, + Channel::Ch2 => 1, + Channel::Ch3 => 2, + Channel::Ch4 => 3, } } } @@ -53,33 +53,33 @@ pub enum Ch4 {} /// Timer channel trait. #[allow(private_bounds)] -pub trait Channel: SealedChannel { +pub trait TimerChannel: SealedTimerChannel { /// The runtime channel. - const CHANNEL: TimerChannel; + const CHANNEL: Channel; } -trait SealedChannel {} +trait SealedTimerChannel {} -impl Channel for Ch1 { - const CHANNEL: TimerChannel = TimerChannel::Ch1; +impl TimerChannel for Ch1 { + const CHANNEL: Channel = Channel::Ch1; } -impl Channel for Ch2 { - const CHANNEL: TimerChannel = TimerChannel::Ch2; +impl TimerChannel for Ch2 { + const CHANNEL: Channel = Channel::Ch2; } -impl Channel for Ch3 { - const CHANNEL: TimerChannel = TimerChannel::Ch3; +impl TimerChannel for Ch3 { + const CHANNEL: Channel = Channel::Ch3; } -impl Channel for Ch4 { - const CHANNEL: TimerChannel = TimerChannel::Ch4; +impl TimerChannel for Ch4 { + const CHANNEL: Channel = Channel::Ch4; } -impl SealedChannel for Ch1 {} -impl SealedChannel for Ch2 {} -impl SealedChannel for Ch3 {} -impl SealedChannel for Ch4 {} +impl SealedTimerChannel for Ch1 {} +impl SealedTimerChannel for Ch2 {} +impl SealedTimerChannel for Ch3 {} +impl SealedTimerChannel for Ch4 {} /// Timer break input. #[derive(Clone, Copy)] @@ -223,10 +223,10 @@ pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + Ad /// Advanced 16-bit timer with 4 channels instance. pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {} -pin_trait!(TimerPin, GeneralInstance4Channel, Channel); +pin_trait!(TimerPin, GeneralInstance4Channel, TimerChannel); pin_trait!(ExternalTriggerPin, GeneralInstance4Channel); -pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, Channel); +pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, TimerChannel); pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput); @@ -236,7 +236,7 @@ pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput); // Update Event trigger DMA for every timer dma_trait!(UpDma, BasicInstance); -dma_trait!(Dma, GeneralInstance4Channel, Channel); +dma_trait!(Dma, GeneralInstance4Channel, TimerChannel); #[allow(unused)] macro_rules! impl_core_timer { diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs index e89ad8390..c8f0cafe7 100644 --- a/embassy-stm32/src/timer/one_pulse.rs +++ b/embassy-stm32/src/timer/one_pulse.rs @@ -9,7 +9,7 @@ use core::task::{Context, Poll}; use super::low_level::{ CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource as Ts, }; -use super::{CaptureCompareInterruptHandler, ExternalTriggerPin, GeneralInstance4Channel, TimerChannel, TimerPin}; +use super::{CaptureCompareInterruptHandler, Channel, ExternalTriggerPin, GeneralInstance4Channel, TimerPin}; pub use super::{Ch1, Ch2}; use crate::gpio::{AfType, AnyPin, Pull}; use crate::interrupt::typelevel::{Binding, Interrupt}; @@ -76,7 +76,7 @@ impl TimerTriggerPin for P where T: GeneralInstance4Channel, P: TimerPin, - C: super::Channel + TriggerSource, + C: super::TimerChannel + TriggerSource, { fn af_num(&self) -> u8 { TimerPin::af_num(self) @@ -97,7 +97,7 @@ impl SealedTimerTriggerPin for P where T: GeneralInstance4Channel, P: TimerPin, - C: super::Channel + TriggerSource, + C: super::TimerChannel + TriggerSource, { } @@ -143,9 +143,9 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { this.inner.set_trigger_source(Ts::TI1F_ED); this.inner - .set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal); + .set_input_ti_selection(Channel::Ch1, InputTISelection::Normal); this.inner - .set_input_capture_filter(TimerChannel::Ch1, FilterValue::NO_FILTER); + .set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER); this.new_inner(freq, pulse_end, counting_mode); this @@ -168,10 +168,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { this.inner.set_trigger_source(Ts::TI1FP1); this.inner - .set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal); + .set_input_ti_selection(Channel::Ch1, InputTISelection::Normal); this.inner - .set_input_capture_filter(TimerChannel::Ch1, FilterValue::NO_FILTER); - this.inner.set_input_capture_mode(TimerChannel::Ch1, capture_mode); + .set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER); + this.inner.set_input_capture_mode(Channel::Ch1, capture_mode); this.new_inner(freq, pulse_end, counting_mode); this @@ -194,10 +194,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { this.inner.set_trigger_source(Ts::TI2FP2); this.inner - .set_input_ti_selection(TimerChannel::Ch2, InputTISelection::Normal); + .set_input_ti_selection(Channel::Ch2, InputTISelection::Normal); this.inner - .set_input_capture_filter(TimerChannel::Ch2, FilterValue::NO_FILTER); - this.inner.set_input_capture_mode(TimerChannel::Ch2, capture_mode); + .set_input_capture_filter(Channel::Ch2, FilterValue::NO_FILTER); + this.inner.set_input_capture_mode(Channel::Ch2, capture_mode); this.new_inner(freq, pulse_end, counting_mode); this @@ -269,7 +269,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// Get a single channel /// /// If you need to use multiple channels, use [`Self::split`]. - pub fn channel(&mut self, channel: TimerChannel) -> OnePulseChannel<'_, T> { + pub fn channel(&mut self, channel: Channel) -> OnePulseChannel<'_, T> { OnePulseChannel { inner: unsafe { self.inner.clone_unchecked() }, channel, @@ -282,7 +282,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch1(&mut self) -> OnePulseChannel<'_, T> { - self.channel(TimerChannel::Ch1) + self.channel(Channel::Ch1) } /// Channel 2 @@ -291,7 +291,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch2(&mut self) -> OnePulseChannel<'_, T> { - self.channel(TimerChannel::Ch2) + self.channel(Channel::Ch2) } /// Channel 3 @@ -300,7 +300,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch3(&mut self) -> OnePulseChannel<'_, T> { - self.channel(TimerChannel::Ch3) + self.channel(Channel::Ch3) } /// Channel 4 @@ -309,7 +309,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch4(&mut self) -> OnePulseChannel<'_, T> { - self.channel(TimerChannel::Ch4) + self.channel(Channel::Ch4) } /// Splits a [`OnePulse`] into four output channels. @@ -328,10 +328,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { }; OnePulseChannels { - ch1: ch(TimerChannel::Ch1), - ch2: ch(TimerChannel::Ch2), - ch3: ch(TimerChannel::Ch3), - ch4: ch(TimerChannel::Ch4), + ch1: ch(Channel::Ch1), + ch2: ch(Channel::Ch2), + ch3: ch(Channel::Ch3), + ch4: ch(Channel::Ch4), } } } @@ -355,7 +355,7 @@ pub struct OnePulseChannels<'d, T: GeneralInstance4Channel> { /// configuration is shared with all four channels. pub struct OnePulseChannel<'d, T: GeneralInstance4Channel> { inner: ManuallyDrop>, - channel: TimerChannel, + channel: Channel, } impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> { @@ -402,7 +402,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> { #[must_use = "futures do nothing unless you `.await` or poll them"] struct OnePulseFuture { - channel: TimerChannel, + channel: Channel, phantom: PhantomData, } diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index 3f9e5f651..2e05a0593 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -1,14 +1,14 @@ //! PWM Input driver. use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource}; -use super::{Ch1, Ch2, GeneralInstance4Channel, TimerChannel, TimerPin}; +use super::{Ch1, Ch2, GeneralInstance4Channel, Channel, TimerPin}; use crate::gpio::{AfType, Pull}; use crate::time::Hertz; use crate::Peri; /// PWM Input driver. pub struct PwmInput<'d, T: GeneralInstance4Channel> { - channel: TimerChannel, + channel: Channel, inner: Timer<'d, T>, } @@ -17,17 +17,17 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { pub fn new(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); - Self::new_inner(tim, freq, TimerChannel::Ch1, TimerChannel::Ch2) + Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2) } /// Create a new PWM input driver. pub fn new_alt(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); - Self::new_inner(tim, freq, TimerChannel::Ch2, TimerChannel::Ch1) + Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1) } - fn new_inner(tim: Peri<'d, T>, freq: Hertz, ch1: TimerChannel, ch2: TimerChannel) -> Self { + fn new_inner(tim: Peri<'d, T>, freq: Hertz, ch1: Channel, ch2: Channel) -> Self { let mut inner = Timer::new(tim); inner.set_counting_mode(CountingMode::EdgeAlignedUp); @@ -44,8 +44,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { inner.set_input_capture_mode(ch2, InputCaptureMode::Falling); inner.set_trigger_source(match ch1 { - TimerChannel::Ch1 => TriggerSource::TI1FP1, - TimerChannel::Ch2 => TriggerSource::TI2FP2, + Channel::Ch1 => TriggerSource::TI1FP1, + Channel::Ch2 => TriggerSource::TI2FP2, _ => panic!("Invalid channel for PWM input"), }); @@ -58,19 +58,19 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { /// Enable the given channel. pub fn enable(&mut self) { - self.inner.enable_channel(TimerChannel::Ch1, true); - self.inner.enable_channel(TimerChannel::Ch2, true); + self.inner.enable_channel(Channel::Ch1, true); + self.inner.enable_channel(Channel::Ch2, true); } /// Disable the given channel. pub fn disable(&mut self) { - self.inner.enable_channel(TimerChannel::Ch1, false); - self.inner.enable_channel(TimerChannel::Ch2, false); + self.inner.enable_channel(Channel::Ch1, false); + self.inner.enable_channel(Channel::Ch2, false); } /// Check whether given channel is enabled pub fn is_enabled(&self) -> bool { - self.inner.get_channel_enable_state(TimerChannel::Ch1) + self.inner.get_channel_enable_state(Channel::Ch1) } /// Get the period tick count @@ -81,8 +81,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { /// Get the pulse width tick count pub fn get_width_ticks(&self) -> u32 { self.inner.get_capture_value(match self.channel { - TimerChannel::Ch1 => TimerChannel::Ch2, - TimerChannel::Ch2 => TimerChannel::Ch1, + Channel::Ch1 => Channel::Ch2, + Channel::Ch2 => Channel::Ch1, _ => panic!("Invalid channel for PWM input"), }) } diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index 657052cfa..eabe1b22a 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -8,7 +8,7 @@ use super::low_level::Timer; pub use super::{Ch1, Ch2}; use super::{GeneralInstance4Channel, TimerPin}; use crate::gpio::{AfType, AnyPin, Pull}; -use crate::timer::Channel; +use crate::timer::TimerChannel; use crate::Peri; /// Counting direction @@ -39,7 +39,7 @@ impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> { } } -trait SealedQeiChannel: Channel {} +trait SealedQeiChannel: TimerChannel {} /// Marker trait for a timer channel eligible for use with QEI. #[expect(private_bounds)] diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 02835c379..c04b1ab97 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -4,7 +4,7 @@ use core::marker::PhantomData; use core::mem::ManuallyDrop; use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer}; -use super::{Ch1, Ch2, Ch3, Ch4, GeneralInstance4Channel, TimerBits, TimerChannel, TimerPin}; +use super::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance4Channel, TimerBits, TimerChannel, TimerPin}; #[cfg(gpio_v2)] use crate::gpio::Pull; use crate::gpio::{AfType, AnyPin, OutputType, Speed}; @@ -34,46 +34,37 @@ pub struct PwmPinConfig { pub pull: Pull, } -macro_rules! channel_impl { - ($new_chx:ident, $new_chx_with_config:ident, $channel:ident, $pin_trait:ident) => { - impl<'d, T: GeneralInstance4Channel> PwmPin<'d, T, $channel> { - #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")] - pub fn $new_chx(pin: Peri<'d, impl $pin_trait>, output_type: OutputType) -> Self { - critical_section::with(|_| { - pin.set_low(); - pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh)); - }); - PwmPin { - _pin: pin.into(), - phantom: PhantomData, - } - } - - #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance with config.")] - pub fn $new_chx_with_config(pin: Peri<'d, impl $pin_trait>, pin_config: PwmPinConfig) -> Self { - critical_section::with(|_| { - pin.set_low(); - pin.set_as_af( - pin.af_num(), - #[cfg(gpio_v1)] - AfType::output(pin_config.output_type, pin_config.speed), - #[cfg(gpio_v2)] - AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull), - ); - }); - PwmPin { - _pin: pin.into(), - phantom: PhantomData, - } - } +impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> { + /// Create a new PWM pin instance. + pub fn new(pin: Peri<'d, impl TimerPin>, output_type: OutputType) -> Self { + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh)); + }); + PwmPin { + _pin: pin.into(), + phantom: PhantomData, } - }; -} + } -channel_impl!(new_ch1, new_ch1_with_config, Ch1, TimerPin); -channel_impl!(new_ch2, new_ch2_with_config, Ch2, TimerPin); -channel_impl!(new_ch3, new_ch3_with_config, Ch3, TimerPin); -channel_impl!(new_ch4, new_ch4_with_config, Ch4, TimerPin); + /// Create a new PWM pin instance with config. + pub fn new_with_config(pin: Peri<'d, impl TimerPin>, pin_config: PwmPinConfig) -> Self { + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af( + pin.af_num(), + #[cfg(gpio_v1)] + AfType::output(pin_config.output_type, pin_config.speed), + #[cfg(gpio_v2)] + AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull), + ); + }); + PwmPin { + _pin: pin.into(), + phantom: PhantomData, + } + } +} /// A single channel of a pwm, obtained from [`SimplePwm::split`], /// [`SimplePwm::channel`], [`SimplePwm::ch1`], etc. @@ -82,7 +73,7 @@ channel_impl!(new_ch4, new_ch4_with_config, Ch4, TimerPin); /// the frequency configuration is shared with all four channels. pub struct SimplePwmChannel<'d, T: GeneralInstance4Channel> { timer: ManuallyDrop>, - channel: TimerChannel, + channel: Channel, } // TODO: check for RMW races @@ -207,18 +198,13 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details this.inner.start(); - [ - TimerChannel::Ch1, - TimerChannel::Ch2, - TimerChannel::Ch3, - TimerChannel::Ch4, - ] - .iter() - .for_each(|&channel| { - this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); - - this.inner.set_output_compare_preload(channel, true); - }); + [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] + .iter() + .for_each(|&channel| { + this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); + + this.inner.set_output_compare_preload(channel, true); + }); this } @@ -226,7 +212,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// Get a single channel /// /// If you need to use multiple channels, use [`Self::split`]. - pub fn channel(&mut self, channel: TimerChannel) -> SimplePwmChannel<'_, T> { + pub fn channel(&mut self, channel: Channel) -> SimplePwmChannel<'_, T> { SimplePwmChannel { timer: unsafe { self.inner.clone_unchecked() }, channel, @@ -239,7 +225,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch1(&mut self) -> SimplePwmChannel<'_, T> { - self.channel(TimerChannel::Ch1) + self.channel(Channel::Ch1) } /// Channel 2 @@ -248,7 +234,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch2(&mut self) -> SimplePwmChannel<'_, T> { - self.channel(TimerChannel::Ch2) + self.channel(Channel::Ch2) } /// Channel 3 @@ -257,7 +243,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch3(&mut self) -> SimplePwmChannel<'_, T> { - self.channel(TimerChannel::Ch3) + self.channel(Channel::Ch3) } /// Channel 4 @@ -266,7 +252,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch4(&mut self) -> SimplePwmChannel<'_, T> { - self.channel(TimerChannel::Ch4) + self.channel(Channel::Ch4) } /// Splits a [`SimplePwm`] into four pwm channels. @@ -288,10 +274,10 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { }; SimplePwmChannels { - ch1: ch(TimerChannel::Ch1), - ch2: ch(TimerChannel::Ch2), - ch3: ch(TimerChannel::Ch3), - ch4: ch(TimerChannel::Ch4), + ch1: ch(Channel::Ch1), + ch2: ch(Channel::Ch2), + ch3: ch(Channel::Ch3), + ch4: ch(Channel::Ch4), } } @@ -322,7 +308,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// Note: /// you will need to provide corresponding TIMx_UP DMA channel to use this method. - pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma>, channel: TimerChannel, duty: &[u16]) { + pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma>, channel: Channel, duty: &[u16]) { #[allow(clippy::let_unit_value)] // eg. stm32f334 let req = dma.request(); @@ -405,8 +391,8 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { pub async fn waveform_up_multi_channel( &mut self, dma: Peri<'_, impl super::UpDma>, - starting_channel: TimerChannel, - ending_channel: TimerChannel, + starting_channel: Channel, + ending_channel: Channel, duty: &[u16], ) { let cr1_addr = self.inner.regs_gp16().cr1().as_ptr() as u32; @@ -462,106 +448,97 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { } } -macro_rules! impl_waveform_chx { - ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => { - impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { - /// Generate a sequence of PWM waveform - pub async fn $fn_name(&mut self, dma: Peri<'_, impl super::$dma_ch>, duty: &[u16]) { - use crate::pac::timer::vals::Ccds; +impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { + /// Generate a sequence of PWM waveform + pub async fn waveform(&mut self, dma: Peri<'_, impl super::Dma>, duty: &[u16]) { + use crate::pac::timer::vals::Ccds; - #[allow(clippy::let_unit_value)] // eg. stm32f334 - let req = dma.request(); + #[allow(clippy::let_unit_value)] // eg. stm32f334 + let req = dma.request(); - let cc_channel = TimerChannel::$cc_ch; + let cc_channel = C::CHANNEL; - let original_duty_state = self.channel(cc_channel).current_duty_cycle(); - let original_enable_state = self.channel(cc_channel).is_enabled(); - let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ON_UPDATE; - let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel); + let original_duty_state = self.channel(cc_channel).current_duty_cycle(); + let original_enable_state = self.channel(cc_channel).is_enabled(); + let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ON_UPDATE; + let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel); - // redirect CC DMA request onto Update Event - if !original_cc_dma_on_update { - self.inner.set_cc_dma_selection(Ccds::ON_UPDATE) - } + // redirect CC DMA request onto Update Event + if !original_cc_dma_on_update { + self.inner.set_cc_dma_selection(Ccds::ON_UPDATE) + } - if !original_cc_dma_enabled { - self.inner.set_cc_dma_enable_state(cc_channel, true); - } + if !original_cc_dma_enabled { + self.inner.set_cc_dma_enable_state(cc_channel, true); + } - if !original_enable_state { - self.channel(cc_channel).enable(); - } + if !original_enable_state { + self.channel(cc_channel).enable(); + } - unsafe { + unsafe { + #[cfg(not(any(bdma, gpdma)))] + use crate::dma::{Burst, FifoThreshold}; + use crate::dma::{Transfer, TransferOptions}; + + let dma_transfer_option = TransferOptions { + #[cfg(not(any(bdma, gpdma)))] + fifo_threshold: Some(FifoThreshold::Full), + #[cfg(not(any(bdma, gpdma)))] + mburst: Burst::Incr8, + ..Default::default() + }; + + match self.inner.bits() { + TimerBits::Bits16 => { + Transfer::new_write( + dma, + req, + duty, + self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16, + dma_transfer_option, + ) + .await + } + #[cfg(not(any(stm32l0)))] + TimerBits::Bits32 => { #[cfg(not(any(bdma, gpdma)))] - use crate::dma::{Burst, FifoThreshold}; - use crate::dma::{Transfer, TransferOptions}; - - let dma_transfer_option = TransferOptions { - #[cfg(not(any(bdma, gpdma)))] - fifo_threshold: Some(FifoThreshold::Full), - #[cfg(not(any(bdma, gpdma)))] - mburst: Burst::Incr8, - ..Default::default() - }; - - match self.inner.bits() { - TimerBits::Bits16 => { - Transfer::new_write( - dma, - req, - duty, - self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16, - dma_transfer_option, - ) - .await - } - #[cfg(not(any(stm32l0)))] - TimerBits::Bits32 => { - #[cfg(not(any(bdma, gpdma)))] - panic!("unsupported timer bits"); - - #[cfg(any(bdma, gpdma))] - Transfer::new_write( - dma, - req, - duty, - self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32, - dma_transfer_option, - ) - .await - } - }; - }; - - // restore output compare state - if !original_enable_state { - self.channel(cc_channel).disable(); + panic!("unsupported timer bits"); + + #[cfg(any(bdma, gpdma))] + Transfer::new_write( + dma, + req, + duty, + self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32, + dma_transfer_option, + ) + .await } + }; + }; - self.channel(cc_channel).set_duty_cycle(original_duty_state); + // restore output compare state + if !original_enable_state { + self.channel(cc_channel).disable(); + } - // Since DMA is closed before timer Capture Compare Event trigger DMA is turn off, - // this can almost always trigger a DMA FIFO error. - // - // optional TODO: - // clean FEIF after disable UDE - if !original_cc_dma_enabled { - self.inner.set_cc_dma_enable_state(cc_channel, false); - } + self.channel(cc_channel).set_duty_cycle(original_duty_state); - if !original_cc_dma_on_update { - self.inner.set_cc_dma_selection(Ccds::ON_COMPARE) - } - } + // Since DMA is closed before timer Capture Compare Event trigger DMA is turn off, + // this can almost always trigger a DMA FIFO error. + // + // optional TODO: + // clean FEIF after disable UDE + if !original_cc_dma_enabled { + self.inner.set_cc_dma_enable_state(cc_channel, false); } - }; -} -impl_waveform_chx!(waveform_ch1, Dma, Ch1); -impl_waveform_chx!(waveform_ch2, Dma, Ch2); -impl_waveform_chx!(waveform_ch3, Dma, Ch3); -impl_waveform_chx!(waveform_ch4, Dma, Ch4); + if !original_cc_dma_on_update { + self.inner.set_cc_dma_selection(Ccds::ON_COMPARE) + } + } +} impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> { type Error = core::convert::Infallible; @@ -599,7 +576,7 @@ impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::SetDutyCycle for Simpl } impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> { - type Channel = TimerChannel; + type Channel = Channel; type Time = Hertz; type Duty = u32; -- cgit From 41327c1325367177548dabc644636617274de7f4 Mon Sep 17 00:00:00 2001 From: melvdl Date: Fri, 27 Jun 2025 01:08:45 +0200 Subject: stm32: adapt examples to timer API changes --- examples/stm32f1/src/bin/input_capture.rs | 2 +- examples/stm32f4/src/bin/input_capture.rs | 2 +- examples/stm32f4/src/bin/pwm.rs | 2 +- examples/stm32f4/src/bin/pwm_complementary.rs | 4 ++-- examples/stm32f4/src/bin/ws2812_pwm.rs | 2 +- examples/stm32g0/src/bin/hf_timer.rs | 4 ++-- examples/stm32g0/src/bin/input_capture.rs | 4 ++-- examples/stm32g0/src/bin/pwm_complementary.rs | 8 ++++---- examples/stm32g0/src/bin/pwm_input.rs | 2 +- examples/stm32g4/src/bin/pwm.rs | 2 +- examples/stm32h7/src/bin/low_level_timer_api.rs | 10 +++++----- examples/stm32h7/src/bin/pwm.rs | 2 +- examples/stm32l0/src/bin/dds.rs | 4 ++-- 13 files changed, 24 insertions(+), 24 deletions(-) diff --git a/examples/stm32f1/src/bin/input_capture.rs b/examples/stm32f1/src/bin/input_capture.rs index 6fe8e0b50..84811fb95 100644 --- a/examples/stm32f1/src/bin/input_capture.rs +++ b/examples/stm32f1/src/bin/input_capture.rs @@ -39,7 +39,7 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(blinky(p.PC13))); - let ch3 = CapturePin::new_ch3(p.PA2, Pull::None); + let ch3 = CapturePin::new(p.PA2, Pull::None); let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); loop { diff --git a/examples/stm32f4/src/bin/input_capture.rs b/examples/stm32f4/src/bin/input_capture.rs index fe5e2bdfc..e15b4d26e 100644 --- a/examples/stm32f4/src/bin/input_capture.rs +++ b/examples/stm32f4/src/bin/input_capture.rs @@ -39,7 +39,7 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(blinky(p.PB2))); - let ch3 = CapturePin::new_ch3(p.PB10, Pull::None); + let ch3 = CapturePin::new(p.PB10, Pull::None); let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); loop { diff --git a/examples/stm32f4/src/bin/pwm.rs b/examples/stm32f4/src/bin/pwm.rs index 04811162b..e385842f0 100644 --- a/examples/stm32f4/src/bin/pwm.rs +++ b/examples/stm32f4/src/bin/pwm.rs @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let ch1_pin = PwmPin::new_ch1(p.PE9, OutputType::PushPull); + let ch1_pin = PwmPin::new(p.PE9, OutputType::PushPull); let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default()); let mut ch1 = pwm.ch1(); ch1.enable(); diff --git a/examples/stm32f4/src/bin/pwm_complementary.rs b/examples/stm32f4/src/bin/pwm_complementary.rs index 161f43c48..c981f1a76 100644 --- a/examples/stm32f4/src/bin/pwm_complementary.rs +++ b/examples/stm32f4/src/bin/pwm_complementary.rs @@ -16,8 +16,8 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let ch1 = PwmPin::new_ch1(p.PE9, OutputType::PushPull); - let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull); + let ch1 = PwmPin::new(p.PE9, OutputType::PushPull); + let ch1n = ComplementaryPwmPin::new(p.PA7, OutputType::PushPull); let mut pwm = ComplementaryPwm::new( p.TIM1, Some(ch1), diff --git a/examples/stm32f4/src/bin/ws2812_pwm.rs b/examples/stm32f4/src/bin/ws2812_pwm.rs index ca924e181..5153e1cfd 100644 --- a/examples/stm32f4/src/bin/ws2812_pwm.rs +++ b/examples/stm32f4/src/bin/ws2812_pwm.rs @@ -50,7 +50,7 @@ async fn main(_spawner: Spawner) { let mut ws2812_pwm = SimplePwm::new( dp.TIM3, - Some(PwmPin::new_ch1(dp.PB4, OutputType::PushPull)), + Some(PwmPin::new(dp.PB4, OutputType::PushPull)), None, None, None, diff --git a/examples/stm32g0/src/bin/hf_timer.rs b/examples/stm32g0/src/bin/hf_timer.rs index dfb6e0edc..705905f01 100644 --- a/examples/stm32g0/src/bin/hf_timer.rs +++ b/examples/stm32g0/src/bin/hf_timer.rs @@ -37,8 +37,8 @@ async fn main(_spawner: Spawner) { } let p = embassy_stm32::init(config); - let ch1 = PwmPin::new_ch1(p.PA8, OutputType::PushPull); - let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull); + let ch1 = PwmPin::new(p.PA8, OutputType::PushPull); + let ch1n = ComplementaryPwmPin::new(p.PA7, OutputType::PushPull); let mut pwm = ComplementaryPwm::new( p.TIM1, diff --git a/examples/stm32g0/src/bin/input_capture.rs b/examples/stm32g0/src/bin/input_capture.rs index 08df4e043..df339d541 100644 --- a/examples/stm32g0/src/bin/input_capture.rs +++ b/examples/stm32g0/src/bin/input_capture.rs @@ -47,12 +47,12 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(blinky(p.PB1))); // Connect PB1 and PA8 with a 1k Ohm resistor - let ch1_pin = PwmPin::new_ch1(p.PA8, OutputType::PushPull); + let ch1_pin = PwmPin::new(p.PA8, OutputType::PushPull); let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default()); pwm.ch1().enable(); pwm.ch1().set_duty_cycle(50); - let ch1 = CapturePin::new_ch1(p.PA0, Pull::None); + let ch1 = CapturePin::new(p.PA0, Pull::None); let mut ic = InputCapture::new(p.TIM2, Some(ch1), None, None, None, Irqs, khz(1000), Default::default()); let mut old_capture = 0; diff --git a/examples/stm32g0/src/bin/pwm_complementary.rs b/examples/stm32g0/src/bin/pwm_complementary.rs index 97b163c40..dbd9194c9 100644 --- a/examples/stm32g0/src/bin/pwm_complementary.rs +++ b/examples/stm32g0/src/bin/pwm_complementary.rs @@ -26,10 +26,10 @@ use {defmt_rtt as _, panic_probe as _}; async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let ch1 = PwmPin::new_ch1(p.PA8, OutputType::PushPull); - let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull); - let ch2 = PwmPin::new_ch2(p.PB3, OutputType::PushPull); - let ch2n = ComplementaryPwmPin::new_ch2(p.PB0, OutputType::PushPull); + let ch1 = PwmPin::new(p.PA8, OutputType::PushPull); + let ch1n = ComplementaryPwmPin::new(p.PA7, OutputType::PushPull); + let ch2 = PwmPin::new(p.PB3, OutputType::PushPull); + let ch2n = ComplementaryPwmPin::new(p.PB0, OutputType::PushPull); let mut pwm = ComplementaryPwm::new( p.TIM1, diff --git a/examples/stm32g0/src/bin/pwm_input.rs b/examples/stm32g0/src/bin/pwm_input.rs index 9d6b5fe97..dc2428607 100644 --- a/examples/stm32g0/src/bin/pwm_input.rs +++ b/examples/stm32g0/src/bin/pwm_input.rs @@ -42,7 +42,7 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(blinky(p.PB1))); // Connect PA8 and PA6 with a 1k Ohm resistor - let ch1_pin = PwmPin::new_ch1(p.PA8, OutputType::PushPull); + let ch1_pin = PwmPin::new(p.PA8, OutputType::PushPull); let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default()); pwm.ch1().set_duty_cycle_fraction(1, 4); pwm.ch1().enable(); diff --git a/examples/stm32g4/src/bin/pwm.rs b/examples/stm32g4/src/bin/pwm.rs index 6c965012c..5b4194927 100644 --- a/examples/stm32g4/src/bin/pwm.rs +++ b/examples/stm32g4/src/bin/pwm.rs @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let ch1_pin = PwmPin::new_ch1(p.PC0, OutputType::PushPull); + let ch1_pin = PwmPin::new(p.PC0, OutputType::PushPull); let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default()); let mut ch1 = pwm.ch1(); ch1.enable(); diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs index 8de31ea5b..12abb8693 100644 --- a/examples/stm32h7/src/bin/low_level_timer_api.rs +++ b/examples/stm32h7/src/bin/low_level_timer_api.rs @@ -6,7 +6,7 @@ use embassy_executor::Spawner; use embassy_stm32::gpio::{AfType, Flex, OutputType, Speed}; use embassy_stm32::time::{khz, Hertz}; use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer}; -use embassy_stm32::timer::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance32bit4Channel}; +use embassy_stm32::timer::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance32bit4Channel, TimerPin}; use embassy_stm32::{Config, Peri}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; @@ -67,10 +67,10 @@ pub struct SimplePwm32<'d, T: GeneralInstance32bit4Channel> { impl<'d, T: GeneralInstance32bit4Channel> SimplePwm32<'d, T> { pub fn new( tim: Peri<'d, T>, - ch1: Peri<'d, impl Channel1Pin>, - ch2: Peri<'d, impl Channel2Pin>, - ch3: Peri<'d, impl Channel3Pin>, - ch4: Peri<'d, impl Channel4Pin>, + ch1: Peri<'d, impl TimerPin>, + ch2: Peri<'d, impl TimerPin>, + ch3: Peri<'d, impl TimerPin>, + ch4: Peri<'d, impl TimerPin>, freq: Hertz, ) -> Self { let af1 = ch1.af_num(); diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs index a1c53fc3f..73b43be69 100644 --- a/examples/stm32h7/src/bin/pwm.rs +++ b/examples/stm32h7/src/bin/pwm.rs @@ -36,7 +36,7 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(config); info!("Hello World!"); - let ch1_pin = PwmPin::new_ch1(p.PA6, OutputType::PushPull); + let ch1_pin = PwmPin::new(p.PA6, OutputType::PushPull); let mut pwm = SimplePwm::new(p.TIM3, Some(ch1_pin), None, None, None, khz(10), Default::default()); let mut ch1 = pwm.ch1(); ch1.enable(); diff --git a/examples/stm32l0/src/bin/dds.rs b/examples/stm32l0/src/bin/dds.rs index a54b28a93..eaa7a61a8 100644 --- a/examples/stm32l0/src/bin/dds.rs +++ b/examples/stm32l0/src/bin/dds.rs @@ -11,7 +11,7 @@ use embassy_stm32::rcc::*; use embassy_stm32::time::hz; use embassy_stm32::timer::low_level::{Timer as LLTimer, *}; use embassy_stm32::timer::simple_pwm::PwmPin; -use embassy_stm32::timer::Channel; +use embassy_stm32::timer::{Ch3, Channel}; use embassy_stm32::{interrupt, pac, Config}; use panic_probe as _; @@ -70,7 +70,7 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(config); // setup PWM pin in AF mode - let _ch3 = PwmPin::new_ch3(p.PA2, OutputType::PushPull); + let _ch3 = PwmPin::<_, Ch3>::new(p.PA2, OutputType::PushPull); // initialize timer // we cannot use SimplePWM here because the Time is privately encapsulated -- cgit From 2727fb266fa7d87b4fa23f7278e5255ca260fd14 Mon Sep 17 00:00:00 2001 From: melvdl Date: Fri, 27 Jun 2025 01:28:47 +0200 Subject: run cargo fmt --- embassy-stm32/src/timer/input_capture.rs | 2 +- embassy-stm32/src/timer/pwm_input.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index 49e22b10f..dda33e7f1 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -6,7 +6,7 @@ use core::pin::Pin; use core::task::{Context, Poll}; use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer}; -use super::{CaptureCompareInterruptHandler, GeneralInstance4Channel, Channel, TimerPin}; +use super::{CaptureCompareInterruptHandler, Channel, GeneralInstance4Channel, TimerPin}; pub use super::{Ch1, Ch2, Ch3, Ch4}; use crate::gpio::{AfType, AnyPin, Pull}; use crate::interrupt::typelevel::{Binding, Interrupt}; diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index 2e05a0593..99afb5582 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -1,7 +1,7 @@ //! PWM Input driver. use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource}; -use super::{Ch1, Ch2, GeneralInstance4Channel, Channel, TimerPin}; +use super::{Ch1, Ch2, Channel, GeneralInstance4Channel, TimerPin}; use crate::gpio::{AfType, Pull}; use crate::time::Hertz; use crate::Peri; -- cgit From b4269f0f592955d12defade8a9f1769479bcf60f Mon Sep 17 00:00:00 2001 From: melvdl Date: Fri, 27 Jun 2025 01:47:05 +0200 Subject: [stm32h723]: fix spdifrx example --- examples/stm32h723/src/bin/spdifrx.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/stm32h723/src/bin/spdifrx.rs b/examples/stm32h723/src/bin/spdifrx.rs index a04d7cb34..61e77249d 100644 --- a/examples/stm32h723/src/bin/spdifrx.rs +++ b/examples/stm32h723/src/bin/spdifrx.rs @@ -7,9 +7,9 @@ use defmt::{info, trace}; use embassy_executor::Spawner; -use embassy_futures::select::{self, select, Either}; +use embassy_futures::select::{select, Either}; use embassy_stm32::spdifrx::{self, Spdifrx}; -use embassy_stm32::{bind_interrupts, peripherals, sai}; +use embassy_stm32::{bind_interrupts, peripherals, sai, Peri}; use grounded::uninit::GroundedArrayCell; use hal::sai::*; use {defmt_rtt as _, embassy_stm32 as hal, panic_probe as _}; @@ -144,9 +144,9 @@ async fn main(_spawner: Spawner) { /// /// Used (again) after dropping the SPDIFRX instance, in case of errors (e.g. source disconnect). fn new_spdif_receiver<'d>( - spdifrx: &'d mut peripherals::SPDIFRX1, - input_pin: &'d mut peripherals::PD7, - dma: &'d mut peripherals::DMA2_CH7, + spdifrx: Peri<'d, peripherals::SPDIFRX1>, + input_pin: Peri<'d, peripherals::PD7>, + dma: Peri<'d, peripherals::DMA2_CH7>, buf: &'d mut [u32], ) -> Spdifrx<'d, peripherals::SPDIFRX1> { Spdifrx::new(spdifrx, Irqs, spdifrx::Config::default(), input_pin, dma, buf) @@ -156,11 +156,11 @@ fn new_spdif_receiver<'d>( /// /// Used (again) after dropping the SAI4 instance, in case of errors (e.g. buffer overrun). fn new_sai_transmitter<'d>( - sai: &'d mut peripherals::SAI4, - sck: &'d mut peripherals::PD13, - sd: &'d mut peripherals::PC1, - fs: &'d mut peripherals::PD12, - dma: &'d mut peripherals::BDMA_CH0, + sai: Peri<'d, peripherals::SAI4>, + sck: Peri<'d, peripherals::PD13>, + sd: Peri<'d, peripherals::PC1>, + fs: Peri<'d, peripherals::PD12>, + dma: Peri<'d, peripherals::BDMA_CH0>, buf: &'d mut [u32], ) -> Sai<'d, peripherals::SAI4, u32> { let mut sai_config = hal::sai::Config::default(); -- cgit From 688cac02716cf9122f82c315baa0a5e68265bb78 Mon Sep 17 00:00:00 2001 From: melvdl Date: Fri, 27 Jun 2025 02:07:58 +0200 Subject: add examples/stm32h723 to ci.sh --- ci.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci.sh b/ci.sh index 33152e559..e54112359 100755 --- a/ci.sh +++ b/ci.sh @@ -246,6 +246,7 @@ cargo batch \ --- build --release --manifest-path examples/stm32h5/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32h5 \ --- build --release --manifest-path examples/stm32h7/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h7 \ --- build --release --manifest-path examples/stm32h7b0/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h7b0 \ + --- build --release --manifest-path examples/stm32h723/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h723 \ --- build --release --manifest-path examples/stm32h735/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h735 \ --- build --release --manifest-path examples/stm32h755cm4/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h755cm4 \ --- build --release --manifest-path examples/stm32h755cm7/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h755cm7 \ -- cgit From 686bdae937c26a006ee79b89931a6966141066dd Mon Sep 17 00:00:00 2001 From: melvdl Date: Fri, 27 Jun 2025 02:28:54 +0200 Subject: stm32h723: remove unused mut from static buffers in spdifrx example --- examples/stm32h723/src/bin/spdifrx.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/stm32h723/src/bin/spdifrx.rs b/examples/stm32h723/src/bin/spdifrx.rs index 61e77249d..6d29e8a4d 100644 --- a/examples/stm32h723/src/bin/spdifrx.rs +++ b/examples/stm32h723/src/bin/spdifrx.rs @@ -25,10 +25,10 @@ const DMA_BUFFER_LENGTH: usize = HALF_DMA_BUFFER_LENGTH * 2; // 2 half-blocks // DMA buffers must be in special regions. Refer https://embassy.dev/book/#_stm32_bdma_only_working_out_of_some_ram_regions #[unsafe(link_section = ".sram1")] -static mut SPDIFRX_BUFFER: GroundedArrayCell = GroundedArrayCell::uninit(); +static SPDIFRX_BUFFER: GroundedArrayCell = GroundedArrayCell::uninit(); #[unsafe(link_section = ".sram4")] -static mut SAI_BUFFER: GroundedArrayCell = GroundedArrayCell::uninit(); +static SAI_BUFFER: GroundedArrayCell = GroundedArrayCell::uninit(); #[embassy_executor::main] async fn main(_spawner: Spawner) { -- cgit From 440b94aecf5964aeda192eb8bb5d1d2b8648e7e4 Mon Sep 17 00:00:00 2001 From: Iris Artin Date: Sun, 22 Jun 2025 00:05:49 -0400 Subject: Added STM32 ADCv1 analog watchdog implementation --- embassy-stm32/src/adc/v1.rs | 23 +++- embassy-stm32/src/adc/watchdog_v1.rs | 188 +++++++++++++++++++++++++++++++ examples/stm32f0/src/bin/adc-watchdog.rs | 34 ++++++ 3 files changed, 241 insertions(+), 4 deletions(-) create mode 100644 embassy-stm32/src/adc/watchdog_v1.rs create mode 100644 examples/stm32f0/src/bin/adc-watchdog.rs diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs index fb6f5b7d0..7fe502da0 100644 --- a/embassy-stm32/src/adc/v1.rs +++ b/embassy-stm32/src/adc/v1.rs @@ -11,6 +11,9 @@ use crate::interrupt::typelevel::Interrupt; use crate::peripherals::ADC1; use crate::{interrupt, rcc, Peri}; +mod watchdog_v1; +pub use watchdog_v1::WatchdogChannels; + pub const VDDA_CALIB_MV: u32 = 3300; pub const VREF_INT: u32 = 1230; @@ -21,8 +24,15 @@ pub struct InterruptHandler { impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { - if T::regs().isr().read().eoc() { + let isr = T::regs().isr().read(); + let ier = T::regs().ier().read(); + if ier.eocie() && isr.eoc() { + // eocie is set during adc.read() T::regs().ier().modify(|w| w.set_eocie(false)); + } else if ier.awdie() && isr.awd() { + // awdie is set during adc.monitor_watchdog() + T::regs().cr().read().set_adstp(true); + T::regs().ier().modify(|w| w.set_awdie(false)); } else { return; } @@ -186,16 +196,21 @@ impl<'d, T: Instance> Adc<'d, T> { T::regs().dr().read().data() } -} -impl<'d, T: Instance> Drop for Adc<'d, T> { - fn drop(&mut self) { + fn teardown_adc() { // A.7.3 ADC disable code example T::regs().cr().modify(|reg| reg.set_adstp(true)); while T::regs().cr().read().adstp() {} T::regs().cr().modify(|reg| reg.set_addis(true)); while T::regs().cr().read().aden() {} + } +} + +impl<'d, T: Instance> Drop for Adc<'d, T> { + fn drop(&mut self) { + Self::teardown_adc(); + Self::teardown_awd(); rcc::disable::(); } diff --git a/embassy-stm32/src/adc/watchdog_v1.rs b/embassy-stm32/src/adc/watchdog_v1.rs new file mode 100644 index 000000000..bbe8e1971 --- /dev/null +++ b/embassy-stm32/src/adc/watchdog_v1.rs @@ -0,0 +1,188 @@ +use core::future::poll_fn; +use core::task::Poll; + +use stm32_metapac::adc::vals::{Align, Awdsgl, Res}; + +use crate::adc::{Adc, AdcChannel, Instance}; + +/// This enum is passed into `Adc::init_watchdog` to specify the channels for the watchdog to monitor +pub enum WatchdogChannels { + // Single channel identified by index + Single(u8), + // Multiple channels identified by mask + Multiple(u16), +} + +impl WatchdogChannels { + pub fn from_channel(channel: &impl AdcChannel) -> Self { + Self::Single(channel.channel()) + } + + pub fn add_channel(self, channel: &impl AdcChannel) -> Self { + WatchdogChannels::Multiple( + (match self { + WatchdogChannels::Single(ch) => 1 << ch, + WatchdogChannels::Multiple(ch) => ch, + }) | 1 << channel.channel(), + ) + } +} + +impl<'d, T: Instance> Adc<'d, T> { + /// Configure the analog window watchdog to monitor one or more ADC channels + /// + /// `high_threshold` and `low_threshold` are expressed in the same way as ADC results. The format + /// depends on the values of CFGR1.ALIGN and CFGR1.RES. + pub fn init_watchdog(&mut self, channels: WatchdogChannels, low_threshold: u16, high_threshold: u16) { + Self::stop_awd(); + + match channels { + WatchdogChannels::Single(ch) => { + T::regs().chselr().modify(|w| { + w.set_chsel_x(ch.into(), true); + }); + T::regs().cfgr1().modify(|w| { + w.set_awdch(ch); + w.set_awdsgl(Awdsgl::SINGLE_CHANNEL) + }); + } + WatchdogChannels::Multiple(ch) => { + T::regs().chselr().modify(|w| w.0 = ch.into()); + T::regs().cfgr1().modify(|w| { + w.set_awdch(0); + w.set_awdsgl(Awdsgl::ALL_CHANNELS) + }); + } + } + + Self::set_watchdog_thresholds(low_threshold, high_threshold); + Self::setup_awd(); + } + + /// Monitor the voltage on the selected channels; return when it crosses the thresholds. + /// + /// ```rust,ignore + /// // Wait for pin to go high + /// adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0, 0x07F); + /// let v_high = adc.monitor_watchdog().await; + /// info!("ADC sample is high {}", v_high); + /// ``` + pub async fn monitor_watchdog(&mut self) -> u16 { + assert!( + match T::regs().cfgr1().read().awdsgl() { + Awdsgl::SINGLE_CHANNEL => T::regs().cfgr1().read().awdch() != 0, + Awdsgl::ALL_CHANNELS => T::regs().cfgr1().read().awdch() == 0, + }, + "`set_channel` should be called before `monitor`", + ); + assert!(T::regs().chselr().read().0 != 0); + T::regs().smpr().modify(|reg| reg.set_smp(self.sample_time.into())); + Self::start_awd(); + + let sample = poll_fn(|cx| { + T::state().waker.register(cx.waker()); + + if T::regs().isr().read().awd() { + Poll::Ready(T::regs().dr().read().data()) + } else { + Poll::Pending + } + }) + .await; + + self.stop_watchdog(); + sample + } + + /// Stop monitoring the selected channels + pub fn stop_watchdog(&mut self) { + Self::stop_awd(); + } + + fn set_watchdog_thresholds(low_threshold: u16, high_threshold: u16) { + // This function takes `high_threshold` and `low_threshold` in the same alignment and resolution + // as ADC results, and programs them into ADC_DR. Because ADC_DR is always right-aligned on 12 bits, + // some bit-shifting may be necessary. See more in table 47 §13.7.1 Analog Watchdog Comparison + + // Verify that the thresholds are in the correct bit positions according to alignment and resolution + let threshold_mask = match (T::regs().cfgr1().read().align(), T::regs().cfgr1().read().res()) { + (Align::LEFT, Res::BITS6) => 0x00FC, + (Align::LEFT, Res::BITS8) => 0xFF00, + (Align::LEFT, Res::BITS10) => 0xFFC0, + (Align::LEFT, Res::BITS12) => 0xFFF0, + (Align::RIGHT, Res::BITS6) => 0x003F, + (Align::RIGHT, Res::BITS8) => 0x00FF, + (Align::RIGHT, Res::BITS10) => 0x03FF, + (Align::RIGHT, Res::BITS12) => 0x0FFF, + }; + assert!( + high_threshold & !threshold_mask == 0, + "High threshold {:x} is invalid — only bits {:x} are allowed", + high_threshold, + threshold_mask + ); + assert!( + low_threshold & !threshold_mask == 0, + "Low threshold {:x} is invalid — only bits {:x} are allowed", + low_threshold, + threshold_mask + ); + + T::regs().tr().modify(|w| { + w.set_lt(low_threshold << threshold_mask.leading_zeros() >> 4); + w.set_ht(high_threshold << threshold_mask.leading_zeros() >> 4); + }) + } + + fn setup_awd() { + // Configure AWD + assert!(!T::regs().cr().read().adstart()); + T::regs().cfgr1().modify(|w| w.set_awden(true)); + } + + fn start_awd() { + // Clear AWD interrupt flag + while T::regs().isr().read().awd() { + T::regs().isr().modify(|regs| { + regs.set_awd(true); + }) + } + + // Enable AWD interrupt + assert!(!T::regs().cr().read().adstart()); + T::regs().ier().modify(|w| { + w.set_eocie(false); + w.set_awdie(true) + }); + + // Start conversion + T::regs().cfgr1().modify(|w| w.set_cont(true)); + T::regs().cr().modify(|w| w.set_adstart(true)); + } + + fn stop_awd() { + // Stop conversion + while T::regs().cr().read().addis() {} + if T::regs().cr().read().adstart() { + T::regs().cr().write(|x| x.set_adstp(true)); + while T::regs().cr().read().adstp() {} + } + T::regs().cfgr1().modify(|w| w.set_cont(false)); + + // Disable AWD interrupt + assert!(!T::regs().cr().read().adstart()); + T::regs().ier().modify(|w| w.set_awdie(false)); + + // Clear AWD interrupt flag + while T::regs().isr().read().awd() { + T::regs().isr().modify(|regs| { + regs.set_awd(true); + }) + } + } + + pub(crate) fn teardown_awd() { + Self::stop_awd(); + T::regs().cfgr1().modify(|w| w.set_awden(false)); + } +} diff --git a/examples/stm32f0/src/bin/adc-watchdog.rs b/examples/stm32f0/src/bin/adc-watchdog.rs new file mode 100644 index 000000000..ff98aac8e --- /dev/null +++ b/examples/stm32f0/src/bin/adc-watchdog.rs @@ -0,0 +1,34 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::adc::{self, Adc, WatchdogChannels}; +use embassy_stm32::bind_interrupts; +use embassy_stm32::peripherals::ADC1; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + ADC1_COMP => adc::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + info!("ADC watchdog example"); + + let mut adc = Adc::new(p.ADC1, Irqs); + let pin = p.PC1; + + loop { + // Wait for pin to go high + adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0, 0x07F); + let v_high = adc.monitor_watchdog().await; + info!("ADC sample is high {}", v_high); + + // Wait for pin to go low + adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0x01f, 0xFFF); + let v_low = adc.monitor_watchdog().await; + info!("ADC sample is low {}", v_low); + } +} -- cgit From 04bf17dde60c022ffaa5e37233ce45f048f0e2c3 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Fri, 20 Jun 2025 13:17:50 +0800 Subject: rename fns and add documentation --- embassy-stm32/src/timer/pwm_input.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index 99afb5582..e5b7335e8 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -7,6 +7,10 @@ use crate::time::Hertz; use crate::Peri; /// PWM Input driver. +/// +/// Only works with CH1 and CH2 +/// Note: Not all timer peripherals are supported +/// Double check your chips reference manual pub struct PwmInput<'d, T: GeneralInstance4Channel> { channel: Channel, inner: Timer<'d, T>, @@ -14,14 +18,14 @@ pub struct PwmInput<'d, T: GeneralInstance4Channel> { impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { /// Create a new PWM input driver. - pub fn new(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { + pub fn new_ch1(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2) } /// Create a new PWM input driver. - pub fn new_alt(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { + pub fn new_ch2(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1) @@ -37,6 +41,7 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.6 // or ST RM0008 (STM32F103) chapter 15.3.6 Input capture mode + // or ST RM0440 (STM32G4) chapter 30.4.8 PWM input mode inner.set_input_ti_selection(ch1, InputTISelection::Normal); inner.set_input_capture_mode(ch1, InputCaptureMode::Rising); -- cgit From 5cbc9a235f806bc961ed58da34ed932e39646e29 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Fri, 20 Jun 2025 13:27:56 +0800 Subject: correct documentation --- embassy-stm32/src/timer/pwm_input.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index e5b7335e8..1e55f2919 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -8,7 +8,7 @@ use crate::Peri; /// PWM Input driver. /// -/// Only works with CH1 and CH2 +/// Only works with CH1 or CH2 /// Note: Not all timer peripherals are supported /// Double check your chips reference manual pub struct PwmInput<'d, T: GeneralInstance4Channel> { -- cgit From b31a423eea6998ee681eda49433edc5dd03a5c63 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Fri, 27 Jun 2025 09:25:24 +0800 Subject: fix examples --- examples/stm32f1/src/bin/pwm_input.rs | 2 +- examples/stm32f4/src/bin/pwm_input.rs | 2 +- examples/stm32g0/src/bin/pwm_input.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs index afbef3edb..aa6a11ff8 100644 --- a/examples/stm32f1/src/bin/pwm_input.rs +++ b/examples/stm32f1/src/bin/pwm_input.rs @@ -38,7 +38,7 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(blinky(p.PC13))); - let mut pwm_input = PwmInput::new(p.TIM2, p.PA0, Pull::None, khz(10)); + let mut pwm_input = PwmInput::new_ch1(p.TIM2, p.PA0, Pull::None, khz(10)); pwm_input.enable(); loop { diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f4/src/bin/pwm_input.rs index 465cbe4f5..74167cbf2 100644 --- a/examples/stm32f4/src/bin/pwm_input.rs +++ b/examples/stm32f4/src/bin/pwm_input.rs @@ -38,7 +38,7 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(blinky(p.PB2))); - let mut pwm_input = PwmInput::new(p.TIM3, p.PA6, Pull::None, khz(10)); + let mut pwm_input = PwmInput::new_ch1(p.TIM3, p.PA6, Pull::None, khz(10)); pwm_input.enable(); loop { diff --git a/examples/stm32g0/src/bin/pwm_input.rs b/examples/stm32g0/src/bin/pwm_input.rs index dc2428607..fd4f53f1e 100644 --- a/examples/stm32g0/src/bin/pwm_input.rs +++ b/examples/stm32g0/src/bin/pwm_input.rs @@ -47,7 +47,7 @@ async fn main(spawner: Spawner) { pwm.ch1().set_duty_cycle_fraction(1, 4); pwm.ch1().enable(); - let mut pwm_input = PwmInput::new(p.TIM2, p.PA0, Pull::None, khz(1000)); + let mut pwm_input = PwmInput::new_ch1(p.TIM2, p.PA0, Pull::None, khz(1000)); pwm_input.enable(); loop { -- cgit From 39c9cbcf49e248f799ac5e765750d90f9c698245 Mon Sep 17 00:00:00 2001 From: 9names <60134748+9names@users.noreply.github.com> Date: Fri, 27 Jun 2025 20:15:14 +1000 Subject: Minimise profile tweaking in rp examples --- examples/rp/Cargo.toml | 10 ++-------- examples/rp235x/Cargo.toml | 7 ++----- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index c8a132a5e..8d05d5a8c 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -58,11 +58,5 @@ rand = { version = "0.9.0", default-features = false } embedded-sdmmc = "0.7.0" [profile.release] -debug = 2 -lto = true -opt-level = 'z' - -[profile.dev] -debug = 2 -lto = true -opt-level = "z" +# Enable generation of debug symbols even on release builds +debug = true diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 1346a75a2..c6afe37db 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -57,9 +57,6 @@ portable-atomic = { version = "1.5", features = ["critical-section"] } log = "0.4" embedded-sdmmc = "0.7.0" -[profile.dev] -debug = 2 - [profile.release] -lto = true -opt-level = "z" +# Enable generation of debug symbols even on release builds +debug = true -- cgit From 71975c72fceef48213b1ffd19bce8219c6d26de6 Mon Sep 17 00:00:00 2001 From: Kelsey Maes Date: Fri, 27 Jun 2025 14:11:01 -0700 Subject: mspm0: Fix inverted GPIO logic --- embassy-mspm0/src/gpio.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/embassy-mspm0/src/gpio.rs b/embassy-mspm0/src/gpio.rs index 738d51928..9fbe34251 100644 --- a/embassy-mspm0/src/gpio.rs +++ b/embassy-mspm0/src/gpio.rs @@ -223,13 +223,13 @@ impl<'d> Flex<'d> { /// Get whether the pin input level is high. #[inline] pub fn is_high(&self) -> bool { - !self.is_low() + self.pin.block().din31_0().read().dio(self.pin.bit_index()) } /// Get whether the pin input level is low. #[inline] pub fn is_low(&self) -> bool { - self.pin.block().din31_0().read().dio(self.pin.bit_index()) + !self.is_high() } /// Returns current pin level @@ -271,22 +271,22 @@ impl<'d> Flex<'d> { } } - /// Get the current pin input level. + /// Get the current pin output level. #[inline] pub fn get_output_level(&self) -> Level { - self.is_high().into() + self.is_set_high().into() } /// Is the output level high? #[inline] pub fn is_set_high(&self) -> bool { - !self.is_set_low() + self.pin.block().dout31_0().read().dio(self.pin.bit_index()) } /// Is the output level low? #[inline] pub fn is_set_low(&self) -> bool { - (self.pin.block().dout31_0().read().0 & self.pin.bit_index() as u32) == 0 + !self.is_set_high() } /// Wait until the pin is high. If it is already high, return immediately. -- cgit From 15c7526c0a2e69880919392a5be7455156a2cba2 Mon Sep 17 00:00:00 2001 From: purepani Date: Mon, 30 Jun 2025 03:04:52 -0500 Subject: Updates stm32-metapac --- embassy-stm32/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 552113a79..d54f8dbae 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-0069be7389d0378d826003304d72a13008f3ebce" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-019a3ce0ea3b5bd832ec2ad53465a0d80b0f4e0a" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-0069be7389d0378d826003304d72a13008f3ebce", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-019a3ce0ea3b5bd832ec2ad53465a0d80b0f4e0a", default-features = false, features = ["metadata"] } [features] default = ["rt"] -- cgit From 08f3b45de67f195eb6b94b1dca478ee2d883cd0f Mon Sep 17 00:00:00 2001 From: purepani Date: Mon, 30 Jun 2025 03:04:52 -0500 Subject: Adds ADC4 for WBA --- embassy-stm32/build.rs | 4 + embassy-stm32/src/adc/adc4.rs | 542 +++++++++++++++++++++++++++++++++++++++ embassy-stm32/src/adc/mod.rs | 66 ++++- embassy-stm32/src/adc/u5_adc4.rs | 478 ---------------------------------- embassy-stm32/src/rcc/wba.rs | 1 + 5 files changed, 601 insertions(+), 490 deletions(-) create mode 100644 embassy-stm32/src/adc/adc4.rs delete mode 100644 embassy-stm32/src/adc/u5_adc4.rs diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 13fc23e54..753f241c7 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1490,6 +1490,10 @@ fn main() { signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma)); } + if chip_name.starts_with("stm32wba") { + signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma4)); + } + if chip_name.starts_with("stm32g4") { let line_number = chip_name.chars().skip(8).next().unwrap(); if line_number == '3' || line_number == '4' { diff --git a/embassy-stm32/src/adc/adc4.rs b/embassy-stm32/src/adc/adc4.rs new file mode 100644 index 000000000..98483489f --- /dev/null +++ b/embassy-stm32/src/adc/adc4.rs @@ -0,0 +1,542 @@ +#[cfg(stm32u5)] +use pac::adc::vals::{Adc4Dmacfg as Dmacfg, Adc4Exten as Exten, Adc4OversamplingRatio as OversamplingRatio}; +#[allow(unused)] +#[cfg(stm32wba)] +use pac::adc::vals::{Chselrmod, Cont, Dmacfg, Exten, OversamplingRatio, Ovss, Smpsel}; + +use super::{blocking_delay_us, AdcChannel, AnyAdcChannel, RxDma4, SealedAdcChannel}; +use crate::dma::Transfer; +#[cfg(stm32u5)] +pub use crate::pac::adc::regs::Adc4Chselrmod0 as Chselr; +#[cfg(stm32wba)] +pub use crate::pac::adc::regs::Chselr; +#[cfg(stm32u5)] +pub use crate::pac::adc::vals::{Adc4Presc as Presc, Adc4Res as Resolution, Adc4SampleTime as SampleTime}; +#[cfg(stm32wba)] +pub use crate::pac::adc::vals::{Presc, Res as Resolution, SampleTime}; +use crate::time::Hertz; +use crate::{pac, rcc, Peri}; + +const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55); + +/// Default VREF voltage used for sample conversion to millivolts. +pub const VREF_DEFAULT_MV: u32 = 3300; +/// VREF voltage used for factory calibration of VREFINTCAL register. +pub const VREF_CALIB_MV: u32 = 3300; + +const VREF_CHANNEL: u8 = 0; +const VCORE_CHANNEL: u8 = 12; +const TEMP_CHANNEL: u8 = 13; +const VBAT_CHANNEL: u8 = 14; +const DAC_CHANNEL: u8 = 21; + +// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs +/// Internal voltage reference channel. +pub struct VrefInt; +impl AdcChannel for VrefInt {} +impl SealedAdcChannel for VrefInt { + fn channel(&self) -> u8 { + VREF_CHANNEL + } +} + +/// Internal temperature channel. +pub struct Temperature; +impl AdcChannel for Temperature {} +impl SealedAdcChannel for Temperature { + fn channel(&self) -> u8 { + TEMP_CHANNEL + } +} + +/// Internal battery voltage channel. +pub struct Vbat; +impl AdcChannel for Vbat {} +impl SealedAdcChannel for Vbat { + fn channel(&self) -> u8 { + VBAT_CHANNEL + } +} + +/// Internal DAC channel. +pub struct Dac; +impl AdcChannel for Dac {} +impl SealedAdcChannel for Dac { + fn channel(&self) -> u8 { + DAC_CHANNEL + } +} + +/// Internal Vcore channel. +pub struct Vcore; +impl AdcChannel for Vcore {} +impl SealedAdcChannel for Vcore { + fn channel(&self) -> u8 { + VCORE_CHANNEL + } +} + +pub enum DacChannel { + OUT1, + OUT2, +} + +/// Number of samples used for averaging. +pub enum Averaging { + Disabled, + Samples2, + Samples4, + Samples8, + Samples16, + Samples32, + Samples64, + Samples128, + Samples256, +} + +pub const fn resolution_to_max_count(res: Resolution) -> u32 { + match res { + Resolution::BITS12 => (1 << 12) - 1, + Resolution::BITS10 => (1 << 10) - 1, + Resolution::BITS8 => (1 << 8) - 1, + Resolution::BITS6 => (1 << 6) - 1, + #[allow(unreachable_patterns)] + _ => core::unreachable!(), + } +} + +// NOTE (unused): The prescaler enum closely copies the hardware capabilities, +// but high prescaling doesn't make a lot of sense in the current implementation and is ommited. +#[allow(unused)] +enum Prescaler { + NotDivided, + DividedBy2, + DividedBy4, + DividedBy6, + DividedBy8, + DividedBy10, + DividedBy12, + DividedBy16, + DividedBy32, + DividedBy64, + DividedBy128, + DividedBy256, +} + +impl Prescaler { + fn from_ker_ck(frequency: Hertz) -> Self { + let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0; + match raw_prescaler { + 0 => Self::NotDivided, + 1 => Self::DividedBy2, + 2..=3 => Self::DividedBy4, + 4..=5 => Self::DividedBy6, + 6..=7 => Self::DividedBy8, + 8..=9 => Self::DividedBy10, + 10..=11 => Self::DividedBy12, + _ => unimplemented!(), + } + } + + fn divisor(&self) -> u32 { + match self { + Prescaler::NotDivided => 1, + Prescaler::DividedBy2 => 2, + Prescaler::DividedBy4 => 4, + Prescaler::DividedBy6 => 6, + Prescaler::DividedBy8 => 8, + Prescaler::DividedBy10 => 10, + Prescaler::DividedBy12 => 12, + Prescaler::DividedBy16 => 16, + Prescaler::DividedBy32 => 32, + Prescaler::DividedBy64 => 64, + Prescaler::DividedBy128 => 128, + Prescaler::DividedBy256 => 256, + } + } + + fn presc(&self) -> Presc { + match self { + Prescaler::NotDivided => Presc::DIV1, + Prescaler::DividedBy2 => Presc::DIV2, + Prescaler::DividedBy4 => Presc::DIV4, + Prescaler::DividedBy6 => Presc::DIV6, + Prescaler::DividedBy8 => Presc::DIV8, + Prescaler::DividedBy10 => Presc::DIV10, + Prescaler::DividedBy12 => Presc::DIV12, + Prescaler::DividedBy16 => Presc::DIV16, + Prescaler::DividedBy32 => Presc::DIV32, + Prescaler::DividedBy64 => Presc::DIV64, + Prescaler::DividedBy128 => Presc::DIV128, + Prescaler::DividedBy256 => Presc::DIV256, + } + } +} + +pub trait SealedInstance { + #[allow(unused)] + fn regs() -> crate::pac::adc::Adc4; +} + +pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral { + type Interrupt: crate::interrupt::typelevel::Interrupt; +} + +pub struct Adc4<'d, T: Instance> { + #[allow(unused)] + adc: crate::Peri<'d, T>, +} + +#[derive(Debug)] +pub enum Adc4Error { + InvalidSequence, + DMAError, +} + +impl<'d, T: Instance> Adc4<'d, T> { + /// Create a new ADC driver. + pub fn new(adc: Peri<'d, T>) -> Self { + rcc::enable_and_reset::(); + let prescaler = Prescaler::from_ker_ck(T::frequency()); + + T::regs().ccr().modify(|w| w.set_presc(prescaler.presc())); + + let frequency = Hertz(T::frequency().0 / prescaler.divisor()); + info!("ADC4 frequency set to {}", frequency); + + if frequency > MAX_ADC_CLK_FREQ { + panic!("Maximal allowed frequency for ADC4 is {} MHz and it varies with different packages, refer to ST docs for more information.", MAX_ADC_CLK_FREQ.0 / 1_000_000 ); + } + + let mut s = Self { adc }; + + s.power_up(); + + s.calibrate(); + blocking_delay_us(1); + + s.enable(); + s.configure(); + + s + } + + fn power_up(&mut self) { + T::regs().isr().modify(|w| { + w.set_ldordy(true); + }); + T::regs().cr().modify(|w| { + w.set_advregen(true); + }); + while !T::regs().isr().read().ldordy() {} + + T::regs().isr().modify(|w| { + w.set_ldordy(true); + }); + } + + fn calibrate(&mut self) { + T::regs().cr().modify(|w| w.set_adcal(true)); + while T::regs().cr().read().adcal() {} + T::regs().isr().modify(|w| w.set_eocal(true)); + } + + fn enable(&mut self) { + T::regs().isr().write(|w| w.set_adrdy(true)); + T::regs().cr().modify(|w| w.set_aden(true)); + while !T::regs().isr().read().adrdy() {} + T::regs().isr().write(|w| w.set_adrdy(true)); + } + + fn configure(&mut self) { + // single conversion mode, software trigger + T::regs().cfgr1().modify(|w| { + #[cfg(stm32u5)] + w.set_cont(false); + #[cfg(stm32wba)] + w.set_cont(Cont::SINGLE); + w.set_discen(false); + w.set_exten(Exten::DISABLED); + #[cfg(stm32u5)] + w.set_chselrmod(false); + #[cfg(stm32wba)] + w.set_chselrmod(Chselrmod::ENABLE_INPUT); + }); + + // only use one channel at the moment + T::regs().smpr().modify(|w| { + #[cfg(stm32u5)] + for i in 0..24 { + w.set_smpsel(i, false); + } + #[cfg(stm32wba)] + for i in 0..14 { + w.set_smpsel(i, Smpsel::SMP1); + } + }); + } + + /// Enable reading the voltage reference internal channel. + pub fn enable_vrefint(&self) -> VrefInt { + T::regs().ccr().modify(|w| { + w.set_vrefen(true); + }); + + VrefInt {} + } + + /// Enable reading the temperature internal channel. + pub fn enable_temperature(&self) -> Temperature { + T::regs().ccr().modify(|w| { + w.set_vsensesel(true); + }); + + Temperature {} + } + + /// Enable reading the vbat internal channel. + #[cfg(stm32u5)] + pub fn enable_vbat(&self) -> Vbat { + T::regs().ccr().modify(|w| { + w.set_vbaten(true); + }); + + Vbat {} + } + + /// Enable reading the vbat internal channel. + pub fn enable_vcore(&self) -> Vcore { + Vcore {} + } + + /// Enable reading the vbat internal channel. + #[cfg(stm32u5)] + pub fn enable_dac_channel(&self, dac: DacChannel) -> Dac { + let mux; + match dac { + DacChannel::OUT1 => mux = false, + DacChannel::OUT2 => mux = true, + } + T::regs().or().modify(|w| w.set_chn21sel(mux)); + Dac {} + } + + /// Set the ADC sample time. + pub fn set_sample_time(&mut self, sample_time: SampleTime) { + T::regs().smpr().modify(|w| { + w.set_smp(0, sample_time); + }); + } + + /// Get the ADC sample time. + pub fn sample_time(&self) -> SampleTime { + T::regs().smpr().read().smp(0) + } + + /// Set the ADC resolution. + pub fn set_resolution(&mut self, resolution: Resolution) { + T::regs().cfgr1().modify(|w| w.set_res(resolution.into())); + } + + /// Set hardware averaging. + #[cfg(stm32u5)] + pub fn set_averaging(&mut self, averaging: Averaging) { + let (enable, samples, right_shift) = match averaging { + Averaging::Disabled => (false, OversamplingRatio::OVERSAMPLE2X, 0), + Averaging::Samples2 => (true, OversamplingRatio::OVERSAMPLE2X, 1), + Averaging::Samples4 => (true, OversamplingRatio::OVERSAMPLE4X, 2), + Averaging::Samples8 => (true, OversamplingRatio::OVERSAMPLE8X, 3), + Averaging::Samples16 => (true, OversamplingRatio::OVERSAMPLE16X, 4), + Averaging::Samples32 => (true, OversamplingRatio::OVERSAMPLE32X, 5), + Averaging::Samples64 => (true, OversamplingRatio::OVERSAMPLE64X, 6), + Averaging::Samples128 => (true, OversamplingRatio::OVERSAMPLE128X, 7), + Averaging::Samples256 => (true, OversamplingRatio::OVERSAMPLE256X, 8), + }; + + T::regs().cfgr2().modify(|w| { + w.set_ovsr(samples); + w.set_ovss(right_shift); + w.set_ovse(enable) + }) + } + #[cfg(stm32wba)] + pub fn set_averaging(&mut self, averaging: Averaging) { + let (enable, samples, right_shift) = match averaging { + Averaging::Disabled => (false, OversamplingRatio::OVERSAMPLE2X, Ovss::SHIFT0), + Averaging::Samples2 => (true, OversamplingRatio::OVERSAMPLE2X, Ovss::SHIFT1), + Averaging::Samples4 => (true, OversamplingRatio::OVERSAMPLE4X, Ovss::SHIFT2), + Averaging::Samples8 => (true, OversamplingRatio::OVERSAMPLE8X, Ovss::SHIFT3), + Averaging::Samples16 => (true, OversamplingRatio::OVERSAMPLE16X, Ovss::SHIFT4), + Averaging::Samples32 => (true, OversamplingRatio::OVERSAMPLE32X, Ovss::SHIFT5), + Averaging::Samples64 => (true, OversamplingRatio::OVERSAMPLE64X, Ovss::SHIFT6), + Averaging::Samples128 => (true, OversamplingRatio::OVERSAMPLE128X, Ovss::SHIFT7), + Averaging::Samples256 => (true, OversamplingRatio::OVERSAMPLE256X, Ovss::SHIFT8), + }; + + T::regs().cfgr2().modify(|w| { + w.set_ovsr(samples); + w.set_ovss(right_shift); + w.set_ovse(enable) + }) + } + + /// Read an ADC channel. + pub fn blocking_read(&mut self, channel: &mut impl AdcChannel) -> u16 { + channel.setup(); + + // Select channel + #[cfg(stm32wba)] + { + T::regs().chselr().write_value(Chselr(0_u32)); + T::regs().chselr().modify(|w| { + w.set_chsel0(channel.channel() as usize, true); + }); + } + #[cfg(stm32u5)] + { + T::regs().chselrmod0().write_value(Chselr(0_u32)); + T::regs().chselrmod0().modify(|w| { + w.set_chsel(channel.channel() as usize, true); + }); + } + + // Reset interrupts + T::regs().isr().modify(|reg| { + reg.set_eos(true); + reg.set_eoc(true); + }); + + // Start conversion + T::regs().cr().modify(|reg| { + reg.set_adstart(true); + }); + + while !T::regs().isr().read().eos() { + // spin + } + + T::regs().dr().read().0 as u16 + } + + /// Read one or multiple ADC channels using DMA. + /// + /// `sequence` iterator and `readings` must have the same length. + /// The channels in `sequence` must be in ascending order. + /// + /// Example + /// ```rust,ignore + /// use embassy_stm32::adc::adc4; + /// use embassy_stm32::adc::AdcChannel; + /// + /// let mut adc4 = adc4::Adc4::new(p.ADC4); + /// let mut adc4_pin1 = p.PC1; + /// let mut adc4_pin2 = p.PC0; + /// let mut.into()d41 = adc4_pin1.into(); + /// let mut.into()d42 = adc4_pin2.into(); + /// let mut measurements = [0u16; 2]; + /// // not that the channels must be in ascending order + /// adc4.read( + /// &mut p.GPDMA1_CH1, + /// [ + /// &mut.into()d42, + /// &mut.into()d41, + /// ] + /// .into_iter(), + /// &mut measurements, + /// ).await.unwrap(); + /// ``` + pub async fn read( + &mut self, + rx_dma: Peri<'_, impl RxDma4>, + sequence: impl ExactSizeIterator>, + readings: &mut [u16], + ) -> Result<(), Adc4Error> { + assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty"); + assert!( + sequence.len() == readings.len(), + "Sequence length must be equal to readings length" + ); + + // Ensure no conversions are ongoing + Self::cancel_conversions(); + + T::regs().isr().modify(|reg| { + reg.set_ovr(true); + reg.set_eos(true); + reg.set_eoc(true); + }); + + T::regs().cfgr1().modify(|reg| { + reg.set_dmaen(true); + reg.set_dmacfg(Dmacfg::ONE_SHOT); + #[cfg(stm32u5)] + reg.set_chselrmod(false); + #[cfg(stm32wba)] + reg.set_chselrmod(Chselrmod::ENABLE_INPUT) + }); + + // Verify and activate sequence + let mut prev_channel: i16 = -1; + #[cfg(stm32wba)] + T::regs().chselr().write_value(Chselr(0_u32)); + #[cfg(stm32u5)] + T::regs().chselrmod0().write_value(Chselr(0_u32)); + for channel in sequence { + let channel_num = channel.channel; + if channel_num as i16 <= prev_channel { + return Err(Adc4Error::InvalidSequence); + }; + prev_channel = channel_num as i16; + + #[cfg(stm32wba)] + T::regs().chselr().modify(|w| { + w.set_chsel0(channel.channel as usize, true); + }); + #[cfg(stm32u5)] + T::regs().chselrmod0().modify(|w| { + w.set_chsel(channel.channel as usize, true); + }); + } + + let request = rx_dma.request(); + let transfer = unsafe { + Transfer::new_read( + rx_dma, + request, + T::regs().dr().as_ptr() as *mut u16, + readings, + Default::default(), + ) + }; + + // Start conversion + T::regs().cr().modify(|reg| { + reg.set_adstart(true); + }); + + transfer.await; + + // Ensure conversions are finished. + Self::cancel_conversions(); + + // Reset configuration. + T::regs().cfgr1().modify(|reg| { + reg.set_dmaen(false); + }); + + if T::regs().isr().read().ovr() { + Err(Adc4Error::DMAError) + } else { + Ok(()) + } + } + + fn cancel_conversions() { + if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { + T::regs().cr().modify(|reg| { + reg.set_adstp(true); + }); + while T::regs().cr().read().adstart() {} + } + } +} diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index f46e87f38..778edc6f6 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -4,7 +4,7 @@ #![allow(missing_docs)] // TODO #![cfg_attr(adc_f3_v2, allow(unused))] -#[cfg(not(any(adc_f3_v2)))] +#[cfg(not(any(adc_f3_v2, adc_wba)))] #[cfg_attr(adc_f1, path = "f1.rs")] #[cfg_attr(adc_f3, path = "f3.rs")] #[cfg_attr(adc_f3_v1_1, path = "f3_v1_1.rs")] @@ -20,14 +20,14 @@ mod _version; use core::marker::PhantomData; #[allow(unused)] -#[cfg(not(any(adc_f3_v2)))] +#[cfg(not(any(adc_f3_v2, adc_wba)))] pub use _version::*; use embassy_hal_internal::{impl_peripheral, PeripheralType}; #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] use embassy_sync::waitqueue::AtomicWaker; -#[cfg(adc_u5)] -#[path = "u5_adc4.rs"] +#[cfg(any(adc_u5, adc_wba))] +#[path = "adc4.rs"] pub mod adc4; pub use crate::pac::adc::vals; @@ -36,15 +36,18 @@ pub use crate::pac::adc::vals::Res as Resolution; pub use crate::pac::adc::vals::SampleTime; use crate::peripherals; +#[cfg(not(adc_wba))] dma_trait!(RxDma, Instance); #[cfg(adc_u5)] dma_trait!(RxDma4, adc4::Instance); +#[cfg(adc_wba)] +dma_trait!(RxDma4, adc4::Instance); /// Analog to Digital driver. pub struct Adc<'d, T: Instance> { #[allow(unused)] adc: crate::Peri<'d, T>, - #[cfg(not(any(adc_f3_v2, adc_f3_v1_1)))] + #[cfg(not(any(adc_f3_v2, adc_f3_v1_1, adc_wba)))] sample_time: SampleTime, } @@ -63,6 +66,7 @@ impl State { } trait SealedInstance { + #[cfg(not(adc_wba))] #[allow(unused)] fn regs() -> crate::pac::adc::Adc; #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))] @@ -73,7 +77,7 @@ trait SealedInstance { } pub(crate) trait SealedAdcChannel { - #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5))] + #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))] fn setup(&mut self) {} #[allow(unused)] @@ -110,7 +114,8 @@ pub(crate) fn blocking_delay_us(us: u32) { adc_h5, adc_h7rs, adc_u5, - adc_c0 + adc_c0, + adc_wba, )))] #[allow(private_bounds)] pub trait Instance: SealedInstance + crate::PeripheralType { @@ -132,7 +137,8 @@ pub trait Instance: SealedInstance + crate::PeripheralType { adc_h5, adc_h7rs, adc_u5, - adc_c0 + adc_c0, + adc_wba, ))] #[allow(private_bounds)] pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral { @@ -144,7 +150,7 @@ pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeri pub trait AdcChannel: SealedAdcChannel + Sized { #[allow(unused_mut)] fn degrade_adc(mut self) -> AnyAdcChannel { - #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5))] + #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))] self.setup(); AnyAdcChannel { @@ -176,6 +182,36 @@ impl AnyAdcChannel { self.channel } } +#[cfg(adc_wba)] +foreach_adc!( + (ADC4, $common_inst:ident, $clock:ident) => { + impl crate::adc::adc4::SealedInstance for peripherals::ADC4 { + fn regs() -> crate::pac::adc::Adc4 { + crate::pac::ADC4 + } + } + + impl crate::adc::adc4::Instance for peripherals::ADC4 { + type Interrupt = crate::_generated::peripheral_interrupts::ADC4::GLOBAL; + } + }; + + ($inst:ident, $common_inst:ident, $clock:ident) => { + impl crate::adc::SealedInstance for peripherals::$inst { + fn regs() -> crate::pac::adc::Adc { + crate::pac::$inst + } + + fn common_regs() -> crate::pac::adccommon::AdcCommon { + return crate::pac::$common_inst + } + } + + impl crate::adc::Instance for peripherals::$inst { + type Interrupt = crate::_generated::peripheral_interrupts::$inst::GLOBAL; + } + }; +); #[cfg(adc_u5)] foreach_adc!( @@ -208,15 +244,21 @@ foreach_adc!( }; ); -#[cfg(not(adc_u5))] +#[cfg(not(any(adc_u5, adc_wba)))] foreach_adc!( ($inst:ident, $common_inst:ident, $clock:ident) => { impl crate::adc::SealedInstance for peripherals::$inst { + #[cfg(not(adc_wba))] fn regs() -> crate::pac::adc::Adc { crate::pac::$inst } - #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))] + #[cfg(adc_wba)] + fn regs() -> crate::pac::adc::Adc4 { + crate::pac::$inst + } + + #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0, adc_u5, adc_wba)))] fn common_regs() -> crate::pac::adccommon::AdcCommon { return crate::pac::$common_inst } @@ -238,7 +280,7 @@ macro_rules! impl_adc_pin { ($inst:ident, $pin:ident, $ch:expr) => { impl crate::adc::AdcChannel for crate::Peri<'_, crate::peripherals::$pin> {} impl crate::adc::SealedAdcChannel for crate::Peri<'_, crate::peripherals::$pin> { - #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5))] + #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))] fn setup(&mut self) { ::set_as_analog(self); } diff --git a/embassy-stm32/src/adc/u5_adc4.rs b/embassy-stm32/src/adc/u5_adc4.rs deleted file mode 100644 index 1dd664366..000000000 --- a/embassy-stm32/src/adc/u5_adc4.rs +++ /dev/null @@ -1,478 +0,0 @@ -#[allow(unused)] -use pac::adc::vals::{Adc4Dmacfg, Adc4Exten, Adc4OversamplingRatio}; - -use super::{blocking_delay_us, AdcChannel, AnyAdcChannel, RxDma4, SealedAdcChannel}; -use crate::dma::Transfer; -pub use crate::pac::adc::regs::Adc4Chselrmod0; -pub use crate::pac::adc::vals::{Adc4Presc as Presc, Adc4Res as Resolution, Adc4SampleTime as SampleTime}; -use crate::time::Hertz; -use crate::{pac, rcc, Peri}; - -const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55); - -/// Default VREF voltage used for sample conversion to millivolts. -pub const VREF_DEFAULT_MV: u32 = 3300; -/// VREF voltage used for factory calibration of VREFINTCAL register. -pub const VREF_CALIB_MV: u32 = 3300; - -const VREF_CHANNEL: u8 = 0; -const VCORE_CHANNEL: u8 = 12; -const TEMP_CHANNEL: u8 = 13; -const VBAT_CHANNEL: u8 = 14; -const DAC_CHANNEL: u8 = 21; - -// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs -/// Internal voltage reference channel. -pub struct VrefInt; -impl AdcChannel for VrefInt {} -impl SealedAdcChannel for VrefInt { - fn channel(&self) -> u8 { - VREF_CHANNEL - } -} - -/// Internal temperature channel. -pub struct Temperature; -impl AdcChannel for Temperature {} -impl SealedAdcChannel for Temperature { - fn channel(&self) -> u8 { - TEMP_CHANNEL - } -} - -/// Internal battery voltage channel. -pub struct Vbat; -impl AdcChannel for Vbat {} -impl SealedAdcChannel for Vbat { - fn channel(&self) -> u8 { - VBAT_CHANNEL - } -} - -/// Internal DAC channel. -pub struct Dac; -impl AdcChannel for Dac {} -impl SealedAdcChannel for Dac { - fn channel(&self) -> u8 { - DAC_CHANNEL - } -} - -/// Internal Vcore channel. -pub struct Vcore; -impl AdcChannel for Vcore {} -impl SealedAdcChannel for Vcore { - fn channel(&self) -> u8 { - VCORE_CHANNEL - } -} - -pub enum DacChannel { - OUT1, - OUT2, -} - -/// Number of samples used for averaging. -pub enum Averaging { - Disabled, - Samples2, - Samples4, - Samples8, - Samples16, - Samples32, - Samples64, - Samples128, - Samples256, -} - -pub const fn resolution_to_max_count(res: Resolution) -> u32 { - match res { - Resolution::BITS12 => (1 << 12) - 1, - Resolution::BITS10 => (1 << 10) - 1, - Resolution::BITS8 => (1 << 8) - 1, - Resolution::BITS6 => (1 << 6) - 1, - #[allow(unreachable_patterns)] - _ => core::unreachable!(), - } -} - -// NOTE (unused): The prescaler enum closely copies the hardware capabilities, -// but high prescaling doesn't make a lot of sense in the current implementation and is ommited. -#[allow(unused)] -enum Prescaler { - NotDivided, - DividedBy2, - DividedBy4, - DividedBy6, - DividedBy8, - DividedBy10, - DividedBy12, - DividedBy16, - DividedBy32, - DividedBy64, - DividedBy128, - DividedBy256, -} - -impl Prescaler { - fn from_ker_ck(frequency: Hertz) -> Self { - let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0; - match raw_prescaler { - 0 => Self::NotDivided, - 1 => Self::DividedBy2, - 2..=3 => Self::DividedBy4, - 4..=5 => Self::DividedBy6, - 6..=7 => Self::DividedBy8, - 8..=9 => Self::DividedBy10, - 10..=11 => Self::DividedBy12, - _ => unimplemented!(), - } - } - - fn divisor(&self) -> u32 { - match self { - Prescaler::NotDivided => 1, - Prescaler::DividedBy2 => 2, - Prescaler::DividedBy4 => 4, - Prescaler::DividedBy6 => 6, - Prescaler::DividedBy8 => 8, - Prescaler::DividedBy10 => 10, - Prescaler::DividedBy12 => 12, - Prescaler::DividedBy16 => 16, - Prescaler::DividedBy32 => 32, - Prescaler::DividedBy64 => 64, - Prescaler::DividedBy128 => 128, - Prescaler::DividedBy256 => 256, - } - } - - fn presc(&self) -> Presc { - match self { - Prescaler::NotDivided => Presc::DIV1, - Prescaler::DividedBy2 => Presc::DIV2, - Prescaler::DividedBy4 => Presc::DIV4, - Prescaler::DividedBy6 => Presc::DIV6, - Prescaler::DividedBy8 => Presc::DIV8, - Prescaler::DividedBy10 => Presc::DIV10, - Prescaler::DividedBy12 => Presc::DIV12, - Prescaler::DividedBy16 => Presc::DIV16, - Prescaler::DividedBy32 => Presc::DIV32, - Prescaler::DividedBy64 => Presc::DIV64, - Prescaler::DividedBy128 => Presc::DIV128, - Prescaler::DividedBy256 => Presc::DIV256, - } - } -} - -pub trait SealedInstance { - #[allow(unused)] - fn regs() -> crate::pac::adc::Adc4; -} - -pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral { - type Interrupt: crate::interrupt::typelevel::Interrupt; -} - -pub struct Adc4<'d, T: Instance> { - #[allow(unused)] - adc: crate::Peri<'d, T>, -} - -#[derive(Debug)] -pub enum Adc4Error { - InvalidSequence, - DMAError, -} - -impl<'d, T: Instance> Adc4<'d, T> { - /// Create a new ADC driver. - pub fn new(adc: Peri<'d, T>) -> Self { - rcc::enable_and_reset::(); - let prescaler = Prescaler::from_ker_ck(T::frequency()); - - T::regs().ccr().modify(|w| w.set_presc(prescaler.presc())); - - let frequency = Hertz(T::frequency().0 / prescaler.divisor()); - info!("ADC4 frequency set to {}", frequency); - - if frequency > MAX_ADC_CLK_FREQ { - panic!("Maximal allowed frequency for ADC4 is {} MHz and it varies with different packages, refer to ST docs for more information.", MAX_ADC_CLK_FREQ.0 / 1_000_000 ); - } - - let mut s = Self { adc }; - - s.power_up(); - - s.calibrate(); - blocking_delay_us(1); - - s.enable(); - s.configure(); - - s - } - - fn power_up(&mut self) { - T::regs().isr().modify(|w| { - w.set_ldordy(true); - }); - T::regs().cr().modify(|w| { - w.set_advregen(true); - }); - while !T::regs().isr().read().ldordy() {} - - T::regs().isr().modify(|w| { - w.set_ldordy(true); - }); - } - - fn calibrate(&mut self) { - T::regs().cr().modify(|w| w.set_adcal(true)); - while T::regs().cr().read().adcal() {} - T::regs().isr().modify(|w| w.set_eocal(true)); - } - - fn enable(&mut self) { - T::regs().isr().write(|w| w.set_adrdy(true)); - T::regs().cr().modify(|w| w.set_aden(true)); - while !T::regs().isr().read().adrdy() {} - T::regs().isr().write(|w| w.set_adrdy(true)); - } - - fn configure(&mut self) { - // single conversion mode, software trigger - T::regs().cfgr1().modify(|w| { - w.set_cont(false); - w.set_discen(false); - w.set_exten(Adc4Exten::DISABLED); - w.set_chselrmod(false); - }); - - // only use one channel at the moment - T::regs().smpr().modify(|w| { - for i in 0..24 { - w.set_smpsel(i, false); - } - }); - } - - /// Enable reading the voltage reference internal channel. - pub fn enable_vrefint(&self) -> VrefInt { - T::regs().ccr().modify(|w| { - w.set_vrefen(true); - }); - - VrefInt {} - } - - /// Enable reading the temperature internal channel. - pub fn enable_temperature(&self) -> Temperature { - T::regs().ccr().modify(|w| { - w.set_vsensesel(true); - }); - - Temperature {} - } - - /// Enable reading the vbat internal channel. - pub fn enable_vbat(&self) -> Vbat { - T::regs().ccr().modify(|w| { - w.set_vbaten(true); - }); - - Vbat {} - } - - /// Enable reading the vbat internal channel. - pub fn enable_vcore(&self) -> Vcore { - Vcore {} - } - - /// Enable reading the vbat internal channel. - pub fn enable_dac_channel(&self, dac: DacChannel) -> Dac { - let mux; - match dac { - DacChannel::OUT1 => mux = false, - DacChannel::OUT2 => mux = true, - } - T::regs().or().modify(|w| w.set_chn21sel(mux)); - Dac {} - } - - /// Set the ADC sample time. - pub fn set_sample_time(&mut self, sample_time: SampleTime) { - T::regs().smpr().modify(|w| { - w.set_smp(0, sample_time); - }); - } - - /// Get the ADC sample time. - pub fn sample_time(&self) -> SampleTime { - T::regs().smpr().read().smp(0) - } - - /// Set the ADC resolution. - pub fn set_resolution(&mut self, resolution: Resolution) { - T::regs().cfgr1().modify(|w| w.set_res(resolution.into())); - } - - /// Set hardware averaging. - pub fn set_averaging(&mut self, averaging: Averaging) { - let (enable, samples, right_shift) = match averaging { - Averaging::Disabled => (false, Adc4OversamplingRatio::OVERSAMPLE2X, 0), - Averaging::Samples2 => (true, Adc4OversamplingRatio::OVERSAMPLE2X, 1), - Averaging::Samples4 => (true, Adc4OversamplingRatio::OVERSAMPLE4X, 2), - Averaging::Samples8 => (true, Adc4OversamplingRatio::OVERSAMPLE8X, 3), - Averaging::Samples16 => (true, Adc4OversamplingRatio::OVERSAMPLE16X, 4), - Averaging::Samples32 => (true, Adc4OversamplingRatio::OVERSAMPLE32X, 5), - Averaging::Samples64 => (true, Adc4OversamplingRatio::OVERSAMPLE64X, 6), - Averaging::Samples128 => (true, Adc4OversamplingRatio::OVERSAMPLE128X, 7), - Averaging::Samples256 => (true, Adc4OversamplingRatio::OVERSAMPLE256X, 8), - }; - - T::regs().cfgr2().modify(|w| { - w.set_ovsr(samples); - w.set_ovss(right_shift); - w.set_ovse(enable) - }) - } - - /// Read an ADC channel. - pub fn blocking_read(&mut self, channel: &mut impl AdcChannel) -> u16 { - channel.setup(); - - // Select channel - T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32)); - T::regs().chselrmod0().modify(|w| { - w.set_chsel(channel.channel() as usize, true); - }); - - // Reset interrupts - T::regs().isr().modify(|reg| { - reg.set_eos(true); - reg.set_eoc(true); - }); - - // Start conversion - T::regs().cr().modify(|reg| { - reg.set_adstart(true); - }); - - while !T::regs().isr().read().eos() { - // spin - } - - T::regs().dr().read().0 as u16 - } - - /// Read one or multiple ADC channels using DMA. - /// - /// `sequence` iterator and `readings` must have the same length. - /// The channels in `sequence` must be in ascending order. - /// - /// Example - /// ```rust,ignore - /// use embassy_stm32::adc::adc4; - /// use embassy_stm32::adc::AdcChannel; - /// - /// let mut adc4 = adc4::Adc4::new(p.ADC4); - /// let mut adc4_pin1 = p.PC1; - /// let mut adc4_pin2 = p.PC0; - /// let mut.into()d41 = adc4_pin1.into(); - /// let mut.into()d42 = adc4_pin2.into(); - /// let mut measurements = [0u16; 2]; - /// // not that the channels must be in ascending order - /// adc4.read( - /// &mut p.GPDMA1_CH1, - /// [ - /// &mut.into()d42, - /// &mut.into()d41, - /// ] - /// .into_iter(), - /// &mut measurements, - /// ).await.unwrap(); - /// ``` - pub async fn read( - &mut self, - rx_dma: Peri<'_, impl RxDma4>, - sequence: impl ExactSizeIterator>, - readings: &mut [u16], - ) -> Result<(), Adc4Error> { - assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty"); - assert!( - sequence.len() == readings.len(), - "Sequence length must be equal to readings length" - ); - - // Ensure no conversions are ongoing - Self::cancel_conversions(); - - T::regs().isr().modify(|reg| { - reg.set_ovr(true); - reg.set_eos(true); - reg.set_eoc(true); - }); - - T::regs().cfgr1().modify(|reg| { - reg.set_dmaen(true); - reg.set_dmacfg(Adc4Dmacfg::ONE_SHOT); - reg.set_chselrmod(false); - }); - - // Verify and activate sequence - let mut prev_channel: i16 = -1; - T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32)); - for channel in sequence { - let channel_num = channel.channel; - if channel_num as i16 <= prev_channel { - return Err(Adc4Error::InvalidSequence); - }; - prev_channel = channel_num as i16; - - T::regs().chselrmod0().modify(|w| { - w.set_chsel(channel.channel as usize, true); - }); - } - - let request = rx_dma.request(); - let transfer = unsafe { - Transfer::new_read( - rx_dma, - request, - T::regs().dr().as_ptr() as *mut u16, - readings, - Default::default(), - ) - }; - - // Start conversion - T::regs().cr().modify(|reg| { - reg.set_adstart(true); - }); - - transfer.await; - - // Ensure conversions are finished. - Self::cancel_conversions(); - - // Reset configuration. - T::regs().cfgr1().modify(|reg| { - reg.set_dmaen(false); - }); - - if T::regs().isr().read().ovr() { - Err(Adc4Error::DMAError) - } else { - Ok(()) - } - } - - fn cancel_conversions() { - if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { - T::regs().cr().modify(|reg| { - reg.set_adstp(true); - }); - while T::regs().cr().read().adstart() {} - } - } -} diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index b9fc4e423..b494997b3 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs @@ -176,6 +176,7 @@ pub(crate) unsafe fn init(config: Config) { // TODO lse: None, lsi: None, + pll1_p: None, pll1_q: None, ); } -- cgit From f597901879f353fcdd59b4a77505309c2aaed187 Mon Sep 17 00:00:00 2001 From: purepani Date: Mon, 30 Jun 2025 03:04:52 -0500 Subject: Adds ADC example for STM32WBA --- examples/stm32wba/src/bin/adc.rs | 49 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 examples/stm32wba/src/bin/adc.rs diff --git a/examples/stm32wba/src/bin/adc.rs b/examples/stm32wba/src/bin/adc.rs new file mode 100644 index 000000000..a9651d57e --- /dev/null +++ b/examples/stm32wba/src/bin/adc.rs @@ -0,0 +1,49 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_stm32::adc::{adc4, AdcChannel}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: embassy_executor::Spawner) { + let config = embassy_stm32::Config::default(); + + let mut p = embassy_stm32::init(config); + + // **** ADC4 init **** + let mut adc4 = adc4::Adc4::new(p.ADC4); + let mut adc4_pin1 = p.PA0; // A4 + let mut adc4_pin2 = p.PA1; // A5 + adc4.set_resolution(adc4::Resolution::BITS12); + adc4.set_averaging(adc4::Averaging::Samples256); + adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); + let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); + + // **** ADC4 blocking read **** + let raw: u16 = adc4.blocking_read(&mut adc4_pin1); + let volt: f32 = 3.0 * raw as f32 / max4 as f32; + info!("Read adc4 pin 1 {}", volt); + + let raw: u16 = adc4.blocking_read(&mut adc4_pin2); + let volt: f32 = 3.3 * raw as f32 / max4 as f32; + info!("Read adc4 pin 2 {}", volt); + + // **** ADC4 async read **** + let mut degraded41 = adc4_pin1.degrade_adc(); + let mut degraded42 = adc4_pin2.degrade_adc(); + let mut measurements = [0u16; 2]; + + // The channels must be in ascending order and can't repeat for ADC4 + adc4.read( + p.GPDMA1_CH1.reborrow(), + [&mut degraded42, &mut degraded41].into_iter(), + &mut measurements, + ) + .await + .unwrap(); + let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; + let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; + info!("Async read 4 pin 1 {}", volt1); + info!("Async read 4 pin 2 {}", volt2); +} -- cgit From 02829f5e4b8340bff35621af47d5d91b9860e96e Mon Sep 17 00:00:00 2001 From: Christoph Baechler Date: Tue, 1 Jul 2025 10:02:07 +0200 Subject: embassy-stm32: fix temperature channel for L0 series --- embassy-stm32/src/adc/v1.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs index fb6f5b7d0..fbe945914 100644 --- a/embassy-stm32/src/adc/v1.rs +++ b/embassy-stm32/src/adc/v1.rs @@ -56,7 +56,11 @@ pub struct Temperature; impl AdcChannel for Temperature {} impl super::SealedAdcChannel for Temperature { fn channel(&self) -> u8 { - 16 + if cfg!(adc_l0) { + 18 + } else { + 16 + } } } -- cgit From 8d2657383e29c78bd6b4a4dd7c2977ee970c636d Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Wed, 2 Jul 2025 10:33:16 +0200 Subject: Link to esp-generate --- docs/pages/new_project.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/pages/new_project.adoc b/docs/pages/new_project.adoc index cd943b4f6..906d89f36 100644 --- a/docs/pages/new_project.adoc +++ b/docs/pages/new_project.adoc @@ -11,6 +11,8 @@ Once you’ve successfully xref:#_getting_started[run some example projects], th - link:https://github.com/lulf/embassy-template[embassy-template] (STM32, NRF, and RP) - link:https://github.com/bentwire/embassy-rp2040-template[embassy-rp2040-template] (RP) +=== esp-generate +- link:https://github.com/esp-rs/esp-generate[esp-generate] (ESP32 using esp-hal) == Starting a project from scratch -- cgit From 30e6d633d3b54b9d34894e9c4b3ce32571115983 Mon Sep 17 00:00:00 2001 From: Juergen Fitschen Date: Wed, 2 Jul 2025 11:39:07 +0200 Subject: embassy-nrf: fix PWM loop count --- embassy-nrf/src/pwm.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index a2e153e26..3d76272ac 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs @@ -479,9 +479,8 @@ impl<'d, 's, T: Instance> Sequencer<'d, 's, T> { let seqstart_index = if start_seq == StartSequence::One { 1 } else { 0 }; match times { - // just the one time, no loop count - SequenceMode::Loop(_) => { - r.loop_().write(|w| w.set_cnt(vals::LoopCnt::DISABLED)); + SequenceMode::Loop(n) => { + r.loop_().write(|w| w.set_cnt(vals::LoopCnt(n))); } // to play infinitely, repeat the sequence one time, then have loops done self trigger seq0 again SequenceMode::Infinite => { -- cgit From 3c0d5063fe59c6831fbcfeae04338606aec05d05 Mon Sep 17 00:00:00 2001 From: Adrian Wowk Date: Wed, 2 Jul 2025 12:31:38 -0500 Subject: rp: add current_core api --- embassy-rp/src/multicore.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs index d10b6837c..64065fcba 100644 --- a/embassy-rp/src/multicore.rs +++ b/embassy-rp/src/multicore.rs @@ -57,6 +57,26 @@ const PAUSE_TOKEN: u32 = 0xDEADBEEF; const RESUME_TOKEN: u32 = !0xDEADBEEF; static IS_CORE1_INIT: AtomicBool = AtomicBool::new(false); +/// Represents a partiticular CPU core (SIO_CPUID) +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[repr(u8)] +pub enum CoreId { + /// Core 0 + Core0 = 0x0, + /// Core 1 + Core1 = 0x1, +} + +/// Gets which core we are currently executing from +pub fn current_core() -> CoreId { + if pac::SIO.cpuid().read() == 0 { + CoreId::Core0 + } else { + CoreId::Core1 + } +} + #[inline(always)] unsafe fn core1_setup(stack_bottom: *mut usize) { if install_stack_guard(stack_bottom).is_err() { -- cgit From db9af5b6cc2d5f47a912836bebf25b48903006f9 Mon Sep 17 00:00:00 2001 From: Sam W Date: Thu, 3 Jul 2025 14:52:33 +0100 Subject: net: correct `UdpSocket::recv_from_with` docs --- embassy-net/src/udp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-net/src/udp.rs b/embassy-net/src/udp.rs index 63c2f4c75..482eb0e56 100644 --- a/embassy-net/src/udp.rs +++ b/embassy-net/src/udp.rs @@ -172,7 +172,7 @@ impl<'a> UdpSocket<'a> { /// register the current task to be notified when a datagram is received. /// /// When a datagram is received, this method will call the provided function - /// with the number of bytes received and the remote endpoint and return + /// with a reference to the received bytes and the remote endpoint and return /// `Poll::Ready` with the function's returned value. pub async fn recv_from_with(&mut self, f: F) -> R where -- cgit From e256f1360b4dff74f712b35db6a5f1bdf794a131 Mon Sep 17 00:00:00 2001 From: qwerty19106 Date: Thu, 3 Jul 2025 18:02:50 +0400 Subject: Fix impl embedded_hal_nb::serial::Write for embassy_stm32::usart::UartTx --- embassy-stm32/src/usart/mod.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index b3f8bc00c..8c9028f08 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -550,6 +550,20 @@ impl<'d, M: Mode> UartTx<'d, M> { reconfigure(self.info, self.kernel_clock, config) } + /// Write a single u8 if there is tx empty, otherwise return WouldBlock + pub(crate) fn nb_write(&mut self, byte: u8) -> Result<(), nb::Error> { + let r = self.info.regs; + let sr = sr(r).read(); + if sr.txe() { + unsafe { + tdr(r).write_volatile(byte); + } + Ok(()) + } else { + Err(nb::Error::WouldBlock) + } + } + /// Perform a blocking UART write pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { let r = self.info.regs; @@ -1864,7 +1878,7 @@ impl<'d, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, M> { impl<'d, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, M> { fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { - self.blocking_write(&[char]).map_err(nb::Error::Other) + self.nb_write(char) } fn flush(&mut self) -> nb::Result<(), Self::Error> { -- cgit From 388eee221e16717fe47913d26a1f6ed4cd35d4bc Mon Sep 17 00:00:00 2001 From: Matt Bhagat-Conway Date: Thu, 3 Jul 2025 10:31:28 -0400 Subject: add note about UART line breaks being different from ASCII --- embassy-rp/src/uart/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index c3a15fda5..b730d33e3 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -515,6 +515,9 @@ impl<'d> UartRx<'d, Async> { /// * If you expect a message of 20 bytes + line break, and provide a 21-byte buffer: /// * The first call to `read_to_break()` will return `Ok(20)`. /// * The next call to `read_to_break()` will work as expected + /// + /// **NOTE**: In the UART context, a line break refers to a break condition (the line being held low for + /// for longer than a single character), not an ASCII line break. pub async fn read_to_break(&mut self, buffer: &mut [u8]) -> Result { self.read_to_break_with_count(buffer, 0).await } @@ -541,6 +544,9 @@ impl<'d> UartRx<'d, Async> { /// * If you expect a message of 20 bytes + line break, and provide a 21-byte buffer: /// * The first call to `read_to_break()` will return `Ok(20)`. /// * The next call to `read_to_break()` will work as expected + /// + /// **NOTE**: In the UART context, a line break refers to a break condition (the line being held low for + /// for longer than a single character), not an ASCII line break. pub async fn read_to_break_with_count( &mut self, buffer: &mut [u8], -- cgit From 6545b051887cd6944557901015b4c5b54a2b6848 Mon Sep 17 00:00:00 2001 From: Matt Bhagat-Conway Date: Thu, 3 Jul 2025 10:37:49 -0400 Subject: fix rustfmt in read_to_break docstring --- embassy-rp/src/uart/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index b730d33e3..cfbce493c 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -544,7 +544,7 @@ impl<'d> UartRx<'d, Async> { /// * If you expect a message of 20 bytes + line break, and provide a 21-byte buffer: /// * The first call to `read_to_break()` will return `Ok(20)`. /// * The next call to `read_to_break()` will work as expected - /// + /// /// **NOTE**: In the UART context, a line break refers to a break condition (the line being held low for /// for longer than a single character), not an ASCII line break. pub async fn read_to_break_with_count( -- cgit From da6c4ff31a3ebc9995c695c0ad9bc260c5ccffed Mon Sep 17 00:00:00 2001 From: Matt Bhagat-Conway Date: Thu, 3 Jul 2025 11:54:00 -0400 Subject: remove line break reference from documentation --- embassy-rp/src/uart/mod.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index cfbce493c..6f4e2ee07 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -495,57 +495,57 @@ impl<'d> UartRx<'d, Async> { unreachable!("unrecognized rx error"); } - /// Read from the UART, waiting for a line break. + /// Read from the UART, waiting for a break. /// /// We read until one of the following occurs: /// - /// * We read `buffer.len()` bytes without a line break + /// * We read `buffer.len()` bytes without a break /// * returns `Err(ReadToBreakError::MissingBreak(buffer.len()))` - /// * We read `n` bytes then a line break occurs + /// * We read `n` bytes then a break occurs /// * returns `Ok(n)` - /// * We encounter some error OTHER than a line break + /// * We encounter some error OTHER than a break /// * returns `Err(ReadToBreakError::Other(error))` /// /// **NOTE**: you MUST provide a buffer one byte larger than your largest expected /// message to reliably detect the framing on one single call to `read_to_break()`. /// - /// * If you expect a message of 20 bytes + line break, and provide a 20-byte buffer: + /// * If you expect a message of 20 bytes + break, and provide a 20-byte buffer: /// * The first call to `read_to_break()` will return `Err(ReadToBreakError::MissingBreak(20))` - /// * The next call to `read_to_break()` will immediately return `Ok(0)`, from the "stale" line break - /// * If you expect a message of 20 bytes + line break, and provide a 21-byte buffer: + /// * The next call to `read_to_break()` will immediately return `Ok(0)`, from the "stale" break + /// * If you expect a message of 20 bytes + break, and provide a 21-byte buffer: /// * The first call to `read_to_break()` will return `Ok(20)`. /// * The next call to `read_to_break()` will work as expected /// - /// **NOTE**: In the UART context, a line break refers to a break condition (the line being held low for + /// **NOTE**: In the UART context, a break refers to a break condition (the line being held low for /// for longer than a single character), not an ASCII line break. pub async fn read_to_break(&mut self, buffer: &mut [u8]) -> Result { self.read_to_break_with_count(buffer, 0).await } - /// Read from the UART, waiting for a line break as soon as at least `min_count` bytes have been read. + /// Read from the UART, waiting for a break as soon as at least `min_count` bytes have been read. /// /// We read until one of the following occurs: /// - /// * We read `buffer.len()` bytes without a line break + /// * We read `buffer.len()` bytes without a break /// * returns `Err(ReadToBreakError::MissingBreak(buffer.len()))` - /// * We read `n > min_count` bytes then a line break occurs + /// * We read `n > min_count` bytes then a break occurs /// * returns `Ok(n)` - /// * We encounter some error OTHER than a line break + /// * We encounter some error OTHER than a break /// * returns `Err(ReadToBreakError::Other(error))` /// - /// If a line break occurs before `min_count` bytes have been read, the break will be ignored and the read will continue + /// If a break occurs before `min_count` bytes have been read, the break will be ignored and the read will continue /// /// **NOTE**: you MUST provide a buffer one byte larger than your largest expected /// message to reliably detect the framing on one single call to `read_to_break()`. /// - /// * If you expect a message of 20 bytes + line break, and provide a 20-byte buffer: + /// * If you expect a message of 20 bytes + break, and provide a 20-byte buffer: /// * The first call to `read_to_break()` will return `Err(ReadToBreakError::MissingBreak(20))` /// * The next call to `read_to_break()` will immediately return `Ok(0)`, from the "stale" line break - /// * If you expect a message of 20 bytes + line break, and provide a 21-byte buffer: + /// * If you expect a message of 20 bytes + break, and provide a 21-byte buffer: /// * The first call to `read_to_break()` will return `Ok(20)`. /// * The next call to `read_to_break()` will work as expected /// - /// **NOTE**: In the UART context, a line break refers to a break condition (the line being held low for + /// **NOTE**: In the UART context, a break refers to a break condition (the line being held low for /// for longer than a single character), not an ASCII line break. pub async fn read_to_break_with_count( &mut self, -- cgit From 72248a601a9ea28ac696f186e2cbe4c2f128a133 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 29 Jun 2025 22:37:11 +0200 Subject: Update Rust nightly, stable. --- embassy-executor/build_common.rs | 32 ----------- .../tests/ui/bad_return_impl_future.stderr | 32 +++++------ embassy-executor/tests/ui/return_impl_send.stderr | 64 +++++++++++----------- embassy-nrf/src/uarte.rs | 2 +- embassy-rp/src/flash.rs | 6 +- embassy-rp/src/relocate.rs | 2 +- .../src/can/fd/message_ram/extended_filter.rs | 8 +-- .../src/can/fd/message_ram/standard_filter.rs | 8 +-- .../src/can/fd/message_ram/txbuffer_element.rs | 18 +++--- embassy-stm32/src/cordic/utils.rs | 2 +- embassy-stm32/src/tsc/acquisition_banks.rs | 6 +- embassy-sync/src/pubsub/mod.rs | 8 +-- embassy-usb/src/class/web_usb.rs | 2 +- rust-toolchain-nightly.toml | 2 +- rust-toolchain.toml | 2 +- 15 files changed, 83 insertions(+), 111 deletions(-) diff --git a/embassy-executor/build_common.rs b/embassy-executor/build_common.rs index b15a8369f..4f24e6d37 100644 --- a/embassy-executor/build_common.rs +++ b/embassy-executor/build_common.rs @@ -92,35 +92,3 @@ pub fn set_target_cfgs(cfgs: &mut CfgSet) { cfgs.set("has_fpu", target.ends_with("-eabihf")); } - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub struct CompilerDate { - year: u16, - month: u8, - day: u8, -} - -impl CompilerDate { - fn parse(date: &str) -> Option { - let mut parts = date.split('-'); - let year = parts.next()?.parse().ok()?; - let month = parts.next()?.parse().ok()?; - let day = parts.next()?.parse().ok()?; - Some(Self { year, month, day }) - } -} - -impl PartialEq<&str> for CompilerDate { - fn eq(&self, other: &&str) -> bool { - let Some(other) = Self::parse(other) else { - return false; - }; - self.eq(&other) - } -} - -impl PartialOrd<&str> for CompilerDate { - fn partial_cmp(&self, other: &&str) -> Option { - Self::parse(other).map(|other| self.cmp(&other)) - } -} diff --git a/embassy-executor/tests/ui/bad_return_impl_future.stderr b/embassy-executor/tests/ui/bad_return_impl_future.stderr index 2980fd18b..57f147714 100644 --- a/embassy-executor/tests/ui/bad_return_impl_future.stderr +++ b/embassy-executor/tests/ui/bad_return_impl_future.stderr @@ -68,6 +68,22 @@ note: required by a bound in `task_pool_align` | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_align` = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) +error[E0277]: task futures must resolve to `()` or `!` + --> tests/ui/bad_return_impl_future.rs:5:4 + | +4 | #[embassy_executor::task] + | ------------------------- required by a bound introduced by this call +5 | fn task() -> impl Future { + | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` + | + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `__task_pool_get` + --> tests/ui/bad_return_impl_future.rs:4:1 + | +4 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `__task_pool_get` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) + error[E0277]: task futures must resolve to `()` or `!` --> tests/ui/bad_return_impl_future.rs:5:4 | @@ -102,19 +118,3 @@ note: required by a bound in `task_pool_new` | F: TaskFn, | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_new` = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: task futures must resolve to `()` or `!` - --> tests/ui/bad_return_impl_future.rs:5:4 - | -4 | #[embassy_executor::task] - | ------------------------- required by a bound introduced by this call -5 | fn task() -> impl Future { - | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Future {__task_task}` - | - = note: use `async fn` or change the return type to `impl Future` -note: required by a bound in `__task_pool_get` - --> tests/ui/bad_return_impl_future.rs:4:1 - | -4 | #[embassy_executor::task] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `__task_pool_get` - = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/embassy-executor/tests/ui/return_impl_send.stderr b/embassy-executor/tests/ui/return_impl_send.stderr index 7e3e468b8..cd693af2b 100644 --- a/embassy-executor/tests/ui/return_impl_send.stderr +++ b/embassy-executor/tests/ui/return_impl_send.stderr @@ -77,30 +77,28 @@ error[E0277]: task futures must resolve to `()` or `!` | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Send {__task_task}` | = note: use `async fn` or change the return type to `impl Future` -note: required by a bound in `task_pool_new` - --> src/lib.rs +note: required by a bound in `__task_pool_get` + --> tests/ui/return_impl_send.rs:3:1 | - | pub const fn task_pool_new(_: F) -> TaskPool - | ------------- required by a bound in this function - | where - | F: TaskFn, - | ^^^^^^^^^ required by this bound in `task_pool_new` +3 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `__task_pool_get` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: task futures must resolve to `()` or `!` +error[E0277]: `impl Send` is not a future --> tests/ui/return_impl_send.rs:3:1 | 3 | #[embassy_executor::task] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Send {__task_task}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `impl Send` is not a future | - = note: use `async fn` or change the return type to `impl Future` -note: required by a bound in `task_pool_new` - --> src/lib.rs + = help: the trait `Future` is not implemented for `impl Send` +note: required by a bound in `TaskPool::::_spawn_async_fn` + --> src/raw/mod.rs | - | pub const fn task_pool_new(_: F) -> TaskPool - | ------------- required by a bound in this function - | where - | F: TaskFn, - | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_new` + | impl TaskPool { + | ^^^^^^ required by this bound in `TaskPool::::_spawn_async_fn` +... + | pub unsafe fn _spawn_async_fn(&'static self, future: FutFn) -> SpawnToken + | --------------- required by a bound in this associated function = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: task futures must resolve to `()` or `!` @@ -112,26 +110,28 @@ error[E0277]: task futures must resolve to `()` or `!` | ^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Send {__task_task}` | = note: use `async fn` or change the return type to `impl Future` -note: required by a bound in `__task_pool_get` - --> tests/ui/return_impl_send.rs:3:1 +note: required by a bound in `task_pool_new` + --> src/lib.rs | -3 | #[embassy_executor::task] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `__task_pool_get` - = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) + | pub const fn task_pool_new(_: F) -> TaskPool + | ------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^ required by this bound in `task_pool_new` -error[E0277]: `impl Send` is not a future +error[E0277]: task futures must resolve to `()` or `!` --> tests/ui/return_impl_send.rs:3:1 | 3 | #[embassy_executor::task] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ `impl Send` is not a future + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TaskFn<_>` is not implemented for fn item `fn() -> impl Send {__task_task}` | - = help: the trait `Future` is not implemented for `impl Send` -note: required by a bound in `TaskPool::::_spawn_async_fn` - --> src/raw/mod.rs + = note: use `async fn` or change the return type to `impl Future` +note: required by a bound in `task_pool_new` + --> src/lib.rs | - | impl TaskPool { - | ^^^^^^ required by this bound in `TaskPool::::_spawn_async_fn` -... - | pub unsafe fn _spawn_async_fn(&'static self, future: FutFn) -> SpawnToken - | --------------- required by a bound in this associated function + | pub const fn task_pool_new(_: F) -> TaskPool + | ------------- required by a bound in this function + | where + | F: TaskFn, + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `task_pool_new` = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index f377df49e..927a0ac08 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -245,7 +245,7 @@ impl<'d, T: Instance> Uarte<'d, T> { } /// Return the endtx event for use with PPI - pub fn event_endtx(&self) -> Event { + pub fn event_endtx(&self) -> Event<'_> { let r = T::regs(); Event::from_reg(r.events_endtx()) } diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs index ef1cd9212..8c809090e 100644 --- a/embassy-rp/src/flash.rs +++ b/embassy-rp/src/flash.rs @@ -482,7 +482,11 @@ mod ram_helpers { /// # Safety /// /// `boot2` must contain a valid 2nd stage boot loader which can be called to re-initialize XIP mode - unsafe fn flash_function_pointers_with_boot2(erase: bool, write: bool, boot2: &[u32; 64]) -> FlashFunctionPointers { + unsafe fn flash_function_pointers_with_boot2( + erase: bool, + write: bool, + boot2: &[u32; 64], + ) -> FlashFunctionPointers<'_> { let boot2_fn_ptr = (boot2 as *const u32 as *const u8).offset(1); let boot2_fn: unsafe extern "C" fn() -> () = core::mem::transmute(boot2_fn_ptr); FlashFunctionPointers { diff --git a/embassy-rp/src/relocate.rs b/embassy-rp/src/relocate.rs index 34487819f..6ff40ddd7 100644 --- a/embassy-rp/src/relocate.rs +++ b/embassy-rp/src/relocate.rs @@ -39,7 +39,7 @@ pub struct RelocatedProgram<'a, const PROGRAM_SIZE: usize> { } impl<'a, const PROGRAM_SIZE: usize> RelocatedProgram<'a, PROGRAM_SIZE> { - pub fn new_with_origin(program: &Program, origin: u8) -> RelocatedProgram { + pub fn new_with_origin(program: &Program, origin: u8) -> RelocatedProgram<'_, PROGRAM_SIZE> { RelocatedProgram { program, origin } } diff --git a/embassy-stm32/src/can/fd/message_ram/extended_filter.rs b/embassy-stm32/src/can/fd/message_ram/extended_filter.rs index 453e9056e..ac47901a8 100644 --- a/embassy-stm32/src/can/fd/message_ram/extended_filter.rs +++ b/embassy-stm32/src/can/fd/message_ram/extended_filter.rs @@ -115,22 +115,22 @@ impl R { impl W { #[doc = "Byte 0 - Bits 0:28 - EFID1"] #[inline(always)] - pub fn efid1(&mut self) -> EFID1_W { + pub fn efid1(&mut self) -> EFID1_W<'_> { EFID1_W { w: self } } #[doc = "Byte 0 - Bits 29:31 - EFEC"] #[inline(always)] - pub fn efec(&mut self) -> EFEC_W { + pub fn efec(&mut self) -> EFEC_W<'_> { EFEC_W { w: self } } #[doc = "Byte 1 - Bits 0:28 - EFID2"] #[inline(always)] - pub fn efid2(&mut self) -> EFID2_W { + pub fn efid2(&mut self) -> EFID2_W<'_> { EFID2_W { w: self } } #[doc = "Byte 1 - Bits 30:31 - EFT"] #[inline(always)] - pub fn eft(&mut self) -> EFT_W { + pub fn eft(&mut self) -> EFT_W<'_> { EFT_W { w: self } } } diff --git a/embassy-stm32/src/can/fd/message_ram/standard_filter.rs b/embassy-stm32/src/can/fd/message_ram/standard_filter.rs index 3a3bbcf12..f52646bfe 100644 --- a/embassy-stm32/src/can/fd/message_ram/standard_filter.rs +++ b/embassy-stm32/src/can/fd/message_ram/standard_filter.rs @@ -115,22 +115,22 @@ impl R { impl W { #[doc = "Bits 0:10 - SFID2"] #[inline(always)] - pub fn sfid2(&mut self) -> SFID2_W { + pub fn sfid2(&mut self) -> SFID2_W<'_> { SFID2_W { w: self } } #[doc = "Bits 16:26 - SFID1"] #[inline(always)] - pub fn sfid1(&mut self) -> SFID1_W { + pub fn sfid1(&mut self) -> SFID1_W<'_> { SFID1_W { w: self } } #[doc = "Bits 27:29 - SFEC"] #[inline(always)] - pub fn sfec(&mut self) -> SFEC_W { + pub fn sfec(&mut self) -> SFEC_W<'_> { SFEC_W { w: self } } #[doc = "Bits 30:31 - SFT"] #[inline(always)] - pub fn sft(&mut self) -> SFT_W { + pub fn sft(&mut self) -> SFT_W<'_> { SFT_W { w: self } } } diff --git a/embassy-stm32/src/can/fd/message_ram/txbuffer_element.rs b/embassy-stm32/src/can/fd/message_ram/txbuffer_element.rs index 455406a1c..6d65a86cb 100644 --- a/embassy-stm32/src/can/fd/message_ram/txbuffer_element.rs +++ b/embassy-stm32/src/can/fd/message_ram/txbuffer_element.rs @@ -376,47 +376,47 @@ impl R { impl W { #[doc = "Byte 0 - Bits 0:28 - ID"] #[inline(always)] - pub fn id(&mut self) -> ID_W { + pub fn id(&mut self) -> ID_W<'_> { ID_W { w: self } } #[doc = "Byte 0 - Bit 29 - RTR"] #[inline(always)] - pub fn rtr(&mut self) -> RTR_W { + pub fn rtr(&mut self) -> RTR_W<'_> { RTR_W { w: self } } #[doc = "Byte 0 - Bit 30 - XTD"] #[inline(always)] - pub fn xtd(&mut self) -> XTD_W { + pub fn xtd(&mut self) -> XTD_W<'_> { XTD_W { w: self } } #[doc = "Byte 0 - Bit 31 - ESI"] #[inline(always)] - pub fn esi(&mut self) -> ESI_W { + pub fn esi(&mut self) -> ESI_W<'_> { ESI_W { w: self } } #[doc = "Byte 1 - Bit 16:19 - DLC"] #[inline(always)] - pub fn dlc(&mut self) -> DLC_W { + pub fn dlc(&mut self) -> DLC_W<'_> { DLC_W { w: self } } #[doc = "Byte 1 - Bit 20 - BRS"] #[inline(always)] - pub fn brs(&mut self) -> BRS_W { + pub fn brs(&mut self) -> BRS_W<'_> { BRS_W { w: self } } #[doc = "Byte 1 - Bit 21 - FDF"] #[inline(always)] - pub fn fdf(&mut self) -> FDF_W { + pub fn fdf(&mut self) -> FDF_W<'_> { FDF_W { w: self } } #[doc = "Byte 1 - Bit 23 - EFC"] #[inline(always)] - pub fn efc(&mut self) -> EFC_W { + pub fn efc(&mut self) -> EFC_W<'_> { EFC_W { w: self } } #[doc = "Byte 1 - Bit 24:31 - MM"] #[inline(always)] - pub fn mm(&mut self) -> MM_W { + pub fn mm(&mut self) -> MM_W<'_> { MM_W { w: self } } #[doc = "Convenience function for setting the data length and frame format"] diff --git a/embassy-stm32/src/cordic/utils.rs b/embassy-stm32/src/cordic/utils.rs index 008f50270..9afa8ef53 100644 --- a/embassy-stm32/src/cordic/utils.rs +++ b/embassy-stm32/src/cordic/utils.rs @@ -5,7 +5,7 @@ macro_rules! floating_fixed_convert { ($f_to_q:ident, $q_to_f:ident, $unsigned_bin_typ:ty, $signed_bin_typ:ty, $float_ty:ty, $offset:literal, $min_positive:literal) => { /// convert float point to fixed point format pub fn $f_to_q(value: $float_ty) -> Result<$unsigned_bin_typ, NumberOutOfRange> { - const MIN_POSITIVE: $float_ty = unsafe { core::mem::transmute($min_positive) }; + const MIN_POSITIVE: $float_ty = <$float_ty>::from_bits($min_positive); if value < -1.0 { return Err(NumberOutOfRange::BelowLowerBound) diff --git a/embassy-stm32/src/tsc/acquisition_banks.rs b/embassy-stm32/src/tsc/acquisition_banks.rs index 6791ef6c1..7d6442b48 100644 --- a/embassy-stm32/src/tsc/acquisition_banks.rs +++ b/embassy-stm32/src/tsc/acquisition_banks.rs @@ -32,7 +32,7 @@ impl AcquisitionBankPins { /// Returns an iterator over the pins in this acquisition bank. /// /// This method allows for easy traversal of all configured pins in the bank. - pub fn iter(&self) -> AcquisitionBankPinsIterator { + pub fn iter(&self) -> AcquisitionBankPinsIterator<'_> { AcquisitionBankPinsIterator(AcquisitionBankIterator::new(self)) } } @@ -90,7 +90,7 @@ impl<'a> Iterator for AcquisitionBankPinsIterator<'a> { impl AcquisitionBankPins { /// Returns an iterator over the available pins in the bank - pub fn pins_iterator(&self) -> AcquisitionBankPinsIterator { + pub fn pins_iterator(&self) -> AcquisitionBankPinsIterator<'_> { AcquisitionBankPinsIterator(AcquisitionBankIterator::new(self)) } } @@ -107,7 +107,7 @@ pub struct AcquisitionBank { impl AcquisitionBank { /// Returns an iterator over the available pins in the bank. - pub fn pins_iterator(&self) -> AcquisitionBankPinsIterator { + pub fn pins_iterator(&self) -> AcquisitionBankPinsIterator<'_> { self.pins.pins_iterator() } diff --git a/embassy-sync/src/pubsub/mod.rs b/embassy-sync/src/pubsub/mod.rs index 606efff0a..9206b9383 100644 --- a/embassy-sync/src/pubsub/mod.rs +++ b/embassy-sync/src/pubsub/mod.rs @@ -88,7 +88,7 @@ impl Result, Error> { + pub fn subscriber(&self) -> Result, Error> { self.inner.lock(|inner| { let mut s = inner.borrow_mut(); @@ -120,7 +120,7 @@ impl Result, Error> { + pub fn publisher(&self) -> Result, Error> { self.inner.lock(|inner| { let mut s = inner.borrow_mut(); @@ -151,13 +151,13 @@ impl ImmediatePublisher { + pub fn immediate_publisher(&self) -> ImmediatePublisher<'_, M, T, CAP, SUBS, PUBS> { ImmediatePublisher(ImmediatePub::new(self)) } /// Create a new publisher that can only send immediate messages. /// This kind of publisher does not take up a publisher slot. - pub fn dyn_immediate_publisher(&self) -> DynImmediatePublisher { + pub fn dyn_immediate_publisher(&self) -> DynImmediatePublisher<'_, T> { DynImmediatePublisher(ImmediatePub::new(self)) } diff --git a/embassy-usb/src/class/web_usb.rs b/embassy-usb/src/class/web_usb.rs index 405944f14..154b219ca 100644 --- a/embassy-usb/src/class/web_usb.rs +++ b/embassy-usb/src/class/web_usb.rs @@ -84,7 +84,7 @@ impl<'d> Control<'d> { } impl<'d> Handler for Control<'d> { - fn control_in(&mut self, req: Request, _data: &mut [u8]) -> Option { + fn control_in(&mut self, req: Request, _data: &mut [u8]) -> Option> { let landing_value = if self.landing_url.is_some() { 1 } else { 0 }; if req.request_type == RequestType::Vendor && req.recipient == Recipient::Device diff --git a/rust-toolchain-nightly.toml b/rust-toolchain-nightly.toml index e75ea40cc..411cc6946 100644 --- a/rust-toolchain-nightly.toml +++ b/rust-toolchain-nightly.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "nightly-2025-03-12" +channel = "nightly-2025-06-29" components = [ "rust-src", "rustfmt", "llvm-tools", "miri" ] targets = [ "thumbv7em-none-eabi", diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 870904c3a..e24864037 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.85" +channel = "1.88" components = [ "rust-src", "rustfmt", "llvm-tools" ] targets = [ "thumbv7em-none-eabi", -- cgit From 00b2567fbf6b264a77dbe63ca2424939957f3128 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 30 Jun 2025 00:19:47 +0200 Subject: stm32/dma: add missing fence on BDMA start. --- embassy-stm32/src/dma/dma_bdma.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/dma/dma_bdma.rs b/embassy-stm32/src/dma/dma_bdma.rs index 7dbbe7b72..caf135989 100644 --- a/embassy-stm32/src/dma/dma_bdma.rs +++ b/embassy-stm32/src/dma/dma_bdma.rs @@ -344,6 +344,9 @@ impl AnyChannel { peripheral_size: WordSize, options: TransferOptions, ) { + // "Preceding reads and writes cannot be moved past subsequent writes." + fence(Ordering::SeqCst); + let info = self.info(); #[cfg(feature = "_dual-core")] { @@ -362,9 +365,6 @@ impl AnyChannel { let state: &ChannelState = &STATE[self.id as usize]; let ch = r.st(info.num); - // "Preceding reads and writes cannot be moved past subsequent writes." - fence(Ordering::SeqCst); - state.complete_count.store(0, Ordering::Release); self.clear_irqs(); -- cgit From 84cc949df649c9b3625a65c2cc14e09155deeede Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 30 Jun 2025 00:18:44 +0200 Subject: stm32/dma: fix packing/unpacking not working. --- embassy-stm32/src/cryp/mod.rs | 13 ++------ embassy-stm32/src/dma/dma_bdma.rs | 63 +++++++++++++++++++++++++-------------- embassy-stm32/src/dma/gpdma.rs | 12 ++++---- embassy-stm32/src/dma/util.rs | 6 ++-- embassy-stm32/src/spi/mod.rs | 2 +- examples/stm32f7/src/bin/cryp.rs | 4 ++- tests/stm32/src/bin/cryp.rs | 2 +- 7 files changed, 57 insertions(+), 45 deletions(-) diff --git a/embassy-stm32/src/cryp/mod.rs b/embassy-stm32/src/cryp/mod.rs index fba3c0fd7..35d9f8cce 100644 --- a/embassy-stm32/src/cryp/mod.rs +++ b/embassy-stm32/src/cryp/mod.rs @@ -2,7 +2,6 @@ #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] use core::cmp::min; use core::marker::PhantomData; -use core::ptr; use embassy_hal_internal::{Peri, PeripheralType}; use embassy_sync::waitqueue::AtomicWaker; @@ -1814,14 +1813,12 @@ impl<'d, T: Instance> Cryp<'d, T, Async> { assert_eq!(blocks.len() % block_size, 0); // Configure DMA to transfer input to crypto core. let dst_ptr: *mut u32 = T::regs().din().as_ptr(); - let num_words = blocks.len() / 4; - let src_ptr: *const [u8] = ptr::slice_from_raw_parts(blocks.as_ptr().cast(), num_words); let options = TransferOptions { #[cfg(not(gpdma))] priority: crate::dma::Priority::High, ..Default::default() }; - let dma_transfer = unsafe { dma.write_raw(src_ptr, dst_ptr, options) }; + let dma_transfer = unsafe { dma.write_raw(blocks, dst_ptr, options) }; T::regs().dmacr().modify(|w| w.set_dien(true)); // Wait for the transfer to complete. dma_transfer.await; @@ -1836,14 +1833,12 @@ impl<'d, T: Instance> Cryp<'d, T, Async> { assert_eq!((blocks.len() * 4) % block_size, 0); // Configure DMA to transfer input to crypto core. let dst_ptr: *mut u32 = T::regs().din().as_ptr(); - let num_words = blocks.len(); - let src_ptr: *const [u32] = ptr::slice_from_raw_parts(blocks.as_ptr().cast(), num_words); let options = TransferOptions { #[cfg(not(gpdma))] priority: crate::dma::Priority::High, ..Default::default() }; - let dma_transfer = unsafe { dma.write_raw(src_ptr, dst_ptr, options) }; + let dma_transfer = unsafe { dma.write_raw(blocks, dst_ptr, options) }; T::regs().dmacr().modify(|w| w.set_dien(true)); // Wait for the transfer to complete. dma_transfer.await; @@ -1857,14 +1852,12 @@ impl<'d, T: Instance> Cryp<'d, T, Async> { assert_eq!(blocks.len() % block_size, 0); // Configure DMA to get output from crypto core. let src_ptr = T::regs().dout().as_ptr(); - let num_words = blocks.len() / 4; - let dst_ptr = ptr::slice_from_raw_parts_mut(blocks.as_mut_ptr().cast(), num_words); let options = TransferOptions { #[cfg(not(gpdma))] priority: crate::dma::Priority::VeryHigh, ..Default::default() }; - let dma_transfer = unsafe { dma.read_raw(src_ptr, dst_ptr, options) }; + let dma_transfer = unsafe { dma.read_raw(src_ptr, blocks, options) }; T::regs().dmacr().modify(|w| w.set_doen(true)); // Wait for the transfer to complete. dma_transfer.await; diff --git a/embassy-stm32/src/dma/dma_bdma.rs b/embassy-stm32/src/dma/dma_bdma.rs index caf135989..464823bfc 100644 --- a/embassy-stm32/src/dma/dma_bdma.rs +++ b/embassy-stm32/src/dma/dma_bdma.rs @@ -341,7 +341,7 @@ impl AnyChannel { mem_len: usize, incr_mem: bool, mem_size: WordSize, - peripheral_size: WordSize, + peri_size: WordSize, options: TransferOptions, ) { // "Preceding reads and writes cannot be moved past subsequent writes." @@ -357,8 +357,6 @@ impl AnyChannel { #[cfg(dmamux)] super::dmamux::configure_dmamux(&info.dmamux, _request); - assert!(mem_len > 0 && mem_len <= 0xFFFF); - match self.info().dma { #[cfg(dma)] DmaInfo::Dma(r) => { @@ -368,14 +366,39 @@ impl AnyChannel { state.complete_count.store(0, Ordering::Release); self.clear_irqs(); + // NDTR is the number of transfers in the *peripheral* word size. + // ex: if mem_size=1, peri_size=4 and ndtr=3 it'll do 12 mem transfers, 3 peri transfers. + let ndtr = match (mem_size, peri_size) { + (WordSize::FourBytes, WordSize::OneByte) => mem_len * 4, + (WordSize::FourBytes, WordSize::TwoBytes) | (WordSize::TwoBytes, WordSize::OneByte) => mem_len * 2, + (WordSize::FourBytes, WordSize::FourBytes) + | (WordSize::TwoBytes, WordSize::TwoBytes) + | (WordSize::OneByte, WordSize::OneByte) => mem_len, + (WordSize::TwoBytes, WordSize::FourBytes) | (WordSize::OneByte, WordSize::TwoBytes) => { + assert!(mem_len % 2 == 0); + mem_len / 2 + } + (WordSize::OneByte, WordSize::FourBytes) => { + assert!(mem_len % 4 == 0); + mem_len / 4 + } + }; + + assert!(ndtr > 0 && ndtr <= 0xFFFF); + ch.par().write_value(peri_addr as u32); ch.m0ar().write_value(mem_addr as u32); - ch.ndtr().write_value(pac::dma::regs::Ndtr(mem_len as _)); + ch.ndtr().write_value(pac::dma::regs::Ndtr(ndtr as _)); ch.fcr().write(|w| { if let Some(fth) = options.fifo_threshold { // FIFO mode w.set_dmdis(pac::dma::vals::Dmdis::DISABLED); w.set_fth(fth.into()); + } else if mem_size != peri_size { + // force FIFO mode if msize != psize + // packing/unpacking doesn't work in direct mode. + w.set_dmdis(pac::dma::vals::Dmdis::DISABLED); + w.set_fth(FifoThreshold::Half.into()); } else { // Direct mode w.set_dmdis(pac::dma::vals::Dmdis::ENABLED); @@ -384,7 +407,7 @@ impl AnyChannel { ch.cr().write(|w| { w.set_dir(dir.into()); w.set_msize(mem_size.into()); - w.set_psize(peripheral_size.into()); + w.set_psize(peri_size.into()); w.set_pl(options.priority.into()); w.set_minc(incr_mem); w.set_pinc(false); @@ -404,6 +427,8 @@ impl AnyChannel { } #[cfg(bdma)] DmaInfo::Bdma(r) => { + assert!(mem_len > 0 && mem_len <= 0xFFFF); + #[cfg(bdma_v2)] critical_section::with(|_| r.cselr().modify(|w| w.set_cs(info.num, _request))); @@ -417,7 +442,7 @@ impl AnyChannel { ch.mar().write_value(mem_addr as u32); ch.ndtr().write(|w| w.set_ndt(mem_len as u16)); ch.cr().write(|w| { - w.set_psize(peripheral_size.into()); + w.set_psize(peri_size.into()); w.set_msize(mem_size.into()); w.set_minc(incr_mem); w.set_dir(dir.into()); @@ -587,11 +612,11 @@ impl<'a> Transfer<'a> { } /// Create a new read DMA transfer (peripheral to memory), using raw pointers. - pub unsafe fn new_read_raw( + pub unsafe fn new_read_raw( channel: Peri<'a, impl Channel>, request: Request, - peri_addr: *mut W, - buf: *mut [W], + peri_addr: *mut PW, + buf: *mut [MW], options: TransferOptions, ) -> Self { Self::new_inner( @@ -599,11 +624,11 @@ impl<'a> Transfer<'a> { request, Dir::PeripheralToMemory, peri_addr as *const u32, - buf as *mut W as *mut u32, + buf as *mut MW as *mut u32, buf.len(), true, - W::size(), - W::size(), + MW::size(), + PW::size(), options, ) } @@ -672,22 +697,14 @@ impl<'a> Transfer<'a> { mem_addr: *mut u32, mem_len: usize, incr_mem: bool, - data_size: WordSize, - peripheral_size: WordSize, + mem_size: WordSize, + peri_size: WordSize, options: TransferOptions, ) -> Self { assert!(mem_len > 0 && mem_len <= 0xFFFF); channel.configure( - _request, - dir, - peri_addr, - mem_addr, - mem_len, - incr_mem, - data_size, - peripheral_size, - options, + _request, dir, peri_addr, mem_addr, mem_len, incr_mem, mem_size, peri_size, options, ); channel.start(); Self { channel } diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs index ade70fb55..151e4ab9f 100644 --- a/embassy-stm32/src/dma/gpdma.rs +++ b/embassy-stm32/src/dma/gpdma.rs @@ -125,11 +125,11 @@ impl<'a> Transfer<'a> { } /// Create a new read DMA transfer (peripheral to memory), using raw pointers. - pub unsafe fn new_read_raw( + pub unsafe fn new_read_raw( channel: Peri<'a, impl Channel>, request: Request, - peri_addr: *mut W, - buf: *mut [W], + peri_addr: *mut PW, + buf: *mut [MW], options: TransferOptions, ) -> Self { Self::new_inner( @@ -137,11 +137,11 @@ impl<'a> Transfer<'a> { request, Dir::PeripheralToMemory, peri_addr as *const u32, - buf as *mut W as *mut u32, + buf as *mut MW as *mut u32, buf.len(), true, - W::size(), - W::size(), + PW::size(), + MW::size(), options, ) } diff --git a/embassy-stm32/src/dma/util.rs b/embassy-stm32/src/dma/util.rs index 8bf89e2fe..3245887c1 100644 --- a/embassy-stm32/src/dma/util.rs +++ b/embassy-stm32/src/dma/util.rs @@ -20,10 +20,10 @@ impl<'d> ChannelAndRequest<'d> { Transfer::new_read(self.channel.reborrow(), self.request, peri_addr, buf, options) } - pub unsafe fn read_raw<'a, W: Word>( + pub unsafe fn read_raw<'a, MW: Word, PW: Word>( &'a mut self, - peri_addr: *mut W, - buf: *mut [W], + peri_addr: *mut PW, + buf: *mut [MW], options: TransferOptions, ) -> Transfer<'a> { Transfer::new_read_raw(self.channel.reborrow(), self.request, peri_addr, buf, options) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 9e2ba093a..c8d83f07e 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -843,7 +843,7 @@ impl<'d> Spi<'d, Async> { set_rxdmaen(self.info.regs, true); - let rx_src = self.info.regs.rx_ptr(); + let rx_src = self.info.regs.rx_ptr::(); let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) }; let tx_dst: *mut W = self.info.regs.tx_ptr(); diff --git a/examples/stm32f7/src/bin/cryp.rs b/examples/stm32f7/src/bin/cryp.rs index 235853cb9..a31e9b4f2 100644 --- a/examples/stm32f7/src/bin/cryp.rs +++ b/examples/stm32f7/src/bin/cryp.rs @@ -68,7 +68,9 @@ async fn main(_spawner: Spawner) -> ! { ); // Decrypt in software using AES-GCM 128-bit - let _ = cipher.decrypt_in_place(&iv.into(), aad.into(), &mut payload_vec); + cipher + .decrypt_in_place(&iv.into(), aad.into(), &mut payload_vec) + .unwrap(); let sw_end_time = Instant::now(); let sw_execution_time = sw_end_time - sw_start_time; diff --git a/tests/stm32/src/bin/cryp.rs b/tests/stm32/src/bin/cryp.rs index 028775ac8..f54c99cc3 100644 --- a/tests/stm32/src/bin/cryp.rs +++ b/tests/stm32/src/bin/cryp.rs @@ -72,7 +72,7 @@ async fn main(_spawner: Spawner) { defmt::assert!(encrypt_tag == payload_vec[ciphertext.len()..ciphertext.len() + encrypt_tag.len()]); // Decrypt in software using AES-GCM 128-bit - let _ = cipher.decrypt_in_place(&iv.into(), &aad, &mut payload_vec); + cipher.decrypt_in_place(&iv.into(), &aad, &mut payload_vec).unwrap(); info!("Test OK"); cortex_m::asm::bkpt(); -- cgit From 3127e1c50b2ea2efddba199ae780cb5ebb571c00 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 30 Jun 2025 04:02:09 +0200 Subject: sdmmc: use div_ceil. --- embassy-stm32/src/sdmmc/mod.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 675d1813b..c82407334 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs @@ -225,8 +225,7 @@ fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u8, Hertz), Error> { return Ok((true, 0, ker_ck)); } - // `ker_ck / sdmmc_ck` rounded up - let clk_div = match (ker_ck.0 + sdmmc_ck - 1) / sdmmc_ck { + let clk_div = match ker_ck.0.div_ceil(sdmmc_ck) { 0 | 1 => Ok(0), x @ 2..=258 => Ok((x - 2) as u8), _ => Err(Error::BadClock), @@ -244,12 +243,11 @@ fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u8, Hertz), Error> { /// `clk_div` is the divisor register value and `clk_f` is the resulting new clock frequency. #[cfg(sdmmc_v2)] fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u16, Hertz), Error> { - // `ker_ck / sdmmc_ck` rounded up - match (ker_ck.0 + sdmmc_ck - 1) / sdmmc_ck { + match ker_ck.0.div_ceil(sdmmc_ck) { 0 | 1 => Ok((false, 0, ker_ck)), x @ 2..=2046 => { // SDMMC_CK frequency = SDMMCCLK / [CLKDIV * 2] - let clk_div = ((x + 1) / 2) as u16; + let clk_div = x.div_ceil(2) as u16; let clk = Hertz(ker_ck.0 / (clk_div as u32 * 2)); Ok((false, clk_div, clk)) -- cgit From c8a4a4995844be1b61d1a1479a6009eeb69b1117 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 4 Jul 2025 00:25:00 +0200 Subject: stm32/sdmmc: misc improvements --- embassy-stm32/src/sdmmc/mod.rs | 124 ++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 71 deletions(-) diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index c82407334..6e5d735d7 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs @@ -32,25 +32,48 @@ pub struct InterruptHandler { } impl InterruptHandler { - fn data_interrupts(enable: bool) { + fn enable_interrupts() { let regs = T::regs(); regs.maskr().write(|w| { - w.set_dcrcfailie(enable); - w.set_dtimeoutie(enable); - w.set_dataendie(enable); + w.set_dcrcfailie(true); + w.set_dtimeoutie(true); + w.set_dataendie(true); + w.set_dbckendie(true); #[cfg(sdmmc_v1)] - w.set_stbiterre(enable); + w.set_stbiterre(true); #[cfg(sdmmc_v2)] - w.set_dabortie(enable); + w.set_dabortie(true); }); } } impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { - Self::data_interrupts(false); T::state().wake(); + let status = T::regs().star().read(); + T::regs().maskr().modify(|w| { + if status.dcrcfail() { + w.set_dcrcfailie(false) + } + if status.dtimeout() { + w.set_dtimeoutie(false) + } + if status.dataend() { + w.set_dataendie(false) + } + if status.dbckend() { + w.set_dbckendie(false) + } + #[cfg(sdmmc_v1)] + if status.stbiterr() { + w.set_stbiterre(false) + } + #[cfg(sdmmc_v2)] + if status.dabort() { + w.set_dabortie(false) + } + }); } } @@ -1002,14 +1025,14 @@ impl<'d, T: Instance> Sdmmc<'d, T> { // Wait for the abort while Self::data_active() {} } - InterruptHandler::::data_interrupts(false); + regs.maskr().write(|_| ()); // disable irqs Self::clear_interrupt_flags(); Self::stop_datapath(); } /// Wait for a previously started datapath transfer to complete from an interrupt. #[inline] - async fn complete_datapath_transfer() -> Result<(), Error> { + async fn complete_datapath_transfer(block: bool) -> Result<(), Error> { let regs = T::regs(); let res = poll_fn(|cx| { @@ -1029,7 +1052,11 @@ impl<'d, T: Instance> Sdmmc<'d, T> { if status.stbiterr() { return Poll::Ready(Err(Error::StBitErr)); } - if status.dataend() { + let done = match block { + true => status.dbckend(), + false => status.dataend(), + }; + if done { return Poll::Ready(Ok(())); } Poll::Pending @@ -1067,10 +1094,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { 512, 9, ); - InterruptHandler::::data_interrupts(true); + InterruptHandler::::enable_interrupts(); Self::cmd(common_cmd::read_single_block(address), true)?; - let res = Self::complete_datapath_transfer().await; + let res = Self::complete_datapath_transfer(true).await; if res.is_ok() { on_drop.defuse(); @@ -1100,7 +1127,6 @@ impl<'d, T: Instance> Sdmmc<'d, T> { }; Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16 - let regs = T::regs(); let on_drop = OnDrop::new(|| Self::on_drop()); let transfer = Self::prepare_datapath_read( @@ -1111,30 +1137,11 @@ impl<'d, T: Instance> Sdmmc<'d, T> { 512 * blocks.len() as u32, 9, ); - InterruptHandler::::data_interrupts(true); + InterruptHandler::::enable_interrupts(); Self::cmd(common_cmd::read_multiple_blocks(address), true)?; - let res = poll_fn(|cx| { - T::state().register(cx.waker()); - let status = regs.star().read(); - - if status.dcrcfail() { - return Poll::Ready(Err(Error::Crc)); - } - if status.dtimeout() { - return Poll::Ready(Err(Error::Timeout)); - } - #[cfg(sdmmc_v1)] - if status.stbiterr() { - return Poll::Ready(Err(Error::StBitErr)); - } - if status.dataend() { - return Poll::Ready(Ok(())); - } - Poll::Pending - }) - .await; + let res = Self::complete_datapath_transfer(false).await; Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12 Self::clear_interrupt_flags(); @@ -1169,12 +1176,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> { Self::cmd(common_cmd::write_single_block(address), true)?; let transfer = self.prepare_datapath_write(buffer, 512, 9); - InterruptHandler::::data_interrupts(true); + InterruptHandler::::enable_interrupts(); #[cfg(sdmmc_v2)] Self::cmd(common_cmd::write_single_block(address), true)?; - let res = Self::complete_datapath_transfer().await; + let res = Self::complete_datapath_transfer(true).await; match res { Ok(_) => { @@ -1225,7 +1232,6 @@ impl<'d, T: Instance> Sdmmc<'d, T> { let block_count = blocks.len(); - let regs = T::regs(); let on_drop = OnDrop::new(|| Self::on_drop()); #[cfg(sdmmc_v1)] @@ -1233,36 +1239,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> { // Setup write command let transfer = self.prepare_datapath_write(buffer, 512 * block_count as u32, 9); - InterruptHandler::::data_interrupts(true); + InterruptHandler::::enable_interrupts(); #[cfg(sdmmc_v2)] Self::cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25 - let res = poll_fn(|cx| { - T::state().register(cx.waker()); - - let status = regs.star().read(); - - if status.dcrcfail() { - return Poll::Ready(Err(Error::Crc)); - } - if status.dtimeout() { - return Poll::Ready(Err(Error::Timeout)); - } - if status.txunderr() { - return Poll::Ready(Err(Error::Underrun)); - } - #[cfg(sdmmc_v1)] - if status.stbiterr() { - return Poll::Ready(Err(Error::StBitErr)); - } - if status.dataend() { - return Poll::Ready(Ok(())); - } - - Poll::Pending - }) - .await; + let res = Self::complete_datapath_transfer(false).await; Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12 Self::clear_interrupt_flags(); @@ -1597,10 +1579,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { 64, 6, ); - InterruptHandler::::data_interrupts(true); + InterruptHandler::::enable_interrupts(); Self::cmd(sd_cmd::cmd6(set_function), true)?; // CMD6 - let res = Self::complete_datapath_transfer().await; + let res = Self::complete_datapath_transfer(true).await; // Host is allowed to use the new functions at least 8 // clocks after the end of the switch command @@ -1657,10 +1639,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { 8, 3, ); - InterruptHandler::::data_interrupts(true); + InterruptHandler::::enable_interrupts(); Self::cmd(sd_cmd::send_scr(), true)?; - let res = Self::complete_datapath_transfer().await; + let res = Self::complete_datapath_transfer(true).await; if res.is_ok() { on_drop.defuse(); @@ -1703,10 +1685,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { 64, 6, ); - InterruptHandler::::data_interrupts(true); + InterruptHandler::::enable_interrupts(); Self::cmd(sd_cmd::sd_status(), true)?; - let res = Self::complete_datapath_transfer().await; + let res = Self::complete_datapath_transfer(true).await; if res.is_ok() { on_drop.defuse(); @@ -1753,10 +1735,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { 512, 9, ); - InterruptHandler::::data_interrupts(true); + InterruptHandler::::enable_interrupts(); Self::cmd(emmc_cmd::send_ext_csd(), true)?; - let res = Self::complete_datapath_transfer().await; + let res = Self::complete_datapath_transfer(true).await; if res.is_ok() { on_drop.defuse(); -- cgit From a29267752a382ff52b052233586ef9007fe84fed Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 4 Jul 2025 00:26:41 +0200 Subject: stm32/sdmmc: disable 1bit test. --- tests/stm32/src/bin/sdmmc.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/stm32/src/bin/sdmmc.rs b/tests/stm32/src/bin/sdmmc.rs index 34a53a725..9f9c526e1 100644 --- a/tests/stm32/src/bin/sdmmc.rs +++ b/tests/stm32/src/bin/sdmmc.rs @@ -95,6 +95,9 @@ async fn main(_spawner: Spawner) { drop(s); + // FIXME: this hangs on Rust 1.86 and higher. + // I haven't been able to figure out why. + /* // ======== Try 1bit. ============== info!("initializing in 1-bit mode..."); let mut s = Sdmmc::new_1bit( @@ -151,6 +154,7 @@ async fn main(_spawner: Spawner) { assert_eq!(&blocks, &patterns); drop(s); + */ info!("Test OK"); cortex_m::asm::bkpt(); -- cgit From fb21fcf4f1d2acfa15cf4da03fff190c0bb9df59 Mon Sep 17 00:00:00 2001 From: Cristian Milatinov Date: Sat, 5 Jul 2025 00:47:30 -0400 Subject: Added sample shifting to qspi config for stm32 --- embassy-stm32/src/qspi/enums.rs | 16 ++++++++++++++++ embassy-stm32/src/qspi/mod.rs | 5 ++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/qspi/enums.rs b/embassy-stm32/src/qspi/enums.rs index 9ec4c1b43..3905fcbf8 100644 --- a/embassy-stm32/src/qspi/enums.rs +++ b/embassy-stm32/src/qspi/enums.rs @@ -331,3 +331,19 @@ impl From for u8 { } } } + +#[allow(missing_docs)] +#[derive(Copy, Clone)] +pub enum SampleShifting { + None, + HalfCycle +} + +impl From for bool { + fn from(value: SampleShifting) -> Self { + match value { + SampleShifting::None => false, + SampleShifting::HalfCycle => true + } + } +} \ No newline at end of file diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index 0df057c53..52b1f3084 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -58,6 +58,8 @@ pub struct Config { pub fifo_threshold: FIFOThresholdLevel, /// Minimum number of cycles that chip select must be high between issued commands pub cs_high_time: ChipSelectHighTime, + /// Shift sampling point of input data (none, or half-cycle) + pub sample_shifting: SampleShifting, } impl Default for Config { @@ -68,6 +70,7 @@ impl Default for Config { prescaler: 128, fifo_threshold: FIFOThresholdLevel::_17Bytes, cs_high_time: ChipSelectHighTime::_5Cycle, + sample_shifting: SampleShifting::None } } } @@ -120,7 +123,7 @@ impl<'d, T: Instance, M: PeriMode> Qspi<'d, T, M> { T::REGS.cr().modify(|w| { w.set_en(true); //w.set_tcen(false); - w.set_sshift(false); + w.set_sshift(config.sample_shifting.into()); w.set_fthres(config.fifo_threshold.into()); w.set_prescaler(config.prescaler); w.set_fsel(fsel.into()); -- cgit From 1f87e4783110cb752f364657ae7c2759d6a2ac27 Mon Sep 17 00:00:00 2001 From: Cristian Milatinov Date: Sat, 5 Jul 2025 01:15:15 -0400 Subject: Run cargo fmt --- embassy-stm32/src/qspi/enums.rs | 6 +++--- embassy-stm32/src/qspi/mod.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/qspi/enums.rs b/embassy-stm32/src/qspi/enums.rs index 3905fcbf8..fa5e36d06 100644 --- a/embassy-stm32/src/qspi/enums.rs +++ b/embassy-stm32/src/qspi/enums.rs @@ -336,14 +336,14 @@ impl From for u8 { #[derive(Copy, Clone)] pub enum SampleShifting { None, - HalfCycle + HalfCycle, } impl From for bool { fn from(value: SampleShifting) -> Self { match value { SampleShifting::None => false, - SampleShifting::HalfCycle => true + SampleShifting::HalfCycle => true, } } -} \ No newline at end of file +} diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index 52b1f3084..1e20d7cd3 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -70,7 +70,7 @@ impl Default for Config { prescaler: 128, fifo_threshold: FIFOThresholdLevel::_17Bytes, cs_high_time: ChipSelectHighTime::_5Cycle, - sample_shifting: SampleShifting::None + sample_shifting: SampleShifting::None, } } } -- cgit From 9134fb2dd4f8430b1630cff98a93f030dae3ebeb Mon Sep 17 00:00:00 2001 From: Cristian Milatinov Date: Sat, 5 Jul 2025 01:32:21 -0400 Subject: Update examples to add SampleShifting in qspi config --- examples/stm32f7/src/bin/qspi.rs | 1 + examples/stm32h742/src/bin/qspi.rs | 1 + examples/stm32l432/src/bin/qspi_mmap.rs | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/stm32f7/src/bin/qspi.rs b/examples/stm32f7/src/bin/qspi.rs index bd3287964..ab29ddeff 100644 --- a/examples/stm32f7/src/bin/qspi.rs +++ b/examples/stm32f7/src/bin/qspi.rs @@ -279,6 +279,7 @@ async fn main(_spawner: Spawner) -> ! { prescaler: 16, cs_high_time: ChipSelectHighTime::_1Cycle, fifo_threshold: FIFOThresholdLevel::_16Bytes, + sample_shifting: SampleShifting::None, }; let driver = Qspi::new_bank1( p.QUADSPI, p.PF8, p.PF9, p.PE2, p.PF6, p.PF10, p.PB10, p.DMA2_CH7, config, diff --git a/examples/stm32h742/src/bin/qspi.rs b/examples/stm32h742/src/bin/qspi.rs index aee07f3f2..50e37ec52 100644 --- a/examples/stm32h742/src/bin/qspi.rs +++ b/examples/stm32h742/src/bin/qspi.rs @@ -272,6 +272,7 @@ async fn main(_spawner: Spawner) -> ! { prescaler: 16, cs_high_time: ChipSelectHighTime::_1Cycle, fifo_threshold: FIFOThresholdLevel::_16Bytes, + sample_shifting: SampleShifting::None, }; let driver = Qspi::new_blocking_bank1(p.QUADSPI, p.PD11, p.PD12, p.PE2, p.PD13, p.PB2, p.PB10, config); let mut flash = FlashMemory::new(driver); diff --git a/examples/stm32l432/src/bin/qspi_mmap.rs b/examples/stm32l432/src/bin/qspi_mmap.rs index 86a20eb3d..414621475 100644 --- a/examples/stm32l432/src/bin/qspi_mmap.rs +++ b/examples/stm32l432/src/bin/qspi_mmap.rs @@ -7,7 +7,8 @@ use defmt::info; use embassy_stm32::mode; use embassy_stm32::qspi::enums::{ - AddressSize, ChipSelectHighTime, DummyCycles, FIFOThresholdLevel, MemorySize, QspiWidth, + AddressSize, ChipSelectHighTime, DummyCycles, FIFOThresholdLevel, MemorySize, QspiWidth, + SampleShifting }; use embassy_stm32::qspi::{self, Instance, TransferConfig}; pub struct FlashMemory { @@ -252,6 +253,7 @@ async fn main(_spawner: Spawner) { prescaler: 200, cs_high_time: ChipSelectHighTime::_1Cycle, fifo_threshold: FIFOThresholdLevel::_16Bytes, + sample_shifting: SampleShifting::None, }; let driver = qspi::Qspi::new_bank1(p.QUADSPI, p.PB1, p.PB0, p.PA7, p.PA6, p.PA3, p.PA2, p.DMA2_CH7, config); let mut flash = FlashMemory::new(driver); -- cgit From bd5b1580dfb07e0bcd5ec1d0e5f8cc8b958d72ba Mon Sep 17 00:00:00 2001 From: Cristian Milatinov Date: Sat, 5 Jul 2025 01:34:10 -0400 Subject: Run cargo fmt --- examples/stm32l432/src/bin/qspi_mmap.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/stm32l432/src/bin/qspi_mmap.rs b/examples/stm32l432/src/bin/qspi_mmap.rs index 414621475..075458fe5 100644 --- a/examples/stm32l432/src/bin/qspi_mmap.rs +++ b/examples/stm32l432/src/bin/qspi_mmap.rs @@ -7,8 +7,7 @@ use defmt::info; use embassy_stm32::mode; use embassy_stm32::qspi::enums::{ - AddressSize, ChipSelectHighTime, DummyCycles, FIFOThresholdLevel, MemorySize, QspiWidth, - SampleShifting + AddressSize, ChipSelectHighTime, DummyCycles, FIFOThresholdLevel, MemorySize, QspiWidth, SampleShifting, }; use embassy_stm32::qspi::{self, Instance, TransferConfig}; pub struct FlashMemory { -- cgit From bfbecdf93acd6f05f9d02477729defbd84a9bdeb Mon Sep 17 00:00:00 2001 From: Thomas Giesel Date: Sun, 29 Jun 2025 21:28:26 +0200 Subject: Use proper RCC clock enable for opamps new() now resets the opamp and enables its clock. The clock is disabled when the opamp is dropped. On families that use SYSCFGEN (F3 and G4), this is not done because this clock is always on in Embassy. This change makes use of the RCC driver, which uses a reference counter to prevent conflicts. The opamp itself is still disabled when its output is dropped. --- embassy-stm32/src/opamp.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs index 0467dbce3..e36719ef3 100644 --- a/embassy-stm32/src/opamp.rs +++ b/embassy-stm32/src/opamp.rs @@ -4,6 +4,8 @@ use embassy_hal_internal::PeripheralType; use crate::pac::opamp::vals::*; +#[cfg(not(any(stm32g4, stm32f3)))] +use crate::rcc::RccInfo; use crate::Peri; /// Performs a busy-wait delay for a specified number of microseconds. @@ -68,6 +70,8 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// /// Does not enable the opamp, but does set the speed mode on some families. pub fn new(opamp: Peri<'d, T>, #[cfg(opamp_v5)] speed: OpAmpSpeed) -> Self { + #[cfg(not(any(stm32g4, stm32f3)))] + T::info().rcc.enable_and_reset(); #[cfg(opamp_v5)] T::regs().csr().modify(|w| { w.set_opahsm(speed == OpAmpSpeed::HighSpeed); @@ -452,6 +456,13 @@ impl<'d, T: Instance> OpAmp<'d, T> { } } +#[cfg(not(any(stm32g4, stm32f3)))] +impl<'d, T: Instance> Drop for OpAmp<'d, T> { + fn drop(&mut self) { + T::info().rcc.disable(); + } +} + impl<'d, T: Instance> Drop for OpAmpOutput<'d, T> { fn drop(&mut self) { T::regs().csr().modify(|w| { @@ -469,7 +480,14 @@ impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> { } } +#[cfg(not(any(stm32g4, stm32f3)))] +pub(crate) struct Info { + rcc: RccInfo, +} + pub(crate) trait SealedInstance { + #[cfg(not(any(stm32g4, stm32f3)))] + fn info() -> &'static Info; fn regs() -> crate::pac::opamp::Opamp; } @@ -600,6 +618,15 @@ foreach_peripheral!( foreach_peripheral! { (opamp, $inst:ident) => { impl SealedInstance for crate::peripherals::$inst { + // G4 and F3 use SYSCFGEN, which is always enabled + #[cfg(not(any(stm32g4, stm32f3)))] + fn info() -> &'static Info { + use crate::rcc::SealedRccPeripheral; + static INFO: Info = Info { + rcc: crate::peripherals::$inst::RCC_INFO, + }; + &INFO + } fn regs() -> crate::pac::opamp::Opamp { crate::pac::$inst } -- cgit From b861dd172829c5b34e95644287544e090dd9f568 Mon Sep 17 00:00:00 2001 From: Florian Grandel Date: Sat, 5 Jul 2025 18:27:46 +0200 Subject: embassy-executor: rtos-trace: fix task naming for new tasks Tasks that are spawned after starting SystemViewer were not named. This change ensures that tasks spawned while SystemViewer is running will be properly named, too. Signed-off-by: Florian Grandel --- embassy-executor/src/raw/trace.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index 6c9cfda25..aa27ab37e 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -283,7 +283,17 @@ pub(crate) fn task_new(executor: &SyncExecutor, task: &TaskRef) { } #[cfg(feature = "rtos-trace")] - rtos_trace::trace::task_new(task.as_ptr() as u32); + { + rtos_trace::trace::task_new(task.as_ptr() as u32); + let name = task.name().unwrap_or("unnamed task\0"); + let info = rtos_trace::TaskInfo { + name, + priority: 0, + stack_base: 0, + stack_size: 0, + }; + rtos_trace::trace::task_send_info(task.id(), info); + } #[cfg(feature = "rtos-trace")] TASK_TRACKER.add(*task); -- cgit From e57dffafa5723931dd529afe8e22cba0c9ea09f0 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Mon, 23 Jun 2025 23:15:09 -0500 Subject: mspm0: add dma driver --- embassy-mspm0/Cargo.toml | 4 +- embassy-mspm0/build.rs | 21 +- embassy-mspm0/src/dma.rs | 626 +++++++++++++++++++++++++++++++++ embassy-mspm0/src/gpio.rs | 18 +- embassy-mspm0/src/lib.rs | 115 +++++- examples/mspm0g3507/.cargo/config.toml | 2 +- tests/mspm0/Cargo.toml | 1 + tests/mspm0/build.rs | 3 + tests/mspm0/memory_g3519.x | 6 + tests/mspm0/src/bin/dma.rs | 503 ++++++++++++++++++++++++++ tests/mspm0/src/bin/uart.rs | 5 +- 11 files changed, 1279 insertions(+), 25 deletions(-) create mode 100644 embassy-mspm0/src/dma.rs create mode 100644 tests/mspm0/memory_g3519.x create mode 100644 tests/mspm0/src/bin/dma.rs diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index 6f767a3c0..550b037c1 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -46,14 +46,14 @@ cortex-m = "0.7.6" critical-section = "1.2.0" # mspm0-metapac = { version = "" } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-26a6f681eda4ef120e8cb614a1631727c848590f" } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-235158ac2865d8aac3a1eceb2d62026eb12bf38f" } [build-dependencies] proc-macro2 = "1.0.94" quote = "1.0.40" # mspm0-metapac = { version = "", default-features = false, features = ["metadata"] } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-26a6f681eda4ef120e8cb614a1631727c848590f", default-features = false, features = ["metadata"] } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-235158ac2865d8aac3a1eceb2d62026eb12bf38f", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs index 6cd62895b..b9ba3aecf 100644 --- a/embassy-mspm0/build.rs +++ b/embassy-mspm0/build.rs @@ -67,6 +67,7 @@ fn generate_code() { g.extend(generate_peripheral_instances()); g.extend(generate_pin_trait_impls()); g.extend(generate_groups()); + g.extend(generate_dma_channel_count()); let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); let out_file = out_dir.join("_generated.rs").to_string_lossy().to_string(); @@ -209,6 +210,12 @@ fn generate_groups() -> TokenStream { } } +fn generate_dma_channel_count() -> TokenStream { + let count = METADATA.dma_channels.len(); + + quote! { pub const DMA_CHANNELS: usize = #count; } +} + #[derive(Debug, Clone)] struct Singleton { name: String, @@ -543,8 +550,6 @@ fn generate_peripheral_instances() -> TokenStream { for peripheral in METADATA.peripherals { let peri = format_ident!("{}", peripheral.name); - // Will be filled in when uart implementation is finished - let _ = peri; let tokens = match peripheral.kind { "uart" => Some(quote! { impl_uart_instance!(#peri); }), _ => None, @@ -555,6 +560,18 @@ fn generate_peripheral_instances() -> TokenStream { } } + // DMA channels + for dma_channel in METADATA.dma_channels.iter() { + let peri = format_ident!("DMA_CH{}", dma_channel.number); + let num = dma_channel.number; + + if dma_channel.full { + impls.push(quote! { impl_full_dma_channel!(#peri, #num); }); + } else { + impls.push(quote! { impl_dma_channel!(#peri, #num); }); + } + } + quote! { #(#impls)* } diff --git a/embassy-mspm0/src/dma.rs b/embassy-mspm0/src/dma.rs new file mode 100644 index 000000000..66b79709c --- /dev/null +++ b/embassy-mspm0/src/dma.rs @@ -0,0 +1,626 @@ +//! Direct Memory Access (DMA) + +#![macro_use] + +use core::future::Future; +use core::mem; +use core::pin::Pin; +use core::sync::atomic::{compiler_fence, Ordering}; +use core::task::{Context, Poll}; + +use critical_section::CriticalSection; +use embassy_hal_internal::interrupt::InterruptExt; +use embassy_hal_internal::{impl_peripheral, PeripheralType}; +use embassy_sync::waitqueue::AtomicWaker; +use mspm0_metapac::common::{Reg, RW}; +use mspm0_metapac::dma::regs; +use mspm0_metapac::dma::vals::{self, Autoen, Em, Incr, Preirq, Wdth}; + +use crate::{interrupt, pac, Peri}; + +/// The burst size of a DMA transfer. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum BurstSize { + /// The whole block transfer is completed in one transfer without interruption. + Complete, + + /// The burst size is 8, after 9 transfers the block transfer is interrupted and the priority + /// is reevaluated. + _8, + + /// The burst size is 16, after 17 transfers the block transfer is interrupted and the priority + /// is reevaluated. + _16, + + /// The burst size is 32, after 32 transfers the block transfer is interrupted and the priority + /// is reevaluated. + _32, +} + +/// DMA channel. +#[allow(private_bounds)] +pub trait Channel: Into + PeripheralType {} + +/// Full DMA channel. +#[allow(private_bounds)] +pub trait FullChannel: Channel + Into {} + +/// Type-erased DMA channel. +pub struct AnyChannel { + pub(crate) id: u8, +} +impl_peripheral!(AnyChannel); + +impl SealedChannel for AnyChannel { + fn id(&self) -> u8 { + self.id + } +} +impl Channel for AnyChannel {} + +/// Type-erased full DMA channel. +pub struct AnyFullChannel { + pub(crate) id: u8, +} +impl_peripheral!(AnyFullChannel); + +impl SealedChannel for AnyFullChannel { + fn id(&self) -> u8 { + self.id + } +} +impl Channel for AnyFullChannel {} +impl FullChannel for AnyFullChannel {} + +impl From for AnyChannel { + fn from(value: AnyFullChannel) -> Self { + Self { id: value.id } + } +} + +#[allow(private_bounds)] +pub trait Word: SealedWord { + /// Size in bytes for the width. + fn size() -> isize; +} + +impl SealedWord for u8 { + fn width() -> vals::Wdth { + vals::Wdth::BYTE + } +} +impl Word for u8 { + fn size() -> isize { + 1 + } +} + +impl SealedWord for u16 { + fn width() -> vals::Wdth { + vals::Wdth::HALF + } +} +impl Word for u16 { + fn size() -> isize { + 2 + } +} + +impl SealedWord for u32 { + fn width() -> vals::Wdth { + vals::Wdth::WORD + } +} +impl Word for u32 { + fn size() -> isize { + 4 + } +} + +impl SealedWord for u64 { + fn width() -> vals::Wdth { + vals::Wdth::LONG + } +} +impl Word for u64 { + fn size() -> isize { + 8 + } +} + +// TODO: u128 (LONGLONG) support. G350x does support it, but other parts do not such as C110x. More metadata is +// needed to properly enable this. +// impl SealedWord for u128 { +// fn width() -> vals::Wdth { +// vals::Wdth::LONGLONG +// } +// } +// impl Word for u128 { +// fn size() -> isize { +// 16 +// } +// } + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Error { + /// The DMA transfer is too large. + /// + /// The hardware limits the DMA to 16384 transfers per channel at a time. This means that transferring + /// 16384 `u8` and 16384 `u64` are equivalent, since the DMA must copy 16384 values. + TooManyTransfers, +} + +/// DMA transfer mode for basic channels. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum TransferMode { + /// Each DMA trigger will transfer a single value. + Single, + + /// Each DMA trigger will transfer the complete block with one trigger. + Block, +} + +/// DMA transfer options. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub struct TransferOptions { + /// DMA transfer mode. + pub mode: TransferMode, + // TODO: Read and write stride. +} + +impl Default for TransferOptions { + fn default() -> Self { + Self { + mode: TransferMode::Single, + } + } +} + +/// DMA transfer. +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Transfer<'a> { + channel: Peri<'a, AnyChannel>, +} + +impl<'a> Transfer<'a> { + /// Software trigger source. + /// + /// Using this trigger source means that a transfer will start immediately rather than waiting for + /// a hardware event. This can be useful if you want to do a DMA accelerated memcpy. + pub const SOFTWARE_TRIGGER: u8 = 0; + + /// Create a new read DMA transfer. + pub unsafe fn new_read( + channel: Peri<'a, impl Channel>, + trigger_source: u8, + src: *mut SW, + dst: &'a mut [DW], + options: TransferOptions, + ) -> Result { + Self::new_read_raw(channel, trigger_source, src, dst, options) + } + + /// Create a new read DMA transfer, using raw pointers. + pub unsafe fn new_read_raw( + channel: Peri<'a, impl Channel>, + trigger_source: u8, + src: *mut SW, + dst: *mut [DW], + options: TransferOptions, + ) -> Result { + verify_transfer::(dst)?; + + let channel = channel.into(); + channel.configure( + trigger_source, + src.cast(), + SW::width(), + dst.cast(), + DW::width(), + dst.len() as u16, + false, + true, + options, + ); + channel.start(); + + Ok(Self { channel }) + } + + /// Create a new write DMA transfer. + pub unsafe fn new_write( + channel: Peri<'a, impl Channel>, + trigger_source: u8, + src: &'a [SW], + dst: *mut DW, + options: TransferOptions, + ) -> Result { + Self::new_write_raw(channel, trigger_source, src, dst, options) + } + + /// Create a new write DMA transfer, using raw pointers. + pub unsafe fn new_write_raw( + channel: Peri<'a, impl Channel>, + trigger_source: u8, + src: *const [SW], + dst: *mut DW, + options: TransferOptions, + ) -> Result { + verify_transfer::(src)?; + + let channel = channel.into(); + channel.configure( + trigger_source, + src.cast(), + SW::width(), + dst.cast(), + DW::width(), + src.len() as u16, + true, + false, + options, + ); + channel.start(); + + Ok(Self { channel }) + } + + // TODO: Copy between slices. + + /// Request the transfer to resume. + pub fn resume(&mut self) { + self.channel.resume(); + } + + /// Request the transfer to pause, keeping the existing configuration for this channel. + /// To restart the transfer, call [`start`](Self::start) again. + /// + /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. + pub fn request_pause(&mut self) { + self.channel.request_pause(); + } + + /// Return whether this transfer is still running. + /// + /// If this returns [`false`], it can be because either the transfer finished, or + /// it was requested to stop early with [`request_stop`]. + pub fn is_running(&mut self) -> bool { + self.channel.is_running() + } + + /// Blocking wait until the transfer finishes. + pub fn blocking_wait(mut self) { + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + compiler_fence(Ordering::SeqCst); + + while self.is_running() {} + + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + compiler_fence(Ordering::SeqCst); + + // Prevent drop from being called since we ran to completion (drop will try to pause). + mem::forget(self); + } +} + +impl<'a> Unpin for Transfer<'a> {} +impl<'a> Future for Transfer<'a> { + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let state: &ChannelState = &STATE[self.channel.id as usize]; + + state.waker.register(cx.waker()); + + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + compiler_fence(Ordering::SeqCst); + + if self.channel.is_running() { + Poll::Pending + } else { + Poll::Ready(()) + } + } +} + +impl<'a> Drop for Transfer<'a> { + fn drop(&mut self) { + self.channel.request_pause(); + while self.is_running() {} + + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + compiler_fence(Ordering::SeqCst); + } +} + +// impl details + +fn verify_transfer(ptr: *const [W]) -> Result<(), Error> { + if ptr.len() > (u16::MAX as usize) { + return Err(Error::TooManyTransfers); + } + + // TODO: Stride checks + + Ok(()) +} + +fn convert_burst_size(value: BurstSize) -> vals::Burstsz { + match value { + BurstSize::Complete => vals::Burstsz::INFINITI, + BurstSize::_8 => vals::Burstsz::BURST_8, + BurstSize::_16 => vals::Burstsz::BURST_16, + BurstSize::_32 => vals::Burstsz::BURST_32, + } +} + +fn convert_mode(mode: TransferMode) -> vals::Tm { + match mode { + TransferMode::Single => vals::Tm::SINGLE, + TransferMode::Block => vals::Tm::BLOCK, + } +} + +const CHANNEL_COUNT: usize = crate::_generated::DMA_CHANNELS; +static STATE: [ChannelState; CHANNEL_COUNT] = [const { ChannelState::new() }; CHANNEL_COUNT]; + +struct ChannelState { + waker: AtomicWaker, +} + +impl ChannelState { + const fn new() -> Self { + Self { + waker: AtomicWaker::new(), + } + } +} + +/// SAFETY: Must only be called once. +/// +/// Changing the burst size mid transfer may have some odd behavior. +pub(crate) unsafe fn init(_cs: CriticalSection, burst_size: BurstSize, round_robin: bool) { + pac::DMA.prio().modify(|prio| { + prio.set_burstsz(convert_burst_size(burst_size)); + prio.set_roundrobin(round_robin); + }); + pac::DMA.int_event(0).imask().modify(|w| { + w.set_dataerr(true); + w.set_addrerr(true); + }); + + interrupt::DMA.enable(); +} + +pub(crate) trait SealedWord { + fn width() -> vals::Wdth; +} + +pub(crate) trait SealedChannel { + fn id(&self) -> u8; + + #[inline] + fn tctl(&self) -> Reg { + pac::DMA.trig(self.id() as usize).tctl() + } + + #[inline] + fn ctl(&self) -> Reg { + pac::DMA.chan(self.id() as usize).ctl() + } + + #[inline] + fn sa(&self) -> Reg { + pac::DMA.chan(self.id() as usize).sa() + } + + #[inline] + fn da(&self) -> Reg { + pac::DMA.chan(self.id() as usize).da() + } + + #[inline] + fn sz(&self) -> Reg { + pac::DMA.chan(self.id() as usize).sz() + } + + #[inline] + fn mask_interrupt(&self, enable: bool) { + // Enabling interrupts is an RMW operation. + critical_section::with(|_cs| { + pac::DMA.int_event(0).imask().modify(|w| { + w.set_ch(self.id() as usize, enable); + }); + }) + } + + /// # Safety + /// + /// - `src` must be valid for the lifetime of the transfer. + /// - `dst` must be valid for the lifetime of the transfer. + unsafe fn configure( + &self, + trigger_sel: u8, + src: *const u32, + src_wdth: Wdth, + dst: *const u32, + dst_wdth: Wdth, + transfer_count: u16, + increment_src: bool, + increment_dst: bool, + options: TransferOptions, + ) { + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + compiler_fence(Ordering::SeqCst); + + self.ctl().modify(|w| { + // SLAU 5.2.5: + // "The DMATSEL bits should be modified only when the DMACTLx.DMAEN bit is + // 0; otherwise, unpredictable DMA triggers can occur." + // + // We also want to stop any transfers before setup. + w.set_en(false); + w.set_req(false); + + // Not every part supports auto enable, so force its value to 0. + w.set_autoen(Autoen::NONE); + w.set_preirq(Preirq::PREIRQ_DISABLE); + w.set_srcwdth(src_wdth); + w.set_dstwdth(dst_wdth); + w.set_srcincr(if increment_src { + Incr::INCREMENT + } else { + Incr::UNCHANGED + }); + w.set_dstincr(if increment_dst { + Incr::INCREMENT + } else { + Incr::UNCHANGED + }); + + w.set_em(Em::NORMAL); + // Single and block will clear the enable bit when the transfers finish. + w.set_tm(convert_mode(options.mode)); + }); + + self.tctl().write(|w| { + w.set_tsel(trigger_sel); + // Basic channels do not implement cross triggering. + w.set_tint(vals::Tint::EXTERNAL); + }); + + self.sz().write(|w| { + w.set_size(transfer_count); + }); + + self.sa().write_value(src as u32); + self.da().write_value(dst as u32); + + // Enable the channel. + self.ctl().modify(|w| { + // FIXME: Why did putting set_req later fix some transfers + w.set_en(true); + w.set_req(true); + }); + } + + fn start(&self) { + self.mask_interrupt(true); + + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + compiler_fence(Ordering::SeqCst); + + // Request the DMA transfer to start. + self.ctl().modify(|w| { + w.set_req(true); + }); + } + + fn resume(&self) { + self.mask_interrupt(true); + + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + compiler_fence(Ordering::SeqCst); + + self.ctl().modify(|w| { + // w.set_en(true); + w.set_req(true); + }); + } + + fn request_pause(&self) { + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + compiler_fence(Ordering::SeqCst); + + // Stop the transfer. + // + // SLAU846 5.2.6: + // "A DMA block transfer in progress can be stopped by clearing the DMAEN bit" + self.ctl().modify(|w| { + // w.set_en(false); + w.set_req(false); + }); + } + + fn is_running(&self) -> bool { + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + compiler_fence(Ordering::SeqCst); + + let ctl = self.ctl().read(); + + // Is the transfer requested? + ctl.req() + // Is the channel enabled? + && ctl.en() + } +} + +macro_rules! impl_dma_channel { + ($instance: ident, $num: expr) => { + impl crate::dma::SealedChannel for crate::peripherals::$instance { + fn id(&self) -> u8 { + $num + } + } + + impl From for crate::dma::AnyChannel { + fn from(value: crate::peripherals::$instance) -> Self { + use crate::dma::SealedChannel; + + Self { id: value.id() } + } + } + + impl crate::dma::Channel for crate::peripherals::$instance {} + }; +} + +// C1104 has no full DMA channels. +#[allow(unused_macros)] +macro_rules! impl_full_dma_channel { + ($instance: ident, $num: expr) => { + impl_dma_channel!($instance, $num); + + impl From for crate::dma::AnyFullChannel { + fn from(value: crate::peripherals::$instance) -> Self { + use crate::dma::SealedChannel; + + Self { id: value.id() } + } + } + + impl crate::dma::FullChannel for crate::peripherals::$instance {} + }; +} + +#[cfg(feature = "rt")] +#[interrupt] +fn DMA() { + use crate::BitIter; + + let events = pac::DMA.int_event(0); + let mis = events.mis().read(); + + // TODO: Handle DATAERR and ADDRERR? However we do not know which channel causes an error. + if mis.dataerr() { + panic!("DMA data error"); + } else if mis.addrerr() { + panic!("DMA address error") + } + + // Ignore preirq interrupts (values greater than 16). + for i in BitIter(mis.0 & 0x0000_FFFF) { + if let Some(state) = STATE.get(i as usize) { + state.waker.wake(); + + // Notify the future that the counter size hit zero + events.imask().modify(|w| { + w.set_ch(i as usize, false); + }); + } + } +} diff --git a/embassy-mspm0/src/gpio.rs b/embassy-mspm0/src/gpio.rs index 738d51928..e6380e819 100644 --- a/embassy-mspm0/src/gpio.rs +++ b/embassy-mspm0/src/gpio.rs @@ -1090,7 +1090,9 @@ pub(crate) fn init(gpio: gpio::Gpio) { #[cfg(feature = "rt")] fn irq_handler(gpio: gpio::Gpio, wakers: &[AtomicWaker; 32]) { + use crate::BitIter; // Only consider pins which have interrupts unmasked. + let bits = gpio.cpu_int().mis().read().0; for i in BitIter(bits) { @@ -1103,22 +1105,6 @@ fn irq_handler(gpio: gpio::Gpio, wakers: &[AtomicWaker; 32]) { } } -struct BitIter(u32); - -impl Iterator for BitIter { - type Item = u32; - - fn next(&mut self) -> Option { - match self.0.trailing_zeros() { - 32 => None, - b => { - self.0 &= !(1 << b); - Some(b) - } - } - } -} - // C110x and L110x have a dedicated interrupts just for GPIOA. // // These chips do not have a GROUP1 interrupt. diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index 7ff60e946..bb8d91403 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -13,6 +13,7 @@ pub(crate) mod fmt; // This must be declared early as well for mod macros; +pub mod dma; pub mod gpio; pub mod timer; pub mod uart; @@ -59,22 +60,106 @@ pub(crate) use mspm0_metapac as pac; pub use crate::_generated::interrupt; +/// Macro to bind interrupts to handlers. +/// +/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) +/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to +/// prove at compile-time that the right interrupts have been bound. +/// +/// Example of how to bind one interrupt: +/// +/// ```rust,ignore +/// use embassy_nrf::{bind_interrupts, spim, peripherals}; +/// +/// bind_interrupts!( +/// /// Binds the SPIM3 interrupt. +/// struct Irqs { +/// SPIM3 => spim::InterruptHandler; +/// } +/// ); +/// ``` +/// +/// Example of how to bind multiple interrupts in a single macro invocation: +/// +/// ```rust,ignore +/// use embassy_nrf::{bind_interrupts, spim, twim, peripherals}; +/// +/// bind_interrupts!(struct Irqs { +/// SPIM3 => spim::InterruptHandler; +/// TWISPI0 => twim::InterruptHandler; +/// }); +/// ``` + +// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`. +#[macro_export] +macro_rules! bind_interrupts { + ($(#[$attr:meta])* $vis:vis struct $name:ident { + $( + $(#[cfg($cond_irq:meta)])? + $irq:ident => $( + $(#[cfg($cond_handler:meta)])? + $handler:ty + ),*; + )* + }) => { + #[derive(Copy, Clone)] + $(#[$attr])* + $vis struct $name; + + $( + #[allow(non_snake_case)] + #[no_mangle] + $(#[cfg($cond_irq)])? + unsafe extern "C" fn $irq() { + $( + $(#[cfg($cond_handler)])? + <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); + + )* + } + + $(#[cfg($cond_irq)])? + $crate::bind_interrupts!(@inner + $( + $(#[cfg($cond_handler)])? + unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {} + )* + ); + )* + }; + (@inner $($t:tt)*) => { + $($t)* + } +} + /// `embassy-mspm0` global configuration. #[non_exhaustive] #[derive(Clone, Copy)] pub struct Config { - // TODO + // TODO: OSC configuration. + /// The size of DMA block transfer burst. + /// + /// If this is set to a value + pub dma_burst_size: dma::BurstSize, + + /// Whether the DMA channels are used in a fixed priority or a round robin fashion. + /// + /// If [`false`], the DMA priorities are fixed. + /// + /// If [`true`], after a channel finishes a transfer it becomes the lowest priority. + pub dma_round_robin: bool, } impl Default for Config { fn default() -> Self { Self { - // TODO + dma_burst_size: dma::BurstSize::Complete, + dma_round_robin: false, } } } -pub fn init(_config: Config) -> Peripherals { +pub fn init(config: Config) -> Peripherals { critical_section::with(|cs| { let peripherals = Peripherals::take_with_cs(cs); @@ -112,9 +197,33 @@ pub fn init(_config: Config) -> Peripherals { crate::interrupt::typelevel::GPIOA::enable(); } + // SAFETY: Peripherals::take_with_cs will only be run once or panic. + unsafe { dma::init(cs, config.dma_burst_size, config.dma_round_robin) }; + #[cfg(feature = "_time-driver")] time_driver::init(cs); peripherals }) } + +pub(crate) mod sealed { + #[allow(dead_code)] + pub trait Sealed {} +} + +struct BitIter(u32); + +impl Iterator for BitIter { + type Item = u32; + + fn next(&mut self) -> Option { + match self.0.trailing_zeros() { + 32 => None, + b => { + self.0 &= !(1 << b); + Some(b) + } + } + } +} diff --git a/examples/mspm0g3507/.cargo/config.toml b/examples/mspm0g3507/.cargo/config.toml index 34c720cdd..e711afaf2 100644 --- a/examples/mspm0g3507/.cargo/config.toml +++ b/examples/mspm0g3507/.cargo/config.toml @@ -6,4 +6,4 @@ runner = "probe-rs run --chip MSPM0G3507 --protocol=swd" target = "thumbv6m-none-eabi" [env] -DEFMT_LOG = "debug" +DEFMT_LOG = "trace" diff --git a/tests/mspm0/Cargo.toml b/tests/mspm0/Cargo.toml index 386536bee..1c6f7d1cd 100644 --- a/tests/mspm0/Cargo.toml +++ b/tests/mspm0/Cargo.toml @@ -6,6 +6,7 @@ license = "MIT OR Apache-2.0" [features] mspm0g3507 = [ "embassy-mspm0/mspm0g3507pm" ] +mspm0g3519 = [ "embassy-mspm0/mspm0g3519pz" ] [dependencies] teleprobe-meta = "1.1" diff --git a/tests/mspm0/build.rs b/tests/mspm0/build.rs index 0b58fb9e9..43a9ac04f 100644 --- a/tests/mspm0/build.rs +++ b/tests/mspm0/build.rs @@ -8,6 +8,9 @@ fn main() -> Result<(), Box> { #[cfg(feature = "mspm0g3507")] let memory_x = include_bytes!("memory_g3507.x"); + #[cfg(feature = "mspm0g3519")] + let memory_x = include_bytes!("memory_g3519.x"); + fs::write(out.join("memory.x"), memory_x).unwrap(); println!("cargo:rustc-link-search={}", out.display()); diff --git a/tests/mspm0/memory_g3519.x b/tests/mspm0/memory_g3519.x new file mode 100644 index 000000000..d62f10360 --- /dev/null +++ b/tests/mspm0/memory_g3519.x @@ -0,0 +1,6 @@ +MEMORY +{ + FLASH : ORIGIN = 0x00000000, LENGTH = 128K + /* Select non-parity range of SRAM due to SRAM_ERR_01 errata in SLAZ758 */ + RAM : ORIGIN = 0x20200000, LENGTH = 64K +} diff --git a/tests/mspm0/src/bin/dma.rs b/tests/mspm0/src/bin/dma.rs new file mode 100644 index 000000000..6fd973a18 --- /dev/null +++ b/tests/mspm0/src/bin/dma.rs @@ -0,0 +1,503 @@ +#![no_std] +#![no_main] + +#[cfg(feature = "mspm0g3507")] +teleprobe_meta::target!(b"lp-mspm0g3507"); + +#[cfg(feature = "mspm0g3519")] +teleprobe_meta::target!(b"lp-mspm0g3519"); + +use core::slice; + +use defmt::{assert, assert_eq, *}; +use embassy_executor::Spawner; +use embassy_mspm0::dma::{Channel, Transfer, TransferMode, TransferOptions, Word}; +use embassy_mspm0::Peri; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut p = embassy_mspm0::init(Default::default()); + info!("Hello World!"); + + { + info!("Single u8 read (blocking)"); + single_read(p.DMA_CH0.reborrow(), 0x41_u8); + + info!("Single u16 read (blocking)"); + single_read(p.DMA_CH0.reborrow(), 0xFF41_u16); + + info!("Single u32 read (blocking)"); + single_read(p.DMA_CH0.reborrow(), 0xFFEE_FF41_u32); + + info!("Single u64 read (blocking)"); + single_read(p.DMA_CH0.reborrow(), 0x0011_2233_FFEE_FF41_u64); + } + + // Widening transfers + { + info!("Single u8 read to u16"); + widening_single_read::(p.DMA_CH0.reborrow(), 0x41); + + info!("Single u8 read to u32"); + widening_single_read::(p.DMA_CH0.reborrow(), 0x43); + + info!("Single u8 read to u64"); + widening_single_read::(p.DMA_CH0.reborrow(), 0x47); + + info!("Single u16 read to u32"); + widening_single_read::(p.DMA_CH0.reborrow(), 0xAE43); + + info!("Single u16 read to u64"); + widening_single_read::(p.DMA_CH0.reborrow(), 0xAF47); + + info!("Single u32 read to u64"); + widening_single_read::(p.DMA_CH0.reborrow(), 0xDEAD_AF47); + } + + // Narrowing transfers. + { + info!("Single u16 read to u8"); + narrowing_single_read::(p.DMA_CH0.reborrow(), 0x4142); + + info!("Single u32 read to u8"); + narrowing_single_read::(p.DMA_CH0.reborrow(), 0x4142_2414); + + info!("Single u64 read to u8"); + narrowing_single_read::(p.DMA_CH0.reborrow(), 0x4142_2414_5153_7776); + + info!("Single u32 read to u16"); + narrowing_single_read::(p.DMA_CH0.reborrow(), 0x4142_2414); + + info!("Single u64 read to u16"); + narrowing_single_read::(p.DMA_CH0.reborrow(), 0x4142_2414_5153_7776); + + info!("Single u64 read to u32"); + narrowing_single_read::(p.DMA_CH0.reborrow(), 0x4142_2414_5153_7776); + } + + { + info!("Single u8 read (async)"); + async_single_read(p.DMA_CH0.reborrow(), 0x42_u8).await; + + info!("Single u16 read (async)"); + async_single_read(p.DMA_CH0.reborrow(), 0xAE42_u16).await; + + info!("Single u32 read (async)"); + async_single_read(p.DMA_CH0.reborrow(), 0xFE44_1500_u32).await; + + info!("Single u64 read (async)"); + async_single_read(p.DMA_CH0.reborrow(), 0x8F7F_6F5F_4F3F_2F1F_u64).await; + } + + { + info!("Multiple u8 reads (blocking)"); + block_read::<_, 16>(p.DMA_CH0.reborrow(), 0x98_u8); + + info!("Multiple u16 reads (blocking)"); + block_read::<_, 2>(p.DMA_CH0.reborrow(), 0x9801_u16); + + info!("Multiple u32 reads (blocking)"); + block_read::<_, 4>(p.DMA_CH0.reborrow(), 0x9821_9801_u32); + + info!("Multiple u64 reads (blocking)"); + block_read::<_, 4>(p.DMA_CH0.reborrow(), 0xABCD_EF01_2345_6789_u64); + } + + { + info!("Multiple u8 reads (async)"); + async_block_read::<_, 8>(p.DMA_CH0.reborrow(), 0x86_u8).await; + + info!("Multiple u16 reads (async)"); + async_block_read::<_, 6>(p.DMA_CH0.reborrow(), 0x7777_u16).await; + + info!("Multiple u32 reads (async)"); + async_block_read::<_, 3>(p.DMA_CH0.reborrow(), 0xA5A5_A5A5_u32).await; + + info!("Multiple u64 reads (async)"); + async_block_read::<_, 14>(p.DMA_CH0.reborrow(), 0x5A5A_5A5A_A5A5_A5A5_u64).await; + } + + // Intentionally skip testing multiple reads in single transfer mode. + // + // If the destination length is greater than 1 and single transfer mode is used then two transfers + // are performed in a trigger. Similarly with any other length of destination above 2, only 2 transfers + // are performed. Issuing another trigger (resume) results in no further progress. More than likely + // the test does not work due to some combination of a hardware bug and the datasheet being unclear + // regarding what ends a software trigger. + // + // However this case works fine with a hardware trigger (such as the ADC hardware trigger). + + { + info!("Single u8 write (blocking)"); + single_write(p.DMA_CH0.reborrow(), 0x41_u8); + + info!("Single u16 write (blocking)"); + single_write(p.DMA_CH0.reborrow(), 0x4142_u16); + + info!("Single u32 write (blocking)"); + single_write(p.DMA_CH0.reborrow(), 0x4142_4344_u32); + + info!("Single u64 write (blocking)"); + single_write(p.DMA_CH0.reborrow(), 0x4142_4344_4546_4748_u64); + } + + { + info!("Single u8 write (async)"); + async_single_write(p.DMA_CH0.reborrow(), 0xAA_u8).await; + + info!("Single u16 write (async)"); + async_single_write(p.DMA_CH0.reborrow(), 0xBBBB_u16).await; + + info!("Single u32 write (async)"); + async_single_write(p.DMA_CH0.reborrow(), 0xCCCC_CCCC_u32).await; + + info!("Single u64 write (async)"); + async_single_write(p.DMA_CH0.reborrow(), 0xDDDD_DDDD_DDDD_DDDD_u64).await; + } + + { + info!("Multiple u8 writes (blocking)"); + block_write(p.DMA_CH0.reborrow(), &[0xFF_u8, 0x7F, 0x3F, 0x1F]); + + info!("Multiple u16 writes (blocking)"); + block_write(p.DMA_CH0.reborrow(), &[0xFFFF_u16, 0xFF7F, 0xFF3F, 0xFF1F]); + + info!("Multiple u32 writes (blocking)"); + block_write( + p.DMA_CH0.reborrow(), + &[0xFF00_00FF_u32, 0xFF00_007F, 0x0000_FF3F, 0xFF1F_0000], + ); + + info!("Multiple u64 writes (blocking)"); + block_write( + p.DMA_CH0.reborrow(), + &[ + 0xFF00_0000_0000_00FF_u64, + 0x0000_FF00_007F_0000, + 0x0000_FF3F_0000_0000, + 0xFF1F_0000_1111_837A, + ], + ); + } + + { + info!("Multiple u8 writes (async)"); + async_block_write(p.DMA_CH0.reborrow(), &[0u8, 1, 2, 3]).await; + + info!("Multiple u16 writes (async)"); + async_block_write(p.DMA_CH0.reborrow(), &[0x9801u16, 0x9802, 0x9803, 0x9800, 0x9000]).await; + + info!("Multiple u32 writes (async)"); + async_block_write(p.DMA_CH0.reborrow(), &[0x9801_ABCDu32, 0xFFAC_9802, 0xDEAD_9803]).await; + + info!("Multiple u64 writes (async)"); + async_block_write( + p.DMA_CH0.reborrow(), + &[ + 0xA55A_1111_3333_5555_u64, + 0x1111_A55A_3333_5555, + 0x5555_A55A_3333_1111, + 0x01234_5678_89AB_CDEF, + ], + ) + .await; + } + + // TODO: Mixed byte and word transfers. + + info!("Test OK"); + cortex_m::asm::bkpt(); +} + +fn single_read(mut channel: Peri<'_, impl Channel>, mut src: W) { + let options = TransferOptions::default(); + let mut dst = W::default(); + + // SAFETY: src and dst outlive the transfer. + let transfer = unsafe { + unwrap!(Transfer::new_read( + channel.reborrow(), + Transfer::SOFTWARE_TRIGGER, + &mut src, + slice::from_mut(&mut dst), + options, + )) + }; + transfer.blocking_wait(); + + assert_eq!(src, dst); +} + +async fn async_single_read( + mut channel: Peri<'_, impl Channel>, + mut src: W, +) { + let options = TransferOptions::default(); + let mut dst = W::default(); + + // SAFETY: src and dst outlive the transfer. + let transfer = unsafe { + unwrap!(Transfer::new_read( + channel.reborrow(), + Transfer::SOFTWARE_TRIGGER, + &mut src, + slice::from_mut(&mut dst), + options, + )) + }; + transfer.await; + + assert_eq!(src, dst); +} + +fn block_read( + mut channel: Peri<'_, impl Channel>, + mut src: W, +) { + let mut options = TransferOptions::default(); + // Complete the entire transfer. + options.mode = TransferMode::Block; + + let mut dst = [W::default(); N]; + + // SAFETY: src and dst outlive the transfer. + let transfer = unsafe { + unwrap!(Transfer::new_read( + channel.reborrow(), + Transfer::SOFTWARE_TRIGGER, + &mut src, + &mut dst[..], + options, + )) + }; + transfer.blocking_wait(); + + assert_eq!(dst, [src; N]); +} + +async fn async_block_read( + mut channel: Peri<'_, impl Channel>, + mut src: W, +) { + let mut options = TransferOptions::default(); + // Complete the entire transfer. + options.mode = TransferMode::Block; + + let mut dst = [W::default(); N]; + + // SAFETY: src and dst outlive the transfer. + let transfer = unsafe { + unwrap!(Transfer::new_read( + channel.reborrow(), + Transfer::SOFTWARE_TRIGGER, + &mut src, + &mut dst[..], + options, + )) + }; + transfer.await; + + assert_eq!(dst, [src; N]); +} + +fn single_write(mut channel: Peri<'_, impl Channel>, src: W) { + let options = TransferOptions::default(); + let mut dst = W::default(); + + // SAFETY: src and dst outlive the transfer. + let transfer = unsafe { + unwrap!(Transfer::new_write( + channel.reborrow(), + Transfer::SOFTWARE_TRIGGER, + slice::from_ref(&src), + &mut dst, + options, + )) + }; + transfer.blocking_wait(); + + assert_eq!(src, dst); +} + +async fn async_single_write(mut channel: Peri<'_, impl Channel>, src: W) { + let options = TransferOptions::default(); + let mut dst = W::default(); + + // SAFETY: src and dst outlive the transfer. + let transfer = unsafe { + unwrap!(Transfer::new_write( + channel.reborrow(), + Transfer::SOFTWARE_TRIGGER, + slice::from_ref(&src), + &mut dst, + options, + )) + }; + transfer.await; + + assert_eq!(src, dst); +} + +fn block_write(mut channel: Peri<'_, impl Channel>, src: &[W]) { + let mut options = TransferOptions::default(); + // Complete the entire transfer. + options.mode = TransferMode::Block; + + let mut dst = W::default(); + + // Starting from 1 because a zero length transfer does nothing. + for i in 1..src.len() { + info!("-> {} write(s)", i); + + // SAFETY: src and dst outlive the transfer. + let transfer = unsafe { + unwrap!(Transfer::new_write( + channel.reborrow(), + Transfer::SOFTWARE_TRIGGER, + &src[..i], + &mut dst, + options, + )) + }; + transfer.blocking_wait(); + + // The result will be the last value written. + assert_eq!(dst, src[i - 1]); + } +} + +async fn async_block_write(mut channel: Peri<'_, impl Channel>, src: &[W]) { + let mut options = TransferOptions::default(); + // Complete the entire transfer. + options.mode = TransferMode::Block; + + let mut dst = W::default(); + + // Starting from 1 because a zero length transfer does nothing. + for i in 1..src.len() { + info!("-> {} write(s)", i); + // SAFETY: src and dst outlive the transfer. + let transfer = unsafe { + unwrap!(Transfer::new_write( + channel.reborrow(), + Transfer::SOFTWARE_TRIGGER, + &src[..i], + &mut dst, + options, + )) + }; + transfer.await; + + // The result will be the last value written. + assert_eq!(dst, src[i - 1]); + } +} + +/// [`single_read`], but testing when the destination is wider than the source. +/// +/// The MSPM0 DMA states that the upper bytes when the destination is longer than the source are zeroed. +/// This matches the behavior in Rust for all unsigned integer types. +fn widening_single_read(mut channel: Peri<'_, impl Channel>, mut src: SW) +where + SW: Word + Copy + Default + Eq + defmt::Format, + DW: Word + Copy + Default + Eq + defmt::Format + From, +{ + assert!( + DW::size() > SW::size(), + "This test only works when the destination is larger than the source" + ); + + let options = TransferOptions::default(); + let mut dst = DW::default(); + + // SAFETY: src and dst outlive the transfer. + let transfer = unsafe { + unwrap!(Transfer::new_read( + channel.reborrow(), + Transfer::SOFTWARE_TRIGGER, + &mut src, + slice::from_mut(&mut dst), + options, + )) + }; + transfer.blocking_wait(); + + assert_eq!(DW::from(src), dst); +} + +/// [`single_read`], but testing when the destination is narrower than the source. +/// +/// The MSPM0 DMA states that the upper bytes when the source is longer than the destination are dropped. +/// This matches the behavior in Rust for all unsigned integer types. +fn narrowing_single_read(mut channel: Peri<'_, impl Channel>, mut src: SW) +where + SW: Word + Copy + Default + Eq + defmt::Format + From, + DW: Word + Copy + Default + Eq + defmt::Format + Narrow, +{ + assert!( + SW::size() > DW::size(), + "This test only works when the source is larger than the destination" + ); + + let options = TransferOptions::default(); + let mut dst = DW::default(); + + // SAFETY: src and dst outlive the transfer. + let transfer = unsafe { + unwrap!(Transfer::new_read( + channel.reborrow(), + Transfer::SOFTWARE_TRIGGER, + &mut src, + slice::from_mut(&mut dst), + options, + )) + }; + transfer.blocking_wait(); + + // The expected value is the source value masked by the maximum destination value. + // This is effectively `src as DW as SW` to drop the upper byte(s). + let expect = SW::from(DW::narrow(src)); + assert_eq!(expect, dst.into()); +} + +/// A pseudo `as` trait to allow downcasting integer types (TryFrom could fail). +trait Narrow { + fn narrow(value: T) -> Self; +} + +impl Narrow for u8 { + fn narrow(value: u16) -> Self { + value as u8 + } +} + +impl Narrow for u8 { + fn narrow(value: u32) -> Self { + value as u8 + } +} + +impl Narrow for u8 { + fn narrow(value: u64) -> Self { + value as u8 + } +} + +impl Narrow for u16 { + fn narrow(value: u32) -> Self { + value as u16 + } +} + +impl Narrow for u16 { + fn narrow(value: u64) -> Self { + value as u16 + } +} + +impl Narrow for u32 { + fn narrow(value: u64) -> Self { + value as u32 + } +} diff --git a/tests/mspm0/src/bin/uart.rs b/tests/mspm0/src/bin/uart.rs index 458129d44..916ce0d4b 100644 --- a/tests/mspm0/src/bin/uart.rs +++ b/tests/mspm0/src/bin/uart.rs @@ -4,6 +4,9 @@ #[cfg(feature = "mspm0g3507")] teleprobe_meta::target!(b"lp-mspm0g3507"); +#[cfg(feature = "mspm0g3519")] +teleprobe_meta::target!(b"lp-mspm0g3519"); + use defmt::{assert_eq, unwrap, *}; use embassy_executor::Spawner; use embassy_mspm0::mode::Blocking; @@ -23,7 +26,7 @@ async fn main(_spawner: Spawner) { // TODO: Allow creating a looped-back UART (so pins are not needed). // Do not select default UART since the virtual COM port is attached to UART0. - #[cfg(feature = "mspm0g3507")] + #[cfg(any(feature = "mspm0g3507", feature = "mspm0g3519"))] let (mut tx, mut rx, mut uart) = (p.PA8, p.PA9, p.UART1); const MFCLK_BUAD_RATES: &[u32] = &[1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200]; -- cgit From 504261a8d0bc58fcfa8b73245eaf859f88d62a94 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 7 Jul 2025 23:33:10 +0200 Subject: Reenable rpi pico tests. --- ci.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/ci.sh b/ci.sh index e54112359..dddef11ae 100755 --- a/ci.sh +++ b/ci.sh @@ -372,9 +372,6 @@ rm out/tests/pimoroni-pico-plus-2/adc # temporarily disabled rm out/tests/pimoroni-pico-plus-2/pwm -# temporarily disabled, bad hardware connection. -rm -f out/tests/rpi-pico/* - if [[ -z "${TELEPROBE_TOKEN-}" ]]; then echo No teleprobe token found, skipping running HIL tests exit -- cgit From 2fe2a0cf9c15bf7e84134cd7fec48017bb0a0db7 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 8 Jul 2025 20:19:01 +0200 Subject: excutor: fix Send unsoundness with `-> impl Future` tasks. --- embassy-executor-macros/src/macros/task.rs | 10 ++++-- embassy-executor/tests/ui.rs | 2 ++ .../tests/ui/return_impl_future_nonsend.rs | 21 +++++++++++ .../tests/ui/return_impl_future_nonsend.stderr | 17 +++++++++ embassy-executor/tests/ui/return_impl_send.stderr | 8 ++--- embassy-executor/tests/ui/spawn_nonsend.rs | 16 +++++++++ embassy-executor/tests/ui/spawn_nonsend.stderr | 41 ++++++++++++++++++++++ 7 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 embassy-executor/tests/ui/return_impl_future_nonsend.rs create mode 100644 embassy-executor/tests/ui/return_impl_future_nonsend.stderr create mode 100644 embassy-executor/tests/ui/spawn_nonsend.rs create mode 100644 embassy-executor/tests/ui/spawn_nonsend.stderr diff --git a/embassy-executor-macros/src/macros/task.rs b/embassy-executor-macros/src/macros/task.rs index 91bf8e940..1c5e3571d 100644 --- a/embassy-executor-macros/src/macros/task.rs +++ b/embassy-executor-macros/src/macros/task.rs @@ -131,6 +131,12 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { )); } + let spawn = if returns_impl_trait { + quote!(spawn) + } else { + quote!(_spawn_async_fn) + }; + #[cfg(feature = "nightly")] let mut task_outer_body = quote! { trait _EmbassyInternalTaskTrait { @@ -147,7 +153,7 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { const POOL_SIZE: usize = #pool_size; static POOL: #embassy_executor::raw::TaskPool<<() as _EmbassyInternalTaskTrait>::Fut, POOL_SIZE> = #embassy_executor::raw::TaskPool::new(); - unsafe { POOL._spawn_async_fn(move || <() as _EmbassyInternalTaskTrait>::construct(#(#full_args,)*)) } + unsafe { POOL.#spawn(move || <() as _EmbassyInternalTaskTrait>::construct(#(#full_args,)*)) } }; #[cfg(not(feature = "nightly"))] let mut task_outer_body = quote! { @@ -164,7 +170,7 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { {#embassy_executor::_export::task_pool_size::<_, _, _, POOL_SIZE>(#task_inner_ident)}, {#embassy_executor::_export::task_pool_align::<_, _, _, POOL_SIZE>(#task_inner_ident)}, > = unsafe { ::core::mem::transmute(#embassy_executor::_export::task_pool_new::<_, _, _, POOL_SIZE>(#task_inner_ident)) }; - unsafe { __task_pool_get(#task_inner_ident)._spawn_async_fn(move || #task_inner_ident(#(#full_args,)*)) } + unsafe { __task_pool_get(#task_inner_ident).#spawn(move || #task_inner_ident(#(#full_args,)*)) } }; let task_outer_attrs = task_inner.attrs.clone(); diff --git a/embassy-executor/tests/ui.rs b/embassy-executor/tests/ui.rs index c4a1a601c..7757775ee 100644 --- a/embassy-executor/tests/ui.rs +++ b/embassy-executor/tests/ui.rs @@ -17,6 +17,8 @@ fn ui() { t.compile_fail("tests/ui/nonstatic_struct_elided.rs"); t.compile_fail("tests/ui/nonstatic_struct_generic.rs"); t.compile_fail("tests/ui/not_async.rs"); + t.compile_fail("tests/ui/spawn_nonsend.rs"); + t.compile_fail("tests/ui/return_impl_future_nonsend.rs"); if rustversion::cfg!(stable) { // output is slightly different on nightly t.compile_fail("tests/ui/bad_return_impl_future.rs"); diff --git a/embassy-executor/tests/ui/return_impl_future_nonsend.rs b/embassy-executor/tests/ui/return_impl_future_nonsend.rs new file mode 100644 index 000000000..b8c184b21 --- /dev/null +++ b/embassy-executor/tests/ui/return_impl_future_nonsend.rs @@ -0,0 +1,21 @@ +#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] + +use core::future::Future; + +use embassy_executor::SendSpawner; + +#[embassy_executor::task] +fn task() -> impl Future { + // runs in spawning thread + let non_send: *mut () = core::ptr::null_mut(); + async move { + // runs in executor thread + println!("{}", non_send as usize); + } +} + +fn send_spawn(s: SendSpawner) { + s.spawn(task()).unwrap(); +} + +fn main() {} diff --git a/embassy-executor/tests/ui/return_impl_future_nonsend.stderr b/embassy-executor/tests/ui/return_impl_future_nonsend.stderr new file mode 100644 index 000000000..8aeb9738a --- /dev/null +++ b/embassy-executor/tests/ui/return_impl_future_nonsend.stderr @@ -0,0 +1,17 @@ +error: future cannot be sent between threads safely + --> tests/ui/return_impl_future_nonsend.rs:18:13 + | +18 | s.spawn(task()).unwrap(); + | ^^^^^^ future created by async block is not `Send` + | + = help: within `impl Sized`, the trait `Send` is not implemented for `*mut ()` +note: captured value is not `Send` + --> tests/ui/return_impl_future_nonsend.rs:13:24 + | +13 | println!("{}", non_send as usize); + | ^^^^^^^^ has type `*mut ()` which is not `Send` +note: required by a bound in `SendSpawner::spawn` + --> src/spawner.rs + | + | pub fn spawn(&self, token: SpawnToken) -> Result<(), SpawnError> { + | ^^^^ required by this bound in `SendSpawner::spawn` diff --git a/embassy-executor/tests/ui/return_impl_send.stderr b/embassy-executor/tests/ui/return_impl_send.stderr index cd693af2b..759be1cde 100644 --- a/embassy-executor/tests/ui/return_impl_send.stderr +++ b/embassy-executor/tests/ui/return_impl_send.stderr @@ -91,14 +91,14 @@ error[E0277]: `impl Send` is not a future | ^^^^^^^^^^^^^^^^^^^^^^^^^ `impl Send` is not a future | = help: the trait `Future` is not implemented for `impl Send` -note: required by a bound in `TaskPool::::_spawn_async_fn` +note: required by a bound in `TaskPool::::spawn` --> src/raw/mod.rs | | impl TaskPool { - | ^^^^^^ required by this bound in `TaskPool::::_spawn_async_fn` + | ^^^^^^ required by this bound in `TaskPool::::spawn` ... - | pub unsafe fn _spawn_async_fn(&'static self, future: FutFn) -> SpawnToken - | --------------- required by a bound in this associated function + | pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken { + | ----- required by a bound in this associated function = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: task futures must resolve to `()` or `!` diff --git a/embassy-executor/tests/ui/spawn_nonsend.rs b/embassy-executor/tests/ui/spawn_nonsend.rs new file mode 100644 index 000000000..4c4cc7697 --- /dev/null +++ b/embassy-executor/tests/ui/spawn_nonsend.rs @@ -0,0 +1,16 @@ +#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] + +use core::future::Future; + +use embassy_executor::SendSpawner; + +#[embassy_executor::task] +async fn task(non_send: *mut ()) { + println!("{}", non_send as usize); +} + +fn send_spawn(s: SendSpawner) { + s.spawn(task(core::ptr::null_mut())).unwrap(); +} + +fn main() {} diff --git a/embassy-executor/tests/ui/spawn_nonsend.stderr b/embassy-executor/tests/ui/spawn_nonsend.stderr new file mode 100644 index 000000000..2a06c8b94 --- /dev/null +++ b/embassy-executor/tests/ui/spawn_nonsend.stderr @@ -0,0 +1,41 @@ +warning: unused import: `core::future::Future` + --> tests/ui/spawn_nonsend.rs:3:5 + | +3 | use core::future::Future; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + +error[E0277]: `*mut ()` cannot be sent between threads safely + --> tests/ui/spawn_nonsend.rs:13:13 + | +7 | #[embassy_executor::task] + | ------------------------- within this `impl Sized` +... +13 | s.spawn(task(core::ptr::null_mut())).unwrap(); + | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: within `impl Sized`, the trait `Send` is not implemented for `*mut ()` +note: required because it's used within this closure + --> tests/ui/spawn_nonsend.rs:7:1 + | +7 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required because it appears within the type `impl Sized` + --> src/raw/mod.rs + | + | pub unsafe fn _spawn_async_fn(&'static self, future: FutFn) -> SpawnToken + | ^^^^^^^^^^ +note: required because it appears within the type `impl Sized` + --> tests/ui/spawn_nonsend.rs:7:1 + | +7 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `SendSpawner::spawn` + --> src/spawner.rs + | + | pub fn spawn(&self, token: SpawnToken) -> Result<(), SpawnError> { + | ^^^^ required by this bound in `SendSpawner::spawn` + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) -- cgit From 0c136c7b050ded4bf660ea7a50381698ab9d5f09 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 8 Jul 2025 22:39:53 +0200 Subject: executor: mark Spawner::for_current_executor() as unsafe. It's unsound with manually-created Contexts, see https://github.com/embassy-rs/embassy/issues/4379 --- embassy-executor/src/spawner.rs | 18 +++++++++++++++++- .../nrf52840/src/bin/self_spawn_current_executor.rs | 3 ++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index 522d97db3..2909d19a0 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -122,10 +122,26 @@ impl Spawner { /// This function is `async` just to get access to the current async /// context. It returns instantly, it does not block/yield. /// + /// Using this method is discouraged due to it being unsafe. Consider the following + /// alternatives instead: + /// + /// - Pass the initial `Spawner` as an argument to tasks. Note that it's `Copy`, so you can + /// make as many copies of it as you want. + /// - Use `SendSpawner::for_current_executor()` instead, which is safe but can only be used + /// if task arguments are `Send`. + /// + /// The only case where using this method is absolutely required is obtaining the `Spawner` + /// for an `InterruptExecutor`. + /// + /// # Safety + /// + /// You must only execute this with an async `Context` created by the Embassy executor. + /// You must not execute it with manually-created `Context`s. + /// /// # Panics /// /// Panics if the current executor is not an Embassy executor. - pub fn for_current_executor() -> impl Future { + pub unsafe fn for_current_executor() -> impl Future { poll_fn(|cx| { let task = raw::task_from_waker(cx.waker()); let executor = unsafe { diff --git a/examples/nrf52840/src/bin/self_spawn_current_executor.rs b/examples/nrf52840/src/bin/self_spawn_current_executor.rs index ec9569a64..ddb40dc53 100644 --- a/examples/nrf52840/src/bin/self_spawn_current_executor.rs +++ b/examples/nrf52840/src/bin/self_spawn_current_executor.rs @@ -10,7 +10,8 @@ use {defmt_rtt as _, panic_probe as _}; async fn my_task(n: u32) { Timer::after_secs(1).await; info!("Spawning self! {}", n); - unwrap!(Spawner::for_current_executor().await.spawn(my_task(n + 1))); + let spawner = unsafe { Spawner::for_current_executor().await }; + unwrap!(spawner.spawn(my_task(n + 1))); } #[embassy_executor::main] -- cgit From 0448d1fc50e80832ecd6382ad3add9575d505d37 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 10:42:45 +0200 Subject: fix `release/bump-dependency.sh`: don't generate backup files the `-rie` arguments of `sed` were probably meant as `-r -i -e`, however, due to the way it was written it ended up being `-r -i e`, thus causing `-i` (edit in-place) to generate backup files. so for every edited `Cargo.toml` it also created a `Cargo.tomle` with the previous content. `-e` is anyway not needed as the last argument of `sed` here is the expression to be executed. --- release/bump-dependency.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/bump-dependency.sh b/release/bump-dependency.sh index 07511d229..97f73cddc 100755 --- a/release/bump-dependency.sh +++ b/release/bump-dependency.sh @@ -8,4 +8,4 @@ # CRATE=$1 TARGET_VER=$2 -find . -name "Cargo.toml" | xargs sed -rie "s/($CRATE = \{.*version = \")[0-9]+.[0-9]+.?[0-9]*(\".*)/\1$TARGET_VER\2/g" +find . -name "Cargo.toml" | xargs sed -ri "s/($CRATE = \{.*version = \")[0-9]+.[0-9]+.?[0-9]*(\".*)/\1$TARGET_VER\2/g" -- cgit From ca21140f5ee326e1a0723fb56a39e73a98e3188a Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 10:00:46 +0200 Subject: add changelog for `embassy-futures` --- embassy-futures/CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 embassy-futures/CHANGELOG.md diff --git a/embassy-futures/CHANGELOG.md b/embassy-futures/CHANGELOG.md new file mode 100644 index 000000000..86ea40540 --- /dev/null +++ b/embassy-futures/CHANGELOG.md @@ -0,0 +1,13 @@ +# Changelog for embassy-futures + +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). + +## Unreleased + +- Preserve location information for `defmt` in `fmt` calls ([#3085](https://github.com/embassy-rs/embassy/pull/3085)) +- Fixed soundness issue in `select_slice` ([#3328](https://github.com/embassy-rs/embassy/pull/3328)) +- Added `select5` and `select6` ([#3430](https://github.com/embassy-rs/embassy/pull/3430)) +- Added `is_x` methods for all `EitherN` enum variants (#[3650](https://github.com/embassy-rs/embassy/pull/3650)) -- cgit From 1bc17b0964a12f2c31275710c90e446f842c027a Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 10:24:04 +0200 Subject: `embassy-futures`: add release automation using `cargo-release` this requires you to install [`cargo-release`]. note that this does not include a URL pointing to the diff on GitHub as is usually done in changelogs since `embassy` is a mono-repo and the GH UI doesn't offer a commit view per folder (see the [GH feature request] for this). [`cargo-release`]: https://crates.io/crates/cargo-release [GH feature request]: https://github.com/orgs/community/discussions/162131 --- embassy-futures/CHANGELOG.md | 3 ++- embassy-futures/release.toml | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 embassy-futures/release.toml diff --git a/embassy-futures/CHANGELOG.md b/embassy-futures/CHANGELOG.md index 86ea40540..eb76cdc4a 100644 --- a/embassy-futures/CHANGELOG.md +++ b/embassy-futures/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate - Preserve location information for `defmt` in `fmt` calls ([#3085](https://github.com/embassy-rs/embassy/pull/3085)) - Fixed soundness issue in `select_slice` ([#3328](https://github.com/embassy-rs/embassy/pull/3328)) diff --git a/embassy-futures/release.toml b/embassy-futures/release.toml new file mode 100644 index 000000000..fb6feaf21 --- /dev/null +++ b/embassy-futures/release.toml @@ -0,0 +1,5 @@ +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, +] -- cgit From 88076255baf1c8e5b25d0fb32dfa3f907030e2c2 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 10:49:57 +0200 Subject: add changelog for `embassy-usb-driver` --- embassy-usb-driver/CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 embassy-usb-driver/CHANGELOG.md diff --git a/embassy-usb-driver/CHANGELOG.md b/embassy-usb-driver/CHANGELOG.md new file mode 100644 index 000000000..4a1090029 --- /dev/null +++ b/embassy-usb-driver/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog for embassy-usb-driver + +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). + +## Unreleased + +- Add `embedded_io_async::Error` implementation for `EndpointError` ([#4176](https://github.com/embassy-rs/embassy/pull/4176)) -- cgit From 1d522c6e4fedc045e6ed7483ffc2f91a99e2d9a6 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 10:51:37 +0200 Subject: `embassy-usb-driver`: add release automation using `cargo-release` this requires you to install [`cargo-release`]. note that this does not include a URL pointing to the diff on GitHub as is usually done in changelogs since `embassy` is a mono-repo and the GH UI doesn't offer a commit view per folder (see the [GH feature request] for this). [`cargo-release`]: https://crates.io/crates/cargo-release [GH feature request]: https://github.com/orgs/community/discussions/162131 --- embassy-usb-driver/CHANGELOG.md | 3 ++- embassy-usb-driver/release.toml | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 embassy-usb-driver/release.toml diff --git a/embassy-usb-driver/CHANGELOG.md b/embassy-usb-driver/CHANGELOG.md index 4a1090029..c02daefdf 100644 --- a/embassy-usb-driver/CHANGELOG.md +++ b/embassy-usb-driver/CHANGELOG.md @@ -5,6 +5,7 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate - Add `embedded_io_async::Error` implementation for `EndpointError` ([#4176](https://github.com/embassy-rs/embassy/pull/4176)) diff --git a/embassy-usb-driver/release.toml b/embassy-usb-driver/release.toml new file mode 100644 index 000000000..fb6feaf21 --- /dev/null +++ b/embassy-usb-driver/release.toml @@ -0,0 +1,5 @@ +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, +] -- cgit From e9296b547a6bc6f6d69f28882fbd95107f0d5e98 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 10:57:03 +0200 Subject: prepare changelog for `embassy-net-driver-channel` v0.4.0 --- embassy-net-driver-channel/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/embassy-net-driver-channel/CHANGELOG.md b/embassy-net-driver-channel/CHANGELOG.md index d7af7e55d..ebc0e96b9 100644 --- a/embassy-net-driver-channel/CHANGELOG.md +++ b/embassy-net-driver-channel/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- Update `embassy-sync` to v0.7.0 + ## 0.3.0 - 2024-08-05 - Add collapse_debuginfo to fmt.rs macros. -- cgit From 010c626a1160cf1a6721d8632119c0e45907e8c2 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 10:58:39 +0200 Subject: `embassy-inet-driver-channel`: add release automation using `cargo-release` this requires you to install [`cargo-release`]. note that this does not include a URL pointing to the diff on GitHub as is usually done in changelogs since `embassy` is a mono-repo and the GH UI doesn't offer a commit view per folder (see the [GH feature request] for this). [`cargo-release`]: https://crates.io/crates/cargo-release [GH feature request]: https://github.com/orgs/community/discussions/162131 --- embassy-net-driver-channel/CHANGELOG.md | 3 ++- embassy-net-driver-channel/release.toml | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 embassy-net-driver-channel/release.toml diff --git a/embassy-net-driver-channel/CHANGELOG.md b/embassy-net-driver-channel/CHANGELOG.md index ebc0e96b9..a5c81cf4d 100644 --- a/embassy-net-driver-channel/CHANGELOG.md +++ b/embassy-net-driver-channel/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate - Update `embassy-sync` to v0.7.0 diff --git a/embassy-net-driver-channel/release.toml b/embassy-net-driver-channel/release.toml new file mode 100644 index 000000000..fb6feaf21 --- /dev/null +++ b/embassy-net-driver-channel/release.toml @@ -0,0 +1,5 @@ +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, +] -- cgit From e38b3c52528da3796208ac9a05e4a75e373cf252 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 11:09:09 +0200 Subject: prepare changelog for `embassy-usb` v0.5.0 --- embassy-usb/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/embassy-usb/CHANGELOG.md b/embassy-usb/CHANGELOG.md index 76fafed31..d941ae068 100644 --- a/embassy-usb/CHANGELOG.md +++ b/embassy-usb/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- `UAC1`: unmute by default ([#3992](https://github.com/embassy-rs/embassy/pull/3992)) +- `cdc_acm`: `State::new` is now `const` ([#4000](https://github.com/embassy-rs/embassy/pull/4000)) +- Add support for CMSIS-DAP v2 USB class ([#4107](https://github.com/embassy-rs/embassy/pull/4107)) +- Reduce `UsbDevice` builder logs to `trace` ([#4130](https://github.com/embassy-rs/embassy/pull/4130)) +- Implement `embedded-io-async` traits for USB CDC ACM ([#4176](https://github.com/embassy-rs/embassy/pull/4176)) +- Update `embassy-sync` to v0.7.0 + ## 0.4.0 - 2025-01-15 - Change config defaults to to composite with IADs. This ensures embassy-usb Just Works in more cases when using classes with multiple interfaces, or multiple classes. (breaking change) -- cgit From 27bae26172757b15597f497b5e3d30d5dc18bd98 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 11:10:21 +0200 Subject: `embassy-usb`: add release automation using `cargo-release` this requires you to install [`cargo-release`]. note that this does not include a URL pointing to the diff on GitHub as is usually done in changelogs since `embassy` is a mono-repo and the GH UI doesn't offer a commit view per folder (see the [GH feature request] for this). [`cargo-release`]: https://crates.io/crates/cargo-release [GH feature request]: https://github.com/orgs/community/discussions/162131 --- embassy-usb/CHANGELOG.md | 3 ++- embassy-usb/release.toml | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 embassy-usb/release.toml diff --git a/embassy-usb/CHANGELOG.md b/embassy-usb/CHANGELOG.md index d941ae068..51db5f03e 100644 --- a/embassy-usb/CHANGELOG.md +++ b/embassy-usb/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate - `UAC1`: unmute by default ([#3992](https://github.com/embassy-rs/embassy/pull/3992)) - `cdc_acm`: `State::new` is now `const` ([#4000](https://github.com/embassy-rs/embassy/pull/4000)) diff --git a/embassy-usb/release.toml b/embassy-usb/release.toml new file mode 100644 index 000000000..fb6feaf21 --- /dev/null +++ b/embassy-usb/release.toml @@ -0,0 +1,5 @@ +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, +] -- cgit From 1c515937ff69cf2358118e13a9a70178dd7a99a0 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Wed, 11 Jun 2025 09:47:25 +0200 Subject: prepare changelog for `embassy-executor` v0.8.0 --- embassy-executor/CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 608c67724..19e41e3e7 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -7,7 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## unreleased +- Added `SpawnToken::id` +- Task pools are now statically allocated on stable rust. All `task-arena-size-*` features have been removed and are no longer necessary. +- New trace hooks: `_embassy_trace_poll_start` & `_embassy_trace_task_end` +- Added task naming capability to tracing infrastructure +- Added `Executor::id` & `Spawner::executor_id` +- Disable `critical-section/std` for arch-std +- Added possibility to select an executor in `#[embassy_executor::main]` +- Fix AVR executor +- executor: Make state implementations and their conditions match - Added support for Cortex-A and Cortex-R +- Added support for `-> impl Future` in `#[task]` +- Fixed `Send` unsoundness with `-> impl Future` tasks +- Marked `Spawner::for_current_executor` as `unsafe` ## 0.7.0 - 2025-01-02 -- cgit From a52ca758ac84af5b9fafa9f6cc0562495a796ffd Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Wed, 11 Jun 2025 09:48:37 +0200 Subject: `embassy-executor`: add release automation using `cargo-release` this requires you to install [`cargo-release`]. note that this does not include a URL pointing to the diff on GitHub as is usually done in changelogs since `embassy` is a mono-repo and the GH UI doesn't offer a commit view per folder (see the [GH feature request] for this). [`cargo-release`]: https://crates.io/crates/cargo-release [GH feature request]: https://github.com/orgs/community/discussions/162131 --- embassy-executor/CHANGELOG.md | 3 ++- embassy-executor/release.toml | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 embassy-executor/release.toml diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 19e41e3e7..914863a83 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## unreleased + +## Unreleased - ReleaseDate - Added `SpawnToken::id` - Task pools are now statically allocated on stable rust. All `task-arena-size-*` features have been removed and are no longer necessary. diff --git a/embassy-executor/release.toml b/embassy-executor/release.toml new file mode 100644 index 000000000..fb6feaf21 --- /dev/null +++ b/embassy-executor/release.toml @@ -0,0 +1,5 @@ +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, +] -- cgit From 9f9c6f328d1da8a4ec7bea41b4d1355665af55cb Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 12:14:56 +0200 Subject: prepare changelog for `embassy-time-driver` v0.2.1 --- embassy-time-driver/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/embassy-time-driver/CHANGELOG.md b/embassy-time-driver/CHANGELOG.md index 744b0f648..349df15a7 100644 --- a/embassy-time-driver/CHANGELOG.md +++ b/embassy-time-driver/CHANGELOG.md @@ -5,6 +5,11 @@ 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). +## Unreleased + +- Allow inlining on time driver boundary +- add 133MHz tick rate to support PR2040 @ 133MHz when `TIMERx`'s `SOURCE` is set to `SYSCLK` + ## 0.2.0 - 2025-01-02 - The `allocate_alarm`, `set_alarm_callback`, `set_alarm` functions have been removed. -- cgit From 80bb09cdb1599e185023ae39d144f353f6ebc10f Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 12:16:07 +0200 Subject: `embassy-time-driver`: add release automation using `cargo-release` this requires you to install [`cargo-release`]. note that this does not include a URL pointing to the diff on GitHub as is usually done in changelogs since `embassy` is a mono-repo and the GH UI doesn't offer a commit view per folder (see the [GH feature request] for this). [`cargo-release`]: https://crates.io/crates/cargo-release [GH feature request]: https://github.com/orgs/community/discussions/162131 --- embassy-time-driver/CHANGELOG.md | 3 ++- embassy-time-driver/release.toml | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 embassy-time-driver/release.toml diff --git a/embassy-time-driver/CHANGELOG.md b/embassy-time-driver/CHANGELOG.md index 349df15a7..b61a10bf6 100644 --- a/embassy-time-driver/CHANGELOG.md +++ b/embassy-time-driver/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate - Allow inlining on time driver boundary - add 133MHz tick rate to support PR2040 @ 133MHz when `TIMERx`'s `SOURCE` is set to `SYSCLK` diff --git a/embassy-time-driver/release.toml b/embassy-time-driver/release.toml new file mode 100644 index 000000000..fb6feaf21 --- /dev/null +++ b/embassy-time-driver/release.toml @@ -0,0 +1,5 @@ +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, +] -- cgit From bb1b682deb5931b24ea7bd191aadf5a927140b14 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 12:23:11 +0200 Subject: prepare changelog for `embassy-time` v0.4.1 --- embassy-time/CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/embassy-time/CHANGELOG.md b/embassy-time/CHANGELOG.md index 09e951ce4..49b3b4586 100644 --- a/embassy-time/CHANGELOG.md +++ b/embassy-time/CHANGELOG.md @@ -5,6 +5,16 @@ 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). +## Unreleased + +- Allow inlining on time driver boundary +- Add `saturating_add` and `saturating_sub` to `Instant` +- Add `Instant::try_from_*` constructor functions +- Add `Duration::try_from_*` constructor functions +- Don't select `critical-section` impl for `std` +- Manually implement the future for `with_timeout` +- Add 133MHz tick rate to support PR2040 @ 133MHz when `TIMERx`'s `SOURCE` is set to `SYSCLK` + ## 0.4.0 - 2025-01-02 - `embassy-time-driver` updated from v0.1 to v0.2. -- cgit From 112c7a16654bf376463586bd2a32ea817fb7f11d Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 12:32:28 +0200 Subject: `embassy-time`: add release automation using `cargo-release` this requires you to install [`cargo-release`]. note that this does not include a URL pointing to the diff on GitHub as is usually done in changelogs since `embassy` is a mono-repo and the GH UI doesn't offer a commit view per folder (see the [GH feature request] for this). [`cargo-release`]: https://crates.io/crates/cargo-release [GH feature request]: https://github.com/orgs/community/discussions/162131 --- embassy-time/CHANGELOG.md | 3 ++- embassy-time/release.toml | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 embassy-time/release.toml diff --git a/embassy-time/CHANGELOG.md b/embassy-time/CHANGELOG.md index 49b3b4586..a0c1abe8d 100644 --- a/embassy-time/CHANGELOG.md +++ b/embassy-time/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate - Allow inlining on time driver boundary - Add `saturating_add` and `saturating_sub` to `Instant` diff --git a/embassy-time/release.toml b/embassy-time/release.toml new file mode 100644 index 000000000..fb6feaf21 --- /dev/null +++ b/embassy-time/release.toml @@ -0,0 +1,5 @@ +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, +] -- cgit From db58ce03cc4bde8582c12c5736a8a4490e160a85 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 12:26:51 +0200 Subject: prepare changelog for `embassy-embedded-hal` v0.4.0 --- embassy-embedded-hal/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/embassy-embedded-hal/CHANGELOG.md b/embassy-embedded-hal/CHANGELOG.md index 224036af4..d19c54354 100644 --- a/embassy-embedded-hal/CHANGELOG.md +++ b/embassy-embedded-hal/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- `SpiDevice` cancel safety: always set CS pin to high on drop +- Update `embassy-sync` to v0.7.0 + ## 0.3.0 - 2025-01-05 - The `std` feature has been removed -- cgit From cd2c9c7e85efb055b3c72971f0a94cc75efd0aa1 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 12:30:26 +0200 Subject: `embassy-embedded-hal`: add release automation using `cargo-release` this requires you to install [`cargo-release`]. note that this does not include a URL pointing to the diff on GitHub as is usually done in changelogs since `embassy` is a mono-repo and the GH UI doesn't offer a commit view per folder (see the [GH feature request] for this). [`cargo-release`]: https://crates.io/crates/cargo-release [GH feature request]: https://github.com/orgs/community/discussions/162131 --- embassy-embedded-hal/CHANGELOG.md | 3 ++- embassy-embedded-hal/release.toml | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 embassy-embedded-hal/release.toml diff --git a/embassy-embedded-hal/CHANGELOG.md b/embassy-embedded-hal/CHANGELOG.md index d19c54354..6f0655adf 100644 --- a/embassy-embedded-hal/CHANGELOG.md +++ b/embassy-embedded-hal/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate - `SpiDevice` cancel safety: always set CS pin to high on drop - Update `embassy-sync` to v0.7.0 diff --git a/embassy-embedded-hal/release.toml b/embassy-embedded-hal/release.toml new file mode 100644 index 000000000..fb6feaf21 --- /dev/null +++ b/embassy-embedded-hal/release.toml @@ -0,0 +1,5 @@ +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, +] -- cgit From 74101a8625ad042d3bfd44f9dc20882a8d1f6944 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 12:03:59 +0200 Subject: prepare changelog for `embassy-rp` v0.5.0 --- embassy-rp/CHANGELOG.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md index 7ac0a47cb..bb58ac54f 100644 --- a/embassy-rp/CHANGELOG.md +++ b/embassy-rp/CHANGELOG.md @@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- Fix wrong `funcsel` on RP2350 gpout/gpin ([#3975](https://github.com/embassy-rs/embassy/pull/3975)) +- Fix potential race condition in `ADC::wait_for_ready` ([#4012](https://github.com/embassy-rs/embassy/pull/4012)) +- `flash`: rename `BOOTROM_BASE` to `BOOTRAM_BASE` ([#4014](https://github.com/embassy-rs/embassy/pull/4014)) +- Remove `Peripheral` trait & rename `PeripheralRef` to `Peri` ([#3999](https://github.com/embassy-rs/embassy/pull/3999)) +- Fix watchdog count on RP235x ([#4021](https://github.com/embassy-rs/embassy/pull/4021)) +- I2C: ensure that wakers are registered before checking status of `wait_on` helpers ([#4043](https://github.com/embassy-rs/embassy/pull/4043)) +- Modify `Uarte` and `BufferedUarte` initialization to take pins before interrupts ([#3983](https://github.com/embassy-rs/embassy/pull/3983)) +- `uart`: increase RX FIFO watermark from 1/8 to 7/8 ([#4055](https://github.com/embassy-rs/embassy/pull/4055)) +- Add `spinlock_mutex` ([#4017](https://github.com/embassy-rs/embassy/pull/4017)) +- Enable input mode for PWM pins on RP235x and disable it on drop ([#4093](https://github.com/embassy-rs/embassy/pull/4093)) +- Add `impl rand_core::CryptoRng for Trng` ([#4096](https://github.com/embassy-rs/embassy/pull/4096)) +- `pwm`: enable pull-down resistors for pins in `Drop` implementation ([#4115](https://github.com/embassy-rs/embassy/pull/4115)) +- Rewrite PIO onewire implementation ([#4128](https://github.com/embassy-rs/embassy/pull/4128)) +- Implement RP2040 overclocking ([#4150](https://github.com/embassy-rs/embassy/pull/4150)) +- Implement RP235x overclocking ([#4187](https://github.com/embassy-rs/embassy/pull/4187)) +- `trng`: improve error handling ([#4139](https://github.com/embassy-rs/embassy/pull/4139)) +- Remove `` from `Uart` and `BufferedUart` ([#4155](https://github.com/embassy-rs/embassy/pull/4155)) +- Make bit-depth of I2S PIO program configurable ([#4193](https://github.com/embassy-rs/embassy/pull/4193)) +- Add the possibility to document `bind_interrupts` `struct`s ([#4206](https://github.com/embassy-rs/embassy/pull/4206)) +- Add missing `Debug` and `defmt::Format` `derive`s for ADC & `AnyPin` ([#4205](https://github.com/embassy-rs/embassy/pull/4205)) +- Add `rand-core` v0.9 support ([#4217](https://github.com/embassy-rs/embassy/pull/4217)) +- Update `embassy-sync` to v0.7.0 ([#4234](https://github.com/embassy-rs/embassy/pull/4234)) +- Add compatibility with ws2812 leds that have 4 addressable lights ([#4236](https://github.com/embassy-rs/embassy/pull/4236)) +- Implement input/output inversion ([#4237](https://github.com/embassy-rs/embassy/pull/4237)) +- Add `multicore::current_core` API ([#4362](https://github.com/embassy-rs/embassy/pull/4362)) + ## 0.4.0 - 2025-03-09 - Add PIO functions. ([#3857](https://github.com/embassy-rs/embassy/pull/3857)) -- cgit From 22e77cb675a2405472cd6d28b66172e311713ee1 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Sun, 8 Jun 2025 12:05:29 +0200 Subject: `embassy-rp`: add release automation using `cargo-release` this requires you to install [`cargo-release`]. note that this does not include a URL pointing to the diff on GitHub as is usually done in changelogs since `embassy` is a mono-repo and the GH UI doesn't offer a commit view per folder (see the [GH feature request] for this). [`cargo-release`]: https://crates.io/crates/cargo-release [GH feature request]: https://github.com/orgs/community/discussions/162131 --- embassy-rp/CHANGELOG.md | 3 ++- embassy-rp/release.toml | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 embassy-rp/release.toml diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md index bb58ac54f..52bf0038e 100644 --- a/embassy-rp/CHANGELOG.md +++ b/embassy-rp/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate - Fix wrong `funcsel` on RP2350 gpout/gpin ([#3975](https://github.com/embassy-rs/embassy/pull/3975)) - Fix potential race condition in `ADC::wait_for_ready` ([#4012](https://github.com/embassy-rs/embassy/pull/4012)) diff --git a/embassy-rp/release.toml b/embassy-rp/release.toml new file mode 100644 index 000000000..fb6feaf21 --- /dev/null +++ b/embassy-rp/release.toml @@ -0,0 +1,5 @@ +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, +] -- cgit From 6609a85f3ce941ef07e471e56981a819b17e9303 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Wed, 25 Jun 2025 22:56:11 -0500 Subject: nxp: add feature for lpc55 this is needed since I will be working on adding support for the MCX families to embassy-nxp Co-authored-by: IriniaCh524 --- ci.sh | 2 +- embassy-nxp/Cargo.toml | 10 ++++++++-- examples/lpc55s69/Cargo.toml | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/ci.sh b/ci.sh index e1fdf998a..036c38d1a 100755 --- a/ci.sh +++ b/ci.sh @@ -176,7 +176,7 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u031r8,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u073mb,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u083rc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv8m.main-none-eabihf \ + --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv8m.main-none-eabihf --features lpc55,defmt \ --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0c1104dgs20,defmt,time-driver-any \ --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3507pm,defmt,time-driver-any \ --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3519pz,defmt,time-driver-any \ diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 426af06a0..010607914 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -9,12 +9,18 @@ cortex-m-rt = "0.7.0" critical-section = "1.1.2" embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } -lpc55-pac = "0.5.0" defmt = { version = "1", optional = true } +## Chip dependencies +lpc55-pac = { version = "0.5.0", optional = true } + [features] default = ["rt"] -rt = ["lpc55-pac/rt"] +# Enable PACs as optional dependencies, since some chip families will use different pac crates. +rt = ["lpc55-pac?/rt"] ## Enable [defmt support](https://docs.rs/defmt) and enables `defmt` debug-log messages and formatting in embassy drivers. defmt = ["dep:defmt", "embassy-hal-internal/defmt", "embassy-sync/defmt"] + +#! ### Chip selection features +lpc55 = ["lpc55-pac"] diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index 7f81e9c7f..6ec6e51a8 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] -embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["rt"] } +embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55", "rt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } -- cgit From 7219df4a5f9a666c6b0114eb9e86b6ab088fdeaa Mon Sep 17 00:00:00 2001 From: i509VCB Date: Sun, 6 Jul 2025 22:39:44 -0500 Subject: nxp: feature gate lpc55 gpio and pint to lpc55 --- embassy-nxp/Cargo.toml | 6 + embassy-nxp/src/chips/lpc55.rs | 70 +++++ embassy-nxp/src/gpio.rs | 357 +--------------------- embassy-nxp/src/gpio/lpc55.rs | 677 +++++++++++++++++++++++++++++++++++++++++ embassy-nxp/src/lib.rs | 90 +----- embassy-nxp/src/pac_utils.rs | 323 -------------------- embassy-nxp/src/pint.rs | 3 +- 7 files changed, 774 insertions(+), 752 deletions(-) create mode 100644 embassy-nxp/src/chips/lpc55.rs create mode 100644 embassy-nxp/src/gpio/lpc55.rs delete mode 100644 embassy-nxp/src/pac_utils.rs diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 010607914..18e9d989c 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -22,5 +22,11 @@ rt = ["lpc55-pac?/rt"] ## Enable [defmt support](https://docs.rs/defmt) and enables `defmt` debug-log messages and formatting in embassy drivers. defmt = ["dep:defmt", "embassy-hal-internal/defmt", "embassy-sync/defmt"] +## Reexport the PAC for the currently enabled chip at `embassy_nxp::pac` (unstable) +unstable-pac = [] +# This is unstable because semver-minor (non-breaking) releases of embassy-nrf may major-bump (breaking) the PAC version. +# If this is an issue for you, you're encouraged to directly depend on a fixed version of the PAC. +# There are no plans to make this stable. + #! ### Chip selection features lpc55 = ["lpc55-pac"] diff --git a/embassy-nxp/src/chips/lpc55.rs b/embassy-nxp/src/chips/lpc55.rs new file mode 100644 index 000000000..c95218af0 --- /dev/null +++ b/embassy-nxp/src/chips/lpc55.rs @@ -0,0 +1,70 @@ +pub use lpc55_pac as pac; + +embassy_hal_internal::peripherals! { + // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other + // peripheral types (e.g. I2C). + PIO0_0, + PIO0_1, + PIO0_2, + PIO0_3, + PIO0_4, + PIO0_5, + PIO0_6, + PIO0_7, + PIO0_8, + PIO0_9, + PIO0_10, + PIO0_11, + PIO0_12, + PIO0_13, + PIO0_14, + PIO0_15, + PIO0_16, + PIO0_17, + PIO0_18, + PIO0_19, + PIO0_20, + PIO0_21, + PIO0_22, + PIO0_23, + PIO0_24, + PIO0_25, + PIO0_26, + PIO0_27, + PIO0_28, + PIO0_29, + PIO0_30, + PIO0_31, + PIO1_0, + PIO1_1, + PIO1_2, + PIO1_3, + PIO1_4, + PIO1_5, + PIO1_6, + PIO1_7, + PIO1_8, + PIO1_9, + PIO1_10, + PIO1_11, + PIO1_12, + PIO1_13, + PIO1_14, + PIO1_15, + PIO1_16, + PIO1_17, + PIO1_18, + PIO1_19, + PIO1_20, + PIO1_21, + PIO1_22, + PIO1_23, + PIO1_24, + PIO1_25, + PIO1_26, + PIO1_27, + PIO1_28, + PIO1_29, + PIO1_30, + PIO1_31, +} diff --git a/embassy-nxp/src/gpio.rs b/embassy-nxp/src/gpio.rs index c7c78ce61..809903d97 100644 --- a/embassy-nxp/src/gpio.rs +++ b/embassy-nxp/src/gpio.rs @@ -1,354 +1,5 @@ -use embassy_hal_internal::{impl_peripheral, PeripheralType}; +//! General purpose input/output (GPIO) driver. -use crate::pac_utils::*; -use crate::{peripherals, Peri}; - -pub(crate) fn init() { - // Enable clocks for GPIO, PINT, and IOCON - syscon_reg() - .ahbclkctrl0 - .modify(|_, w| w.gpio0().enable().gpio1().enable().mux().enable().iocon().enable()); -} - -/// The GPIO pin level for pins set on "Digital" mode. -#[derive(Debug, Eq, PartialEq, Clone, Copy)] -pub enum Level { - /// Logical low. Corresponds to 0V. - Low, - /// Logical high. Corresponds to VDD. - High, -} - -/// Pull setting for a GPIO input set on "Digital" mode. -#[derive(Debug, Clone, Copy, Eq, PartialEq)] -pub enum Pull { - /// No pull. - None, - /// Internal pull-up resistor. - Up, - /// Internal pull-down resistor. - Down, -} - -/// The LPC55 boards have two GPIO banks, each with 32 pins. This enum represents the two banks. -#[derive(Debug, Eq, PartialEq, Clone, Copy)] -pub enum Bank { - Bank0 = 0, - Bank1 = 1, -} - -/// GPIO output driver. Internally, this is a specialized [Flex] pin. -pub struct Output<'d> { - pub(crate) pin: Flex<'d>, -} - -impl<'d> Output<'d> { - /// Create GPIO output driver for a [Pin] with the provided [initial output](Level). - #[inline] - pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self { - let mut pin = Flex::new(pin); - pin.set_as_output(); - let mut result = Self { pin }; - - match initial_output { - Level::High => result.set_high(), - Level::Low => result.set_low(), - }; - - result - } - - pub fn set_high(&mut self) { - gpio_reg().set[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) - } - - pub fn set_low(&mut self) { - gpio_reg().clr[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) - } - - pub fn toggle(&mut self) { - gpio_reg().not[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) - } - - /// Get the current output level of the pin. Note that the value returned by this function is - /// the voltage level reported by the pin, not the value set by the output driver. - pub fn level(&self) -> Level { - let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits(); - if bits & self.pin.bit() != 0 { - Level::High - } else { - Level::Low - } - } -} - -/// GPIO input driver. Internally, this is a specialized [Flex] pin. -pub struct Input<'d> { - pub(crate) pin: Flex<'d>, -} - -impl<'d> Input<'d> { - /// Create GPIO output driver for a [Pin] with the provided [Pull]. - #[inline] - pub fn new(pin: Peri<'d, impl Pin>, pull: Pull) -> Self { - let mut pin = Flex::new(pin); - pin.set_as_input(); - let mut result = Self { pin }; - result.set_pull(pull); - - result - } - - /// Set the pull configuration for the pin. To disable the pull, use [Pull::None]. - pub fn set_pull(&mut self, pull: Pull) { - match_iocon!(register, iocon_reg(), self.pin.pin_bank(), self.pin.pin_number(), { - register.modify(|_, w| match pull { - Pull::None => w.mode().inactive(), - Pull::Up => w.mode().pull_up(), - Pull::Down => w.mode().pull_down(), - }); - }); - } - - /// Get the current input level of the pin. - pub fn read(&self) -> Level { - let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits(); - if bits & self.pin.bit() != 0 { - Level::High - } else { - Level::Low - } - } -} - -/// A flexible GPIO (digital mode) pin whose mode is not yet determined. Under the hood, this is a -/// reference to a type-erased pin called ["AnyPin"](AnyPin). -pub struct Flex<'d> { - pub(crate) pin: Peri<'d, AnyPin>, -} - -impl<'d> Flex<'d> { - /// Wrap the pin in a `Flex`. - /// - /// Note: you cannot assume that the pin will be in Digital mode after this call. - #[inline] - pub fn new(pin: Peri<'d, impl Pin>) -> Self { - Self { pin: pin.into() } - } - - /// Get the bank of this pin. See also [Bank]. - /// - /// # Example - /// - /// ``` - /// use embassy_nxp::gpio::{Bank, Flex}; - /// - /// let p = embassy_nxp::init(Default::default()); - /// let pin = Flex::new(p.PIO1_15); - /// - /// assert_eq!(pin.pin_bank(), Bank::Bank1); - /// ``` - pub fn pin_bank(&self) -> Bank { - self.pin.pin_bank() - } - - /// Get the number of this pin within its bank. See also [Bank]. - /// - /// # Example - /// - /// ``` - /// use embassy_nxp::gpio::Flex; - /// - /// let p = embassy_nxp::init(Default::default()); - /// let pin = Flex::new(p.PIO1_15); - /// - /// assert_eq!(pin.pin_number(), 15 as u8); - /// ``` - pub fn pin_number(&self) -> u8 { - self.pin.pin_number() - } - - /// Get the bit mask for this pin. Useful for setting or clearing bits in a register. Note: - /// PIOx_0 is bit 0, PIOx_1 is bit 1, etc. - /// - /// # Example - /// - /// ``` - /// use embassy_nxp::gpio::Flex; - /// - /// let p = embassy_nxp::init(Default::default()); - /// let pin = Flex::new(p.PIO1_3); - /// - /// assert_eq!(pin.bit(), 0b0000_1000); - /// ``` - pub fn bit(&self) -> u32 { - 1 << self.pin.pin_number() - } - - /// Set the pin to digital mode. This is required for using a pin as a GPIO pin. The default - /// setting for pins is (usually) non-digital. - fn set_as_digital(&mut self) { - match_iocon!(register, iocon_reg(), self.pin_bank(), self.pin_number(), { - register.modify(|_, w| w.digimode().digital()); - }); - } - - /// Set the pin in output mode. This implies setting the pin to digital mode, which this - /// function handles itself. - pub fn set_as_output(&mut self) { - self.set_as_digital(); - gpio_reg().dirset[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirsetp().bits(self.bit()) }) - } - - pub fn set_as_input(&mut self) { - self.set_as_digital(); - gpio_reg().dirclr[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirclrp().bits(self.bit()) }) - } -} - -/// Sealed trait for pins. This trait is sealed and cannot be implemented outside of this crate. -pub(crate) trait SealedPin: Sized { - fn pin_bank(&self) -> Bank; - fn pin_number(&self) -> u8; -} - -/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an -/// [AnyPin]. By default, this trait is sealed and cannot be implemented outside of the -/// `embassy-nxp` crate due to the [SealedPin] trait. -#[allow(private_bounds)] -pub trait Pin: PeripheralType + Into + SealedPin + Sized + 'static { - /// Returns the pin number within a bank - #[inline] - fn pin(&self) -> u8 { - self.pin_number() - } - - /// Returns the bank of this pin - #[inline] - fn bank(&self) -> Bank { - self.pin_bank() - } -} - -/// Type-erased GPIO pin. -pub struct AnyPin { - pin_bank: Bank, - pin_number: u8, -} - -impl AnyPin { - /// Unsafely create a new type-erased pin. - /// - /// # Safety - /// - /// You must ensure that you’re only using one instance of this type at a time. - pub unsafe fn steal(pin_bank: Bank, pin_number: u8) -> Peri<'static, Self> { - Peri::new_unchecked(Self { pin_bank, pin_number }) - } -} - -impl_peripheral!(AnyPin); - -impl Pin for AnyPin {} -impl SealedPin for AnyPin { - #[inline] - fn pin_bank(&self) -> Bank { - self.pin_bank - } - - #[inline] - fn pin_number(&self) -> u8 { - self.pin_number - } -} - -macro_rules! impl_pin { - ($name:ident, $bank:expr, $pin_num:expr) => { - impl Pin for peripherals::$name {} - impl SealedPin for peripherals::$name { - #[inline] - fn pin_bank(&self) -> Bank { - $bank - } - - #[inline] - fn pin_number(&self) -> u8 { - $pin_num - } - } - - impl From for crate::gpio::AnyPin { - fn from(val: peripherals::$name) -> Self { - Self { - pin_bank: val.pin_bank(), - pin_number: val.pin_number(), - } - } - } - }; -} - -impl_pin!(PIO0_0, Bank::Bank0, 0); -impl_pin!(PIO0_1, Bank::Bank0, 1); -impl_pin!(PIO0_2, Bank::Bank0, 2); -impl_pin!(PIO0_3, Bank::Bank0, 3); -impl_pin!(PIO0_4, Bank::Bank0, 4); -impl_pin!(PIO0_5, Bank::Bank0, 5); -impl_pin!(PIO0_6, Bank::Bank0, 6); -impl_pin!(PIO0_7, Bank::Bank0, 7); -impl_pin!(PIO0_8, Bank::Bank0, 8); -impl_pin!(PIO0_9, Bank::Bank0, 9); -impl_pin!(PIO0_10, Bank::Bank0, 10); -impl_pin!(PIO0_11, Bank::Bank0, 11); -impl_pin!(PIO0_12, Bank::Bank0, 12); -impl_pin!(PIO0_13, Bank::Bank0, 13); -impl_pin!(PIO0_14, Bank::Bank0, 14); -impl_pin!(PIO0_15, Bank::Bank0, 15); -impl_pin!(PIO0_16, Bank::Bank0, 16); -impl_pin!(PIO0_17, Bank::Bank0, 17); -impl_pin!(PIO0_18, Bank::Bank0, 18); -impl_pin!(PIO0_19, Bank::Bank0, 19); -impl_pin!(PIO0_20, Bank::Bank0, 20); -impl_pin!(PIO0_21, Bank::Bank0, 21); -impl_pin!(PIO0_22, Bank::Bank0, 22); -impl_pin!(PIO0_23, Bank::Bank0, 23); -impl_pin!(PIO0_24, Bank::Bank0, 24); -impl_pin!(PIO0_25, Bank::Bank0, 25); -impl_pin!(PIO0_26, Bank::Bank0, 26); -impl_pin!(PIO0_27, Bank::Bank0, 27); -impl_pin!(PIO0_28, Bank::Bank0, 28); -impl_pin!(PIO0_29, Bank::Bank0, 29); -impl_pin!(PIO0_30, Bank::Bank0, 30); -impl_pin!(PIO0_31, Bank::Bank0, 31); -impl_pin!(PIO1_0, Bank::Bank1, 0); -impl_pin!(PIO1_1, Bank::Bank1, 1); -impl_pin!(PIO1_2, Bank::Bank1, 2); -impl_pin!(PIO1_3, Bank::Bank1, 3); -impl_pin!(PIO1_4, Bank::Bank1, 4); -impl_pin!(PIO1_5, Bank::Bank1, 5); -impl_pin!(PIO1_6, Bank::Bank1, 6); -impl_pin!(PIO1_7, Bank::Bank1, 7); -impl_pin!(PIO1_8, Bank::Bank1, 8); -impl_pin!(PIO1_9, Bank::Bank1, 9); -impl_pin!(PIO1_10, Bank::Bank1, 10); -impl_pin!(PIO1_11, Bank::Bank1, 11); -impl_pin!(PIO1_12, Bank::Bank1, 12); -impl_pin!(PIO1_13, Bank::Bank1, 13); -impl_pin!(PIO1_14, Bank::Bank1, 14); -impl_pin!(PIO1_15, Bank::Bank1, 15); -impl_pin!(PIO1_16, Bank::Bank1, 16); -impl_pin!(PIO1_17, Bank::Bank1, 17); -impl_pin!(PIO1_18, Bank::Bank1, 18); -impl_pin!(PIO1_19, Bank::Bank1, 19); -impl_pin!(PIO1_20, Bank::Bank1, 20); -impl_pin!(PIO1_21, Bank::Bank1, 21); -impl_pin!(PIO1_22, Bank::Bank1, 22); -impl_pin!(PIO1_23, Bank::Bank1, 23); -impl_pin!(PIO1_24, Bank::Bank1, 24); -impl_pin!(PIO1_25, Bank::Bank1, 25); -impl_pin!(PIO1_26, Bank::Bank1, 26); -impl_pin!(PIO1_27, Bank::Bank1, 27); -impl_pin!(PIO1_28, Bank::Bank1, 28); -impl_pin!(PIO1_29, Bank::Bank1, 29); -impl_pin!(PIO1_30, Bank::Bank1, 30); -impl_pin!(PIO1_31, Bank::Bank1, 31); +#[cfg_attr(feature = "lpc55", path = "./gpio/lpc55.rs")] +mod inner; +pub use inner::*; diff --git a/embassy-nxp/src/gpio/lpc55.rs b/embassy-nxp/src/gpio/lpc55.rs new file mode 100644 index 000000000..94cd8b7f8 --- /dev/null +++ b/embassy-nxp/src/gpio/lpc55.rs @@ -0,0 +1,677 @@ +use embassy_hal_internal::{impl_peripheral, PeripheralType}; + +use crate::{peripherals, Peri}; + +pub(crate) fn init() { + // Enable clocks for GPIO, PINT, and IOCON + syscon_reg() + .ahbclkctrl0 + .modify(|_, w| w.gpio0().enable().gpio1().enable().mux().enable().iocon().enable()); +} + +/// The GPIO pin level for pins set on "Digital" mode. +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum Level { + /// Logical low. Corresponds to 0V. + Low, + /// Logical high. Corresponds to VDD. + High, +} + +/// Pull setting for a GPIO input set on "Digital" mode. +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum Pull { + /// No pull. + None, + /// Internal pull-up resistor. + Up, + /// Internal pull-down resistor. + Down, +} + +/// The LPC55 boards have two GPIO banks, each with 32 pins. This enum represents the two banks. +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum Bank { + Bank0 = 0, + Bank1 = 1, +} + +/// GPIO output driver. Internally, this is a specialized [Flex] pin. +pub struct Output<'d> { + pub(crate) pin: Flex<'d>, +} + +impl<'d> Output<'d> { + /// Create GPIO output driver for a [Pin] with the provided [initial output](Level). + #[inline] + pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self { + let mut pin = Flex::new(pin); + pin.set_as_output(); + let mut result = Self { pin }; + + match initial_output { + Level::High => result.set_high(), + Level::Low => result.set_low(), + }; + + result + } + + pub fn set_high(&mut self) { + gpio_reg().set[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) + } + + pub fn set_low(&mut self) { + gpio_reg().clr[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) + } + + pub fn toggle(&mut self) { + gpio_reg().not[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) + } + + /// Get the current output level of the pin. Note that the value returned by this function is + /// the voltage level reported by the pin, not the value set by the output driver. + pub fn level(&self) -> Level { + let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits(); + if bits & self.pin.bit() != 0 { + Level::High + } else { + Level::Low + } + } +} + +/// GPIO input driver. Internally, this is a specialized [Flex] pin. +pub struct Input<'d> { + pub(crate) pin: Flex<'d>, +} + +impl<'d> Input<'d> { + /// Create GPIO output driver for a [Pin] with the provided [Pull]. + #[inline] + pub fn new(pin: Peri<'d, impl Pin>, pull: Pull) -> Self { + let mut pin = Flex::new(pin); + pin.set_as_input(); + let mut result = Self { pin }; + result.set_pull(pull); + + result + } + + /// Set the pull configuration for the pin. To disable the pull, use [Pull::None]. + pub fn set_pull(&mut self, pull: Pull) { + match_iocon!(register, iocon_reg(), self.pin.pin_bank(), self.pin.pin_number(), { + register.modify(|_, w| match pull { + Pull::None => w.mode().inactive(), + Pull::Up => w.mode().pull_up(), + Pull::Down => w.mode().pull_down(), + }); + }); + } + + /// Get the current input level of the pin. + pub fn read(&self) -> Level { + let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits(); + if bits & self.pin.bit() != 0 { + Level::High + } else { + Level::Low + } + } +} + +/// A flexible GPIO (digital mode) pin whose mode is not yet determined. Under the hood, this is a +/// reference to a type-erased pin called ["AnyPin"](AnyPin). +pub struct Flex<'d> { + pub(crate) pin: Peri<'d, AnyPin>, +} + +impl<'d> Flex<'d> { + /// Wrap the pin in a `Flex`. + /// + /// Note: you cannot assume that the pin will be in Digital mode after this call. + #[inline] + pub fn new(pin: Peri<'d, impl Pin>) -> Self { + Self { pin: pin.into() } + } + + /// Get the bank of this pin. See also [Bank]. + /// + /// # Example + /// + /// ``` + /// use embassy_nxp::gpio::{Bank, Flex}; + /// + /// let p = embassy_nxp::init(Default::default()); + /// let pin = Flex::new(p.PIO1_15); + /// + /// assert_eq!(pin.pin_bank(), Bank::Bank1); + /// ``` + pub fn pin_bank(&self) -> Bank { + self.pin.pin_bank() + } + + /// Get the number of this pin within its bank. See also [Bank]. + /// + /// # Example + /// + /// ``` + /// use embassy_nxp::gpio::Flex; + /// + /// let p = embassy_nxp::init(Default::default()); + /// let pin = Flex::new(p.PIO1_15); + /// + /// assert_eq!(pin.pin_number(), 15 as u8); + /// ``` + pub fn pin_number(&self) -> u8 { + self.pin.pin_number() + } + + /// Get the bit mask for this pin. Useful for setting or clearing bits in a register. Note: + /// PIOx_0 is bit 0, PIOx_1 is bit 1, etc. + /// + /// # Example + /// + /// ``` + /// use embassy_nxp::gpio::Flex; + /// + /// let p = embassy_nxp::init(Default::default()); + /// let pin = Flex::new(p.PIO1_3); + /// + /// assert_eq!(pin.bit(), 0b0000_1000); + /// ``` + pub fn bit(&self) -> u32 { + 1 << self.pin.pin_number() + } + + /// Set the pin to digital mode. This is required for using a pin as a GPIO pin. The default + /// setting for pins is (usually) non-digital. + fn set_as_digital(&mut self) { + match_iocon!(register, iocon_reg(), self.pin_bank(), self.pin_number(), { + register.modify(|_, w| w.digimode().digital()); + }); + } + + /// Set the pin in output mode. This implies setting the pin to digital mode, which this + /// function handles itself. + pub fn set_as_output(&mut self) { + self.set_as_digital(); + gpio_reg().dirset[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirsetp().bits(self.bit()) }) + } + + pub fn set_as_input(&mut self) { + self.set_as_digital(); + gpio_reg().dirclr[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirclrp().bits(self.bit()) }) + } +} + +/// Sealed trait for pins. This trait is sealed and cannot be implemented outside of this crate. +pub(crate) trait SealedPin: Sized { + fn pin_bank(&self) -> Bank; + fn pin_number(&self) -> u8; +} + +/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an +/// [AnyPin]. By default, this trait is sealed and cannot be implemented outside of the +/// `embassy-nxp` crate due to the [SealedPin] trait. +#[allow(private_bounds)] +pub trait Pin: PeripheralType + Into + SealedPin + Sized + 'static { + /// Returns the pin number within a bank + #[inline] + fn pin(&self) -> u8 { + self.pin_number() + } + + /// Returns the bank of this pin + #[inline] + fn bank(&self) -> Bank { + self.pin_bank() + } +} + +/// Type-erased GPIO pin. +pub struct AnyPin { + pin_bank: Bank, + pin_number: u8, +} + +impl AnyPin { + /// Unsafely create a new type-erased pin. + /// + /// # Safety + /// + /// You must ensure that you’re only using one instance of this type at a time. + pub unsafe fn steal(pin_bank: Bank, pin_number: u8) -> Peri<'static, Self> { + Peri::new_unchecked(Self { pin_bank, pin_number }) + } +} + +impl_peripheral!(AnyPin); + +impl Pin for AnyPin {} +impl SealedPin for AnyPin { + #[inline] + fn pin_bank(&self) -> Bank { + self.pin_bank + } + + #[inline] + fn pin_number(&self) -> u8 { + self.pin_number + } +} + +/// Get the GPIO register block. This is used to configure all GPIO pins. +/// +/// # Safety +/// Due to the type system of peripherals, access to the settings of a single pin is possible only +/// by a single thread at a time. Read/Write operations on a single registers are NOT atomic. You +/// must ensure that the GPIO registers are not accessed concurrently by multiple threads. +pub(crate) fn gpio_reg() -> &'static lpc55_pac::gpio::RegisterBlock { + unsafe { &*lpc55_pac::GPIO::ptr() } +} + +/// Get the IOCON register block. +/// +/// # Safety +/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO +/// registers are not accessed concurrently by multiple threads. +pub(crate) fn iocon_reg() -> &'static lpc55_pac::iocon::RegisterBlock { + unsafe { &*lpc55_pac::IOCON::ptr() } +} + +/// Get the INPUTMUX register block. +/// +/// # Safety +/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO +/// registers are not accessed concurrently by multiple threads. +pub(crate) fn inputmux_reg() -> &'static lpc55_pac::inputmux::RegisterBlock { + unsafe { &*lpc55_pac::INPUTMUX::ptr() } +} + +/// Get the SYSCON register block. +/// +/// # Safety +/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO +/// registers are not accessed concurrently by multiple threads. +pub(crate) fn syscon_reg() -> &'static lpc55_pac::syscon::RegisterBlock { + unsafe { &*lpc55_pac::SYSCON::ptr() } +} + +/// Get the PINT register block. +/// +/// # Safety +/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO +/// registers are not accessed concurrently by multiple threads. +pub(crate) fn pint_reg() -> &'static lpc55_pac::pint::RegisterBlock { + unsafe { &*lpc55_pac::PINT::ptr() } +} + +/// Match the pin bank and number of a pin to the corresponding IOCON register. +/// +/// # Example +/// ``` +/// use embassy_nxp::gpio::Bank; +/// use embassy_nxp::pac_utils::{iocon_reg, match_iocon}; +/// +/// // Make pin PIO1_6 digital and set it to pull-down mode. +/// match_iocon!(register, iocon_reg(), Bank::Bank1, 6, { +/// register.modify(|_, w| w.mode().pull_down().digimode().digital()); +/// }); +/// ``` +macro_rules! match_iocon { + ($register:ident, $iocon_register:expr, $pin_bank:expr, $pin_number:expr, $action:expr) => { + match ($pin_bank, $pin_number) { + (Bank::Bank0, 0) => { + let $register = &($iocon_register).pio0_0; + $action; + } + (Bank::Bank0, 1) => { + let $register = &($iocon_register).pio0_1; + $action; + } + (Bank::Bank0, 2) => { + let $register = &($iocon_register).pio0_2; + $action; + } + (Bank::Bank0, 3) => { + let $register = &($iocon_register).pio0_3; + $action; + } + (Bank::Bank0, 4) => { + let $register = &($iocon_register).pio0_4; + $action; + } + (Bank::Bank0, 5) => { + let $register = &($iocon_register).pio0_5; + $action; + } + (Bank::Bank0, 6) => { + let $register = &($iocon_register).pio0_6; + $action; + } + (Bank::Bank0, 7) => { + let $register = &($iocon_register).pio0_7; + $action; + } + (Bank::Bank0, 8) => { + let $register = &($iocon_register).pio0_8; + $action; + } + (Bank::Bank0, 9) => { + let $register = &($iocon_register).pio0_9; + $action; + } + (Bank::Bank0, 10) => { + let $register = &($iocon_register).pio0_10; + $action; + } + (Bank::Bank0, 11) => { + let $register = &($iocon_register).pio0_11; + $action; + } + (Bank::Bank0, 12) => { + let $register = &($iocon_register).pio0_12; + $action; + } + (Bank::Bank0, 13) => { + let $register = &($iocon_register).pio0_13; + $action; + } + (Bank::Bank0, 14) => { + let $register = &($iocon_register).pio0_14; + $action; + } + (Bank::Bank0, 15) => { + let $register = &($iocon_register).pio0_15; + $action; + } + (Bank::Bank0, 16) => { + let $register = &($iocon_register).pio0_16; + $action; + } + (Bank::Bank0, 17) => { + let $register = &($iocon_register).pio0_17; + $action; + } + (Bank::Bank0, 18) => { + let $register = &($iocon_register).pio0_18; + $action; + } + (Bank::Bank0, 19) => { + let $register = &($iocon_register).pio0_19; + $action; + } + (Bank::Bank0, 20) => { + let $register = &($iocon_register).pio0_20; + $action; + } + (Bank::Bank0, 21) => { + let $register = &($iocon_register).pio0_21; + $action; + } + (Bank::Bank0, 22) => { + let $register = &($iocon_register).pio0_22; + $action; + } + (Bank::Bank0, 23) => { + let $register = &($iocon_register).pio0_23; + $action; + } + (Bank::Bank0, 24) => { + let $register = &($iocon_register).pio0_24; + $action; + } + (Bank::Bank0, 25) => { + let $register = &($iocon_register).pio0_25; + $action; + } + (Bank::Bank0, 26) => { + let $register = &($iocon_register).pio0_26; + $action; + } + (Bank::Bank0, 27) => { + let $register = &($iocon_register).pio0_27; + $action; + } + (Bank::Bank0, 28) => { + let $register = &($iocon_register).pio0_28; + $action; + } + (Bank::Bank0, 29) => { + let $register = &($iocon_register).pio0_29; + $action; + } + (Bank::Bank0, 30) => { + let $register = &($iocon_register).pio0_30; + $action; + } + (Bank::Bank0, 31) => { + let $register = &($iocon_register).pio0_31; + $action; + } + (Bank::Bank1, 0) => { + let $register = &($iocon_register).pio1_0; + $action; + } + (Bank::Bank1, 1) => { + let $register = &($iocon_register).pio1_1; + $action; + } + (Bank::Bank1, 2) => { + let $register = &($iocon_register).pio1_2; + $action; + } + (Bank::Bank1, 3) => { + let $register = &($iocon_register).pio1_3; + $action; + } + (Bank::Bank1, 4) => { + let $register = &($iocon_register).pio1_4; + $action; + } + (Bank::Bank1, 5) => { + let $register = &($iocon_register).pio1_5; + $action; + } + (Bank::Bank1, 6) => { + let $register = &($iocon_register).pio1_6; + $action; + } + (Bank::Bank1, 7) => { + let $register = &($iocon_register).pio1_7; + $action; + } + (Bank::Bank1, 8) => { + let $register = &($iocon_register).pio1_8; + $action; + } + (Bank::Bank1, 9) => { + let $register = &($iocon_register).pio1_9; + $action; + } + (Bank::Bank1, 10) => { + let $register = &($iocon_register).pio1_10; + $action; + } + (Bank::Bank1, 11) => { + let $register = &($iocon_register).pio1_11; + $action; + } + (Bank::Bank1, 12) => { + let $register = &($iocon_register).pio1_12; + $action; + } + (Bank::Bank1, 13) => { + let $register = &($iocon_register).pio1_13; + $action; + } + (Bank::Bank1, 14) => { + let $register = &($iocon_register).pio1_14; + $action; + } + (Bank::Bank1, 15) => { + let $register = &($iocon_register).pio1_15; + $action; + } + (Bank::Bank1, 16) => { + let $register = &($iocon_register).pio1_16; + $action; + } + (Bank::Bank1, 17) => { + let $register = &($iocon_register).pio1_17; + $action; + } + (Bank::Bank1, 18) => { + let $register = &($iocon_register).pio1_18; + $action; + } + (Bank::Bank1, 19) => { + let $register = &($iocon_register).pio1_19; + $action; + } + (Bank::Bank1, 20) => { + let $register = &($iocon_register).pio1_20; + $action; + } + (Bank::Bank1, 21) => { + let $register = &($iocon_register).pio1_21; + $action; + } + (Bank::Bank1, 22) => { + let $register = &($iocon_register).pio1_22; + $action; + } + (Bank::Bank1, 23) => { + let $register = &($iocon_register).pio1_23; + $action; + } + (Bank::Bank1, 24) => { + let $register = &($iocon_register).pio1_24; + $action; + } + (Bank::Bank1, 25) => { + let $register = &($iocon_register).pio1_25; + $action; + } + (Bank::Bank1, 26) => { + let $register = &($iocon_register).pio1_26; + $action; + } + (Bank::Bank1, 27) => { + let $register = &($iocon_register).pio1_27; + $action; + } + (Bank::Bank1, 28) => { + let $register = &($iocon_register).pio1_28; + $action; + } + (Bank::Bank1, 29) => { + let $register = &($iocon_register).pio1_29; + $action; + } + (Bank::Bank1, 30) => { + let $register = &($iocon_register).pio1_30; + $action; + } + (Bank::Bank1, 31) => { + let $register = &($iocon_register).pio1_31; + $action; + } + _ => unreachable!(), + } + }; +} + +pub(crate) use match_iocon; + +macro_rules! impl_pin { + ($name:ident, $bank:expr, $pin_num:expr) => { + impl Pin for peripherals::$name {} + impl SealedPin for peripherals::$name { + #[inline] + fn pin_bank(&self) -> Bank { + $bank + } + + #[inline] + fn pin_number(&self) -> u8 { + $pin_num + } + } + + impl From for crate::gpio::AnyPin { + fn from(val: peripherals::$name) -> Self { + Self { + pin_bank: val.pin_bank(), + pin_number: val.pin_number(), + } + } + } + }; +} + +impl_pin!(PIO0_0, Bank::Bank0, 0); +impl_pin!(PIO0_1, Bank::Bank0, 1); +impl_pin!(PIO0_2, Bank::Bank0, 2); +impl_pin!(PIO0_3, Bank::Bank0, 3); +impl_pin!(PIO0_4, Bank::Bank0, 4); +impl_pin!(PIO0_5, Bank::Bank0, 5); +impl_pin!(PIO0_6, Bank::Bank0, 6); +impl_pin!(PIO0_7, Bank::Bank0, 7); +impl_pin!(PIO0_8, Bank::Bank0, 8); +impl_pin!(PIO0_9, Bank::Bank0, 9); +impl_pin!(PIO0_10, Bank::Bank0, 10); +impl_pin!(PIO0_11, Bank::Bank0, 11); +impl_pin!(PIO0_12, Bank::Bank0, 12); +impl_pin!(PIO0_13, Bank::Bank0, 13); +impl_pin!(PIO0_14, Bank::Bank0, 14); +impl_pin!(PIO0_15, Bank::Bank0, 15); +impl_pin!(PIO0_16, Bank::Bank0, 16); +impl_pin!(PIO0_17, Bank::Bank0, 17); +impl_pin!(PIO0_18, Bank::Bank0, 18); +impl_pin!(PIO0_19, Bank::Bank0, 19); +impl_pin!(PIO0_20, Bank::Bank0, 20); +impl_pin!(PIO0_21, Bank::Bank0, 21); +impl_pin!(PIO0_22, Bank::Bank0, 22); +impl_pin!(PIO0_23, Bank::Bank0, 23); +impl_pin!(PIO0_24, Bank::Bank0, 24); +impl_pin!(PIO0_25, Bank::Bank0, 25); +impl_pin!(PIO0_26, Bank::Bank0, 26); +impl_pin!(PIO0_27, Bank::Bank0, 27); +impl_pin!(PIO0_28, Bank::Bank0, 28); +impl_pin!(PIO0_29, Bank::Bank0, 29); +impl_pin!(PIO0_30, Bank::Bank0, 30); +impl_pin!(PIO0_31, Bank::Bank0, 31); +impl_pin!(PIO1_0, Bank::Bank1, 0); +impl_pin!(PIO1_1, Bank::Bank1, 1); +impl_pin!(PIO1_2, Bank::Bank1, 2); +impl_pin!(PIO1_3, Bank::Bank1, 3); +impl_pin!(PIO1_4, Bank::Bank1, 4); +impl_pin!(PIO1_5, Bank::Bank1, 5); +impl_pin!(PIO1_6, Bank::Bank1, 6); +impl_pin!(PIO1_7, Bank::Bank1, 7); +impl_pin!(PIO1_8, Bank::Bank1, 8); +impl_pin!(PIO1_9, Bank::Bank1, 9); +impl_pin!(PIO1_10, Bank::Bank1, 10); +impl_pin!(PIO1_11, Bank::Bank1, 11); +impl_pin!(PIO1_12, Bank::Bank1, 12); +impl_pin!(PIO1_13, Bank::Bank1, 13); +impl_pin!(PIO1_14, Bank::Bank1, 14); +impl_pin!(PIO1_15, Bank::Bank1, 15); +impl_pin!(PIO1_16, Bank::Bank1, 16); +impl_pin!(PIO1_17, Bank::Bank1, 17); +impl_pin!(PIO1_18, Bank::Bank1, 18); +impl_pin!(PIO1_19, Bank::Bank1, 19); +impl_pin!(PIO1_20, Bank::Bank1, 20); +impl_pin!(PIO1_21, Bank::Bank1, 21); +impl_pin!(PIO1_22, Bank::Bank1, 22); +impl_pin!(PIO1_23, Bank::Bank1, 23); +impl_pin!(PIO1_24, Bank::Bank1, 24); +impl_pin!(PIO1_25, Bank::Bank1, 25); +impl_pin!(PIO1_26, Bank::Bank1, 26); +impl_pin!(PIO1_27, Bank::Bank1, 27); +impl_pin!(PIO1_28, Bank::Bank1, 28); +impl_pin!(PIO1_29, Bank::Bank1, 29); +impl_pin!(PIO1_30, Bank::Bank1, 30); +impl_pin!(PIO1_31, Bank::Bank1, 31); diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs index ad2056c06..433aca9e0 100644 --- a/embassy-nxp/src/lib.rs +++ b/embassy-nxp/src/lib.rs @@ -1,11 +1,19 @@ #![no_std] pub mod gpio; -mod pac_utils; +#[cfg(feature = "lpc55")] pub mod pint; -pub use embassy_hal_internal::Peri; -pub use lpc55_pac as pac; +// This mod MUST go last, so that it sees all the `impl_foo!` macros +#[cfg_attr(feature = "lpc55", path = "chips/lpc55.rs")] +mod chip; + +#[cfg(feature = "unstable-pac")] +pub use chip::pac; +#[cfg(not(feature = "unstable-pac"))] +pub(crate) use chip::pac; +pub use chip::{peripherals, Peripherals}; +pub use embassy_hal_internal::{Peri, PeripheralType}; /// Initialize the `embassy-nxp` HAL with the provided configuration. /// @@ -13,81 +21,15 @@ pub use lpc55_pac as pac; /// /// This should only be called once and at startup, otherwise it panics. pub fn init(_config: config::Config) -> Peripherals { - gpio::init(); - pint::init(); + #[cfg(feature = "lpc55")] + { + gpio::init(); + pint::init(); + } crate::Peripherals::take() } -embassy_hal_internal::peripherals! { - // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other - // peripheral types (e.g. I2C). - PIO0_0, - PIO0_1, - PIO0_2, - PIO0_3, - PIO0_4, - PIO0_5, - PIO0_6, - PIO0_7, - PIO0_8, - PIO0_9, - PIO0_10, - PIO0_11, - PIO0_12, - PIO0_13, - PIO0_14, - PIO0_15, - PIO0_16, - PIO0_17, - PIO0_18, - PIO0_19, - PIO0_20, - PIO0_21, - PIO0_22, - PIO0_23, - PIO0_24, - PIO0_25, - PIO0_26, - PIO0_27, - PIO0_28, - PIO0_29, - PIO0_30, - PIO0_31, - PIO1_0, - PIO1_1, - PIO1_2, - PIO1_3, - PIO1_4, - PIO1_5, - PIO1_6, - PIO1_7, - PIO1_8, - PIO1_9, - PIO1_10, - PIO1_11, - PIO1_12, - PIO1_13, - PIO1_14, - PIO1_15, - PIO1_16, - PIO1_17, - PIO1_18, - PIO1_19, - PIO1_20, - PIO1_21, - PIO1_22, - PIO1_23, - PIO1_24, - PIO1_25, - PIO1_26, - PIO1_27, - PIO1_28, - PIO1_29, - PIO1_30, - PIO1_31, -} - /// HAL configuration for the NXP board. pub mod config { #[derive(Default)] diff --git a/embassy-nxp/src/pac_utils.rs b/embassy-nxp/src/pac_utils.rs deleted file mode 100644 index 86a807f6c..000000000 --- a/embassy-nxp/src/pac_utils.rs +++ /dev/null @@ -1,323 +0,0 @@ -/// Get the GPIO register block. This is used to configure all GPIO pins. -/// -/// # Safety -/// Due to the type system of peripherals, access to the settings of a single pin is possible only -/// by a single thread at a time. Read/Write operations on a single registers are NOT atomic. You -/// must ensure that the GPIO registers are not accessed concurrently by multiple threads. -pub(crate) fn gpio_reg() -> &'static lpc55_pac::gpio::RegisterBlock { - unsafe { &*lpc55_pac::GPIO::ptr() } -} - -/// Get the IOCON register block. -/// -/// # Safety -/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO -/// registers are not accessed concurrently by multiple threads. -pub(crate) fn iocon_reg() -> &'static lpc55_pac::iocon::RegisterBlock { - unsafe { &*lpc55_pac::IOCON::ptr() } -} - -/// Get the INPUTMUX register block. -/// -/// # Safety -/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO -/// registers are not accessed concurrently by multiple threads. -pub(crate) fn inputmux_reg() -> &'static lpc55_pac::inputmux::RegisterBlock { - unsafe { &*lpc55_pac::INPUTMUX::ptr() } -} - -/// Get the SYSCON register block. -/// -/// # Safety -/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO -/// registers are not accessed concurrently by multiple threads. -pub(crate) fn syscon_reg() -> &'static lpc55_pac::syscon::RegisterBlock { - unsafe { &*lpc55_pac::SYSCON::ptr() } -} - -/// Get the PINT register block. -/// -/// # Safety -/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO -/// registers are not accessed concurrently by multiple threads. -pub(crate) fn pint_reg() -> &'static lpc55_pac::pint::RegisterBlock { - unsafe { &*lpc55_pac::PINT::ptr() } -} - -/// Match the pin bank and number of a pin to the corresponding IOCON register. -/// -/// # Example -/// ``` -/// use embassy_nxp::gpio::Bank; -/// use embassy_nxp::pac_utils::{iocon_reg, match_iocon}; -/// -/// // Make pin PIO1_6 digital and set it to pull-down mode. -/// match_iocon!(register, iocon_reg(), Bank::Bank1, 6, { -/// register.modify(|_, w| w.mode().pull_down().digimode().digital()); -/// }); -/// ``` -macro_rules! match_iocon { - ($register:ident, $iocon_register:expr, $pin_bank:expr, $pin_number:expr, $action:expr) => { - match ($pin_bank, $pin_number) { - (Bank::Bank0, 0) => { - let $register = &($iocon_register).pio0_0; - $action; - } - (Bank::Bank0, 1) => { - let $register = &($iocon_register).pio0_1; - $action; - } - (Bank::Bank0, 2) => { - let $register = &($iocon_register).pio0_2; - $action; - } - (Bank::Bank0, 3) => { - let $register = &($iocon_register).pio0_3; - $action; - } - (Bank::Bank0, 4) => { - let $register = &($iocon_register).pio0_4; - $action; - } - (Bank::Bank0, 5) => { - let $register = &($iocon_register).pio0_5; - $action; - } - (Bank::Bank0, 6) => { - let $register = &($iocon_register).pio0_6; - $action; - } - (Bank::Bank0, 7) => { - let $register = &($iocon_register).pio0_7; - $action; - } - (Bank::Bank0, 8) => { - let $register = &($iocon_register).pio0_8; - $action; - } - (Bank::Bank0, 9) => { - let $register = &($iocon_register).pio0_9; - $action; - } - (Bank::Bank0, 10) => { - let $register = &($iocon_register).pio0_10; - $action; - } - (Bank::Bank0, 11) => { - let $register = &($iocon_register).pio0_11; - $action; - } - (Bank::Bank0, 12) => { - let $register = &($iocon_register).pio0_12; - $action; - } - (Bank::Bank0, 13) => { - let $register = &($iocon_register).pio0_13; - $action; - } - (Bank::Bank0, 14) => { - let $register = &($iocon_register).pio0_14; - $action; - } - (Bank::Bank0, 15) => { - let $register = &($iocon_register).pio0_15; - $action; - } - (Bank::Bank0, 16) => { - let $register = &($iocon_register).pio0_16; - $action; - } - (Bank::Bank0, 17) => { - let $register = &($iocon_register).pio0_17; - $action; - } - (Bank::Bank0, 18) => { - let $register = &($iocon_register).pio0_18; - $action; - } - (Bank::Bank0, 19) => { - let $register = &($iocon_register).pio0_19; - $action; - } - (Bank::Bank0, 20) => { - let $register = &($iocon_register).pio0_20; - $action; - } - (Bank::Bank0, 21) => { - let $register = &($iocon_register).pio0_21; - $action; - } - (Bank::Bank0, 22) => { - let $register = &($iocon_register).pio0_22; - $action; - } - (Bank::Bank0, 23) => { - let $register = &($iocon_register).pio0_23; - $action; - } - (Bank::Bank0, 24) => { - let $register = &($iocon_register).pio0_24; - $action; - } - (Bank::Bank0, 25) => { - let $register = &($iocon_register).pio0_25; - $action; - } - (Bank::Bank0, 26) => { - let $register = &($iocon_register).pio0_26; - $action; - } - (Bank::Bank0, 27) => { - let $register = &($iocon_register).pio0_27; - $action; - } - (Bank::Bank0, 28) => { - let $register = &($iocon_register).pio0_28; - $action; - } - (Bank::Bank0, 29) => { - let $register = &($iocon_register).pio0_29; - $action; - } - (Bank::Bank0, 30) => { - let $register = &($iocon_register).pio0_30; - $action; - } - (Bank::Bank0, 31) => { - let $register = &($iocon_register).pio0_31; - $action; - } - (Bank::Bank1, 0) => { - let $register = &($iocon_register).pio1_0; - $action; - } - (Bank::Bank1, 1) => { - let $register = &($iocon_register).pio1_1; - $action; - } - (Bank::Bank1, 2) => { - let $register = &($iocon_register).pio1_2; - $action; - } - (Bank::Bank1, 3) => { - let $register = &($iocon_register).pio1_3; - $action; - } - (Bank::Bank1, 4) => { - let $register = &($iocon_register).pio1_4; - $action; - } - (Bank::Bank1, 5) => { - let $register = &($iocon_register).pio1_5; - $action; - } - (Bank::Bank1, 6) => { - let $register = &($iocon_register).pio1_6; - $action; - } - (Bank::Bank1, 7) => { - let $register = &($iocon_register).pio1_7; - $action; - } - (Bank::Bank1, 8) => { - let $register = &($iocon_register).pio1_8; - $action; - } - (Bank::Bank1, 9) => { - let $register = &($iocon_register).pio1_9; - $action; - } - (Bank::Bank1, 10) => { - let $register = &($iocon_register).pio1_10; - $action; - } - (Bank::Bank1, 11) => { - let $register = &($iocon_register).pio1_11; - $action; - } - (Bank::Bank1, 12) => { - let $register = &($iocon_register).pio1_12; - $action; - } - (Bank::Bank1, 13) => { - let $register = &($iocon_register).pio1_13; - $action; - } - (Bank::Bank1, 14) => { - let $register = &($iocon_register).pio1_14; - $action; - } - (Bank::Bank1, 15) => { - let $register = &($iocon_register).pio1_15; - $action; - } - (Bank::Bank1, 16) => { - let $register = &($iocon_register).pio1_16; - $action; - } - (Bank::Bank1, 17) => { - let $register = &($iocon_register).pio1_17; - $action; - } - (Bank::Bank1, 18) => { - let $register = &($iocon_register).pio1_18; - $action; - } - (Bank::Bank1, 19) => { - let $register = &($iocon_register).pio1_19; - $action; - } - (Bank::Bank1, 20) => { - let $register = &($iocon_register).pio1_20; - $action; - } - (Bank::Bank1, 21) => { - let $register = &($iocon_register).pio1_21; - $action; - } - (Bank::Bank1, 22) => { - let $register = &($iocon_register).pio1_22; - $action; - } - (Bank::Bank1, 23) => { - let $register = &($iocon_register).pio1_23; - $action; - } - (Bank::Bank1, 24) => { - let $register = &($iocon_register).pio1_24; - $action; - } - (Bank::Bank1, 25) => { - let $register = &($iocon_register).pio1_25; - $action; - } - (Bank::Bank1, 26) => { - let $register = &($iocon_register).pio1_26; - $action; - } - (Bank::Bank1, 27) => { - let $register = &($iocon_register).pio1_27; - $action; - } - (Bank::Bank1, 28) => { - let $register = &($iocon_register).pio1_28; - $action; - } - (Bank::Bank1, 29) => { - let $register = &($iocon_register).pio1_29; - $action; - } - (Bank::Bank1, 30) => { - let $register = &($iocon_register).pio1_30; - $action; - } - (Bank::Bank1, 31) => { - let $register = &($iocon_register).pio1_31; - $action; - } - _ => unreachable!(), - } - }; -} - -pub(crate) use match_iocon; diff --git a/embassy-nxp/src/pint.rs b/embassy-nxp/src/pint.rs index 8d6dc1277..dc117e7e3 100644 --- a/embassy-nxp/src/pint.rs +++ b/embassy-nxp/src/pint.rs @@ -7,9 +7,8 @@ use core::task::{Context, Poll}; use critical_section::Mutex; use embassy_sync::waitqueue::AtomicWaker; -use crate::gpio::{self, AnyPin, Level, SealedPin}; +use crate::gpio::{self, inputmux_reg, pint_reg, syscon_reg, AnyPin, Level, SealedPin}; use crate::pac::interrupt; -use crate::pac_utils::*; use crate::Peri; struct PinInterrupt { -- cgit From e4aa539708781af2474240c5c16456ffe554754b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 9 Jul 2025 14:02:20 +0200 Subject: add embassy sync channel example for message passing between interrupt and task --- embassy-sync/src/channel.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs index dda91c651..a0e39fcb5 100644 --- a/embassy-sync/src/channel.rs +++ b/embassy-sync/src/channel.rs @@ -17,6 +17,31 @@ //! messages that it can store, and if this limit is reached, trying to send //! another message will result in an error being returned. //! +//! # Example: Message passing between task and interrupt handler +//! +//! ```rust +//! use embassy_sync::channel::Channel; +//! use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +//! +//! static SHARED_CHANNEL: Channel = Channel::new(); +//! +//! fn my_interrupt_handler() { +//! // Do some work.. +//! // ... +//! if let Err(e) = SHARED_CHANNEL.sender().try_send(42) { +//! // Channel is full.. +//! } +//! } +//! +//! async fn my_async_task() { +//! // ... +//! let receiver = SHARED_CHANNEL.receiver(); +//! loop { +//! let data_from_interrupt = receiver.receive().await; +//! // Do something with the data. +//! } +//! } +//! ``` use core::cell::RefCell; use core::future::Future; -- cgit From 42c8379c5a571aa76214cdd73ef05a2c720eeb6e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 9 Jul 2025 14:21:19 +0200 Subject: some minor documentation fixes --- embassy-sync/src/mutex.rs | 2 +- embassy-sync/src/pipe.rs | 8 ++++---- embassy-sync/src/priority_channel.rs | 4 ++-- embassy-sync/src/pubsub/publisher.rs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/embassy-sync/src/mutex.rs b/embassy-sync/src/mutex.rs index 7528a9f68..67c682704 100644 --- a/embassy-sync/src/mutex.rs +++ b/embassy-sync/src/mutex.rs @@ -23,7 +23,7 @@ struct State { /// Async mutex. /// -/// The mutex is generic over a blocking [`RawMutex`](crate::blocking_mutex::raw::RawMutex). +/// The mutex is generic over a blocking [RawMutex]. /// The raw mutex is used to guard access to the internal "is locked" flag. It /// is held for very short periods only, while locking and unlocking. It is *not* held /// for the entire time the async Mutex is locked. diff --git a/embassy-sync/src/pipe.rs b/embassy-sync/src/pipe.rs index 2598652d2..df3b28b45 100644 --- a/embassy-sync/src/pipe.rs +++ b/embassy-sync/src/pipe.rs @@ -152,7 +152,7 @@ where impl<'p, M, const N: usize> Unpin for ReadFuture<'p, M, N> where M: RawMutex {} -/// Future returned by [`Pipe::fill_buf`] and [`Reader::fill_buf`]. +/// Future returned by [`Reader::fill_buf`]. #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct FillBufFuture<'p, M, const N: usize> where @@ -587,7 +587,7 @@ where } } -/// Write-only access to a [`DynamicPipe`]. +/// Write-only access to the dynamic pipe. pub struct DynamicWriter<'p> { pipe: &'p dyn DynamicPipe, } @@ -657,7 +657,7 @@ where } } -/// Read-only access to a [`DynamicPipe`]. +/// Read-only access to a dynamic pipe. pub struct DynamicReader<'p> { pipe: &'p dyn DynamicPipe, } @@ -742,7 +742,7 @@ where } } -/// Future returned by [`DynamicPipe::fill_buf`] and [`DynamicReader::fill_buf`]. +/// Future returned by [`DynamicReader::fill_buf`]. #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct DynamicFillBufFuture<'p> { pipe: Option<&'p dyn DynamicPipe>, diff --git a/embassy-sync/src/priority_channel.rs b/embassy-sync/src/priority_channel.rs index 623c52993..a6fbe8def 100644 --- a/embassy-sync/src/priority_channel.rs +++ b/embassy-sync/src/priority_channel.rs @@ -1,7 +1,7 @@ //! A queue for sending values between asynchronous tasks. //! //! Similar to a [`Channel`](crate::channel::Channel), however [`PriorityChannel`] sifts higher priority items to the front of the queue. -//! Priority is determined by the `Ord` trait. Priority behavior is determined by the [`Kind`](heapless::binary_heap::Kind) parameter of the channel. +//! Priority is determined by the `Ord` trait. Priority behavior is determined by the [Kind] parameter of the channel. use core::cell::RefCell; use core::future::Future; @@ -473,7 +473,7 @@ where /// received from the channel. /// /// Sent data may be reordered based on their priority within the channel. -/// For example, in a [`Max`](heapless::binary_heap::Max) [`PriorityChannel`] +/// For example, in a [Max][PriorityChannel] /// containing `u32`'s, data sent in the following order `[1, 2, 3]` will be received as `[3, 2, 1]`. pub struct PriorityChannel where diff --git a/embassy-sync/src/pubsub/publisher.rs b/embassy-sync/src/pubsub/publisher.rs index 7a1ab66de..2af1a9334 100644 --- a/embassy-sync/src/pubsub/publisher.rs +++ b/embassy-sync/src/pubsub/publisher.rs @@ -75,7 +75,7 @@ impl<'a, PSB: PubSubBehavior + ?Sized, T: Clone> Pub<'a, PSB, T> { self.channel.is_full() } - /// Create a [`futures::Sink`] adapter for this publisher. + /// Create a [futures_sink::Sink] adapter for this publisher. #[inline] pub const fn sink(&self) -> PubSink<'a, '_, PSB, T> { PubSink { publ: self, fut: None } -- cgit From da392ed942bbf78117f1dbba32208458de7cdea8 Mon Sep 17 00:00:00 2001 From: Robin Mueller <31589589+robamu@users.noreply.github.com> Date: Wed, 9 Jul 2025 14:26:20 +0200 Subject: Update embassy-sync/src/mutex.rs Co-authored-by: James Munns --- embassy-sync/src/mutex.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-sync/src/mutex.rs b/embassy-sync/src/mutex.rs index 67c682704..8496f34bf 100644 --- a/embassy-sync/src/mutex.rs +++ b/embassy-sync/src/mutex.rs @@ -23,7 +23,7 @@ struct State { /// Async mutex. /// -/// The mutex is generic over a blocking [RawMutex]. +/// The mutex is generic over a blocking [`RawMutex`]. /// The raw mutex is used to guard access to the internal "is locked" flag. It /// is held for very short periods only, while locking and unlocking. It is *not* held /// for the entire time the async Mutex is locked. -- cgit From 9892963da946aa896d9387916ee2b5d509b63e3b Mon Sep 17 00:00:00 2001 From: Robin Mueller <31589589+robamu@users.noreply.github.com> Date: Wed, 9 Jul 2025 14:28:18 +0200 Subject: Update embassy-sync/src/priority_channel.rs Co-authored-by: James Munns --- embassy-sync/src/priority_channel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-sync/src/priority_channel.rs b/embassy-sync/src/priority_channel.rs index a6fbe8def..6765a1503 100644 --- a/embassy-sync/src/priority_channel.rs +++ b/embassy-sync/src/priority_channel.rs @@ -1,7 +1,7 @@ //! A queue for sending values between asynchronous tasks. //! //! Similar to a [`Channel`](crate::channel::Channel), however [`PriorityChannel`] sifts higher priority items to the front of the queue. -//! Priority is determined by the `Ord` trait. Priority behavior is determined by the [Kind] parameter of the channel. +//! Priority is determined by the `Ord` trait. Priority behavior is determined by the [`Kind`] parameter of the channel. use core::cell::RefCell; use core::future::Future; -- cgit From 554fbef571cf9f4692d6361d66f962df926615df Mon Sep 17 00:00:00 2001 From: Robin Mueller <31589589+robamu@users.noreply.github.com> Date: Wed, 9 Jul 2025 14:31:04 +0200 Subject: Update embassy-sync/src/priority_channel.rs Co-authored-by: James Munns --- embassy-sync/src/priority_channel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-sync/src/priority_channel.rs b/embassy-sync/src/priority_channel.rs index 6765a1503..715a20e86 100644 --- a/embassy-sync/src/priority_channel.rs +++ b/embassy-sync/src/priority_channel.rs @@ -473,7 +473,7 @@ where /// received from the channel. /// /// Sent data may be reordered based on their priority within the channel. -/// For example, in a [Max][PriorityChannel] +/// For example, in a [`Max`] [`PriorityChannel`] /// containing `u32`'s, data sent in the following order `[1, 2, 3]` will be received as `[3, 2, 1]`. pub struct PriorityChannel where -- cgit From fa0f6bc670c29b799e0ef8812de041727c5d86f3 Mon Sep 17 00:00:00 2001 From: Robin Mueller <31589589+robamu@users.noreply.github.com> Date: Wed, 9 Jul 2025 14:31:42 +0200 Subject: Update embassy-sync/src/pubsub/publisher.rs Co-authored-by: James Munns --- embassy-sync/src/pubsub/publisher.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-sync/src/pubsub/publisher.rs b/embassy-sync/src/pubsub/publisher.rs index 2af1a9334..52a52f926 100644 --- a/embassy-sync/src/pubsub/publisher.rs +++ b/embassy-sync/src/pubsub/publisher.rs @@ -75,7 +75,7 @@ impl<'a, PSB: PubSubBehavior + ?Sized, T: Clone> Pub<'a, PSB, T> { self.channel.is_full() } - /// Create a [futures_sink::Sink] adapter for this publisher. + /// Create a [`futures_sink::Sink`] adapter for this publisher. #[inline] pub const fn sink(&self) -> PubSink<'a, '_, PSB, T> { PubSink { publ: self, fut: None } -- cgit From 9589c056d1963a2a342a4486181f3ce139ddeea5 Mon Sep 17 00:00:00 2001 From: dimi Date: Wed, 9 Jul 2025 20:00:49 +0200 Subject: fix typo --- embassy-stm32/src/timer/one_pulse.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs index c8f0cafe7..498d9c082 100644 --- a/embassy-stm32/src/timer/one_pulse.rs +++ b/embassy-stm32/src/timer/one_pulse.rs @@ -183,7 +183,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// as an output. pub fn new_ch2( tim: Peri<'d, T>, - _pin: TriggerPin<'d, T, Ch1>, + _pin: TriggerPin<'d, T, Ch2>, _irq: impl Binding> + 'd, freq: Hertz, pulse_end: u32, -- cgit From 423870d1f73e8b3110ae1ecc76989b112cb2da2b Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Thu, 10 Jul 2025 15:57:45 +0200 Subject: Introduce traits for special channels --- embassy-stm32/src/adc/g4.rs | 119 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 94 insertions(+), 25 deletions(-) diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs index 1fce3085a..cb3e342d8 100644 --- a/embassy-stm32/src/adc/g4.rs +++ b/embassy-stm32/src/adc/g4.rs @@ -24,44 +24,31 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60); #[cfg(stm32h7)] const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); -#[cfg(stm32g4)] -const VREF_CHANNEL: u8 = 18; -#[cfg(stm32g4)] -const TEMP_CHANNEL: u8 = 16; - -#[cfg(stm32h7)] -const VREF_CHANNEL: u8 = 19; -#[cfg(stm32h7)] -const TEMP_CHANNEL: u8 = 18; - -// TODO this should be 14 for H7a/b/35 -const VBAT_CHANNEL: u8 = 17; - // NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs /// Internal voltage reference channel. pub struct VrefInt; -impl AdcChannel for VrefInt {} -impl super::SealedAdcChannel for VrefInt { +impl AdcChannel for VrefInt {} +impl super::SealedAdcChannel for VrefInt { fn channel(&self) -> u8 { - VREF_CHANNEL + T::CHANNEL } } /// Internal temperature channel. pub struct Temperature; -impl AdcChannel for Temperature {} -impl super::SealedAdcChannel for Temperature { +impl AdcChannel for Temperature {} +impl super::SealedAdcChannel for Temperature { fn channel(&self) -> u8 { - TEMP_CHANNEL + T::CHANNEL } } /// Internal battery voltage channel. pub struct Vbat; -impl AdcChannel for Vbat {} -impl super::SealedAdcChannel for Vbat { +impl AdcChannel for Vbat {} +impl super::SealedAdcChannel for Vbat { fn channel(&self) -> u8 { - VBAT_CHANNEL + T::CHANNEL } } @@ -234,7 +221,10 @@ impl<'d, T: Instance> Adc<'d, T> { } /// Enable reading the voltage reference internal channel. - pub fn enable_vrefint(&self) -> VrefInt { + pub fn enable_vrefint(&self) -> VrefInt + where + T: VrefChannel, + { T::common_regs().ccr().modify(|reg| { reg.set_vrefen(true); }); @@ -243,7 +233,10 @@ impl<'d, T: Instance> Adc<'d, T> { } /// Enable reading the temperature internal channel. - pub fn enable_temperature(&self) -> Temperature { + pub fn enable_temperature(&self) -> Temperature + where + T: TemperatureChannel, + { T::common_regs().ccr().modify(|reg| { reg.set_vsenseen(true); }); @@ -252,7 +245,10 @@ impl<'d, T: Instance> Adc<'d, T> { } /// Enable reading the vbat internal channel. - pub fn enable_vbat(&self) -> Vbat { + pub fn enable_vbat(&self) -> Vbat + where + T: VBatChannel, + { T::common_regs().ccr().modify(|reg| { reg.set_vbaten(true); }); @@ -519,3 +515,76 @@ impl<'d, T: Instance> Adc<'d, T> { } } } + +/// Implemented for ADCs that have a Temperature channel +pub trait TemperatureChannel { + const CHANNEL: u8; +} +/// Implemented for ADCs that have a Vref channel +pub trait VrefChannel { + const CHANNEL: u8; +} +/// Implemented for ADCs that have a VBat channel +pub trait VBatChannel { + const CHANNEL: u8; +} + +#[cfg(stm32g4)] +mod g4 { + pub use super::*; + + impl TemperatureChannel for crate::peripherals::ADC1 { + const CHANNEL: u8 = 16; + } + + impl VrefChannel for crate::peripherals::ADC1 { + const CHANNEL: u8 = 18; + } + + impl VBatChannel for crate::peripherals::ADC1 { + const CHANNEL: u8 = 17; + } + + impl VrefChannel for crate::peripherals::ADC3 { + const CHANNEL: u8 = 18; + } + + impl VBatChannel for crate::peripherals::ADC3 { + const CHANNEL: u8 = 17; + } + + #[cfg(not(stm32g4x1))] + impl VrefChannel for crate::peripherals::ADC4 { + const CHANNEL: u8 = 18; + } + + #[cfg(not(stm32g4x1))] + impl TemperatureChannel for crate::peripherals::ADC5 { + const CHANNEL: u8 = 4; + } + + #[cfg(not(stm32g4x1))] + impl VrefChannel for crate::peripherals::ADC5 { + const CHANNEL: u8 = 18; + } + + #[cfg(not(stm32g4x1))] + impl VBatChannel for crate::peripherals::ADC5 { + const CHANNEL: u8 = 17; + } +} + +// TODO this should look at each ADC individually and impl the correct channels +#[cfg(stm32h7)] +mod h7 { + impl TemperatureChannel for T { + const CHANNEL: u8 = 18; + } + impl VrefChannel for T { + const CHANNEL: u8 = 19; + } + impl VBatChannel for T { + // TODO this should be 14 for H7a/b/35 + const CHANNEL: u8 = 17; + } +} -- cgit From 7b7a62a0c255890f26dc59c17f2e3815b71455e7 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Thu, 10 Jul 2025 18:45:31 +0200 Subject: Fixing the nrf54l drive configuration bug --- embassy-nrf/src/gpio.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index d02da9ac5..65f2d99f7 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs @@ -292,7 +292,7 @@ pub(crate) fn convert_drive(w: &mut pac::gpio::regs::PinCnf, drive: OutputDrive) } w.set_drive0(convert(drive.low)); - w.set_drive0(convert(drive.high)); + w.set_drive1(convert(drive.high)); } } -- cgit From a8e905f14ecf238675b343c037d20700ab6f4881 Mon Sep 17 00:00:00 2001 From: "robert.jeutter" Date: Thu, 5 Jun 2025 06:48:44 +0200 Subject: net-nrf91: add nrf9151 support. --- .github/ci/doc.sh | 1 + embassy-net-nrf91/src/lib.rs | 51 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 58ffe5f2e..06c61f8c0 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -42,6 +42,7 @@ docserver-builder -i ./embassy-usb-logger -o webroot/crates/embassy-usb-logger/g docserver-builder -i ./embassy-usb-synopsys-otg -o webroot/crates/embassy-usb-synopsys-otg/git.zup docserver-builder -i ./embassy-net -o webroot/crates/embassy-net/git.zup +docserver-builder -i ./embassy-net-nrf91 -o webroot/crates/embassy-net-nrf91/git.zup docserver-builder -i ./embassy-net-driver -o webroot/crates/embassy-net-driver/git.zup docserver-builder -i ./embassy-net-driver-channel -o webroot/crates/embassy-net-driver-channel/git.zup docserver-builder -i ./embassy-net-wiznet -o webroot/crates/embassy-net-wiznet/git.zup diff --git a/embassy-net-nrf91/src/lib.rs b/embassy-net-nrf91/src/lib.rs index 61fcaea1f..0bd9be0d9 100644 --- a/embassy-net-nrf91/src/lib.rs +++ b/embassy-net-nrf91/src/lib.rs @@ -119,14 +119,16 @@ async fn new_internal<'a>( let shmem_ptr = shmem.as_mut_ptr() as *mut u8; const SPU_REGION_SIZE: usize = 8192; // 8kb - assert!(shmem_len != 0); + trace!(" shmem_ptr = {}, shmem_len = {}", shmem_ptr, shmem_len); + + assert!(shmem_len != 0, "shmem length must not be zero"); assert!( shmem_len % SPU_REGION_SIZE == 0, "shmem length must be a multiple of 8kb" ); assert!( (shmem_ptr as usize) % SPU_REGION_SIZE == 0, - "shmem length must be a multiple of 8kb" + "shmem pointer must be 8kb-aligned" ); assert!( (shmem_ptr as usize + shmem_len) < 0x2002_0000, @@ -135,8 +137,15 @@ async fn new_internal<'a>( let spu = pac::SPU_S; debug!("Setting IPC RAM as nonsecure..."); + trace!( + " SPU_REGION_SIZE={}, shmem_ptr=0x{:08X}, shmem_len={}", + SPU_REGION_SIZE, + shmem_ptr as usize, + shmem_len + ); let region_start = (shmem_ptr as usize - 0x2000_0000) / SPU_REGION_SIZE; let region_end = region_start + shmem_len / SPU_REGION_SIZE; + trace!(" region_start={}, region_end={}", region_start, region_end); for i in region_start..region_end { spu.ramregion(i).perm().write(|w| { w.set_execute(true); @@ -154,13 +163,18 @@ async fn new_internal<'a>( end: unsafe { shmem_ptr.add(shmem_len) }, _phantom: PhantomData, }; - - let ipc = pac::IPC_NS; - let power = pac::POWER_S; + trace!( + " Allocator: start=0x{:08X}, end=0x{:08X}", + alloc.start as usize, + alloc.end as usize + ); let cb: &mut ControlBlock = alloc.alloc().write(unsafe { mem::zeroed() }); + let rx = alloc.alloc_bytes(RX_SIZE); + trace!(" RX buffer at {}, size={}", rx.as_ptr(), RX_SIZE); let trace = alloc.alloc_bytes(TRACE_SIZE); + trace!(" Trace buffer at {}, size={}", trace.as_ptr(), TRACE_SIZE); cb.version = 0x00010000; cb.rx_base = rx.as_mut_ptr() as _; @@ -174,8 +188,10 @@ async fn new_internal<'a>( cb.trace.base = trace.as_mut_ptr() as _; cb.trace.size = TRACE_SIZE; + let ipc = pac::IPC_NS; ipc.gpmem(0).write_value(cb as *mut _ as u32); ipc.gpmem(1).write_value(0); + trace!(" GPMEM[0]={:#X}, GPMEM[1]={}", cb as *mut _ as u32, 0); // connect task/event i to channel i for i in 0..8 { @@ -185,8 +201,9 @@ async fn new_internal<'a>( compiler_fence(Ordering::SeqCst); + let power = pac::POWER_S; // POWER.LTEMODEM.STARTN = 0 - // The reg is missing in the PAC?? + // TODO: The reg is missing in the PAC?? let startn = unsafe { (power.as_ptr() as *mut u32).add(0x610 / 4) }; unsafe { startn.write_volatile(0) } @@ -202,6 +219,8 @@ async fn new_internal<'a>( rx_control_list: ptr::null_mut(), rx_data_list: ptr::null_mut(), + rx_control_len: 0, + rx_data_len: 0, rx_seq_no: 0, rx_check: PointerChecker { start: rx.as_mut_ptr() as *mut u8, @@ -310,6 +329,10 @@ struct StateInner { rx_control_list: *mut List, rx_data_list: *mut List, + /// Number of entries in the control list + rx_control_len: usize, + /// Number of entries in the data list + rx_data_len: usize, rx_seq_no: u16, rx_check: PointerChecker, @@ -346,8 +369,11 @@ impl StateInner { self.rx_data_list = desc.data_list_ptr; let rx_control_len = unsafe { addr_of!((*self.rx_control_list).len).read_volatile() }; let rx_data_len = unsafe { addr_of!((*self.rx_data_list).len).read_volatile() }; - assert_eq!(rx_control_len, LIST_LEN); - assert_eq!(rx_data_len, LIST_LEN); + + trace!("modem control list length: {}", rx_control_len); + trace!("modem data list length: {}", rx_data_len); + self.rx_control_len = rx_control_len; + self.rx_data_len = rx_data_len; self.init = true; debug!("IPC initialized OK!"); @@ -463,7 +489,12 @@ impl StateInner { fn process(&mut self, list: *mut List, is_control: bool, ch: &mut ch::Runner) -> bool { let mut did_work = false; - for i in 0..LIST_LEN { + let max = if is_control { + self.rx_control_len + } else { + self.rx_data_len + }; + for i in 0..max { let item_ptr = unsafe { addr_of_mut!((*list).items[i]) }; let preamble = unsafe { addr_of!((*item_ptr).state).read_volatile() }; if preamble & 0xFF == 0x01 && preamble >> 16 == self.rx_seq_no as u32 { @@ -947,7 +978,7 @@ impl<'a> Runner<'a> { } } -const LIST_LEN: usize = 16; +const LIST_LEN: usize = 32; #[repr(C)] struct ControlBlock { -- cgit From b666a88ab175043d711c97b67b5b4d3bf409f102 Mon Sep 17 00:00:00 2001 From: korbin Date: Sun, 13 Jul 2025 20:30:26 -0600 Subject: make usb endpoint allocator methods accept an optional EndpointAddress --- embassy-nrf/src/usb/mod.rs | 51 +++++++++++++++++++++++-------- embassy-rp/src/usb.rs | 30 ++++++++++++++----- embassy-stm32/src/usb/otg.rs | 8 +++-- embassy-stm32/src/usb/usb.rs | 56 ++++++++++++++++++++++++++++------- embassy-usb-driver/src/lib.rs | 2 ++ embassy-usb-synopsys-otg/src/lib.rs | 43 +++++++++++++++++++-------- embassy-usb/src/builder.rs | 47 ++++++++++++++++++++++------- embassy-usb/src/class/cdc_acm.rs | 6 ++-- embassy-usb/src/class/cdc_ncm/mod.rs | 6 ++-- embassy-usb/src/class/cmsis_dap_v2.rs | 6 ++-- embassy-usb/src/class/hid.rs | 4 +-- embassy-usb/src/class/midi.rs | 4 +-- embassy-usb/src/class/uac1/speaker.rs | 3 +- examples/rp/src/bin/usb_raw_bulk.rs | 4 +-- examples/rp/src/bin/usb_webusb.rs | 4 +-- examples/rp235x/src/bin/usb_webusb.rs | 4 +-- 16 files changed, 204 insertions(+), 74 deletions(-) diff --git a/embassy-nrf/src/usb/mod.rs b/embassy-nrf/src/usb/mod.rs index 6cc1b0111..c6970fc0f 100644 --- a/embassy-nrf/src/usb/mod.rs +++ b/embassy-nrf/src/usb/mod.rs @@ -121,10 +121,11 @@ impl<'d, T: Instance, V: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, V fn alloc_endpoint_in( &mut self, ep_type: EndpointType, + ep_addr: Option, packet_size: u16, interval_ms: u8, ) -> Result { - let index = self.alloc_in.allocate(ep_type)?; + let index = self.alloc_in.allocate(ep_type, ep_addr)?; let ep_addr = EndpointAddress::from_parts(index, Direction::In); Ok(Endpoint::new(EndpointInfo { addr: ep_addr, @@ -137,10 +138,11 @@ impl<'d, T: Instance, V: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, V fn alloc_endpoint_out( &mut self, ep_type: EndpointType, + ep_addr: Option, packet_size: u16, interval_ms: u8, ) -> Result { - let index = self.alloc_out.allocate(ep_type)?; + let index = self.alloc_out.allocate(ep_type, ep_addr)?; let ep_addr = EndpointAddress::from_parts(index, Direction::Out); Ok(Endpoint::new(EndpointInfo { addr: ep_addr, @@ -734,7 +736,11 @@ impl Allocator { Self { used: 0 } } - fn allocate(&mut self, ep_type: EndpointType) -> Result { + fn allocate( + &mut self, + ep_type: EndpointType, + ep_addr: Option, + ) -> Result { // Endpoint addresses are fixed in hardware: // - 0x80 / 0x00 - Control EP0 // - 0x81 / 0x01 - Bulk/Interrupt EP1 @@ -748,16 +754,37 @@ impl Allocator { // Endpoint directions are allocated individually. - let alloc_index = match ep_type { - EndpointType::Isochronous => 8, - EndpointType::Control => return Err(driver::EndpointAllocError), - EndpointType::Interrupt | EndpointType::Bulk => { - // Find rightmost zero bit in 1..=7 - let ones = (self.used >> 1).trailing_ones() as usize; - if ones >= 7 { - return Err(driver::EndpointAllocError); + let alloc_index = if let Some(addr) = ep_addr { + // Use the specified endpoint address + let requested_index = addr.index(); + // Validate the requested index based on endpoint type + match ep_type { + EndpointType::Isochronous => { + if requested_index != 8 { + return Err(driver::EndpointAllocError); + } + } + EndpointType::Control => return Err(driver::EndpointAllocError), + EndpointType::Interrupt | EndpointType::Bulk => { + if requested_index < 1 || requested_index > 7 { + return Err(driver::EndpointAllocError); + } + } + } + requested_index + } else { + // Allocate any available endpoint + match ep_type { + EndpointType::Isochronous => 8, + EndpointType::Control => return Err(driver::EndpointAllocError), + EndpointType::Interrupt | EndpointType::Bulk => { + // Find rightmost zero bit in 1..=7 + let ones = (self.used >> 1).trailing_ones() as usize; + if ones >= 7 { + return Err(driver::EndpointAllocError); + } + ones + 1 } - ones + 1 } }; diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs index 96541ade6..671ecbd32 100644 --- a/embassy-rp/src/usb.rs +++ b/embassy-rp/src/usb.rs @@ -153,6 +153,7 @@ impl<'d, T: Instance> Driver<'d, T> { fn alloc_endpoint( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, ) -> Result, driver::EndpointAllocError> { @@ -169,12 +170,25 @@ impl<'d, T: Instance> Driver<'d, T> { Direction::In => &mut self.ep_in, }; - let index = alloc.iter_mut().enumerate().find(|(i, ep)| { - if *i == 0 { - return false; // reserved for control pipe + let index = if let Some(addr) = ep_addr { + // Use the specified endpoint address + let requested_index = addr.index(); + if requested_index == 0 || requested_index >= EP_COUNT { + return Err(EndpointAllocError); } - !ep.used - }); + if alloc[requested_index].used { + return Err(EndpointAllocError); + } + Some((requested_index, &mut alloc[requested_index])) + } else { + // Find any available endpoint + alloc.iter_mut().enumerate().find(|(i, ep)| { + if *i == 0 { + return false; // reserved for control pipe + } + !ep.used + }) + }; let (index, ep) = index.ok_or(EndpointAllocError)?; assert!(!ep.used); @@ -299,19 +313,21 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { fn alloc_endpoint_in( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, ) -> Result { - self.alloc_endpoint(ep_type, max_packet_size, interval_ms) + self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms) } fn alloc_endpoint_out( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, ) -> Result { - self.alloc_endpoint(ep_type, max_packet_size, interval_ms) + self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms) } fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) { diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index 590d1a427..3547ded00 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -231,19 +231,23 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> { fn alloc_endpoint_in( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, ) -> Result { - self.inner.alloc_endpoint_in(ep_type, max_packet_size, interval_ms) + self.inner + .alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms) } fn alloc_endpoint_out( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, ) -> Result { - self.inner.alloc_endpoint_out(ep_type, max_packet_size, interval_ms) + self.inner + .alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms) } fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) { diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index 3e8e74a1f..05c28aceb 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -362,6 +362,7 @@ impl<'d, T: Instance> Driver<'d, T> { fn alloc_endpoint( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, ) -> Result, driver::EndpointAllocError> { @@ -373,25 +374,56 @@ impl<'d, T: Instance> Driver<'d, T> { D::dir() ); - let index = self.alloc.iter_mut().enumerate().find(|(i, ep)| { - if *i == 0 && ep_type != EndpointType::Control { - return false; // reserved for control pipe + let index = if let Some(addr) = ep_addr { + // Use the specified endpoint address + let requested_index = addr.index(); + if requested_index >= EP_COUNT { + return Err(EndpointAllocError); } + if requested_index == 0 && ep_type != EndpointType::Control { + return Err(EndpointAllocError); // EP0 is reserved for control + } + + let ep = &self.alloc[requested_index]; let used = ep.used_out || ep.used_in; if used && (ep.ep_type == EndpointType::Isochronous) { // Isochronous endpoints are always double-buffered. // Their corresponding endpoint/channel registers are forced to be unidirectional. // Do not reuse this index. - // FIXME: Bulk endpoints can be double buffered, but are not in the current implementation. - return false; + return Err(EndpointAllocError); } let used_dir = match D::dir() { Direction::Out => ep.used_out, Direction::In => ep.used_in, }; - !used || (ep.ep_type == ep_type && !used_dir) - }); + if used && (ep.ep_type != ep_type || used_dir) { + return Err(EndpointAllocError); + } + + Some((requested_index, &mut self.alloc[requested_index])) + } else { + // Find any available endpoint + self.alloc.iter_mut().enumerate().find(|(i, ep)| { + if *i == 0 && ep_type != EndpointType::Control { + return false; // reserved for control pipe + } + let used = ep.used_out || ep.used_in; + if used && (ep.ep_type == EndpointType::Isochronous) { + // Isochronous endpoints are always double-buffered. + // Their corresponding endpoint/channel registers are forced to be unidirectional. + // Do not reuse this index. + // FIXME: Bulk endpoints can be double buffered, but are not in the current implementation. + return false; + } + + let used_dir = match D::dir() { + Direction::Out => ep.used_out, + Direction::In => ep.used_in, + }; + !used || (ep.ep_type == ep_type && !used_dir) + }) + }; let (index, ep) = match index { Some(x) => x, @@ -479,27 +511,29 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { fn alloc_endpoint_in( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, ) -> Result { - self.alloc_endpoint(ep_type, max_packet_size, interval_ms) + self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms) } fn alloc_endpoint_out( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, ) -> Result { - self.alloc_endpoint(ep_type, max_packet_size, interval_ms) + self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms) } fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) { let ep_out = self - .alloc_endpoint(EndpointType::Control, control_max_packet_size, 0) + .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0) .unwrap(); let ep_in = self - .alloc_endpoint(EndpointType::Control, control_max_packet_size, 0) + .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0) .unwrap(); assert_eq!(ep_out.info.addr.index(), 0); assert_eq!(ep_in.info.addr.index(), 0); diff --git a/embassy-usb-driver/src/lib.rs b/embassy-usb-driver/src/lib.rs index d204e4d85..99616f1ec 100644 --- a/embassy-usb-driver/src/lib.rs +++ b/embassy-usb-driver/src/lib.rs @@ -136,6 +136,7 @@ pub trait Driver<'a> { fn alloc_endpoint_out( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, ) -> Result; @@ -153,6 +154,7 @@ pub trait Driver<'a> { fn alloc_endpoint_in( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, ) -> Result; diff --git a/embassy-usb-synopsys-otg/src/lib.rs b/embassy-usb-synopsys-otg/src/lib.rs index fc4428b54..7fc142a4e 100644 --- a/embassy-usb-synopsys-otg/src/lib.rs +++ b/embassy-usb-synopsys-otg/src/lib.rs @@ -345,6 +345,7 @@ impl<'d, const MAX_EP_COUNT: usize> Driver<'d, MAX_EP_COUNT> { fn alloc_endpoint( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, ) -> Result, EndpointAllocError> { @@ -379,15 +380,31 @@ impl<'d, const MAX_EP_COUNT: usize> Driver<'d, MAX_EP_COUNT> { Direction::In => &mut self.ep_in[..self.instance.endpoint_count], }; - // Find free endpoint slot - let slot = eps.iter_mut().enumerate().find(|(i, ep)| { - if *i == 0 && ep_type != EndpointType::Control { - // reserved for control pipe - false - } else { - ep.is_none() + // Find endpoint slot + let slot = if let Some(addr) = ep_addr { + // Use the specified endpoint address + let requested_index = addr.index(); + if requested_index >= self.instance.endpoint_count { + return Err(EndpointAllocError); } - }); + if requested_index == 0 && ep_type != EndpointType::Control { + return Err(EndpointAllocError); // EP0 is reserved for control + } + if eps[requested_index].is_some() { + return Err(EndpointAllocError); // Already allocated + } + Some((requested_index, &mut eps[requested_index])) + } else { + // Find any free endpoint slot + eps.iter_mut().enumerate().find(|(i, ep)| { + if *i == 0 && ep_type != EndpointType::Control { + // reserved for control pipe + false + } else { + ep.is_none() + } + }) + }; let index = match slot { Some((index, ep)) => { @@ -438,27 +455,29 @@ impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Driver<'d> for Driver<'d fn alloc_endpoint_in( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, ) -> Result { - self.alloc_endpoint(ep_type, max_packet_size, interval_ms) + self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms) } fn alloc_endpoint_out( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, ) -> Result { - self.alloc_endpoint(ep_type, max_packet_size, interval_ms) + self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms) } fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) { let ep_out = self - .alloc_endpoint(EndpointType::Control, control_max_packet_size, 0) + .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0) .unwrap(); let ep_in = self - .alloc_endpoint(EndpointType::Control, control_max_packet_size, 0) + .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0) .unwrap(); assert_eq!(ep_out.info.addr.index(), 0); assert_eq!(ep_in.info.addr.index(), 0); diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs index 6c4b3f9a4..8d7abe46c 100644 --- a/embassy-usb/src/builder.rs +++ b/embassy-usb/src/builder.rs @@ -2,7 +2,7 @@ use heapless::Vec; use crate::config::MAX_HANDLER_COUNT; use crate::descriptor::{BosWriter, DescriptorWriter, SynchronizationType, UsageType}; -use crate::driver::{Driver, Endpoint, EndpointInfo, EndpointType}; +use crate::driver::{Driver, Endpoint, EndpointAddress, EndpointInfo, EndpointType}; use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter}; use crate::types::{InterfaceNumber, StringIndex}; use crate::{Handler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START}; @@ -465,11 +465,17 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { /// Allocate an IN endpoint, without writing its descriptor. /// /// Used for granular control over the order of endpoint and descriptor creation. - pub fn alloc_endpoint_in(&mut self, ep_type: EndpointType, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn { + pub fn alloc_endpoint_in( + &mut self, + ep_type: EndpointType, + ep_addr: Option, + max_packet_size: u16, + interval_ms: u8, + ) -> D::EndpointIn { let ep = self .builder .driver - .alloc_endpoint_in(ep_type, max_packet_size, interval_ms) + .alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms) .expect("alloc_endpoint_in failed"); ep @@ -478,13 +484,14 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { fn endpoint_in( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, synchronization_type: SynchronizationType, usage_type: UsageType, extra_fields: &[u8], ) -> D::EndpointIn { - let ep = self.alloc_endpoint_in(ep_type, max_packet_size, interval_ms); + let ep = self.alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms); self.endpoint_descriptor(ep.info(), synchronization_type, usage_type, extra_fields); ep @@ -496,13 +503,14 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { pub fn alloc_endpoint_out( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, ) -> D::EndpointOut { let ep = self .builder .driver - .alloc_endpoint_out(ep_type, max_packet_size, interval_ms) + .alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms) .expect("alloc_endpoint_out failed"); ep @@ -511,13 +519,14 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { fn endpoint_out( &mut self, ep_type: EndpointType, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, synchronization_type: SynchronizationType, usage_type: UsageType, extra_fields: &[u8], ) -> D::EndpointOut { - let ep = self.alloc_endpoint_out(ep_type, max_packet_size, interval_ms); + let ep = self.alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms); self.endpoint_descriptor(ep.info(), synchronization_type, usage_type, extra_fields); ep @@ -527,9 +536,10 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { /// /// Descriptors are written in the order builder functions are called. Note that some /// classes care about the order. - pub fn endpoint_bulk_in(&mut self, max_packet_size: u16) -> D::EndpointIn { + pub fn endpoint_bulk_in(&mut self, ep_addr: Option, max_packet_size: u16) -> D::EndpointIn { self.endpoint_in( EndpointType::Bulk, + ep_addr, max_packet_size, 0, SynchronizationType::NoSynchronization, @@ -542,9 +552,10 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { /// /// Descriptors are written in the order builder functions are called. Note that some /// classes care about the order. - pub fn endpoint_bulk_out(&mut self, max_packet_size: u16) -> D::EndpointOut { + pub fn endpoint_bulk_out(&mut self, ep_addr: Option, max_packet_size: u16) -> D::EndpointOut { self.endpoint_out( EndpointType::Bulk, + ep_addr, max_packet_size, 0, SynchronizationType::NoSynchronization, @@ -557,9 +568,15 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { /// /// Descriptors are written in the order builder functions are called. Note that some /// classes care about the order. - pub fn endpoint_interrupt_in(&mut self, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn { + pub fn endpoint_interrupt_in( + &mut self, + ep_addr: Option, + max_packet_size: u16, + interval_ms: u8, + ) -> D::EndpointIn { self.endpoint_in( EndpointType::Interrupt, + ep_addr, max_packet_size, interval_ms, SynchronizationType::NoSynchronization, @@ -569,9 +586,15 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { } /// Allocate a INTERRUPT OUT endpoint and write its descriptor. - pub fn endpoint_interrupt_out(&mut self, max_packet_size: u16, interval_ms: u8) -> D::EndpointOut { + pub fn endpoint_interrupt_out( + &mut self, + ep_addr: Option, + max_packet_size: u16, + interval_ms: u8, + ) -> D::EndpointOut { self.endpoint_out( EndpointType::Interrupt, + ep_addr, max_packet_size, interval_ms, SynchronizationType::NoSynchronization, @@ -586,6 +609,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { /// classes care about the order. pub fn endpoint_isochronous_in( &mut self, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, synchronization_type: SynchronizationType, @@ -594,6 +618,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { ) -> D::EndpointIn { self.endpoint_in( EndpointType::Isochronous, + ep_addr, max_packet_size, interval_ms, synchronization_type, @@ -605,6 +630,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { /// Allocate a ISOCHRONOUS OUT endpoint and write its descriptor. pub fn endpoint_isochronous_out( &mut self, + ep_addr: Option, max_packet_size: u16, interval_ms: u8, synchronization_type: SynchronizationType, @@ -613,6 +639,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { ) -> D::EndpointOut { self.endpoint_out( EndpointType::Isochronous, + ep_addr, max_packet_size, interval_ms, synchronization_type, diff --git a/embassy-usb/src/class/cdc_acm.rs b/embassy-usb/src/class/cdc_acm.rs index 732a433f8..a1144ce05 100644 --- a/embassy-usb/src/class/cdc_acm.rs +++ b/embassy-usb/src/class/cdc_acm.rs @@ -254,14 +254,14 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { ], ); - let comm_ep = alt.endpoint_interrupt_in(8, 255); + let comm_ep = alt.endpoint_interrupt_in(None, 8, 255); // Data interface let mut iface = func.interface(); let data_if = iface.interface_number(); let mut alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NONE, None); - let read_ep = alt.endpoint_bulk_out(max_packet_size); - let write_ep = alt.endpoint_bulk_in(max_packet_size); + let read_ep = alt.endpoint_bulk_out(None, max_packet_size); + let write_ep = alt.endpoint_bulk_in(None, max_packet_size); drop(func); diff --git a/embassy-usb/src/class/cdc_ncm/mod.rs b/embassy-usb/src/class/cdc_ncm/mod.rs index 09d923d2a..3af853091 100644 --- a/embassy-usb/src/class/cdc_ncm/mod.rs +++ b/embassy-usb/src/class/cdc_ncm/mod.rs @@ -313,15 +313,15 @@ impl<'d, D: Driver<'d>> CdcNcmClass<'d, D> { ], ); - let comm_ep = alt.endpoint_interrupt_in(8, 255); + let comm_ep = alt.endpoint_interrupt_in(None, 8, 255); // Data interface let mut iface = func.interface(); let data_if = iface.interface_number(); let _alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NTB, None); let mut alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NTB, None); - let read_ep = alt.endpoint_bulk_out(max_packet_size); - let write_ep = alt.endpoint_bulk_in(max_packet_size); + let read_ep = alt.endpoint_bulk_out(None, max_packet_size); + let write_ep = alt.endpoint_bulk_in(None, max_packet_size); drop(func); diff --git a/embassy-usb/src/class/cmsis_dap_v2.rs b/embassy-usb/src/class/cmsis_dap_v2.rs index a94e3ddb7..a9fd9cdf0 100644 --- a/embassy-usb/src/class/cmsis_dap_v2.rs +++ b/embassy-usb/src/class/cmsis_dap_v2.rs @@ -61,10 +61,10 @@ impl<'d, D: Driver<'d>> CmsisDapV2Class<'d, D> { )); let mut interface = function.interface(); let mut alt = interface.alt_setting(0xFF, 0, 0, Some(iface_string)); - let read_ep = alt.endpoint_bulk_out(max_packet_size); - let write_ep = alt.endpoint_bulk_in(max_packet_size); + let read_ep = alt.endpoint_bulk_out(None, max_packet_size); + let write_ep = alt.endpoint_bulk_in(None, max_packet_size); let trace_ep = if trace { - Some(alt.endpoint_bulk_in(max_packet_size)) + Some(alt.endpoint_bulk_in(None, max_packet_size)) } else { None }; diff --git a/embassy-usb/src/class/hid.rs b/embassy-usb/src/class/hid.rs index 6d9e0aced..182e1f83f 100644 --- a/embassy-usb/src/class/hid.rs +++ b/embassy-usb/src/class/hid.rs @@ -133,9 +133,9 @@ fn build<'d, D: Driver<'d>>( ], ); - let ep_in = alt.endpoint_interrupt_in(config.max_packet_size, config.poll_ms); + let ep_in = alt.endpoint_interrupt_in(None, config.max_packet_size, config.poll_ms); let ep_out = if with_out_endpoint { - Some(alt.endpoint_interrupt_out(config.max_packet_size, config.poll_ms)) + Some(alt.endpoint_interrupt_out(None, config.max_packet_size, config.poll_ms)) } else { None }; diff --git a/embassy-usb/src/class/midi.rs b/embassy-usb/src/class/midi.rs index 52a96f278..1d152ca44 100644 --- a/embassy-usb/src/class/midi.rs +++ b/embassy-usb/src/class/midi.rs @@ -129,14 +129,14 @@ impl<'d, D: Driver<'d>> MidiClass<'d, D> { for i in 0..n_out_jacks { endpoint_data[2 + i as usize] = in_jack_id_emb(i); } - let read_ep = alt.endpoint_bulk_out(max_packet_size); + let read_ep = alt.endpoint_bulk_out(None, max_packet_size); alt.descriptor(CS_ENDPOINT, &endpoint_data[0..2 + n_out_jacks as usize]); endpoint_data[1] = n_in_jacks; for i in 0..n_in_jacks { endpoint_data[2 + i as usize] = out_jack_id_emb(i); } - let write_ep = alt.endpoint_bulk_in(max_packet_size); + let write_ep = alt.endpoint_bulk_in(None, max_packet_size); alt.descriptor(CS_ENDPOINT, &endpoint_data[0..2 + n_in_jacks as usize]); MidiClass { read_ep, write_ep } diff --git a/embassy-usb/src/class/uac1/speaker.rs b/embassy-usb/src/class/uac1/speaker.rs index 1ff29088c..9565e2a25 100644 --- a/embassy-usb/src/class/uac1/speaker.rs +++ b/embassy-usb/src/class/uac1/speaker.rs @@ -268,9 +268,10 @@ impl<'d, D: Driver<'d>> Speaker<'d, D> { alt.descriptor(CS_INTERFACE, &format_descriptor); - let streaming_endpoint = alt.alloc_endpoint_out(EndpointType::Isochronous, max_packet_size, 1); + let streaming_endpoint = alt.alloc_endpoint_out(EndpointType::Isochronous, None, max_packet_size, 1); let feedback_endpoint = alt.alloc_endpoint_in( EndpointType::Isochronous, + None, 4, // Feedback packets are 24 bit (10.14 format). 1, ); diff --git a/examples/rp/src/bin/usb_raw_bulk.rs b/examples/rp/src/bin/usb_raw_bulk.rs index 103269791..0747901d1 100644 --- a/examples/rp/src/bin/usb_raw_bulk.rs +++ b/examples/rp/src/bin/usb_raw_bulk.rs @@ -96,8 +96,8 @@ async fn main(_spawner: Spawner) { let mut function = builder.function(0xFF, 0, 0); let mut interface = function.interface(); let mut alt = interface.alt_setting(0xFF, 0, 0, None); - let mut read_ep = alt.endpoint_bulk_out(64); - let mut write_ep = alt.endpoint_bulk_in(64); + let mut read_ep = alt.endpoint_bulk_out(None, 64); + let mut write_ep = alt.endpoint_bulk_in(None, 64); drop(function); // Build the builder. diff --git a/examples/rp/src/bin/usb_webusb.rs b/examples/rp/src/bin/usb_webusb.rs index a5dc94d5b..5cecb92f0 100644 --- a/examples/rp/src/bin/usb_webusb.rs +++ b/examples/rp/src/bin/usb_webusb.rs @@ -125,8 +125,8 @@ impl<'d, D: Driver<'d>> WebEndpoints<'d, D> { let mut iface = func.interface(); let mut alt = iface.alt_setting(0xff, 0x00, 0x00, None); - let write_ep = alt.endpoint_bulk_in(config.max_packet_size); - let read_ep = alt.endpoint_bulk_out(config.max_packet_size); + let write_ep = alt.endpoint_bulk_in(None, config.max_packet_size); + let read_ep = alt.endpoint_bulk_out(None, config.max_packet_size); WebEndpoints { write_ep, read_ep } } diff --git a/examples/rp235x/src/bin/usb_webusb.rs b/examples/rp235x/src/bin/usb_webusb.rs index 75d28c853..a68163b61 100644 --- a/examples/rp235x/src/bin/usb_webusb.rs +++ b/examples/rp235x/src/bin/usb_webusb.rs @@ -125,8 +125,8 @@ impl<'d, D: Driver<'d>> WebEndpoints<'d, D> { let mut iface = func.interface(); let mut alt = iface.alt_setting(0xff, 0x00, 0x00, None); - let write_ep = alt.endpoint_bulk_in(config.max_packet_size); - let read_ep = alt.endpoint_bulk_out(config.max_packet_size); + let write_ep = alt.endpoint_bulk_in(None, config.max_packet_size); + let read_ep = alt.endpoint_bulk_out(None, config.max_packet_size); WebEndpoints { write_ep, read_ep } } -- cgit From 93e2fdf51267f112adf0c14ccb7b46eb51edd48c Mon Sep 17 00:00:00 2001 From: korbin Date: Sun, 13 Jul 2025 22:44:48 -0600 Subject: consolidate endpoint validation logic in stm32 --- embassy-stm32/src/usb/usb.rs | 78 ++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 46 deletions(-) diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index 05c28aceb..92c1601cc 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -359,6 +359,34 @@ impl<'d, T: Instance> Driver<'d, T> { addr } + fn is_endpoint_available(&self, index: usize, ep_type: EndpointType) -> bool { + if index == 0 && ep_type != EndpointType::Control { + return false; // EP0 is reserved for control + } + + let ep = match self.alloc.get(index) { + Some(ep) => ep, + None => return false, + }; + + let used = ep.used_out || ep.used_in; + + if used && ep.ep_type == EndpointType::Isochronous { + // Isochronous endpoints are always double-buffered. + // Their corresponding endpoint/channel registers are forced to be unidirectional. + // Do not reuse this index. + // FIXME: Bulk endpoints can be double buffered, but are not in the current implementation. + return false; + } + + let used_dir = match D::dir() { + Direction::Out => ep.used_out, + Direction::In => ep.used_in, + }; + + !used || (ep.ep_type == ep_type && !used_dir) + } + fn alloc_endpoint( &mut self, ep_type: EndpointType, @@ -376,57 +404,15 @@ impl<'d, T: Instance> Driver<'d, T> { let index = if let Some(addr) = ep_addr { // Use the specified endpoint address - let requested_index = addr.index(); - if requested_index >= EP_COUNT { - return Err(EndpointAllocError); - } - if requested_index == 0 && ep_type != EndpointType::Control { - return Err(EndpointAllocError); // EP0 is reserved for control - } - - let ep = &self.alloc[requested_index]; - let used = ep.used_out || ep.used_in; - if used && (ep.ep_type == EndpointType::Isochronous) { - // Isochronous endpoints are always double-buffered. - // Their corresponding endpoint/channel registers are forced to be unidirectional. - // Do not reuse this index. - return Err(EndpointAllocError); - } - - let used_dir = match D::dir() { - Direction::Out => ep.used_out, - Direction::In => ep.used_in, - }; - if used && (ep.ep_type != ep_type || used_dir) { - return Err(EndpointAllocError); - } - - Some((requested_index, &mut self.alloc[requested_index])) + self.is_endpoint_available::(addr.index(), ep_type) + .then_some(addr.index()) } else { // Find any available endpoint - self.alloc.iter_mut().enumerate().find(|(i, ep)| { - if *i == 0 && ep_type != EndpointType::Control { - return false; // reserved for control pipe - } - let used = ep.used_out || ep.used_in; - if used && (ep.ep_type == EndpointType::Isochronous) { - // Isochronous endpoints are always double-buffered. - // Their corresponding endpoint/channel registers are forced to be unidirectional. - // Do not reuse this index. - // FIXME: Bulk endpoints can be double buffered, but are not in the current implementation. - return false; - } - - let used_dir = match D::dir() { - Direction::Out => ep.used_out, - Direction::In => ep.used_in, - }; - !used || (ep.ep_type == ep_type && !used_dir) - }) + (0..self.alloc.len()).find(|&i| self.is_endpoint_available::(i, ep_type)) }; let (index, ep) = match index { - Some(x) => x, + Some(i) => (i, &mut self.alloc[i]), None => return Err(EndpointAllocError), }; -- cgit From 791c32e28408475695f192c4f1bc9a187aaa78e1 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 14 Jul 2025 11:13:34 +0200 Subject: docs: add missing feature for doc gen --- embassy-net-nrf91/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml index 62813e546..1c27cabb4 100644 --- a/embassy-net-nrf91/Cargo.toml +++ b/embassy-net-nrf91/Cargo.toml @@ -33,7 +33,7 @@ at-commands = "0.5.4" src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-nrf91-v$VERSION/embassy-net-nrf91/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-nrf91/src/" target = "thumbv7em-none-eabi" -features = ["defmt"] +features = ["defmt", "nrf-pac/nrf9160"] [package.metadata.docs.rs] features = ["defmt"] -- cgit From 64e1a806fae3a54dcd5009c46e8ab7e66ba1add8 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 14 Jul 2025 11:46:23 +0200 Subject: chore: update to `embassy-hal-internal` v0.3.0 --- embassy-embedded-hal/Cargo.toml | 2 +- embassy-imxrt/Cargo.toml | 2 +- embassy-mspm0/Cargo.toml | 2 +- embassy-nrf/Cargo.toml | 2 +- embassy-nxp/Cargo.toml | 2 +- embassy-rp/Cargo.toml | 2 +- embassy-stm32-wpan/Cargo.toml | 2 +- embassy-stm32/Cargo.toml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index efc3173d4..2bc817758 100644 --- a/embassy-embedded-hal/Cargo.toml +++ b/embassy-embedded-hal/Cargo.toml @@ -22,7 +22,7 @@ time = ["dep:embassy-time"] default = ["time"] [dependencies] -embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal" } +embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } diff --git a/embassy-imxrt/Cargo.toml b/embassy-imxrt/Cargo.toml index 49dc8089c..a7caa307e 100644 --- a/embassy-imxrt/Cargo.toml +++ b/embassy-imxrt/Cargo.toml @@ -67,7 +67,7 @@ embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.4", path = "../embassy-time", optional = true } -embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } +embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false } embassy-futures = { version = "0.1.1", path = "../embassy-futures" } diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index 09bce9aa7..a2ecbc7db 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -31,7 +31,7 @@ embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true, features = ["tick-hz-32_768"] } embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } +embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false } embassy-executor = { version = "0.7.0", path = "../embassy-executor", optional = true } diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 47eb92697..71ac70031 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -144,7 +144,7 @@ embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", option embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } -embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } +embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false } embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 18e9d989c..01f57c4e2 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" cortex-m = "0.7.7" cortex-m-rt = "0.7.0" critical-section = "1.1.2" -embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } +embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } defmt = { version = "1", optional = true } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 5df9e154c..f09b32a7a 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -141,7 +141,7 @@ embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", option embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } +embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal" } embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } atomic-polyfill = "1.0.1" diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index b749625aa..795c09cb9 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -23,7 +23,7 @@ embassy-stm32 = { version = "0.2.0", path = "../embassy-stm32" } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal" } +embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal" } embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver", optional=true } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 552113a79..6c1731760 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -53,7 +53,7 @@ embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } +embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } -- cgit From 1df59ffec4eed74ade4086da496a32d376e4190a Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 14 Jul 2025 11:40:51 +0200 Subject: chore: update to `embassy-nrf` v0.4.0 --- docs/examples/basic/Cargo.toml | 2 +- embassy-boot-nrf/Cargo.toml | 2 +- examples/boot/application/nrf/Cargo.toml | 2 +- examples/nrf-rtos-trace/Cargo.toml | 2 +- examples/nrf51/Cargo.toml | 2 +- examples/nrf52810/Cargo.toml | 2 +- examples/nrf52840-rtic/Cargo.toml | 2 +- examples/nrf52840/Cargo.toml | 2 +- examples/nrf5340/Cargo.toml | 2 +- examples/nrf54l15/Cargo.toml | 2 +- examples/nrf9151/ns/Cargo.toml | 2 +- examples/nrf9151/s/Cargo.toml | 2 +- examples/nrf9160/Cargo.toml | 2 +- tests/nrf/Cargo.toml | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/examples/basic/Cargo.toml b/docs/examples/basic/Cargo.toml index f5cf2b231..09fc517e7 100644 --- a/docs/examples/basic/Cargo.toml +++ b/docs/examples/basic/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["defmt", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt"] } -embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } +embassy-nrf = { version = "0.4.0", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index 3cfaa5a80..d15eca0ef 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -25,7 +25,7 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4.17", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } -embassy-nrf = { version = "0.3.1", path = "../embassy-nrf", default-features = false } +embassy-nrf = { version = "0.4.0", path = "../embassy-nrf", default-features = false } embassy-boot = { version = "0.4.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 4d633e8a8..415d013ca 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } -embassy-nrf = { version = "0.3.1", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } +embassy-nrf = { version = "0.4.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } embassy-boot = { version = "0.4.0", path = "../../../../embassy-boot", features = [] } embassy-boot-nrf = { version = "0.4.0", path = "../../../../embassy-boot-nrf", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index d9e8ca2f9..7bf38cb3f 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -18,7 +18,7 @@ log = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } embassy-time = { version = "0.4.0", path = "../../embassy-time" } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml index 91f78737f..89f78efa0 100644 --- a/examples/nrf51/Cargo.toml +++ b/examples/nrf51/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index 87da89efe..548a16c8d 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index afd269f72..efe57f264 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml @@ -11,7 +11,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } embassy-time-queue-utils = { version = "0.1", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 4140e49d2..6c741f344 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io = { version = "0.6.0", features = ["defmt-03"] } diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index dc4fba4fd..0351cfe27 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io-async = { version = "0.6.1" } diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index 4b229d06d..b1189e887 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml index a083aa5e7..32501e88d 100644 --- a/examples/nrf9151/ns/Cargo.toml +++ b/examples/nrf9151/ns/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.4.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml index ae98631ef..23238412c 100644 --- a/examples/nrf9151/s/Cargo.toml +++ b/examples/nrf9151/s/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.4.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml index 25aedf624..f34c3a053 100644 --- a/examples/nrf9160/Cargo.toml +++ b/examples/nrf9160/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index 30c4223b7..b46498a7a 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -11,7 +11,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt", ] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } embassy-net-esp-hosted = { version = "0.2.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } -- cgit From a7ffa44a08cfd8daf054c555056ab10360593840 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 14 Jul 2025 11:49:23 +0200 Subject: chore: Release embassy-hal-internal version 0.3.0 --- embassy-hal-internal/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-hal-internal/Cargo.toml b/embassy-hal-internal/Cargo.toml index cc360682e..b4c52ccfa 100644 --- a/embassy-hal-internal/Cargo.toml +++ b/embassy-hal-internal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-hal-internal" -version = "0.2.0" +version = "0.3.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Internal implementation details for Embassy HALs. DO NOT USE DIRECTLY." -- cgit From c7e33b28b8134662a0e0cf3e7215a78a00b2f1dd Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 14 Jul 2025 11:50:13 +0200 Subject: Revert "chore: update to `embassy-nrf` v0.4.0" This reverts commit 1df59ffec4eed74ade4086da496a32d376e4190a. --- docs/examples/basic/Cargo.toml | 2 +- embassy-boot-nrf/Cargo.toml | 2 +- examples/boot/application/nrf/Cargo.toml | 2 +- examples/nrf-rtos-trace/Cargo.toml | 2 +- examples/nrf51/Cargo.toml | 2 +- examples/nrf52810/Cargo.toml | 2 +- examples/nrf52840-rtic/Cargo.toml | 2 +- examples/nrf52840/Cargo.toml | 2 +- examples/nrf5340/Cargo.toml | 2 +- examples/nrf54l15/Cargo.toml | 2 +- examples/nrf9151/ns/Cargo.toml | 2 +- examples/nrf9151/s/Cargo.toml | 2 +- examples/nrf9160/Cargo.toml | 2 +- tests/nrf/Cargo.toml | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/examples/basic/Cargo.toml b/docs/examples/basic/Cargo.toml index 09fc517e7..f5cf2b231 100644 --- a/docs/examples/basic/Cargo.toml +++ b/docs/examples/basic/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["defmt", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt"] } -embassy-nrf = { version = "0.4.0", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } +embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index d15eca0ef..3cfaa5a80 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -25,7 +25,7 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4.17", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } -embassy-nrf = { version = "0.4.0", path = "../embassy-nrf", default-features = false } +embassy-nrf = { version = "0.3.1", path = "../embassy-nrf", default-features = false } embassy-boot = { version = "0.4.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 415d013ca..4d633e8a8 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } -embassy-nrf = { version = "0.4.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } +embassy-nrf = { version = "0.3.1", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } embassy-boot = { version = "0.4.0", path = "../../../../embassy-boot", features = [] } embassy-boot-nrf = { version = "0.4.0", path = "../../../../embassy-boot-nrf", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index 7bf38cb3f..d9e8ca2f9 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -18,7 +18,7 @@ log = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } embassy-time = { version = "0.4.0", path = "../../embassy-time" } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml index 89f78efa0..91f78737f 100644 --- a/examples/nrf51/Cargo.toml +++ b/examples/nrf51/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } +embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index 548a16c8d..87da89efe 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index efe57f264..afd269f72 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml @@ -11,7 +11,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } embassy-time-queue-utils = { version = "0.1", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 6c741f344..4140e49d2 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io = { version = "0.6.0", features = ["defmt-03"] } diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 0351cfe27..dc4fba4fd 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io-async = { version = "0.6.1" } diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index b1189e887..4b229d06d 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml index 32501e88d..a083aa5e7 100644 --- a/examples/nrf9151/ns/Cargo.toml +++ b/examples/nrf9151/ns/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml index 23238412c..ae98631ef 100644 --- a/examples/nrf9151/s/Cargo.toml +++ b/examples/nrf9151/s/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml index f34c3a053..25aedf624 100644 --- a/examples/nrf9160/Cargo.toml +++ b/examples/nrf9160/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index b46498a7a..30c4223b7 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -11,7 +11,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt", ] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } embassy-net-esp-hosted = { version = "0.2.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } -- cgit From 4f50c85221f11eecb334169e98d96b7fb94a2753 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 14 Jul 2025 11:40:51 +0200 Subject: chore: update to `embassy-nrf` v0.4.0 --- docs/examples/basic/Cargo.toml | 2 +- embassy-boot-nrf/Cargo.toml | 2 +- examples/boot/application/nrf/Cargo.toml | 2 +- examples/nrf-rtos-trace/Cargo.toml | 2 +- examples/nrf51/Cargo.toml | 2 +- examples/nrf52810/Cargo.toml | 2 +- examples/nrf52840-rtic/Cargo.toml | 2 +- examples/nrf52840/Cargo.toml | 2 +- examples/nrf5340/Cargo.toml | 2 +- examples/nrf54l15/Cargo.toml | 2 +- examples/nrf9151/ns/Cargo.toml | 2 +- examples/nrf9151/s/Cargo.toml | 2 +- examples/nrf9160/Cargo.toml | 2 +- tests/nrf/Cargo.toml | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/examples/basic/Cargo.toml b/docs/examples/basic/Cargo.toml index f5cf2b231..09fc517e7 100644 --- a/docs/examples/basic/Cargo.toml +++ b/docs/examples/basic/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["defmt", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt"] } -embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } +embassy-nrf = { version = "0.4.0", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index 3cfaa5a80..d15eca0ef 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -25,7 +25,7 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4.17", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } -embassy-nrf = { version = "0.3.1", path = "../embassy-nrf", default-features = false } +embassy-nrf = { version = "0.4.0", path = "../embassy-nrf", default-features = false } embassy-boot = { version = "0.4.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 4d633e8a8..415d013ca 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } -embassy-nrf = { version = "0.3.1", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } +embassy-nrf = { version = "0.4.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } embassy-boot = { version = "0.4.0", path = "../../../../embassy-boot", features = [] } embassy-boot-nrf = { version = "0.4.0", path = "../../../../embassy-boot-nrf", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index d9e8ca2f9..7bf38cb3f 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -18,7 +18,7 @@ log = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } embassy-time = { version = "0.4.0", path = "../../embassy-time" } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml index 91f78737f..89f78efa0 100644 --- a/examples/nrf51/Cargo.toml +++ b/examples/nrf51/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index 87da89efe..548a16c8d 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index afd269f72..efe57f264 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml @@ -11,7 +11,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } embassy-time-queue-utils = { version = "0.1", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 4140e49d2..6c741f344 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io = { version = "0.6.0", features = ["defmt-03"] } diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index dc4fba4fd..0351cfe27 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io-async = { version = "0.6.1" } diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index 4b229d06d..b1189e887 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml index a083aa5e7..32501e88d 100644 --- a/examples/nrf9151/ns/Cargo.toml +++ b/examples/nrf9151/ns/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.4.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml index ae98631ef..23238412c 100644 --- a/examples/nrf9151/s/Cargo.toml +++ b/examples/nrf9151/s/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.4.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml index 25aedf624..f34c3a053 100644 --- a/examples/nrf9160/Cargo.toml +++ b/examples/nrf9160/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index 30c4223b7..b46498a7a 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -11,7 +11,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt", ] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } embassy-net-esp-hosted = { version = "0.2.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } -- cgit From 7e01c9bb4d8039cbc4b719d8d8f07b9b63b65842 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 14 Jul 2025 11:55:57 +0200 Subject: chore: Release embassy-nrf version 0.4.0 --- embassy-nrf/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 71ac70031..e343cefdb 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-nrf" -version = "0.3.1" +version = "0.4.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Embassy Hardware Abstraction Layer (HAL) for nRF series microcontrollers" -- cgit From 006f4cdb530b63156e6dd3bdfb094f2065f4c7bb Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 14 Jul 2025 12:00:17 +0200 Subject: chore: add release docs --- RELEASE.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 RELEASE.md diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 000000000..711a93ae4 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,59 @@ +# RELEASE.md + +This document outlines the process for releasing Embassy crates using `cargo-release` and the `release/bump-dependency.sh` script. + +When releasing a crate, keep in mind that you may need to recursively release dependencies as well. + +## Prerequisites + +- Install [`cargo-release`](https://github.com/crate-ci/cargo-release): + + ```sh + cargo binstall cargo-release +``` + +## Crate release + +Check if there are changes to the public API since the last release. If there is a breaking change, follow +the process for creating a minor release. Otherewise, follow the process for creating a new patch release. + +Keep in mind that some crates may need the --features and --target flags passed to cargo release. For more information on that, +look at the `Cargo.toml` files. + +### Patch release (no breaking public API changes) + +``` +cd embassy-nrf/ +cargo release patch --features time,defmt,unstable-pac,gpiote,time-driver-rtc1,nrf52840 --target thumbv7em-none-eabi + +# If dry-run is OK (no missing dependencies on crates.io) +cargo release patch --execute --features time,defmt,unstable-pac,gpiote,time-driver-rtc1,nrf52840 --target thumbv7em-none-eabi +``` + +### Minor release + +``` +# Bump versions in crate files +./release/bump-dependency.sh embassy-nrf 0.4.0 + +# Commit version bump +git commit -am 'chore: update to `embassy-nrf` v0.4.0' + +# Release crate +cd embassy-nrf/ +cargo release minor --features time,defmt,unstable-pac,gpiote,time-driver-rtc1,nrf52840 --target thumbv7em-none-eabi + +# If dry-run is OK (no missing dependencies on crates.io) +cargo release minor --execute --features time,defmt,unstable-pac,gpiote,time-driver-rtc1,nrf52840 --target thumbv7em-none-eabi +``` + +## Push tags + +Push the git tags that `cargo release` created earlier: + +``` +git push --tags +``` +## Reference + +* [PR introducing release automation](https://github.com/embassy-rs/embassy/pull/4289) -- cgit From c62b610db34609c179c55f7bdec368bc8bd4c054 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 14 Jul 2025 12:02:42 +0200 Subject: docs: fix markdown syntax --- RELEASE.md | 1 - 1 file changed, 1 deletion(-) diff --git a/RELEASE.md b/RELEASE.md index 711a93ae4..0ebcfd9fa 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -10,7 +10,6 @@ When releasing a crate, keep in mind that you may need to recursively release de ```sh cargo binstall cargo-release -``` ## Crate release -- cgit From 0c366c21fcb8bc1d04b538cbf852f05bcd9769d9 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 14 Jul 2025 12:18:29 +0200 Subject: chore: add missing metadata for changelog generation --- embassy-nrf/CHANGELOG.md | 3 ++- embassy-nrf/release.toml | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 embassy-nrf/release.toml diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index ffa7997f7..5863e8f28 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate ## 0.3.1 - 2025-01-09 diff --git a/embassy-nrf/release.toml b/embassy-nrf/release.toml new file mode 100644 index 000000000..fb6feaf21 --- /dev/null +++ b/embassy-nrf/release.toml @@ -0,0 +1,5 @@ +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, +] -- cgit From 5a8956209f7626ea8fb2a299a100f268599cad66 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 14 Jul 2025 12:20:38 +0200 Subject: docs: update nrf changelog --- embassy-nrf/CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index 5863e8f28..00deb7f20 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -8,6 +8,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- changed: nrf52833: configure internal LDO +- changed: nrf5340: add more options to clock config +- bugfix: clean the SAADC's register while dropping +- changed: Remove Peripheral trait, rename PeripheralRef->Peri. +- changed: take pins before interrupts in buffered uart init +- changed: nrf5340: add wdt support +- changed: remove nrf radio BLE +- changed: add Blocking/Async Mode param. +- bugfix: fix PWM loop count +- bugfix: fixing the nrf54l drive configuration bug +- changed: add temp driver for nrf5340 +- changed: add support for rand 0.9 + ## 0.3.1 - 2025-01-09 - bugfix: nrf twim return errors in async\_wait instead of waiting indefinitely -- cgit From 8e940c315ca2b252229fb88f2266cbe0aea94bd0 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 14 Jul 2025 12:21:22 +0200 Subject: chore: Release embassy-nrf version 0.4.1 --- embassy-nrf/CHANGELOG.md | 2 ++ embassy-nrf/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index 00deb7f20..30f29d669 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.4.1 - 2025-07-14 + - changed: nrf52833: configure internal LDO - changed: nrf5340: add more options to clock config - bugfix: clean the SAADC's register while dropping diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index e343cefdb..3e43d3c93 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-nrf" -version = "0.4.0" +version = "0.4.1" edition = "2021" license = "MIT OR Apache-2.0" description = "Embassy Hardware Abstraction Layer (HAL) for nRF series microcontrollers" -- cgit From 416612d2f916d8c49d3a3cb9ffba38ffc2f95c91 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 14 Jul 2025 16:04:32 +0200 Subject: chore: bump embassy-boot-nrf version --- examples/boot/application/nrf/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 415d013ca..e9616aa54 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } embassy-nrf = { version = "0.4.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } embassy-boot = { version = "0.4.0", path = "../../../../embassy-boot", features = [] } -embassy-boot-nrf = { version = "0.4.0", path = "../../../../embassy-boot-nrf", features = [] } +embassy-boot-nrf = { version = "0.5.0", path = "../../../../embassy-boot-nrf", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } -- cgit From f5006284f8defd5134cfd6eec7d144236aeee0c1 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 14 Jul 2025 16:05:11 +0200 Subject: chore: Release embassy-boot-nrf version 0.5.0 --- embassy-boot-nrf/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index d15eca0ef..f5edc0716 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-nrf" -version = "0.4.0" +version = "0.5.0" description = "Bootloader lib for nRF chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" -- cgit From ed64d99a510dab0d2a8c9a1b6bf362a95e5ffd35 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Mon, 14 Jul 2025 16:49:50 -0700 Subject: WIP for USB_OTG support on STM32WBA devices --- embassy-stm32/Cargo.toml | 4 ++-- embassy-stm32/src/usb/mod.rs | 28 ++++++++++++++++++++++++++-- embassy-stm32/src/usb/otg.rs | 21 ++++++++++++++++++--- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index c086fbbcf..c28636dc8 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-019a3ce0ea3b5bd832ec2ad53465a0d80b0f4e0a" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-60582dd866b34e690f156cd72b91300a9a8057c0" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-019a3ce0ea3b5bd832ec2ad53465a0d80b0f4e0a", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-60582dd866b34e690f156cd72b91300a9a8057c0", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs index ae5963420..692897b59 100644 --- a/embassy-stm32/src/usb/mod.rs +++ b/embassy-stm32/src/usb/mod.rs @@ -15,7 +15,7 @@ fn common_init() { let freq = T::frequency(); // On the H7RS, the USBPHYC embeds a PLL accepting one of the input frequencies listed below and providing 48MHz to OTG_FS and 60MHz to OTG_HS internally - #[cfg(any(stm32h7rs, all(stm32u5, peri_usb_otg_hs)))] + #[cfg(any(stm32h7rs, all(stm32u5, peri_usb_otg_hs), all(stm32wba, peri_usb_otg_hs)))] if ![16_000_000, 19_200_000, 20_000_000, 24_000_000, 26_000_000, 32_000_000].contains(&freq.0) { panic!( "USB clock should be one of 16, 19.2, 20, 24, 26, 32Mhz but is {} Hz. Please double-check your RCC settings.", @@ -25,7 +25,7 @@ fn common_init() { // Check frequency is within the 0.25% tolerance allowed by the spec. // Clock might not be exact 48Mhz due to rounding errors in PLL calculation, or if the user // has tight clock restrictions due to something else (like audio). - #[cfg(not(any(stm32h7rs, all(stm32u5, peri_usb_otg_hs))))] + #[cfg(not(any(stm32h7rs, all(stm32u5, peri_usb_otg_hs), all(stm32wba, peri_usb_otg_hs))))] if freq.0.abs_diff(48_000_000) > 120_000 { panic!( "USB clock should be 48Mhz but is {} Hz. Please double-check your RCC settings.", @@ -102,6 +102,30 @@ fn common_init() { } } + #[cfg(stm32wba)] + { + // Enable USB power + critical_section::with(|_| { + crate::pac::PWR.svmcr().modify(|w| { + w.set_usv(crate::pac::pwr::vals::Usv::B_0X1); + // w.set_uvmen(true); + }) + }); + + // Wait for USB power to stabilize + while !crate::pac::PWR.vosr().read().vdd11usbrdy() {} + + // Now set up transceiver power if it's a OTG-HS + #[cfg(peri_usb_otg_hs)] + { + crate::pac::PWR.vosr().modify(|w| { + w.set_usbpwren(true); + w.set_usbboosten(true); + }); + while !crate::pac::PWR.vosr().read().usbboostrdy() {} + } + } + T::Interrupt::unpend(); unsafe { T::Interrupt::enable() }; diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index 590d1a427..d664709d3 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -105,7 +105,7 @@ impl<'d, T: Instance> Driver<'d, T> { config: Config, ) -> Self { // For STM32U5 High speed pins need to be left in analog mode - #[cfg(not(all(stm32u5, peri_usb_otg_hs)))] + #[cfg(not(any(all(stm32u5, peri_usb_otg_hs),all(stm32wba, peri_usb_otg_hs))))] { _dp.set_as_af(_dp.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); _dm.set_as_af(_dm.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); @@ -323,6 +323,20 @@ impl<'d, T: Instance> Bus<'d, T> { }); } + #[cfg(all(stm32wba, peri_usb_otg_hs))] + { + crate::pac::SYSCFG.otghsphycr().modify(|w| { + w.set_en(true); + }); + + critical_section::with(|_| { + crate::pac::RCC.ahb2enr().modify(|w| { + w.set_otgen(true); + w.set_otghsphyen(true); + }); + }); + } + let r = T::regs(); let core_id = r.cid().read().0; trace!("Core id {:08x}", core_id); @@ -464,6 +478,7 @@ foreach_interrupt!( stm32f7, stm32l4, stm32u5, + stm32wba, ))] { const FIFO_DEPTH_WORDS: u16 = 320; const ENDPOINT_COUNT: usize = 6; @@ -473,7 +488,7 @@ foreach_interrupt!( } else if #[cfg(any(stm32h7, stm32h7rs))] { const FIFO_DEPTH_WORDS: u16 = 1024; const ENDPOINT_COUNT: usize = 9; - } else if #[cfg(stm32u5)] { + } else if #[cfg(any(stm32wba, stm32u5))] { const FIFO_DEPTH_WORDS: u16 = 320; const ENDPOINT_COUNT: usize = 6; } else { @@ -523,7 +538,7 @@ foreach_interrupt!( ))] { const FIFO_DEPTH_WORDS: u16 = 1024; const ENDPOINT_COUNT: usize = 9; - } else if #[cfg(stm32u5)] { + } else if #[cfg(any(stm32wba, stm32u5))] { const FIFO_DEPTH_WORDS: u16 = 1024; const ENDPOINT_COUNT: usize = 9; } else { -- cgit From e2ceb2b1f7cd0fd7778b53aaf8ba1caa71b2f7f5 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Fri, 11 Jul 2025 17:38:42 +0800 Subject: otg: Improve IN write performance chunks_exact() can be handled by the compiler more efficiently. Previous code was making a memcpy call for each 4 byte chunk slice. Hoisting the fifo out of the loop avoids recalculating the pointer each time. In my benchmark I see a jump from ~13 megabyte/sec to ~25MB/sec after this change (opt-level=3). opt-level = "z" goes 9MB/s to 18MB/s. The benchmark was on a stm32h7s3l8, 600mhz clock, 512 byte bulk writes, data in DTCM. The benchmark isn't just USB writes, also has some unrelated memcpys for packet construction. --- embassy-usb-synopsys-otg/src/lib.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/embassy-usb-synopsys-otg/src/lib.rs b/embassy-usb-synopsys-otg/src/lib.rs index fc4428b54..3f6531813 100644 --- a/embassy-usb-synopsys-otg/src/lib.rs +++ b/embassy-usb-synopsys-otg/src/lib.rs @@ -1210,10 +1210,23 @@ impl<'d> embassy_usb_driver::EndpointIn for Endpoint<'d, In> { }); // Write data to FIFO - for chunk in buf.chunks(4) { + let chunks = buf.chunks_exact(4); + // Stash the last partial chunk + let rem = chunks.remainder(); + let last_chunk = (!rem.is_empty()).then(|| { let mut tmp = [0u8; 4]; - tmp[0..chunk.len()].copy_from_slice(chunk); - self.regs.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp))); + tmp[0..rem.len()].copy_from_slice(rem); + u32::from_ne_bytes(tmp) + }); + + let fifo = self.regs.fifo(index); + for chunk in chunks { + let val = u32::from_ne_bytes(chunk.try_into().unwrap()); + fifo.write_value(regs::Fifo(val)); + } + // Write any last chunk + if let Some(val) = last_chunk { + fifo.write_value(regs::Fifo(val)); } }); -- cgit From 249433a7ed7a9d29a5da0fe169dc31acaad9b8bb Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 15 Jul 2025 10:25:13 +0200 Subject: chore: update changelog --- cyw43-pio/CHANGELOG.md | 3 ++- cyw43-pio/release.toml | 5 +++++ cyw43/CHANGELOG.md | 7 ++++++- cyw43/release.toml | 5 +++++ 4 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 cyw43-pio/release.toml create mode 100644 cyw43/release.toml diff --git a/cyw43-pio/CHANGELOG.md b/cyw43-pio/CHANGELOG.md index 4d56973df..b13f6c75c 100644 --- a/cyw43-pio/CHANGELOG.md +++ b/cyw43-pio/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate - Update embassy-rp to 0.4.0 diff --git a/cyw43-pio/release.toml b/cyw43-pio/release.toml new file mode 100644 index 000000000..fb6feaf21 --- /dev/null +++ b/cyw43-pio/release.toml @@ -0,0 +1,5 @@ +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, +] diff --git a/cyw43/CHANGELOG.md b/cyw43/CHANGELOG.md index 40a638388..fc4b4930e 100644 --- a/cyw43/CHANGELOG.md +++ b/cyw43/CHANGELOG.md @@ -5,7 +5,12 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate + +- bump embassy-sync to 0.7.0 +- bump bt-hci to 0.3.0 +- make State::new const fn ## 0.3.0 - 2025-01-05 diff --git a/cyw43/release.toml b/cyw43/release.toml new file mode 100644 index 000000000..fb6feaf21 --- /dev/null +++ b/cyw43/release.toml @@ -0,0 +1,5 @@ +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, +] -- cgit From 9811f1c999521a80cccf82cfe1a5192f9112b5af Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 15 Jul 2025 11:10:56 +0200 Subject: chore: prepare embassy-rp for release --- cyw43-pio/Cargo.toml | 2 +- embassy-boot-rp/Cargo.toml | 2 +- examples/boot/application/rp/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- tests/rp/Cargo.toml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index 93a2e7089..7dcbaf00b 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -11,7 +11,7 @@ documentation = "https://docs.embassy.dev/cyw43-pio" [dependencies] cyw43 = { version = "0.3.0", path = "../cyw43" } -embassy-rp = { version = "0.4.0", path = "../embassy-rp" } +embassy-rp = { version = "0.5.0", path = "../embassy-rp" } fixed = "1.23.1" defmt = { version = "1.0.1", optional = true } diff --git a/embassy-boot-rp/Cargo.toml b/embassy-boot-rp/Cargo.toml index afe5d6691..9b838641b 100644 --- a/embassy-boot-rp/Cargo.toml +++ b/embassy-boot-rp/Cargo.toml @@ -25,7 +25,7 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } -embassy-rp = { version = "0.4.0", path = "../embassy-rp", default-features = false } +embassy-rp = { version = "0.5.0", path = "../embassy-rp", default-features = false } embassy-boot = { version = "0.4.0", path = "../embassy-boot" } embassy-time = { version = "0.4.0", path = "../embassy-time" } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index be283fb27..cc0ec0deb 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } -embassy-rp = { version = "0.4.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } +embassy-rp = { version = "0.5.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } embassy-boot-rp = { version = "0.5.0", path = "../../../../embassy-boot-rp", features = [] } embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 8d05d5a8c..68259f525 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -10,7 +10,7 @@ embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal", embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-rp = { version = "0.4.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } +embassy-rp = { version = "0.5.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index c6afe37db..1530d9885 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -10,7 +10,7 @@ embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal", embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-rp = { version = "0.4.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } +embassy-rp = { version = "0.5.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 2be37f525..567c2a7b1 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -15,7 +15,7 @@ teleprobe-meta = "1.1" embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", ] } -embassy-rp = { version = "0.4.0", path = "../../embassy-rp", features = [ "defmt", "unstable-pac", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } +embassy-rp = { version = "0.5.0", path = "../../embassy-rp", features = [ "defmt", "unstable-pac", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } -- cgit From e4f500eb1937d1f0d388b09c8f498a26dfc74487 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 15 Jul 2025 11:13:35 +0200 Subject: chore: Release embassy-rp version 0.5.0 --- embassy-rp/CHANGELOG.md | 2 ++ embassy-rp/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md index 52bf0038e..8989c4371 100644 --- a/embassy-rp/CHANGELOG.md +++ b/embassy-rp/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.5.0 - 2025-07-15 + - Fix wrong `funcsel` on RP2350 gpout/gpin ([#3975](https://github.com/embassy-rs/embassy/pull/3975)) - Fix potential race condition in `ADC::wait_for_ready` ([#4012](https://github.com/embassy-rs/embassy/pull/4012)) - `flash`: rename `BOOTROM_BASE` to `BOOTRAM_BASE` ([#4014](https://github.com/embassy-rs/embassy/pull/4014)) diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index f09b32a7a..8b78bb378 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-rp" -version = "0.4.0" +version = "0.5.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Embassy Hardware Abstraction Layer (HAL) for the Raspberry Pi RP2040 or RP235x microcontroller" -- cgit From f2413bd20dfc7d96b3615398906a74916b2f2f98 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 15 Jul 2025 11:14:43 +0200 Subject: chore: Release cyw43 version 0.4.0 --- cyw43/CHANGELOG.md | 2 ++ cyw43/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cyw43/CHANGELOG.md b/cyw43/CHANGELOG.md index fc4b4930e..c800e785b 100644 --- a/cyw43/CHANGELOG.md +++ b/cyw43/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.4.0 - 2025-07-15 + - bump embassy-sync to 0.7.0 - bump bt-hci to 0.3.0 - make State::new const fn diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index c52a653bd..c4b399d29 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cyw43" -version = "0.3.0" +version = "0.4.0" edition = "2021" description = "Rust driver for the CYW43439 WiFi chip, used in the Raspberry Pi Pico W." keywords = ["embedded", "cyw43", "embassy-net", "embedded-hal-async", "wifi"] -- cgit From c35d5fb9ce4dc5eaea141f090e8047c738712593 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 15 Jul 2025 11:15:19 +0200 Subject: chore: bump cyw43 version --- cyw43-pio/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index 7dcbaf00b..0e7c39223 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/cyw43-pio" [dependencies] -cyw43 = { version = "0.3.0", path = "../cyw43" } +cyw43 = { version = "0.4.0", path = "../cyw43" } embassy-rp = { version = "0.5.0", path = "../embassy-rp" } fixed = "1.23.1" defmt = { version = "1.0.1", optional = true } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 68259f525..4469c1267 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -16,7 +16,7 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defm embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.4.0", path = "../../embassy-usb-logger" } -cyw43 = { version = "0.3.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } +cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { version = "0.4.0", path = "../../cyw43-pio", features = ["defmt"] } defmt = "1.0.1" diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 1530d9885..c3bc65ba2 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -16,7 +16,7 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defm embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.4.0", path = "../../embassy-usb-logger" } -cyw43 = { version = "0.3.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } +cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { version = "0.4.0", path = "../../cyw43-pio", features = ["defmt"] } defmt = "1.0.1" -- cgit From f5b9b83cf4a439607ee0f86e5557b16786c828e1 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 15 Jul 2025 11:15:46 +0200 Subject: chore: bump cyw43-pio dependency --- cyw43-pio/CHANGELOG.md | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cyw43-pio/CHANGELOG.md b/cyw43-pio/CHANGELOG.md index b13f6c75c..4c3a9c95b 100644 --- a/cyw43-pio/CHANGELOG.md +++ b/cyw43-pio/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate -- Update embassy-rp to 0.4.0 +- Update embassy-rp to 0.5.0 ## 0.3.0 - 2025-01-05 diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 4469c1267..713f5fe05 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -17,7 +17,7 @@ embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", fea embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.4.0", path = "../../embassy-usb-logger" } cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } -cyw43-pio = { version = "0.4.0", path = "../../cyw43-pio", features = ["defmt"] } +cyw43-pio = { version = "0.5.0", path = "../../cyw43-pio", features = ["defmt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index c3bc65ba2..ee37480e4 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -17,7 +17,7 @@ embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", fea embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.4.0", path = "../../embassy-usb-logger" } cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } -cyw43-pio = { version = "0.4.0", path = "../../cyw43-pio", features = ["defmt"] } +cyw43-pio = { version = "0.5.0", path = "../../cyw43-pio", features = ["defmt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" -- cgit From adbe5859c0c3a63afcae93e919109a17af596b6d Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 15 Jul 2025 11:17:13 +0200 Subject: chore: Release cyw43-pio version 0.5.0 --- cyw43-pio/CHANGELOG.md | 2 ++ cyw43-pio/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cyw43-pio/CHANGELOG.md b/cyw43-pio/CHANGELOG.md index 4c3a9c95b..06b18e503 100644 --- a/cyw43-pio/CHANGELOG.md +++ b/cyw43-pio/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.5.0 - 2025-07-15 + - Update embassy-rp to 0.5.0 ## 0.3.0 - 2025-01-05 diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index 0e7c39223..7c07d35db 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cyw43-pio" -version = "0.4.0" +version = "0.5.0" edition = "2021" description = "RP2040 PIO SPI implementation for cyw43" keywords = ["embedded", "cyw43", "embassy-net", "embedded-hal-async", "wifi"] -- cgit From 27f7cb62362608406af92cef818fce4be6613608 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 15 Jul 2025 16:47:01 +0200 Subject: nrf: add support for nrf9120, nrf9151, nrf9161 approtect. --- embassy-nrf/src/lib.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 9d44ae7e6..44990ed85 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -586,6 +586,8 @@ mod consts { pub const UICR_APPROTECT: *mut u32 = 0x00FF8000 as *mut u32; pub const UICR_SECUREAPPROTECT: *mut u32 = 0x00FF802C as *mut u32; pub const APPROTECT_ENABLED: u32 = 0x0000_0000; + #[cfg(feature = "_nrf9120")] + pub const APPROTECT_DISABLED: u32 = 0x50FA50FA; } #[cfg(feature = "_nrf5340-app")] @@ -768,6 +770,28 @@ pub fn init(config: config::Config) -> Peripherals { } // nothing to do on the nrf9160, debug is allowed by default. + + // nrf9151, nrf9161 use the new-style approtect that requires writing a register. + #[cfg(feature = "nrf9120-s")] + unsafe { + let p = pac::APPROTECT_S; + + let res = uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_DISABLED); + needs_reset |= res == WriteResult::Written; + p.approtect() + .disable() + .write(|w| w.set_disable(pac::approtect::vals::ApprotectDisableDisable::SW_UNPROTECTED)); + + let res = uicr_write(consts::UICR_SECUREAPPROTECT, consts::APPROTECT_DISABLED); + needs_reset |= res == WriteResult::Written; + p.secureapprotect() + .disable() + .write(|w| w.set_disable(pac::approtect::vals::SecureapprotectDisableDisable::SW_UNPROTECTED)); + + // TODO: maybe add workaround for this errata + // It uses extra power, not sure how to let the user choose. + // https://docs.nordicsemi.com/bundle/errata_nRF9151_Rev1/page/ERR/nRF9151/Rev1/latest/anomaly_151_36.html#anomaly_151_36 + } } config::Debug::Disallowed => { // TODO: Handle nRF54L @@ -783,6 +807,13 @@ pub fn init(config: config::Config) -> Peripherals { let res = uicr_write(consts::UICR_SECUREAPPROTECT, consts::APPROTECT_ENABLED); needs_reset |= res == WriteResult::Written; } + + #[cfg(feature = "nrf9120-s")] + { + let p = pac::APPROTECT_S; + p.approtect().forceprotect().write(|w| w.set_forceprotect(true)); + p.secureapprotect().forceprotect().write(|w| w.set_forceprotect(true)); + } } } config::Debug::NotConfigured => {} -- cgit From f32e8f6025ca3787fa402e13cda4031d88e6f518 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 15 Jul 2025 21:40:37 +0200 Subject: release: embassy-usb-driver 0.1.1 --- embassy-nrf/Cargo.toml | 2 +- embassy-rp/Cargo.toml | 2 +- embassy-stm32/Cargo.toml | 2 +- embassy-usb-driver/CHANGELOG.md | 2 ++ embassy-usb-driver/Cargo.toml | 2 +- embassy-usb-synopsys-otg/Cargo.toml | 2 +- embassy-usb/Cargo.toml | 2 +- 7 files changed, 8 insertions(+), 6 deletions(-) diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 3e43d3c93..db4ccea04 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -146,7 +146,7 @@ embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false } -embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } +embassy-usb-driver = { version = "0.1.1", path = "../embassy-usb-driver" } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 8b78bb378..c4fe0b8bb 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -143,7 +143,7 @@ embassy-time = { version = "0.4.0", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal" } -embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } +embassy-usb-driver = { version = "0.1.1", path = "../embassy-usb-driver" } atomic-polyfill = "1.0.1" defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 6c1731760..4ed7b5163 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -56,7 +56,7 @@ embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } -embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } +embassy-usb-driver = { version = "0.1.1", path = "../embassy-usb-driver" } embassy-usb-synopsys-otg = { version = "0.2.0", path = "../embassy-usb-synopsys-otg" } embassy-executor = { version = "0.7.0", path = "../embassy-executor", optional = true } diff --git a/embassy-usb-driver/CHANGELOG.md b/embassy-usb-driver/CHANGELOG.md index c02daefdf..512ce407c 100644 --- a/embassy-usb-driver/CHANGELOG.md +++ b/embassy-usb-driver/CHANGELOG.md @@ -8,4 +8,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.1.1 - 2025-07-15 + - Add `embedded_io_async::Error` implementation for `EndpointError` ([#4176](https://github.com/embassy-rs/embassy/pull/4176)) diff --git a/embassy-usb-driver/Cargo.toml b/embassy-usb-driver/Cargo.toml index e40421649..a148e9ae8 100644 --- a/embassy-usb-driver/Cargo.toml +++ b/embassy-usb-driver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-usb-driver" -version = "0.1.0" +version = "0.1.1" edition = "2021" license = "MIT OR Apache-2.0" description = "Driver trait for `embassy-usb`, an async USB device stack for embedded devices." diff --git a/embassy-usb-synopsys-otg/Cargo.toml b/embassy-usb-synopsys-otg/Cargo.toml index 6252feaef..304fc0db8 100644 --- a/embassy-usb-synopsys-otg/Cargo.toml +++ b/embassy-usb-synopsys-otg/Cargo.toml @@ -19,7 +19,7 @@ target = "thumbv7em-none-eabi" critical-section = "1.1" embassy-sync = { version = "0.7.0", path = "../embassy-sync" } -embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } +embassy-usb-driver = { version = "0.1.1", path = "../embassy-usb-driver" } defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml index 31fd1c1e0..7ed8f82e9 100644 --- a/embassy-usb/Cargo.toml +++ b/embassy-usb/Cargo.toml @@ -47,7 +47,7 @@ max-handler-count-8 = [] [dependencies] embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } +embassy-usb-driver = { version = "0.1.1", path = "../embassy-usb-driver" } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } -- cgit From 25bae18ea622593b5dca15e8fb96d5e185eb8685 Mon Sep 17 00:00:00 2001 From: Bailey Quarters Date: Tue, 15 Jul 2025 22:04:27 +0200 Subject: RP2350: Correct SRAM8 and SRAM9 base addresses in example memory.x --- examples/rp235x/memory.x | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/rp235x/memory.x b/examples/rp235x/memory.x index c803896f6..4382e2065 100644 --- a/examples/rp235x/memory.x +++ b/examples/rp235x/memory.x @@ -17,8 +17,8 @@ MEMORY { * of access times. * Example: Separate stacks for core0 and core1. */ - SRAM4 : ORIGIN = 0x20080000, LENGTH = 4K - SRAM5 : ORIGIN = 0x20081000, LENGTH = 4K + SRAM8 : ORIGIN = 0x20080000, LENGTH = 4K + SRAM9 : ORIGIN = 0x20081000, LENGTH = 4K } SECTIONS { -- cgit From 31022db25c18111b8e8ab7130d1eec673214f1ec Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 16 Jul 2025 00:07:22 +0200 Subject: Disable flaky test --- ci.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci.sh b/ci.sh index 32c9f9321..3dc403171 100755 --- a/ci.sh +++ b/ci.sh @@ -372,6 +372,9 @@ rm out/tests/pimoroni-pico-plus-2/adc # temporarily disabled rm out/tests/pimoroni-pico-plus-2/pwm +# flaky +rm out/tests/rpi-pico/pwm + if [[ -z "${TELEPROBE_TOKEN-}" ]]; then echo No teleprobe token found, skipping running HIL tests exit -- cgit From 38807ff5fd508ce1a1400c1589e029c0361d0ef0 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 16 Jul 2025 09:26:46 +0200 Subject: chore: Release embassy-net-driver-channel version 0.3.1 --- cyw43/Cargo.toml | 2 +- embassy-net-adin1110/Cargo.toml | 2 +- embassy-net-driver-channel/CHANGELOG.md | 2 ++ embassy-net-driver-channel/Cargo.toml | 2 +- embassy-net-esp-hosted/Cargo.toml | 2 +- embassy-net-nrf91/Cargo.toml | 2 +- embassy-net-ppp/Cargo.toml | 2 +- embassy-net-wiznet/Cargo.toml | 2 +- embassy-usb/Cargo.toml | 2 +- 9 files changed, 10 insertions(+), 8 deletions(-) diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index c4b399d29..8aef8963c 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -21,7 +21,7 @@ firmware-logs = [] embassy-time = { version = "0.4.0", path = "../embassy-time"} embassy-sync = { version = "0.7.0", path = "../embassy-sync"} embassy-futures = { version = "0.1.0", path = "../embassy-futures"} -embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel"} +embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel"} defmt = { version = "1.0.1", optional = true } log = { version = "0.4.17", optional = true } diff --git a/embassy-net-adin1110/Cargo.toml b/embassy-net-adin1110/Cargo.toml index a620928cb..9cda4dc5b 100644 --- a/embassy-net-adin1110/Cargo.toml +++ b/embassy-net-adin1110/Cargo.toml @@ -16,7 +16,7 @@ log = { version = "0.4", default-features = false, optional = true } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-hal-bus = { version = "0.1", features = ["async"] } -embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } +embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel" } embassy-time = { version = "0.4.0", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } bitfield = "0.14.0" diff --git a/embassy-net-driver-channel/CHANGELOG.md b/embassy-net-driver-channel/CHANGELOG.md index a5c81cf4d..1189e50c3 100644 --- a/embassy-net-driver-channel/CHANGELOG.md +++ b/embassy-net-driver-channel/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.3.1 - 2025-07-16 + - Update `embassy-sync` to v0.7.0 ## 0.3.0 - 2024-08-05 diff --git a/embassy-net-driver-channel/Cargo.toml b/embassy-net-driver-channel/Cargo.toml index c16c4be74..386d492c6 100644 --- a/embassy-net-driver-channel/Cargo.toml +++ b/embassy-net-driver-channel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-net-driver-channel" -version = "0.3.0" +version = "0.3.1" edition = "2021" license = "MIT OR Apache-2.0" description = "High-level channel-based driver for the `embassy-net` async TCP/IP network stack." diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml index dea74ed65..7ccef84e8 100644 --- a/embassy-net-esp-hosted/Cargo.toml +++ b/embassy-net-esp-hosted/Cargo.toml @@ -20,7 +20,7 @@ log = { version = "0.4.14", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time" } embassy-sync = { version = "0.7.0", path = "../embassy-sync"} embassy-futures = { version = "0.1.0", path = "../embassy-futures"} -embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel"} +embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel"} embedded-hal = { version = "1.0" } embedded-hal-async = { version = "1.0" } diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml index 1c27cabb4..f3c0a0078 100644 --- a/embassy-net-nrf91/Cargo.toml +++ b/embassy-net-nrf91/Cargo.toml @@ -23,7 +23,7 @@ cortex-m = "0.7.7" embassy-time = { version = "0.4.0", path = "../embassy-time" } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } +embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel" } heapless = "0.8" embedded-io = "0.6.1" diff --git a/embassy-net-ppp/Cargo.toml b/embassy-net-ppp/Cargo.toml index 0936626eb..b724401c9 100644 --- a/embassy-net-ppp/Cargo.toml +++ b/embassy-net-ppp/Cargo.toml @@ -18,7 +18,7 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } embedded-io-async = { version = "0.6.1" } -embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } +embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } ppproto = { version = "0.2.1"} embassy-sync = { version = "0.7.0", path = "../embassy-sync" } diff --git a/embassy-net-wiznet/Cargo.toml b/embassy-net-wiznet/Cargo.toml index a06a09302..3ff01f72b 100644 --- a/embassy-net-wiznet/Cargo.toml +++ b/embassy-net-wiznet/Cargo.toml @@ -12,7 +12,7 @@ documentation = "https://docs.embassy.dev/embassy-net-wiznet" [dependencies] embedded-hal = { version = "1.0" } embedded-hal-async = { version = "1.0" } -embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } +embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel" } embassy-time = { version = "0.4.0", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } defmt = { version = "1.0.1", optional = true } diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml index 7ed8f82e9..e706bec13 100644 --- a/embassy-usb/Cargo.toml +++ b/embassy-usb/Cargo.toml @@ -49,7 +49,7 @@ max-handler-count-8 = [] embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-usb-driver = { version = "0.1.1", path = "../embassy-usb-driver" } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } -embassy-net-driver-channel = { version = "0.3.0", path = "../embassy-net-driver-channel" } +embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel" } defmt = { version = "1", optional = true } log = { version = "0.4.14", optional = true } -- cgit From 71ad56357925a3f2b98a20bcce3c1bdb0ac63be5 Mon Sep 17 00:00:00 2001 From: nikvoid Date: Fri, 4 Jul 2025 17:26:37 +0300 Subject: stm32: add `waveform_up` function for complementary PWM too --- embassy-stm32/src/timer/complementary_pwm.rs | 60 ++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index a450705a2..07d5ec826 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -134,6 +134,66 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { self.inner.set_dead_time_clock_division(ckd); self.inner.set_dead_time_value(value); } + + /// Generate a sequence of PWM waveform + /// + /// Note: + /// you will need to provide corresponding TIMx_UP DMA channel to use this method. + pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma>, channel: Channel, duty: &[u16]) { + #[allow(clippy::let_unit_value)] // eg. stm32f334 + let req = dma.request(); + + let original_duty_state = self.inner.get_compare_value(channel); + let original_enable_state = self.inner.get_channel_enable_state(channel); + let original_update_dma_state = self.inner.get_update_dma_state(); + + if !original_update_dma_state { + self.inner.enable_update_dma(true); + } + + if !original_enable_state { + self.inner.enable_channel(channel, true); + } + + unsafe { + #[cfg(not(any(bdma, gpdma)))] + use crate::dma::{Burst, FifoThreshold}; + use crate::dma::{Transfer, TransferOptions}; + + let dma_transfer_option = TransferOptions { + #[cfg(not(any(bdma, gpdma)))] + fifo_threshold: Some(FifoThreshold::Full), + #[cfg(not(any(bdma, gpdma)))] + mburst: Burst::Incr8, + ..Default::default() + }; + + Transfer::new_write( + dma, + req, + duty, + self.inner.regs_gp16().ccr(channel.index()).as_ptr() as *mut u16, + dma_transfer_option, + ) + .await + }; + + // restore output compare state + if !original_enable_state { + self.inner.enable_channel(channel, false); + } + + self.inner.set_compare_value(channel, original_duty_state); + + // Since DMA is closed before timer update event trigger DMA is turn off, + // this can almost always trigger a DMA FIFO error. + // + // optional TODO: + // clean FEIF after disable UDE + if !original_update_dma_state { + self.inner.enable_update_dma(false); + } + } } impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { -- cgit From 386c586afab378584a8622f32bdeb14a6ae60645 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 16 Jul 2025 14:52:21 +0200 Subject: chore: Release embassy-embedded-hal version 0.3.1 --- embassy-boot/Cargo.toml | 2 +- embassy-embedded-hal/CHANGELOG.md | 2 ++ embassy-embedded-hal/Cargo.toml | 2 +- embassy-imxrt/Cargo.toml | 2 +- embassy-mspm0/Cargo.toml | 2 +- embassy-nrf/Cargo.toml | 2 +- embassy-rp/Cargo.toml | 2 +- embassy-stm32-wpan/Cargo.toml | 2 +- embassy-stm32/Cargo.toml | 2 +- examples/boot/application/nrf/Cargo.toml | 2 +- examples/boot/application/rp/Cargo.toml | 2 +- examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wb-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wl/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- examples/stm32h7/Cargo.toml | 2 +- examples/stm32h735/Cargo.toml | 2 +- examples/stm32h755cm4/Cargo.toml | 2 +- examples/stm32h755cm7/Cargo.toml | 2 +- examples/stm32h7b0/Cargo.toml | 2 +- examples/stm32l4/Cargo.toml | 2 +- examples/stm32wl/Cargo.toml | 2 +- tests/mspm0/Cargo.toml | 2 +- tests/rp/Cargo.toml | 2 +- 30 files changed, 31 insertions(+), 29 deletions(-) diff --git a/embassy-boot/Cargo.toml b/embassy-boot/Cargo.toml index f12e8e304..281278abb 100644 --- a/embassy-boot/Cargo.toml +++ b/embassy-boot/Cargo.toml @@ -28,7 +28,7 @@ defmt = { version = "1.0.1", optional = true } digest = "0.10" log = { version = "0.4", optional = true } ed25519-dalek = { version = "2", default-features = false, features = ["digest"], optional = true } -embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal" } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embedded-storage = "0.3.1" embedded-storage-async = { version = "0.4.1" } diff --git a/embassy-embedded-hal/CHANGELOG.md b/embassy-embedded-hal/CHANGELOG.md index 6f0655adf..04d95415c 100644 --- a/embassy-embedded-hal/CHANGELOG.md +++ b/embassy-embedded-hal/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.3.1 - 2025-07-16 + - `SpiDevice` cancel safety: always set CS pin to high on drop - Update `embassy-sync` to v0.7.0 diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index 2bc817758..aab6e0f1e 100644 --- a/embassy-embedded-hal/Cargo.toml +++ b/embassy-embedded-hal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-embedded-hal" -version = "0.3.0" +version = "0.3.1" edition = "2021" license = "MIT OR Apache-2.0" description = "Collection of utilities to use `embedded-hal` and `embedded-storage` traits with Embassy." diff --git a/embassy-imxrt/Cargo.toml b/embassy-imxrt/Cargo.toml index a7caa307e..df4687043 100644 --- a/embassy-imxrt/Cargo.toml +++ b/embassy-imxrt/Cargo.toml @@ -68,7 +68,7 @@ embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", option embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.4", path = "../embassy-time", optional = true } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } -embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false } +embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } embassy-futures = { version = "0.1.1", path = "../embassy-futures" } defmt = { version = "1.0.1", optional = true } diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index a2ecbc7db..d2adc63d7 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -32,7 +32,7 @@ embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", option embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } -embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false } +embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } embassy-executor = { version = "0.7.0", path = "../embassy-executor", optional = true } embedded-hal = { version = "1.0" } diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index db4ccea04..a3feba7d5 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -145,7 +145,7 @@ embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-util embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } -embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false } +embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } embassy-usb-driver = { version = "0.1.1", path = "../embassy-usb-driver" } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index c4fe0b8bb..52a69b6ca 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -142,7 +142,7 @@ embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-util embassy-time = { version = "0.4.0", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } -embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal" } embassy-usb-driver = { version = "0.1.1", path = "../embassy-usb-driver" } atomic-polyfill = "1.0.1" defmt = { version = "1.0.1", optional = true } diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 795c09cb9..a16aa4b54 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -24,7 +24,7 @@ embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal" } -embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver", optional=true } defmt = { version = "1.0.1", optional = true } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 4ed7b5163..b19053da6 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -54,7 +54,7 @@ embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", option embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } -embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false } +embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } embassy-usb-driver = { version = "0.1.1", path = "../embassy-usb-driver" } embassy-usb-synopsys-otg = { version = "0.2.0", path = "../embassy-usb-synopsys-otg" } diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index e9616aa54..93fcbfb24 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -11,7 +11,7 @@ embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features embassy-nrf = { version = "0.4.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } embassy-boot = { version = "0.4.0", path = "../../../../embassy-boot", features = [] } embassy-boot-nrf = { version = "0.5.0", path = "../../../../embassy-boot-nrf", features = [] } -embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index cc0ec0deb..9571c789d 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } embassy-rp = { version = "0.5.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } embassy-boot-rp = { version = "0.5.0", path = "../../../../embassy-boot-rp", features = [] } -embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index b3466e288..4cd2d1338 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32" } -embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index 72dbded5f..f3d74f53a 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index 57fb8312c..427b15bcb 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 7dbbba138..46e79f7ed 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 9549b2048..ae3cd3600 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index 03daeb0bc..a41b25562 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index e582628aa..b0a89c6fe 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } embassy-usb = { version = "0.4.0", path = "../../../../embassy-usb" } embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index 3ed04b472..af49db260 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 713f5fe05..e52e717b8 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] -embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal", features = ["defmt"] } +embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal", features = ["defmt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index ee37480e4..3d05eddc2 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] -embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal", features = ["defmt"] } +embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal", features = ["defmt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 27c59d980..c981e6708 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml index 8d23c346a..e4938e15b 100644 --- a/examples/stm32h735/Cargo.toml +++ b/examples/stm32h735/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index 71bd50d60..2ee5bc83f 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32h755zi-cm4 to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index 8e960932a..a66e1276d 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml index 72f86e0cf..7fc13b652 100644 --- a/examples/stm32h7b0/Cargo.toml +++ b/examples/stm32h7b0/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 7da09e5b0..0c45f9c73 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -10,7 +10,7 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } -embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net-adin1110 = { version = "0.3.0", path = "../../embassy-net-adin1110" } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] } diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 5ecd77443..1c5d9c07a 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -10,7 +10,7 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [" embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/tests/mspm0/Cargo.toml b/tests/mspm0/Cargo.toml index 5d34ece7e..2d5b8cd52 100644 --- a/tests/mspm0/Cargo.toml +++ b/tests/mspm0/Cargo.toml @@ -15,7 +15,7 @@ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = [ "d embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt" ] } embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = [ "rt", "defmt", "unstable-pac", "time-driver-any" ] } -embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal/"} +embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal/"} defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 567c2a7b1..86eded861 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -19,7 +19,7 @@ embassy-rp = { version = "0.5.0", path = "../../embassy-rp", features = [ "defmt embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } -embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal/"} +embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal/"} cyw43 = { path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { path = "../../cyw43-pio", features = ["defmt"] } perf-client = { path = "../perf-client" } -- cgit From 24349a90126cb1c082e34b9d8fc14a7c3e08be6a Mon Sep 17 00:00:00 2001 From: Jianqing Liu Date: Sun, 13 Jul 2025 14:34:07 -0400 Subject: Fix CDC ACM BufferedReceiver buffer calculation Co-authored-by: Ralph Ursprung <39383228+rursprung@users.noreply.github.com> --- embassy-usb/src/class/cdc_acm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-usb/src/class/cdc_acm.rs b/embassy-usb/src/class/cdc_acm.rs index a1144ce05..0a1a5e64f 100644 --- a/embassy-usb/src/class/cdc_acm.rs +++ b/embassy-usb/src/class/cdc_acm.rs @@ -501,7 +501,7 @@ impl<'d, D: Driver<'d>> BufferedReceiver<'d, D> { fn read_from_buffer(&mut self, buf: &mut [u8]) -> usize { let available = &self.buffer[self.start..self.end]; let len = core::cmp::min(available.len(), buf.len()); - buf[..len].copy_from_slice(&self.buffer[..len]); + buf[..len].copy_from_slice(&available[..len]); self.start += len; len } -- cgit From c484e7d0e530d20e1fdfaa4a1578e9321cc8b283 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 16 Jul 2025 15:34:59 +0200 Subject: chore: Release embassy-usb version 0.5.0 --- embassy-usb-dfu/Cargo.toml | 2 +- embassy-usb-logger/Cargo.toml | 2 +- embassy-usb/CHANGELOG.md | 3 +++ embassy-usb/Cargo.toml | 2 +- examples/boot/application/stm32wb-dfu/Cargo.toml | 2 +- examples/boot/bootloader/stm32wb-dfu/Cargo.toml | 2 +- examples/nrf52840/Cargo.toml | 2 +- examples/nrf5340/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- examples/stm32f1/Cargo.toml | 2 +- examples/stm32f3/Cargo.toml | 2 +- examples/stm32f334/Cargo.toml | 2 +- examples/stm32f4/Cargo.toml | 2 +- examples/stm32f7/Cargo.toml | 2 +- examples/stm32g0/Cargo.toml | 2 +- examples/stm32g4/Cargo.toml | 2 +- examples/stm32h5/Cargo.toml | 2 +- examples/stm32h7/Cargo.toml | 2 +- examples/stm32h742/Cargo.toml | 2 +- examples/stm32h755cm4/Cargo.toml | 2 +- examples/stm32h755cm7/Cargo.toml | 2 +- examples/stm32h7b0/Cargo.toml | 2 +- examples/stm32h7rs/Cargo.toml | 2 +- examples/stm32l1/Cargo.toml | 2 +- examples/stm32l4/Cargo.toml | 2 +- examples/stm32l5/Cargo.toml | 2 +- examples/stm32u0/Cargo.toml | 2 +- examples/stm32u5/Cargo.toml | 2 +- 29 files changed, 31 insertions(+), 28 deletions(-) diff --git a/embassy-usb-dfu/Cargo.toml b/embassy-usb-dfu/Cargo.toml index 8b2467bca..cdad3ce00 100644 --- a/embassy-usb-dfu/Cargo.toml +++ b/embassy-usb-dfu/Cargo.toml @@ -35,7 +35,7 @@ embassy-boot = { version = "0.4.0", path = "../embassy-boot" } embassy-futures = { version = "0.1.1", path = "../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-usb = { version = "0.4.0", path = "../embassy-usb", default-features = false } +embassy-usb = { version = "0.5.0", path = "../embassy-usb", default-features = false } embedded-storage = { version = "0.3.1" } esp32c3-hal = { version = "0.13.0", optional = true, default-features = false } diff --git a/embassy-usb-logger/Cargo.toml b/embassy-usb-logger/Cargo.toml index 6b8e9af47..6dd2637f2 100644 --- a/embassy-usb-logger/Cargo.toml +++ b/embassy-usb-logger/Cargo.toml @@ -15,7 +15,7 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-l target = "thumbv7em-none-eabi" [dependencies] -embassy-usb = { version = "0.4.0", path = "../embassy-usb" } +embassy-usb = { version = "0.5.0", path = "../embassy-usb" } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } log = "0.4" diff --git a/embassy-usb/CHANGELOG.md b/embassy-usb/CHANGELOG.md index 51db5f03e..3ee75e226 100644 --- a/embassy-usb/CHANGELOG.md +++ b/embassy-usb/CHANGELOG.md @@ -8,12 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.5.0 - 2025-07-16 + - `UAC1`: unmute by default ([#3992](https://github.com/embassy-rs/embassy/pull/3992)) - `cdc_acm`: `State::new` is now `const` ([#4000](https://github.com/embassy-rs/embassy/pull/4000)) - Add support for CMSIS-DAP v2 USB class ([#4107](https://github.com/embassy-rs/embassy/pull/4107)) - Reduce `UsbDevice` builder logs to `trace` ([#4130](https://github.com/embassy-rs/embassy/pull/4130)) - Implement `embedded-io-async` traits for USB CDC ACM ([#4176](https://github.com/embassy-rs/embassy/pull/4176)) - Update `embassy-sync` to v0.7.0 +- Fix CDC ACM BufferedReceiver buffer calculation ## 0.4.0 - 2025-01-15 diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml index e706bec13..1f90f84ad 100644 --- a/embassy-usb/Cargo.toml +++ b/embassy-usb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-usb" -version = "0.4.0" +version = "0.5.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Async USB device stack for embedded devices in Rust." diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index b0a89c6fe..287fcf806 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -11,7 +11,7 @@ embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } -embassy-usb = { version = "0.4.0", path = "../../../../embassy-usb" } +embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb" } embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml index 0bb93b12e..d101e6ace 100644 --- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml @@ -18,7 +18,7 @@ embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" cfg-if = "1.0.0" embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } -embassy-usb = { version = "0.4.0", path = "../../../../embassy-usb", default-features = false } +embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb", default-features = false } embassy-futures = { version = "0.1.1", path = "../../../../embassy-futures" } [features] diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 6c741f344..bcbb8160c 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -11,7 +11,7 @@ embassy-executor = { version = "0.7.0", path = "../../embassy-executor", feature embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io = { version = "0.6.0", features = ["defmt-03"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } embassy-net-esp-hosted = { version = "0.2.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 0351cfe27..03d585ccb 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -11,7 +11,7 @@ embassy-executor = { version = "0.7.0", path = "../../embassy-executor", feature embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io-async = { version = "0.6.1" } defmt = "1.0.1" diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index e52e717b8..05bc8742e 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -11,7 +11,7 @@ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-rp = { version = "0.5.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 3d05eddc2..bf7e6d164 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -11,7 +11,7 @@ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-rp = { version = "0.5.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 261733305..01f4fd84a 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -10,7 +10,7 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index f675b0be1..ab7d6b255 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -10,7 +10,7 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml index b47a81e1b..6595804e1 100644 --- a/examples/stm32f334/Cargo.toml +++ b/examples/stm32f334/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index edab9ea00..80c43f2ab 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -10,7 +10,7 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [" embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt" ] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt" ] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index c5801ea90..5995211d2 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -12,7 +12,7 @@ embassy-executor = { version = "0.7.0", path = "../../embassy-executor", feature embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embedded-io-async = { version = "0.6.1" } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index bf1e7250e..1c290fcfa 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml @@ -10,7 +10,7 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index 3d2c2aa7d..a503420e5 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -10,7 +10,7 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } usbd-hid = "0.8.1" diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index f3fda7ff3..0ac9016d4 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -11,7 +11,7 @@ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index c981e6708..9053289ea 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -12,7 +12,7 @@ embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml index 31eff4379..efa71e144 100644 --- a/examples/stm32h742/Cargo.toml +++ b/examples/stm32h742/Cargo.toml @@ -34,7 +34,7 @@ embassy-net = { version = "0.7.0", path = "../../embassy-net", features = [ "medium-ethernet", ] } embedded-io-async = { version = "0.6.1" } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = [ +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = [ "defmt", ] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index 2ee5bc83f..eaaeb1ac0 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -12,7 +12,7 @@ embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index a66e1276d..e7fc05948 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -12,7 +12,7 @@ embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml index 7fc13b652..bfa7f9202 100644 --- a/examples/stm32h7b0/Cargo.toml +++ b/examples/stm32h7b0/Cargo.toml @@ -11,7 +11,7 @@ embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml index 5f1ce8dfc..9794c6dbd 100644 --- a/examples/stm32h7rs/Cargo.toml +++ b/examples/stm32h7rs/Cargo.toml @@ -11,7 +11,7 @@ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ethernet", "medium-ip", "proto-ipv4"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index a0a7916a7..5d5d401f6 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 0c45f9c73..a6b4efcf8 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -11,7 +11,7 @@ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net-adin1110 = { version = "0.3.0", path = "../../embassy-net-adin1110" } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 3ea3bcd5c..1379d963c 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -10,7 +10,7 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } usbd-hid = "0.8.1" diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml index 3aa45dc79..612d12ac2 100644 --- a/examples/stm32u0/Cargo.toml +++ b/examples/stm32u0/Cargo.toml @@ -10,7 +10,7 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index 777d3ed4c..f92e85852 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -10,7 +10,7 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [" embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" -- cgit From 6f2f469c565f7bacc8e5312f6f2ae20828941308 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 16 Jul 2025 15:41:57 +0200 Subject: chore: Release embassy-usb-driver version 0.2.0 --- embassy-nrf/Cargo.toml | 2 +- embassy-rp/Cargo.toml | 2 +- embassy-stm32/Cargo.toml | 2 +- embassy-usb-driver/CHANGELOG.md | 4 ++++ embassy-usb-driver/Cargo.toml | 2 +- embassy-usb-synopsys-otg/Cargo.toml | 2 +- embassy-usb/Cargo.toml | 2 +- 7 files changed, 10 insertions(+), 6 deletions(-) diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index a3feba7d5..bc643942a 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -146,7 +146,7 @@ embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } -embassy-usb-driver = { version = "0.1.1", path = "../embassy-usb-driver" } +embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 52a69b6ca..ac3b3fe1a 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -143,7 +143,7 @@ embassy-time = { version = "0.4.0", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal" } -embassy-usb-driver = { version = "0.1.1", path = "../embassy-usb-driver" } +embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } atomic-polyfill = "1.0.1" defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index b19053da6..c01859fae 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -56,7 +56,7 @@ embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } -embassy-usb-driver = { version = "0.1.1", path = "../embassy-usb-driver" } +embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } embassy-usb-synopsys-otg = { version = "0.2.0", path = "../embassy-usb-synopsys-otg" } embassy-executor = { version = "0.7.0", path = "../embassy-executor", optional = true } diff --git a/embassy-usb-driver/CHANGELOG.md b/embassy-usb-driver/CHANGELOG.md index 512ce407c..15875e087 100644 --- a/embassy-usb-driver/CHANGELOG.md +++ b/embassy-usb-driver/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.2.0 - 2025-07-16 + +- Make USB endpoint allocator methods accept an optional `EndpointAddress`. + ## 0.1.1 - 2025-07-15 - Add `embedded_io_async::Error` implementation for `EndpointError` ([#4176](https://github.com/embassy-rs/embassy/pull/4176)) diff --git a/embassy-usb-driver/Cargo.toml b/embassy-usb-driver/Cargo.toml index a148e9ae8..de69bf694 100644 --- a/embassy-usb-driver/Cargo.toml +++ b/embassy-usb-driver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-usb-driver" -version = "0.1.1" +version = "0.2.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Driver trait for `embassy-usb`, an async USB device stack for embedded devices." diff --git a/embassy-usb-synopsys-otg/Cargo.toml b/embassy-usb-synopsys-otg/Cargo.toml index 304fc0db8..511cddacf 100644 --- a/embassy-usb-synopsys-otg/Cargo.toml +++ b/embassy-usb-synopsys-otg/Cargo.toml @@ -19,7 +19,7 @@ target = "thumbv7em-none-eabi" critical-section = "1.1" embassy-sync = { version = "0.7.0", path = "../embassy-sync" } -embassy-usb-driver = { version = "0.1.1", path = "../embassy-usb-driver" } +embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml index 1f90f84ad..4743fde65 100644 --- a/embassy-usb/Cargo.toml +++ b/embassy-usb/Cargo.toml @@ -47,7 +47,7 @@ max-handler-count-8 = [] [dependencies] embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-usb-driver = { version = "0.1.1", path = "../embassy-usb-driver" } +embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel" } -- cgit From 8c087e3641e2bf1f863c73a388b2f483051e6b29 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 16 Jul 2025 15:47:37 +0200 Subject: chore: release embassy-nrf 0.5.0 and embassy-rp 0.6.0 --- cyw43-pio/Cargo.toml | 2 +- docs/examples/basic/Cargo.toml | 2 +- embassy-boot-nrf/Cargo.toml | 2 +- embassy-boot-rp/Cargo.toml | 2 +- embassy-nrf/CHANGELOG.md | 2 ++ embassy-rp/CHANGELOG.md | 2 ++ examples/boot/application/nrf/Cargo.toml | 2 +- examples/boot/application/rp/Cargo.toml | 2 +- examples/nrf-rtos-trace/Cargo.toml | 2 +- examples/nrf51/Cargo.toml | 2 +- examples/nrf52810/Cargo.toml | 2 +- examples/nrf52840-rtic/Cargo.toml | 2 +- examples/nrf52840/Cargo.toml | 2 +- examples/nrf5340/Cargo.toml | 2 +- examples/nrf54l15/Cargo.toml | 2 +- examples/nrf9151/ns/Cargo.toml | 2 +- examples/nrf9151/s/Cargo.toml | 2 +- examples/nrf9160/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- tests/nrf/Cargo.toml | 2 +- tests/rp/Cargo.toml | 2 +- 22 files changed, 24 insertions(+), 20 deletions(-) diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index 7c07d35db..21f365db4 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -11,7 +11,7 @@ documentation = "https://docs.embassy.dev/cyw43-pio" [dependencies] cyw43 = { version = "0.4.0", path = "../cyw43" } -embassy-rp = { version = "0.5.0", path = "../embassy-rp" } +embassy-rp = { version = "0.6.0", path = "../embassy-rp" } fixed = "1.23.1" defmt = { version = "1.0.1", optional = true } diff --git a/docs/examples/basic/Cargo.toml b/docs/examples/basic/Cargo.toml index 09fc517e7..c4b72d81a 100644 --- a/docs/examples/basic/Cargo.toml +++ b/docs/examples/basic/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["defmt", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt"] } -embassy-nrf = { version = "0.4.0", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } +embassy-nrf = { version = "0.5.0", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index f5edc0716..1230cbd3b 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -25,7 +25,7 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4.17", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } -embassy-nrf = { version = "0.4.0", path = "../embassy-nrf", default-features = false } +embassy-nrf = { version = "0.5.0", path = "../embassy-nrf", default-features = false } embassy-boot = { version = "0.4.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } diff --git a/embassy-boot-rp/Cargo.toml b/embassy-boot-rp/Cargo.toml index 9b838641b..23d6c7853 100644 --- a/embassy-boot-rp/Cargo.toml +++ b/embassy-boot-rp/Cargo.toml @@ -25,7 +25,7 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } -embassy-rp = { version = "0.5.0", path = "../embassy-rp", default-features = false } +embassy-rp = { version = "0.6.0", path = "../embassy-rp", default-features = false } embassy-boot = { version = "0.4.0", path = "../embassy-boot" } embassy-time = { version = "0.4.0", path = "../embassy-time" } diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index 30f29d669..48a7b25af 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- changed: update to latest embassy-usb-driver + ## 0.4.1 - 2025-07-14 - changed: nrf52833: configure internal LDO diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md index 8989c4371..b0dc92b6c 100644 --- a/embassy-rp/CHANGELOG.md +++ b/embassy-rp/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- update to latest embassy-usb-driver + ## 0.5.0 - 2025-07-15 - Fix wrong `funcsel` on RP2350 gpout/gpin ([#3975](https://github.com/embassy-rs/embassy/pull/3975)) diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 93fcbfb24..9c7fdf148 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } -embassy-nrf = { version = "0.4.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } +embassy-nrf = { version = "0.5.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } embassy-boot = { version = "0.4.0", path = "../../../../embassy-boot", features = [] } embassy-boot-nrf = { version = "0.5.0", path = "../../../../embassy-boot-nrf", features = [] } embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index 9571c789d..afb0871e6 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } -embassy-rp = { version = "0.5.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } +embassy-rp = { version = "0.6.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } embassy-boot-rp = { version = "0.5.0", path = "../../../../embassy-boot-rp", features = [] } embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index 7bf38cb3f..f1c40192d 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -18,7 +18,7 @@ log = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } embassy-time = { version = "0.4.0", path = "../../embassy-time" } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml index 89f78efa0..a21d7f6ce 100644 --- a/examples/nrf51/Cargo.toml +++ b/examples/nrf51/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } +embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index 548a16c8d..baa873f22 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index efe57f264..3e499e9bc 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml @@ -11,7 +11,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } embassy-time-queue-utils = { version = "0.1", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index bcbb8160c..d2baebf8e 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io = { version = "0.6.0", features = ["defmt-03"] } diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 03d585ccb..bdebd5386 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io-async = { version = "0.6.1" } diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index b1189e887..27d5babee 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml index 32501e88d..2a492b595 100644 --- a/examples/nrf9151/ns/Cargo.toml +++ b/examples/nrf9151/ns/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.5.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml index 23238412c..62ef3e4ce 100644 --- a/examples/nrf9151/s/Cargo.toml +++ b/examples/nrf9151/s/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.5.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml index f34c3a053..c896afdbe 100644 --- a/examples/nrf9160/Cargo.toml +++ b/examples/nrf9160/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 05bc8742e..c069190fc 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -10,7 +10,7 @@ embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal", embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-rp = { version = "0.5.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } +embassy-rp = { version = "0.6.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index bf7e6d164..2efa9dc59 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -10,7 +10,7 @@ embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal", embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-rp = { version = "0.5.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } +embassy-rp = { version = "0.6.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index b46498a7a..b167c589e 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -11,7 +11,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt", ] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.4.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } embassy-net-esp-hosted = { version = "0.2.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 86eded861..298955fe3 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -15,7 +15,7 @@ teleprobe-meta = "1.1" embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", ] } -embassy-rp = { version = "0.5.0", path = "../../embassy-rp", features = [ "defmt", "unstable-pac", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } +embassy-rp = { version = "0.6.0", path = "../../embassy-rp", features = [ "defmt", "unstable-pac", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } -- cgit From 3a7a2720b19dda9449313e04ba68ed4884683add Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 16 Jul 2025 15:48:56 +0200 Subject: chore: Release embassy-rp version 0.6.0 --- embassy-rp/CHANGELOG.md | 2 ++ embassy-rp/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md index b0dc92b6c..36e1ea9b4 100644 --- a/embassy-rp/CHANGELOG.md +++ b/embassy-rp/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.6.0 - 2025-07-16 + - update to latest embassy-usb-driver ## 0.5.0 - 2025-07-15 diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index ac3b3fe1a..dcf4e7178 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-rp" -version = "0.5.0" +version = "0.6.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Embassy Hardware Abstraction Layer (HAL) for the Raspberry Pi RP2040 or RP235x microcontroller" -- cgit From 6810889ff19c83323ef70ff50171b01f8c54a8f4 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 16 Jul 2025 15:49:34 +0200 Subject: chore: Release embassy-nrf version 0.5.0 --- embassy-nrf/CHANGELOG.md | 2 ++ embassy-nrf/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index 48a7b25af..a4cb8ceaf 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.5.0 - 2025-07-16 + - changed: update to latest embassy-usb-driver ## 0.4.1 - 2025-07-14 diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index bc643942a..8fa20580d 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-nrf" -version = "0.4.1" +version = "0.5.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Embassy Hardware Abstraction Layer (HAL) for nRF series microcontrollers" -- cgit From 1dd8c2a745ff20ec0522d6e1866521cd91b64570 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 16 Jul 2025 15:51:27 +0200 Subject: chore: Release cyw43-pio version 0.5.1 --- cyw43-pio/CHANGELOG.md | 2 ++ cyw43-pio/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cyw43-pio/CHANGELOG.md b/cyw43-pio/CHANGELOG.md index 06b18e503..218271e15 100644 --- a/cyw43-pio/CHANGELOG.md +++ b/cyw43-pio/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.5.1 - 2025-07-16 + ## 0.5.0 - 2025-07-15 - Update embassy-rp to 0.5.0 diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index 21f365db4..d60793bdc 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cyw43-pio" -version = "0.5.0" +version = "0.5.1" edition = "2021" description = "RP2040 PIO SPI implementation for cyw43" keywords = ["embedded", "cyw43", "embassy-net", "embedded-hal-async", "wifi"] diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index c069190fc..971f99fff 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -17,7 +17,7 @@ embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", fea embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.4.0", path = "../../embassy-usb-logger" } cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } -cyw43-pio = { version = "0.5.0", path = "../../cyw43-pio", features = ["defmt"] } +cyw43-pio = { version = "0.5.1", path = "../../cyw43-pio", features = ["defmt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 2efa9dc59..d909aca1b 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -17,7 +17,7 @@ embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", fea embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.4.0", path = "../../embassy-usb-logger" } cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } -cyw43-pio = { version = "0.5.0", path = "../../cyw43-pio", features = ["defmt"] } +cyw43-pio = { version = "0.5.1", path = "../../cyw43-pio", features = ["defmt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" -- cgit From 0180c8067656f37a601fc6e9672707e46646b86a Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Wed, 16 Jul 2025 16:54:14 +0200 Subject: add `derive(Debug)` for `embassy_rp::i2c::I2c` --- embassy-rp/src/i2c.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index a983b7bc3..172193a07 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -76,6 +76,7 @@ impl Default for Config { pub const FIFO_SIZE: u8 = 16; /// I2C driver. +#[derive(Debug)] pub struct I2c<'d, T: Instance, M: Mode> { phantom: PhantomData<(&'d mut T, M)>, } -- cgit From 62b9b03325ae94f650439070e9838885b7bcb345 Mon Sep 17 00:00:00 2001 From: chemicstry Date: Wed, 16 Jul 2025 20:48:44 +0300 Subject: Fix stm32 buffered half-duplex uart receive --- embassy-stm32/src/usart/buffered.rs | 2 ++ embassy-stm32/src/usart/mod.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 73ab46404..729440c46 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -87,6 +87,8 @@ unsafe fn on_interrupt(r: Regs, state: &'static State) { r.cr1().modify(|w| { w.set_tcie(false); + // Reenable receiver for half-duplex if it was disabled + w.set_re(true); }); state.tx_done.store(true, Ordering::Release); diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 8c9028f08..5bece6d66 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -651,7 +651,7 @@ pub fn send_break(regs: &Regs) { /// In case of readback, keep Receiver enabled fn half_duplex_set_rx_tx_before_write(r: &Regs, enable_readback: bool) { let mut cr1 = r.cr1().read(); - if r.cr3().read().hdsel() && !cr1.te() { + if r.cr3().read().hdsel() { cr1.set_te(true); cr1.set_re(enable_readback); r.cr1().write_value(cr1); -- cgit From c78dfa7e31e0808d413ad37de8d966cffe4a8fdd Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 16 Jul 2025 20:14:47 +0200 Subject: stm32: fix stm32g0b0 build. It has USB but not HSI48 which would break things. Only g0x1 has HSI48. --- ci.sh | 1 + embassy-stm32/Cargo.toml | 4 ++-- embassy-stm32/src/rcc/mco.rs | 2 +- embassy-stm32/src/usb/otg.rs | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ci.sh b/ci.sh index 3dc403171..05720e4f2 100755 --- a/ci.sh +++ b/ci.sh @@ -155,6 +155,7 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303c8,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f398ve,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f378cc,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g0b0ce,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g0c1ve,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time-driver-any,low-power,time \ diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 356a2b5bb..eaf8bafbf 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-019a3ce0ea3b5bd832ec2ad53465a0d80b0f4e0a" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-85e2c0f43f3460b3305a2f97962bd39deed09d13" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-019a3ce0ea3b5bd832ec2ad53465a0d80b0f4e0a", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-85e2c0f43f3460b3305a2f97962bd39deed09d13", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs index c50e071fb..0371b9141 100644 --- a/embassy-stm32/src/rcc/mco.rs +++ b/embassy-stm32/src/rcc/mco.rs @@ -74,7 +74,7 @@ macro_rules! impl_peri { }; } -#[cfg(any(rcc_c0, rcc_g0, rcc_u0))] +#[cfg(any(rcc_c0, rcc_g0x0, rcc_g0x1, rcc_u0))] #[allow(unused_imports)] use self::{McoSource as Mco1Source, McoSource as Mco2Source}; diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index 3547ded00..e9afc0c54 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -527,7 +527,7 @@ foreach_interrupt!( ))] { const FIFO_DEPTH_WORDS: u16 = 1024; const ENDPOINT_COUNT: usize = 9; - } else if #[cfg(stm32u5)] { + } else if #[cfg(any(stm32u5, stm32wba))] { const FIFO_DEPTH_WORDS: u16 = 1024; const ENDPOINT_COUNT: usize = 9; } else { -- cgit From d3308f7e5a02da5fb6ccdd6059afe8656761a685 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Wed, 16 Jul 2025 17:32:34 -0700 Subject: Fixed register names from recent stm32-data changes --- embassy-stm32/src/usb/otg.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index a8b625e8c..5602a2541 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -335,7 +335,7 @@ impl<'d, T: Instance> Bus<'d, T> { critical_section::with(|_| { crate::pac::RCC.ahb2enr().modify(|w| { - w.set_otgen(true); + w.set_usb_otg_hsen(true); w.set_otghsphyen(true); }); }); -- cgit From f46bfd4c6ff50740b7177c054918da6a393ca7f1 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Wed, 16 Jul 2025 17:47:48 -0700 Subject: Cargo fmt recent changes --- embassy-stm32/src/usb/otg.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index 5602a2541..b074cfa1b 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -105,7 +105,7 @@ impl<'d, T: Instance> Driver<'d, T> { config: Config, ) -> Self { // For STM32U5 High speed pins need to be left in analog mode - #[cfg(not(any(all(stm32u5, peri_usb_otg_hs),all(stm32wba, peri_usb_otg_hs))))] + #[cfg(not(any(all(stm32u5, peri_usb_otg_hs), all(stm32wba, peri_usb_otg_hs))))] { _dp.set_as_af(_dp.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); _dm.set_as_af(_dm.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); -- cgit From 17fbfc6ffc21349c2032b6e55200fbc4897606d0 Mon Sep 17 00:00:00 2001 From: Wouter Geraedts Date: Thu, 17 Jul 2025 13:37:55 +0200 Subject: Removed reference to ADC3 for STM32G4x1 if the peripheral does not exist and added stm32g431kb to CI for testing --- ci.sh | 1 + embassy-stm32/src/adc/g4.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/ci.sh b/ci.sh index 05720e4f2..842215a6b 100755 --- a/ci.sh +++ b/ci.sh @@ -161,6 +161,7 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time-driver-any,low-power,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32wl54jc-cm0p,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wle5jb,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g431kb,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g474pe,dual-bank,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f107vc,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f103re,defmt,exti,time-driver-any,time \ diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs index cb3e342d8..43498966f 100644 --- a/embassy-stm32/src/adc/g4.rs +++ b/embassy-stm32/src/adc/g4.rs @@ -545,10 +545,12 @@ mod g4 { const CHANNEL: u8 = 17; } + #[cfg(peri_adc3_common)] impl VrefChannel for crate::peripherals::ADC3 { const CHANNEL: u8 = 18; } + #[cfg(peri_adc3_common)] impl VBatChannel for crate::peripherals::ADC3 { const CHANNEL: u8 = 17; } -- cgit From 233bd18fae2da8017a611b9b4f3210af90ff8710 Mon Sep 17 00:00:00 2001 From: Fabian Wolter Date: Thu, 17 Jul 2025 18:00:27 +0200 Subject: STM32F107: Fix inadvertent re-configuration of the SWJ/JTAG pins when activating the (R)MII interface --- embassy-stm32/Cargo.toml | 4 ++-- embassy-stm32/src/eth/v1/mod.rs | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index eaf8bafbf..0266b53b6 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-85e2c0f43f3460b3305a2f97962bd39deed09d13" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f761780b74faf840220b367b15d556b9e10c2334" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-85e2c0f43f3460b3305a2f97962bd39deed09d13", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f761780b74faf840220b367b15d556b9e10c2334", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index 01e321bce..b9746231f 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -122,7 +122,10 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { // Select RMII (Reduced Media Independent Interface) // Must be done prior to enabling peripheral clock - AFIO.mapr().modify(|w| w.set_mii_rmii_sel(true)); + AFIO.mapr().modify(|w| { + w.set_mii_rmii_sel(true); + w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP); + }); RCC.ahbenr().modify(|w| { w.set_ethen(true); @@ -316,7 +319,10 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { // Select MII (Media Independent Interface) // Must be done prior to enabling peripheral clock - AFIO.mapr().modify(|w| w.set_mii_rmii_sel(false)); + AFIO.mapr().modify(|w| { + w.set_mii_rmii_sel(false); + w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP); + }); RCC.ahbenr().modify(|w| { w.set_ethen(true); -- cgit From c279063c426b57f22d8bdeb7356b3c541b16bb08 Mon Sep 17 00:00:00 2001 From: Fabian Wolter Date: Sun, 15 Dec 2024 20:15:11 +0100 Subject: STM32F0/F3 Remap DMA channels Fixes #3643 --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/build.rs | 19 ++++++++++++++++++- embassy-stm32/src/macros.rs | 14 +++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index b6781905e..c4c2cd013 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - Modify BufferedUart initialization to take pins before interrupts ([#3983](https://github.com/embassy-rs/embassy/pull/3983)) - Added a 'single-bank' and a 'dual-bank' feature so chips with configurable flash bank setups are be supported in embassy ([#4125](https://github.com/embassy-rs/embassy/pull/4125)) +- Add automatic setting of remap bits when using alternate DMA channels on STM32F0 and STM32F3 devices ([#3653](https://github.com/embassy-rs/embassy/pull/3653)) ## 0.2.0 - 2025-01-10 diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 753f241c7..068dadf4b 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1551,9 +1551,26 @@ fn main() { quote!(()) }; + let mut remap = quote!(); + for remap_info in ch.remap { + let peripheral = format_ident!("{}", remap_info.peripheral); + let register = format_ident!("{}", remap_info.register.to_lowercase()); + let setter = format_ident!("set_{}", remap_info.field.to_lowercase()); + + let value = if remap_info.value.contains("true") || remap_info.value.contains("false") { + let value = format_ident!("{}", remap_info.value); + quote!(#value) + } else { + let value = remap_info.value.parse::().unwrap(); + quote!(#value.into()) + }; + + remap.extend(quote!(crate::pac::#peripheral.#register().modify(|w| w.#setter(#value));)); + } + let channel = format_ident!("{}", channel); g.extend(quote! { - dma_trait_impl!(#tr, #peri, #channel, #request); + dma_trait_impl!(#tr, #peri, #channel, #request, {#remap}); }); } } diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs index 7526bb180..3a0b490ba 100644 --- a/embassy-stm32/src/macros.rs +++ b/embassy-stm32/src/macros.rs @@ -81,17 +81,28 @@ macro_rules! dma_trait { /// Note: in some chips, ST calls this the "channel", and calls channels "streams". /// `embassy-stm32` always uses the "channel" and "request number" names. fn request(&self) -> crate::dma::Request; + #[doc = "Remap the DMA channel"] + fn remap(&self); } }; } #[allow(unused)] macro_rules! dma_trait_impl { - (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $channel:ident, $request:expr) => { + (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $channel:ident, $request:expr, $remap:expr) => { impl crate::$mod::$trait for crate::peripherals::$channel { fn request(&self) -> crate::dma::Request { $request } + + fn remap(&self) { + critical_section::with(|_| { + #[allow(unused_unsafe)] + unsafe { + $remap; + } + }); + } } }; } @@ -111,6 +122,7 @@ macro_rules! new_dma_nonopt { macro_rules! new_dma { ($name:ident) => {{ let dma = $name; + dma.remap(); let request = dma.request(); Some(crate::dma::ChannelAndRequest { channel: dma.into(), -- cgit From d9f0d80f733abba5d1ca9e1f8b0b81582975d9a1 Mon Sep 17 00:00:00 2001 From: Fabian Wolter Date: Tue, 15 Jul 2025 09:45:05 +0200 Subject: Make remap value a number --- embassy-stm32/build.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 068dadf4b..11b3b4479 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1557,11 +1557,21 @@ fn main() { let register = format_ident!("{}", remap_info.register.to_lowercase()); let setter = format_ident!("set_{}", remap_info.field.to_lowercase()); - let value = if remap_info.value.contains("true") || remap_info.value.contains("false") { - let value = format_ident!("{}", remap_info.value); - quote!(#value) + let field_metadata = METADATA + .peripherals + .iter() + .filter(|p| p.name.eq_ignore_ascii_case(remap_info.peripheral)) + .flat_map(|p| p.registers.as_ref().unwrap().ir.fieldsets.iter()) + .filter(|f| f.name.eq_ignore_ascii_case(remap_info.register)) + .flat_map(|f| f.fields.iter()) + .find(|f| f.name.eq_ignore_ascii_case(remap_info.field)) + .unwrap(); + + let value = if field_metadata.bit_size == 1 { + let bool_value = format_ident!("{}", remap_info.value > 0); + quote!(#bool_value) } else { - let value = remap_info.value.parse::().unwrap(); + let value = remap_info.value; quote!(#value.into()) }; -- cgit From 5ef796ded0aabfb74e25d9050476f9ac9cd2c6ac Mon Sep 17 00:00:00 2001 From: Fabian Wolter Date: Thu, 17 Jul 2025 17:23:02 +0200 Subject: Refactor --- embassy-stm32/build.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 11b3b4479..ad07b0269 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1553,14 +1553,13 @@ fn main() { let mut remap = quote!(); for remap_info in ch.remap { - let peripheral = format_ident!("{}", remap_info.peripheral); let register = format_ident!("{}", remap_info.register.to_lowercase()); let setter = format_ident!("set_{}", remap_info.field.to_lowercase()); let field_metadata = METADATA .peripherals .iter() - .filter(|p| p.name.eq_ignore_ascii_case(remap_info.peripheral)) + .filter(|p| p.name == "SYSCFG") .flat_map(|p| p.registers.as_ref().unwrap().ir.fieldsets.iter()) .filter(|f| f.name.eq_ignore_ascii_case(remap_info.register)) .flat_map(|f| f.fields.iter()) @@ -1575,7 +1574,7 @@ fn main() { quote!(#value.into()) }; - remap.extend(quote!(crate::pac::#peripheral.#register().modify(|w| w.#setter(#value));)); + remap.extend(quote!(crate::pac::SYSCFG.#register().modify(|w| w.#setter(#value));)); } let channel = format_ident!("{}", channel); -- cgit From a3c367d54ef6ec0fe7a2c358c209871a486eadcb Mon Sep 17 00:00:00 2001 From: Fabian Wolter Date: Thu, 17 Jul 2025 21:08:33 +0200 Subject: Update stm32-data-generated dependency --- embassy-stm32/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 0266b53b6..d9c5d1dd9 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f761780b74faf840220b367b15d556b9e10c2334" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6e47f105286c0de07f641e22f27db060f1395e86" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f761780b74faf840220b367b15d556b9e10c2334", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6e47f105286c0de07f641e22f27db060f1395e86", default-features = false, features = ["metadata"] } [features] default = ["rt"] -- cgit From 7be5ce2a31cc2106d589dbb63552ebc509eb27bb Mon Sep 17 00:00:00 2001 From: Bailey Quarters Date: Thu, 17 Jul 2025 23:16:05 +0200 Subject: RP2350: Fix PIO clock divider in the blinky Wi-Fi example --- examples/rp235x/src/bin/blinky_wifi.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/rp235x/src/bin/blinky_wifi.rs b/examples/rp235x/src/bin/blinky_wifi.rs index 8c352ebc4..ef6057a1c 100644 --- a/examples/rp235x/src/bin/blinky_wifi.rs +++ b/examples/rp235x/src/bin/blinky_wifi.rs @@ -5,7 +5,7 @@ #![no_std] #![no_main] -use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER}; +use cyw43_pio::{PioSpi, RM2_CLOCK_DIVIDER}; use defmt::*; use embassy_executor::Spawner; use embassy_rp::bind_interrupts; @@ -58,7 +58,9 @@ async fn main(spawner: Spawner) { let spi = PioSpi::new( &mut pio.common, pio.sm0, - DEFAULT_CLOCK_DIVIDER, + // SPI communication won't work if the speed is too high, so we use a divider larger than `DEFAULT_CLOCK_DIVIDER`. + // See: https://github.com/embassy-rs/embassy/issues/3960. + RM2_CLOCK_DIVIDER, pio.irq0, cs, p.PIN_24, -- cgit From 6d79c4c81187d5f2704e2d2f72a3deba05ca449a Mon Sep 17 00:00:00 2001 From: Roy Date: Wed, 2 Jul 2025 15:24:01 +0300 Subject: feat: added log-to-defmt feature Signed-off-by: Roy --- ci.sh | 1 + embassy-nxp/Cargo.toml | 4 ++++ embassy-nxp/src/lib.rs | 5 +++-- examples/lpc55s69/Cargo.toml | 4 ++++ examples/lpc55s69/src/bin/log_to_defmt.rs | 18 ++++++++++++++++++ 5 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 examples/lpc55s69/src/bin/log_to_defmt.rs diff --git a/ci.sh b/ci.sh index 842215a6b..4f8845158 100755 --- a/ci.sh +++ b/ci.sh @@ -264,6 +264,7 @@ cargo batch \ --- build --release --manifest-path examples/stm32wba/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32wba \ --- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32wl \ --- build --release --manifest-path examples/lpc55s69/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/lpc55s69 \ + --- build --release --manifest-path examples/lpc55s69/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nxp/log-to-defmt --artifact-dir out/examples/lpc55s69 \ --- build --release --manifest-path examples/mspm0g3507/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3507 \ --- build --release --manifest-path examples/mspm0g3519/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3519 \ --- build --release --manifest-path examples/mspm0l1306/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0l1306 \ diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 01f57c4e2..9eb48be17 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -10,6 +10,8 @@ critical-section = "1.1.2" embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } defmt = { version = "1", optional = true } +log = "0.4.27" +log-to-defmt = { version = "0.1.0", optional = true} ## Chip dependencies lpc55-pac = { version = "0.5.0", optional = true } @@ -30,3 +32,5 @@ unstable-pac = [] #! ### Chip selection features lpc55 = ["lpc55-pac"] +## Enable debug logs +log-to-defmt = ["dep:log-to-defmt"] diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs index 433aca9e0..79c66e7f6 100644 --- a/embassy-nxp/src/lib.rs +++ b/embassy-nxp/src/lib.rs @@ -3,7 +3,6 @@ pub mod gpio; #[cfg(feature = "lpc55")] pub mod pint; - // This mod MUST go last, so that it sees all the `impl_foo!` macros #[cfg_attr(feature = "lpc55", path = "chips/lpc55.rs")] mod chip; @@ -25,8 +24,10 @@ pub fn init(_config: config::Config) -> Peripherals { { gpio::init(); pint::init(); + #[cfg(feature = "log-to-defmt")] + log_to_defmt::setup(); + log::info!("Initialization complete"); } - crate::Peripherals::take() } diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index 6ec6e51a8..7e3b82432 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml @@ -18,5 +18,9 @@ defmt-rtt = "1.0.0" panic-probe = { version = "1.0.0", features = ["print-defmt"] } panic-semihosting = "0.6.0" +[features] +## To test all-logs mode +log-to-defmt = ["embassy-nxp/log-to-defmt"] + [profile.release] debug = 2 diff --git a/examples/lpc55s69/src/bin/log_to_defmt.rs b/examples/lpc55s69/src/bin/log_to_defmt.rs new file mode 100644 index 000000000..7aaab5e54 --- /dev/null +++ b/examples/lpc55s69/src/bin/log_to_defmt.rs @@ -0,0 +1,18 @@ +/// To test log-to-defmt feature, you have to run the binary file with the corresponding flag +/// Example: cargo run --bin --feature log-to-defmt + + +#![no_std] +#![no_main] + +use log::*; +use embassy_executor::Spawner; +use {defmt_rtt as _, panic_halt as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + info!("Hello World"); + loop{ + info!("Another test"); + } +} -- cgit From 3e2b23d2f453d10324896484f9d045d2821bd567 Mon Sep 17 00:00:00 2001 From: Nils Ponsard Date: Fri, 18 Jul 2025 16:26:17 +0200 Subject: feat(embassy-nrf): add uicr hfxo workaround In the MDK, there is a workaround "UICR_HFXO_WORKAROUND" that resests the HFXO values if they are erased. This is necessary on my nrf9151 to have the modem working properly. I found this thanks to these two messages: https://github.com/diondokter/nrf-modem/issues/32#issuecomment-2704598018 https://devzone.nordicsemi.com/f/nordic-q-a/96093/nrf9160-porting-the-modem-library-to-work-with-bare-metal-application/435351?focus=true Signed-off-by: Nils Ponsard --- embassy-nrf/src/lib.rs | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 44990ed85..8a88051b4 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -584,6 +584,8 @@ pub mod config { #[allow(unused)] mod consts { pub const UICR_APPROTECT: *mut u32 = 0x00FF8000 as *mut u32; + pub const UICR_HFXOSRC: *mut u32 = 0x00FF801C as *mut u32; + pub const UICR_HFXOCNT: *mut u32 = 0x00FF8020 as *mut u32; pub const UICR_SECUREAPPROTECT: *mut u32 = 0x00FF802C as *mut u32; pub const APPROTECT_ENABLED: u32 = 0x0000_0000; #[cfg(feature = "_nrf9120")] @@ -650,13 +652,18 @@ unsafe fn uicr_write_masked(address: *mut u32, value: u32, mask: u32) -> WriteRe return WriteResult::Failed; } - let nvmc = pac::NVMC; - nvmc.config().write(|w| w.set_wen(pac::nvmc::vals::Wen::WEN)); - while !nvmc.ready().read().ready() {} - address.write_volatile(value | !mask); - while !nvmc.ready().read().ready() {} - nvmc.config().write(|_| {}); - while !nvmc.ready().read().ready() {} + // Nrf9151 errata 7, need to disable interrups + use DSB https://docs.nordicsemi.com/bundle/errata_nRF9151_Rev2/page/ERR/nRF9151/Rev2/latest/anomaly_151_7.html + cortex_m::interrupt::free(|_cs| { + let nvmc = pac::NVMC; + + nvmc.config().write(|w| w.set_wen(pac::nvmc::vals::Wen::WEN)); + while !nvmc.ready().read().ready() {} + address.write_volatile(value | !mask); + cortex_m::asm::dsb(); + while !nvmc.ready().read().ready() {} + nvmc.config().write(|_| {}); + while !nvmc.ready().read().ready() {} + }); WriteResult::Written } @@ -674,6 +681,28 @@ pub fn init(config: config::Config) -> Peripherals { #[allow(unused_mut)] let mut needs_reset = false; + // Workaround used in the nrf mdk: file system_nrf91.c , function SystemInit(), after `#if !defined(NRF_SKIP_UICR_HFXO_WORKAROUND)` + #[cfg(all(feature = "_nrf91", feature = "_s"))] + { + let uicr = pac::UICR_S; + let hfxocnt = uicr.hfxocnt().read().hfxocnt().to_bits(); + let hfxosrc = uicr.hfxosrc().read().hfxosrc().to_bits(); + + if hfxosrc == 1 { + unsafe { + let _ = uicr_write(consts::UICR_HFXOSRC, 0); + } + needs_reset = true; + } + + if hfxocnt == 255 { + unsafe { + let _ = uicr_write(consts::UICR_HFXOCNT, 32); + } + needs_reset = true; + } + } + // Setup debug protection. #[cfg(not(feature = "_nrf51"))] match config.debug { -- cgit From d9cd93ca228b7d4d38066d88b50ff06bb7a5297a Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Fri, 18 Jul 2025 14:23:52 -0700 Subject: Added RTC low-power support for STM32WBA65 Also added low-power feature for STM32WBA65RI build --- ci.sh | 2 +- embassy-stm32/src/rtc/low_power.rs | 12 +++++++++--- embassy-stm32/src/rtc/mod.rs | 2 +- embassy-stm32/src/rtc/v3.rs | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ci.sh b/ci.sh index 842215a6b..229ddaae8 100755 --- a/ci.sh +++ b/ci.sh @@ -172,7 +172,7 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba50ke,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba55ug,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba62cg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba65ri,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba65ri,defmt,exti,time-driver-any,low-power,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u5f9zj,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u5g9nj,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb35ce,defmt,exti,time-driver-any,time \ diff --git a/embassy-stm32/src/rtc/low_power.rs b/embassy-stm32/src/rtc/low_power.rs index cd075f3de..78ccd3e6c 100644 --- a/embassy-stm32/src/rtc/low_power.rs +++ b/embassy-stm32/src/rtc/low_power.rs @@ -66,7 +66,7 @@ pub(crate) enum WakeupPrescaler { } #[cfg(any( - stm32f4, stm32l0, stm32g4, stm32l4, stm32l5, stm32wb, stm32h5, stm32g0, stm32u5, stm32u0 + stm32f4, stm32l0, stm32g4, stm32l4, stm32l5, stm32wb, stm32h5, stm32g0, stm32u5, stm32u0, stm32wba ))] impl From for crate::pac::rtc::vals::Wucksel { fn from(val: WakeupPrescaler) -> Self { @@ -82,7 +82,7 @@ impl From for crate::pac::rtc::vals::Wucksel { } #[cfg(any( - stm32f4, stm32l0, stm32g4, stm32l4, stm32l5, stm32wb, stm32h5, stm32g0, stm32u5, stm32u0 + stm32f4, stm32l0, stm32g4, stm32l4, stm32l5, stm32wb, stm32h5, stm32g0, stm32u5, stm32u0, stm32wba ))] impl From for WakeupPrescaler { fn from(val: crate::pac::rtc::vals::Wucksel) -> Self { @@ -227,7 +227,7 @@ impl Rtc { ::WakeupInterrupt::unpend(); unsafe { ::WakeupInterrupt::enable() }; - #[cfg(not(any(stm32u5, stm32u0)))] + #[cfg(not(any(stm32u5, stm32u0, stm32wba)))] { use crate::pac::EXTI; EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); @@ -247,5 +247,11 @@ impl Rtc { RCC.srdamr().modify(|w| w.set_rtcapbamen(true)); RCC.apb3smenr().modify(|w| w.set_rtcapbsmen(true)); } + #[cfg(stm32wba)] + { + use crate::pac::RCC; + // RCC.srdamr().modify(|w| w.set_rtcapbamen(true)); + RCC.apb7smenr().modify(|w| w.set_rtcapbsmen(true)); + } } } diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 2c5aaca35..449f3008a 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -296,7 +296,7 @@ trait SealedInstance { const BACKUP_REGISTER_COUNT: usize; #[cfg(feature = "low-power")] - #[cfg(not(any(stm32u5, stm32u0)))] + #[cfg(not(any(stm32wba, stm32u5, stm32u0)))] const EXTI_WAKEUP_LINE: usize; #[cfg(feature = "low-power")] diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 39aa6c5cb..d0b52049e 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -146,7 +146,7 @@ impl SealedInstance for crate::peripherals::RTC { type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP; } else if #[cfg(any(stm32g0, stm32u0))] { type WakeupInterrupt = crate::interrupt::typelevel::RTC_TAMP; - } else if #[cfg(any(stm32l5, stm32h5, stm32u5))] { + } else if #[cfg(any(stm32l5, stm32h5, stm32u5, stm32wba))] { type WakeupInterrupt = crate::interrupt::typelevel::RTC; } ); -- cgit From 8c696a579f763163c8820904ba7e3f4d3eaba2a5 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Sat, 19 Jul 2025 21:41:03 -0700 Subject: embassy-stm32: account for WBA devices and VDDIO2 - Different power domain - Same split domain as STM32U5 - Added low_power fixes for STM32WBA too --- embassy-stm32/src/lib.rs | 13 ++++++++++--- embassy-stm32/src/low_power.rs | 6 +++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 06c91ef97..700905850 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -242,12 +242,12 @@ pub struct Config { #[cfg(dbgmcu)] pub enable_debug_during_sleep: bool, - /// On low-power boards (eg. `stm32l4`, `stm32l5` and `stm32u5`), + /// On low-power boards (eg. `stm32l4`, `stm32l5`, `stm32wba` and `stm32u5`), /// some GPIO pins are powered by an auxiliary, independent power supply (`VDDIO2`), /// which needs to be enabled before these pins can be used. /// /// May increase power consumption. Defaults to true. - #[cfg(any(stm32l4, stm32l5, stm32u5))] + #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))] pub enable_independent_io_supply: bool, /// On the U5 series all analog peripherals are powered by a separate supply. @@ -291,7 +291,7 @@ impl Default for Config { rcc: Default::default(), #[cfg(dbgmcu)] enable_debug_during_sleep: true, - #[cfg(any(stm32l4, stm32l5, stm32u5))] + #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))] enable_independent_io_supply: true, #[cfg(stm32u5)] enable_independent_analog_supply: true, @@ -540,6 +540,13 @@ fn init_hw(config: Config) -> Peripherals { w.set_iosv(config.enable_independent_io_supply); }); } + #[cfg(stm32wba)] + { + use crate::pac::pwr::vals; + crate::pac::PWR.svmcr().modify(|w| { + w.set_io2sv(vals::Io2sv::B_0X1); + }); + } #[cfg(stm32u5)] { crate::pac::PWR.svmcr().modify(|w| { diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 7734365f1..4607eb230 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -124,10 +124,10 @@ pub enum StopMode { Stop2, } -#[cfg(any(stm32l4, stm32l5, stm32u5, stm32u0))] +#[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba, stm32u0))] use stm32_metapac::pwr::vals::Lpms; -#[cfg(any(stm32l4, stm32l5, stm32u5, stm32u0))] +#[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba, stm32u0))] impl Into for StopMode { fn into(self) -> Lpms { match self { @@ -198,7 +198,7 @@ impl Executor { #[allow(unused_variables)] fn configure_stop(&mut self, stop_mode: StopMode) { - #[cfg(any(stm32l4, stm32l5, stm32u5, stm32u0))] + #[cfg(any(stm32l4, stm32l5, stm32u5, stm32u0, stm32wba))] crate::pac::PWR.cr1().modify(|m| m.set_lpms(stop_mode.into())); #[cfg(stm32h5)] crate::pac::PWR.pmcr().modify(|v| { -- cgit From 2be8be074764f292822ddf022cc81a5d441ad28d Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 20 Jul 2025 18:45:48 +0100 Subject: Use `unsafe` block in IRQ handlers --- embassy-imxrt/src/lib.rs | 8 +++++--- embassy-mspm0/src/lib.rs | 10 ++++++---- embassy-nrf/src/lib.rs | 10 ++++++---- embassy-rp/src/lib.rs | 10 ++++++---- embassy-stm32/src/lib.rs | 10 ++++++---- 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/embassy-imxrt/src/lib.rs b/embassy-imxrt/src/lib.rs index 5846afe5c..a3437c655 100644 --- a/embassy-imxrt/src/lib.rs +++ b/embassy-imxrt/src/lib.rs @@ -76,9 +76,11 @@ macro_rules! bind_interrupts { #[allow(non_snake_case)] #[no_mangle] unsafe extern "C" fn $irq() { - $( - <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); - )* + unsafe { + $( + <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); + )* + } } $( diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index bb8d91403..629ebfa1f 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -111,11 +111,13 @@ macro_rules! bind_interrupts { #[no_mangle] $(#[cfg($cond_irq)])? unsafe extern "C" fn $irq() { - $( - $(#[cfg($cond_handler)])? - <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); + unsafe { + $( + $(#[cfg($cond_handler)])? + <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); - )* + )* + } } $(#[cfg($cond_irq)])? diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 44990ed85..caa274ff5 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -240,11 +240,13 @@ macro_rules! bind_interrupts { #[no_mangle] $(#[cfg($cond_irq)])? unsafe extern "C" fn $irq() { - $( - $(#[cfg($cond_handler)])? - <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); + unsafe { + $( + $(#[cfg($cond_handler)])? + <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); - )* + )* + } } $(#[cfg($cond_irq)])? diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index f3c5a35bb..9c450b6dc 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -189,11 +189,13 @@ macro_rules! bind_interrupts { #[no_mangle] $(#[cfg($cond_irq)])? unsafe extern "C" fn $irq() { - $( - $(#[cfg($cond_handler)])? - <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); + unsafe { + $( + $(#[cfg($cond_handler)])? + <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); - )* + )* + } } $(#[cfg($cond_irq)])? diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 06c91ef97..46661008f 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -196,11 +196,13 @@ macro_rules! bind_interrupts { $(#[cfg($cond_irq)])? $(#[doc = $doc])* unsafe extern "C" fn $irq() { - $( - $(#[cfg($cond_handler)])? - <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); + unsafe { + $( + $(#[cfg($cond_handler)])? + <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); - )* + )* + } } $(#[cfg($cond_irq)])? -- cgit From e1407f80c00f3749235c0827c14a50a64d87dfb7 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sat, 19 Jul 2025 21:23:40 +0100 Subject: Control RFWKPSEL with ClockMux --- embassy-stm32/Cargo.toml | 4 ++-- embassy-stm32/build.rs | 7 +++++++ embassy-stm32/src/ipcc.rs | 3 --- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index d9c5d1dd9..1a73d84b6 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6e47f105286c0de07f641e22f27db060f1395e86" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-dded8a33a460ae0eb182aee3ccb048beb659982b" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6e47f105286c0de07f641e22f27db060f1395e86", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-dded8a33a460ae0eb182aee3ccb048beb659982b", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index ad07b0269..f4781380c 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -505,6 +505,13 @@ fn main() { field: "CLK48SEL", }, ); + clock_gen.chained_muxes.insert( + "RFWKP", + &PeripheralRccRegister { + register: "CSR", + field: "RFWKPSEL", + }, + ); } if chip_name.starts_with("stm32f7") { clock_gen.chained_muxes.insert( diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs index 20cd20dca..670d8332c 100644 --- a/embassy-stm32/src/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs @@ -104,9 +104,6 @@ impl Ipcc { rcc::enable_and_reset::(); IPCC::set_cpu2(true); - // set RF wake-up clock = LSE - crate::pac::RCC.csr().modify(|w| w.set_rfwkpsel(0b01)); - let regs = IPCC::regs(); regs.cpu(0).cr().modify(|w| { -- cgit From 876ad001128823e8069625c6ad7428c0fdabf7a8 Mon Sep 17 00:00:00 2001 From: obe1line Date: Mon, 21 Jul 2025 12:52:23 +1000 Subject: Update Cargo.toml Added STMC071 and other missing C0 chips --- embassy-stm32/Cargo.toml | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 1a73d84b6..248639385 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -237,6 +237,47 @@ stm32c031g4 = [ "stm32-metapac/stm32c031g4" ] stm32c031g6 = [ "stm32-metapac/stm32c031g6" ] stm32c031k4 = [ "stm32-metapac/stm32c031k4" ] stm32c031k6 = [ "stm32-metapac/stm32c031k6" ] +stm32c051c6 = [ "stm32-metapac/stm32c051c6" ] +stm32c051c8 = [ "stm32-metapac/stm32c051c8" ] +stm32c051d8 = [ "stm32-metapac/stm32c051d8" ] +stm32c051f6 = [ "stm32-metapac/stm32c051f6" ] +stm32c051f8 = [ "stm32-metapac/stm32c051f8" ] +stm32c051g6 = [ "stm32-metapac/stm32c051g6" ] +stm32c051g8 = [ "stm32-metapac/stm32c051g8" ] +stm32c051k6 = [ "stm32-metapac/stm32c051k6" ] +stm32c051k8 = [ "stm32-metapac/stm32c051k8" ] +stm32c071c8 = [ "stm32-metapac/stm32c071c8" ] +stm32c071cb = [ "stm32-metapac/stm32c071cb" ] +stm32c071f8 = [ "stm32-metapac/stm32c071f8" ] +stm32c071fb = [ "stm32-metapac/stm32c071fb" ] +stm32c071g8 = [ "stm32-metapac/stm32c071g8" ] +stm32c071gb = [ "stm32-metapac/stm32c071gb" ] +stm32c071k8 = [ "stm32-metapac/stm32c071k8" ] +stm32c071kb = [ "stm32-metapac/stm32c071kb" ] +stm32c071r8 = [ "stm32-metapac/stm32c071r8" ] +stm32c071rb = [ "stm32-metapac/stm32c071rb" ] +stm32c091cb = [ "stm32-metapac/stm32c091cb" ] +stm32c091cc = [ "stm32-metapac/stm32c091cc" ] +stm32c091ec = [ "stm32-metapac/stm32c091ec" ] +stm32c091fb = [ "stm32-metapac/stm32c091fb" ] +stm32c091fc = [ "stm32-metapac/stm32c091fc" ] +stm32c091gb = [ "stm32-metapac/stm32c091gb" ] +stm32c091gc = [ "stm32-metapac/stm32c091gc" ] +stm32c091kb = [ "stm32-metapac/stm32c091kb" ] +stm32c091kc = [ "stm32-metapac/stm32c091kc" ] +stm32c091rb = [ "stm32-metapac/stm32c091rb" ] +stm32c091rc = [ "stm32-metapac/stm32c091rc" ] +stm32c092cb = [ "stm32-metapac/stm32c092cb" ] +stm32c092cc = [ "stm32-metapac/stm32c092cc" ] +stm32c092ec = [ "stm32-metapac/stm32c092ec" ] +stm32c092fb = [ "stm32-metapac/stm32c092fb" ] +stm32c092fc = [ "stm32-metapac/stm32c092fc" ] +stm32c092gb = [ "stm32-metapac/stm32c092gb" ] +stm32c092gc = [ "stm32-metapac/stm32c092gc" ] +stm32c092kb = [ "stm32-metapac/stm32c092kb" ] +stm32c092kc = [ "stm32-metapac/stm32c092kc" ] +stm32c092rb = [ "stm32-metapac/stm32c092rb" ] +stm32c092rc = [ "stm32-metapac/stm32c092rc" ] stm32f030c6 = [ "stm32-metapac/stm32f030c6" ] stm32f030c8 = [ "stm32-metapac/stm32f030c8" ] stm32f030cc = [ "stm32-metapac/stm32f030cc" ] -- cgit From 87f469792a5e41cb415ce51dd6fa85908248b478 Mon Sep 17 00:00:00 2001 From: obe1line Date: Mon, 21 Jul 2025 13:37:48 +1000 Subject: Added rcc_c0v2 to fix undefined McoSource with STM32C071 --- embassy-stm32/src/rcc/mco.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs index 0371b9141..96e628b1a 100644 --- a/embassy-stm32/src/rcc/mco.rs +++ b/embassy-stm32/src/rcc/mco.rs @@ -74,7 +74,7 @@ macro_rules! impl_peri { }; } -#[cfg(any(rcc_c0, rcc_g0x0, rcc_g0x1, rcc_u0))] +#[cfg(any(rcc_c0, rcc_c0v2, rcc_g0x0, rcc_g0x1, rcc_u0))] #[allow(unused_imports)] use self::{McoSource as Mco1Source, McoSource as Mco2Source}; -- cgit From 6bfdbf0ed827da7ab447359f97799cc1b707fde9 Mon Sep 17 00:00:00 2001 From: obe1line Date: Mon, 21 Jul 2025 14:27:05 +1000 Subject: Added stm32fc071 to cfg to force RCC.cr to be used --- embassy-stm32/src/rcc/hsi48.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/rcc/hsi48.rs b/embassy-stm32/src/rcc/hsi48.rs index 3ea5c96c9..49be4af5e 100644 --- a/embassy-stm32/src/rcc/hsi48.rs +++ b/embassy-stm32/src/rcc/hsi48.rs @@ -39,9 +39,9 @@ pub(crate) fn init_hsi48(config: Hsi48Config) -> Hertz { }); // Enable HSI48 - #[cfg(not(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba, stm32f0)))] + #[cfg(not(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba, stm32f0, stm32c071)))] let r = RCC.crrcr(); - #[cfg(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba))] + #[cfg(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba, stm32c071))] let r = RCC.cr(); #[cfg(any(stm32f0))] let r = RCC.cr2(); -- cgit From ac996e7e0a08f0a8914c76e4ee040e75a4b2b19b Mon Sep 17 00:00:00 2001 From: obe1line Date: Mon, 21 Jul 2025 14:31:48 +1000 Subject: Added ccipr1 conditional for STM32C071 --- embassy-stm32/src/rcc/c0.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs index cac2a9149..5a584d993 100644 --- a/embassy-stm32/src/rcc/c0.rs +++ b/embassy-stm32/src/rcc/c0.rs @@ -192,8 +192,12 @@ pub(crate) unsafe fn init(config: Config) { lse: None, ); - RCC.ccipr() - .modify(|w| w.set_adc1sel(stm32_metapac::rcc::vals::Adcsel::SYS)); + #[cfg(not(any(stm32c071)))] + let r = RCC.ccipr(); + #[cfg(any(stm32c071))] + let r = RCC.ccipr1(); + + r.modify(|w| w.set_adc1sel(stm32_metapac::rcc::vals::Adcsel::SYS)); } mod max { -- cgit From 26232778e69bdfddcd1df0747b7414ef936e3ea2 Mon Sep 17 00:00:00 2001 From: obe1line Date: Mon, 21 Jul 2025 14:39:07 +1000 Subject: hsi48 field missing for STM32C071 --- embassy-stm32/src/rcc/c0.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs index 5a584d993..d44914719 100644 --- a/embassy-stm32/src/rcc/c0.rs +++ b/embassy-stm32/src/rcc/c0.rs @@ -186,7 +186,10 @@ pub(crate) unsafe fn init(config: Config) { hsiker: hsiker, hse: hse, rtc: rtc, - + + #[cfg(any(stm32c071))] + hsi48: hsi, + // TODO lsi: None, lse: None, -- cgit From 0fc1ab290fed27301b455a039c2ae9c16ce7c30c Mon Sep 17 00:00:00 2001 From: Roi Bachynskyi Date: Mon, 21 Jul 2025 10:47:21 +0300 Subject: Revert "feat: added log-to-defmt feature" This reverts commit 6d79c4c81187d5f2704e2d2f72a3deba05ca449a. --- ci.sh | 1 - embassy-nxp/Cargo.toml | 4 ---- embassy-nxp/src/lib.rs | 5 ++--- examples/lpc55s69/Cargo.toml | 4 ---- examples/lpc55s69/src/bin/log_to_defmt.rs | 18 ------------------ 5 files changed, 2 insertions(+), 30 deletions(-) delete mode 100644 examples/lpc55s69/src/bin/log_to_defmt.rs diff --git a/ci.sh b/ci.sh index 4f8845158..842215a6b 100755 --- a/ci.sh +++ b/ci.sh @@ -264,7 +264,6 @@ cargo batch \ --- build --release --manifest-path examples/stm32wba/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32wba \ --- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32wl \ --- build --release --manifest-path examples/lpc55s69/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/lpc55s69 \ - --- build --release --manifest-path examples/lpc55s69/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nxp/log-to-defmt --artifact-dir out/examples/lpc55s69 \ --- build --release --manifest-path examples/mspm0g3507/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3507 \ --- build --release --manifest-path examples/mspm0g3519/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3519 \ --- build --release --manifest-path examples/mspm0l1306/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0l1306 \ diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 9eb48be17..01f57c4e2 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -10,8 +10,6 @@ critical-section = "1.1.2" embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } defmt = { version = "1", optional = true } -log = "0.4.27" -log-to-defmt = { version = "0.1.0", optional = true} ## Chip dependencies lpc55-pac = { version = "0.5.0", optional = true } @@ -32,5 +30,3 @@ unstable-pac = [] #! ### Chip selection features lpc55 = ["lpc55-pac"] -## Enable debug logs -log-to-defmt = ["dep:log-to-defmt"] diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs index 79c66e7f6..433aca9e0 100644 --- a/embassy-nxp/src/lib.rs +++ b/embassy-nxp/src/lib.rs @@ -3,6 +3,7 @@ pub mod gpio; #[cfg(feature = "lpc55")] pub mod pint; + // This mod MUST go last, so that it sees all the `impl_foo!` macros #[cfg_attr(feature = "lpc55", path = "chips/lpc55.rs")] mod chip; @@ -24,10 +25,8 @@ pub fn init(_config: config::Config) -> Peripherals { { gpio::init(); pint::init(); - #[cfg(feature = "log-to-defmt")] - log_to_defmt::setup(); - log::info!("Initialization complete"); } + crate::Peripherals::take() } diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index 7e3b82432..6ec6e51a8 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml @@ -18,9 +18,5 @@ defmt-rtt = "1.0.0" panic-probe = { version = "1.0.0", features = ["print-defmt"] } panic-semihosting = "0.6.0" -[features] -## To test all-logs mode -log-to-defmt = ["embassy-nxp/log-to-defmt"] - [profile.release] debug = 2 diff --git a/examples/lpc55s69/src/bin/log_to_defmt.rs b/examples/lpc55s69/src/bin/log_to_defmt.rs deleted file mode 100644 index 7aaab5e54..000000000 --- a/examples/lpc55s69/src/bin/log_to_defmt.rs +++ /dev/null @@ -1,18 +0,0 @@ -/// To test log-to-defmt feature, you have to run the binary file with the corresponding flag -/// Example: cargo run --bin --feature log-to-defmt - - -#![no_std] -#![no_main] - -use log::*; -use embassy_executor::Spawner; -use {defmt_rtt as _, panic_halt as _}; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - info!("Hello World"); - loop{ - info!("Another test"); - } -} -- cgit From 2a696579275a035ab56023313284f8a66ef37a45 Mon Sep 17 00:00:00 2001 From: Roi Bachynskyi Date: Mon, 21 Jul 2025 12:49:17 +0300 Subject: feat: fmt.rs was added --- embassy-nxp/Cargo.toml | 2 +- embassy-nxp/src/fmt.rs | 284 ++++++++++++++++++++++++++++++++++++++++++ embassy-nxp/src/gpio/lpc55.rs | 1 + embassy-nxp/src/lib.rs | 1 + embassy-nxp/src/pint.rs | 2 + examples/lpc55s69/Cargo.toml | 2 +- 6 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 embassy-nxp/src/fmt.rs diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 01f57c4e2..56d00bfb2 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -10,6 +10,7 @@ critical-section = "1.1.2" embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } defmt = { version = "1", optional = true } +log = { version = "0.4.27", optional = true } ## Chip dependencies lpc55-pac = { version = "0.5.0", optional = true } @@ -21,7 +22,6 @@ rt = ["lpc55-pac?/rt"] ## Enable [defmt support](https://docs.rs/defmt) and enables `defmt` debug-log messages and formatting in embassy drivers. defmt = ["dep:defmt", "embassy-hal-internal/defmt", "embassy-sync/defmt"] - ## Reexport the PAC for the currently enabled chip at `embassy_nxp::pac` (unstable) unstable-pac = [] # This is unstable because semver-minor (non-breaking) releases of embassy-nrf may major-bump (breaking) the PAC version. diff --git a/embassy-nxp/src/fmt.rs b/embassy-nxp/src/fmt.rs new file mode 100644 index 000000000..27d41ace6 --- /dev/null +++ b/embassy-nxp/src/fmt.rs @@ -0,0 +1,284 @@ +//! Copied from embassy-rp + +#![macro_use] +#![allow(unused)] + +use core::fmt::{Debug, Display, LowerHex}; + +#[cfg(all(feature = "defmt", feature = "log"))] +compile_error!("You may not enable both `defmt` and `log` features."); + +#[collapse_debuginfo(yes)] +macro_rules! assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert!($($x)*); + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_eq!($($x)*); + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_ne!($($x)*); + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! debug_assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert!($($x)*); + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! debug_assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert_eq!($($x)*); + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! debug_assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert_ne!($($x)*); + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! todo { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::todo!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::todo!($($x)*); + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! unreachable { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! unimplemented { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::unimplemented!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unimplemented!($($x)*); + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! panic { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::panic!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::panic!($($x)*); + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! trace { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::trace!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::trace!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! debug { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::debug!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::debug!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! info { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::info!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::info!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! warn { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::warn!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::warn!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! error { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::error!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::error!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[cfg(feature = "defmt")] +#[collapse_debuginfo(yes)] +macro_rules! unwrap { + ($($x:tt)*) => { + ::defmt::unwrap!($($x)*) + }; +} + +#[cfg(not(feature = "defmt"))] +#[collapse_debuginfo(yes)] +macro_rules! unwrap { + ($arg:expr) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); + } + } + }; + ($arg:expr, $($msg:expr),+ $(,)? ) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); + } + } + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct NoneError; + +pub trait Try { + type Ok; + type Error; + fn into_result(self) -> Result; +} + +impl Try for Option { + type Ok = T; + type Error = NoneError; + + #[inline] + fn into_result(self) -> Result { + self.ok_or(NoneError) + } +} + +impl Try for Result { + type Ok = T; + type Error = E; + + #[inline] + fn into_result(self) -> Self { + self + } +} + +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/embassy-nxp/src/gpio/lpc55.rs b/embassy-nxp/src/gpio/lpc55.rs index 94cd8b7f8..8f407bb3a 100644 --- a/embassy-nxp/src/gpio/lpc55.rs +++ b/embassy-nxp/src/gpio/lpc55.rs @@ -7,6 +7,7 @@ pub(crate) fn init() { syscon_reg() .ahbclkctrl0 .modify(|_, w| w.gpio0().enable().gpio1().enable().mux().enable().iocon().enable()); + info!("GPIO initialized"); } /// The GPIO pin level for pins set on "Digital" mode. diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs index 433aca9e0..1abaca708 100644 --- a/embassy-nxp/src/lib.rs +++ b/embassy-nxp/src/lib.rs @@ -1,5 +1,6 @@ #![no_std] +pub mod fmt; pub mod gpio; #[cfg(feature = "lpc55")] pub mod pint; diff --git a/embassy-nxp/src/pint.rs b/embassy-nxp/src/pint.rs index dc117e7e3..ff414b4e6 100644 --- a/embassy-nxp/src/pint.rs +++ b/embassy-nxp/src/pint.rs @@ -101,6 +101,8 @@ pub(crate) fn init() { crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT6); crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT7); }; + + info!("Pin interrupts initialized"); } #[must_use = "futures do nothing unless you `.await` or poll them"] diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index 6ec6e51a8..1724a22d4 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] -embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55", "rt"] } +embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55", "rt", "defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } -- cgit From 726991f2e9e951569e37552b5560fb06891d99e8 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Mon, 21 Jul 2025 03:07:41 -0700 Subject: Working example in usb_hs_serial.rs --- embassy-stm32/Cargo.toml | 4 +- examples/stm32wba/.cargo/config.toml | 2 +- examples/stm32wba/Cargo.toml | 4 +- examples/stm32wba/src/bin/usb_hs_serial.rs | 112 +++++++++++++++++++++++++++ examples/stm32wba/src/bin/usb_serial.rs | 119 +++++++++++++++++++++++++++++ 5 files changed, 237 insertions(+), 4 deletions(-) create mode 100644 examples/stm32wba/src/bin/usb_hs_serial.rs create mode 100644 examples/stm32wba/src/bin/usb_serial.rs diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 1a73d84b6..5eecce848 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-dded8a33a460ae0eb182aee3ccb048beb659982b" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6201a7707ff38ac42ad50d5317dbd9e1e3686de3" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-dded8a33a460ae0eb182aee3ccb048beb659982b", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6201a7707ff38ac42ad50d5317dbd9e1e3686de3", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/examples/stm32wba/.cargo/config.toml b/examples/stm32wba/.cargo/config.toml index c96a5cb6c..1896068d8 100644 --- a/examples/stm32wba/.cargo/config.toml +++ b/examples/stm32wba/.cargo/config.toml @@ -1,5 +1,5 @@ [target.'cfg(all(target_arch = "arm", target_os = "none"))'] -runner = "probe-rs run --chip STM32WBA55CGUx" +runner = "probe-rs run --chip STM32WBA65RI" [build] target = "thumbv8m.main-none-eabihf" diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml index 2c638f9f4..1ddae5fee 100644 --- a/examples/stm32wba/Cargo.toml +++ b/examples/stm32wba/Cargo.toml @@ -5,11 +5,13 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] } +embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba65ri", "time-driver-any", "memory-x", "exti"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32wba/src/bin/usb_hs_serial.rs b/examples/stm32wba/src/bin/usb_hs_serial.rs new file mode 100644 index 000000000..4684e3aa6 --- /dev/null +++ b/examples/stm32wba/src/bin/usb_hs_serial.rs @@ -0,0 +1,112 @@ +#![no_std] +#![no_main] + +use defmt::{panic, *}; +use defmt_rtt as _; // global logger +use embassy_executor::Spawner; +use embassy_futures::join::join; +use embassy_stm32::usb::{Driver, Instance}; +use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; +use embassy_stm32::rcc::{VoltageScale, Hse, HsePrescaler, Sysclk, mux}; +use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; +use embassy_usb::driver::EndpointError; +use embassy_usb::Builder; +use panic_probe as _; + +bind_interrupts!(struct Irqs { + USB_OTG_HS => usb::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + info!("Hello World!"); + + let mut config = Config::default(); + + // ── Run off the external 32 MHz crystal directly ── + config.rcc.hse = Some(Hse { prescaler: HsePrescaler::DIV1 }); + config.rcc.sys = Sysclk::HSE; + // route HSE into the USB‐OTG‐HS block + config.rcc.mux.otghssel = mux::Otghssel::HSE; + config.rcc.sys = Sysclk::PLL1_R; + config.rcc.voltage_scale = VoltageScale::RANGE1; + + let p = embassy_stm32::init(config); + + // Create the driver, from the HAL. + let mut ep_out_buffer = [0u8; 256]; + let mut config = embassy_stm32::usb::Config::default(); + // Do not enable vbus_detection. This is a safe default that works in all boards. + // However, if your USB device is self-powered (can stay powered on if USB is unplugged), you need + // to enable vbus_detection to comply with the USB spec. If you enable it, the board + // has to support it or USB won't work at all. See docs on `vbus_detection` for details. + config.vbus_detection = false; + let driver = Driver::new_hs(p.USB_OTG_HS, Irqs, p.PD6, p.PD7, &mut ep_out_buffer, config); + + // Create embassy-usb Config + let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Embassy"); + config.product = Some("USB-serial example"); + config.serial_number = Some("12345678"); + + // Create embassy-usb DeviceBuilder using the driver and config. + // It needs some buffers for building the descriptors. + let mut config_descriptor = [0; 256]; + let mut bos_descriptor = [0; 256]; + let mut control_buf = [0; 64]; + + let mut state = State::new(); + + let mut builder = Builder::new( + driver, + config, + &mut config_descriptor, + &mut bos_descriptor, + &mut [], // no msos descriptors + &mut control_buf, + ); + + // Create classes on the builder. + let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); + + // Build the builder. + let mut usb = builder.build(); + + // Run the USB device. + let usb_fut = usb.run(); + + // Do stuff with the class! + let echo_fut = async { + loop { + class.wait_connection().await; + info!("Connected"); + let _ = echo(&mut class).await; + info!("Disconnected"); + } + }; + + // Run everything concurrently. + // If we had made everything `'static` above instead, we could do this using separate tasks instead. + join(usb_fut, echo_fut).await; +} + +struct Disconnected {} + +impl From for Disconnected { + fn from(val: EndpointError) -> Self { + match val { + EndpointError::BufferOverflow => panic!("Buffer overflow"), + EndpointError::Disabled => Disconnected {}, + } + } +} + +async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> { + let mut buf = [0; 64]; + loop { + let n = class.read_packet(&mut buf).await?; + let data = &buf[..n]; + info!("data: {:x}", data); + class.write_packet(data).await?; + } +} diff --git a/examples/stm32wba/src/bin/usb_serial.rs b/examples/stm32wba/src/bin/usb_serial.rs new file mode 100644 index 000000000..8d60aed8c --- /dev/null +++ b/examples/stm32wba/src/bin/usb_serial.rs @@ -0,0 +1,119 @@ +#![no_std] +#![no_main] + +use defmt::{panic, *}; +use defmt_rtt as _; // global logger +use embassy_executor::Spawner; +use embassy_futures::join::join; +use embassy_stm32::usb::{Driver, Instance}; +use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; +use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; +use embassy_usb::driver::EndpointError; +use embassy_usb::Builder; +use panic_probe as _; + +bind_interrupts!(struct Irqs { + OTG_HS => usb::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + info!("Hello World!"); + + let mut config = Config::default(); + { + use embassy_stm32::rcc::*; + config.rcc.hsi = true; + config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, // 16 MHz + prediv: PllPreDiv::DIV1, + mul: PllMul::MUL10, + divp: None, + divq: None, + divr: Some(PllDiv::DIV1), // 160 MHz + }); + config.rcc.sys = Sysclk::PLL1_R; + config.rcc.voltage_range = VoltageScale::RANGE1; + config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB + config.rcc.mux.iclksel = mux::Iclksel::HSI48; // USB uses ICLK + } + + let p = embassy_stm32::init(config); + + // Create the driver, from the HAL. + let mut ep_out_buffer = [0u8; 256]; + let mut config = embassy_stm32::usb::Config::default(); + // Do not enable vbus_detection. This is a safe default that works in all boards. + // However, if your USB device is self-powered (can stay powered on if USB is unplugged), you need + // to enable vbus_detection to comply with the USB spec. If you enable it, the board + // has to support it or USB won't work at all. See docs on `vbus_detection` for details. + config.vbus_detection = false; + let driver = Driver::new_hs(p.USB_OTG_HS, Irqs, p.PD6, p.PD7, &mut ep_out_buffer, config); + + // Create embassy-usb Config + let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Embassy"); + config.product = Some("USB-serial example"); + config.serial_number = Some("12345678"); + + // Create embassy-usb DeviceBuilder using the driver and config. + // It needs some buffers for building the descriptors. + let mut config_descriptor = [0; 256]; + let mut bos_descriptor = [0; 256]; + let mut control_buf = [0; 64]; + + let mut state = State::new(); + + let mut builder = Builder::new( + driver, + config, + &mut config_descriptor, + &mut bos_descriptor, + &mut [], // no msos descriptors + &mut control_buf, + ); + + // Create classes on the builder. + let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); + + // Build the builder. + let mut usb = builder.build(); + + // Run the USB device. + let usb_fut = usb.run(); + + // Do stuff with the class! + let echo_fut = async { + loop { + class.wait_connection().await; + info!("Connected"); + let _ = echo(&mut class).await; + info!("Disconnected"); + } + }; + + // Run everything concurrently. + // If we had made everything `'static` above instead, we could do this using separate tasks instead. + join(usb_fut, echo_fut).await; +} + +struct Disconnected {} + +impl From for Disconnected { + fn from(val: EndpointError) -> Self { + match val { + EndpointError::BufferOverflow => panic!("Buffer overflow"), + EndpointError::Disabled => Disconnected {}, + } + } +} + +async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> { + let mut buf = [0; 64]; + loop { + let n = class.read_packet(&mut buf).await?; + let data = &buf[..n]; + info!("data: {:x}", data); + class.write_packet(data).await?; + } +} -- cgit From de4537d000ffeb8821a58056a99e76bb12c1536e Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 21 Jul 2025 13:20:35 +0200 Subject: stm32: Fix build for WBA lowpower. --- embassy-stm32/src/low_power.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 4607eb230..d13df5a6b 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -132,7 +132,10 @@ impl Into for StopMode { fn into(self) -> Lpms { match self { StopMode::Stop1 => Lpms::STOP1, + #[cfg(not(stm32wba))] StopMode::Stop2 => Lpms::STOP2, + #[cfg(stm32wba)] + StopMode::Stop2 => Lpms::STOP1, // TODO: WBA has no STOP2? } } } -- cgit From 4c098faef528e18e0b17e540b12487eef9acccbc Mon Sep 17 00:00:00 2001 From: Timo Kröger Date: Mon, 21 Jul 2025 11:26:01 +0200 Subject: chore: Prepare release for `embassy-boot-*` crates Prepare the bootloader crates for a release with `embassy-sync@0.7.0` as dependency for compatiblity with other released crates. `embassy-sync` is used in the public api of `embassy-boot` which is reexported by the `embassy-boot-*` crates. That is why a minor version bump of all crates is required. --- embassy-boot-nrf/Cargo.toml | 4 ++-- embassy-boot-rp/Cargo.toml | 4 ++-- embassy-boot-stm32/Cargo.toml | 4 ++-- embassy-boot/Cargo.toml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index 1230cbd3b..81479759c 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-nrf" -version = "0.5.0" +version = "0.6.0" description = "Bootloader lib for nRF chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" @@ -26,7 +26,7 @@ log = { version = "0.4.17", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-nrf = { version = "0.5.0", path = "../embassy-nrf", default-features = false } -embassy-boot = { version = "0.4.0", path = "../embassy-boot" } +embassy-boot = { version = "0.5.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" diff --git a/embassy-boot-rp/Cargo.toml b/embassy-boot-rp/Cargo.toml index 23d6c7853..8ca999f67 100644 --- a/embassy-boot-rp/Cargo.toml +++ b/embassy-boot-rp/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-rp" -version = "0.5.0" +version = "0.6.0" description = "Bootloader lib for RP2040 chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" @@ -26,7 +26,7 @@ log = { version = "0.4", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-rp = { version = "0.6.0", path = "../embassy-rp", default-features = false } -embassy-boot = { version = "0.4.0", path = "../embassy-boot" } +embassy-boot = { version = "0.5.0", path = "../embassy-boot" } embassy-time = { version = "0.4.0", path = "../embassy-time" } cortex-m = { version = "0.7.6" } diff --git a/embassy-boot-stm32/Cargo.toml b/embassy-boot-stm32/Cargo.toml index 11ad453b8..b92d06c54 100644 --- a/embassy-boot-stm32/Cargo.toml +++ b/embassy-boot-stm32/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-stm32" -version = "0.3.0" +version = "0.4.0" description = "Bootloader lib for STM32 chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" @@ -26,7 +26,7 @@ log = { version = "0.4", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-stm32 = { version = "0.2.0", path = "../embassy-stm32", default-features = false } -embassy-boot = { version = "0.4.0", path = "../embassy-boot" } +embassy-boot = { version = "0.5.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" diff --git a/embassy-boot/Cargo.toml b/embassy-boot/Cargo.toml index 281278abb..172330ef2 100644 --- a/embassy-boot/Cargo.toml +++ b/embassy-boot/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot" -version = "0.4.0" +version = "0.5.0" description = "A lightweight bootloader supporting firmware updates in a power-fail-safe way, with trial boots and rollbacks." license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" -- cgit From fad100cfa033df7553b0754820ff94ede3376d26 Mon Sep 17 00:00:00 2001 From: Timo Kröger Date: Mon, 21 Jul 2025 13:02:56 +0200 Subject: chore: Update examples to new `nrf-boot-*` version --- examples/boot/application/nrf/Cargo.toml | 4 ++-- examples/boot/application/rp/Cargo.toml | 2 +- examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wb-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wl/Cargo.toml | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 9c7fdf148..37183df97 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -9,8 +9,8 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } embassy-nrf = { version = "0.5.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } -embassy-boot = { version = "0.4.0", path = "../../../../embassy-boot", features = [] } -embassy-boot-nrf = { version = "0.5.0", path = "../../../../embassy-boot-nrf", features = [] } +embassy-boot = { version = "0.5.0", path = "../../../../embassy-boot", features = [] } +embassy-boot-nrf = { version = "0.6.0", path = "../../../../embassy-boot-nrf", features = [] } embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index afb0871e6..e5568f6bb 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } embassy-rp = { version = "0.6.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } -embassy-boot-rp = { version = "0.5.0", path = "../../../../embassy-boot-rp", features = [] } +embassy-boot-rp = { version = "0.6.0", path = "../../../../embassy-boot-rp", features = [] } embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = "1.0.1" diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index 4cd2d1338..be8b7bff1 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32" } +embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32" } embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index f3d74f53a..2b0175a0c 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } -embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index 427b15bcb..3c88f4241 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 46e79f7ed..b4e7e090a 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } -embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index ae3cd3600..394578e1a 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index a41b25562..abe0451fd 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index 287fcf806..bc4681f79 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb" } embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index af49db260..0552d109a 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.3.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } -- cgit From 9b3c97bcf7efc84f1943ee5de2ae251502ca071c Mon Sep 17 00:00:00 2001 From: Timo Kröger Date: Mon, 21 Jul 2025 13:12:48 +0200 Subject: chore: Bump `embassy-boot` version also for `embassy-usb-dfu` --- embassy-usb-dfu/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-usb-dfu/Cargo.toml b/embassy-usb-dfu/Cargo.toml index cdad3ce00..011046ba4 100644 --- a/embassy-usb-dfu/Cargo.toml +++ b/embassy-usb-dfu/Cargo.toml @@ -31,7 +31,7 @@ log = { version = "0.4.17", optional = true } bitflags = "2.4.1" cortex-m = { version = "0.7.7", features = ["inline-asm"], optional = true } -embassy-boot = { version = "0.4.0", path = "../embassy-boot" } +embassy-boot = { version = "0.5.0", path = "../embassy-boot" } embassy-futures = { version = "0.1.1", path = "../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time" } -- cgit From a80eb48e67d486ace9b9a4733f2b54d58a80eb52 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Mon, 21 Jul 2025 04:46:29 -0700 Subject: WIP changes --- embassy-stm32/src/usb/otg.rs | 2 +- examples/stm32wba/src/bin/usb_hs_serial.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index b074cfa1b..c8499bdc7 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -354,7 +354,7 @@ impl<'d, T: Instance> Bus<'d, T> { // Configuring Vbus sense and SOF output match core_id { 0x0000_1200 | 0x0000_1100 | 0x0000_1000 => self.inner.config_v1(), - 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 => self.inner.config_v2v3(), + 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 | 0x0000_6100 => self.inner.config_v2v3(), 0x0000_5000 => self.inner.config_v5(), _ => unimplemented!("Unknown USB core id {:X}", core_id), } diff --git a/examples/stm32wba/src/bin/usb_hs_serial.rs b/examples/stm32wba/src/bin/usb_hs_serial.rs index 4684e3aa6..1ffd94906 100644 --- a/examples/stm32wba/src/bin/usb_hs_serial.rs +++ b/examples/stm32wba/src/bin/usb_hs_serial.rs @@ -28,7 +28,7 @@ async fn main(_spawner: Spawner) { config.rcc.sys = Sysclk::HSE; // route HSE into the USB‐OTG‐HS block config.rcc.mux.otghssel = mux::Otghssel::HSE; - config.rcc.sys = Sysclk::PLL1_R; + config.rcc.sys = Sysclk::HSE; config.rcc.voltage_scale = VoltageScale::RANGE1; let p = embassy_stm32::init(config); -- cgit From 4db3910011a6a2fddc14f17bcc34a2aeb093d7b6 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 21 Jul 2025 14:17:12 +0200 Subject: Disable flaky test rpi-pico/cyw43-perf --- ci.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci.sh b/ci.sh index 229ddaae8..9d3e47a41 100755 --- a/ci.sh +++ b/ci.sh @@ -376,6 +376,7 @@ rm out/tests/pimoroni-pico-plus-2/pwm # flaky rm out/tests/rpi-pico/pwm +rm out/tests/rpi-pico/cyw43-perf if [[ -z "${TELEPROBE_TOKEN-}" ]]; then echo No teleprobe token found, skipping running HIL tests -- cgit From 79fbf214ccc7be89d8d656cf0c5b5ffe5425bece Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 20 Jul 2025 15:38:42 +0100 Subject: Enable oversampling for ADC v3 --- embassy-stm32/src/adc/v3.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index 313244e19..fd74d5318 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -1,5 +1,7 @@ use cfg_if::cfg_if; use pac::adc::vals::Dmacfg; +#[cfg(adc_v3)] +use pac::adc::vals::{OversamplingRatio, OversamplingShift, Rovsm, Trovs}; use super::{ blocking_delay_us, Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, @@ -470,6 +472,23 @@ impl<'d, T: Instance> Adc<'d, T> { T::regs().cfgr2().modify(|reg| reg.set_ovse(enable)); } + #[cfg(adc_v3)] + pub fn enable_regular_oversampling_mode(&mut self, mode: Rovsm, trig_mode: Trovs, enable: bool) { + T::regs().cfgr2().modify(|reg| reg.set_trovs(trig_mode)); + T::regs().cfgr2().modify(|reg| reg.set_rovsm(mode)); + T::regs().cfgr2().modify(|reg| reg.set_rovse(enable)); + } + + #[cfg(adc_v3)] + pub fn set_oversampling_ratio(&mut self, ratio: OversamplingRatio) { + T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio)); + } + + #[cfg(adc_v3)] + pub fn set_oversampling_shift(&mut self, shift: OversamplingShift) { + T::regs().cfgr2().modify(|reg| reg.set_ovss(shift)); + } + fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) { cfg_if! { if #[cfg(any(adc_g0, adc_u0))] { -- cgit From f96f68077b4f7d3cb9e9cd914df0d5157c17c297 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Tue, 22 Jul 2025 10:36:29 +0800 Subject: chore: bump embassy-usb-synopsys-otg version Signed-off-by: Haobo Gu --- embassy-stm32/Cargo.toml | 2 +- embassy-usb-synopsys-otg/CHANGELOG.md | 4 ++++ embassy-usb-synopsys-otg/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 1a73d84b6..43aee4e1a 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -57,7 +57,7 @@ embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", fe embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } -embassy-usb-synopsys-otg = { version = "0.2.0", path = "../embassy-usb-synopsys-otg" } +embassy-usb-synopsys-otg = { version = "0.3.0", path = "../embassy-usb-synopsys-otg" } embassy-executor = { version = "0.7.0", path = "../embassy-executor", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } diff --git a/embassy-usb-synopsys-otg/CHANGELOG.md b/embassy-usb-synopsys-otg/CHANGELOG.md index 293363d9a..9913ee533 100644 --- a/embassy-usb-synopsys-otg/CHANGELOG.md +++ b/embassy-usb-synopsys-otg/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## 0.3.0 - 2025-07-22 + +- Bump `embassy-usb-driver` to v0.2.0 + ## 0.2.0 - 2024-12-06 - Fix corruption in CONTROL OUT transfers (and remove `quirk_setup_late_cnak`) diff --git a/embassy-usb-synopsys-otg/Cargo.toml b/embassy-usb-synopsys-otg/Cargo.toml index 511cddacf..78cce24de 100644 --- a/embassy-usb-synopsys-otg/Cargo.toml +++ b/embassy-usb-synopsys-otg/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-usb-synopsys-otg" -version = "0.2.0" +version = "0.3.0" edition = "2021" license = "MIT OR Apache-2.0" description = "`embassy-usb-driver` implementation for Synopsys OTG USB controllers" -- cgit From f3cc62b77d343e0d70f4564ea7f2dadea9cf9d84 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Tue, 22 Jul 2025 14:03:45 +0800 Subject: chore: bump embassy-usb-logger version Signed-off-by: Haobo Gu --- embassy-usb-logger/CHANGELOG.md | 4 ++++ embassy-usb-logger/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/embassy-usb-logger/CHANGELOG.md b/embassy-usb-logger/CHANGELOG.md index 86a9fb032..79ea25839 100644 --- a/embassy-usb-logger/CHANGELOG.md +++ b/embassy-usb-logger/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## 0.5.0 - 2025-07-22 + +- Update `embassy-usb` to 0.5.0 + ## 0.4.0 - 2025-01-15 - Update `embassy-usb` to 0.4.0 diff --git a/embassy-usb-logger/Cargo.toml b/embassy-usb-logger/Cargo.toml index 6dd2637f2..68b11ad8a 100644 --- a/embassy-usb-logger/Cargo.toml +++ b/embassy-usb-logger/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-usb-logger" -version = "0.4.0" +version = "0.5.0" edition = "2021" license = "MIT OR Apache-2.0" description = "`log` implementation for USB serial using `embassy-usb`." diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 971f99fff..eefd69315 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -15,7 +15,7 @@ embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defm embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-usb-logger = { version = "0.4.0", path = "../../embassy-usb-logger" } +embassy-usb-logger = { version = "0.5.0", path = "../../embassy-usb-logger" } cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { version = "0.5.1", path = "../../cyw43-pio", features = ["defmt"] } diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index d909aca1b..4d3dc77b5 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -15,7 +15,7 @@ embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defm embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-usb-logger = { version = "0.4.0", path = "../../embassy-usb-logger" } +embassy-usb-logger = { version = "0.5.0", path = "../../embassy-usb-logger" } cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { version = "0.5.1", path = "../../cyw43-pio", features = ["defmt"] } -- cgit From 1ad5d5a771d5109a763361454fb724b85ae25fdd Mon Sep 17 00:00:00 2001 From: i509VCB Date: Wed, 9 Jul 2025 23:08:59 -0500 Subject: nxp: Add MIMXRT1011 GPIO and time driver PIT is used for the time driver --- .vscode/settings.json | 1 + ci.sh | 2 + embassy-nxp/Cargo.toml | 36 +- embassy-nxp/build.rs | 136 +++++ embassy-nxp/build_common.rs | 94 ++++ embassy-nxp/src/chips/mimxrt1011.rs | 113 +++++ embassy-nxp/src/gpio.rs | 2 + embassy-nxp/src/gpio/rt1xxx.rs | 895 +++++++++++++++++++++++++++++++++ embassy-nxp/src/lib.rs | 87 +++- embassy-nxp/src/time_driver/pit.rs | 187 +++++++ examples/mimxrt1011/.cargo/config.toml | 8 + examples/mimxrt1011/Cargo.toml | 29 ++ examples/mimxrt1011/build.rs | 14 + examples/mimxrt1011/src/bin/blinky.rs | 48 ++ examples/mimxrt1011/src/bin/button.rs | 62 +++ examples/mimxrt1011/src/lib.rs | 75 +++ 16 files changed, 1780 insertions(+), 9 deletions(-) create mode 100644 embassy-nxp/build.rs create mode 100644 embassy-nxp/build_common.rs create mode 100644 embassy-nxp/src/chips/mimxrt1011.rs create mode 100644 embassy-nxp/src/gpio/rt1xxx.rs create mode 100644 embassy-nxp/src/time_driver/pit.rs create mode 100644 examples/mimxrt1011/.cargo/config.toml create mode 100644 examples/mimxrt1011/Cargo.toml create mode 100644 examples/mimxrt1011/build.rs create mode 100644 examples/mimxrt1011/src/bin/blinky.rs create mode 100644 examples/mimxrt1011/src/bin/button.rs create mode 100644 examples/mimxrt1011/src/lib.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index e4814ff27..070e8fbd3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -36,6 +36,7 @@ // "examples/nrf52840-rtic/Cargo.toml", // "examples/nrf5340/Cargo.toml", // "examples/nrf-rtos-trace/Cargo.toml", + // "examples/mimxrt1011/Cargo.toml", // "examples/rp/Cargo.toml", // "examples/std/Cargo.toml", // "examples/stm32c0/Cargo.toml", diff --git a/ci.sh b/ci.sh index 9d3e47a41..e225bc7c9 100755 --- a/ci.sh +++ b/ci.sh @@ -181,6 +181,7 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u073mb,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u083rc,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv8m.main-none-eabihf --features lpc55,defmt \ + --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv7em-none-eabihf --features mimxrt1011,defmt,time-driver-pit \ --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0c1104dgs20,defmt,time-driver-any \ --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3507pm,defmt,time-driver-any \ --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3519pz,defmt,time-driver-any \ @@ -264,6 +265,7 @@ cargo batch \ --- build --release --manifest-path examples/stm32wba/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32wba \ --- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32wl \ --- build --release --manifest-path examples/lpc55s69/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/lpc55s69 \ + --- build --release --manifest-path examples/mimxrt1011/Cargo.toml --target thumbv7em-none-eabihf --artifact-dir out/examples/mimxrt1011 \ --- build --release --manifest-path examples/mspm0g3507/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3507 \ --- build --release --manifest-path examples/mspm0g3519/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3519 \ --- build --release --manifest-path examples/mspm0l1306/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0l1306 \ diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 56d00bfb2..625906183 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -11,22 +11,50 @@ embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", fe embassy-sync = { version = "0.7.0", path = "../embassy-sync" } defmt = { version = "1", optional = true } log = { version = "0.4.27", optional = true } +embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } +embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } +embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } ## Chip dependencies lpc55-pac = { version = "0.5.0", optional = true } +nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/i509VCB/nxp-pac", rev = "1e010dbe75ab0e14dd908e4646391403414c8a8e" } + +imxrt-rt = { version = "0.1.7", optional = true, features = ["device"] } + +[build-dependencies] +cfg_aliases = "0.2.1" +nxp-pac = { version = "0.1.0", git = "https://github.com/i509VCB/nxp-pac", rev = "1e010dbe75ab0e14dd908e4646391403414c8a8e", features = ["metadata"], optional = true } +proc-macro2 = "1.0.95" +quote = "1.0.15" [features] default = ["rt"] -# Enable PACs as optional dependencies, since some chip families will use different pac crates. -rt = ["lpc55-pac?/rt"] +# Enable PACs as optional dependencies, since some chip families will use different pac crates (temporarily). +rt = ["lpc55-pac?/rt", "nxp-pac?/rt"] ## Enable [defmt support](https://docs.rs/defmt) and enables `defmt` debug-log messages and formatting in embassy drivers. defmt = ["dep:defmt", "embassy-hal-internal/defmt", "embassy-sync/defmt"] + +log = ["dep:log"] + +## Use Periodic Interrupt Timer (PIT) as the time driver for `embassy-time`, with a tick rate of 1 MHz +time-driver-pit = ["_time_driver", "embassy-time?/tick-hz-1_000_000"] + ## Reexport the PAC for the currently enabled chip at `embassy_nxp::pac` (unstable) unstable-pac = [] -# This is unstable because semver-minor (non-breaking) releases of embassy-nrf may major-bump (breaking) the PAC version. +# This is unstable because semver-minor (non-breaking) releases of embassy-nxp may major-bump (breaking) the PAC version. # If this is an issue for you, you're encouraged to directly depend on a fixed version of the PAC. # There are no plans to make this stable. +## internal use only +# +# This feature is unfortunately a hack around the fact that cfg_aliases cannot apply to the buildscript +# that creates the aliases. +_rt1xxx = [] + +# A timer driver is enabled. +_time_driver = ["dep:embassy-time-driver", "dep:embassy-time-queue-utils"] + #! ### Chip selection features -lpc55 = ["lpc55-pac"] +lpc55 = ["dep:lpc55-pac"] +mimxrt1011 = ["nxp-pac/mimxrt1011", "_rt1xxx", "dep:imxrt-rt"] diff --git a/embassy-nxp/build.rs b/embassy-nxp/build.rs new file mode 100644 index 000000000..6c10d0e69 --- /dev/null +++ b/embassy-nxp/build.rs @@ -0,0 +1,136 @@ +use std::io::Write; +use std::path::{Path, PathBuf}; +use std::process::Command; +use std::{env, fs}; + +use cfg_aliases::cfg_aliases; +#[cfg(feature = "_rt1xxx")] +use nxp_pac::metadata; +#[allow(unused)] +use proc_macro2::TokenStream; +#[allow(unused)] +use quote::quote; + +#[path = "./build_common.rs"] +mod common; + +fn main() { + let mut cfgs = common::CfgSet::new(); + common::set_target_cfgs(&mut cfgs); + + let chip_name = match env::vars() + .map(|(a, _)| a) + .filter(|x| x.starts_with("CARGO_FEATURE_MIMXRT") || x.starts_with("CARGO_FEATURE_LPC")) + .get_one() + { + Ok(x) => x, + Err(GetOneError::None) => panic!("No mimxrt/lpc Cargo feature enabled"), + Err(GetOneError::Multiple) => panic!("Multiple mimxrt/lpc Cargo features enabled"), + } + .strip_prefix("CARGO_FEATURE_") + .unwrap() + .to_ascii_lowercase(); + + cfg_aliases! { + rt1xxx: { feature = "mimxrt1011" }, + gpio1: { feature = "mimxrt1011" }, + gpio2: { feature = "mimxrt1011" }, + gpio5: { feature = "mimxrt1011" }, + } + + eprintln!("chip: {chip_name}"); + + generate_code(); +} + +#[cfg(feature = "_rt1xxx")] +fn generate_iomuxc() -> TokenStream { + use proc_macro2::{Ident, Span}; + + let pads = metadata::iomuxc::IOMUXC_REGISTERS.iter().map(|registers| { + let name = Ident::new(®isters.name, Span::call_site()); + let address = registers.pad_ctl; + + quote! { + pub const #name: u32 = #address; + } + }); + + let muxes = metadata::iomuxc::IOMUXC_REGISTERS.iter().map(|registers| { + let name = Ident::new(®isters.name, Span::call_site()); + let address = registers.mux_ctl; + + quote! { + pub const #name: u32 = #address; + } + }); + + quote! { + pub mod iomuxc { + pub mod pads { + #(#pads)* + } + + pub mod muxes { + #(#muxes)* + } + } + } +} + +fn generate_code() { + #[allow(unused)] + use std::fmt::Write; + + let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + #[allow(unused_mut)] + let mut output = String::new(); + + #[cfg(feature = "_rt1xxx")] + writeln!(&mut output, "{}", generate_iomuxc()).unwrap(); + + let out_file = out_dir.join("_generated.rs").to_string_lossy().to_string(); + fs::write(&out_file, output).unwrap(); + rustfmt(&out_file); +} + +/// rustfmt a given path. +/// Failures are logged to stderr and ignored. +fn rustfmt(path: impl AsRef) { + let path = path.as_ref(); + match Command::new("rustfmt").args([path]).output() { + Err(e) => { + eprintln!("failed to exec rustfmt {:?}: {:?}", path, e); + } + Ok(out) => { + if !out.status.success() { + eprintln!("rustfmt {:?} failed:", path); + eprintln!("=== STDOUT:"); + std::io::stderr().write_all(&out.stdout).unwrap(); + eprintln!("=== STDERR:"); + std::io::stderr().write_all(&out.stderr).unwrap(); + } + } + } +} + +enum GetOneError { + None, + Multiple, +} + +trait IteratorExt: Iterator { + fn get_one(self) -> Result; +} + +impl IteratorExt for T { + fn get_one(mut self) -> Result { + match self.next() { + None => Err(GetOneError::None), + Some(res) => match self.next() { + Some(_) => Err(GetOneError::Multiple), + None => Ok(res), + }, + } + } +} diff --git a/embassy-nxp/build_common.rs b/embassy-nxp/build_common.rs new file mode 100644 index 000000000..4f24e6d37 --- /dev/null +++ b/embassy-nxp/build_common.rs @@ -0,0 +1,94 @@ +// NOTE: this file is copy-pasted between several Embassy crates, because there is no +// straightforward way to share this code: +// - it cannot be placed into the root of the repo and linked from each build.rs using `#[path = +// "../build_common.rs"]`, because `cargo publish` requires that all files published with a crate +// reside in the crate's directory, +// - it cannot be symlinked from `embassy-xxx/build_common.rs` to `../build_common.rs`, because +// symlinks don't work on Windows. + +use std::collections::HashSet; +use std::env; + +/// Helper for emitting cargo instruction for enabling configs (`cargo:rustc-cfg=X`) and declaring +/// them (`cargo:rust-check-cfg=cfg(X)`). +#[derive(Debug)] +pub struct CfgSet { + enabled: HashSet, + declared: HashSet, +} + +impl CfgSet { + pub fn new() -> Self { + Self { + enabled: HashSet::new(), + declared: HashSet::new(), + } + } + + /// Enable a config, which can then be used in `#[cfg(...)]` for conditional compilation. + /// + /// All configs that can potentially be enabled should be unconditionally declared using + /// [`Self::declare()`]. + pub fn enable(&mut self, cfg: impl AsRef) { + if self.enabled.insert(cfg.as_ref().to_owned()) { + println!("cargo:rustc-cfg={}", cfg.as_ref()); + } + } + + pub fn enable_all(&mut self, cfgs: &[impl AsRef]) { + for cfg in cfgs.iter() { + self.enable(cfg.as_ref()); + } + } + + /// Declare a valid config for conditional compilation, without enabling it. + /// + /// This enables rustc to check that the configs in `#[cfg(...)]` attributes are valid. + pub fn declare(&mut self, cfg: impl AsRef) { + if self.declared.insert(cfg.as_ref().to_owned()) { + println!("cargo:rustc-check-cfg=cfg({})", cfg.as_ref()); + } + } + + pub fn declare_all(&mut self, cfgs: &[impl AsRef]) { + for cfg in cfgs.iter() { + self.declare(cfg.as_ref()); + } + } + + pub fn set(&mut self, cfg: impl Into, enable: bool) { + let cfg = cfg.into(); + if enable { + self.enable(cfg.clone()); + } + self.declare(cfg); + } +} + +/// Sets configs that describe the target platform. +pub fn set_target_cfgs(cfgs: &mut CfgSet) { + let target = env::var("TARGET").unwrap(); + + if target.starts_with("thumbv6m-") { + cfgs.enable_all(&["cortex_m", "armv6m"]); + } else if target.starts_with("thumbv7m-") { + cfgs.enable_all(&["cortex_m", "armv7m"]); + } else if target.starts_with("thumbv7em-") { + cfgs.enable_all(&["cortex_m", "armv7m", "armv7em"]); + } else if target.starts_with("thumbv8m.base") { + cfgs.enable_all(&["cortex_m", "armv8m", "armv8m_base"]); + } else if target.starts_with("thumbv8m.main") { + cfgs.enable_all(&["cortex_m", "armv8m", "armv8m_main"]); + } + cfgs.declare_all(&[ + "cortex_m", + "armv6m", + "armv7m", + "armv7em", + "armv8m", + "armv8m_base", + "armv8m_main", + ]); + + cfgs.set("has_fpu", target.ends_with("-eabihf")); +} diff --git a/embassy-nxp/src/chips/mimxrt1011.rs b/embassy-nxp/src/chips/mimxrt1011.rs new file mode 100644 index 000000000..a74d953fc --- /dev/null +++ b/embassy-nxp/src/chips/mimxrt1011.rs @@ -0,0 +1,113 @@ +// This must be imported so that __preinit is defined. +use imxrt_rt as _; +pub use nxp_pac as pac; + +embassy_hal_internal::peripherals! { + // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other + // peripheral types (e.g. I2C). + GPIO_00, + GPIO_01, + GPIO_02, + GPIO_03, + GPIO_04, + GPIO_05, + GPIO_06, + GPIO_07, + GPIO_08, + GPIO_09, + GPIO_10, + GPIO_11, + GPIO_12, + GPIO_13, + GPIO_AD_00, + GPIO_AD_01, + GPIO_AD_02, + GPIO_AD_03, + GPIO_AD_04, + GPIO_AD_05, + GPIO_AD_06, + GPIO_AD_07, + GPIO_AD_08, + GPIO_AD_09, + GPIO_AD_10, + GPIO_AD_11, + GPIO_AD_12, + GPIO_AD_13, + GPIO_AD_14, + GPIO_SD_00, + GPIO_SD_01, + GPIO_SD_02, + GPIO_SD_03, + GPIO_SD_04, + GPIO_SD_05, + GPIO_SD_06, + GPIO_SD_07, + GPIO_SD_08, + GPIO_SD_09, + GPIO_SD_10, + GPIO_SD_11, + GPIO_SD_12, + GPIO_SD_13, + PMIC_ON_REQ, +} + +impl_gpio! { + // GPIO Bank 1 + GPIO_00(Gpio1, 0); + GPIO_01(Gpio1, 1); + GPIO_02(Gpio1, 2); + GPIO_03(Gpio1, 3); + GPIO_04(Gpio1, 4); + GPIO_05(Gpio1, 5); + GPIO_06(Gpio1, 6); + GPIO_07(Gpio1, 7); + GPIO_08(Gpio1, 8); + GPIO_09(Gpio1, 9); + GPIO_10(Gpio1, 10); + GPIO_11(Gpio1, 11); + GPIO_12(Gpio1, 12); + GPIO_13(Gpio1, 13); + GPIO_AD_00(Gpio1, 14); + GPIO_AD_01(Gpio1, 15); + GPIO_AD_02(Gpio1, 16); + GPIO_AD_03(Gpio1, 17); + GPIO_AD_04(Gpio1, 18); + GPIO_AD_05(Gpio1, 19); + GPIO_AD_06(Gpio1, 20); + GPIO_AD_07(Gpio1, 21); + GPIO_AD_08(Gpio1, 22); + GPIO_AD_09(Gpio1, 23); + GPIO_AD_10(Gpio1, 24); + GPIO_AD_11(Gpio1, 25); + GPIO_AD_12(Gpio1, 26); + GPIO_AD_13(Gpio1, 27); + GPIO_AD_14(Gpio1, 28); + + // GPIO Bank 2 + GPIO_SD_00(Gpio2, 0); + GPIO_SD_01(Gpio2, 1); + GPIO_SD_02(Gpio2, 2); + GPIO_SD_03(Gpio2, 3); + GPIO_SD_04(Gpio2, 4); + GPIO_SD_05(Gpio2, 5); + GPIO_SD_06(Gpio2, 6); + GPIO_SD_07(Gpio2, 7); + GPIO_SD_08(Gpio2, 8); + GPIO_SD_09(Gpio2, 9); + GPIO_SD_10(Gpio2, 10); + GPIO_SD_11(Gpio2, 11); + GPIO_SD_12(Gpio2, 12); + GPIO_SD_13(Gpio2, 13); + + // GPIO Bank 5 + PMIC_ON_REQ(Gpio5, 0); +} + +pub(crate) mod _generated { + #![allow(dead_code)] + #![allow(unused_imports)] + #![allow(non_snake_case)] + #![allow(missing_docs)] + + include!(concat!(env!("OUT_DIR"), "/_generated.rs")); +} diff --git a/embassy-nxp/src/gpio.rs b/embassy-nxp/src/gpio.rs index 809903d97..3049cc12d 100644 --- a/embassy-nxp/src/gpio.rs +++ b/embassy-nxp/src/gpio.rs @@ -1,5 +1,7 @@ //! General purpose input/output (GPIO) driver. +#![macro_use] #[cfg_attr(feature = "lpc55", path = "./gpio/lpc55.rs")] +#[cfg_attr(rt1xxx, path = "./gpio/rt1xxx.rs")] mod inner; pub use inner::*; diff --git a/embassy-nxp/src/gpio/rt1xxx.rs b/embassy-nxp/src/gpio/rt1xxx.rs new file mode 100644 index 000000000..9c58e8a7d --- /dev/null +++ b/embassy-nxp/src/gpio/rt1xxx.rs @@ -0,0 +1,895 @@ +#![macro_use] + +use core::future::Future; +use core::ops::Not; +use core::pin::Pin as FuturePin; +use core::task::{Context, Poll}; + +use embassy_hal_internal::{impl_peripheral, Peri, PeripheralType}; +use embassy_sync::waitqueue::AtomicWaker; +use nxp_pac::gpio::vals::Icr; +use nxp_pac::iomuxc::vals::Pus; + +use crate::chip::{mux_address, pad_address}; +use crate::pac::common::{Reg, RW}; +#[cfg(feature = "rt")] +use crate::pac::interrupt; +use crate::pac::iomuxc::regs::{Ctl, MuxCtl}; +#[cfg(gpio5)] +use crate::pac::{self, gpio::Gpio}; + +/// The GPIO pin level for pins set on "Digital" mode. +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum Level { + /// Logical low. Corresponds to 0V. + Low, + /// Logical high. Corresponds to VDD. + High, +} + +impl From for Level { + fn from(val: bool) -> Self { + match val { + true => Self::High, + false => Self::Low, + } + } +} + +impl From for bool { + fn from(level: Level) -> bool { + match level { + Level::Low => false, + Level::High => true, + } + } +} + +impl Not for Level { + type Output = Self; + + fn not(self) -> Self::Output { + match self { + Level::Low => Level::High, + Level::High => Level::Low, + } + } +} + +/// Pull setting for a GPIO input set on "Digital" mode. +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum Pull { + /// No pull. + None, + + // TODO: What Does PUE::KEEPER mean here? + + // 22 kOhm pull-up resistor. + Up22K, + + // 47 kOhm pull-up resistor. + Up47K, + + // 100 kOhm pull-up resistor. + Up100K, + + // 100 kOhm pull-down resistor. + Down100K, +} + +/// Drive strength of an output +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Drive { + Disabled, + _150R, + _75R, + _50R, + _37R, + _30R, + _25R, + _20R, +} + +/// Slew rate of an output +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum SlewRate { + Slow, + + Fast, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Bank { + /// Bank 1 + #[cfg(gpio1)] + Gpio1, + + /// Bank 2 + #[cfg(gpio2)] + Gpio2, + + /// Bank 5 + #[cfg(gpio5)] + Gpio5, +} + +/// GPIO flexible pin. +/// +/// This pin can either be a disconnected, input, or output pin, or both. The level register bit will remain +/// set while not in output mode, so the pin's level will be 'remembered' when it is not in output +/// mode. +pub struct Flex<'d> { + pub(crate) pin: Peri<'d, AnyPin>, +} + +impl<'d> Flex<'d> { + /// Wrap the pin in a `Flex`. + /// + /// The pin remains disconnected. The initial output level is unspecified, but can be changed + /// before the pin is put into output mode. + #[inline] + pub fn new(pin: Peri<'d, impl Pin>) -> Self { + Self { pin: pin.into() } + } + + /// Set the pin's pull. + #[inline] + pub fn set_pull(&mut self, pull: Pull) { + let (pke, pue, pus) = match pull { + Pull::None => (false, true, Pus::PUS_0_100K_OHM_PULL_DOWN), + Pull::Up22K => (true, true, Pus::PUS_3_22K_OHM_PULL_UP), + Pull::Up47K => (true, true, Pus::PUS_1_47K_OHM_PULL_UP), + Pull::Up100K => (true, true, Pus::PUS_2_100K_OHM_PULL_UP), + Pull::Down100K => (true, true, Pus::PUS_0_100K_OHM_PULL_DOWN), + }; + + self.pin.pad().modify(|w| { + w.set_pke(pke); + w.set_pue(pue); + w.set_pus(pus); + }); + } + + // Set the pin's slew rate. + #[inline] + pub fn set_slewrate(&mut self, rate: SlewRate) { + self.pin.pad().modify(|w| { + w.set_sre(match rate { + SlewRate::Slow => false, + SlewRate::Fast => true, + }); + }); + } + + /// Set the pin's Schmitt trigger. + #[inline] + pub fn set_schmitt(&mut self, enable: bool) { + self.pin.pad().modify(|w| { + w.set_hys(enable); + }); + } + + /// Put the pin into input mode. + /// + /// The pull setting is left unchanged. + #[inline] + pub fn set_as_input(&mut self) { + self.pin.mux().modify(|w| { + w.set_mux_mode(GPIO_MUX_MODE); + }); + + // Setting direction is RMW + critical_section::with(|_cs| { + self.pin.block().gdir().modify(|w| { + w.set_gdir(self.pin.pin_number() as usize, false); + }); + }) + } + + /// Put the pin into output mode. + /// + /// The pin level will be whatever was set before (or low by default). If you want it to begin + /// at a specific level, call `set_high`/`set_low` on the pin first. + #[inline] + pub fn set_as_output(&mut self) { + self.pin.mux().modify(|w| { + w.set_mux_mode(GPIO_MUX_MODE); + }); + + // Setting direction is RMW + critical_section::with(|_cs| { + self.pin.block().gdir().modify(|w| { + w.set_gdir(self.pin.pin_number() as usize, true); + }); + }) + } + + /// Put the pin into input + open-drain output mode. + /// + /// The hardware will drive the line low if you set it to low, and will leave it floating if you set + /// it to high, in which case you can read the input to figure out whether another device + /// is driving the line low. + /// + /// The pin level will be whatever was set before (or low by default). If you want it to begin + /// at a specific level, call `set_high`/`set_low` on the pin first. + /// + /// The internal weak pull-up and pull-down resistors will be disabled. + #[inline] + pub fn set_as_input_output(&mut self) { + self.pin.pad().modify(|w| { + w.set_ode(true); + }); + } + + /// Set the pin as "disconnected", ie doing nothing and consuming the lowest + /// amount of power possible. + /// + /// This is currently the same as [`Self::set_as_analog()`] but is semantically different + /// really. Drivers should `set_as_disconnected()` pins when dropped. + /// + /// Note that this also disables the pull-up and pull-down resistors. + #[inline] + pub fn set_as_disconnected(&mut self) { + self.pin.pad().modify(|w| { + w.set_ode(false); + w.set_pke(false); + w.set_pue(false); + w.set_pus(Pus::PUS_0_100K_OHM_PULL_DOWN); + }); + } + + /// Get whether the pin input level is high. + #[inline] + pub fn is_high(&self) -> bool { + self.pin.block().psr().read().psr(self.pin.pin_number() as usize) + } + + /// Get whether the pin input level is low. + #[inline] + pub fn is_low(&self) -> bool { + !self.is_high() + } + + /// Returns current pin level + #[inline] + pub fn get_level(&self) -> Level { + self.is_high().into() + } + + /// Set the output as high. + #[inline] + pub fn set_high(&mut self) { + self.pin.block().dr_set().write(|w| { + w.set_dr_set(self.pin.pin_number() as usize, true); + }); + } + + /// Set the output as low. + #[inline] + pub fn set_low(&mut self) { + self.pin.block().dr_clear().write(|w| { + w.set_dr_clear(self.pin.pin_number() as usize, true); + }); + } + + /// Toggle pin output + #[inline] + pub fn toggle(&mut self) { + self.pin.block().dr_toggle().write(|w| { + w.set_dr_toggle(self.pin.pin_number() as usize, true); + }); + } + + /// Set the output level. + #[inline] + pub fn set_level(&mut self, level: Level) { + match level { + Level::Low => self.set_low(), + Level::High => self.set_high(), + } + } + + /// Get the current pin output level. + #[inline] + pub fn get_output_level(&self) -> Level { + self.is_set_high().into() + } + + /// Is the output level high? + /// + /// If the [`Flex`] is set as an input, then this is equivalent to [`Flex::is_high`]. + #[inline] + pub fn is_set_high(&self) -> bool { + self.pin.block().dr().read().dr(self.pin.pin_number() as usize) + } + + /// Is the output level low? + /// + /// If the [`Flex`] is set as an input, then this is equivalent to [`Flex::is_low`]. + #[inline] + pub fn is_set_low(&self) -> bool { + !self.is_set_high() + } + + /// Wait until the pin is high. If it is already high, return immediately. + #[inline] + pub async fn wait_for_high(&mut self) { + InputFuture::new(self.pin.reborrow(), InterruptConfiguration::High).await + } + + /// Wait until the pin is low. If it is already low, return immediately. + #[inline] + pub async fn wait_for_low(&mut self) { + InputFuture::new(self.pin.reborrow(), InterruptConfiguration::Low).await + } + + /// Wait for the pin to undergo a transition from low to high. + #[inline] + pub async fn wait_for_rising_edge(&mut self) { + InputFuture::new(self.pin.reborrow(), InterruptConfiguration::RisingEdge).await + } + + /// Wait for the pin to undergo a transition from high to low. + #[inline] + pub async fn wait_for_falling_edge(&mut self) { + InputFuture::new(self.pin.reborrow(), InterruptConfiguration::FallingEdge).await + } + + /// Wait for the pin to undergo any transition, i.e low to high OR high to low. + #[inline] + pub async fn wait_for_any_edge(&mut self) { + InputFuture::new(self.pin.reborrow(), InterruptConfiguration::AnyEdge).await + } +} + +impl<'d> Drop for Flex<'d> { + fn drop(&mut self) { + self.set_as_disconnected(); + } +} + +/// GPIO input driver. +pub struct Input<'d> { + pin: Flex<'d>, +} + +impl<'d> Input<'d> { + /// Create GPIO input driver for a [Pin] with the provided [Pull] configuration. + #[inline] + pub fn new(pin: Peri<'d, impl Pin>, pull: Pull) -> Self { + let mut pin = Flex::new(pin); + pin.set_as_input(); + pin.set_pull(pull); + Self { pin } + } + + /// Get whether the pin input level is high. + #[inline] + pub fn is_high(&self) -> bool { + self.pin.is_high() + } + + /// Get whether the pin input level is low. + #[inline] + pub fn is_low(&self) -> bool { + self.pin.is_low() + } + + /// Get the current pin input level. + #[inline] + pub fn get_level(&self) -> Level { + self.pin.get_level() + } + + /// Wait until the pin is high. If it is already high, return immediately. + #[inline] + pub async fn wait_for_high(&mut self) { + self.pin.wait_for_high().await + } + + /// Wait until the pin is low. If it is already low, return immediately. + #[inline] + pub async fn wait_for_low(&mut self) { + self.pin.wait_for_low().await + } + + /// Wait for the pin to undergo a transition from low to high. + #[inline] + pub async fn wait_for_rising_edge(&mut self) { + self.pin.wait_for_rising_edge().await + } + + /// Wait for the pin to undergo a transition from high to low. + #[inline] + pub async fn wait_for_falling_edge(&mut self) { + self.pin.wait_for_falling_edge().await + } + + /// Wait for the pin to undergo any transition, i.e low to high OR high to low. + #[inline] + pub async fn wait_for_any_edge(&mut self) { + self.pin.wait_for_any_edge().await + } +} + +/// GPIO output driver. +/// +/// Note that pins will **return to their floating state** when `Output` is dropped. +/// If pins should retain their state indefinitely, either keep ownership of the +/// `Output`, or pass it to [`core::mem::forget`]. +pub struct Output<'d> { + pin: Flex<'d>, +} + +impl<'d> Output<'d> { + /// Create GPIO output driver for a [Pin] with the provided [Level] configuration. + #[inline] + pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self { + let mut pin = Flex::new(pin); + pin.set_as_output(); + pin.set_level(initial_output); + Self { pin } + } + + /// Set the output as high. + #[inline] + pub fn set_high(&mut self) { + self.pin.set_high(); + } + + /// Set the output as low. + #[inline] + pub fn set_low(&mut self) { + self.pin.set_low(); + } + + /// Set the output level. + #[inline] + pub fn set_level(&mut self, level: Level) { + self.pin.set_level(level) + } + + /// Is the output pin set as high? + #[inline] + pub fn is_set_high(&self) -> bool { + self.pin.is_set_high() + } + + /// Is the output pin set as low? + #[inline] + pub fn is_set_low(&self) -> bool { + self.pin.is_set_low() + } + + /// What level output is set to + #[inline] + pub fn get_output_level(&self) -> Level { + self.pin.get_output_level() + } + + /// Toggle pin output + #[inline] + pub fn toggle(&mut self) { + self.pin.toggle(); + } +} + +/// GPIO output open-drain driver. +/// +/// Note that pins will **return to their floating state** when `OutputOpenDrain` is dropped. +/// If pins should retain their state indefinitely, either keep ownership of the +/// `OutputOpenDrain`, or pass it to [`core::mem::forget`]. +pub struct OutputOpenDrain<'d> { + pin: Flex<'d>, +} + +impl<'d> OutputOpenDrain<'d> { + /// Create a new GPIO open drain output driver for a [Pin] with the provided [Level]. + #[inline] + pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self { + let mut pin = Flex::new(pin); + pin.set_level(initial_output); + pin.set_as_input_output(); + Self { pin } + } + + /// Get whether the pin input level is high. + #[inline] + pub fn is_high(&self) -> bool { + !self.pin.is_low() + } + + /// Get whether the pin input level is low. + #[inline] + pub fn is_low(&self) -> bool { + self.pin.is_low() + } + + /// Get the current pin input level. + #[inline] + pub fn get_level(&self) -> Level { + self.pin.get_level() + } + + /// Set the output as high. + #[inline] + pub fn set_high(&mut self) { + self.pin.set_high(); + } + + /// Set the output as low. + #[inline] + pub fn set_low(&mut self) { + self.pin.set_low(); + } + + /// Set the output level. + #[inline] + pub fn set_level(&mut self, level: Level) { + self.pin.set_level(level); + } + + /// Get whether the output level is set to high. + #[inline] + pub fn is_set_high(&self) -> bool { + self.pin.is_set_high() + } + + /// Get whether the output level is set to low. + #[inline] + pub fn is_set_low(&self) -> bool { + self.pin.is_set_low() + } + + /// Get the current output level. + #[inline] + pub fn get_output_level(&self) -> Level { + self.pin.get_output_level() + } + + /// Toggle pin output + #[inline] + pub fn toggle(&mut self) { + self.pin.toggle() + } + + /// Wait until the pin is high. If it is already high, return immediately. + #[inline] + pub async fn wait_for_high(&mut self) { + self.pin.wait_for_high().await + } + + /// Wait until the pin is low. If it is already low, return immediately. + #[inline] + pub async fn wait_for_low(&mut self) { + self.pin.wait_for_low().await + } + + /// Wait for the pin to undergo a transition from low to high. + #[inline] + pub async fn wait_for_rising_edge(&mut self) { + self.pin.wait_for_rising_edge().await + } + + /// Wait for the pin to undergo a transition from high to low. + #[inline] + pub async fn wait_for_falling_edge(&mut self) { + self.pin.wait_for_falling_edge().await + } + + /// Wait for the pin to undergo any transition, i.e low to high OR high to low. + #[inline] + pub async fn wait_for_any_edge(&mut self) { + self.pin.wait_for_any_edge().await + } +} + +#[allow(private_bounds)] +pub trait Pin: PeripheralType + Into + SealedPin + Sized + 'static { + /// Returns the pin number within a bank + #[inline] + fn pin(&self) -> u8 { + self.pin_number() + } + + #[inline] + fn bank(&self) -> Bank { + self._bank() + } +} + +/// Type-erased GPIO pin. +pub struct AnyPin { + pub(crate) pin_number: u8, + pub(crate) bank: Bank, +} + +impl AnyPin { + /// Unsafely create a new type-erased pin. + /// + /// # Safety + /// + /// You must ensure that you’re only using one instance of this type at a time. + pub unsafe fn steal(bank: Bank, pin_number: u8) -> Peri<'static, Self> { + Peri::new_unchecked(Self { pin_number, bank }) + } +} + +impl_peripheral!(AnyPin); + +impl Pin for AnyPin {} +impl SealedPin for AnyPin { + #[inline] + fn pin_number(&self) -> u8 { + self.pin_number + } + + #[inline] + fn _bank(&self) -> Bank { + self.bank + } +} + +// Impl details + +/// Mux mode for GPIO pins. This is constant across all RT1xxx parts. +const GPIO_MUX_MODE: u8 = 0b101; + +// FIXME: These don't always need to be 32 entries. GPIO5 on RT1101 contains a single pin and GPIO2 only 14. +#[cfg(gpio1)] +static GPIO1_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32]; +#[cfg(gpio2)] +static GPIO2_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32]; +#[cfg(gpio5)] +static GPIO5_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32]; + +/// Sealed trait for pins. This trait is sealed and cannot be implemented outside of this crate. +pub(crate) trait SealedPin: Sized { + fn pin_number(&self) -> u8; + + fn _bank(&self) -> Bank; + + #[inline] + fn block(&self) -> Gpio { + match self._bank() { + #[cfg(gpio1)] + Bank::Gpio1 => pac::GPIO1, + #[cfg(gpio2)] + Bank::Gpio2 => pac::GPIO2, + #[cfg(gpio5)] + Bank::Gpio5 => pac::GPIO5, + } + } + + #[inline] + fn mux(&self) -> Reg { + // SAFETY: The generated mux address table is valid since it is generated from the SVD files. + let address = unsafe { mux_address(self._bank(), self.pin_number()).unwrap_unchecked() }; + + // SAFETY: The register at the address is an instance of MuxCtl. + unsafe { Reg::from_ptr(address as *mut _) } + } + + #[inline] + fn pad(&self) -> Reg { + // SAFETY: The generated pad address table is valid since it is generated from the SVD files. + let address = unsafe { pad_address(self._bank(), self.pin_number()).unwrap_unchecked() }; + + // SAFETY: The register at the address is an instance of Ctl. + unsafe { Reg::from_ptr(address as *mut _) } + } + + fn waker(&self) -> &AtomicWaker { + match self._bank() { + #[cfg(gpio1)] + Bank::Gpio1 => &GPIO1_WAKERS[self.pin_number() as usize], + #[cfg(gpio2)] + Bank::Gpio2 => &GPIO2_WAKERS[self.pin_number() as usize], + #[cfg(gpio5)] + Bank::Gpio5 => &GPIO5_WAKERS[self.pin_number() as usize], + } + } +} + +/// This enum matches the layout of Icr. +enum InterruptConfiguration { + Low, + High, + RisingEdge, + FallingEdge, + AnyEdge, +} + +#[must_use = "futures do nothing unless you `.await` or poll them"] +struct InputFuture<'d> { + pin: Peri<'d, AnyPin>, +} + +impl<'d> InputFuture<'d> { + fn new(pin: Peri<'d, AnyPin>, config: InterruptConfiguration) -> Self { + let block = pin.block(); + + let (icr, edge_sel) = match config { + InterruptConfiguration::Low => (Icr::LOW_LEVEL, false), + InterruptConfiguration::High => (Icr::HIGH_LEVEL, false), + InterruptConfiguration::RisingEdge => (Icr::RISING_EDGE, false), + InterruptConfiguration::FallingEdge => (Icr::FALLING_EDGE, false), + InterruptConfiguration::AnyEdge => (Icr::FALLING_EDGE, true), + }; + + let index = if pin.pin_number() > 15 { 1 } else { 0 }; + + // Interrupt configuration performs RMW + critical_section::with(|_cs| { + // Disable interrupt so a level/edge detection change does not cause ISR to be set. + block.imr().modify(|w| { + w.set_imr(pin.pin_number() as usize, false); + }); + + block.icr(index).modify(|w| { + w.set_pin(pin.pin_number() as usize, icr); + }); + + block.edge_sel().modify(|w| { + w.set_edge_sel(pin.pin_number() as usize, edge_sel); + }); + + // Clear the previous interrupt. + block.isr().modify(|w| { + // "Status flags are cleared by writing a 1 to the corresponding bit position." + w.set_isr(pin.pin_number() as usize, true); + }); + }); + + Self { pin } + } +} + +impl<'d> Future for InputFuture<'d> { + type Output = (); + + fn poll(self: FuturePin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // We need to register/re-register the waker for each poll because any + // calls to wake will deregister the waker. + let waker = self.pin.waker(); + waker.register(cx.waker()); + + // Enabling interrupt is RMW + critical_section::with(|_cs| { + self.pin.block().imr().modify(|w| { + w.set_imr(self.pin.pin_number() as usize, true); + }); + }); + + let isr = self.pin.block().isr().read(); + + if isr.isr(self.pin.pin_number() as usize) { + return Poll::Ready(()); + } + + Poll::Pending + } +} + +/// A macro to generate all GPIO pins. +/// +/// This generates a lookup table for IOMUX register addresses. +macro_rules! impl_gpio { + ( + $($name: ident($bank: ident, $pin_number: expr);)* + ) => { + #[inline] + pub(crate) const fn pad_address(bank: crate::gpio::Bank, pin: u8) -> Option { + match (bank, pin) { + $( + (crate::gpio::Bank::$bank, $pin_number) => Some(crate::chip::_generated::iomuxc::pads::$name), + )* + _ => None + } + } + + #[inline] + pub(crate) const fn mux_address(bank: crate::gpio::Bank, pin: u8) -> Option { + match (bank, pin) { + $( + (crate::gpio::Bank::$bank, $pin_number) => Some(crate::chip::_generated::iomuxc::muxes::$name), + )* + _ => None + } + } + + $( + impl_pin!($name, $bank, $pin_number); + )* + }; +} + +macro_rules! impl_pin { + ($name: ident, $bank: ident, $pin_num: expr) => { + impl crate::gpio::Pin for crate::peripherals::$name {} + impl crate::gpio::SealedPin for crate::peripherals::$name { + #[inline] + fn pin_number(&self) -> u8 { + $pin_num + } + + #[inline] + fn _bank(&self) -> crate::gpio::Bank { + crate::gpio::Bank::$bank + } + } + + impl From for crate::gpio::AnyPin { + fn from(val: peripherals::$name) -> Self { + use crate::gpio::SealedPin; + + Self { + pin_number: val.pin_number(), + bank: val._bank(), + } + } + } + }; +} + +pub(crate) fn init() { + #[cfg(feature = "rt")] + unsafe { + use embassy_hal_internal::interrupt::InterruptExt; + + pac::Interrupt::GPIO1_COMBINED_0_15.enable(); + pac::Interrupt::GPIO1_COMBINED_16_31.enable(); + pac::Interrupt::GPIO2_COMBINED_0_15.enable(); + pac::Interrupt::GPIO5_COMBINED_0_15.enable(); + } +} + +/// IRQ handler for GPIO pins. +/// +/// If `high_bits` is false, then the interrupt is for pins 0 through 15. If true, then the interrupt +/// is for pins 16 through 31 +#[cfg(feature = "rt")] +fn irq_handler(block: Gpio, wakers: &[AtomicWaker; 32], high_bits: bool) { + use crate::BitIter; + + let isr = block.isr().read().0; + let imr = block.imr().read().0; + let mask = if high_bits { 0xFFFF_0000 } else { 0x0000_FFFF }; + let bits = isr & imr & mask; + + for bit in BitIter(bits) { + wakers[bit as usize].wake(); + + // Disable further interrupts for this pin. The input future will check ISR (which is kept + // until reset). + block.imr().modify(|w| { + w.set_imr(bit as usize, false); + }); + } +} + +#[cfg(all(feature = "mimxrt1011", feature = "rt"))] +#[interrupt] +fn GPIO1_COMBINED_0_15() { + irq_handler(pac::GPIO1, &GPIO1_WAKERS, false); +} + +#[cfg(all(feature = "mimxrt1011", feature = "rt"))] +#[interrupt] +fn GPIO1_COMBINED_16_31() { + irq_handler(pac::GPIO1, &GPIO1_WAKERS, true); +} + +#[cfg(all(feature = "mimxrt1011", feature = "rt"))] +#[interrupt] +fn GPIO2_COMBINED_0_15() { + irq_handler(pac::GPIO2, &GPIO2_WAKERS, false); +} + +#[cfg(all(feature = "mimxrt1011", feature = "rt"))] +#[interrupt] +fn GPIO5_COMBINED_0_15() { + irq_handler(pac::GPIO5, &GPIO5_WAKERS, false); +} diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs index 1abaca708..a715770c4 100644 --- a/embassy-nxp/src/lib.rs +++ b/embassy-nxp/src/lib.rs @@ -1,12 +1,19 @@ #![no_std] -pub mod fmt; +// This mod MUST go first, so that the others see its macros. +pub(crate) mod fmt; + pub mod gpio; #[cfg(feature = "lpc55")] pub mod pint; +#[cfg(feature = "_time_driver")] +#[cfg_attr(feature = "time-driver-pit", path = "time_driver/pit.rs")] +mod time_driver; + // This mod MUST go last, so that it sees all the `impl_foo!` macros #[cfg_attr(feature = "lpc55", path = "chips/lpc55.rs")] +#[cfg_attr(feature = "mimxrt1011", path = "chips/mimxrt1011.rs")] mod chip; #[cfg(feature = "unstable-pac")] @@ -22,13 +29,66 @@ pub use embassy_hal_internal::{Peri, PeripheralType}; /// /// This should only be called once and at startup, otherwise it panics. pub fn init(_config: config::Config) -> Peripherals { - #[cfg(feature = "lpc55")] + // Do this first, so that it panics if user is calling `init` a second time + // before doing anything important. + let peripherals = Peripherals::take(); + + #[cfg(feature = "mimxrt1011")] { - gpio::init(); - pint::init(); + // The RT1010 Reference manual states that core clock root must be switched before + // reprogramming PLL2. + pac::CCM.cbcdr().modify(|w| { + w.set_periph_clk_sel(pac::ccm::vals::PeriphClkSel::PERIPH_CLK_SEL_1); + }); + + while matches!( + pac::CCM.cdhipr().read().periph_clk_sel_busy(), + pac::ccm::vals::PeriphClkSelBusy::PERIPH_CLK_SEL_BUSY_1 + ) {} + + info!("Core clock root switched"); + + // 480 * 18 / 24 = 360 + pac::CCM_ANALOG.pfd_480().modify(|x| x.set_pfd2_frac(12)); + + //480*18/24(pfd0)/4 + pac::CCM_ANALOG.pfd_480().modify(|x| x.set_pfd0_frac(24)); + pac::CCM.cscmr1().modify(|x| x.set_flexspi_podf(3.into())); + + // CPU Core + pac::CCM_ANALOG.pfd_528().modify(|x| x.set_pfd3_frac(18)); + cortex_m::asm::delay(500_000); + + // Clock core clock with PLL 2. + pac::CCM + .cbcdr() + .modify(|x| x.set_periph_clk_sel(pac::ccm::vals::PeriphClkSel::PERIPH_CLK_SEL_0)); // false + + while matches!( + pac::CCM.cdhipr().read().periph_clk_sel_busy(), + pac::ccm::vals::PeriphClkSelBusy::PERIPH_CLK_SEL_BUSY_1 + ) {} + + pac::CCM + .cbcmr() + .write(|v| v.set_pre_periph_clk_sel(pac::ccm::vals::PrePeriphClkSel::PRE_PERIPH_CLK_SEL_0)); + + // TODO: Some for USB PLLs + + // DCDC clock? + pac::CCM.ccgr6().modify(|v| v.set_cg0(1)); } - crate::Peripherals::take() + #[cfg(any(feature = "lpc55", rt1xxx))] + gpio::init(); + + #[cfg(feature = "lpc55")] + pint::init(); + + #[cfg(feature = "_time_driver")] + time_driver::init(); + + peripherals } /// HAL configuration for the NXP board. @@ -36,3 +96,20 @@ pub mod config { #[derive(Default)] pub struct Config {} } + +#[allow(unused)] +struct BitIter(u32); + +impl Iterator for BitIter { + type Item = u32; + + fn next(&mut self) -> Option { + match self.0.trailing_zeros() { + 32 => None, + b => { + self.0 &= !(1 << b); + Some(b) + } + } + } +} diff --git a/embassy-nxp/src/time_driver/pit.rs b/embassy-nxp/src/time_driver/pit.rs new file mode 100644 index 000000000..985e5e815 --- /dev/null +++ b/embassy-nxp/src/time_driver/pit.rs @@ -0,0 +1,187 @@ +//! Time driver using Periodic Interrupt Timer (PIT) +//! +//! This driver is used with the iMXRT1xxx parts. +//! +//! The PIT is run in lifetime mode. Timer 1 is chained to timer 0 to provide a free-running 64-bit timer. +//! The 64-bit timer is used to track how many ticks since boot. +//! +//! Timer 2 counts how many ticks there are within the current u32::MAX tick period. Timer 2 is restarted when +//! a new alarm is set (or every u32::MAX ticks). One caveat is that an alarm could be a few ticks late due to +//! restart. However the Cortex-M7 cores run at 500 MHz easily and the PIT will generally run at 1 MHz or lower. +//! Along with the fact that scheduling an alarm takes a critical section worst case an alarm may be a few +//! microseconds late. +//! +//! All PIT timers are clocked in lockstep, so the late start will not cause the now() count to drift. + +use core::cell::{Cell, RefCell}; +use core::task::Waker; + +use critical_section::{CriticalSection, Mutex}; +use embassy_hal_internal::interrupt::InterruptExt; +use embassy_time_driver::Driver as _; +use embassy_time_queue_utils::Queue; + +use crate::pac::{self, interrupt}; + +struct Driver { + alarm: Mutex>, + queue: Mutex>, +} + +impl embassy_time_driver::Driver for Driver { + fn now(&self) -> u64 { + loop { + // Even though reading LTMR64H will latch LTMR64L if another thread preempts between any of the + // three reads and calls now() then the value in LTMR64L will be wrong when execution returns to + // thread which was preempted. + let hi = pac::PIT.ltmr64h().read().lth(); + let lo = pac::PIT.ltmr64l().read().ltl(); + let hi2 = pac::PIT.ltmr64h().read().lth(); + + if hi == hi2 { + // PIT timers always count down. + return u64::MAX - ((hi as u64) << 32 | (lo as u64)); + } + } + } + + fn schedule_wake(&self, at: u64, waker: &Waker) { + critical_section::with(|cs| { + let mut queue = self.queue.borrow(cs).borrow_mut(); + + if queue.schedule_wake(at, waker) { + let mut next = queue.next_expiration(self.now()); + + while !self.set_alarm(cs, next) { + next = queue.next_expiration(self.now()); + } + } + }) + } +} + +impl Driver { + fn init(&'static self) { + // Disable PIT clock during mux configuration. + pac::CCM.ccgr1().modify(|r| r.set_cg6(0b00)); + + // TODO: This forces the PIT to be driven by the oscillator. However that isn't the only option as you + // could divide the clock root by up to 64. + pac::CCM.cscmr1().modify(|r| { + // 1 MHz + r.set_perclk_podf(pac::ccm::vals::PerclkPodf::DIVIDE_24); + r.set_perclk_clk_sel(pac::ccm::vals::PerclkClkSel::PERCLK_CLK_SEL_1); + }); + + pac::CCM.ccgr1().modify(|r| r.set_cg6(0b11)); + + // Disable clock during init. + // + // It is important that the PIT clock is prepared to not exceed limit (50 MHz on RT1011), or else + // you will need to recover the device with boot mode switches when using any PIT registers. + pac::PIT.mcr().modify(|w| { + w.set_mdis(true); + }); + + pac::PIT.timer(0).ldval().write_value(u32::MAX); + pac::PIT.timer(1).ldval().write_value(u32::MAX); + pac::PIT.timer(2).ldval().write_value(0); + pac::PIT.timer(3).ldval().write_value(0); + + pac::PIT.timer(1).tctrl().write(|w| { + // In lifetime mode, timer 1 is chained to timer 0 to form a 64-bit timer. + w.set_chn(true); + w.set_ten(true); + w.set_tie(false); + }); + + pac::PIT.timer(0).tctrl().write(|w| { + w.set_chn(false); + w.set_ten(true); + w.set_tie(false); + }); + + pac::PIT.timer(2).tctrl().write(|w| { + w.set_tie(true); + }); + + unsafe { interrupt::PIT.enable() }; + + pac::PIT.mcr().write(|w| { + w.set_mdis(false); + }); + } + + fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool { + let alarm = self.alarm.borrow(cs); + alarm.set(timestamp); + + let timer = pac::PIT.timer(2); + let now = self.now(); + + if timestamp <= now { + alarm.set(u64::MAX); + + return false; + } + + timer.tctrl().modify(|x| x.set_ten(false)); + timer.tflg().modify(|x| x.set_tif(true)); + + // If the next alarm happens in more than u32::MAX cycles then the alarm will be restarted later. + timer.ldval().write_value((timestamp - now) as u32); + timer.tctrl().modify(|x| x.set_ten(true)); + + true + } + + fn trigger_alarm(&self, cs: CriticalSection) { + let mut next = self.queue.borrow_ref_mut(cs).next_expiration(self.now()); + + while !self.set_alarm(cs, next) { + next = self.queue.borrow_ref_mut(cs).next_expiration(self.now()); + } + } + + fn on_interrupt(&self) { + critical_section::with(|cs| { + let timer = pac::PIT.timer(2); + let alarm = self.alarm.borrow(cs); + let interrupted = timer.tflg().read().tif(); + timer.tflg().write(|r| r.set_tif(true)); + + if interrupted { + // A new load value will not apply until the next timer expiration. + // + // The expiry may be up to u32::MAX cycles away, so the timer must be restarted. + timer.tctrl().modify(|r| r.set_ten(false)); + + let now = self.now(); + let timestamp = alarm.get(); + + if timestamp <= now { + self.trigger_alarm(cs); + } else { + // The alarm is not ready. Wait for u32::MAX cycles and check again or set the next alarm. + timer.ldval().write_value((timestamp - now) as u32); + timer.tctrl().modify(|r| r.set_ten(true)); + } + } + }); + } +} + +embassy_time_driver::time_driver_impl!(static DRIVER: Driver = Driver { + alarm: Mutex::new(Cell::new(0)), + queue: Mutex::new(RefCell::new(Queue::new())) +}); + +pub(crate) fn init() { + DRIVER.init(); +} + +#[cfg(feature = "rt")] +#[interrupt] +fn PIT() { + DRIVER.on_interrupt(); +} diff --git a/examples/mimxrt1011/.cargo/config.toml b/examples/mimxrt1011/.cargo/config.toml new file mode 100644 index 000000000..12f4b27b2 --- /dev/null +++ b/examples/mimxrt1011/.cargo/config.toml @@ -0,0 +1,8 @@ +[target.thumbv7em-none-eabihf] +runner = 'probe-rs run --chip MIMXRT1010' + +[build] +target = "thumbv7em-none-eabihf" # Cortex-M7 + +[env] +DEFMT_LOG = "trace" diff --git a/examples/mimxrt1011/Cargo.toml b/examples/mimxrt1011/Cargo.toml new file mode 100644 index 000000000..cf4e4c163 --- /dev/null +++ b/examples/mimxrt1011/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "embassy-imxrt1011-examples" +version = "0.1.0" +edition = "2021" +license = "MIT or Apache-2.0" + +[dependencies] +cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } +cortex-m-rt = "0.7.3" +defmt = "1.0.1" +defmt-rtt = "1.0.0" + +embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } +embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["defmt", "mimxrt1011", "unstable-pac", "time-driver-pit"] } +embassy-time = { version = "0.4", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime" # RT1011 hard faults currently with this enabled. +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embedded-hal-1 = { package = "embedded-hal", version = "1.0" } +embedded-hal-async = "1.0.0" + +imxrt-boot-gen = { version = "0.3.4", features = ["imxrt1010"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } +panic-semihosting = "0.6.0" + +[build-dependencies] +imxrt-rt = { version = "0.1.7", features = ["device"] } + +[profile.release] +debug = 2 diff --git a/examples/mimxrt1011/build.rs b/examples/mimxrt1011/build.rs new file mode 100644 index 000000000..99e172aba --- /dev/null +++ b/examples/mimxrt1011/build.rs @@ -0,0 +1,14 @@ +use imxrt_rt::{Family, RuntimeBuilder}; + +fn main() { + // The IMXRT1010-EVK technically has 128M of flash, but we only ever use 8MB so that the examples + // will build fine on the Adafruit Metro M7 boards. + RuntimeBuilder::from_flexspi(Family::Imxrt1010, 8 * 1024 * 1024) + .build() + .unwrap(); + + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + // Not link.x, as imxrt-rt needs to do some special things + println!("cargo:rustc-link-arg-bins=-Timxrt-link.x"); +} diff --git a/examples/mimxrt1011/src/bin/blinky.rs b/examples/mimxrt1011/src/bin/blinky.rs new file mode 100644 index 000000000..a5d5de6b3 --- /dev/null +++ b/examples/mimxrt1011/src/bin/blinky.rs @@ -0,0 +1,48 @@ +//! This example works on the following boards: +//! - IMXRT1010-EVK +//! - Adafruit Metro M7 (with microSD or with AirLift), requires an external button +//! - Makerdiary iMX RT1011 Nano Kit (TODO: currently untested, please change this) +//! +//! Although beware you will need to change the GPIO pins being used (scroll down). + +#![no_std] +#![no_main] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_nxp::gpio::{Level, Output}; +use embassy_time::Timer; +// Must include `embassy_imxrt1011_examples` to ensure the FCB gets linked. +use {defmt_rtt as _, embassy_imxrt1011_examples as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let p = embassy_nxp::init(Default::default()); + info!("Hello world!"); + + /* Pick the pins to use depending on your board. */ + + // IMXRT1010-EVK + // + // LED (D25) + let led = p.GPIO_11; + + // Adafruit Metro M7 (both microSD and AirLift variants) + // + // The LED is connected to D13 on the board. + // let led = p.GPIO_03; + + // Makerdiary iMX RT1011 Nano Kit + // + // LED0 + // let led = p.GPIO_SD_04; + + let mut led = Output::new(led, Level::Low); + + loop { + Timer::after_millis(500).await; + + info!("Toggle"); + led.toggle(); + } +} diff --git a/examples/mimxrt1011/src/bin/button.rs b/examples/mimxrt1011/src/bin/button.rs new file mode 100644 index 000000000..e63d7171d --- /dev/null +++ b/examples/mimxrt1011/src/bin/button.rs @@ -0,0 +1,62 @@ +//! This example works on the following boards: +//! - IMXRT1010-EVK +//! - Adafruit Metro M7 (with microSD or with AirLift), requires an external button +//! - Makerdiary iMX RT1011 Nano Kit (TODO: currently untested, please change this) +//! +//! Although beware you will need to change the GPIO pins being used (scroll down). + +#![no_std] +#![no_main] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_nxp::gpio::{Input, Level, Output, Pull}; +// Must include `embassy_imxrt1011_examples` to ensure the FCB gets linked. +use {defmt_rtt as _, embassy_imxrt1011_examples as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let p = embassy_nxp::init(Default::default()); + info!("Hello world!"); + + /* Pick the pins to use depending on your board. */ + + // IMXRT1010-EVK + // + // LED (D25) and user button (SW4) + let (led, button) = (p.GPIO_11, p.GPIO_SD_05); + + // Adafruit Metro M7 (both microSD and AirLift variants) + // + // The LED is connected to D13 on the board. + // + // In particular the Metro M7 has no board user buttons, so you will need to connect a button. + // Any other GPIO pin can be used. GPIO_04 is used for example since it is on pin D12. + // let (led, button) = (p.GPIO_03, p.GPIO_04); + + // Makerdiary iMX RT1011 Nano Kit + // + // LED0 and user button. + // let (led, button) = (p.GPIO_SD_04, p.GPIO_SD_03); + + let mut button = Input::new(button, Pull::Up100K); + let mut led = Output::new(led, Level::Low); + led.set_high(); + + loop { + button.wait_for_falling_edge().await; + + info!("Toggled"); + led.toggle(); + + // The RT1010EVK has a 100 nF debouncing capacitor which results in false positive events + // when listening for a falling edge in a loop, wait for the rising edge and then wait for + // stabilization. + button.wait_for_rising_edge().await; + + // Stabilization. + for _ in 0..100_000 { + cortex_m::asm::nop(); + } + } +} diff --git a/examples/mimxrt1011/src/lib.rs b/examples/mimxrt1011/src/lib.rs new file mode 100644 index 000000000..f0391ef57 --- /dev/null +++ b/examples/mimxrt1011/src/lib.rs @@ -0,0 +1,75 @@ +//! FlexSPI configuration block (FCB) for iMXRT1011 boards. +//! +//! This is a generic FCB that should work with most QSPI flash. + +#![no_std] + +use imxrt_boot_gen::flexspi; +use imxrt_boot_gen::flexspi::opcodes::sdr::*; +use imxrt_boot_gen::flexspi::{ + ColumnAddressWidth, Command, DeviceModeConfiguration, FlashPadType, Instr, LookupTable, Pads, + ReadSampleClockSource, Sequence, SequenceBuilder, SerialClockFrequency, SerialFlashRegion, + WaitTimeConfigurationCommands, +}; +use imxrt_boot_gen::serial_flash::nor; + +/// While the IMXRT1010-EVK and Makerdiary iMX RT1011 Nano Kit have 128MBit of flash we limit to 64Mbit +/// to allow the Metro M7 boards to use the same FCB configuration. +const DENSITY_BITS: u32 = 64 * 1024 * 1024; +const DENSITY_BYTES: u32 = DENSITY_BITS / 8; + +const SEQ_READ: Sequence = SequenceBuilder::new() + .instr(Instr::new(CMD, Pads::One, 0xEB)) + .instr(Instr::new(RADDR, Pads::Four, 0x18)) + .instr(Instr::new(DUMMY, Pads::Four, 0x06)) + .instr(Instr::new(READ, Pads::Four, 0x04)) + .build(); + +const SEQ_READ_STATUS: Sequence = SequenceBuilder::new() + .instr(Instr::new(CMD, Pads::One, 0x05)) + .instr(Instr::new(READ, Pads::One, 0x01)) + .build(); + +const SEQ_WRITE_ENABLE: Sequence = SequenceBuilder::new().instr(Instr::new(CMD, Pads::One, 0x06)).build(); + +const SEQ_ERASE_SECTOR: Sequence = SequenceBuilder::new() + .instr(Instr::new(CMD, Pads::One, 0x20)) + .instr(Instr::new(RADDR, Pads::One, 0x18)) + .build(); + +const SEQ_PAGE_PROGRAM: Sequence = SequenceBuilder::new() + .instr(Instr::new(CMD, Pads::One, 0x02)) + .instr(Instr::new(RADDR, Pads::One, 0x18)) + .instr(Instr::new(WRITE, Pads::One, 0x04)) + .build(); + +const SEQ_CHIP_ERASE: Sequence = SequenceBuilder::new().instr(Instr::new(CMD, Pads::One, 0x60)).build(); + +const LUT: LookupTable = LookupTable::new() + .command(Command::Read, SEQ_READ) + .command(Command::ReadStatus, SEQ_READ_STATUS) + .command(Command::WriteEnable, SEQ_WRITE_ENABLE) + .command(Command::EraseSector, SEQ_ERASE_SECTOR) + .command(Command::PageProgram, SEQ_PAGE_PROGRAM) + .command(Command::ChipErase, SEQ_CHIP_ERASE); + +const COMMON_CONFIGURATION_BLOCK: flexspi::ConfigurationBlock = flexspi::ConfigurationBlock::new(LUT) + .read_sample_clk_src(ReadSampleClockSource::LoopbackFromDQSPad) + .cs_hold_time(0x03) + .cs_setup_time(0x03) + .column_address_width(ColumnAddressWidth::OtherDevices) + .device_mode_configuration(DeviceModeConfiguration::Disabled) + .wait_time_cfg_commands(WaitTimeConfigurationCommands::disable()) + .flash_size(SerialFlashRegion::A1, DENSITY_BYTES) + .serial_clk_freq(SerialClockFrequency::MHz120) + .serial_flash_pad_type(FlashPadType::Quad); + +pub const SERIAL_NOR_CONFIGURATION_BLOCK: nor::ConfigurationBlock = + nor::ConfigurationBlock::new(COMMON_CONFIGURATION_BLOCK) + .page_size(256) + .sector_size(4096) + .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30); + +#[unsafe(no_mangle)] +#[cfg_attr(all(target_arch = "arm", target_os = "none"), link_section = ".fcb")] +pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK; -- cgit From 03b86d75b6861ed8151f4f48682e9b4f5b159232 Mon Sep 17 00:00:00 2001 From: dimi Date: Tue, 22 Jul 2025 18:16:11 +0200 Subject: derive Copy, Clone for adc config enums --- embassy-stm32/src/adc/adc4.rs | 4 +++- embassy-stm32/src/adc/c0.rs | 3 ++- embassy-stm32/src/adc/f3_v1_1.rs | 2 ++ embassy-stm32/src/adc/v4.rs | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/adc/adc4.rs b/embassy-stm32/src/adc/adc4.rs index 98483489f..31cbdc0d7 100644 --- a/embassy-stm32/src/adc/adc4.rs +++ b/embassy-stm32/src/adc/adc4.rs @@ -76,12 +76,14 @@ impl SealedAdcChannel for Vcore { } } +#[derive(Copy, Clone)] pub enum DacChannel { OUT1, OUT2, } /// Number of samples used for averaging. +#[derive(Copy, Clone)] pub enum Averaging { Disabled, Samples2, @@ -187,7 +189,7 @@ pub struct Adc4<'d, T: Instance> { adc: crate::Peri<'d, T>, } -#[derive(Debug)] +#[derive(Copy, Clone, Debug)] pub enum Adc4Error { InvalidSequence, DMAError, diff --git a/embassy-stm32/src/adc/c0.rs b/embassy-stm32/src/adc/c0.rs index 936ad7413..f5870801e 100644 --- a/embassy-stm32/src/adc/c0.rs +++ b/embassy-stm32/src/adc/c0.rs @@ -48,7 +48,7 @@ impl SealedAdcChannel for Temperature { } } -#[derive(Debug)] +#[derive(Copy, Clone, Debug)] pub enum Prescaler { NotDivided, DividedBy2, @@ -138,6 +138,7 @@ impl<'a> defmt::Format for Prescaler { /// Number of samples used for averaging. /// TODO: Implement hardware averaging setting. #[allow(unused)] +#[derive(Copy, Clone)] pub enum Averaging { Disabled, Samples2, diff --git a/embassy-stm32/src/adc/f3_v1_1.rs b/embassy-stm32/src/adc/f3_v1_1.rs index 944e971bb..84613078c 100644 --- a/embassy-stm32/src/adc/f3_v1_1.rs +++ b/embassy-stm32/src/adc/f3_v1_1.rs @@ -17,6 +17,7 @@ pub const VDDA_CALIB_MV: u32 = 3300; pub const ADC_MAX: u32 = (1 << 12) - 1; pub const VREF_INT: u32 = 1230; +#[derive(Copy, Clone)] pub enum AdcPowerMode { AlwaysOn, DelayOff, @@ -24,6 +25,7 @@ pub enum AdcPowerMode { DelayIdleOff, } +#[derive(Copy, Clone)] pub enum Prescaler { Div1, Div2, diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index 39e0d51b9..b0871019a 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs @@ -142,6 +142,7 @@ impl Prescaler { } /// Number of samples used for averaging. +#[derive(Copy, Clone)] pub enum Averaging { Disabled, Samples2, -- cgit From 1d46f55bddf402c33143959e1ad26af59bb15855 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Mon, 21 Jul 2025 20:29:34 -0500 Subject: nxp: Add mimxrt1062 support The examples in this case are designed for the IMXRT1060-EVK. The same chip is used in the Teensy 4.0/1, but that will probably get its own set of examples due to some differences such as the FCB. --- .vscode/settings.json | 1 + ci.sh | 4 +- embassy-nxp/Cargo.toml | 5 +- embassy-nxp/build.rs | 10 +- embassy-nxp/src/chips/mimxrt1062.rs | 282 +++++++++++++++++++++++++++++ embassy-nxp/src/gpio/rt1xxx.rs | 62 ++++++- embassy-nxp/src/lib.rs | 1 + examples/mimxrt1062-evk/.cargo/config.toml | 8 + examples/mimxrt1062-evk/Cargo.toml | 29 +++ examples/mimxrt1062-evk/build.rs | 12 ++ examples/mimxrt1062-evk/src/bin/blinky.rs | 25 +++ examples/mimxrt1062-evk/src/bin/button.rs | 36 ++++ examples/mimxrt1062-evk/src/lib.rs | 60 ++++++ 13 files changed, 522 insertions(+), 13 deletions(-) create mode 100644 embassy-nxp/src/chips/mimxrt1062.rs create mode 100644 examples/mimxrt1062-evk/.cargo/config.toml create mode 100644 examples/mimxrt1062-evk/Cargo.toml create mode 100644 examples/mimxrt1062-evk/build.rs create mode 100644 examples/mimxrt1062-evk/src/bin/blinky.rs create mode 100644 examples/mimxrt1062-evk/src/bin/button.rs create mode 100644 examples/mimxrt1062-evk/src/lib.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index 070e8fbd3..6edd9312a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -37,6 +37,7 @@ // "examples/nrf5340/Cargo.toml", // "examples/nrf-rtos-trace/Cargo.toml", // "examples/mimxrt1011/Cargo.toml", + // "examples/mimxrt1062-evk/Cargo.toml", // "examples/rp/Cargo.toml", // "examples/std/Cargo.toml", // "examples/stm32c0/Cargo.toml", diff --git a/ci.sh b/ci.sh index e225bc7c9..1a9a1d209 100755 --- a/ci.sh +++ b/ci.sh @@ -181,7 +181,8 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u073mb,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u083rc,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv8m.main-none-eabihf --features lpc55,defmt \ - --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv7em-none-eabihf --features mimxrt1011,defmt,time-driver-pit \ + --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv7em-none-eabihf --features mimxrt1011,rt,defmt,time-driver-pit \ + --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv7em-none-eabihf --features mimxrt1062,rt,defmt,time-driver-pit \ --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0c1104dgs20,defmt,time-driver-any \ --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3507pm,defmt,time-driver-any \ --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3519pz,defmt,time-driver-any \ @@ -266,6 +267,7 @@ cargo batch \ --- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32wl \ --- build --release --manifest-path examples/lpc55s69/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/lpc55s69 \ --- build --release --manifest-path examples/mimxrt1011/Cargo.toml --target thumbv7em-none-eabihf --artifact-dir out/examples/mimxrt1011 \ + --- build --release --manifest-path examples/mimxrt1062-evk/Cargo.toml --target thumbv7em-none-eabihf --artifact-dir out/examples/mimxrt1062-evk \ --- build --release --manifest-path examples/mspm0g3507/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3507 \ --- build --release --manifest-path examples/mspm0g3519/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3519 \ --- build --release --manifest-path examples/mspm0l1306/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0l1306 \ diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 625906183..293791d34 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -17,13 +17,13 @@ embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-util ## Chip dependencies lpc55-pac = { version = "0.5.0", optional = true } -nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/i509VCB/nxp-pac", rev = "1e010dbe75ab0e14dd908e4646391403414c8a8e" } +nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/i509VCB/nxp-pac", rev = "be4dd0936c20d5897364a381b1d95a99514c1e7e" } imxrt-rt = { version = "0.1.7", optional = true, features = ["device"] } [build-dependencies] cfg_aliases = "0.2.1" -nxp-pac = { version = "0.1.0", git = "https://github.com/i509VCB/nxp-pac", rev = "1e010dbe75ab0e14dd908e4646391403414c8a8e", features = ["metadata"], optional = true } +nxp-pac = { version = "0.1.0", git = "https://github.com/i509VCB/nxp-pac", rev = "be4dd0936c20d5897364a381b1d95a99514c1e7e", features = ["metadata"], optional = true } proc-macro2 = "1.0.95" quote = "1.0.15" @@ -58,3 +58,4 @@ _time_driver = ["dep:embassy-time-driver", "dep:embassy-time-queue-utils"] #! ### Chip selection features lpc55 = ["dep:lpc55-pac"] mimxrt1011 = ["nxp-pac/mimxrt1011", "_rt1xxx", "dep:imxrt-rt"] +mimxrt1062 = ["nxp-pac/mimxrt1062", "_rt1xxx", "dep:imxrt-rt"] diff --git a/embassy-nxp/build.rs b/embassy-nxp/build.rs index 6c10d0e69..f3c062c87 100644 --- a/embassy-nxp/build.rs +++ b/embassy-nxp/build.rs @@ -32,10 +32,12 @@ fn main() { .to_ascii_lowercase(); cfg_aliases! { - rt1xxx: { feature = "mimxrt1011" }, - gpio1: { feature = "mimxrt1011" }, - gpio2: { feature = "mimxrt1011" }, - gpio5: { feature = "mimxrt1011" }, + rt1xxx: { any(feature = "mimxrt1011", feature = "mimxrt1062") }, + gpio1: { any(feature = "mimxrt1011", feature = "mimxrt1062") }, + gpio2: { any(feature = "mimxrt1011", feature = "mimxrt1062") }, + gpio3: { feature = "mimxrt1062" }, + gpio4: { feature = "mimxrt1062" }, + gpio5: { any(feature = "mimxrt1011", feature = "mimxrt1062") }, } eprintln!("chip: {chip_name}"); diff --git a/embassy-nxp/src/chips/mimxrt1062.rs b/embassy-nxp/src/chips/mimxrt1062.rs new file mode 100644 index 000000000..ef153bd66 --- /dev/null +++ b/embassy-nxp/src/chips/mimxrt1062.rs @@ -0,0 +1,282 @@ +// This must be imported so that __preinit is defined. +use imxrt_rt as _; +pub use nxp_pac as pac; + +embassy_hal_internal::peripherals! { + // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other + // peripheral types (e.g. I2C). + GPIO_AD_B0_00, + GPIO_AD_B0_01, + GPIO_AD_B0_02, + GPIO_AD_B0_03, + GPIO_AD_B0_04, + GPIO_AD_B0_05, + GPIO_AD_B0_06, + GPIO_AD_B0_07, + GPIO_AD_B0_08, + GPIO_AD_B0_09, + GPIO_AD_B0_10, + GPIO_AD_B0_11, + GPIO_AD_B0_12, + GPIO_AD_B0_13, + GPIO_AD_B0_14, + GPIO_AD_B0_15, + GPIO_AD_B1_00, + GPIO_AD_B1_01, + GPIO_AD_B1_02, + GPIO_AD_B1_03, + GPIO_AD_B1_04, + GPIO_AD_B1_05, + GPIO_AD_B1_06, + GPIO_AD_B1_07, + GPIO_AD_B1_08, + GPIO_AD_B1_09, + GPIO_AD_B1_10, + GPIO_AD_B1_11, + GPIO_AD_B1_12, + GPIO_AD_B1_13, + GPIO_AD_B1_14, + GPIO_AD_B1_15, + GPIO_B0_00, + GPIO_B0_01, + GPIO_B0_02, + GPIO_B0_03, + GPIO_B0_04, + GPIO_B0_05, + GPIO_B0_06, + GPIO_B0_07, + GPIO_B0_08, + GPIO_B0_09, + GPIO_B0_10, + GPIO_B0_11, + GPIO_B0_12, + GPIO_B0_13, + GPIO_B0_14, + GPIO_B0_15, + GPIO_B1_00, + GPIO_B1_01, + GPIO_B1_02, + GPIO_B1_03, + GPIO_B1_04, + GPIO_B1_05, + GPIO_B1_06, + GPIO_B1_07, + GPIO_B1_08, + GPIO_B1_09, + GPIO_B1_10, + GPIO_B1_11, + GPIO_B1_12, + GPIO_B1_13, + GPIO_B1_14, + GPIO_B1_15, + GPIO_EMC_00, + GPIO_EMC_01, + GPIO_EMC_02, + GPIO_EMC_03, + GPIO_EMC_04, + GPIO_EMC_05, + GPIO_EMC_06, + GPIO_EMC_07, + GPIO_EMC_08, + GPIO_EMC_09, + GPIO_EMC_10, + GPIO_EMC_11, + GPIO_EMC_12, + GPIO_EMC_13, + GPIO_EMC_14, + GPIO_EMC_15, + GPIO_EMC_16, + GPIO_EMC_17, + GPIO_EMC_18, + GPIO_EMC_19, + GPIO_EMC_20, + GPIO_EMC_21, + GPIO_EMC_22, + GPIO_EMC_23, + GPIO_EMC_24, + GPIO_EMC_25, + GPIO_EMC_26, + GPIO_EMC_27, + GPIO_EMC_28, + GPIO_EMC_29, + GPIO_EMC_30, + GPIO_EMC_31, + GPIO_EMC_32, + GPIO_EMC_33, + GPIO_EMC_34, + GPIO_EMC_35, + GPIO_EMC_36, + GPIO_EMC_37, + GPIO_EMC_38, + GPIO_EMC_39, + GPIO_EMC_40, + GPIO_EMC_41, + GPIO_SD_B0_00, + GPIO_SD_B0_01, + GPIO_SD_B0_02, + GPIO_SD_B0_03, + GPIO_SD_B0_04, + GPIO_SD_B0_05, + GPIO_SD_B1_00, + GPIO_SD_B1_01, + GPIO_SD_B1_02, + GPIO_SD_B1_03, + GPIO_SD_B1_04, + GPIO_SD_B1_05, + GPIO_SD_B1_06, + GPIO_SD_B1_07, + GPIO_SD_B1_08, + GPIO_SD_B1_09, + GPIO_SD_B1_10, + GPIO_SD_B1_11, + WAKEUP, + PMIC_ON_REQ, + PMIC_STBY_REQ, +} + +impl_gpio! { + // GPIO Bank 1 + GPIO_AD_B0_00(Gpio1, 0); + GPIO_AD_B0_01(Gpio1, 1); + GPIO_AD_B0_02(Gpio1, 2); + GPIO_AD_B0_03(Gpio1, 3); + GPIO_AD_B0_04(Gpio1, 4); + GPIO_AD_B0_05(Gpio1, 5); + GPIO_AD_B0_06(Gpio1, 6); + GPIO_AD_B0_07(Gpio1, 7); + GPIO_AD_B0_08(Gpio1, 8); + GPIO_AD_B0_09(Gpio1, 9); + GPIO_AD_B0_10(Gpio1, 10); + GPIO_AD_B0_11(Gpio1, 11); + GPIO_AD_B0_12(Gpio1, 12); + GPIO_AD_B0_13(Gpio1, 13); + GPIO_AD_B0_14(Gpio1, 14); + GPIO_AD_B0_15(Gpio1, 15); + GPIO_AD_B1_00(Gpio1, 16); + GPIO_AD_B1_01(Gpio1, 17); + GPIO_AD_B1_02(Gpio1, 18); + GPIO_AD_B1_03(Gpio1, 19); + GPIO_AD_B1_04(Gpio1, 20); + GPIO_AD_B1_05(Gpio1, 21); + GPIO_AD_B1_06(Gpio1, 22); + GPIO_AD_B1_07(Gpio1, 23); + GPIO_AD_B1_08(Gpio1, 24); + GPIO_AD_B1_09(Gpio1, 25); + GPIO_AD_B1_10(Gpio1, 26); + GPIO_AD_B1_11(Gpio1, 27); + GPIO_AD_B1_12(Gpio1, 28); + GPIO_AD_B1_13(Gpio1, 29); + GPIO_AD_B1_14(Gpio1, 30); + GPIO_AD_B1_15(Gpio1, 31); + + // GPIO Bank 2 + GPIO_B0_00(Gpio2, 0); + GPIO_B0_01(Gpio2, 1); + GPIO_B0_02(Gpio2, 2); + GPIO_B0_03(Gpio2, 3); + GPIO_B0_04(Gpio2, 4); + GPIO_B0_05(Gpio2, 5); + GPIO_B0_06(Gpio2, 6); + GPIO_B0_07(Gpio2, 7); + GPIO_B0_08(Gpio2, 8); + GPIO_B0_09(Gpio2, 9); + GPIO_B0_10(Gpio2, 10); + GPIO_B0_11(Gpio2, 11); + GPIO_B0_12(Gpio2, 12); + GPIO_B0_13(Gpio2, 13); + GPIO_B0_14(Gpio2, 14); + GPIO_B0_15(Gpio2, 15); + GPIO_B1_00(Gpio2, 16); + GPIO_B1_01(Gpio2, 17); + GPIO_B1_02(Gpio2, 18); + GPIO_B1_03(Gpio2, 19); + GPIO_B1_04(Gpio2, 20); + GPIO_B1_05(Gpio2, 21); + GPIO_B1_06(Gpio2, 22); + GPIO_B1_07(Gpio2, 23); + GPIO_B1_08(Gpio2, 24); + GPIO_B1_09(Gpio2, 25); + GPIO_B1_10(Gpio2, 26); + GPIO_B1_11(Gpio2, 27); + GPIO_B1_12(Gpio2, 28); + GPIO_B1_13(Gpio2, 29); + GPIO_B1_14(Gpio2, 30); + GPIO_B1_15(Gpio2, 31); + + // GPIO Bank 4 (EMC is 4, then 3) + GPIO_EMC_00(Gpio4, 0); + GPIO_EMC_01(Gpio4, 1); + GPIO_EMC_02(Gpio4, 2); + GPIO_EMC_03(Gpio4, 3); + GPIO_EMC_04(Gpio4, 4); + GPIO_EMC_05(Gpio4, 5); + GPIO_EMC_06(Gpio4, 6); + GPIO_EMC_07(Gpio4, 7); + GPIO_EMC_08(Gpio4, 8); + GPIO_EMC_09(Gpio4, 9); + GPIO_EMC_10(Gpio4, 10); + GPIO_EMC_11(Gpio4, 11); + GPIO_EMC_12(Gpio4, 12); + GPIO_EMC_13(Gpio4, 13); + GPIO_EMC_14(Gpio4, 14); + GPIO_EMC_15(Gpio4, 15); + GPIO_EMC_16(Gpio4, 16); + GPIO_EMC_17(Gpio4, 17); + GPIO_EMC_18(Gpio4, 18); + GPIO_EMC_19(Gpio4, 19); + GPIO_EMC_20(Gpio4, 20); + GPIO_EMC_21(Gpio4, 21); + GPIO_EMC_22(Gpio4, 22); + GPIO_EMC_23(Gpio4, 23); + GPIO_EMC_24(Gpio4, 24); + GPIO_EMC_25(Gpio4, 25); + GPIO_EMC_26(Gpio4, 26); + GPIO_EMC_27(Gpio4, 27); + GPIO_EMC_28(Gpio4, 28); + GPIO_EMC_29(Gpio4, 29); + GPIO_EMC_30(Gpio4, 30); + GPIO_EMC_31(Gpio4, 31); + + // GPIO Bank 3 + GPIO_EMC_32(Gpio3, 18); + GPIO_EMC_33(Gpio3, 19); + GPIO_EMC_34(Gpio3, 20); + GPIO_EMC_35(Gpio3, 21); + GPIO_EMC_36(Gpio3, 22); + GPIO_EMC_37(Gpio3, 23); + GPIO_EMC_38(Gpio3, 24); + GPIO_EMC_39(Gpio3, 25); + GPIO_EMC_40(Gpio3, 26); + GPIO_EMC_41(Gpio3, 27); + GPIO_SD_B0_00(Gpio3, 12); + GPIO_SD_B0_01(Gpio3, 13); + GPIO_SD_B0_02(Gpio3, 14); + GPIO_SD_B0_03(Gpio3, 15); + GPIO_SD_B0_04(Gpio3, 16); + GPIO_SD_B0_05(Gpio3, 17); + GPIO_SD_B1_00(Gpio3, 0); + GPIO_SD_B1_01(Gpio3, 1); + GPIO_SD_B1_02(Gpio3, 2); + GPIO_SD_B1_03(Gpio3, 3); + GPIO_SD_B1_04(Gpio3, 4); + GPIO_SD_B1_05(Gpio3, 5); + GPIO_SD_B1_06(Gpio3, 6); + GPIO_SD_B1_07(Gpio3, 7); + GPIO_SD_B1_08(Gpio3, 8); + GPIO_SD_B1_09(Gpio3, 9); + GPIO_SD_B1_10(Gpio3, 10); + GPIO_SD_B1_11(Gpio3, 11); + + WAKEUP(Gpio5, 0); + PMIC_ON_REQ(Gpio5, 1); + PMIC_STBY_REQ(Gpio5, 2); +} + +pub(crate) mod _generated { + #![allow(dead_code)] + #![allow(unused_imports)] + #![allow(non_snake_case)] + #![allow(missing_docs)] + + include!(concat!(env!("OUT_DIR"), "/_generated.rs")); +} diff --git a/embassy-nxp/src/gpio/rt1xxx.rs b/embassy-nxp/src/gpio/rt1xxx.rs index 9c58e8a7d..1d60a0d51 100644 --- a/embassy-nxp/src/gpio/rt1xxx.rs +++ b/embassy-nxp/src/gpio/rt1xxx.rs @@ -12,11 +12,11 @@ use nxp_pac::iomuxc::vals::Pus; use crate::chip::{mux_address, pad_address}; use crate::pac::common::{Reg, RW}; +use crate::pac::gpio::Gpio; #[cfg(feature = "rt")] use crate::pac::interrupt; use crate::pac::iomuxc::regs::{Ctl, MuxCtl}; -#[cfg(gpio5)] -use crate::pac::{self, gpio::Gpio}; +use crate::pac::{self}; /// The GPIO pin level for pins set on "Digital" mode. #[derive(Debug, Eq, PartialEq, Clone, Copy)] @@ -110,6 +110,14 @@ pub enum Bank { #[cfg(gpio2)] Gpio2, + /// Bank 3 + #[cfg(gpio3)] + Gpio3, + + /// Bank 4 + #[cfg(gpio4)] + Gpio4, + /// Bank 5 #[cfg(gpio5)] Gpio5, @@ -642,6 +650,10 @@ const GPIO_MUX_MODE: u8 = 0b101; static GPIO1_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32]; #[cfg(gpio2)] static GPIO2_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32]; +#[cfg(gpio3)] +static GPIO3_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32]; +#[cfg(gpio4)] +static GPIO4_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32]; #[cfg(gpio5)] static GPIO5_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32]; @@ -658,6 +670,10 @@ pub(crate) trait SealedPin: Sized { Bank::Gpio1 => pac::GPIO1, #[cfg(gpio2)] Bank::Gpio2 => pac::GPIO2, + #[cfg(gpio3)] + Bank::Gpio3 => pac::GPIO3, + #[cfg(gpio4)] + Bank::Gpio4 => pac::GPIO4, #[cfg(gpio5)] Bank::Gpio5 => pac::GPIO5, } @@ -687,6 +703,10 @@ pub(crate) trait SealedPin: Sized { Bank::Gpio1 => &GPIO1_WAKERS[self.pin_number() as usize], #[cfg(gpio2)] Bank::Gpio2 => &GPIO2_WAKERS[self.pin_number() as usize], + #[cfg(gpio3)] + Bank::Gpio3 => &GPIO3_WAKERS[self.pin_number() as usize], + #[cfg(gpio4)] + Bank::Gpio4 => &GPIO4_WAKERS[self.pin_number() as usize], #[cfg(gpio5)] Bank::Gpio5 => &GPIO5_WAKERS[self.pin_number() as usize], } @@ -870,25 +890,55 @@ fn irq_handler(block: Gpio, wakers: &[AtomicWaker; 32], high_bits: bool) { } } -#[cfg(all(feature = "mimxrt1011", feature = "rt"))] +#[cfg(all(any(feature = "mimxrt1011", feature = "mimxrt1062"), feature = "rt"))] #[interrupt] fn GPIO1_COMBINED_0_15() { irq_handler(pac::GPIO1, &GPIO1_WAKERS, false); } -#[cfg(all(feature = "mimxrt1011", feature = "rt"))] +#[cfg(all(any(feature = "mimxrt1011", feature = "mimxrt1062"), feature = "rt"))] #[interrupt] fn GPIO1_COMBINED_16_31() { irq_handler(pac::GPIO1, &GPIO1_WAKERS, true); } -#[cfg(all(feature = "mimxrt1011", feature = "rt"))] +#[cfg(all(any(feature = "mimxrt1011", feature = "mimxrt1062"), feature = "rt"))] #[interrupt] fn GPIO2_COMBINED_0_15() { irq_handler(pac::GPIO2, &GPIO2_WAKERS, false); } -#[cfg(all(feature = "mimxrt1011", feature = "rt"))] +#[cfg(all(feature = "mimxrt1062", feature = "rt"))] +#[interrupt] +fn GPIO2_COMBINED_16_31() { + irq_handler(pac::GPIO2, &GPIO2_WAKERS, true); +} + +#[cfg(all(feature = "mimxrt1062", feature = "rt"))] +#[interrupt] +fn GPIO3_COMBINED_0_15() { + irq_handler(pac::GPIO3, &GPIO3_WAKERS, false); +} + +#[cfg(all(feature = "mimxrt1062", feature = "rt"))] +#[interrupt] +fn GPIO3_COMBINED_16_31() { + irq_handler(pac::GPIO3, &GPIO3_WAKERS, true); +} + +#[cfg(all(feature = "mimxrt1062", feature = "rt"))] +#[interrupt] +fn GPIO4_COMBINED_0_15() { + irq_handler(pac::GPIO4, &GPIO4_WAKERS, false); +} + +#[cfg(all(feature = "mimxrt1062", feature = "rt"))] +#[interrupt] +fn GPIO4_COMBINED_16_31() { + irq_handler(pac::GPIO4, &GPIO4_WAKERS, true); +} + +#[cfg(all(any(feature = "mimxrt1011", feature = "mimxrt1062"), feature = "rt"))] #[interrupt] fn GPIO5_COMBINED_0_15() { irq_handler(pac::GPIO5, &GPIO5_WAKERS, false); diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs index a715770c4..5e77fc0db 100644 --- a/embassy-nxp/src/lib.rs +++ b/embassy-nxp/src/lib.rs @@ -14,6 +14,7 @@ mod time_driver; // This mod MUST go last, so that it sees all the `impl_foo!` macros #[cfg_attr(feature = "lpc55", path = "chips/lpc55.rs")] #[cfg_attr(feature = "mimxrt1011", path = "chips/mimxrt1011.rs")] +#[cfg_attr(feature = "mimxrt1062", path = "chips/mimxrt1062.rs")] mod chip; #[cfg(feature = "unstable-pac")] diff --git a/examples/mimxrt1062-evk/.cargo/config.toml b/examples/mimxrt1062-evk/.cargo/config.toml new file mode 100644 index 000000000..ca4c606dc --- /dev/null +++ b/examples/mimxrt1062-evk/.cargo/config.toml @@ -0,0 +1,8 @@ +[target.thumbv7em-none-eabihf] +runner = 'probe-rs run --chip MIMXRT1060' + +[build] +target = "thumbv7em-none-eabihf" # Cortex-M7 + +[env] +DEFMT_LOG = "trace" diff --git a/examples/mimxrt1062-evk/Cargo.toml b/examples/mimxrt1062-evk/Cargo.toml new file mode 100644 index 000000000..430a26b41 --- /dev/null +++ b/examples/mimxrt1062-evk/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "embassy-imxrt1062-evk-examples" +version = "0.1.0" +edition = "2021" +license = "MIT or Apache-2.0" + +[dependencies] +cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } +cortex-m-rt = "0.7.3" +defmt = "1.0.1" +defmt-rtt = "1.0.0" + +embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } +embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["defmt", "mimxrt1062", "unstable-pac", "time-driver-pit"] } +embassy-time = { version = "0.4", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime" +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embedded-hal-1 = { package = "embedded-hal", version = "1.0" } +embedded-hal-async = "1.0.0" + +imxrt-boot-gen = { version = "0.3.4", features = ["imxrt1060"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } +panic-semihosting = "0.6.0" + +[build-dependencies] +imxrt-rt = { version = "0.1.7", features = ["device"] } + +[profile.release] +debug = 2 diff --git a/examples/mimxrt1062-evk/build.rs b/examples/mimxrt1062-evk/build.rs new file mode 100644 index 000000000..e0e0d547e --- /dev/null +++ b/examples/mimxrt1062-evk/build.rs @@ -0,0 +1,12 @@ +use imxrt_rt::{Family, RuntimeBuilder}; + +fn main() { + RuntimeBuilder::from_flexspi(Family::Imxrt1060, 8 * 1024 * 1024) + .build() + .unwrap(); + + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + // Not link.x, as imxrt-rt needs to do some special things + println!("cargo:rustc-link-arg-bins=-Timxrt-link.x"); +} diff --git a/examples/mimxrt1062-evk/src/bin/blinky.rs b/examples/mimxrt1062-evk/src/bin/blinky.rs new file mode 100644 index 000000000..b6d90d94d --- /dev/null +++ b/examples/mimxrt1062-evk/src/bin/blinky.rs @@ -0,0 +1,25 @@ +#![no_std] +#![no_main] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_nxp::gpio::{Level, Output}; +use embassy_time::Timer; +// Must include `embassy_imxrt1062_evk_examples` to ensure the FCB gets linked. +use {defmt_rtt as _, embassy_imxrt1062_evk_examples as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let p = embassy_nxp::init(Default::default()); + info!("Hello world!"); + + let led = p.GPIO_AD_B0_08; + let mut led = Output::new(led, Level::Low); + + loop { + Timer::after_millis(500).await; + + info!("Toggle"); + led.toggle(); + } +} diff --git a/examples/mimxrt1062-evk/src/bin/button.rs b/examples/mimxrt1062-evk/src/bin/button.rs new file mode 100644 index 000000000..d60fa3dac --- /dev/null +++ b/examples/mimxrt1062-evk/src/bin/button.rs @@ -0,0 +1,36 @@ +#![no_std] +#![no_main] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_nxp::gpio::{Input, Level, Output, Pull}; +use {defmt_rtt as _, embassy_imxrt1062_evk_examples as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let p = embassy_nxp::init(Default::default()); + info!("Hello world!"); + + // User LED (D8) + let led = p.GPIO_AD_B0_08; + // User button (SW5) + let button = p.WAKEUP; + let mut button = Input::new(button, Pull::Up100K); + let mut led = Output::new(led, Level::Low); + led.set_high(); + + loop { + button.wait_for_falling_edge().await; + + info!("Toggled"); + led.toggle(); + + // Software debounce. + button.wait_for_rising_edge().await; + + // Stabilization. + for _ in 0..100_000 { + cortex_m::asm::nop(); + } + } +} diff --git a/examples/mimxrt1062-evk/src/lib.rs b/examples/mimxrt1062-evk/src/lib.rs new file mode 100644 index 000000000..3f99f9db3 --- /dev/null +++ b/examples/mimxrt1062-evk/src/lib.rs @@ -0,0 +1,60 @@ +//! FlexSPI configuration block (FCB) for the iMXRT1060-EVK +//! +//! This uses IS25WP QuadSPI flash. + +#![no_std] + +use imxrt_boot_gen::flexspi::opcodes::sdr::*; +use imxrt_boot_gen::flexspi::{self, FlashPadType, ReadSampleClockSource, SerialClockFrequency, SerialFlashRegion, *}; +use imxrt_boot_gen::serial_flash::*; +pub use nor::ConfigurationBlock; + +const SEQ_READ: Sequence = SequenceBuilder::new() + .instr(Instr::new(CMD, Pads::One, 0xEB)) + .instr(Instr::new(RADDR, Pads::Four, 0x18)) + .instr(Instr::new(DUMMY, Pads::Four, 0x06)) + .instr(Instr::new(READ, Pads::Four, 0x04)) + .build(); +const SEQ_READ_STATUS: Sequence = SequenceBuilder::new() + .instr(Instr::new(CMD, Pads::One, 0x05)) + .instr(Instr::new(READ, Pads::One, 0x04)) + .build(); +const SEQ_WRITE_ENABLE: Sequence = SequenceBuilder::new().instr(Instr::new(CMD, Pads::One, 0x06)).build(); +const SEQ_ERASE_SECTOR: Sequence = SequenceBuilder::new() + .instr(Instr::new(CMD, Pads::One, 0x20)) + .instr(Instr::new(RADDR, Pads::One, 0x18)) + .build(); +const SEQ_PAGE_PROGRAM: Sequence = SequenceBuilder::new() + .instr(Instr::new(CMD, Pads::One, 0x02)) + .instr(Instr::new(RADDR, Pads::One, 0x18)) + .instr(Instr::new(WRITE, Pads::One, 0x04)) + .build(); +const SEQ_CHIP_ERASE: Sequence = SequenceBuilder::new().instr(Instr::new(CMD, Pads::One, 0x60)).build(); + +const LUT: LookupTable = LookupTable::new() + .command(Command::Read, SEQ_READ) + .command(Command::ReadStatus, SEQ_READ_STATUS) + .command(Command::WriteEnable, SEQ_WRITE_ENABLE) + .command(Command::EraseSector, SEQ_ERASE_SECTOR) + .command(Command::PageProgram, SEQ_PAGE_PROGRAM) + .command(Command::ChipErase, SEQ_CHIP_ERASE); + +const COMMON_CONFIGURATION_BLOCK: flexspi::ConfigurationBlock = flexspi::ConfigurationBlock::new(LUT) + .version(Version::new(1, 4, 0)) + .read_sample_clk_src(ReadSampleClockSource::LoopbackFromDQSPad) + .cs_hold_time(3) + .cs_setup_time(3) + .controller_misc_options(0x10) + .serial_flash_pad_type(FlashPadType::Quad) + .serial_clk_freq(SerialClockFrequency::MHz133) + .flash_size(SerialFlashRegion::A1, 8 * 1024 * 1024); + +pub const SERIAL_NOR_CONFIGURATION_BLOCK: nor::ConfigurationBlock = + nor::ConfigurationBlock::new(COMMON_CONFIGURATION_BLOCK) + .page_size(256) + .sector_size(4096) + .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30); + +#[no_mangle] +#[cfg_attr(all(target_arch = "arm", target_os = "none"), link_section = ".fcb")] +pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK; -- cgit From a1867f0d742f597a25384e4a33209beeec7ec676 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Sun, 6 Jul 2025 17:35:19 -0500 Subject: mspm0: add buffered uart driver And tests for G3507. --- embassy-mspm0/Cargo.toml | 4 + embassy-mspm0/src/uart.rs | 1111 -------------------------------- embassy-mspm0/src/uart/buffered.rs | 1060 ++++++++++++++++++++++++++++++ embassy-mspm0/src/uart/mod.rs | 1174 ++++++++++++++++++++++++++++++++++ examples/mspm0g3507/Cargo.toml | 2 + tests/mspm0/Cargo.toml | 3 + tests/mspm0/src/bin/uart_buffered.rs | 115 ++++ 7 files changed, 2358 insertions(+), 1111 deletions(-) delete mode 100644 embassy-mspm0/src/uart.rs create mode 100644 embassy-mspm0/src/uart/buffered.rs create mode 100644 embassy-mspm0/src/uart/mod.rs create mode 100644 tests/mspm0/src/bin/uart_buffered.rs diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index d2adc63d7..61afcd76d 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -36,7 +36,10 @@ embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", de embassy-executor = { version = "0.7.0", path = "../embassy-executor", optional = true } embedded-hal = { version = "1.0" } +embedded-hal-nb = { version = "1.0" } embedded-hal-async = { version = "1.0" } +embedded-io = "0.6.1" +embedded-io-async = "0.6.1" defmt = { version = "1.0.1", optional = true } fixed = "1.29" @@ -51,6 +54,7 @@ mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag [build-dependencies] proc-macro2 = "1.0.94" quote = "1.0.40" +cfg_aliases = "0.2.1" # mspm0-metapac = { version = "", default-features = false, features = ["metadata"] } mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-235158ac2865d8aac3a1eceb2d62026eb12bf38f", default-features = false, features = ["metadata"] } diff --git a/embassy-mspm0/src/uart.rs b/embassy-mspm0/src/uart.rs deleted file mode 100644 index bc1d2e343..000000000 --- a/embassy-mspm0/src/uart.rs +++ /dev/null @@ -1,1111 +0,0 @@ -#![macro_use] - -use core::marker::PhantomData; -use core::sync::atomic::{compiler_fence, AtomicU32, Ordering}; - -use embassy_embedded_hal::SetConfig; -use embassy_hal_internal::PeripheralType; - -use crate::gpio::{AnyPin, PfType, Pull, SealedPin}; -use crate::interrupt::{Interrupt, InterruptExt}; -use crate::mode::{Blocking, Mode}; -use crate::pac::uart::{vals, Uart as Regs}; -use crate::Peri; - -/// The clock source for the UART. -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum ClockSel { - /// Use the low frequency clock. - /// - /// The LFCLK runs at 32.768 kHz. - LfClk, - - /// Use the middle frequency clock. - /// - /// The MCLK runs at 4 MHz. - MfClk, - // BusClk, - // BusClk depends on the timer's power domain. - // This will be implemented later. -} - -#[non_exhaustive] -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -/// The order of bits in byte. -pub enum BitOrder { - /// The most significant bit is first. - MsbFirst, - - /// The least significant bit is first. - LsbFirst, -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -/// Number of data bits -pub enum DataBits { - /// 5 Data Bits - DataBits5, - - /// 6 Data Bits - DataBits6, - - /// 7 Data Bits - DataBits7, - - /// 8 Data Bits - DataBits8, -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -/// Parity -pub enum Parity { - /// No parity - ParityNone, - - /// Even Parity - ParityEven, - - /// Odd Parity - ParityOdd, -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -/// Number of stop bits -pub enum StopBits { - /// One stop bit - Stop1, - - /// Two stop bits - Stop2, -} - -#[non_exhaustive] -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -/// Config Error -pub enum ConfigError { - /// Rx or Tx not enabled - RxOrTxNotEnabled, - - /// The baud rate could not be configured with the given clocks. - InvalidBaudRate, -} - -#[non_exhaustive] -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -/// Config -pub struct Config { - /// UART clock source. - pub clock_source: ClockSel, - - /// Baud rate - pub baudrate: u32, - - /// Number of data bits. - pub data_bits: DataBits, - - /// Number of stop bits. - pub stop_bits: StopBits, - - /// Parity type. - pub parity: Parity, - - /// The order of bits in a transmitted/received byte. - pub msb_order: BitOrder, - - /// If true: the `TX` is internally connected to `RX`. - pub loop_back_enable: bool, - - // TODO: Pending way to check if uart is extended - // /// If true: [manchester coding] is used. - // /// - // /// [manchester coding]: https://en.wikipedia.org/wiki/Manchester_code - // pub manchester: bool, - - // TODO: majority voting - - // TODO: fifo level select - need power domain info in metapac - - // TODO: glitch suppression - /// If true: invert TX pin signal values (VDD = 0/mark, Gnd = 1/idle). - pub invert_tx: bool, - - /// If true: invert RX pin signal values (VDD = 0/mark, Gnd = 1/idle). - pub invert_rx: bool, - - /// If true: invert RTS pin signal values (VDD = 0/mark, Gnd = 1/idle). - pub invert_rts: bool, - - /// If true: invert CTS pin signal values (VDD = 0/mark, Gnd = 1/idle). - pub invert_cts: bool, - - /// Set the pull configuration for the TX pin. - pub tx_pull: Pull, - - /// Set the pull configuration for the RX pin. - pub rx_pull: Pull, - - /// Set the pull configuration for the RTS pin. - pub rts_pull: Pull, - - /// Set the pull configuration for the CTS pin. - pub cts_pull: Pull, -} - -impl Default for Config { - fn default() -> Self { - Self { - clock_source: ClockSel::MfClk, - baudrate: 115200, - data_bits: DataBits::DataBits8, - stop_bits: StopBits::Stop1, - parity: Parity::ParityNone, - // hardware default - msb_order: BitOrder::LsbFirst, - loop_back_enable: false, - // manchester: false, - invert_tx: false, - invert_rx: false, - invert_rts: false, - invert_cts: false, - tx_pull: Pull::None, - rx_pull: Pull::None, - rts_pull: Pull::None, - cts_pull: Pull::None, - } - } -} - -/// Bidirectional UART Driver, which acts as a combination of [`UartTx`] and [`UartRx`]. -/// -/// ### Notes on [`embedded_io::Read`] -/// -/// `embedded_io::Read` requires guarantees that the base [`UartRx`] cannot provide. -/// -/// See [`UartRx`] for more details, and see [`BufferedUart`] and [`RingBufferedUartRx`] -/// as alternatives that do provide the necessary guarantees for `embedded_io::Read`. -pub struct Uart<'d, M: Mode> { - tx: UartTx<'d, M>, - rx: UartRx<'d, M>, -} - -impl<'d, M: Mode> SetConfig for Uart<'d, M> { - type Config = Config; - type ConfigError = ConfigError; - - fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { - self.tx.set_config(config)?; - self.rx.set_config(config) - } -} - -/// Serial error -#[derive(Debug, Eq, PartialEq, Copy, Clone)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -#[non_exhaustive] -pub enum Error { - Framing, - - Noise, - - Overrun, - - Parity, - - Break, -} - -impl core::fmt::Display for Error { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - let message = match self { - Self::Framing => "Framing Error", - Self::Noise => "Noise Error", - Self::Overrun => "RX Buffer Overrun", - Self::Parity => "Parity Check Error", - Self::Break => "Break Error", - }; - - write!(f, "{}", message) - } -} - -impl core::error::Error for Error {} - -/// Rx-only UART Driver. -/// -/// Can be obtained from [`Uart::split`], or can be constructed independently, -/// if you do not need the transmitting half of the driver. -pub struct UartRx<'d, M: Mode> { - info: &'static Info, - state: &'static State, - rx: Option>, - rts: Option>, - _phantom: PhantomData, -} - -impl<'d, M: Mode> SetConfig for UartRx<'d, M> { - type Config = Config; - type ConfigError = ConfigError; - - fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { - self.set_config(config) - } -} - -impl<'d> UartRx<'d, Blocking> { - /// Create a new rx-only UART with no hardware flow control. - /// - /// Useful if you only want Uart Rx. It saves 1 pin . - pub fn new_blocking( - peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - config: Config, - ) -> Result { - Self::new_inner(peri, new_pin!(rx, config.rx_pf()), None, config) - } - - /// Create a new rx-only UART with a request-to-send pin - pub fn new_blocking_with_rts( - peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - rts: Peri<'d, impl RtsPin>, - config: Config, - ) -> Result { - Self::new_inner( - peri, - new_pin!(rx, config.rx_pf()), - new_pin!(rts, config.rts_pf()), - config, - ) - } -} - -impl<'d, M: Mode> UartRx<'d, M> { - /// Reconfigure the driver - pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { - if let Some(ref rx) = self.rx { - rx.update_pf(config.rx_pf()); - } - - if let Some(ref rts) = self.rts { - rts.update_pf(config.rts_pf()); - } - - reconfigure(self.info, self.state, config) - } - - /// Perform a blocking read into `buffer` - pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { - let r = self.info.regs; - - for b in buffer { - // Wait if nothing has arrived yet. - while r.stat().read().rxfe() {} - - // Prevent the compiler from reading from buffer too early - compiler_fence(Ordering::Acquire); - *b = read_with_error(r)?; - } - - Ok(()) - } - - /// Set baudrate - pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError> { - set_baudrate(&self.info, self.state.clock.load(Ordering::Relaxed), baudrate) - } -} - -impl<'d, M: Mode> Drop for UartRx<'d, M> { - fn drop(&mut self) { - self.rx.as_ref().map(|x| x.set_as_disconnected()); - self.rts.as_ref().map(|x| x.set_as_disconnected()); - } -} - -/// Tx-only UART Driver. -/// -/// Can be obtained from [`Uart::split`], or can be constructed independently, -/// if you do not need the receiving half of the driver. -pub struct UartTx<'d, M: Mode> { - info: &'static Info, - state: &'static State, - tx: Option>, - cts: Option>, - _phantom: PhantomData, -} - -impl<'d, M: Mode> SetConfig for UartTx<'d, M> { - type Config = Config; - type ConfigError = ConfigError; - - fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { - reconfigure(self.info, self.state, config) - } -} - -impl<'d> UartTx<'d, Blocking> { - /// Create a new blocking tx-only UART with no hardware flow control. - /// - /// Useful if you only want Uart Tx. It saves 1 pin. - pub fn new_blocking( - peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, - config: Config, - ) -> Result { - Self::new_inner(peri, new_pin!(tx, config.tx_pf()), None, config) - } - - /// Create a new blocking tx-only UART with a clear-to-send pin - pub fn new_blocking_with_cts( - peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, - cts: Peri<'d, impl CtsPin>, - config: Config, - ) -> Result { - Self::new_inner( - peri, - new_pin!(tx, config.tx_pf()), - new_pin!(cts, config.cts_pf()), - config, - ) - } -} - -impl<'d, M: Mode> UartTx<'d, M> { - /// Reconfigure the driver - pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { - if let Some(ref tx) = self.tx { - tx.update_pf(config.tx_pf()); - } - - if let Some(ref cts) = self.cts { - cts.update_pf(config.cts_pf()); - } - - reconfigure(self.info, self.state, config) - } - - /// Perform a blocking UART write - pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { - let r = self.info.regs; - - for &b in buffer { - // Wait if there is no space - while !r.stat().read().txfe() {} - - // Prevent the compiler from writing to buffer too early - compiler_fence(Ordering::Release); - r.txdata().write(|w| { - w.set_data(b); - }); - } - - Ok(()) - } - - /// Block until transmission complete - pub fn blocking_flush(&mut self) -> Result<(), Error> { - let r = self.info.regs; - - // Wait until TX fifo/buffer is empty - while r.stat().read().txfe() {} - Ok(()) - } - - /// Send break character - pub fn send_break(&self) { - let r = self.info.regs; - - r.lcrh().modify(|w| { - w.set_brk(true); - }); - } - - /// Set baudrate - pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError> { - set_baudrate(&self.info, self.state.clock.load(Ordering::Relaxed), baudrate) - } -} - -impl<'d, M: Mode> Drop for UartTx<'d, M> { - fn drop(&mut self) { - self.tx.as_ref().map(|x| x.set_as_disconnected()); - self.cts.as_ref().map(|x| x.set_as_disconnected()); - } -} - -impl<'d> Uart<'d, Blocking> { - /// Create a new blocking bidirectional UART. - pub fn new_blocking( - peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, - config: Config, - ) -> Result { - Self::new_inner( - peri, - new_pin!(rx, config.rx_pf()), - new_pin!(tx, config.tx_pf()), - None, - None, - config, - ) - } - - /// Create a new bidirectional UART with request-to-send and clear-to-send pins - pub fn new_blocking_with_rtscts( - peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, - rts: Peri<'d, impl RtsPin>, - cts: Peri<'d, impl CtsPin>, - config: Config, - ) -> Result { - Self::new_inner( - peri, - new_pin!(rx, config.rx_pf()), - new_pin!(tx, config.tx_pf()), - new_pin!(rts, config.rts_pf()), - new_pin!(cts, config.cts_pf()), - config, - ) - } -} - -impl<'d, M: Mode> Uart<'d, M> { - /// Perform a blocking write - pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { - self.tx.blocking_write(buffer) - } - - /// Block until transmission complete - pub fn blocking_flush(&mut self) -> Result<(), Error> { - self.tx.blocking_flush() - } - - /// Perform a blocking read into `buffer` - pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { - self.rx.blocking_read(buffer) - } - - /// Split the Uart into a transmitter and receiver, which is - /// particularly useful when having two tasks correlating to - /// transmitting and receiving. - pub fn split(self) -> (UartTx<'d, M>, UartRx<'d, M>) { - (self.tx, self.rx) - } - - /// Split the Uart into a transmitter and receiver by mutable reference, - /// which is particularly useful when having two tasks correlating to - /// transmitting and receiving. - pub fn split_ref(&mut self) -> (&mut UartTx<'d, M>, &mut UartRx<'d, M>) { - (&mut self.tx, &mut self.rx) - } - - /// Send break character - pub fn send_break(&self) { - self.tx.send_break(); - } - - /// Set baudrate - pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError> { - set_baudrate(&self.tx.info, self.tx.state.clock.load(Ordering::Relaxed), baudrate) - } -} - -/// Peripheral instance trait. -#[allow(private_bounds)] -pub trait Instance: SealedInstance + PeripheralType { - type Interrupt: crate::interrupt::typelevel::Interrupt; -} - -/// UART `TX` pin trait -pub trait TxPin: crate::gpio::Pin { - /// Get the PF number needed to use this pin as `TX`. - fn pf_num(&self) -> u8; -} - -/// UART `RX` pin trait -pub trait RxPin: crate::gpio::Pin { - /// Get the PF number needed to use this pin as `RX`. - fn pf_num(&self) -> u8; -} - -/// UART `CTS` pin trait -pub trait CtsPin: crate::gpio::Pin { - /// Get the PF number needed to use this pin as `CTS`. - fn pf_num(&self) -> u8; -} - -/// UART `RTS` pin trait -pub trait RtsPin: crate::gpio::Pin { - /// Get the PF number needed to use this pin as `RTS`. - fn pf_num(&self) -> u8; -} - -// ==== IMPL types ==== - -pub(crate) struct Info { - pub(crate) regs: Regs, - pub(crate) interrupt: Interrupt, -} - -pub(crate) struct State { - /// The clock rate of the UART. This might be configured. - pub(crate) clock: AtomicU32, -} - -impl<'d, M: Mode> UartRx<'d, M> { - fn new_inner( - _peri: Peri<'d, T>, - rx: Option>, - rts: Option>, - config: Config, - ) -> Result { - let mut this = Self { - info: T::info(), - state: T::state(), - rx, - rts, - _phantom: PhantomData, - }; - this.enable_and_configure(&config)?; - - Ok(this) - } - - fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { - let info = self.info; - - enable(info.regs); - configure(info, self.state, config, true, self.rts.is_some(), false, false)?; - - Ok(()) - } -} - -impl<'d, M: Mode> UartTx<'d, M> { - fn new_inner( - _peri: Peri<'d, T>, - tx: Option>, - cts: Option>, - config: Config, - ) -> Result { - let mut this = Self { - info: T::info(), - state: T::state(), - tx, - cts, - _phantom: PhantomData, - }; - this.enable_and_configure(&config)?; - - Ok(this) - } - - fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { - let info = self.info; - let state = self.state; - - enable(info.regs); - configure(info, state, config, false, false, true, self.cts.is_some())?; - - Ok(()) - } -} - -impl<'d, M: Mode> Uart<'d, M> { - fn new_inner( - _peri: Peri<'d, T>, - rx: Option>, - tx: Option>, - rts: Option>, - cts: Option>, - config: Config, - ) -> Result { - let info = T::info(); - let state = T::state(); - - let mut this = Self { - tx: UartTx { - info, - state, - tx, - cts, - _phantom: PhantomData, - }, - rx: UartRx { - info, - state, - rx, - rts, - _phantom: PhantomData, - }, - }; - this.enable_and_configure(&config)?; - - Ok(this) - } - - fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { - let info = self.rx.info; - let state = self.rx.state; - - enable(info.regs); - configure( - info, - state, - config, - true, - self.rx.rts.is_some(), - true, - self.tx.cts.is_some(), - )?; - - info.interrupt.unpend(); - unsafe { info.interrupt.enable() }; - - Ok(()) - } -} - -impl Config { - fn tx_pf(&self) -> PfType { - PfType::output(self.tx_pull, self.invert_tx) - } - - fn rx_pf(&self) -> PfType { - PfType::input(self.rx_pull, self.invert_rx) - } - - fn rts_pf(&self) -> PfType { - PfType::output(self.rts_pull, self.invert_rts) - } - - fn cts_pf(&self) -> PfType { - PfType::input(self.rts_pull, self.invert_rts) - } -} - -fn enable(regs: Regs) { - let gprcm = regs.gprcm(0); - - gprcm.rstctl().write(|w| { - w.set_resetstkyclr(true); - w.set_resetassert(true); - w.set_key(vals::ResetKey::KEY); - }); - - gprcm.pwren().write(|w| { - w.set_enable(true); - w.set_key(vals::PwrenKey::KEY); - }); -} - -fn configure( - info: &Info, - state: &State, - config: &Config, - enable_rx: bool, - enable_rts: bool, - enable_tx: bool, - enable_cts: bool, -) -> Result<(), ConfigError> { - let r = info.regs; - - if !enable_rx && !enable_tx { - return Err(ConfigError::RxOrTxNotEnabled); - } - - // SLAU846B says that clocks should be enabled before disabling the uart. - r.clksel().write(|w| match config.clock_source { - ClockSel::LfClk => { - w.set_lfclk_sel(true); - w.set_mfclk_sel(false); - w.set_busclk_sel(false); - } - ClockSel::MfClk => { - w.set_mfclk_sel(true); - w.set_lfclk_sel(false); - w.set_busclk_sel(false); - } - }); - - let clock = match config.clock_source { - ClockSel::LfClk => 32768, - ClockSel::MfClk => 4_000_000, - }; - - state.clock.store(clock, Ordering::Relaxed); - - info.regs.ctl0().modify(|w| { - w.set_lbe(config.loop_back_enable); - w.set_rxe(enable_rx); - w.set_txe(enable_tx); - // RXD_OUT_EN and TXD_OUT_EN? - w.set_menc(false); - w.set_mode(vals::Mode::UART); - w.set_rtsen(enable_rts); - w.set_ctsen(enable_cts); - // oversampling is set later - // TODO: config - w.set_fen(false); - // TODO: config - w.set_majvote(false); - w.set_msbfirst(matches!(config.msb_order, BitOrder::MsbFirst)); - }); - - info.regs.lcrh().modify(|w| { - let eps = if matches!(config.parity, Parity::ParityEven) { - vals::Eps::EVEN - } else { - vals::Eps::ODD - }; - - let wlen = match config.data_bits { - DataBits::DataBits5 => vals::Wlen::DATABIT5, - DataBits::DataBits6 => vals::Wlen::DATABIT6, - DataBits::DataBits7 => vals::Wlen::DATABIT7, - DataBits::DataBits8 => vals::Wlen::DATABIT8, - }; - - // Used in LIN mode only - w.set_brk(false); - w.set_pen(config.parity != Parity::ParityNone); - w.set_eps(eps); - w.set_stp2(matches!(config.stop_bits, StopBits::Stop2)); - w.set_wlen(wlen); - // appears to only be used in RS-485 mode. - w.set_sps(false); - // IDLE pattern? - w.set_sendidle(false); - // ignore extdir_setup and extdir_hold, only used in RS-485 mode. - }); - - set_baudrate_inner(info.regs, clock, config.baudrate)?; - - r.ctl0().modify(|w| { - w.set_enable(true); - }); - - Ok(()) -} - -fn reconfigure(info: &Info, state: &State, config: &Config) -> Result<(), ConfigError> { - info.interrupt.disable(); - let r = info.regs; - let ctl0 = r.ctl0().read(); - configure(info, state, config, ctl0.rxe(), ctl0.rtsen(), ctl0.txe(), ctl0.ctsen())?; - - info.interrupt.unpend(); - unsafe { info.interrupt.enable() }; - - Ok(()) -} - -/// Set the baud rate and clock settings. -/// -/// This should be done relatively late during configuration since some clock settings are invalid depending on mode. -fn set_baudrate(info: &Info, clock: u32, baudrate: u32) -> Result<(), ConfigError> { - let r = info.regs; - - info.interrupt.disable(); - - // Programming baud rate requires that the peripheral is disabled - critical_section::with(|_cs| { - r.ctl0().modify(|w| { - w.set_enable(false); - }); - }); - - // Wait for end of transmission per suggestion in SLAU 845 section 18.3.28 - while !r.stat().read().txfe() {} - - set_baudrate_inner(r, clock, baudrate)?; - - critical_section::with(|_cs| { - r.ctl0().modify(|w| { - w.set_enable(true); - }); - }); - - info.interrupt.unpend(); - unsafe { info.interrupt.enable() }; - - Ok(()) -} - -fn set_baudrate_inner(regs: Regs, clock: u32, baudrate: u32) -> Result<(), ConfigError> { - // Quoting SLAU846 section 18.2.3.4: - // "When IBRD = 0, FBRD is ignored and no data gets transferred by the UART." - const MIN_IBRD: u16 = 1; - - // FBRD can be 0 - // FBRD is at most a 6-bit number. - const MAX_FBRD: u8 = 2_u8.pow(6); - - const DIVS: [(u8, vals::Clkdiv); 8] = [ - (1, vals::Clkdiv::DIV_BY_1), - (2, vals::Clkdiv::DIV_BY_2), - (3, vals::Clkdiv::DIV_BY_3), - (4, vals::Clkdiv::DIV_BY_4), - (5, vals::Clkdiv::DIV_BY_5), - (6, vals::Clkdiv::DIV_BY_6), - (7, vals::Clkdiv::DIV_BY_7), - (8, vals::Clkdiv::DIV_BY_8), - ]; - - // Quoting from SLAU 846 section 18.2.3.4: - // "Select oversampling by 3 or 8 to achieve higher speed with UARTclk/8 or UARTclk/3. In this case - // the receiver tolerance to clock deviation is reduced." - // - // "Select oversampling by 16 to increase the tolerance of the receiver to clock deviations. The - // maximum speed is limited to UARTclk/16." - // - // Based on these requirements, prioritize higher oversampling first to increase tolerance to clock - // deviation. If no valid BRD value can be found satisifying the highest sample rate, then reduce - // sample rate until valid parameters are found. - const OVS: [(u8, vals::Hse); 3] = [(16, vals::Hse::OVS16), (8, vals::Hse::OVS8), (3, vals::Hse::OVS3)]; - - // 3x oversampling is not supported with manchester coding, DALI or IrDA. - let x3_invalid = { - let ctl0 = regs.ctl0().read(); - let irctl = regs.irctl().read(); - - ctl0.menc() || matches!(ctl0.mode(), vals::Mode::DALI) || irctl.iren() - }; - let mut found = None; - - 'outer: for &(oversampling, hse_value) in &OVS { - if matches!(hse_value, vals::Hse::OVS3) && x3_invalid { - continue; - } - - // Verify that the selected oversampling does not require a clock faster than what the hardware - // is provided. - let Some(min_clock) = baudrate.checked_mul(oversampling as u32) else { - trace!( - "{}x oversampling would cause overflow for clock: {} Hz", - oversampling, - clock - ); - continue; - }; - - if min_clock > clock { - trace!("{} oversampling is too high for clock: {} Hz", oversampling, clock); - continue; - } - - for &(div, div_value) in &DIVS { - trace!( - "Trying div: {}, oversampling {} for {} baud", - div, - oversampling, - baudrate - ); - - let Some((ibrd, fbrd)) = calculate_brd(clock, div, baudrate, oversampling) else { - trace!("Calculating BRD overflowed: trying another divider"); - continue; - }; - - if ibrd < MIN_IBRD || fbrd > MAX_FBRD { - trace!("BRD was invalid: trying another divider"); - continue; - } - - found = Some((hse_value, div_value, ibrd, fbrd)); - break 'outer; - } - } - - let Some((hse, div, ibrd, fbrd)) = found else { - return Err(ConfigError::InvalidBaudRate); - }; - - regs.clkdiv().write(|w| { - w.set_ratio(div); - }); - - regs.ibrd().write(|w| { - w.set_divint(ibrd); - }); - - regs.fbrd().write(|w| { - w.set_divfrac(fbrd); - }); - - regs.ctl0().modify(|w| { - w.set_hse(hse); - }); - - Ok(()) -} - -/// Calculate the integer and fractional parts of the `BRD` value. -/// -/// Returns [`None`] if calculating this results in overflows. -/// -/// Values returned are `(ibrd, fbrd)` -fn calculate_brd(clock: u32, div: u8, baud: u32, oversampling: u8) -> Option<(u16, u8)> { - use fixed::types::U26F6; - - // Calculate BRD according to SLAU 846 section 18.2.3.4. - // - // BRD is a 22-bit value with 16 integer bits and 6 fractional bits. - // - // uart_clock = clock / div - // brd = ibrd.fbrd = uart_clock / (oversampling * baud)" - // - // It is tempting to rearrange the equation such that there is only a single division in - // order to reduce error. However this is wrong since the denominator ends up being too - // small to represent in 6 fraction bits. This means that FBRD would always be 0. - // - // Calculations are done in a U16F6 format. However the fixed crate has no such representation. - // U26F6 is used since it has the same number of fractional bits and we verify at the end that - // the integer part did not overflow. - let clock = U26F6::from_num(clock); - let div = U26F6::from_num(div); - let oversampling = U26F6::from_num(oversampling); - let baud = U26F6::from_num(baud); - - let uart_clock = clock.checked_div(div)?; - - // oversampling * baud - let denom = oversampling.checked_mul(baud)?; - // uart_clock / (oversampling * baud) - let brd = uart_clock.checked_div(denom)?; - - // Checked is used to determine overflow in the 10 most singificant bits since the - // actual representation of BRD is U16F6. - let ibrd = brd.checked_to_num::()?; - - // We need to scale FBRD's representation to an integer. - let fbrd_scale = U26F6::from_num(2_u32.checked_pow(U26F6::FRAC_NBITS)?); - - // It is suggested that 0.5 is added to ensure that any fractional parts round up to the next - // integer. If it doesn't round up then it'll get discarded which is okay. - let half = U26F6::from_num(1) / U26F6::from_num(2); - // fbrd = INT(((FRAC(BRD) * 64) + 0.5)) - let fbrd = brd - .frac() - .checked_mul(fbrd_scale)? - .checked_add(half)? - .checked_to_num::()?; - - Some((ibrd, fbrd)) -} - -fn read_with_error(r: Regs) -> Result { - let rx = r.rxdata().read(); - - if rx.frmerr() { - return Err(Error::Framing); - } else if rx.parerr() { - return Err(Error::Parity); - } else if rx.brkerr() { - return Err(Error::Break); - } else if rx.ovrerr() { - return Err(Error::Overrun); - } else if rx.nerr() { - return Err(Error::Noise); - } - - Ok(rx.data()) -} - -pub(crate) trait SealedInstance { - fn info() -> &'static Info; - fn state() -> &'static State; -} - -macro_rules! impl_uart_instance { - ($instance: ident) => { - impl crate::uart::SealedInstance for crate::peripherals::$instance { - fn info() -> &'static crate::uart::Info { - use crate::interrupt::typelevel::Interrupt; - use crate::uart::Info; - - const INFO: Info = Info { - regs: crate::pac::$instance, - interrupt: crate::interrupt::typelevel::$instance::IRQ, - }; - &INFO - } - - fn state() -> &'static crate::uart::State { - use crate::interrupt::typelevel::Interrupt; - use crate::uart::State; - - static STATE: State = State { - clock: core::sync::atomic::AtomicU32::new(0), - }; - &STATE - } - } - - impl crate::uart::Instance for crate::peripherals::$instance { - type Interrupt = crate::interrupt::typelevel::$instance; - } - }; -} - -macro_rules! impl_uart_tx_pin { - ($instance: ident, $pin: ident, $pf: expr) => { - impl crate::uart::TxPin for crate::peripherals::$pin { - fn pf_num(&self) -> u8 { - $pf - } - } - }; -} - -macro_rules! impl_uart_rx_pin { - ($instance: ident, $pin: ident, $pf: expr) => { - impl crate::uart::RxPin for crate::peripherals::$pin { - fn pf_num(&self) -> u8 { - $pf - } - } - }; -} - -macro_rules! impl_uart_cts_pin { - ($instance: ident, $pin: ident, $pf: expr) => { - impl crate::uart::CtsPin for crate::peripherals::$pin { - fn pf_num(&self) -> u8 { - $pf - } - } - }; -} - -macro_rules! impl_uart_rts_pin { - ($instance: ident, $pin: ident, $pf: expr) => { - impl crate::uart::RtsPin for crate::peripherals::$pin { - fn pf_num(&self) -> u8 { - $pf - } - } - }; -} - -#[cfg(test)] -mod tests { - use super::calculate_brd; - - /// This is a smoke test based on the example in SLAU 846 section 18.2.3.4. - #[test] - fn datasheet() { - let brd = calculate_brd(40_000_000, 1, 19200, 16); - - assert!(matches!(brd, Some((130, 13)))); - } -} diff --git a/embassy-mspm0/src/uart/buffered.rs b/embassy-mspm0/src/uart/buffered.rs new file mode 100644 index 000000000..cbc0b6c80 --- /dev/null +++ b/embassy-mspm0/src/uart/buffered.rs @@ -0,0 +1,1060 @@ +use core::future::{poll_fn, Future}; +use core::marker::PhantomData; +use core::slice; +use core::sync::atomic::{AtomicU8, Ordering}; +use core::task::Poll; + +use embassy_embedded_hal::SetConfig; +use embassy_hal_internal::atomic_ring_buffer::RingBuffer; +use embassy_hal_internal::interrupt::InterruptExt; +use embassy_sync::waitqueue::AtomicWaker; +use embedded_hal_nb::nb; + +use crate::gpio::{AnyPin, SealedPin}; +use crate::interrupt::typelevel::Binding; +use crate::pac::uart::Uart as Regs; +use crate::uart::{Config, ConfigError, CtsPin, Error, Info, Instance, RtsPin, RxPin, State, TxPin}; +use crate::{interrupt, Peri}; + +/// Interrupt handler. +pub struct BufferedInterruptHandler { + _uart: PhantomData, +} + +impl interrupt::typelevel::Handler for BufferedInterruptHandler { + unsafe fn on_interrupt() { + on_interrupt(T::info().regs, T::buffered_state()) + } +} + +/// Bidirectional buffered UART which acts as a combination of [`BufferedUartTx`] and [`BufferedUartRx`]. +pub struct BufferedUart<'d> { + rx: BufferedUartRx<'d>, + tx: BufferedUartTx<'d>, +} + +impl SetConfig for BufferedUart<'_> { + type Config = Config; + type ConfigError = ConfigError; + + fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { + self.set_config(config) + } +} + +impl<'d> BufferedUart<'d> { + /// Create a new bidirectional buffered UART. + pub fn new( + uart: Peri<'d, T>, + tx: Peri<'d, impl TxPin>, + rx: Peri<'d, impl RxPin>, + _irq: impl Binding>, + tx_buffer: &'d mut [u8], + rx_buffer: &'d mut [u8], + config: Config, + ) -> Result { + Self::new_inner( + uart, + new_pin!(rx, config.rx_pf()), + new_pin!(tx, config.tx_pf()), + None, + None, + tx_buffer, + rx_buffer, + config, + ) + } + + /// Create a new bidirectional buffered UART with request-to-send and clear-to-send pins + pub fn new_with_rtscts( + uart: Peri<'d, T>, + tx: Peri<'d, impl TxPin>, + rx: Peri<'d, impl RxPin>, + rts: Peri<'d, impl RtsPin>, + cts: Peri<'d, impl CtsPin>, + _irq: impl Binding>, + tx_buffer: &'d mut [u8], + rx_buffer: &'d mut [u8], + config: Config, + ) -> Result { + Self::new_inner( + uart, + new_pin!(rx, config.rx_pf()), + new_pin!(tx, config.tx_pf()), + new_pin!(rts, config.rts_pf()), + new_pin!(cts, config.cts_pf()), + tx_buffer, + rx_buffer, + config, + ) + } + + /// Reconfigure the driver + pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { + self.tx.set_config(config)?; + self.rx.set_config(config) + } + + /// Set baudrate + pub fn set_baudrate(&mut self, baudrate: u32) -> Result<(), ConfigError> { + self.rx.set_baudrate(baudrate) + } + + /// Write to UART TX buffer, blocking execution until done. + pub fn blocking_write(&mut self, buffer: &[u8]) -> Result { + self.tx.blocking_write(buffer) + } + + /// Flush UART TX buffer, blocking execution until done. + pub fn blocking_flush(&mut self) -> Result<(), Error> { + self.tx.blocking_flush() + } + + /// Check if UART is busy. + pub fn busy(&self) -> bool { + self.tx.busy() + } + + /// Read from UART RX buffer, blocking execution until done. + pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result { + self.rx.blocking_read(buffer) + } + + /// Send break character. + pub fn send_break(&mut self) { + self.tx.send_break() + } + + /// Split into separate RX and TX handles. + pub fn split(self) -> (BufferedUartTx<'d>, BufferedUartRx<'d>) { + (self.tx, self.rx) + } + + /// Split into separate RX and TX handles. + pub fn split_ref(&mut self) -> (BufferedUartTx<'_>, BufferedUartRx<'_>) { + ( + BufferedUartTx { + info: self.tx.info, + state: self.tx.state, + tx: self.tx.tx.as_mut().map(Peri::reborrow), + cts: self.tx.cts.as_mut().map(Peri::reborrow), + reborrowed: true, + }, + BufferedUartRx { + info: self.rx.info, + state: self.rx.state, + rx: self.rx.rx.as_mut().map(Peri::reborrow), + rts: self.rx.rts.as_mut().map(Peri::reborrow), + reborrowed: true, + }, + ) + } +} + +/// Rx-only buffered UART. +/// +/// Can be obtained from [`BufferedUart::split`], or can be constructed independently, +/// if you do not need the transmitting half of the driver. +pub struct BufferedUartRx<'d> { + info: &'static Info, + state: &'static BufferedState, + rx: Option>, + rts: Option>, + reborrowed: bool, +} + +impl SetConfig for BufferedUartRx<'_> { + type Config = Config; + type ConfigError = ConfigError; + + fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { + self.set_config(config) + } +} + +impl<'d> BufferedUartRx<'d> { + /// Create a new rx-only buffered UART with no hardware flow control. + /// + /// Useful if you only want Uart Rx. It saves 1 pin. + pub fn new( + uart: Peri<'d, T>, + rx: Peri<'d, impl RxPin>, + _irq: impl Binding>, + rx_buffer: &'d mut [u8], + config: Config, + ) -> Result { + Self::new_inner(uart, new_pin!(rx, config.rx_pf()), None, rx_buffer, config) + } + + /// Create a new rx-only buffered UART with a request-to-send pin + pub fn new_with_rts( + uart: Peri<'d, T>, + rx: Peri<'d, impl RxPin>, + rts: Peri<'d, impl RtsPin>, + _irq: impl Binding>, + rx_buffer: &'d mut [u8], + config: Config, + ) -> Result { + Self::new_inner( + uart, + new_pin!(rx, config.rx_pf()), + new_pin!(rts, config.rts_pf()), + rx_buffer, + config, + ) + } + + /// Reconfigure the driver + pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { + if let Some(ref rx) = self.rx { + rx.update_pf(config.rx_pf()); + } + + if let Some(ref rts) = self.rts { + rts.update_pf(config.rts_pf()); + } + + super::reconfigure(&self.info, &self.state.state, config) + } + + /// Set baudrate + pub fn set_baudrate(&mut self, baudrate: u32) -> Result<(), ConfigError> { + super::set_baudrate(&self.info, self.state.state.clock.load(Ordering::Relaxed), baudrate) + } + + /// Read from UART RX buffer, blocking execution until done. + pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result { + self.blocking_read_inner(buffer) + } +} + +impl Drop for BufferedUartRx<'_> { + fn drop(&mut self) { + if !self.reborrowed { + let state = self.state; + + // SAFETY: RX is being dropped (and is not reborrowed), so the ring buffer must be deinitialized + // in order to meet the requirements of init. + unsafe { + state.rx_buf.deinit(); + } + + // TX is inactive if the buffer is not available. If this is true, then disable the + // interrupt handler since we are running in RX only mode. + if state.tx_buf.len() == 0 { + self.info.interrupt.disable(); + } + + self.rx.as_ref().map(|x| x.set_as_disconnected()); + self.rts.as_ref().map(|x| x.set_as_disconnected()); + } + } +} + +/// Tx-only buffered UART. +/// +/// Can be obtained from [`BufferedUart::split`], or can be constructed independently, +/// if you do not need the receiving half of the driver. +pub struct BufferedUartTx<'d> { + info: &'static Info, + state: &'static BufferedState, + tx: Option>, + cts: Option>, + reborrowed: bool, +} + +impl SetConfig for BufferedUartTx<'_> { + type Config = Config; + type ConfigError = ConfigError; + + fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { + self.set_config(config) + } +} + +impl<'d> BufferedUartTx<'d> { + /// Create a new tx-only buffered UART with no hardware flow control. + /// + /// Useful if you only want Uart Tx. It saves 1 pin. + pub fn new( + uart: Peri<'d, T>, + tx: Peri<'d, impl TxPin>, + _irq: impl Binding>, + tx_buffer: &'d mut [u8], + config: Config, + ) -> Result { + Self::new_inner(uart, new_pin!(tx, config.tx_pf()), None, tx_buffer, config) + } + + /// Create a new tx-only buffered UART with a clear-to-send pin + pub fn new_with_rts( + uart: Peri<'d, T>, + tx: Peri<'d, impl TxPin>, + cts: Peri<'d, impl CtsPin>, + _irq: impl Binding>, + tx_buffer: &'d mut [u8], + config: Config, + ) -> Result { + Self::new_inner( + uart, + new_pin!(tx, config.tx_pf()), + new_pin!(cts, config.cts_pf()), + tx_buffer, + config, + ) + } + + /// Reconfigure the driver + pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { + if let Some(ref tx) = self.tx { + tx.update_pf(config.tx_pf()); + } + + if let Some(ref cts) = self.cts { + cts.update_pf(config.cts_pf()); + } + + super::reconfigure(self.info, &self.state.state, config) + } + + /// Set baudrate + pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError> { + super::set_baudrate(&self.info, self.state.state.clock.load(Ordering::Relaxed), baudrate) + } + + /// Write to UART TX buffer, blocking execution until done. + pub fn blocking_write(&mut self, buffer: &[u8]) -> Result { + self.blocking_write_inner(buffer) + } + + /// Flush UART TX buffer, blocking execution until done. + pub fn blocking_flush(&mut self) -> Result<(), Error> { + let state = self.state; + + loop { + if state.tx_buf.is_empty() { + return Ok(()); + } + } + } + + /// Check if UART is busy. + pub fn busy(&self) -> bool { + super::busy(self.info.regs) + } + + /// Send break character + pub fn send_break(&mut self) { + let r = self.info.regs; + + r.lcrh().modify(|w| { + w.set_brk(true); + }); + } +} + +impl Drop for BufferedUartTx<'_> { + fn drop(&mut self) { + if !self.reborrowed { + let state = self.state; + + // SAFETY: TX is being dropped (and is not reborrowed), so the ring buffer must be deinitialized + // in order to meet the requirements of init. + unsafe { + state.tx_buf.deinit(); + } + + // RX is inactive if the buffer is not available. If this is true, then disable the + // interrupt handler since we are running in TX only mode. + if state.rx_buf.len() == 0 { + self.info.interrupt.disable(); + } + + self.tx.as_ref().map(|x| x.set_as_disconnected()); + self.cts.as_ref().map(|x| x.set_as_disconnected()); + } + } +} + +impl embedded_io_async::ErrorType for BufferedUart<'_> { + type Error = Error; +} + +impl embedded_io_async::ErrorType for BufferedUartRx<'_> { + type Error = Error; +} + +impl embedded_io_async::ErrorType for BufferedUartTx<'_> { + type Error = Error; +} + +impl embedded_io_async::Read for BufferedUart<'_> { + async fn read(&mut self, buf: &mut [u8]) -> Result { + self.rx.read(buf).await + } +} + +impl embedded_io_async::Read for BufferedUartRx<'_> { + async fn read(&mut self, buf: &mut [u8]) -> Result { + self.read_inner(buf).await + } +} + +impl embedded_io_async::ReadReady for BufferedUart<'_> { + fn read_ready(&mut self) -> Result { + self.rx.read_ready() + } +} + +impl embedded_io_async::ReadReady for BufferedUartRx<'_> { + fn read_ready(&mut self) -> Result { + self.read_ready_inner() + } +} + +impl embedded_io_async::BufRead for BufferedUart<'_> { + async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { + self.rx.fill_buf().await + } + + fn consume(&mut self, amt: usize) { + self.rx.consume(amt); + } +} + +impl embedded_io_async::BufRead for BufferedUartRx<'_> { + async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { + self.fill_buf_inner().await + } + + fn consume(&mut self, amt: usize) { + self.consume_inner(amt); + } +} + +impl embedded_io_async::Write for BufferedUart<'_> { + async fn write(&mut self, buf: &[u8]) -> Result { + self.tx.write_inner(buf).await + } +} + +impl embedded_io_async::Write for BufferedUartTx<'_> { + async fn write(&mut self, buf: &[u8]) -> Result { + self.write_inner(buf).await + } + + async fn flush(&mut self) -> Result<(), Self::Error> { + self.flush_inner().await + } +} + +impl embedded_io::Read for BufferedUart<'_> { + fn read(&mut self, buf: &mut [u8]) -> Result { + self.rx.read(buf) + } +} + +impl embedded_io::Read for BufferedUartRx<'_> { + fn read(&mut self, buf: &mut [u8]) -> Result { + self.blocking_read_inner(buf) + } +} + +impl embedded_io::Write for BufferedUart<'_> { + fn write(&mut self, buf: &[u8]) -> Result { + self.tx.write(buf) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + self.tx.flush() + } +} + +impl embedded_io::Write for BufferedUartTx<'_> { + fn write(&mut self, buf: &[u8]) -> Result { + self.blocking_write_inner(buf) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + self.blocking_flush() + } +} + +impl embedded_hal_nb::serial::Error for Error { + fn kind(&self) -> embedded_hal_nb::serial::ErrorKind { + match self { + Error::Framing => embedded_hal_nb::serial::ErrorKind::FrameFormat, + Error::Noise => embedded_hal_nb::serial::ErrorKind::Noise, + Error::Overrun => embedded_hal_nb::serial::ErrorKind::Overrun, + Error::Parity => embedded_hal_nb::serial::ErrorKind::Parity, + Error::Break => embedded_hal_nb::serial::ErrorKind::Other, + } + } +} + +impl embedded_hal_nb::serial::ErrorType for BufferedUart<'_> { + type Error = Error; +} + +impl embedded_hal_nb::serial::ErrorType for BufferedUartRx<'_> { + type Error = Error; +} + +impl embedded_hal_nb::serial::ErrorType for BufferedUartTx<'_> { + type Error = Error; +} + +impl embedded_hal_nb::serial::Read for BufferedUart<'_> { + fn read(&mut self) -> nb::Result { + self.rx.read() + } +} + +impl embedded_hal_nb::serial::Read for BufferedUartRx<'_> { + fn read(&mut self) -> nb::Result { + if self.info.regs.stat().read().rxfe() { + return Err(nb::Error::WouldBlock); + } + + super::read_with_error(self.info.regs).map_err(nb::Error::Other) + } +} + +impl embedded_hal_nb::serial::Write for BufferedUart<'_> { + fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { + self.tx.write(word) + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + self.tx.flush() + } +} + +impl embedded_hal_nb::serial::Write for BufferedUartTx<'_> { + fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { + self.blocking_write(&[word]).map(drop).map_err(nb::Error::Other) + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + self.blocking_flush().map_err(nb::Error::Other) + } +} + +// Impl details + +/// Buffered UART state. +pub(crate) struct BufferedState { + /// non-buffered UART state. This is inline in order to avoid [`BufferedUartRx`]/Tx + /// needing to carry around a 2nd static reference and waste another 4 bytes. + state: State, + rx_waker: AtomicWaker, + rx_buf: RingBuffer, + tx_waker: AtomicWaker, + tx_buf: RingBuffer, + rx_error: AtomicU8, +} + +// these must match bits 8..12 in RXDATA, but shifted by 8 to the right +const RXE_NOISE: u8 = 16; +const RXE_OVERRUN: u8 = 8; +const RXE_BREAK: u8 = 4; +const RXE_PARITY: u8 = 2; +const RXE_FRAMING: u8 = 1; + +impl BufferedState { + pub const fn new() -> Self { + Self { + state: State::new(), + rx_waker: AtomicWaker::new(), + rx_buf: RingBuffer::new(), + tx_waker: AtomicWaker::new(), + tx_buf: RingBuffer::new(), + rx_error: AtomicU8::new(0), + } + } +} + +impl<'d> BufferedUart<'d> { + fn new_inner( + _peri: Peri<'d, T>, + rx: Option>, + tx: Option>, + rts: Option>, + cts: Option>, + tx_buffer: &'d mut [u8], + rx_buffer: &'d mut [u8], + config: Config, + ) -> Result { + let info = T::info(); + let state = T::buffered_state(); + + let mut this = Self { + tx: BufferedUartTx { + info, + state, + tx, + cts, + reborrowed: false, + }, + rx: BufferedUartRx { + info, + state, + rx, + rts, + reborrowed: false, + }, + }; + this.enable_and_configure(tx_buffer, rx_buffer, &config)?; + + Ok(this) + } + + fn enable_and_configure( + &mut self, + tx_buffer: &'d mut [u8], + rx_buffer: &'d mut [u8], + config: &Config, + ) -> Result<(), ConfigError> { + let info = self.rx.info; + let state = self.rx.state; + + assert!(!tx_buffer.is_empty()); + assert!(!rx_buffer.is_empty()); + + init_buffers(info, state, Some(tx_buffer), Some(rx_buffer)); + super::enable(info.regs); + super::configure( + info, + &state.state, + config, + true, + self.rx.rts.is_some(), + true, + self.tx.cts.is_some(), + )?; + + info.interrupt.unpend(); + unsafe { info.interrupt.enable() }; + + Ok(()) + } +} + +impl<'d> BufferedUartRx<'d> { + fn new_inner( + _peri: Peri<'d, T>, + rx: Option>, + rts: Option>, + rx_buffer: &'d mut [u8], + config: Config, + ) -> Result { + let mut this = Self { + info: T::info(), + state: T::buffered_state(), + rx, + rts, + reborrowed: false, + }; + this.enable_and_configure(rx_buffer, &config)?; + + Ok(this) + } + + fn enable_and_configure(&mut self, rx_buffer: &'d mut [u8], config: &Config) -> Result<(), ConfigError> { + let info = self.info; + let state = self.state; + + init_buffers(info, state, None, Some(rx_buffer)); + super::enable(info.regs); + super::configure(info, &self.state.state, config, true, self.rts.is_some(), false, false)?; + + info.interrupt.unpend(); + unsafe { info.interrupt.enable() }; + + Ok(()) + } + + async fn read_inner(&self, buf: &mut [u8]) -> Result { + poll_fn(move |cx| { + let state = self.state; + + if let Poll::Ready(r) = self.try_read(buf) { + return Poll::Ready(r); + } + + state.rx_waker.register(cx.waker()); + Poll::Pending + }) + .await + } + + fn blocking_read_inner(&self, buffer: &mut [u8]) -> Result { + loop { + match self.try_read(buffer) { + Poll::Ready(res) => return res, + Poll::Pending => continue, + } + } + } + + fn fill_buf_inner(&self) -> impl Future> { + poll_fn(move |cx| { + let mut rx_reader = unsafe { self.state.rx_buf.reader() }; + let (p, n) = rx_reader.pop_buf(); + let result = if n == 0 { + match Self::get_rx_error(self.state) { + None => { + self.state.rx_waker.register(cx.waker()); + return Poll::Pending; + } + Some(e) => Err(e), + } + } else { + let buf = unsafe { slice::from_raw_parts(p, n) }; + Ok(buf) + }; + + Poll::Ready(result) + }) + } + + fn consume_inner(&self, amt: usize) { + let mut rx_reader = unsafe { self.state.rx_buf.reader() }; + rx_reader.pop_done(amt); + + // (Re-)Enable the interrupt to receive more data in case it was + // disabled because the buffer was full or errors were detected. + self.info.regs.cpu_int(0).imask().modify(|w| { + w.set_rxint(true); + w.set_rtout(true); + }); + } + + /// we are ready to read if there is data in the buffer + fn read_ready_inner(&self) -> Result { + Ok(!self.state.rx_buf.is_empty()) + } + + fn try_read(&self, buf: &mut [u8]) -> Poll> { + let state = self.state; + + if buf.is_empty() { + return Poll::Ready(Ok(0)); + } + + let mut rx_reader = unsafe { state.rx_buf.reader() }; + let n = rx_reader.pop(|data| { + let n = data.len().min(buf.len()); + buf[..n].copy_from_slice(&data[..n]); + n + }); + + let result = if n == 0 { + match Self::get_rx_error(state) { + None => return Poll::Pending, + Some(e) => Err(e), + } + } else { + Ok(n) + }; + + // (Re-)Enable the interrupt to receive more data in case it was + // disabled because the buffer was full or errors were detected. + self.info.regs.cpu_int(0).imask().modify(|w| { + w.set_rxint(true); + w.set_rtout(true); + }); + + Poll::Ready(result) + } + + fn get_rx_error(state: &BufferedState) -> Option { + // Cortex-M0 has does not support atomic swap, so we must do two operations. + let errs = critical_section::with(|_cs| { + let errs = state.rx_error.load(Ordering::Relaxed); + state.rx_error.store(0, Ordering::Relaxed); + + errs + }); + + if errs & RXE_NOISE != 0 { + Some(Error::Noise) + } else if errs & RXE_OVERRUN != 0 { + Some(Error::Overrun) + } else if errs & RXE_BREAK != 0 { + Some(Error::Break) + } else if errs & RXE_PARITY != 0 { + Some(Error::Parity) + } else if errs & RXE_FRAMING != 0 { + Some(Error::Framing) + } else { + None + } + } +} + +impl<'d> BufferedUartTx<'d> { + fn new_inner( + _peri: Peri<'d, T>, + tx: Option>, + cts: Option>, + tx_buffer: &'d mut [u8], + config: Config, + ) -> Result { + let mut this = Self { + info: T::info(), + state: T::buffered_state(), + tx, + cts, + reborrowed: false, + }; + + this.enable_and_configure(tx_buffer, &config)?; + + Ok(this) + } + + async fn write_inner(&self, buf: &[u8]) -> Result { + poll_fn(move |cx| { + let state = self.state; + + if buf.is_empty() { + return Poll::Ready(Ok(0)); + } + + let mut tx_writer = unsafe { state.tx_buf.writer() }; + let n = tx_writer.push(|data| { + let n = data.len().min(buf.len()); + data[..n].copy_from_slice(&buf[..n]); + n + }); + + if n == 0 { + state.tx_waker.register(cx.waker()); + return Poll::Pending; + } + + // The TX interrupt only triggers when the there was data in the + // FIFO and the number of bytes drops below a threshold. When the + // FIFO was empty we have to manually pend the interrupt to shovel + // TX data from the buffer into the FIFO. + self.info.interrupt.pend(); + Poll::Ready(Ok(n)) + }) + .await + } + + fn blocking_write_inner(&self, buffer: &[u8]) -> Result { + let state = self.state; + + loop { + let empty = state.tx_buf.is_empty(); + + // SAFETY: tx buf must be initialized if BufferedUartTx exists. + let mut tx_writer = unsafe { state.tx_buf.writer() }; + let data = tx_writer.push_slice(); + + if !data.is_empty() { + let n = data.len().min(buffer.len()); + data[..n].copy_from_slice(&buffer[..n]); + tx_writer.push_done(n); + + if empty { + self.info.interrupt.pend(); + } + + return Ok(n); + } + } + } + + async fn flush_inner(&self) -> Result<(), Error> { + poll_fn(move |cx| { + let state = self.state; + + if !state.tx_buf.is_empty() { + state.tx_waker.register(cx.waker()); + return Poll::Pending; + } + + Poll::Ready(Ok(())) + }) + .await + } + + fn enable_and_configure(&mut self, tx_buffer: &'d mut [u8], config: &Config) -> Result<(), ConfigError> { + let info = self.info; + let state = self.state; + + init_buffers(info, state, Some(tx_buffer), None); + super::enable(info.regs); + super::configure(info, &state.state, config, false, false, true, self.cts.is_some())?; + + info.interrupt.unpend(); + unsafe { info.interrupt.enable() }; + + Ok(()) + } +} + +fn init_buffers<'d>( + info: &Info, + state: &BufferedState, + tx_buffer: Option<&'d mut [u8]>, + rx_buffer: Option<&'d mut [u8]>, +) { + if let Some(tx_buffer) = tx_buffer { + let len = tx_buffer.len(); + unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; + } + + if let Some(rx_buffer) = rx_buffer { + let len = rx_buffer.len(); + unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; + } + + info.regs.cpu_int(0).imask().modify(|w| { + w.set_nerr(true); + w.set_frmerr(true); + w.set_parerr(true); + w.set_brkerr(true); + w.set_ovrerr(true); + }); +} + +fn on_interrupt(r: Regs, state: &'static BufferedState) { + let int = r.cpu_int(0).mis().read(); + + // Per https://github.com/embassy-rs/embassy/pull/1458, both buffered and unbuffered handlers may be bound. + if super::dma_enabled(r) { + return; + } + + // RX + if state.rx_buf.is_available() { + // SAFETY: RX must have been initialized if RXE is set. + let mut rx_writer = unsafe { state.rx_buf.writer() }; + let rx_buf = rx_writer.push_slice(); + let mut n_read = 0; + let mut error = false; + + for rx_byte in rx_buf { + let stat = r.stat().read(); + + if stat.rxfe() { + break; + } + + let data = r.rxdata().read(); + + if (data.0 >> 8) != 0 { + // Cortex-M0 does not support atomic fetch_or, must do 2 operations. + critical_section::with(|_cs| { + let mut value = state.rx_error.load(Ordering::Relaxed); + value |= (data.0 >> 8) as u8; + state.rx_error.store(value, Ordering::Relaxed); + }); + error = true; + + // only fill the buffer with valid characters. the current character is fine + // if the error is an overrun, but if we add it to the buffer we'll report + // the overrun one character too late. drop it instead and pretend we were + // a bit slower at draining the rx fifo than we actually were. + // this is consistent with blocking uart error reporting. + break; + } + + *rx_byte = data.data(); + n_read += 1; + } + + if n_read > 0 { + rx_writer.push_done(n_read); + state.rx_waker.wake(); + } else if error { + state.rx_waker.wake(); + } + + // Disable any further RX interrupts when the buffer becomes full or + // errors have occurred. This lets us buffer additional errors in the + // fifo without needing more error storage locations, and most applications + // will want to do a full reset of their uart state anyway once an error + // has happened. + if state.rx_buf.is_full() || error { + r.cpu_int(0).imask().modify(|w| { + w.set_rxint(false); + w.set_rtout(false); + }); + } + } + + if int.eot() { + r.cpu_int(0).imask().modify(|w| { + w.set_eot(false); + }); + + r.cpu_int(0).iclr().write(|w| { + w.set_eot(true); + }); + + state.tx_waker.wake(); + } + + // TX + if state.tx_buf.is_available() { + // SAFETY: TX must have been initialized if TXE is set. + let mut tx_reader = unsafe { state.tx_buf.reader() }; + let buf = tx_reader.pop_slice(); + let mut n_written = 0; + + for tx_byte in buf.iter_mut() { + let stat = r.stat().read(); + + if stat.txff() { + break; + } + + r.txdata().write(|w| { + w.set_data(*tx_byte); + }); + n_written += 1; + } + + if n_written > 0 { + // EOT will wake. + r.cpu_int(0).imask().modify(|w| { + w.set_eot(true); + }); + + tx_reader.pop_done(n_written); + } + } + + // Clear TX and error interrupt flags + // RX interrupt flags are cleared by writing to ICLR. + let mis = r.cpu_int(0).mis().read(); + r.cpu_int(0).iclr().write(|w| { + w.set_nerr(mis.nerr()); + w.set_frmerr(mis.frmerr()); + w.set_parerr(mis.parerr()); + w.set_brkerr(mis.brkerr()); + w.set_ovrerr(mis.ovrerr()); + }); + + // Errors + if mis.nerr() { + warn!("Noise error"); + } + if mis.frmerr() { + warn!("Framing error"); + } + if mis.parerr() { + warn!("Parity error"); + } + if mis.brkerr() { + warn!("Break error"); + } + if mis.ovrerr() { + warn!("Overrun error"); + } +} diff --git a/embassy-mspm0/src/uart/mod.rs b/embassy-mspm0/src/uart/mod.rs new file mode 100644 index 000000000..6599cea06 --- /dev/null +++ b/embassy-mspm0/src/uart/mod.rs @@ -0,0 +1,1174 @@ +#![macro_use] + +mod buffered; + +use core::marker::PhantomData; +use core::sync::atomic::{compiler_fence, AtomicU32, Ordering}; + +pub use buffered::*; +use embassy_embedded_hal::SetConfig; +use embassy_hal_internal::PeripheralType; + +use crate::gpio::{AnyPin, PfType, Pull, SealedPin}; +use crate::interrupt::{Interrupt, InterruptExt}; +use crate::mode::{Blocking, Mode}; +use crate::pac::uart::{vals, Uart as Regs}; +use crate::Peri; + +/// The clock source for the UART. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ClockSel { + /// Use the low frequency clock. + /// + /// The LFCLK runs at 32.768 kHz. + LfClk, + + /// Use the middle frequency clock. + /// + /// The MCLK runs at 4 MHz. + MfClk, + // BusClk, + // BusClk depends on the timer's power domain. + // This will be implemented later. +} + +#[non_exhaustive] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// The order of bits in byte. +pub enum BitOrder { + /// The most significant bit is first. + MsbFirst, + + /// The least significant bit is first. + LsbFirst, +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// Number of data bits +pub enum DataBits { + /// 5 Data Bits + DataBits5, + + /// 6 Data Bits + DataBits6, + + /// 7 Data Bits + DataBits7, + + /// 8 Data Bits + DataBits8, +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// Parity +pub enum Parity { + /// No parity + ParityNone, + + /// Even Parity + ParityEven, + + /// Odd Parity + ParityOdd, +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// Number of stop bits +pub enum StopBits { + /// One stop bit + Stop1, + + /// Two stop bits + Stop2, +} + +#[non_exhaustive] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// Config Error +pub enum ConfigError { + /// Rx or Tx not enabled + RxOrTxNotEnabled, + + /// The baud rate could not be configured with the given clocks. + InvalidBaudRate, +} + +#[non_exhaustive] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +/// Config +pub struct Config { + /// UART clock source. + pub clock_source: ClockSel, + + /// Baud rate + pub baudrate: u32, + + /// Number of data bits. + pub data_bits: DataBits, + + /// Number of stop bits. + pub stop_bits: StopBits, + + /// Parity type. + pub parity: Parity, + + /// The order of bits in a transmitted/received byte. + pub msb_order: BitOrder, + + /// If true: the `TX` is internally connected to `RX`. + pub loop_back_enable: bool, + + // TODO: Pending way to check if uart is extended + // /// If true: [manchester coding] is used. + // /// + // /// [manchester coding]: https://en.wikipedia.org/wiki/Manchester_code + // pub manchester: bool, + + // TODO: majority voting + /// If true: the built-in FIFO is enabled. + pub fifo_enable: bool, + + // TODO: glitch suppression + /// If true: invert TX pin signal values (VDD = 0/mark, Gnd = 1/idle). + pub invert_tx: bool, + + /// If true: invert RX pin signal values (VDD = 0/mark, Gnd = 1/idle). + pub invert_rx: bool, + + /// If true: invert RTS pin signal values (VDD = 0/mark, Gnd = 1/idle). + pub invert_rts: bool, + + /// If true: invert CTS pin signal values (VDD = 0/mark, Gnd = 1/idle). + pub invert_cts: bool, + + /// Set the pull configuration for the TX pin. + pub tx_pull: Pull, + + /// Set the pull configuration for the RX pin. + pub rx_pull: Pull, + + /// Set the pull configuration for the RTS pin. + pub rts_pull: Pull, + + /// Set the pull configuration for the CTS pin. + pub cts_pull: Pull, +} + +impl Default for Config { + fn default() -> Self { + Self { + clock_source: ClockSel::MfClk, + baudrate: 115200, + data_bits: DataBits::DataBits8, + stop_bits: StopBits::Stop1, + parity: Parity::ParityNone, + // hardware default + msb_order: BitOrder::LsbFirst, + loop_back_enable: false, + // manchester: false, + fifo_enable: false, + invert_tx: false, + invert_rx: false, + invert_rts: false, + invert_cts: false, + tx_pull: Pull::None, + rx_pull: Pull::None, + rts_pull: Pull::None, + cts_pull: Pull::None, + } + } +} + +/// Bidirectional UART Driver, which acts as a combination of [`UartTx`] and [`UartRx`]. +/// +/// ### Notes on [`embedded_io::Read`] +/// +/// [`embedded_io::Read`] requires guarantees that the base [`UartRx`] cannot provide. +/// +/// See [`UartRx`] for more details, and see [`BufferedUart`] and [`RingBufferedUartRx`] +/// as alternatives that do provide the necessary guarantees for `embedded_io::Read`. +pub struct Uart<'d, M: Mode> { + tx: UartTx<'d, M>, + rx: UartRx<'d, M>, +} + +impl<'d, M: Mode> SetConfig for Uart<'d, M> { + type Config = Config; + type ConfigError = ConfigError; + + fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { + self.set_config(config) + } +} + +/// Serial error +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub enum Error { + Framing, + + Noise, + + Overrun, + + Parity, + + Break, +} + +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let message = match self { + Self::Framing => "Framing Error", + Self::Noise => "Noise Error", + Self::Overrun => "RX Buffer Overrun", + Self::Parity => "Parity Check Error", + Self::Break => "Break Error", + }; + + write!(f, "{}", message) + } +} + +impl core::error::Error for Error {} + +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + embedded_io::ErrorKind::Other + } +} + +/// Rx-only UART Driver. +/// +/// Can be obtained from [`Uart::split`], or can be constructed independently, +/// if you do not need the transmitting half of the driver. +pub struct UartRx<'d, M: Mode> { + info: &'static Info, + state: &'static State, + rx: Option>, + rts: Option>, + _phantom: PhantomData, +} + +impl<'d, M: Mode> SetConfig for UartRx<'d, M> { + type Config = Config; + type ConfigError = ConfigError; + + fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { + self.set_config(config) + } +} + +impl<'d> UartRx<'d, Blocking> { + /// Create a new rx-only UART with no hardware flow control. + /// + /// Useful if you only want Uart Rx. It saves 1 pin. + pub fn new_blocking( + peri: Peri<'d, T>, + rx: Peri<'d, impl RxPin>, + config: Config, + ) -> Result { + Self::new_inner(peri, new_pin!(rx, config.rx_pf()), None, config) + } + + /// Create a new rx-only UART with a request-to-send pin + pub fn new_blocking_with_rts( + peri: Peri<'d, T>, + rx: Peri<'d, impl RxPin>, + rts: Peri<'d, impl RtsPin>, + config: Config, + ) -> Result { + Self::new_inner( + peri, + new_pin!(rx, config.rx_pf()), + new_pin!(rts, config.rts_pf()), + config, + ) + } +} + +impl<'d, M: Mode> UartRx<'d, M> { + /// Perform a blocking read into `buffer` + pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { + let r = self.info.regs; + + for b in buffer { + // Wait if nothing has arrived yet. + while r.stat().read().rxfe() {} + + // Prevent the compiler from reading from buffer too early + compiler_fence(Ordering::Acquire); + *b = read_with_error(r)?; + } + + Ok(()) + } + + /// Reconfigure the driver + pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { + if let Some(ref rx) = self.rx { + rx.update_pf(config.rx_pf()); + } + + if let Some(ref rts) = self.rts { + rts.update_pf(config.rts_pf()); + } + + reconfigure(self.info, self.state, config) + } + + /// Set baudrate + pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError> { + set_baudrate(&self.info, self.state.clock.load(Ordering::Relaxed), baudrate) + } +} + +impl<'d, M: Mode> Drop for UartRx<'d, M> { + fn drop(&mut self) { + self.rx.as_ref().map(|x| x.set_as_disconnected()); + self.rts.as_ref().map(|x| x.set_as_disconnected()); + } +} + +/// Tx-only UART Driver. +/// +/// Can be obtained from [`Uart::split`], or can be constructed independently, +/// if you do not need the receiving half of the driver. +pub struct UartTx<'d, M: Mode> { + info: &'static Info, + state: &'static State, + tx: Option>, + cts: Option>, + _phantom: PhantomData, +} + +impl<'d, M: Mode> SetConfig for UartTx<'d, M> { + type Config = Config; + type ConfigError = ConfigError; + + fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { + reconfigure(self.info, self.state, config) + } +} + +impl<'d> UartTx<'d, Blocking> { + /// Create a new blocking tx-only UART with no hardware flow control. + /// + /// Useful if you only want Uart Tx. It saves 1 pin. + pub fn new_blocking( + peri: Peri<'d, T>, + tx: Peri<'d, impl TxPin>, + config: Config, + ) -> Result { + Self::new_inner(peri, new_pin!(tx, config.tx_pf()), None, config) + } + + /// Create a new blocking tx-only UART with a clear-to-send pin + pub fn new_blocking_with_cts( + peri: Peri<'d, T>, + tx: Peri<'d, impl TxPin>, + cts: Peri<'d, impl CtsPin>, + config: Config, + ) -> Result { + Self::new_inner( + peri, + new_pin!(tx, config.tx_pf()), + new_pin!(cts, config.cts_pf()), + config, + ) + } +} + +impl<'d, M: Mode> UartTx<'d, M> { + /// Perform a blocking UART write + pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { + let r = self.info.regs; + + for &b in buffer { + // Wait if there is no space + while !r.stat().read().txfe() {} + + // Prevent the compiler from writing to buffer too early + compiler_fence(Ordering::Release); + r.txdata().write(|w| { + w.set_data(b); + }); + } + + Ok(()) + } + + /// Block until transmission complete + pub fn blocking_flush(&mut self) -> Result<(), Error> { + let r = self.info.regs; + + // Wait until TX fifo/buffer is empty + while r.stat().read().txfe() {} + Ok(()) + } + + /// Send break character + pub fn send_break(&self) { + let r = self.info.regs; + + r.lcrh().modify(|w| { + w.set_brk(true); + }); + } + + /// Check if UART is busy. + pub fn busy(&self) -> bool { + busy(self.info.regs) + } + + /// Reconfigure the driver + pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { + if let Some(ref tx) = self.tx { + tx.update_pf(config.tx_pf()); + } + + if let Some(ref cts) = self.cts { + cts.update_pf(config.cts_pf()); + } + + reconfigure(self.info, self.state, config) + } + + /// Set baudrate + pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError> { + set_baudrate(&self.info, self.state.clock.load(Ordering::Relaxed), baudrate) + } +} + +impl<'d, M: Mode> Drop for UartTx<'d, M> { + fn drop(&mut self) { + self.tx.as_ref().map(|x| x.set_as_disconnected()); + self.cts.as_ref().map(|x| x.set_as_disconnected()); + } +} + +impl<'d> Uart<'d, Blocking> { + /// Create a new blocking bidirectional UART. + pub fn new_blocking( + peri: Peri<'d, T>, + rx: Peri<'d, impl RxPin>, + tx: Peri<'d, impl TxPin>, + config: Config, + ) -> Result { + Self::new_inner( + peri, + new_pin!(rx, config.rx_pf()), + new_pin!(tx, config.tx_pf()), + None, + None, + config, + ) + } + + /// Create a new bidirectional UART with request-to-send and clear-to-send pins + pub fn new_blocking_with_rtscts( + peri: Peri<'d, T>, + rx: Peri<'d, impl RxPin>, + tx: Peri<'d, impl TxPin>, + rts: Peri<'d, impl RtsPin>, + cts: Peri<'d, impl CtsPin>, + config: Config, + ) -> Result { + Self::new_inner( + peri, + new_pin!(rx, config.rx_pf()), + new_pin!(tx, config.tx_pf()), + new_pin!(rts, config.rts_pf()), + new_pin!(cts, config.cts_pf()), + config, + ) + } +} + +impl<'d, M: Mode> Uart<'d, M> { + /// Perform a blocking write + pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { + self.tx.blocking_write(buffer) + } + + /// Block until transmission complete + pub fn blocking_flush(&mut self) -> Result<(), Error> { + self.tx.blocking_flush() + } + + /// Check if UART is busy. + pub fn busy(&self) -> bool { + self.tx.busy() + } + + /// Perform a blocking read into `buffer` + pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { + self.rx.blocking_read(buffer) + } + + /// Split the Uart into a transmitter and receiver, which is + /// particularly useful when having two tasks correlating to + /// transmitting and receiving. + pub fn split(self) -> (UartTx<'d, M>, UartRx<'d, M>) { + (self.tx, self.rx) + } + + /// Split the Uart into a transmitter and receiver by mutable reference, + /// which is particularly useful when having two tasks correlating to + /// transmitting and receiving. + pub fn split_ref(&mut self) -> (&mut UartTx<'d, M>, &mut UartRx<'d, M>) { + (&mut self.tx, &mut self.rx) + } + + /// Reconfigure the driver + pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { + self.tx.set_config(config)?; + self.rx.set_config(config) + } + + /// Send break character + pub fn send_break(&self) { + self.tx.send_break(); + } + + /// Set baudrate + pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError> { + set_baudrate(&self.tx.info, self.tx.state.clock.load(Ordering::Relaxed), baudrate) + } +} + +/// Peripheral instance trait. +#[allow(private_bounds)] +pub trait Instance: SealedInstance + PeripheralType { + type Interrupt: crate::interrupt::typelevel::Interrupt; +} + +/// UART `TX` pin trait +pub trait TxPin: crate::gpio::Pin { + /// Get the PF number needed to use this pin as `TX`. + fn pf_num(&self) -> u8; +} + +/// UART `RX` pin trait +pub trait RxPin: crate::gpio::Pin { + /// Get the PF number needed to use this pin as `RX`. + fn pf_num(&self) -> u8; +} + +/// UART `CTS` pin trait +pub trait CtsPin: crate::gpio::Pin { + /// Get the PF number needed to use this pin as `CTS`. + fn pf_num(&self) -> u8; +} + +/// UART `RTS` pin trait +pub trait RtsPin: crate::gpio::Pin { + /// Get the PF number needed to use this pin as `RTS`. + fn pf_num(&self) -> u8; +} + +// ==== IMPL types ==== + +pub(crate) struct Info { + pub(crate) regs: Regs, + pub(crate) interrupt: Interrupt, +} + +pub(crate) struct State { + /// The clock rate of the UART in Hz. + clock: AtomicU32, +} + +impl State { + pub const fn new() -> Self { + Self { + clock: AtomicU32::new(0), + } + } +} + +impl<'d, M: Mode> UartRx<'d, M> { + fn new_inner( + _peri: Peri<'d, T>, + rx: Option>, + rts: Option>, + config: Config, + ) -> Result { + let mut this = Self { + info: T::info(), + state: T::state(), + rx, + rts, + _phantom: PhantomData, + }; + this.enable_and_configure(&config)?; + + Ok(this) + } + + fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { + let info = self.info; + + enable(info.regs); + configure(info, self.state, config, true, self.rts.is_some(), false, false)?; + + Ok(()) + } +} + +impl<'d, M: Mode> UartTx<'d, M> { + fn new_inner( + _peri: Peri<'d, T>, + tx: Option>, + cts: Option>, + config: Config, + ) -> Result { + let mut this = Self { + info: T::info(), + state: T::state(), + tx, + cts, + _phantom: PhantomData, + }; + this.enable_and_configure(&config)?; + + Ok(this) + } + + fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { + let info = self.info; + let state = self.state; + + enable(info.regs); + configure(info, state, config, false, false, true, self.cts.is_some())?; + + Ok(()) + } +} + +impl<'d, M: Mode> Uart<'d, M> { + fn new_inner( + _peri: Peri<'d, T>, + rx: Option>, + tx: Option>, + rts: Option>, + cts: Option>, + config: Config, + ) -> Result { + let info = T::info(); + let state = T::state(); + + let mut this = Self { + tx: UartTx { + info, + state, + tx, + cts, + _phantom: PhantomData, + }, + rx: UartRx { + info, + state, + rx, + rts, + _phantom: PhantomData, + }, + }; + this.enable_and_configure(&config)?; + + Ok(this) + } + + fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { + let info = self.rx.info; + let state = self.rx.state; + + enable(info.regs); + configure( + info, + state, + config, + true, + self.rx.rts.is_some(), + true, + self.tx.cts.is_some(), + )?; + + info.interrupt.unpend(); + unsafe { info.interrupt.enable() }; + + Ok(()) + } +} + +impl Config { + fn tx_pf(&self) -> PfType { + PfType::output(self.tx_pull, self.invert_tx) + } + + fn rx_pf(&self) -> PfType { + PfType::input(self.rx_pull, self.invert_rx) + } + + fn rts_pf(&self) -> PfType { + PfType::output(self.rts_pull, self.invert_rts) + } + + fn cts_pf(&self) -> PfType { + PfType::input(self.rts_pull, self.invert_rts) + } +} + +fn enable(regs: Regs) { + let gprcm = regs.gprcm(0); + + gprcm.rstctl().write(|w| { + w.set_resetstkyclr(true); + w.set_resetassert(true); + w.set_key(vals::ResetKey::KEY); + }); + + gprcm.pwren().write(|w| { + w.set_enable(true); + w.set_key(vals::PwrenKey::KEY); + }); +} + +fn configure( + info: &Info, + state: &State, + config: &Config, + enable_rx: bool, + enable_rts: bool, + enable_tx: bool, + enable_cts: bool, +) -> Result<(), ConfigError> { + let r = info.regs; + + if !enable_rx && !enable_tx { + return Err(ConfigError::RxOrTxNotEnabled); + } + + // SLAU846B says that clocks should be enabled before disabling the uart. + r.clksel().write(|w| match config.clock_source { + ClockSel::LfClk => { + w.set_lfclk_sel(true); + w.set_mfclk_sel(false); + w.set_busclk_sel(false); + } + ClockSel::MfClk => { + w.set_mfclk_sel(true); + w.set_lfclk_sel(false); + w.set_busclk_sel(false); + } + }); + + let clock = match config.clock_source { + ClockSel::LfClk => 32768, + ClockSel::MfClk => 4_000_000, + }; + + state.clock.store(clock, Ordering::Relaxed); + + info.regs.ctl0().modify(|w| { + w.set_lbe(config.loop_back_enable); + // Errata UART_ERR_02, must set RXE to allow use of EOT. + w.set_rxe(enable_rx | enable_tx); + w.set_txe(enable_tx); + // RXD_OUT_EN and TXD_OUT_EN? + w.set_menc(false); + w.set_mode(vals::Mode::UART); + w.set_rtsen(enable_rts); + w.set_ctsen(enable_cts); + // oversampling is set later + w.set_fen(config.fifo_enable); + // TODO: config + w.set_majvote(false); + w.set_msbfirst(matches!(config.msb_order, BitOrder::MsbFirst)); + }); + + info.regs.ifls().modify(|w| { + // TODO: Need power domain info for other options. + w.set_txiflsel(vals::Iflssel::AT_LEAST_ONE); + w.set_rxiflsel(vals::Iflssel::AT_LEAST_ONE); + }); + + info.regs.lcrh().modify(|w| { + let eps = if matches!(config.parity, Parity::ParityEven) { + vals::Eps::EVEN + } else { + vals::Eps::ODD + }; + + let wlen = match config.data_bits { + DataBits::DataBits5 => vals::Wlen::DATABIT5, + DataBits::DataBits6 => vals::Wlen::DATABIT6, + DataBits::DataBits7 => vals::Wlen::DATABIT7, + DataBits::DataBits8 => vals::Wlen::DATABIT8, + }; + + // Used in LIN mode only + w.set_brk(false); + w.set_pen(config.parity != Parity::ParityNone); + w.set_eps(eps); + w.set_stp2(matches!(config.stop_bits, StopBits::Stop2)); + w.set_wlen(wlen); + // appears to only be used in RS-485 mode. + w.set_sps(false); + // IDLE pattern? + w.set_sendidle(false); + // ignore extdir_setup and extdir_hold, only used in RS-485 mode. + }); + + set_baudrate_inner(info.regs, clock, config.baudrate)?; + + r.ctl0().modify(|w| { + w.set_enable(true); + }); + + Ok(()) +} + +fn reconfigure(info: &Info, state: &State, config: &Config) -> Result<(), ConfigError> { + info.interrupt.disable(); + let r = info.regs; + let ctl0 = r.ctl0().read(); + configure(info, state, config, ctl0.rxe(), ctl0.rtsen(), ctl0.txe(), ctl0.ctsen())?; + + info.interrupt.unpend(); + unsafe { info.interrupt.enable() }; + + Ok(()) +} + +/// Set the baud rate and clock settings. +/// +/// This should be done relatively late during configuration since some clock settings are invalid depending on mode. +fn set_baudrate(info: &Info, clock: u32, baudrate: u32) -> Result<(), ConfigError> { + let r = info.regs; + + info.interrupt.disable(); + + // Programming baud rate requires that the peripheral is disabled + critical_section::with(|_cs| { + r.ctl0().modify(|w| { + w.set_enable(false); + }); + }); + + // Wait for end of transmission per suggestion in SLAU 845 section 18.3.28 + while !r.stat().read().txfe() {} + + set_baudrate_inner(r, clock, baudrate)?; + + critical_section::with(|_cs| { + r.ctl0().modify(|w| { + w.set_enable(true); + }); + }); + + info.interrupt.unpend(); + unsafe { info.interrupt.enable() }; + + Ok(()) +} + +fn set_baudrate_inner(regs: Regs, clock: u32, baudrate: u32) -> Result<(), ConfigError> { + // Quoting SLAU846 section 18.2.3.4: + // "When IBRD = 0, FBRD is ignored and no data gets transferred by the UART." + const MIN_IBRD: u16 = 1; + + // FBRD can be 0 + // FBRD is at most a 6-bit number. + const MAX_FBRD: u8 = 2_u8.pow(6); + + const DIVS: [(u8, vals::Clkdiv); 8] = [ + (1, vals::Clkdiv::DIV_BY_1), + (2, vals::Clkdiv::DIV_BY_2), + (3, vals::Clkdiv::DIV_BY_3), + (4, vals::Clkdiv::DIV_BY_4), + (5, vals::Clkdiv::DIV_BY_5), + (6, vals::Clkdiv::DIV_BY_6), + (7, vals::Clkdiv::DIV_BY_7), + (8, vals::Clkdiv::DIV_BY_8), + ]; + + // Quoting from SLAU 846 section 18.2.3.4: + // "Select oversampling by 3 or 8 to achieve higher speed with UARTclk/8 or UARTclk/3. In this case + // the receiver tolerance to clock deviation is reduced." + // + // "Select oversampling by 16 to increase the tolerance of the receiver to clock deviations. The + // maximum speed is limited to UARTclk/16." + // + // Based on these requirements, prioritize higher oversampling first to increase tolerance to clock + // deviation. If no valid BRD value can be found satisifying the highest sample rate, then reduce + // sample rate until valid parameters are found. + const OVS: [(u8, vals::Hse); 3] = [(16, vals::Hse::OVS16), (8, vals::Hse::OVS8), (3, vals::Hse::OVS3)]; + + // 3x oversampling is not supported with manchester coding, DALI or IrDA. + let x3_invalid = { + let ctl0 = regs.ctl0().read(); + let irctl = regs.irctl().read(); + + ctl0.menc() || matches!(ctl0.mode(), vals::Mode::DALI) || irctl.iren() + }; + let mut found = None; + + 'outer: for &(oversampling, hse_value) in &OVS { + if matches!(hse_value, vals::Hse::OVS3) && x3_invalid { + continue; + } + + // Verify that the selected oversampling does not require a clock faster than what the hardware + // is provided. + let Some(min_clock) = baudrate.checked_mul(oversampling as u32) else { + trace!( + "{}x oversampling would cause overflow for clock: {} Hz", + oversampling, + clock + ); + continue; + }; + + if min_clock > clock { + trace!("{} oversampling is too high for clock: {} Hz", oversampling, clock); + continue; + } + + for &(div, div_value) in &DIVS { + trace!( + "Trying div: {}, oversampling {} for {} baud", + div, + oversampling, + baudrate + ); + + let Some((ibrd, fbrd)) = calculate_brd(clock, div, baudrate, oversampling) else { + trace!("Calculating BRD overflowed: trying another divider"); + continue; + }; + + if ibrd < MIN_IBRD || fbrd > MAX_FBRD { + trace!("BRD was invalid: trying another divider"); + continue; + } + + found = Some((hse_value, div_value, ibrd, fbrd)); + break 'outer; + } + } + + let Some((hse, div, ibrd, fbrd)) = found else { + return Err(ConfigError::InvalidBaudRate); + }; + + regs.clkdiv().write(|w| { + w.set_ratio(div); + }); + + regs.ibrd().write(|w| { + w.set_divint(ibrd); + }); + + regs.fbrd().write(|w| { + w.set_divfrac(fbrd); + }); + + regs.ctl0().modify(|w| { + w.set_hse(hse); + }); + + Ok(()) +} + +/// Calculate the integer and fractional parts of the `BRD` value. +/// +/// Returns [`None`] if calculating this results in overflows. +/// +/// Values returned are `(ibrd, fbrd)` +fn calculate_brd(clock: u32, div: u8, baud: u32, oversampling: u8) -> Option<(u16, u8)> { + use fixed::types::U26F6; + + // Calculate BRD according to SLAU 846 section 18.2.3.4. + // + // BRD is a 22-bit value with 16 integer bits and 6 fractional bits. + // + // uart_clock = clock / div + // brd = ibrd.fbrd = uart_clock / (oversampling * baud)" + // + // It is tempting to rearrange the equation such that there is only a single division in + // order to reduce error. However this is wrong since the denominator ends up being too + // small to represent in 6 fraction bits. This means that FBRD would always be 0. + // + // Calculations are done in a U16F6 format. However the fixed crate has no such representation. + // U26F6 is used since it has the same number of fractional bits and we verify at the end that + // the integer part did not overflow. + let clock = U26F6::from_num(clock); + let div = U26F6::from_num(div); + let oversampling = U26F6::from_num(oversampling); + let baud = U26F6::from_num(baud); + + let uart_clock = clock.checked_div(div)?; + + // oversampling * baud + let denom = oversampling.checked_mul(baud)?; + // uart_clock / (oversampling * baud) + let brd = uart_clock.checked_div(denom)?; + + // Checked is used to determine overflow in the 10 most singificant bits since the + // actual representation of BRD is U16F6. + let ibrd = brd.checked_to_num::()?; + + // We need to scale FBRD's representation to an integer. + let fbrd_scale = U26F6::from_num(2_u32.checked_pow(U26F6::FRAC_NBITS)?); + + // It is suggested that 0.5 is added to ensure that any fractional parts round up to the next + // integer. If it doesn't round up then it'll get discarded which is okay. + let half = U26F6::from_num(1) / U26F6::from_num(2); + // fbrd = INT(((FRAC(BRD) * 64) + 0.5)) + let fbrd = brd + .frac() + .checked_mul(fbrd_scale)? + .checked_add(half)? + .checked_to_num::()?; + + Some((ibrd, fbrd)) +} + +fn read_with_error(r: Regs) -> Result { + let rx = r.rxdata().read(); + + if rx.frmerr() { + return Err(Error::Framing); + } else if rx.parerr() { + return Err(Error::Parity); + } else if rx.brkerr() { + return Err(Error::Break); + } else if rx.ovrerr() { + return Err(Error::Overrun); + } else if rx.nerr() { + return Err(Error::Noise); + } + + Ok(rx.data()) +} + +/// This function assumes CTL0.ENABLE is set (for errata cases). +fn busy(r: Regs) -> bool { + // Errata UART_ERR_08 + if cfg!(any( + mspm0g151x, mspm0g351x, mspm0l110x, mspm0l130x, mspm0l134x, mspm0c110x, + )) { + let stat = r.stat().read(); + // "Poll TXFIFO status and the CTL0.ENABLE register bit to identify BUSY status." + !stat.txfe() + } else { + r.stat().read().busy() + } +} + +// TODO: Implement when dma uart is implemented. +fn dma_enabled(_r: Regs) -> bool { + false +} + +pub(crate) trait SealedInstance { + fn info() -> &'static Info; + fn state() -> &'static State; + fn buffered_state() -> &'static BufferedState; +} + +macro_rules! impl_uart_instance { + ($instance: ident) => { + impl crate::uart::SealedInstance for crate::peripherals::$instance { + fn info() -> &'static crate::uart::Info { + use crate::interrupt::typelevel::Interrupt; + use crate::uart::Info; + + const INFO: Info = Info { + regs: crate::pac::$instance, + interrupt: crate::interrupt::typelevel::$instance::IRQ, + }; + &INFO + } + + fn state() -> &'static crate::uart::State { + use crate::uart::State; + + static STATE: State = State::new(); + &STATE + } + + fn buffered_state() -> &'static crate::uart::BufferedState { + use crate::uart::BufferedState; + + static STATE: BufferedState = BufferedState::new(); + &STATE + } + } + + impl crate::uart::Instance for crate::peripherals::$instance { + type Interrupt = crate::interrupt::typelevel::$instance; + } + }; +} + +macro_rules! impl_uart_tx_pin { + ($instance: ident, $pin: ident, $pf: expr) => { + impl crate::uart::TxPin for crate::peripherals::$pin { + fn pf_num(&self) -> u8 { + $pf + } + } + }; +} + +macro_rules! impl_uart_rx_pin { + ($instance: ident, $pin: ident, $pf: expr) => { + impl crate::uart::RxPin for crate::peripherals::$pin { + fn pf_num(&self) -> u8 { + $pf + } + } + }; +} + +macro_rules! impl_uart_cts_pin { + ($instance: ident, $pin: ident, $pf: expr) => { + impl crate::uart::CtsPin for crate::peripherals::$pin { + fn pf_num(&self) -> u8 { + $pf + } + } + }; +} + +macro_rules! impl_uart_rts_pin { + ($instance: ident, $pin: ident, $pf: expr) => { + impl crate::uart::RtsPin for crate::peripherals::$pin { + fn pf_num(&self) -> u8 { + $pf + } + } + }; +} + +#[cfg(test)] +mod tests { + use super::calculate_brd; + + /// This is a smoke test based on the example in SLAU 846 section 18.2.3.4. + #[test] + fn datasheet() { + let brd = calculate_brd(40_000_000, 1, 19200, 16); + + assert!(matches!(brd, Some((130, 13)))); + } +} diff --git a/examples/mspm0g3507/Cargo.toml b/examples/mspm0g3507/Cargo.toml index b6621c9c5..cc40b3109 100644 --- a/examples/mspm0g3507/Cargo.toml +++ b/examples/mspm0g3507/Cargo.toml @@ -17,5 +17,7 @@ defmt-rtt = "1.0.0" panic-probe = { version = "1.0.0", features = ["print-defmt"] } panic-semihosting = "0.6.0" +embedded-io-async = "0.6.1" + [profile.release] debug = 2 diff --git a/tests/mspm0/Cargo.toml b/tests/mspm0/Cargo.toml index 2d5b8cd52..5ba3e586b 100644 --- a/tests/mspm0/Cargo.toml +++ b/tests/mspm0/Cargo.toml @@ -13,6 +13,7 @@ teleprobe-meta = "1.1" embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = [ "defmt" ] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } +embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt" ] } embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = [ "rt", "defmt", "unstable-pac", "time-driver-any" ] } embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal/"} @@ -24,6 +25,8 @@ cortex-m = { version = "0.7.6", features = [ "inline-asm", "critical-section-sin cortex-m-rt = "0.7.0" embedded-hal = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } +embedded-io = { version = "0.6.1", features = ["defmt-03"] } +embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } panic-probe = { version = "1.0.0", features = ["print-defmt"] } static_cell = "2" portable-atomic = { version = "1.5", features = ["critical-section"] } diff --git a/tests/mspm0/src/bin/uart_buffered.rs b/tests/mspm0/src/bin/uart_buffered.rs new file mode 100644 index 000000000..135ac1287 --- /dev/null +++ b/tests/mspm0/src/bin/uart_buffered.rs @@ -0,0 +1,115 @@ +#![no_std] +#![no_main] + +#[cfg(feature = "mspm0g3507")] +teleprobe_meta::target!(b"lp-mspm0g3507"); + +use defmt::{assert_eq, unwrap, *}; +use embassy_executor::Spawner; +use embassy_mspm0::uart::{BufferedInterruptHandler, BufferedUart, Config}; +use embassy_mspm0::{bind_interrupts, peripherals}; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + UART1 => BufferedInterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_mspm0::init(Default::default()); + info!("Hello World!"); + + // TODO: Allow creating a looped-back UART (so pins are not needed). + // Do not select default UART since the virtual COM port is attached to UART0. + #[cfg(any(feature = "mspm0g3507"))] + let (mut tx, mut rx, mut uart) = (p.PA8, p.PA9, p.UART1); + + { + use embedded_io_async::{Read, Write}; + + let mut config = Config::default(); + config.loop_back_enable = true; + config.fifo_enable = false; + + let tx_buf = &mut [0u8; 16]; + let rx_buf = &mut [0u8; 16]; + let mut uart = unwrap!(BufferedUart::new( + uart.reborrow(), + tx.reborrow(), + rx.reborrow(), + Irqs, + tx_buf, + rx_buf, + config + )); + + let mut buf = [0; 16]; + for (j, b) in buf.iter_mut().enumerate() { + *b = j as u8; + } + + unwrap!(uart.write_all(&buf).await); + unwrap!(uart.flush().await); + + unwrap!(uart.read_exact(&mut buf).await); + for (j, b) in buf.iter().enumerate() { + assert_eq!(*b, j as u8); + } + + // Buffer is unclogged, should be able to write again. + unwrap!(uart.write_all(&buf).await); + unwrap!(uart.flush().await); + + unwrap!(uart.read_exact(&mut buf).await); + for (j, b) in buf.iter().enumerate() { + assert_eq!(*b, j as u8); + } + } + + info!("Blocking buffered"); + { + use embedded_io::{Read, Write}; + + let mut config = Config::default(); + config.loop_back_enable = true; + config.fifo_enable = false; + + let tx_buf = &mut [0u8; 16]; + let rx_buf = &mut [0u8; 16]; + let mut uart = unwrap!(BufferedUart::new( + uart.reborrow(), + tx.reborrow(), + rx.reborrow(), + Irqs, + tx_buf, + rx_buf, + config + )); + + let mut buf = [0; 16]; + + for (j, b) in buf.iter_mut().enumerate() { + *b = j as u8; + } + + unwrap!(uart.write_all(&buf)); + unwrap!(uart.blocking_flush()); + unwrap!(uart.read_exact(&mut buf)); + + for (j, b) in buf.iter().enumerate() { + assert_eq!(*b, j as u8); + } + + // Buffer is unclogged, should be able to write again. + unwrap!(uart.write_all(&buf)); + unwrap!(uart.blocking_flush()); + unwrap!(uart.read_exact(&mut buf)); + + for (j, b) in buf.iter().enumerate() { + assert_eq!(*b, j as u8, "at {}", j); + } + } + + info!("Test OK"); + cortex_m::asm::bkpt(); +} -- cgit From 510adb3b69daffec533292140221be36e2ed5ba2 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Tue, 22 Jul 2025 18:30:31 -0500 Subject: nxp: make docs generate --- .github/ci/doc.sh | 1 + embassy-nxp/Cargo.toml | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 06c61f8c0..90662af82 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -26,6 +26,7 @@ docserver-builder -i ./embassy-futures -o webroot/crates/embassy-futures/git.zup docserver-builder -i ./embassy-nrf -o webroot/crates/embassy-nrf/git.zup docserver-builder -i ./embassy-rp -o webroot/crates/embassy-rp/git.zup docserver-builder -i ./embassy-mspm0 -o webroot/crates/embassy-mspm0/git.zup +docserver-builder -i ./embassy-nxp -o webroot/crates/embassy-nxp/git.zup docserver-builder -i ./embassy-sync -o webroot/crates/embassy-sync/git.zup docserver-builder -i ./cyw43 -o webroot/crates/cyw43/git.zup docserver-builder -i ./cyw43-pio -o webroot/crates/cyw43-pio/git.zup diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 01f57c4e2..078a3a7d8 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -3,6 +3,16 @@ name = "embassy-nxp" version = "0.1.0" edition = "2021" +[package.metadata.embassy_docs] +src_base = "https://github.com/embassy-rs/embassy/blob/embassy-nxp-v$VERSION/embassy-nxp/src/" +src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-nxp/src/" +features = ["defmt", "unstable-pac" ] # TODO: Add time-driver-any, as both lpc55 and mimxrt1xxx use different drivers. + +flavors = [ + { regex_feature = "lpc55", target = "thumbv8m.main-none-eabihf" }, + { regex_feature = "mimxrt.*", target = "thumbv7em-none-eabihf" }, +] + [dependencies] cortex-m = "0.7.7" cortex-m-rt = "0.7.0" -- cgit From e64c23076d2c003efe60419eab6b86630d7886b4 Mon Sep 17 00:00:00 2001 From: Chris Storah Date: Wed, 23 Jul 2025 12:38:58 +1000 Subject: Updated version of stm32-data and added c071 and c051 into ci.sh --- ci.sh | 3 +++ embassy-stm32/Cargo.toml | 4 ++-- embassy-stm32/src/rcc/c0.rs | 11 ++--------- tests/stm32/Cargo.toml | 1 + tests/stm32/build.rs | 1 + tests/stm32/src/common.rs | 10 +++++++++- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/ci.sh b/ci.sh index 229ddaae8..b2277a6d7 100755 --- a/ci.sh +++ b/ci.sh @@ -102,6 +102,8 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,single-bank,defmt \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c071rb,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c051f6,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f038f6,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f030c6,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f058t8,defmt,exti,time-driver-any,time \ @@ -299,6 +301,7 @@ cargo batch \ --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g491re --artifact-dir out/tests/stm32g491re \ --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g071rb --artifact-dir out/tests/stm32g071rb \ --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c031c6 --artifact-dir out/tests/stm32c031c6 \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c071rb --artifact-dir out/tests/stm32c071rb \ --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi --artifact-dir out/tests/stm32h755zi \ --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h753zi --artifact-dir out/tests/stm32h753zi \ --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7a3zi --artifact-dir out/tests/stm32h7a3zi \ diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 248639385..8f3a471af 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-dded8a33a460ae0eb182aee3ccb048beb659982b" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9fc86ca7b3a8bc05182bf1ce3045602df1f5dce3" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-dded8a33a460ae0eb182aee3ccb048beb659982b", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9fc86ca7b3a8bc05182bf1ce3045602df1f5dce3", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs index d44914719..b9773d1af 100644 --- a/embassy-stm32/src/rcc/c0.rs +++ b/embassy-stm32/src/rcc/c0.rs @@ -187,20 +187,13 @@ pub(crate) unsafe fn init(config: Config) { hse: hse, rtc: rtc, - #[cfg(any(stm32c071))] - hsi48: hsi, - // TODO lsi: None, lse: None, + hsi48: None, ); - #[cfg(not(any(stm32c071)))] - let r = RCC.ccipr(); - #[cfg(any(stm32c071))] - let r = RCC.ccipr1(); - - r.modify(|w| w.set_adc1sel(stm32_metapac::rcc::vals::Adcsel::SYS)); + RCC.ccipr().modify(|w| w.set_adc1sel(stm32_metapac::rcc::vals::Adcsel::SYS)); } mod max { diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 8d10f6593..7c32c0ce1 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -7,6 +7,7 @@ autobins = false [features] stm32c031c6 = ["embassy-stm32/stm32c031c6", "cm0", "not-gpdma"] +stm32c071rb = ["embassy-stm32/stm32c071rb", "cm0", "not-gpdma"] stm32f103c8 = ["embassy-stm32/stm32f103c8", "spi-v1", "not-gpdma"] stm32f207zg = ["embassy-stm32/stm32f207zg", "spi-v1", "chrono", "not-gpdma", "eth", "rng"] stm32f303ze = ["embassy-stm32/stm32f303ze", "chrono", "not-gpdma"] diff --git a/tests/stm32/build.rs b/tests/stm32/build.rs index 722671bf1..556d77a20 100644 --- a/tests/stm32/build.rs +++ b/tests/stm32/build.rs @@ -12,6 +12,7 @@ fn main() -> Result<(), Box> { // too little RAM to run from RAM. feature = "stm32f103c8", // 20 kb feature = "stm32c031c6", // 6 kb + feature = "stm32c071rb", // 24 kb feature = "stm32l073rz", // 20 kb feature = "stm32h503rb", // 32 kb // no VTOR, so interrupts can't work when running from RAM diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index 829f2cff0..a4d8048ce 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs @@ -34,6 +34,8 @@ teleprobe_meta::target!(b"nucleo-stm32u5a5zj"); teleprobe_meta::target!(b"nucleo-stm32h563zi"); #[cfg(feature = "stm32c031c6")] teleprobe_meta::target!(b"nucleo-stm32c031c6"); +#[cfg(feature = "stm32c071rb")] +teleprobe_meta::target!(b"nucleo-stm32c071rb"); #[cfg(feature = "stm32l073rz")] teleprobe_meta::target!(b"nucleo-stm32l073rz"); #[cfg(feature = "stm32l152re")] @@ -186,6 +188,12 @@ define_peris!( SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH1, SPI_RX_DMA = DMA1_CH2, @irq UART = {USART1 => embassy_stm32::usart::InterruptHandler;}, ); +#[cfg(feature = "stm32c071rb")] +define_peris!( + UART = USART1, UART_TX = PB6, UART_RX = PB7, UART_TX_DMA = DMA1_CH1, UART_RX_DMA = DMA1_CH2, + SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH1, SPI_RX_DMA = DMA1_CH2, + @irq UART = {USART1 => embassy_stm32::usart::InterruptHandler;}, +); #[cfg(feature = "stm32l496zg")] define_peris!( UART = USART3, UART_TX = PD8, UART_RX = PD9, UART_TX_DMA = DMA1_CH2, UART_RX_DMA = DMA1_CH3, @@ -271,7 +279,7 @@ pub fn config() -> Config { #[allow(unused_mut)] let mut config = Config::default(); - #[cfg(feature = "stm32c031c6")] + #[cfg(any(feature = "stm32c031c6", feature = "stm32c071rb"))] { config.rcc.hsi = Some(Hsi { sys_div: HsiSysDiv::DIV1, // 48Mhz -- cgit From bb29fdd3e2b864325bbdea53810843cc2447d3c3 Mon Sep 17 00:00:00 2001 From: Chris Storah Date: Wed, 23 Jul 2025 12:50:01 +1000 Subject: Formatting update to resolve rustfmt error --- embassy-stm32/src/rcc/c0.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs index b9773d1af..763f1b19c 100644 --- a/embassy-stm32/src/rcc/c0.rs +++ b/embassy-stm32/src/rcc/c0.rs @@ -186,14 +186,15 @@ pub(crate) unsafe fn init(config: Config) { hsiker: hsiker, hse: hse, rtc: rtc, - + // TODO lsi: None, lse: None, hsi48: None, ); - RCC.ccipr().modify(|w| w.set_adc1sel(stm32_metapac::rcc::vals::Adcsel::SYS)); + RCC.ccipr() + .modify(|w| w.set_adc1sel(stm32_metapac::rcc::vals::Adcsel::SYS)); } mod max { -- cgit From 487b42f62cd11292d421831a8943de01b2b25a39 Mon Sep 17 00:00:00 2001 From: Chris Storah Date: Wed, 23 Jul 2025 15:52:36 +1000 Subject: Added missing guard for hsi48. Updated use of removed enums from stm32-data u5 chip --- embassy-stm32/src/flash/u5.rs | 22 +++++++++++----------- embassy-stm32/src/rcc/c0.rs | 1 + 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/embassy-stm32/src/flash/u5.rs b/embassy-stm32/src/flash/u5.rs index 131caa195..2d06fdc67 100644 --- a/embassy-stm32/src/flash/u5.rs +++ b/embassy-stm32/src/flash/u5.rs @@ -30,19 +30,19 @@ pub(crate) unsafe fn enable_blocking_write() { #[cfg(feature = "trustzone-secure")] pac::FLASH.seccr().write(|w| { - w.set_pg(pac::flash::vals::SeccrPg::B_0X1); + w.set_pg(true); }); #[cfg(not(feature = "trustzone-secure"))] pac::FLASH.nscr().write(|w| { - w.set_pg(pac::flash::vals::NscrPg::B_0X1); + w.set_pg(true); }); } pub(crate) unsafe fn disable_blocking_write() { #[cfg(feature = "trustzone-secure")] - pac::FLASH.seccr().write(|w| w.set_pg(pac::flash::vals::SeccrPg::B_0X0)); + pac::FLASH.seccr().write(|w| w.set_pg(false)); #[cfg(not(feature = "trustzone-secure"))] - pac::FLASH.nscr().write(|w| w.set_pg(pac::flash::vals::NscrPg::B_0X0)); + pac::FLASH.nscr().write(|w| w.set_pg(false)); } pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { @@ -65,19 +65,19 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E w.set_pnb(sector.index_in_bank); // TODO: add check for bank swap w.set_bker(match sector.bank { - FlashBank::Bank1 => pac::flash::vals::SeccrBker::B_0X0, - FlashBank::Bank2 => pac::flash::vals::SeccrBker::B_0X1, + FlashBank::Bank1 => false, + FlashBank::Bank2 => true, _ => unreachable!(), }); }); #[cfg(not(feature = "trustzone-secure"))] pac::FLASH.nscr().modify(|w| { - w.set_per(pac::flash::vals::NscrPer::B_0X1); + w.set_per(true); w.set_pnb(sector.index_in_bank); // TODO: add check for bank swap w.set_bker(match sector.bank { - FlashBank::Bank1 => pac::flash::vals::NscrBker::B_0X0, - FlashBank::Bank2 => pac::flash::vals::NscrBker::B_0X1, + FlashBank::Bank1 => false, + FlashBank::Bank2 => true, _ => unreachable!(), }); }); @@ -95,11 +95,11 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E #[cfg(feature = "trustzone-secure")] pac::FLASH .seccr() - .modify(|w| w.set_per(pac::flash::vals::SeccrPer::B_0X0)); + .modify(|w| w.set_per(false)); #[cfg(not(feature = "trustzone-secure"))] pac::FLASH .nscr() - .modify(|w| w.set_per(pac::flash::vals::NscrPer::B_0X0)); + .modify(|w| w.set_per(false)); clear_all_err(); ret } diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs index 763f1b19c..c2295bab6 100644 --- a/embassy-stm32/src/rcc/c0.rs +++ b/embassy-stm32/src/rcc/c0.rs @@ -190,6 +190,7 @@ pub(crate) unsafe fn init(config: Config) { // TODO lsi: None, lse: None, + #[cfg(crs)] hsi48: None, ); -- cgit From 420cbb437fb37a0679859a459ed3b45239b60467 Mon Sep 17 00:00:00 2001 From: Chris Storah Date: Wed, 23 Jul 2025 15:55:14 +1000 Subject: Fix formatting of u5 file --- embassy-stm32/src/flash/u5.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/embassy-stm32/src/flash/u5.rs b/embassy-stm32/src/flash/u5.rs index 2d06fdc67..6c3d4b422 100644 --- a/embassy-stm32/src/flash/u5.rs +++ b/embassy-stm32/src/flash/u5.rs @@ -93,13 +93,9 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E let ret: Result<(), Error> = blocking_wait_ready(); #[cfg(feature = "trustzone-secure")] - pac::FLASH - .seccr() - .modify(|w| w.set_per(false)); + pac::FLASH.seccr().modify(|w| w.set_per(false)); #[cfg(not(feature = "trustzone-secure"))] - pac::FLASH - .nscr() - .modify(|w| w.set_per(false)); + pac::FLASH.nscr().modify(|w| w.set_per(false)); clear_all_err(); ret } -- cgit From cf9856255e1c2abf3ad2164ce669645f5da098c6 Mon Sep 17 00:00:00 2001 From: Frank Stevenson Date: Wed, 23 Jul 2025 10:08:41 +0200 Subject: Make MSI calibration configurabke. Refine detection and handling of shared clock sources between MSIS and MSIK --- embassy-stm32/src/rcc/u5.rs | 101 +++++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 34 deletions(-) diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index e7fe50f33..0c7dc8ecc 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -64,6 +64,28 @@ pub struct Pll { pub divr: Option, } +#[derive(Clone, Copy, PartialEq)] +pub enum MsiAutoCalibration { + /// MSI auto-calibration is disabled + Disabled, + /// MSIS is given priority for auto-calibration + MSIS, + /// MSIK is given priority for auto-calibration + MSIK, +} + +impl MsiAutoCalibration { + const fn default() -> Self { + MsiAutoCalibration::Disabled + } +} + +impl Default for MsiAutoCalibration { + fn default() -> Self { + Self::default() + } +} + #[derive(Clone, Copy)] pub struct Config { // base clock sources @@ -95,6 +117,7 @@ pub struct Config { /// Per-peripheral kernel clock selection muxes pub mux: super::mux::ClockMux, + pub auto_calibration: MsiAutoCalibration, } impl Config { @@ -116,6 +139,7 @@ impl Config { voltage_range: VoltageScale::RANGE1, ls: crate::rcc::LsConfig::new(), mux: super::mux::ClockMux::default(), + auto_calibration: MsiAutoCalibration::default(), } } } @@ -133,7 +157,8 @@ pub(crate) unsafe fn init(config: Config) { let lse_calibration_freq = match config.ls.lse { Some(lse_config) => { - if lse_config.peripherals_clocked && (31_000..=34_000).contains(&lse_config.frequency.0) { + // Allow +/- 5% tolerance for LSE frequency + if lse_config.peripherals_clocked && (31_100..=34_400).contains(&lse_config.frequency.0) { Some(lse_config.frequency) } else { None @@ -167,11 +192,19 @@ pub(crate) unsafe fn init(config: Config) { w.set_msipllen(false); w.set_msison(true); }); + let msis = if let (Some(freq), MsiAutoCalibration::MSIS) = (lse_calibration_freq, config.auto_calibration) { + // Enable the MSIS auto-calibration feature + RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIS)); + RCC.cr().modify(|w| w.set_msipllen(true)); + calculate_calibrated_msi_frequency(range, freq) + } else { + msirange_to_hertz(range) + }; while !RCC.cr().read().msisrdy() {} - msirange_to_hertz(range) + msis }); - let msik = config.msik.map(|range| { + let mut msik = config.msik.map(|range| { // Check MSI output per RM0456 § 11.4.10 match config.voltage_range { VoltageScale::RANGE4 => { @@ -195,24 +228,38 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().modify(|w| { w.set_msikon(true); }); - if lse_calibration_freq.is_some() { + let msik = if let (Some(freq), MsiAutoCalibration::MSIK) = (lse_calibration_freq, config.auto_calibration) { // Enable the MSIK auto-calibration feature RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIK)); RCC.cr().modify(|w| w.set_msipllen(true)); - } - while !RCC.cr().read().msikrdy() {} - if let Some(freq) = lse_calibration_freq { - let msik_freq = calculate_calibrated_msi_frequency(range, freq); - if config.msis == config.msik { - // If MSIS and MSIK are the same range both will be auto calibrated to the same frequency - msis = Some(msik_freq) - } - msik_freq + calculate_calibrated_msi_frequency(range, freq) } else { msirange_to_hertz(range) - } + }; + while !RCC.cr().read().msikrdy() {} + msik }); + // If both MSIS and MSIK are enabled, we need to check if they are using the same internal source. + if let Some(lse_freq) = lse_calibration_freq { + if let (Some(msis_range), Some(msik_range)) = (config.msis, config.msik) { + if (msis_range as u8 >> 2) == (msik_range as u8 >> 2) { + // Clock source is shared, both will be auto calibrated. + match config.auto_calibration { + MsiAutoCalibration::MSIS => { + // MSIS and MSIK are using the same clock source, recalibrate + msik = Some(calculate_calibrated_msi_frequency(msik_range, lse_freq)); + } + MsiAutoCalibration::MSIK => { + // MSIS and MSIK are using the same clock source, recalibrate + msis = Some(calculate_calibrated_msi_frequency(msis_range, lse_freq)); + } + _ => {} + } + } + } + } + let hsi = config.hsi.then(|| { RCC.cr().modify(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} @@ -559,27 +606,13 @@ impl MsiFraction { } } -/// Get the calibration fraction for a given MSI range -/// Based on STM32U5 datasheet table for LSE = 32.768 kHz fn get_msi_calibration_fraction(range: Msirange) -> MsiFraction { - match range { - Msirange::RANGE_48MHZ => MsiFraction::new(1465, 1), // Range 0: 48.005 MHz - Msirange::RANGE_24MHZ => MsiFraction::new(1465, 2), // Range 1: 24.003 MHz - Msirange::RANGE_16MHZ => MsiFraction::new(1465, 3), // Range 2: 16.002 MHz - Msirange::RANGE_12MHZ => MsiFraction::new(1465, 4), // Range 3: 12.001 MHz - Msirange::RANGE_4MHZ => MsiFraction::new(122, 1), // Range 4: 3.998 MHz - Msirange::RANGE_2MHZ => MsiFraction::new(61, 1), // Range 5: 1.999 MHz - Msirange::RANGE_1_33MHZ => MsiFraction::new(122, 3), // Range 6: 1.333 MHz - Msirange::RANGE_1MHZ => MsiFraction::new(61, 2), // Range 7: 0.999 MHz - Msirange::RANGE_3_072MHZ => MsiFraction::new(94, 1), // Range 8: 3.08 MHz - Msirange::RANGE_1_536MHZ => MsiFraction::new(47, 1), // Range 9: 1.54 MHz - Msirange::RANGE_1_024MHZ => MsiFraction::new(94, 3), // Range 10: 1.027 MHz - Msirange::RANGE_768KHZ => MsiFraction::new(47, 2), // Range 11: 0.77 MHz - Msirange::RANGE_400KHZ => MsiFraction::new(12, 1), // Range 12: 393 kHz - Msirange::RANGE_200KHZ => MsiFraction::new(6, 1), // Range 13: 196.6 kHz - Msirange::RANGE_133KHZ => MsiFraction::new(4, 1), // Range 14: 131 kHz - Msirange::RANGE_100KHZ => MsiFraction::new(3, 1), // Range 15: 98.3 kHz - } + // Exploiting the MSIx internals to make calculations compact + let denominator = (range as u32 & 0x03) + 1; + // Base multipliers are deduced from Table 82: MSI oscillator characteristics in data sheet + let numerator = [1465, 122, 94, 12][(range as u32 >> 2) as usize]; + + MsiFraction::new(numerator, denominator) } /// Calculate the calibrated MSI frequency for a given range and LSE frequency -- cgit From e9211682a1a7067ae3a1fac36f94d981aab44912 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 23 Jul 2025 12:23:51 +0200 Subject: stm32: do not run stm32c071rb tests. --- ci.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci.sh b/ci.sh index 6be6e98e4..94f70aae8 100755 --- a/ci.sh +++ b/ci.sh @@ -385,6 +385,9 @@ rm out/tests/pimoroni-pico-plus-2/pwm rm out/tests/rpi-pico/pwm rm out/tests/rpi-pico/cyw43-perf +# tests are implemented but the HIL test farm doesn't actually have this board yet +rm -rf out/tests/stm32c071rb + if [[ -z "${TELEPROBE_TOKEN-}" ]]; then echo No teleprobe token found, skipping running HIL tests exit -- cgit From 378035aa9171b3ff6ab3b6b49f5970151a99115f Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Wed, 23 Jul 2025 04:54:42 -0700 Subject: Added PLL HAL code for STM32WBA --- embassy-stm32/src/rcc/wba.rs | 188 +++++++++++++++++++++++++++-- examples/stm32wba/src/bin/usb_hs_serial.rs | 26 +++- 2 files changed, 202 insertions(+), 12 deletions(-) diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index b494997b3..30076b60d 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs @@ -1,9 +1,17 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale; use crate::pac::rcc::regs::Cfgr1; -pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk}; +pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk, Pllsrc as PllSource }; +use crate::pac::rcc::vals::Pllrge; use crate::pac::{FLASH, RCC}; +use crate::rcc::LSI_FREQ; use crate::time::Hertz; +#[cfg(all(peri_usb_otg_hs))] +pub use crate::pac::rcc::vals::Otghssel; + +#[cfg(all(peri_usb_otg_hs))] +pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG}; + /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); // HSE speed @@ -14,6 +22,39 @@ pub struct Hse { pub prescaler: HsePrescaler, } +#[derive(Clone, Copy)] +pub struct Pll { + /// The clock source for the PLL. + pub source: PllSource, + /// The PLL pre-divider. + /// + /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz. + pub pllm: u8, + /// The PLL multiplier. + /// + /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544 + /// MHz. The upper limit may be lower depending on the `Config { voltage_range }`. + pub mul: u8, + /// The divider for the P output. + /// + /// The P output is one of several options + /// that can be used to feed the SAI/MDF/ADF Clock mux's. + pub divp: Option, + /// The divider for the Q output. + /// + /// The Q ouput is one of severals options that can be used to feed the 48MHz clocks + /// and the OCTOSPI clock. It may also be used on the MDF/ADF clock mux's. + pub divq: Option, + /// The divider for the R output. + /// + /// When used to drive the system clock, `source` divided by `m` times `n` divided by `r` + /// must not exceed 160 MHz. System clocks above 55 MHz require a non-default + /// `Config { voltage_range }`. + pub divr: Option, + + pub frac: Option, +} + /// Clocks configuration #[derive(Clone, Copy)] pub struct Config { @@ -21,6 +62,9 @@ pub struct Config { pub hsi: bool, pub hse: Option, + // pll + pub pll1: Option, + // sysclk, buses. pub sys: Sysclk, pub ahb_pre: AHBPrescaler, @@ -29,7 +73,8 @@ pub struct Config { pub apb7_pre: APBPrescaler, // low speed LSI/LSE/RTC - pub ls: super::LsConfig, + pub lsi: super::LsConfig, + // pub lsi2: super::LsConfig, pub voltage_scale: VoltageScale, @@ -40,14 +85,16 @@ pub struct Config { impl Config { pub const fn new() -> Self { Config { - hse: None, hsi: true, + hse: None, + pll1: None, sys: Sysclk::HSI, ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, apb7_pre: APBPrescaler::DIV1, - ls: crate::rcc::LsConfig::new(), + lsi: crate::rcc::LsConfig::new(), + // lsi2: crate::rcc::LsConfig::new(), voltage_scale: VoltageScale::RANGE2, mux: super::mux::ClockMux::default(), } @@ -81,7 +128,7 @@ pub(crate) unsafe fn init(config: Config) { crate::pac::PWR.vosr().write(|w| w.set_vos(config.voltage_scale)); while !crate::pac::PWR.vosr().read().vosrdy() {} - let rtc = config.ls.init(); + let rtc = config.lsi.init(); let hsi = config.hsi.then(|| { hsi_enable(); @@ -99,11 +146,15 @@ pub(crate) unsafe fn init(config: Config) { HSE_FREQ }); + let pll_input = PllInput {hse, hsi }; + + let pll1 = init_pll(config.pll1, &pll_input, config.voltage_scale); + let sys_clk = match config.sys { Sysclk::HSE => hse.unwrap(), Sysclk::HSI => hsi.unwrap(), Sysclk::_RESERVED_1 => unreachable!(), - Sysclk::PLL1_R => todo!(), + Sysclk::PLL1_R => pll1.r.unwrap(), }; assert!(sys_clk.0 <= 100_000_000); @@ -157,6 +208,33 @@ pub(crate) unsafe fn init(config: Config) { w.set_ppre2(config.apb2_pre); }); + #[cfg(all(stm32wba, peri_usb_otg_hs))] + let usb_refck = match config.mux.otghssel { + Otghssel::HSE => hse, + Otghssel::HSE_DIV_2 => hse.map(|hse_val| hse_val / 2u8), + Otghssel::PLL1_P => pll1.p, + Otghssel::PLL1_P_DIV_2 => pll1.p.map(|pll1p_val| pll1p_val / 2u8), + }; + #[cfg(all(stm32wba, peri_usb_otg_hs))] + let usb_refck_sel = match usb_refck { + Some(clk_val) => match clk_val { + Hertz(16_000_000) => Usbrefcksel::MHZ16, + Hertz(19_200_000) => Usbrefcksel::MHZ19_2, + Hertz(20_000_000) => Usbrefcksel::MHZ20, + Hertz(24_000_000) => Usbrefcksel::MHZ24, + Hertz(26_000_000) => Usbrefcksel::MHZ26, + Hertz(32_000_000) => Usbrefcksel::MHZ32, + _ => panic!("cannot select OTG_HS reference clock with source frequency of {}, must be one of 16, 19.2, 20, 24, 26, 32 MHz", clk_val), + }, + None => Usbrefcksel::MHZ24, + }; + #[cfg(all(stm32wba, peri_usb_otg_hs))] + SYSCFG.otghsphycr().modify(|w| { + w.set_clksel(usb_refck_sel); + }); + + let lsi = config.lsi.lsi.then_some(LSI_FREQ); + config.mux.init(); set_clocks!( @@ -171,12 +249,104 @@ pub(crate) unsafe fn init(config: Config) { pclk2_tim: Some(pclk2_tim), rtc: rtc, hse: hse, + lsi: lsi, hsi: hsi, + pll1_p: pll1.p, + pll1_q: pll1.q, + pll1_r: pll1.r, // TODO lse: None, - lsi: None, - pll1_p: None, - pll1_q: None, ); } + +pub(super) struct PllInput { + pub hsi: Option, + pub hse: Option, +} + +#[allow(unused)] +#[derive(Default)] +pub(super) struct PllOutput { + pub p: Option, + pub q: Option, + pub r: Option, +} + +fn pll_enable(enabled: bool) { + RCC.cr().modify(|w| w.set_pllon(enabled)); + while RCC.cr().read().pllrdy() != enabled {} +} + +fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) -> PllOutput { + // Disable PLL + pll_enable(false); + + let Some(pll) = config else { return PllOutput::default() }; + + let src_freq = match pll.source { + PllSource::DISABLE => panic!("must not select PLL source as DISABLE"), + PllSource::HSE => unwrap!(input.hse), + PllSource::HSI => unwrap!(input.hsi), + PllSource::_RESERVED_1 => panic!("must not select RESERVED_1 source as DISABLE"), + }; + + // Calculate the reference clock, which is the source divided by m + let ref_freq = src_freq / pll.pllm; + // Check limits per RM0515 § 12.4.3 + assert!(Hertz::mhz(4) <= ref_freq && ref_freq <= Hertz::mhz(16)); + + // Check PLL clocks per RM0515 § 12.4.5 + let (vco_min, vco_max, out_max) = match voltage_range { + VoltageScale::RANGE1 => (Hertz::mhz(128), Hertz::mhz(544), Hertz::mhz(100)), + VoltageScale::RANGE2 => panic!("PLL is unavailable in voltage range 2"), + }; + + // Calculate the PLL VCO clock + let vco_freq = ref_freq * pll.mul; + assert!(vco_freq >= vco_min && vco_freq <= vco_max); + + // Calculate output clocks. + let p = pll.divp.map(|div| vco_freq / div); + let q = pll.divq.map(|div| vco_freq / div); + let r = pll.divr.map(|div| vco_freq / div); + for freq in [p, q, r] { + if let Some(freq) = freq { + assert!(freq <= out_max); + } + } + + let divr = RCC.pll1divr(); + divr.write(|w| { + w.set_plln(pll.mul as u16); + w.set_pllp(pll.divp.unwrap_or(1)); + w.set_pllq(pll.divq.unwrap_or(1)); + w.set_pllr(pll.divr.unwrap_or(1)); + // w.set_pllfracn(pll.frac.unwrap_or(1)); + }); + RCC.pll1fracr().write(|w| {w.set_pllfracn(pll.frac.unwrap_or(1));}); + + let input_range = match ref_freq.0 { + ..=8_000_000 => Pllrge::FREQ_4TO8MHZ, + _ => Pllrge::FREQ_8TO16MHZ, + }; + + macro_rules! write_fields { + ($w:ident) => { + $w.set_pllpen(pll.divp.is_some()); + $w.set_pllqen(pll.divq.is_some()); + $w.set_pllren(pll.divr.is_some()); + $w.set_pllfracen(pll.frac.is_some()); + $w.set_pllm(pll.pllm); + $w.set_pllsrc(pll.source); + $w.set_pllrge(input_range); + }; + } + + RCC.pll1cfgr().write(|w| {write_fields!(w);}); + + // Enable PLL + pll_enable(true); + + PllOutput{ p, q, r } +} \ No newline at end of file diff --git a/examples/stm32wba/src/bin/usb_hs_serial.rs b/examples/stm32wba/src/bin/usb_hs_serial.rs index 1ffd94906..be2d0a4e5 100644 --- a/examples/stm32wba/src/bin/usb_hs_serial.rs +++ b/examples/stm32wba/src/bin/usb_hs_serial.rs @@ -7,9 +7,10 @@ use embassy_executor::Spawner; use embassy_futures::join::join; use embassy_stm32::usb::{Driver, Instance}; use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; -use embassy_stm32::rcc::{VoltageScale, Hse, HsePrescaler, Sysclk, mux}; +use embassy_stm32::rcc::{VoltageScale, Hse, HsePrescaler, APBPrescaler, AHBPrescaler, Sysclk, mux}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; use embassy_usb::driver::EndpointError; +use embassy_stm32::rcc::PllSource; use embassy_usb::Builder; use panic_probe as _; @@ -23,12 +24,31 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); - // ── Run off the external 32 MHz crystal directly ── + // External HSE (32 MHz) setup config.rcc.hse = Some(Hse { prescaler: HsePrescaler::DIV1 }); - config.rcc.sys = Sysclk::HSE; + // route HSE into the USB‐OTG‐HS block config.rcc.mux.otghssel = mux::Otghssel::HSE; config.rcc.sys = Sysclk::HSE; + + // Fine-tune PLL1 dividers/multipliers + config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { + source: PllSource::HSE, + pllm: 2, // PLLM = 2 → HSE / 2 = 16 MHz input + mul: 12, // PLLN = 12 → 16 MHz * 12 = 192 MHz VCO + divp: Some(2), // PLLP = 2 → 96 MHz + divq: Some(2), // PLLQ = 2 → 96 MHz + divr: Some(2), // PLLR = 2 → 96 MHz + frac: Some(4096), // Fractional part (enabled) + }); + + + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV1; + config.rcc.apb2_pre = APBPrescaler::DIV1; + config.rcc.apb7_pre = APBPrescaler::DIV1; + + // voltage scale for max performance config.rcc.voltage_scale = VoltageScale::RANGE1; let p = embassy_stm32::init(config); -- cgit From 4abacac2522b93a7f1d44c353b81f5f5054ed7cc Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 23 Jul 2025 15:20:25 +0100 Subject: stm32/wb: Add memory manager to GATT example --- examples/stm32wb/src/bin/gatt_server.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs index 041dc0cf5..9864fa026 100644 --- a/examples/stm32wb/src/bin/gatt_server.rs +++ b/examples/stm32wb/src/bin/gatt_server.rs @@ -27,6 +27,7 @@ use embassy_stm32_wpan::hci::vendor::event::{self, AttributeHandle, VendorEvent} use embassy_stm32_wpan::hci::{BdAddr, Event}; use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp; use embassy_stm32_wpan::sub::ble::Ble; +use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; @@ -38,7 +39,7 @@ bind_interrupts!(struct Irqs{ const BLE_GAP_DEVICE_NAME_LENGTH: u8 = 7; #[embassy_executor::main] -async fn main(_spawner: Spawner) { +async fn main(spawner: Spawner) { /* How to make this work: @@ -70,6 +71,7 @@ async fn main(_spawner: Spawner) { let config = Config::default(); let mut mbox = TlMbox::init(p.IPCC, Irqs, config); + spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); @@ -221,6 +223,11 @@ async fn main(_spawner: Spawner) { } } +#[embassy_executor::task] +async fn run_mm_queue(memory_manager: mm::MemoryManager) { + memory_manager.run_queue().await; +} + fn get_bd_addr() -> BdAddr { let mut bytes = [0u8; 6]; -- cgit From af4a75e4932cdca2e3fecfde06c6ced39659873c Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 23 Jul 2025 15:33:27 +0100 Subject: stm32/build: Remove extra braces from generated code --- embassy-stm32/build.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index f4781380c..73860c64a 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1918,9 +1918,9 @@ fn main() { } g.extend(quote!( - pub fn gpio_block(n: usize) -> crate::pac::gpio::Gpio {{ - unsafe {{ crate::pac::gpio::Gpio::from_ptr((#gpio_base + #gpio_stride*n) as _) }} - }} + pub fn gpio_block(n: usize) -> crate::pac::gpio::Gpio { + unsafe { crate::pac::gpio::Gpio::from_ptr((#gpio_base + #gpio_stride*n) as _) } + } )); // ======== -- cgit From 978a007baf4e1ef345af7b7e622cecd1fc01e415 Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Wed, 23 Jul 2025 16:56:34 +0200 Subject: add missing `Debug` and `defmt::Format` derives for `embassy_rp::gpio` --- embassy-rp/src/gpio.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index 9b5faac15..f79bf8948 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs @@ -26,6 +26,7 @@ static QSPI_WAKERS: [AtomicWaker; QSPI_PIN_COUNT] = [const { AtomicWaker::new() /// Represents a digital input or output level. #[derive(Debug, Eq, PartialEq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Level { /// Logical low. Low, @@ -53,6 +54,7 @@ impl From for bool { /// Represents a pull setting for an input. #[derive(Debug, Clone, Copy, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Pull { /// No pull. None, @@ -64,6 +66,7 @@ pub enum Pull { /// Drive strength of an output #[derive(Debug, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Drive { /// 2 mA drive. _2mA, @@ -76,6 +79,7 @@ pub enum Drive { } /// Slew rate of an output #[derive(Debug, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SlewRate { /// Fast slew rate. Fast, @@ -85,6 +89,7 @@ pub enum SlewRate { /// A GPIO bank with up to 32 pins. #[derive(Debug, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Bank { /// Bank 0. Bank0 = 0, @@ -108,6 +113,8 @@ pub struct DormantWakeConfig { } /// GPIO input driver. +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Input<'d> { pin: Flex<'d>, } @@ -358,6 +365,8 @@ impl<'d> Future for InputFuture<'d> { } /// GPIO output driver. +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Output<'d> { pin: Flex<'d>, } @@ -445,6 +454,8 @@ impl<'d> Output<'d> { } /// GPIO output open-drain. +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct OutputOpenDrain<'d> { pin: Flex<'d>, } @@ -592,6 +603,8 @@ impl<'d> OutputOpenDrain<'d> { /// This pin can be either an input or output pin. The output level register bit will remain /// set while not in output mode, so the pin's level will be 'remembered' when it is not in output /// mode. +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Flex<'d> { pin: Peri<'d, AnyPin>, } @@ -864,6 +877,8 @@ impl<'d> Drop for Flex<'d> { } /// Dormant wake driver. +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DormantWake<'w> { pin: Peri<'w, AnyPin>, cfg: DormantWakeConfig, -- cgit From b4dc4e567c7eda25fe533c7fa771466d1628cb90 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Wed, 23 Jul 2025 09:50:18 -0700 Subject: Cargo fmt --- examples/stm32wba/src/bin/usb_hs_serial.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/examples/stm32wba/src/bin/usb_hs_serial.rs b/examples/stm32wba/src/bin/usb_hs_serial.rs index be2d0a4e5..d77a679fe 100644 --- a/examples/stm32wba/src/bin/usb_hs_serial.rs +++ b/examples/stm32wba/src/bin/usb_hs_serial.rs @@ -5,12 +5,12 @@ use defmt::{panic, *}; use defmt_rtt as _; // global logger use embassy_executor::Spawner; use embassy_futures::join::join; +use embassy_stm32::rcc::PllSource; +use embassy_stm32::rcc::{mux, AHBPrescaler, APBPrescaler, Hse, HsePrescaler, Sysclk, VoltageScale}; use embassy_stm32::usb::{Driver, Instance}; use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; -use embassy_stm32::rcc::{VoltageScale, Hse, HsePrescaler, APBPrescaler, AHBPrescaler, Sysclk, mux}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; use embassy_usb::driver::EndpointError; -use embassy_stm32::rcc::PllSource; use embassy_usb::Builder; use panic_probe as _; @@ -25,7 +25,9 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); // External HSE (32 MHz) setup - config.rcc.hse = Some(Hse { prescaler: HsePrescaler::DIV1 }); + config.rcc.hse = Some(Hse { + prescaler: HsePrescaler::DIV1, + }); // route HSE into the USB‐OTG‐HS block config.rcc.mux.otghssel = mux::Otghssel::HSE; @@ -33,16 +35,15 @@ async fn main(_spawner: Spawner) { // Fine-tune PLL1 dividers/multipliers config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { - source: PllSource::HSE, - pllm: 2, // PLLM = 2 → HSE / 2 = 16 MHz input - mul: 12, // PLLN = 12 → 16 MHz * 12 = 192 MHz VCO - divp: Some(2), // PLLP = 2 → 96 MHz - divq: Some(2), // PLLQ = 2 → 96 MHz - divr: Some(2), // PLLR = 2 → 96 MHz - frac: Some(4096), // Fractional part (enabled) + source: PllSource::HSE, + pllm: 2, // PLLM = 2 → HSE / 2 = 16 MHz input + mul: 12, // PLLN = 12 → 16 MHz * 12 = 192 MHz VCO + divp: Some(2), // PLLP = 2 → 96 MHz + divq: Some(2), // PLLQ = 2 → 96 MHz + divr: Some(2), // PLLR = 2 → 96 MHz + frac: Some(4096), // Fractional part (enabled) }); - config.rcc.ahb_pre = AHBPrescaler::DIV1; config.rcc.apb1_pre = APBPrescaler::DIV1; config.rcc.apb2_pre = APBPrescaler::DIV1; -- cgit From a52965dc5d3d0c706310998d3eda8bc15cd45b02 Mon Sep 17 00:00:00 2001 From: Brezak Date: Tue, 22 Jul 2025 20:56:46 +0200 Subject: embassy-executor: unsafe tasks as unsafe --- embassy-executor-macros/src/macros/task.rs | 15 ++++++++++++- embassy-executor/CHANGELOG.md | 1 + embassy-executor/tests/ui.rs | 1 + embassy-executor/tests/ui/task_safety_attribute.rs | 25 ++++++++++++++++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 embassy-executor/tests/ui/task_safety_attribute.rs diff --git a/embassy-executor-macros/src/macros/task.rs b/embassy-executor-macros/src/macros/task.rs index 1c5e3571d..f01cc3b6c 100644 --- a/embassy-executor-macros/src/macros/task.rs +++ b/embassy-executor-macros/src/macros/task.rs @@ -120,6 +120,18 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { task_inner.vis = syn::Visibility::Inherited; task_inner.sig.ident = task_inner_ident.clone(); + // Forcefully mark the inner task as safe. + // SAFETY: We only ever call task_inner in functions + // with the same safety preconditions as task_inner + task_inner.sig.unsafety = None; + let task_body = task_inner.body; + task_inner.body = quote! { + #[allow(unused_unsafe, reason = "Not all function bodies may require being in an unsafe block")] + unsafe { + #task_body + } + }; + // assemble the original input arguments, // including any attributes that may have // been applied previously @@ -186,6 +198,7 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { // Copy the generics + where clause to avoid more spurious errors. let generics = &f.sig.generics; let where_clause = &f.sig.generics.where_clause; + let unsafety = &f.sig.unsafety; let result = quote! { // This is the user's task function, renamed. @@ -196,7 +209,7 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { #task_inner #(#task_outer_attrs)* - #visibility fn #task_ident #generics (#fargs) -> #embassy_executor::SpawnToken #where_clause{ + #visibility #unsafety fn #task_ident #generics (#fargs) -> #embassy_executor::SpawnToken #where_clause{ #task_outer_body } diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 914863a83..7404961f3 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added support for `-> impl Future` in `#[task]` - Fixed `Send` unsoundness with `-> impl Future` tasks - Marked `Spawner::for_current_executor` as `unsafe` +- `#[task]` now properly marks the generated function as unsafe if the task is marked unsafe ## 0.7.0 - 2025-01-02 diff --git a/embassy-executor/tests/ui.rs b/embassy-executor/tests/ui.rs index 7757775ee..8b83cd368 100644 --- a/embassy-executor/tests/ui.rs +++ b/embassy-executor/tests/ui.rs @@ -32,4 +32,5 @@ fn ui() { t.compile_fail("tests/ui/self.rs"); t.compile_fail("tests/ui/type_error.rs"); t.compile_fail("tests/ui/where_clause.rs"); + t.pass("tests/ui/task_safety_attribute.rs"); } diff --git a/embassy-executor/tests/ui/task_safety_attribute.rs b/embassy-executor/tests/ui/task_safety_attribute.rs new file mode 100644 index 000000000..ab5a2f99f --- /dev/null +++ b/embassy-executor/tests/ui/task_safety_attribute.rs @@ -0,0 +1,25 @@ +#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] +#![deny(unused_unsafe)] + +use std::mem; + +#[embassy_executor::task] +async fn safe() {} + +#[embassy_executor::task] +async unsafe fn not_safe() {} + +#[export_name = "__pender"] +fn pender(_: *mut ()) { + // The test doesn't link if we don't include this. + // We never call this anyway. +} + +fn main() { + let _forget_me = safe(); + // SAFETY: not_safe has not safety preconditions + let _forget_me2 = unsafe { not_safe() }; + + mem::forget(_forget_me); + mem::forget(_forget_me2); +} -- cgit From 1b42e624246f9355a91ef98ddf96d5af1b9b3687 Mon Sep 17 00:00:00 2001 From: Brezak Date: Wed, 23 Jul 2025 19:20:09 +0200 Subject: embassy-executor: explicitly return impl Future in task inner task --- embassy-executor-macros/src/macros/task.rs | 78 ++++++++++++++-------- .../tests/ui/nonstatic_struct_elided.stderr | 14 ++++ 2 files changed, 66 insertions(+), 26 deletions(-) diff --git a/embassy-executor-macros/src/macros/task.rs b/embassy-executor-macros/src/macros/task.rs index f01cc3b6c..5b360b128 100644 --- a/embassy-executor-macros/src/macros/task.rs +++ b/embassy-executor-macros/src/macros/task.rs @@ -112,25 +112,11 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { } } - let task_ident = f.sig.ident.clone(); - let task_inner_ident = format_ident!("__{}_task", task_ident); - - let mut task_inner = f.clone(); - let visibility = task_inner.vis.clone(); - task_inner.vis = syn::Visibility::Inherited; - task_inner.sig.ident = task_inner_ident.clone(); - - // Forcefully mark the inner task as safe. - // SAFETY: We only ever call task_inner in functions - // with the same safety preconditions as task_inner - task_inner.sig.unsafety = None; - let task_body = task_inner.body; - task_inner.body = quote! { - #[allow(unused_unsafe, reason = "Not all function bodies may require being in an unsafe block")] - unsafe { - #task_body - } - }; + // Copy the generics + where clause to avoid more spurious errors. + let generics = &f.sig.generics; + let where_clause = &f.sig.generics.where_clause; + let unsafety = &f.sig.unsafety; + let visibility = &f.vis; // assemble the original input arguments, // including any attributes that may have @@ -143,6 +129,51 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { )); } + let task_ident = f.sig.ident.clone(); + let task_inner_ident = format_ident!("__{}_task", task_ident); + + let task_inner_future_output = match &f.sig.output { + ReturnType::Default => quote! {-> impl ::core::future::Future}, + // Special case the never type since we can't stuff it into a `impl Future` + ReturnType::Type(arrow, maybe_never) if matches!(**maybe_never, Type::Never(_)) => quote! { + #arrow #maybe_never + }, + // Grab the arrow span, why not + ReturnType::Type(arrow, typ) if f.sig.asyncness.is_some() => quote! { + #arrow impl ::core::future::Future + }, + // We assume that if `f` isn't async, it must return `-> impl Future<...>` + // This is checked using traits later + ReturnType::Type(arrow, typ) => quote! { + #arrow #typ + }, + }; + + let task_inner_body = if errors.is_empty() { + quote! { + #f + + // SAFETY: All the preconditions to `#task_ident` apply to + // all contexts `#task_inner_ident` is called in + #unsafety { + #task_ident(#(#full_args,)*) + } + } + } else { + quote! { + async {::core::todo!()} + } + }; + + let task_inner = quote! { + #visibility fn #task_inner_ident #generics (#fargs) + #task_inner_future_output + #where_clause + { + #task_inner_body + } + }; + let spawn = if returns_impl_trait { quote!(spawn) } else { @@ -185,7 +216,7 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { unsafe { __task_pool_get(#task_inner_ident).#spawn(move || #task_inner_ident(#(#full_args,)*)) } }; - let task_outer_attrs = task_inner.attrs.clone(); + let task_outer_attrs = &f.attrs; if !errors.is_empty() { task_outer_body = quote! { @@ -195,11 +226,6 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { }; } - // Copy the generics + where clause to avoid more spurious errors. - let generics = &f.sig.generics; - let where_clause = &f.sig.generics.where_clause; - let unsafety = &f.sig.unsafety; - let result = quote! { // This is the user's task function, renamed. // We put it outside the #task_ident fn below, because otherwise @@ -226,7 +252,7 @@ fn check_arg_ty(errors: &mut TokenStream, ty: &Type) { impl<'a, 'ast> Visit<'ast> for Visitor<'a> { fn visit_type_reference(&mut self, i: &'ast syn::TypeReference) { - // only check for elided lifetime here. If not elided, it's checked by `visit_lifetime`. + // Only check for elided lifetime here. If not elided, it's checked by `visit_lifetime`. if i.lifetime.is_none() { error( self.errors, diff --git a/embassy-executor/tests/ui/nonstatic_struct_elided.stderr b/embassy-executor/tests/ui/nonstatic_struct_elided.stderr index 099ef8b4e..0ee1bfe0c 100644 --- a/embassy-executor/tests/ui/nonstatic_struct_elided.stderr +++ b/embassy-executor/tests/ui/nonstatic_struct_elided.stderr @@ -8,3 +8,17 @@ help: indicate the anonymous lifetime | 6 | async fn task(_x: Foo<'_>) {} | ++++ + +error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds + --> tests/ui/nonstatic_struct_elided.rs:5:1 + | +5 | #[embassy_executor::task] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type defined here +6 | async fn task(_x: Foo) {} + | --- hidden type `impl Sized` captures the anonymous lifetime defined here + | + = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add a `use<...>` bound to explicitly capture `'_` + | +5 | #[embassy_executor::task] + use<'_> + | +++++++++ -- cgit From 539ff78ebbdedbb75d0faf940e3ee69f5e7f276a Mon Sep 17 00:00:00 2001 From: Brezak Date: Wed, 23 Jul 2025 19:51:31 +0200 Subject: embassy-executor: explicitly return impl Future in task inner task --- embassy-executor-macros/src/macros/task.rs | 19 ++++++++++++++++--- embassy-executor/src/lib.rs | 8 ++++---- embassy-executor/tests/test.rs | 11 ++++++++++- .../tests/ui/bad_return_impl_future_nightly.stderr | 2 +- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/embassy-executor-macros/src/macros/task.rs b/embassy-executor-macros/src/macros/task.rs index 5b360b128..fc8673743 100644 --- a/embassy-executor-macros/src/macros/task.rs +++ b/embassy-executor-macros/src/macros/task.rs @@ -5,7 +5,7 @@ use darling::FromMeta; use proc_macro2::{Span, TokenStream}; use quote::{format_ident, quote}; use syn::visit::{self, Visit}; -use syn::{Expr, ExprLit, Lit, LitInt, ReturnType, Type}; +use syn::{Expr, ExprLit, Lit, LitInt, ReturnType, Type, Visibility}; use crate::util::*; @@ -135,6 +135,13 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { let task_inner_future_output = match &f.sig.output { ReturnType::Default => quote! {-> impl ::core::future::Future}, // Special case the never type since we can't stuff it into a `impl Future` + ReturnType::Type(arrow, maybe_never) + if f.sig.asyncness.is_some() && matches!(**maybe_never, Type::Never(_)) => + { + quote! { + #arrow impl ::core::future::Future + } + } ReturnType::Type(arrow, maybe_never) if matches!(**maybe_never, Type::Never(_)) => quote! { #arrow #maybe_never }, @@ -149,14 +156,20 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { }, }; + // We have to rename the function since it might be recursive; + let mut task_inner_function = f.clone(); + let task_inner_function_ident = format_ident!("__{}_task_inner_function", task_ident); + task_inner_function.sig.ident = task_inner_function_ident.clone(); + task_inner_function.vis = Visibility::Inherited; + let task_inner_body = if errors.is_empty() { quote! { - #f + #task_inner_function // SAFETY: All the preconditions to `#task_ident` apply to // all contexts `#task_inner_ident` is called in #unsafety { - #task_ident(#(#full_args,)*) + #task_inner_function_ident(#(#full_args,)*) } } } else { diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index e174a0594..0747db032 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -216,7 +216,7 @@ pub mod _export { ); #[allow(dead_code)] - trait HasOutput { + pub trait HasOutput { type Output; } @@ -225,7 +225,7 @@ pub mod _export { } #[allow(dead_code)] - type Never = ! as HasOutput>::Output; + pub type Never = ! as HasOutput>::Output; } /// Implementation details for embassy macros. @@ -242,7 +242,7 @@ pub mod _export { impl TaskReturnValue for Never {} #[allow(dead_code)] - trait HasOutput { + pub trait HasOutput { type Output; } @@ -251,5 +251,5 @@ pub mod _export { } #[allow(dead_code)] - type Never = ! as HasOutput>::Output; + pub type Never = ! as HasOutput>::Output; } diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs index c1e7ec5d7..b84d3785a 100644 --- a/embassy-executor/tests/test.rs +++ b/embassy-executor/tests/test.rs @@ -7,7 +7,7 @@ use std::sync::{Arc, Mutex}; use std::task::Poll; use embassy_executor::raw::Executor; -use embassy_executor::task; +use embassy_executor::{task, Spawner}; #[export_name = "__pender"] fn __pender(context: *mut ()) { @@ -317,3 +317,12 @@ fn executor_task_cfg_args() { let (_, _, _) = (a, b, c); } } + +#[test] +fn recursive_task() { + #[embassy_executor::task(pool_size = 2)] + async fn task1() { + let spawner = unsafe { Spawner::for_current_executor().await }; + spawner.spawn(task1()); + } +} diff --git a/embassy-executor/tests/ui/bad_return_impl_future_nightly.stderr b/embassy-executor/tests/ui/bad_return_impl_future_nightly.stderr index 73ceb989d..3c3c9503b 100644 --- a/embassy-executor/tests/ui/bad_return_impl_future_nightly.stderr +++ b/embassy-executor/tests/ui/bad_return_impl_future_nightly.stderr @@ -7,4 +7,4 @@ error[E0277]: task futures must resolve to `()` or `!` = note: use `async fn` or change the return type to `impl Future` = help: the following other types implement trait `TaskReturnValue`: () - ! as _export::HasOutput>::Output + ! as HasOutput>::Output -- cgit From 54d9a7fed3ab211b1049aae0af0bc49f912c9df4 Mon Sep 17 00:00:00 2001 From: Brezak Date: Wed, 23 Jul 2025 21:17:12 +0200 Subject: embassy-executor: add macro ui test for unsafe ops in unsafe tasks Check if the #[task] macro properly handles unsafe functions so the `unsafe_op_in_unsafe_fn` lint still works --- embassy-executor/tests/ui.rs | 2 ++ embassy-executor/tests/ui/unsafe_op_in_unsafe_task.rs | 10 ++++++++++ .../tests/ui/unsafe_op_in_unsafe_task.stderr | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 embassy-executor/tests/ui/unsafe_op_in_unsafe_task.rs create mode 100644 embassy-executor/tests/ui/unsafe_op_in_unsafe_task.stderr diff --git a/embassy-executor/tests/ui.rs b/embassy-executor/tests/ui.rs index 8b83cd368..5486a0624 100644 --- a/embassy-executor/tests/ui.rs +++ b/embassy-executor/tests/ui.rs @@ -32,5 +32,7 @@ fn ui() { t.compile_fail("tests/ui/self.rs"); t.compile_fail("tests/ui/type_error.rs"); t.compile_fail("tests/ui/where_clause.rs"); + t.compile_fail("tests/ui/unsafe_op_in_unsafe_task.rs"); + t.pass("tests/ui/task_safety_attribute.rs"); } diff --git a/embassy-executor/tests/ui/unsafe_op_in_unsafe_task.rs b/embassy-executor/tests/ui/unsafe_op_in_unsafe_task.rs new file mode 100644 index 000000000..ee7924838 --- /dev/null +++ b/embassy-executor/tests/ui/unsafe_op_in_unsafe_task.rs @@ -0,0 +1,10 @@ +#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] +#![deny(unsafe_op_in_unsafe_fn)] + +#[embassy_executor::task] +async unsafe fn task() { + let x = 5; + (&x as *const i32).read(); +} + +fn main() {} diff --git a/embassy-executor/tests/ui/unsafe_op_in_unsafe_task.stderr b/embassy-executor/tests/ui/unsafe_op_in_unsafe_task.stderr new file mode 100644 index 000000000..d987a4b95 --- /dev/null +++ b/embassy-executor/tests/ui/unsafe_op_in_unsafe_task.stderr @@ -0,0 +1,18 @@ +error[E0133]: call to unsafe function `std::ptr::const_ptr::::read` is unsafe and requires unsafe block + --> tests/ui/unsafe_op_in_unsafe_task.rs:7:5 + | +7 | (&x as *const i32).read(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: for more information, see + = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> tests/ui/unsafe_op_in_unsafe_task.rs:5:1 + | +5 | async unsafe fn task() { + | ^^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> tests/ui/unsafe_op_in_unsafe_task.rs:2:9 + | +2 | #![deny(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ -- cgit From c5565ccc288863b7d7e5a82aa42141eb7a1cff9f Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Wed, 23 Jul 2025 15:05:04 -0700 Subject: Working USB. Still no enumeration --- embassy-stm32/Cargo.toml | 4 ++-- embassy-stm32/src/rcc/wba.rs | 23 +++++++++++++---------- embassy-stm32/src/usb/otg.rs | 2 +- examples/stm32wba/src/bin/usb_hs_serial.rs | 10 +++++----- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 38254ee40..b5b734910 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9fc86ca7b3a8bc05182bf1ce3045602df1f5dce3" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-dbdc1a4ea26229805def4738b777933803086f93" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9fc86ca7b3a8bc05182bf1ce3045602df1f5dce3", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-dbdc1a4ea26229805def4738b777933803086f93", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index 30076b60d..4ca622614 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs @@ -1,6 +1,9 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale; use crate::pac::rcc::regs::Cfgr1; -pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk, Pllsrc as PllSource }; +pub use crate::pac::rcc::vals::{ + Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk, Pllsrc as PllSource, + Plldiv as PllDiv, Pllm, Plln as PllMul, +}; use crate::pac::rcc::vals::Pllrge; use crate::pac::{FLASH, RCC}; use crate::rcc::LSI_FREQ; @@ -29,28 +32,28 @@ pub struct Pll { /// The PLL pre-divider. /// /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz. - pub pllm: u8, + pub pllm: Pllm, /// The PLL multiplier. /// /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544 /// MHz. The upper limit may be lower depending on the `Config { voltage_range }`. - pub mul: u8, + pub mul: PllMul, /// The divider for the P output. /// /// The P output is one of several options /// that can be used to feed the SAI/MDF/ADF Clock mux's. - pub divp: Option, + pub divp: Option, /// The divider for the Q output. /// /// The Q ouput is one of severals options that can be used to feed the 48MHz clocks /// and the OCTOSPI clock. It may also be used on the MDF/ADF clock mux's. - pub divq: Option, + pub divq: Option, /// The divider for the R output. /// /// When used to drive the system clock, `source` divided by `m` times `n` divided by `r` /// must not exceed 160 MHz. System clocks above 55 MHz require a non-default /// `Config { voltage_range }`. - pub divr: Option, + pub divr: Option, pub frac: Option, } @@ -318,10 +321,10 @@ fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) let divr = RCC.pll1divr(); divr.write(|w| { - w.set_plln(pll.mul as u16); - w.set_pllp(pll.divp.unwrap_or(1)); - w.set_pllq(pll.divq.unwrap_or(1)); - w.set_pllr(pll.divr.unwrap_or(1)); + w.set_plln(pll.mul); + w.set_pllp(pll.divp.unwrap_or(PllDiv::DIV1)); + w.set_pllq(pll.divq.unwrap_or(PllDiv::DIV1)); + w.set_pllr(pll.divr.unwrap_or(PllDiv::DIV1)); // w.set_pllfracn(pll.frac.unwrap_or(1)); }); RCC.pll1fracr().write(|w| {w.set_pllfracn(pll.frac.unwrap_or(1));}); diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index c8499bdc7..02b27ed48 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -336,7 +336,7 @@ impl<'d, T: Instance> Bus<'d, T> { critical_section::with(|_| { crate::pac::RCC.ahb2enr().modify(|w| { w.set_usb_otg_hsen(true); - w.set_otghsphyen(true); + w.set_usb_otg_hs_phyen(true); }); }); } diff --git a/examples/stm32wba/src/bin/usb_hs_serial.rs b/examples/stm32wba/src/bin/usb_hs_serial.rs index d77a679fe..e30f33625 100644 --- a/examples/stm32wba/src/bin/usb_hs_serial.rs +++ b/examples/stm32wba/src/bin/usb_hs_serial.rs @@ -36,11 +36,11 @@ async fn main(_spawner: Spawner) { // Fine-tune PLL1 dividers/multipliers config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { source: PllSource::HSE, - pllm: 2, // PLLM = 2 → HSE / 2 = 16 MHz input - mul: 12, // PLLN = 12 → 16 MHz * 12 = 192 MHz VCO - divp: Some(2), // PLLP = 2 → 96 MHz - divq: Some(2), // PLLQ = 2 → 96 MHz - divr: Some(2), // PLLR = 2 → 96 MHz + pllm: 2.into(), // PLLM = 2 → HSE / 2 = 16 MHz input + mul: 12.into(), // PLLN = 12 → 16 MHz * 12 = 192 MHz VCO + divp: Some(2.into()), // PLLP = 2 → 96 MHz + divq: Some(2.into()), // PLLQ = 2 → 96 MHz + divr: Some(2.into()), // PLLR = 2 → 96 MHz frac: Some(4096), // Fractional part (enabled) }); -- cgit From f819b0d63c4b670f2aef3e8e9b35b0745090052d Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Wed, 23 Jul 2025 16:51:33 +0200 Subject: feat(embedded-hal)!: rely on v1.0 traits for `SpiBus` on `BlockingAsync` --- embassy-embedded-hal/src/adapter/blocking_async.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/embassy-embedded-hal/src/adapter/blocking_async.rs b/embassy-embedded-hal/src/adapter/blocking_async.rs index bafc31583..bc965fbdd 100644 --- a/embassy-embedded-hal/src/adapter/blocking_async.rs +++ b/embassy-embedded-hal/src/adapter/blocking_async.rs @@ -63,16 +63,16 @@ where impl embedded_hal_async::spi::ErrorType for BlockingAsync where - E: embedded_hal_1::spi::Error, - T: blocking::spi::Transfer + blocking::spi::Write, + E: embedded_hal_async::spi::Error, + T: embedded_hal_1::spi::SpiBus, { type Error = E; } impl embedded_hal_async::spi::SpiBus for BlockingAsync where - E: embedded_hal_1::spi::Error + 'static, - T: blocking::spi::Transfer + blocking::spi::Write, + E: embedded_hal_async::spi::Error, + T: embedded_hal_1::spi::SpiBus, { async fn flush(&mut self) -> Result<(), Self::Error> { Ok(()) @@ -84,21 +84,17 @@ where } async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { - self.wrapped.transfer(data)?; + self.wrapped.read(data)?; Ok(()) } async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { - // Ensure we write the expected bytes - for i in 0..core::cmp::min(read.len(), write.len()) { - read[i] = write[i].clone(); - } - self.wrapped.transfer(read)?; + self.wrapped.transfer(read, write)?; Ok(()) } async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { - self.wrapped.transfer(data)?; + self.wrapped.transfer_in_place(data)?; Ok(()) } } -- cgit From 00824a900c6babf9727708357527b2a2807aa673 Mon Sep 17 00:00:00 2001 From: ROMemories <152802150+ROMemories@users.noreply.github.com> Date: Wed, 23 Jul 2025 17:08:54 +0200 Subject: feat(embedded-hal)!: rely on v1.0 traits for `I2c` on `BlockingAsync` --- embassy-embedded-hal/src/adapter/blocking_async.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/embassy-embedded-hal/src/adapter/blocking_async.rs b/embassy-embedded-hal/src/adapter/blocking_async.rs index bc965fbdd..3b6e0ec00 100644 --- a/embassy-embedded-hal/src/adapter/blocking_async.rs +++ b/embassy-embedded-hal/src/adapter/blocking_async.rs @@ -1,5 +1,3 @@ -use embedded_hal_02::blocking; - /// Wrapper that implements async traits using blocking implementations. /// /// This allows driver writers to depend on the async traits while still supporting embedded-hal peripheral implementations. @@ -24,7 +22,7 @@ impl BlockingAsync { impl embedded_hal_1::i2c::ErrorType for BlockingAsync where E: embedded_hal_1::i2c::Error + 'static, - T: blocking::i2c::WriteRead + blocking::i2c::Read + blocking::i2c::Write, + T: embedded_hal_1::i2c::I2c, { type Error = E; } @@ -32,7 +30,7 @@ where impl embedded_hal_async::i2c::I2c for BlockingAsync where E: embedded_hal_1::i2c::Error + 'static, - T: blocking::i2c::WriteRead + blocking::i2c::Read + blocking::i2c::Write, + T: embedded_hal_1::i2c::I2c, { async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { self.wrapped.read(address, read) @@ -51,9 +49,7 @@ where address: u8, operations: &mut [embedded_hal_1::i2c::Operation<'_>], ) -> Result<(), Self::Error> { - let _ = address; - let _ = operations; - todo!() + self.wrapped.transaction(address, operations) } } -- cgit From fd3cdfcf251225fb333870f0341ae9ce416f54ad Mon Sep 17 00:00:00 2001 From: Frank Stevenson Date: Thu, 24 Jul 2025 13:26:10 +0200 Subject: Introduce configration options for Pll fast modes. Ensure that the auto calibration is applied to an active clock. --- embassy-stm32/src/rcc/u5.rs | 54 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index 0c7dc8ecc..ae0ef73f4 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -5,7 +5,7 @@ pub use crate::pac::rcc::vals::{ Hpre as AHBPrescaler, Msirange, Msirange as MSIRange, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk, }; -use crate::pac::rcc::vals::{Hseext, Msipllsel, Msirgsel, Pllmboost, Pllrge}; +use crate::pac::rcc::vals::{Hseext, Msipllfast, Msipllsel, Msirgsel, Pllmboost, Pllrge}; #[cfg(all(peri_usb_otg_hs))] pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG}; use crate::pac::{FLASH, PWR, RCC}; @@ -72,12 +72,30 @@ pub enum MsiAutoCalibration { MSIS, /// MSIK is given priority for auto-calibration MSIK, + /// MSIS with fast mode (always on) + MsisFast, + /// MSIK with fast mode (always on) + MsikFast, } impl MsiAutoCalibration { const fn default() -> Self { MsiAutoCalibration::Disabled } + + fn base_mode(&self) -> Self { + match self { + MsiAutoCalibration::Disabled => MsiAutoCalibration::Disabled, + MsiAutoCalibration::MSIS => MsiAutoCalibration::MSIS, + MsiAutoCalibration::MSIK => MsiAutoCalibration::MSIK, + MsiAutoCalibration::MsisFast => MsiAutoCalibration::MSIS, + MsiAutoCalibration::MsikFast => MsiAutoCalibration::MSIK, + } + } + + fn is_fast(&self) -> bool { + matches!(self, MsiAutoCalibration::MsisFast | MsiAutoCalibration::MsikFast) + } } impl Default for MsiAutoCalibration { @@ -159,7 +177,23 @@ pub(crate) unsafe fn init(config: Config) { Some(lse_config) => { // Allow +/- 5% tolerance for LSE frequency if lse_config.peripherals_clocked && (31_100..=34_400).contains(&lse_config.frequency.0) { - Some(lse_config.frequency) + // Check that the calibration is applied to an active clock + match ( + config.auto_calibration.base_mode(), + config.msis.is_some(), + config.msik.is_some(), + ) { + (MsiAutoCalibration::MSIS, true, _) => { + // MSIS is active and using LSE for auto-calibration + Some(lse_config.frequency) + } + (MsiAutoCalibration::MSIK, _, true) => { + // MSIK is active and using LSE for auto-calibration + Some(lse_config.frequency) + } + // improper configuration, no LSE calibration + _ => None, + } } else { None } @@ -192,7 +226,9 @@ pub(crate) unsafe fn init(config: Config) { w.set_msipllen(false); w.set_msison(true); }); - let msis = if let (Some(freq), MsiAutoCalibration::MSIS) = (lse_calibration_freq, config.auto_calibration) { + let msis = if let (Some(freq), MsiAutoCalibration::MSIS) = + (lse_calibration_freq, config.auto_calibration.base_mode()) + { // Enable the MSIS auto-calibration feature RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIS)); RCC.cr().modify(|w| w.set_msipllen(true)); @@ -228,7 +264,9 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().modify(|w| { w.set_msikon(true); }); - let msik = if let (Some(freq), MsiAutoCalibration::MSIK) = (lse_calibration_freq, config.auto_calibration) { + let msik = if let (Some(freq), MsiAutoCalibration::MSIK) = + (lse_calibration_freq, config.auto_calibration.base_mode()) + { // Enable the MSIK auto-calibration feature RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIK)); RCC.cr().modify(|w| w.set_msipllen(true)); @@ -242,10 +280,16 @@ pub(crate) unsafe fn init(config: Config) { // If both MSIS and MSIK are enabled, we need to check if they are using the same internal source. if let Some(lse_freq) = lse_calibration_freq { + // Check if Fast mode should be used + if config.auto_calibration.is_fast() { + RCC.cr().modify(|w| { + w.set_msipllfast(Msipllfast::FAST); + }); + } if let (Some(msis_range), Some(msik_range)) = (config.msis, config.msik) { if (msis_range as u8 >> 2) == (msik_range as u8 >> 2) { // Clock source is shared, both will be auto calibrated. - match config.auto_calibration { + match config.auto_calibration.base_mode() { MsiAutoCalibration::MSIS => { // MSIS and MSIK are using the same clock source, recalibrate msik = Some(calculate_calibrated_msi_frequency(msik_range, lse_freq)); -- cgit From 3394f3ab9d2c0640bbd0804d5fd28cc68153786d Mon Sep 17 00:00:00 2001 From: Frank Stevenson Date: Thu, 24 Jul 2025 13:51:35 +0200 Subject: Panic on improper auto-calibration configurations --- embassy-stm32/src/rcc/u5.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index ae0ef73f4..d12416a72 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -191,9 +191,8 @@ pub(crate) unsafe fn init(config: Config) { // MSIK is active and using LSE for auto-calibration Some(lse_config.frequency) } - // improper configuration, no LSE calibration - _ => None, - } + // improper configuration + _ => panic!("MSIx auto-calibration is enabled for a source that has not been configured.") } } else { None } -- cgit From aa243e4d3e51719d32314ba47ea68674ecc6c95e Mon Sep 17 00:00:00 2001 From: Frank Stevenson Date: Thu, 24 Jul 2025 18:08:29 +0200 Subject: Improved error checks, and some cleanup --- embassy-stm32/src/rcc/u5.rs | 72 ++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index d12416a72..7a7ffc939 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -173,31 +173,39 @@ pub(crate) unsafe fn init(config: Config) { PWR.vosr().modify(|w| w.set_vos(config.voltage_range)); while !PWR.vosr().read().vosrdy() {} - let lse_calibration_freq = match config.ls.lse { - Some(lse_config) => { - // Allow +/- 5% tolerance for LSE frequency - if lse_config.peripherals_clocked && (31_100..=34_400).contains(&lse_config.frequency.0) { - // Check that the calibration is applied to an active clock - match ( - config.auto_calibration.base_mode(), - config.msis.is_some(), - config.msik.is_some(), - ) { - (MsiAutoCalibration::MSIS, true, _) => { - // MSIS is active and using LSE for auto-calibration - Some(lse_config.frequency) - } - (MsiAutoCalibration::MSIK, _, true) => { - // MSIK is active and using LSE for auto-calibration - Some(lse_config.frequency) - } - // improper configuration - _ => panic!("MSIx auto-calibration is enabled for a source that has not been configured.") } - } else { - None + let lse_calibration_freq = if config.auto_calibration != MsiAutoCalibration::Disabled { + // LSE must be configured and peripherals clocked for MSI auto-calibration + let lse_config = config + .ls + .lse + .clone() + .expect("LSE must be configured for MSI auto-calibration"); + assert!(lse_config.peripherals_clocked); + + // Expect less than +/- 5% deviation for LSE frequency + if (31_100..=34_400).contains(&lse_config.frequency.0) { + // Check that the calibration is applied to an active clock + match ( + config.auto_calibration.base_mode(), + config.msis.is_some(), + config.msik.is_some(), + ) { + (MsiAutoCalibration::MSIS, true, _) => { + // MSIS is active and using LSE for auto-calibration + Some(lse_config.frequency) + } + (MsiAutoCalibration::MSIK, _, true) => { + // MSIK is active and using LSE for auto-calibration + Some(lse_config.frequency) + } + // improper configuration + _ => panic!("MSIx auto-calibration is enabled for a source that has not been configured."), } + } else { + panic!("LSE frequency more than 5% off from 32.768 kHz, cannot use for MSI auto-calibration"); } - _ => None, + } else { + None }; let mut msis = config.msis.map(|range| { @@ -277,30 +285,28 @@ pub(crate) unsafe fn init(config: Config) { msik }); - // If both MSIS and MSIK are enabled, we need to check if they are using the same internal source. if let Some(lse_freq) = lse_calibration_freq { - // Check if Fast mode should be used - if config.auto_calibration.is_fast() { - RCC.cr().modify(|w| { - w.set_msipllfast(Msipllfast::FAST); - }); - } + // If both MSIS and MSIK are enabled, we need to check if they are using the same internal source. if let (Some(msis_range), Some(msik_range)) = (config.msis, config.msik) { if (msis_range as u8 >> 2) == (msik_range as u8 >> 2) { - // Clock source is shared, both will be auto calibrated. + // Clock source is shared, both will be auto calibrated, recalculate other frequency match config.auto_calibration.base_mode() { MsiAutoCalibration::MSIS => { - // MSIS and MSIK are using the same clock source, recalibrate msik = Some(calculate_calibrated_msi_frequency(msik_range, lse_freq)); } MsiAutoCalibration::MSIK => { - // MSIS and MSIK are using the same clock source, recalibrate msis = Some(calculate_calibrated_msi_frequency(msis_range, lse_freq)); } _ => {} } } } + // Check if Fast mode should be used + if config.auto_calibration.is_fast() { + RCC.cr().modify(|w| { + w.set_msipllfast(Msipllfast::FAST); + }); + } } let hsi = config.hsi.then(|| { -- cgit From e4cb80be7cc74203259dbb82092f83a154bcd8a2 Mon Sep 17 00:00:00 2001 From: Rick Rogers Date: Thu, 24 Jul 2025 15:12:12 -0400 Subject: add pll divs/t for h7rs --- embassy-stm32/src/rcc/h.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index 383f48874..354824e26 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs @@ -8,6 +8,9 @@ use crate::pac::rcc::vals::{Pllrge, Pllvcosel, Timpre}; use crate::pac::{FLASH, PWR, RCC}; use crate::time::Hertz; +#[cfg(stm32h7rs)] +use stm32_metapac::rcc::vals::Plldivst; + /// HSI speed pub const HSI_FREQ: Hertz = Hertz(64_000_000); @@ -78,6 +81,12 @@ pub struct Pll { pub divq: Option, /// PLL R division factor. If None, PLL R output is disabled. pub divr: Option, + #[cfg(stm32h7rs)] + /// PLL S division factor. If None, PLL S output is disabled. + pub divs: Option, + #[cfg(stm32h7rs)] + /// PLL T division factor. If None, PLL T output is disabled. + pub divt: Option, } fn apb_div_tim(apb: &APBPrescaler, clk: Hertz, tim: TimerPrescaler) -> Hertz { -- cgit From 0d1e34d0fcc1fb995f0da46eede063cfbd9c962e Mon Sep 17 00:00:00 2001 From: Frank Stevenson Date: Thu, 24 Jul 2025 21:17:30 +0200 Subject: Minor cleanup --- embassy-stm32/src/rcc/u5.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index 7a7ffc939..06895a99a 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -659,7 +659,7 @@ fn get_msi_calibration_fraction(range: Msirange) -> MsiFraction { // Exploiting the MSIx internals to make calculations compact let denominator = (range as u32 & 0x03) + 1; // Base multipliers are deduced from Table 82: MSI oscillator characteristics in data sheet - let numerator = [1465, 122, 94, 12][(range as u32 >> 2) as usize]; + let numerator = [1465, 122, 94, 12][range as usize >> 2]; MsiFraction::new(numerator, denominator) } -- cgit From b49d809346bb420c7994c75fa0121f6d28870c05 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 24 Jul 2025 23:29:54 +0200 Subject: Add dedup to doc job. --- .github/ci/doc.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 90662af82..9162b37ae 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -1,5 +1,7 @@ #!/bin/bash ## on push branch=main +## priority -10 +## dedup dequeue set -euxo pipefail -- cgit From 915513753aea689f73d1300acc069ac985be3a0b Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 24 Jul 2025 23:30:36 +0200 Subject: Add dedup to book job. --- .github/ci/book.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ci/book.sh b/.github/ci/book.sh index 285cdc8fa..2466f53f5 100755 --- a/.github/ci/book.sh +++ b/.github/ci/book.sh @@ -1,5 +1,7 @@ #!/bin/bash ## on push branch=main +## priority -9 +## dedup dequeue set -euxo pipefail -- cgit From 9863406346fdf5defcb8fe8de4bb5d122fa0b05f Mon Sep 17 00:00:00 2001 From: Knaifhogg Date: Wed, 18 Jun 2025 08:26:12 +0200 Subject: fix: stm32 i2c slave blocking r/w This fixes an issue where the slave interface would time out when the master goes from a short write to a read (e.g. when accessing memory registers) with a START signal between. The previous implementation would expect the full buffer length to be written before starting to listen to new commands. This also adds debug trace printing which helped during implemention and testing. Places error checking into a function inspired from a C implementation of HAL. --- embassy-stm32/Cargo.toml | 1 + embassy-stm32/src/i2c/v2.rs | 278 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 221 insertions(+), 58 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 38254ee40..02e75733e 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -129,6 +129,7 @@ defmt = [ "embassy-net-driver/defmt", "embassy-time?/defmt", "embassy-usb-synopsys-otg/defmt", + "stm32-metapac/defmt" ] exti = [] diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 35dc91c86..e24cce5c6 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -36,11 +36,46 @@ impl Address { } } +enum ReceiveResult { + DataAvailable, + StopReceived, + NewStart, +} + +fn debug_print_interrupts(isr: stm32_metapac::i2c::regs::Isr) { + if isr.tcr() { + trace!("interrupt: tcr"); + } + if isr.tc() { + trace!("interrupt: tc"); + } + if isr.addr() { + trace!("interrupt: addr"); + } + if isr.stopf() { + trace!("interrupt: stopf"); + } + if isr.nackf() { + trace!("interrupt: nackf"); + } + if isr.berr() { + trace!("interrupt: berr"); + } + if isr.arlo() { + trace!("interrupt: arlo"); + } + if isr.ovr() { + trace!("interrupt: ovr"); + } +} + pub(crate) unsafe fn on_interrupt() { let regs = T::info().regs; let isr = regs.isr().read(); if isr.tcr() || isr.tc() || isr.addr() || isr.stopf() || isr.nackf() || isr.berr() || isr.arlo() || isr.ovr() { + debug_print_interrupts(isr); + T::state().waker.wake(); } @@ -193,49 +228,132 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { fn flush_txdr(&self) { if self.info.regs.isr().read().txis() { - self.info.regs.txdr().write(|w| w.set_txdata(0)); + trace!("Flush TXDATA with zeroes"); + self.info.regs.txdr().modify(|w| w.set_txdata(0)); } if !self.info.regs.isr().read().txe() { + trace!("Flush TXDR"); self.info.regs.isr().modify(|w| w.set_txe(true)) } } - fn wait_txe(&self, timeout: Timeout) -> Result<(), Error> { + fn error_occurred(&self, isr: &i2c::regs::Isr, timeout: Timeout) -> Result<(), Error> { + if isr.nackf() { + trace!("NACK triggered."); + self.info.regs.icr().modify(|reg| reg.set_nackcf(true)); + // NACK should be followed by STOP + if let Ok(()) = self.wait_stop(timeout) { + trace!("Got STOP after NACK, clearing flag."); + self.info.regs.icr().modify(|reg| reg.set_stopcf(true)); + } + self.flush_txdr(); + return Err(Error::Nack); + } else if isr.berr() { + trace!("BERR triggered."); + self.info.regs.icr().modify(|reg| reg.set_berrcf(true)); + self.flush_txdr(); + return Err(Error::Bus); + } else if isr.arlo() { + trace!("ARLO triggered."); + self.info.regs.icr().modify(|reg| reg.set_arlocf(true)); + self.flush_txdr(); + return Err(Error::Arbitration); + } else if isr.ovr() { + trace!("OVR triggered."); + self.info.regs.icr().modify(|reg| reg.set_ovrcf(true)); + return Err(Error::Overrun); + } + return Ok(()); + } + + fn wait_txis(&self, timeout: Timeout) -> Result<(), Error> { + let mut first_loop = true; + loop { let isr = self.info.regs.isr().read(); - if isr.txe() { + self.error_occurred(&isr, timeout)?; + if isr.txis() { + trace!("TXIS"); return Ok(()); - } else if isr.berr() { - self.info.regs.icr().write(|reg| reg.set_berrcf(true)); - return Err(Error::Bus); - } else if isr.arlo() { - self.info.regs.icr().write(|reg| reg.set_arlocf(true)); - return Err(Error::Arbitration); - } else if isr.nackf() { - self.info.regs.icr().write(|reg| reg.set_nackcf(true)); - self.flush_txdr(); - return Err(Error::Nack); } + { + if first_loop { + trace!("Waiting for TXIS..."); + first_loop = false; + } + } timeout.check()?; } } - fn wait_rxne(&self, timeout: Timeout) -> Result<(), Error> { + fn wait_stop_or_err(&self, timeout: Timeout) -> Result<(), Error> { + loop { + let isr = self.info.regs.isr().read(); + self.error_occurred(&isr, timeout)?; + if isr.stopf() { + trace!("STOP triggered."); + self.info.regs.icr().modify(|reg| reg.set_stopcf(true)); + return Ok(()); + } + timeout.check()?; + } + } + fn wait_stop(&self, timeout: Timeout) -> Result<(), Error> { loop { let isr = self.info.regs.isr().read(); - if isr.rxne() { + if isr.stopf() { + trace!("STOP triggered."); + self.info.regs.icr().modify(|reg| reg.set_stopcf(true)); return Ok(()); - } else if isr.berr() { - self.info.regs.icr().write(|reg| reg.set_berrcf(true)); - return Err(Error::Bus); - } else if isr.arlo() { - self.info.regs.icr().write(|reg| reg.set_arlocf(true)); - return Err(Error::Arbitration); - } else if isr.nackf() { - self.info.regs.icr().write(|reg| reg.set_nackcf(true)); - self.flush_txdr(); - return Err(Error::Nack); + } + timeout.check()?; + } + } + + fn wait_af(&self, timeout: Timeout) -> Result<(), Error> { + loop { + let isr = self.info.regs.isr().read(); + if isr.nackf() { + trace!("AF triggered."); + self.info.regs.icr().modify(|reg| reg.set_nackcf(true)); + return Ok(()); + } + timeout.check()?; + } + } + + fn wait_rxne(&self, timeout: Timeout) -> Result { + let mut first_loop = true; + + loop { + let isr = self.info.regs.isr().read(); + self.error_occurred(&isr, timeout)?; + if isr.stopf() { + trace!("STOP when waiting for RXNE."); + if self.info.regs.isr().read().rxne() { + trace!("Data received with STOP."); + return Ok(ReceiveResult::DataAvailable); + } + trace!("STOP triggered without data."); + return Ok(ReceiveResult::StopReceived); + } else if isr.rxne() { + trace!("RXNE."); + return Ok(ReceiveResult::DataAvailable); + } else if isr.addr() { + // Another addr event received, which means START was sent again + // which happens when accessing memory registers (common i2c interface design) + // e.g. master sends: START, write 1 byte (register index), START, read N bytes (until NACK) + // Possible to receive this flag at the same time as rxne, so check rxne first + trace!("START when waiting for RXNE. Ending receive loop."); + // Return without clearing ADDR so `listen` can catch it + return Ok(ReceiveResult::NewStart); + } + { + if first_loop { + trace!("Waiting for RXNE..."); + first_loop = false; + } } timeout.check()?; @@ -245,20 +363,10 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> { loop { let isr = self.info.regs.isr().read(); + self.error_occurred(&isr, timeout)?; if isr.tc() { return Ok(()); - } else if isr.berr() { - self.info.regs.icr().write(|reg| reg.set_berrcf(true)); - return Err(Error::Bus); - } else if isr.arlo() { - self.info.regs.icr().write(|reg| reg.set_arlocf(true)); - return Err(Error::Arbitration); - } else if isr.nackf() { - self.info.regs.icr().write(|reg| reg.set_nackcf(true)); - self.flush_txdr(); - return Err(Error::Nack); } - timeout.check()?; } } @@ -344,7 +452,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { // Wait until we are allowed to send data // (START has been ACKed or last byte when // through) - if let Err(err) = self.wait_txe(timeout) { + if let Err(err) = self.wait_txis(timeout) { if send_stop { self.master_stop(); } @@ -459,7 +567,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { // Wait until we are allowed to send data // (START has been ACKed or last byte when // through) - if let Err(err) = self.wait_txe(timeout) { + if let Err(err) = self.wait_txis(timeout) { self.master_stop(); return Err(err); } @@ -884,10 +992,11 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { // clear the address flag, will stop the clock stretching. // this should only be done after the dma transfer has been set up. info.regs.icr().modify(|reg| reg.set_addrcf(true)); + trace!("ADDRCF cleared (ADDR interrupt enabled, clock stretching ended)"); } // A blocking read operation - fn slave_read_internal(&self, read: &mut [u8], timeout: Timeout) -> Result<(), Error> { + fn slave_read_internal(&self, read: &mut [u8], timeout: Timeout) -> Result { let completed_chunks = read.len() / 255; let total_chunks = if completed_chunks * 255 == read.len() { completed_chunks @@ -895,20 +1004,46 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { completed_chunks + 1 }; let last_chunk_idx = total_chunks.saturating_sub(1); + let total_len = read.len(); + let mut remaining_len = total_len; + for (number, chunk) in read.chunks_mut(255).enumerate() { - if number != 0 { + trace!( + "--- Slave RX transmission start - chunk: {}, expected (max) size: {}", + number, + chunk.len() + ); + if number == 0 { + Self::slave_start(self.info, chunk.len(), number != last_chunk_idx); + } else { Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; } + let mut index = 0; + for byte in chunk { // Wait until we have received something - self.wait_rxne(timeout)?; - - *byte = self.info.regs.rxdr().read().rxdata(); + match self.wait_rxne(timeout) { + Ok(ReceiveResult::StopReceived) | Ok(ReceiveResult::NewStart) => { + trace!("--- Slave RX transmission end (early)"); + return Ok(total_len - remaining_len); // Return N bytes read + } + Ok(ReceiveResult::DataAvailable) => { + *byte = self.info.regs.rxdr().read().rxdata(); + remaining_len = remaining_len.saturating_sub(1); + { + trace!("Slave RX data {}: {:#04x}", index, byte); + index = index + 1; + } + } + Err(e) => return Err(e), + }; } } + self.wait_stop_or_err(timeout)?; - Ok(()) + trace!("--- Slave RX transmission end"); + Ok(total_len - remaining_len) // Return N bytes read } // A blocking write operation @@ -922,19 +1057,36 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { let last_chunk_idx = total_chunks.saturating_sub(1); for (number, chunk) in write.chunks(255).enumerate() { - if number != 0 { + trace!( + "--- Slave TX transmission start - chunk: {}, size: {}", + number, + chunk.len() + ); + if number == 0 { + Self::slave_start(self.info, chunk.len(), number != last_chunk_idx); + } else { Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; } + let mut index = 0; + for byte in chunk { // Wait until we are allowed to send data - // (START has been ACKed or last byte when - // through) - self.wait_txe(timeout)?; + // (START has been ACKed or last byte when through) + self.wait_txis(timeout)?; + { + trace!("Slave TX data {}: {:#04x}", index, byte); + index = index + 1; + } self.info.regs.txdr().write(|w| w.set_txdata(*byte)); } } + self.wait_af(timeout)?; + self.flush_txdr(); + self.wait_stop_or_err(timeout)?; + + trace!("--- Slave TX transmission end"); Ok(()) } @@ -945,6 +1097,7 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { let state = self.state; self.info.regs.cr1().modify(|reg| { reg.set_addrie(true); + trace!("Enable ADDRIE"); }); poll_fn(|cx| { @@ -953,17 +1106,24 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { if !isr.addr() { Poll::Pending } else { + trace!("ADDR triggered (address match)"); // we do not clear the address flag here as it will be cleared by the dma read/write // if we clear it here the clock stretching will stop and the master will read in data before the slave is ready to send it match isr.dir() { - i2c::vals::Dir::WRITE => Poll::Ready(Ok(SlaveCommand { - kind: SlaveCommandKind::Write, - address: self.determine_matched_address()?, - })), - i2c::vals::Dir::READ => Poll::Ready(Ok(SlaveCommand { - kind: SlaveCommandKind::Read, - address: self.determine_matched_address()?, - })), + i2c::vals::Dir::WRITE => { + trace!("DIR: write"); + Poll::Ready(Ok(SlaveCommand { + kind: SlaveCommandKind::Write, + address: self.determine_matched_address()?, + })) + } + i2c::vals::Dir::READ => { + trace!("DIR: read"); + Poll::Ready(Ok(SlaveCommand { + kind: SlaveCommandKind::Read, + address: self.determine_matched_address()?, + })) + } } } }) @@ -971,7 +1131,9 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> { } /// Respond to a write command. - pub fn blocking_respond_to_write(&self, read: &mut [u8]) -> Result<(), Error> { + /// + /// Returns total number of bytes received. + pub fn blocking_respond_to_write(&self, read: &mut [u8]) -> Result { let timeout = self.timeout(); self.slave_read_internal(read, timeout) } @@ -1025,7 +1187,7 @@ impl<'d> I2c<'d, Async, MultiMaster> { w.set_rxdmaen(false); w.set_stopie(false); w.set_tcie(false); - }) + }); }); let total_received = poll_fn(|cx| { -- cgit From 3329089412e3ab367893eb975d611be49c8f5c5d Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 25 Jul 2025 00:11:42 +0200 Subject: embassy-embedded-hal: make time feature non-default default features considered harmful. --- ci.sh | 2 ++ embassy-embedded-hal/Cargo.toml | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ci.sh b/ci.sh index 94f70aae8..f4db1da03 100755 --- a/ci.sh +++ b/ci.sh @@ -40,6 +40,8 @@ cargo batch \ --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7r-none-eabihf --features arch-cortex-ar,executor-thread \ --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32 \ --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32,executor-thread \ + --- build --release --manifest-path embassy-embedded-hal/Cargo.toml --target thumbv7em-none-eabi \ + --- build --release --manifest-path embassy-embedded-hal/Cargo.toml --target thumbv7em-none-eabi --features time \ --- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features defmt \ --- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features defmt,defmt-timestamp-uptime,mock-driver \ --- build --release --manifest-path embassy-time-queue-utils/Cargo.toml --target thumbv6m-none-eabi \ diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index aab6e0f1e..8277aa291 100644 --- a/embassy-embedded-hal/Cargo.toml +++ b/embassy-embedded-hal/Cargo.toml @@ -19,7 +19,6 @@ target = "x86_64-unknown-linux-gnu" [features] time = ["dep:embassy-time"] -default = ["time"] [dependencies] embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal" } -- cgit From a8d215ff1484cde754695b08e91663e2220c9790 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Thu, 24 Jul 2025 16:28:59 -0700 Subject: Partially working USB example --- embassy-stm32/src/rcc/wba.rs | 14 ++++++++------ embassy-stm32/src/usb/otg.rs | 26 +++++++++++++++++++------- examples/stm32wba/src/bin/usb_hs_serial.rs | 20 ++++++++++---------- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index 4ca622614..a5e6b33ff 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs @@ -2,7 +2,7 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale; use crate::pac::rcc::regs::Cfgr1; pub use crate::pac::rcc::vals::{ Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk, Pllsrc as PllSource, - Plldiv as PllDiv, Pllm, Plln as PllMul, + Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, }; use crate::pac::rcc::vals::Pllrge; use crate::pac::{FLASH, RCC}; @@ -32,7 +32,7 @@ pub struct Pll { /// The PLL pre-divider. /// /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz. - pub pllm: Pllm, + pub prediv: PllPreDiv, /// The PLL multiplier. /// /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544 @@ -287,15 +287,18 @@ fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) let Some(pll) = config else { return PllOutput::default() }; - let src_freq = match pll.source { + let pre_src_freq = match pll.source { PllSource::DISABLE => panic!("must not select PLL source as DISABLE"), PllSource::HSE => unwrap!(input.hse), PllSource::HSI => unwrap!(input.hsi), PllSource::_RESERVED_1 => panic!("must not select RESERVED_1 source as DISABLE"), }; + let hse_div = RCC.cr().read().hsepre(); + let src_freq = pre_src_freq / hse_div; + // Calculate the reference clock, which is the source divided by m - let ref_freq = src_freq / pll.pllm; + let ref_freq = src_freq / pll.prediv; // Check limits per RM0515 § 12.4.3 assert!(Hertz::mhz(4) <= ref_freq && ref_freq <= Hertz::mhz(16)); @@ -325,7 +328,6 @@ fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) w.set_pllp(pll.divp.unwrap_or(PllDiv::DIV1)); w.set_pllq(pll.divq.unwrap_or(PllDiv::DIV1)); w.set_pllr(pll.divr.unwrap_or(PllDiv::DIV1)); - // w.set_pllfracn(pll.frac.unwrap_or(1)); }); RCC.pll1fracr().write(|w| {w.set_pllfracn(pll.frac.unwrap_or(1));}); @@ -340,7 +342,7 @@ fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) $w.set_pllqen(pll.divq.is_some()); $w.set_pllren(pll.divr.is_some()); $w.set_pllfracen(pll.frac.is_some()); - $w.set_pllm(pll.pllm); + $w.set_pllm(pll.prediv); $w.set_pllsrc(pll.source); $w.set_pllrge(input_range); }; diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index 02b27ed48..6b28ac980 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -315,30 +315,42 @@ impl<'d, T: Instance> Bus<'d, T> { #[cfg(all(stm32u5, peri_usb_otg_hs))] { - crate::pac::SYSCFG.otghsphycr().modify(|w| { - w.set_en(true); - }); - critical_section::with(|_| { crate::pac::RCC.ahb2enr1().modify(|w| { w.set_usb_otg_hsen(true); w.set_usb_otg_hs_phyen(true); }); }); - } - #[cfg(all(stm32wba, peri_usb_otg_hs))] - { crate::pac::SYSCFG.otghsphycr().modify(|w| { w.set_en(true); }); + } + #[cfg(all(stm32wba, peri_usb_otg_hs))] + { critical_section::with(|_| { + crate::pac::RCC.apb7enr().modify(|w| { + w.set_syscfgen(true); + }); crate::pac::RCC.ahb2enr().modify(|w| { w.set_usb_otg_hsen(true); w.set_usb_otg_hs_phyen(true); }); }); + + // pub use crate::pac::rcc::vals::Otghssel; + // // select HSE + // crate::pac::RCC.ccipr2().modify(|w| {w.set_otghssel(Otghssel::HSE);}); + + crate::pac::SYSCFG.otghsphytuner2().modify(|w| { + w.set_compdistune(0b010); + w.set_sqrxtune(0b000); + }); + + crate::pac::SYSCFG.otghsphycr().modify(|w| { + w.set_en(true); + }); } let r = T::regs(); diff --git a/examples/stm32wba/src/bin/usb_hs_serial.rs b/examples/stm32wba/src/bin/usb_hs_serial.rs index e30f33625..bda4a5013 100644 --- a/examples/stm32wba/src/bin/usb_hs_serial.rs +++ b/examples/stm32wba/src/bin/usb_hs_serial.rs @@ -5,7 +5,7 @@ use defmt::{panic, *}; use defmt_rtt as _; // global logger use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_stm32::rcc::PllSource; +use embassy_stm32::rcc::{PllSource, PllPreDiv, PllMul, PllDiv}; use embassy_stm32::rcc::{mux, AHBPrescaler, APBPrescaler, Hse, HsePrescaler, Sysclk, VoltageScale}; use embassy_stm32::usb::{Driver, Instance}; use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; @@ -26,21 +26,18 @@ async fn main(_spawner: Spawner) { // External HSE (32 MHz) setup config.rcc.hse = Some(Hse { - prescaler: HsePrescaler::DIV1, + prescaler: HsePrescaler::DIV2, }); - // route HSE into the USB‐OTG‐HS block - config.rcc.mux.otghssel = mux::Otghssel::HSE; - config.rcc.sys = Sysclk::HSE; // Fine-tune PLL1 dividers/multipliers config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { source: PllSource::HSE, - pllm: 2.into(), // PLLM = 2 → HSE / 2 = 16 MHz input - mul: 12.into(), // PLLN = 12 → 16 MHz * 12 = 192 MHz VCO - divp: Some(2.into()), // PLLP = 2 → 96 MHz - divq: Some(2.into()), // PLLQ = 2 → 96 MHz - divr: Some(2.into()), // PLLR = 2 → 96 MHz + prediv: PllPreDiv::DIV2, // PLLM = 2 → HSE / 2 = 8 MHz + mul: PllMul::MUL60, // PLLN = 60 → 8 MHz * 60 = 480 MHz VCO + divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) + divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (USB) + divp: Some(PllDiv::DIV15), // PLLP = 15 → 32 MHz (USBOTG) frac: Some(4096), // Fractional part (enabled) }); @@ -51,6 +48,9 @@ async fn main(_spawner: Spawner) { // voltage scale for max performance config.rcc.voltage_scale = VoltageScale::RANGE1; + // route PLL1_P into the USB‐OTG‐HS block + config.rcc.mux.otghssel = mux::Otghssel::PLL1_P; + config.rcc.sys = Sysclk::PLL1_R; let p = embassy_stm32::init(config); -- cgit From 24b2794931e73325ad969d83453d0cf872ac4775 Mon Sep 17 00:00:00 2001 From: Rick Rogers Date: Thu, 24 Jul 2025 21:09:24 -0400 Subject: add plls/t to stm32h7rs examples --- examples/stm32h7rs/src/bin/blinky.rs | 2 ++ examples/stm32h7rs/src/bin/eth.rs | 2 ++ examples/stm32h7rs/src/bin/usb_serial.rs | 2 ++ examples/stm32h7rs/src/bin/xspi_memory_mapped.rs | 2 ++ 4 files changed, 8 insertions(+) diff --git a/examples/stm32h7rs/src/bin/blinky.rs b/examples/stm32h7rs/src/bin/blinky.rs index 137c585b7..5fd50fb15 100644 --- a/examples/stm32h7rs/src/bin/blinky.rs +++ b/examples/stm32h7rs/src/bin/blinky.rs @@ -25,6 +25,8 @@ async fn main(_spawner: Spawner) { divp: Some(PllDiv::DIV2), divq: None, divr: None, + divs: None, + divt: None, }); config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz diff --git a/examples/stm32h7rs/src/bin/eth.rs b/examples/stm32h7rs/src/bin/eth.rs index 6d246bb09..d8002e9ba 100644 --- a/examples/stm32h7rs/src/bin/eth.rs +++ b/examples/stm32h7rs/src/bin/eth.rs @@ -41,6 +41,8 @@ async fn main(spawner: Spawner) -> ! { divp: Some(PllDiv::DIV2), divq: None, divr: None, + divs: None, + divt: None, }); config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz diff --git a/examples/stm32h7rs/src/bin/usb_serial.rs b/examples/stm32h7rs/src/bin/usb_serial.rs index 56a9884af..23abc3e2f 100644 --- a/examples/stm32h7rs/src/bin/usb_serial.rs +++ b/examples/stm32h7rs/src/bin/usb_serial.rs @@ -40,6 +40,8 @@ async fn main(_spawner: Spawner) { divp: Some(PllDiv::DIV1), //600 MHz divq: Some(PllDiv::DIV2), // 300 MHz divr: Some(PllDiv::DIV2), // 300 MHz + divs: None, + divt: None, }); config.rcc.sys = Sysclk::PLL1_P; // 600 MHz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 MHz diff --git a/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs b/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs index 59045ca2e..4c1b450b4 100644 --- a/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs +++ b/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs @@ -36,6 +36,8 @@ async fn main(_spawner: Spawner) { divp: Some(PllDiv::DIV2), divq: None, divr: None, + divs: None, + divt: None, }); config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz -- cgit From 3a30458b253083087b43b85c43cc8eaf10870414 Mon Sep 17 00:00:00 2001 From: Rick Rogers Date: Fri, 25 Jul 2025 12:10:17 -0400 Subject: address rustfmt ci check --- embassy-stm32/src/rcc/h.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index 354824e26..c31b1bbd1 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs @@ -1,5 +1,8 @@ use core::ops::RangeInclusive; +#[cfg(stm32h7rs)] +use stm32_metapac::rcc::vals::Plldivst; + use crate::pac; pub use crate::pac::rcc::vals::{ Hsidiv as HSIPrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, Pllsrc as PllSource, Sw as Sysclk, @@ -8,9 +11,6 @@ use crate::pac::rcc::vals::{Pllrge, Pllvcosel, Timpre}; use crate::pac::{FLASH, PWR, RCC}; use crate::time::Hertz; -#[cfg(stm32h7rs)] -use stm32_metapac::rcc::vals::Plldivst; - /// HSI speed pub const HSI_FREQ: Hertz = Hertz(64_000_000); -- cgit From c37fb51cfe25511b2222e92e37b80933079ed3fc Mon Sep 17 00:00:00 2001 From: Rick Rogers Date: Fri, 25 Jul 2025 12:24:54 -0400 Subject: address ci test failure --- tests/stm32/src/common.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index a4d8048ce..cb63b3374 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs @@ -681,6 +681,8 @@ pub fn config() -> Config { divp: Some(PllDiv::DIV2), // 600Mhz divq: Some(PllDiv::DIV25), // 48Mhz divr: None, + divs: None, + divt: None, }); config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz -- cgit From 777e0c71c99fde779cf91c364849ac6906cb3d97 Mon Sep 17 00:00:00 2001 From: emkanea-dev Date: Fri, 25 Jul 2025 20:53:04 +0200 Subject: fixed build after rebase --- embassy-stm32/src/adc/v3.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index 805dae564..a2e42fe52 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -257,8 +257,8 @@ impl<'d, T: Instance> Adc<'d, T> { #[cfg(any(adc_h5, adc_h7rs))] reg.set_ovsr(samples.into()); #[cfg(not(any(adc_h5, adc_h7rs)))] - reg.set_ovsr(samples); - reg.set_ovss(right_shift); + reg.set_ovsr(samples.into()); + reg.set_ovss(right_shift.into()); }) } /* -- cgit From a5a9c02543fbe978c68a707654029552f6b7b00a Mon Sep 17 00:00:00 2001 From: Rick Rogers Date: Fri, 25 Jul 2025 15:03:37 -0400 Subject: include proper pll divs/divt initialization --- embassy-stm32/build.rs | 2 +- embassy-stm32/src/rcc/h.rs | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 73860c64a..753f94fa6 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1599,7 +1599,7 @@ fn main() { for e in rcc_registers.ir.enums { fn is_rcc_name(e: &str) -> bool { match e { - "Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" => true, + "Pllp" | "Pllq" | "Pllr" | "Plldivst" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" => true, "Timpre" | "Pllrclkpre" => false, e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true, _ => false, diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index c31b1bbd1..837210b6a 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs @@ -758,6 +758,12 @@ struct PllOutput { q: Option, #[allow(dead_code)] r: Option, + #[cfg(stm32h7rs)] + #[allow(dead_code)] + s: Option, + #[cfg(stm32h7rs)] + #[allow(dead_code)] + t: Option, } fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { @@ -776,6 +782,10 @@ fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { p: None, q: None, r: None, + #[cfg(stm32h7rs)] + s: None, + #[cfg(stm32h7rs)] + t: None, }; }; @@ -823,6 +833,10 @@ fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { }); let q = config.divq.map(|div| vco_clk / div); let r = config.divr.map(|div| vco_clk / div); + #[cfg(stm32h7rs)] + let s = config.divs.map(|div| vco_clk / div); + #[cfg(stm32h7rs)] + let t = config.divt.map(|div| vco_clk / div); #[cfg(stm32h5)] RCC.pllcfgr(num).write(|w| { @@ -849,6 +863,10 @@ fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { w.set_divpen(num, p.is_some()); w.set_divqen(num, q.is_some()); w.set_divren(num, r.is_some()); + #[cfg(stm32h7rs)] + w.set_divsen(num, s.is_some()); + #[cfg(stm32h7rs)] + w.set_divten(num, t.is_some()); }); } @@ -859,10 +877,24 @@ fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { w.set_pllr(config.divr.unwrap_or(PllDiv::DIV2)); }); + #[cfg(stm32h7rs)] + RCC.plldivr2(num).write(|w| { + w.set_plls(config.divs.unwrap_or(Plldivst::DIV2)); + w.set_pllt(config.divt.unwrap_or(Plldivst::DIV2)); + }); + RCC.cr().modify(|w| w.set_pllon(num, true)); while !RCC.cr().read().pllrdy(num) {} - PllOutput { p, q, r } + PllOutput { + p, + q, + r, + #[cfg(stm32h7rs)] + s, + #[cfg(stm32h7rs)] + t, + } } fn flash_setup(clk: Hertz, vos: VoltageScale) { -- cgit From 75c1039aa11fa9a134511ce0988aefa088a0e6b0 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Fri, 25 Jul 2025 14:26:06 -0700 Subject: Moved from HSE to HSI to generate USB_OTG_HS_CLK --- embassy-stm32/src/lib.rs | 2 +- embassy-stm32/src/rcc/wba.rs | 64 +++++++++++++++++++++++++++--- embassy-stm32/src/usb/mod.rs | 8 +++- embassy-stm32/src/usb/otg.rs | 10 ++--- examples/stm32wba/src/bin/usb_hs_serial.rs | 24 ++++++----- 5 files changed, 83 insertions(+), 25 deletions(-) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index c7a33ed72..d893f1b54 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -546,7 +546,7 @@ fn init_hw(config: Config) -> Peripherals { { use crate::pac::pwr::vals; crate::pac::PWR.svmcr().modify(|w| { - w.set_io2sv(vals::Io2sv::B_0X1); + w.set_io2sv(if config.enable_independent_io_supply {vals::Io2sv::B_0X1} else {vals::Io2sv::B_0X0}); }); } #[cfg(stm32u5)] diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index a5e6b33ff..0025d2a51 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs @@ -1,8 +1,9 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale; use crate::pac::rcc::regs::Cfgr1; +use core::ops::Div; pub use crate::pac::rcc::vals::{ Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk, Pllsrc as PllSource, - Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, + Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, Hpre5 as AHB5Prescaler, Hdiv5, }; use crate::pac::rcc::vals::Pllrge; use crate::pac::{FLASH, RCC}; @@ -20,6 +21,23 @@ pub const HSI_FREQ: Hertz = Hertz(16_000_000); // HSE speed pub const HSE_FREQ: Hertz = Hertz(32_000_000); +// Allow dividing a Hertz value by an AHB5 prescaler directly +impl Div for Hertz { + type Output = Hertz; + fn div(self, rhs: AHB5Prescaler) -> Hertz { + // Map the prescaler enum to its integer divisor + let divisor = match rhs { + AHB5Prescaler::DIV1 => 1, + AHB5Prescaler::DIV2 => 2, + AHB5Prescaler::DIV3 => 3, + AHB5Prescaler::DIV4 => 4, + AHB5Prescaler::DIV6 => 6, + _ => unreachable!("Invalid AHB5 prescaler: {:?}", rhs), + }; + Hertz(self.0 / divisor) + } +} + #[derive(Clone, Copy, Eq, PartialEq)] pub struct Hse { pub prescaler: HsePrescaler, @@ -71,6 +89,7 @@ pub struct Config { // sysclk, buses. pub sys: Sysclk, pub ahb_pre: AHBPrescaler, + pub ahb5_pre: AHB5Prescaler, pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, pub apb7_pre: APBPrescaler, @@ -93,6 +112,7 @@ impl Config { pll1: None, sys: Sysclk::HSI, ahb_pre: AHBPrescaler::DIV1, + ahb5_pre: AHB5Prescaler::DIV1, apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, apb7_pre: APBPrescaler::DIV1, @@ -165,7 +185,6 @@ pub(crate) unsafe fn init(config: Config) { let hclk1 = sys_clk / config.ahb_pre; let hclk2 = hclk1; let hclk4 = hclk1; - // TODO: hclk5 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre); let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre); let (pclk7, _) = super::util::calc_pclk(hclk1, config.apb7_pre); @@ -211,6 +230,27 @@ pub(crate) unsafe fn init(config: Config) { w.set_ppre2(config.apb2_pre); }); + // Set AHB5 prescaler depending on sysclk source + RCC.cfgr4().modify(|w| match config.sys { + // When using HSI or HSE, use HDIV5 bit (0 = div1, 1 = div2) + Sysclk::HSI | Sysclk::HSE => { + // Only Div1 and Div2 are valid for HDIV5, enforce this + match config.ahb5_pre { + AHB5Prescaler::DIV1 => w.set_hdiv5(Hdiv5::DIV1), + AHB5Prescaler::DIV2 => w.set_hdiv5(Hdiv5::DIV2), + _ => panic!("Invalid ahb5_pre for HSI/HSE sysclk: only DIV1 and DIV2 are allowed"), + }; + } + // When using PLL1, use HPRE5 bits [2:0] + Sysclk::PLL1_R => { + w.set_hpre5(config.ahb5_pre); + } + _ => {} + }); + + let hclk5 = sys_clk / config.ahb5_pre; + + #[cfg(all(stm32wba, peri_usb_otg_hs))] let usb_refck = match config.mux.otghssel { Otghssel::HSE => hse, @@ -245,6 +285,7 @@ pub(crate) unsafe fn init(config: Config) { hclk1: Some(hclk1), hclk2: Some(hclk2), hclk4: Some(hclk4), + hclk5: Some(hclk5), pclk1: Some(pclk1), pclk2: Some(pclk2), pclk7: Some(pclk7), @@ -294,8 +335,15 @@ fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) PllSource::_RESERVED_1 => panic!("must not select RESERVED_1 source as DISABLE"), }; - let hse_div = RCC.cr().read().hsepre(); - let src_freq = pre_src_freq / hse_div; + // Only divide by the HSE prescaler when the PLL source is HSE + let src_freq = match pll.source { + PllSource::HSE => { + // read the prescaler bits and divide + let hsepre = RCC.cr().read().hsepre(); + pre_src_freq / hsepre + } + _ => pre_src_freq, + }; // Calculate the reference clock, which is the source divided by m let ref_freq = src_freq / pll.prediv; @@ -309,7 +357,11 @@ fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) }; // Calculate the PLL VCO clock - let vco_freq = ref_freq * pll.mul; + // let vco_freq = ref_freq * pll.mul; + // Calculate VCO frequency including fractional part: FVCO = Fref_ck × (N + FRAC/2^13) + let numerator = (ref_freq.0 as u64) * (((pll.mul as u64) + 1 << 13) + pll.frac.unwrap_or(0) as u64); + let vco_hz = (numerator >> 13) as u32; + let vco_freq = Hertz(vco_hz); assert!(vco_freq >= vco_min && vco_freq <= vco_max); // Calculate output clocks. @@ -329,7 +381,7 @@ fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) w.set_pllq(pll.divq.unwrap_or(PllDiv::DIV1)); w.set_pllr(pll.divr.unwrap_or(PllDiv::DIV1)); }); - RCC.pll1fracr().write(|w| {w.set_pllfracn(pll.frac.unwrap_or(1));}); + RCC.pll1fracr().write(|w| {w.set_pllfracn(pll.frac.unwrap_or(0));}); let input_range = match ref_freq.0 { ..=8_000_000 => Pllrge::FREQ_4TO8MHZ, diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs index 692897b59..d987a056d 100644 --- a/embassy-stm32/src/usb/mod.rs +++ b/embassy-stm32/src/usb/mod.rs @@ -108,7 +108,12 @@ fn common_init() { critical_section::with(|_| { crate::pac::PWR.svmcr().modify(|w| { w.set_usv(crate::pac::pwr::vals::Usv::B_0X1); - // w.set_uvmen(true); + }); + crate::pac::PWR.vosr().modify(|w| { + w.set_vdd11usbdis(true); + }); + crate::pac::PWR.vosr().modify(|w| { + w.set_usbpwren(true); }) }); @@ -119,7 +124,6 @@ fn common_init() { #[cfg(peri_usb_otg_hs)] { crate::pac::PWR.vosr().modify(|w| { - w.set_usbpwren(true); w.set_usbboosten(true); }); while !crate::pac::PWR.vosr().read().usbboostrdy() {} diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index 6b28ac980..abf54cbad 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -330,9 +330,9 @@ impl<'d, T: Instance> Bus<'d, T> { #[cfg(all(stm32wba, peri_usb_otg_hs))] { critical_section::with(|_| { - crate::pac::RCC.apb7enr().modify(|w| { - w.set_syscfgen(true); - }); + // crate::pac::RCC.apb7enr().modify(|w| { + // w.set_syscfgen(true); + // }); crate::pac::RCC.ahb2enr().modify(|w| { w.set_usb_otg_hsen(true); w.set_usb_otg_hs_phyen(true); @@ -366,8 +366,8 @@ impl<'d, T: Instance> Bus<'d, T> { // Configuring Vbus sense and SOF output match core_id { 0x0000_1200 | 0x0000_1100 | 0x0000_1000 => self.inner.config_v1(), - 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 | 0x0000_6100 => self.inner.config_v2v3(), - 0x0000_5000 => self.inner.config_v5(), + 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 => self.inner.config_v2v3(), + 0x0000_5000 | 0x0000_6100 => self.inner.config_v5(), _ => unimplemented!("Unknown USB core id {:X}", core_id), } } diff --git a/examples/stm32wba/src/bin/usb_hs_serial.rs b/examples/stm32wba/src/bin/usb_hs_serial.rs index bda4a5013..393f8be6b 100644 --- a/examples/stm32wba/src/bin/usb_hs_serial.rs +++ b/examples/stm32wba/src/bin/usb_hs_serial.rs @@ -6,7 +6,7 @@ use defmt_rtt as _; // global logger use embassy_executor::Spawner; use embassy_futures::join::join; use embassy_stm32::rcc::{PllSource, PllPreDiv, PllMul, PllDiv}; -use embassy_stm32::rcc::{mux, AHBPrescaler, APBPrescaler, Hse, HsePrescaler, Sysclk, VoltageScale}; +use embassy_stm32::rcc::{mux, AHBPrescaler, AHB5Prescaler, APBPrescaler, Hse, HsePrescaler, Sysclk, VoltageScale}; use embassy_stm32::usb::{Driver, Instance}; use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; @@ -25,26 +25,28 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); // External HSE (32 MHz) setup - config.rcc.hse = Some(Hse { - prescaler: HsePrescaler::DIV2, - }); + // config.rcc.hse = Some(Hse { + // prescaler: HsePrescaler::DIV2, + // }); // Fine-tune PLL1 dividers/multipliers config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { - source: PllSource::HSE, - prediv: PllPreDiv::DIV2, // PLLM = 2 → HSE / 2 = 8 MHz - mul: PllMul::MUL60, // PLLN = 60 → 8 MHz * 60 = 480 MHz VCO - divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) - divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (USB) - divp: Some(PllDiv::DIV15), // PLLP = 15 → 32 MHz (USBOTG) - frac: Some(4096), // Fractional part (enabled) + source: PllSource::HSI, + prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz + mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO + divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) + // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) + divq: None, + divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) + frac: Some(0), // Fractional part (enabled) }); config.rcc.ahb_pre = AHBPrescaler::DIV1; config.rcc.apb1_pre = APBPrescaler::DIV1; config.rcc.apb2_pre = APBPrescaler::DIV1; config.rcc.apb7_pre = APBPrescaler::DIV1; + config.rcc.ahb5_pre = AHB5Prescaler::DIV4; // voltage scale for max performance config.rcc.voltage_scale = VoltageScale::RANGE1; -- cgit From 8733a5f56a310de3caba95246a0076fc33940d41 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Fri, 25 Jul 2025 18:46:09 -0700 Subject: Fixed usb_hs_serial example --- examples/stm32wba/src/bin/usb_hs_serial.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/examples/stm32wba/src/bin/usb_hs_serial.rs b/examples/stm32wba/src/bin/usb_hs_serial.rs index 393f8be6b..41440a940 100644 --- a/examples/stm32wba/src/bin/usb_hs_serial.rs +++ b/examples/stm32wba/src/bin/usb_hs_serial.rs @@ -5,8 +5,8 @@ use defmt::{panic, *}; use defmt_rtt as _; // global logger use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_stm32::rcc::{PllSource, PllPreDiv, PllMul, PllDiv}; -use embassy_stm32::rcc::{mux, AHBPrescaler, AHB5Prescaler, APBPrescaler, Hse, HsePrescaler, Sysclk, VoltageScale}; +use embassy_stm32::rcc::{mux, AHB5Prescaler, AHBPrescaler, APBPrescaler, Hse, HsePrescaler, Sysclk, VoltageScale}; +use embassy_stm32::rcc::{PllDiv, PllMul, PllPreDiv, PllSource}; use embassy_stm32::usb::{Driver, Instance}; use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; @@ -29,17 +29,16 @@ async fn main(_spawner: Spawner) { // prescaler: HsePrescaler::DIV2, // }); - // Fine-tune PLL1 dividers/multipliers config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { source: PllSource::HSI, - prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz - mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO - divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) + prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz + mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO + divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) divq: None, - divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) - frac: Some(0), // Fractional part (enabled) + divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) + frac: Some(0), // Fractional part (enabled) }); config.rcc.ahb_pre = AHBPrescaler::DIV1; -- cgit From a5e8891fe315e2ee84992d94bd7f7d5b7710cce6 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Fri, 25 Jul 2025 18:57:27 -0700 Subject: Added support for PLL as a clock source on STM32WBA - PLL multiplier and dividers work - Added timer example --- embassy-stm32/Cargo.toml | 4 +- embassy-stm32/src/rcc/wba.rs | 247 +++++++++++++++++++++++++++++++++++++-- examples/stm32wba/src/bin/pwm.rs | 65 +++++++++++ 3 files changed, 304 insertions(+), 12 deletions(-) create mode 100644 examples/stm32wba/src/bin/pwm.rs diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 02e75733e..520443466 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9fc86ca7b3a8bc05182bf1ce3045602df1f5dce3" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-df3f5212f2dd70955a6b3d0137e7b4457c6047bf" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9fc86ca7b3a8bc05182bf1ce3045602df1f5dce3", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-df3f5212f2dd70955a6b3d0137e7b4457c6047bf", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index b494997b3..0025d2a51 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs @@ -1,19 +1,81 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale; use crate::pac::rcc::regs::Cfgr1; -pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk}; +use core::ops::Div; +pub use crate::pac::rcc::vals::{ + Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk, Pllsrc as PllSource, + Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, Hpre5 as AHB5Prescaler, Hdiv5, +}; +use crate::pac::rcc::vals::Pllrge; use crate::pac::{FLASH, RCC}; +use crate::rcc::LSI_FREQ; use crate::time::Hertz; +#[cfg(all(peri_usb_otg_hs))] +pub use crate::pac::rcc::vals::Otghssel; + +#[cfg(all(peri_usb_otg_hs))] +pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG}; + /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); // HSE speed pub const HSE_FREQ: Hertz = Hertz(32_000_000); +// Allow dividing a Hertz value by an AHB5 prescaler directly +impl Div for Hertz { + type Output = Hertz; + fn div(self, rhs: AHB5Prescaler) -> Hertz { + // Map the prescaler enum to its integer divisor + let divisor = match rhs { + AHB5Prescaler::DIV1 => 1, + AHB5Prescaler::DIV2 => 2, + AHB5Prescaler::DIV3 => 3, + AHB5Prescaler::DIV4 => 4, + AHB5Prescaler::DIV6 => 6, + _ => unreachable!("Invalid AHB5 prescaler: {:?}", rhs), + }; + Hertz(self.0 / divisor) + } +} + #[derive(Clone, Copy, Eq, PartialEq)] pub struct Hse { pub prescaler: HsePrescaler, } +#[derive(Clone, Copy)] +pub struct Pll { + /// The clock source for the PLL. + pub source: PllSource, + /// The PLL pre-divider. + /// + /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz. + pub prediv: PllPreDiv, + /// The PLL multiplier. + /// + /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544 + /// MHz. The upper limit may be lower depending on the `Config { voltage_range }`. + pub mul: PllMul, + /// The divider for the P output. + /// + /// The P output is one of several options + /// that can be used to feed the SAI/MDF/ADF Clock mux's. + pub divp: Option, + /// The divider for the Q output. + /// + /// The Q ouput is one of severals options that can be used to feed the 48MHz clocks + /// and the OCTOSPI clock. It may also be used on the MDF/ADF clock mux's. + pub divq: Option, + /// The divider for the R output. + /// + /// When used to drive the system clock, `source` divided by `m` times `n` divided by `r` + /// must not exceed 160 MHz. System clocks above 55 MHz require a non-default + /// `Config { voltage_range }`. + pub divr: Option, + + pub frac: Option, +} + /// Clocks configuration #[derive(Clone, Copy)] pub struct Config { @@ -21,15 +83,20 @@ pub struct Config { pub hsi: bool, pub hse: Option, + // pll + pub pll1: Option, + // sysclk, buses. pub sys: Sysclk, pub ahb_pre: AHBPrescaler, + pub ahb5_pre: AHB5Prescaler, pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, pub apb7_pre: APBPrescaler, // low speed LSI/LSE/RTC - pub ls: super::LsConfig, + pub lsi: super::LsConfig, + // pub lsi2: super::LsConfig, pub voltage_scale: VoltageScale, @@ -40,14 +107,17 @@ pub struct Config { impl Config { pub const fn new() -> Self { Config { - hse: None, hsi: true, + hse: None, + pll1: None, sys: Sysclk::HSI, ahb_pre: AHBPrescaler::DIV1, + ahb5_pre: AHB5Prescaler::DIV1, apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, apb7_pre: APBPrescaler::DIV1, - ls: crate::rcc::LsConfig::new(), + lsi: crate::rcc::LsConfig::new(), + // lsi2: crate::rcc::LsConfig::new(), voltage_scale: VoltageScale::RANGE2, mux: super::mux::ClockMux::default(), } @@ -81,7 +151,7 @@ pub(crate) unsafe fn init(config: Config) { crate::pac::PWR.vosr().write(|w| w.set_vos(config.voltage_scale)); while !crate::pac::PWR.vosr().read().vosrdy() {} - let rtc = config.ls.init(); + let rtc = config.lsi.init(); let hsi = config.hsi.then(|| { hsi_enable(); @@ -99,11 +169,15 @@ pub(crate) unsafe fn init(config: Config) { HSE_FREQ }); + let pll_input = PllInput {hse, hsi }; + + let pll1 = init_pll(config.pll1, &pll_input, config.voltage_scale); + let sys_clk = match config.sys { Sysclk::HSE => hse.unwrap(), Sysclk::HSI => hsi.unwrap(), Sysclk::_RESERVED_1 => unreachable!(), - Sysclk::PLL1_R => todo!(), + Sysclk::PLL1_R => pll1.r.unwrap(), }; assert!(sys_clk.0 <= 100_000_000); @@ -111,7 +185,6 @@ pub(crate) unsafe fn init(config: Config) { let hclk1 = sys_clk / config.ahb_pre; let hclk2 = hclk1; let hclk4 = hclk1; - // TODO: hclk5 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre); let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre); let (pclk7, _) = super::util::calc_pclk(hclk1, config.apb7_pre); @@ -157,6 +230,54 @@ pub(crate) unsafe fn init(config: Config) { w.set_ppre2(config.apb2_pre); }); + // Set AHB5 prescaler depending on sysclk source + RCC.cfgr4().modify(|w| match config.sys { + // When using HSI or HSE, use HDIV5 bit (0 = div1, 1 = div2) + Sysclk::HSI | Sysclk::HSE => { + // Only Div1 and Div2 are valid for HDIV5, enforce this + match config.ahb5_pre { + AHB5Prescaler::DIV1 => w.set_hdiv5(Hdiv5::DIV1), + AHB5Prescaler::DIV2 => w.set_hdiv5(Hdiv5::DIV2), + _ => panic!("Invalid ahb5_pre for HSI/HSE sysclk: only DIV1 and DIV2 are allowed"), + }; + } + // When using PLL1, use HPRE5 bits [2:0] + Sysclk::PLL1_R => { + w.set_hpre5(config.ahb5_pre); + } + _ => {} + }); + + let hclk5 = sys_clk / config.ahb5_pre; + + + #[cfg(all(stm32wba, peri_usb_otg_hs))] + let usb_refck = match config.mux.otghssel { + Otghssel::HSE => hse, + Otghssel::HSE_DIV_2 => hse.map(|hse_val| hse_val / 2u8), + Otghssel::PLL1_P => pll1.p, + Otghssel::PLL1_P_DIV_2 => pll1.p.map(|pll1p_val| pll1p_val / 2u8), + }; + #[cfg(all(stm32wba, peri_usb_otg_hs))] + let usb_refck_sel = match usb_refck { + Some(clk_val) => match clk_val { + Hertz(16_000_000) => Usbrefcksel::MHZ16, + Hertz(19_200_000) => Usbrefcksel::MHZ19_2, + Hertz(20_000_000) => Usbrefcksel::MHZ20, + Hertz(24_000_000) => Usbrefcksel::MHZ24, + Hertz(26_000_000) => Usbrefcksel::MHZ26, + Hertz(32_000_000) => Usbrefcksel::MHZ32, + _ => panic!("cannot select OTG_HS reference clock with source frequency of {}, must be one of 16, 19.2, 20, 24, 26, 32 MHz", clk_val), + }, + None => Usbrefcksel::MHZ24, + }; + #[cfg(all(stm32wba, peri_usb_otg_hs))] + SYSCFG.otghsphycr().modify(|w| { + w.set_clksel(usb_refck_sel); + }); + + let lsi = config.lsi.lsi.then_some(LSI_FREQ); + config.mux.init(); set_clocks!( @@ -164,6 +285,7 @@ pub(crate) unsafe fn init(config: Config) { hclk1: Some(hclk1), hclk2: Some(hclk2), hclk4: Some(hclk4), + hclk5: Some(hclk5), pclk1: Some(pclk1), pclk2: Some(pclk2), pclk7: Some(pclk7), @@ -171,12 +293,117 @@ pub(crate) unsafe fn init(config: Config) { pclk2_tim: Some(pclk2_tim), rtc: rtc, hse: hse, + lsi: lsi, hsi: hsi, + pll1_p: pll1.p, + pll1_q: pll1.q, + pll1_r: pll1.r, // TODO lse: None, - lsi: None, - pll1_p: None, - pll1_q: None, ); } + +pub(super) struct PllInput { + pub hsi: Option, + pub hse: Option, +} + +#[allow(unused)] +#[derive(Default)] +pub(super) struct PllOutput { + pub p: Option, + pub q: Option, + pub r: Option, +} + +fn pll_enable(enabled: bool) { + RCC.cr().modify(|w| w.set_pllon(enabled)); + while RCC.cr().read().pllrdy() != enabled {} +} + +fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) -> PllOutput { + // Disable PLL + pll_enable(false); + + let Some(pll) = config else { return PllOutput::default() }; + + let pre_src_freq = match pll.source { + PllSource::DISABLE => panic!("must not select PLL source as DISABLE"), + PllSource::HSE => unwrap!(input.hse), + PllSource::HSI => unwrap!(input.hsi), + PllSource::_RESERVED_1 => panic!("must not select RESERVED_1 source as DISABLE"), + }; + + // Only divide by the HSE prescaler when the PLL source is HSE + let src_freq = match pll.source { + PllSource::HSE => { + // read the prescaler bits and divide + let hsepre = RCC.cr().read().hsepre(); + pre_src_freq / hsepre + } + _ => pre_src_freq, + }; + + // Calculate the reference clock, which is the source divided by m + let ref_freq = src_freq / pll.prediv; + // Check limits per RM0515 § 12.4.3 + assert!(Hertz::mhz(4) <= ref_freq && ref_freq <= Hertz::mhz(16)); + + // Check PLL clocks per RM0515 § 12.4.5 + let (vco_min, vco_max, out_max) = match voltage_range { + VoltageScale::RANGE1 => (Hertz::mhz(128), Hertz::mhz(544), Hertz::mhz(100)), + VoltageScale::RANGE2 => panic!("PLL is unavailable in voltage range 2"), + }; + + // Calculate the PLL VCO clock + // let vco_freq = ref_freq * pll.mul; + // Calculate VCO frequency including fractional part: FVCO = Fref_ck × (N + FRAC/2^13) + let numerator = (ref_freq.0 as u64) * (((pll.mul as u64) + 1 << 13) + pll.frac.unwrap_or(0) as u64); + let vco_hz = (numerator >> 13) as u32; + let vco_freq = Hertz(vco_hz); + assert!(vco_freq >= vco_min && vco_freq <= vco_max); + + // Calculate output clocks. + let p = pll.divp.map(|div| vco_freq / div); + let q = pll.divq.map(|div| vco_freq / div); + let r = pll.divr.map(|div| vco_freq / div); + for freq in [p, q, r] { + if let Some(freq) = freq { + assert!(freq <= out_max); + } + } + + let divr = RCC.pll1divr(); + divr.write(|w| { + w.set_plln(pll.mul); + w.set_pllp(pll.divp.unwrap_or(PllDiv::DIV1)); + w.set_pllq(pll.divq.unwrap_or(PllDiv::DIV1)); + w.set_pllr(pll.divr.unwrap_or(PllDiv::DIV1)); + }); + RCC.pll1fracr().write(|w| {w.set_pllfracn(pll.frac.unwrap_or(0));}); + + let input_range = match ref_freq.0 { + ..=8_000_000 => Pllrge::FREQ_4TO8MHZ, + _ => Pllrge::FREQ_8TO16MHZ, + }; + + macro_rules! write_fields { + ($w:ident) => { + $w.set_pllpen(pll.divp.is_some()); + $w.set_pllqen(pll.divq.is_some()); + $w.set_pllren(pll.divr.is_some()); + $w.set_pllfracen(pll.frac.is_some()); + $w.set_pllm(pll.prediv); + $w.set_pllsrc(pll.source); + $w.set_pllrge(input_range); + }; + } + + RCC.pll1cfgr().write(|w| {write_fields!(w);}); + + // Enable PLL + pll_enable(true); + + PllOutput{ p, q, r } +} \ No newline at end of file diff --git a/examples/stm32wba/src/bin/pwm.rs b/examples/stm32wba/src/bin/pwm.rs new file mode 100644 index 000000000..54d223d34 --- /dev/null +++ b/examples/stm32wba/src/bin/pwm.rs @@ -0,0 +1,65 @@ +#![no_std] +#![no_main] + +use defmt::*; +use defmt_rtt as _; // global logger +use embassy_executor::Spawner; +use embassy_stm32::gpio::OutputType; +use embassy_stm32::rcc::{mux, AHB5Prescaler, AHBPrescaler, APBPrescaler, Sysclk, VoltageScale}; +use embassy_stm32::rcc::{PllDiv, PllMul, PllPreDiv, PllSource}; +use embassy_stm32::time::khz; +use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; +use embassy_stm32::Config; +use embassy_time::Timer; +use panic_probe as _; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + info!("Hello World!"); + + let mut config = Config::default(); + // Fine-tune PLL1 dividers/multipliers + config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { + source: PllSource::HSI, + prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz + mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO + divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) + // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) + divq: None, + divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) + frac: Some(0), // Fractional part (enabled) + }); + + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV1; + config.rcc.apb2_pre = APBPrescaler::DIV1; + config.rcc.apb7_pre = APBPrescaler::DIV1; + config.rcc.ahb5_pre = AHB5Prescaler::DIV4; + + // voltage scale for max performance + config.rcc.voltage_scale = VoltageScale::RANGE1; + // route PLL1_P into the USB‐OTG‐HS block + config.rcc.mux.otghssel = mux::Otghssel::PLL1_P; + config.rcc.sys = Sysclk::PLL1_R; + + let p = embassy_stm32::init(config); + + let ch1_pin = PwmPin::new(p.PA2, OutputType::PushPull); + let mut pwm = SimplePwm::new(p.TIM3, Some(ch1_pin), None, None, None, khz(10), Default::default()); + let mut ch1 = pwm.ch1(); + ch1.enable(); + + info!("PWM initialized"); + info!("PWM max duty {}", ch1.max_duty_cycle()); + + loop { + ch1.set_duty_cycle_fully_off(); + Timer::after_millis(300).await; + ch1.set_duty_cycle_fraction(1, 4); + Timer::after_millis(300).await; + ch1.set_duty_cycle_fraction(1, 2); + Timer::after_millis(300).await; + ch1.set_duty_cycle(ch1.max_duty_cycle() - 1); + Timer::after_millis(300).await; + } +} -- cgit From ee42deaab71b102ee2272f2db80a6509b98916e7 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Fri, 25 Jul 2025 20:05:45 -0700 Subject: WIP changes --- examples/stm32wba/src/bin/pwm.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/stm32wba/src/bin/pwm.rs b/examples/stm32wba/src/bin/pwm.rs index 54d223d34..fc1e0ff2d 100644 --- a/examples/stm32wba/src/bin/pwm.rs +++ b/examples/stm32wba/src/bin/pwm.rs @@ -5,7 +5,7 @@ use defmt::*; use defmt_rtt as _; // global logger use embassy_executor::Spawner; use embassy_stm32::gpio::OutputType; -use embassy_stm32::rcc::{mux, AHB5Prescaler, AHBPrescaler, APBPrescaler, Sysclk, VoltageScale}; +use embassy_stm32::rcc::{AHB5Prescaler, AHBPrescaler, APBPrescaler, Sysclk, VoltageScale}; use embassy_stm32::rcc::{PllDiv, PllMul, PllPreDiv, PllSource}; use embassy_stm32::time::khz; use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; @@ -38,8 +38,6 @@ async fn main(_spawner: Spawner) { // voltage scale for max performance config.rcc.voltage_scale = VoltageScale::RANGE1; - // route PLL1_P into the USB‐OTG‐HS block - config.rcc.mux.otghssel = mux::Otghssel::PLL1_P; config.rcc.sys = Sysclk::PLL1_R; let p = embassy_stm32::init(config); -- cgit From 1ccf6ef6c0ee5fb141631491c1c6629db218bbc1 Mon Sep 17 00:00:00 2001 From: korbin Date: Sat, 26 Jul 2025 17:41:18 -0600 Subject: add embassy-net defmt derives for config structs --- embassy-net/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 693a39ed5..2b1888170 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -106,6 +106,7 @@ impl StackResources { /// Static IP address configuration. #[cfg(feature = "proto-ipv4")] #[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct StaticConfigV4 { /// IP address and subnet mask. pub address: Ipv4Cidr, @@ -118,6 +119,7 @@ pub struct StaticConfigV4 { /// Static IPv6 address configuration #[cfg(feature = "proto-ipv6")] #[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct StaticConfigV6 { /// IP address and subnet mask. pub address: Ipv6Cidr, @@ -130,6 +132,7 @@ pub struct StaticConfigV6 { /// DHCP configuration. #[cfg(feature = "dhcpv4")] #[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub struct DhcpConfig { /// Maximum lease duration. @@ -169,6 +172,7 @@ impl Default for DhcpConfig { /// Network stack configuration. #[derive(Debug, Clone, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub struct Config { /// IPv4 configuration @@ -220,6 +224,7 @@ impl Config { /// Network stack IPv4 configuration. #[cfg(feature = "proto-ipv4")] #[derive(Debug, Clone, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ConfigV4 { /// Do not configure IPv4. #[default] @@ -234,6 +239,7 @@ pub enum ConfigV4 { /// Network stack IPv6 configuration. #[cfg(feature = "proto-ipv6")] #[derive(Debug, Clone, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ConfigV6 { /// Do not configure IPv6. #[default] -- cgit From 1379e15d6385e6a4613dc4ddd543ad9f42805bd2 Mon Sep 17 00:00:00 2001 From: korbin Date: Sat, 26 Jul 2025 17:45:27 -0600 Subject: add embassy-time/defmt config flag passthrough --- embassy-net/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index 526c8a4b3..a2665c770 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -24,7 +24,7 @@ features = ["defmt", "tcp", "udp", "raw", "dns", "icmp", "dhcpv4", "proto-ipv6", [features] ## Enable defmt -defmt = ["dep:defmt", "smoltcp/defmt", "embassy-net-driver/defmt", "heapless/defmt-03", "defmt?/ip_in_core"] +defmt = ["dep:defmt", "smoltcp/defmt", "embassy-net-driver/defmt", "embassy-time/defmt", "heapless/defmt-03", "defmt?/ip_in_core"] ## Trace all raw received and transmitted packets using defmt or log. packet-trace = [] -- cgit From 77a8bc27e9c34e363f321132ebb9e8d8ff684a9f Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 27 Jul 2025 02:03:43 +0200 Subject: ci: lower book, doc job prio --- .github/ci/book.sh | 2 +- .github/ci/doc.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ci/book.sh b/.github/ci/book.sh index 2466f53f5..c91d10d16 100755 --- a/.github/ci/book.sh +++ b/.github/ci/book.sh @@ -1,6 +1,6 @@ #!/bin/bash ## on push branch=main -## priority -9 +## priority -100 ## dedup dequeue set -euxo pipefail diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 9162b37ae..26971afdc 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -1,6 +1,6 @@ #!/bin/bash ## on push branch=main -## priority -10 +## priority -100 ## dedup dequeue set -euxo pipefail -- cgit From 4c98cda167ab8b704ff087be7af99a8db5915d31 Mon Sep 17 00:00:00 2001 From: korbin Date: Sun, 27 Jul 2025 06:47:25 -0600 Subject: add missing PartialEq and Eq trait derives to embassy-net config structs --- embassy-net/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 2b1888170..0bc6ffe6c 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -171,7 +171,7 @@ impl Default for DhcpConfig { } /// Network stack configuration. -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub struct Config { @@ -223,7 +223,7 @@ impl Config { /// Network stack IPv4 configuration. #[cfg(feature = "proto-ipv4")] -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ConfigV4 { /// Do not configure IPv4. @@ -238,7 +238,7 @@ pub enum ConfigV4 { /// Network stack IPv6 configuration. #[cfg(feature = "proto-ipv6")] -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ConfigV6 { /// Do not configure IPv6. -- cgit From 1b3674b30ac2b7deb8e19b132d5ba15351cb8ebd Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Sun, 27 Jul 2025 09:35:13 -0700 Subject: Added changes based on PR review --- embassy-stm32/build.rs | 2 +- embassy-stm32/src/rcc/wba.rs | 27 ++++----------------------- embassy-stm32/src/usb/otg.rs | 2 +- examples/stm32wba/src/bin/pwm.rs | 3 +-- 4 files changed, 7 insertions(+), 27 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 73860c64a..a4ed86bdf 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1599,7 +1599,7 @@ fn main() { for e in rcc_registers.ir.enums { fn is_rcc_name(e: &str) -> bool { match e { - "Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" => true, + "Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" | "Hpre5" => true, "Timpre" | "Pllrclkpre" => false, e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true, _ => false, diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index 0025d2a51..5f9d4d30a 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs @@ -1,6 +1,5 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale; use crate::pac::rcc::regs::Cfgr1; -use core::ops::Div; pub use crate::pac::rcc::vals::{ Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk, Pllsrc as PllSource, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, Hpre5 as AHB5Prescaler, Hdiv5, @@ -21,23 +20,6 @@ pub const HSI_FREQ: Hertz = Hertz(16_000_000); // HSE speed pub const HSE_FREQ: Hertz = Hertz(32_000_000); -// Allow dividing a Hertz value by an AHB5 prescaler directly -impl Div for Hertz { - type Output = Hertz; - fn div(self, rhs: AHB5Prescaler) -> Hertz { - // Map the prescaler enum to its integer divisor - let divisor = match rhs { - AHB5Prescaler::DIV1 => 1, - AHB5Prescaler::DIV2 => 2, - AHB5Prescaler::DIV3 => 3, - AHB5Prescaler::DIV4 => 4, - AHB5Prescaler::DIV6 => 6, - _ => unreachable!("Invalid AHB5 prescaler: {:?}", rhs), - }; - Hertz(self.0 / divisor) - } -} - #[derive(Clone, Copy, Eq, PartialEq)] pub struct Hse { pub prescaler: HsePrescaler, @@ -95,8 +77,7 @@ pub struct Config { pub apb7_pre: APBPrescaler, // low speed LSI/LSE/RTC - pub lsi: super::LsConfig, - // pub lsi2: super::LsConfig, + pub ls: super::LsConfig, pub voltage_scale: VoltageScale, @@ -116,7 +97,7 @@ impl Config { apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, apb7_pre: APBPrescaler::DIV1, - lsi: crate::rcc::LsConfig::new(), + ls: crate::rcc::LsConfig::new(), // lsi2: crate::rcc::LsConfig::new(), voltage_scale: VoltageScale::RANGE2, mux: super::mux::ClockMux::default(), @@ -151,7 +132,7 @@ pub(crate) unsafe fn init(config: Config) { crate::pac::PWR.vosr().write(|w| w.set_vos(config.voltage_scale)); while !crate::pac::PWR.vosr().read().vosrdy() {} - let rtc = config.lsi.init(); + let rtc = config.ls.init(); let hsi = config.hsi.then(|| { hsi_enable(); @@ -276,7 +257,7 @@ pub(crate) unsafe fn init(config: Config) { w.set_clksel(usb_refck_sel); }); - let lsi = config.lsi.lsi.then_some(LSI_FREQ); + let lsi = config.ls.lsi.then_some(LSI_FREQ); config.mux.init(); diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index b074cfa1b..81e6bff4c 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -336,7 +336,7 @@ impl<'d, T: Instance> Bus<'d, T> { critical_section::with(|_| { crate::pac::RCC.ahb2enr().modify(|w| { w.set_usb_otg_hsen(true); - w.set_otghsphyen(true); + w.set_usb_otg_hs_phyen(true); }); }); } diff --git a/examples/stm32wba/src/bin/pwm.rs b/examples/stm32wba/src/bin/pwm.rs index 54d223d34..611d7c097 100644 --- a/examples/stm32wba/src/bin/pwm.rs +++ b/examples/stm32wba/src/bin/pwm.rs @@ -5,7 +5,7 @@ use defmt::*; use defmt_rtt as _; // global logger use embassy_executor::Spawner; use embassy_stm32::gpio::OutputType; -use embassy_stm32::rcc::{mux, AHB5Prescaler, AHBPrescaler, APBPrescaler, Sysclk, VoltageScale}; +use embassy_stm32::rcc::{AHB5Prescaler, AHBPrescaler, APBPrescaler, Sysclk, VoltageScale}; use embassy_stm32::rcc::{PllDiv, PllMul, PllPreDiv, PllSource}; use embassy_stm32::time::khz; use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; @@ -39,7 +39,6 @@ async fn main(_spawner: Spawner) { // voltage scale for max performance config.rcc.voltage_scale = VoltageScale::RANGE1; // route PLL1_P into the USB‐OTG‐HS block - config.rcc.mux.otghssel = mux::Otghssel::PLL1_P; config.rcc.sys = Sysclk::PLL1_R; let p = embassy_stm32::init(config); -- cgit From 982117f5b0650734aece226d93343a30ac3a0b65 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Sun, 27 Jul 2025 09:42:17 -0700 Subject: Cargo fmt --- embassy-stm32/src/rcc/wba.rs | 33 +++++++++++++++++---------------- examples/stm32wba/src/bin/pwm.rs | 5 +++-- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index 5f9d4d30a..56ba7b58b 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs @@ -1,20 +1,18 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale; use crate::pac::rcc::regs::Cfgr1; +#[cfg(all(peri_usb_otg_hs))] +pub use crate::pac::rcc::vals::Otghssel; +use crate::pac::rcc::vals::Pllrge; pub use crate::pac::rcc::vals::{ - Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk, Pllsrc as PllSource, - Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, Hpre5 as AHB5Prescaler, Hdiv5, + Hdiv5, Hpre as AHBPrescaler, Hpre5 as AHB5Prescaler, Hsepre as HsePrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, + Plln as PllMul, Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk, }; -use crate::pac::rcc::vals::Pllrge; +#[cfg(all(peri_usb_otg_hs))] +pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG}; use crate::pac::{FLASH, RCC}; use crate::rcc::LSI_FREQ; use crate::time::Hertz; -#[cfg(all(peri_usb_otg_hs))] -pub use crate::pac::rcc::vals::Otghssel; - -#[cfg(all(peri_usb_otg_hs))] -pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG}; - /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); // HSE speed @@ -150,7 +148,7 @@ pub(crate) unsafe fn init(config: Config) { HSE_FREQ }); - let pll_input = PllInput {hse, hsi }; + let pll_input = PllInput { hse, hsi }; let pll1 = init_pll(config.pll1, &pll_input, config.voltage_scale); @@ -231,7 +229,6 @@ pub(crate) unsafe fn init(config: Config) { let hclk5 = sys_clk / config.ahb5_pre; - #[cfg(all(stm32wba, peri_usb_otg_hs))] let usb_refck = match config.mux.otghssel { Otghssel::HSE => hse, @@ -341,7 +338,7 @@ fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) // let vco_freq = ref_freq * pll.mul; // Calculate VCO frequency including fractional part: FVCO = Fref_ck × (N + FRAC/2^13) let numerator = (ref_freq.0 as u64) * (((pll.mul as u64) + 1 << 13) + pll.frac.unwrap_or(0) as u64); - let vco_hz = (numerator >> 13) as u32; + let vco_hz = (numerator >> 13) as u32; let vco_freq = Hertz(vco_hz); assert!(vco_freq >= vco_min && vco_freq <= vco_max); @@ -362,7 +359,9 @@ fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) w.set_pllq(pll.divq.unwrap_or(PllDiv::DIV1)); w.set_pllr(pll.divr.unwrap_or(PllDiv::DIV1)); }); - RCC.pll1fracr().write(|w| {w.set_pllfracn(pll.frac.unwrap_or(0));}); + RCC.pll1fracr().write(|w| { + w.set_pllfracn(pll.frac.unwrap_or(0)); + }); let input_range = match ref_freq.0 { ..=8_000_000 => Pllrge::FREQ_4TO8MHZ, @@ -381,10 +380,12 @@ fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) }; } - RCC.pll1cfgr().write(|w| {write_fields!(w);}); + RCC.pll1cfgr().write(|w| { + write_fields!(w); + }); // Enable PLL pll_enable(true); - PllOutput{ p, q, r } -} \ No newline at end of file + PllOutput { p, q, r } +} diff --git a/examples/stm32wba/src/bin/pwm.rs b/examples/stm32wba/src/bin/pwm.rs index 611d7c097..2c696834a 100644 --- a/examples/stm32wba/src/bin/pwm.rs +++ b/examples/stm32wba/src/bin/pwm.rs @@ -5,8 +5,9 @@ use defmt::*; use defmt_rtt as _; // global logger use embassy_executor::Spawner; use embassy_stm32::gpio::OutputType; -use embassy_stm32::rcc::{AHB5Prescaler, AHBPrescaler, APBPrescaler, Sysclk, VoltageScale}; -use embassy_stm32::rcc::{PllDiv, PllMul, PllPreDiv, PllSource}; +use embassy_stm32::rcc::{ + AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, +}; use embassy_stm32::time::khz; use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; use embassy_stm32::Config; -- cgit From 1d3c48cf4539fe1959f25918a6fa3521a5678837 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Sun, 27 Jul 2025 13:49:39 -0700 Subject: Working USB_OTG_HS example --- embassy-stm32/build.rs | 2 +- embassy-stm32/src/rcc/wba.rs | 60 +++++++++----------------- embassy-stm32/src/usb/mod.rs | 2 +- examples/stm32wba/Cargo.toml | 3 +- examples/stm32wba/src/bin/usb_hs_serial.rs | 68 ++++++++++++++++-------------- 5 files changed, 60 insertions(+), 75 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 753f94fa6..deefb13c1 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1599,7 +1599,7 @@ fn main() { for e in rcc_registers.ir.enums { fn is_rcc_name(e: &str) -> bool { match e { - "Pllp" | "Pllq" | "Pllr" | "Plldivst" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" => true, + "Pllp" | "Pllq" | "Pllr" | "Plldivst" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" | "Hpre5" => true, "Timpre" | "Pllrclkpre" => false, e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true, _ => false, diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index 0025d2a51..56ba7b58b 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs @@ -1,43 +1,23 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale; use crate::pac::rcc::regs::Cfgr1; -use core::ops::Div; +#[cfg(all(peri_usb_otg_hs))] +pub use crate::pac::rcc::vals::Otghssel; +use crate::pac::rcc::vals::Pllrge; pub use crate::pac::rcc::vals::{ - Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk, Pllsrc as PllSource, - Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, Hpre5 as AHB5Prescaler, Hdiv5, + Hdiv5, Hpre as AHBPrescaler, Hpre5 as AHB5Prescaler, Hsepre as HsePrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, + Plln as PllMul, Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk, }; -use crate::pac::rcc::vals::Pllrge; +#[cfg(all(peri_usb_otg_hs))] +pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG}; use crate::pac::{FLASH, RCC}; use crate::rcc::LSI_FREQ; use crate::time::Hertz; -#[cfg(all(peri_usb_otg_hs))] -pub use crate::pac::rcc::vals::Otghssel; - -#[cfg(all(peri_usb_otg_hs))] -pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG}; - /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); // HSE speed pub const HSE_FREQ: Hertz = Hertz(32_000_000); -// Allow dividing a Hertz value by an AHB5 prescaler directly -impl Div for Hertz { - type Output = Hertz; - fn div(self, rhs: AHB5Prescaler) -> Hertz { - // Map the prescaler enum to its integer divisor - let divisor = match rhs { - AHB5Prescaler::DIV1 => 1, - AHB5Prescaler::DIV2 => 2, - AHB5Prescaler::DIV3 => 3, - AHB5Prescaler::DIV4 => 4, - AHB5Prescaler::DIV6 => 6, - _ => unreachable!("Invalid AHB5 prescaler: {:?}", rhs), - }; - Hertz(self.0 / divisor) - } -} - #[derive(Clone, Copy, Eq, PartialEq)] pub struct Hse { pub prescaler: HsePrescaler, @@ -95,8 +75,7 @@ pub struct Config { pub apb7_pre: APBPrescaler, // low speed LSI/LSE/RTC - pub lsi: super::LsConfig, - // pub lsi2: super::LsConfig, + pub ls: super::LsConfig, pub voltage_scale: VoltageScale, @@ -116,7 +95,7 @@ impl Config { apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, apb7_pre: APBPrescaler::DIV1, - lsi: crate::rcc::LsConfig::new(), + ls: crate::rcc::LsConfig::new(), // lsi2: crate::rcc::LsConfig::new(), voltage_scale: VoltageScale::RANGE2, mux: super::mux::ClockMux::default(), @@ -151,7 +130,7 @@ pub(crate) unsafe fn init(config: Config) { crate::pac::PWR.vosr().write(|w| w.set_vos(config.voltage_scale)); while !crate::pac::PWR.vosr().read().vosrdy() {} - let rtc = config.lsi.init(); + let rtc = config.ls.init(); let hsi = config.hsi.then(|| { hsi_enable(); @@ -169,7 +148,7 @@ pub(crate) unsafe fn init(config: Config) { HSE_FREQ }); - let pll_input = PllInput {hse, hsi }; + let pll_input = PllInput { hse, hsi }; let pll1 = init_pll(config.pll1, &pll_input, config.voltage_scale); @@ -250,7 +229,6 @@ pub(crate) unsafe fn init(config: Config) { let hclk5 = sys_clk / config.ahb5_pre; - #[cfg(all(stm32wba, peri_usb_otg_hs))] let usb_refck = match config.mux.otghssel { Otghssel::HSE => hse, @@ -276,7 +254,7 @@ pub(crate) unsafe fn init(config: Config) { w.set_clksel(usb_refck_sel); }); - let lsi = config.lsi.lsi.then_some(LSI_FREQ); + let lsi = config.ls.lsi.then_some(LSI_FREQ); config.mux.init(); @@ -360,7 +338,7 @@ fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) // let vco_freq = ref_freq * pll.mul; // Calculate VCO frequency including fractional part: FVCO = Fref_ck × (N + FRAC/2^13) let numerator = (ref_freq.0 as u64) * (((pll.mul as u64) + 1 << 13) + pll.frac.unwrap_or(0) as u64); - let vco_hz = (numerator >> 13) as u32; + let vco_hz = (numerator >> 13) as u32; let vco_freq = Hertz(vco_hz); assert!(vco_freq >= vco_min && vco_freq <= vco_max); @@ -381,7 +359,9 @@ fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) w.set_pllq(pll.divq.unwrap_or(PllDiv::DIV1)); w.set_pllr(pll.divr.unwrap_or(PllDiv::DIV1)); }); - RCC.pll1fracr().write(|w| {w.set_pllfracn(pll.frac.unwrap_or(0));}); + RCC.pll1fracr().write(|w| { + w.set_pllfracn(pll.frac.unwrap_or(0)); + }); let input_range = match ref_freq.0 { ..=8_000_000 => Pllrge::FREQ_4TO8MHZ, @@ -400,10 +380,12 @@ fn init_pll(config: Option, input: &PllInput, voltage_range: VoltageScale) }; } - RCC.pll1cfgr().write(|w| {write_fields!(w);}); + RCC.pll1cfgr().write(|w| { + write_fields!(w); + }); // Enable PLL pll_enable(true); - PllOutput{ p, q, r } -} \ No newline at end of file + PllOutput { p, q, r } +} diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs index d987a056d..d052934f8 100644 --- a/embassy-stm32/src/usb/mod.rs +++ b/embassy-stm32/src/usb/mod.rs @@ -110,7 +110,7 @@ fn common_init() { w.set_usv(crate::pac::pwr::vals::Usv::B_0X1); }); crate::pac::PWR.vosr().modify(|w| { - w.set_vdd11usbdis(true); + w.set_vdd11usbdis(false); }); crate::pac::PWR.vosr().modify(|w| { w.set_usbpwren(true); diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml index 1ddae5fee..336ea1e2e 100644 --- a/examples/stm32wba/Cargo.toml +++ b/examples/stm32wba/Cargo.toml @@ -9,7 +9,6 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } @@ -18,7 +17,7 @@ defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -embedded-hal = "1.0.0" +embedded-hal = "0.2.6" panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.8", default-features = false } static_cell = "2" diff --git a/examples/stm32wba/src/bin/usb_hs_serial.rs b/examples/stm32wba/src/bin/usb_hs_serial.rs index 41440a940..2e17e52d1 100644 --- a/examples/stm32wba/src/bin/usb_hs_serial.rs +++ b/examples/stm32wba/src/bin/usb_hs_serial.rs @@ -2,17 +2,14 @@ #![no_main] use defmt::{panic, *}; -use defmt_rtt as _; // global logger use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_stm32::rcc::{mux, AHB5Prescaler, AHBPrescaler, APBPrescaler, Hse, HsePrescaler, Sysclk, VoltageScale}; -use embassy_stm32::rcc::{PllDiv, PllMul, PllPreDiv, PllSource}; use embassy_stm32::usb::{Driver, Instance}; use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; use embassy_usb::driver::EndpointError; use embassy_usb::Builder; -use panic_probe as _; +use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { USB_OTG_HS => usb::InterruptHandler; @@ -24,37 +21,44 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); - // External HSE (32 MHz) setup - // config.rcc.hse = Some(Hse { - // prescaler: HsePrescaler::DIV2, - // }); - - // Fine-tune PLL1 dividers/multipliers - config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { - source: PllSource::HSI, - prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz - mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO - divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) - // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) - divq: None, - divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) - frac: Some(0), // Fractional part (enabled) - }); - - config.rcc.ahb_pre = AHBPrescaler::DIV1; - config.rcc.apb1_pre = APBPrescaler::DIV1; - config.rcc.apb2_pre = APBPrescaler::DIV1; - config.rcc.apb7_pre = APBPrescaler::DIV1; - config.rcc.ahb5_pre = AHB5Prescaler::DIV4; - - // voltage scale for max performance - config.rcc.voltage_scale = VoltageScale::RANGE1; - // route PLL1_P into the USB‐OTG‐HS block - config.rcc.mux.otghssel = mux::Otghssel::PLL1_P; - config.rcc.sys = Sysclk::PLL1_R; + + { + use embassy_stm32::rcc::*; + // External HSE (32 MHz) setup + // config.rcc.hse = Some(Hse { + // prescaler: HsePrescaler::DIV2, + // }); + + // Fine-tune PLL1 dividers/multipliers + config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, + prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz + mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO + divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) + divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) + // divq: None, + divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) + frac: Some(0), // Fractional part (enabled) + }); + + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV1; + config.rcc.apb2_pre = APBPrescaler::DIV1; + config.rcc.apb7_pre = APBPrescaler::DIV1; + config.rcc.ahb5_pre = AHB5Prescaler::DIV4; + + config.rcc.voltage_scale = VoltageScale::RANGE1; + config.rcc.mux.otghssel = mux::Otghssel::PLL1_P; + config.rcc.sys = Sysclk::PLL1_R; + } let p = embassy_stm32::init(config); + // TRDT set to 5 + // ASVLD set to 1 + // BSVLD set to 1 + + // Create the driver, from the HAL. let mut ep_out_buffer = [0u8; 256]; let mut config = embassy_stm32::usb::Config::default(); -- cgit From 21566666b852e38641ef8ccb3d2b988dfd5a34c5 Mon Sep 17 00:00:00 2001 From: Oscar Aurin Date: Sun, 13 Jul 2025 23:41:17 +0200 Subject: examples: fix RP2040 link establishing logic --- examples/rp/src/bin/wifi_tcp_server.rs | 27 +++++++++++---------------- examples/rp/src/bin/wifi_webrequest.rs | 33 ++++++++++----------------------- 2 files changed, 21 insertions(+), 39 deletions(-) diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index fbc957e0e..ed1a03fcf 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -18,7 +18,7 @@ use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{DMA_CH0, PIO0}; use embassy_rp::pio::{InterruptHandler, Pio}; -use embassy_time::{Duration, Timer}; +use embassy_time::Duration; use embedded_io_async::Write; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; @@ -97,26 +97,21 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(net_task(runner))); - loop { - match control - .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) - .await - { - Ok(_) => break, - Err(err) => { - info!("join failed with status={}", err.status); - } - } + while let Err(err) = control + .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) + .await + { + info!("join failed with status={}", err.status); } - // Wait for DHCP, not necessary when using static IP + info!("waiting for link..."); + stack.wait_link_up().await; + info!("waiting for DHCP..."); - while !stack.is_config_up() { - Timer::after_millis(100).await; - } - info!("DHCP is now up!"); + stack.wait_config_up().await; // And now we can use it! + info!("Stack is up!"); let mut rx_buffer = [0; 4096]; let mut tx_buffer = [0; 4096]; diff --git a/examples/rp/src/bin/wifi_webrequest.rs b/examples/rp/src/bin/wifi_webrequest.rs index 1efd1cd28..a75253bb0 100644 --- a/examples/rp/src/bin/wifi_webrequest.rs +++ b/examples/rp/src/bin/wifi_webrequest.rs @@ -100,33 +100,20 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(net_task(runner))); - loop { - match control - .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) - .await - { - Ok(_) => break, - Err(err) => { - info!("join failed with status={}", err.status); - } - } - } - - // Wait for DHCP, not necessary when using static IP - info!("waiting for DHCP..."); - while !stack.is_config_up() { - Timer::after_millis(100).await; + while let Err(err) = control + .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) + .await + { + info!("join failed with status={}", err.status); } - info!("DHCP is now up!"); - info!("waiting for link up..."); - while !stack.is_link_up() { - Timer::after_millis(500).await; - } - info!("Link is up!"); + info!("waiting for link..."); + stack.wait_link_up().await; - info!("waiting for stack to be up..."); + info!("waiting for DHCP..."); stack.wait_config_up().await; + + // And now we can use it! info!("Stack is up!"); // And now we can use it! -- cgit From 05f1c75f8b01e36e641dca35b6d6f763b6babde5 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Sun, 27 Jul 2025 14:24:36 -0700 Subject: Fixed timer config on STM32WBA pwm example --- examples/stm32wba/src/bin/pwm.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/stm32wba/src/bin/pwm.rs b/examples/stm32wba/src/bin/pwm.rs index 2c696834a..de690fda0 100644 --- a/examples/stm32wba/src/bin/pwm.rs +++ b/examples/stm32wba/src/bin/pwm.rs @@ -44,8 +44,8 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(config); - let ch1_pin = PwmPin::new(p.PA2, OutputType::PushPull); - let mut pwm = SimplePwm::new(p.TIM3, Some(ch1_pin), None, None, None, khz(10), Default::default()); + let ch1_pin = PwmPin::new(p.PB8, OutputType::PushPull); + let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default()); let mut ch1 = pwm.ch1(); ch1.enable(); -- cgit From c708cefe03363135c466a3c0e8543a95973bce7a Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 27 Jul 2025 23:38:23 +0200 Subject: Add cooldown to doc, book jobs. --- .github/ci/book.sh | 2 ++ .github/ci/doc.sh | 1 + 2 files changed, 3 insertions(+) diff --git a/.github/ci/book.sh b/.github/ci/book.sh index c91d10d16..dada4b348 100755 --- a/.github/ci/book.sh +++ b/.github/ci/book.sh @@ -2,6 +2,7 @@ ## on push branch=main ## priority -100 ## dedup dequeue +## cooldown 15m set -euxo pipefail @@ -17,3 +18,4 @@ kubectl exec $POD -- mkdir -p /usr/share/nginx/html kubectl cp book.tar $POD:/usr/share/nginx/html/ kubectl exec $POD -- find /usr/share/nginx/html kubectl exec $POD -- tar -C /usr/share/nginx/html -xvf /usr/share/nginx/html/book.tar +3 diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 26971afdc..ac96008d8 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -2,6 +2,7 @@ ## on push branch=main ## priority -100 ## dedup dequeue +## cooldown 15m set -euxo pipefail -- cgit From 81bef219e315aca005e50143757c681d5bc122ee Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Sun, 27 Jul 2025 16:44:43 -0700 Subject: Working USB_OTG_HS example for STM32WBA --- embassy-stm32/src/lib.rs | 6 +- embassy-stm32/src/usb/mod.rs | 4 +- embassy-stm32/src/usb/otg.rs | 7 -- examples/stm32wba/src/bin/usb_hs_serial.rs | 25 ++---- examples/stm32wba/src/bin/usb_serial.rs | 119 ----------------------------- 5 files changed, 12 insertions(+), 149 deletions(-) delete mode 100644 examples/stm32wba/src/bin/usb_serial.rs diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index d893f1b54..a676677e1 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -546,7 +546,11 @@ fn init_hw(config: Config) -> Peripherals { { use crate::pac::pwr::vals; crate::pac::PWR.svmcr().modify(|w| { - w.set_io2sv(if config.enable_independent_io_supply {vals::Io2sv::B_0X1} else {vals::Io2sv::B_0X0}); + w.set_io2sv(if config.enable_independent_io_supply { + vals::Io2sv::B_0X1 + } else { + vals::Io2sv::B_0X0 + }); }); } #[cfg(stm32u5)] diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs index d052934f8..62c751ac8 100644 --- a/embassy-stm32/src/usb/mod.rs +++ b/embassy-stm32/src/usb/mod.rs @@ -111,10 +111,8 @@ fn common_init() { }); crate::pac::PWR.vosr().modify(|w| { w.set_vdd11usbdis(false); - }); - crate::pac::PWR.vosr().modify(|w| { w.set_usbpwren(true); - }) + }); }); // Wait for USB power to stabilize diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index abf54cbad..1c3b99b93 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -330,19 +330,12 @@ impl<'d, T: Instance> Bus<'d, T> { #[cfg(all(stm32wba, peri_usb_otg_hs))] { critical_section::with(|_| { - // crate::pac::RCC.apb7enr().modify(|w| { - // w.set_syscfgen(true); - // }); crate::pac::RCC.ahb2enr().modify(|w| { w.set_usb_otg_hsen(true); w.set_usb_otg_hs_phyen(true); }); }); - // pub use crate::pac::rcc::vals::Otghssel; - // // select HSE - // crate::pac::RCC.ccipr2().modify(|w| {w.set_otghssel(Otghssel::HSE);}); - crate::pac::SYSCFG.otghsphytuner2().modify(|w| { w.set_compdistune(0b010); w.set_sqrxtune(0b000); diff --git a/examples/stm32wba/src/bin/usb_hs_serial.rs b/examples/stm32wba/src/bin/usb_hs_serial.rs index 2e17e52d1..20bdeaac3 100644 --- a/examples/stm32wba/src/bin/usb_hs_serial.rs +++ b/examples/stm32wba/src/bin/usb_hs_serial.rs @@ -21,24 +21,16 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); - { use embassy_stm32::rcc::*; - // External HSE (32 MHz) setup - // config.rcc.hse = Some(Hse { - // prescaler: HsePrescaler::DIV2, - // }); - - // Fine-tune PLL1 dividers/multipliers config.rcc.pll1 = Some(Pll { source: PllSource::HSI, - prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz - mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO - divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) - divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) - // divq: None, - divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) - frac: Some(0), // Fractional part (enabled) + prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz + mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO + divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) + divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz + divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USB_OTG_HS) + frac: Some(0), // Fractional part (disabled) }); config.rcc.ahb_pre = AHBPrescaler::DIV1; @@ -54,11 +46,6 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(config); - // TRDT set to 5 - // ASVLD set to 1 - // BSVLD set to 1 - - // Create the driver, from the HAL. let mut ep_out_buffer = [0u8; 256]; let mut config = embassy_stm32::usb::Config::default(); diff --git a/examples/stm32wba/src/bin/usb_serial.rs b/examples/stm32wba/src/bin/usb_serial.rs deleted file mode 100644 index 8d60aed8c..000000000 --- a/examples/stm32wba/src/bin/usb_serial.rs +++ /dev/null @@ -1,119 +0,0 @@ -#![no_std] -#![no_main] - -use defmt::{panic, *}; -use defmt_rtt as _; // global logger -use embassy_executor::Spawner; -use embassy_futures::join::join; -use embassy_stm32::usb::{Driver, Instance}; -use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; -use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; -use embassy_usb::driver::EndpointError; -use embassy_usb::Builder; -use panic_probe as _; - -bind_interrupts!(struct Irqs { - OTG_HS => usb::InterruptHandler; -}); - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - info!("Hello World!"); - - let mut config = Config::default(); - { - use embassy_stm32::rcc::*; - config.rcc.hsi = true; - config.rcc.pll1 = Some(Pll { - source: PllSource::HSI, // 16 MHz - prediv: PllPreDiv::DIV1, - mul: PllMul::MUL10, - divp: None, - divq: None, - divr: Some(PllDiv::DIV1), // 160 MHz - }); - config.rcc.sys = Sysclk::PLL1_R; - config.rcc.voltage_range = VoltageScale::RANGE1; - config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB - config.rcc.mux.iclksel = mux::Iclksel::HSI48; // USB uses ICLK - } - - let p = embassy_stm32::init(config); - - // Create the driver, from the HAL. - let mut ep_out_buffer = [0u8; 256]; - let mut config = embassy_stm32::usb::Config::default(); - // Do not enable vbus_detection. This is a safe default that works in all boards. - // However, if your USB device is self-powered (can stay powered on if USB is unplugged), you need - // to enable vbus_detection to comply with the USB spec. If you enable it, the board - // has to support it or USB won't work at all. See docs on `vbus_detection` for details. - config.vbus_detection = false; - let driver = Driver::new_hs(p.USB_OTG_HS, Irqs, p.PD6, p.PD7, &mut ep_out_buffer, config); - - // Create embassy-usb Config - let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); - config.manufacturer = Some("Embassy"); - config.product = Some("USB-serial example"); - config.serial_number = Some("12345678"); - - // Create embassy-usb DeviceBuilder using the driver and config. - // It needs some buffers for building the descriptors. - let mut config_descriptor = [0; 256]; - let mut bos_descriptor = [0; 256]; - let mut control_buf = [0; 64]; - - let mut state = State::new(); - - let mut builder = Builder::new( - driver, - config, - &mut config_descriptor, - &mut bos_descriptor, - &mut [], // no msos descriptors - &mut control_buf, - ); - - // Create classes on the builder. - let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); - - // Build the builder. - let mut usb = builder.build(); - - // Run the USB device. - let usb_fut = usb.run(); - - // Do stuff with the class! - let echo_fut = async { - loop { - class.wait_connection().await; - info!("Connected"); - let _ = echo(&mut class).await; - info!("Disconnected"); - } - }; - - // Run everything concurrently. - // If we had made everything `'static` above instead, we could do this using separate tasks instead. - join(usb_fut, echo_fut).await; -} - -struct Disconnected {} - -impl From for Disconnected { - fn from(val: EndpointError) -> Self { - match val { - EndpointError::BufferOverflow => panic!("Buffer overflow"), - EndpointError::Disabled => Disconnected {}, - } - } -} - -async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> { - let mut buf = [0; 64]; - loop { - let n = class.read_packet(&mut buf).await?; - let data = &buf[..n]; - info!("data: {:x}", data); - class.write_packet(data).await?; - } -} -- cgit From 9a1f1cc02c7eb83c3b30de2706cd33eab95a221e Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Sun, 27 Jul 2025 17:05:43 -0700 Subject: Separated USB_OTG_HS to STM32WBA6 --- embassy-stm32/Cargo.toml | 4 +- examples/stm32wba/src/bin/usb_hs_serial.rs | 125 ---------------------------- examples/stm32wba6/.cargo/config.toml | 8 ++ examples/stm32wba6/Cargo.toml | 26 ++++++ examples/stm32wba6/build.rs | 10 +++ examples/stm32wba6/src/bin/adc.rs | 49 +++++++++++ examples/stm32wba6/src/bin/blinky.rs | 26 ++++++ examples/stm32wba6/src/bin/button_exti.rs | 25 ++++++ examples/stm32wba6/src/bin/pwm.rs | 65 +++++++++++++++ examples/stm32wba6/src/bin/usb_hs_serial.rs | 125 ++++++++++++++++++++++++++++ 10 files changed, 336 insertions(+), 127 deletions(-) delete mode 100644 examples/stm32wba/src/bin/usb_hs_serial.rs create mode 100644 examples/stm32wba6/.cargo/config.toml create mode 100644 examples/stm32wba6/Cargo.toml create mode 100644 examples/stm32wba6/build.rs create mode 100644 examples/stm32wba6/src/bin/adc.rs create mode 100644 examples/stm32wba6/src/bin/blinky.rs create mode 100644 examples/stm32wba6/src/bin/button_exti.rs create mode 100644 examples/stm32wba6/src/bin/pwm.rs create mode 100644 examples/stm32wba6/src/bin/usb_hs_serial.rs diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index ab3a34726..520443466 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-dbdc1a4ea26229805def4738b777933803086f93" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-df3f5212f2dd70955a6b3d0137e7b4457c6047bf" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-dbdc1a4ea26229805def4738b777933803086f93", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-df3f5212f2dd70955a6b3d0137e7b4457c6047bf", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/examples/stm32wba/src/bin/usb_hs_serial.rs b/examples/stm32wba/src/bin/usb_hs_serial.rs deleted file mode 100644 index 20bdeaac3..000000000 --- a/examples/stm32wba/src/bin/usb_hs_serial.rs +++ /dev/null @@ -1,125 +0,0 @@ -#![no_std] -#![no_main] - -use defmt::{panic, *}; -use embassy_executor::Spawner; -use embassy_futures::join::join; -use embassy_stm32::usb::{Driver, Instance}; -use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; -use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; -use embassy_usb::driver::EndpointError; -use embassy_usb::Builder; -use {defmt_rtt as _, panic_probe as _}; - -bind_interrupts!(struct Irqs { - USB_OTG_HS => usb::InterruptHandler; -}); - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - info!("Hello World!"); - - let mut config = Config::default(); - - { - use embassy_stm32::rcc::*; - config.rcc.pll1 = Some(Pll { - source: PllSource::HSI, - prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz - mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO - divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) - divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz - divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USB_OTG_HS) - frac: Some(0), // Fractional part (disabled) - }); - - config.rcc.ahb_pre = AHBPrescaler::DIV1; - config.rcc.apb1_pre = APBPrescaler::DIV1; - config.rcc.apb2_pre = APBPrescaler::DIV1; - config.rcc.apb7_pre = APBPrescaler::DIV1; - config.rcc.ahb5_pre = AHB5Prescaler::DIV4; - - config.rcc.voltage_scale = VoltageScale::RANGE1; - config.rcc.mux.otghssel = mux::Otghssel::PLL1_P; - config.rcc.sys = Sysclk::PLL1_R; - } - - let p = embassy_stm32::init(config); - - // Create the driver, from the HAL. - let mut ep_out_buffer = [0u8; 256]; - let mut config = embassy_stm32::usb::Config::default(); - // Do not enable vbus_detection. This is a safe default that works in all boards. - // However, if your USB device is self-powered (can stay powered on if USB is unplugged), you need - // to enable vbus_detection to comply with the USB spec. If you enable it, the board - // has to support it or USB won't work at all. See docs on `vbus_detection` for details. - config.vbus_detection = false; - let driver = Driver::new_hs(p.USB_OTG_HS, Irqs, p.PD6, p.PD7, &mut ep_out_buffer, config); - - // Create embassy-usb Config - let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); - config.manufacturer = Some("Embassy"); - config.product = Some("USB-serial example"); - config.serial_number = Some("12345678"); - - // Create embassy-usb DeviceBuilder using the driver and config. - // It needs some buffers for building the descriptors. - let mut config_descriptor = [0; 256]; - let mut bos_descriptor = [0; 256]; - let mut control_buf = [0; 64]; - - let mut state = State::new(); - - let mut builder = Builder::new( - driver, - config, - &mut config_descriptor, - &mut bos_descriptor, - &mut [], // no msos descriptors - &mut control_buf, - ); - - // Create classes on the builder. - let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); - - // Build the builder. - let mut usb = builder.build(); - - // Run the USB device. - let usb_fut = usb.run(); - - // Do stuff with the class! - let echo_fut = async { - loop { - class.wait_connection().await; - info!("Connected"); - let _ = echo(&mut class).await; - info!("Disconnected"); - } - }; - - // Run everything concurrently. - // If we had made everything `'static` above instead, we could do this using separate tasks instead. - join(usb_fut, echo_fut).await; -} - -struct Disconnected {} - -impl From for Disconnected { - fn from(val: EndpointError) -> Self { - match val { - EndpointError::BufferOverflow => panic!("Buffer overflow"), - EndpointError::Disabled => Disconnected {}, - } - } -} - -async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> { - let mut buf = [0; 64]; - loop { - let n = class.read_packet(&mut buf).await?; - let data = &buf[..n]; - info!("data: {:x}", data); - class.write_packet(data).await?; - } -} diff --git a/examples/stm32wba6/.cargo/config.toml b/examples/stm32wba6/.cargo/config.toml new file mode 100644 index 000000000..1896068d8 --- /dev/null +++ b/examples/stm32wba6/.cargo/config.toml @@ -0,0 +1,8 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +runner = "probe-rs run --chip STM32WBA65RI" + +[build] +target = "thumbv8m.main-none-eabihf" + +[env] +DEFMT_LOG = "trace" diff --git a/examples/stm32wba6/Cargo.toml b/examples/stm32wba6/Cargo.toml new file mode 100644 index 000000000..19c5e1e75 --- /dev/null +++ b/examples/stm32wba6/Cargo.toml @@ -0,0 +1,26 @@ +[package] +edition = "2021" +name = "embassy-stm32wba-examples" +version = "0.1.0" +license = "MIT OR Apache-2.0" + +[dependencies] +embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba65ri", "time-driver-any", "memory-x", "exti"] } +embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } + +defmt = "1.0.1" +defmt-rtt = "1.0.0" + +cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } +cortex-m-rt = "0.7.0" +embedded-hal = "1.0.0" +panic-probe = { version = "1.0.0", features = ["print-defmt"] } +heapless = { version = "0.8", default-features = false } +static_cell = "2" + +[profile.release] +debug = 2 diff --git a/examples/stm32wba6/build.rs b/examples/stm32wba6/build.rs new file mode 100644 index 000000000..8fc6faab8 --- /dev/null +++ b/examples/stm32wba6/build.rs @@ -0,0 +1,10 @@ +use std::error::Error; + +fn main() -> Result<(), Box> { + println!("cargo:rerun-if-changed=link.x"); + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + + Ok(()) +} diff --git a/examples/stm32wba6/src/bin/adc.rs b/examples/stm32wba6/src/bin/adc.rs new file mode 100644 index 000000000..a9651d57e --- /dev/null +++ b/examples/stm32wba6/src/bin/adc.rs @@ -0,0 +1,49 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_stm32::adc::{adc4, AdcChannel}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: embassy_executor::Spawner) { + let config = embassy_stm32::Config::default(); + + let mut p = embassy_stm32::init(config); + + // **** ADC4 init **** + let mut adc4 = adc4::Adc4::new(p.ADC4); + let mut adc4_pin1 = p.PA0; // A4 + let mut adc4_pin2 = p.PA1; // A5 + adc4.set_resolution(adc4::Resolution::BITS12); + adc4.set_averaging(adc4::Averaging::Samples256); + adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); + let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); + + // **** ADC4 blocking read **** + let raw: u16 = adc4.blocking_read(&mut adc4_pin1); + let volt: f32 = 3.0 * raw as f32 / max4 as f32; + info!("Read adc4 pin 1 {}", volt); + + let raw: u16 = adc4.blocking_read(&mut adc4_pin2); + let volt: f32 = 3.3 * raw as f32 / max4 as f32; + info!("Read adc4 pin 2 {}", volt); + + // **** ADC4 async read **** + let mut degraded41 = adc4_pin1.degrade_adc(); + let mut degraded42 = adc4_pin2.degrade_adc(); + let mut measurements = [0u16; 2]; + + // The channels must be in ascending order and can't repeat for ADC4 + adc4.read( + p.GPDMA1_CH1.reborrow(), + [&mut degraded42, &mut degraded41].into_iter(), + &mut measurements, + ) + .await + .unwrap(); + let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; + let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; + info!("Async read 4 pin 1 {}", volt1); + info!("Async read 4 pin 2 {}", volt2); +} diff --git a/examples/stm32wba6/src/bin/blinky.rs b/examples/stm32wba6/src/bin/blinky.rs new file mode 100644 index 000000000..0d803b257 --- /dev/null +++ b/examples/stm32wba6/src/bin/blinky.rs @@ -0,0 +1,26 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::gpio::{Level, Output, Speed}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + info!("Hello World!"); + + let mut led = Output::new(p.PB4, Level::High, Speed::Low); + + loop { + info!("high"); + led.set_high(); + Timer::after_millis(500).await; + + info!("low"); + led.set_low(); + Timer::after_millis(500).await; + } +} diff --git a/examples/stm32wba6/src/bin/button_exti.rs b/examples/stm32wba6/src/bin/button_exti.rs new file mode 100644 index 000000000..34a08bbc6 --- /dev/null +++ b/examples/stm32wba6/src/bin/button_exti.rs @@ -0,0 +1,25 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::exti::ExtiInput; +use embassy_stm32::gpio::Pull; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + info!("Hello World!"); + + let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); + + info!("Press the USER button..."); + + loop { + button.wait_for_falling_edge().await; + info!("Pressed!"); + button.wait_for_rising_edge().await; + info!("Released!"); + } +} diff --git a/examples/stm32wba6/src/bin/pwm.rs b/examples/stm32wba6/src/bin/pwm.rs new file mode 100644 index 000000000..2c696834a --- /dev/null +++ b/examples/stm32wba6/src/bin/pwm.rs @@ -0,0 +1,65 @@ +#![no_std] +#![no_main] + +use defmt::*; +use defmt_rtt as _; // global logger +use embassy_executor::Spawner; +use embassy_stm32::gpio::OutputType; +use embassy_stm32::rcc::{ + AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, +}; +use embassy_stm32::time::khz; +use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; +use embassy_stm32::Config; +use embassy_time::Timer; +use panic_probe as _; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + info!("Hello World!"); + + let mut config = Config::default(); + // Fine-tune PLL1 dividers/multipliers + config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { + source: PllSource::HSI, + prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz + mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO + divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) + // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) + divq: None, + divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) + frac: Some(0), // Fractional part (enabled) + }); + + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV1; + config.rcc.apb2_pre = APBPrescaler::DIV1; + config.rcc.apb7_pre = APBPrescaler::DIV1; + config.rcc.ahb5_pre = AHB5Prescaler::DIV4; + + // voltage scale for max performance + config.rcc.voltage_scale = VoltageScale::RANGE1; + // route PLL1_P into the USB‐OTG‐HS block + config.rcc.sys = Sysclk::PLL1_R; + + let p = embassy_stm32::init(config); + + let ch1_pin = PwmPin::new(p.PA2, OutputType::PushPull); + let mut pwm = SimplePwm::new(p.TIM3, Some(ch1_pin), None, None, None, khz(10), Default::default()); + let mut ch1 = pwm.ch1(); + ch1.enable(); + + info!("PWM initialized"); + info!("PWM max duty {}", ch1.max_duty_cycle()); + + loop { + ch1.set_duty_cycle_fully_off(); + Timer::after_millis(300).await; + ch1.set_duty_cycle_fraction(1, 4); + Timer::after_millis(300).await; + ch1.set_duty_cycle_fraction(1, 2); + Timer::after_millis(300).await; + ch1.set_duty_cycle(ch1.max_duty_cycle() - 1); + Timer::after_millis(300).await; + } +} diff --git a/examples/stm32wba6/src/bin/usb_hs_serial.rs b/examples/stm32wba6/src/bin/usb_hs_serial.rs new file mode 100644 index 000000000..20bdeaac3 --- /dev/null +++ b/examples/stm32wba6/src/bin/usb_hs_serial.rs @@ -0,0 +1,125 @@ +#![no_std] +#![no_main] + +use defmt::{panic, *}; +use embassy_executor::Spawner; +use embassy_futures::join::join; +use embassy_stm32::usb::{Driver, Instance}; +use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; +use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; +use embassy_usb::driver::EndpointError; +use embassy_usb::Builder; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + USB_OTG_HS => usb::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + info!("Hello World!"); + + let mut config = Config::default(); + + { + use embassy_stm32::rcc::*; + config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, + prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz + mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO + divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) + divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz + divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USB_OTG_HS) + frac: Some(0), // Fractional part (disabled) + }); + + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV1; + config.rcc.apb2_pre = APBPrescaler::DIV1; + config.rcc.apb7_pre = APBPrescaler::DIV1; + config.rcc.ahb5_pre = AHB5Prescaler::DIV4; + + config.rcc.voltage_scale = VoltageScale::RANGE1; + config.rcc.mux.otghssel = mux::Otghssel::PLL1_P; + config.rcc.sys = Sysclk::PLL1_R; + } + + let p = embassy_stm32::init(config); + + // Create the driver, from the HAL. + let mut ep_out_buffer = [0u8; 256]; + let mut config = embassy_stm32::usb::Config::default(); + // Do not enable vbus_detection. This is a safe default that works in all boards. + // However, if your USB device is self-powered (can stay powered on if USB is unplugged), you need + // to enable vbus_detection to comply with the USB spec. If you enable it, the board + // has to support it or USB won't work at all. See docs on `vbus_detection` for details. + config.vbus_detection = false; + let driver = Driver::new_hs(p.USB_OTG_HS, Irqs, p.PD6, p.PD7, &mut ep_out_buffer, config); + + // Create embassy-usb Config + let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Embassy"); + config.product = Some("USB-serial example"); + config.serial_number = Some("12345678"); + + // Create embassy-usb DeviceBuilder using the driver and config. + // It needs some buffers for building the descriptors. + let mut config_descriptor = [0; 256]; + let mut bos_descriptor = [0; 256]; + let mut control_buf = [0; 64]; + + let mut state = State::new(); + + let mut builder = Builder::new( + driver, + config, + &mut config_descriptor, + &mut bos_descriptor, + &mut [], // no msos descriptors + &mut control_buf, + ); + + // Create classes on the builder. + let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); + + // Build the builder. + let mut usb = builder.build(); + + // Run the USB device. + let usb_fut = usb.run(); + + // Do stuff with the class! + let echo_fut = async { + loop { + class.wait_connection().await; + info!("Connected"); + let _ = echo(&mut class).await; + info!("Disconnected"); + } + }; + + // Run everything concurrently. + // If we had made everything `'static` above instead, we could do this using separate tasks instead. + join(usb_fut, echo_fut).await; +} + +struct Disconnected {} + +impl From for Disconnected { + fn from(val: EndpointError) -> Self { + match val { + EndpointError::BufferOverflow => panic!("Buffer overflow"), + EndpointError::Disabled => Disconnected {}, + } + } +} + +async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> { + let mut buf = [0; 64]; + loop { + let n = class.read_packet(&mut buf).await?; + let data = &buf[..n]; + info!("data: {:x}", data); + class.write_packet(data).await?; + } +} -- cgit From 8be35ebafd5bc18f7d2ccf851ef702b4b6d99eb8 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Sun, 27 Jul 2025 17:26:30 -0700 Subject: Added examples/stm32wba6 to ci.sh --- ci.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci.sh b/ci.sh index f4db1da03..fa75c703e 100755 --- a/ci.sh +++ b/ci.sh @@ -268,6 +268,7 @@ cargo batch \ --- build --release --manifest-path examples/stm32u5/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32u5 \ --- build --release --manifest-path examples/stm32wb/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32wb \ --- build --release --manifest-path examples/stm32wba/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32wba \ + --- build --release --manifest-path examples/stm32wba6/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32wba6 \ --- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32wl \ --- build --release --manifest-path examples/lpc55s69/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/lpc55s69 \ --- build --release --manifest-path examples/mimxrt1011/Cargo.toml --target thumbv7em-none-eabihf --artifact-dir out/examples/mimxrt1011 \ -- cgit From eb62efa670b8691d2a834d0dea9494496525e4b2 Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Mon, 28 Jul 2025 09:48:53 +0200 Subject: Impl multiwrite flash for partition --- embassy-embedded-hal/src/flash/partition/asynch.rs | 4 +++- embassy-embedded-hal/src/flash/partition/blocking.rs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/embassy-embedded-hal/src/flash/partition/asynch.rs b/embassy-embedded-hal/src/flash/partition/asynch.rs index 1b0c91232..82e27bb7c 100644 --- a/embassy-embedded-hal/src/flash/partition/asynch.rs +++ b/embassy-embedded-hal/src/flash/partition/asynch.rs @@ -1,7 +1,7 @@ use embassy_sync::blocking_mutex::raw::RawMutex; use embassy_sync::mutex::Mutex; use embedded_storage::nor_flash::ErrorType; -use embedded_storage_async::nor_flash::{NorFlash, ReadNorFlash}; +use embedded_storage_async::nor_flash::{MultiwriteNorFlash, NorFlash, ReadNorFlash}; use super::Error; @@ -99,6 +99,8 @@ impl NorFlash for Partition<'_, M, T> { } } +impl MultiwriteNorFlash for Partition<'_, M, T> {} + #[cfg(test)] mod tests { use embassy_sync::blocking_mutex::raw::NoopRawMutex; diff --git a/embassy-embedded-hal/src/flash/partition/blocking.rs b/embassy-embedded-hal/src/flash/partition/blocking.rs index a68df7812..951998166 100644 --- a/embassy-embedded-hal/src/flash/partition/blocking.rs +++ b/embassy-embedded-hal/src/flash/partition/blocking.rs @@ -2,7 +2,7 @@ use core::cell::RefCell; use embassy_sync::blocking_mutex::raw::RawMutex; use embassy_sync::blocking_mutex::Mutex; -use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash}; +use embedded_storage::nor_flash::{ErrorType, MultiwriteNorFlash, NorFlash, ReadNorFlash}; use super::Error; @@ -109,6 +109,8 @@ impl NorFlash for BlockingPartition<'_, M, T> { } } +impl MultiwriteNorFlash for BlockingPartition<'_, M, T> {} + #[cfg(test)] mod tests { use embassy_sync::blocking_mutex::raw::NoopRawMutex; -- cgit From 77e0b918db2a33d8fe5dfe02acb4c8fef90f8e9c Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Mon, 28 Jul 2025 09:51:29 +0200 Subject: Impl multiwrite trait for concat flash --- embassy-embedded-hal/src/flash/concat_flash.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/embassy-embedded-hal/src/flash/concat_flash.rs b/embassy-embedded-hal/src/flash/concat_flash.rs index 499941d19..fe5a18ce2 100644 --- a/embassy-embedded-hal/src/flash/concat_flash.rs +++ b/embassy-embedded-hal/src/flash/concat_flash.rs @@ -1,5 +1,7 @@ -use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, ReadNorFlash}; -use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash}; +use embedded_storage::nor_flash::{ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, ReadNorFlash}; +use embedded_storage_async::nor_flash::{ + MultiwriteNorFlash as AsyncMultiwriteNorFlash, NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash, +}; /// Convenience helper for concatenating two consecutive flashes into one. /// This is especially useful if used with "flash regions", where one may @@ -116,6 +118,14 @@ where } } +impl MultiwriteNorFlash for ConcatFlash +where + First: MultiwriteNorFlash, + Second: MultiwriteNorFlash, + E: NorFlashError, +{ +} + impl AsyncReadNorFlash for ConcatFlash where First: AsyncReadNorFlash, @@ -185,6 +195,14 @@ where } } +impl AsyncMultiwriteNorFlash for ConcatFlash +where + First: AsyncMultiwriteNorFlash, + Second: AsyncMultiwriteNorFlash, + E: NorFlashError, +{ +} + #[cfg(test)] mod tests { use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; -- cgit From 6fe79869e11f1dfb378da25dd11ae1d87cb922d1 Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Mon, 28 Jul 2025 09:53:43 +0200 Subject: Impl multiwrite flash for yielding async --- embassy-embedded-hal/src/adapter/yielding_async.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/embassy-embedded-hal/src/adapter/yielding_async.rs b/embassy-embedded-hal/src/adapter/yielding_async.rs index fe9c9c341..87f822a63 100644 --- a/embassy-embedded-hal/src/adapter/yielding_async.rs +++ b/embassy-embedded-hal/src/adapter/yielding_async.rs @@ -147,6 +147,11 @@ impl embedded_storage_async::nor } } +impl embedded_storage_async::nor_flash::MultiwriteNorFlash + for YieldingAsync +{ +} + #[cfg(test)] mod tests { use embedded_storage_async::nor_flash::NorFlash; -- cgit From 98595f659c309703aab411b6b3be7579b6e93c5d Mon Sep 17 00:00:00 2001 From: Ralph Ursprung Date: Mon, 28 Jul 2025 15:37:34 +0200 Subject: `embassy-time`: add missing `Debug` & `defmt::Format` derives `defmt::Format` is *not* implemented for `MockDriver` and `InnerMockDriver` because the former contains the latter and the latter is using `Queue` from `embassy-time-queue-utils` which so far does not have a `defmt` dependency. since this is just a mock driver it shouldn't be relevant if it has no `defmt::Format` impl. --- embassy-executor/src/raw/mod.rs | 2 +- embassy-time-queue-utils/src/lib.rs | 1 + embassy-time-queue-utils/src/queue_generic.rs | 2 ++ embassy-time-queue-utils/src/queue_integrated.rs | 1 + embassy-time/src/delay.rs | 3 ++- embassy-time/src/driver_mock.rs | 2 ++ embassy-time/src/driver_std.rs | 6 ++++++ embassy-time/src/driver_wasm.rs | 6 ++++++ embassy-time/src/lib.rs | 1 + embassy-time/src/timer.rs | 6 ++++++ 10 files changed, 28 insertions(+), 2 deletions(-) diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 913da2e25..c8f1f46c2 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -98,7 +98,7 @@ pub(crate) struct TaskHeader { } /// This is essentially a `&'static TaskStorage` where the type of the future has been erased. -#[derive(Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct TaskRef { ptr: NonNull, } diff --git a/embassy-time-queue-utils/src/lib.rs b/embassy-time-queue-utils/src/lib.rs index a6f66913f..08e186432 100644 --- a/embassy-time-queue-utils/src/lib.rs +++ b/embassy-time-queue-utils/src/lib.rs @@ -1,6 +1,7 @@ #![no_std] #![doc = include_str!("../README.md")] #![warn(missing_docs)] +#![deny(missing_debug_implementations)] #[cfg(feature = "_generic-queue")] pub mod queue_generic; diff --git a/embassy-time-queue-utils/src/queue_generic.rs b/embassy-time-queue-utils/src/queue_generic.rs index 232035bc6..bff7a4735 100644 --- a/embassy-time-queue-utils/src/queue_generic.rs +++ b/embassy-time-queue-utils/src/queue_generic.rs @@ -34,6 +34,7 @@ impl Ord for Timer { } /// A timer queue with a pre-determined capacity. +#[derive(Debug)] pub struct ConstGenericQueue { queue: Vec, } @@ -119,6 +120,7 @@ const QUEUE_SIZE: usize = 128; const QUEUE_SIZE: usize = 64; /// A timer queue with a pre-determined capacity. +#[derive(Debug)] pub struct Queue { queue: ConstGenericQueue, } diff --git a/embassy-time-queue-utils/src/queue_integrated.rs b/embassy-time-queue-utils/src/queue_integrated.rs index 246cf1d63..748cd7843 100644 --- a/embassy-time-queue-utils/src/queue_integrated.rs +++ b/embassy-time-queue-utils/src/queue_integrated.rs @@ -6,6 +6,7 @@ use core::task::Waker; use embassy_executor::raw::TaskRef; /// A timer queue, with items integrated into tasks. +#[derive(Debug)] pub struct Queue { head: Cell>, } diff --git a/embassy-time/src/delay.rs b/embassy-time/src/delay.rs index f77859d4a..67345f726 100644 --- a/embassy-time/src/delay.rs +++ b/embassy-time/src/delay.rs @@ -13,7 +13,8 @@ pub fn block_for(duration: Duration) { /// the amount provided, but accuracy can be affected by many factors, including interrupt usage. /// Make sure to use a suitable tick rate for your use case. The tick rate is defined by the currently /// active driver. -#[derive(Clone)] +#[derive(Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Delay; impl embedded_hal_1::delay::DelayNs for Delay { diff --git a/embassy-time/src/driver_mock.rs b/embassy-time/src/driver_mock.rs index bb1961bf2..bcde2a6c9 100644 --- a/embassy-time/src/driver_mock.rs +++ b/embassy-time/src/driver_mock.rs @@ -28,6 +28,7 @@ use crate::{Duration, Instant}; /// assert_eq!(true, has_a_second_passed(reference)); /// } /// ``` +#[derive(Debug)] pub struct MockDriver(CsMutex>); embassy_time_driver::time_driver_impl!(static DRIVER: MockDriver = MockDriver::new()); @@ -80,6 +81,7 @@ impl Driver for MockDriver { } } +#[derive(Debug)] struct InnerMockDriver { now: Instant, queue: Queue, diff --git a/embassy-time/src/driver_std.rs b/embassy-time/src/driver_std.rs index 87d7ef7eb..a77eed75e 100644 --- a/embassy-time/src/driver_std.rs +++ b/embassy-time/src/driver_std.rs @@ -5,11 +5,15 @@ use std::time::{Duration as StdDuration, Instant as StdInstant}; use embassy_time_driver::Driver; use embassy_time_queue_utils::Queue; +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct TimeDriver { signaler: Signaler, inner: Mutex, } +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct Inner { zero_instant: Option, queue: Queue, @@ -64,6 +68,8 @@ fn alarm_thread() { } } +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct Signaler { mutex: Mutex, condvar: Condvar, diff --git a/embassy-time/src/driver_wasm.rs b/embassy-time/src/driver_wasm.rs index e3207691a..646ce170e 100644 --- a/embassy-time/src/driver_wasm.rs +++ b/embassy-time/src/driver_wasm.rs @@ -5,6 +5,8 @@ use embassy_time_queue_utils::Queue; use wasm_bindgen::prelude::*; use wasm_timer::Instant as StdInstant; +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct AlarmState { token: Option, } @@ -21,10 +23,14 @@ extern "C" { fn clearTimeout(token: f64); } +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct TimeDriver { inner: Mutex, } +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct Inner { alarm: AlarmState, zero_instant: Option, diff --git a/embassy-time/src/lib.rs b/embassy-time/src/lib.rs index 80a359413..77f4b344d 100644 --- a/embassy-time/src/lib.rs +++ b/embassy-time/src/lib.rs @@ -3,6 +3,7 @@ #![doc = include_str!("../README.md")] #![allow(clippy::new_without_default)] #![warn(missing_docs)] +#![deny(missing_debug_implementations)] //! ## Feature flags #![doc = document_features::document_features!(feature_label = r#"{feature}"#)] diff --git a/embassy-time/src/timer.rs b/embassy-time/src/timer.rs index d3f1e1621..54bb9b6d8 100644 --- a/embassy-time/src/timer.rs +++ b/embassy-time/src/timer.rs @@ -66,6 +66,8 @@ impl WithTimeout for F { /// Future for the [`with_timeout`] and [`with_deadline`] functions. #[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct TimeoutFuture { timer: Timer, fut: F, @@ -92,6 +94,8 @@ impl Future for TimeoutFuture { /// A future that completes at a specified [Instant](struct.Instant.html). #[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Timer { expires_at: Instant, yielded_once: bool, @@ -227,6 +231,8 @@ impl Future for Timer { /// ## Cancel safety /// It is safe to cancel waiting for the next tick, /// meaning no tick is lost if the Future is dropped. +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Ticker { expires_at: Instant, duration: Duration, -- cgit From 0e82b7dbd819ce225ba259b40cfa627fe75de1aa Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 27 Jul 2025 02:20:01 +0200 Subject: stm32: fix build for stm32c09x --- ci.sh | 2 ++ embassy-stm32/Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ci.sh b/ci.sh index fa75c703e..1208086a6 100755 --- a/ci.sh +++ b/ci.sh @@ -106,6 +106,8 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,single-bank,defmt \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c071rb,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c051f6,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c091gb,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c092rc,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f038f6,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f030c6,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f058t8,defmt,exti,time-driver-any,time \ diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 520443466..af14e652c 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-df3f5212f2dd70955a6b3d0137e7b4457c6047bf" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-0cf2bd99dd5ebbaab9574b4fb42c12f358ff2ed8" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-df3f5212f2dd70955a6b3d0137e7b4457c6047bf", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-0cf2bd99dd5ebbaab9574b4fb42c12f358ff2ed8", default-features = false, features = ["metadata"] } [features] default = ["rt"] -- cgit From a19d5476dcdf170b3b5aa8ff16daced44d11cff5 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Tue, 29 Jul 2025 01:01:15 -0700 Subject: Aligned STM32WBA with U5 flash HAL --- embassy-stm32/src/flash/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index a3f9e00f7..3e74d857a 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -101,7 +101,7 @@ compile_error!("The 'eeprom' cfg is enabled for a non-L0/L1 chip family. This is #[cfg_attr(any(flash_g0x0, flash_g0x1, flash_g4c2, flash_g4c3, flash_g4c4), path = "g.rs")] #[cfg_attr(flash_h7, path = "h7.rs")] #[cfg_attr(flash_h7ab, path = "h7.rs")] -#[cfg_attr(flash_u5, path = "u5.rs")] +#[cfg_attr(any(flash_u5, flash_wba), path = "u5.rs")] #[cfg_attr(flash_h5, path = "h5.rs")] #[cfg_attr(flash_h50, path = "h50.rs")] #[cfg_attr(flash_u0, path = "u0.rs")] @@ -109,7 +109,7 @@ compile_error!("The 'eeprom' cfg is enabled for a non-L0/L1 chip family. This is not(any( flash_l0, flash_l1, flash_l4, flash_l5, flash_wl, flash_wb, flash_f0, flash_f1, flash_f2, flash_f3, flash_f4, flash_f7, flash_g0x0, flash_g0x1, flash_g4c2, flash_g4c3, flash_g4c4, flash_h7, flash_h7ab, flash_u5, - flash_h50, flash_u0, flash_h5, + flash_wba, flash_h50, flash_u0, flash_h5, )), path = "other.rs" )] -- cgit From b00de39af82dee0c0e46ae504b5790ed2d61178f Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 29 Jul 2025 13:31:54 +0200 Subject: Fix build of embassy-time with std+defmt. --- .github/ci/book.sh | 1 - ci.sh | 1 + embassy-time/src/driver_std.rs | 3 --- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/ci/book.sh b/.github/ci/book.sh index dada4b348..6c300bf09 100755 --- a/.github/ci/book.sh +++ b/.github/ci/book.sh @@ -18,4 +18,3 @@ kubectl exec $POD -- mkdir -p /usr/share/nginx/html kubectl cp book.tar $POD:/usr/share/nginx/html/ kubectl exec $POD -- find /usr/share/nginx/html kubectl exec $POD -- tar -C /usr/share/nginx/html -xvf /usr/share/nginx/html/book.tar -3 diff --git a/ci.sh b/ci.sh index 1208086a6..bb918b186 100755 --- a/ci.sh +++ b/ci.sh @@ -44,6 +44,7 @@ cargo batch \ --- build --release --manifest-path embassy-embedded-hal/Cargo.toml --target thumbv7em-none-eabi --features time \ --- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features defmt \ --- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features defmt,defmt-timestamp-uptime,mock-driver \ + --- build --release --manifest-path embassy-time/Cargo.toml --features defmt,std \ --- build --release --manifest-path embassy-time-queue-utils/Cargo.toml --target thumbv6m-none-eabi \ --- build --release --manifest-path embassy-time-queue-utils/Cargo.toml --target thumbv6m-none-eabi --features generic-queue-8 \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet,packet-trace \ diff --git a/embassy-time/src/driver_std.rs b/embassy-time/src/driver_std.rs index a77eed75e..0cdb8f4ac 100644 --- a/embassy-time/src/driver_std.rs +++ b/embassy-time/src/driver_std.rs @@ -6,14 +6,12 @@ use embassy_time_driver::Driver; use embassy_time_queue_utils::Queue; #[derive(Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct TimeDriver { signaler: Signaler, inner: Mutex, } #[derive(Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct Inner { zero_instant: Option, queue: Queue, @@ -69,7 +67,6 @@ fn alarm_thread() { } #[derive(Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct Signaler { mutex: Mutex, condvar: Condvar, -- cgit From 1b4ea556c0e99622a18c48126cfc6899ffa102b1 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Tue, 29 Jul 2025 01:19:22 -0700 Subject: STM32WBA usb-dfu example - Added sample application - Added sample bootloader Removed trace import --- ci.sh | 2 + .../application/stm32wba-dfu/.cargo/config.toml | 9 ++ examples/boot/application/stm32wba-dfu/Cargo.toml | 32 +++++ examples/boot/application/stm32wba-dfu/README.md | 9 ++ examples/boot/application/stm32wba-dfu/build.rs | 37 +++++ examples/boot/application/stm32wba-dfu/memory.x | 15 ++ .../boot/application/stm32wba-dfu/secrets/key.sec | 2 + examples/boot/application/stm32wba-dfu/src/main.rs | 114 +++++++++++++++ .../bootloader/stm32wba-dfu/.cargo/config.toml | 8 ++ examples/boot/bootloader/stm32wba-dfu/Cargo.toml | 64 +++++++++ examples/boot/bootloader/stm32wba-dfu/README.md | 63 ++++++++ examples/boot/bootloader/stm32wba-dfu/build.rs | 27 ++++ examples/boot/bootloader/stm32wba-dfu/memory.x | 18 +++ .../bootloader/stm32wba-dfu/secrets/key.pub.short | 1 + examples/boot/bootloader/stm32wba-dfu/src/main.rs | 158 +++++++++++++++++++++ 15 files changed, 559 insertions(+) create mode 100644 examples/boot/application/stm32wba-dfu/.cargo/config.toml create mode 100644 examples/boot/application/stm32wba-dfu/Cargo.toml create mode 100644 examples/boot/application/stm32wba-dfu/README.md create mode 100644 examples/boot/application/stm32wba-dfu/build.rs create mode 100644 examples/boot/application/stm32wba-dfu/memory.x create mode 100644 examples/boot/application/stm32wba-dfu/secrets/key.sec create mode 100644 examples/boot/application/stm32wba-dfu/src/main.rs create mode 100644 examples/boot/bootloader/stm32wba-dfu/.cargo/config.toml create mode 100644 examples/boot/bootloader/stm32wba-dfu/Cargo.toml create mode 100644 examples/boot/bootloader/stm32wba-dfu/README.md create mode 100644 examples/boot/bootloader/stm32wba-dfu/build.rs create mode 100644 examples/boot/bootloader/stm32wba-dfu/memory.x create mode 100644 examples/boot/bootloader/stm32wba-dfu/secrets/key.pub.short create mode 100644 examples/boot/bootloader/stm32wba-dfu/src/main.rs diff --git a/ci.sh b/ci.sh index 1208086a6..e85b2f272 100755 --- a/ci.sh +++ b/ci.sh @@ -293,6 +293,7 @@ cargo batch \ --- build --release --manifest-path examples/boot/application/stm32l4/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32l4 \ --- build --release --manifest-path examples/boot/application/stm32wl/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32wl \ --- build --release --manifest-path examples/boot/application/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/boot/stm32wb-dfu \ + --- build --release --manifest-path examples/boot/application/stm32wba-dfu/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/boot/stm32wba-dfu \ --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \ --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns \ --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9120-ns \ @@ -302,6 +303,7 @@ cargo batch \ --- build --release --manifest-path examples/boot/bootloader/stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32l496zg \ --- build --release --manifest-path examples/boot/bootloader/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wb55rg \ --- build --release --manifest-path examples/boot/bootloader/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wb55rg,verify \ + --- build --release --manifest-path examples/boot/bootloader/stm32wba-dfu/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-stm32/stm32wba65ri,verify \ --- build --release --manifest-path examples/boot/bootloader/stm32-dual-bank/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32h743zi \ --- build --release --manifest-path examples/wasm/Cargo.toml --target wasm32-unknown-unknown --artifact-dir out/examples/wasm \ --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f103c8 --artifact-dir out/tests/stm32f103c8 \ diff --git a/examples/boot/application/stm32wba-dfu/.cargo/config.toml b/examples/boot/application/stm32wba-dfu/.cargo/config.toml new file mode 100644 index 000000000..a18ec3944 --- /dev/null +++ b/examples/boot/application/stm32wba-dfu/.cargo/config.toml @@ -0,0 +1,9 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +# replace your chip as listed in `probe-rs chip list` +runner = "probe-rs run --chip STM32WBA65RI" + +[build] +target = "thumbv8m.main-none-eabihf" + +[env] +DEFMT_LOG = "trace" diff --git a/examples/boot/application/stm32wba-dfu/Cargo.toml b/examples/boot/application/stm32wba-dfu/Cargo.toml new file mode 100644 index 000000000..30dc51274 --- /dev/null +++ b/examples/boot/application/stm32wba-dfu/Cargo.toml @@ -0,0 +1,32 @@ +[package] +edition = "2021" +name = "embassy-boot-stm32wba-dfu-examples" +version = "0.1.0" +license = "MIT OR Apache-2.0" + +[dependencies] +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wba65ri", "time-driver-any", "exti"] } +embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } +embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb" } +embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } + +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } +panic-reset = { version = "0.1.1" } +embedded-hal = { version = "0.2.6" } + +cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } +cortex-m-rt = "0.7.0" + +[features] +defmt = [ + "dep:defmt", + "dep:defmt-rtt", + "embassy-stm32/defmt", + "embassy-boot-stm32/defmt", + "embassy-sync/defmt", +] diff --git a/examples/boot/application/stm32wba-dfu/README.md b/examples/boot/application/stm32wba-dfu/README.md new file mode 100644 index 000000000..30692034c --- /dev/null +++ b/examples/boot/application/stm32wba-dfu/README.md @@ -0,0 +1,9 @@ +# Examples using bootloader + +Example for STM32WBA demonstrating the USB DFU application. + +## Usage + +``` +cargo flash --release --chip STM32WBA65RI +``` diff --git a/examples/boot/application/stm32wba-dfu/build.rs b/examples/boot/application/stm32wba-dfu/build.rs new file mode 100644 index 000000000..e1da69328 --- /dev/null +++ b/examples/boot/application/stm32wba-dfu/build.rs @@ -0,0 +1,37 @@ +//! This build script copies the `memory.x` file from the crate root into +//! a directory where the linker can always find it at build time. +//! For many projects this is optional, as the linker always searches the +//! project root directory -- wherever `Cargo.toml` is. However, if you +//! are using a workspace or have a more complicated build setup, this +//! build script becomes required. Additionally, by requesting that +//! Cargo re-run the build script whenever `memory.x` is changed, +//! updating `memory.x` ensures a rebuild of the application with the +//! new memory settings. + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put `memory.x` in our output directory and ensure it's + // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // By default, Cargo will re-run a build script whenever + // any file in the project changes. By specifying `memory.x` + // here, we ensure the build script is only re-run when + // `memory.x` is changed. + println!("cargo:rerun-if-changed=memory.x"); + + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + if env::var("CARGO_FEATURE_DEFMT").is_ok() { + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + } +} diff --git a/examples/boot/application/stm32wba-dfu/memory.x b/examples/boot/application/stm32wba-dfu/memory.x new file mode 100644 index 000000000..fcdb6b6d2 --- /dev/null +++ b/examples/boot/application/stm32wba-dfu/memory.x @@ -0,0 +1,15 @@ +MEMORY +{ + /* NOTE 1 K = 1 KiBi = 1024 bytes */ + BOOTLOADER : ORIGIN = 0x08000000, LENGTH = 80K + BOOTLOADER_STATE : ORIGIN = 0x08014000, LENGTH = 8K + FLASH : ORIGIN = 0x08016000, LENGTH = 120K + DFU : ORIGIN = 0x0803C000, LENGTH = 160K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 400K +} + +__bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER); +__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER); + +__bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(BOOTLOADER); +__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(BOOTLOADER); diff --git a/examples/boot/application/stm32wba-dfu/secrets/key.sec b/examples/boot/application/stm32wba-dfu/secrets/key.sec new file mode 100644 index 000000000..52e7f125b --- /dev/null +++ b/examples/boot/application/stm32wba-dfu/secrets/key.sec @@ -0,0 +1,2 @@ +untrusted comment: signify secret key +RWRCSwAAAAATdHQF3B4jEIoNZrjADRp2LbjJjNdNNzKwTCe4IB6mDNq96pe53nbNxwbdCc/T4hrz7W+Kx1MwrZ0Yz5xebSK5Z0Kh/3Cdf039U5f+eoTDS2fIGbohyUbrtwKzjyE0qXI= diff --git a/examples/boot/application/stm32wba-dfu/src/main.rs b/examples/boot/application/stm32wba-dfu/src/main.rs new file mode 100644 index 000000000..bf17a7150 --- /dev/null +++ b/examples/boot/application/stm32wba-dfu/src/main.rs @@ -0,0 +1,114 @@ +#![no_std] +#![no_main] + +use core::cell::RefCell; + +#[cfg(feature = "defmt")] +use defmt_rtt as _; +use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareState, FirmwareUpdaterConfig}; +use embassy_executor::Spawner; +use embassy_stm32::flash::{Flash, WRITE_SIZE}; +use embassy_stm32::usb::{self, Driver}; +use embassy_stm32::{bind_interrupts, peripherals}; +use embassy_sync::blocking_mutex::Mutex; +use embassy_time::Duration; +use embassy_usb::{msos, Builder}; +use embassy_usb_dfu::consts::DfuAttributes; +use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; +use panic_reset as _; + +bind_interrupts!(struct Irqs { + USB_OTG_HS => usb::InterruptHandler; +}); + +// This is a randomly generated GUID to allow clients on Windows to find your device. +// +// N.B. update to a custom GUID for your own device! +const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = embassy_stm32::Config::default(); + + { + use embassy_stm32::rcc::*; + config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, + prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz + mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO + divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) + divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz + divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USB_OTG_HS) + frac: Some(0), // Fractional part (disabled) + }); + + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV1; + config.rcc.apb2_pre = APBPrescaler::DIV1; + config.rcc.apb7_pre = APBPrescaler::DIV1; + config.rcc.ahb5_pre = AHB5Prescaler::DIV4; + + config.rcc.voltage_scale = VoltageScale::RANGE1; + config.rcc.mux.otghssel = mux::Otghssel::PLL1_P; + config.rcc.sys = Sysclk::PLL1_R; + } + + let p = embassy_stm32::init(config); + let flash = Flash::new_blocking(p.FLASH); + let flash = Mutex::new(RefCell::new(flash)); + + let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash, &flash); + let mut magic = AlignedBuffer([0; WRITE_SIZE]); + let mut firmware_state = BlockingFirmwareState::from_config(config, &mut magic.0); + firmware_state.mark_booted().expect("Failed to mark booted"); + + // Create the driver, from the HAL. + let mut ep_out_buffer = [0u8; 256]; + let mut config = embassy_stm32::usb::Config::default(); + config.vbus_detection = false; + + let driver = Driver::new_hs(p.USB_OTG_HS, Irqs, p.PD6, p.PD7, &mut ep_out_buffer, config); + let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Embassy"); + config.product = Some("USB-DFU Runtime example"); + config.serial_number = Some("1235678"); + + let mut config_descriptor = [0; 256]; + let mut bos_descriptor = [0; 256]; + let mut control_buf = [0; 64]; + let mut state = Control::new(firmware_state, DfuAttributes::CAN_DOWNLOAD, ResetImmediate); + let mut builder = Builder::new( + driver, + config, + &mut config_descriptor, + &mut bos_descriptor, + &mut [], + &mut control_buf, + ); + + // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. + // Otherwise users need to do this manually using a tool like Zadig. + // + // It seems these always need to be at added at the device level for this to work and for + // composite devices they also need to be added on the function level (as shown later). + + builder.msos_descriptor(msos::windows_version::WIN8_1, 2); + builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); + builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( + "DeviceInterfaceGUIDs", + msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), + )); + + usb_dfu(&mut builder, &mut state, Duration::from_millis(1000), |func| { + // You likely don't have to add these function level headers if your USB device is not composite + // (i.e. if your device does not expose another interface in addition to DFU) + func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); + func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( + "DeviceInterfaceGUIDs", + msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), + )); + }); + + let mut dev = builder.build(); + dev.run().await +} diff --git a/examples/boot/bootloader/stm32wba-dfu/.cargo/config.toml b/examples/boot/bootloader/stm32wba-dfu/.cargo/config.toml new file mode 100644 index 000000000..1896068d8 --- /dev/null +++ b/examples/boot/bootloader/stm32wba-dfu/.cargo/config.toml @@ -0,0 +1,8 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +runner = "probe-rs run --chip STM32WBA65RI" + +[build] +target = "thumbv8m.main-none-eabihf" + +[env] +DEFMT_LOG = "trace" diff --git a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml new file mode 100644 index 000000000..9240d1808 --- /dev/null +++ b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml @@ -0,0 +1,64 @@ +[package] +edition = "2021" +name = "stm32wba6-dfu-bootloader-example" +version = "0.1.0" +description = "Example USB DFUbootloader for the STM32WBA series of chips" +license = "MIT OR Apache-2.0" + +[dependencies] +defmt = { version = "1.0.1", optional = true } +defmt-rtt = { version = "1.0.0", optional = true } + +embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } +embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } +cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } +embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +cortex-m-rt = { version = "0.7" } +embedded-storage = "0.3.1" +embedded-storage-async = "0.4.0" +cfg-if = "1.0.0" +embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } +embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb", default-features = false } +embassy-futures = { version = "0.1.1", path = "../../../../embassy-futures" } + +[features] +defmt = [ + "dep:defmt", + "dep:defmt-rtt", + "embassy-boot-stm32/defmt", + "embassy-stm32/defmt", + "embassy-usb/defmt", + "embassy-usb-dfu/defmt" +] +verify = ["embassy-usb-dfu/ed25519-salty"] + +[profile.dev] +debug = 2 +debug-assertions = true +incremental = false +opt-level = 'z' +overflow-checks = true + +[profile.release] +codegen-units = 1 +debug = 2 +debug-assertions = false +incremental = false +lto = 'fat' +opt-level = 'z' +overflow-checks = false + +# do not optimize proc-macro crates = faster builds from scratch +[profile.dev.build-override] +codegen-units = 8 +debug = false +debug-assertions = false +opt-level = 0 +overflow-checks = false + +[profile.release.build-override] +codegen-units = 8 +debug = false +debug-assertions = false +opt-level = 0 +overflow-checks = false diff --git a/examples/boot/bootloader/stm32wba-dfu/README.md b/examples/boot/bootloader/stm32wba-dfu/README.md new file mode 100644 index 000000000..d50164255 --- /dev/null +++ b/examples/boot/bootloader/stm32wba-dfu/README.md @@ -0,0 +1,63 @@ +# Bootloader for STM32 + +This bootloader implementation uses `embassy-boot` and `embassy-usb-dfu` to manage firmware updates and interact with the flash memory on STM32WB55 devices. + +## Prerequisites + +- Rust toolchain with `cargo` installed +- `cargo-flash` for flashing the bootloader +- `dfu-util` for firmware updates +- `cargo-binutils` for binary generation + +## Usage + +### 1. Flash the Bootloader + +First, flash the bootloader to your device: + +``` +cargo flash --features embassy-stm32/stm32wba65ri --release --chip STM32WBA65RI +``` + +### 2. Build and Flash Application + +Generate your application binary and flash it using DFU: + +``` +cargo objcopy --release -- -O binary fw.bin +dfu-util -d c0de:cafe -w -D fw.bin +``` + +### 3. Sign Updates Before Flashing (Optional) + +Currently, embassy-usb-dfu only supports a limited implementation of the generic support for ed25519-based update verfication in embassy-boot. This implementation assumes that a signature is simply concatenated to the end of an update binary. For more details, please see https://embassy.dev/book/#_verification and/or refer to the documentation for embassy-boot-dfu. + +To sign (and then verify) application updates, you will first need to generate a key pair: + +``` +signify-openbsd -G -n -p secrets/key.pub -s secrets/key.sec +tail -n1 secrets/key.pub | base64 -d -i - | dd ibs=10 skip=1 > secrets/key.pub.short +``` + +Then you will need to sign all you binaries with the private key: + +``` +cargo objcopy --release -- -O binary fw.bin +shasum -a 512 -b fw.bin | head -c128 | xxd -p -r > target/fw-hash.txt +signify-openbsd -S -s secrets/key.sec -m target/fw-hash.txt -x target/fw-hash.sig +cp fw.bin fw-signed.bin +tail -n1 target/fw-hash.sig | base64 -d -i - | dd ibs=10 skip=1 >> fw-signed.bin +dfu-util -d c0de:cafe -w -D fw-signed.bin +``` + +Finally, as shown in this example with the `verify` feature flag enabled, you then need to embed the public key into your bootloader so that it can verify update signatures. + +N.B. Please note that the exact steps above are NOT a good example of how to manage your keys securely. In a production environment, you should take great care to ensure that (at least the private key) is protected and not leaked into your version control system. + +## Troubleshooting + +- Make sure your device is in DFU mode before flashing +- Verify the USB VID:PID matches your device (c0de:cafe) +- Check USB connections if the device is not detected +- Make sure the transfer size option of `dfu-util` matches the bootloader configuration. By default, `dfu-util` will use the transfer size reported by the device, but you can override it with the `-t` option if needed. +- Make sure `control_buf` size is larger than or equal to the `usb_dfu` `BLOCK_SIZE` parameter (in this example, both are set to 4096 bytes). diff --git a/examples/boot/bootloader/stm32wba-dfu/build.rs b/examples/boot/bootloader/stm32wba-dfu/build.rs new file mode 100644 index 000000000..fd605991f --- /dev/null +++ b/examples/boot/bootloader/stm32wba-dfu/build.rs @@ -0,0 +1,27 @@ +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put `memory.x` in our output directory and ensure it's + // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // By default, Cargo will re-run a build script whenever + // any file in the project changes. By specifying `memory.x` + // here, we ensure the build script is only re-run when + // `memory.x` is changed. + println!("cargo:rerun-if-changed=memory.x"); + + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + if env::var("CARGO_FEATURE_DEFMT").is_ok() { + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + } +} diff --git a/examples/boot/bootloader/stm32wba-dfu/memory.x b/examples/boot/bootloader/stm32wba-dfu/memory.x new file mode 100644 index 000000000..105c9e960 --- /dev/null +++ b/examples/boot/bootloader/stm32wba-dfu/memory.x @@ -0,0 +1,18 @@ +MEMORY +{ + /* NOTE 1 K = 1 KiBi = 1024 bytes */ + FLASH : ORIGIN = 0x08000000, LENGTH = 80K + BOOTLOADER_STATE : ORIGIN = 0x08014000, LENGTH = 8K + ACTIVE : ORIGIN = 0x08016000, LENGTH = 120K + DFU : ORIGIN = 0x0803C000, LENGTH = 160K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 400K +} + +__bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(FLASH); +__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE) - ORIGIN(FLASH); + +__bootloader_active_start = ORIGIN(ACTIVE) - ORIGIN(FLASH); +__bootloader_active_end = ORIGIN(ACTIVE) + LENGTH(ACTIVE) - ORIGIN(FLASH); + +__bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(FLASH); +__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(FLASH); \ No newline at end of file diff --git a/examples/boot/bootloader/stm32wba-dfu/secrets/key.pub.short b/examples/boot/bootloader/stm32wba-dfu/secrets/key.pub.short new file mode 100644 index 000000000..7a4de8585 --- /dev/null +++ b/examples/boot/bootloader/stm32wba-dfu/secrets/key.pub.short @@ -0,0 +1 @@ +gBpMSzKg!F!4r \ No newline at end of file diff --git a/examples/boot/bootloader/stm32wba-dfu/src/main.rs b/examples/boot/bootloader/stm32wba-dfu/src/main.rs new file mode 100644 index 000000000..75d8d4199 --- /dev/null +++ b/examples/boot/bootloader/stm32wba-dfu/src/main.rs @@ -0,0 +1,158 @@ +#![no_std] +#![no_main] + +use core::cell::RefCell; + +use cortex_m_rt::{entry, exception}; +#[cfg(feature = "defmt")] +use defmt_rtt as _; +use embassy_boot_stm32::*; +use embassy_stm32::flash::{Flash, BANK1_REGION, WRITE_SIZE}; +use embassy_stm32::usb::Driver; +use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; +use embassy_sync::blocking_mutex::Mutex; +use embassy_usb::{msos, Builder}; +use embassy_usb_dfu::consts::DfuAttributes; +use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; + +bind_interrupts!(struct Irqs { + USB_OTG_HS => usb::InterruptHandler; +}); + +// This is a randomly generated GUID to allow clients on Windows to find your device. +// +// N.B. update to a custom GUID for your own device! +const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; + +// This is a randomly generated example key. +// +// N.B. Please replace with your own! +#[cfg(feature = "verify")] +static PUBLIC_SIGNING_KEY: &[u8; 32] = include_bytes!("../secrets/key.pub.short"); + +#[entry] +fn main() -> ! { + let mut config = Config::default(); + + { + use embassy_stm32::rcc::*; + config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, + prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz + mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO + divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) + divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz + divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USB_OTG_HS) + frac: Some(0), // Fractional part (disabled) + }); + + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV1; + config.rcc.apb2_pre = APBPrescaler::DIV1; + config.rcc.apb7_pre = APBPrescaler::DIV1; + config.rcc.ahb5_pre = AHB5Prescaler::DIV4; + + config.rcc.voltage_scale = VoltageScale::RANGE1; + config.rcc.mux.otghssel = mux::Otghssel::PLL1_P; + config.rcc.sys = Sysclk::PLL1_R; + } + + let p = embassy_stm32::init(config); + + // Prevent a hard fault when accessing flash 'too early' after boot. + #[cfg(feature = "defmt")] + for _ in 0..10000000 { + cortex_m::asm::nop(); + } + + let layout = Flash::new_blocking(p.FLASH).into_blocking_regions(); + let flash = Mutex::new(RefCell::new(layout.bank1_region)); + + let config = BootLoaderConfig::from_linkerfile_blocking(&flash, &flash, &flash); + let active_offset = config.active.offset(); + let bl = BootLoader::prepare::<_, _, _, 2048>(config); + + // Create the driver, from the HAL. + let mut ep_out_buffer = [0u8; 256]; + let mut config = embassy_stm32::usb::Config::default(); + + config.vbus_detection = false; + + if bl.state == State::DfuDetach { + let driver = Driver::new_hs(p.USB_OTG_HS, Irqs, p.PD6, p.PD7, &mut ep_out_buffer, config); + let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Embassy"); + config.product = Some("USB-DFU Bootloader example"); + config.serial_number = Some("1235678"); + + let fw_config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash, &flash); + let mut buffer = AlignedBuffer([0; WRITE_SIZE]); + let updater = BlockingFirmwareUpdater::new(fw_config, &mut buffer.0[..]); + + let mut config_descriptor = [0; 256]; + let mut bos_descriptor = [0; 256]; + let mut control_buf = [0; 4096]; + + #[cfg(not(feature = "verify"))] + let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate); + + #[cfg(feature = "verify")] + let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate, PUBLIC_SIGNING_KEY); + + let mut builder = Builder::new( + driver, + config, + &mut config_descriptor, + &mut bos_descriptor, + &mut [], + &mut control_buf, + ); + + // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. + // Otherwise users need to do this manually using a tool like Zadig. + // + // It seems these always need to be at added at the device level for this to work and for + // composite devices they also need to be added on the function level (as shown later). + + builder.msos_descriptor(msos::windows_version::WIN8_1, 2); + builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); + builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( + "DeviceInterfaceGUIDs", + msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), + )); + + usb_dfu::<_, _, _, _, 4096>(&mut builder, &mut state, |func| { + // You likely don't have to add these function level headers if your USB device is not composite + // (i.e. if your device does not expose another interface in addition to DFU) + func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); + func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new( + "DeviceInterfaceGUIDs", + msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), + )); + }); + + let mut dev = builder.build(); + embassy_futures::block_on(dev.run()); + } + + unsafe { bl.load(BANK1_REGION.base + active_offset) } +} + +#[no_mangle] +#[cfg_attr(target_os = "none", link_section = ".HardFault.user")] +unsafe extern "C" fn HardFault() { + cortex_m::peripheral::SCB::sys_reset(); +} + +#[exception] +unsafe fn DefaultHandler(_: i16) -> ! { + const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; + let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; + + panic!("DefaultHandler #{:?}", irqn); +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + cortex_m::asm::udf(); +} -- cgit From dbd10486b3e034fa193694a68f2c1803b4896365 Mon Sep 17 00:00:00 2001 From: Malte Brieske <9287988+mbrieske@users.noreply.github.com> Date: Tue, 29 Jul 2025 19:18:14 +0200 Subject: Add mutable accessors for ID in Header and Frame structs --- embassy-stm32/src/can/frame.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/embassy-stm32/src/can/frame.rs b/embassy-stm32/src/can/frame.rs index 0fbab053b..a498f195f 100644 --- a/embassy-stm32/src/can/frame.rs +++ b/embassy-stm32/src/can/frame.rs @@ -59,6 +59,11 @@ impl Header { &self.id } + /// Get mutable reference to ID + pub fn id_mut(&mut self) -> &mut embedded_can::Id { + &mut self.id + } + /// Return length as u8 pub fn len(&self) -> u8 { self.len @@ -207,6 +212,11 @@ impl Frame { &self.can_header.id } + /// Get mutable reference to ID + pub fn id_mut(&mut self) -> &mut embedded_can::Id { + &mut self.can_header.id + } + /// Get reference to data pub fn data(&self) -> &[u8] { &self.data.raw()[..self.can_header.len as usize] -- cgit From 03b60dd5619bb65dff697cf9dd96f57ccc23f35e Mon Sep 17 00:00:00 2001 From: Anthony Grondin <104731965+AnthonyGrondin@users.noreply.github.com> Date: Wed, 30 Jul 2025 16:01:11 -0400 Subject: feat(embassy-sync): Add `get_mut` for `LazyLock` --- embassy-sync/CHANGELOG.md | 2 ++ embassy-sync/src/lazy_lock.rs | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/embassy-sync/CHANGELOG.md b/embassy-sync/CHANGELOG.md index 89684de0c..c445e9ba1 100644 --- a/embassy-sync/CHANGELOG.md +++ b/embassy-sync/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- Add `get_mut` to `LazyLock` + ## 0.7.0 - 2025-05-28 - Add `remove_if` to `priority_channel::{Receiver, PriorityChannel}`. diff --git a/embassy-sync/src/lazy_lock.rs b/embassy-sync/src/lazy_lock.rs index f1bd88b61..a919f0037 100644 --- a/embassy-sync/src/lazy_lock.rs +++ b/embassy-sync/src/lazy_lock.rs @@ -57,6 +57,14 @@ impl T> LazyLock { unsafe { &(*self.data.get()).value } } + /// Get a mutable reference to the underlying value, initializing it if it + /// has not been done already. + #[inline] + pub fn get_mut(&mut self) -> &mut T { + self.ensure_init_fast(); + unsafe { &mut (*self.data.get()).value } + } + /// Consume the `LazyLock`, returning the underlying value. The /// initialization function will be called if it has not been /// already. @@ -122,6 +130,13 @@ mod tests { assert_eq!(reference, &20); } #[test] + fn test_lazy_lock_mutation() { + let mut value: LazyLock = LazyLock::new(|| 20); + *value.get_mut() = 21; + let reference = value.get(); + assert_eq!(reference, &21); + } + #[test] fn test_lazy_lock_into_inner() { let lazy: LazyLock = LazyLock::new(|| 20); let value = lazy.into_inner(); -- cgit From 3f1ddaf60e8fe2ce330ab7d5fefdf4814348df9e Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Thu, 31 Jul 2025 10:32:01 +0200 Subject: chore: prepare embassy-executor 0.8 release --- docs/examples/basic/Cargo.toml | 2 +- docs/examples/layer-by-layer/blinky-async/Cargo.toml | 2 +- embassy-executor/Cargo.toml | 2 +- embassy-mspm0/Cargo.toml | 2 +- embassy-rp/Cargo.toml | 2 +- embassy-stm32/Cargo.toml | 2 +- embassy-time-queue-utils/Cargo.toml | 2 +- embassy-time/Cargo.toml | 2 +- examples/boot/application/nrf/Cargo.toml | 2 +- examples/boot/application/rp/Cargo.toml | 2 +- examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wb-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wba-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wl/Cargo.toml | 2 +- examples/lpc55s69/Cargo.toml | 2 +- examples/mimxrt1011/Cargo.toml | 2 +- examples/mimxrt1062-evk/Cargo.toml | 2 +- examples/mimxrt6/Cargo.toml | 2 +- examples/mspm0c1104/Cargo.toml | 2 +- examples/mspm0g3507/Cargo.toml | 2 +- examples/mspm0g3519/Cargo.toml | 2 +- examples/mspm0l1306/Cargo.toml | 2 +- examples/mspm0l2228/Cargo.toml | 2 +- examples/nrf-rtos-trace/Cargo.toml | 2 +- examples/nrf51/Cargo.toml | 2 +- examples/nrf52810/Cargo.toml | 2 +- examples/nrf52840/Cargo.toml | 2 +- examples/nrf5340/Cargo.toml | 2 +- examples/nrf54l15/Cargo.toml | 2 +- examples/nrf9151/ns/Cargo.toml | 2 +- examples/nrf9151/s/Cargo.toml | 2 +- examples/nrf9160/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- examples/std/Cargo.toml | 2 +- examples/stm32c0/Cargo.toml | 2 +- examples/stm32f0/Cargo.toml | 2 +- examples/stm32f1/Cargo.toml | 2 +- examples/stm32f2/Cargo.toml | 2 +- examples/stm32f3/Cargo.toml | 2 +- examples/stm32f334/Cargo.toml | 2 +- examples/stm32f4/Cargo.toml | 2 +- examples/stm32f469/Cargo.toml | 2 +- examples/stm32f7/Cargo.toml | 2 +- examples/stm32g0/Cargo.toml | 2 +- examples/stm32g4/Cargo.toml | 2 +- examples/stm32h5/Cargo.toml | 2 +- examples/stm32h7/Cargo.toml | 2 +- examples/stm32h723/Cargo.toml | 2 +- examples/stm32h735/Cargo.toml | 2 +- examples/stm32h742/Cargo.toml | 2 +- examples/stm32h755cm4/Cargo.toml | 2 +- examples/stm32h755cm7/Cargo.toml | 2 +- examples/stm32h7b0/Cargo.toml | 2 +- examples/stm32h7rs/Cargo.toml | 2 +- examples/stm32l0/Cargo.toml | 2 +- examples/stm32l1/Cargo.toml | 2 +- examples/stm32l4/Cargo.toml | 2 +- examples/stm32l432/Cargo.toml | 2 +- examples/stm32l5/Cargo.toml | 2 +- examples/stm32u0/Cargo.toml | 2 +- examples/stm32u5/Cargo.toml | 2 +- examples/stm32wb/Cargo.toml | 2 +- examples/stm32wba/Cargo.toml | 2 +- examples/stm32wba6/Cargo.toml | 2 +- examples/stm32wl/Cargo.toml | 2 +- examples/wasm/Cargo.toml | 2 +- tests/mspm0/Cargo.toml | 2 +- tests/nrf/Cargo.toml | 2 +- tests/riscv32/Cargo.toml | 2 +- tests/rp/Cargo.toml | 2 +- tests/stm32/Cargo.toml | 2 +- 77 files changed, 77 insertions(+), 77 deletions(-) diff --git a/docs/examples/basic/Cargo.toml b/docs/examples/basic/Cargo.toml index c4b72d81a..32e326134 100644 --- a/docs/examples/basic/Cargo.toml +++ b/docs/examples/basic/Cargo.toml @@ -6,7 +6,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["defmt", "arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../../../embassy-executor", features = ["defmt", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt"] } embassy-nrf = { version = "0.5.0", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } diff --git a/docs/examples/layer-by-layer/blinky-async/Cargo.toml b/docs/examples/layer-by-layer/blinky-async/Cargo.toml index 2a6741b33..7a9782960 100644 --- a/docs/examples/layer-by-layer/blinky-async/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-async/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" cortex-m = { version = "0.7", features = ["critical-section-single-core"] } cortex-m-rt = "0.7" embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x", "exti"] } -embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 2dbf2c29a..db3029967 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -33,7 +33,7 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } rtos-trace = { version = "0.1.3", optional = true } -embassy-executor-macros = { version = "0.6.2", path = "../embassy-executor-macros" } +embassy-executor-macros = { version = "0.7.0", path = "../embassy-executor-macros" } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } critical-section = "1.1" diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index 61afcd76d..743254b58 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -33,7 +33,7 @@ embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-util embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } -embassy-executor = { version = "0.7.0", path = "../embassy-executor", optional = true } +embassy-executor = { version = "0.8.0", path = "../embassy-executor", optional = true } embedded-hal = { version = "1.0" } embedded-hal-nb = { version = "1.0" } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index dcf4e7178..fa13ec1d9 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -177,5 +177,5 @@ rp-binary-info = { version = "0.1.0", optional = true } smart-leds = "0.4.0" [dev-dependencies] -embassy-executor = { version = "0.7.0", path = "../embassy-executor", features = ["arch-std", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../embassy-executor", features = ["arch-std", "executor-thread"] } static_cell = { version = "2" } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index af14e652c..a63325679 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -58,7 +58,7 @@ embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", de embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } embassy-usb-synopsys-otg = { version = "0.3.0", path = "../embassy-usb-synopsys-otg" } -embassy-executor = { version = "0.7.0", path = "../embassy-executor", optional = true } +embassy-executor = { version = "0.8.0", path = "../embassy-executor", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } diff --git a/embassy-time-queue-utils/Cargo.toml b/embassy-time-queue-utils/Cargo.toml index 48be12118..fd98a1633 100644 --- a/embassy-time-queue-utils/Cargo.toml +++ b/embassy-time-queue-utils/Cargo.toml @@ -22,7 +22,7 @@ links = "embassy-time-queue" [dependencies] heapless = "0.8" -embassy-executor = { version = "0.7.0", path = "../embassy-executor" } +embassy-executor = { version = "0.8.0", path = "../embassy-executor" } [features] #! ### Generic Queue diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index 2284906b0..618c6f518 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml @@ -441,4 +441,4 @@ wasm-timer = { version = "0.2.5", optional = true } [dev-dependencies] serial_test = "0.9" critical-section = { version = "1.1", features = ["std"] } -embassy-executor = { version = "0.7.0", path = "../embassy-executor" } +embassy-executor = { version = "0.8.0", path = "../embassy-executor" } diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 37183df97..4fda710a5 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } embassy-nrf = { version = "0.5.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } embassy-boot = { version = "0.5.0", path = "../../../../embassy-boot", features = [] } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index e5568f6bb..d060bc8c0 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } embassy-rp = { version = "0.6.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } embassy-boot-rp = { version = "0.6.0", path = "../../../../embassy-boot-rp", features = [] } diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index be8b7bff1..00d435799 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32" } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index 2b0175a0c..ae36fc835 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index 3c88f4241..bf3da53b8 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index b4e7e090a..7cc10a18e 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 394578e1a..c175f6c7f 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index abe0451fd..37735e725 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index bc4681f79..ccb7d0807 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } diff --git a/examples/boot/application/stm32wba-dfu/Cargo.toml b/examples/boot/application/stm32wba-dfu/Cargo.toml index 30dc51274..ab719e28c 100644 --- a/examples/boot/application/stm32wba-dfu/Cargo.toml +++ b/examples/boot/application/stm32wba-dfu/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wba65ri", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index 0552d109a..3b9d7b5d5 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index 1724a22d4..5faec13da 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55", "rt", "defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" diff --git a/examples/mimxrt1011/Cargo.toml b/examples/mimxrt1011/Cargo.toml index cf4e4c163..e6bb3b10b 100644 --- a/examples/mimxrt1011/Cargo.toml +++ b/examples/mimxrt1011/Cargo.toml @@ -10,7 +10,7 @@ cortex-m-rt = "0.7.3" defmt = "1.0.1" defmt-rtt = "1.0.0" -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["defmt", "mimxrt1011", "unstable-pac", "time-driver-pit"] } embassy-time = { version = "0.4", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime" # RT1011 hard faults currently with this enabled. diff --git a/examples/mimxrt1062-evk/Cargo.toml b/examples/mimxrt1062-evk/Cargo.toml index 430a26b41..7f7e0c8a3 100644 --- a/examples/mimxrt1062-evk/Cargo.toml +++ b/examples/mimxrt1062-evk/Cargo.toml @@ -10,7 +10,7 @@ cortex-m-rt = "0.7.3" defmt = "1.0.1" defmt-rtt = "1.0.0" -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["defmt", "mimxrt1062", "unstable-pac", "time-driver-pit"] } embassy-time = { version = "0.4", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime" diff --git a/examples/mimxrt6/Cargo.toml b/examples/mimxrt6/Cargo.toml index 65cb9e3ca..390a6e9f9 100644 --- a/examples/mimxrt6/Cargo.toml +++ b/examples/mimxrt6/Cargo.toml @@ -10,7 +10,7 @@ cortex-m-rt = "0.7.3" defmt = "1.0.1" defmt-rtt = "1.0.0" -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } embassy-imxrt = { version = "0.1.0", path = "../../embassy-imxrt", features = ["defmt", "mimxrt685s", "unstable-pac", "time", "time-driver-os-timer"] } embassy-time = { version = "0.4", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } diff --git a/examples/mspm0c1104/Cargo.toml b/examples/mspm0c1104/Cargo.toml index 79f9c0959..52817034f 100644 --- a/examples/mspm0c1104/Cargo.toml +++ b/examples/mspm0c1104/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0c1104dgs20", "defmt", "rt", "time-driver-any"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" diff --git a/examples/mspm0g3507/Cargo.toml b/examples/mspm0g3507/Cargo.toml index cc40b3109..c3940b070 100644 --- a/examples/mspm0g3507/Cargo.toml +++ b/examples/mspm0g3507/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3507pm", "defmt", "rt", "time-driver-any"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" diff --git a/examples/mspm0g3519/Cargo.toml b/examples/mspm0g3519/Cargo.toml index fd0e97c01..463b20978 100644 --- a/examples/mspm0g3519/Cargo.toml +++ b/examples/mspm0g3519/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3519pz", "defmt", "rt", "time-driver-any"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" diff --git a/examples/mspm0l1306/Cargo.toml b/examples/mspm0l1306/Cargo.toml index 6b1125810..7834d7f5d 100644 --- a/examples/mspm0l1306/Cargo.toml +++ b/examples/mspm0l1306/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l1306rhb", "defmt", "rt", "time-driver-any"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" diff --git a/examples/mspm0l2228/Cargo.toml b/examples/mspm0l2228/Cargo.toml index 08dfd5ff6..85a351479 100644 --- a/examples/mspm0l2228/Cargo.toml +++ b/examples/mspm0l2228/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l2228pn", "defmt", "rt", "time-driver-any"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index f1c40192d..029fd62a3 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -16,7 +16,7 @@ log = [ [dependencies] embassy-sync = { version = "0.7.0", path = "../../embassy-sync" } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } embassy-time = { version = "0.4.0", path = "../../embassy-time" } embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml index a21d7f6ce..ddac7e2c9 100644 --- a/examples/nrf51/Cargo.toml +++ b/examples/nrf51/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index baa873f22..f9069d6c4 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index d2baebf8e..c25e33e82 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index bdebd5386..7e11f123f 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index 27d5babee..515514cb0 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml index 2a492b595..f729e410b 100644 --- a/examples/nrf9151/ns/Cargo.toml +++ b/examples/nrf9151/ns/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.5.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml index 62ef3e4ce..175de0e5b 100644 --- a/examples/nrf9151/s/Cargo.toml +++ b/examples/nrf9151/s/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.5.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml index c896afdbe..03b3bc702 100644 --- a/examples/nrf9160/Cargo.toml +++ b/examples/nrf9160/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index eefd69315..428d49c1a 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal", features = ["defmt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-rp = { version = "0.6.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 4d3dc77b5..85481069b 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal", features = ["defmt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-rp = { version = "0.6.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 63740963d..520a66ab1 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["log"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["log", "std", ] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features=[ "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" } diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index 70a7b0895..b06d53a22 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32c031c6 to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "1.0.1" diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index 400e6b94c..9ccce3910 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -13,7 +13,7 @@ defmt = "1.0.1" defmt-rtt = "1.0.0" panic-probe = { version = "1.0.0", features = ["print-defmt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } static_cell = "2" portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 01f4fd84a..1d49afcc4 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32f103c8 to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index 905cffff0..e5ad745d8 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32f207zg to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "1.0.1" diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index ab7d6b255..c45450495 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32f303ze to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-tim2", "exti"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml index 6595804e1..76be93913 100644 --- a/examples/stm32f334/Cargo.toml +++ b/examples/stm32f334/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 80c43f2ab..8cadeec9a 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32f429zi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-tim4", "exti", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt" ] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } diff --git a/examples/stm32f469/Cargo.toml b/examples/stm32f469/Cargo.toml index 87a3b8f75..6adb96a45 100644 --- a/examples/stm32f469/Cargo.toml +++ b/examples/stm32f469/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Specific examples only for stm32f469 embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32f469ni", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "1.0.1" diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 5995211d2..ab2991b68 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32f777zi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32f777zi", "memory-x", "unstable-pac", "time-driver-any", "exti", "single-bank"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embedded-io-async = { version = "0.6.1" } diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index 1c290fcfa..5cdcec42e 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32g0b1re to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g0b1re", "memory-x", "unstable-pac", "exti"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index a503420e5..a5b10c476 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32g491re to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 0ac9016d4..60ee73476 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32h563zi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 9053289ea..a3e1327b9 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32h723/Cargo.toml b/examples/stm32h723/Cargo.toml index fb219733f..af21a6647 100644 --- a/examples/stm32h723/Cargo.toml +++ b/examples/stm32h723/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32h723zg to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h723zg", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml index e4938e15b..58dc81d2e 100644 --- a/examples/stm32h735/Cargo.toml +++ b/examples/stm32h735/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml index efa71e144..5a983b8de 100644 --- a/examples/stm32h742/Cargo.toml +++ b/examples/stm32h742/Cargo.toml @@ -17,7 +17,7 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = [ "defmt", ] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = [ +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt", diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index cf324d3df..ae058802c 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index ac1429f30..cc1fa302d 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml index bfa7f9202..611b38ed8 100644 --- a/examples/stm32h7b0/Cargo.toml +++ b/examples/stm32h7b0/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml index 9794c6dbd..cc02a595a 100644 --- a/examples/stm32h7rs/Cargo.toml +++ b/examples/stm32h7rs/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ethernet", "medium-ip", "proto-ipv4"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 3101cf7ce..57eea6a95 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32l072cz to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32l073rz", "unstable-pac", "time-driver-any", "exti", "memory-x"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "1.0.1" diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 5d5d401f6..2b2160749 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index a6b4efcf8..0bbb33c10 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32l4s5vi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4r5zi", "memory-x", "time-driver-any", "exti", "chrono", "dual-bank"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32l432/Cargo.toml b/examples/stm32l432/Cargo.toml index c38462355..f4add6ea2 100644 --- a/examples/stm32l432/Cargo.toml +++ b/examples/stm32l432/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32l4s5vi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l432kc", "memory-x", "time-driver-any", "exti", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = [ "defmt" ] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "tick-hz-32_768" ] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 1379d963c..6931b848d 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32l552ze to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x", "low-power", "dual-bank"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml index 612d12ac2..ca5286f3a 100644 --- a/examples/stm32u0/Cargo.toml +++ b/examples/stm32u0/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32u083rc to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index f92e85852..2576c1326 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32u5g9zj to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u5g9zj", "time-driver-any", "memory-x" ] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index dbe9660e2..69deb0155 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml index 2c638f9f4..20c1570c8 100644 --- a/examples/stm32wba/Cargo.toml +++ b/examples/stm32wba/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } diff --git a/examples/stm32wba6/Cargo.toml b/examples/stm32wba6/Cargo.toml index 19c5e1e75..2a5850806 100644 --- a/examples/stm32wba6/Cargo.toml +++ b/examples/stm32wba6/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba65ri", "time-driver-any", "memory-x", "exti"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 1c5d9c07a..d6565502a 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32wl55jc-cm4 to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml index 9e553f52b..fb6e5dc16 100644 --- a/examples/wasm/Cargo.toml +++ b/examples/wasm/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] [dependencies] embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["log"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["log", "wasm", ] } wasm-logger = "0.2.0" diff --git a/tests/mspm0/Cargo.toml b/tests/mspm0/Cargo.toml index 5ba3e586b..5b570ebec 100644 --- a/tests/mspm0/Cargo.toml +++ b/tests/mspm0/Cargo.toml @@ -12,7 +12,7 @@ mspm0g3519 = [ "embassy-mspm0/mspm0g3519pz" ] teleprobe-meta = "1.1" embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = [ "defmt" ] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt" ] } embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = [ "rt", "defmt", "unstable-pac", "time-driver-any" ] } diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index b167c589e..3e1113ccf 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -9,7 +9,7 @@ teleprobe-meta = "1" embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt", ] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } diff --git a/tests/riscv32/Cargo.toml b/tests/riscv32/Cargo.toml index c5f6a1194..6bce9a0e3 100644 --- a/tests/riscv32/Cargo.toml +++ b/tests/riscv32/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] critical-section = { version = "1.1.1", features = ["restore-state-bool"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync" } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-riscv32", "executor-thread"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-riscv32", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../embassy-time" } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 298955fe3..ca1fa53da 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -13,7 +13,7 @@ rp235xb = ["embassy-rp/rp235xb"] teleprobe-meta = "1.1" embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", ] } embassy-rp = { version = "0.6.0", path = "../../embassy-rp", features = [ "defmt", "unstable-pac", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 7c32c0ce1..58ee10d77 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -64,7 +64,7 @@ cm0 = ["portable-atomic/unsafe-assume-single-core"] teleprobe-meta = "1" embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "tick-hz-131_072", "defmt-timestamp-uptime"] } embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "memory-x", "time-driver-any"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -- cgit From 746d4fe3a324e74b53ce6888470990c3feb47929 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Thu, 31 Jul 2025 10:33:58 +0200 Subject: chore: Release embassy-executor-macros version 0.7.0 --- embassy-executor-macros/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-executor-macros/Cargo.toml b/embassy-executor-macros/Cargo.toml index 5a38f2f06..f803e6644 100644 --- a/embassy-executor-macros/Cargo.toml +++ b/embassy-executor-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-executor-macros" -version = "0.6.2" +version = "0.7.0" edition = "2021" license = "MIT OR Apache-2.0" description = "macros for creating the entry point and tasks for embassy-executor" -- cgit From afc8be91a85c34cc9ec913b6fe608decc9eaf673 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Thu, 31 Jul 2025 10:34:07 +0200 Subject: chore: Release embassy-executor version 0.8.0 --- embassy-executor/CHANGELOG.md | 2 ++ embassy-executor/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 914863a83..3a809f075 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.8.0 - 2025-07-31 + - Added `SpawnToken::id` - Task pools are now statically allocated on stable rust. All `task-arena-size-*` features have been removed and are no longer necessary. - New trace hooks: `_embassy_trace_poll_start` & `_embassy_trace_task_end` diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index db3029967..5e950bf45 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-executor" -version = "0.7.0" +version = "0.8.0" edition = "2021" license = "MIT OR Apache-2.0" description = "async/await executor designed for embedded usage" -- cgit From 6f7a48efcd865043b110c174b3b93b26b7b67410 Mon Sep 17 00:00:00 2001 From: Preston Peranich Date: Thu, 31 Jul 2025 17:53:39 -0400 Subject: fix: remove static lifetime requirements from i2c shared bus. --- embassy-embedded-hal/src/shared_bus/asynch/i2c.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs b/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs index 71ce09def..6de685ee1 100644 --- a/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs +++ b/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs @@ -50,8 +50,8 @@ where impl i2c::I2c for I2cDevice<'_, M, BUS> where - M: RawMutex + 'static, - BUS: i2c::I2c + 'static, + M: RawMutex, + BUS: i2c::I2c, { async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), I2cDeviceError> { let mut bus = self.bus.lock().await; @@ -124,8 +124,8 @@ where impl i2c::I2c for I2cDeviceWithConfig<'_, M, BUS> where - M: RawMutex + 'static, - BUS: i2c::I2c + SetConfig + 'static, + M: RawMutex, + BUS: i2c::I2c + SetConfig, { async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), I2cDeviceError> { let mut bus = self.bus.lock().await; -- cgit From 59db841320df6d84e8a6f0b5de3ea5ef7dc11f6e Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 1 Aug 2025 15:17:40 +0200 Subject: fix: relax embassy-executor version requirement --- embassy-time-queue-utils/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-time-queue-utils/Cargo.toml b/embassy-time-queue-utils/Cargo.toml index fd98a1633..86a714be6 100644 --- a/embassy-time-queue-utils/Cargo.toml +++ b/embassy-time-queue-utils/Cargo.toml @@ -22,7 +22,7 @@ links = "embassy-time-queue" [dependencies] heapless = "0.8" -embassy-executor = { version = "0.8.0", path = "../embassy-executor" } +embassy-executor = { version = ">=0.7, <= 0.8", path = "../embassy-executor" } [features] #! ### Generic Queue -- cgit From e818e49d7a3c27a237bcd6d84df7971c3a02deba Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 1 Aug 2025 15:35:04 +0200 Subject: chore: Release embassy-time-queue-utils version 0.1.1 --- embassy-time-queue-utils/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-time-queue-utils/Cargo.toml b/embassy-time-queue-utils/Cargo.toml index 86a714be6..0523461df 100644 --- a/embassy-time-queue-utils/Cargo.toml +++ b/embassy-time-queue-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-time-queue-utils" -version = "0.1.0" +version = "0.1.1" edition = "2021" description = "Timer queue driver trait for embassy-time" repository = "https://github.com/embassy-rs/embassy" -- cgit From 89d52827564b7997f0900614c7b0eb67664c121a Mon Sep 17 00:00:00 2001 From: Brezak Date: Fri, 1 Aug 2025 18:42:25 +0200 Subject: embassy-sync: Update `MultiWakerRegistration::register` docs In 3081ecf301a54f8ed3d0f72350dd21f8ac9e1b18 `register` was changed to clear the buffer when it's full, but the docs weren't updated. --- embassy-sync/src/waitqueue/multi_waker.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-sync/src/waitqueue/multi_waker.rs b/embassy-sync/src/waitqueue/multi_waker.rs index 0384d6bed..1c05f8eaf 100644 --- a/embassy-sync/src/waitqueue/multi_waker.rs +++ b/embassy-sync/src/waitqueue/multi_waker.rs @@ -15,7 +15,9 @@ impl MultiWakerRegistration { Self { wakers: Vec::new() } } - /// Register a waker. If the buffer is full the function returns it in the error + /// Register a waker. + /// + /// If the buffer is full, [wakes all the wakers](Self::wake), clears its buffer and registers the waker. pub fn register(&mut self, w: &Waker) { // If we already have some waker that wakes the same task as `w`, do nothing. // This avoids cloning wakers, and avoids unnecessary mass-wakes. -- cgit From 0eceb08b90b1a7917db64ace80c3564d09394439 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 1 Aug 2025 21:42:23 +0200 Subject: fix: do full minor version bump for time queue utils --- embassy-imxrt/Cargo.toml | 2 +- embassy-mspm0/Cargo.toml | 2 +- embassy-nrf/Cargo.toml | 2 +- embassy-nxp/Cargo.toml | 2 +- embassy-rp/Cargo.toml | 2 +- embassy-stm32/Cargo.toml | 2 +- embassy-time-queue-utils/Cargo.toml | 4 ++-- embassy-time/Cargo.toml | 2 +- examples/nrf52840-rtic/Cargo.toml | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/embassy-imxrt/Cargo.toml b/embassy-imxrt/Cargo.toml index df4687043..8c3fa6492 100644 --- a/embassy-imxrt/Cargo.toml +++ b/embassy-imxrt/Cargo.toml @@ -65,7 +65,7 @@ mimxrt633s = ["mimxrt633s-pac", "_mimxrt633s"] [dependencies] embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } -embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } +embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.4", path = "../embassy-time", optional = true } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index 743254b58..0eb8237b5 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -29,7 +29,7 @@ embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } # TODO: Support other tick rates embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true, features = ["tick-hz-32_768"] } -embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } +embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 8fa20580d..d8579cfb6 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -141,7 +141,7 @@ _multi_wdt = [] [dependencies] embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } -embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } +embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 14fa7201d..2644b0fa9 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -23,7 +23,7 @@ defmt = { version = "1", optional = true } log = { version = "0.4.27", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } -embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } +embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } ## Chip dependencies lpc55-pac = { version = "0.5.0", optional = true } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index fa13ec1d9..a1011bc4e 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -138,7 +138,7 @@ binary-info = ["rt", "dep:rp-binary-info", "rp-binary-info?/binary-info"] [dependencies] embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } -embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } +embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index a63325679..643ab7eac 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -51,7 +51,7 @@ rustdoc-args = ["--cfg", "docsrs"] embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } -embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } +embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } diff --git a/embassy-time-queue-utils/Cargo.toml b/embassy-time-queue-utils/Cargo.toml index 0523461df..93fa0ce3c 100644 --- a/embassy-time-queue-utils/Cargo.toml +++ b/embassy-time-queue-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-time-queue-utils" -version = "0.1.1" +version = "0.2.0" edition = "2021" description = "Timer queue driver trait for embassy-time" repository = "https://github.com/embassy-rs/embassy" @@ -22,7 +22,7 @@ links = "embassy-time-queue" [dependencies] heapless = "0.8" -embassy-executor = { version = ">=0.7, <= 0.8", path = "../embassy-executor" } +embassy-executor = { version = "0.8", path = "../embassy-executor" } [features] #! ### Generic Queue diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index 618c6f518..163dbe95f 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml @@ -418,7 +418,7 @@ tick-hz-5_242_880_000 = ["embassy-time-driver/tick-hz-5_242_880_000"] [dependencies] embassy-time-driver = { version = "0.2", path = "../embassy-time-driver" } -embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true} +embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true} defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index 3e499e9bc..932c88eca 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml @@ -10,7 +10,7 @@ rtic = { version = "2", features = ["thumbv7-backend"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } -embassy-time-queue-utils = { version = "0.1", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } +embassy-time-queue-utils = { version = "0.2", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" -- cgit From 701e824175bf709f032e25fa991259582211b1d6 Mon Sep 17 00:00:00 2001 From: Piotr Esden-Tempski Date: Fri, 1 Aug 2025 18:06:42 -0700 Subject: ucpd: Add software trim setting of the CC Rp/Rd for stm32u5 parts. --- embassy-stm32/src/ucpd.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/embassy-stm32/src/ucpd.rs b/embassy-stm32/src/ucpd.rs index 87693f148..0a80adb8f 100644 --- a/embassy-stm32/src/ucpd.rs +++ b/embassy-stm32/src/ucpd.rs @@ -193,6 +193,18 @@ impl<'d, T: Instance> Ucpd<'d, T> { }); } + // Software trim according to RM0456, p. 3480/3462 + #[cfg(stm32u5)] + { + let trim_rd_cc1 = unsafe { *(0x0BFA_0544 as *const u8) & 0xF }; + let trim_rd_cc2 = unsafe { *(0x0BFA_0546 as *const u8) & 0xF }; + + r.cfgr3().write(|w| { + w.set_trim_cc1_rd(trim_rd_cc1); + w.set_trim_cc2_rd(trim_rd_cc2); + }); + } + Self { cc_phy: CcPhy { _lifetime: PhantomData }, } @@ -314,6 +326,25 @@ impl<'d, T: Instance> CcPhy<'d, T> { } }); + // Software trim according to RM0456, p. 3480/3462 + #[cfg(stm32u5)] + T::REGS.cfgr3().modify(|w| match cc_pull { + CcPull::Source1_5A => { + let trim_1a5_cc1 = unsafe { *(0x0BFA_07A7 as *const u8) & 0xF }; + let trim_1a5_cc2 = unsafe { *(0x0BFA_07A8 as *const u8) & 0xF }; + + w.set_trim_cc1_rp(trim_1a5_cc1); + w.set_trim_cc2_rp(trim_1a5_cc2); + } + _ => { + let trim_3a0_cc1 = unsafe { *(0x0BFA_0545 as *const u8) & 0xF }; + let trim_3a0_cc2 = unsafe { *(0x0BFA_0547 as *const u8) & 0xF }; + + w.set_trim_cc1_rp(trim_3a0_cc1); + w.set_trim_cc2_rp(trim_3a0_cc2); + } + }); + // Disable dead-battery pull-down resistors which are enabled by default on boot. critical_section::with(|cs| { init( -- cgit From 1652d9269e58fd56590da539fc5c35a15bdaf497 Mon Sep 17 00:00:00 2001 From: Elliot Sayes Date: Sat, 2 Aug 2025 17:26:42 +0400 Subject: Add IRQ StatusSource for _rp235x --- embassy-rp/src/pio/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/embassy-rp/src/pio/mod.rs b/embassy-rp/src/pio/mod.rs index ec698d99c..0d8a94776 100644 --- a/embassy-rp/src/pio/mod.rs +++ b/embassy-rp/src/pio/mod.rs @@ -98,6 +98,9 @@ pub enum StatusSource { TxFifoLevel = 0, /// All-ones if RX FIFO level < N, otherwise all-zeroes. RxFifoLevel = 1, + /// All-ones if the indexed IRQ flag is raised, otherwise all-zeroes + #[cfg(feature = "_rp235x")] + Irq = 2, } const RXNEMPTY_MASK: u32 = 1 << 0; @@ -736,6 +739,7 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { w.set_status_sel(match config.status_sel { StatusSource::TxFifoLevel => pac::pio::vals::ExecctrlStatusSel::TXLEVEL, StatusSource::RxFifoLevel => pac::pio::vals::ExecctrlStatusSel::RXLEVEL, + StatusSource::Irq => pac::pio::vals::ExecctrlStatusSel::IRQ, }); #[cfg(feature = "rp2040")] w.set_status_sel(match config.status_sel { -- cgit From d4f469576f66c2aa5a0eac0d50e6d816ddc07cf1 Mon Sep 17 00:00:00 2001 From: Magnus Nordlander Date: Sat, 2 Aug 2025 12:32:31 +0200 Subject: Added support for QMI CS1, and for APS6404L PSRAM on the RP2350 --- embassy-rp/src/lib.rs | 6 + embassy-rp/src/psram.rs | 669 ++++++++++++++++++++++++++++++++++++++++++++++ embassy-rp/src/qmi_cs1.rs | 73 +++++ 3 files changed, 748 insertions(+) create mode 100644 embassy-rp/src/psram.rs create mode 100644 embassy-rp/src/qmi_cs1.rs diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index eb497de1a..e5e964752 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -43,6 +43,10 @@ pub mod rtc; pub mod spi; mod spinlock; pub mod spinlock_mutex; +#[cfg(feature = "_rp235x")] +pub mod qmi_cs1; +#[cfg(feature = "_rp235x")] +pub mod psram; #[cfg(feature = "time-driver")] pub mod time_driver; #[cfg(feature = "_rp235x")] @@ -381,6 +385,8 @@ embassy_hal_internal::peripherals! { SPI0, SPI1, + QMI_CS1, + I2C0, I2C1, diff --git a/embassy-rp/src/psram.rs b/embassy-rp/src/psram.rs new file mode 100644 index 000000000..621f9300d --- /dev/null +++ b/embassy-rp/src/psram.rs @@ -0,0 +1,669 @@ +//! PSRAM driver for APS6404L and compatible devices +//! +//! This driver provides support for PSRAM (Pseudo-Static RAM) devices connected via QMI CS1. +//! It handles device verification, initialization, and memory-mapped access configuration. +//! +//! This driver is only available on RP235x chips as it requires the QMI CS1 peripheral. + +// Credit: Initially based on https://github.com/Altaflux/gb-rp2350 (also licensed Apache 2.0 + MIT). +// Copyright (c) Altaflux + +#![cfg(feature = "_rp235x")] + +use critical_section::{acquire, release, CriticalSection, RestoreState}; +use embassy_hal_internal::Peri; +use crate::qmi_cs1::QmiCs1; +use crate::{pac, peripherals}; + +/// PSRAM errors. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub enum Error { + /// PSRAM device is not detected or not supported + DeviceNotFound, + /// Invalid configuration + InvalidConfig, + /// Detected PSRAM size does not match the expected size + SizeMismatch, +} + +/// PSRAM device verification type. +#[derive(Clone, Copy)] +pub enum VerificationType { + /// Skip device verification + None, + /// Verify as APS6404L device + Aps6404l, +} + +/// Memory configuration. +#[derive(Clone)] +pub struct Config { + /// System clock frequency in Hz + pub clock_hz: u32, + /// Maximum memory operating frequency in Hz + pub max_mem_freq: u32, + /// Maximum CS assert time in microseconds (must be <= 8 us) + pub max_select_us: u32, + /// Minimum CS deassert time in nanoseconds (must be >= 18 ns) + pub min_deselect_ns: u32, + /// Cooldown period between operations (in SCLK cycles) + pub cooldown: u8, + /// Page break size for memory operations + pub page_break: PageBreak, + /// Clock divisor for direct mode operations during initialization + pub init_clkdiv: u8, + /// Enter Quad Mode command + pub enter_quad_cmd: Option, + /// Quad Read command (fast read with 4-bit data) + pub quad_read_cmd: u8, + /// Quad Write command (page program with 4-bit data) + pub quad_write_cmd: Option, + /// Number of dummy cycles for quad read operations + pub dummy_cycles: u8, + /// Read format configuration + pub read_format: FormatConfig, + /// Write format configuration + pub write_format: Option, + /// Expected memory size in bytes + pub mem_size: usize, + /// Device verification type + pub verification_type: VerificationType, + /// Whether the memory is writable via XIP (e.g., PSRAM vs. read-only flash) + pub xip_writable: bool, +} + +/// Page break configuration for memory window operations. +#[derive(Clone, Copy)] +pub enum PageBreak { + /// No page breaks + None, + /// Break at 256-byte boundaries + _256, + /// Break at 1024-byte boundaries + _1024, + /// Break at 4096-byte boundaries + _4096, +} + +/// Format configuration for read/write operations. +#[derive(Clone)] +pub struct FormatConfig { + /// Width of command prefix phase + pub prefix_width: Width, + /// Width of address phase + pub addr_width: Width, + /// Width of command suffix phase + pub suffix_width: Width, + /// Width of dummy/turnaround phase + pub dummy_width: Width, + /// Width of data phase + pub data_width: Width, + /// Length of prefix (None or 8 bits) + pub prefix_len: bool, + /// Length of suffix (None or 8 bits) + pub suffix_len: bool, +} + +/// Interface width for different phases of SPI transfer. +#[derive(Clone, Copy)] +pub enum Width { + /// Single-bit (standard SPI) + Single, + /// Dual-bit (2 data lines) + Dual, + /// Quad-bit (4 data lines) + Quad, +} + +impl Default for Config { + fn default() -> Self { + Self::aps6404l() + } +} + +impl Config { + /// Create configuration for APS6404L PSRAM. + pub fn aps6404l() -> Self { + Self { + clock_hz: 125_000_000, // Default to 125MHz + max_mem_freq: 133_000_000, // APS6404L max frequency + max_select_us: 8, // 8 microseconds max CS assert + min_deselect_ns: 18, // 18 nanoseconds min CS deassert + cooldown: 1, // 1 SCLK cycle cooldown + page_break: PageBreak::_1024, // 1024-byte page boundaries + init_clkdiv: 10, // Medium clock for initialization + enter_quad_cmd: Some(0x35), // Enter Quad Mode + quad_read_cmd: 0xEB, // Fast Quad Read + quad_write_cmd: Some(0x38), // Quad Page Program + dummy_cycles: 24, // 24 dummy cycles for quad read + read_format: FormatConfig { + prefix_width: Width::Quad, + addr_width: Width::Quad, + suffix_width: Width::Quad, + dummy_width: Width::Quad, + data_width: Width::Quad, + prefix_len: true, // 8-bit prefix + suffix_len: false, // No suffix + }, + write_format: Some(FormatConfig { + prefix_width: Width::Quad, + addr_width: Width::Quad, + suffix_width: Width::Quad, + dummy_width: Width::Quad, + data_width: Width::Quad, + prefix_len: true, // 8-bit prefix + suffix_len: false, // No suffix + }), + mem_size: 8 * 1024 * 1024, // 8MB for APS6404L + verification_type: VerificationType::Aps6404l, + xip_writable: true, // PSRAM is writable + } + } + + /// Create a custom memory configuration. + pub fn custom( + clock_hz: u32, + max_mem_freq: u32, + max_select_us: u32, + min_deselect_ns: u32, + cooldown: u8, + page_break: PageBreak, + init_clkdiv: u8, + enter_quad_cmd: Option, + quad_read_cmd: u8, + quad_write_cmd: Option, + dummy_cycles: u8, + read_format: FormatConfig, + write_format: Option, + mem_size: usize, + verification_type: VerificationType, + xip_writable: bool, + ) -> Self { + Self { + clock_hz, + max_mem_freq, + max_select_us, + min_deselect_ns, + cooldown, + page_break, + init_clkdiv, + enter_quad_cmd, + quad_read_cmd, + quad_write_cmd, + dummy_cycles, + read_format, + write_format, + mem_size, + verification_type, + xip_writable, + } + } +} + +/// PSRAM driver. +pub struct Psram<'d> { + qmi_cs1: QmiCs1<'d>, + size: usize, +} + +impl<'d> Psram<'d> { + /// Create a new PSRAM driver instance. + /// + /// This will detect the PSRAM device and configure it for memory-mapped access. + pub fn new( + qmi_cs1_peripheral: Peri<'d, peripherals::QMI_CS1>, + cs1: Peri<'d, impl crate::qmi_cs1::QmiCs1Pin>, + config: Config, + ) -> Result { + let qmi_cs1 = QmiCs1::new(qmi_cs1_peripheral, cs1); + let qmi = qmi_cs1.regs(); + + let xip = pac::XIP_CTRL; + + // Verify PSRAM device if requested + match config.verification_type { + VerificationType::Aps6404l => { + Self::verify_aps6404l(&qmi, config.mem_size)?; + debug!("APS6404L PSRAM verified, size: {:#x}", config.mem_size); + } + VerificationType::None => { + debug!("Skipping PSRAM verification, assuming size: {:#x}", config.mem_size); + } + } + + // Initialize PSRAM with proper timing + Self::init_psram(&qmi, &xip, &config)?; + + Ok(Self { qmi_cs1, size: config.mem_size }) + } + + /// Get the detected PSRAM size in bytes. + pub fn size(&self) -> usize { + self.size + } + + /// Get the base address for memory-mapped access. + /// + /// After initialization, PSRAM can be accessed directly through memory mapping. + /// The base address for CS1 is typically 0x11000000. + pub fn base_address(&self) -> *mut u8 { + 0x1100_0000 as *mut u8 + } + + /// Verify APS6404L PSRAM device matches expected configuration. + #[link_section = ".data.ram_func"] + #[inline(never)] + fn verify_aps6404l(qmi: &pac::qmi::Qmi, expected_size: usize) -> Result<(), Error> { + // APS6404L-specific constants + const RESET_ENABLE_CMD: u8 = 0xf5; + const READ_ID_CMD: u8 = 0x9f; + const EXPECTED_KGD: u8 = 0x5D; + crate::multicore::pause_core1(); + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + + { + // Helper for making sure `release` is called even if `f` panics. + struct Guard { + state: RestoreState, + } + + impl Drop for Guard { + #[inline(always)] + fn drop(&mut self) { + unsafe { release(self.state) } + } + } + + let state = unsafe { acquire() }; + let _guard = Guard { state }; + + let _cs = unsafe { CriticalSection::new() }; + + let qmi_base = qmi.as_ptr() as usize; + + #[allow(unused_assignments)] + let mut kgd: u32 = 0; + #[allow(unused_assignments)] + let mut eid: u32 = 0; + + unsafe { + core::arch::asm!( + // Configure DIRECT_CSR: shift clkdiv (30) to bits 29:22 and set EN (bit 0) + "movs {temp}, #30", + "lsls {temp}, {temp}, #22", + "orr {temp}, {temp}, #1", // Set EN bit + "str {temp}, [{qmi_base}]", + + // Poll for BUSY to clear before first operation + "1:", + "ldr {temp}, [{qmi_base}]", + "lsls {temp}, {temp}, #30", // Shift BUSY bit to sign position + "bmi 1b", // Branch if negative (BUSY = 1) + + // Assert CS1N (bit 3) + "ldr {temp}, [{qmi_base}]", + "orr {temp}, {temp}, #8", // Set ASSERT_CS1N bit (bit 3) + "str {temp}, [{qmi_base}]", + + // Transmit RESET_ENABLE_CMD as quad + // DIRECT_TX: OE=1 (bit 19), IWIDTH=2 (bits 17:16), DATA=RESET_ENABLE_CMD + "movs {temp}, {reset_enable_cmd}", + "orr {temp}, {temp}, #0x80000", // Set OE (bit 19) + "orr {temp}, {temp}, #0x20000", // Set IWIDTH=2 (quad, bits 17:16) + "str {temp}, [{qmi_base}, #4]", // Store to DIRECT_TX + + // Wait for BUSY to clear + "2:", + "ldr {temp}, [{qmi_base}]", + "lsls {temp}, {temp}, #30", + "bmi 2b", + + // Read and discard RX data + "ldr {temp}, [{qmi_base}, #8]", + + // Deassert CS1N + "ldr {temp}, [{qmi_base}]", + "bic {temp}, {temp}, #8", // Clear ASSERT_CS1N bit + "str {temp}, [{qmi_base}]", + + // Assert CS1N again + "ldr {temp}, [{qmi_base}]", + "orr {temp}, {temp}, #8", // Set ASSERT_CS1N bit + "str {temp}, [{qmi_base}]", + + // Read ID loop (7 iterations) + "movs {counter}, #0", // Initialize counter + + "3:", // Loop start + "cmp {counter}, #0", + "bne 4f", // If not first iteration, send 0xFF + + // First iteration: send READ_ID_CMD + "movs {temp}, {read_id_cmd}", + "b 5f", + + "4:", // Other iterations: send 0xFF + "movs {temp}, #0xFF", + + "5:", + "str {temp}, [{qmi_base}, #4]", // Store to DIRECT_TX + + // Wait for TXEMPTY + "6:", + "ldr {temp}, [{qmi_base}]", + "lsls {temp}, {temp}, #20", // Shift TXEMPTY (bit 11) to bit 31 + "bpl 6b", // Branch if positive (TXEMPTY = 0) + + // Wait for BUSY to clear + "7:", + "ldr {temp}, [{qmi_base}]", + "lsls {temp}, {temp}, #30", // Shift BUSY bit to sign position + "bmi 7b", // Branch if negative (BUSY = 1) + + // Read RX data + "ldr {temp}, [{qmi_base}, #8]", + "uxth {temp}, {temp}", // Extract lower 16 bits + + // Store KGD or EID based on iteration + "cmp {counter}, #5", + "bne 8f", + "mov {kgd}, {temp}", // Store KGD + "b 9f", + + "8:", + "cmp {counter}, #6", + "bne 9f", + "mov {eid}, {temp}", // Store EID + + "9:", + "adds {counter}, #1", + "cmp {counter}, #7", + "blt 3b", // Continue loop if counter < 7 + + // Disable direct mode: clear EN and ASSERT_CS1N + "movs {temp}, #0", + "str {temp}, [{qmi_base}]", + + // Memory barriers + "dmb", + "dsb", + "isb", + + qmi_base = in(reg) qmi_base, + temp = out(reg) _, + counter = out(reg) _, + kgd = out(reg) kgd, + eid = out(reg) eid, + reset_enable_cmd = const RESET_ENABLE_CMD as u32, + read_id_cmd = const READ_ID_CMD as u32, + options(nostack), + ); + } + + let mut detected_size: u32 = 0; + if kgd == EXPECTED_KGD as u32 { + detected_size = 1024 * 1024; + let size_id = eid >> 5; + if eid == 0x26 || size_id == 2 { // APS6404L-3SQR-SN or 8MB variants + detected_size *= 8; + } else if size_id == 0 { + detected_size *= 2; + } else if size_id == 1 { + detected_size *= 4; + } + } + + // Verify the detected size matches the expected size + if detected_size as usize != expected_size { + return Err(Error::SizeMismatch); + } + + Ok(()) + }?; + + crate::multicore::resume_core1(); + + Ok(()) + } + + /// Initialize PSRAM with proper timing. + #[link_section = ".data.ram_func"] + #[inline(never)] + fn init_psram(qmi: &pac::qmi::Qmi, xip_ctrl: &pac::xip_ctrl::XipCtrl, config: &Config) -> Result<(), Error> { + // Set PSRAM timing for APS6404 + // + // Using an rxdelay equal to the divisor isn't enough when running the APS6404 close to 133 MHz. + // So: don't allow running at divisor 1 above 100 MHz (because delay of 2 would be too late), + // and add an extra 1 to the rxdelay if the divided clock is > 100 MHz (i.e., sys clock > 200 MHz). + let clock_hz = config.clock_hz; + let max_psram_freq = config.max_mem_freq; + + let mut divisor: u32 = (clock_hz + max_psram_freq - 1) / max_psram_freq; + if divisor == 1 && clock_hz > 100_000_000 { + divisor = 2; + } + let mut rxdelay: u32 = divisor; + if clock_hz / divisor > 100_000_000 { + rxdelay += 1; + } + + // - Max select must be <= 8 us. The value is given in multiples of 64 system clocks. + // - Min deselect must be >= 18ns. The value is given in system clock cycles - ceil(divisor / 2). + let clock_period_fs: u64 = 1_000_000_000_000_000_u64 / u64::from(clock_hz); + let max_select: u8 = ((config.max_select_us as u64 * 1_000_000) / clock_period_fs) as u8; + let min_deselect: u32 = ((config.min_deselect_ns as u64 * 1_000_000 + (clock_period_fs - 1)) / clock_period_fs + - u64::from(divisor + 1) / 2) as u32; + + crate::multicore::pause_core1(); + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + + if let Some(enter_quad_cmd) = config.enter_quad_cmd { + // Helper for making sure `release` is called even if `f` panics. + struct Guard { + state: RestoreState, + } + + impl Drop for Guard { + #[inline(always)] + fn drop(&mut self) { + unsafe { release(self.state) } + } + } + + let state = unsafe { acquire() }; + let _guard = Guard { state }; + + let _cs = unsafe { CriticalSection::new() }; + + unsafe { + core::arch::asm!( + // Full memory barrier + "dmb", + "dsb", + "isb", + + // Configure QMI Direct CSR register + // Load base address of QMI (0x400D0000) + "movw {base}, #0x0000", + "movt {base}, #0x400D", + + // Load init_clkdiv and shift to bits 29:22 + "lsl {temp}, {clkdiv}, #22", + + // OR with EN (bit 0) and AUTO_CS1N (bit 7) + "orr {temp}, {temp}, #0x81", + + // Store to DIRECT_CSR register + "str {temp}, [{base}, #0]", + + // Memory barrier + "dmb", + + // First busy wait loop + "1:", + "ldr {temp}, [{base}, #0]", // Load DIRECT_CSR + "tst {temp}, #0x2", // Test BUSY bit (bit 1) + "bne 1b", // Branch if busy + + // Write to Direct TX register + "mov {temp}, {enter_quad_cmd}", + + // OR with NOPUSH (bit 20) + "orr {temp}, {temp}, #0x100000", + + // Store to DIRECT_TX register (offset 0x4) + "str {temp}, [{base}, #4]", + + // Memory barrier + "dmb", + + // Second busy wait loop + "2:", + "ldr {temp}, [{base}, #0]", // Load DIRECT_CSR + "tst {temp}, #0x2", // Test BUSY bit (bit 1) + "bne 2b", // Branch if busy + + // Disable Direct CSR + "mov {temp}, #0", + "str {temp}, [{base}, #0]", // Clear DIRECT_CSR register + + // Full memory barrier to ensure no prefetching + "dmb", + "dsb", + "isb", + + base = out(reg) _, + temp = out(reg) _, + clkdiv = in(reg) config.init_clkdiv as u32, + enter_quad_cmd = in(reg) u32::from(enter_quad_cmd), + options(nostack), + ); + } + + qmi.mem(1).timing().write(|w| { + w.set_cooldown(config.cooldown); + w.set_pagebreak(match config.page_break { + PageBreak::None => pac::qmi::vals::Pagebreak::NONE, + PageBreak::_256 => pac::qmi::vals::Pagebreak::_256, + PageBreak::_1024 => pac::qmi::vals::Pagebreak::_1024, + PageBreak::_4096 => pac::qmi::vals::Pagebreak::_4096, + }); + w.set_max_select(max_select); + w.set_min_deselect(min_deselect as u8); + w.set_rxdelay(rxdelay as u8); + w.set_clkdiv(divisor as u8); + }); + + // Set PSRAM commands and formats + qmi.mem(1).rfmt().write(|w| { + let width_to_pac = |w: Width| match w { + Width::Single => pac::qmi::vals::PrefixWidth::S, + Width::Dual => pac::qmi::vals::PrefixWidth::D, + Width::Quad => pac::qmi::vals::PrefixWidth::Q, + }; + + w.set_prefix_width(width_to_pac(config.read_format.prefix_width)); + w.set_addr_width(match config.read_format.addr_width { + Width::Single => pac::qmi::vals::AddrWidth::S, + Width::Dual => pac::qmi::vals::AddrWidth::D, + Width::Quad => pac::qmi::vals::AddrWidth::Q, + }); + w.set_suffix_width(match config.read_format.suffix_width { + Width::Single => pac::qmi::vals::SuffixWidth::S, + Width::Dual => pac::qmi::vals::SuffixWidth::D, + Width::Quad => pac::qmi::vals::SuffixWidth::Q, + }); + w.set_dummy_width(match config.read_format.dummy_width { + Width::Single => pac::qmi::vals::DummyWidth::S, + Width::Dual => pac::qmi::vals::DummyWidth::D, + Width::Quad => pac::qmi::vals::DummyWidth::Q, + }); + w.set_data_width(match config.read_format.data_width { + Width::Single => pac::qmi::vals::DataWidth::S, + Width::Dual => pac::qmi::vals::DataWidth::D, + Width::Quad => pac::qmi::vals::DataWidth::Q, + }); + w.set_prefix_len(if config.read_format.prefix_len { + pac::qmi::vals::PrefixLen::_8 + } else { + pac::qmi::vals::PrefixLen::NONE + }); + w.set_suffix_len(if config.read_format.suffix_len { + pac::qmi::vals::SuffixLen::_8 + } else { + pac::qmi::vals::SuffixLen::NONE + }); + w.set_dummy_len(match config.dummy_cycles { + 0 => pac::qmi::vals::DummyLen::NONE, + 4 => pac::qmi::vals::DummyLen::_4, + 8 => pac::qmi::vals::DummyLen::_8, + 12 => pac::qmi::vals::DummyLen::_12, + 16 => pac::qmi::vals::DummyLen::_16, + 20 => pac::qmi::vals::DummyLen::_20, + 24 => pac::qmi::vals::DummyLen::_24, + 28 => pac::qmi::vals::DummyLen::_28, + _ => pac::qmi::vals::DummyLen::_24, // Default to 24 + }); + }); + + qmi.mem(1).rcmd().write(|w| w.set_prefix(config.quad_read_cmd)); + + if let Some(ref write_format) = config.write_format { + qmi.mem(1).wfmt().write(|w| { + w.set_prefix_width(match write_format.prefix_width { + Width::Single => pac::qmi::vals::PrefixWidth::S, + Width::Dual => pac::qmi::vals::PrefixWidth::D, + Width::Quad => pac::qmi::vals::PrefixWidth::Q, + }); + w.set_addr_width(match write_format.addr_width { + Width::Single => pac::qmi::vals::AddrWidth::S, + Width::Dual => pac::qmi::vals::AddrWidth::D, + Width::Quad => pac::qmi::vals::AddrWidth::Q, + }); + w.set_suffix_width(match write_format.suffix_width { + Width::Single => pac::qmi::vals::SuffixWidth::S, + Width::Dual => pac::qmi::vals::SuffixWidth::D, + Width::Quad => pac::qmi::vals::SuffixWidth::Q, + }); + w.set_dummy_width(match write_format.dummy_width { + Width::Single => pac::qmi::vals::DummyWidth::S, + Width::Dual => pac::qmi::vals::DummyWidth::D, + Width::Quad => pac::qmi::vals::DummyWidth::Q, + }); + w.set_data_width(match write_format.data_width { + Width::Single => pac::qmi::vals::DataWidth::S, + Width::Dual => pac::qmi::vals::DataWidth::D, + Width::Quad => pac::qmi::vals::DataWidth::Q, + }); + w.set_prefix_len(if write_format.prefix_len { + pac::qmi::vals::PrefixLen::_8 + } else { + pac::qmi::vals::PrefixLen::NONE + }); + w.set_suffix_len(if write_format.suffix_len { + pac::qmi::vals::SuffixLen::_8 + } else { + pac::qmi::vals::SuffixLen::NONE + }); + }); + } + + if let Some(quad_write_cmd) = config.quad_write_cmd { + qmi.mem(1).wcmd().write(|w| w.set_prefix(quad_write_cmd)); + } + + if config.xip_writable { + // Enable XIP writable mode for PSRAM + xip_ctrl.ctrl().modify(|w| w.set_writable_m1(true)); + } else { + // Disable XIP writable mode + xip_ctrl.ctrl().modify(|w| w.set_writable_m1(false)); + } + } + crate::multicore::resume_core1(); + + Ok(()) + } +} \ No newline at end of file diff --git a/embassy-rp/src/qmi_cs1.rs b/embassy-rp/src/qmi_cs1.rs new file mode 100644 index 000000000..a8bcd81f7 --- /dev/null +++ b/embassy-rp/src/qmi_cs1.rs @@ -0,0 +1,73 @@ +//! QMI CS1 peripheral for RP235x +//! +//! This module provides access to the QMI CS1 functionality for use with external memory devices +//! such as PSRAM. The QMI (Quad SPI) controller supports CS1 as a second chip select signal. +//! +//! This peripheral is only available on RP235x chips. + +#![cfg(feature = "_rp235x")] + +use embassy_hal_internal::{Peri, PeripheralType}; + +use crate::gpio::Pin as GpioPin; +use crate::{pac, peripherals}; + +/// QMI CS1 driver. +pub struct QmiCs1<'d> { + _inner: Peri<'d, peripherals::QMI_CS1>, +} + +impl<'d> QmiCs1<'d> { + /// Create a new QMI CS1 instance. + pub fn new( + qmi_cs1: Peri<'d, peripherals::QMI_CS1>, + cs1: Peri<'d, impl QmiCs1Pin>, + ) -> Self { + // Configure CS1 pin for QMI function (funcsel = 9) + cs1.gpio().ctrl().write(|w| w.set_funcsel(9)); + + // Configure pad settings for high-speed operation + cs1.pad_ctrl().write(|w| { + #[cfg(feature = "_rp235x")] + w.set_iso(false); + w.set_ie(true); + w.set_drive(pac::pads::vals::Drive::_12M_A); + w.set_slewfast(true); + }); + + Self { _inner: qmi_cs1 } + } + + /// Get access to the QMI peripheral registers. + /// + /// This allows low-level access to configure the QMI controller for specific memory devices. + pub fn regs(&self) -> pac::qmi::Qmi { + pac::QMI + } +} + +trait SealedInstance { + fn regs(&self) -> pac::qmi::Qmi; +} + +/// QMI CS1 instance trait. +#[allow(private_bounds)] +pub trait Instance: SealedInstance + PeripheralType {} + +impl SealedInstance for peripherals::QMI_CS1 { + fn regs(&self) -> pac::qmi::Qmi { + pac::QMI + } +} + +impl Instance for peripherals::QMI_CS1 {} + +/// CS1 pin trait for QMI. +pub trait QmiCs1Pin: GpioPin {} + +// Implement pin traits for CS1-capable GPIO pins +impl QmiCs1Pin for peripherals::PIN_0 {} +impl QmiCs1Pin for peripherals::PIN_8 {} +impl QmiCs1Pin for peripherals::PIN_19 {} +#[cfg(feature = "rp235xb")] +impl QmiCs1Pin for peripherals::PIN_47 {} -- cgit From af6b74ad5a423b3d9a0ad7776723b5ec7e0116af Mon Sep 17 00:00:00 2001 From: Magnus Nordlander Date: Sat, 2 Aug 2025 18:45:56 +0200 Subject: Apply rustfmt --- embassy-rp/src/lib.rs | 8 +- embassy-rp/src/psram.rs | 220 +++++++++++++++++++++++----------------------- embassy-rp/src/qmi_cs1.rs | 15 ++-- 3 files changed, 122 insertions(+), 121 deletions(-) diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index e5e964752..6fb680b34 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -35,7 +35,11 @@ pub mod multicore; #[cfg(feature = "_rp235x")] pub mod otp; pub mod pio_programs; +#[cfg(feature = "_rp235x")] +pub mod psram; pub mod pwm; +#[cfg(feature = "_rp235x")] +pub mod qmi_cs1; mod reset; pub mod rom_data; #[cfg(feature = "rp2040")] @@ -43,10 +47,6 @@ pub mod rtc; pub mod spi; mod spinlock; pub mod spinlock_mutex; -#[cfg(feature = "_rp235x")] -pub mod qmi_cs1; -#[cfg(feature = "_rp235x")] -pub mod psram; #[cfg(feature = "time-driver")] pub mod time_driver; #[cfg(feature = "_rp235x")] diff --git a/embassy-rp/src/psram.rs b/embassy-rp/src/psram.rs index 621f9300d..190a7eb09 100644 --- a/embassy-rp/src/psram.rs +++ b/embassy-rp/src/psram.rs @@ -10,10 +10,10 @@ #![cfg(feature = "_rp235x")] -use critical_section::{acquire, release, CriticalSection, RestoreState}; -use embassy_hal_internal::Peri; use crate::qmi_cs1::QmiCs1; use crate::{pac, peripherals}; +use critical_section::{acquire, release, CriticalSection, RestoreState}; +use embassy_hal_internal::Peri; /// PSRAM errors. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -127,25 +127,25 @@ impl Config { /// Create configuration for APS6404L PSRAM. pub fn aps6404l() -> Self { Self { - clock_hz: 125_000_000, // Default to 125MHz + clock_hz: 125_000_000, // Default to 125MHz max_mem_freq: 133_000_000, // APS6404L max frequency - max_select_us: 8, // 8 microseconds max CS assert - min_deselect_ns: 18, // 18 nanoseconds min CS deassert - cooldown: 1, // 1 SCLK cycle cooldown - page_break: PageBreak::_1024, // 1024-byte page boundaries - init_clkdiv: 10, // Medium clock for initialization - enter_quad_cmd: Some(0x35), // Enter Quad Mode - quad_read_cmd: 0xEB, // Fast Quad Read - quad_write_cmd: Some(0x38), // Quad Page Program - dummy_cycles: 24, // 24 dummy cycles for quad read + max_select_us: 8, // 8 microseconds max CS assert + min_deselect_ns: 18, // 18 nanoseconds min CS deassert + cooldown: 1, // 1 SCLK cycle cooldown + page_break: PageBreak::_1024, // 1024-byte page boundaries + init_clkdiv: 10, // Medium clock for initialization + enter_quad_cmd: Some(0x35), // Enter Quad Mode + quad_read_cmd: 0xEB, // Fast Quad Read + quad_write_cmd: Some(0x38), // Quad Page Program + dummy_cycles: 24, // 24 dummy cycles for quad read read_format: FormatConfig { prefix_width: Width::Quad, addr_width: Width::Quad, suffix_width: Width::Quad, dummy_width: Width::Quad, data_width: Width::Quad, - prefix_len: true, // 8-bit prefix - suffix_len: false, // No suffix + prefix_len: true, // 8-bit prefix + suffix_len: false, // No suffix }, write_format: Some(FormatConfig { prefix_width: Width::Quad, @@ -153,15 +153,15 @@ impl Config { suffix_width: Width::Quad, dummy_width: Width::Quad, data_width: Width::Quad, - prefix_len: true, // 8-bit prefix - suffix_len: false, // No suffix + prefix_len: true, // 8-bit prefix + suffix_len: false, // No suffix }), - mem_size: 8 * 1024 * 1024, // 8MB for APS6404L + mem_size: 8 * 1024 * 1024, // 8MB for APS6404L verification_type: VerificationType::Aps6404l, - xip_writable: true, // PSRAM is writable + xip_writable: true, // PSRAM is writable } } - + /// Create a custom memory configuration. pub fn custom( clock_hz: u32, @@ -236,7 +236,10 @@ impl<'d> Psram<'d> { // Initialize PSRAM with proper timing Self::init_psram(&qmi, &xip, &config)?; - Ok(Self { qmi_cs1, size: config.mem_size }) + Ok(Self { + qmi_cs1, + size: config.mem_size, + }) } /// Get the detected PSRAM size in bytes. @@ -245,7 +248,7 @@ impl<'d> Psram<'d> { } /// Get the base address for memory-mapped access. - /// + /// /// After initialization, PSRAM can be accessed directly through memory mapping. /// The base address for CS1 is typically 0x11000000. pub fn base_address(&self) -> *mut u8 { @@ -280,14 +283,14 @@ impl<'d> Psram<'d> { let _guard = Guard { state }; let _cs = unsafe { CriticalSection::new() }; - + let qmi_base = qmi.as_ptr() as usize; #[allow(unused_assignments)] let mut kgd: u32 = 0; #[allow(unused_assignments)] let mut eid: u32 = 0; - + unsafe { core::arch::asm!( // Configure DIRECT_CSR: shift clkdiv (30) to bits 29:22 and set EN (bit 0) @@ -295,102 +298,102 @@ impl<'d> Psram<'d> { "lsls {temp}, {temp}, #22", "orr {temp}, {temp}, #1", // Set EN bit "str {temp}, [{qmi_base}]", - + // Poll for BUSY to clear before first operation "1:", "ldr {temp}, [{qmi_base}]", "lsls {temp}, {temp}, #30", // Shift BUSY bit to sign position "bmi 1b", // Branch if negative (BUSY = 1) - + // Assert CS1N (bit 3) "ldr {temp}, [{qmi_base}]", "orr {temp}, {temp}, #8", // Set ASSERT_CS1N bit (bit 3) "str {temp}, [{qmi_base}]", - + // Transmit RESET_ENABLE_CMD as quad // DIRECT_TX: OE=1 (bit 19), IWIDTH=2 (bits 17:16), DATA=RESET_ENABLE_CMD "movs {temp}, {reset_enable_cmd}", "orr {temp}, {temp}, #0x80000", // Set OE (bit 19) "orr {temp}, {temp}, #0x20000", // Set IWIDTH=2 (quad, bits 17:16) "str {temp}, [{qmi_base}, #4]", // Store to DIRECT_TX - + // Wait for BUSY to clear "2:", "ldr {temp}, [{qmi_base}]", "lsls {temp}, {temp}, #30", "bmi 2b", - + // Read and discard RX data "ldr {temp}, [{qmi_base}, #8]", - + // Deassert CS1N "ldr {temp}, [{qmi_base}]", "bic {temp}, {temp}, #8", // Clear ASSERT_CS1N bit "str {temp}, [{qmi_base}]", - + // Assert CS1N again "ldr {temp}, [{qmi_base}]", "orr {temp}, {temp}, #8", // Set ASSERT_CS1N bit "str {temp}, [{qmi_base}]", - + // Read ID loop (7 iterations) "movs {counter}, #0", // Initialize counter - + "3:", // Loop start "cmp {counter}, #0", "bne 4f", // If not first iteration, send 0xFF - + // First iteration: send READ_ID_CMD "movs {temp}, {read_id_cmd}", "b 5f", - + "4:", // Other iterations: send 0xFF "movs {temp}, #0xFF", - + "5:", "str {temp}, [{qmi_base}, #4]", // Store to DIRECT_TX - + // Wait for TXEMPTY "6:", "ldr {temp}, [{qmi_base}]", "lsls {temp}, {temp}, #20", // Shift TXEMPTY (bit 11) to bit 31 "bpl 6b", // Branch if positive (TXEMPTY = 0) - + // Wait for BUSY to clear "7:", "ldr {temp}, [{qmi_base}]", "lsls {temp}, {temp}, #30", // Shift BUSY bit to sign position "bmi 7b", // Branch if negative (BUSY = 1) - + // Read RX data "ldr {temp}, [{qmi_base}, #8]", "uxth {temp}, {temp}", // Extract lower 16 bits - + // Store KGD or EID based on iteration "cmp {counter}, #5", "bne 8f", "mov {kgd}, {temp}", // Store KGD "b 9f", - + "8:", "cmp {counter}, #6", "bne 9f", "mov {eid}, {temp}", // Store EID - + "9:", "adds {counter}, #1", "cmp {counter}, #7", "blt 3b", // Continue loop if counter < 7 - + // Disable direct mode: clear EN and ASSERT_CS1N "movs {temp}, #0", "str {temp}, [{qmi_base}]", - + // Memory barriers "dmb", "dsb", "isb", - + qmi_base = in(reg) qmi_base, temp = out(reg) _, counter = out(reg) _, @@ -406,7 +409,8 @@ impl<'d> Psram<'d> { if kgd == EXPECTED_KGD as u32 { detected_size = 1024 * 1024; let size_id = eid >> 5; - if eid == 0x26 || size_id == 2 { // APS6404L-3SQR-SN or 8MB variants + if eid == 0x26 || size_id == 2 { + // APS6404L-3SQR-SN or 8MB variants detected_size *= 8; } else if size_id == 0 { detected_size *= 2; @@ -476,70 +480,70 @@ impl<'d> Psram<'d> { let _guard = Guard { state }; let _cs = unsafe { CriticalSection::new() }; - + unsafe { core::arch::asm!( - // Full memory barrier - "dmb", - "dsb", - "isb", - - // Configure QMI Direct CSR register - // Load base address of QMI (0x400D0000) - "movw {base}, #0x0000", - "movt {base}, #0x400D", - - // Load init_clkdiv and shift to bits 29:22 - "lsl {temp}, {clkdiv}, #22", - - // OR with EN (bit 0) and AUTO_CS1N (bit 7) - "orr {temp}, {temp}, #0x81", - - // Store to DIRECT_CSR register - "str {temp}, [{base}, #0]", - - // Memory barrier - "dmb", - - // First busy wait loop - "1:", - "ldr {temp}, [{base}, #0]", // Load DIRECT_CSR - "tst {temp}, #0x2", // Test BUSY bit (bit 1) - "bne 1b", // Branch if busy - - // Write to Direct TX register - "mov {temp}, {enter_quad_cmd}", - - // OR with NOPUSH (bit 20) - "orr {temp}, {temp}, #0x100000", - - // Store to DIRECT_TX register (offset 0x4) - "str {temp}, [{base}, #4]", - - // Memory barrier - "dmb", - - // Second busy wait loop - "2:", - "ldr {temp}, [{base}, #0]", // Load DIRECT_CSR - "tst {temp}, #0x2", // Test BUSY bit (bit 1) - "bne 2b", // Branch if busy - - // Disable Direct CSR - "mov {temp}, #0", - "str {temp}, [{base}, #0]", // Clear DIRECT_CSR register - - // Full memory barrier to ensure no prefetching - "dmb", - "dsb", - "isb", - - base = out(reg) _, - temp = out(reg) _, - clkdiv = in(reg) config.init_clkdiv as u32, - enter_quad_cmd = in(reg) u32::from(enter_quad_cmd), - options(nostack), - ); + // Full memory barrier + "dmb", + "dsb", + "isb", + + // Configure QMI Direct CSR register + // Load base address of QMI (0x400D0000) + "movw {base}, #0x0000", + "movt {base}, #0x400D", + + // Load init_clkdiv and shift to bits 29:22 + "lsl {temp}, {clkdiv}, #22", + + // OR with EN (bit 0) and AUTO_CS1N (bit 7) + "orr {temp}, {temp}, #0x81", + + // Store to DIRECT_CSR register + "str {temp}, [{base}, #0]", + + // Memory barrier + "dmb", + + // First busy wait loop + "1:", + "ldr {temp}, [{base}, #0]", // Load DIRECT_CSR + "tst {temp}, #0x2", // Test BUSY bit (bit 1) + "bne 1b", // Branch if busy + + // Write to Direct TX register + "mov {temp}, {enter_quad_cmd}", + + // OR with NOPUSH (bit 20) + "orr {temp}, {temp}, #0x100000", + + // Store to DIRECT_TX register (offset 0x4) + "str {temp}, [{base}, #4]", + + // Memory barrier + "dmb", + + // Second busy wait loop + "2:", + "ldr {temp}, [{base}, #0]", // Load DIRECT_CSR + "tst {temp}, #0x2", // Test BUSY bit (bit 1) + "bne 2b", // Branch if busy + + // Disable Direct CSR + "mov {temp}, #0", + "str {temp}, [{base}, #0]", // Clear DIRECT_CSR register + + // Full memory barrier to ensure no prefetching + "dmb", + "dsb", + "isb", + + base = out(reg) _, + temp = out(reg) _, + clkdiv = in(reg) config.init_clkdiv as u32, + enter_quad_cmd = in(reg) u32::from(enter_quad_cmd), + options(nostack), + ); } qmi.mem(1).timing().write(|w| { @@ -666,4 +670,4 @@ impl<'d> Psram<'d> { Ok(()) } -} \ No newline at end of file +} diff --git a/embassy-rp/src/qmi_cs1.rs b/embassy-rp/src/qmi_cs1.rs index a8bcd81f7..4e2dc0dbf 100644 --- a/embassy-rp/src/qmi_cs1.rs +++ b/embassy-rp/src/qmi_cs1.rs @@ -1,5 +1,5 @@ //! QMI CS1 peripheral for RP235x -//! +//! //! This module provides access to the QMI CS1 functionality for use with external memory devices //! such as PSRAM. The QMI (Quad SPI) controller supports CS1 as a second chip select signal. //! @@ -19,14 +19,11 @@ pub struct QmiCs1<'d> { impl<'d> QmiCs1<'d> { /// Create a new QMI CS1 instance. - pub fn new( - qmi_cs1: Peri<'d, peripherals::QMI_CS1>, - cs1: Peri<'d, impl QmiCs1Pin>, - ) -> Self { + pub fn new(qmi_cs1: Peri<'d, peripherals::QMI_CS1>, cs1: Peri<'d, impl QmiCs1Pin>) -> Self { // Configure CS1 pin for QMI function (funcsel = 9) cs1.gpio().ctrl().write(|w| w.set_funcsel(9)); - - // Configure pad settings for high-speed operation + + // Configure pad settings for high-speed operation cs1.pad_ctrl().write(|w| { #[cfg(feature = "_rp235x")] w.set_iso(false); @@ -39,7 +36,7 @@ impl<'d> QmiCs1<'d> { } /// Get access to the QMI peripheral registers. - /// + /// /// This allows low-level access to configure the QMI controller for specific memory devices. pub fn regs(&self) -> pac::qmi::Qmi { pac::QMI @@ -70,4 +67,4 @@ impl QmiCs1Pin for peripherals::PIN_0 {} impl QmiCs1Pin for peripherals::PIN_8 {} impl QmiCs1Pin for peripherals::PIN_19 {} #[cfg(feature = "rp235xb")] -impl QmiCs1Pin for peripherals::PIN_47 {} +impl QmiCs1Pin for peripherals::PIN_47 {} -- cgit From 8843b08b90dcf983ebeb13fc09d2a8c0b6e48c10 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 15 Jul 2025 11:04:36 +0200 Subject: feat: add embassy-release tool * Print dependencies of a crate * Bump version in dependent crates * Release using cargo release * Config file to control features and target --- embassy-release/Cargo.toml | 12 ++ embassy-release/src/main.rs | 303 ++++++++++++++++++++++++++++++++++++++++++++ release/config.toml | 1 + 3 files changed, 316 insertions(+) create mode 100644 embassy-release/Cargo.toml create mode 100644 embassy-release/src/main.rs create mode 100644 release/config.toml diff --git a/embassy-release/Cargo.toml b/embassy-release/Cargo.toml new file mode 100644 index 000000000..de548e650 --- /dev/null +++ b/embassy-release/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "embassy-release" +version = "0.1.0" +edition = "2021" + +[dependencies] +clap = { version = "4.5.1", features = ["derive"] } +walkdir = "2.5.0" +toml = "0.8.8" +toml_edit = { version = "0.23.1", features = ["serde"] } +serde = { version = "1.0.198", features = ["derive"] } +regex = "1.10.4" diff --git a/embassy-release/src/main.rs b/embassy-release/src/main.rs new file mode 100644 index 000000000..321d3872c --- /dev/null +++ b/embassy-release/src/main.rs @@ -0,0 +1,303 @@ +use std::collections::{HashMap, HashSet}; +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::Command as ProcessCommand; + +use clap::{Parser, Subcommand, ValueEnum}; +use regex::Regex; +use serde::Deserialize; +use toml_edit::{DocumentMut, Item, Value}; +use walkdir::WalkDir; + +/// Tool to traverse and operate on intra-repo Rust crate dependencies +#[derive(Parser, Debug)] +#[command(author, version, about)] +struct Args { + /// Path to the root crate + #[arg(value_name = "CRATE_PATH")] + crate_path: PathBuf, + + /// Command to perform on each crate + #[command(subcommand)] + command: Command, + + /// Traversal order + #[arg(short, long, default_value = "post")] + order: TraversalOrder, +} + +#[derive(Debug, Clone, ValueEnum, PartialEq)] +enum TraversalOrder { + Pre, + Post, +} + +#[derive(Debug, Subcommand)] +enum Command { + /// Print all dependencies + Dependencies, + + /// Release crate + Release { + #[command(subcommand)] + kind: ReleaseKind, + }, +} + +#[derive(Debug, Subcommand, Clone, Copy, PartialEq)] +enum ReleaseKind { + Patch, + Minor, +} + +#[derive(Debug, Deserialize)] +struct CargoToml { + package: Option, + dependencies: Option, +} + +#[derive(Debug, Deserialize)] +struct Package { + name: String, + version: Option, +} + +#[derive(Debug, Deserialize)] +#[serde(untagged)] +enum Dep { + Version(String), + DetailedTable(HashMap), +} + +type Deps = std::collections::HashMap; + +#[derive(Debug, Deserialize)] +struct CrateConfig { + features: Option>, + target: Option, +} + +type ReleaseConfig = HashMap; + +fn find_path_deps(cargo_path: &Path) -> Vec { + let content = fs::read_to_string(cargo_path).unwrap_or_else(|_| { + panic!("Failed to read {:?}", cargo_path); + }); + let parsed: CargoToml = toml::from_str(&content).unwrap_or_else(|e| { + panic!("Failed to parse {:?}: {}", cargo_path, e); + }); + + let mut paths = vec![]; + if let Some(deps) = parsed.dependencies { + for (_name, dep) in deps { + match dep { + Dep::Version(_) => { + // External dependency — skip + } + Dep::DetailedTable(table) => { + if let Some(toml::Value::String(path)) = table.get("path") { + let dep_path = cargo_path.parent().unwrap().join(path).canonicalize().unwrap(); + paths.push(dep_path); + } + } + } + } + } + + paths +} + +fn visit_recursive( + root_crate: &Path, + visited: &mut HashSet, + output: &mut Vec, + order: &TraversalOrder, +) { + if !visited.insert(root_crate.to_path_buf()) { + return; + } + + let cargo_toml = root_crate.join("Cargo.toml"); + let deps = find_path_deps(&cargo_toml); + + if *order == TraversalOrder::Pre { + output.push(root_crate.to_path_buf()); + } + + let mut deps_sorted = deps; + deps_sorted.sort(); + for dep in deps_sorted { + visit_recursive(&dep, visited, output, order); + } + + if *order == TraversalOrder::Post { + output.push(root_crate.to_path_buf()); + } +} + +fn get_crate_metadata(crate_path: &Path) -> Option<(String, String)> { + let cargo_toml = crate_path.join("Cargo.toml"); + let content = fs::read_to_string(&cargo_toml).ok()?; + let parsed: CargoToml = toml::from_str(&content).ok()?; + let pkg = parsed.package?; + let name = pkg.name; + let version = pkg.version?; + Some((name, version)) +} + +fn load_release_config() -> ReleaseConfig { + let config_path = PathBuf::from("release/config.toml"); + if !config_path.exists() { + return HashMap::new(); + } + let content = fs::read_to_string(&config_path).expect("Failed to read release/config.toml"); + toml::from_str(&content).expect("Invalid TOML format in release/config.toml") +} + +fn bump_dependency_versions(crate_name: &str, new_version: &str) -> Result<(), String> { + let mut cargo_files: Vec = WalkDir::new(".") + .into_iter() + .filter_map(Result::ok) + .filter(|e| e.file_name() == "Cargo.toml") + .map(|e| e.into_path()) + .collect(); + + cargo_files.sort(); + + for path in cargo_files { + let content = fs::read_to_string(&path).map_err(|e| format!("Failed to read {}: {}", path.display(), e))?; + + let mut doc: DocumentMut = content + .parse() + .map_err(|e| format!("Failed to parse TOML in {}: {}", path.display(), e))?; + + let mut changed = false; + + for section in ["dependencies", "dev-dependencies", "build-dependencies"] { + if let Some(Item::Table(dep_table)) = doc.get_mut(section) { + if let Some(item) = dep_table.get_mut(crate_name) { + match item { + // e.g., foo = "0.1.0" + Item::Value(Value::String(_)) => { + *item = Item::Value(Value::from(new_version)); + changed = true; + } + // e.g., foo = { version = "...", ... } + Item::Value(Value::InlineTable(inline)) => { + if inline.contains_key("version") { + inline["version"] = Value::from(new_version); + changed = true; + } + } + _ => {} // Leave unusual formats untouched + } + } + } + } + + if changed { + fs::write(&path, doc.to_string()).map_err(|e| format!("Failed to write {}: {}", path.display(), e))?; + println!("🔧 Updated {} to {} in {}", crate_name, new_version, path.display()); + } + } + + Ok(()) +} + +fn run_release_command( + crate_path: &Path, + crate_name: &str, + version: &str, + kind: &ReleaseKind, + config: Option<&CrateConfig>, +) -> Result<(), String> { + let kind_str = match kind { + ReleaseKind::Patch => "patch", + ReleaseKind::Minor => "minor", + }; + + if *kind == ReleaseKind::Minor { + bump_dependency_versions(crate_name, version)?; + } + + let mut args: Vec = vec!["release".into(), kind_str.into()]; + + if let Some(cfg) = config { + if let Some(features) = &cfg.features { + args.push("--features".into()); + args.push(features.join(",")); + } + if let Some(target) = &cfg.target { + args.push("--target".into()); + args.push(target.clone()); + } + } + + let status = ProcessCommand::new("cargo") + .args(&args) + .current_dir(crate_path) + .status() + .map_err(|e| format!("Failed to run cargo release: {}", e))?; + + if !status.success() { + return Err(format!("`cargo release {}` failed in crate {}", kind_str, crate_name)); + } + + //args.push("--execute".into()); + //let status = ProcessCommand::new("cargo") + // .args(&args) + // .current_dir(crate_path) + // .status() + // .map_err(|e| format!("Failed to run cargo release --execute: {}", e))?; + + //if !status.success() { + // return Err(format!( + // "`cargo release {kind_str} --execute` failed in crate {crate_name}" + // )); + //} + + Ok(()) +} + +fn main() { + let args = Args::parse(); + let root = args.crate_path.canonicalize().expect("Invalid root crate path"); + + match args.command { + Command::Dependencies => { + let mut visited = HashSet::new(); + let mut ordered = vec![]; + visit_recursive(&root, &mut visited, &mut ordered, &args.order); + for path in ordered { + if let Some((name, _)) = get_crate_metadata(&path) { + println!("{name}"); + } else { + eprintln!("Warning: could not read crate name from {:?}", path); + } + } + } + Command::Release { kind } => { + let config = load_release_config(); + let path = root; + match get_crate_metadata(&path) { + Some((name, version)) => { + println!("🚀 Releasing {name}..."); + let crate_cfg = config.get(&name); + match run_release_command(&path, &name, &version, &kind, crate_cfg) { + Ok(_) => { + println!("✅ Released {name}"); + } + Err(e) => { + eprintln!("❌ Error releasing {name}:\n{e}"); + eprintln!("\nYou may retry with: `cargo run -- {path:?} release {kind:?}`"); + std::process::exit(1); + } + } + } + None => { + eprintln!("Warning: Could not parse crate metadata in {:?}", path); + } + } + } + } +} diff --git a/release/config.toml b/release/config.toml new file mode 100644 index 000000000..2292f4077 --- /dev/null +++ b/release/config.toml @@ -0,0 +1 @@ +embassy-rp = { features = ["defmt", "unstable-pac", "time-driver", "rp2040"], target = "thumbv6m-none-eabi" } -- cgit From 78a333d008490a7720555abea0b1f78a693d6f76 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 3 Aug 2025 00:44:51 +0200 Subject: Release embassy-embedded-hal v0.4 --- embassy-boot/Cargo.toml | 2 +- embassy-embedded-hal/CHANGELOG.md | 12 ++++++++++++ embassy-embedded-hal/Cargo.toml | 2 +- embassy-imxrt/Cargo.toml | 2 +- embassy-mspm0/Cargo.toml | 2 +- embassy-nrf/Cargo.toml | 2 +- embassy-rp/Cargo.toml | 2 +- embassy-stm32-wpan/Cargo.toml | 2 +- embassy-stm32/Cargo.toml | 2 +- examples/boot/application/nrf/Cargo.toml | 2 +- examples/boot/application/rp/Cargo.toml | 2 +- examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wb-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wba-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wl/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- examples/stm32h7/Cargo.toml | 2 +- examples/stm32h735/Cargo.toml | 2 +- examples/stm32h755cm4/Cargo.toml | 2 +- examples/stm32h755cm7/Cargo.toml | 2 +- examples/stm32h7b0/Cargo.toml | 2 +- examples/stm32l4/Cargo.toml | 2 +- examples/stm32wl/Cargo.toml | 2 +- tests/mspm0/Cargo.toml | 2 +- tests/rp/Cargo.toml | 2 +- 31 files changed, 42 insertions(+), 30 deletions(-) diff --git a/embassy-boot/Cargo.toml b/embassy-boot/Cargo.toml index 172330ef2..4dde4a3ff 100644 --- a/embassy-boot/Cargo.toml +++ b/embassy-boot/Cargo.toml @@ -28,7 +28,7 @@ defmt = { version = "1.0.1", optional = true } digest = "0.10" log = { version = "0.4", optional = true } ed25519-dalek = { version = "2", default-features = false, features = ["digest"], optional = true } -embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal" } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embedded-storage = "0.3.1" embedded-storage-async = { version = "0.4.1" } diff --git a/embassy-embedded-hal/CHANGELOG.md b/embassy-embedded-hal/CHANGELOG.md index 04d95415c..86eab3357 100644 --- a/embassy-embedded-hal/CHANGELOG.md +++ b/embassy-embedded-hal/CHANGELOG.md @@ -8,8 +8,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.4.0 - 2025-08-03 + +- `SpiDevice` cancel safety: always set CS pin to high on drop +- Update `embassy-sync` to v0.7.0 + +## 0.3.2 - 2025-08-03 + +- Reverted changes in 0.3.1 +- Reexport `SetConfig`, `GetConfig` traits from v0.4.0. + ## 0.3.1 - 2025-07-16 +YANKED due to embassy-sync upgrade being a breaking change. + - `SpiDevice` cancel safety: always set CS pin to high on drop - Update `embassy-sync` to v0.7.0 diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index 8277aa291..25088a62d 100644 --- a/embassy-embedded-hal/Cargo.toml +++ b/embassy-embedded-hal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-embedded-hal" -version = "0.3.1" +version = "0.4.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Collection of utilities to use `embedded-hal` and `embedded-storage` traits with Embassy." diff --git a/embassy-imxrt/Cargo.toml b/embassy-imxrt/Cargo.toml index 8c3fa6492..0453ab4a0 100644 --- a/embassy-imxrt/Cargo.toml +++ b/embassy-imxrt/Cargo.toml @@ -68,7 +68,7 @@ embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", option embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.4", path = "../embassy-time", optional = true } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } -embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } +embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal", default-features = false } embassy-futures = { version = "0.1.1", path = "../embassy-futures" } defmt = { version = "1.0.1", optional = true } diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index 0eb8237b5..edd926c2b 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -32,7 +32,7 @@ embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", option embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } -embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } +embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal", default-features = false } embassy-executor = { version = "0.8.0", path = "../embassy-executor", optional = true } embedded-hal = { version = "1.0" } diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index d8579cfb6..a3df1b905 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -145,7 +145,7 @@ embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-util embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } -embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } +embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal", default-features = false } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index a1011bc4e..bb28d21c8 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -142,7 +142,7 @@ embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-util embassy-time = { version = "0.4.0", path = "../embassy-time" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } -embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal" } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } atomic-polyfill = "1.0.1" defmt = { version = "1.0.1", optional = true } diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index a16aa4b54..1f33c92cd 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -24,7 +24,7 @@ embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal" } -embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver", optional=true } defmt = { version = "1.0.1", optional = true } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 643ab7eac..535de7fc8 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -54,7 +54,7 @@ embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", option embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } -embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } +embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal", default-features = false } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } embassy-usb-synopsys-otg = { version = "0.3.0", path = "../embassy-usb-synopsys-otg" } diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 4fda710a5..31b99709e 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -11,7 +11,7 @@ embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features embassy-nrf = { version = "0.5.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } embassy-boot = { version = "0.5.0", path = "../../../../embassy-boot", features = [] } embassy-boot-nrf = { version = "0.6.0", path = "../../../../embassy-boot-nrf", features = [] } -embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index d060bc8c0..199ef52bf 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } embassy-rp = { version = "0.6.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } embassy-boot-rp = { version = "0.6.0", path = "../../../../embassy-boot-rp", features = [] } -embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index 00d435799..d3b1a4eea 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32" } -embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index ae36fc835..1f8f3c7d8 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index bf3da53b8..8d4cc98da 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 7cc10a18e..8f581fba9 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index c175f6c7f..9502a7832 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index 37735e725..d222f0260 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index ccb7d0807..1ac302a81 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb" } embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } diff --git a/examples/boot/application/stm32wba-dfu/Cargo.toml b/examples/boot/application/stm32wba-dfu/Cargo.toml index ab719e28c..dae9a2498 100644 --- a/examples/boot/application/stm32wba-dfu/Cargo.toml +++ b/examples/boot/application/stm32wba-dfu/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wba65ri", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb" } embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index 3b9d7b5d5..429bbf846 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.3.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 428d49c1a..7fa84c7ec 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] -embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal", features = ["defmt"] } +embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal", features = ["defmt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 85481069b..42d112c75 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] -embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal", features = ["defmt"] } +embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal", features = ["defmt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index a3e1327b9..5222c17dc 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml index 58dc81d2e..c219eb506 100644 --- a/examples/stm32h735/Cargo.toml +++ b/examples/stm32h735/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index ae058802c..fbda7a687 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32h755zi-cm4 to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index cc1fa302d..e3b79aa89 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml index 611b38ed8..73edd4c6e 100644 --- a/examples/stm32h7b0/Cargo.toml +++ b/examples/stm32h7b0/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 0bbb33c10..3e6671f89 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -10,7 +10,7 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } -embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net-adin1110 = { version = "0.3.0", path = "../../embassy-net-adin1110" } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] } diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index d6565502a..79b6f8110 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -10,7 +10,7 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [" embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/tests/mspm0/Cargo.toml b/tests/mspm0/Cargo.toml index 5b570ebec..6742537e5 100644 --- a/tests/mspm0/Cargo.toml +++ b/tests/mspm0/Cargo.toml @@ -16,7 +16,7 @@ embassy-executor = { version = "0.8.0", path = "../../embassy-executor", feature embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt" ] } embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = [ "rt", "defmt", "unstable-pac", "time-driver-any" ] } -embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal/"} +embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal/"} defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index ca1fa53da..1f2bbdb22 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -19,7 +19,7 @@ embassy-rp = { version = "0.6.0", path = "../../embassy-rp", features = [ "defmt embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } -embassy-embedded-hal = { version = "0.3.1", path = "../../embassy-embedded-hal/"} +embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal/"} cyw43 = { path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { path = "../../cyw43-pio", features = ["defmt"] } perf-client = { path = "../perf-client" } -- cgit From 65bab430a6a64a7212f4bc83ddd92f986a06d712 Mon Sep 17 00:00:00 2001 From: Phirks Date: Sun, 3 Aug 2025 08:37:58 -0400 Subject: removed the rp2040 flag from the dormant function --- embassy-rp/src/clocks.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index d79bffab3..2eddc0bcc 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -63,7 +63,6 @@ //! // Set other parameters as needed... //! ``` -#[cfg(feature = "rp2040")] use core::arch::asm; use core::marker::PhantomData; #[cfg(feature = "rp2040")] @@ -73,7 +72,6 @@ use core::sync::atomic::{AtomicU32, Ordering}; use pac::clocks::vals::*; use crate::gpio::{AnyPin, SealedPin}; -#[cfg(feature = "rp2040")] use crate::pac::common::{Reg, RW}; use crate::{pac, reset, Peri}; @@ -1844,7 +1842,7 @@ impl rand_core_09::CryptoRng for RoscRng {} /// and can only be exited through resets, dormant-wake GPIO interrupts, /// and RTC interrupts. If RTC is clocked from an internal clock source /// it will be stopped and not function as a wakeup source. -#[cfg(all(target_arch = "arm", feature = "rp2040"))] +#[cfg(all(target_arch = "arm"))] pub fn dormant_sleep() { struct Set(Reg, T, F); -- cgit From 7c640799d66f82f9936f6378cc5dd9856953662e Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Mon, 21 Jul 2025 14:12:48 +0200 Subject: mspm0: Add I2C Controller (blocking & async) - lib: add i2c mod to lib - lib: add `bind_interrupts` mod for async workflow - lib: set SYSOSCBASE as system oscillator - config: add I2C SDA,SCA pin traits code generation - config: add clock source for the I2C - config: add clock divider for the I2C - config: add I2C BusSpeed configuration - I2C: add blocking API: blocking_read, blocking_write, blocking_write_read - I2C: add async API: async_write, async_read, async_write_read - I2C: add embedded-hal (v0.2) API for blocking & async impl. - I2C: add embedded-hal (v1.0) API for blocking & async impl. - I2C-tests: checks for timer_period & check_clock_rate fn's --- embassy-mspm0/Cargo.toml | 1 + embassy-mspm0/build.rs | 4 + embassy-mspm0/src/i2c.rs | 1156 ++++++++++++++++++++++++++++++++++++++++++++++ embassy-mspm0/src/lib.rs | 5 + 4 files changed, 1166 insertions(+) create mode 100644 embassy-mspm0/src/i2c.rs diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index d2adc63d7..e8fb2e9a9 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -35,6 +35,7 @@ embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", fe embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false } embassy-executor = { version = "0.7.0", path = "../embassy-executor", optional = true } +embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal = { version = "1.0" } embedded-hal-async = { version = "1.0" } diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs index b9ba3aecf..328db3926 100644 --- a/embassy-mspm0/build.rs +++ b/embassy-mspm0/build.rs @@ -552,6 +552,7 @@ fn generate_peripheral_instances() -> TokenStream { let tokens = match peripheral.kind { "uart" => Some(quote! { impl_uart_instance!(#peri); }), + "i2c" => Some(quote! { impl_i2c_instance!(#peri); }), _ => None, }; @@ -598,6 +599,9 @@ fn generate_pin_trait_impls() -> TokenStream { ("uart", "RX") => Some(quote! { impl_uart_rx_pin!(#peri, #pin_name, #pf); }), ("uart", "CTS") => Some(quote! { impl_uart_cts_pin!(#peri, #pin_name, #pf); }), ("uart", "RTS") => Some(quote! { impl_uart_rts_pin!(#peri, #pin_name, #pf); }), + ("i2c", "SDA") => Some(quote! { impl_i2c_sda_pin!(#peri, #pin_name, #pf); }), + ("i2c", "SCL") => Some(quote! { impl_i2c_scl_pin!(#peri, #pin_name, #pf); }), + _ => None, }; diff --git a/embassy-mspm0/src/i2c.rs b/embassy-mspm0/src/i2c.rs new file mode 100644 index 000000000..168cfccda --- /dev/null +++ b/embassy-mspm0/src/i2c.rs @@ -0,0 +1,1156 @@ +#![macro_use] + +use core::future; +use core::marker::PhantomData; +use core::sync::atomic::{AtomicU32, Ordering}; +use core::task::Poll; + +use embassy_embedded_hal::SetConfig; +use embassy_hal_internal::PeripheralType; +use embassy_sync::waitqueue::AtomicWaker; +use mspm0_metapac::i2c; + +use crate::gpio::{AnyPin, PfType, Pull, SealedPin}; +use crate::interrupt::typelevel::Binding; +use crate::interrupt::{Interrupt, InterruptExt}; +use crate::mode::{Async, Blocking, Mode}; +use crate::pac::i2c::{vals, I2c as Regs}; +use crate::pac::{self}; +use crate::Peri; + +/// The clock source for the I2C. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ClockSel { + /// Use the bus clock. + /// + /// By default the BusClk runs at 32 MHz. + BusClk, + + /// Use the middle frequency clock. + /// + /// The MCLK runs at 4 MHz. + MfClk, + // BusClk, + // BusClk depends on the timer's power domain. + // This will be implemented later. +} + +/// The clock divider for the I2C. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ClockDiv { + // "Do not divide clock source. + DivBy1, + // "Divide clock source by 2. + DivBy2, + // "Divide clock source by 3. + DivBy3, + // "Divide clock source by 4. + DivBy4, + // "Divide clock source by 5. + DivBy5, + // "Divide clock source by 6. + DivBy6, + // "Divide clock source by 7. + DivBy7, + // "Divide clock source by 8. + DivBy8, +} + +impl Into for ClockDiv { + fn into(self) -> vals::Ratio { + match self { + Self::DivBy1 => vals::Ratio::DIV_BY_1, + Self::DivBy2 => vals::Ratio::DIV_BY_2, + Self::DivBy3 => vals::Ratio::DIV_BY_3, + Self::DivBy4 => vals::Ratio::DIV_BY_4, + Self::DivBy5 => vals::Ratio::DIV_BY_5, + Self::DivBy6 => vals::Ratio::DIV_BY_6, + Self::DivBy7 => vals::Ratio::DIV_BY_7, + Self::DivBy8 => vals::Ratio::DIV_BY_8, + } + } +} + +impl ClockDiv { + fn divider(self) -> u32 { + match self { + Self::DivBy1 => 1, + Self::DivBy2 => 2, + Self::DivBy3 => 3, + Self::DivBy4 => 4, + Self::DivBy5 => 5, + Self::DivBy6 => 6, + Self::DivBy7 => 7, + Self::DivBy8 => 8, + } + } +} + +/// The I2C mode. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum BusSpeed { + /// Standard mode. + /// + /// The Standard mode runs at 100 kHz. + Standard, + + /// Fast mode. + /// + /// The fast mode runs at 400 kHz. + FastMode, + + /// Fast mode plus. + /// + /// The fast mode plus runs at 1 MHz. + FastModePlus, + + /// Custom mode. + /// + /// The custom mode frequency (in Hz) can be set manually. + Custom(u32), +} + +impl BusSpeed { + fn hertz(self) -> u32 { + match self { + Self::Standard => 100_000, + Self::FastMode => 400_000, + Self::FastModePlus => 1_000_000, + Self::Custom(s) => s, + } + } +} + +#[non_exhaustive] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// Config Error +pub enum ConfigError { + /// The clock rate could not be configured with the given conifguratoin. + InvalidClockRate, +} + +#[non_exhaustive] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +/// Config +pub struct Config { + /// I2C clock source. + pub clock_source: ClockSel, + + /// I2C clock divider. + pub clock_div: ClockDiv, + + /// If true: invert SDA pin signal values (VDD = 0/mark, Gnd = 1/idle). + pub invert_sda: bool, + + /// If true: invert SCL pin signal values (VDD = 0/mark, Gnd = 1/idle). + pub invert_scl: bool, + + /// Set the pull configuration for the SDA pin. + pub sda_pull: Pull, + + /// Set the pull configuration for the SCL pin. + pub scl_pull: Pull, + + /// Set the pull configuration for the SCL pin. + pub bus_speed: BusSpeed, +} + +impl Default for Config { + fn default() -> Self { + Self { + clock_source: ClockSel::BusClk, + clock_div: ClockDiv::DivBy1, + invert_sda: false, + invert_scl: false, + sda_pull: Pull::None, + scl_pull: Pull::None, + bus_speed: BusSpeed::FastMode, + } + } +} + +impl Config { + pub fn sda_pf(&self) -> PfType { + PfType::input(self.sda_pull, self.invert_sda) + } + pub fn scl_pf(&self) -> PfType { + PfType::input(self.scl_pull, self.invert_scl) + } + fn timer_period(&self, clock_speed: u32) -> u8 { + // Sets the timer period to bring the clock frequency to the selected I2C speed + // From the documentation: SCL_PERIOD = (1 + TPR ) * (SCL_LP + SCL_HP ) * INT_CLK_PRD where: + // - SCL_PRD is the SCL line period (I2C clock) + // - TPR is the Timer Period register value (range of 1 to 127) + // - SCL_LP is the SCL Low period (fixed at 6) + // - SCL_HP is the SCL High period (fixed at 4) + // - CLK_PRD is the functional clock period in ns + let scl_period = (1.0 / self.bus_speed.hertz() as f64) * 1_000_000_000.0; + let clock = (clock_speed as f64) / self.clock_div.divider() as f64; + let clk_period = (1.0 / clock) * 1_000_000_000.0; + let tpr = scl_period / (10.0 * clk_period) - 1.0; + tpr.clamp(0.0, 255.0) as u8 + } + + #[cfg(any(mspm0c110x))] + pub fn calculate_clock_rate(&self) -> u32 { + // Assume that BusClk has default value. + // TODO: calculate BusClk more precisely. + match self.clock_source { + ClockSel::MfClk => 4_000_000, + ClockSel::BusClk => 24_000_000, + } + } + + #[cfg(any( + mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x, mspm0l110x, mspm0l122x, mspm0l130x, + mspm0l134x, mspm0l222x + ))] + pub fn calculate_clock_rate(&self) -> u32 { + // Assume that BusClk has default value. + // TODO: calculate BusClk more precisely. + match self.clock_source { + ClockSel::MfClk => 4_000_000, + ClockSel::BusClk => 32_000_000, + } + } + + pub fn check_clock_rate(&self) -> bool { + // make sure source clock is ~20 faster than i2c clock + let clk_ratio = 20; + + let i2c_clk = self.bus_speed.hertz() / self.clock_div.divider(); + let src_clk = self.calculate_clock_rate(); + + // check clock rate + return src_clk >= clk_ratio * i2c_clk; + } +} + +/// Serial error +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub enum Error { + /// Bus error + Bus, + + /// Arbitration lost + Arbitration, + + /// ACK not received (either to the address or to a data byte) + Nack, + + /// Timeout + Timeout, + + /// CRC error + Crc, + + /// Overrun error + Overrun, + + /// Zero-length transfers are not allowed. + ZeroLengthTransfer, +} + +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let message = match self { + Self::Bus => "Bus Error", + Self::Arbitration => "Arbitration Lost", + Self::Nack => "ACK Not Received", + Self::Timeout => "Request Timed Out", + Self::Crc => "CRC Mismatch", + Self::Overrun => "Buffer Overrun", + Self::ZeroLengthTransfer => "Zero-Length Transfers are not allowed", + }; + + write!(f, "{}", message) + } +} + +impl core::error::Error for Error {} + +/// mspm0g, mspm0c, mspm0l, msps00 have 8-bytes FIFO +pub const FIFO_SIZE: usize = 8; + +/// I2C Driver. +pub struct I2c<'d, M: Mode> { + info: &'static Info, + state: &'static State, + scl: Option>, + sda: Option>, + _phantom: PhantomData, +} + +impl<'d, M: Mode> SetConfig for I2c<'d, M> { + type Config = Config; + type ConfigError = ConfigError; + + fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { + self.set_config(config) + } +} + +impl<'d> I2c<'d, Blocking> { + pub fn new_blocking( + peri: Peri<'d, T>, + scl: Peri<'d, impl SclPin>, + sda: Peri<'d, impl SdaPin>, + config: Config, + ) -> Result { + if !config.check_clock_rate() { + return Err(ConfigError::InvalidClockRate); + } + + Self::new_inner(peri, scl, sda, config) + } +} + +impl<'d> I2c<'d, Async> { + pub fn new_async( + peri: Peri<'d, T>, + scl: Peri<'d, impl SclPin>, + sda: Peri<'d, impl SdaPin>, + _irq: impl Binding> + 'd, + config: Config, + ) -> Result { + if !config.check_clock_rate() { + return Err(ConfigError::InvalidClockRate); + } + + let i2c = Self::new_inner(peri, scl, sda, config); + + T::info().interrupt.unpend(); + unsafe { T::info().interrupt.enable() }; + + i2c + } +} + +impl<'d, M: Mode> I2c<'d, M> { + /// Reconfigure the driver + pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { + if !config.check_clock_rate() { + return Err(ConfigError::InvalidClockRate); + } + + self.info.interrupt.disable(); + + if let Some(ref sda) = self.sda { + sda.update_pf(config.sda_pf()); + } + + if let Some(ref scl) = self.scl { + scl.update_pf(config.scl_pf()); + } + + self.init(config) + } + + fn init(&mut self, config: &Config) -> Result<(), ConfigError> { + // Init I2C + self.info.regs.clksel().write(|w| match config.clock_source { + ClockSel::BusClk => { + w.set_mfclk_sel(false); + w.set_busclk_sel(true); + } + ClockSel::MfClk => { + w.set_mfclk_sel(true); + w.set_busclk_sel(false); + } + }); + self.info.regs.clkdiv().write(|w| w.set_ratio(config.clock_div.into())); + + // set up glitch filter + self.info.regs.gfctl().modify(|w| { + w.set_agfen(false); + w.set_agfsel(vals::Agfsel::AGLIT_50); + w.set_chain(true); + }); + + // Reset controller transfer, follow TI example + self.info + .regs + .controller(0) + .cctr() + .write_value(i2c::regs::Cctr::default()); + + let clock = config.calculate_clock_rate(); + + self.state.clock.store(clock, Ordering::Relaxed); + + self.info + .regs + .controller(0) + .ctpr() + .write(|w| w.set_tpr(config.timer_period(clock))); + + // Set Tx Fifo threshold, follow TI example + self.info + .regs + .controller(0) + .cfifoctl() + .write(|w| w.set_txtrig(vals::CfifoctlTxtrig::EMPTY)); + // Set Rx Fifo threshold, follow TI example + self.info + .regs + .controller(0) + .cfifoctl() + .write(|w| w.set_rxtrig(vals::CfifoctlRxtrig::LEVEL_1)); + // Enable controller clock stretching, follow TI example + + self.info.regs.controller(0).ccr().modify(|w| { + w.set_clkstretch(true); + w.set_active(true); + }); + + Ok(()) + } + + fn master_stop(&mut self) { + // not the first transaction, delay 1000 cycles + cortex_m::asm::delay(1000); + + // Stop transaction + self.info.regs.controller(0).cctr().modify(|w| { + w.set_cblen(0); + w.set_stop(true); + w.set_start(false); + }); + } + + fn master_continue(&mut self, length: usize, send_ack_nack: bool, send_stop: bool) -> Result<(), Error> { + assert!(length <= FIFO_SIZE && length > 0); + + // delay between ongoing transactions, 1000 cycles + cortex_m::asm::delay(1000); + + // Update transaction to length amount of bytes + self.info.regs.controller(0).cctr().modify(|w| { + w.set_cblen(length as u16); + w.set_start(false); + w.set_ack(send_ack_nack); + if send_stop { + w.set_stop(true); + } + }); + + Ok(()) + } + + fn master_read( + &mut self, + address: u8, + length: usize, + restart: bool, + send_ack_nack: bool, + send_stop: bool, + ) -> Result<(), Error> { + if restart { + // not the first transaction, delay 1000 cycles + cortex_m::asm::delay(1000); + } + + // Set START and prepare to receive bytes into + // `buffer`. The START bit can be set even if the bus + // is BUSY or I2C is in slave mode. + self.info.regs.controller(0).csa().modify(|w| { + w.set_taddr(address as u16); + w.set_cmode(vals::Mode::MODE7); + w.set_dir(vals::Dir::RECEIVE); + }); + + self.info.regs.controller(0).cctr().modify(|w| { + w.set_cblen(length as u16); + w.set_burstrun(true); + w.set_ack(send_ack_nack); + w.set_start(true); + if send_stop { + w.set_stop(true); + } + }); + + Ok(()) + } + + fn master_write(&mut self, address: u8, length: usize, send_stop: bool) -> Result<(), Error> { + assert!(length <= FIFO_SIZE && length > 0); + + // Start transfer of length amount of bytes + self.info.regs.controller(0).csa().modify(|w| { + w.set_taddr(address as u16); + w.set_cmode(vals::Mode::MODE7); + w.set_dir(vals::Dir::TRANSMIT); + }); + self.info.regs.controller(0).cctr().modify(|w| { + w.set_cblen(length as u16); + w.set_burstrun(true); + w.set_start(true); + if send_stop { + w.set_stop(true); + } + }); + + Ok(()) + } + + fn check_error(&self) -> Result<(), Error> { + let csr = self.info.regs.controller(0).csr().read(); + if csr.err() { + return Err(Error::Nack); + } else if csr.arblst() { + return Err(Error::Arbitration); + } + Ok(()) + } +} + +impl<'d> I2c<'d, Blocking> { + fn master_blocking_continue(&mut self, length: usize, send_ack_nack: bool, send_stop: bool) -> Result<(), Error> { + // Perform transaction + self.master_continue(length, send_ack_nack, send_stop)?; + + // Poll until the Controller process all bytes or NACK + while self.info.regs.controller(0).csr().read().busy() {} + + Ok(()) + } + + fn master_blocking_read( + &mut self, + address: u8, + length: usize, + restart: bool, + send_ack_nack: bool, + send_stop: bool, + ) -> Result<(), Error> { + assert!(length <= FIFO_SIZE && length > 0); + + // unless restart, Wait for the controller to be idle, + if !restart { + while !self.info.regs.controller(0).csr().read().idle() {} + } + + self.master_read(address, length, restart, send_ack_nack, send_stop)?; + + // Poll until the Controller process all bytes or NACK + while self.info.regs.controller(0).csr().read().busy() {} + + Ok(()) + } + + fn master_blocking_write(&mut self, address: u8, length: usize, send_stop: bool) -> Result<(), Error> { + // Wait for the controller to be idle + while !self.info.regs.controller(0).csr().read().idle() {} + + // Perform writing + self.master_write(address, length, send_stop)?; + + // Poll until the Controller writes all bytes or NACK + while self.info.regs.controller(0).csr().read().busy() {} + + Ok(()) + } + + fn read_blocking_internal( + &mut self, + address: u8, + read: &mut [u8], + restart: bool, + end_w_stop: bool, + ) -> Result<(), Error> { + let read_len = read.len(); + + let mut bytes_to_read = read_len; + for (number, chunk) in read.chunks_mut(FIFO_SIZE).enumerate() { + bytes_to_read -= chunk.len(); + // if the current transaction is the last & end_w_stop, send stop + let send_stop = bytes_to_read == 0 && end_w_stop; + // if there are still bytes to read, send ACK + let send_ack_nack = bytes_to_read != 0; + + if number == 0 { + self.master_blocking_read(address, chunk.len().min(FIFO_SIZE), restart, send_ack_nack, send_stop)? + } else { + self.master_blocking_continue(chunk.len(), send_ack_nack, send_stop)?; + } + + // check errors + if let Err(err) = self.check_error() { + self.master_stop(); + return Err(err); + } + + for byte in chunk { + *byte = self.info.regs.controller(0).crxdata().read().value(); + } + } + Ok(()) + } + + fn write_blocking_internal(&mut self, address: u8, write: &[u8], end_w_stop: bool) -> Result<(), Error> { + if write.is_empty() { + return Err(Error::ZeroLengthTransfer); + } + + let mut bytes_to_send = write.len(); + for (number, chunk) in write.chunks(FIFO_SIZE).enumerate() { + for byte in chunk { + let ctrl0 = self.info.regs.controller(0).ctxdata(); + ctrl0.write(|w| w.set_value(*byte)); + } + + // if the current transaction is the last & end_w_stop, send stop + bytes_to_send -= chunk.len(); + let send_stop = end_w_stop && bytes_to_send == 0; + + if number == 0 { + self.master_blocking_write(address, chunk.len(), send_stop)?; + } else { + self.master_blocking_continue(chunk.len(), false, send_stop)?; + } + + // check errors + if let Err(err) = self.check_error() { + self.master_stop(); + return Err(err); + } + } + Ok(()) + } + + // ========================= + // Blocking public API + + /// Blocking read. + pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { + // wait until bus is free + while self.info.regs.controller(0).csr().read().busbsy() {} + self.read_blocking_internal(address, read, false, true) + } + + /// Blocking write. + pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { + // wait until bus is free + while self.info.regs.controller(0).csr().read().busbsy() {} + self.write_blocking_internal(address, write, true) + } + + /// Blocking write, restart, read. + pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { + // wait until bus is free + while self.info.regs.controller(0).csr().read().busbsy() {} + let err = self.write_blocking_internal(address, write, false); + if err != Ok(()) { + return err; + } + self.read_blocking_internal(address, read, true, true) + } +} + +impl<'d> I2c<'d, Async> { + async fn write_async_internal(&mut self, addr: u8, write: &[u8], end_w_stop: bool) -> Result<(), Error> { + let ctrl = self.info.regs.controller(0); + + let mut bytes_to_send = write.len(); + for (number, chunk) in write.chunks(FIFO_SIZE).enumerate() { + self.info.regs.cpu_int(0).imask().modify(|w| { + w.set_carblost(true); + w.set_cnack(true); + w.set_ctxdone(true); + }); + + for byte in chunk { + ctrl.ctxdata().write(|w| w.set_value(*byte)); + } + + // if the current transaction is the last & end_w_stop, send stop + bytes_to_send -= chunk.len(); + let send_stop = end_w_stop && bytes_to_send == 0; + + if number == 0 { + self.master_write(addr, chunk.len(), send_stop)?; + } else { + self.master_continue(chunk.len(), false, send_stop)?; + } + + let res: Result<(), Error> = future::poll_fn(|cx| { + use crate::i2c::vals::CpuIntIidxStat; + // Register prior to checking the condition + self.state.waker.register(cx.waker()); + + let result = match self.info.regs.cpu_int(0).iidx().read().stat() { + CpuIntIidxStat::NO_INTR => Poll::Pending, + CpuIntIidxStat::CNACKFG => Poll::Ready(Err(Error::Nack)), + CpuIntIidxStat::CARBLOSTFG => Poll::Ready(Err(Error::Arbitration)), + CpuIntIidxStat::CTXDONEFG => Poll::Ready(Ok(())), + _ => Poll::Pending, + }; + + if !result.is_pending() { + self.info + .regs + .cpu_int(0) + .imask() + .write_value(i2c::regs::CpuInt::default()); + } + return result; + }) + .await; + + if res.is_err() { + self.master_stop(); + return res; + } + } + Ok(()) + } + + async fn read_async_internal( + &mut self, + addr: u8, + read: &mut [u8], + restart: bool, + end_w_stop: bool, + ) -> Result<(), Error> { + let read_len = read.len(); + + let mut bytes_to_read = read_len; + for (number, chunk) in read.chunks_mut(FIFO_SIZE).enumerate() { + bytes_to_read -= chunk.len(); + // if the current transaction is the last & end_w_stop, send stop + let send_stop = bytes_to_read == 0 && end_w_stop; + // if there are still bytes to read, send ACK + let send_ack_nack = bytes_to_read != 0; + + self.info.regs.cpu_int(0).imask().modify(|w| { + w.set_carblost(true); + w.set_cnack(true); + w.set_crxdone(true); + }); + + if number == 0 { + self.master_read(addr, chunk.len(), restart, send_ack_nack, send_stop)? + } else { + self.master_continue(chunk.len(), send_ack_nack, send_stop)?; + } + + let res: Result<(), Error> = future::poll_fn(|cx| { + use crate::i2c::vals::CpuIntIidxStat; + // Register prior to checking the condition + self.state.waker.register(cx.waker()); + + let result = match self.info.regs.cpu_int(0).iidx().read().stat() { + CpuIntIidxStat::NO_INTR => Poll::Pending, + CpuIntIidxStat::CNACKFG => Poll::Ready(Err(Error::Nack)), + CpuIntIidxStat::CARBLOSTFG => Poll::Ready(Err(Error::Arbitration)), + CpuIntIidxStat::CRXDONEFG => Poll::Ready(Ok(())), + _ => Poll::Pending, + }; + + if !result.is_pending() { + self.info + .regs + .cpu_int(0) + .imask() + .write_value(i2c::regs::CpuInt::default()); + } + return result; + }) + .await; + + if res.is_err() { + self.master_stop(); + return res; + } + + for byte in chunk { + *byte = self.info.regs.controller(0).crxdata().read().value(); + } + } + Ok(()) + } + + // ========================= + // Async public API + + pub async fn async_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { + // wait until bus is free + while self.info.regs.controller(0).csr().read().busbsy() {} + self.write_async_internal(address, write, true).await + } + + pub async fn async_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { + // wait until bus is free + while self.info.regs.controller(0).csr().read().busbsy() {} + self.read_async_internal(address, read, false, true).await + } + + pub async fn async_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { + // wait until bus is free + while self.info.regs.controller(0).csr().read().busbsy() {} + + let err = self.write_async_internal(address, write, false).await; + if err != Ok(()) { + return err; + } + self.read_async_internal(address, read, true, true).await + } +} + +impl<'d> embedded_hal_02::blocking::i2c::Read for I2c<'d, Blocking> { + type Error = Error; + + fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_read(address, buffer) + } +} + +impl<'d> embedded_hal_02::blocking::i2c::Write for I2c<'d, Blocking> { + type Error = Error; + + fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(address, bytes) + } +} + +impl<'d> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, Blocking> { + type Error = Error; + + fn write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_write_read(address, bytes, buffer) + } +} + +impl<'d> embedded_hal_02::blocking::i2c::Transactional for I2c<'d, Blocking> { + type Error = Error; + + fn exec( + &mut self, + address: u8, + operations: &mut [embedded_hal_02::blocking::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + // wait until bus is free + while self.info.regs.controller(0).csr().read().busbsy() {} + for i in 0..operations.len() { + match &mut operations[i] { + embedded_hal_02::blocking::i2c::Operation::Read(buf) => { + self.read_blocking_internal(address, buf, false, false)? + } + embedded_hal_02::blocking::i2c::Operation::Write(buf) => { + self.write_blocking_internal(address, buf, false)? + } + } + } + self.master_stop(); + Ok(()) + } +} + +impl embedded_hal::i2c::Error for Error { + fn kind(&self) -> embedded_hal::i2c::ErrorKind { + match *self { + Self::Bus => embedded_hal::i2c::ErrorKind::Bus, + Self::Arbitration => embedded_hal::i2c::ErrorKind::ArbitrationLoss, + Self::Nack => embedded_hal::i2c::ErrorKind::NoAcknowledge(embedded_hal::i2c::NoAcknowledgeSource::Unknown), + Self::Timeout => embedded_hal::i2c::ErrorKind::Other, + Self::Crc => embedded_hal::i2c::ErrorKind::Other, + Self::Overrun => embedded_hal::i2c::ErrorKind::Overrun, + Self::ZeroLengthTransfer => embedded_hal::i2c::ErrorKind::Other, + } + } +} + +impl<'d, M: Mode> embedded_hal::i2c::ErrorType for I2c<'d, M> { + type Error = Error; +} + +impl<'d> embedded_hal::i2c::I2c for I2c<'d, Blocking> { + fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_read(address, read) + } + + fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(address, write) + } + + fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_write_read(address, write, read) + } + + fn transaction( + &mut self, + address: u8, + operations: &mut [embedded_hal::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + // wait until bus is free + while self.info.regs.controller(0).csr().read().busbsy() {} + for i in 0..operations.len() { + match &mut operations[i] { + embedded_hal::i2c::Operation::Read(buf) => self.read_blocking_internal(address, buf, false, false)?, + embedded_hal::i2c::Operation::Write(buf) => self.write_blocking_internal(address, buf, false)?, + } + } + self.master_stop(); + Ok(()) + } +} + +impl<'d> embedded_hal_async::i2c::I2c for I2c<'d, Async> { + async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { + self.async_read(address, read).await + } + + async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { + self.async_write(address, write).await + } + + async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { + self.async_write_read(address, write, read).await + } + + async fn transaction( + &mut self, + address: u8, + operations: &mut [embedded_hal::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + // wait until bus is free + while self.info.regs.controller(0).csr().read().busbsy() {} + for i in 0..operations.len() { + match &mut operations[i] { + embedded_hal::i2c::Operation::Read(buf) => self.read_async_internal(address, buf, false, false).await?, + embedded_hal::i2c::Operation::Write(buf) => self.write_async_internal(address, buf, false).await?, + } + } + self.master_stop(); + Ok(()) + } +} + +/// Interrupt handler. +pub struct InterruptHandler { + _i2c: PhantomData, +} + +impl crate::interrupt::typelevel::Handler for InterruptHandler { + // Mask interrupts and wake any task waiting for this interrupt + unsafe fn on_interrupt() { + T::state().waker.wake(); + } +} + +/// Peripheral instance trait. +#[allow(private_bounds)] +pub trait Instance: SealedInstance + PeripheralType { + type Interrupt: crate::interrupt::typelevel::Interrupt; +} + +/// I2C `SDA` pin trait +pub trait SdaPin: crate::gpio::Pin { + /// Get the PF number needed to use this pin as `SDA`. + fn pf_num(&self) -> u8; +} + +/// I2C `SCL` pin trait +pub trait SclPin: crate::gpio::Pin { + /// Get the PF number needed to use this pin as `SCL`. + fn pf_num(&self) -> u8; +} + +// ==== IMPL types ==== + +pub(crate) struct Info { + pub(crate) regs: Regs, + pub(crate) interrupt: Interrupt, +} + +pub(crate) struct State { + /// The clock rate of the I2C. This might be configured. + pub(crate) clock: AtomicU32, + pub(crate) waker: AtomicWaker, +} + +impl<'d, M: Mode> I2c<'d, M> { + fn new_inner( + _peri: Peri<'d, T>, + scl: Peri<'d, impl SclPin>, + sda: Peri<'d, impl SdaPin>, + config: Config, + ) -> Result { + // Init power for I2C + T::info().regs.gprcm(0).rstctl().write(|w| { + w.set_resetstkyclr(true); + w.set_resetassert(true); + w.set_key(vals::ResetKey::KEY); + }); + + T::info().regs.gprcm(0).pwren().write(|w| { + w.set_enable(true); + w.set_key(vals::PwrenKey::KEY); + }); + + // init delay, 16 cycles + cortex_m::asm::delay(16); + + // Init GPIO + let scl_inner = new_pin!(scl, config.scl_pf()); + let sda_inner = new_pin!(sda, config.sda_pf()); + + if let Some(ref scl) = scl_inner { + let pincm = pac::IOMUX.pincm(scl._pin_cm() as usize); + pincm.modify(|w| { + w.set_hiz1(true); + }); + } + + if let Some(ref sda) = sda_inner { + let pincm = pac::IOMUX.pincm(sda._pin_cm() as usize); + pincm.modify(|w| { + w.set_hiz1(true); + }); + } + + let mut this = Self { + info: T::info(), + state: T::state(), + scl: scl_inner, + sda: sda_inner, + _phantom: PhantomData, + }; + this.init(&config)?; + + Ok(this) + } +} + +pub(crate) trait SealedInstance { + fn info() -> &'static Info; + fn state() -> &'static State; +} + +macro_rules! impl_i2c_instance { + ($instance: ident) => { + impl crate::i2c::SealedInstance for crate::peripherals::$instance { + fn info() -> &'static crate::i2c::Info { + use crate::i2c::Info; + use crate::interrupt::typelevel::Interrupt; + + const INFO: Info = Info { + regs: crate::pac::$instance, + interrupt: crate::interrupt::typelevel::$instance::IRQ, + }; + &INFO + } + + fn state() -> &'static crate::i2c::State { + use crate::i2c::State; + use crate::interrupt::typelevel::Interrupt; + + static STATE: State = State { + clock: core::sync::atomic::AtomicU32::new(0), + waker: embassy_sync::waitqueue::AtomicWaker::new(), + }; + &STATE + } + } + + impl crate::i2c::Instance for crate::peripherals::$instance { + type Interrupt = crate::interrupt::typelevel::$instance; + } + }; +} + +macro_rules! impl_i2c_sda_pin { + ($instance: ident, $pin: ident, $pf: expr) => { + impl crate::i2c::SdaPin for crate::peripherals::$pin { + fn pf_num(&self) -> u8 { + $pf + } + } + }; +} + +macro_rules! impl_i2c_scl_pin { + ($instance: ident, $pin: ident, $pf: expr) => { + impl crate::i2c::SclPin for crate::peripherals::$pin { + fn pf_num(&self) -> u8 { + $pf + } + } + }; +} + +#[cfg(test)] +mod tests { + use crate::i2c::{BusSpeed, ClockDiv, ClockSel, Config}; + + /// These tests are based on TI's reference caluclation. + #[test] + fn ti_timer_period() { + let mut config = Config::default(); + config.clock_div = ClockDiv::DivBy1; + config.bus_speed = BusSpeed::FastMode; + assert!(matches!(config.timer_period(32_000_000), 7)); + } + + #[test] + fn ti_timer_period_2() { + let mut config = Config::default(); + config.clock_div = ClockDiv::DivBy2; + config.bus_speed = BusSpeed::FastMode; + assert!(matches!(config.timer_period(32_000_000), 3)); + } + + #[test] + fn ti_timer_period_3() { + let mut config = Config::default(); + config.clock_div = ClockDiv::DivBy2; + config.bus_speed = BusSpeed::Standard; + assert!(matches!(config.timer_period(32_000_000), 15)); + } + + #[test] + fn ti_timer_period_4() { + let mut config = Config::default(); + config.clock_div = ClockDiv::DivBy2; + config.bus_speed = BusSpeed::Custom(100_000); + assert!(matches!(config.timer_period(32_000_000), 15)); + } + + #[test] + fn clock_check_fastmodeplus_rate_with_busclk() { + let mut config = Config::default(); + config.clock_source = ClockSel::BusClk; + config.bus_speed = BusSpeed::FastModePlus; + assert!(config.check_clock_rate()); + } + + #[test] + fn clock_check_fastmode_rate_with_busclk() { + let mut config = Config::default(); + config.clock_source = ClockSel::BusClk; + config.bus_speed = BusSpeed::FastMode; + assert!(config.check_clock_rate()); + } + + #[test] + fn clock_check_fastmodeplus_rate_with_mfclk() { + let mut config = Config::default(); + config.clock_source = ClockSel::MfClk; + config.bus_speed = BusSpeed::FastModePlus; + assert!(!config.check_clock_rate()); + } + + #[test] + fn clock_check_fastmode_rate_with_mfclk() { + let mut config = Config::default(); + config.clock_source = ClockSel::MfClk; + config.bus_speed = BusSpeed::FastMode; + assert!(!config.check_clock_rate()); + } +} diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index bb8d91403..403f9d50c 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -15,6 +15,7 @@ mod macros; pub mod dma; pub mod gpio; +pub mod i2c; pub mod timer; pub mod uart; @@ -179,6 +180,10 @@ pub fn init(config: Config) -> Peripherals { w.set_mfpclken(true); }); + pac::SYSCTL.sysosccfg().modify(|w| { + w.set_freq(pac::sysctl::vals::SysosccfgFreq::SYSOSCBASE); + }); + pac::SYSCTL.borthreshold().modify(|w| { w.set_level(0); }); -- cgit From f9753f3d314ca00fb36103fa39b0911d3e3047ba Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Mon, 21 Jul 2025 14:22:32 +0200 Subject: mspm0: Add I2C Controller examples for mspm0l1306, mspm0g3507 MCUs - mspm0l1306 examples: add I2C blocking & async examples - mspm0l1306 examples: add -O2 optimization due to Flash limitations - mspm0g3507 examples: add I2C blocking & async examples --- examples/mspm0g3507/src/bin/i2c.rs | 37 +++++++++++++++++++++++++++ examples/mspm0g3507/src/bin/i2c_async.rs | 43 ++++++++++++++++++++++++++++++++ examples/mspm0l1306/Cargo.toml | 4 +++ examples/mspm0l1306/src/bin/i2c.rs | 37 +++++++++++++++++++++++++++ examples/mspm0l1306/src/bin/i2c_async.rs | 43 ++++++++++++++++++++++++++++++++ 5 files changed, 164 insertions(+) create mode 100644 examples/mspm0g3507/src/bin/i2c.rs create mode 100644 examples/mspm0g3507/src/bin/i2c_async.rs create mode 100644 examples/mspm0l1306/src/bin/i2c.rs create mode 100644 examples/mspm0l1306/src/bin/i2c_async.rs diff --git a/examples/mspm0g3507/src/bin/i2c.rs b/examples/mspm0g3507/src/bin/i2c.rs new file mode 100644 index 000000000..752649dbc --- /dev/null +++ b/examples/mspm0g3507/src/bin/i2c.rs @@ -0,0 +1,37 @@ +//! Example of using blocking I2C +//! +//! This uses the virtual COM port provided on the LP-MSPM0G3507 board. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_mspm0::i2c::{BusSpeed, ClockSel, Config, I2c}; +use {defmt_rtt as _, panic_halt as _}; + +const ADDRESS: u8 = 0x6a; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let p = embassy_mspm0::init(Default::default()); + + let instance = p.I2C1; + let scl = p.PB2; + let sda = p.PB3; + + let mut config = Config::default(); + config.clock_source = ClockSel::BusClk; + config.bus_speed = BusSpeed::FastMode; + let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, config)); + + let mut to_read = [0u8; 1]; + let to_write: u8 = 0x0F; + + match i2c.blocking_write_read(ADDRESS, &[to_write], &mut to_read) { + Ok(()) => info!("Register {}: {}", to_write, to_read[0]), + Err(e) => error!("I2c Error: {:?}", e), + } + + loop {} +} diff --git a/examples/mspm0g3507/src/bin/i2c_async.rs b/examples/mspm0g3507/src/bin/i2c_async.rs new file mode 100644 index 000000000..bc50a2623 --- /dev/null +++ b/examples/mspm0g3507/src/bin/i2c_async.rs @@ -0,0 +1,43 @@ +//! Example of using async I2C +//! +//! This uses the virtual COM port provided on the LP-MSPM0G3507 board. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_mspm0::bind_interrupts; +use embassy_mspm0::i2c::{BusSpeed, ClockSel, Config, I2c, InterruptHandler}; +use embassy_mspm0::peripherals::I2C1; +use {defmt_rtt as _, panic_halt as _}; + +const ADDRESS: u8 = 0x6a; + +bind_interrupts!(struct Irqs { + I2C1 => InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let p = embassy_mspm0::init(Default::default()); + + let instance = p.I2C1; + let scl = p.PB2; + let sda = p.PB3; + + let mut config = Config::default(); + config.clock_source = ClockSel::BusClk; + config.bus_speed = BusSpeed::FastMode; + let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, config)); + + let mut to_read = [0u8; 1]; + let to_write: u8 = 0x0F; + + match i2c.async_write_read(ADDRESS, &[to_write], &mut to_read).await { + Ok(()) => info!("Register {}: {}", to_write, to_read[0]), + Err(e) => error!("I2c Error: {:?}", e), + } + + loop {} +} diff --git a/examples/mspm0l1306/Cargo.toml b/examples/mspm0l1306/Cargo.toml index 6b1125810..b59c06257 100644 --- a/examples/mspm0l1306/Cargo.toml +++ b/examples/mspm0l1306/Cargo.toml @@ -19,3 +19,7 @@ panic-semihosting = "0.6.0" [profile.release] debug = 2 + +[profile.dev] +debug = 2 +opt-level = 2 diff --git a/examples/mspm0l1306/src/bin/i2c.rs b/examples/mspm0l1306/src/bin/i2c.rs new file mode 100644 index 000000000..02c0ee740 --- /dev/null +++ b/examples/mspm0l1306/src/bin/i2c.rs @@ -0,0 +1,37 @@ +//! Example of using blocking I2C +//! +//! This uses the virtual COM port provided on the LP-MSPM0L1306 board. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_mspm0::i2c::{BusSpeed, ClockSel, Config, I2c}; +use {defmt_rtt as _, panic_halt as _}; + +const ADDRESS: u8 = 0x6a; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let p = embassy_mspm0::init(Default::default()); + + let instance = p.I2C0; + let scl = p.PA1; + let sda = p.PA0; + + let mut config = Config::default(); + config.clock_source = ClockSel::BusClk; + config.bus_speed = BusSpeed::FastMode; + let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, config)); + + let mut to_read = [0u8; 1]; + let to_write: u8 = 0x0F; + + match i2c.blocking_write_read(ADDRESS, &[to_write], &mut to_read) { + Ok(()) => info!("Register {}: {}", to_write, to_read[0]), + Err(e) => error!("I2c Error: {:?}", e), + } + + loop {} +} diff --git a/examples/mspm0l1306/src/bin/i2c_async.rs b/examples/mspm0l1306/src/bin/i2c_async.rs new file mode 100644 index 000000000..34e2c64e7 --- /dev/null +++ b/examples/mspm0l1306/src/bin/i2c_async.rs @@ -0,0 +1,43 @@ +//! Example of using async I2C +//! +//! This uses the virtual COM port provided on the LP-MSPM0L1306 board. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_mspm0::bind_interrupts; +use embassy_mspm0::i2c::{BusSpeed, ClockSel, Config, I2c, InterruptHandler}; +use embassy_mspm0::peripherals::I2C0; +use {defmt_rtt as _, panic_halt as _}; + +const ADDRESS: u8 = 0x6a; + +bind_interrupts!(struct Irqs { + I2C0 => InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let p = embassy_mspm0::init(Default::default()); + + let instance = p.I2C0; + let scl = p.PA1; + let sda = p.PA0; + + let mut config = Config::default(); + config.clock_source = ClockSel::BusClk; + config.bus_speed = BusSpeed::FastMode; + let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, config)); + + let mut to_read = [0u8; 1]; + let to_write: u8 = 0x0F; + + match i2c.async_write_read(ADDRESS, &[to_write], &mut to_read).await { + Ok(()) => info!("Register {}: {}", to_write, to_read[0]), + Err(e) => error!("I2c Error: {:?}", e), + } + + loop {} +} -- cgit From 45852b852bf7623718f20ab9151655a417370655 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Tue, 22 Jul 2025 16:40:06 +0200 Subject: mspm0-I2C: add type for I2C clock rates + fixed comments --- embassy-mspm0/src/i2c.rs | 68 +++++++++++++++---------------- embassy-mspm0/src/lib.rs | 1 + embassy-mspm0/src/time.rs | 102 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 34 deletions(-) create mode 100644 embassy-mspm0/src/time.rs diff --git a/embassy-mspm0/src/i2c.rs b/embassy-mspm0/src/i2c.rs index 168cfccda..f99e02c59 100644 --- a/embassy-mspm0/src/i2c.rs +++ b/embassy-mspm0/src/i2c.rs @@ -16,6 +16,7 @@ use crate::interrupt::{Interrupt, InterruptExt}; use crate::mode::{Async, Blocking, Mode}; use crate::pac::i2c::{vals, I2c as Regs}; use crate::pac::{self}; +use crate::time::Hertz; use crate::Peri; /// The clock source for the I2C. @@ -31,9 +32,6 @@ pub enum ClockSel { /// /// The MCLK runs at 4 MHz. MfClk, - // BusClk, - // BusClk depends on the timer's power domain. - // This will be implemented later. } /// The clock divider for the I2C. @@ -110,15 +108,15 @@ pub enum BusSpeed { /// Custom mode. /// /// The custom mode frequency (in Hz) can be set manually. - Custom(u32), + Custom(Hertz), } impl BusSpeed { - fn hertz(self) -> u32 { + fn hertz(self) -> Hertz { match self { - Self::Standard => 100_000, - Self::FastMode => 400_000, - Self::FastModePlus => 1_000_000, + Self::Standard => Hertz::khz(100), + Self::FastMode => Hertz::khz(400), + Self::FastModePlus => Hertz::mhz(1), Self::Custom(s) => s, } } @@ -168,7 +166,7 @@ impl Default for Config { invert_scl: false, sda_pull: Pull::None, scl_pull: Pull::None, - bus_speed: BusSpeed::FastMode, + bus_speed: BusSpeed::Standard, } } } @@ -180,28 +178,26 @@ impl Config { pub fn scl_pf(&self) -> PfType { PfType::input(self.scl_pull, self.invert_scl) } - fn timer_period(&self, clock_speed: u32) -> u8 { + fn timer_period(&self) -> u8 { // Sets the timer period to bring the clock frequency to the selected I2C speed - // From the documentation: SCL_PERIOD = (1 + TPR ) * (SCL_LP + SCL_HP ) * INT_CLK_PRD where: - // - SCL_PRD is the SCL line period (I2C clock) + // From the documentation: TPR = (I2C_CLK / (I2C_FREQ * (SCL_LP + SCL_HP))) - 1 where: + // - I2C_FREQ is desired I2C frequency (= I2C_BASE_FREQ divided by I2C_DIV) // - TPR is the Timer Period register value (range of 1 to 127) // - SCL_LP is the SCL Low period (fixed at 6) // - SCL_HP is the SCL High period (fixed at 4) - // - CLK_PRD is the functional clock period in ns - let scl_period = (1.0 / self.bus_speed.hertz() as f64) * 1_000_000_000.0; - let clock = (clock_speed as f64) / self.clock_div.divider() as f64; - let clk_period = (1.0 / clock) * 1_000_000_000.0; - let tpr = scl_period / (10.0 * clk_period) - 1.0; - tpr.clamp(0.0, 255.0) as u8 + // - I2C_CLK is functional clock frequency + return (((self.calculate_clock_rate() * self.clock_div.divider()) / (self.bus_speed.hertz() * 10u32)) - 1) + .try_into() + .unwrap(); } #[cfg(any(mspm0c110x))] - pub fn calculate_clock_rate(&self) -> u32 { + pub fn calculate_clock_rate(&self) -> Hertz { // Assume that BusClk has default value. // TODO: calculate BusClk more precisely. match self.clock_source { - ClockSel::MfClk => 4_000_000, - ClockSel::BusClk => 24_000_000, + ClockSel::MfClk => Hertz::mhz(4), + ClockSel::BusClk => Hertz::mhz(24), } } @@ -209,24 +205,24 @@ impl Config { mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x, mspm0l110x, mspm0l122x, mspm0l130x, mspm0l134x, mspm0l222x ))] - pub fn calculate_clock_rate(&self) -> u32 { + pub fn calculate_clock_rate(&self) -> Hertz { // Assume that BusClk has default value. // TODO: calculate BusClk more precisely. match self.clock_source { - ClockSel::MfClk => 4_000_000, - ClockSel::BusClk => 32_000_000, + ClockSel::MfClk => Hertz::mhz(4), + ClockSel::BusClk => Hertz::mhz(32), } } pub fn check_clock_rate(&self) -> bool { // make sure source clock is ~20 faster than i2c clock - let clk_ratio = 20; + let clk_ratio = 20u8; let i2c_clk = self.bus_speed.hertz() / self.clock_div.divider(); let src_clk = self.calculate_clock_rate(); // check clock rate - return src_clk >= clk_ratio * i2c_clk; + return src_clk >= i2c_clk * clk_ratio; } } @@ -380,15 +376,15 @@ impl<'d, M: Mode> I2c<'d, M> { .cctr() .write_value(i2c::regs::Cctr::default()); - let clock = config.calculate_clock_rate(); - - self.state.clock.store(clock, Ordering::Relaxed); + self.state + .clock + .store(config.calculate_clock_rate().0, Ordering::Relaxed); self.info .regs .controller(0) .ctpr() - .write(|w| w.set_tpr(config.timer_period(clock))); + .write(|w| w.set_tpr(config.timer_period())); // Set Tx Fifo threshold, follow TI example self.info @@ -1095,7 +1091,8 @@ mod tests { let mut config = Config::default(); config.clock_div = ClockDiv::DivBy1; config.bus_speed = BusSpeed::FastMode; - assert!(matches!(config.timer_period(32_000_000), 7)); + config.clock_source = ClockSel::BusClk; + assert!(matches!(config.timer_period(), 7)); } #[test] @@ -1103,7 +1100,8 @@ mod tests { let mut config = Config::default(); config.clock_div = ClockDiv::DivBy2; config.bus_speed = BusSpeed::FastMode; - assert!(matches!(config.timer_period(32_000_000), 3)); + config.clock_source = ClockSel::BusClk; + assert!(matches!(config.timer_period(), 3)); } #[test] @@ -1111,7 +1109,8 @@ mod tests { let mut config = Config::default(); config.clock_div = ClockDiv::DivBy2; config.bus_speed = BusSpeed::Standard; - assert!(matches!(config.timer_period(32_000_000), 15)); + config.clock_source = ClockSel::BusClk; + assert!(matches!(config.timer_period(), 15)); } #[test] @@ -1119,7 +1118,8 @@ mod tests { let mut config = Config::default(); config.clock_div = ClockDiv::DivBy2; config.bus_speed = BusSpeed::Custom(100_000); - assert!(matches!(config.timer_period(32_000_000), 15)); + config.clock_source = ClockSel::BusClk; + assert!(matches!(config.timer_period(), 15)); } #[test] diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index 403f9d50c..fd8450daf 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -16,6 +16,7 @@ mod macros; pub mod dma; pub mod gpio; pub mod i2c; +pub mod time; pub mod timer; pub mod uart; diff --git a/embassy-mspm0/src/time.rs b/embassy-mspm0/src/time.rs new file mode 100644 index 000000000..1353a909a --- /dev/null +++ b/embassy-mspm0/src/time.rs @@ -0,0 +1,102 @@ +//! Time units + +use core::fmt::Display; +use core::ops::{Div, Mul}; + +/// Hertz +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug)] +pub struct Hertz(pub u32); + +impl Display for Hertz { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{} Hz", self.0) + } +} + +#[cfg(feature = "defmt")] +impl defmt::Format for Hertz { + fn format(&self, f: defmt::Formatter) { + defmt::write!(f, "{=u32} Hz", self.0) + } +} + +impl Hertz { + /// Create a `Hertz` from the given hertz. + pub const fn hz(hertz: u32) -> Self { + Self(hertz) + } + + /// Create a `Hertz` from the given kilohertz. + pub const fn khz(kilohertz: u32) -> Self { + Self(kilohertz * 1_000) + } + + /// Create a `Hertz` from the given megahertz. + pub const fn mhz(megahertz: u32) -> Self { + Self(megahertz * 1_000_000) + } +} + +/// This is a convenience shortcut for [`Hertz::hz`] +pub const fn hz(hertz: u32) -> Hertz { + Hertz::hz(hertz) +} + +/// This is a convenience shortcut for [`Hertz::khz`] +pub const fn khz(kilohertz: u32) -> Hertz { + Hertz::khz(kilohertz) +} + +/// This is a convenience shortcut for [`Hertz::mhz`] +pub const fn mhz(megahertz: u32) -> Hertz { + Hertz::mhz(megahertz) +} + +impl Mul for Hertz { + type Output = Hertz; + fn mul(self, rhs: u32) -> Self::Output { + Hertz(self.0 * rhs) + } +} + +impl Div for Hertz { + type Output = Hertz; + fn div(self, rhs: u32) -> Self::Output { + Hertz(self.0 / rhs) + } +} + +impl Mul for Hertz { + type Output = Hertz; + fn mul(self, rhs: u16) -> Self::Output { + self * (rhs as u32) + } +} + +impl Div for Hertz { + type Output = Hertz; + fn div(self, rhs: u16) -> Self::Output { + self / (rhs as u32) + } +} + +impl Mul for Hertz { + type Output = Hertz; + fn mul(self, rhs: u8) -> Self::Output { + self * (rhs as u32) + } +} + +impl Div for Hertz { + type Output = Hertz; + fn div(self, rhs: u8) -> Self::Output { + self / (rhs as u32) + } +} + +impl Div for Hertz { + type Output = u32; + fn div(self, rhs: Hertz) -> Self::Output { + self.0 / rhs.0 + } +} -- cgit From 917a509c1a899d7054f1a9cf2a21369dc143f46b Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Wed, 23 Jul 2025 17:00:10 +0200 Subject: mspm0-I2C: automate source clock definition - i2c-config: automatically defines clock source based on input I2C rate - i2c: proper config functions naming - i2c-examples: adapt to changed API - i2c: save initialization pf cctr register --- embassy-mspm0/src/i2c.rs | 120 +++++++++++++++++++++---------- examples/mspm0g3507/src/bin/i2c.rs | 7 +- examples/mspm0g3507/src/bin/i2c_async.rs | 7 +- examples/mspm0l1306/src/bin/i2c.rs | 7 +- examples/mspm0l1306/src/bin/i2c_async.rs | 7 +- 5 files changed, 89 insertions(+), 59 deletions(-) diff --git a/embassy-mspm0/src/i2c.rs b/embassy-mspm0/src/i2c.rs index f99e02c59..d093a7e21 100644 --- a/embassy-mspm0/src/i2c.rs +++ b/embassy-mspm0/src/i2c.rs @@ -25,7 +25,7 @@ use crate::Peri; pub enum ClockSel { /// Use the bus clock. /// - /// By default the BusClk runs at 32 MHz. + /// Configurable clock. BusClk, /// Use the middle frequency clock. @@ -127,8 +127,15 @@ impl BusSpeed { #[cfg_attr(feature = "defmt", derive(defmt::Format))] /// Config Error pub enum ConfigError { + /// Invalid clock rate. + /// /// The clock rate could not be configured with the given conifguratoin. InvalidClockRate, + + /// Clock source not enabled. + /// + /// The clock soure is not enabled is SYSCTL. + ClockSourceNotEnabled, } #[non_exhaustive] @@ -136,7 +143,7 @@ pub enum ConfigError { /// Config pub struct Config { /// I2C clock source. - pub clock_source: ClockSel, + clock_source: ClockSel, /// I2C clock divider. pub clock_div: ClockDiv, @@ -160,7 +167,7 @@ pub struct Config { impl Default for Config { fn default() -> Self { Self { - clock_source: ClockSel::BusClk, + clock_source: ClockSel::MfClk, clock_div: ClockDiv::DivBy1, invert_sda: false, invert_scl: false, @@ -178,7 +185,7 @@ impl Config { pub fn scl_pf(&self) -> PfType { PfType::input(self.scl_pull, self.invert_scl) } - fn timer_period(&self) -> u8 { + fn calculate_timer_period(&self) -> u8 { // Sets the timer period to bring the clock frequency to the selected I2C speed // From the documentation: TPR = (I2C_CLK / (I2C_FREQ * (SCL_LP + SCL_HP))) - 1 where: // - I2C_FREQ is desired I2C frequency (= I2C_BASE_FREQ divided by I2C_DIV) @@ -186,13 +193,13 @@ impl Config { // - SCL_LP is the SCL Low period (fixed at 6) // - SCL_HP is the SCL High period (fixed at 4) // - I2C_CLK is functional clock frequency - return (((self.calculate_clock_rate() * self.clock_div.divider()) / (self.bus_speed.hertz() * 10u32)) - 1) + return (((self.calculate_clock_source() * self.clock_div.divider()) / (self.bus_speed.hertz() * 10u32)) - 1) .try_into() .unwrap(); } #[cfg(any(mspm0c110x))] - pub fn calculate_clock_rate(&self) -> Hertz { + fn calculate_clock_source(&self) -> Hertz { // Assume that BusClk has default value. // TODO: calculate BusClk more precisely. match self.clock_source { @@ -205,7 +212,7 @@ impl Config { mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x, mspm0l110x, mspm0l122x, mspm0l130x, mspm0l134x, mspm0l222x ))] - pub fn calculate_clock_rate(&self) -> Hertz { + fn calculate_clock_source(&self) -> Hertz { // Assume that BusClk has default value. // TODO: calculate BusClk more precisely. match self.clock_source { @@ -214,16 +221,47 @@ impl Config { } } - pub fn check_clock_rate(&self) -> bool { + fn check_clock_i2c(&self) -> bool { // make sure source clock is ~20 faster than i2c clock let clk_ratio = 20u8; let i2c_clk = self.bus_speed.hertz() / self.clock_div.divider(); - let src_clk = self.calculate_clock_rate(); + let src_clk = self.calculate_clock_source(); // check clock rate return src_clk >= i2c_clk * clk_ratio; } + + fn define_clock_source(&mut self) -> bool { + // decide which clock source to choose based on i2c clock. + // If i2c speed <= 200kHz, use MfClk, otherwise use BusClk + if self.bus_speed.hertz() / self.clock_div.divider() > Hertz::khz(200) { + // TODO: check if BUSCLK enabled + self.clock_source = ClockSel::BusClk; + } else { + // is MFCLK enabled + if !pac::SYSCTL.mclkcfg().read().usemftick() { + return false; + } + self.clock_source = ClockSel::MfClk; + } + return true; + } + + /// Check the config. + /// + /// Make sure that configuration is valid and enabled by the system. + pub fn check_config(&mut self) -> Result<(), ConfigError> { + if !self.define_clock_source() { + return Err(ConfigError::ClockSourceNotEnabled); + } + + if !self.check_clock_i2c() { + return Err(ConfigError::InvalidClockRate); + } + + Ok(()) + } } /// Serial error @@ -288,7 +326,7 @@ impl<'d, M: Mode> SetConfig for I2c<'d, M> { type ConfigError = ConfigError; fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> { - self.set_config(config) + self.set_config(*config) } } @@ -297,10 +335,10 @@ impl<'d> I2c<'d, Blocking> { peri: Peri<'d, T>, scl: Peri<'d, impl SclPin>, sda: Peri<'d, impl SdaPin>, - config: Config, + mut config: Config, ) -> Result { - if !config.check_clock_rate() { - return Err(ConfigError::InvalidClockRate); + if let Err(err) = config.check_config() { + return Err(err); } Self::new_inner(peri, scl, sda, config) @@ -313,10 +351,10 @@ impl<'d> I2c<'d, Async> { scl: Peri<'d, impl SclPin>, sda: Peri<'d, impl SdaPin>, _irq: impl Binding> + 'd, - config: Config, + mut config: Config, ) -> Result { - if !config.check_clock_rate() { - return Err(ConfigError::InvalidClockRate); + if let Err(err) = config.check_config() { + return Err(err); } let i2c = Self::new_inner(peri, scl, sda, config); @@ -330,9 +368,9 @@ impl<'d> I2c<'d, Async> { impl<'d, M: Mode> I2c<'d, M> { /// Reconfigure the driver - pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { - if !config.check_clock_rate() { - return Err(ConfigError::InvalidClockRate); + pub fn set_config(&mut self, mut config: Config) -> Result<(), ConfigError> { + if let Err(err) = config.check_config() { + return Err(err); } self.info.interrupt.disable(); @@ -345,7 +383,7 @@ impl<'d, M: Mode> I2c<'d, M> { scl.update_pf(config.scl_pf()); } - self.init(config) + self.init(&config) } fn init(&mut self, config: &Config) -> Result<(), ConfigError> { @@ -370,21 +408,25 @@ impl<'d, M: Mode> I2c<'d, M> { }); // Reset controller transfer, follow TI example - self.info - .regs - .controller(0) - .cctr() - .write_value(i2c::regs::Cctr::default()); + self.info.regs.controller(0).cctr().modify(|w| { + w.set_burstrun(false); + w.set_start(false); + w.set_stop(false); + w.set_ack(false); + w.set_cackoen(false); + w.set_rd_on_txempty(false); + w.set_cblen(0); + }); self.state .clock - .store(config.calculate_clock_rate().0, Ordering::Relaxed); + .store(config.calculate_clock_source().0, Ordering::Relaxed); self.info .regs .controller(0) .ctpr() - .write(|w| w.set_tpr(config.timer_period())); + .write(|w| w.set_tpr(config.calculate_timer_period())); // Set Tx Fifo threshold, follow TI example self.info @@ -1087,39 +1129,39 @@ mod tests { /// These tests are based on TI's reference caluclation. #[test] - fn ti_timer_period() { + fn ti_calculate_timer_period() { let mut config = Config::default(); config.clock_div = ClockDiv::DivBy1; config.bus_speed = BusSpeed::FastMode; config.clock_source = ClockSel::BusClk; - assert!(matches!(config.timer_period(), 7)); + assert!(matches!(config.calculate_timer_period(), 7)); } #[test] - fn ti_timer_period_2() { + fn ti_calculate_timer_period_2() { let mut config = Config::default(); config.clock_div = ClockDiv::DivBy2; config.bus_speed = BusSpeed::FastMode; config.clock_source = ClockSel::BusClk; - assert!(matches!(config.timer_period(), 3)); + assert!(matches!(config.calculate_timer_period(), 3)); } #[test] - fn ti_timer_period_3() { + fn ti_calculate_timer_period_3() { let mut config = Config::default(); config.clock_div = ClockDiv::DivBy2; config.bus_speed = BusSpeed::Standard; config.clock_source = ClockSel::BusClk; - assert!(matches!(config.timer_period(), 15)); + assert!(matches!(config.calculate_timer_period(), 15)); } #[test] - fn ti_timer_period_4() { + fn ti_calculate_timer_period_4() { let mut config = Config::default(); config.clock_div = ClockDiv::DivBy2; config.bus_speed = BusSpeed::Custom(100_000); config.clock_source = ClockSel::BusClk; - assert!(matches!(config.timer_period(), 15)); + assert!(matches!(config.calculate_timer_period(), 15)); } #[test] @@ -1127,7 +1169,7 @@ mod tests { let mut config = Config::default(); config.clock_source = ClockSel::BusClk; config.bus_speed = BusSpeed::FastModePlus; - assert!(config.check_clock_rate()); + assert!(config.check_clock_i2c()); } #[test] @@ -1135,7 +1177,7 @@ mod tests { let mut config = Config::default(); config.clock_source = ClockSel::BusClk; config.bus_speed = BusSpeed::FastMode; - assert!(config.check_clock_rate()); + assert!(config.check_clock_i2c()); } #[test] @@ -1143,7 +1185,7 @@ mod tests { let mut config = Config::default(); config.clock_source = ClockSel::MfClk; config.bus_speed = BusSpeed::FastModePlus; - assert!(!config.check_clock_rate()); + assert!(!config.check_clock_i2c()); } #[test] @@ -1151,6 +1193,6 @@ mod tests { let mut config = Config::default(); config.clock_source = ClockSel::MfClk; config.bus_speed = BusSpeed::FastMode; - assert!(!config.check_clock_rate()); + assert!(!config.check_clock_i2c()); } } diff --git a/examples/mspm0g3507/src/bin/i2c.rs b/examples/mspm0g3507/src/bin/i2c.rs index 752649dbc..b87a0184f 100644 --- a/examples/mspm0g3507/src/bin/i2c.rs +++ b/examples/mspm0g3507/src/bin/i2c.rs @@ -7,7 +7,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_mspm0::i2c::{BusSpeed, ClockSel, Config, I2c}; +use embassy_mspm0::i2c::{Config, I2c}; use {defmt_rtt as _, panic_halt as _}; const ADDRESS: u8 = 0x6a; @@ -20,10 +20,7 @@ async fn main(_spawner: Spawner) -> ! { let scl = p.PB2; let sda = p.PB3; - let mut config = Config::default(); - config.clock_source = ClockSel::BusClk; - config.bus_speed = BusSpeed::FastMode; - let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, config)); + let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, Config::default())); let mut to_read = [0u8; 1]; let to_write: u8 = 0x0F; diff --git a/examples/mspm0g3507/src/bin/i2c_async.rs b/examples/mspm0g3507/src/bin/i2c_async.rs index bc50a2623..044a71355 100644 --- a/examples/mspm0g3507/src/bin/i2c_async.rs +++ b/examples/mspm0g3507/src/bin/i2c_async.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_mspm0::bind_interrupts; -use embassy_mspm0::i2c::{BusSpeed, ClockSel, Config, I2c, InterruptHandler}; +use embassy_mspm0::i2c::{Config, I2c, InterruptHandler}; use embassy_mspm0::peripherals::I2C1; use {defmt_rtt as _, panic_halt as _}; @@ -26,10 +26,7 @@ async fn main(_spawner: Spawner) -> ! { let scl = p.PB2; let sda = p.PB3; - let mut config = Config::default(); - config.clock_source = ClockSel::BusClk; - config.bus_speed = BusSpeed::FastMode; - let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, config)); + let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default())); let mut to_read = [0u8; 1]; let to_write: u8 = 0x0F; diff --git a/examples/mspm0l1306/src/bin/i2c.rs b/examples/mspm0l1306/src/bin/i2c.rs index 02c0ee740..cf65206b2 100644 --- a/examples/mspm0l1306/src/bin/i2c.rs +++ b/examples/mspm0l1306/src/bin/i2c.rs @@ -7,7 +7,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_mspm0::i2c::{BusSpeed, ClockSel, Config, I2c}; +use embassy_mspm0::i2c::{Config, I2c}; use {defmt_rtt as _, panic_halt as _}; const ADDRESS: u8 = 0x6a; @@ -20,10 +20,7 @@ async fn main(_spawner: Spawner) -> ! { let scl = p.PA1; let sda = p.PA0; - let mut config = Config::default(); - config.clock_source = ClockSel::BusClk; - config.bus_speed = BusSpeed::FastMode; - let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, config)); + let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, Config::default())); let mut to_read = [0u8; 1]; let to_write: u8 = 0x0F; diff --git a/examples/mspm0l1306/src/bin/i2c_async.rs b/examples/mspm0l1306/src/bin/i2c_async.rs index 34e2c64e7..a54beebe5 100644 --- a/examples/mspm0l1306/src/bin/i2c_async.rs +++ b/examples/mspm0l1306/src/bin/i2c_async.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_mspm0::bind_interrupts; -use embassy_mspm0::i2c::{BusSpeed, ClockSel, Config, I2c, InterruptHandler}; +use embassy_mspm0::i2c::{Config, I2c, InterruptHandler}; use embassy_mspm0::peripherals::I2C0; use {defmt_rtt as _, panic_halt as _}; @@ -26,10 +26,7 @@ async fn main(_spawner: Spawner) -> ! { let scl = p.PA1; let sda = p.PA0; - let mut config = Config::default(); - config.clock_source = ClockSel::BusClk; - config.bus_speed = BusSpeed::FastMode; - let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, config)); + let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default())); let mut to_read = [0u8; 1]; let to_write: u8 = 0x0F; -- cgit From dc52ead73231ee963d1a492e70e49013df7e7127 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Thu, 24 Jul 2025 11:39:30 +0200 Subject: mspm0-I2C: remove SYSOSC init, make ClockDiv::Into private --- embassy-mspm0/src/i2c.rs | 4 +--- embassy-mspm0/src/lib.rs | 4 ---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/embassy-mspm0/src/i2c.rs b/embassy-mspm0/src/i2c.rs index d093a7e21..3406623fb 100644 --- a/embassy-mspm0/src/i2c.rs +++ b/embassy-mspm0/src/i2c.rs @@ -56,7 +56,7 @@ pub enum ClockDiv { DivBy8, } -impl Into for ClockDiv { +impl ClockDiv { fn into(self) -> vals::Ratio { match self { Self::DivBy1 => vals::Ratio::DIV_BY_1, @@ -69,9 +69,7 @@ impl Into for ClockDiv { Self::DivBy8 => vals::Ratio::DIV_BY_8, } } -} -impl ClockDiv { fn divider(self) -> u32 { match self { Self::DivBy1 => 1, diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index fd8450daf..55aef79b1 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -181,10 +181,6 @@ pub fn init(config: Config) -> Peripherals { w.set_mfpclken(true); }); - pac::SYSCTL.sysosccfg().modify(|w| { - w.set_freq(pac::sysctl::vals::SysosccfgFreq::SYSOSCBASE); - }); - pac::SYSCTL.borthreshold().modify(|w| { w.set_level(0); }); -- cgit From d6a87b411432d9c6eedd48aa30b72cda069bd86c Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Tue, 29 Jul 2025 15:26:34 +0200 Subject: mspm0-I2C: mention blocking API's restrictions - blocking API for transfering max 8 bytes - async API has no such limitations --- examples/mspm0g3507/src/bin/i2c.rs | 3 ++- examples/mspm0g3507/src/bin/i2c_async.rs | 8 ++++---- examples/mspm0l1306/src/bin/i2c.rs | 3 ++- examples/mspm0l1306/src/bin/i2c_async.rs | 8 ++++---- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/examples/mspm0g3507/src/bin/i2c.rs b/examples/mspm0g3507/src/bin/i2c.rs index b87a0184f..2e3bf2ca1 100644 --- a/examples/mspm0g3507/src/bin/i2c.rs +++ b/examples/mspm0g3507/src/bin/i2c.rs @@ -1,4 +1,5 @@ -//! Example of using blocking I2C +//! This example uses FIFO with polling, and the maximum FIFO size is 8. +//! Refer to async example to handle larger packets. //! //! This uses the virtual COM port provided on the LP-MSPM0G3507 board. diff --git a/examples/mspm0g3507/src/bin/i2c_async.rs b/examples/mspm0g3507/src/bin/i2c_async.rs index 044a71355..294550605 100644 --- a/examples/mspm0g3507/src/bin/i2c_async.rs +++ b/examples/mspm0g3507/src/bin/i2c_async.rs @@ -1,4 +1,4 @@ -//! Example of using async I2C +//! The example uses FIFO and interrupts, wrapped in async API. //! //! This uses the virtual COM port provided on the LP-MSPM0G3507 board. @@ -28,10 +28,10 @@ async fn main(_spawner: Spawner) -> ! { let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default())); - let mut to_read = [0u8; 1]; - let to_write: u8 = 0x0F; + let mut to_read = [1u8; 17]; + let to_write = [0u8; 17]; - match i2c.async_write_read(ADDRESS, &[to_write], &mut to_read).await { + match i2c.async_write_read(ADDRESS, &to_write, &mut to_read).await { Ok(()) => info!("Register {}: {}", to_write, to_read[0]), Err(e) => error!("I2c Error: {:?}", e), } diff --git a/examples/mspm0l1306/src/bin/i2c.rs b/examples/mspm0l1306/src/bin/i2c.rs index cf65206b2..51327dff5 100644 --- a/examples/mspm0l1306/src/bin/i2c.rs +++ b/examples/mspm0l1306/src/bin/i2c.rs @@ -1,4 +1,5 @@ -//! Example of using blocking I2C +//! This example uses FIFO with polling, and the maximum FIFO size is 8. +//! Refer to async example to handle larger packets. //! //! This uses the virtual COM port provided on the LP-MSPM0L1306 board. diff --git a/examples/mspm0l1306/src/bin/i2c_async.rs b/examples/mspm0l1306/src/bin/i2c_async.rs index a54beebe5..74826bcc4 100644 --- a/examples/mspm0l1306/src/bin/i2c_async.rs +++ b/examples/mspm0l1306/src/bin/i2c_async.rs @@ -1,4 +1,4 @@ -//! Example of using async I2C +//! The example uses FIFO and interrupts, wrapped in async API. //! //! This uses the virtual COM port provided on the LP-MSPM0L1306 board. @@ -28,10 +28,10 @@ async fn main(_spawner: Spawner) -> ! { let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default())); - let mut to_read = [0u8; 1]; - let to_write: u8 = 0x0F; + let mut to_read = [1u8; 17]; + let to_write = [0u8; 17]; - match i2c.async_write_read(ADDRESS, &[to_write], &mut to_read).await { + match i2c.async_write_read(ADDRESS, &to_write, &mut to_read).await { Ok(()) => info!("Register {}: {}", to_write, to_read[0]), Err(e) => error!("I2c Error: {:?}", e), } -- cgit From 934e7809b5036047f5113a9241c6af680f9a8c4b Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Mon, 4 Aug 2025 09:31:24 +0200 Subject: mspm0-I2C: update mspm0-metapac revision --- embassy-mspm0/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index e8fb2e9a9..ef1bb18fd 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -47,14 +47,14 @@ cortex-m = "0.7.6" critical-section = "1.2.0" # mspm0-metapac = { version = "" } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-235158ac2865d8aac3a1eceb2d62026eb12bf38f" } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-df572e257eabf06e6e0ae6c9077e0a2fec1fb5e1" } [build-dependencies] proc-macro2 = "1.0.94" quote = "1.0.40" # mspm0-metapac = { version = "", default-features = false, features = ["metadata"] } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-235158ac2865d8aac3a1eceb2d62026eb12bf38f", default-features = false, features = ["metadata"] } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-df572e257eabf06e6e0ae6c9077e0a2fec1fb5e1", default-features = false, features = ["metadata"] } [features] default = ["rt"] -- cgit From 8091155a2f0eaa64f3ca7c9da4c835c956e860e8 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Mon, 4 Aug 2025 09:38:35 +0200 Subject: mspm0-I2C: forward fifo size to i2c controller --- embassy-mspm0/build.rs | 3 ++- embassy-mspm0/src/i2c.rs | 45 +++++++++++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs index 328db3926..efbe6645f 100644 --- a/embassy-mspm0/build.rs +++ b/embassy-mspm0/build.rs @@ -549,10 +549,11 @@ fn generate_peripheral_instances() -> TokenStream { for peripheral in METADATA.peripherals { let peri = format_ident!("{}", peripheral.name); + let fifo_size = peripheral.sys_fentries; let tokens = match peripheral.kind { "uart" => Some(quote! { impl_uart_instance!(#peri); }), - "i2c" => Some(quote! { impl_i2c_instance!(#peri); }), + "i2c" => Some(quote! { impl_i2c_instance!(#peri, #fifo_size); }), _ => None, }; diff --git a/embassy-mspm0/src/i2c.rs b/embassy-mspm0/src/i2c.rs index 3406623fb..7581f131e 100644 --- a/embassy-mspm0/src/i2c.rs +++ b/embassy-mspm0/src/i2c.rs @@ -287,6 +287,9 @@ pub enum Error { /// Zero-length transfers are not allowed. ZeroLengthTransfer, + + /// Transfer length is over limit. + TransferLengthIsOverLimit, } impl core::fmt::Display for Error { @@ -299,6 +302,7 @@ impl core::fmt::Display for Error { Self::Crc => "CRC Mismatch", Self::Overrun => "Buffer Overrun", Self::ZeroLengthTransfer => "Zero-Length Transfers are not allowed", + Self::TransferLengthIsOverLimit => "Transfer length is over limit", }; write!(f, "{}", message) @@ -307,9 +311,6 @@ impl core::fmt::Display for Error { impl core::error::Error for Error {} -/// mspm0g, mspm0c, mspm0l, msps00 have 8-bytes FIFO -pub const FIFO_SIZE: usize = 8; - /// I2C Driver. pub struct I2c<'d, M: Mode> { info: &'static Info, @@ -461,8 +462,6 @@ impl<'d, M: Mode> I2c<'d, M> { } fn master_continue(&mut self, length: usize, send_ack_nack: bool, send_stop: bool) -> Result<(), Error> { - assert!(length <= FIFO_SIZE && length > 0); - // delay between ongoing transactions, 1000 cycles cortex_m::asm::delay(1000); @@ -515,8 +514,6 @@ impl<'d, M: Mode> I2c<'d, M> { } fn master_write(&mut self, address: u8, length: usize, send_stop: bool) -> Result<(), Error> { - assert!(length <= FIFO_SIZE && length > 0); - // Start transfer of length amount of bytes self.info.regs.controller(0).csa().modify(|w| { w.set_taddr(address as u16); @@ -565,8 +562,6 @@ impl<'d> I2c<'d, Blocking> { send_ack_nack: bool, send_stop: bool, ) -> Result<(), Error> { - assert!(length <= FIFO_SIZE && length > 0); - // unless restart, Wait for the controller to be idle, if !restart { while !self.info.regs.controller(0).csr().read().idle() {} @@ -600,10 +595,16 @@ impl<'d> I2c<'d, Blocking> { restart: bool, end_w_stop: bool, ) -> Result<(), Error> { - let read_len = read.len(); + if read.is_empty() { + return Err(Error::ZeroLengthTransfer); + } + if read.len() > self.info.fifo_size { + return Err(Error::TransferLengthIsOverLimit); + } + let read_len = read.len(); let mut bytes_to_read = read_len; - for (number, chunk) in read.chunks_mut(FIFO_SIZE).enumerate() { + for (number, chunk) in read.chunks_mut(self.info.fifo_size).enumerate() { bytes_to_read -= chunk.len(); // if the current transaction is the last & end_w_stop, send stop let send_stop = bytes_to_read == 0 && end_w_stop; @@ -611,7 +612,13 @@ impl<'d> I2c<'d, Blocking> { let send_ack_nack = bytes_to_read != 0; if number == 0 { - self.master_blocking_read(address, chunk.len().min(FIFO_SIZE), restart, send_ack_nack, send_stop)? + self.master_blocking_read( + address, + chunk.len().min(self.info.fifo_size), + restart, + send_ack_nack, + send_stop, + )? } else { self.master_blocking_continue(chunk.len(), send_ack_nack, send_stop)?; } @@ -633,9 +640,12 @@ impl<'d> I2c<'d, Blocking> { if write.is_empty() { return Err(Error::ZeroLengthTransfer); } + if write.len() > self.info.fifo_size { + return Err(Error::TransferLengthIsOverLimit); + } let mut bytes_to_send = write.len(); - for (number, chunk) in write.chunks(FIFO_SIZE).enumerate() { + for (number, chunk) in write.chunks(self.info.fifo_size).enumerate() { for byte in chunk { let ctrl0 = self.info.regs.controller(0).ctxdata(); ctrl0.write(|w| w.set_value(*byte)); @@ -694,7 +704,7 @@ impl<'d> I2c<'d, Async> { let ctrl = self.info.regs.controller(0); let mut bytes_to_send = write.len(); - for (number, chunk) in write.chunks(FIFO_SIZE).enumerate() { + for (number, chunk) in write.chunks(self.info.fifo_size).enumerate() { self.info.regs.cpu_int(0).imask().modify(|w| { w.set_carblost(true); w.set_cnack(true); @@ -757,7 +767,7 @@ impl<'d> I2c<'d, Async> { let read_len = read.len(); let mut bytes_to_read = read_len; - for (number, chunk) in read.chunks_mut(FIFO_SIZE).enumerate() { + for (number, chunk) in read.chunks_mut(self.info.fifo_size).enumerate() { bytes_to_read -= chunk.len(); // if the current transaction is the last & end_w_stop, send stop let send_stop = bytes_to_read == 0 && end_w_stop; @@ -898,6 +908,7 @@ impl embedded_hal::i2c::Error for Error { Self::Crc => embedded_hal::i2c::ErrorKind::Other, Self::Overrun => embedded_hal::i2c::ErrorKind::Overrun, Self::ZeroLengthTransfer => embedded_hal::i2c::ErrorKind::Other, + Self::TransferLengthIsOverLimit => embedded_hal::i2c::ErrorKind::Other, } } } @@ -1003,6 +1014,7 @@ pub trait SclPin: crate::gpio::Pin { pub(crate) struct Info { pub(crate) regs: Regs, pub(crate) interrupt: Interrupt, + pub fifo_size: usize, } pub(crate) struct State { @@ -1070,7 +1082,7 @@ pub(crate) trait SealedInstance { } macro_rules! impl_i2c_instance { - ($instance: ident) => { + ($instance: ident, $fifo_size: expr) => { impl crate::i2c::SealedInstance for crate::peripherals::$instance { fn info() -> &'static crate::i2c::Info { use crate::i2c::Info; @@ -1079,6 +1091,7 @@ macro_rules! impl_i2c_instance { const INFO: Info = Info { regs: crate::pac::$instance, interrupt: crate::interrupt::typelevel::$instance::IRQ, + fifo_size: $fifo_size, }; &INFO } -- cgit From 3b7b343863ac347bf86f4d2a79cb43788b5fcdc0 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Mon, 4 Aug 2025 10:15:37 +0200 Subject: mspm0-I2C: remove type time:Herz usage --- embassy-mspm0/src/i2c.rs | 29 +++++++------ embassy-mspm0/src/lib.rs | 1 - embassy-mspm0/src/time.rs | 102 ---------------------------------------------- 3 files changed, 14 insertions(+), 118 deletions(-) delete mode 100644 embassy-mspm0/src/time.rs diff --git a/embassy-mspm0/src/i2c.rs b/embassy-mspm0/src/i2c.rs index 7581f131e..d1b260114 100644 --- a/embassy-mspm0/src/i2c.rs +++ b/embassy-mspm0/src/i2c.rs @@ -16,7 +16,6 @@ use crate::interrupt::{Interrupt, InterruptExt}; use crate::mode::{Async, Blocking, Mode}; use crate::pac::i2c::{vals, I2c as Regs}; use crate::pac::{self}; -use crate::time::Hertz; use crate::Peri; /// The clock source for the I2C. @@ -106,15 +105,15 @@ pub enum BusSpeed { /// Custom mode. /// /// The custom mode frequency (in Hz) can be set manually. - Custom(Hertz), + Custom(u32), } impl BusSpeed { - fn hertz(self) -> Hertz { + fn hertz(self) -> u32 { match self { - Self::Standard => Hertz::khz(100), - Self::FastMode => Hertz::khz(400), - Self::FastModePlus => Hertz::mhz(1), + Self::Standard => 100_000, + Self::FastMode => 400_000, + Self::FastModePlus => 1_000_000, Self::Custom(s) => s, } } @@ -197,12 +196,12 @@ impl Config { } #[cfg(any(mspm0c110x))] - fn calculate_clock_source(&self) -> Hertz { + fn calculate_clock_source(&self) -> u32 { // Assume that BusClk has default value. // TODO: calculate BusClk more precisely. match self.clock_source { - ClockSel::MfClk => Hertz::mhz(4), - ClockSel::BusClk => Hertz::mhz(24), + ClockSel::MfClk => 4_000_000, + ClockSel::BusClk => 24_000_000, } } @@ -210,18 +209,18 @@ impl Config { mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x, mspm0l110x, mspm0l122x, mspm0l130x, mspm0l134x, mspm0l222x ))] - fn calculate_clock_source(&self) -> Hertz { + fn calculate_clock_source(&self) -> u32 { // Assume that BusClk has default value. // TODO: calculate BusClk more precisely. match self.clock_source { - ClockSel::MfClk => Hertz::mhz(4), - ClockSel::BusClk => Hertz::mhz(32), + ClockSel::MfClk => 4_000_000, + ClockSel::BusClk => 24_000_000, } } fn check_clock_i2c(&self) -> bool { // make sure source clock is ~20 faster than i2c clock - let clk_ratio = 20u8; + let clk_ratio = 20; let i2c_clk = self.bus_speed.hertz() / self.clock_div.divider(); let src_clk = self.calculate_clock_source(); @@ -233,7 +232,7 @@ impl Config { fn define_clock_source(&mut self) -> bool { // decide which clock source to choose based on i2c clock. // If i2c speed <= 200kHz, use MfClk, otherwise use BusClk - if self.bus_speed.hertz() / self.clock_div.divider() > Hertz::khz(200) { + if self.bus_speed.hertz() / self.clock_div.divider() > 200_000 { // TODO: check if BUSCLK enabled self.clock_source = ClockSel::BusClk; } else { @@ -419,7 +418,7 @@ impl<'d, M: Mode> I2c<'d, M> { self.state .clock - .store(config.calculate_clock_source().0, Ordering::Relaxed); + .store(config.calculate_clock_source(), Ordering::Relaxed); self.info .regs diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index 55aef79b1..c7cf40e0c 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -16,7 +16,6 @@ mod macros; pub mod dma; pub mod gpio; pub mod i2c; -pub mod time; pub mod timer; pub mod uart; diff --git a/embassy-mspm0/src/time.rs b/embassy-mspm0/src/time.rs deleted file mode 100644 index 1353a909a..000000000 --- a/embassy-mspm0/src/time.rs +++ /dev/null @@ -1,102 +0,0 @@ -//! Time units - -use core::fmt::Display; -use core::ops::{Div, Mul}; - -/// Hertz -#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug)] -pub struct Hertz(pub u32); - -impl Display for Hertz { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{} Hz", self.0) - } -} - -#[cfg(feature = "defmt")] -impl defmt::Format for Hertz { - fn format(&self, f: defmt::Formatter) { - defmt::write!(f, "{=u32} Hz", self.0) - } -} - -impl Hertz { - /// Create a `Hertz` from the given hertz. - pub const fn hz(hertz: u32) -> Self { - Self(hertz) - } - - /// Create a `Hertz` from the given kilohertz. - pub const fn khz(kilohertz: u32) -> Self { - Self(kilohertz * 1_000) - } - - /// Create a `Hertz` from the given megahertz. - pub const fn mhz(megahertz: u32) -> Self { - Self(megahertz * 1_000_000) - } -} - -/// This is a convenience shortcut for [`Hertz::hz`] -pub const fn hz(hertz: u32) -> Hertz { - Hertz::hz(hertz) -} - -/// This is a convenience shortcut for [`Hertz::khz`] -pub const fn khz(kilohertz: u32) -> Hertz { - Hertz::khz(kilohertz) -} - -/// This is a convenience shortcut for [`Hertz::mhz`] -pub const fn mhz(megahertz: u32) -> Hertz { - Hertz::mhz(megahertz) -} - -impl Mul for Hertz { - type Output = Hertz; - fn mul(self, rhs: u32) -> Self::Output { - Hertz(self.0 * rhs) - } -} - -impl Div for Hertz { - type Output = Hertz; - fn div(self, rhs: u32) -> Self::Output { - Hertz(self.0 / rhs) - } -} - -impl Mul for Hertz { - type Output = Hertz; - fn mul(self, rhs: u16) -> Self::Output { - self * (rhs as u32) - } -} - -impl Div for Hertz { - type Output = Hertz; - fn div(self, rhs: u16) -> Self::Output { - self / (rhs as u32) - } -} - -impl Mul for Hertz { - type Output = Hertz; - fn mul(self, rhs: u8) -> Self::Output { - self * (rhs as u32) - } -} - -impl Div for Hertz { - type Output = Hertz; - fn div(self, rhs: u8) -> Self::Output { - self / (rhs as u32) - } -} - -impl Div for Hertz { - type Output = u32; - fn div(self, rhs: Hertz) -> Self::Output { - self.0 / rhs.0 - } -} -- cgit From 517714c98e4b5dc4c7ee844527f5d33fdc342125 Mon Sep 17 00:00:00 2001 From: Irina Chiorean Date: Fri, 25 Jul 2025 18:00:49 +0300 Subject: feat: add RTC time driver --- embassy-nxp/Cargo.toml | 3 + embassy-nxp/src/lib.rs | 1 + embassy-nxp/src/time_driver/rtc.rs | 172 +++++++++++++++++++++++ examples/lpc55s69/Cargo.toml | 4 +- examples/lpc55s69/README.md | 12 ++ examples/lpc55s69/src/bin/blinky_embassy_time.rs | 26 ++++ 6 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 embassy-nxp/src/time_driver/rtc.rs create mode 100644 examples/lpc55s69/README.md create mode 100644 examples/lpc55s69/src/bin/blinky_embassy_time.rs diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 2644b0fa9..9fa48c4b9 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -50,6 +50,9 @@ log = ["dep:log"] ## Use Periodic Interrupt Timer (PIT) as the time driver for `embassy-time`, with a tick rate of 1 MHz time-driver-pit = ["_time_driver", "embassy-time?/tick-hz-1_000_000"] +## Use Real Time Clock (RTC) as the time driver for `embassy-time`, with a tick rate of 32768 Hz +time-driver-rtc = ["_time_driver", "embassy-time?/tick-hz-32_768"] + ## Reexport the PAC for the currently enabled chip at `embassy_nxp::pac` (unstable) unstable-pac = [] # This is unstable because semver-minor (non-breaking) releases of embassy-nxp may major-bump (breaking) the PAC version. diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs index 5e77fc0db..b2e910f7e 100644 --- a/embassy-nxp/src/lib.rs +++ b/embassy-nxp/src/lib.rs @@ -9,6 +9,7 @@ pub mod pint; #[cfg(feature = "_time_driver")] #[cfg_attr(feature = "time-driver-pit", path = "time_driver/pit.rs")] +#[cfg_attr(feature = "time-driver-rtc", path = "time_driver/rtc.rs")] mod time_driver; // This mod MUST go last, so that it sees all the `impl_foo!` macros diff --git a/embassy-nxp/src/time_driver/rtc.rs b/embassy-nxp/src/time_driver/rtc.rs new file mode 100644 index 000000000..94272e9c2 --- /dev/null +++ b/embassy-nxp/src/time_driver/rtc.rs @@ -0,0 +1,172 @@ +use core::cell::{Cell, RefCell}; +use core::task::Waker; + +use critical_section::CriticalSection; +use embassy_hal_internal::interrupt::{InterruptExt, Priority}; +use embassy_sync::blocking_mutex::CriticalSectionMutex as Mutex; +use embassy_time_driver::{time_driver_impl, Driver}; +use embassy_time_queue_utils::Queue; +use lpc55_pac::{interrupt, PMC, RTC, SYSCON}; +struct AlarmState { + timestamp: Cell, +} + +unsafe impl Send for AlarmState {} + +impl AlarmState { + const fn new() -> Self { + Self { + timestamp: Cell::new(u64::MAX), + } + } +} + +pub struct RtcDriver { + alarms: Mutex, + queue: Mutex>, +} + +time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { + alarms: Mutex::new(AlarmState::new()), + queue: Mutex::new(RefCell::new(Queue::new())), +}); +impl RtcDriver { + fn init(&'static self) { + let syscon = unsafe { &*SYSCON::ptr() }; + let pmc = unsafe { &*PMC::ptr() }; + let rtc = unsafe { &*RTC::ptr() }; + + syscon.ahbclkctrl0.modify(|_, w| w.rtc().enable()); + + // By default the RTC enters software reset. If for some reason it is + // not in reset, we enter and them promptly leave.q + rtc.ctrl.modify(|_, w| w.swreset().set_bit()); + rtc.ctrl.modify(|_, w| w.swreset().clear_bit()); + + // Select clock source - either XTAL or FRO + // pmc.rtcosc32k.write(|w| w.sel().xtal32k()); + pmc.rtcosc32k.write(|w| w.sel().fro32k()); + + // Start the RTC peripheral + rtc.ctrl.modify(|_, w| w.rtc_osc_pd().power_up()); + + // rtc.ctrl.modify(|_, w| w.rtc_en().clear_bit()); // EXTRA + + //reset/clear(?) counter + rtc.count.reset(); + //en rtc main counter + rtc.ctrl.modify(|_, w| w.rtc_en().set_bit()); + rtc.ctrl.modify(|_, w| w.rtc1khz_en().set_bit()); + // subsec counter enable + rtc.ctrl.modify(|_, w| w.rtc_subsec_ena().set_bit()); + + // enable irq + unsafe { + interrupt::RTC.set_priority(Priority::from(3)); + interrupt::RTC.enable(); + } + } + + fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool { + let rtc = unsafe { &*RTC::ptr() }; + let alarm = &self.alarms.borrow(cs); + alarm.timestamp.set(timestamp); + let now = self.now(); + + if timestamp <= now { + alarm.timestamp.set(u64::MAX); + return false; + } + + //time diff in sub-sec not ticks (32kHz) + let diff = timestamp - now; + let sec = (diff / 32768) as u32; + let subsec = (diff % 32768) as u32; + + let current_sec = rtc.count.read().val().bits(); + let target_sec = current_sec.wrapping_add(sec as u32); + + rtc.match_.write(|w| unsafe { w.matval().bits(target_sec) }); + rtc.wake.write(|w| unsafe { + let ms = (subsec * 1000) / 32768; + w.val().bits(ms as u16) + }); + if subsec > 0 { + let ms = (subsec * 1000) / 32768; + rtc.wake.write(|w| unsafe { w.val().bits(ms as u16) }); + } + rtc.ctrl.modify(|_, w| w.alarm1hz().clear_bit().wake1khz().clear_bit()); + true + } + + fn on_interrupt(&self) { + critical_section::with(|cs| { + let rtc = unsafe { &*RTC::ptr() }; + let flags = rtc.ctrl.read(); + if flags.alarm1hz().bit_is_clear() { + rtc.ctrl.modify(|_, w| w.alarm1hz().set_bit()); + self.trigger_alarm(cs); + } + + if flags.wake1khz().bit_is_clear() { + rtc.ctrl.modify(|_, w| w.wake1khz().set_bit()); + self.trigger_alarm(cs); + } + }); + } + + fn trigger_alarm(&self, cs: CriticalSection) { + let alarm = &self.alarms.borrow(cs); + alarm.timestamp.set(u64::MAX); + let mut next = self.queue.borrow(cs).borrow_mut().next_expiration(self.now()); + if next == u64::MAX { + // no scheduled events, skipping + return; + } + while !self.set_alarm(cs, next) { + next = self.queue.borrow(cs).borrow_mut().next_expiration(self.now()); + if next == u64::MAX { + //no next event found after retry + return; + } + } + } +} + +impl Driver for RtcDriver { + fn now(&self) -> u64 { + let rtc = unsafe { &*RTC::ptr() }; + + loop { + let sec1 = rtc.count.read().val().bits() as u64; + let sub1 = rtc.subsec.read().subsec().bits() as u64; + let sec2 = rtc.count.read().val().bits() as u64; + let sub2 = rtc.subsec.read().subsec().bits() as u64; + + if sec1 == sec2 && sub1 == sub2 { + return sec1 * 32768 + sub1; + } + } + } + + fn schedule_wake(&self, at: u64, waker: &Waker) { + critical_section::with(|cs| { + let mut queue = self.queue.borrow(cs).borrow_mut(); + + if queue.schedule_wake(at, waker) { + let mut next = queue.next_expiration(self.now()); + while !self.set_alarm(cs, next) { + next = queue.next_expiration(self.now()); + } + } + }) + } +} +#[cortex_m_rt::interrupt] +fn RTC() { + DRIVER.on_interrupt(); +} + +pub fn init() { + DRIVER.init(); +} diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index 5faec13da..f9bd409e2 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml @@ -6,10 +6,10 @@ license = "MIT OR Apache-2.0" [dependencies] -embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55", "rt", "defmt"] } +embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55", "rt", "defmt", "time-driver-rtc"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } +embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = { version = "0.7.0"} diff --git a/examples/lpc55s69/README.md b/examples/lpc55s69/README.md new file mode 100644 index 000000000..d200f4f99 --- /dev/null +++ b/examples/lpc55s69/README.md @@ -0,0 +1,12 @@ +# LPC55S69 Examples + +## Available examples: +- blinky_nop: Blink the integrated RED LED using nops as delay. Useful for flashing simple and known-good software on board. +- button_executor: Turn on/off an LED by pressing the USER button. Demonstrates how to use the PINT and GPIO drivers. +- blinky_embassy_time: Blink the integrated RED LED using `embassy-time`. Demonstrates how to use the time-driver that uses RTC. + +## Important Notes + +On older version of probe-rs, some examples (such as `blinky_embassy_time`) do not work directly after flashing and the board must be reset after flashing. It is reccomended to update the version of probe-rs to the latest one. + +When developing drivers for this board, probe-rs might not be able to flash the board after entering a fault. Either reset the board to clear the fault, or use NXP's proprietary software `LinkServer`/`LinkFlash` to bring the board back to a known-good state. \ No newline at end of file diff --git a/examples/lpc55s69/src/bin/blinky_embassy_time.rs b/examples/lpc55s69/src/bin/blinky_embassy_time.rs new file mode 100644 index 000000000..adc3d8bd3 --- /dev/null +++ b/examples/lpc55s69/src/bin/blinky_embassy_time.rs @@ -0,0 +1,26 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_nxp::gpio::{Level, Output}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_halt as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nxp::init(Default::default()); + info!("Initialization complete"); + let mut led = Output::new(p.PIO1_6, Level::Low); + + info!("Entering main loop"); + loop { + info!("led off!"); + led.set_high(); + Timer::after_millis(500).await; + + info!("led on!"); + led.set_low(); + Timer::after_millis(500).await; + } +} -- cgit From e78959ed67f8c89f2adc78f5e4580c62d3c66081 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Mon, 4 Aug 2025 13:10:39 +0200 Subject: mspm0-I2C: replace examples for mspm0l1306 & mspm0g3507 with AD5171 --- examples/mspm0g3507/src/bin/i2c.rs | 26 ++++++++++++++++++-------- examples/mspm0g3507/src/bin/i2c_async.rs | 26 ++++++++++++++++++-------- examples/mspm0l1306/src/bin/i2c.rs | 28 +++++++++++++++++++--------- examples/mspm0l1306/src/bin/i2c_async.rs | 26 ++++++++++++++++++-------- 4 files changed, 73 insertions(+), 33 deletions(-) diff --git a/examples/mspm0g3507/src/bin/i2c.rs b/examples/mspm0g3507/src/bin/i2c.rs index 2e3bf2ca1..8d1ed1726 100644 --- a/examples/mspm0g3507/src/bin/i2c.rs +++ b/examples/mspm0g3507/src/bin/i2c.rs @@ -1,7 +1,7 @@ //! This example uses FIFO with polling, and the maximum FIFO size is 8. //! Refer to async example to handle larger packets. //! -//! This uses the virtual COM port provided on the LP-MSPM0G3507 board. +//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0G3507 board. #![no_std] #![no_main] @@ -9,6 +9,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_mspm0::i2c::{Config, I2c}; +use embassy_time::Timer; use {defmt_rtt as _, panic_halt as _}; const ADDRESS: u8 = 0x6a; @@ -23,13 +24,22 @@ async fn main(_spawner: Spawner) -> ! { let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, Config::default())); - let mut to_read = [0u8; 1]; - let to_write: u8 = 0x0F; + let mut pot_value: u8 = 0; - match i2c.blocking_write_read(ADDRESS, &[to_write], &mut to_read) { - Ok(()) => info!("Register {}: {}", to_write, to_read[0]), - Err(e) => error!("I2c Error: {:?}", e), - } + loop { + let to_write = [0u8, pot_value]; + + match i2c.blocking_write(ADDRESS, &to_write) { + Ok(()) => info!("New potentioemter value: {}", pot_value), + Err(e) => error!("I2c Error: {:?}", e), + } - loop {} + pot_value += 1; + // if reached 64th position (max) + // start over from lowest value + if pot_value == 64 { + pot_value = 0; + } + Timer::after_millis(500).await; + } } diff --git a/examples/mspm0g3507/src/bin/i2c_async.rs b/examples/mspm0g3507/src/bin/i2c_async.rs index 294550605..d486e2a03 100644 --- a/examples/mspm0g3507/src/bin/i2c_async.rs +++ b/examples/mspm0g3507/src/bin/i2c_async.rs @@ -1,6 +1,6 @@ //! The example uses FIFO and interrupts, wrapped in async API. //! -//! This uses the virtual COM port provided on the LP-MSPM0G3507 board. +//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0G3507 board. #![no_std] #![no_main] @@ -10,6 +10,7 @@ use embassy_executor::Spawner; use embassy_mspm0::bind_interrupts; use embassy_mspm0::i2c::{Config, I2c, InterruptHandler}; use embassy_mspm0::peripherals::I2C1; +use embassy_time::Timer; use {defmt_rtt as _, panic_halt as _}; const ADDRESS: u8 = 0x6a; @@ -28,13 +29,22 @@ async fn main(_spawner: Spawner) -> ! { let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default())); - let mut to_read = [1u8; 17]; - let to_write = [0u8; 17]; + let mut pot_value: u8 = 0; - match i2c.async_write_read(ADDRESS, &to_write, &mut to_read).await { - Ok(()) => info!("Register {}: {}", to_write, to_read[0]), - Err(e) => error!("I2c Error: {:?}", e), - } + loop { + let to_write = [0u8, pot_value]; + + match i2c.async_write(ADDRESS, &to_write).await { + Ok(()) => info!("New potentioemter value: {}", pot_value), + Err(e) => error!("I2c Error: {:?}", e), + } - loop {} + pot_value += 1; + // if reached 64th position (max) + // start over from lowest value + if pot_value == 64 { + pot_value = 0; + } + Timer::after_millis(500).await; + } } diff --git a/examples/mspm0l1306/src/bin/i2c.rs b/examples/mspm0l1306/src/bin/i2c.rs index 51327dff5..e8801c485 100644 --- a/examples/mspm0l1306/src/bin/i2c.rs +++ b/examples/mspm0l1306/src/bin/i2c.rs @@ -1,7 +1,7 @@ //! This example uses FIFO with polling, and the maximum FIFO size is 8. //! Refer to async example to handle larger packets. //! -//! This uses the virtual COM port provided on the LP-MSPM0L1306 board. +//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0L1306 board. #![no_std] #![no_main] @@ -9,9 +9,10 @@ use defmt::*; use embassy_executor::Spawner; use embassy_mspm0::i2c::{Config, I2c}; +use embassy_time::Timer; use {defmt_rtt as _, panic_halt as _}; -const ADDRESS: u8 = 0x6a; +const ADDRESS: u8 = 0x2c; #[embassy_executor::main] async fn main(_spawner: Spawner) -> ! { @@ -23,13 +24,22 @@ async fn main(_spawner: Spawner) -> ! { let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, Config::default())); - let mut to_read = [0u8; 1]; - let to_write: u8 = 0x0F; + let mut pot_value: u8 = 0; - match i2c.blocking_write_read(ADDRESS, &[to_write], &mut to_read) { - Ok(()) => info!("Register {}: {}", to_write, to_read[0]), - Err(e) => error!("I2c Error: {:?}", e), - } + loop { + let to_write = [0u8, pot_value]; + + match i2c.blocking_write(ADDRESS, &to_write) { + Ok(()) => info!("New potentioemter value: {}", pot_value), + Err(e) => error!("I2c Error: {:?}", e), + } - loop {} + pot_value += 1; + // if reached 64th position (max) + // start over from lowest value + if pot_value == 64 { + pot_value = 0; + } + Timer::after_millis(500).await; + } } diff --git a/examples/mspm0l1306/src/bin/i2c_async.rs b/examples/mspm0l1306/src/bin/i2c_async.rs index 74826bcc4..c4a6938ff 100644 --- a/examples/mspm0l1306/src/bin/i2c_async.rs +++ b/examples/mspm0l1306/src/bin/i2c_async.rs @@ -1,6 +1,6 @@ //! The example uses FIFO and interrupts, wrapped in async API. //! -//! This uses the virtual COM port provided on the LP-MSPM0L1306 board. +//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0L1306 board. #![no_std] #![no_main] @@ -10,6 +10,7 @@ use embassy_executor::Spawner; use embassy_mspm0::bind_interrupts; use embassy_mspm0::i2c::{Config, I2c, InterruptHandler}; use embassy_mspm0::peripherals::I2C0; +use embassy_time::Timer; use {defmt_rtt as _, panic_halt as _}; const ADDRESS: u8 = 0x6a; @@ -28,13 +29,22 @@ async fn main(_spawner: Spawner) -> ! { let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default())); - let mut to_read = [1u8; 17]; - let to_write = [0u8; 17]; + let mut pot_value: u8 = 0; - match i2c.async_write_read(ADDRESS, &to_write, &mut to_read).await { - Ok(()) => info!("Register {}: {}", to_write, to_read[0]), - Err(e) => error!("I2c Error: {:?}", e), - } + loop { + let to_write = [0u8, pot_value]; + + match i2c.async_write(ADDRESS, &to_write).await { + Ok(()) => info!("New potentioemter value: {}", pot_value), + Err(e) => error!("I2c Error: {:?}", e), + } - loop {} + pot_value += 1; + // if reached 64th position (max) + // start over from lowest value + if pot_value == 64 { + pot_value = 0; + } + Timer::after_millis(500).await; + } } -- cgit From 9ca44b519ac707f8a95fba55d72d4bf09ccb44c0 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 4 Aug 2025 14:07:30 +0200 Subject: chore: bump nrf and rp hal versions --- cyw43-pio/Cargo.toml | 2 +- docs/examples/basic/Cargo.toml | 2 +- embassy-boot-nrf/Cargo.toml | 2 +- embassy-boot-rp/Cargo.toml | 2 +- examples/boot/application/nrf/Cargo.toml | 2 +- examples/boot/application/rp/Cargo.toml | 2 +- examples/nrf-rtos-trace/Cargo.toml | 2 +- examples/nrf51/Cargo.toml | 2 +- examples/nrf52810/Cargo.toml | 2 +- examples/nrf52840-rtic/Cargo.toml | 2 +- examples/nrf52840/Cargo.toml | 2 +- examples/nrf5340/Cargo.toml | 2 +- examples/nrf54l15/Cargo.toml | 2 +- examples/nrf9151/ns/Cargo.toml | 2 +- examples/nrf9151/s/Cargo.toml | 2 +- examples/nrf9160/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- tests/nrf/Cargo.toml | 2 +- tests/rp/Cargo.toml | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index d60793bdc..d6e270537 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -11,7 +11,7 @@ documentation = "https://docs.embassy.dev/cyw43-pio" [dependencies] cyw43 = { version = "0.4.0", path = "../cyw43" } -embassy-rp = { version = "0.6.0", path = "../embassy-rp" } +embassy-rp = { version = "0.7.0", path = "../embassy-rp" } fixed = "1.23.1" defmt = { version = "1.0.1", optional = true } diff --git a/docs/examples/basic/Cargo.toml b/docs/examples/basic/Cargo.toml index 32e326134..15fd42703 100644 --- a/docs/examples/basic/Cargo.toml +++ b/docs/examples/basic/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.8.0", path = "../../../embassy-executor", features = ["defmt", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt"] } -embassy-nrf = { version = "0.5.0", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } +embassy-nrf = { version = "0.6.0", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index 81479759c..0706ed28a 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -25,7 +25,7 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4.17", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } -embassy-nrf = { version = "0.5.0", path = "../embassy-nrf", default-features = false } +embassy-nrf = { version = "0.6.0", path = "../embassy-nrf", default-features = false } embassy-boot = { version = "0.5.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } diff --git a/embassy-boot-rp/Cargo.toml b/embassy-boot-rp/Cargo.toml index 8ca999f67..71ea73b0c 100644 --- a/embassy-boot-rp/Cargo.toml +++ b/embassy-boot-rp/Cargo.toml @@ -25,7 +25,7 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } -embassy-rp = { version = "0.6.0", path = "../embassy-rp", default-features = false } +embassy-rp = { version = "0.7.0", path = "../embassy-rp", default-features = false } embassy-boot = { version = "0.5.0", path = "../embassy-boot" } embassy-time = { version = "0.4.0", path = "../embassy-time" } diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 31b99709e..165e7a79b 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } -embassy-nrf = { version = "0.5.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } +embassy-nrf = { version = "0.6.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } embassy-boot = { version = "0.5.0", path = "../../../../embassy-boot", features = [] } embassy-boot-nrf = { version = "0.6.0", path = "../../../../embassy-boot-nrf", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index 199ef52bf..db564984c 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } -embassy-rp = { version = "0.6.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } +embassy-rp = { version = "0.7.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } embassy-boot-rp = { version = "0.6.0", path = "../../../../embassy-boot-rp", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index 029fd62a3..df592154c 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -18,7 +18,7 @@ log = [ embassy-sync = { version = "0.7.0", path = "../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } embassy-time = { version = "0.4.0", path = "../../embassy-time" } -embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml index ddac7e2c9..524feca38 100644 --- a/examples/nrf51/Cargo.toml +++ b/examples/nrf51/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } +embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index f9069d6c4..37c8fee7b 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index 932c88eca..5afb0c97a 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml @@ -11,7 +11,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } embassy-time-queue-utils = { version = "0.2", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } -embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index c25e33e82..4d27a459c 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io = { version = "0.6.0", features = ["defmt-03"] } diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 7e11f123f..7f38f9035 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embedded-io-async = { version = "0.6.1" } diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index 515514cb0..faa3a4abe 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml index f729e410b..e7551723d 100644 --- a/examples/nrf9151/ns/Cargo.toml +++ b/examples/nrf9151/ns/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.8.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.5.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.6.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml index 175de0e5b..7f675c5e1 100644 --- a/examples/nrf9151/s/Cargo.toml +++ b/examples/nrf9151/s/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.8.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.5.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.6.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml index 03b3bc702..263986c4e 100644 --- a/examples/nrf9160/Cargo.toml +++ b/examples/nrf9160/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 7fa84c7ec..3f9b71bcc 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -10,7 +10,7 @@ embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal", embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-rp = { version = "0.6.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } +embassy-rp = { version = "0.7.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 42d112c75..ffc03abe4 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -10,7 +10,7 @@ embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal", embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-rp = { version = "0.6.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } +embassy-rp = { version = "0.7.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index 3e1113ccf..bc7ab9891 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -11,7 +11,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt", ] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.5.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } embassy-net-esp-hosted = { version = "0.2.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 1f2bbdb22..711b6f733 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -15,7 +15,7 @@ teleprobe-meta = "1.1" embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", ] } -embassy-rp = { version = "0.6.0", path = "../../embassy-rp", features = [ "defmt", "unstable-pac", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } +embassy-rp = { version = "0.7.0", path = "../../embassy-rp", features = [ "defmt", "unstable-pac", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } -- cgit From bcc904c187ab69aa34bbbafd3166ec6aacb08bba Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 4 Aug 2025 14:09:25 +0200 Subject: chore: Release embassy-rp version 0.7.0 --- embassy-rp/CHANGELOG.md | 2 ++ embassy-rp/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md index 36e1ea9b4..25c3e80ad 100644 --- a/embassy-rp/CHANGELOG.md +++ b/embassy-rp/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.7.0 - 2025-08-04 + ## 0.6.0 - 2025-07-16 - update to latest embassy-usb-driver diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index bb28d21c8..d48b27ef5 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-rp" -version = "0.6.0" +version = "0.7.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Embassy Hardware Abstraction Layer (HAL) for the Raspberry Pi RP2040 or RP235x microcontroller" -- cgit From 6ba76e817670f42e8962fc0e3a312e5aed94587f Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 4 Aug 2025 14:10:24 +0200 Subject: chore: Release embassy-nrf version 0.6.0 --- embassy-nrf/CHANGELOG.md | 2 ++ embassy-nrf/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index a4cb8ceaf..5b36d0aad 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.6.0 - 2025-08-04 + ## 0.5.0 - 2025-07-16 - changed: update to latest embassy-usb-driver diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index a3df1b905..95ec83824 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-nrf" -version = "0.5.0" +version = "0.6.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Embassy Hardware Abstraction Layer (HAL) for nRF series microcontrollers" -- cgit From 206cf0e451e8cd96b79b34630129257fcc5387ea Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 4 Aug 2025 14:20:55 +0200 Subject: fix: add missing entries in changelog --- embassy-nrf/CHANGELOG.md | 2 ++ embassy-rp/CHANGELOG.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index 5b36d0aad..5709b28b5 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 0.6.0 - 2025-08-04 +- changed: update to latest embassy-time-queue-utils + ## 0.5.0 - 2025-07-16 - changed: update to latest embassy-usb-driver diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md index 25c3e80ad..c5bc55941 100644 --- a/embassy-rp/CHANGELOG.md +++ b/embassy-rp/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 0.7.0 - 2025-08-04 +- changed: update to latest embassy-time-queue-utils + ## 0.6.0 - 2025-07-16 - update to latest embassy-usb-driver -- cgit From ee053f0babb9e31c3092b600e3013f1d3044fbc7 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 4 Aug 2025 14:55:46 +0200 Subject: chore: bump versions --- embassy-boot-nrf/Cargo.toml | 2 +- embassy-boot-rp/Cargo.toml | 2 +- embassy-boot-stm32/Cargo.toml | 2 +- embassy-usb-dfu/Cargo.toml | 2 +- examples/boot/application/nrf/Cargo.toml | 4 ++-- examples/boot/application/rp/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index 0706ed28a..6278006da 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -26,7 +26,7 @@ log = { version = "0.4.17", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-nrf = { version = "0.6.0", path = "../embassy-nrf", default-features = false } -embassy-boot = { version = "0.5.0", path = "../embassy-boot" } +embassy-boot = { version = "0.6.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" diff --git a/embassy-boot-rp/Cargo.toml b/embassy-boot-rp/Cargo.toml index 71ea73b0c..fa2f4b39e 100644 --- a/embassy-boot-rp/Cargo.toml +++ b/embassy-boot-rp/Cargo.toml @@ -26,7 +26,7 @@ log = { version = "0.4", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-rp = { version = "0.7.0", path = "../embassy-rp", default-features = false } -embassy-boot = { version = "0.5.0", path = "../embassy-boot" } +embassy-boot = { version = "0.6.0", path = "../embassy-boot" } embassy-time = { version = "0.4.0", path = "../embassy-time" } cortex-m = { version = "0.7.6" } diff --git a/embassy-boot-stm32/Cargo.toml b/embassy-boot-stm32/Cargo.toml index b92d06c54..54bbd5f77 100644 --- a/embassy-boot-stm32/Cargo.toml +++ b/embassy-boot-stm32/Cargo.toml @@ -26,7 +26,7 @@ log = { version = "0.4", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-stm32 = { version = "0.2.0", path = "../embassy-stm32", default-features = false } -embassy-boot = { version = "0.5.0", path = "../embassy-boot" } +embassy-boot = { version = "0.6.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" diff --git a/embassy-usb-dfu/Cargo.toml b/embassy-usb-dfu/Cargo.toml index 011046ba4..1c88e3977 100644 --- a/embassy-usb-dfu/Cargo.toml +++ b/embassy-usb-dfu/Cargo.toml @@ -31,7 +31,7 @@ log = { version = "0.4.17", optional = true } bitflags = "2.4.1" cortex-m = { version = "0.7.7", features = ["inline-asm"], optional = true } -embassy-boot = { version = "0.5.0", path = "../embassy-boot" } +embassy-boot = { version = "0.6.0", path = "../embassy-boot" } embassy-futures = { version = "0.1.1", path = "../embassy-futures" } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time" } diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 165e7a79b..af2ba4638 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -9,8 +9,8 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } embassy-nrf = { version = "0.6.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } -embassy-boot = { version = "0.5.0", path = "../../../../embassy-boot", features = [] } -embassy-boot-nrf = { version = "0.6.0", path = "../../../../embassy-boot-nrf", features = [] } +embassy-boot = { version = "0.6.0", path = "../../../../embassy-boot", features = [] } +embassy-boot-nrf = { version = "0.7.0", path = "../../../../embassy-boot-nrf", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index db564984c..ccd34e802 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } embassy-rp = { version = "0.7.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } -embassy-boot-rp = { version = "0.6.0", path = "../../../../embassy-boot-rp", features = [] } +embassy-boot-rp = { version = "0.7.0", path = "../../../../embassy-boot-rp", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = "1.0.1" diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 3f9b71bcc..e09caa1d6 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -17,7 +17,7 @@ embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", fea embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.5.0", path = "../../embassy-usb-logger" } cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } -cyw43-pio = { version = "0.5.1", path = "../../cyw43-pio", features = ["defmt"] } +cyw43-pio = { version = "0.6.0", path = "../../cyw43-pio", features = ["defmt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index ffc03abe4..eecd98894 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -17,7 +17,7 @@ embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", fea embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.5.0", path = "../../embassy-usb-logger" } cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } -cyw43-pio = { version = "0.5.1", path = "../../cyw43-pio", features = ["defmt"] } +cyw43-pio = { version = "0.6.0", path = "../../cyw43-pio", features = ["defmt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" -- cgit From 8047a59d820251ea9ded8b318051ef62e9cf8521 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 4 Aug 2025 15:01:20 +0200 Subject: chore: Release embassy-boot version 0.6.0 --- embassy-boot/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-boot/Cargo.toml b/embassy-boot/Cargo.toml index 4dde4a3ff..4e2eb2695 100644 --- a/embassy-boot/Cargo.toml +++ b/embassy-boot/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot" -version = "0.5.0" +version = "0.6.0" description = "A lightweight bootloader supporting firmware updates in a power-fail-safe way, with trial boots and rollbacks." license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" -- cgit From bad6441b42e0099459637a747bd8541b8cd38390 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 4 Aug 2025 15:02:01 +0200 Subject: chore: Release embassy-boot-nrf version 0.7.0 --- embassy-boot-nrf/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index 6278006da..9d02f61e3 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-nrf" -version = "0.6.0" +version = "0.7.0" description = "Bootloader lib for nRF chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" -- cgit From 80c3d64262c93791dbfb7a5873a8b05ebe41956a Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 4 Aug 2025 15:03:04 +0200 Subject: chore: Release embassy-boot-rp version 0.7.0 --- embassy-boot-rp/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-boot-rp/Cargo.toml b/embassy-boot-rp/Cargo.toml index fa2f4b39e..71888c8b0 100644 --- a/embassy-boot-rp/Cargo.toml +++ b/embassy-boot-rp/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-rp" -version = "0.6.0" +version = "0.7.0" description = "Bootloader lib for RP2040 chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" -- cgit From 31db37aeea8285e0278c3a94297a9dce9bb2e861 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 4 Aug 2025 15:05:02 +0200 Subject: chore: Release cyw43-pio version 0.6.0 --- cyw43-pio/CHANGELOG.md | 2 ++ cyw43-pio/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cyw43-pio/CHANGELOG.md b/cyw43-pio/CHANGELOG.md index 218271e15..3b792948b 100644 --- a/cyw43-pio/CHANGELOG.md +++ b/cyw43-pio/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.6.0 - 2025-08-04 + ## 0.5.1 - 2025-07-16 ## 0.5.0 - 2025-07-15 diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index d6e270537..a45adeccb 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cyw43-pio" -version = "0.5.1" +version = "0.6.0" edition = "2021" description = "RP2040 PIO SPI implementation for cyw43" keywords = ["embedded", "cyw43", "embassy-net", "embedded-hal-async", "wifi"] -- cgit From 6d38e8b3060e4408ce493aee259048e5cf55dbb0 Mon Sep 17 00:00:00 2001 From: Magnus Nordlander Date: Tue, 5 Aug 2025 09:34:09 +0200 Subject: Remove regs since it doesn’t really make sense to return the QMI peripheral from QMI CS1. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- embassy-rp/src/psram.rs | 9 +++++---- embassy-rp/src/qmi_cs1.rs | 13 ++----------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/embassy-rp/src/psram.rs b/embassy-rp/src/psram.rs index 190a7eb09..6da852b26 100644 --- a/embassy-rp/src/psram.rs +++ b/embassy-rp/src/psram.rs @@ -10,11 +10,12 @@ #![cfg(feature = "_rp235x")] -use crate::qmi_cs1::QmiCs1; -use crate::{pac, peripherals}; use critical_section::{acquire, release, CriticalSection, RestoreState}; use embassy_hal_internal::Peri; +use crate::qmi_cs1::QmiCs1; +use crate::{pac, peripherals}; + /// PSRAM errors. #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -204,6 +205,7 @@ impl Config { /// PSRAM driver. pub struct Psram<'d> { + #[allow(dead_code)] qmi_cs1: QmiCs1<'d>, size: usize, } @@ -218,8 +220,7 @@ impl<'d> Psram<'d> { config: Config, ) -> Result { let qmi_cs1 = QmiCs1::new(qmi_cs1_peripheral, cs1); - let qmi = qmi_cs1.regs(); - + let qmi = pac::QMI; let xip = pac::XIP_CTRL; // Verify PSRAM device if requested diff --git a/embassy-rp/src/qmi_cs1.rs b/embassy-rp/src/qmi_cs1.rs index 4e2dc0dbf..ada420432 100644 --- a/embassy-rp/src/qmi_cs1.rs +++ b/embassy-rp/src/qmi_cs1.rs @@ -34,17 +34,10 @@ impl<'d> QmiCs1<'d> { Self { _inner: qmi_cs1 } } - - /// Get access to the QMI peripheral registers. - /// - /// This allows low-level access to configure the QMI controller for specific memory devices. - pub fn regs(&self) -> pac::qmi::Qmi { - pac::QMI - } } trait SealedInstance { - fn regs(&self) -> pac::qmi::Qmi; + } /// QMI CS1 instance trait. @@ -52,9 +45,7 @@ trait SealedInstance { pub trait Instance: SealedInstance + PeripheralType {} impl SealedInstance for peripherals::QMI_CS1 { - fn regs(&self) -> pac::qmi::Qmi { - pac::QMI - } + } impl Instance for peripherals::QMI_CS1 {} -- cgit From 8965a13da4149a6f1a56c5abcf879ff8ad822844 Mon Sep 17 00:00:00 2001 From: Magnus Nordlander Date: Tue, 5 Aug 2025 09:53:16 +0200 Subject: Interface changes and added example --- embassy-rp/src/psram.rs | 7 ++---- examples/rp235x/src/bin/psram.rs | 49 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 examples/rp235x/src/bin/psram.rs diff --git a/embassy-rp/src/psram.rs b/embassy-rp/src/psram.rs index 6da852b26..a4d619565 100644 --- a/embassy-rp/src/psram.rs +++ b/embassy-rp/src/psram.rs @@ -11,10 +11,9 @@ #![cfg(feature = "_rp235x")] use critical_section::{acquire, release, CriticalSection, RestoreState}; -use embassy_hal_internal::Peri; use crate::qmi_cs1::QmiCs1; -use crate::{pac, peripherals}; +use crate::pac; /// PSRAM errors. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -215,11 +214,9 @@ impl<'d> Psram<'d> { /// /// This will detect the PSRAM device and configure it for memory-mapped access. pub fn new( - qmi_cs1_peripheral: Peri<'d, peripherals::QMI_CS1>, - cs1: Peri<'d, impl crate::qmi_cs1::QmiCs1Pin>, + qmi_cs1: QmiCs1<'d>, config: Config, ) -> Result { - let qmi_cs1 = QmiCs1::new(qmi_cs1_peripheral, cs1); let qmi = pac::QMI; let xip = pac::XIP_CTRL; diff --git a/examples/rp235x/src/bin/psram.rs b/examples/rp235x/src/bin/psram.rs new file mode 100644 index 000000000..c0e41dd9e --- /dev/null +++ b/examples/rp235x/src/bin/psram.rs @@ -0,0 +1,49 @@ +//! This example tests an APS6404L PSRAM chip connected to the RP235x +//! It fills the PSRAM with alternating patterns and reads back a value +//! +//! In this example, the PSRAM CS is connected to Pin 0. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; +use core::slice; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let config = embassy_rp::config::Config::default(); + let p = embassy_rp::init(config); + let psram_config = embassy_rp::psram::Config::aps6404l(); + let psram = embassy_rp::psram::Psram::new(embassy_rp::qmi_cs1::QmiCs1::new(p.QMI_CS1, p.PIN_0), psram_config); + + let Ok(psram) = psram else { + error!("PSRAM not found"); + loop { + Timer::after_secs(1).await; + }; + }; + + let psram_slice = unsafe { + let psram_ptr = psram.base_address(); + let slice: &'static mut [u8] = + slice::from_raw_parts_mut(psram_ptr, psram.size() as usize); + slice + }; + + loop { + psram_slice.fill(0x55); + info!("PSRAM filled with 0x55"); + let at_addr = psram_slice[0x100]; + info!("Read from PSRAM at address 0x100: 0x{:02x}", at_addr); + Timer::after_secs(1).await; + + psram_slice.fill(0xAA); + info!("PSRAM filled with 0xAA"); + let at_addr = psram_slice[0x100]; + info!("Read from PSRAM at address 0x100: 0x{:02x}", at_addr); + Timer::after_secs(1).await; + } +} -- cgit From 1e918331184f6fb11c08e5c5c7019d50452239dc Mon Sep 17 00:00:00 2001 From: Magnus Nordlander Date: Tue, 5 Aug 2025 09:58:33 +0200 Subject: Apply rustfmt --- embassy-rp/src/psram.rs | 7 ++----- embassy-rp/src/qmi_cs1.rs | 8 ++------ examples/rp235x/src/bin/psram.rs | 7 +++---- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/embassy-rp/src/psram.rs b/embassy-rp/src/psram.rs index a4d619565..0823b4be6 100644 --- a/embassy-rp/src/psram.rs +++ b/embassy-rp/src/psram.rs @@ -12,8 +12,8 @@ use critical_section::{acquire, release, CriticalSection, RestoreState}; -use crate::qmi_cs1::QmiCs1; use crate::pac; +use crate::qmi_cs1::QmiCs1; /// PSRAM errors. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -213,10 +213,7 @@ impl<'d> Psram<'d> { /// Create a new PSRAM driver instance. /// /// This will detect the PSRAM device and configure it for memory-mapped access. - pub fn new( - qmi_cs1: QmiCs1<'d>, - config: Config, - ) -> Result { + pub fn new(qmi_cs1: QmiCs1<'d>, config: Config) -> Result { let qmi = pac::QMI; let xip = pac::XIP_CTRL; diff --git a/embassy-rp/src/qmi_cs1.rs b/embassy-rp/src/qmi_cs1.rs index ada420432..b8ae41e35 100644 --- a/embassy-rp/src/qmi_cs1.rs +++ b/embassy-rp/src/qmi_cs1.rs @@ -36,17 +36,13 @@ impl<'d> QmiCs1<'d> { } } -trait SealedInstance { - -} +trait SealedInstance {} /// QMI CS1 instance trait. #[allow(private_bounds)] pub trait Instance: SealedInstance + PeripheralType {} -impl SealedInstance for peripherals::QMI_CS1 { - -} +impl SealedInstance for peripherals::QMI_CS1 {} impl Instance for peripherals::QMI_CS1 {} diff --git a/examples/rp235x/src/bin/psram.rs b/examples/rp235x/src/bin/psram.rs index c0e41dd9e..b2ddf91c9 100644 --- a/examples/rp235x/src/bin/psram.rs +++ b/examples/rp235x/src/bin/psram.rs @@ -6,11 +6,11 @@ #![no_std] #![no_main] +use core::slice; use defmt::*; use embassy_executor::Spawner; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; -use core::slice; #[embassy_executor::main] async fn main(_spawner: Spawner) { @@ -23,13 +23,12 @@ async fn main(_spawner: Spawner) { error!("PSRAM not found"); loop { Timer::after_secs(1).await; - }; + } }; let psram_slice = unsafe { let psram_ptr = psram.base_address(); - let slice: &'static mut [u8] = - slice::from_raw_parts_mut(psram_ptr, psram.size() as usize); + let slice: &'static mut [u8] = slice::from_raw_parts_mut(psram_ptr, psram.size() as usize); slice }; -- cgit From 0e913319f240a96cef43fd0662f1759fbca8ac07 Mon Sep 17 00:00:00 2001 From: Magnus Nordlander Date: Tue, 5 Aug 2025 09:59:34 +0200 Subject: Manual rustfmt fix --- examples/rp235x/src/bin/psram.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/rp235x/src/bin/psram.rs b/examples/rp235x/src/bin/psram.rs index b2ddf91c9..716ac7695 100644 --- a/examples/rp235x/src/bin/psram.rs +++ b/examples/rp235x/src/bin/psram.rs @@ -7,6 +7,7 @@ #![no_main] use core::slice; + use defmt::*; use embassy_executor::Spawner; use embassy_time::Timer; -- cgit From ccbdf9cbf1f63d017fd8666accca503e0388f045 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Tue, 5 Aug 2025 01:00:29 -0700 Subject: Updated stm32-metapac for GPDMA1 fix on STM32WBA --- embassy-stm32/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 535de7fc8..145a89b77 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-0cf2bd99dd5ebbaab9574b4fb42c12f358ff2ed8" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-cad609e02a866422ffdbb8e07be26311cfdd07d9" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-0cf2bd99dd5ebbaab9574b4fb42c12f358ff2ed8", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-cad609e02a866422ffdbb8e07be26311cfdd07d9", default-features = false, features = ["metadata"] } [features] default = ["rt"] -- cgit From 88934c42d3b70d1da21808436daaeb7210580ab4 Mon Sep 17 00:00:00 2001 From: Magnus Nordlander Date: Tue, 5 Aug 2025 12:52:20 +0200 Subject: Gate ARM-specific assembly using cfg --- embassy-rp/src/psram.rs | 386 +++++++++++++++++++++++++----------------------- 1 file changed, 200 insertions(+), 186 deletions(-) diff --git a/embassy-rp/src/psram.rs b/embassy-rp/src/psram.rs index 0823b4be6..ae43dd5aa 100644 --- a/embassy-rp/src/psram.rs +++ b/embassy-rp/src/psram.rs @@ -255,8 +255,6 @@ impl<'d> Psram<'d> { #[inline(never)] fn verify_aps6404l(qmi: &pac::qmi::Qmi, expected_size: usize) -> Result<(), Error> { // APS6404L-specific constants - const RESET_ENABLE_CMD: u8 = 0xf5; - const READ_ID_CMD: u8 = 0x9f; const EXPECTED_KGD: u8 = 0x5D; crate::multicore::pause_core1(); core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); @@ -279,126 +277,7 @@ impl<'d> Psram<'d> { let _cs = unsafe { CriticalSection::new() }; - let qmi_base = qmi.as_ptr() as usize; - - #[allow(unused_assignments)] - let mut kgd: u32 = 0; - #[allow(unused_assignments)] - let mut eid: u32 = 0; - - unsafe { - core::arch::asm!( - // Configure DIRECT_CSR: shift clkdiv (30) to bits 29:22 and set EN (bit 0) - "movs {temp}, #30", - "lsls {temp}, {temp}, #22", - "orr {temp}, {temp}, #1", // Set EN bit - "str {temp}, [{qmi_base}]", - - // Poll for BUSY to clear before first operation - "1:", - "ldr {temp}, [{qmi_base}]", - "lsls {temp}, {temp}, #30", // Shift BUSY bit to sign position - "bmi 1b", // Branch if negative (BUSY = 1) - - // Assert CS1N (bit 3) - "ldr {temp}, [{qmi_base}]", - "orr {temp}, {temp}, #8", // Set ASSERT_CS1N bit (bit 3) - "str {temp}, [{qmi_base}]", - - // Transmit RESET_ENABLE_CMD as quad - // DIRECT_TX: OE=1 (bit 19), IWIDTH=2 (bits 17:16), DATA=RESET_ENABLE_CMD - "movs {temp}, {reset_enable_cmd}", - "orr {temp}, {temp}, #0x80000", // Set OE (bit 19) - "orr {temp}, {temp}, #0x20000", // Set IWIDTH=2 (quad, bits 17:16) - "str {temp}, [{qmi_base}, #4]", // Store to DIRECT_TX - - // Wait for BUSY to clear - "2:", - "ldr {temp}, [{qmi_base}]", - "lsls {temp}, {temp}, #30", - "bmi 2b", - - // Read and discard RX data - "ldr {temp}, [{qmi_base}, #8]", - - // Deassert CS1N - "ldr {temp}, [{qmi_base}]", - "bic {temp}, {temp}, #8", // Clear ASSERT_CS1N bit - "str {temp}, [{qmi_base}]", - - // Assert CS1N again - "ldr {temp}, [{qmi_base}]", - "orr {temp}, {temp}, #8", // Set ASSERT_CS1N bit - "str {temp}, [{qmi_base}]", - - // Read ID loop (7 iterations) - "movs {counter}, #0", // Initialize counter - - "3:", // Loop start - "cmp {counter}, #0", - "bne 4f", // If not first iteration, send 0xFF - - // First iteration: send READ_ID_CMD - "movs {temp}, {read_id_cmd}", - "b 5f", - - "4:", // Other iterations: send 0xFF - "movs {temp}, #0xFF", - - "5:", - "str {temp}, [{qmi_base}, #4]", // Store to DIRECT_TX - - // Wait for TXEMPTY - "6:", - "ldr {temp}, [{qmi_base}]", - "lsls {temp}, {temp}, #20", // Shift TXEMPTY (bit 11) to bit 31 - "bpl 6b", // Branch if positive (TXEMPTY = 0) - - // Wait for BUSY to clear - "7:", - "ldr {temp}, [{qmi_base}]", - "lsls {temp}, {temp}, #30", // Shift BUSY bit to sign position - "bmi 7b", // Branch if negative (BUSY = 1) - - // Read RX data - "ldr {temp}, [{qmi_base}, #8]", - "uxth {temp}, {temp}", // Extract lower 16 bits - - // Store KGD or EID based on iteration - "cmp {counter}, #5", - "bne 8f", - "mov {kgd}, {temp}", // Store KGD - "b 9f", - - "8:", - "cmp {counter}, #6", - "bne 9f", - "mov {eid}, {temp}", // Store EID - - "9:", - "adds {counter}, #1", - "cmp {counter}, #7", - "blt 3b", // Continue loop if counter < 7 - - // Disable direct mode: clear EN and ASSERT_CS1N - "movs {temp}, #0", - "str {temp}, [{qmi_base}]", - - // Memory barriers - "dmb", - "dsb", - "isb", - - qmi_base = in(reg) qmi_base, - temp = out(reg) _, - counter = out(reg) _, - kgd = out(reg) kgd, - eid = out(reg) eid, - reset_enable_cmd = const RESET_ENABLE_CMD as u32, - read_id_cmd = const READ_ID_CMD as u32, - options(nostack), - ); - } + let (kgd, eid) = unsafe { Self::read_aps6404l_kgd_eid(qmi) }; let mut detected_size: u32 = 0; if kgd == EXPECTED_KGD as u32 { @@ -427,6 +306,134 @@ impl<'d> Psram<'d> { Ok(()) } + #[link_section = ".data.ram_func"] + #[inline(never)] + unsafe fn read_aps6404l_kgd_eid(qmi: &pac::qmi::Qmi) -> (u32, u32) { + const RESET_ENABLE_CMD: u8 = 0xf5; + const READ_ID_CMD: u8 = 0x9f; + + #[allow(unused_assignments)] + let mut kgd: u32 = 0; + #[allow(unused_assignments)] + let mut eid: u32 = 0; + + let qmi_base = qmi.as_ptr() as usize; + + #[cfg(target_arch = "arm")] + core::arch::asm!( + // Configure DIRECT_CSR: shift clkdiv (30) to bits 29:22 and set EN (bit 0) + "movs {temp}, #30", + "lsls {temp}, {temp}, #22", + "orr {temp}, {temp}, #1", // Set EN bit + "str {temp}, [{qmi_base}]", + + // Poll for BUSY to clear before first operation + "1:", + "ldr {temp}, [{qmi_base}]", + "lsls {temp}, {temp}, #30", // Shift BUSY bit to sign position + "bmi 1b", // Branch if negative (BUSY = 1) + + // Assert CS1N (bit 3) + "ldr {temp}, [{qmi_base}]", + "orr {temp}, {temp}, #8", // Set ASSERT_CS1N bit (bit 3) + "str {temp}, [{qmi_base}]", + + // Transmit RESET_ENABLE_CMD as quad + // DIRECT_TX: OE=1 (bit 19), IWIDTH=2 (bits 17:16), DATA=RESET_ENABLE_CMD + "movs {temp}, {reset_enable_cmd}", + "orr {temp}, {temp}, #0x80000", // Set OE (bit 19) + "orr {temp}, {temp}, #0x20000", // Set IWIDTH=2 (quad, bits 17:16) + "str {temp}, [{qmi_base}, #4]", // Store to DIRECT_TX + + // Wait for BUSY to clear + "2:", + "ldr {temp}, [{qmi_base}]", + "lsls {temp}, {temp}, #30", + "bmi 2b", + + // Read and discard RX data + "ldr {temp}, [{qmi_base}, #8]", + + // Deassert CS1N + "ldr {temp}, [{qmi_base}]", + "bic {temp}, {temp}, #8", // Clear ASSERT_CS1N bit + "str {temp}, [{qmi_base}]", + + // Assert CS1N again + "ldr {temp}, [{qmi_base}]", + "orr {temp}, {temp}, #8", // Set ASSERT_CS1N bit + "str {temp}, [{qmi_base}]", + + // Read ID loop (7 iterations) + "movs {counter}, #0", // Initialize counter + + "3:", // Loop start + "cmp {counter}, #0", + "bne 4f", // If not first iteration, send 0xFF + + // First iteration: send READ_ID_CMD + "movs {temp}, {read_id_cmd}", + "b 5f", + "4:", // Other iterations: send 0xFF + "movs {temp}, #0xFF", + "5:", + "str {temp}, [{qmi_base}, #4]", // Store to DIRECT_TX + + // Wait for TXEMPTY + "6:", + "ldr {temp}, [{qmi_base}]", + "lsls {temp}, {temp}, #20", // Shift TXEMPTY (bit 11) to bit 31 + "bpl 6b", // Branch if positive (TXEMPTY = 0) + + // Wait for BUSY to clear + "7:", + "ldr {temp}, [{qmi_base}]", + "lsls {temp}, {temp}, #30", // Shift BUSY bit to sign position + "bmi 7b", // Branch if negative (BUSY = 1) + + // Read RX data + "ldr {temp}, [{qmi_base}, #8]", + "uxth {temp}, {temp}", // Extract lower 16 bits + + // Store KGD or EID based on iteration + "cmp {counter}, #5", + "bne 8f", + "mov {kgd}, {temp}", // Store KGD + "b 9f", + "8:", + "cmp {counter}, #6", + "bne 9f", + "mov {eid}, {temp}", // Store EID + + "9:", + "adds {counter}, #1", + "cmp {counter}, #7", + "blt 3b", // Continue loop if counter < 7 + + // Disable direct mode: clear EN and ASSERT_CS1N + "movs {temp}, #0", + "str {temp}, [{qmi_base}]", + + // Memory barriers + "dmb", + "dsb", + "isb", + qmi_base = in(reg) qmi_base, + temp = out(reg) _, + counter = out(reg) _, + kgd = out(reg) kgd, + eid = out(reg) eid, + reset_enable_cmd = const RESET_ENABLE_CMD as u32, + read_id_cmd = const READ_ID_CMD as u32, + options(nostack), + ); + + #[cfg(target_arch = "riscv32")] + unimplemented!("APS6404L PSRAM verification not implemented for RISC-V"); + + (kgd, eid) + } + /// Initialize PSRAM with proper timing. #[link_section = ".data.ram_func"] #[inline(never)] @@ -476,70 +483,7 @@ impl<'d> Psram<'d> { let _cs = unsafe { CriticalSection::new() }; - unsafe { - core::arch::asm!( - // Full memory barrier - "dmb", - "dsb", - "isb", - - // Configure QMI Direct CSR register - // Load base address of QMI (0x400D0000) - "movw {base}, #0x0000", - "movt {base}, #0x400D", - - // Load init_clkdiv and shift to bits 29:22 - "lsl {temp}, {clkdiv}, #22", - - // OR with EN (bit 0) and AUTO_CS1N (bit 7) - "orr {temp}, {temp}, #0x81", - - // Store to DIRECT_CSR register - "str {temp}, [{base}, #0]", - - // Memory barrier - "dmb", - - // First busy wait loop - "1:", - "ldr {temp}, [{base}, #0]", // Load DIRECT_CSR - "tst {temp}, #0x2", // Test BUSY bit (bit 1) - "bne 1b", // Branch if busy - - // Write to Direct TX register - "mov {temp}, {enter_quad_cmd}", - - // OR with NOPUSH (bit 20) - "orr {temp}, {temp}, #0x100000", - - // Store to DIRECT_TX register (offset 0x4) - "str {temp}, [{base}, #4]", - - // Memory barrier - "dmb", - - // Second busy wait loop - "2:", - "ldr {temp}, [{base}, #0]", // Load DIRECT_CSR - "tst {temp}, #0x2", // Test BUSY bit (bit 1) - "bne 2b", // Branch if busy - - // Disable Direct CSR - "mov {temp}, #0", - "str {temp}, [{base}, #0]", // Clear DIRECT_CSR register - - // Full memory barrier to ensure no prefetching - "dmb", - "dsb", - "isb", - - base = out(reg) _, - temp = out(reg) _, - clkdiv = in(reg) config.init_clkdiv as u32, - enter_quad_cmd = in(reg) u32::from(enter_quad_cmd), - options(nostack), - ); - } + unsafe { Self::direct_csr_send_init_command(config, enter_quad_cmd) }; qmi.mem(1).timing().write(|w| { w.set_cooldown(config.cooldown); @@ -665,4 +609,74 @@ impl<'d> Psram<'d> { Ok(()) } + + #[link_section = ".data.ram_func"] + #[inline(never)] + unsafe fn direct_csr_send_init_command(config: &Config, init_cmd: u8) { + #[cfg(target_arch = "arm")] + core::arch::asm!( + // Full memory barrier + "dmb", + "dsb", + "isb", + + // Configure QMI Direct CSR register + // Load base address of QMI (0x400D0000) + "movw {base}, #0x0000", + "movt {base}, #0x400D", + + // Load init_clkdiv and shift to bits 29:22 + "lsl {temp}, {clkdiv}, #22", + + // OR with EN (bit 0) and AUTO_CS1N (bit 7) + "orr {temp}, {temp}, #0x81", + + // Store to DIRECT_CSR register + "str {temp}, [{base}, #0]", + + // Memory barrier + "dmb", + + // First busy wait loop + "1:", + "ldr {temp}, [{base}, #0]", // Load DIRECT_CSR + "tst {temp}, #0x2", // Test BUSY bit (bit 1) + "bne 1b", // Branch if busy + + // Write to Direct TX register + "mov {temp}, {enter_quad_cmd}", + + // OR with NOPUSH (bit 20) + "orr {temp}, {temp}, #0x100000", + + // Store to DIRECT_TX register (offset 0x4) + "str {temp}, [{base}, #4]", + + // Memory barrier + "dmb", + + // Second busy wait loop + "2:", + "ldr {temp}, [{base}, #0]", // Load DIRECT_CSR + "tst {temp}, #0x2", // Test BUSY bit (bit 1) + "bne 2b", // Branch if busy + + // Disable Direct CSR + "mov {temp}, #0", + "str {temp}, [{base}, #0]", // Clear DIRECT_CSR register + + // Full memory barrier to ensure no prefetching + "dmb", + "dsb", + "isb", + base = out(reg) _, + temp = out(reg) _, + clkdiv = in(reg) config.init_clkdiv as u32, + enter_quad_cmd = in(reg) u32::from(init_cmd), + options(nostack), + ); + + #[cfg(target_arch = "riscv32")] + unimplemented!("Direct CSR command sending is not implemented for RISC-V yet"); + } } -- cgit From 303f160e9423247f571adf56866c3c5f6ccca325 Mon Sep 17 00:00:00 2001 From: riceman2000 Date: Thu, 7 Aug 2025 23:36:13 -0400 Subject: Add examples for wiznet devboard --- examples/rp235x/Cargo.toml | 2 +- examples/rp235x/src/bin/ethernet_w5500_icmp.rs | 143 +++++++++++++++++++++ .../rp235x/src/bin/ethernet_w5500_icmp_ping.rs | 134 +++++++++++++++++++ .../rp235x/src/bin/ethernet_w5500_multisocket.rs | 139 ++++++++++++++++++++ .../rp235x/src/bin/ethernet_w5500_tcp_client.rs | 127 ++++++++++++++++++ .../rp235x/src/bin/ethernet_w5500_tcp_server.rs | 136 ++++++++++++++++++++ examples/rp235x/src/bin/ethernet_w5500_udp.rs | 116 +++++++++++++++++ 7 files changed, 796 insertions(+), 1 deletion(-) create mode 100644 examples/rp235x/src/bin/ethernet_w5500_icmp.rs create mode 100644 examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs create mode 100644 examples/rp235x/src/bin/ethernet_w5500_multisocket.rs create mode 100644 examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs create mode 100644 examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs create mode 100644 examples/rp235x/src/bin/ethernet_w5500_udp.rs diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index eecd98894..2a4e888d9 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -12,7 +12,7 @@ embassy-executor = { version = "0.8.0", path = "../../embassy-executor", feature embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-rp = { version = "0.7.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } +embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.5.0", path = "../../embassy-usb-logger" } diff --git a/examples/rp235x/src/bin/ethernet_w5500_icmp.rs b/examples/rp235x/src/bin/ethernet_w5500_icmp.rs new file mode 100644 index 000000000..f1abd311c --- /dev/null +++ b/examples/rp235x/src/bin/ethernet_w5500_icmp.rs @@ -0,0 +1,143 @@ +//! This example implements an echo (ping) with an ICMP Socket and using defmt to report the results. +//! +//! Although there is a better way to execute pings using the child module ping of the icmp module, +//! this example allows for other icmp messages like `Destination unreachable` to be sent aswell. +//! +//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::icmp::{ChecksumCapabilities, IcmpEndpoint, IcmpSocket, Icmpv4Packet, Icmpv4Repr, PacketMetadata}; +use embassy_net::{Stack, StackResources}; +use embassy_net_wiznet::chip::W5500; +use embassy_net_wiznet::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::SPI0; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embassy_time::{Delay, Instant, Timer}; +use embedded_hal_bus::spi::ExclusiveDevice; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +type ExclusiveSpiDevice = ExclusiveDevice, Output<'static>, Delay>; + +#[embassy_executor::task] +async fn ethernet_task(runner: Runner<'static, W5500, ExclusiveSpiDevice, Input<'static>, Output<'static>>) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { + runner.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + static STATE: StaticCell> = StaticCell::new(); + let state = STATE.init(State::<8, 8>::new()); + let (device, runner) = embassy_net_wiznet::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await + .unwrap(); + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + static RESOURCES: StaticCell> = StaticCell::new(); + let (stack, runner) = embassy_net::new( + device, + embassy_net::Config::dhcpv4(Default::default()), + RESOURCES.init(StackResources::new()), + seed, + ); + + // Launch network task + unwrap!(spawner.spawn(net_task(runner))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + // Then we can use it! + let mut rx_buffer = [0; 256]; + let mut tx_buffer = [0; 256]; + let mut rx_meta = [PacketMetadata::EMPTY]; + let mut tx_meta = [PacketMetadata::EMPTY]; + + // Identifier used for the ICMP socket + let ident = 42; + + // Create and bind the socket + let mut socket = IcmpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); + socket.bind(IcmpEndpoint::Ident(ident)).unwrap(); + + // Create the repr for the packet + let icmp_repr = Icmpv4Repr::EchoRequest { + ident, + seq_no: 0, + data: b"Hello, icmp!", + }; + + // Send the packet and store the starting instant to mesure latency later + let start = socket + .send_to_with(icmp_repr.buffer_len(), cfg.gateway.unwrap(), |buf| { + // Create and populate the packet buffer allocated by `send_to_with` + let mut icmp_packet = Icmpv4Packet::new_unchecked(buf); + icmp_repr.emit(&mut icmp_packet, &ChecksumCapabilities::default()); + Instant::now() // Return the instant where the packet was sent + }) + .await + .unwrap(); + + // Recieve and log the data of the reply + socket + .recv_from_with(|(buf, addr)| { + let packet = Icmpv4Packet::new_checked(buf).unwrap(); + info!( + "Recieved {:?} from {} in {}ms", + packet.data(), + addr, + start.elapsed().as_millis() + ); + }) + .await + .unwrap(); + + loop { + Timer::after_secs(10).await; + } +} + +async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { + loop { + if let Some(config) = stack.config_v4() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs b/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs new file mode 100644 index 000000000..1f799a6b0 --- /dev/null +++ b/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs @@ -0,0 +1,134 @@ +//! This example implements a LAN ping scan with the ping utilities in the icmp module of embassy-net. +//! +//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board. + +#![no_std] +#![no_main] + +use core::net::Ipv4Addr; +use core::ops::Not; +use core::str::FromStr; + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::icmp::ping::{PingManager, PingParams}; +use embassy_net::icmp::PacketMetadata; +use embassy_net::{Ipv4Cidr, Stack, StackResources}; +use embassy_net_wiznet::chip::W5500; +use embassy_net_wiznet::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::SPI0; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embassy_time::{Delay, Duration}; +use embedded_hal_bus::spi::ExclusiveDevice; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +type ExclusiveSpiDevice = ExclusiveDevice, Output<'static>, Delay>; + +#[embassy_executor::task] +async fn ethernet_task(runner: Runner<'static, W5500, ExclusiveSpiDevice, Input<'static>, Output<'static>>) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { + runner.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + static STATE: StaticCell> = StaticCell::new(); + let state = STATE.init(State::<8, 8>::new()); + let (device, runner) = embassy_net_wiznet::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await + .unwrap(); + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + static RESOURCES: StaticCell> = StaticCell::new(); + let (stack, runner) = embassy_net::new( + device, + embassy_net::Config::dhcpv4(Default::default()), + RESOURCES.init(StackResources::new()), + seed, + ); + + // Launch network task + unwrap!(spawner.spawn(net_task(runner))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + let gateway = cfg.gateway.unwrap(); + let mask = cfg.address.netmask(); + let lower_bound = (gateway.to_bits() & mask.to_bits()) + 1; + let upper_bound = gateway.to_bits() | mask.to_bits().not(); + let addr_range = lower_bound..=upper_bound; + + // Then we can use it! + let mut rx_buffer = [0; 256]; + let mut tx_buffer = [0; 256]; + let mut rx_meta = [PacketMetadata::EMPTY]; + let mut tx_meta = [PacketMetadata::EMPTY]; + + // Create the ping manager instance + let mut ping_manager = PingManager::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); + let addr = "192.168.8.1"; // Address to ping to + // Create the PingParams with the target address + let mut ping_params = PingParams::new(Ipv4Addr::from_str(addr).unwrap()); + // (optional) Set custom properties of the ping + ping_params.set_payload(b"Hello, Ping!"); // custom payload + ping_params.set_count(1); // ping 1 times per ping call + ping_params.set_timeout(Duration::from_millis(500)); // wait .5 seconds instead of 4 + + info!("Online hosts in {}:", Ipv4Cidr::from_netmask(gateway, mask).unwrap()); + let mut total_online_hosts = 0u32; + for addr in addr_range { + let ip_addr = Ipv4Addr::from_bits(addr); + // Set the target address in the ping params + ping_params.set_target(ip_addr); + // Execute the ping with the given parameters and wait for the reply + match ping_manager.ping(&ping_params).await { + Ok(time) => { + info!("{} is online\n- latency: {}ms\n", ip_addr, time.as_millis()); + total_online_hosts += 1; + } + _ => continue, + } + } + info!("Ping scan complete, total online hosts: {}", total_online_hosts); +} + +async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { + loop { + if let Some(config) = stack.config_v4() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs b/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs new file mode 100644 index 000000000..fd8bc5c7a --- /dev/null +++ b/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs @@ -0,0 +1,139 @@ +//! This example shows how you can allow multiple simultaneous TCP connections, by having multiple sockets listening on the same port. +//! +//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::{Stack, StackResources}; +use embassy_net_wiznet::chip::W5500; +use embassy_net_wiznet::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::SPI0; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embassy_time::{Delay, Duration}; +use embedded_hal_bus::spi::ExclusiveDevice; +use embedded_io_async::Write; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + W5500, + ExclusiveDevice, Output<'static>, Delay>, + Input<'static>, + Output<'static>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { + runner.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + static STATE: StaticCell> = StaticCell::new(); + let state = STATE.init(State::<8, 8>::new()); + let (device, runner) = embassy_net_wiznet::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await + .unwrap(); + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + static RESOURCES: StaticCell> = StaticCell::new(); + let (stack, runner) = embassy_net::new( + device, + embassy_net::Config::dhcpv4(Default::default()), + RESOURCES.init(StackResources::new()), + seed, + ); + + // Launch network task + unwrap!(spawner.spawn(net_task(runner))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + // Create two sockets listening to the same port, to handle simultaneous connections + unwrap!(spawner.spawn(listen_task(stack, 0, 1234))); + unwrap!(spawner.spawn(listen_task(stack, 1, 1234))); +} + +#[embassy_executor::task(pool_size = 2)] +async fn listen_task(stack: Stack<'static>, id: u8, port: u16) { + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut buf = [0; 4096]; + loop { + let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(Duration::from_secs(10))); + + info!("SOCKET {}: Listening on TCP:{}...", id, port); + if let Err(e) = socket.accept(port).await { + warn!("accept error: {:?}", e); + continue; + } + info!("SOCKET {}: Received connection from {:?}", id, socket.remote_endpoint()); + + loop { + let n = match socket.read(&mut buf).await { + Ok(0) => { + warn!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + warn!("SOCKET {}: {:?}", id, e); + break; + } + }; + info!("SOCKET {}: rxd {}", id, core::str::from_utf8(&buf[..n]).unwrap()); + + if let Err(e) = socket.write_all(&buf[..n]).await { + warn!("write error: {:?}", e); + break; + } + } + } +} + +async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { + loop { + if let Some(config) = stack.config_v4() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs new file mode 100644 index 000000000..b726b9cc6 --- /dev/null +++ b/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs @@ -0,0 +1,127 @@ +//! This example implements a TCP client that attempts to connect to a host on port 1234 and send it some data once per second. +//! +//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board. + +#![no_std] +#![no_main] + +use core::str::FromStr; + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::{Stack, StackResources}; +use embassy_net_wiznet::chip::W5500; +use embassy_net_wiznet::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::SPI0; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embassy_time::{Delay, Duration, Timer}; +use embedded_hal_bus::spi::ExclusiveDevice; +use embedded_io_async::Write; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + W5500, + ExclusiveDevice, Output<'static>, Delay>, + Input<'static>, + Output<'static>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { + runner.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + let mut led = Output::new(p.PIN_25, Level::Low); + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + static STATE: StaticCell> = StaticCell::new(); + let state = STATE.init(State::<8, 8>::new()); + let (device, runner) = embassy_net_wiznet::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await + .unwrap(); + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + static RESOURCES: StaticCell> = StaticCell::new(); + let (stack, runner) = embassy_net::new( + device, + embassy_net::Config::dhcpv4(Default::default()), + RESOURCES.init(StackResources::new()), + seed, + ); + + // Launch network task + unwrap!(spawner.spawn(net_task(runner))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + loop { + let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(Duration::from_secs(10))); + + led.set_low(); + info!("Connecting..."); + let host_addr = embassy_net::Ipv4Address::from_str("192.168.0.118").unwrap(); + if let Err(e) = socket.connect((host_addr, 1234)).await { + warn!("connect error: {:?}", e); + continue; + } + info!("Connected to {:?}", socket.remote_endpoint()); + led.set_high(); + + let msg = b"Hello world!\n"; + loop { + if let Err(e) = socket.write_all(msg).await { + warn!("write error: {:?}", e); + break; + } + info!("txd: {}", core::str::from_utf8(msg).unwrap()); + Timer::after_secs(1).await; + } + } +} + +async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { + loop { + if let Some(config) = stack.config_v4() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs new file mode 100644 index 000000000..32b3880f6 --- /dev/null +++ b/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs @@ -0,0 +1,136 @@ +//! This example implements a TCP echo server on port 1234 and using DHCP. +//! Send it some data, you should see it echoed back and printed in the console. +//! +//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::{Stack, StackResources}; +use embassy_net_wiznet::chip::W5500; +use embassy_net_wiznet::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::SPI0; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embassy_time::{Delay, Duration}; +use embedded_hal_bus::spi::ExclusiveDevice; +use embedded_io_async::Write; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + W5500, + ExclusiveDevice, Output<'static>, Delay>, + Input<'static>, + Output<'static>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { + runner.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + let mut led = Output::new(p.PIN_25, Level::Low); + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + static STATE: StaticCell> = StaticCell::new(); + let state = STATE.init(State::<8, 8>::new()); + let (device, runner) = embassy_net_wiznet::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await + .unwrap(); + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + static RESOURCES: StaticCell> = StaticCell::new(); + let (stack, runner) = embassy_net::new( + device, + embassy_net::Config::dhcpv4(Default::default()), + RESOURCES.init(StackResources::new()), + seed, + ); + + // Launch network task + unwrap!(spawner.spawn(net_task(runner))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut buf = [0; 4096]; + loop { + let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(Duration::from_secs(10))); + + led.set_low(); + info!("Listening on TCP:1234..."); + if let Err(e) = socket.accept(1234).await { + warn!("accept error: {:?}", e); + continue; + } + info!("Received connection from {:?}", socket.remote_endpoint()); + led.set_high(); + + loop { + let n = match socket.read(&mut buf).await { + Ok(0) => { + warn!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + warn!("{:?}", e); + break; + } + }; + info!("rxd {}", core::str::from_utf8(&buf[..n]).unwrap()); + + if let Err(e) = socket.write_all(&buf[..n]).await { + warn!("write error: {:?}", e); + break; + } + } + } +} + +async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { + loop { + if let Some(config) = stack.config_v4() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/rp235x/src/bin/ethernet_w5500_udp.rs b/examples/rp235x/src/bin/ethernet_w5500_udp.rs new file mode 100644 index 000000000..cd0824df1 --- /dev/null +++ b/examples/rp235x/src/bin/ethernet_w5500_udp.rs @@ -0,0 +1,116 @@ +//! This example implements a UDP server listening on port 1234 and echoing back the data. +//! +//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::udp::{PacketMetadata, UdpSocket}; +use embassy_net::{Stack, StackResources}; +use embassy_net_wiznet::chip::W5500; +use embassy_net_wiznet::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::SPI0; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embassy_time::Delay; +use embedded_hal_bus::spi::ExclusiveDevice; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + W5500, + ExclusiveDevice, Output<'static>, Delay>, + Input<'static>, + Output<'static>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { + runner.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + static STATE: StaticCell> = StaticCell::new(); + let state = STATE.init(State::<8, 8>::new()); + let (device, runner) = embassy_net_wiznet::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await + .unwrap(); + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + static RESOURCES: StaticCell> = StaticCell::new(); + let (stack, runner) = embassy_net::new( + device, + embassy_net::Config::dhcpv4(Default::default()), + RESOURCES.init(StackResources::new()), + seed, + ); + + // Launch network task + unwrap!(spawner.spawn(net_task(runner))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + // Then we can use it! + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut rx_meta = [PacketMetadata::EMPTY; 16]; + let mut tx_meta = [PacketMetadata::EMPTY; 16]; + let mut buf = [0; 4096]; + loop { + let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); + socket.bind(1234).unwrap(); + + loop { + let (n, ep) = socket.recv_from(&mut buf).await.unwrap(); + if let Ok(s) = core::str::from_utf8(&buf[..n]) { + info!("rxd from {}: {}", ep, s); + } + socket.send_to(&buf[..n], ep).await.unwrap(); + } + } +} + +async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { + loop { + if let Some(config) = stack.config_v4() { + return config.clone(); + } + yield_now().await; + } +} -- cgit From 556ae0106bba66e49f62f45aa3cc458e31094dc7 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Fri, 8 Aug 2025 03:10:35 -0700 Subject: Working draft of VREFBUF driver --- embassy-stm32/Cargo.toml | 4 +-- embassy-stm32/src/lib.rs | 2 ++ embassy-stm32/src/vrefbuf/mod.rs | 69 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 embassy-stm32/src/vrefbuf/mod.rs diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 145a89b77..590216c21 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-cad609e02a866422ffdbb8e07be26311cfdd07d9" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f0ef9106642ed869e7cfbf82d891d364c98ebb43" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-cad609e02a866422ffdbb8e07be26311cfdd07d9", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f0ef9106642ed869e7cfbf82d891d364c98ebb43", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index a676677e1..e4a8ff0ab 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -125,6 +125,8 @@ pub mod uid; pub mod usart; #[cfg(any(usb, otg))] pub mod usb; +#[cfg(vrefbuf)] +pub mod vrefbuf; #[cfg(iwdg)] pub mod wdg; #[cfg(xspi)] diff --git a/embassy-stm32/src/vrefbuf/mod.rs b/embassy-stm32/src/vrefbuf/mod.rs new file mode 100644 index 000000000..2546ccfed --- /dev/null +++ b/embassy-stm32/src/vrefbuf/mod.rs @@ -0,0 +1,69 @@ +//! Voltage Reference Buffer (VREFBUF) +// use core::ptr::{read_volatile, write_volatile}; +use core::marker::PhantomData; + +use embassy_hal_internal::PeripheralType; +use stm32_metapac::vrefbuf::vals::*; + +use crate::pac::RCC; +use crate::Peri; + +/// Voltage Reference (VREFBUF) driver. +pub struct VoltageReferenceBuffer<'d, T: Instance> { + vrefbuf: PhantomData<&'d mut T>, +} + +impl<'d, T: Instance> VoltageReferenceBuffer<'d, T> { + /// Creates an VREFBUF (Voltage Reference) instance with a voltage scale and impedance mode. + /// + /// [Self] has to be started with [Self::new()]. + pub fn new(_instance: Peri<'d, T>, voltage_scale: Vrs, impedance_mode: Hiz) -> Self { + #[cfg(rcc_wba)] + { + RCC.apb7enr().modify(|w| w.set_vrefen(true)); + } + #[cfg(any(rcc_u5, rcc_h50, rcc_h5))] + { + RCC.apb3enr().modify(|w| w.set_vrefen(true)); + } + #[cfg(any(rcc_h7rs, rcc_h7rm0433, rcc_h7ab, rcc_h7))] + { + RCC.apb4enr().modify(|w| w.set_vrefen(true)); + } + let vrefbuf = T::regs(); + vrefbuf.csr().modify(|w| { + w.set_hiz(impedance_mode); + w.set_envr(true); + w.set_vrs(voltage_scale); + }); + while vrefbuf.csr().read().vrr() != false { + // wait... + } + trace!( + "Vrefbuf configured with voltage scale {} and impedance mode {}", + voltage_scale, + impedance_mode + ); + VoltageReferenceBuffer { vrefbuf: PhantomData } + } +} + +trait SealedInstance { + fn regs() -> crate::pac::vrefbuf::Vrefbuf; +} + +/// VREFBUF instance trait. +#[allow(private_bounds)] +pub trait Instance: SealedInstance + PeripheralType {} + +foreach_peripheral!( + (vrefbuf, $inst:ident) => { + impl SealedInstance for crate::peripherals::$inst { + fn regs() -> crate::pac::vrefbuf::Vrefbuf { + crate::pac::$inst + } + } + + impl Instance for crate::peripherals::$inst {} + }; +); -- cgit From f9da2888c4d0e1a27cbd0f2a915fecb26eb4cc62 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Fri, 8 Aug 2025 22:39:09 +0800 Subject: i2s --- embassy-stm32/src/i2s.rs | 27 ++++++++++++--------------- examples/stm32f4/src/bin/i2s_dma.rs | 1 - 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index 5005a5cdb..a51d21bb0 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs @@ -155,6 +155,10 @@ impl ClockPolarity { #[non_exhaustive] #[derive(Copy, Clone)] pub struct Config { + /// Frequency + pub frequency: Hertz, + /// GPIO Speed + pub gpio_speed: Speed, /// Mode pub mode: Mode, /// Which I2S standard to use. @@ -170,6 +174,8 @@ pub struct Config { impl Default for Config { fn default() -> Self { Self { + frequency: Hertz::khz(48), + gpio_speed: Speed::VeryHigh, mode: Mode::Master, standard: Standard::Philips, format: Format::Data16Channel16, @@ -243,7 +249,6 @@ impl<'d, W: Word> I2S<'d, W> { mck: Peri<'d, impl MckPin>, txdma: Peri<'d, impl TxDma>, txdma_buf: &'d mut [W], - freq: Hertz, config: Config, ) -> Self { Self::new_inner( @@ -255,7 +260,6 @@ impl<'d, W: Word> I2S<'d, W> { new_pin!(mck, AfType::output(OutputType::PushPull, Speed::VeryHigh)), new_dma!(txdma).map(|d| (d, txdma_buf)), None, - freq, config, Function::Transmit, ) @@ -269,7 +273,6 @@ impl<'d, W: Word> I2S<'d, W> { ck: Peri<'d, impl CkPin>, txdma: Peri<'d, impl TxDma>, txdma_buf: &'d mut [W], - freq: Hertz, config: Config, ) -> Self { Self::new_inner( @@ -281,7 +284,6 @@ impl<'d, W: Word> I2S<'d, W> { None, new_dma!(txdma).map(|d| (d, txdma_buf)), None, - freq, config, Function::Transmit, ) @@ -296,7 +298,6 @@ impl<'d, W: Word> I2S<'d, W> { mck: Peri<'d, impl MckPin>, rxdma: Peri<'d, impl RxDma>, rxdma_buf: &'d mut [W], - freq: Hertz, config: Config, ) -> Self { Self::new_inner( @@ -308,7 +309,6 @@ impl<'d, W: Word> I2S<'d, W> { new_pin!(mck, AfType::output(OutputType::PushPull, Speed::VeryHigh)), None, new_dma!(rxdma).map(|d| (d, rxdma_buf)), - freq, config, Function::Receive, ) @@ -327,7 +327,6 @@ impl<'d, W: Word> I2S<'d, W> { txdma_buf: &'d mut [W], rxdma: Peri<'d, impl RxDma>, rxdma_buf: &'d mut [W], - freq: Hertz, config: Config, ) -> Self { Self::new_inner( @@ -339,7 +338,6 @@ impl<'d, W: Word> I2S<'d, W> { new_pin!(mck, AfType::output(OutputType::PushPull, Speed::VeryHigh)), new_dma!(txdma).map(|d| (d, txdma_buf)), new_dma!(rxdma).map(|d| (d, rxdma_buf)), - freq, config, Function::FullDuplex, ) @@ -473,17 +471,16 @@ impl<'d, W: Word> I2S<'d, W> { mck: Option>, txdma: Option<(ChannelAndRequest<'d>, &'d mut [W])>, rxdma: Option<(ChannelAndRequest<'d>, &'d mut [W])>, - freq: Hertz, config: Config, function: Function, ) -> Self { - ws.set_as_af(ws.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); - ck.set_as_af(ck.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); + ws.set_as_af(ws.af_num(), AfType::output(OutputType::PushPull, config.gpio_speed)); + ck.set_as_af(ck.af_num(), AfType::output(OutputType::PushPull, config.gpio_speed)); let spi = Spi::new_internal(peri, None, None, { - let mut config = SpiConfig::default(); - config.frequency = freq; - config + let mut spi_config = SpiConfig::default(); + spi_config.frequency = config.frequency; + spi_config }); let regs = T::info().regs; @@ -493,7 +490,7 @@ impl<'d, W: Word> I2S<'d, W> { #[cfg(not(all(rcc_f4, not(stm32f410))))] let pclk = T::frequency(); - let (odd, div) = compute_baud_rate(pclk, freq, config.master_clock, config.format); + let (odd, div) = compute_baud_rate(pclk, config.frequency, config.master_clock, config.format); #[cfg(any(spi_v1, spi_v3, spi_f1))] { diff --git a/examples/stm32f4/src/bin/i2s_dma.rs b/examples/stm32f4/src/bin/i2s_dma.rs index db5103d0f..6051a3c5a 100644 --- a/examples/stm32f4/src/bin/i2s_dma.rs +++ b/examples/stm32f4/src/bin/i2s_dma.rs @@ -72,7 +72,6 @@ async fn main(_spawner: Spawner) { p.PB3, // ck p.DMA1_CH7, &mut dma_buffer, - Hertz(48_000), i2s_config, ); i2s.start(); -- cgit From 5e3221bcc47bc1ce30eaf8d347377d652dbba7e2 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Fri, 8 Aug 2025 23:01:11 +0800 Subject: i2c --- embassy-stm32/src/i2c/config.rs | 14 ++++++++++---- embassy-stm32/src/i2c/mod.rs | 11 +++-------- embassy-stm32/src/i2c/v1.rs | 18 +++++++++--------- embassy-stm32/src/i2c/v2.rs | 4 ++-- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/embassy-stm32/src/i2c/config.rs b/embassy-stm32/src/i2c/config.rs index daae43bcd..0b4e091b8 100644 --- a/embassy-stm32/src/i2c/config.rs +++ b/embassy-stm32/src/i2c/config.rs @@ -109,6 +109,10 @@ impl SlaveAddrConfig { #[non_exhaustive] #[derive(Copy, Clone)] pub struct Config { + /// Frequency + pub frequency: Hertz, + /// GPIO Speed + pub gpio_speed: Speed, /// Enable internal pullup on SDA. /// /// Using external pullup resistors is recommended for I2C. If you do @@ -129,6 +133,8 @@ pub struct Config { impl Default for Config { fn default() -> Self { Self { + frequency: Hertz::khz(100), + gpio_speed: Speed::Medium, #[cfg(gpio_v2)] sda_pullup: false, #[cfg(gpio_v2)] @@ -142,11 +148,11 @@ impl Default for Config { impl Config { pub(super) fn scl_af(&self) -> AfType { #[cfg(gpio_v1)] - return AfType::output(OutputType::OpenDrain, Speed::Medium); + return AfType::output(OutputType::OpenDrain, self.gpio_speed); #[cfg(gpio_v2)] return AfType::output_pull( OutputType::OpenDrain, - Speed::Medium, + self.gpio_speed, match self.scl_pullup { true => Pull::Up, false => Pull::Down, @@ -156,11 +162,11 @@ impl Config { pub(super) fn sda_af(&self) -> AfType { #[cfg(gpio_v1)] - return AfType::output(OutputType::OpenDrain, Speed::Medium); + return AfType::output(OutputType::OpenDrain, self.gpio_speed); #[cfg(gpio_v2)] return AfType::output_pull( OutputType::OpenDrain, - Speed::Medium, + self.gpio_speed, match self.sda_pullup { true => Pull::Up, false => Pull::Down, diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 825dd240c..5fb49f943 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -158,7 +158,6 @@ impl<'d> I2c<'d, Async, Master> { + 'd, tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, - freq: Hertz, config: Config, ) -> Self { Self::new_inner( @@ -167,7 +166,6 @@ impl<'d> I2c<'d, Async, Master> { new_pin!(sda, config.sda_af()), new_dma!(tx_dma), new_dma!(rx_dma), - freq, config, ) } @@ -179,7 +177,6 @@ impl<'d> I2c<'d, Blocking, Master> { peri: Peri<'d, T>, scl: Peri<'d, impl SclPin>, sda: Peri<'d, impl SdaPin>, - freq: Hertz, config: Config, ) -> Self { Self::new_inner( @@ -188,7 +185,6 @@ impl<'d> I2c<'d, Blocking, Master> { new_pin!(sda, config.sda_af()), None, None, - freq, config, ) } @@ -202,7 +198,6 @@ impl<'d, M: Mode> I2c<'d, M, Master> { sda: Option>, tx_dma: Option>, rx_dma: Option>, - freq: Hertz, config: Config, ) -> Self { unsafe { T::EventInterrupt::enable() }; @@ -224,14 +219,14 @@ impl<'d, M: Mode> I2c<'d, M, Master> { sda, }, }; - this.enable_and_init(freq, config); + this.enable_and_init(config); this } - fn enable_and_init(&mut self, freq: Hertz, config: Config) { + fn enable_and_init(&mut self, config: Config) { self.info.rcc.enable_and_reset(); - self.init(freq, config); + self.init(config); } } diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 35f13ab46..081eb1191 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -43,7 +43,7 @@ pub unsafe fn on_interrupt() { } impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> { - pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { + pub(crate) fn init(&mut self, config: Config) { self.info.regs.cr1().modify(|reg| { reg.set_pe(false); //reg.set_anfoff(false); @@ -75,7 +75,7 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> { reg.set_swrst(false); }); - let timings = Timings::new(self.kernel_clock, freq); + let timings = Timings::new(self.kernel_clock, config.frequency); self.info.regs.cr2().modify(|reg| { reg.set_freq(timings.freq); @@ -738,15 +738,15 @@ struct Timings { } impl Timings { - fn new(i2cclk: Hertz, speed: Hertz) -> Self { + fn new(i2cclk: Hertz, frequency: Hertz) -> Self { // Calculate settings for I2C speed modes - let speed = speed.0; + let frequency = frequency.0; let clock = i2cclk.0; let freq = clock / 1_000_000; assert!((2..=50).contains(&freq)); // Configure bus frequency into I2C peripheral - let trise = if speed <= 100_000 { + let trise = if frequency <= 100_000 { freq + 1 } else { (freq * 300) / 1000 + 1 @@ -757,11 +757,11 @@ impl Timings { let mode; // I2C clock control calculation - if speed <= 100_000 { + if frequency <= 100_000 { duty = Duty::Duty2_1; mode = Mode::Standard; ccr = { - let ccr = clock / (speed * 2); + let ccr = clock / (frequency * 2); if ccr < 4 { 4 } else { @@ -773,13 +773,13 @@ impl Timings { mode = Mode::Fast; if DUTYCYCLE == 0 { duty = Duty::Duty2_1; - ccr = clock / (speed * 3); + ccr = clock / (frequency * 3); ccr = if ccr < 1 { 1 } else { ccr }; // Set clock to fast mode with appropriate parameters for selected speed (2:1 duty cycle) } else { duty = Duty::Duty16_9; - ccr = clock / (speed * 25); + ccr = clock / (frequency * 25); ccr = if ccr < 1 { 1 } else { ccr }; // Set clock to fast mode with appropriate parameters for selected speed (16:9 duty cycle) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index e24cce5c6..76f0d25dc 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -93,13 +93,13 @@ pub(crate) unsafe fn on_interrupt() { } impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { - pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { + pub(crate) fn init(&mut self, config: Config) { self.info.regs.cr1().modify(|reg| { reg.set_pe(false); reg.set_anfoff(false); }); - let timings = Timings::new(self.kernel_clock, freq.into()); + let timings = Timings::new(self.kernel_clock, config.frequency.into()); self.info.regs.timingr().write(|reg| { reg.set_presc(timings.prescale); -- cgit From 70bf63723a316d18fb255cae2f6ef9b36f37405b Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Fri, 8 Aug 2025 23:06:17 +0800 Subject: i2c examples --- examples/stm32f4/src/bin/i2c.rs | 3 +-- examples/stm32f4/src/bin/i2c_async.rs | 2 -- examples/stm32f4/src/bin/i2c_comparison.rs | 4 ---- examples/stm32g0/src/bin/i2c_async.rs | 2 -- examples/stm32g4/src/bin/i2c_slave.rs | 9 ++++----- examples/stm32h5/src/bin/i2c.rs | 2 -- examples/stm32h7/src/bin/camera.rs | 2 -- examples/stm32h7/src/bin/i2c.rs | 2 -- examples/stm32h7/src/bin/i2c_shared.rs | 2 -- examples/stm32h7rs/src/bin/i2c.rs | 2 -- examples/stm32l4/src/bin/i2c.rs | 3 +-- examples/stm32l4/src/bin/i2c_blocking_async.rs | 3 +-- examples/stm32l4/src/bin/i2c_dma.rs | 2 -- examples/stm32l4/src/bin/spe_adin1110_http_server.rs | 1 - examples/stm32u0/src/bin/i2c.rs | 3 +-- examples/stm32u5/src/bin/i2c.rs | 3 +-- 16 files changed, 9 insertions(+), 36 deletions(-) diff --git a/examples/stm32f4/src/bin/i2c.rs b/examples/stm32f4/src/bin/i2c.rs index 4a96357a4..49710a92a 100644 --- a/examples/stm32f4/src/bin/i2c.rs +++ b/examples/stm32f4/src/bin/i2c.rs @@ -4,7 +4,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::i2c::{Error, I2c}; -use embassy_stm32::time::Hertz; use {defmt_rtt as _, panic_probe as _}; const ADDRESS: u8 = 0x5F; @@ -15,7 +14,7 @@ async fn main(_spawner: Spawner) { info!("Hello world!"); let p = embassy_stm32::init(Default::default()); - let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default()); + let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Default::default()); let mut data = [0u8; 1]; diff --git a/examples/stm32f4/src/bin/i2c_async.rs b/examples/stm32f4/src/bin/i2c_async.rs index 90d11d4b4..e065910d8 100644 --- a/examples/stm32f4/src/bin/i2c_async.rs +++ b/examples/stm32f4/src/bin/i2c_async.rs @@ -7,7 +7,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::i2c::I2c; -use embassy_stm32::time::Hertz; use embassy_stm32::{bind_interrupts, i2c, peripherals}; use {defmt_rtt as _, panic_probe as _}; @@ -30,7 +29,6 @@ async fn main(_spawner: Spawner) { Irqs, p.DMA1_CH6, p.DMA1_CH0, - Hertz(100_000), Default::default(), ); diff --git a/examples/stm32f4/src/bin/i2c_comparison.rs b/examples/stm32f4/src/bin/i2c_comparison.rs index 55c4891e3..3713601b1 100644 --- a/examples/stm32f4/src/bin/i2c_comparison.rs +++ b/examples/stm32f4/src/bin/i2c_comparison.rs @@ -10,7 +10,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::i2c::I2c; -use embassy_stm32::time::Hertz; use embassy_stm32::{bind_interrupts, i2c, peripherals}; use embassy_time::Instant; use futures_util::future::try_join3; @@ -55,7 +54,6 @@ async fn main(_spawner: Spawner) { Irqs, p.DMA1_CH6, p.DMA1_CH0, - Hertz(100_000), Default::default(), ); @@ -66,7 +64,6 @@ async fn main(_spawner: Spawner) { Irqs, p.DMA1_CH7, p.DMA1_CH3, - Hertz(100_000), Default::default(), ); @@ -77,7 +74,6 @@ async fn main(_spawner: Spawner) { Irqs, p.DMA1_CH4, p.DMA1_CH2, - Hertz(100_000), Default::default(), ); diff --git a/examples/stm32g0/src/bin/i2c_async.rs b/examples/stm32g0/src/bin/i2c_async.rs index 7e3189b05..19c52c21d 100644 --- a/examples/stm32g0/src/bin/i2c_async.rs +++ b/examples/stm32g0/src/bin/i2c_async.rs @@ -4,7 +4,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::i2c::{self, I2c}; -use embassy_stm32::time::Hertz; use embassy_stm32::{bind_interrupts, peripherals}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -30,7 +29,6 @@ async fn main(_spawner: Spawner) { Irqs, p.DMA1_CH1, p.DMA1_CH2, - Hertz(100_000), Default::default(), ); diff --git a/examples/stm32g4/src/bin/i2c_slave.rs b/examples/stm32g4/src/bin/i2c_slave.rs index a723a0e18..adf1f74fa 100644 --- a/examples/stm32g4/src/bin/i2c_slave.rs +++ b/examples/stm32g4/src/bin/i2c_slave.rs @@ -6,7 +6,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::i2c::{Address, OwnAddresses, SlaveCommandKind}; use embassy_stm32::mode::Async; -use embassy_stm32::time::Hertz; use embassy_stm32::{bind_interrupts, i2c, peripherals}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; @@ -127,8 +126,8 @@ async fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let speed = Hertz::khz(400); - let config = i2c::Config::default(); + let mut config = i2c::Config::default(); + config.frequency = Hertz::khz(400); let d_addr_config = i2c::SlaveAddrConfig { addr: OwnAddresses::OA1(Address::SevenBit(DEV_ADDR)), @@ -136,14 +135,14 @@ async fn main(spawner: Spawner) { }; let d_sda = p.PA8; let d_scl = p.PA9; - let device = i2c::I2c::new(p.I2C2, d_scl, d_sda, Irqs, p.DMA1_CH1, p.DMA1_CH2, speed, config) + let device = i2c::I2c::new(p.I2C2, d_scl, d_sda, Irqs, p.DMA1_CH1, p.DMA1_CH2, config) .into_slave_multimaster(d_addr_config); unwrap!(spawner.spawn(device_task(device))); let c_sda = p.PB8; let c_scl = p.PB7; - let controller = i2c::I2c::new(p.I2C1, c_sda, c_scl, Irqs, p.DMA1_CH3, p.DMA1_CH4, speed, config); + let controller = i2c::I2c::new(p.I2C1, c_sda, c_scl, Irqs, p.DMA1_CH3, p.DMA1_CH4, config); unwrap!(spawner.spawn(controller_task(controller))); } diff --git a/examples/stm32h5/src/bin/i2c.rs b/examples/stm32h5/src/bin/i2c.rs index 31e83cbb5..870c57e0f 100644 --- a/examples/stm32h5/src/bin/i2c.rs +++ b/examples/stm32h5/src/bin/i2c.rs @@ -4,7 +4,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::i2c::{Error, I2c}; -use embassy_stm32::time::Hertz; use embassy_stm32::{bind_interrupts, i2c, peripherals}; use {defmt_rtt as _, panic_probe as _}; @@ -28,7 +27,6 @@ async fn main(_spawner: Spawner) { Irqs, p.GPDMA1_CH4, p.GPDMA1_CH5, - Hertz(100_000), Default::default(), ); diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs index 170a5aa28..799291f76 100644 --- a/examples/stm32h7/src/bin/camera.rs +++ b/examples/stm32h7/src/bin/camera.rs @@ -6,7 +6,6 @@ use embassy_stm32::dcmi::{self, *}; use embassy_stm32::gpio::{Level, Output, Speed}; use embassy_stm32::i2c::I2c; use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler}; -use embassy_stm32::time::khz; use embassy_stm32::{bind_interrupts, i2c, peripherals, Config}; use embassy_time::Timer; use ov7725::*; @@ -59,7 +58,6 @@ async fn main(_spawner: Spawner) { Irqs, p.DMA1_CH1, p.DMA1_CH2, - khz(100), Default::default(), ); diff --git a/examples/stm32h7/src/bin/i2c.rs b/examples/stm32h7/src/bin/i2c.rs index 3bf39eb44..90c1c8d80 100644 --- a/examples/stm32h7/src/bin/i2c.rs +++ b/examples/stm32h7/src/bin/i2c.rs @@ -4,7 +4,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::i2c::{Error, I2c}; -use embassy_stm32::time::Hertz; use embassy_stm32::{bind_interrupts, i2c, peripherals}; use {defmt_rtt as _, panic_probe as _}; @@ -28,7 +27,6 @@ async fn main(_spawner: Spawner) { Irqs, p.DMA1_CH4, p.DMA1_CH5, - Hertz(100_000), Default::default(), ); diff --git a/examples/stm32h7/src/bin/i2c_shared.rs b/examples/stm32h7/src/bin/i2c_shared.rs index 655ff901f..3135636ee 100644 --- a/examples/stm32h7/src/bin/i2c_shared.rs +++ b/examples/stm32h7/src/bin/i2c_shared.rs @@ -8,7 +8,6 @@ use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice; use embassy_executor::Spawner; use embassy_stm32::i2c::{self, I2c}; use embassy_stm32::mode::Async; -use embassy_stm32::time::Hertz; use embassy_stm32::{bind_interrupts, peripherals}; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::blocking_mutex::NoopMutex; @@ -97,7 +96,6 @@ async fn main(spawner: Spawner) { Irqs, p.DMA1_CH4, p.DMA1_CH5, - Hertz(100_000), Default::default(), ); let i2c_bus = NoopMutex::new(RefCell::new(i2c)); diff --git a/examples/stm32h7rs/src/bin/i2c.rs b/examples/stm32h7rs/src/bin/i2c.rs index 31e83cbb5..870c57e0f 100644 --- a/examples/stm32h7rs/src/bin/i2c.rs +++ b/examples/stm32h7rs/src/bin/i2c.rs @@ -4,7 +4,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::i2c::{Error, I2c}; -use embassy_stm32::time::Hertz; use embassy_stm32::{bind_interrupts, i2c, peripherals}; use {defmt_rtt as _, panic_probe as _}; @@ -28,7 +27,6 @@ async fn main(_spawner: Spawner) { Irqs, p.GPDMA1_CH4, p.GPDMA1_CH5, - Hertz(100_000), Default::default(), ); diff --git a/examples/stm32l4/src/bin/i2c.rs b/examples/stm32l4/src/bin/i2c.rs index 2861bc091..3c42ba8f5 100644 --- a/examples/stm32l4/src/bin/i2c.rs +++ b/examples/stm32l4/src/bin/i2c.rs @@ -4,7 +4,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::i2c::I2c; -use embassy_stm32::time::Hertz; use {defmt_rtt as _, panic_probe as _}; const ADDRESS: u8 = 0x5F; @@ -13,7 +12,7 @@ const WHOAMI: u8 = 0x0F; #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default()); + let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Default::default()); let mut data = [0u8; 1]; unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data)); diff --git a/examples/stm32l4/src/bin/i2c_blocking_async.rs b/examples/stm32l4/src/bin/i2c_blocking_async.rs index a014b23e0..62153bfc8 100644 --- a/examples/stm32l4/src/bin/i2c_blocking_async.rs +++ b/examples/stm32l4/src/bin/i2c_blocking_async.rs @@ -5,7 +5,6 @@ use defmt::*; use embassy_embedded_hal::adapter::BlockingAsync; use embassy_executor::Spawner; use embassy_stm32::i2c::I2c; -use embassy_stm32::time::Hertz; use embedded_hal_async::i2c::I2c as I2cTrait; use {defmt_rtt as _, panic_probe as _}; @@ -15,7 +14,7 @@ const WHOAMI: u8 = 0x0F; #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default()); + let i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Default::default()); let mut i2c = BlockingAsync::new(i2c); let mut data = [0u8; 1]; diff --git a/examples/stm32l4/src/bin/i2c_dma.rs b/examples/stm32l4/src/bin/i2c_dma.rs index 794972a33..f34a484c5 100644 --- a/examples/stm32l4/src/bin/i2c_dma.rs +++ b/examples/stm32l4/src/bin/i2c_dma.rs @@ -4,7 +4,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::i2c::I2c; -use embassy_stm32::time::Hertz; use embassy_stm32::{bind_interrupts, i2c, peripherals}; use {defmt_rtt as _, panic_probe as _}; @@ -26,7 +25,6 @@ async fn main(_spawner: Spawner) { Irqs, p.DMA1_CH4, p.DMA1_CH5, - Hertz(100_000), Default::default(), ); diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index dc90a3b85..516badcb2 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs @@ -115,7 +115,6 @@ async fn main(spawner: Spawner) { Irqs, dp.DMA1_CH6, dp.DMA1_CH7, - Hertz(100_000), I2C_Config::default(), ); diff --git a/examples/stm32u0/src/bin/i2c.rs b/examples/stm32u0/src/bin/i2c.rs index 2861bc091..3c42ba8f5 100644 --- a/examples/stm32u0/src/bin/i2c.rs +++ b/examples/stm32u0/src/bin/i2c.rs @@ -4,7 +4,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::i2c::I2c; -use embassy_stm32::time::Hertz; use {defmt_rtt as _, panic_probe as _}; const ADDRESS: u8 = 0x5F; @@ -13,7 +12,7 @@ const WHOAMI: u8 = 0x0F; #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default()); + let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Default::default()); let mut data = [0u8; 1]; unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data)); diff --git a/examples/stm32u5/src/bin/i2c.rs b/examples/stm32u5/src/bin/i2c.rs index d5f5d6f60..5577f7211 100644 --- a/examples/stm32u5/src/bin/i2c.rs +++ b/examples/stm32u5/src/bin/i2c.rs @@ -4,7 +4,6 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; use embassy_stm32::i2c::I2c; -use embassy_stm32::time::Hertz; use {defmt_rtt as _, panic_probe as _}; const HTS221_ADDRESS: u8 = 0x5F; @@ -13,7 +12,7 @@ const WHOAMI: u8 = 0x0F; #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let mut i2c = I2c::new_blocking(p.I2C2, p.PF1, p.PF0, Hertz(100_000), Default::default()); + let mut i2c = I2c::new_blocking(p.I2C2, p.PF1, p.PF0, Default::default()); let mut data = [0u8; 1]; unwrap!(i2c.blocking_write_read(HTS221_ADDRESS, &[WHOAMI], &mut data)); -- cgit From 8b65101a7cc685c17acebddce87330581107f1ea Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Fri, 8 Aug 2025 23:09:39 +0800 Subject: rename rise_fall_speed to gpio_speed for spi --- embassy-stm32/src/spi/mod.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index c8d83f07e..4c5308eba 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -71,7 +71,7 @@ pub struct Config { pub miso_pull: Pull, /// signal rise/fall speed (slew rate) - defaults to `Medium`. /// Increase for high SPI speeds. Change to `Low` to reduce ringing. - pub rise_fall_speed: Speed, + pub gpio_speed: Speed, } impl Default for Config { @@ -81,7 +81,7 @@ impl Default for Config { bit_order: BitOrder::MsbFirst, frequency: Hertz(1_000_000), miso_pull: Pull::None, - rise_fall_speed: Speed::VeryHigh, + gpio_speed: Speed::VeryHigh, } } } @@ -110,14 +110,14 @@ impl Config { #[cfg(gpio_v1)] fn sck_af(&self) -> AfType { - AfType::output(OutputType::PushPull, self.rise_fall_speed) + AfType::output(OutputType::PushPull, self.gpio_speed) } #[cfg(gpio_v2)] fn sck_af(&self) -> AfType { AfType::output_pull( OutputType::PushPull, - self.rise_fall_speed, + self.gpio_speed, match self.mode.polarity { Polarity::IdleLow => Pull::Down, Polarity::IdleHigh => Pull::Up, @@ -136,7 +136,7 @@ pub struct Spi<'d, M: PeriMode> { rx_dma: Option>, _phantom: PhantomData, current_word_size: word_impl::Config, - rise_fall_speed: Speed, + gpio_speed: Speed, } impl<'d, M: PeriMode> Spi<'d, M> { @@ -159,7 +159,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { rx_dma, current_word_size: ::CONFIG, _phantom: PhantomData, - rise_fall_speed: config.rise_fall_speed, + gpio_speed: config.gpio_speed, }; this.enable_and_init(config); this @@ -265,12 +265,12 @@ impl<'d, M: PeriMode> Spi<'d, M> { #[cfg(gpio_v2)] { - self.rise_fall_speed = config.rise_fall_speed; + self.gpio_speed = config.gpio_speed; if let Some(sck) = self.sck.as_ref() { - sck.set_speed(config.rise_fall_speed); + sck.set_speed(config.gpio_speed); } if let Some(mosi) = self.mosi.as_ref() { - mosi.set_speed(config.rise_fall_speed); + mosi.set_speed(config.gpio_speed); } } @@ -347,7 +347,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { bit_order, frequency, miso_pull, - rise_fall_speed: self.rise_fall_speed, + gpio_speed: self.gpio_speed, } } @@ -481,7 +481,7 @@ impl<'d> Spi<'d, Blocking> { Self::new_inner( peri, new_pin!(sck, config.sck_af()), - new_pin!(mosi, AfType::output(OutputType::PushPull, config.rise_fall_speed)), + new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), new_pin!(miso, AfType::input(config.miso_pull)), None, None, @@ -517,7 +517,7 @@ impl<'d> Spi<'d, Blocking> { Self::new_inner( peri, new_pin!(sck, config.sck_af()), - new_pin!(mosi, AfType::output(OutputType::PushPull, config.rise_fall_speed)), + new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), None, None, None, @@ -536,7 +536,7 @@ impl<'d> Spi<'d, Blocking> { Self::new_inner( peri, None, - new_pin!(mosi, AfType::output(OutputType::PushPull, config.rise_fall_speed)), + new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), None, None, None, @@ -559,7 +559,7 @@ impl<'d> Spi<'d, Async> { Self::new_inner( peri, new_pin!(sck, config.sck_af()), - new_pin!(mosi, AfType::output(OutputType::PushPull, config.rise_fall_speed)), + new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), new_pin!(miso, AfType::input(config.miso_pull)), new_dma!(tx_dma), new_dma!(rx_dma), @@ -601,7 +601,7 @@ impl<'d> Spi<'d, Async> { Self::new_inner( peri, new_pin!(sck, config.sck_af()), - new_pin!(mosi, AfType::output(OutputType::PushPull, config.rise_fall_speed)), + new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), None, new_dma!(tx_dma), None, @@ -621,7 +621,7 @@ impl<'d> Spi<'d, Async> { Self::new_inner( peri, None, - new_pin!(mosi, AfType::output(OutputType::PushPull, config.rise_fall_speed)), + new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), None, new_dma!(tx_dma), None, -- cgit From d5bf29a30308211bb5d415e59d91507e233b6d4a Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Fri, 8 Aug 2025 23:14:08 +0800 Subject: stm32 i2c v2: rename freq to frequency --- embassy-stm32/src/i2c/v2.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 76f0d25dc..4d341bab1 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -1320,9 +1320,9 @@ struct Timings { } impl Timings { - fn new(i2cclk: Hertz, freq: Hertz) -> Self { + fn new(i2cclk: Hertz, frequency: Hertz) -> Self { let i2cclk = i2cclk.0; - let freq = freq.0; + let frequency = frequency.0; // Refer to RM0433 Rev 7 Figure 539 for setup and hold timing: // // t_I2CCLK = 1 / PCLK1 @@ -1332,13 +1332,13 @@ impl Timings { // // t_SYNC1 + t_SYNC2 > 4 * t_I2CCLK // t_SCL ~= t_SYNC1 + t_SYNC2 + t_SCLL + t_SCLH - let ratio = i2cclk / freq; + let ratio = i2cclk / frequency; // For the standard-mode configuration method, we must have a ratio of 4 // or higher assert!(ratio >= 4, "The I2C PCLK must be at least 4 times the bus frequency!"); - let (presc_reg, scll, sclh, sdadel, scldel) = if freq > 100_000 { + let (presc_reg, scll, sclh, sdadel, scldel) = if frequency > 100_000 { // Fast-mode (Fm) or Fast-mode Plus (Fm+) // here we pick SCLL + 1 = 2 * (SCLH + 1) @@ -1352,7 +1352,7 @@ impl Timings { let sclh = ((ratio / presc) - 3) / 3; let scll = (2 * (sclh + 1)) - 1; - let (sdadel, scldel) = if freq > 400_000 { + let (sdadel, scldel) = if frequency > 400_000 { // Fast-mode Plus (Fm+) assert!(i2cclk >= 17_000_000); // See table in datsheet -- cgit From cf41ad464ca3f81f95889366ee42700c6f5cbf41 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Fri, 8 Aug 2025 23:30:11 +0800 Subject: add forgotten import --- embassy-stm32/src/i2c/config.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/src/i2c/config.rs b/embassy-stm32/src/i2c/config.rs index 0b4e091b8..b27bb778c 100644 --- a/embassy-stm32/src/i2c/config.rs +++ b/embassy-stm32/src/i2c/config.rs @@ -1,6 +1,7 @@ #[cfg(gpio_v2)] use crate::gpio::Pull; use crate::gpio::{AfType, OutputType, Speed}; +use crate::time::Hertz; #[repr(u8)] #[derive(Copy, Clone)] -- cgit From da0b59ce284e8818d297fac20acef56d99cdbeb3 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Fri, 8 Aug 2025 23:32:42 +0800 Subject: rustfmt --- examples/stm32f4/src/bin/i2c_async.rs | 10 +--------- examples/stm32f4/src/bin/i2c_comparison.rs | 30 +++--------------------------- examples/stm32g0/src/bin/i2c_async.rs | 10 +--------- examples/stm32g4/src/bin/i2c_slave.rs | 4 ++-- examples/stm32h7/src/bin/camera.rs | 10 +--------- examples/stm32h7/src/bin/i2c.rs | 10 +--------- examples/stm32h7/src/bin/i2c_shared.rs | 10 +--------- examples/stm32l4/src/bin/i2c_dma.rs | 10 +--------- 8 files changed, 11 insertions(+), 83 deletions(-) diff --git a/examples/stm32f4/src/bin/i2c_async.rs b/examples/stm32f4/src/bin/i2c_async.rs index e065910d8..0065e92f3 100644 --- a/examples/stm32f4/src/bin/i2c_async.rs +++ b/examples/stm32f4/src/bin/i2c_async.rs @@ -22,15 +22,7 @@ async fn main(_spawner: Spawner) { info!("Hello world!"); let p = embassy_stm32::init(Default::default()); - let mut i2c = I2c::new( - p.I2C1, - p.PB8, - p.PB7, - Irqs, - p.DMA1_CH6, - p.DMA1_CH0, - Default::default(), - ); + let mut i2c = I2c::new(p.I2C1, p.PB8, p.PB7, Irqs, p.DMA1_CH6, p.DMA1_CH0, Default::default()); loop { let a1454_read_sensor_command = [0x1F]; diff --git a/examples/stm32f4/src/bin/i2c_comparison.rs b/examples/stm32f4/src/bin/i2c_comparison.rs index 3713601b1..59bdb8b67 100644 --- a/examples/stm32f4/src/bin/i2c_comparison.rs +++ b/examples/stm32f4/src/bin/i2c_comparison.rs @@ -47,35 +47,11 @@ async fn main(_spawner: Spawner) { info!("Setting up peripherals."); let p = embassy_stm32::init(Default::default()); - let mut i2c1 = I2c::new( - p.I2C1, - p.PB8, - p.PB7, - Irqs, - p.DMA1_CH6, - p.DMA1_CH0, - Default::default(), - ); + let mut i2c1 = I2c::new(p.I2C1, p.PB8, p.PB7, Irqs, p.DMA1_CH6, p.DMA1_CH0, Default::default()); - let mut i2c2 = I2c::new( - p.I2C2, - p.PB10, - p.PB11, - Irqs, - p.DMA1_CH7, - p.DMA1_CH3, - Default::default(), - ); + let mut i2c2 = I2c::new(p.I2C2, p.PB10, p.PB11, Irqs, p.DMA1_CH7, p.DMA1_CH3, Default::default()); - let mut i2c3 = I2c::new( - p.I2C3, - p.PA8, - p.PC9, - Irqs, - p.DMA1_CH4, - p.DMA1_CH2, - Default::default(), - ); + let mut i2c3 = I2c::new(p.I2C3, p.PA8, p.PC9, Irqs, p.DMA1_CH4, p.DMA1_CH2, Default::default()); let a1454_read_sensor_command = [0x1F]; let mut i2c1_buffer: [u8; 4] = [0, 0, 0, 0]; diff --git a/examples/stm32g0/src/bin/i2c_async.rs b/examples/stm32g0/src/bin/i2c_async.rs index 19c52c21d..e62d9266b 100644 --- a/examples/stm32g0/src/bin/i2c_async.rs +++ b/examples/stm32g0/src/bin/i2c_async.rs @@ -22,15 +22,7 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); let mut data = [0u8; 2]; - let mut i2c = I2c::new( - p.I2C1, - p.PB8, - p.PB9, - Irqs, - p.DMA1_CH1, - p.DMA1_CH2, - Default::default(), - ); + let mut i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, p.DMA1_CH1, p.DMA1_CH2, Default::default()); loop { match i2c.write_read(TMP117_ADDR, &[TMP117_TEMP_RESULT], &mut data).await { diff --git a/examples/stm32g4/src/bin/i2c_slave.rs b/examples/stm32g4/src/bin/i2c_slave.rs index adf1f74fa..9eac612b6 100644 --- a/examples/stm32g4/src/bin/i2c_slave.rs +++ b/examples/stm32g4/src/bin/i2c_slave.rs @@ -135,8 +135,8 @@ async fn main(spawner: Spawner) { }; let d_sda = p.PA8; let d_scl = p.PA9; - let device = i2c::I2c::new(p.I2C2, d_scl, d_sda, Irqs, p.DMA1_CH1, p.DMA1_CH2, config) - .into_slave_multimaster(d_addr_config); + let device = + i2c::I2c::new(p.I2C2, d_scl, d_sda, Irqs, p.DMA1_CH1, p.DMA1_CH2, config).into_slave_multimaster(d_addr_config); unwrap!(spawner.spawn(device_task(device))); diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs index 799291f76..8f2e265d6 100644 --- a/examples/stm32h7/src/bin/camera.rs +++ b/examples/stm32h7/src/bin/camera.rs @@ -51,15 +51,7 @@ async fn main(_spawner: Spawner) { let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV3); let mut led = Output::new(p.PE3, Level::High, Speed::Low); - let cam_i2c = I2c::new( - p.I2C1, - p.PB8, - p.PB9, - Irqs, - p.DMA1_CH1, - p.DMA1_CH2, - Default::default(), - ); + let cam_i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, p.DMA1_CH1, p.DMA1_CH2, Default::default()); let mut camera = Ov7725::new(cam_i2c, mco); diff --git a/examples/stm32h7/src/bin/i2c.rs b/examples/stm32h7/src/bin/i2c.rs index 90c1c8d80..c40af4935 100644 --- a/examples/stm32h7/src/bin/i2c.rs +++ b/examples/stm32h7/src/bin/i2c.rs @@ -20,15 +20,7 @@ async fn main(_spawner: Spawner) { info!("Hello world!"); let p = embassy_stm32::init(Default::default()); - let mut i2c = I2c::new( - p.I2C2, - p.PB10, - p.PB11, - Irqs, - p.DMA1_CH4, - p.DMA1_CH5, - Default::default(), - ); + let mut i2c = I2c::new(p.I2C2, p.PB10, p.PB11, Irqs, p.DMA1_CH4, p.DMA1_CH5, Default::default()); let mut data = [0u8; 1]; diff --git a/examples/stm32h7/src/bin/i2c_shared.rs b/examples/stm32h7/src/bin/i2c_shared.rs index 3135636ee..560f97aa3 100644 --- a/examples/stm32h7/src/bin/i2c_shared.rs +++ b/examples/stm32h7/src/bin/i2c_shared.rs @@ -89,15 +89,7 @@ async fn humidity(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async, async fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let i2c = I2c::new( - p.I2C1, - p.PB8, - p.PB9, - Irqs, - p.DMA1_CH4, - p.DMA1_CH5, - Default::default(), - ); + let i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, p.DMA1_CH4, p.DMA1_CH5, Default::default()); let i2c_bus = NoopMutex::new(RefCell::new(i2c)); let i2c_bus = I2C_BUS.init(i2c_bus); diff --git a/examples/stm32l4/src/bin/i2c_dma.rs b/examples/stm32l4/src/bin/i2c_dma.rs index f34a484c5..0f5690e37 100644 --- a/examples/stm32l4/src/bin/i2c_dma.rs +++ b/examples/stm32l4/src/bin/i2c_dma.rs @@ -18,15 +18,7 @@ bind_interrupts!(struct Irqs { #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let mut i2c = I2c::new( - p.I2C2, - p.PB10, - p.PB11, - Irqs, - p.DMA1_CH4, - p.DMA1_CH5, - Default::default(), - ); + let mut i2c = I2c::new(p.I2C2, p.PB10, p.PB11, Irqs, p.DMA1_CH4, p.DMA1_CH5, Default::default()); let mut data = [0u8; 1]; unwrap!(i2c.write_read(ADDRESS, &[WHOAMI], &mut data).await); -- cgit From 66008e4140d8e4f87b3f57d2459617047405fa14 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Fri, 8 Aug 2025 23:37:47 +0800 Subject: revert deleted import --- examples/stm32g4/src/bin/i2c_slave.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/stm32g4/src/bin/i2c_slave.rs b/examples/stm32g4/src/bin/i2c_slave.rs index 9eac612b6..8b255b0e6 100644 --- a/examples/stm32g4/src/bin/i2c_slave.rs +++ b/examples/stm32g4/src/bin/i2c_slave.rs @@ -6,6 +6,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::i2c::{Address, OwnAddresses, SlaveCommandKind}; use embassy_stm32::mode::Async; +use embassy_stm32::time::Hertz; use embassy_stm32::{bind_interrupts, i2c, peripherals}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; -- cgit From a165339276e751909a88f685760f4cabb71e50d1 Mon Sep 17 00:00:00 2001 From: nerwalt Date: Thu, 7 Aug 2025 09:07:29 -0600 Subject: Adds RRAMC support for the nrf54l15 Adds an Nvmc driver alias for compatibility --- embassy-nrf/src/chips/nrf54l15_app.rs | 8 +- embassy-nrf/src/lib.rs | 6 +- embassy-nrf/src/rramc.rs | 176 ++++++++++++++++++++++++++++++++++ examples/nrf54l15/Cargo.toml | 2 + examples/nrf54l15/src/bin/nvmc.rs | 44 +++++++++ 5 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 embassy-nrf/src/rramc.rs create mode 100644 examples/nrf54l15/src/bin/nvmc.rs diff --git a/embassy-nrf/src/chips/nrf54l15_app.rs b/embassy-nrf/src/chips/nrf54l15_app.rs index b133eb565..3a4e1ae4a 100644 --- a/embassy-nrf/src/chips/nrf54l15_app.rs +++ b/embassy-nrf/src/chips/nrf54l15_app.rs @@ -201,9 +201,15 @@ pub mod pac { pub const EASY_DMA_SIZE: usize = (1 << 16) - 1; //pub const FORCE_COPY_BUFFER_SIZE: usize = 1024; -//pub const FLASH_SIZE: usize = 1024 * 1024; +// 1.5 MB NVM +#[allow(unused)] +pub const FLASH_SIZE: usize = 1536 * 1024; embassy_hal_internal::peripherals! { + #[cfg(feature = "_s")] + // RRAMC + RRAMC, + // GPIO port 0 P0_00, P0_01, diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index ba8206d13..d3c4b3bb1 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -98,8 +98,12 @@ pub mod ipc; feature = "_nrf5340-app" ))] pub mod nfct; -#[cfg(not(feature = "_nrf54l"))] // TODO +#[cfg(not(feature = "_nrf54l"))] pub mod nvmc; +#[cfg(feature = "nrf54l15-app-s")] +pub mod rramc; +#[cfg(feature = "nrf54l15-app-s")] +pub use rramc as nvmc; #[cfg(not(feature = "_nrf54l"))] // TODO #[cfg(any( feature = "nrf52810", diff --git a/embassy-nrf/src/rramc.rs b/embassy-nrf/src/rramc.rs new file mode 100644 index 000000000..7cb5660cb --- /dev/null +++ b/embassy-nrf/src/rramc.rs @@ -0,0 +1,176 @@ +//! Resistive Random-Access Memory Controller driver. + +use core::{ptr, slice}; + +use embedded_storage::nor_flash::{ + ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash, +}; + +use crate::peripherals::RRAMC; +use crate::{pac, Peri}; + +// +// Export Nvmc alias and page size for downstream compatibility +// +/// RRAM-backed `Nvmc` compatibile driver. +pub type Nvmc<'d> = Rramc<'d>; +/// Emulated page size. RRAM does not use pages. This exists only for downstream compatibility. +pub const PAGE_SIZE: usize = 4096; + +// In bytes, one line is 128 bits +const WRITE_LINE_SIZE: usize = 16; + +/// Size of RRAM flash in bytes. +pub const FLASH_SIZE: usize = crate::chip::FLASH_SIZE; + +/// Error type for RRAMC operations. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Error { + /// Operation using a location not in flash. + OutOfBounds, + /// Unaligned operation or using unaligned buffers. + Unaligned, +} + +impl NorFlashError for Error { + fn kind(&self) -> NorFlashErrorKind { + match self { + Self::OutOfBounds => NorFlashErrorKind::OutOfBounds, + Self::Unaligned => NorFlashErrorKind::NotAligned, + } + } +} + +/// Resistive Random-Access Memory Controller (RRAMC) that implements the `embedded-storage` +/// traits. +pub struct Rramc<'d> { + _p: Peri<'d, RRAMC>, +} + +impl<'d> Rramc<'d> { + /// Create Rramc driver. + pub fn new(_p: Peri<'d, RRAMC>) -> Self { + Self { _p } + } + + fn regs() -> pac::rramc::Rramc { + pac::RRAMC + } + + fn wait_ready(&mut self) { + let p = Self::regs(); + while !p.ready().read().ready() {} + } + + fn wait_ready_write(&mut self) { + let p = Self::regs(); + while !p.readynext().read().readynext() {} + while !p.bufstatus().writebufempty().read().empty() {} + } + + fn enable_read(&self) { + Self::regs().config().write(|w| w.set_wen(false)); + } + + fn enable_write(&self) { + Self::regs().config().write(|w| w.set_wen(true)); + } +} + +// +// RRAM is not NOR flash, but many crates require embedded-storage NorFlash traits. We therefore +// implement the traits for downstream compatibility. +// + +impl<'d> MultiwriteNorFlash for Rramc<'d> {} + +impl<'d> ErrorType for Rramc<'d> { + type Error = Error; +} + +impl<'d> ReadNorFlash for Rramc<'d> { + const READ_SIZE: usize = 1; + + fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { + if offset as usize >= FLASH_SIZE || offset as usize + bytes.len() > FLASH_SIZE { + return Err(Error::OutOfBounds); + } + + let flash_data = unsafe { slice::from_raw_parts(offset as *const u8, bytes.len()) }; + bytes.copy_from_slice(flash_data); + Ok(()) + } + + fn capacity(&self) -> usize { + FLASH_SIZE + } +} + +impl<'d> NorFlash for Rramc<'d> { + const WRITE_SIZE: usize = WRITE_LINE_SIZE; + const ERASE_SIZE: usize = PAGE_SIZE; + + // RRAM can overwrite in-place, so emulate page erases by overwriting the page bytes with 0xFF. + fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { + if to < from || to as usize > FLASH_SIZE { + return Err(Error::OutOfBounds); + } + if from as usize % Self::ERASE_SIZE != 0 || to as usize % Self::ERASE_SIZE != 0 { + return Err(Error::Unaligned); + } + + self.enable_write(); + self.wait_ready(); + + // Treat each emulated page separately so callers can rely on post‑erase read‑back + // returning 0xFF just like on real NOR flash. + let buf = [0xFFu8; Self::WRITE_SIZE]; + for page_addr in (from..to).step_by(Self::ERASE_SIZE) { + let page_end = page_addr + Self::ERASE_SIZE as u32; + for line_addr in (page_addr..page_end).step_by(Self::WRITE_SIZE) { + unsafe { + let src = buf.as_ptr() as *const u32; + let dst = line_addr as *mut u32; + for i in 0..(Self::WRITE_SIZE / 4) { + core::ptr::write_volatile(dst.add(i), core::ptr::read_unaligned(src.add(i))); + } + } + self.wait_ready_write(); + } + } + + self.enable_read(); + self.wait_ready(); + Ok(()) + } + + fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { + if offset as usize + bytes.len() > FLASH_SIZE { + return Err(Error::OutOfBounds); + } + if offset as usize % Self::WRITE_SIZE != 0 || bytes.len() % Self::WRITE_SIZE != 0 { + return Err(Error::Unaligned); + } + + self.enable_write(); + self.wait_ready(); + + unsafe { + let p_src = bytes.as_ptr() as *const u32; + let p_dst = offset as *mut u32; + let words = bytes.len() / 4; + for i in 0..words { + let w = ptr::read_unaligned(p_src.add(i)); + ptr::write_volatile(p_dst.add(i), w); + if (i + 1) % (Self::WRITE_SIZE / 4) == 0 { + self.wait_ready_write(); + } + } + } + + self.enable_read(); + self.wait_ready(); + Ok(()) + } +} diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index faa3a4abe..5f1ee50a0 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml @@ -16,5 +16,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" +embedded-storage = "0.3.1" + [profile.release] debug = 2 diff --git a/examples/nrf54l15/src/bin/nvmc.rs b/examples/nrf54l15/src/bin/nvmc.rs new file mode 100644 index 000000000..f990604cd --- /dev/null +++ b/examples/nrf54l15/src/bin/nvmc.rs @@ -0,0 +1,44 @@ +#![no_std] +#![no_main] + +use defmt::{info, unwrap}; +use embassy_executor::Spawner; +use embassy_nrf::nvmc::{Nvmc, PAGE_SIZE}; +use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + info!("Hello RRAMC NVMC!"); + + let mut f = Nvmc::new(p.RRAMC); + + const ADDR: u32 = 0x80000; + let mut buf = [0u8; 4]; + + info!("Reading..."); + unwrap!(f.read(ADDR, &mut buf)); + info!("Read: {=[u8]:x}", buf); + + info!("Erasing..."); + unwrap!(f.erase(ADDR, ADDR + PAGE_SIZE as u32)); + + info!("Reading..."); + unwrap!(f.read(ADDR, &mut buf)); + info!("Read: {=[u8]:x}", buf); + + info!("Writing..."); + // 16 B (128-bit) write minimum + let out: [u8; 16] = [ + 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, + ]; + unwrap!(f.write(ADDR, &out)); + + info!("Reading..."); + // Can read arbitrary sizes + for addr in (ADDR..ADDR + 16).step_by(4) { + unwrap!(f.read(addr, &mut buf)); + info!("Read: {=[u8]:x}", buf); + } +} -- cgit From adc0fc0a974476e0424077c2cf6c652e6c42ea86 Mon Sep 17 00:00:00 2001 From: nerwalt Date: Fri, 8 Aug 2025 10:23:22 -0600 Subject: Adds WDT support for the nrf54l15 --- embassy-nrf/Cargo.toml | 2 +- embassy-nrf/src/chips/nrf54l15_app.rs | 9 ++++++++ embassy-nrf/src/lib.rs | 1 - embassy-nrf/src/wdt.rs | 8 +++---- examples/nrf54l15/src/bin/wdt.rs | 41 +++++++++++++++++++++++++++++++++++ 5 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 examples/nrf54l15/src/bin/wdt.rs diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 95ec83824..92378db0b 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -88,7 +88,7 @@ nrf5340-app-ns = ["_nrf5340-app", "_ns"] ## nRF5340 network core nrf5340-net = ["_nrf5340-net"] ## nRF54L15 application core in Secure mode -nrf54l15-app-s = ["_nrf54l15-app", "_s"] +nrf54l15-app-s = ["_nrf54l15-app", "_s", "_multi_wdt"] ## nRF54L15 application core in Non-Secure mode nrf54l15-app-ns = ["_nrf54l15-app", "_ns"] diff --git a/embassy-nrf/src/chips/nrf54l15_app.rs b/embassy-nrf/src/chips/nrf54l15_app.rs index b133eb565..f8d1befd7 100644 --- a/embassy-nrf/src/chips/nrf54l15_app.rs +++ b/embassy-nrf/src/chips/nrf54l15_app.rs @@ -204,6 +204,11 @@ pub const EASY_DMA_SIZE: usize = (1 << 16) - 1; //pub const FLASH_SIZE: usize = 1024 * 1024; embassy_hal_internal::peripherals! { + // WDT + WDT0, + #[cfg(feature = "_s")] + WDT1, + // GPIO port 0 P0_00, P0_01, @@ -285,6 +290,10 @@ impl_pin!(P2_08, 2, 8); impl_pin!(P2_09, 2, 9); impl_pin!(P2_10, 2, 10); +impl_wdt!(WDT0, WDT31, WDT31, 0); +#[cfg(feature = "_s")] +impl_wdt!(WDT1, WDT30, WDT30, 1); + embassy_hal_internal::interrupt_mod!( SWI00, SWI01, diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index ba8206d13..3d1f2d4c0 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -170,7 +170,6 @@ pub mod uarte; feature = "nrf52840" ))] pub mod usb; -#[cfg(not(feature = "_nrf54l"))] // TODO pub mod wdt; // This mod MUST go last, so that it sees all the `impl_foo!` macros diff --git a/embassy-nrf/src/wdt.rs b/embassy-nrf/src/wdt.rs index 308071726..7ab9adc29 100644 --- a/embassy-nrf/src/wdt.rs +++ b/embassy-nrf/src/wdt.rs @@ -37,9 +37,9 @@ impl Config { pub fn try_new(_wdt: &Peri<'_, T>) -> Option { let r = T::REGS; - #[cfg(not(any(feature = "_nrf91", feature = "_nrf5340")))] + #[cfg(not(any(feature = "_nrf91", feature = "_nrf5340", feature = "_nrf54l")))] let runstatus = r.runstatus().read().runstatus(); - #[cfg(any(feature = "_nrf91", feature = "_nrf5340"))] + #[cfg(any(feature = "_nrf91", feature = "_nrf5340", feature = "_nrf54l"))] let runstatus = r.runstatus().read().runstatuswdt(); if runstatus { @@ -90,9 +90,9 @@ impl Watchdog { let crv = config.timeout_ticks.max(MIN_TICKS); let rren = crate::pac::wdt::regs::Rren((1u32 << N) - 1); - #[cfg(not(any(feature = "_nrf91", feature = "_nrf5340")))] + #[cfg(not(any(feature = "_nrf91", feature = "_nrf5340", feature = "_nrf54l")))] let runstatus = r.runstatus().read().runstatus(); - #[cfg(any(feature = "_nrf91", feature = "_nrf5340"))] + #[cfg(any(feature = "_nrf91", feature = "_nrf5340", feature = "_nrf54l"))] let runstatus = r.runstatus().read().runstatuswdt(); if runstatus { diff --git a/examples/nrf54l15/src/bin/wdt.rs b/examples/nrf54l15/src/bin/wdt.rs new file mode 100644 index 000000000..28856dad4 --- /dev/null +++ b/examples/nrf54l15/src/bin/wdt.rs @@ -0,0 +1,41 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_nrf::wdt::{Config, HaltConfig, Watchdog}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + info!("Hello WDT"); + + const TIMEOUT_S: u32 = 5; + + let mut config = Config::default(); + config.timeout_ticks = 32768 * TIMEOUT_S; + + // This is needed for `probe-rs run` to be able to catch the panic message + // in the WDT interrupt. The core resets 2 ticks after firing the interrupt. + config.action_during_debug_halt = HaltConfig::PAUSE; + + // The nrf54l15 has two watchdogs. Only WDT0 is available in non-secure (ns) mode, as WDT1 is + // reserved for the secure (s) environment. In secure mode, both WDT0 and WDT1 are available. + info!("Watchdog launched with {} s timeout", TIMEOUT_S); + let (_wdt, [mut handle]) = match Watchdog::try_new(p.WDT1, config) { + Ok(x) => x, + Err(_) => { + info!("Watchdog already active with wrong config, waiting for it to timeout..."); + loop {} + } + }; + + for wait in 1..=TIMEOUT_S { + info!("Waiting {} seconds ...", wait); + Timer::after_secs(wait as u64).await; + handle.pet(); + info!("Pet watchdog"); + } +} -- cgit From 1d08cde6e45c900fad970d07529296f9850c3dff Mon Sep 17 00:00:00 2001 From: nerwalt Date: Fri, 8 Aug 2025 11:03:36 -0600 Subject: Fixes broken NS build --- embassy-nrf/src/chips/nrf54l15_app.rs | 6 ++++++ examples/nrf54l15/src/bin/wdt.rs | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/embassy-nrf/src/chips/nrf54l15_app.rs b/embassy-nrf/src/chips/nrf54l15_app.rs index f8d1befd7..9893cbd13 100644 --- a/embassy-nrf/src/chips/nrf54l15_app.rs +++ b/embassy-nrf/src/chips/nrf54l15_app.rs @@ -205,6 +205,9 @@ pub const EASY_DMA_SIZE: usize = (1 << 16) - 1; embassy_hal_internal::peripherals! { // WDT + #[cfg(feature = "_ns")] + WDT, + #[cfg(feature = "_s")] WDT0, #[cfg(feature = "_s")] WDT1, @@ -290,6 +293,9 @@ impl_pin!(P2_08, 2, 8); impl_pin!(P2_09, 2, 9); impl_pin!(P2_10, 2, 10); +#[cfg(feature = "_ns")] +impl_wdt!(WDT, WDT31, WDT31, 0); +#[cfg(feature = "_s")] impl_wdt!(WDT0, WDT31, WDT31, 0); #[cfg(feature = "_s")] impl_wdt!(WDT1, WDT30, WDT30, 1); diff --git a/examples/nrf54l15/src/bin/wdt.rs b/examples/nrf54l15/src/bin/wdt.rs index 28856dad4..9fe37d080 100644 --- a/examples/nrf54l15/src/bin/wdt.rs +++ b/examples/nrf54l15/src/bin/wdt.rs @@ -21,8 +21,9 @@ async fn main(_spawner: Spawner) { // in the WDT interrupt. The core resets 2 ticks after firing the interrupt. config.action_during_debug_halt = HaltConfig::PAUSE; - // The nrf54l15 has two watchdogs. Only WDT0 is available in non-secure (ns) mode, as WDT1 is - // reserved for the secure (s) environment. In secure mode, both WDT0 and WDT1 are available. + // The nrf54l15 has two watchdogs. Only one (WDT) is available in non-secure (ns) mode, as the + // other is reserved for the secure (s) environment. In secure mode, both are available as WDT0 + // and WDT1. info!("Watchdog launched with {} s timeout", TIMEOUT_S); let (_wdt, [mut handle]) = match Watchdog::try_new(p.WDT1, config) { Ok(x) => x, -- cgit From 0b8d448dbaa5603f5ae970eb9c80b9adcd8298e3 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Sat, 9 Aug 2025 19:06:32 +0200 Subject: chore: bump bt-hci version to 0.4.0 for cyw43 --- cyw43/CHANGELOG.md | 2 ++ cyw43/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cyw43/CHANGELOG.md b/cyw43/CHANGELOG.md index c800e785b..7de0073b6 100644 --- a/cyw43/CHANGELOG.md +++ b/cyw43/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- bump bt-hci to 0.4.0 + ## 0.4.0 - 2025-07-15 - bump embassy-sync to 0.7.0 diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index 8aef8963c..74c9f1f3a 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -36,7 +36,7 @@ heapless = "0.8.0" # Bluetooth deps embedded-io-async = { version = "0.6.0", optional = true } -bt-hci = { version = "0.3.0", optional = true } +bt-hci = { version = "0.4.0", optional = true } [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/cyw43-v$VERSION/cyw43/src/" -- cgit From 7dad187ff740a0a1940d2d503fbc373218f4bd01 Mon Sep 17 00:00:00 2001 From: Jakob Date: Wed, 6 Aug 2025 10:46:21 +0200 Subject: Add methods for setting ossi, ossr, osi and oisn along with software trigger for break input --- embassy-stm32/src/timer/complementary_pwm.rs | 45 +++++++++++++++++++++++++++- embassy-stm32/src/timer/low_level.rs | 25 ++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index b00cc18ad..1178e7d83 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -2,7 +2,7 @@ use core::marker::PhantomData; -use stm32_metapac::timer::vals::Ckd; +pub use stm32_metapac::timer::vals::{Ckd, Ossi, Ossr}; use super::low_level::{CountingMode, OutputPolarity, Timer}; use super::simple_pwm::PwmPin; @@ -82,6 +82,49 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { this } + /// Set output idle state for all channels + /// - `output_high_when_idle` - true if the output for the normal channels should + /// be high when idle, which means that the complementary channels are low. Opposite + /// for `false`. + pub fn set_output_idle_state(&self, output_high_when_idle: bool) { + [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] + .iter() + .for_each(|&channel| { + self.inner.set_ois(channel, output_high_when_idle); + self.inner.set_oisn(channel, !output_high_when_idle); + }); + } + + /// Set state of OSSI-bit in BDTR register + pub fn set_off_state_selection_idle(&self, val: Ossi) { + self.inner.set_ossi(val); + } + + /// Set state of OSSR-bit in BDTR register + pub fn set_off_state_selection_run(&self, val: Ossr) { + self.inner.set_ossr(val); + } + + /// Trigger break input from software + pub fn trigger_software_break(&self, n: usize) { + self.inner.trigger_software_break(n); + } + + /// Set Master Output Enable + pub fn set_master_output_enable(&mut self, enable: bool) { + self.inner.set_moe(enable); + } + + /// Set Master Slave Mode 2 + pub fn set_mms2(&mut self, mms2: Mms2) { + self.inner.set_mms2_selection(mms2); + } + + /// Set Repetition Counter + pub fn set_repetition_counter(&mut self, val: u16) { + self.inner.set_repetition_counter(val); + } + /// Enable the given channel. pub fn enable(&mut self, channel: Channel) { self.inner.enable_channel(channel, true); diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index dc8ceb725..01bf60869 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -686,6 +686,16 @@ impl<'d, T: AdvancedInstance1Channel> Timer<'d, T> { self.regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value)); } + /// Set state of OSSI-bit in BDTR register + pub fn set_ossi(&self, val: vals::Ossi) { + self.regs_1ch_cmp().bdtr().modify(|w| w.set_ossi(val)); + } + + /// Set state of OSSR-bit in BDTR register + pub fn set_ossr(&self, val: vals::Ossr) { + self.regs_1ch_cmp().bdtr().modify(|w| w.set_ossr(val)); + } + /// Set state of MOE-bit in BDTR register to en-/disable output pub fn set_moe(&self, enable: bool) { self.regs_1ch_cmp().bdtr().modify(|w| w.set_moe(enable)); @@ -725,4 +735,19 @@ impl<'d, T: AdvancedInstance4Channel> Timer<'d, T> { .ccer() .modify(|w| w.set_ccne(channel.index(), enable)); } + + /// Set Output Idle State + pub fn set_ois(&self, channel: Channel, val: bool) { + self.regs_advanced().cr2().modify(|w| w.set_ois(channel.index(), val)); + } + /// Set Output Idle State Complementary Channel + pub fn set_oisn(&self, channel: Channel, val: bool) { + self.regs_advanced().cr2().modify(|w| w.set_oisn(channel.index(), val)); + } + + /// Trigger software break 1 or 2 + /// Setting this bit generates a break event. This bit is automatically cleared by the hardware. + pub fn trigger_software_break(&self, n: usize) { + self.regs_advanced().egr().write(|r| r.set_bg(n, true)); + } } -- cgit From 0941a76be60a3c95aed9a3e1835ec1de6f03ac12 Mon Sep 17 00:00:00 2001 From: Jakob Date: Wed, 6 Aug 2025 15:04:48 +0200 Subject: Add get methods for meo, ossi and ossr --- embassy-stm32/src/timer/complementary_pwm.rs | 15 +++++++++++++++ embassy-stm32/src/timer/low_level.rs | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 1178e7d83..bf76155dd 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -100,11 +100,21 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { self.inner.set_ossi(val); } + /// Get state of OSSR-bit in BDTR register + pub fn get_off_state_selection_idle(&self) -> Ossi { + self.inner.get_ossi() + } + /// Set state of OSSR-bit in BDTR register pub fn set_off_state_selection_run(&self, val: Ossr) { self.inner.set_ossr(val); } + /// Get state of OSSR-bit in BDTR register + pub fn get_off_state_selection_run(&self) -> Ossr { + self.inner.get_ossr() + } + /// Trigger break input from software pub fn trigger_software_break(&self, n: usize) { self.inner.trigger_software_break(n); @@ -115,6 +125,11 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { self.inner.set_moe(enable); } + /// Get Master Output Enable + pub fn get_master_output_enable(&mut self) -> bool { + self.inner.get_moe() + } + /// Set Master Slave Mode 2 pub fn set_mms2(&mut self, mms2: Mms2) { self.inner.set_mms2_selection(mms2); diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index 01bf60869..ac039bb0d 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -691,15 +691,30 @@ impl<'d, T: AdvancedInstance1Channel> Timer<'d, T> { self.regs_1ch_cmp().bdtr().modify(|w| w.set_ossi(val)); } + /// Get state of OSSI-bit in BDTR register + pub fn get_ossi(&self) -> vals::Ossi { + self.regs_1ch_cmp().bdtr().read().ossi() + } + /// Set state of OSSR-bit in BDTR register pub fn set_ossr(&self, val: vals::Ossr) { self.regs_1ch_cmp().bdtr().modify(|w| w.set_ossr(val)); } + /// Get state of OSSR-bit in BDTR register + pub fn get_ossr(&self) -> vals::Ossr { + self.regs_1ch_cmp().bdtr().read().ossr() + } + /// Set state of MOE-bit in BDTR register to en-/disable output pub fn set_moe(&self, enable: bool) { self.regs_1ch_cmp().bdtr().modify(|w| w.set_moe(enable)); } + + /// Get state of MOE-bit in BDTR register + pub fn get_moe(&self) -> bool { + self.regs_1ch_cmp().bdtr().read().moe() + } } #[cfg(not(stm32l0))] -- cgit From c46cae734f3566a1e77d59b37d8bd714e542fd21 Mon Sep 17 00:00:00 2001 From: Jakob Date: Wed, 6 Aug 2025 15:25:01 +0200 Subject: Change method arugments to be non-mutable --- embassy-stm32/src/timer/complementary_pwm.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index bf76155dd..dcfe8f5dd 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -100,7 +100,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { self.inner.set_ossi(val); } - /// Get state of OSSR-bit in BDTR register + /// Get state of OSSI-bit in BDTR register pub fn get_off_state_selection_idle(&self) -> Ossi { self.inner.get_ossi() } @@ -121,12 +121,12 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { } /// Set Master Output Enable - pub fn set_master_output_enable(&mut self, enable: bool) { + pub fn set_master_output_enable(&self, enable: bool) { self.inner.set_moe(enable); } /// Get Master Output Enable - pub fn get_master_output_enable(&mut self) -> bool { + pub fn get_master_output_enable(&self) -> bool { self.inner.get_moe() } @@ -136,18 +136,18 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { } /// Set Repetition Counter - pub fn set_repetition_counter(&mut self, val: u16) { + pub fn set_repetition_counter(&self, val: u16) { self.inner.set_repetition_counter(val); } /// Enable the given channel. - pub fn enable(&mut self, channel: Channel) { + pub fn enable(&self, channel: Channel) { self.inner.enable_channel(channel, true); self.inner.enable_complementary_channel(channel, true); } /// Disable the given channel. - pub fn disable(&mut self, channel: Channel) { + pub fn disable(&self, channel: Channel) { self.inner.enable_complementary_channel(channel, false); self.inner.enable_channel(channel, false); } -- cgit From b6ee237fb1c59eaa0c0aa1bf876d1caf7888e940 Mon Sep 17 00:00:00 2001 From: Jakob Date: Fri, 8 Aug 2025 11:43:51 +0200 Subject: Add enum for IdlePolarity to make interface clearer for set_output_idle_state method --- embassy-stm32/src/timer/complementary_pwm.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index dcfe8f5dd..4d83875f5 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -43,6 +43,15 @@ pub struct ComplementaryPwm<'d, T: AdvancedInstance4Channel> { inner: Timer<'d, T>, } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +/// Determines which outputs are active when PWM is in idle mode +pub enum IdlePolarity { + /// Normal channels are forced active and complementary channels are forced inactive + OisActive, + /// Normal channels are forced inactive and complementary channels are forced active + OisnActive, +} + impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { /// Create a new complementary PWM driver. #[allow(clippy::too_many_arguments)] @@ -82,16 +91,17 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { this } - /// Set output idle state for all channels - /// - `output_high_when_idle` - true if the output for the normal channels should - /// be high when idle, which means that the complementary channels are low. Opposite - /// for `false`. - pub fn set_output_idle_state(&self, output_high_when_idle: bool) { + /// Sets the idle output state for all channels. + pub fn set_output_idle_state(&self, polarity: IdlePolarity) { + let ois_active = match polarity { + IdlePolarity::OisActive => true, + IdlePolarity::OisnActive => false, + }; [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] .iter() .for_each(|&channel| { - self.inner.set_ois(channel, output_high_when_idle); - self.inner.set_oisn(channel, !output_high_when_idle); + self.inner.set_ois(channel, ois_active); + self.inner.set_oisn(channel, !ois_active); }); } -- cgit From b0cef8c0adad0f90779a29f5b6c4e60fd5e38c1a Mon Sep 17 00:00:00 2001 From: Jakob Date: Sat, 9 Aug 2025 10:10:41 +0200 Subject: Adjust which methods should have mut reference to self. Change set_output_idle_state to accept channel iterator as input --- embassy-stm32/src/timer/complementary_pwm.rs | 37 ++++++++++++++-------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 4d83875f5..1f049cb32 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -91,22 +91,21 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { this } - /// Sets the idle output state for all channels. - pub fn set_output_idle_state(&self, polarity: IdlePolarity) { - let ois_active = match polarity { - IdlePolarity::OisActive => true, - IdlePolarity::OisnActive => false, - }; - [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] - .iter() - .for_each(|&channel| { - self.inner.set_ois(channel, ois_active); - self.inner.set_oisn(channel, !ois_active); - }); + /// Sets the idle output state for the given channels. + pub fn set_output_idle_state( + &mut self, + channels: &[Channel], + polarity: IdlePolarity, + ) { + let ois_active = matches!(polarity, IdlePolarity::OisActive); + for &channel in channels { + self.inner.set_ois(channel, ois_active); + self.inner.set_oisn(channel, !ois_active); + } } /// Set state of OSSI-bit in BDTR register - pub fn set_off_state_selection_idle(&self, val: Ossi) { + pub fn set_off_state_selection_idle(&mut self, val: Ossi) { self.inner.set_ossi(val); } @@ -116,7 +115,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { } /// Set state of OSSR-bit in BDTR register - pub fn set_off_state_selection_run(&self, val: Ossr) { + pub fn set_off_state_selection_run(&mut self, val: Ossr) { self.inner.set_ossr(val); } @@ -126,12 +125,12 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { } /// Trigger break input from software - pub fn trigger_software_break(&self, n: usize) { + pub fn trigger_software_break(&mut self, n: usize) { self.inner.trigger_software_break(n); } /// Set Master Output Enable - pub fn set_master_output_enable(&self, enable: bool) { + pub fn set_master_output_enable(&mut self, enable: bool) { self.inner.set_moe(enable); } @@ -146,18 +145,18 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { } /// Set Repetition Counter - pub fn set_repetition_counter(&self, val: u16) { + pub fn set_repetition_counter(&mut self, val: u16) { self.inner.set_repetition_counter(val); } /// Enable the given channel. - pub fn enable(&self, channel: Channel) { + pub fn enable(&mut self, channel: Channel) { self.inner.enable_channel(channel, true); self.inner.enable_complementary_channel(channel, true); } /// Disable the given channel. - pub fn disable(&self, channel: Channel) { + pub fn disable(&mut self, channel: Channel) { self.inner.enable_complementary_channel(channel, false); self.inner.enable_channel(channel, false); } -- cgit From c228ffe666c4354c909ea454cebc14387930c9c0 Mon Sep 17 00:00:00 2001 From: Jakob Date: Sun, 10 Aug 2025 09:22:49 +0200 Subject: Remove unrelated cahnges --- embassy-stm32/src/timer/complementary_pwm.rs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 1f049cb32..b291fc155 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -92,11 +92,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { } /// Sets the idle output state for the given channels. - pub fn set_output_idle_state( - &mut self, - channels: &[Channel], - polarity: IdlePolarity, - ) { + pub fn set_output_idle_state(&mut self, channels: &[Channel], polarity: IdlePolarity) { let ois_active = matches!(polarity, IdlePolarity::OisActive); for &channel in channels { self.inner.set_ois(channel, ois_active); @@ -139,16 +135,6 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { self.inner.get_moe() } - /// Set Master Slave Mode 2 - pub fn set_mms2(&mut self, mms2: Mms2) { - self.inner.set_mms2_selection(mms2); - } - - /// Set Repetition Counter - pub fn set_repetition_counter(&mut self, val: u16) { - self.inner.set_repetition_counter(val); - } - /// Enable the given channel. pub fn enable(&mut self, channel: Channel) { self.inner.enable_channel(channel, true); -- cgit From 92d12b5d8896d9bfa2789c1d5c157e1fa96e617b Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Sun, 10 Aug 2025 01:58:48 -0700 Subject: Updated stm32-metapac --- embassy-stm32/Cargo.toml | 4 ++-- embassy-stm32/src/vrefbuf/mod.rs | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 590216c21..c4322b9ba 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f0ef9106642ed869e7cfbf82d891d364c98ebb43" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-a236d845991bb48198427e08dc61ae3e257057a8" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f0ef9106642ed869e7cfbf82d891d364c98ebb43", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-a236d845991bb48198427e08dc61ae3e257057a8", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/src/vrefbuf/mod.rs b/embassy-stm32/src/vrefbuf/mod.rs index 2546ccfed..f614fcf99 100644 --- a/embassy-stm32/src/vrefbuf/mod.rs +++ b/embassy-stm32/src/vrefbuf/mod.rs @@ -5,7 +5,6 @@ use core::marker::PhantomData; use embassy_hal_internal::PeripheralType; use stm32_metapac::vrefbuf::vals::*; -use crate::pac::RCC; use crate::Peri; /// Voltage Reference (VREFBUF) driver. @@ -20,14 +19,17 @@ impl<'d, T: Instance> VoltageReferenceBuffer<'d, T> { pub fn new(_instance: Peri<'d, T>, voltage_scale: Vrs, impedance_mode: Hiz) -> Self { #[cfg(rcc_wba)] { + use crate::pac::RCC; RCC.apb7enr().modify(|w| w.set_vrefen(true)); } #[cfg(any(rcc_u5, rcc_h50, rcc_h5))] { + use crate::pac::RCC; RCC.apb3enr().modify(|w| w.set_vrefen(true)); } #[cfg(any(rcc_h7rs, rcc_h7rm0433, rcc_h7ab, rcc_h7))] { + use crate::pac::RCC; RCC.apb4enr().modify(|w| w.set_vrefen(true)); } let vrefbuf = T::regs(); -- cgit From 4a3cf3231666bf137900066c961e906ce7e0bb78 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Sun, 10 Aug 2025 19:32:23 -0700 Subject: Added vrefbuf driver. Also updated stm32-data-generated to latest --- embassy-stm32/Cargo.toml | 4 ++-- embassy-stm32/src/rcc/wba.rs | 14 +++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index c4322b9ba..39e6f13f0 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-a236d845991bb48198427e08dc61ae3e257057a8" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9941f338734a2e6c1652267f64b13f7b35d8c9db" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-a236d845991bb48198427e08dc61ae3e257057a8", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9941f338734a2e6c1652267f64b13f7b35d8c9db", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index 56ba7b58b..481437939 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs @@ -5,7 +5,7 @@ pub use crate::pac::rcc::vals::Otghssel; use crate::pac::rcc::vals::Pllrge; pub use crate::pac::rcc::vals::{ Hdiv5, Hpre as AHBPrescaler, Hpre5 as AHB5Prescaler, Hsepre as HsePrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, - Plln as PllMul, Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk, + Plln as PllMul, Pllsrc as PllSource, Ppre as APBPrescaler, Sai1sel, Sw as Sysclk, }; #[cfg(all(peri_usb_otg_hs))] pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG}; @@ -254,6 +254,16 @@ pub(crate) unsafe fn init(config: Config) { w.set_clksel(usb_refck_sel); }); + #[cfg(sai_v4_2pdm)] + let audioclk = match config.mux.sai1sel { + Sai1sel::HSI => Some(HSI_FREQ), + Sai1sel::PLL1_Q => Some(pll1.q.expect("PLL1.Q not configured")), + Sai1sel::PLL1_P => Some(pll1.p.expect("PLL1.P not configured")), + Sai1sel::SYS => panic!("SYS not supported yet"), + Sai1sel::AUDIOCLK => panic!("AUDIOCLK not supported yet"), + _ => None, + }; + let lsi = config.ls.lsi.then_some(LSI_FREQ); config.mux.init(); @@ -279,6 +289,8 @@ pub(crate) unsafe fn init(config: Config) { // TODO lse: None, + #[cfg(sai_v4_2pdm)] + audioclk: audioclk, ); } -- cgit From f3f819fc37720c1cbe24834df255cae9bfe68eb9 Mon Sep 17 00:00:00 2001 From: Roi Bachynskyi Date: Sat, 2 Aug 2025 20:45:01 +0300 Subject: feat: lpc55 blocking usart added --- embassy-nxp/Cargo.toml | 3 +- embassy-nxp/src/chips/lpc55.rs | 9 + embassy-nxp/src/lib.rs | 20 + embassy-nxp/src/usart.rs | 6 + embassy-nxp/src/usart/lpc55.rs | 885 ++++++++++++++++++++++++++++ examples/lpc55s69/src/bin/usart_blocking.rs | 40 ++ 6 files changed, 962 insertions(+), 1 deletion(-) create mode 100644 embassy-nxp/src/usart.rs create mode 100644 embassy-nxp/src/usart/lpc55.rs create mode 100644 examples/lpc55s69/src/bin/usart_blocking.rs diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 9fa48c4b9..cdfaee64d 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -24,7 +24,8 @@ log = { version = "0.4.27", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } - +embedded-io = "0.6.1" +embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } ## Chip dependencies lpc55-pac = { version = "0.5.0", optional = true } nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/i509VCB/nxp-pac", rev = "be4dd0936c20d5897364a381b1d95a99514c1e7e" } diff --git a/embassy-nxp/src/chips/lpc55.rs b/embassy-nxp/src/chips/lpc55.rs index c95218af0..e168ced00 100644 --- a/embassy-nxp/src/chips/lpc55.rs +++ b/embassy-nxp/src/chips/lpc55.rs @@ -67,4 +67,13 @@ embassy_hal_internal::peripherals! { PIO1_29, PIO1_30, PIO1_31, + + USART0, + USART1, + USART2, + USART3, + USART4, + USART5, + USART6, + USART7 } diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs index b2e910f7e..3fcb14b7e 100644 --- a/embassy-nxp/src/lib.rs +++ b/embassy-nxp/src/lib.rs @@ -6,6 +6,8 @@ pub(crate) mod fmt; pub mod gpio; #[cfg(feature = "lpc55")] pub mod pint; +#[cfg(feature = "lpc55")] +pub mod usart; #[cfg(feature = "_time_driver")] #[cfg_attr(feature = "time-driver-pit", path = "time_driver/pit.rs")] @@ -115,3 +117,21 @@ impl Iterator for BitIter { } } } + +trait SealedMode {} + +/// UART mode. +#[allow(private_bounds)] +pub trait Mode: SealedMode {} + +macro_rules! impl_mode { + ($name:ident) => { + impl SealedMode for $name {} + impl Mode for $name {} + }; +} + +/// Blocking mode. +pub struct Blocking; + +impl_mode!(Blocking); diff --git a/embassy-nxp/src/usart.rs b/embassy-nxp/src/usart.rs new file mode 100644 index 000000000..009c251e2 --- /dev/null +++ b/embassy-nxp/src/usart.rs @@ -0,0 +1,6 @@ +//! Universal Synchronous/Asynchronous Receiver/Transmitter (USART) driver. +#![macro_use] + +#[cfg_attr(feature = "lpc55", path = "./usart/lpc55.rs")] +mod inner; +pub use inner::*; diff --git a/embassy-nxp/src/usart/lpc55.rs b/embassy-nxp/src/usart/lpc55.rs new file mode 100644 index 000000000..3f7456a2e --- /dev/null +++ b/embassy-nxp/src/usart/lpc55.rs @@ -0,0 +1,885 @@ +use core::marker::PhantomData; + +use embassy_hal_internal::{Peri, PeripheralType}; +use embedded_io::{self, ErrorKind}; +pub use sealed::SealedInstance; + +use crate::gpio::AnyPin; +use crate::{Blocking, Mode}; + +/// Serial error +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub enum Error { + /// Triggered when the FIFO (or shift-register) is overflowed. + Overrun, + /// Triggered when there is a parity mismatch between what's received and + /// our settings. + Parity, + /// Triggered when the received character didn't have a valid stop bit. + Framing, + /// Triggered when the receiver detects noise + Noise, + /// Triggered when the receiver gets a break + Break, +} + +impl embedded_io::Error for Error { + fn kind(&self) -> ErrorKind { + match self { + Error::Overrun => ErrorKind::Other, + Error::Parity => ErrorKind::InvalidData, + Error::Framing => ErrorKind::InvalidData, + Error::Noise => ErrorKind::Other, + Error::Break => ErrorKind::Interrupted, + } + } +} +/// Word length. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum DataBits { + /// 7 bits data length. + DataBits7, + /// 8 bits data length. + DataBits8, + /// 9 bits data length. The 9th bit is commonly used for addressing in multidrop mode. + DataBits9, +} + +impl DataBits { + fn bits(&self) -> u8 { + match self { + Self::DataBits7 => 0b00, + Self::DataBits8 => 0b01, + Self::DataBits9 => 0b10, + } + } +} + +/// Parity bit. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum Parity { + /// No parity. + ParityNone, + /// Even parity. + ParityEven, + /// Odd parity. + ParityOdd, +} + +impl Parity { + fn bits(&self) -> u8 { + match self { + Self::ParityNone => 0b00, + Self::ParityEven => 0b10, + Self::ParityOdd => 0b11, + } + } +} + +/// Stop bits. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum StopBits { + /// 1 stop bit. + Stop1, + /// 2 stop bits. This setting should only be used for asynchronous communication. + Stop2, +} + +impl StopBits { + fn bits(&self) -> bool { + return match self { + Self::Stop1 => false, + Self::Stop2 => true, + }; + } +} + +/// UART config. +#[non_exhaustive] +#[derive(Clone, Debug)] +pub struct Config { + /// Baud rate. + pub baudrate: u32, + /// Word length. + pub data_bits: DataBits, + /// Stop bits. + pub stop_bits: StopBits, + /// Parity bit. + pub parity: Parity, + /// Invert the tx pin output + pub invert_tx: bool, + /// Invert the rx pin input + pub invert_rx: bool, +} + +impl Default for Config { + fn default() -> Self { + Self { + baudrate: 9600, + data_bits: DataBits::DataBits8, + stop_bits: StopBits::Stop1, + parity: Parity::ParityNone, + invert_rx: false, + invert_tx: false, + } + } +} + +/// # Type parameters +/// 'd: the lifetime marker ensuring correct borrow checking for peripherals used at compile time +/// T: the peripheral instance type allowing usage of peripheral specific registers +/// M: the operating mode of USART peripheral +pub struct Usart<'d, T: Instance, M: Mode> { + tx: UsartTx<'d, T, M>, + rx: UsartRx<'d, T, M>, +} + +pub struct UsartTx<'d, T: Instance, M: Mode> { + phantom: PhantomData<(&'d (), T, M)>, +} + +pub struct UsartRx<'d, T: Instance, M: Mode> { + phantom: PhantomData<(&'d (), T, M)>, +} + +impl<'d, T: Instance, M: Mode> UsartTx<'d, T, M> { + pub fn new(_usart: Peri<'d, T>, tx: Peri<'d, impl TxPin>, config: Config) -> Self { + Usart::::init(Some(tx.into()), None, config); + Self::new_inner() + } + + #[inline] + fn new_inner() -> Self { + Self { phantom: PhantomData } + } + + pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { + T::blocking_write(buffer) + } + + pub fn blocking_flush(&mut self) -> Result<(), Error> { + T::blocking_flush() + } + + pub fn tx_busy(&self) -> bool { + T::tx_busy() + } +} + +impl<'d, T: Instance> UsartTx<'d, T, Blocking> { + pub fn new_blocking(_usart: Peri<'d, T>, tx: Peri<'d, impl TxPin>, config: Config) -> Self { + Usart::::init(Some(tx.into()), None, config); + Self::new_inner() + } +} + +impl<'d, T: Instance, M: Mode> UsartRx<'d, T, M> { + pub fn new(_usart: Peri<'d, T>, rx: Peri<'d, impl RxPin>, config: Config) -> Self { + Usart::::init(None, Some(rx.into()), config); + Self::new_inner() + } + + #[inline] + fn new_inner() -> Self { + Self { phantom: PhantomData } + } + + pub fn blocking_read(&mut self, mut buffer: &mut [u8]) -> Result<(), Error> { + while !buffer.is_empty() { + match Self::drain_fifo(self, buffer) { + Ok(0) => continue, // Wait for more data + Ok(n) => buffer = &mut buffer[n..], + Err((_, err)) => return Err(err), + } + } + Ok(()) + } + + /// Returns: + /// - Ok(n) -> read n bytes + /// - Err(n, Error) -> read n-1 bytes, but encountered an error while reading nth byte + fn drain_fifo(&mut self, buffer: &mut [u8]) -> Result { + T::drain_fifo(buffer) + } +} + +impl<'d, T: Instance> UsartRx<'d, T, Blocking> { + pub fn new_blocking(_usart: Peri<'d, T>, rx: Peri<'d, impl RxPin>, config: Config) -> Self { + Usart::::init(None, Some(rx.into()), config); + Self::new_inner() + } +} + +impl<'d, T: Instance> Usart<'d, T, Blocking> { + pub fn new_blocking( + usart: Peri<'d, T>, + tx: Peri<'d, impl TxPin>, + rx: Peri<'d, impl RxPin>, + config: Config, + ) -> Self { + Self::new_inner(usart, tx.into(), rx.into(), config) + } +} + +impl<'d, T: Instance, M: Mode> Usart<'d, T, M> { + fn new_inner(_usart: Peri<'d, T>, mut tx: Peri<'d, AnyPin>, mut rx: Peri<'d, AnyPin>, config: Config) -> Self { + Self::init(Some(tx.reborrow()), Some(rx.reborrow()), config); + Self { + tx: UsartTx::new_inner(), + rx: UsartRx::new_inner(), + } + } + + fn init(_tx: Option>, _rx: Option>, config: Config) { + T::enable_clock(); + T::reset_flexcomm(); + let source_clock: u32 = T::select_clock(config.baudrate); + T::configure_flexcomm(); + T::tx_pin_config(); + T::rx_pin_config(); + Self::set_baudrate(source_clock, config.baudrate); + T::configure_usart(config); + T::disable_dma(); + T::enable_usart(); + } + + fn set_baudrate(source_clock: u32, baudrate: u32) { + // There are two types of dividers: integer divider (baud rate generator register and oversample selection value) + // and fractional divider (fractional rate divider). + // For oversampling, the default is industry standard 16x oversampling, i.e. OSRVAL = 15 + + // The formulas are: + + // FLCK = (clock selected via FCCLKSEL) / (1 + MULT / DIV) + // DIV is always 256, then: + // FLCK = (clock selected via FCCLKSEL) / (1 + MULT / 256) + + // Baud rate = [FCLK / (OSRVAL+1)] / (BRGVAL + 1) => + // Baud rate = [FCLK / 16] / (BRGVAL + 1) + + // There are 2 unknowns: MULT and BRGVAL. + // MULT is responsible for fractional division + // BRGVAL is responsible for integer division + + // The Fractional Rate Generator can be used to obtain more precise baud rates when the + // function clock is not a good multiple of standard (or otherwise desirable) baud rates. + // The FRG is typically set up to produce an integer multiple of the highest required baud + // rate, or a very close approximation. The BRG is then used to obtain the actual baud rate + // needed. + + // Firstly, BRGVAL is calculated to get the raw clock which is a rough approximation that has to be adjusted + // so that the desired baud rate is obtained. + // Secondly, MULT is calculated to ultimately 'chisel' the clock to get the baud rate. + // The deduced formulas are written below. + + let brg_value = (source_clock / (16 * baudrate)).min(255); + let raw_clock = source_clock / (16 * brg_value); + let mult_value = ((raw_clock * 256 / baudrate) - 256).min(255); + T::set_baudrate(mult_value as u8, brg_value as u8); + } +} + +impl<'d, T: Instance, M: Mode> Usart<'d, T, M> { + /// Transmit the provided buffer blocking execution until done. + pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { + self.tx.blocking_write(buffer) + } + + /// Flush USART TX blocking execution until done. + pub fn blocking_flush(&mut self) -> Result<(), Error> { + self.tx.blocking_flush() + } + + /// Read from USART RX blocking execution until done. + pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { + self.rx.blocking_read(buffer) + } + + /// Check if UART is busy transmitting. + pub fn tx_busy(&self) -> bool { + self.tx.tx_busy() + } + + /// Split the Usart into a transmitter and receiver, which is particularly + /// useful when having two tasks correlating to transmitting and receiving. + pub fn split(self) -> (UsartTx<'d, T, M>, UsartRx<'d, T, M>) { + (self.tx, self.rx) + } + + /// Split the Usart into a transmitter and receiver by mutable reference, + /// which is particularly useful when having two tasks correlating to + /// transmitting and receiving. + pub fn split_ref(&mut self) -> (&mut UsartTx<'d, T, M>, &mut UsartRx<'d, T, M>) { + (&mut self.tx, &mut self.rx) + } +} + +impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write for UsartTx<'d, T, M> { + type Error = Error; + + fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(buffer) + } + + fn bflush(&mut self) -> Result<(), Self::Error> { + self.blocking_flush() + } +} + +impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write for Usart<'d, T, M> { + type Error = Error; + + fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(buffer) + } + + fn bflush(&mut self) -> Result<(), Self::Error> { + self.blocking_flush() + } +} + +impl<'d, T: Instance> embedded_io::ErrorType for UsartTx<'d, T, Blocking> { + type Error = Error; +} + +impl<'d, T: Instance> embedded_io::Write for UsartTx<'d, T, Blocking> { + fn write(&mut self, buf: &[u8]) -> Result { + self.blocking_write(buf).map(|_| buf.len()) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + self.blocking_flush() + } +} + +impl<'d, T: Instance> embedded_io::ErrorType for UsartRx<'d, T, Blocking> { + type Error = Error; +} + +impl<'d, T: Instance> embedded_io::Read for UsartRx<'d, T, Blocking> { + fn read(&mut self, buf: &mut [u8]) -> Result { + self.blocking_read(buf).map(|_| buf.len()) + } +} + +impl<'d, T: Instance> embedded_io::ErrorType for Usart<'d, T, Blocking> { + type Error = Error; +} + +impl<'d, T: Instance> embedded_io::Write for Usart<'d, T, Blocking> { + fn write(&mut self, buf: &[u8]) -> Result { + self.blocking_write(buf).map(|_| buf.len()) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + self.blocking_flush() + } +} + +impl<'d, T: Instance> embedded_io::Read for Usart<'d, T, Blocking> { + fn read(&mut self, buf: &mut [u8]) -> Result { + self.blocking_read(buf).map(|_| buf.len()) + } +} + +type UsartRegBlock = crate::pac::usart0::RegisterBlock; + +mod sealed { + use crate::usart::inner::UsartRegBlock; + use crate::usart::{Config, Error}; + pub trait SealedInstance { + fn usart_reg() -> &'static UsartRegBlock; + fn enable_clock(); + fn select_clock(baudrate: u32) -> u32; + fn configure_flexcomm(); + fn set_baudrate(mult_value: u8, brg_value: u8); + fn reset_flexcomm(); + fn tx_pin_config(); + fn rx_pin_config(); + + fn configure_usart(config: Config) { + // See section 34.6.1 + Self::usart_reg().cfg.modify(|_, w| { + // LIN break mode enable + w.linmode() + // Disabled. Break detect and generate is configured for normal operation. + .disabled() + //CTS Enable. Determines whether CTS is used for flow control. CTS can be from the + //input pin, or from the USART’s own RTS if loopback mode is enabled. + .ctsen() + // No flow control. The transmitter does not receive any automatic flow control signal. + .disabled() + // Selects synchronous or asynchronous operation. + .syncen() + .asynchronous_mode() + // Selects the clock polarity and sampling edge of received data in synchronous mode. + .clkpol() + .rising_edge() + // Synchronous mode Master select. + .syncmst() + // When synchronous mode is enabled, the USART is a master. + .master() + // Selects data loopback mode + .loop_() + // Normal operation + .normal() + // Output Enable Turnaround time enable for RS-485 operation. + .oeta() + // Disabled. If selected by OESEL, the Output Enable signal deasserted at the end of + // the last stop bit of a transmission. + .disabled() + // Output enable select. + .oesel() + // Standard. The RTS signal is used as the standard flow control function. + .standard() + // Automatic address matching enable. + .autoaddr() + // Disabled. When addressing is enabled by ADDRDET, address matching is done by + // software. This provides the possibility of versatile addressing (e.g. respond to more + // than one address) + .disabled() + // Output enable polarity. + .oepol() + // Low. If selected by OESEL, the output enable is active low. + .low() + }); + + Self::usart_reg().cfg.modify(|_, w| unsafe { + w.datalen() + .bits(config.data_bits.bits()) + .paritysel() + .bits(config.parity.bits()) + .stoplen() + .bit(config.stop_bits.bits()) + .rxpol() + .bit(config.invert_rx) + .txpol() + .bit(config.invert_tx) + }); + } + fn disable_dma() { + Self::usart_reg() + .fifocfg + .modify(|_, w| w.dmatx().disabled().dmarx().disabled()); + } + fn enable_usart() { + Self::usart_reg() + .fifocfg + .modify(|_, w| w.enabletx().enabled().enablerx().enabled()); + Self::usart_reg().cfg.modify(|_, w| w.enable().enabled()); + while Self::usart_reg().fifostat.read().rxnotempty().bit_is_set() { + let _ = Self::usart_reg().fiford.read().bits(); + } + } + fn blocking_write(buffer: &[u8]) -> Result<(), Error> { + for &b in buffer { + while Self::usart_reg().fifostat.read().txnotfull().bit_is_clear() {} + Self::usart_reg() + .fifowr + .modify(|_, w| unsafe { w.txdata().bits(b as u16) }); + } + Ok(()) + } + fn blocking_flush() -> Result<(), Error> { + while Self::usart_reg().fifostat.read().txempty().bit_is_clear() {} + Ok(()) + } + fn tx_busy() -> bool { + Self::usart_reg().fifostat.read().txempty().bit_is_clear() + } + fn drain_fifo(buffer: &mut [u8]) -> Result { + for (i, b) in buffer.iter_mut().enumerate() { + while Self::usart_reg().fifostat.read().rxnotempty().bit_is_clear() {} + + if Self::usart_reg().fifostat.read().rxerr().bit_is_set() { + return Err((i, Error::Overrun)); + } else if Self::usart_reg().fifordnopop.read().parityerr().bit_is_set() { + return Err((i, Error::Parity)); + } else if Self::usart_reg().fifordnopop.read().framerr().bit_is_set() { + return Err((i, Error::Framing)); + } else if Self::usart_reg().fifordnopop.read().rxnoise().bit_is_set() { + return Err((i, Error::Noise)); + } else if Self::usart_reg().intstat.read().deltarxbrk().bit_is_set() { + return Err((i, Error::Break)); + } + let dr = Self::usart_reg().fiford.read().bits() as u8; + *b = dr; + } + Ok(buffer.len()) + } + } +} + +/// UART instance. +#[allow(private_bounds)] +pub trait Instance: sealed::SealedInstance + PeripheralType {} + +#[macro_export] +macro_rules! impl_instance { + ( + $inst:ident, + usart_peripheral: $USARTX:ident, + usart_crate: $usartX:ident, + + flexcomm: { + field: $FLEXCOMM_FIELD:ident, + clock_field: $FLEXCOMM_CLK_FIELD:ident + }, + + reset: { + bit: $RESET_BIT:ident + }, + + clock: { + sel_field: $CLKSEL_FIELD:ident, + frg_field: $FRG_FIELD:ident + }, + + pins: { + tx: $TX_IOCON:ident => $TX_FUNC:expr, + rx: $RX_IOCON:ident => $RX_FUNC:expr + } + + ) => { + impl $crate::usart::SealedInstance for $crate::peripherals::$inst { + fn usart_reg() -> &'static UsartRegBlock { + unsafe { &*$crate::pac::$USARTX::ptr() } + } + + fn enable_clock() { + critical_section::with(|_cs| { + if syscon_reg().ahbclkctrl0.read().iocon().is_disable() { + syscon_reg().ahbclkctrl0.modify(|_, w| w.iocon().enable()); + } + if syscon_reg().ahbclkctrl1.read().$FLEXCOMM_CLK_FIELD().is_disable() { + syscon_reg() + .ahbclkctrl1 + .modify(|_, w| w.$FLEXCOMM_CLK_FIELD().enable()); + } + }); + } + + fn configure_flexcomm() { + let flexcomm = unsafe { &*$crate::pac::$FLEXCOMM_FIELD::ptr() }; + flexcomm.pselid.modify(|_, w| w.persel().usart()); + } + + fn reset_flexcomm() { + syscon_reg().presetctrl1.modify(|_, w| w.$RESET_BIT().set_bit()); + syscon_reg().presetctrl1.modify(|_, w| w.$RESET_BIT().clear_bit()); + } + + fn select_clock(baudrate: u32) -> u32 { + // Adaptive clock choice based on baud rate + // To get the desired baud rate, it is essential to choose the clock bigger than baud rate so that it can be 'chiseled' + // There are two types of dividers: integer divider (baud rate generator register and oversample selection value) + // and fractional divider (fractional rate divider). + + // By default, oversampling rate is 16 which is an industry standard. + // That means 16 clocks are used to deliver the byte to recipient. + // In this way the probability of getting correct bytes instead of noise directly increases as oversampling increases as well. + + // Minimum and maximum values were computed taking these formulas into account: + // For minimum value, MULT = 0, BRGVAL = 0 + // For maximum value, MULT = 255, BRGVAL = 255 + // Flexcomm Interface function clock = (clock selected via FCCLKSEL) / (1 + MULT / DIV) + // By default, OSRVAL = 15 (see above) + // Baud rate = [FCLK / (OSRVAL+1)] / (BRGVAL + 1) + return match baudrate { + 750_001..=6000000 => { + syscon_reg().$CLKSEL_FIELD().write(|w| w.sel().enum_0x3()); // 96 MHz + 96_000_000 + } + 1501..=750_000 => { + syscon_reg().$CLKSEL_FIELD().write(|w| w.sel().enum_0x2()); // 12 MHz + 12_000_000 + } + 121..=1500 => { + syscon_reg().$CLKSEL_FIELD().write(|w| w.sel().enum_0x4()); // 1 MHz + 1_000_000 + } + _ => { + panic!("{} baudrate is not permitted in this mode", baudrate); + } + }; + } + + fn set_baudrate(mult_value: u8, brg_value: u8) { + // FCLK = (clock selected via FCCLKSEL) / (1+ MULT / DIV) + // Remark: To use the fractional baud rate generator, 0xFF must be wirtten to the DIV value + // to yield a denominator vale of 256. All other values are not supported + syscon_reg() + .$FRG_FIELD() + .modify(|_, w| unsafe { w.div().bits(0xFF).mult().bits(mult_value as u8) }); + + // Baud rate = [FCLK / (OSRVAL+1)] / (BRGVAL + 1) + // By default, oversampling is 16x, i.e. OSRVAL = 15 + + // Typical industry standard USARTs use a 16x oversample clock to transmit and receive + // asynchronous data. This is the number of BRG clocks used for one data bit. The + // Oversample Select Register (OSR) allows this USART to use a 16x down to a 5x + // oversample clock. There is no oversampling in synchronous modes. + Self::usart_reg() + .brg + .modify(|_, w| unsafe { w.brgval().bits((brg_value - 1) as u16) }); + } + + fn tx_pin_config() { + iocon_reg().$TX_IOCON.modify(|_, w| unsafe { + w.func() + .bits($TX_FUNC) + .digimode() + .digital() + .slew() + .standard() + .mode() + .inactive() + .invert() + .disabled() + .od() + .normal() + }); + } + + fn rx_pin_config() { + iocon_reg().$RX_IOCON.modify(|_, w| unsafe { + w.func() + .bits($RX_FUNC) + .digimode() + .digital() + .slew() + .standard() + .mode() + .inactive() + .invert() + .disabled() + .od() + .normal() + }); + } + } + + impl $crate::usart::Instance for $crate::peripherals::$inst {} + }; +} + +impl_instance!(USART0, usart_peripheral: USART0, usart_crate: usart0, + flexcomm: { + field: FLEXCOMM0, + clock_field: fc0 + }, + + reset: { + bit: fc0_rst + }, + + clock: { + sel_field: fcclksel0, + frg_field: flexfrg0ctrl + }, + + pins: { + tx: pio1_6 => 1, + rx: pio1_5 => 1 + } +); + +impl_instance!(USART1, usart_peripheral: USART1, usart_crate: usart1, + flexcomm: { + field: FLEXCOMM1, + clock_field: fc1 + }, + + reset: { + bit: fc1_rst + }, + + clock: { + sel_field: fcclksel1, + frg_field: flexfrg1ctrl + }, + + pins: { + tx: pio1_11 => 2, + rx: pio1_10 => 2 + } +); + +impl_instance!(USART2, usart_peripheral: USART2, usart_crate: usart2, + flexcomm: { + field: FLEXCOMM2, + clock_field: fc2 + }, + + reset: { + bit: fc2_rst + }, + + clock: { + sel_field: fcclksel2, + frg_field: flexfrg2ctrl + }, + + pins: { + tx: pio0_27 => 1, + rx: pio1_24 => 1 + } +); + +impl_instance!(USART3, usart_peripheral: USART3, usart_crate: usart3, + flexcomm: { + field: FLEXCOMM3, + clock_field: fc3 + }, + + reset: { + bit: fc3_rst + }, + + clock: { + sel_field: fcclksel3, + frg_field: flexfrg3ctrl + }, + + pins: { + tx: pio0_2 => 1, + rx: pio0_3 => 1 + } +); + +impl_instance!(USART4, usart_peripheral: USART4, usart_crate: usart4, + flexcomm: { + field: FLEXCOMM4, + clock_field: fc4 + }, + + reset: { + bit: fc4_rst + }, + + clock: { + sel_field: fcclksel4, + frg_field: flexfrg4ctrl + }, + + pins: { + tx: pio0_16 => 1, + rx: pio0_5 => 2 + } +); + +impl_instance!(USART5, usart_peripheral: USART5, usart_crate: usart5, + flexcomm: { + field: FLEXCOMM5, + clock_field: fc5 + }, + + reset: { + bit: fc5_rst + }, + + clock: { + sel_field: fcclksel5, + frg_field: flexfrg5ctrl + }, + + pins: { + tx: pio0_9 => 3, + rx: pio0_8 => 3 + } +); + +impl_instance!(USART6, usart_peripheral: USART6, usart_crate: usart6, + flexcomm: { + field: FLEXCOMM6, + clock_field: fc6 + }, + + reset: { + bit: fc6_rst + }, + + clock: { + sel_field: fcclksel6, + frg_field: flexfrg6ctrl + }, + + pins: { + tx: pio1_16 => 2, + rx: pio1_13 => 2 + } +); + +impl_instance!(USART7, usart_peripheral: USART7, usart_crate: usart7, + flexcomm: { + field: FLEXCOMM7, + clock_field: fc7 + }, + + reset: { + bit: fc7_rst + }, + + clock: { + sel_field: fcclksel7, + frg_field: flexfrg7ctrl + }, + + pins: { + tx: pio0_19 => 7, + rx: pio0_20 => 7 + } +); + +/// Trait for TX pins. +pub trait TxPin: crate::gpio::Pin {} +/// Trait for RX pins. +pub trait RxPin: crate::gpio::Pin {} + +// TODO: Add RTS, CTS and CLK pin traits + +macro_rules! impl_pin { + ($pin:ident, $instance:ident, Tx) => { + impl TxPin for crate::peripherals::$pin {} + }; + ($pin:ident, $instance:ident, Rx) => { + impl RxPin for crate::peripherals::$pin {} + }; +} + +impl_pin!(PIO1_5, USART0, Rx); +impl_pin!(PIO1_6, USART0, Tx); +impl_pin!(PIO1_10, USART1, Rx); +impl_pin!(PIO1_11, USART1, Tx); +impl_pin!(PIO0_27, USART2, Tx); +impl_pin!(PIO1_24, USART2, Rx); +impl_pin!(PIO0_2, USART3, Tx); +impl_pin!(PIO0_3, USART3, Rx); +impl_pin!(PIO0_16, USART4, Tx); +impl_pin!(PIO0_5, USART4, Rx); +impl_pin!(PIO0_8, USART5, Rx); +impl_pin!(PIO0_9, USART5, Tx); +impl_pin!(PIO1_16, USART6, Tx); +impl_pin!(PIO1_13, USART6, Rx); +impl_pin!(PIO0_20, USART7, Rx); +impl_pin!(PIO0_19, USART7, Tx); + +/// Get the SYSCON register block. +/// +/// # Safety +/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO +/// registers are not accessed concurrently by multiple threads. +pub(crate) fn syscon_reg() -> &'static crate::pac::syscon::RegisterBlock { + unsafe { &*crate::pac::SYSCON::ptr() } +} + +/// Get the IOCON register block. +/// +/// # Safety +/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO +/// registers are not accessed concurrently by multiple threads. +pub(crate) fn iocon_reg() -> &'static crate::pac::iocon::RegisterBlock { + unsafe { &*crate::pac::IOCON::ptr() } +} diff --git a/examples/lpc55s69/src/bin/usart_blocking.rs b/examples/lpc55s69/src/bin/usart_blocking.rs new file mode 100644 index 000000000..a38ec0c5b --- /dev/null +++ b/examples/lpc55s69/src/bin/usart_blocking.rs @@ -0,0 +1,40 @@ +#![no_std] +#![no_main] + +use core::str::from_utf8_mut; + +use defmt::*; +use embassy_executor::Spawner; +use embassy_nxp::usart::{Config, Usart}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_halt as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nxp::init(Default::default()); + let mut usart = Usart::new_blocking(p.USART2, p.PIO0_27, p.PIO1_24, Config::default()); + let tx_buf = b"Hello, Ferris!"; + let mut rx_buf = [0u8; 14]; + + loop { + info!("Write a message"); + usart.blocking_write(tx_buf).unwrap(); + usart.blocking_flush().unwrap(); + + Timer::after_millis(500).await; + + info!("Read a message"); + usart.blocking_read(&mut rx_buf).unwrap(); + + match from_utf8_mut(&mut rx_buf) { + Ok(str) => { + info!("The message is: {}", str); + } + Err(_) => { + error!("Error in converting to UTF8"); + } + } + + Timer::after_millis(500).await; + } +} -- cgit From 794477eca3062471a2cdc378730b5c2952cfd2c3 Mon Sep 17 00:00:00 2001 From: Rob Wells Date: Mon, 11 Aug 2025 19:56:31 +0100 Subject: book: Suggest Picotool for RP chips instead of elf2uf2-rs --- docs/pages/faq.adoc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/pages/faq.adoc b/docs/pages/faq.adoc index b21be9a30..8098e12ac 100644 --- a/docs/pages/faq.adoc +++ b/docs/pages/faq.adoc @@ -6,16 +6,16 @@ Please feel free to add items to link:https://github.com/embassy-rs/embassy/edit == How to deploy to RP2040 or RP235x without a debugging probe. -Install link:https://github.com/JoNil/elf2uf2-rs[elf2uf2-rs] for converting the generated elf binary into a uf2 file. +Install link:https://github.com/raspberrypi/pico-sdk-tools/releases[Picotool] for uploading the binary. Configure the runner to use this tool, add this to `.cargo/config.toml`: [source,toml] ---- [target.'cfg(all(target_arch = "arm", target_os = "none"))'] -runner = "elf2uf2-rs --deploy --serial --verbose" +runner = "picotool load --update --verify --execute -t elf" ---- -The command-line parameters `--deploy` will detect your device and upload the binary, `--serial` starts a serial connection. See the documentation for more info. +Picotool will detect your device and upload the binary, skipping identical flash sectors (the `--update` command-line flag), verify that the binary was written correctly (`--verify`), and then run your new code (`--execute`). Run `picotool help load` for more information. == Missing main macro @@ -209,7 +209,7 @@ MEMORY _stack_start = ORIGIN(RAM) + LENGTH(RAM); ``` -Please refer to the STM32 documentation for the specific values suitable for your board and setup. The STM32 Cube examples often contain a linker script `.ld` file. +Please refer to the STM32 documentation for the specific values suitable for your board and setup. The STM32 Cube examples often contain a linker script `.ld` file. Look for the `MEMORY` section and try to determine the FLASH and RAM sizes and section start. If you find a case where the memory.x is wrong, please report it on link:https://github.com/embassy-rs/stm32-data/issues/301[this Github issue] so other users are not caught by surprise. @@ -334,7 +334,7 @@ There are two main ways to handle concurrency in Embassy: In general, either of these approaches will work. The main differences of these approaches are: -When using **separate tasks**, each task needs its own RAM allocation, so there's a little overhead for each task, so one task that does three things will likely be a little bit smaller than three tasks that do one thing (not a lot, probably a couple dozen bytes). In contrast, with **multiple futures in one task**, you don't need multiple task allocations, and it will generally be easier to share data, or use borrowed resources, inside of a single task. +When using **separate tasks**, each task needs its own RAM allocation, so there's a little overhead for each task, so one task that does three things will likely be a little bit smaller than three tasks that do one thing (not a lot, probably a couple dozen bytes). In contrast, with **multiple futures in one task**, you don't need multiple task allocations, and it will generally be easier to share data, or use borrowed resources, inside of a single task. An example showcasing some methods for sharing things between tasks link:https://github.com/embassy-rs/embassy/blob/main/examples/rp/src/bin/sharing.rs[can be found here]. But when it comes to "waking" tasks, for example when a data transfer is complete or a button is pressed, it's faster to wake a dedicated task, because that task does not need to check which future is actually ready. `join` and `select` must check ALL of the futures they are managing to see which one (or which ones) are ready to do more work. This is because all Rust executors (like Embassy or Tokio) only have the ability to wake tasks, not specific futures. This means you will use slightly less CPU time juggling futures when using dedicated tasks. -- cgit From 2f0e8aa24481f1a9a79126756a0c294d82229f3d Mon Sep 17 00:00:00 2001 From: redfast00 Date: Tue, 12 Aug 2025 15:44:41 +0200 Subject: docs: clarify that timer will expire immediately if in past --- embassy-time/src/timer.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-time/src/timer.rs b/embassy-time/src/timer.rs index 54bb9b6d8..fcf79f58e 100644 --- a/embassy-time/src/timer.rs +++ b/embassy-time/src/timer.rs @@ -103,6 +103,7 @@ pub struct Timer { impl Timer { /// Expire at specified [Instant](struct.Instant.html) + /// Will expire immediately if the Instant is in the past. pub fn at(expires_at: Instant) -> Self { Self { expires_at, -- cgit From 985cdba7b3763346da78890f10a7330e56b3d19b Mon Sep 17 00:00:00 2001 From: nerwalt Date: Tue, 12 Aug 2025 09:56:50 -0600 Subject: Enable temp support on the nrf54l15 Alphabetize ther peripherals in the pac --- embassy-nrf/src/chips/nrf54l15_app.rs | 27 +++++++++++++++------------ embassy-nrf/src/lib.rs | 1 - examples/nrf54l15/src/bin/temp.rs | 25 +++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 examples/nrf54l15/src/bin/temp.rs diff --git a/embassy-nrf/src/chips/nrf54l15_app.rs b/embassy-nrf/src/chips/nrf54l15_app.rs index 2bc346092..ff05bbec0 100644 --- a/embassy-nrf/src/chips/nrf54l15_app.rs +++ b/embassy-nrf/src/chips/nrf54l15_app.rs @@ -206,18 +206,6 @@ pub const EASY_DMA_SIZE: usize = (1 << 16) - 1; pub const FLASH_SIZE: usize = 1536 * 1024; embassy_hal_internal::peripherals! { - // WDT - #[cfg(feature = "_ns")] - WDT, - #[cfg(feature = "_s")] - WDT0, - #[cfg(feature = "_s")] - WDT1, - - #[cfg(feature = "_s")] - // RRAMC - RRAMC, - // GPIO port 0 P0_00, P0_01, @@ -259,6 +247,21 @@ embassy_hal_internal::peripherals! { P2_08, P2_09, P2_10, + + #[cfg(feature = "_s")] + // RRAMC + RRAMC, + + // TEMP + TEMP, + + // WDT + #[cfg(feature = "_ns")] + WDT, + #[cfg(feature = "_s")] + WDT0, + #[cfg(feature = "_s")] + WDT1, } impl_pin!(P0_00, 0, 0); diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 9c1211f0a..2b72debeb 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -152,7 +152,6 @@ pub mod spim; #[cfg(not(feature = "_nrf54l"))] // TODO #[cfg(not(feature = "_nrf51"))] pub mod spis; -#[cfg(not(feature = "_nrf54l"))] // TODO #[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))] pub mod temp; #[cfg(not(feature = "_nrf54l"))] // TODO diff --git a/examples/nrf54l15/src/bin/temp.rs b/examples/nrf54l15/src/bin/temp.rs new file mode 100644 index 000000000..1d28f8ecf --- /dev/null +++ b/examples/nrf54l15/src/bin/temp.rs @@ -0,0 +1,25 @@ +#![no_std] +#![no_main] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_nrf::temp::Temp; +use embassy_nrf::{bind_interrupts, temp}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + TEMP => temp::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + let mut temp = Temp::new(p.TEMP, Irqs); + + loop { + let value = temp.read().await; + info!("temperature: {}℃", value.to_num::()); + Timer::after_secs(1).await; + } +} -- cgit From c4c5167e3d18eafee7726a526093bed2b3d2d119 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 12 Aug 2025 18:16:50 +0200 Subject: chore: update metapac and prepare embassy-stm32 0.3.0 --- docs/examples/layer-by-layer/blinky-async/Cargo.toml | 2 +- docs/examples/layer-by-layer/blinky-hal/Cargo.toml | 2 +- docs/examples/layer-by-layer/blinky-irq/Cargo.toml | 2 +- embassy-boot-stm32/Cargo.toml | 2 +- embassy-stm32-wpan/Cargo.toml | 2 +- embassy-stm32/CHANGELOG.md | 4 +++- embassy-stm32/Cargo.toml | 10 +++++----- embassy-stm32/release.toml | 5 +++++ examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wb-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wba-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wl/Cargo.toml | 2 +- examples/stm32c0/Cargo.toml | 2 +- examples/stm32f0/Cargo.toml | 2 +- examples/stm32f1/Cargo.toml | 2 +- examples/stm32f2/Cargo.toml | 2 +- examples/stm32f3/Cargo.toml | 2 +- examples/stm32f334/Cargo.toml | 2 +- examples/stm32f4/Cargo.toml | 2 +- examples/stm32f469/Cargo.toml | 2 +- examples/stm32f7/Cargo.toml | 2 +- examples/stm32g0/Cargo.toml | 2 +- examples/stm32g4/Cargo.toml | 2 +- examples/stm32h5/Cargo.toml | 2 +- examples/stm32h7/Cargo.toml | 2 +- examples/stm32h723/Cargo.toml | 2 +- examples/stm32h735/Cargo.toml | 2 +- examples/stm32h742/Cargo.toml | 2 +- examples/stm32h755cm4/Cargo.toml | 2 +- examples/stm32h755cm7/Cargo.toml | 2 +- examples/stm32h7b0/Cargo.toml | 2 +- examples/stm32h7rs/Cargo.toml | 2 +- examples/stm32l0/Cargo.toml | 2 +- examples/stm32l1/Cargo.toml | 2 +- examples/stm32l4/Cargo.toml | 2 +- examples/stm32l432/Cargo.toml | 2 +- examples/stm32l5/Cargo.toml | 2 +- examples/stm32u0/Cargo.toml | 2 +- examples/stm32u5/Cargo.toml | 2 +- examples/stm32wb/Cargo.toml | 2 +- examples/stm32wba/Cargo.toml | 2 +- examples/stm32wba6/Cargo.toml | 2 +- examples/stm32wl/Cargo.toml | 2 +- tests/stm32/Cargo.toml | 2 +- 49 files changed, 59 insertions(+), 52 deletions(-) create mode 100644 embassy-stm32/release.toml diff --git a/docs/examples/layer-by-layer/blinky-async/Cargo.toml b/docs/examples/layer-by-layer/blinky-async/Cargo.toml index 7a9782960..dd0adf938 100644 --- a/docs/examples/layer-by-layer/blinky-async/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-async/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] cortex-m = { version = "0.7", features = ["critical-section-single-core"] } cortex-m-rt = "0.7" -embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x", "exti"] } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } defmt = "1.0.1" diff --git a/docs/examples/layer-by-layer/blinky-hal/Cargo.toml b/docs/examples/layer-by-layer/blinky-hal/Cargo.toml index 9a261f804..55795e4e2 100644 --- a/docs/examples/layer-by-layer/blinky-hal/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-hal/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] cortex-m-rt = "0.7" cortex-m = { version = "0.7", features = ["critical-section-single-core"] } -embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x"] } +embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/docs/examples/layer-by-layer/blinky-irq/Cargo.toml b/docs/examples/layer-by-layer/blinky-irq/Cargo.toml index c3ec9ad1a..4a4bda4c4 100644 --- a/docs/examples/layer-by-layer/blinky-irq/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-irq/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" [dependencies] cortex-m = { version = "0.7", features = ["critical-section-single-core"] } cortex-m-rt = { version = "0.7" } -embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x", "unstable-pac"] } +embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x", "unstable-pac"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/embassy-boot-stm32/Cargo.toml b/embassy-boot-stm32/Cargo.toml index 54bbd5f77..dd434341a 100644 --- a/embassy-boot-stm32/Cargo.toml +++ b/embassy-boot-stm32/Cargo.toml @@ -25,7 +25,7 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4", optional = true } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } -embassy-stm32 = { version = "0.2.0", path = "../embassy-stm32", default-features = false } +embassy-stm32 = { version = "0.3.0", path = "../embassy-stm32", default-features = false } embassy-boot = { version = "0.6.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 1f33c92cd..cb9f3ec66 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -19,7 +19,7 @@ features = ["stm32wb55rg", "ble", "mac"] features = ["stm32wb55rg", "ble", "mac"] [dependencies] -embassy-stm32 = { version = "0.2.0", path = "../embassy-stm32" } +embassy-stm32 = { version = "0.3.0", path = "../embassy-stm32" } embassy-sync = { version = "0.7.0", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index c4c2cd013..7816c92d1 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -5,7 +5,9 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate + - Modify BufferedUart initialization to take pins before interrupts ([#3983](https://github.com/embassy-rs/embassy/pull/3983)) - Added a 'single-bank' and a 'dual-bank' feature so chips with configurable flash bank setups are be supported in embassy ([#4125](https://github.com/embassy-rs/embassy/pull/4125)) - Add automatic setting of remap bits when using alternate DMA channels on STM32F0 and STM32F3 devices ([#3653](https://github.com/embassy-rs/embassy/pull/3653)) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 39e6f13f0..c26cc194e 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-stm32" -version = "0.2.0" +version = "0.3.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Embassy Hardware Abstraction Layer (HAL) for ST STM32 series microcontrollers" @@ -80,8 +80,8 @@ cortex-m = "0.7.6" futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" -#stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9941f338734a2e6c1652267f64b13f7b35d8c9db" } +stm32-metapac = { version = "17" } +# stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9941f338734a2e6c1652267f64b13f7b35d8c9db" } vcell = "0.1.3" nb = "1.0.0" @@ -109,8 +109,8 @@ proptest-state-machine = "0.3.0" proc-macro2 = "1.0.36" quote = "1.0.15" -#stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9941f338734a2e6c1652267f64b13f7b35d8c9db", default-features = false, features = ["metadata"] } +stm32-metapac = { version = "17", default-features = false, features = ["metadata"]} +#stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9941f338734a2e6c1652267f64b13f7b35d8c9db", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/release.toml b/embassy-stm32/release.toml new file mode 100644 index 000000000..fb6feaf21 --- /dev/null +++ b/embassy-stm32/release.toml @@ -0,0 +1,5 @@ +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, +] diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index d3b1a4eea..5d4d63655 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32" } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index 1f8f3c7d8..dc7252f40 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } +embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index 8d4cc98da..20bc7e0ea 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 8f581fba9..2f0e1b1bc 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } +embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 9502a7832..0caa8d342 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index d222f0260..b7514d440 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index 1ac302a81..21fbc0a0c 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb" } diff --git a/examples/boot/application/stm32wba-dfu/Cargo.toml b/examples/boot/application/stm32wba-dfu/Cargo.toml index dae9a2498..cb059e42a 100644 --- a/examples/boot/application/stm32wba-dfu/Cargo.toml +++ b/examples/boot/application/stm32wba-dfu/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wba65ri", "time-driver-any", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32wba65ri", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb" } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index 429bbf846..dc6b156b3 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index b06d53a22..f8ac571e4 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32c031c6 to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti", "chrono"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index 9ccce3910..c236a6133 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f091rc to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "memory-x", "stm32f091rc", "time-driver-tim2", "exti", "unstable-pac"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "memory-x", "stm32f091rc", "time-driver-tim2", "exti", "unstable-pac"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" defmt = "1.0.1" diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 1d49afcc4..3655cb5f9 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f103c8 to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index e5ad745d8..206e5f298 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f207zg to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index c45450495..4f25203ee 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f303ze to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-tim2", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-tim2", "exti"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml index 76be93913..7afe65080 100644 --- a/examples/stm32f334/Cargo.toml +++ b/examples/stm32f334/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 8cadeec9a..7bcc675a4 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f429zi to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-tim4", "exti", "chrono"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-tim4", "exti", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32f469/Cargo.toml b/examples/stm32f469/Cargo.toml index 6adb96a45..a35a811e2 100644 --- a/examples/stm32f469/Cargo.toml +++ b/examples/stm32f469/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Specific examples only for stm32f469 -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32f469ni", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32f469ni", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index ab2991b68..f70624cff 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f777zi to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32f777zi", "memory-x", "unstable-pac", "time-driver-any", "exti", "single-bank"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32f777zi", "memory-x", "unstable-pac", "time-driver-any", "exti", "single-bank"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index 5cdcec42e..d536eaed4 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32g0b1re to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g0b1re", "memory-x", "unstable-pac", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g0b1re", "memory-x", "unstable-pac", "exti"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index a5b10c476..44c7385d6 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32g491re to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 60ee73476..276790797 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h563zi to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 5222c17dc..ab65fd561 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h743bi to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } diff --git a/examples/stm32h723/Cargo.toml b/examples/stm32h723/Cargo.toml index af21a6647..3fc4fd8a4 100644 --- a/examples/stm32h723/Cargo.toml +++ b/examples/stm32h723/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h723zg to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h723zg", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h723zg", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml index c219eb506..fa6d48ef3 100644 --- a/examples/stm32h735/Cargo.toml +++ b/examples/stm32h735/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml index 5a983b8de..22b19d304 100644 --- a/examples/stm32h742/Cargo.toml +++ b/examples/stm32h742/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f777zi to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32h742vi", "memory-x", diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index fbda7a687..5ecc4c377 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h755zi-cm4 to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index e3b79aa89..9dc8d1ae5 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h743bi to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml index 73edd4c6e..6d4ff8563 100644 --- a/examples/stm32h7b0/Cargo.toml +++ b/examples/stm32h7b0/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml index cc02a595a..c2efa8d4d 100644 --- a/examples/stm32h7rs/Cargo.toml +++ b/examples/stm32h7rs/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h743bi to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 57eea6a95..df72c429e 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32l072cz to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32l073rz", "unstable-pac", "time-driver-any", "exti", "memory-x"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32l073rz", "unstable-pac", "time-driver-any", "exti", "memory-x"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 2b2160749..d04845d19 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 3e6671f89..759143bef 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32l4s5vi to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4r5zi", "memory-x", "time-driver-any", "exti", "chrono", "dual-bank"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4r5zi", "memory-x", "time-driver-any", "exti", "chrono", "dual-bank"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } diff --git a/examples/stm32l432/Cargo.toml b/examples/stm32l432/Cargo.toml index f4add6ea2..b675e7e41 100644 --- a/examples/stm32l432/Cargo.toml +++ b/examples/stm32l432/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32l4s5vi to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l432kc", "memory-x", "time-driver-any", "exti", "chrono"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l432kc", "memory-x", "time-driver-any", "exti", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = [ "defmt" ] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "tick-hz-32_768" ] } diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 6931b848d..b84015469 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32l552ze to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x", "low-power", "dual-bank"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x", "low-power", "dual-bank"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml index ca5286f3a..1ab29d813 100644 --- a/examples/stm32u0/Cargo.toml +++ b/examples/stm32u0/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32u083rc to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index 2576c1326..5b8f05b72 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32u5g9zj to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u5g9zj", "time-driver-any", "memory-x" ] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u5g9zj", "time-driver-any", "memory-x" ] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 69deb0155..d67a792db 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32wb55rg to your chip name in both dependencies, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml index 20c1570c8..a64401a3b 100644 --- a/examples/stm32wba/Cargo.toml +++ b/examples/stm32wba/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32wba6/Cargo.toml b/examples/stm32wba6/Cargo.toml index 2a5850806..5775b1fc7 100644 --- a/examples/stm32wba6/Cargo.toml +++ b/examples/stm32wba6/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba65ri", "time-driver-any", "memory-x", "exti"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba65ri", "time-driver-any", "memory-x", "exti"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 79b6f8110..4e851e3f1 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32wl55jc-cm4 to your chip name, if necessary. -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 58ee10d77..33dce2c36 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -66,7 +66,7 @@ teleprobe-meta = "1" embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "tick-hz-131_072", "defmt-timestamp-uptime"] } -embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "memory-x", "time-driver-any"] } +embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "memory-x", "time-driver-any"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg", "ble"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } -- cgit From 825ea1c3379edb713f5bcd6157a7cf3b60b1937a Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 12 Aug 2025 18:47:15 +0200 Subject: chore: add more items to changelog --- embassy-stm32/CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 7816c92d1..071b166bf 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -8,6 +8,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- Added VREFBUF voltage reference buffer driver +- Added ADC4 support for STM32WBA devices +- Added USB OTG HS support for STM32WBA devices +- Added STM32C071 and STM32C051 RCC support +- Added hardware oversampling support for ADC v3 +- Added PWM pin configuration options for different GPIO modes +- Added RTC low-power support for STM32WBA65 +- Added eMMC support for SDMMC +- Added I2C slave blocking read/write support +- Added auto-calibration for MSI frequencies on U5 devices +- Fixed buffered UART half-duplex receive functionality +- Fixed STM32WBA VDDIO2 configuration +- Fixed timer break input 2 trait naming +- Fixed dead-time computation in complementary PWM +- Improve error handling for I2C v2 NACK conditions +- Renamed frequency parameters for consistency (freq -> frequency) - Modify BufferedUart initialization to take pins before interrupts ([#3983](https://github.com/embassy-rs/embassy/pull/3983)) - Added a 'single-bank' and a 'dual-bank' feature so chips with configurable flash bank setups are be supported in embassy ([#4125](https://github.com/embassy-rs/embassy/pull/4125)) - Add automatic setting of remap bits when using alternate DMA channels on STM32F0 and STM32F3 devices ([#3653](https://github.com/embassy-rs/embassy/pull/3653)) -- cgit From c4d2879d9eca23a801a32c5b3a98fb10b01666ba Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 12 Aug 2025 19:48:54 +0200 Subject: chore: update changelog --- embassy-stm32/CHANGELOG.md | 56 +++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 071b166bf..9da153480 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -6,27 +6,41 @@ 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). -## Unreleased - ReleaseDate - -- Added VREFBUF voltage reference buffer driver -- Added ADC4 support for STM32WBA devices -- Added USB OTG HS support for STM32WBA devices -- Added STM32C071 and STM32C051 RCC support -- Added hardware oversampling support for ADC v3 -- Added PWM pin configuration options for different GPIO modes -- Added RTC low-power support for STM32WBA65 -- Added eMMC support for SDMMC -- Added I2C slave blocking read/write support -- Added auto-calibration for MSI frequencies on U5 devices -- Fixed buffered UART half-duplex receive functionality -- Fixed STM32WBA VDDIO2 configuration -- Fixed timer break input 2 trait naming -- Fixed dead-time computation in complementary PWM -- Improve error handling for I2C v2 NACK conditions -- Renamed frequency parameters for consistency (freq -> frequency) -- Modify BufferedUart initialization to take pins before interrupts ([#3983](https://github.com/embassy-rs/embassy/pull/3983)) -- Added a 'single-bank' and a 'dual-bank' feature so chips with configurable flash bank setups are be supported in embassy ([#4125](https://github.com/embassy-rs/embassy/pull/4125)) -- Add automatic setting of remap bits when using alternate DMA channels on STM32F0 and STM32F3 devices ([#3653](https://github.com/embassy-rs/embassy/pull/3653)) +## 0.3.0 - 2025-08-12 + +- feat: Added VREFBUF voltage reference buffer driver ([#4524](https://github.com/embassy-rs/embassy/pull/4524)) +- feat: Added complementary PWM idle-state control methods ([#4522](https://github.com/embassy-rs/embassy/pull/4522)) +- feat: Added hardware oversampling support for ADC v3 ([#4279](https://github.com/embassy-rs/embassy/pull/4279)) +- feat: Added ADC4 support for STM32WBA devices +- feat: Added USB OTG HS support for STM32WBA devices +- feat: Added STM32C071 and STM32C051 RCC support +- feat: Added PWM pin configuration options for different GPIO modes +- feat: Added RTC low-power support for STM32WBA65 ([#4418](https://github.com/embassy-rs/embassy/pull/4418)) +- feat: Added eMMC support for SDMMC +- feat: Added auto-calibration for MSI frequencies on U5 devices ([#4313](https://github.com/embassy-rs/embassy/pull/4313)) +- feat: Added DAC::new_unbuffered method ([#4183](https://github.com/embassy-rs/embassy/pull/4183)) +- feat: Added helper methods for low-power interrupt timer ([#4305](https://github.com/embassy-rs/embassy/pull/4305)) +- feat: Added ADC v1 analog watchdog implementation ([#4330](https://github.com/embassy-rs/embassy/pull/4330)) +- feat: Added OPAMP RCC initialization ([#4358](https://github.com/embassy-rs/embassy/pull/4358)) +- feat: Added const constructors for RCC Config structs ([#4231](https://github.com/embassy-rs/embassy/pull/4231)) +- feat: Added FDCAN/BXCAN RAII instance counters ([#4272](https://github.com/embassy-rs/embassy/pull/4272)) +- fix: Fixed I2C slave blocking read/write support ([#4454](https://github.com/embassy-rs/embassy/pull/4454)) +- fix: Fixed STM32WBA VDDIO2 configuration ([#4424](https://github.com/embassy-rs/embassy/pull/4424)) +- fix: Fixed timer break input 2 trait naming +- fix: Fixed dead-time computation in complementary PWM +- fix: Fixed get_max_duty off-by-one error for center-aligned mode ([#4302](https://github.com/embassy-rs/embassy/pull/4302)) +- fix: Fixed STM32C09x build issues +- fix: Fixed STM32G0B0 build issues +- fix: Fixed HSEM CPUID detection and added missing RCC initialization ([#4324](https://github.com/embassy-rs/embassy/pull/4324)) +- fix: Enable autoreload preload for complementary PWM ([#4303](https://github.com/embassy-rs/embassy/pull/4303)) +- fix: Fixed DMA packing/unpacking functionality +- fix: Added missing fence on BDMA start operations +- fix: Improve error handling for I2C v2 NACK conditions +- fix: Renamed frequency parameters for consistency (freq -> frequency) +- chore: Updated stm32-metapac and stm32-data dependencies +- chore: Modify BufferedUart initialization to take pins before interrupts ([#3983](https://github.com/embassy-rs/embassy/pull/3983)) +- feat: Added a 'single-bank' and a 'dual-bank' feature so chips with configurable flash bank setups are be supported in embassy ([#4125](https://github.com/embassy-rs/embassy/pull/4125)) +- feat: Add automatic setting of remap bits when using alternate DMA channels on STM32F0 and STM32F3 devices ([#3653](https://github.com/embassy-rs/embassy/pull/3653)) ## 0.2.0 - 2025-01-10 -- cgit From ac46e28c4b4f025279d8974adfb6120c6740e44e Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 12 Aug 2025 19:52:24 +0200 Subject: fix: use correct feature set for docs --- embassy-stm32/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index c26cc194e..b4c1e5a14 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -44,7 +44,7 @@ flavors = [ ] [package.metadata.docs.rs] -features = ["defmt", "unstable-pac", "exti", "time-driver-any", "time", "stm32h755zi-cm7", "single-bank"] +features = ["defmt", "unstable-pac", "exti", "time-driver-any", "time", "stm32h755zi-cm7", "dual-bank"] rustdoc-args = ["--cfg", "docsrs"] [dependencies] -- cgit From c7b9060a7443cd004d366586c418a3d95bf3447a Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 12 Aug 2025 20:23:20 +0200 Subject: fix: prepare embassy-sync 0.7.1 release * Add newtype for moved type to preserve API compat --- cyw43/Cargo.toml | 2 +- embassy-boot-nrf/Cargo.toml | 2 +- embassy-boot-rp/Cargo.toml | 2 +- embassy-boot-stm32/Cargo.toml | 2 +- embassy-boot/Cargo.toml | 2 +- embassy-embedded-hal/Cargo.toml | 2 +- embassy-imxrt/Cargo.toml | 2 +- embassy-mspm0/Cargo.toml | 2 +- embassy-net-driver-channel/Cargo.toml | 2 +- embassy-net-esp-hosted/Cargo.toml | 2 +- embassy-net-nrf91/Cargo.toml | 2 +- embassy-net-ppp/Cargo.toml | 2 +- embassy-net/Cargo.toml | 2 +- embassy-nrf/Cargo.toml | 2 +- embassy-nxp/Cargo.toml | 2 +- embassy-rp/Cargo.toml | 2 +- embassy-stm32-wpan/Cargo.toml | 2 +- embassy-stm32/Cargo.toml | 2 +- embassy-sync/Cargo.toml | 2 +- embassy-sync/src/channel.rs | 5 +++++ embassy-usb-dfu/Cargo.toml | 2 +- embassy-usb-logger/Cargo.toml | 2 +- embassy-usb-synopsys-otg/Cargo.toml | 2 +- embassy-usb/Cargo.toml | 2 +- examples/boot/application/nrf/Cargo.toml | 2 +- examples/boot/application/rp/Cargo.toml | 2 +- examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wb-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wba-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wl/Cargo.toml | 2 +- examples/boot/bootloader/nrf/Cargo.toml | 2 +- examples/boot/bootloader/rp/Cargo.toml | 2 +- examples/boot/bootloader/stm32-dual-bank/Cargo.toml | 2 +- examples/boot/bootloader/stm32/Cargo.toml | 2 +- examples/boot/bootloader/stm32wb-dfu/Cargo.toml | 2 +- examples/boot/bootloader/stm32wba-dfu/Cargo.toml | 2 +- examples/lpc55s69/Cargo.toml | 2 +- examples/mimxrt1011/Cargo.toml | 2 +- examples/mimxrt1062-evk/Cargo.toml | 2 +- examples/mimxrt6/Cargo.toml | 2 +- examples/mspm0c1104/Cargo.toml | 2 +- examples/mspm0g3507/Cargo.toml | 2 +- examples/mspm0g3519/Cargo.toml | 2 +- examples/mspm0l1306/Cargo.toml | 2 +- examples/mspm0l2228/Cargo.toml | 2 +- examples/nrf-rtos-trace/Cargo.toml | 2 +- examples/nrf52810/Cargo.toml | 2 +- examples/nrf52840-rtic/Cargo.toml | 2 +- examples/nrf52840/Cargo.toml | 2 +- examples/nrf5340/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- examples/std/Cargo.toml | 2 +- examples/stm32c0/Cargo.toml | 2 +- examples/stm32f0/Cargo.toml | 2 +- examples/stm32f1/Cargo.toml | 2 +- examples/stm32f2/Cargo.toml | 2 +- examples/stm32f3/Cargo.toml | 2 +- examples/stm32f334/Cargo.toml | 2 +- examples/stm32f4/Cargo.toml | 2 +- examples/stm32f7/Cargo.toml | 2 +- examples/stm32g0/Cargo.toml | 2 +- examples/stm32g4/Cargo.toml | 2 +- examples/stm32h5/Cargo.toml | 2 +- examples/stm32h7/Cargo.toml | 2 +- examples/stm32h723/Cargo.toml | 2 +- examples/stm32h735/Cargo.toml | 2 +- examples/stm32h742/Cargo.toml | 2 +- examples/stm32h755cm4/Cargo.toml | 2 +- examples/stm32h755cm7/Cargo.toml | 2 +- examples/stm32h7b0/Cargo.toml | 2 +- examples/stm32h7rs/Cargo.toml | 2 +- examples/stm32l0/Cargo.toml | 2 +- examples/stm32l1/Cargo.toml | 2 +- examples/stm32l4/Cargo.toml | 2 +- examples/stm32l432/Cargo.toml | 2 +- examples/stm32l5/Cargo.toml | 2 +- examples/stm32u0/Cargo.toml | 2 +- examples/stm32u5/Cargo.toml | 2 +- examples/stm32wb/Cargo.toml | 2 +- examples/stm32wba/Cargo.toml | 2 +- examples/stm32wba6/Cargo.toml | 2 +- examples/stm32wl/Cargo.toml | 2 +- examples/wasm/Cargo.toml | 2 +- tests/mspm0/Cargo.toml | 2 +- tests/nrf/Cargo.toml | 2 +- tests/riscv32/Cargo.toml | 2 +- tests/rp/Cargo.toml | 2 +- tests/stm32/Cargo.toml | 2 +- 94 files changed, 98 insertions(+), 93 deletions(-) diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index 74c9f1f3a..94d9ef3eb 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -19,7 +19,7 @@ firmware-logs = [] [dependencies] embassy-time = { version = "0.4.0", path = "../embassy-time"} -embassy-sync = { version = "0.7.0", path = "../embassy-sync"} +embassy-sync = { version = "0.7.1", path = "../embassy-sync"} embassy-futures = { version = "0.1.0", path = "../embassy-futures"} embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel"} diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index 9d02f61e3..f89561066 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -24,7 +24,7 @@ target = "thumbv7em-none-eabi" defmt = { version = "1.0.1", optional = true } log = { version = "0.4.17", optional = true } -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-nrf = { version = "0.6.0", path = "../embassy-nrf", default-features = false } embassy-boot = { version = "0.6.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } diff --git a/embassy-boot-rp/Cargo.toml b/embassy-boot-rp/Cargo.toml index 71888c8b0..5fe376645 100644 --- a/embassy-boot-rp/Cargo.toml +++ b/embassy-boot-rp/Cargo.toml @@ -24,7 +24,7 @@ features = ["embassy-rp/rp2040"] defmt = { version = "1.0.1", optional = true } log = { version = "0.4", optional = true } -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-rp = { version = "0.7.0", path = "../embassy-rp", default-features = false } embassy-boot = { version = "0.6.0", path = "../embassy-boot" } embassy-time = { version = "0.4.0", path = "../embassy-time" } diff --git a/embassy-boot-stm32/Cargo.toml b/embassy-boot-stm32/Cargo.toml index dd434341a..7cdd5136a 100644 --- a/embassy-boot-stm32/Cargo.toml +++ b/embassy-boot-stm32/Cargo.toml @@ -24,7 +24,7 @@ target = "thumbv7em-none-eabi" defmt = { version = "1.0.1", optional = true } log = { version = "0.4", optional = true } -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-stm32 = { version = "0.3.0", path = "../embassy-stm32", default-features = false } embassy-boot = { version = "0.6.0", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } diff --git a/embassy-boot/Cargo.toml b/embassy-boot/Cargo.toml index 4e2eb2695..632e60c35 100644 --- a/embassy-boot/Cargo.toml +++ b/embassy-boot/Cargo.toml @@ -29,7 +29,7 @@ digest = "0.10" log = { version = "0.4", optional = true } ed25519-dalek = { version = "2", default-features = false, features = ["digest"], optional = true } embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal" } -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embedded-storage = "0.3.1" embedded-storage-async = { version = "0.4.1" } salty = { version = "0.3", optional = true } diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index 25088a62d..73eb19c39 100644 --- a/embassy-embedded-hal/Cargo.toml +++ b/embassy-embedded-hal/Cargo.toml @@ -23,7 +23,7 @@ time = ["dep:embassy-time"] [dependencies] embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [ "unproven", diff --git a/embassy-imxrt/Cargo.toml b/embassy-imxrt/Cargo.toml index 0453ab4a0..466d5dc2c 100644 --- a/embassy-imxrt/Cargo.toml +++ b/embassy-imxrt/Cargo.toml @@ -63,7 +63,7 @@ mimxrt685s = ["mimxrt685s-pac", "_mimxrt685s"] mimxrt633s = ["mimxrt633s-pac", "_mimxrt633s"] [dependencies] -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.4", path = "../embassy-time", optional = true } diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index edd926c2b..ae0c93862 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -25,7 +25,7 @@ features = ["defmt", "unstable-pac", "time-driver-any", "time", "mspm0g3507"] rustdoc-args = ["--cfg", "docsrs"] [dependencies] -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } # TODO: Support other tick rates embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true, features = ["tick-hz-32_768"] } diff --git a/embassy-net-driver-channel/Cargo.toml b/embassy-net-driver-channel/Cargo.toml index 386d492c6..c3a9f79a7 100644 --- a/embassy-net-driver-channel/Cargo.toml +++ b/embassy-net-driver-channel/Cargo.toml @@ -25,6 +25,6 @@ features = ["defmt"] defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml index 7ccef84e8..f76998d1a 100644 --- a/embassy-net-esp-hosted/Cargo.toml +++ b/embassy-net-esp-hosted/Cargo.toml @@ -18,7 +18,7 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-sync = { version = "0.7.0", path = "../embassy-sync"} +embassy-sync = { version = "0.7.1", path = "../embassy-sync"} embassy-futures = { version = "0.1.0", path = "../embassy-futures"} embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel"} diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml index f3c0a0078..9201dc84c 100644 --- a/embassy-net-nrf91/Cargo.toml +++ b/embassy-net-nrf91/Cargo.toml @@ -21,7 +21,7 @@ nrf-pac = "0.1.0" cortex-m = "0.7.7" embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel" } diff --git a/embassy-net-ppp/Cargo.toml b/embassy-net-ppp/Cargo.toml index b724401c9..33ef5230e 100644 --- a/embassy-net-ppp/Cargo.toml +++ b/embassy-net-ppp/Cargo.toml @@ -21,7 +21,7 @@ embedded-io-async = { version = "0.6.1" } embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } ppproto = { version = "0.2.1"} -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-ppp-v$VERSION/embassy-net-ppp/src/" diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index a2665c770..babd63157 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -78,7 +78,7 @@ smoltcp = { version = "0.12.0", default-features = false, features = [ embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embedded-io-async = { version = "0.6.1" } managed = { version = "0.8.0", default-features = false, features = [ "map" ] } diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 92378db0b..98013aa5b 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -143,7 +143,7 @@ _multi_wdt = [] embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal", default-features = false } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index cdfaee64d..3303cabdb 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -18,7 +18,7 @@ cortex-m = "0.7.7" cortex-m-rt = "0.7.0" critical-section = "1.1.2" embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } defmt = { version = "1", optional = true } log = { version = "0.4.27", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index d48b27ef5..7f2167f90 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -136,7 +136,7 @@ _test = [] binary-info = ["rt", "dep:rp-binary-info", "rp-binary-info?/binary-info"] [dependencies] -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.4.0", path = "../embassy-time" } diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index cb9f3ec66..0932e4739 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -20,7 +20,7 @@ features = ["stm32wb55rg", "ble", "mac"] [dependencies] embassy-stm32 = { version = "0.3.0", path = "../embassy-stm32" } -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal" } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index b4c1e5a14..691ce3b90 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -48,7 +48,7 @@ features = ["defmt", "unstable-pac", "exti", "time-driver-any", "time", "stm32h7 rustdoc-args = ["--cfg", "docsrs"] [dependencies] -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml index 9e5c39f5e..e60f5e34c 100644 --- a/embassy-sync/Cargo.toml +++ b/embassy-sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-sync" -version = "0.7.0" +version = "0.7.1" edition = "2021" description = "no-std, no-alloc synchronization primitives with async support" repository = "https://github.com/embassy-rs/embassy" diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs index a0e39fcb5..8e9fcc234 100644 --- a/embassy-sync/src/channel.rs +++ b/embassy-sync/src/channel.rs @@ -419,6 +419,11 @@ pub struct SendDynamicReceiver<'ch, T> { pub(crate) channel: &'ch dyn DynamicChannel, } +/// Receive-only access to a [`Channel`] without knowing channel size. +/// This version can be sent between threads but can only be created if the underlying mutex is Sync. +#[deprecated(since = "0.7.1", note = "please use `SendDynamicReceiver` instead")] +pub type SendableDynamicReceiver<'ch, T> = SendDynamicReceiver<'ch, T>; + impl<'ch, T> Clone for SendDynamicReceiver<'ch, T> { fn clone(&self) -> Self { *self diff --git a/embassy-usb-dfu/Cargo.toml b/embassy-usb-dfu/Cargo.toml index 1c88e3977..8d1f231ed 100644 --- a/embassy-usb-dfu/Cargo.toml +++ b/embassy-usb-dfu/Cargo.toml @@ -33,7 +33,7 @@ bitflags = "2.4.1" cortex-m = { version = "0.7.7", features = ["inline-asm"], optional = true } embassy-boot = { version = "0.6.0", path = "../embassy-boot" } embassy-futures = { version = "0.1.1", path = "../embassy-futures" } -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-time = { version = "0.4.0", path = "../embassy-time" } embassy-usb = { version = "0.5.0", path = "../embassy-usb", default-features = false } embedded-storage = { version = "0.3.1" } diff --git a/embassy-usb-logger/Cargo.toml b/embassy-usb-logger/Cargo.toml index 68b11ad8a..810accf76 100644 --- a/embassy-usb-logger/Cargo.toml +++ b/embassy-usb-logger/Cargo.toml @@ -16,6 +16,6 @@ target = "thumbv7em-none-eabi" [dependencies] embassy-usb = { version = "0.5.0", path = "../embassy-usb" } -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } log = "0.4" diff --git a/embassy-usb-synopsys-otg/Cargo.toml b/embassy-usb-synopsys-otg/Cargo.toml index 78cce24de..e9ec8d330 100644 --- a/embassy-usb-synopsys-otg/Cargo.toml +++ b/embassy-usb-synopsys-otg/Cargo.toml @@ -18,7 +18,7 @@ target = "thumbv7em-none-eabi" [dependencies] critical-section = "1.1" -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } defmt = { version = "1.0.1", optional = true } diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml index 4743fde65..93e3e1e31 100644 --- a/embassy-usb/Cargo.toml +++ b/embassy-usb/Cargo.toml @@ -48,7 +48,7 @@ max-handler-count-8 = [] [dependencies] embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } -embassy-sync = { version = "0.7.0", path = "../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../embassy-sync" } embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel" } defmt = { version = "1", optional = true } diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index af2ba4638..c8e1def4a 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } embassy-nrf = { version = "0.6.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index ccd34e802..7fd6f8f97 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } embassy-rp = { version = "0.7.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index 5d4d63655..5d736d875 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index dc7252f40..cc658459f 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index 20bc7e0ea..03884257b 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 2f0e1b1bc..09d9474e9 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 0caa8d342..a49366c2b 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index b7514d440..8f0c95f0f 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index 21fbc0a0c..f3dbdc4de 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } diff --git a/examples/boot/application/stm32wba-dfu/Cargo.toml b/examples/boot/application/stm32wba-dfu/Cargo.toml index cb059e42a..cab2c2b03 100644 --- a/examples/boot/application/stm32wba-dfu/Cargo.toml +++ b/examples/boot/application/stm32wba-dfu/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32wba65ri", "time-driver-any", "exti"] } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index dc6b156b3..4e4ab945b 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } diff --git a/examples/boot/bootloader/nrf/Cargo.toml b/examples/boot/bootloader/nrf/Cargo.toml index 897890ca4..157448054 100644 --- a/examples/boot/bootloader/nrf/Cargo.toml +++ b/examples/boot/bootloader/nrf/Cargo.toml @@ -12,7 +12,7 @@ defmt-rtt = { version = "1.0.0", optional = true } embassy-nrf = { path = "../../../../embassy-nrf", features = [] } embassy-boot-nrf = { path = "../../../../embassy-boot-nrf" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } cortex-m-rt = { version = "0.7" } cfg-if = "1.0.0" diff --git a/examples/boot/bootloader/rp/Cargo.toml b/examples/boot/bootloader/rp/Cargo.toml index 090a581d4..034043274 100644 --- a/examples/boot/bootloader/rp/Cargo.toml +++ b/examples/boot/bootloader/rp/Cargo.toml @@ -11,7 +11,7 @@ defmt-rtt = { version = "1.0.0", optional = true } embassy-rp = { path = "../../../../embassy-rp", features = ["rp2040"] } embassy-boot-rp = { path = "../../../../embassy-boot-rp" } -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-time = { path = "../../../../embassy-time", features = [] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml index 67edc6a6c..75c7783b8 100644 --- a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml +++ b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml @@ -15,7 +15,7 @@ cortex-m = { version = "0.7.6", features = [ "inline-asm", "critical-section-single-core", ] } -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" diff --git a/examples/boot/bootloader/stm32/Cargo.toml b/examples/boot/bootloader/stm32/Cargo.toml index fe81b5151..3f54b823b 100644 --- a/examples/boot/bootloader/stm32/Cargo.toml +++ b/examples/boot/bootloader/stm32/Cargo.toml @@ -12,7 +12,7 @@ defmt-rtt = { version = "1.0.0", optional = true } embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml index d101e6ace..1aad71ebc 100644 --- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml @@ -12,7 +12,7 @@ defmt-rtt = { version = "1.0.0", optional = true } embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" diff --git a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml index 9240d1808..e31edb699 100644 --- a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml @@ -12,7 +12,7 @@ defmt-rtt = { version = "1.0.0", optional = true } embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } -embassy-sync = { version = "0.7.0", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index f9bd409e2..d66e3e2ec 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55", "rt", "defmt", "time-driver-rtc"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/mimxrt1011/Cargo.toml b/examples/mimxrt1011/Cargo.toml index e6bb3b10b..59b1eaa10 100644 --- a/examples/mimxrt1011/Cargo.toml +++ b/examples/mimxrt1011/Cargo.toml @@ -14,7 +14,7 @@ embassy-executor = { version = "0.8.0", path = "../../embassy-executor", feature embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["defmt", "mimxrt1011", "unstable-pac", "time-driver-pit"] } embassy-time = { version = "0.4", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime" # RT1011 hard faults currently with this enabled. -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = "1.0.0" diff --git a/examples/mimxrt1062-evk/Cargo.toml b/examples/mimxrt1062-evk/Cargo.toml index 7f7e0c8a3..bfa06f608 100644 --- a/examples/mimxrt1062-evk/Cargo.toml +++ b/examples/mimxrt1062-evk/Cargo.toml @@ -14,7 +14,7 @@ embassy-executor = { version = "0.8.0", path = "../../embassy-executor", feature embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["defmt", "mimxrt1062", "unstable-pac", "time-driver-pit"] } embassy-time = { version = "0.4", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime" -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = "1.0.0" diff --git a/examples/mimxrt6/Cargo.toml b/examples/mimxrt6/Cargo.toml index 390a6e9f9..2667ec089 100644 --- a/examples/mimxrt6/Cargo.toml +++ b/examples/mimxrt6/Cargo.toml @@ -14,7 +14,7 @@ embassy-executor = { version = "0.8.0", path = "../../embassy-executor", feature embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } embassy-imxrt = { version = "0.1.0", path = "../../embassy-imxrt", features = ["defmt", "mimxrt685s", "unstable-pac", "time", "time-driver-os-timer"] } embassy-time = { version = "0.4", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = "1.0.0" diff --git a/examples/mspm0c1104/Cargo.toml b/examples/mspm0c1104/Cargo.toml index 52817034f..93ae4913a 100644 --- a/examples/mspm0c1104/Cargo.toml +++ b/examples/mspm0c1104/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0c1104dgs20", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/mspm0g3507/Cargo.toml b/examples/mspm0g3507/Cargo.toml index c3940b070..7544db230 100644 --- a/examples/mspm0g3507/Cargo.toml +++ b/examples/mspm0g3507/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3507pm", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/mspm0g3519/Cargo.toml b/examples/mspm0g3519/Cargo.toml index 463b20978..145a67b96 100644 --- a/examples/mspm0g3519/Cargo.toml +++ b/examples/mspm0g3519/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3519pz", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/mspm0l1306/Cargo.toml b/examples/mspm0l1306/Cargo.toml index 7834d7f5d..16562f3ee 100644 --- a/examples/mspm0l1306/Cargo.toml +++ b/examples/mspm0l1306/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l1306rhb", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/mspm0l2228/Cargo.toml b/examples/mspm0l2228/Cargo.toml index 85a351479..0bec500db 100644 --- a/examples/mspm0l2228/Cargo.toml +++ b/examples/mspm0l2228/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l2228pn", "defmt", "rt", "time-driver-any"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index df592154c..4ef986d96 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -15,7 +15,7 @@ log = [ ] [dependencies] -embassy-sync = { version = "0.7.0", path = "../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } embassy-time = { version = "0.4.0", path = "../../embassy-time" } embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index 37c8fee7b..2b4612a51 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index 5afb0c97a..d5fddd46e 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" rtic = { version = "2", features = ["thumbv7-backend"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } embassy-time-queue-utils = { version = "0.2", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 4d27a459c..b28ee0f4f 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 7f38f9035..19c5e707f 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index e09caa1d6..afe8a90d8 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal", features = ["defmt"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-rp = { version = "0.7.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 2a4e888d9..9087c4c83 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal", features = ["defmt"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-rp = { version = "0.7.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 520a66ab1..9b0ff8be2 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["log"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["log"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["log", "std", ] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features=[ "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index f8ac571e4..0a8d4ff2d 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32c031c6 to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti", "chrono"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index c236a6133..c3d1b99e5 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -12,7 +12,7 @@ cortex-m-rt = "0.7.0" defmt = "1.0.1" defmt-rtt = "1.0.0" panic-probe = { version = "1.0.0", features = ["print-defmt"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } static_cell = "2" diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 3655cb5f9..b91c781db 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f103c8 to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index 206e5f298..74ecb141d 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f207zg to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 4f25203ee..2cea5028a 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f303ze to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-tim2", "exti"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml index 7afe65080..8d015eae7 100644 --- a/examples/stm32f334/Cargo.toml +++ b/examples/stm32f334/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 7bcc675a4..3139bdf71 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f429zi to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-tim4", "exti", "chrono"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt" ] } diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index f70624cff..261524bc1 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f777zi to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32f777zi", "memory-x", "unstable-pac", "time-driver-any", "exti", "single-bank"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index d536eaed4..61e20168c 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32g0b1re to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g0b1re", "memory-x", "unstable-pac", "exti"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index 44c7385d6..c25df6ea8 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32g491re to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 276790797..68563dba0 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h563zi to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index ab65fd561..04c9b5bda 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32h723/Cargo.toml b/examples/stm32h723/Cargo.toml index 3fc4fd8a4..f7d819867 100644 --- a/examples/stm32h723/Cargo.toml +++ b/examples/stm32h723/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h723zg to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h723zg", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml index fa6d48ef3..946daf550 100644 --- a/examples/stm32h735/Cargo.toml +++ b/examples/stm32h735/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml index 22b19d304..8448c2c7a 100644 --- a/examples/stm32h742/Cargo.toml +++ b/examples/stm32h742/Cargo.toml @@ -14,7 +14,7 @@ embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "time-driver-any", "exti", ] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = [ +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = [ "defmt", ] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = [ diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index 5ecc4c377..e1ddf59be 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h755zi-cm4 to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index 9dc8d1ae5..b09095ea1 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml index 6d4ff8563..dc876159a 100644 --- a/examples/stm32h7b0/Cargo.toml +++ b/examples/stm32h7b0/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml index c2efa8d4d..4068fa5df 100644 --- a/examples/stm32h7rs/Cargo.toml +++ b/examples/stm32h7rs/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ethernet", "medium-ip", "proto-ipv4"] } diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index df72c429e..b76f6765f 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32l072cz to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32l073rz", "unstable-pac", "time-driver-any", "exti", "memory-x"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index d04845d19..442a5c795 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" license = "MIT OR Apache-2.0" [dependencies] -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 759143bef..bbe592212 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32l4s5vi to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4r5zi", "memory-x", "time-driver-any", "exti", "chrono", "dual-bank"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } diff --git a/examples/stm32l432/Cargo.toml b/examples/stm32l432/Cargo.toml index b675e7e41..483403b1d 100644 --- a/examples/stm32l432/Cargo.toml +++ b/examples/stm32l432/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32l4s5vi to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l432kc", "memory-x", "time-driver-any", "exti", "chrono"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = [ "defmt" ] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = [ "defmt" ] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "tick-hz-32_768" ] } defmt = "1.0.1" diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index b84015469..1739f0889 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32l552ze to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x", "low-power", "dual-bank"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml index 1ab29d813..1362aa422 100644 --- a/examples/stm32u0/Cargo.toml +++ b/examples/stm32u0/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32u083rc to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index 5b8f05b72..53f4ee618 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32u5g9zj to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u5g9zj", "time-driver-any", "memory-x" ] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index d67a792db..1b2fb9cbd 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" # Change stm32wb55rg to your chip name in both dependencies, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml index a64401a3b..a6ea433cf 100644 --- a/examples/stm32wba/Cargo.toml +++ b/examples/stm32wba/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } diff --git a/examples/stm32wba6/Cargo.toml b/examples/stm32wba6/Cargo.toml index 5775b1fc7..980091eaf 100644 --- a/examples/stm32wba6/Cargo.toml +++ b/examples/stm32wba6/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba65ri", "time-driver-any", "memory-x", "exti"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 4e851e3f1..31729565d 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32wl55jc-cm4 to your chip name, if necessary. embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml index fb6e5dc16..af139fdbd 100644 --- a/examples/wasm/Cargo.toml +++ b/examples/wasm/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" crate-type = ["cdylib"] [dependencies] -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["log"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["log"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["log", "wasm", ] } diff --git a/tests/mspm0/Cargo.toml b/tests/mspm0/Cargo.toml index 6742537e5..e4033b8b7 100644 --- a/tests/mspm0/Cargo.toml +++ b/tests/mspm0/Cargo.toml @@ -11,7 +11,7 @@ mspm0g3519 = [ "embassy-mspm0/mspm0g3519pz" ] [dependencies] teleprobe-meta = "1.1" -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = [ "defmt" ] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = [ "defmt" ] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt" ] } diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index bc7ab9891..ef7dc96ec 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" teleprobe-meta = "1" embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt", ] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt", ] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } diff --git a/tests/riscv32/Cargo.toml b/tests/riscv32/Cargo.toml index 6bce9a0e3..283ea5033 100644 --- a/tests/riscv32/Cargo.toml +++ b/tests/riscv32/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] critical-section = { version = "1.1.1", features = ["restore-state-bool"] } -embassy-sync = { version = "0.7.0", path = "../../embassy-sync" } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-riscv32", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../embassy-time" } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 711b6f733..eef6c47ae 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -12,7 +12,7 @@ rp235xb = ["embassy-rp/rp235xb"] [dependencies] teleprobe-meta = "1.1" -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", ] } embassy-rp = { version = "0.7.0", path = "../../embassy-rp", features = [ "defmt", "unstable-pac", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 33dce2c36..96b49f027 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -63,7 +63,7 @@ cm0 = ["portable-atomic/unsafe-assume-single-core"] [dependencies] teleprobe-meta = "1" -embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "tick-hz-131_072", "defmt-timestamp-uptime"] } embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "memory-x", "time-driver-any"] } -- cgit From 29555a88be25278fb676a89e84541993ec371555 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 12 Aug 2025 21:28:15 +0200 Subject: chore: add missing changelog header --- embassy-stm32/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 9da153480..c68377432 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -6,6 +6,8 @@ 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). +## Unreleased - ReleaseDate + ## 0.3.0 - 2025-08-12 - feat: Added VREFBUF voltage reference buffer driver ([#4524](https://github.com/embassy-rs/embassy/pull/4524)) -- cgit From 34aa186734caaed386789d4c37d2f1e9a202059a Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 12 Aug 2025 21:29:14 +0200 Subject: chore: prepare embassy-boot-stm32 release --- embassy-boot-stm32/Cargo.toml | 2 +- examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wb-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wba-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wl/Cargo.toml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/embassy-boot-stm32/Cargo.toml b/embassy-boot-stm32/Cargo.toml index 7cdd5136a..b1087da1c 100644 --- a/embassy-boot-stm32/Cargo.toml +++ b/embassy-boot-stm32/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-stm32" -version = "0.4.0" +version = "0.5.0" description = "Bootloader lib for STM32 chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index 5d736d875..f9d5922b1 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32" } +embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32" } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index cc658459f..f831e7f68 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } -embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index 03884257b..29d54c47f 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 09d9474e9..7c6c1dc78 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } -embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index a49366c2b..ecb498325 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index 8f0c95f0f..075f7b986 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index f3dbdc4de..65fac6062 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb" } embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } diff --git a/examples/boot/application/stm32wba-dfu/Cargo.toml b/examples/boot/application/stm32wba-dfu/Cargo.toml index cab2c2b03..469924422 100644 --- a/examples/boot/application/stm32wba-dfu/Cargo.toml +++ b/examples/boot/application/stm32wba-dfu/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32wba65ri", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb" } embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index 4e4ab945b..fb8112edf 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.4.0", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } -- cgit From 8bbfa7ac1b7165a690f5062ce85c45898b3160bd Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 12 Aug 2025 21:35:54 +0200 Subject: chore: add changelog enforcement --- .github/workflows/changelog.yml | 353 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 353 insertions(+) create mode 100644 .github/workflows/changelog.yml diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml new file mode 100644 index 000000000..94e8f353a --- /dev/null +++ b/.github/workflows/changelog.yml @@ -0,0 +1,353 @@ +name: Changelog check + +on: + pull_request: + # We will not track changes for the following packages/directories. + paths-ignore: + - "/examples/" + - "/docs/" + - "/out/" + - "/tests/" + - "/release/" + - "/cyw43-firmware/" + # Run on labeled/unlabeled in addition to defaults to detect + # adding/removing skip-changelog labels. + types: [opened, reopened, labeled, unlabeled, synchronize] + +jobs: + changelog: + runs-on: ubuntu-latest + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Check which package is modified + uses: dorny/paths-filter@v3 + id: changes + with: + filters: | + cyw43: + - 'cyw43/**' + cyw43-pio: + - 'cyw43-pio/**' + embassy-boot: + - 'embassy-boot/**' + embassy-boot-nrf: + - 'embassy-boot-nrf/**' + embassy-boot-rp: + - 'embassy-boot-rp/**' + embassy-boot-stm32: + - 'embassy-boot-stm32/**' + embassy-embedded-hal: + - 'embassy-embedded-hal/**' + embassy-executor: + - 'embassy-executor/**' + embassy-executor-macros: + - 'embassy-executor-macros/**' + embassy-futures: + - 'embassy-futures/**' + embassy-imxrt: + - 'embassy-imxrt/**' + embassy-mspm0: + - 'embassy-mspm0/**' + embassy-net: + - 'embassy-net/**' + embassy-net-adin1110: + - 'embassy-net-adin1110/**' + embassy-net-driver: + - 'embassy-net-driver/**' + embassy-net-driver-channel: + - 'embassy-net-driver-channel/**' + embassy-net-enc28j60: + - 'embassy-net-enc28j60/**' + embassy-net-esp-hosted: + - 'embassy-net-esp-hosted/**' + embassy-net-nrf91: + - 'embassy-net-nrf91/**' + embassy-net-ppp: + - 'embassy-net-ppp/**' + embassy-net-tuntap: + - 'embassy-net-tuntap/**' + embassy-net-wiznet: + - 'embassy-net-wiznet/**' + embassy-nrf: + - 'embassy-nrf/**' + embassy-nxp: + - 'embassy-nxp/**' + embassy-rp: + - 'embassy-rp/**' + embassy-stm32: + - 'embassy-stm32/**' + embassy-stm32-wpan: + - 'embassy-stm32-wpan/**' + embassy-sync: + - 'embassy-sync/**' + embassy-time: + - 'embassy-time/**' + embassy-time-driver: + - 'embassy-time-driver/**' + embassy-time-queue-utils: + - 'embassy-time-queue-utils/**' + embassy-usb: + - 'embassy-usb/**' + embassy-usb-dfu: + - 'embassy-usb-dfu/**' + embassy-usb-driver: + - 'embassy-usb-driver/**' + embassy-usb-logger: + - 'embassy-usb-logger/**' + embassy-usb-synopsys-otg: + - 'embassy-usb-synopsys-otg/**' + - name: Check that changelog updated (cyw43) + if: steps.changes.outputs.cyw43 == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: cyw43/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the cyw43/CHANGELOG.md file." + - name: Check that changelog updated (cyw43-pio) + if: steps.changes.outputs.cyw43-pio == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: cyw43-pio/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the cyw43-pio/CHANGELOG.md file." + - name: Check that changelog updated (embassy-boot) + if: steps.changes.outputs.embassy-boot == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-boot/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-boot/CHANGELOG.md file." + - name: Check that changelog updated (embassy-boot-nrf) + if: steps.changes.outputs.embassy-boot-nrf == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-boot-nrf/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-boot-nrf/CHANGELOG.md file." + - name: Check that changelog updated (embassy-boot-rp) + if: steps.changes.outputs.embassy-boot-rp == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-boot-rp/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-boot-rp/CHANGELOG.md file." + - name: Check that changelog updated (embassy-boot-stm32) + if: steps.changes.outputs.embassy-boot-stm32 == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-boot-stm32/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-boot-stm32/CHANGELOG.md file." + - name: Check that changelog updated (embassy-embedded-hal) + if: steps.changes.outputs.embassy-embedded-hal == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-embedded-hal/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-embedded-hal/CHANGELOG.md file." + - name: Check that changelog updated (embassy-executor) + if: steps.changes.outputs.embassy-executor == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-executor/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-executor/CHANGELOG.md file." + - name: Check that changelog updated (embassy-executor-macros) + if: steps.changes.outputs.embassy-executor-macros == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-executor-macros/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-executor-macros/CHANGELOG.md file." + - name: Check that changelog updated (embassy-futures) + if: steps.changes.outputs.embassy-futures == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-futures/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-futures/CHANGELOG.md file." + - name: Check that changelog updated (embassy-imxrt) + if: steps.changes.outputs.embassy-imxrt == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-imxrt/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-imxrt/CHANGELOG.md file." + - name: Check that changelog updated (embassy-mspm0) + if: steps.changes.outputs.embassy-mspm0 == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-mspm0/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-mspm0/CHANGELOG.md file." + - name: Check that changelog updated (embassy-net) + if: steps.changes.outputs.embassy-net == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-net/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-net/CHANGELOG.md file." + - name: Check that changelog updated (embassy-net-adin1110) + if: steps.changes.outputs.embassy-net-adin1110 == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-net-adin1110/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-net-adin1110/CHANGELOG.md file." + - name: Check that changelog updated (embassy-net-driver) + if: steps.changes.outputs.embassy-net-driver == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-net-driver/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-net-driver/CHANGELOG.md file." + - name: Check that changelog updated (embassy-net-driver-channel) + if: steps.changes.outputs.embassy-net-driver-channel == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-net-driver-channel/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-net-driver-channel/CHANGELOG.md file." + - name: Check that changelog updated (embassy-net-enc28j60) + if: steps.changes.outputs.embassy-net-enc28j60 == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-net-enc28j60/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-net-enc28j60/CHANGELOG.md file." + - name: Check that changelog updated (embassy-net-esp-hosted) + if: steps.changes.outputs.embassy-net-esp-hosted == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-net-esp-hosted/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-net-esp-hosted/CHANGELOG.md file." + - name: Check that changelog updated (embassy-net-nrf91) + if: steps.changes.outputs.embassy-net-nrf91 == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-net-nrf91/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-net-nrf91/CHANGELOG.md file." + - name: Check that changelog updated (embassy-net-ppp) + if: steps.changes.outputs.embassy-net-ppp == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-net-ppp/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-net-ppp/CHANGELOG.md file." + - name: Check that changelog updated (embassy-net-tuntap) + if: steps.changes.outputs.embassy-net-tuntap == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-net-tuntap/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-net-tuntap/CHANGELOG.md file." + - name: Check that changelog updated (embassy-net-wiznet) + if: steps.changes.outputs.embassy-net-wiznet == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-net-wiznet/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-net-wiznet/CHANGELOG.md file." + - name: Check that changelog updated (embassy-nrf) + if: steps.changes.outputs.embassy-nrf == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-nrf/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-nrf/CHANGELOG.md file." + - name: Check that changelog updated (embassy-nxp) + if: steps.changes.outputs.embassy-nxp == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-nxp/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-nxp/CHANGELOG.md file." + - name: Check that changelog updated (embassy-rp) + if: steps.changes.outputs.embassy-rp == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-rp/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-rp/CHANGELOG.md file." + - name: Check that changelog updated (embassy-stm32) + if: steps.changes.outputs.embassy-stm32 == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-stm32/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-stm32/CHANGELOG.md file." + - name: Check that changelog updated (embassy-stm32-wpan) + if: steps.changes.outputs.embassy-stm32-wpan == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-stm32-wpan/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-stm32-wpan/CHANGELOG.md file." + - name: Check that changelog updated (embassy-sync) + if: steps.changes.outputs.embassy-sync == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-sync/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-sync/CHANGELOG.md file." + - name: Check that changelog updated (embassy-time) + if: steps.changes.outputs.embassy-time == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-time/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-time/CHANGELOG.md file." + - name: Check that changelog updated (embassy-time-driver) + if: steps.changes.outputs.embassy-time-driver == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-time-driver/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-time-driver/CHANGELOG.md file." + - name: Check that changelog updated (embassy-time-queue-utils) + if: steps.changes.outputs.embassy-time-queue-utils == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-time-queue-utils/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-time-queue-utils/CHANGELOG.md file." + - name: Check that changelog updated (embassy-usb) + if: steps.changes.outputs.embassy-usb == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-usb/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-usb/CHANGELOG.md file." + - name: Check that changelog updated (embassy-usb-dfu) + if: steps.changes.outputs.embassy-usb-dfu == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-usb-dfu/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-usb-dfu/CHANGELOG.md file." + - name: Check that changelog updated (embassy-usb-driver) + if: steps.changes.outputs.embassy-usb-driver == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-usb-driver/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-usb-driver/CHANGELOG.md file." + - name: Check that changelog updated (embassy-usb-logger) + if: steps.changes.outputs.embassy-usb-logger == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-usb-logger/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-usb-logger/CHANGELOG.md file." + - name: Check that changelog updated (embassy-usb-synopsys-otg) + if: steps.changes.outputs.embassy-usb-synopsys-otg == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-usb-synopsys-otg/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-usb-synopsys-otg/CHANGELOG.md file." -- cgit From ba5201c44f1adf7769d18017db5a3d40b0bd9bce Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Tue, 12 Aug 2025 19:00:38 -0700 Subject: Added VREFBUF-TRIM manual write. Known errata --- embassy-stm32/src/vrefbuf/mod.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/vrefbuf/mod.rs b/embassy-stm32/src/vrefbuf/mod.rs index f614fcf99..5c7dbfa50 100644 --- a/embassy-stm32/src/vrefbuf/mod.rs +++ b/embassy-stm32/src/vrefbuf/mod.rs @@ -1,5 +1,4 @@ //! Voltage Reference Buffer (VREFBUF) -// use core::ptr::{read_volatile, write_volatile}; use core::marker::PhantomData; use embassy_hal_internal::PeripheralType; @@ -12,6 +11,26 @@ pub struct VoltageReferenceBuffer<'d, T: Instance> { vrefbuf: PhantomData<&'d mut T>, } +#[cfg(rcc_wba)] +#[repr(usize)] +enum VRefBufTrim { + VRefBuf3Trim = 0x0BFA_07A8, + VRefBuf2Trim = 0x0BFA_07A9, + VRefBuf1Trim = 0x0BFA_07AA, + VRefBuf0Trim = 0x0BFA_07AB, +} + +#[cfg(rcc_wba)] +fn get_refbuf_trim(voltage_scale: Vrs) -> VRefBufTrim { + match voltage_scale { + Vrs::VREF0 => VRefBufTrim::VRefBuf0Trim, + Vrs::VREF1 => VRefBufTrim::VRefBuf1Trim, + Vrs::VREF2 => VRefBufTrim::VRefBuf2Trim, + Vrs::VREF3 => VRefBufTrim::VRefBuf3Trim, + _ => panic!("Incorrect Vrs setting!"), + } +} + impl<'d, T: Instance> VoltageReferenceBuffer<'d, T> { /// Creates an VREFBUF (Voltage Reference) instance with a voltage scale and impedance mode. /// @@ -21,6 +40,15 @@ impl<'d, T: Instance> VoltageReferenceBuffer<'d, T> { { use crate::pac::RCC; RCC.apb7enr().modify(|w| w.set_vrefen(true)); + // This is an errata for WBA6 devices. VREFBUF_TRIM value isn't set correctly + // [Link explaining it](https://www.st.com/resource/en/errata_sheet/es0644-stm32wba6xxx-device-errata-stmicroelectronics.pdf) + unsafe { + use crate::pac::VREFBUF; + let addr = get_refbuf_trim(voltage_scale) as usize; + let buf_trim_ptr = core::ptr::with_exposed_provenance::(addr); + let trim_val = core::ptr::read_volatile(buf_trim_ptr); + VREFBUF.ccr().write(|w| w.set_trim((trim_val & 0xFF) as u8)); + } } #[cfg(any(rcc_u5, rcc_h50, rcc_h5))] { -- cgit From 1cf63731425684e76fac311e44ff3d46227e5ff8 Mon Sep 17 00:00:00 2001 From: Malte Brieske <9287988+mbrieske@users.noreply.github.com> Date: Wed, 13 Aug 2025 13:07:36 +0200 Subject: wait for STOPF in blocking read --- embassy-stm32/src/i2c/v2.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 4d341bab1..7f73ff82b 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -408,6 +408,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { *byte = self.info.regs.rxdr().read().rxdata(); } } + self.wait_stop(timeout)?; Ok(()) } -- cgit From 55d9399ab85efc6250f60fd4440fc3cf97e506a5 Mon Sep 17 00:00:00 2001 From: Malte Brieske <9287988+mbrieske@users.noreply.github.com> Date: Wed, 13 Aug 2025 16:25:52 +0200 Subject: wait for STOP flag when writing too --- embassy-stm32/src/i2c/v2.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 7f73ff82b..aeb4c1c00 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -464,11 +464,13 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { } } // Wait until the write finishes - let result = self.wait_tc(timeout); + self.wait_tc(timeout)?; if send_stop { self.master_stop(); + self.wait_stop(timeout)?; } - result + + Ok(()) } // ========================= -- cgit From b0024ecb45fe5f66549494571e3b11bf2c6ec9b2 Mon Sep 17 00:00:00 2001 From: Malte Brieske <9287988+mbrieske@users.noreply.github.com> Date: Wed, 13 Aug 2025 17:27:39 +0200 Subject: wait for STOP flag in blocking_write_vectored as well --- embassy-stm32/src/i2c/v2.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index aeb4c1c00..3b09f1b34 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -582,9 +582,11 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { } } // Wait until the write finishes - let result = self.wait_tc(timeout); + self.wait_tc(timeout)?; self.master_stop(); - result + self.wait_stop(timeout)?; + + Ok(()) } } -- cgit From 2a43e68cc342cdd7335140219704cb3513847bb6 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Wed, 13 Aug 2025 14:17:02 -0700 Subject: Removed uneeded enum --- embassy-stm32/src/vrefbuf/mod.rs | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/embassy-stm32/src/vrefbuf/mod.rs b/embassy-stm32/src/vrefbuf/mod.rs index 5c7dbfa50..54b4f8903 100644 --- a/embassy-stm32/src/vrefbuf/mod.rs +++ b/embassy-stm32/src/vrefbuf/mod.rs @@ -12,21 +12,12 @@ pub struct VoltageReferenceBuffer<'d, T: Instance> { } #[cfg(rcc_wba)] -#[repr(usize)] -enum VRefBufTrim { - VRefBuf3Trim = 0x0BFA_07A8, - VRefBuf2Trim = 0x0BFA_07A9, - VRefBuf1Trim = 0x0BFA_07AA, - VRefBuf0Trim = 0x0BFA_07AB, -} - -#[cfg(rcc_wba)] -fn get_refbuf_trim(voltage_scale: Vrs) -> VRefBufTrim { +fn get_refbuf_trim(voltage_scale: Vrs) -> usize { match voltage_scale { - Vrs::VREF0 => VRefBufTrim::VRefBuf0Trim, - Vrs::VREF1 => VRefBufTrim::VRefBuf1Trim, - Vrs::VREF2 => VRefBufTrim::VRefBuf2Trim, - Vrs::VREF3 => VRefBufTrim::VRefBuf3Trim, + Vrs::VREF0 => 0x0BFA_07A8usize, + Vrs::VREF1 => 0x0BFA_07A9usize, + Vrs::VREF2 => 0x0BFA_07AAusize, + Vrs::VREF3 => 0x0BFA_07ABusize, _ => panic!("Incorrect Vrs setting!"), } } @@ -44,10 +35,10 @@ impl<'d, T: Instance> VoltageReferenceBuffer<'d, T> { // [Link explaining it](https://www.st.com/resource/en/errata_sheet/es0644-stm32wba6xxx-device-errata-stmicroelectronics.pdf) unsafe { use crate::pac::VREFBUF; - let addr = get_refbuf_trim(voltage_scale) as usize; + let addr = get_refbuf_trim(voltage_scale); let buf_trim_ptr = core::ptr::with_exposed_provenance::(addr); let trim_val = core::ptr::read_volatile(buf_trim_ptr); - VREFBUF.ccr().write(|w| w.set_trim((trim_val & 0xFF) as u8)); + VREFBUF.ccr().write(|w| w.set_trim((trim_val & 0x3F) as u8)); } } #[cfg(any(rcc_u5, rcc_h50, rcc_h5))] -- cgit From b7964df8875384269ac4d2a52ae149e25abecbaf Mon Sep 17 00:00:00 2001 From: Bart Slinger Date: Thu, 14 Aug 2025 13:54:43 +0800 Subject: add missing feature gate for rtos-trace --- embassy-executor/src/raw/trace.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index aa27ab37e..f484abf58 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -84,6 +84,7 @@ use core::cell::UnsafeCell; use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; +#[cfg(feature = "rtos-trace")] use rtos_trace::TaskInfo; use crate::raw::{SyncExecutor, TaskHeader, TaskRef}; -- cgit From b66fa9ae4a3f994a61bde0e49dac642aaeb8ed4f Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Thu, 14 Aug 2025 10:06:15 +0200 Subject: mspm0-I2C: fix calculate_timer_period function & tests --- embassy-mspm0/src/i2c.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/embassy-mspm0/src/i2c.rs b/embassy-mspm0/src/i2c.rs index d1b260114..7e22bb724 100644 --- a/embassy-mspm0/src/i2c.rs +++ b/embassy-mspm0/src/i2c.rs @@ -190,7 +190,7 @@ impl Config { // - SCL_LP is the SCL Low period (fixed at 6) // - SCL_HP is the SCL High period (fixed at 4) // - I2C_CLK is functional clock frequency - return (((self.calculate_clock_source() * self.clock_div.divider()) / (self.bus_speed.hertz() * 10u32)) - 1) + return ((self.calculate_clock_source() / (self.bus_speed.hertz() * 10u32)) - 1) .try_into() .unwrap(); } @@ -200,8 +200,8 @@ impl Config { // Assume that BusClk has default value. // TODO: calculate BusClk more precisely. match self.clock_source { - ClockSel::MfClk => 4_000_000, - ClockSel::BusClk => 24_000_000, + ClockSel::MfClk => 4_000_000 / self.clock_div.divider(), + ClockSel::BusClk => 24_000_000 / self.clock_div.divider(), } } @@ -213,8 +213,8 @@ impl Config { // Assume that BusClk has default value. // TODO: calculate BusClk more precisely. match self.clock_source { - ClockSel::MfClk => 4_000_000, - ClockSel::BusClk => 24_000_000, + ClockSel::MfClk => 4_000_000 / self.clock_div.divider(), + ClockSel::BusClk => 32_000_000 / self.clock_div.divider(), } } @@ -1144,7 +1144,7 @@ mod tests { config.clock_div = ClockDiv::DivBy1; config.bus_speed = BusSpeed::FastMode; config.clock_source = ClockSel::BusClk; - assert!(matches!(config.calculate_timer_period(), 7)); + assert_eq!(config.calculate_timer_period(), 7u8); } #[test] @@ -1153,7 +1153,7 @@ mod tests { config.clock_div = ClockDiv::DivBy2; config.bus_speed = BusSpeed::FastMode; config.clock_source = ClockSel::BusClk; - assert!(matches!(config.calculate_timer_period(), 3)); + assert_eq!(config.calculate_timer_period(), 3u8); } #[test] @@ -1162,7 +1162,7 @@ mod tests { config.clock_div = ClockDiv::DivBy2; config.bus_speed = BusSpeed::Standard; config.clock_source = ClockSel::BusClk; - assert!(matches!(config.calculate_timer_period(), 15)); + assert_eq!(config.calculate_timer_period(), 15u8); } #[test] @@ -1171,7 +1171,7 @@ mod tests { config.clock_div = ClockDiv::DivBy2; config.bus_speed = BusSpeed::Custom(100_000); config.clock_source = ClockSel::BusClk; - assert!(matches!(config.calculate_timer_period(), 15)); + assert_eq!(config.calculate_timer_period(), 15u8); } #[test] -- cgit From f84eb9a7eb2df85b2d0dc7a934f2568640ef6161 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Thu, 14 Aug 2025 10:29:41 +0200 Subject: embassy-mspm0: add changes to the CHANGELOG.md --- embassy-mspm0/CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 embassy-mspm0/CHANGELOG.md diff --git a/embassy-mspm0/CHANGELOG.md b/embassy-mspm0/CHANGELOG.md new file mode 100644 index 000000000..7c22b2f28 --- /dev/null +++ b/embassy-mspm0/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog for embassy-mspm0 + +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). + +## Unreleased - ReleaseDate + +- feat: Add I2C Controller (blocking & async) + examples for mspm0l1306, mspm0g3507 (tested MCUs) (#4435) -- cgit From a977b0a975deccd08aefa7b8889ae1db6bc17a91 Mon Sep 17 00:00:00 2001 From: nerwalt Date: Thu, 14 Aug 2025 10:33:14 -0600 Subject: Use from_bits in LoopCnt --- embassy-nrf/src/pwm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index 3d76272ac..d6b40b5c0 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs @@ -480,7 +480,7 @@ impl<'d, 's, T: Instance> Sequencer<'d, 's, T> { match times { SequenceMode::Loop(n) => { - r.loop_().write(|w| w.set_cnt(vals::LoopCnt(n))); + r.loop_().write(|w| w.set_cnt(vals::LoopCnt::from_bits(n))); } // to play infinitely, repeat the sequence one time, then have loops done self trigger seq0 again SequenceMode::Infinite => { -- cgit From 4c556dcbf23c0024766e78d5839ce3f717bbc0e9 Mon Sep 17 00:00:00 2001 From: Fabian Wolter Date: Thu, 14 Aug 2025 19:41:00 +0200 Subject: stm32 tests: move can_common out of the bin folder --- tests/stm32/src/bin/can.rs | 1 + tests/stm32/src/bin/can_common.rs | 109 -------------------------------------- tests/stm32/src/bin/fdcan.rs | 1 + tests/stm32/src/can_common.rs | 109 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 109 deletions(-) delete mode 100644 tests/stm32/src/bin/can_common.rs create mode 100644 tests/stm32/src/can_common.rs diff --git a/tests/stm32/src/bin/can.rs b/tests/stm32/src/bin/can.rs index 778d88a7b..348cd049d 100644 --- a/tests/stm32/src/bin/can.rs +++ b/tests/stm32/src/bin/can.rs @@ -15,6 +15,7 @@ use embassy_stm32::peripherals::CAN1; use embassy_time::Duration; use {defmt_rtt as _, panic_probe as _}; +#[path = "../can_common.rs"] mod can_common; use can_common::*; diff --git a/tests/stm32/src/bin/can_common.rs b/tests/stm32/src/bin/can_common.rs deleted file mode 100644 index 4e1740ad5..000000000 --- a/tests/stm32/src/bin/can_common.rs +++ /dev/null @@ -1,109 +0,0 @@ -use defmt::{assert, *}; -use embassy_stm32::can; -use embassy_time::{Duration, Instant}; - -#[derive(Clone, Copy, Debug)] -pub struct TestOptions { - pub max_latency: Duration, - pub max_buffered: u8, -} - -pub async fn run_can_tests<'d>(can: &mut can::Can<'d>, options: &TestOptions) { - //pub async fn run_can_tests<'d, T: can::Instance>(can: &mut can::Can<'d, T>, options: &TestOptions) { - let mut i: u8 = 0; - loop { - //let tx_frame = can::frame::Frame::new_standard(0x123, &[i, 0x12 as u8, 0x34 as u8, 0x56 as u8, 0x78 as u8, 0x9A as u8, 0xBC as u8 ]).unwrap(); - let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap(); - - //info!("Transmitting frame..."); - let tx_ts = Instant::now(); - can.write(&tx_frame).await; - - let (frame, timestamp) = can.read().await.unwrap().parts(); - //info!("Frame received!"); - - // Check data. - assert!(i == frame.data()[0], "{} == {}", i, frame.data()[0]); - - //info!("loopback time {}", timestamp); - //info!("loopback frame {=u8}", frame.data()[0]); - let latency = timestamp.saturating_duration_since(tx_ts); - info!("loopback latency {} us", latency.as_micros()); - - // Theoretical minimum latency is 55us, actual is usually ~80us - const MIN_LATENCY: Duration = Duration::from_micros(50); - // Was failing at 150 but we are not getting a real time stamp. I'm not - // sure if there are other delays - assert!( - MIN_LATENCY <= latency && latency <= options.max_latency, - "{} <= {} <= {}", - MIN_LATENCY, - latency, - options.max_latency - ); - - i += 1; - if i > 5 { - break; - } - } - - // Below here, check that we can receive from both FIFO0 and FIFO1 - // Above we configured FIFO1 for extended ID packets. There are only 3 slots - // in each FIFO so make sure we write enough to fill them both up before reading. - for i in 0..options.max_buffered { - // Try filling up the RX FIFO0 buffers - //let tx_frame = if 0 != (i & 0x01) { - let tx_frame = if i < options.max_buffered / 2 { - info!("Transmitting standard frame {}", i); - can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap() - } else { - info!("Transmitting extended frame {}", i); - can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap() - }; - can.write(&tx_frame).await; - } - - // Try and receive all 6 packets - for _i in 0..options.max_buffered { - let (frame, _ts) = can.read().await.unwrap().parts(); - match frame.id() { - embedded_can::Id::Extended(_id) => { - info!("Extended received! {}", frame.data()[0]); - //info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i); - } - embedded_can::Id::Standard(_id) => { - info!("Standard received! {}", frame.data()[0]); - //info!("Standard received! {:x} {} {}", id.as_raw(), frame.data()[0], i); - } - } - } -} - -pub async fn run_split_can_tests<'d>(tx: &mut can::CanTx<'d>, rx: &mut can::CanRx<'d>, options: &TestOptions) { - for i in 0..options.max_buffered { - // Try filling up the RX FIFO0 buffers - //let tx_frame = if 0 != (i & 0x01) { - let tx_frame = if i < options.max_buffered / 2 { - info!("Transmitting standard frame {}", i); - can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap() - } else { - info!("Transmitting extended frame {}", i); - can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap() - }; - tx.write(&tx_frame).await; - } - - // Try and receive all 6 packets - for _i in 0..options.max_buffered { - let (frame, _ts) = rx.read().await.unwrap().parts(); - match frame.id() { - embedded_can::Id::Extended(_id) => { - info!("Extended received! {}", frame.data()[0]); - } - embedded_can::Id::Standard(_id) => { - info!("Standard received! {}", frame.data()[0]); - } - } - } -} diff --git a/tests/stm32/src/bin/fdcan.rs b/tests/stm32/src/bin/fdcan.rs index 83d7eca85..c2a1a7bb8 100644 --- a/tests/stm32/src/bin/fdcan.rs +++ b/tests/stm32/src/bin/fdcan.rs @@ -12,6 +12,7 @@ use embassy_stm32::{bind_interrupts, can, Config}; use embassy_time::Duration; use {defmt_rtt as _, panic_probe as _}; +#[path = "../can_common.rs"] mod can_common; use can_common::*; diff --git a/tests/stm32/src/can_common.rs b/tests/stm32/src/can_common.rs new file mode 100644 index 000000000..4e1740ad5 --- /dev/null +++ b/tests/stm32/src/can_common.rs @@ -0,0 +1,109 @@ +use defmt::{assert, *}; +use embassy_stm32::can; +use embassy_time::{Duration, Instant}; + +#[derive(Clone, Copy, Debug)] +pub struct TestOptions { + pub max_latency: Duration, + pub max_buffered: u8, +} + +pub async fn run_can_tests<'d>(can: &mut can::Can<'d>, options: &TestOptions) { + //pub async fn run_can_tests<'d, T: can::Instance>(can: &mut can::Can<'d, T>, options: &TestOptions) { + let mut i: u8 = 0; + loop { + //let tx_frame = can::frame::Frame::new_standard(0x123, &[i, 0x12 as u8, 0x34 as u8, 0x56 as u8, 0x78 as u8, 0x9A as u8, 0xBC as u8 ]).unwrap(); + let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap(); + + //info!("Transmitting frame..."); + let tx_ts = Instant::now(); + can.write(&tx_frame).await; + + let (frame, timestamp) = can.read().await.unwrap().parts(); + //info!("Frame received!"); + + // Check data. + assert!(i == frame.data()[0], "{} == {}", i, frame.data()[0]); + + //info!("loopback time {}", timestamp); + //info!("loopback frame {=u8}", frame.data()[0]); + let latency = timestamp.saturating_duration_since(tx_ts); + info!("loopback latency {} us", latency.as_micros()); + + // Theoretical minimum latency is 55us, actual is usually ~80us + const MIN_LATENCY: Duration = Duration::from_micros(50); + // Was failing at 150 but we are not getting a real time stamp. I'm not + // sure if there are other delays + assert!( + MIN_LATENCY <= latency && latency <= options.max_latency, + "{} <= {} <= {}", + MIN_LATENCY, + latency, + options.max_latency + ); + + i += 1; + if i > 5 { + break; + } + } + + // Below here, check that we can receive from both FIFO0 and FIFO1 + // Above we configured FIFO1 for extended ID packets. There are only 3 slots + // in each FIFO so make sure we write enough to fill them both up before reading. + for i in 0..options.max_buffered { + // Try filling up the RX FIFO0 buffers + //let tx_frame = if 0 != (i & 0x01) { + let tx_frame = if i < options.max_buffered / 2 { + info!("Transmitting standard frame {}", i); + can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap() + } else { + info!("Transmitting extended frame {}", i); + can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap() + }; + can.write(&tx_frame).await; + } + + // Try and receive all 6 packets + for _i in 0..options.max_buffered { + let (frame, _ts) = can.read().await.unwrap().parts(); + match frame.id() { + embedded_can::Id::Extended(_id) => { + info!("Extended received! {}", frame.data()[0]); + //info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i); + } + embedded_can::Id::Standard(_id) => { + info!("Standard received! {}", frame.data()[0]); + //info!("Standard received! {:x} {} {}", id.as_raw(), frame.data()[0], i); + } + } + } +} + +pub async fn run_split_can_tests<'d>(tx: &mut can::CanTx<'d>, rx: &mut can::CanRx<'d>, options: &TestOptions) { + for i in 0..options.max_buffered { + // Try filling up the RX FIFO0 buffers + //let tx_frame = if 0 != (i & 0x01) { + let tx_frame = if i < options.max_buffered / 2 { + info!("Transmitting standard frame {}", i); + can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap() + } else { + info!("Transmitting extended frame {}", i); + can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap() + }; + tx.write(&tx_frame).await; + } + + // Try and receive all 6 packets + for _i in 0..options.max_buffered { + let (frame, _ts) = rx.read().await.unwrap().parts(); + match frame.id() { + embedded_can::Id::Extended(_id) => { + info!("Extended received! {}", frame.data()[0]); + } + embedded_can::Id::Standard(_id) => { + info!("Standard received! {}", frame.data()[0]); + } + } + } +} -- cgit From 695ca5b0a5585fba38cf1deeeba159e29a2b664e Mon Sep 17 00:00:00 2001 From: i509VCB Date: Thu, 14 Aug 2025 15:35:14 -0500 Subject: ci: 5340dk is dead --- ci.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci.sh b/ci.sh index 68bf38881..94bf83675 100755 --- a/ci.sh +++ b/ci.sh @@ -358,6 +358,7 @@ DEFMT_RTT_BUFFER_SIZE="72" cargo batch \ rm -rf out/tests/stm32f103c8 rm -rf out/tests/nrf52840-dk rm -rf out/tests/nrf52833-dk +rm -rf out/tests/nrf5340-dk # disabled because these boards are not on the shelf rm -rf out/tests/mspm0g3507 -- cgit From dd233b38f52e51fc80817e2bee01e61ffa9b329f Mon Sep 17 00:00:00 2001 From: i509VCB Date: Thu, 14 Aug 2025 16:01:31 -0500 Subject: mspm0: actually enable GPIOA interrupt for l110x --- embassy-mspm0/CHANGELOG.md | 1 + embassy-mspm0/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/embassy-mspm0/CHANGELOG.md b/embassy-mspm0/CHANGELOG.md index 7c22b2f28..cf8aeb046 100644 --- a/embassy-mspm0/CHANGELOG.md +++ b/embassy-mspm0/CHANGELOG.md @@ -8,3 +8,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate - feat: Add I2C Controller (blocking & async) + examples for mspm0l1306, mspm0g3507 (tested MCUs) (#4435) +- fix gpio interrupt not being set for mspm0l110x diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index 54ac2d9e6..6217669d2 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -194,7 +194,7 @@ pub fn init(config: Config) -> Peripherals { _generated::enable_group_interrupts(cs); - #[cfg(mspm0c110x)] + #[cfg(any(mspm0c110x, mspm0l110x))] unsafe { use crate::_generated::interrupt::typelevel::Interrupt; crate::interrupt::typelevel::GPIOA::enable(); -- cgit From 1347daf7635007423c6df1464c4f45580d3236d0 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Fri, 15 Aug 2025 11:11:09 +0800 Subject: stm32: Fix vrefbuf trace with log feature Vrs and Hiz don't implement core::fmt::Display --- embassy-stm32/CHANGELOG.md | 2 ++ embassy-stm32/src/vrefbuf/mod.rs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index c68377432..0c2d23246 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- fix: Fix vrefbuf building with log feature + ## 0.3.0 - 2025-08-12 - feat: Added VREFBUF voltage reference buffer driver ([#4524](https://github.com/embassy-rs/embassy/pull/4524)) diff --git a/embassy-stm32/src/vrefbuf/mod.rs b/embassy-stm32/src/vrefbuf/mod.rs index 54b4f8903..ccbd748d5 100644 --- a/embassy-stm32/src/vrefbuf/mod.rs +++ b/embassy-stm32/src/vrefbuf/mod.rs @@ -62,8 +62,8 @@ impl<'d, T: Instance> VoltageReferenceBuffer<'d, T> { } trace!( "Vrefbuf configured with voltage scale {} and impedance mode {}", - voltage_scale, - impedance_mode + voltage_scale as u8, + impedance_mode as u8, ); VoltageReferenceBuffer { vrefbuf: PhantomData } } -- cgit From 17f50c886105e3aecec8e1e272a34c30fb40a9b6 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Fri, 15 Aug 2025 11:12:14 +0800 Subject: ci: Build stm32h7s3a8 with log feature Covers some different peripherals to the existing stm32f429zi,log build. --- ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci.sh b/ci.sh index 94bf83675..4fdce65d2 100755 --- a/ci.sh +++ b/ci.sh @@ -148,7 +148,7 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-tim1,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7r3z8,defmt,exti,time-driver-tim1,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7r7a8,defmt,exti,time-driver-tim1,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s3a8,defmt,exti,time-driver-tim1,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s3a8,log,exti,time-driver-tim1,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s7z8,defmt,exti,time-driver-tim1,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l431cb,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \ -- cgit From 410a18b536e73c005285b458eaeb8b6c3a71c1af Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Tue, 12 Aug 2025 17:09:52 +0800 Subject: stm32/hash: Clear HMAC mode bit when hashing Running a hash after a hmac would hang, the CR.MODE bit isn't cleared by INIT. Test it by running the test twice. --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/src/hash/mod.rs | 2 ++ tests/stm32/src/bin/hash.rs | 17 ++++++++++++----- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 0c2d23246..9ad117312 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate - fix: Fix vrefbuf building with log feature +- fix: Fix performing a hash after performing a hmac ## 0.3.0 - 2025-08-12 diff --git a/embassy-stm32/src/hash/mod.rs b/embassy-stm32/src/hash/mod.rs index e62151bb5..a4c275242 100644 --- a/embassy-stm32/src/hash/mod.rs +++ b/embassy-stm32/src/hash/mod.rs @@ -198,6 +198,8 @@ impl<'d, T: Instance, M: Mode> Hash<'d, T, M> { if key.len() > 64 { T::regs().cr().modify(|w| w.set_lkey(true)); } + } else { + T::regs().cr().modify(|w| w.set_mode(false)); } T::regs().cr().modify(|w| w.set_init(true)); diff --git a/tests/stm32/src/bin/hash.rs b/tests/stm32/src/bin/hash.rs index 52b84a499..2499f42ed 100644 --- a/tests/stm32/src/bin/hash.rs +++ b/tests/stm32/src/bin/hash.rs @@ -7,6 +7,7 @@ mod common; use common::*; use embassy_executor::Spawner; use embassy_stm32::hash::*; +use embassy_stm32::mode::Blocking; use embassy_stm32::{bind_interrupts, hash, peripherals}; use hmac::{Hmac, Mac}; use sha2::{Digest, Sha224, Sha256}; @@ -32,11 +33,7 @@ bind_interrupts!(struct Irqs { HASH => hash::InterruptHandler; }); -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p: embassy_stm32::Peripherals = init(); - let mut hw_hasher = Hash::new_blocking(p.HASH, Irqs); - +fn test_interrupt(hw_hasher: &mut Hash<'_, peripherals::HASH, Blocking>) { let test_1: &[u8] = b"as;dfhaslfhas;oifvnasd;nifvnhasd;nifvhndlkfghsd;nvfnahssdfgsdafgsasdfasdfasdfasdfasdfghjklmnbvcalskdjghalskdjgfbaslkdjfgbalskdjgbalskdjbdfhsdfhsfghsfghfgh"; let test_2: &[u8] = b"fdhalksdjfhlasdjkfhalskdjfhgal;skdjfgalskdhfjgalskdjfglafgadfgdfgdafgaadsfgfgdfgadrgsyfthxfgjfhklhjkfgukhulkvhlvhukgfhfsrghzdhxyfufynufyuszeradrtydyytserr"; let test_3: &[u8] = b"a.ewtkluGWEBR.KAJRBTA,RMNRBG,FDMGB.kger.tkasjrbt.akrjtba.krjtba.ktmyna,nmbvtyliasd;gdrtba,sfvs.kgjzshd.gkbsr.tksejb.SDkfBSE.gkfgb>ESkfbSE>gkJSBESE>kbSE>fk"; @@ -95,6 +92,16 @@ async fn main(_spawner: Spawner) { info!("Hardware HMAC: {:?}", hw_hmac); info!("Software HMAC: {:?}", sw_hmac[..]); defmt::assert!(hw_hmac == sw_hmac[..]); +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p: embassy_stm32::Peripherals = init(); + let mut hw_hasher = Hash::new_blocking(p.HASH, Irqs); + + test_interrupt(&mut hw_hasher); + // Run it a second time to check hash-after-hmac + test_interrupt(&mut hw_hasher); info!("Test OK"); cortex_m::asm::bkpt(); -- cgit From 37707a7c7c34100e00d803717bcf11836b708380 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Fri, 15 Aug 2025 08:49:41 +0800 Subject: stm32: Update stm32-metapac For hash algorithm register update. --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/Cargo.toml | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 9ad117312..0f044419e 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - fix: Fix vrefbuf building with log feature - fix: Fix performing a hash after performing a hmac +- chore: Updated stm32-metapac and stm32-data dependencies ## 0.3.0 - 2025-08-12 diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 691ce3b90..45b351acf 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -80,8 +80,8 @@ cortex-m = "0.7.6" futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" -stm32-metapac = { version = "17" } -# stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9941f338734a2e6c1652267f64b13f7b35d8c9db" } +# stm32-metapac = { version = "17" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ecb93d42a6cbcd9e09cab74873908a2ca22327f7" } vcell = "0.1.3" nb = "1.0.0" @@ -109,8 +109,8 @@ proptest-state-machine = "0.3.0" proc-macro2 = "1.0.36" quote = "1.0.15" -stm32-metapac = { version = "17", default-features = false, features = ["metadata"]} -#stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9941f338734a2e6c1652267f64b13f7b35d8c9db", default-features = false, features = ["metadata"] } +# stm32-metapac = { version = "17", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ecb93d42a6cbcd9e09cab74873908a2ca22327f7", default-features = false, features = ["metadata"] } [features] default = ["rt"] -- cgit From d939d901e245c30f924e30a7605e378be0be5cca Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Tue, 12 Aug 2025 17:13:21 +0800 Subject: stm32: Add hash test for sha512, varying lengths sha512 is only supported by hash_v3 and hash_v4, so add a feature for those chips. --- tests/stm32/Cargo.toml | 5 +++-- tests/stm32/src/bin/hash.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 96b49f027..c011a6d7d 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -16,7 +16,7 @@ stm32f446re = ["embassy-stm32/stm32f446re", "spi-v1", "chrono", "stop", "can", " stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng", "single-bank"] stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac", "ucpd"] stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng", "fdcan", "cordic"] -stm32h563zi = ["embassy-stm32/stm32h563zi", "spi-v345", "chrono", "eth", "rng", "fdcan", "hash", "cordic", "stop"] +stm32h563zi = ["embassy-stm32/stm32h563zi", "spi-v345", "chrono", "eth", "rng", "fdcan", "hash-v34", "cordic", "stop"] stm32h753zi = ["embassy-stm32/stm32h753zi", "spi-v345", "chrono", "not-gpdma", "eth", "rng", "fdcan", "hash", "cryp"] stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "spi-v345", "chrono", "not-gpdma", "eth", "dac", "rng", "fdcan", "hash", "cryp"] stm32h7a3zi = ["embassy-stm32/stm32h7a3zi", "spi-v345", "not-gpdma", "rng", "fdcan"] @@ -33,13 +33,14 @@ stm32wba52cg = ["embassy-stm32/stm32wba52cg", "spi-v345", "chrono", "rng", "hash stm32wl55jc = ["embassy-stm32/stm32wl55jc-cm4", "not-gpdma", "rng", "chrono"] stm32f091rc = ["embassy-stm32/stm32f091rc", "cm0", "not-gpdma", "chrono"] stm32h503rb = ["embassy-stm32/stm32h503rb", "spi-v345", "rng", "stop"] -stm32h7s3l8 = ["embassy-stm32/stm32h7s3l8", "spi-v345", "rng", "cordic", "hash"] # TODO: fdcan crashes, cryp dma hangs. +stm32h7s3l8 = ["embassy-stm32/stm32h7s3l8", "spi-v345", "rng", "cordic", "hash-v34"] # TODO: fdcan crashes, cryp dma hangs. stm32u083rc = ["embassy-stm32/stm32u083rc", "cm0", "rng", "chrono"] spi-v1 = [] spi-v345 = [] cryp = [] hash = [] +hash-v34 = ["hash"] eth = [] rng = [] sdmmc = [] diff --git a/tests/stm32/src/bin/hash.rs b/tests/stm32/src/bin/hash.rs index 2499f42ed..bb08d0cf1 100644 --- a/tests/stm32/src/bin/hash.rs +++ b/tests/stm32/src/bin/hash.rs @@ -94,6 +94,34 @@ fn test_interrupt(hw_hasher: &mut Hash<'_, peripherals::HASH, Blocking>) { defmt::assert!(hw_hmac == sw_hmac[..]); } +// This uses sha512, so only supported on hash_v3 and up +#[cfg(feature = "hash-v34")] +fn test_sizes(hw_hasher: &mut Hash<'_, peripherals::HASH, Blocking>) { + let in1 = b"4BPuGudaDK"; + let in2 = b"cfFIGf0XSNhFBQ5LaIqzjnRKDRkoWweJI06HLUcicIUGjpuDNfOTQNSrRxDoveDPlazeZtt06SIYO5CvHvsJ98XSfO9yJEMHoDpDAmNQtwZOPlKmdiagRXsJ7w7IjdKpQH6I2t"; + + for i in 1..10 { + // sha512 block size is 128, so test around there + for j in [1, 1, 2, 3, 4, 5, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133] { + info!("test_sizes i {} j {}", i, j); + let mut sw = sha2::Sha512::new(); + let mut ctx = hw_hasher.start(Algorithm::SHA512, DataType::Width8, None); + + sw.update(&in1[..i]); + sw.update(&in2[..j]); + hw_hasher.update_blocking(&mut ctx, &in1[..i]); + hw_hasher.update_blocking(&mut ctx, &in2[..j]); + + let sw_digest = sw.finalize(); + let mut hw_digest = [0u8; 64]; + hw_hasher.finish_blocking(ctx, &mut hw_digest); + info!("Hardware: {:?}", hw_digest); + info!("Software: {:?}", sw_digest[..]); + defmt::assert!(hw_digest == *sw_digest); + } + } +} + #[embassy_executor::main] async fn main(_spawner: Spawner) { let p: embassy_stm32::Peripherals = init(); @@ -103,6 +131,9 @@ async fn main(_spawner: Spawner) { // Run it a second time to check hash-after-hmac test_interrupt(&mut hw_hasher); + #[cfg(feature = "hash-v34")] + test_sizes(&mut hw_hasher); + info!("Test OK"); cortex_m::asm::bkpt(); } -- cgit From 86e257bc8df5e76c3857644f78650e65447523ad Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Tue, 12 Aug 2025 15:28:52 +0800 Subject: stm32/hash: Improve performance when hashing chunks_exact produces better code --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/src/hash/mod.rs | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 0f044419e..d2dccaea5 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- feat: Improve blocking hash speed - fix: Fix vrefbuf building with log feature - fix: Fix performing a hash after performing a hmac - chore: Updated stm32-metapac and stm32-data dependencies diff --git a/embassy-stm32/src/hash/mod.rs b/embassy-stm32/src/hash/mod.rs index a4c275242..90c06c0d8 100644 --- a/embassy-stm32/src/hash/mod.rs +++ b/embassy-stm32/src/hash/mod.rs @@ -353,13 +353,17 @@ impl<'d, T: Instance, M: Mode> Hash<'d, T, M> { let num_valid_bits: u8 = (8 * (input.len() % 4)) as u8; T::regs().str().modify(|w| w.set_nblw(num_valid_bits)); - let mut i = 0; - while i < input.len() { + let mut chunks = input.chunks_exact(4); + for chunk in &mut chunks { + T::regs() + .din() + .write_value(u32::from_ne_bytes(chunk.try_into().unwrap())); + } + let rem = chunks.remainder(); + if !rem.is_empty() { let mut word: [u8; 4] = [0; 4]; - let copy_idx = min(i + 4, input.len()); - word[0..copy_idx - i].copy_from_slice(&input[i..copy_idx]); + word[0..rem.len()].copy_from_slice(rem); T::regs().din().write_value(u32::from_ne_bytes(word)); - i += 4; } } -- cgit From 011c382b7785485b632d567d941ff670797a0d74 Mon Sep 17 00:00:00 2001 From: 823984418 <823984418@qq.com> Date: Sun, 17 Aug 2025 22:18:04 +0800 Subject: modify async fn to return impl Future --- embassy-time/src/delay.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/embassy-time/src/delay.rs b/embassy-time/src/delay.rs index 67345f726..11b54b098 100644 --- a/embassy-time/src/delay.rs +++ b/embassy-time/src/delay.rs @@ -1,3 +1,5 @@ +use core::future::Future; + use super::{Duration, Instant}; use crate::Timer; @@ -32,16 +34,16 @@ impl embedded_hal_1::delay::DelayNs for Delay { } impl embedded_hal_async::delay::DelayNs for Delay { - async fn delay_ns(&mut self, ns: u32) { - Timer::after_nanos(ns as _).await + fn delay_ns(&mut self, ns: u32) -> impl Future { + Timer::after_nanos(ns as _) } - async fn delay_us(&mut self, us: u32) { - Timer::after_micros(us as _).await + fn delay_us(&mut self, us: u32) -> impl Future { + Timer::after_micros(us as _) } - async fn delay_ms(&mut self, ms: u32) { - Timer::after_millis(ms as _).await + fn delay_ms(&mut self, ms: u32) -> impl Future { + Timer::after_millis(ms as _) } } -- cgit From 1b246d77c9972706285193b7a17ae0f5543e5a34 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Sat, 16 Aug 2025 22:40:04 +0800 Subject: time: implement Sum for Duration --- embassy-time/CHANGELOG.md | 1 + embassy-time/src/duration.rs | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/embassy-time/CHANGELOG.md b/embassy-time/CHANGELOG.md index a0c1abe8d..2e94e0112 100644 --- a/embassy-time/CHANGELOG.md +++ b/embassy-time/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Don't select `critical-section` impl for `std` - Manually implement the future for `with_timeout` - Add 133MHz tick rate to support PR2040 @ 133MHz when `TIMERx`'s `SOURCE` is set to `SYSCLK` +- Implement Sum for Duration ## 0.4.0 - 2025-01-02 diff --git a/embassy-time/src/duration.rs b/embassy-time/src/duration.rs index dcda705d3..5b140eeff 100644 --- a/embassy-time/src/duration.rs +++ b/embassy-time/src/duration.rs @@ -293,3 +293,12 @@ impl From for core::time::Duration { core::time::Duration::from_micros(value.as_micros()) } } + +impl core::iter::Sum for Duration { + fn sum(iter: I) -> Self + where + I: Iterator, + { + Duration::from_ticks(iter.map(|d| d.as_ticks()).sum()) + } +} -- cgit From 74037f04933f4ec9a678e0b47fd6819e7c0489a9 Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Mon, 4 Aug 2025 00:05:25 +0200 Subject: Make TimerQueueItem opaque --- embassy-executor-timer-queue/CHANGELOG.md | 10 ++ embassy-executor-timer-queue/Cargo.toml | 35 +++++++ embassy-executor-timer-queue/README.md | 10 ++ embassy-executor-timer-queue/src/lib.rs | 97 ++++++++++++++++++ embassy-executor/CHANGELOG.md | 5 + embassy-executor/Cargo.toml | 17 +--- embassy-executor/src/raw/mod.rs | 33 +++--- embassy-executor/src/raw/timer_queue.rs | 73 -------------- embassy-time-queue-utils/CHANGELOG.md | 8 ++ embassy-time-queue-utils/Cargo.toml | 2 +- embassy-time-queue-utils/src/lib.rs | 1 - embassy-time-queue-utils/src/queue_integrated.rs | 122 ++++++++++++++++------- 12 files changed, 267 insertions(+), 146 deletions(-) create mode 100644 embassy-executor-timer-queue/CHANGELOG.md create mode 100644 embassy-executor-timer-queue/Cargo.toml create mode 100644 embassy-executor-timer-queue/README.md create mode 100644 embassy-executor-timer-queue/src/lib.rs delete mode 100644 embassy-executor/src/raw/timer_queue.rs diff --git a/embassy-executor-timer-queue/CHANGELOG.md b/embassy-executor-timer-queue/CHANGELOG.md new file mode 100644 index 000000000..d43e0060d --- /dev/null +++ b/embassy-executor-timer-queue/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog for embassy-time-queue-utils + +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). + +## Unreeased + +- Initial implementation diff --git a/embassy-executor-timer-queue/Cargo.toml b/embassy-executor-timer-queue/Cargo.toml new file mode 100644 index 000000000..0db327ba9 --- /dev/null +++ b/embassy-executor-timer-queue/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "embassy-executor-timer-queue" +version = "0.1.0" +edition = "2021" +description = "Timer queue item and interface between embassy-executor and timer queues" +repository = "https://github.com/embassy-rs/embassy" +documentation = "https://docs.embassy.dev/embassy-executor-timer-queue" +readme = "README.md" +license = "MIT OR Apache-2.0" +categories = [ + "embedded", + "no-std", + "concurrency", + "asynchronous", +] + +[dependencies] + +[features] +#! ### Timer Queue Item Size +#! Sets the size of the timer items. + +## 4 words +timer-item-size-4-words = [] + +## 6 words +timer-item-size-6-words = [] + +## 8 words +timer-item-size-8-words = [] + +[package.metadata.embassy_docs] +src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-timer-queue-v$VERSION/embassy-executor-timer-queue/src/" +src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor-timer-queue/src/" +target = "x86_64-unknown-linux-gnu" diff --git a/embassy-executor-timer-queue/README.md b/embassy-executor-timer-queue/README.md new file mode 100644 index 000000000..602aca7b1 --- /dev/null +++ b/embassy-executor-timer-queue/README.md @@ -0,0 +1,10 @@ +# embassy-executor-time-queue + +This crate defines the timer queue item that embassy-executor provides, and a way to access it, for +executor-integrated timer queues. The crate decouples the release cycle of embassy-executor from +that of the queue implementations'. + +As a HAL implementer, you only need to depend on this crate if you want to implement executor-integrated +timer queues yourself, without using [`embassy-time-queue-utils`](https://crates.io/crates/embassy-time-queue-utils). + +As a HAL user, you should not need to depend on this crate. diff --git a/embassy-executor-timer-queue/src/lib.rs b/embassy-executor-timer-queue/src/lib.rs new file mode 100644 index 000000000..456ccaec3 --- /dev/null +++ b/embassy-executor-timer-queue/src/lib.rs @@ -0,0 +1,97 @@ +//! Timer queue item for embassy-executor integrated timer queues +//! +//! `embassy-executor` provides the memory needed to implement integrated timer queues. This crate +//! exists to separate that memory from `embassy-executor` itself, to decouple the timer queue's +//! release cycle from `embassy-executor`. +//! +//! This crate contains two things: +//! - [`TimerQueueItem`]: The item type that can be requested from the executor. The size of this +//! type can be configured using the `timer-item-size-N-words` Cargo features. +//! - The expectation that `extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &mut TimerQueueItem` +//! is implemented (by `embassy-executor`, most likely). This function must return a mutable +//! reference to the `TimerQueueItem` associated with the given waker. +//! +//! As a queue implementor, you will need to choose one of the `timer-item-size-N-words` features to +//! select a queue item size. You can then define your own item type, which must be +//! `#[repr(align(8))]` (or less) and must fit into the size you selected. +//! +//! You can access the `TimerQueueItem` from a `Waker` using the [`from_embassy_waker`](TimerQueueItem::from_embassy_waker) +//! method. You can then use the [`as_ref`](TimerQueueItem::as_ref) and [`as_mut`](TimerQueueItem::as_mut) +//! methods to reinterpret the data stored in the item as your custom item type. +#![no_std] + +use core::task::Waker; + +const ITEM_SIZE: usize = if cfg!(feature = "timer-item-size-8-words") { + 8 +} else if cfg!(feature = "timer-item-size-6-words") { + 6 +} else if cfg!(feature = "timer-item-size-4-words") { + 4 +} else { + 0 +}; + +/// The timer queue item provided by the executor. +/// +/// This type is opaque, it only provides the raw storage for a queue item. The queue implementation +/// is responsible for reinterpreting the contents of the item using [`TimerQueueItem::as_ref`] and +/// [`TimerQueueItem::as_mut`]. +#[repr(align(8))] +pub struct TimerQueueItem { + data: [usize; ITEM_SIZE], +} + +impl TimerQueueItem { + /// Creates a new, zero-initialized `TimerQueueItem`. + pub const fn new() -> Self { + Self { data: [0; ITEM_SIZE] } + } + + /// Retrieves the `TimerQueueItem` reference that belongs to the task of the waker. + /// + /// Panics if called with a non-embassy waker. + /// + /// # Safety + /// + /// The caller must ensure they are not violating Rust's aliasing rules - it is not allowed + /// to use this method to create multiple mutable references to the same `TimerQueueItem` at + /// the same time. + /// + /// This function must only be called in the context of a timer queue implementation. + pub unsafe fn from_embassy_waker(waker: &Waker) -> &'static mut Self { + unsafe extern "Rust" { + // Waker -> TimerQueueItem, validates that Waker is an embassy Waker. + fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static mut TimerQueueItem; + } + unsafe { __embassy_time_queue_item_from_waker(waker) } + } + + /// Access the data as a reference to a type `T`. + /// + /// Safety: + /// + /// - The type must be valid when zero-initialized. + /// - The timer queue should only be interpreted as a single type `T` during its lifetime. + pub unsafe fn as_ref(&self) -> &T { + const { + assert!(core::mem::size_of::() >= core::mem::size_of::()); + assert!(core::mem::align_of::() >= core::mem::align_of::()); + } + unsafe { &*(self.data.as_ptr() as *const T) } + } + + /// Access the data as a reference to a type `T`. + /// + /// Safety: + /// + /// - The type must be valid when zero-initialized. + /// - The timer queue should only be interpreted as a single type `T` during its lifetime. + pub unsafe fn as_mut(&self) -> &mut T { + const { + assert!(core::mem::size_of::() >= core::mem::size_of::()); + assert!(core::mem::align_of::() >= core::mem::align_of::()); + } + unsafe { &mut *(self.data.as_ptr() as *mut T) } + } +} diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index c35ad10f3..e2214b8ef 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- Added `extern "Rust" fn __embassy_time_queue_item_from_waker` +- Removed `TaskRef::dangling` and `TaskRef::timer_queue_item` +- Added `embassy_time_queue_utils` as a dependency +- Moved the `TimeQueueItem` struct and `timer-item-payload-size-*` features into embassy-time-queue-utils + ## 0.8.0 - 2025-07-31 - Added `SpawnToken::id` diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 5e950bf45..bff13de56 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -35,6 +35,7 @@ rtos-trace = { version = "0.1.3", optional = true } embassy-executor-macros = { version = "0.7.0", path = "../embassy-executor-macros" } embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } +embassy-executor-timer-queue = { version = "0.1", path = "../embassy-executor-timer-queue" } critical-section = "1.1" document-features = "0.2.7" @@ -98,19 +99,3 @@ executor-interrupt = [] trace = [] ## Enable support for rtos-trace framework rtos-trace = ["dep:rtos-trace", "trace", "dep:embassy-time-driver"] - -#! ### Timer Item Payload Size -#! Sets the size of the payload for timer items, allowing integrated timer implementors to store -#! additional data in the timer item. The payload field will be aligned to this value as well. -#! If these features are not defined, the timer item will contain no payload field. - -_timer-item-payload = [] # A size was picked - -## 1 bytes -timer-item-payload-size-1 = ["_timer-item-payload"] -## 2 bytes -timer-item-payload-size-2 = ["_timer-item-payload"] -## 4 bytes -timer-item-payload-size-4 = ["_timer-item-payload"] -## 8 bytes -timer-item-payload-size-8 = ["_timer-item-payload"] diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index c8f1f46c2..8e783b2af 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -16,7 +16,6 @@ mod run_queue; #[cfg_attr(not(target_has_atomic = "8"), path = "state_critical_section.rs")] mod state; -pub mod timer_queue; #[cfg(feature = "trace")] pub mod trace; pub(crate) mod util; @@ -31,8 +30,9 @@ use core::ptr::NonNull; #[cfg(not(feature = "arch-avr"))] use core::sync::atomic::AtomicPtr; use core::sync::atomic::Ordering; -use core::task::{Context, Poll}; +use core::task::{Context, Poll, Waker}; +use embassy_executor_timer_queue::TimerQueueItem; #[cfg(feature = "arch-avr")] use portable_atomic::AtomicPtr; @@ -42,6 +42,11 @@ use self::util::{SyncUnsafeCell, UninitCell}; pub use self::waker::task_from_waker; use super::SpawnToken; +#[no_mangle] +extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static mut TimerQueueItem { + unsafe { task_from_waker(waker).timer_queue_item() } +} + /// Raw task header for use in task pointers. /// /// A task can be in one of the following states: @@ -88,7 +93,7 @@ pub(crate) struct TaskHeader { poll_fn: SyncUnsafeCell>, /// Integrated timer queue storage. This field should not be accessed outside of the timer queue. - pub(crate) timer_queue_item: timer_queue::TimerQueueItem, + pub(crate) timer_queue_item: TimerQueueItem, #[cfg(feature = "trace")] pub(crate) name: Option<&'static str>, #[cfg(feature = "trace")] @@ -120,16 +125,6 @@ impl TaskRef { } } - /// # Safety - /// - /// The result of this function must only be compared - /// for equality, or stored, but not used. - pub const unsafe fn dangling() -> Self { - Self { - ptr: NonNull::dangling(), - } - } - pub(crate) fn header(self) -> &'static TaskHeader { unsafe { self.ptr.as_ref() } } @@ -140,9 +135,13 @@ impl TaskRef { executor.as_ref().map(|e| Executor::wrap(e)) } - /// Returns a reference to the timer queue item. - pub fn timer_queue_item(&self) -> &'static timer_queue::TimerQueueItem { - &self.header().timer_queue_item + /// Returns a mutable reference to the timer queue item. + /// + /// Safety + /// + /// This function must only be called in the context of the integrated timer queue. + unsafe fn timer_queue_item(mut self) -> &'static mut TimerQueueItem { + unsafe { &mut self.ptr.as_mut().timer_queue_item } } /// The returned pointer is valid for the entire TaskStorage. @@ -189,7 +188,7 @@ impl TaskStorage { // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss` poll_fn: SyncUnsafeCell::new(None), - timer_queue_item: timer_queue::TimerQueueItem::new(), + timer_queue_item: TimerQueueItem::new(), #[cfg(feature = "trace")] name: None, #[cfg(feature = "trace")] diff --git a/embassy-executor/src/raw/timer_queue.rs b/embassy-executor/src/raw/timer_queue.rs deleted file mode 100644 index e52453be4..000000000 --- a/embassy-executor/src/raw/timer_queue.rs +++ /dev/null @@ -1,73 +0,0 @@ -//! Timer queue operations. - -use core::cell::Cell; - -use super::TaskRef; - -#[cfg(feature = "_timer-item-payload")] -macro_rules! define_opaque { - ($size:tt) => { - /// An opaque data type. - #[repr(align($size))] - pub struct OpaqueData { - data: [u8; $size], - } - - impl OpaqueData { - const fn new() -> Self { - Self { data: [0; $size] } - } - - /// Access the data as a reference to a type `T`. - /// - /// Safety: - /// - /// The caller must ensure that the size of the type `T` is less than, or equal to - /// the size of the payload, and must ensure that the alignment of the type `T` is - /// less than, or equal to the alignment of the payload. - /// - /// The type must be valid when zero-initialized. - pub unsafe fn as_ref(&self) -> &T { - &*(self.data.as_ptr() as *const T) - } - } - }; -} - -#[cfg(feature = "timer-item-payload-size-1")] -define_opaque!(1); -#[cfg(feature = "timer-item-payload-size-2")] -define_opaque!(2); -#[cfg(feature = "timer-item-payload-size-4")] -define_opaque!(4); -#[cfg(feature = "timer-item-payload-size-8")] -define_opaque!(8); - -/// An item in the timer queue. -pub struct TimerQueueItem { - /// The next item in the queue. - /// - /// If this field contains `Some`, the item is in the queue. The last item in the queue has a - /// value of `Some(dangling_pointer)` - pub next: Cell>, - - /// The time at which this item expires. - pub expires_at: Cell, - - /// Some implementation-defined, zero-initialized piece of data. - #[cfg(feature = "_timer-item-payload")] - pub payload: OpaqueData, -} - -unsafe impl Sync for TimerQueueItem {} - -impl TimerQueueItem { - pub(crate) const fn new() -> Self { - Self { - next: Cell::new(None), - expires_at: Cell::new(0), - #[cfg(feature = "_timer-item-payload")] - payload: OpaqueData::new(), - } - } -} diff --git a/embassy-time-queue-utils/CHANGELOG.md b/embassy-time-queue-utils/CHANGELOG.md index ae4714f62..ebd6565d1 100644 --- a/embassy-time-queue-utils/CHANGELOG.md +++ b/embassy-time-queue-utils/CHANGELOG.md @@ -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). +## Unreleased + +- Removed the embassy-executor dependency + +## 0.2.0 - 2025-08-04 + +Bumpep embassy-executor + ## 0.1.0 - 2024-01-11 Initial release diff --git a/embassy-time-queue-utils/Cargo.toml b/embassy-time-queue-utils/Cargo.toml index 93fa0ce3c..8991da66c 100644 --- a/embassy-time-queue-utils/Cargo.toml +++ b/embassy-time-queue-utils/Cargo.toml @@ -22,7 +22,7 @@ links = "embassy-time-queue" [dependencies] heapless = "0.8" -embassy-executor = { version = "0.8", path = "../embassy-executor" } +embassy-executor-timer-queue = { version = "0.1", path = "../embassy-executor-timer-queue", features = ["timer-item-size-6-words"] } [features] #! ### Generic Queue diff --git a/embassy-time-queue-utils/src/lib.rs b/embassy-time-queue-utils/src/lib.rs index 08e186432..a6f66913f 100644 --- a/embassy-time-queue-utils/src/lib.rs +++ b/embassy-time-queue-utils/src/lib.rs @@ -1,7 +1,6 @@ #![no_std] #![doc = include_str!("../README.md")] #![warn(missing_docs)] -#![deny(missing_debug_implementations)] #[cfg(feature = "_generic-queue")] pub mod queue_generic; diff --git a/embassy-time-queue-utils/src/queue_integrated.rs b/embassy-time-queue-utils/src/queue_integrated.rs index 748cd7843..2731d1ac6 100644 --- a/embassy-time-queue-utils/src/queue_integrated.rs +++ b/embassy-time-queue-utils/src/queue_integrated.rs @@ -1,16 +1,50 @@ //! Timer queue operations. use core::cell::Cell; use core::cmp::min; +use core::ptr::NonNull; use core::task::Waker; -use embassy_executor::raw::TaskRef; +use embassy_executor_timer_queue::TimerQueueItem; + +/// An item in the timer queue. +#[derive(Default)] +struct QueueItem { + /// The next item in the queue. + /// + /// If this field contains `Some`, the item is in the queue. The last item in the queue has a + /// value of `Some(dangling_pointer)` + pub next: Cell>>, + + /// The time at which this item expires. + pub expires_at: u64, + + /// The registered waker. If Some, the item is enqueued in the timer queue. + pub waker: Option, +} + +unsafe impl Sync for QueueItem {} /// A timer queue, with items integrated into tasks. -#[derive(Debug)] +/// +/// # Safety +/// +/// **This Queue is only safe when there is a single integrated queue in the system.** +/// +/// If there are multiple integrated queues, additional checks are necessary to ensure that a Waker +/// is not attempted to be enqueued in multiple queues. pub struct Queue { - head: Cell>, + head: Cell>>, } +impl core::fmt::Debug for Queue { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Queue").finish() + } +} + +unsafe impl Send for Queue {} +unsafe impl Sync for Queue {} + impl Queue { /// Creates a new timer queue. pub const fn new() -> Self { @@ -22,25 +56,41 @@ impl Queue { /// If this function returns `true`, the called should find the next expiration time and set /// a new alarm for that time. pub fn schedule_wake(&mut self, at: u64, waker: &Waker) -> bool { - let task = embassy_executor::raw::task_from_waker(waker); - let item = task.timer_queue_item(); - if item.next.get().is_none() { - // If not in the queue, add it and update. - let prev = self.head.replace(Some(task)); - item.next.set(if prev.is_none() { - Some(unsafe { TaskRef::dangling() }) - } else { - prev - }); - item.expires_at.set(at); - true - } else if at <= item.expires_at.get() { - // If expiration is sooner than previously set, update. - item.expires_at.set(at); - true - } else { - // Task does not need to be updated. - false + let item = unsafe { + // Safety: the `&mut self`, along with the Safety note of the Queue, are sufficient to + // ensure that this function creates the only mutable reference to the queue item. + TimerQueueItem::from_embassy_waker(waker) + }; + let item = unsafe { item.as_mut::() }; + match item.waker.as_ref() { + Some(_) if at <= item.expires_at => { + // If expiration is sooner than previously set, update. + item.expires_at = at; + // The waker is always stored in its own queue item, so we don't need to update it. + + // Trigger a queue update in case this item can be immediately dequeued. + true + } + Some(_) => { + // Queue item does not need to be updated, the task will be scheduled to be woken + // before the new expiration. + false + } + None => { + // If not in the queue, add it and update. + let mut item_ptr = NonNull::from(item); + let prev = self.head.replace(Some(item_ptr)); + + let item = unsafe { item_ptr.as_mut() }; + + item.expires_at = at; + item.waker = Some(waker.clone()); + item.next.set(prev); + // The default implementation doesn't care about the + // opaque payload, leave it unchanged. + + true + } } } @@ -51,33 +101,29 @@ impl Queue { pub fn next_expiration(&mut self, now: u64) -> u64 { let mut next_expiration = u64::MAX; - self.retain(|p| { - let item = p.timer_queue_item(); - let expires = item.expires_at.get(); - - if expires <= now { + self.retain(|item| { + if item.expires_at <= now { // Timer expired, process task. - embassy_executor::raw::wake_task(p); + if let Some(waker) = item.waker.take() { + waker.wake(); + } false } else { // Timer didn't yet expire, or never expires. - next_expiration = min(next_expiration, expires); - expires != u64::MAX + next_expiration = min(next_expiration, item.expires_at); + item.expires_at != u64::MAX } }); next_expiration } - fn retain(&self, mut f: impl FnMut(TaskRef) -> bool) { + fn retain(&mut self, mut f: impl FnMut(&mut QueueItem) -> bool) { let mut prev = &self.head; - while let Some(p) = prev.get() { - if unsafe { p == TaskRef::dangling() } { - // prev was the last item, stop - break; - } - let item = p.timer_queue_item(); - if f(p) { + while let Some(mut p) = prev.get() { + let mut item = unsafe { p.as_mut() }; + + if f(&mut item) { // Skip to next prev = &item.next; } else { -- cgit From 31967e1f901454014d0c452dd0328f98a80c8a9c Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Sat, 16 Aug 2025 11:50:14 +0200 Subject: Print more informative panic messages --- embassy-executor-timer-queue/src/lib.rs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/embassy-executor-timer-queue/src/lib.rs b/embassy-executor-timer-queue/src/lib.rs index 456ccaec3..de94e3faf 100644 --- a/embassy-executor-timer-queue/src/lib.rs +++ b/embassy-executor-timer-queue/src/lib.rs @@ -22,7 +22,7 @@ use core::task::Waker; -const ITEM_SIZE: usize = if cfg!(feature = "timer-item-size-8-words") { +const ITEM_WORDS: usize = if cfg!(feature = "timer-item-size-8-words") { 8 } else if cfg!(feature = "timer-item-size-6-words") { 6 @@ -39,13 +39,13 @@ const ITEM_SIZE: usize = if cfg!(feature = "timer-item-size-8-words") { /// [`TimerQueueItem::as_mut`]. #[repr(align(8))] pub struct TimerQueueItem { - data: [usize; ITEM_SIZE], + data: [usize; ITEM_WORDS], } impl TimerQueueItem { /// Creates a new, zero-initialized `TimerQueueItem`. pub const fn new() -> Self { - Self { data: [0; ITEM_SIZE] } + Self { data: [0; ITEM_WORDS] } } /// Retrieves the `TimerQueueItem` reference that belongs to the task of the waker. @@ -74,10 +74,7 @@ impl TimerQueueItem { /// - The type must be valid when zero-initialized. /// - The timer queue should only be interpreted as a single type `T` during its lifetime. pub unsafe fn as_ref(&self) -> &T { - const { - assert!(core::mem::size_of::() >= core::mem::size_of::()); - assert!(core::mem::align_of::() >= core::mem::align_of::()); - } + const { validate::() } unsafe { &*(self.data.as_ptr() as *const T) } } @@ -88,10 +85,20 @@ impl TimerQueueItem { /// - The type must be valid when zero-initialized. /// - The timer queue should only be interpreted as a single type `T` during its lifetime. pub unsafe fn as_mut(&self) -> &mut T { - const { - assert!(core::mem::size_of::() >= core::mem::size_of::()); - assert!(core::mem::align_of::() >= core::mem::align_of::()); - } + const { validate::() } unsafe { &mut *(self.data.as_ptr() as *mut T) } } } + +const fn validate() { + const { + assert!( + core::mem::size_of::() >= core::mem::size_of::(), + "embassy-executor-timer-queue item size is smaller than the requested type. Select a larger timer-item-size-N-words feature." + ); + assert!( + core::mem::align_of::() >= core::mem::align_of::(), + "the alignment of the requested type is greater than 8" + ); + } +} -- cgit From b96f44cfd41175dda9789bb27bf18c12340e225a Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Sat, 16 Aug 2025 12:11:38 +0200 Subject: Add changelog check --- .github/workflows/changelog.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 94e8f353a..13e04d954 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -45,6 +45,8 @@ jobs: - 'embassy-executor/**' embassy-executor-macros: - 'embassy-executor-macros/**' + embassy-executor-timer-queue: + - 'embassy-executor-timer-queue/**' embassy-futures: - 'embassy-futures/**' embassy-imxrt: @@ -162,6 +164,13 @@ jobs: changeLogPath: embassy-executor-macros/CHANGELOG.md skipLabels: "skip-changelog" missingUpdateErrorMessage: "Please add a changelog entry in the embassy-executor-macros/CHANGELOG.md file." + - name: Check that changelog updated (embassy-executor-timer-queue) + if: steps.changes.outputs.embassy-executor-timer-queue == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: embassy-executor-timer-queue/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-executor-timer-queue/CHANGELOG.md file." - name: Check that changelog updated (embassy-futures) if: steps.changes.outputs.embassy-futures == 'true' uses: dangoslen/changelog-enforcer@v3 -- cgit From 1bf3a44e5d9a6709eb0ce1dc518de82a64a72a05 Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Sun, 17 Aug 2025 11:45:53 +0200 Subject: Retain timer_queue_item --- embassy-executor/CHANGELOG.md | 2 +- embassy-executor/src/raw/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index e2214b8ef..91a1448c2 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate - Added `extern "Rust" fn __embassy_time_queue_item_from_waker` -- Removed `TaskRef::dangling` and `TaskRef::timer_queue_item` +- Removed `TaskRef::dangling` - Added `embassy_time_queue_utils` as a dependency - Moved the `TimeQueueItem` struct and `timer-item-payload-size-*` features into embassy-time-queue-utils diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 8e783b2af..4b17d4982 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -140,7 +140,7 @@ impl TaskRef { /// Safety /// /// This function must only be called in the context of the integrated timer queue. - unsafe fn timer_queue_item(mut self) -> &'static mut TimerQueueItem { + pub unsafe fn timer_queue_item(mut self) -> &'static mut TimerQueueItem { unsafe { &mut self.ptr.as_mut().timer_queue_item } } -- cgit From 3d1ce0fb7daadf647298230b51a7fb8fbaa1feed Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Mon, 18 Aug 2025 12:51:27 +0200 Subject: Fix typo --- embassy-time-queue-utils/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-time-queue-utils/CHANGELOG.md b/embassy-time-queue-utils/CHANGELOG.md index ebd6565d1..26200503c 100644 --- a/embassy-time-queue-utils/CHANGELOG.md +++ b/embassy-time-queue-utils/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 0.2.0 - 2025-08-04 -Bumpep embassy-executor +Bumped embassy-executor ## 0.1.0 - 2024-01-11 -- cgit From bbc3e49c585a2bf58091add9aeac3628d9044297 Mon Sep 17 00:00:00 2001 From: erwin Date: Mon, 18 Aug 2025 12:16:30 +0200 Subject: Add configurable internal pullups for rp i2c - Example updated to demonstrate enabling internal pullups - Add `sda_pullup` and `scl_pullup` fields to I2C Config --- embassy-rp/src/i2c.rs | 26 +++++++++++++++++++------- embassy-rp/src/i2c_slave.rs | 16 ++++++++++++++-- examples/rp/src/bin/i2c_blocking.rs | 6 +++++- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index 172193a07..089c2d080 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -64,14 +64,26 @@ pub enum ConfigError { pub struct Config { /// Frequency. pub frequency: u32, + /// Enable internal pullup on SDA. + /// + /// Using external pullup resistors is recommended for I2C. If you do + /// have external pullups you should not enable this. + pub sda_pullup: bool, + /// Enable internal pullup on SCL. + /// + /// Using external pullup resistors is recommended for I2C. If you do + /// have external pullups you should not enable this. + pub scl_pullup: bool, } - impl Default for Config { fn default() -> Self { - Self { frequency: 100_000 } + Self { + frequency: 100_000, + sda_pullup: false, + scl_pullup: false, + } } } - /// Size of I2C FIFO. pub const FIFO_SIZE: u8 = 16; @@ -359,7 +371,7 @@ impl interrupt::typelevel::Handler for InterruptHandl } } -pub(crate) fn set_up_i2c_pin(pin: &P) +pub(crate) fn set_up_i2c_pin(pin: &P, pullup: bool) where P: core::ops::Deref, T: crate::gpio::Pin, @@ -372,7 +384,7 @@ where w.set_slewfast(false); w.set_ie(true); w.set_od(false); - w.set_pue(true); + w.set_pue(pullup); w.set_pde(false); }); } @@ -384,8 +396,8 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { crate::reset::unreset_wait(reset); // Configure SCL & SDA pins - set_up_i2c_pin(&scl); - set_up_i2c_pin(&sda); + set_up_i2c_pin(&scl, config.scl_pullup); + set_up_i2c_pin(&sda, config.sda_pullup); let mut me = Self { phantom: PhantomData }; diff --git a/embassy-rp/src/i2c_slave.rs b/embassy-rp/src/i2c_slave.rs index 7bc14511d..bfee0c45b 100644 --- a/embassy-rp/src/i2c_slave.rs +++ b/embassy-rp/src/i2c_slave.rs @@ -65,6 +65,16 @@ pub struct Config { pub addr: u16, /// Control if the peripheral should ack to and report general calls. pub general_call: bool, + /// Enable internal pullup on SDA. + /// + /// Using external pullup resistors is recommended for I2C. If you do + /// have external pullups you should not enable this. + pub sda_pullup: bool, + /// Enable internal pullup on SCL. + /// + /// Using external pullup resistors is recommended for I2C. If you do + /// have external pullups you should not enable this. + pub scl_pullup: bool, } impl Default for Config { @@ -72,6 +82,8 @@ impl Default for Config { Self { addr: 0x55, general_call: true, + sda_pullup: false, + scl_pullup: false, } } } @@ -95,8 +107,8 @@ impl<'d, T: Instance> I2cSlave<'d, T> { assert!(config.addr != 0); // Configure SCL & SDA pins - set_up_i2c_pin(&scl); - set_up_i2c_pin(&sda); + set_up_i2c_pin(&scl, config.scl_pullup); + set_up_i2c_pin(&sda, config.sda_pullup); let mut ret = Self { phantom: PhantomData, diff --git a/examples/rp/src/bin/i2c_blocking.rs b/examples/rp/src/bin/i2c_blocking.rs index c9c8a2760..6a57ded20 100644 --- a/examples/rp/src/bin/i2c_blocking.rs +++ b/examples/rp/src/bin/i2c_blocking.rs @@ -49,7 +49,11 @@ async fn main(_spawner: Spawner) { let scl = p.PIN_15; info!("set up i2c "); - let mut i2c = i2c::I2c::new_blocking(p.I2C1, scl, sda, Config::default()); + let mut config = Config::default(); + // by default internal pullup resitors are disabled + config.sda_pullup = true; + config.scl_pullup = true; + let mut i2c = i2c::I2c::new_blocking(p.I2C1, scl, sda, config); use mcp23017::*; -- cgit From e2794a270679bae2b070b034b286aa20cbab263a Mon Sep 17 00:00:00 2001 From: erwin Date: Mon, 18 Aug 2025 14:47:46 +0200 Subject: add entry to the changelog --- embassy-rp/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md index c5bc55941..5482f277f 100644 --- a/embassy-rp/CHANGELOG.md +++ b/embassy-rp/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- add `i2c` internal pullup options ([#4564](https://github.com/embassy-rs/embassy/pull/4564)) ## 0.7.0 - 2025-08-04 -- cgit From badcdcc24c223954b3fd828ecd925e225e850d29 Mon Sep 17 00:00:00 2001 From: erwin Date: Tue, 19 Aug 2025 12:14:48 +0200 Subject: change default internal pullup state to be active to make this change nonbreaking --- embassy-rp/src/i2c.rs | 4 ++-- embassy-rp/src/i2c_slave.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index 089c2d080..ffbef63be 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -79,8 +79,8 @@ impl Default for Config { fn default() -> Self { Self { frequency: 100_000, - sda_pullup: false, - scl_pullup: false, + sda_pullup: true, + scl_pullup: true, } } } diff --git a/embassy-rp/src/i2c_slave.rs b/embassy-rp/src/i2c_slave.rs index bfee0c45b..c263047ad 100644 --- a/embassy-rp/src/i2c_slave.rs +++ b/embassy-rp/src/i2c_slave.rs @@ -82,8 +82,8 @@ impl Default for Config { Self { addr: 0x55, general_call: true, - sda_pullup: false, - scl_pullup: false, + sda_pullup: true, + scl_pullup: true, } } } -- cgit From 0d8350f326361a0f7c5aa2d71f48cbec7c39287a Mon Sep 17 00:00:00 2001 From: René van Dorst Date: Tue, 19 Aug 2025 16:37:24 +0200 Subject: stm32/i2c: Pull-down enabled when non-pull was requested. When no internal pull-up is needed, the pull-down was enabled instead of pull-none. With the pull-down resistors and external pull-up resistors, this creates a voltage divider, which causes unwanted situation. --- embassy-stm32/src/i2c/config.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/i2c/config.rs b/embassy-stm32/src/i2c/config.rs index b27bb778c..4e3b736c7 100644 --- a/embassy-stm32/src/i2c/config.rs +++ b/embassy-stm32/src/i2c/config.rs @@ -156,7 +156,7 @@ impl Config { self.gpio_speed, match self.scl_pullup { true => Pull::Up, - false => Pull::Down, + false => Pull::None, }, ); } @@ -170,7 +170,7 @@ impl Config { self.gpio_speed, match self.sda_pullup { true => Pull::Up, - false => Pull::Down, + false => Pull::None, }, ); } -- cgit From 8aac4aa9d3fc7ee8a4825dd723f36bb1c6020a82 Mon Sep 17 00:00:00 2001 From: René van Dorst Date: Tue, 19 Aug 2025 16:56:45 +0200 Subject: added changelog entry --- embassy-stm32/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 0c2d23246..26b643aa0 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate - fix: Fix vrefbuf building with log feature +- fix: stm32/i2c: pull-down was enabled instead of pull-none when no internal pull-up was needed. ## 0.3.0 - 2025-08-12 -- cgit From 9c72c684d1446d36598c9ce628df41996420fb32 Mon Sep 17 00:00:00 2001 From: Rob Wells Date: Tue, 19 Aug 2025 19:02:20 +0100 Subject: rp: fix blocking I2C example regarding pull-up resistors This amends the blocking I2C example for embassy-rp. Commit bbc3e49 added a pull-up configuration and a comment that pull-ups were not enabled by default. This was made out-of-date by badcdcc, which ensured pull-ups were enabled by default to make the larger I2C configuration change non-breaking. This commit removes the (now-unnecessary) pull-up configuration, and adds a comment to clarify that the default I2C configuration enables pull-ups. --- examples/rp/src/bin/i2c_blocking.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/rp/src/bin/i2c_blocking.rs b/examples/rp/src/bin/i2c_blocking.rs index 6a57ded20..317921374 100644 --- a/examples/rp/src/bin/i2c_blocking.rs +++ b/examples/rp/src/bin/i2c_blocking.rs @@ -49,10 +49,8 @@ async fn main(_spawner: Spawner) { let scl = p.PIN_15; info!("set up i2c "); - let mut config = Config::default(); - // by default internal pullup resitors are disabled - config.sda_pullup = true; - config.scl_pullup = true; + // Default I2C config enables internal pull-up resistors. + let config = Config::default(); let mut i2c = i2c::I2c::new_blocking(p.I2C1, scl, sda, config); use mcp23017::*; -- cgit From 368738bef44dbba1a178383d878a6d9423b1ccd9 Mon Sep 17 00:00:00 2001 From: Curly Date: Tue, 19 Aug 2025 22:30:53 -0700 Subject: chore: add more `Debug` impls to `embassy-sync`, particularly on `OnceLock` All tests green --- embassy-sync/CHANGELOG.md | 1 + embassy-sync/src/blocking_mutex/mod.rs | 1 + embassy-sync/src/blocking_mutex/raw.rs | 2 ++ embassy-sync/src/channel.rs | 7 +++++++ embassy-sync/src/lazy_lock.rs | 2 ++ embassy-sync/src/mutex.rs | 1 + embassy-sync/src/once_lock.rs | 10 ++++++++++ embassy-sync/src/pipe.rs | 8 ++++++++ embassy-sync/src/pubsub/mod.rs | 2 ++ embassy-sync/src/pubsub/publisher.rs | 6 ++++++ embassy-sync/src/pubsub/subscriber.rs | 3 +++ embassy-sync/src/ring_buffer.rs | 1 + embassy-sync/src/rwlock.rs | 1 + embassy-sync/src/semaphore.rs | 6 ++++++ embassy-sync/src/signal.rs | 1 + embassy-sync/src/waitqueue/atomic_waker_turbo.rs | 1 + embassy-sync/src/waitqueue/multi_waker.rs | 1 + embassy-sync/src/watch.rs | 6 ++++++ embassy-sync/src/zerocopy_channel.rs | 5 +++++ 19 files changed, 65 insertions(+) diff --git a/embassy-sync/CHANGELOG.md b/embassy-sync/CHANGELOG.md index c445e9ba1..fa0340c68 100644 --- a/embassy-sync/CHANGELOG.md +++ b/embassy-sync/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - Add `get_mut` to `LazyLock` +- Add more `Debug` impls to `embassy-sync`, particularly on `OnceLock` ## 0.7.0 - 2025-05-28 diff --git a/embassy-sync/src/blocking_mutex/mod.rs b/embassy-sync/src/blocking_mutex/mod.rs index a41bc3569..11809c763 100644 --- a/embassy-sync/src/blocking_mutex/mod.rs +++ b/embassy-sync/src/blocking_mutex/mod.rs @@ -22,6 +22,7 @@ use self::raw::RawMutex; /// /// In all cases, the blocking mutex is intended to be short lived and not held across await points. /// Use the async [`Mutex`](crate::mutex::Mutex) if you need a lock that is held across await points. +#[derive(Debug)] pub struct Mutex { // NOTE: `raw` must be FIRST, so when using ThreadModeMutex the "can't drop in non-thread-mode" gets // to run BEFORE dropping `data`. diff --git a/embassy-sync/src/blocking_mutex/raw.rs b/embassy-sync/src/blocking_mutex/raw.rs index a8afcad34..50f965e00 100644 --- a/embassy-sync/src/blocking_mutex/raw.rs +++ b/embassy-sync/src/blocking_mutex/raw.rs @@ -37,6 +37,7 @@ pub unsafe trait RawMutex { /// # Safety /// /// This mutex is safe to share between different executors and interrupts. +#[derive(Debug)] pub struct CriticalSectionRawMutex { _phantom: PhantomData<()>, } @@ -65,6 +66,7 @@ unsafe impl RawMutex for CriticalSectionRawMutex { /// # Safety /// /// **This Mutex is only safe within a single executor.** +#[derive(Debug)] pub struct NoopRawMutex { _phantom: PhantomData<*mut ()>, } diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs index 8e9fcc234..de437cc52 100644 --- a/embassy-sync/src/channel.rs +++ b/embassy-sync/src/channel.rs @@ -55,6 +55,7 @@ use crate::blocking_mutex::Mutex; use crate::waitqueue::WakerRegistration; /// Send-only access to a [`Channel`]. +#[derive(Debug)] pub struct Sender<'ch, M, T, const N: usize> where M: RawMutex, @@ -241,6 +242,7 @@ impl<'ch, T> SendDynamicSender<'ch, T> { } /// Receive-only access to a [`Channel`]. +#[derive(Debug)] pub struct Receiver<'ch, M, T, const N: usize> where M: RawMutex, @@ -486,6 +488,7 @@ where /// Future returned by [`Channel::receive`] and [`Receiver::receive`]. #[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] pub struct ReceiveFuture<'ch, M, T, const N: usize> where M: RawMutex, @@ -506,6 +509,7 @@ where /// Future returned by [`Channel::ready_to_receive`] and [`Receiver::ready_to_receive`]. #[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] pub struct ReceiveReadyFuture<'ch, M, T, const N: usize> where M: RawMutex, @@ -549,6 +553,7 @@ impl<'ch, M: RawMutex, T, const N: usize> From> for /// Future returned by [`Channel::send`] and [`Sender::send`]. #[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] pub struct SendFuture<'ch, M, T, const N: usize> where M: RawMutex, @@ -646,6 +651,7 @@ pub enum TrySendError { Full(T), } +#[derive(Debug)] struct ChannelState { queue: Deque, receiver_waker: WakerRegistration, @@ -785,6 +791,7 @@ impl ChannelState { /// received from the channel. /// /// All data sent will become available in the same order as it was sent. +#[derive(Debug)] pub struct Channel where M: RawMutex, diff --git a/embassy-sync/src/lazy_lock.rs b/embassy-sync/src/lazy_lock.rs index a919f0037..945560a80 100644 --- a/embassy-sync/src/lazy_lock.rs +++ b/embassy-sync/src/lazy_lock.rs @@ -21,6 +21,7 @@ use core::sync::atomic::{AtomicBool, Ordering}; /// let reference = VALUE.get(); /// assert_eq!(reference, &20); /// ``` +#[derive(Debug)] pub struct LazyLock T> { init: AtomicBool, data: UnsafeCell>, @@ -144,6 +145,7 @@ mod tests { } static DROP_CHECKER: AtomicU32 = AtomicU32::new(0); + #[derive(Debug)] struct DropCheck; impl Drop for DropCheck { diff --git a/embassy-sync/src/mutex.rs b/embassy-sync/src/mutex.rs index 8496f34bf..4ce6dd987 100644 --- a/embassy-sync/src/mutex.rs +++ b/embassy-sync/src/mutex.rs @@ -16,6 +16,7 @@ use crate::waitqueue::WakerRegistration; #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct TryLockError; +#[derive(Debug)] struct State { locked: bool, waker: WakerRegistration, diff --git a/embassy-sync/src/once_lock.rs b/embassy-sync/src/once_lock.rs index 1e848685a..73edfea9a 100644 --- a/embassy-sync/src/once_lock.rs +++ b/embassy-sync/src/once_lock.rs @@ -1,6 +1,7 @@ //! Synchronization primitive for initializing a value once, allowing others to await a reference to the value. use core::cell::Cell; +use core::fmt::{Debug, Formatter}; use core::future::{poll_fn, Future}; use core::mem::MaybeUninit; use core::sync::atomic::{AtomicBool, Ordering}; @@ -42,6 +43,15 @@ pub struct OnceLock { data: Cell>, } +impl Debug for OnceLock { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + f.debug_struct("OnceLock") + .field("init", &self.init) + .field("data", &"Cell>") + .finish() + } +} + unsafe impl Sync for OnceLock where T: Sync {} impl OnceLock { diff --git a/embassy-sync/src/pipe.rs b/embassy-sync/src/pipe.rs index df3b28b45..6d624979a 100644 --- a/embassy-sync/src/pipe.rs +++ b/embassy-sync/src/pipe.rs @@ -13,6 +13,7 @@ use crate::ring_buffer::RingBuffer; use crate::waitqueue::WakerRegistration; /// Write-only access to a [`Pipe`]. +#[derive(Debug)] pub struct Writer<'p, M, const N: usize> where M: RawMutex, @@ -52,6 +53,7 @@ where /// Future returned by [`Pipe::write`] and [`Writer::write`]. #[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] pub struct WriteFuture<'p, M, const N: usize> where M: RawMutex, @@ -77,6 +79,7 @@ where impl<'p, M, const N: usize> Unpin for WriteFuture<'p, M, N> where M: RawMutex {} /// Read-only access to a [`Pipe`]. +#[derive(Debug)] pub struct Reader<'p, M, const N: usize> where M: RawMutex, @@ -128,6 +131,7 @@ where /// Future returned by [`Pipe::read`] and [`Reader::read`]. #[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] pub struct ReadFuture<'p, M, const N: usize> where M: RawMutex, @@ -154,6 +158,7 @@ impl<'p, M, const N: usize> Unpin for ReadFuture<'p, M, N> where M: RawMutex {} /// Future returned by [`Reader::fill_buf`]. #[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] pub struct FillBufFuture<'p, M, const N: usize> where M: RawMutex, @@ -199,6 +204,7 @@ pub enum TryWriteError { Full, } +#[derive(Debug)] struct PipeState { buffer: RingBuffer, read_waker: WakerRegistration, @@ -206,6 +212,7 @@ struct PipeState { } #[repr(transparent)] +#[derive(Debug)] struct Buffer(UnsafeCell<[u8; N]>); impl Buffer { @@ -230,6 +237,7 @@ unsafe impl Sync for Buffer {} /// buffer is full, attempts to `write` new bytes will wait until buffer space is freed up. /// /// All data written will become available in the same order as it was written. +#[derive(Debug)] pub struct Pipe where M: RawMutex, diff --git a/embassy-sync/src/pubsub/mod.rs b/embassy-sync/src/pubsub/mod.rs index 9206b9383..ad9402f5a 100644 --- a/embassy-sync/src/pubsub/mod.rs +++ b/embassy-sync/src/pubsub/mod.rs @@ -71,6 +71,7 @@ pub use subscriber::{DynSubscriber, Subscriber}; /// # block_on(test); /// ``` /// +#[derive(Debug)] pub struct PubSubChannel { inner: Mutex>>, } @@ -297,6 +298,7 @@ impl { /// The queue contains the last messages that have been published and a countdown of how many subscribers are yet to read it queue: Deque<(T, usize), CAP>, diff --git a/embassy-sync/src/pubsub/publisher.rs b/embassy-sync/src/pubsub/publisher.rs index 52a52f926..2a67a0002 100644 --- a/embassy-sync/src/pubsub/publisher.rs +++ b/embassy-sync/src/pubsub/publisher.rs @@ -10,6 +10,7 @@ use super::{PubSubBehavior, PubSubChannel}; use crate::blocking_mutex::raw::RawMutex; /// A publisher to a channel +#[derive(Debug)] pub struct Pub<'a, PSB: PubSubBehavior + ?Sized, T: Clone> { /// The channel we are a publisher for channel: &'a PSB, @@ -106,6 +107,7 @@ impl<'a, T: Clone> DerefMut for DynPublisher<'a, T> { } /// A publisher that holds a generic reference to the channel +#[derive(Debug)] pub struct Publisher<'a, M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS: usize>( pub(super) Pub<'a, PubSubChannel, T>, ); @@ -130,6 +132,7 @@ impl<'a, M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS: /// A publisher that can only use the `publish_immediate` function, but it doesn't have to be registered with the channel. /// (So an infinite amount is possible) +#[derive(Debug)] pub struct ImmediatePub<'a, PSB: PubSubBehavior + ?Sized, T: Clone> { /// The channel we are a publisher for channel: &'a PSB, @@ -205,6 +208,7 @@ impl<'a, T: Clone> DerefMut for DynImmediatePublisher<'a, T> { } /// An immediate publisher that holds a generic reference to the channel +#[derive(Debug)] pub struct ImmediatePublisher<'a, M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS: usize>( pub(super) ImmediatePub<'a, PubSubChannel, T>, ); @@ -229,6 +233,7 @@ impl<'a, M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS: #[must_use = "Sinks do nothing unless polled"] /// [`futures_sink::Sink`] adapter for [`Pub`]. +#[derive(Debug)] pub struct PubSink<'a, 'p, PSB, T> where T: Clone, @@ -290,6 +295,7 @@ where /// Future for the publisher wait action #[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] pub struct PublisherWaitFuture<'s, 'a, PSB: PubSubBehavior + ?Sized, T: Clone> { /// The message we need to publish message: Option, diff --git a/embassy-sync/src/pubsub/subscriber.rs b/embassy-sync/src/pubsub/subscriber.rs index 649382cf1..356de23f6 100644 --- a/embassy-sync/src/pubsub/subscriber.rs +++ b/embassy-sync/src/pubsub/subscriber.rs @@ -10,6 +10,7 @@ use super::{PubSubBehavior, PubSubChannel, WaitResult}; use crate::blocking_mutex::raw::RawMutex; /// A subscriber to a channel +#[derive(Debug)] pub struct Sub<'a, PSB: PubSubBehavior + ?Sized, T: Clone> { /// The message id of the next message we are yet to receive next_message_id: u64, @@ -151,6 +152,7 @@ impl<'a, T: Clone> DerefMut for DynSubscriber<'a, T> { } /// A subscriber that holds a generic reference to the channel +#[derive(Debug)] pub struct Subscriber<'a, M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS: usize>( pub(super) Sub<'a, PubSubChannel, T>, ); @@ -175,6 +177,7 @@ impl<'a, M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS: /// Future for the subscriber wait action #[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] pub struct SubscriberWaitFuture<'s, 'a, PSB: PubSubBehavior + ?Sized, T: Clone> { subscriber: &'s mut Sub<'a, PSB, T>, } diff --git a/embassy-sync/src/ring_buffer.rs b/embassy-sync/src/ring_buffer.rs index 81e60c42b..f03b7dd8f 100644 --- a/embassy-sync/src/ring_buffer.rs +++ b/embassy-sync/src/ring_buffer.rs @@ -1,5 +1,6 @@ use core::ops::Range; +#[derive(Debug)] pub struct RingBuffer { start: usize, end: usize, diff --git a/embassy-sync/src/rwlock.rs b/embassy-sync/src/rwlock.rs index deeadd167..0d784a7dc 100644 --- a/embassy-sync/src/rwlock.rs +++ b/embassy-sync/src/rwlock.rs @@ -16,6 +16,7 @@ use crate::waitqueue::WakerRegistration; #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct TryLockError; +#[derive(Debug)] struct State { readers: usize, writer: bool, diff --git a/embassy-sync/src/semaphore.rs b/embassy-sync/src/semaphore.rs index d30eee30b..4e82b0fcd 100644 --- a/embassy-sync/src/semaphore.rs +++ b/embassy-sync/src/semaphore.rs @@ -46,6 +46,7 @@ pub trait Semaphore: Sized { /// A representation of a number of acquired permits. /// /// The acquired permits will be released back to the [`Semaphore`] when this is dropped. +#[derive(Debug)] pub struct SemaphoreReleaser<'a, S: Semaphore> { semaphore: &'a S, permits: usize, @@ -181,6 +182,7 @@ impl Semaphore for GreedySemaphore { } } +#[derive(Debug)] struct SemaphoreState { permits: usize, waker: WakerRegistration, @@ -221,6 +223,7 @@ impl SemaphoreState { /// /// Up to `N` tasks may attempt to acquire permits concurrently. If additional /// tasks attempt to acquire a permit, a [`WaitQueueFull`] error will be returned. +#[derive(Debug)] pub struct FairSemaphore where M: RawMutex, @@ -341,6 +344,7 @@ impl Semaphore for FairSemaphore { } } +#[derive(Debug)] struct FairAcquire<'a, M: RawMutex, const N: usize> { sema: &'a FairSemaphore, permits: usize, @@ -364,6 +368,7 @@ impl<'a, M: RawMutex, const N: usize> core::future::Future for FairAcquire<'a, M } } +#[derive(Debug)] struct FairAcquireAll<'a, M: RawMutex, const N: usize> { sema: &'a FairSemaphore, min: usize, @@ -387,6 +392,7 @@ impl<'a, M: RawMutex, const N: usize> core::future::Future for FairAcquireAll<'a } } +#[derive(Debug)] struct FairSemaphoreState { permits: usize, next_ticket: usize, diff --git a/embassy-sync/src/signal.rs b/embassy-sync/src/signal.rs index e7095401e..d96e36245 100644 --- a/embassy-sync/src/signal.rs +++ b/embassy-sync/src/signal.rs @@ -39,6 +39,7 @@ where state: Mutex>>, } +#[derive(Debug)] enum State { None, Waiting(Waker), diff --git a/embassy-sync/src/waitqueue/atomic_waker_turbo.rs b/embassy-sync/src/waitqueue/atomic_waker_turbo.rs index c06b83056..a45adeab8 100644 --- a/embassy-sync/src/waitqueue/atomic_waker_turbo.rs +++ b/embassy-sync/src/waitqueue/atomic_waker_turbo.rs @@ -7,6 +7,7 @@ use core::task::Waker; /// If a waker is registered, registering another waker will replace the previous one without waking it. /// The intended use case is to wake tasks from interrupts. Therefore, it is generally not expected, /// that multiple tasks register try to register a waker simultaneously. +#[derive(Debug)] pub struct AtomicWaker { waker: AtomicPtr<()>, } diff --git a/embassy-sync/src/waitqueue/multi_waker.rs b/embassy-sync/src/waitqueue/multi_waker.rs index 1c05f8eaf..56c0cd1b2 100644 --- a/embassy-sync/src/waitqueue/multi_waker.rs +++ b/embassy-sync/src/waitqueue/multi_waker.rs @@ -5,6 +5,7 @@ use heapless::Vec; /// Utility struct to register and wake multiple wakers. /// Queue of wakers with a maximum length of `N`. /// Intended for waking multiple tasks. +#[derive(Debug)] pub struct MultiWakerRegistration { wakers: Vec, } diff --git a/embassy-sync/src/watch.rs b/embassy-sync/src/watch.rs index 08d6a833d..332ab5405 100644 --- a/embassy-sync/src/watch.rs +++ b/embassy-sync/src/watch.rs @@ -65,10 +65,12 @@ use crate::waitqueue::MultiWakerRegistration; /// }; /// block_on(f); /// ``` +#[derive(Debug)] pub struct Watch { mutex: Mutex>>, } +#[derive(Debug)] struct WatchState { data: Option, current_id: u64, @@ -392,6 +394,7 @@ impl Watch { } /// A receiver can `.await` a change in the `Watch` value. +#[derive(Debug)] pub struct Snd<'a, T: Clone, W: WatchBehavior + ?Sized> { watch: &'a W, _phantom: PhantomData, @@ -467,6 +470,7 @@ impl<'a, T: Clone, W: WatchBehavior + ?Sized> Snd<'a, T, W> { /// /// For a simpler type definition, consider [`DynSender`] at the expense of /// some runtime performance due to dynamic dispatch. +#[derive(Debug)] pub struct Sender<'a, M: RawMutex, T: Clone, const N: usize>(Snd<'a, T, Watch>); impl<'a, M: RawMutex, T: Clone, const N: usize> Clone for Sender<'a, M, T, N> { @@ -622,6 +626,7 @@ impl<'a, T: Clone, W: WatchBehavior + ?Sized> Drop for Rcv<'a, T, W> { } /// A anonymous receiver can NOT `.await` a change in the `Watch` value. +#[derive(Debug)] pub struct AnonRcv<'a, T: Clone, W: WatchBehavior + ?Sized> { watch: &'a W, at_id: u64, @@ -726,6 +731,7 @@ impl<'a, T: Clone> DerefMut for DynReceiver<'a, T> { } /// A receiver of a `Watch` channel that cannot `.await` values. +#[derive(Debug)] pub struct AnonReceiver<'a, M: RawMutex, T: Clone, const N: usize>(AnonRcv<'a, T, Watch>); impl<'a, M: RawMutex, T: Clone, const N: usize> AnonReceiver<'a, M, T, N> { diff --git a/embassy-sync/src/zerocopy_channel.rs b/embassy-sync/src/zerocopy_channel.rs index e3e5b2538..b3f7dbe8c 100644 --- a/embassy-sync/src/zerocopy_channel.rs +++ b/embassy-sync/src/zerocopy_channel.rs @@ -34,6 +34,7 @@ use crate::waitqueue::WakerRegistration; /// /// The channel requires a buffer of recyclable elements. Writing to the channel is done through /// an `&mut T`. +#[derive(Debug)] pub struct Channel<'a, M: RawMutex, T> { buf: BufferPtr, phantom: PhantomData<&'a mut T>, @@ -95,6 +96,7 @@ impl<'a, M: RawMutex, T> Channel<'a, M, T> { } #[repr(transparent)] +#[derive(Debug)] struct BufferPtr(*mut T); impl BufferPtr { @@ -107,6 +109,7 @@ unsafe impl Send for BufferPtr {} unsafe impl Sync for BufferPtr {} /// Send-only access to a [`Channel`]. +#[derive(Debug)] pub struct Sender<'a, M: RawMutex, T> { channel: &'a Channel<'a, M, T>, } @@ -190,6 +193,7 @@ impl<'a, M: RawMutex, T> Sender<'a, M, T> { } /// Receive-only access to a [`Channel`]. +#[derive(Debug)] pub struct Receiver<'a, M: RawMutex, T> { channel: &'a Channel<'a, M, T>, } @@ -272,6 +276,7 @@ impl<'a, M: RawMutex, T> Receiver<'a, M, T> { } } +#[derive(Debug)] struct State { /// Maximum number of elements the channel can hold. capacity: usize, -- cgit From a7c64fd6bf66cd3192a7e6b13706a47bb49e6e66 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Thu, 21 Aug 2025 09:23:38 +0200 Subject: msmp0-watchdog: bump revision for mspm0-data-generated --- embassy-mspm0/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index 221026b26..da0b77289 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -50,7 +50,7 @@ cortex-m = "0.7.6" critical-section = "1.2.0" # mspm0-metapac = { version = "" } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-df572e257eabf06e6e0ae6c9077e0a2fec1fb5e1" } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-fe17d879548757ca29821da66a1bebf2debd4846" } [build-dependencies] proc-macro2 = "1.0.94" @@ -58,7 +58,7 @@ quote = "1.0.40" cfg_aliases = "0.2.1" # mspm0-metapac = { version = "", default-features = false, features = ["metadata"] } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-df572e257eabf06e6e0ae6c9077e0a2fec1fb5e1", default-features = false, features = ["metadata"] } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-fe17d879548757ca29821da66a1bebf2debd4846", default-features = false, features = ["metadata"] } [features] default = ["rt"] -- cgit From 9db5a173d093e402b9cc10640c9619950849c57d Mon Sep 17 00:00:00 2001 From: Kevin Lannen Date: Thu, 1 May 2025 13:25:54 -0600 Subject: STM32 XSPI: Disable alternate bytes if not requested If a previous command used alternate bytes and the next command does not have them the alternate bytes need to be turned off --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/src/xspi/mod.rs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 301c20055..9cd4d5951 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - fix: Fix vrefbuf building with log feature - fix: Fix performing a hash after performing a hmac - chore: Updated stm32-metapac and stm32-data dependencies +- fix: Fix XSPI not disabling alternate bytes when they were previously enabled ## 0.3.0 - 2025-08-12 diff --git a/embassy-stm32/src/xspi/mod.rs b/embassy-stm32/src/xspi/mod.rs index 44c10b961..60ccf3c97 100644 --- a/embassy-stm32/src/xspi/mod.rs +++ b/embassy-stm32/src/xspi/mod.rs @@ -429,6 +429,11 @@ impl<'d, T: Instance, M: PeriMode> Xspi<'d, T, M> { w.set_abdtr(command.abdtr); w.set_absize(CcrAbsize::from_bits(command.absize.into())); }) + } else { + T::REGS.ccr().modify(|w| { + // disable alternate bytes + w.set_abmode(CcrAbmode::B_0X0); + }) } // Configure dummy cycles -- cgit From 5a1be543ac8838963a6597dda2ddf3918397e39b Mon Sep 17 00:00:00 2001 From: Gabriel Smith Date: Fri, 13 Jun 2025 12:59:56 +0000 Subject: stm32/adc/v3: allow DMA reads to loop through enabled channels Tested on an STM32H533RE. Documentation of other chips has been reviewed, but not extensively. --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/src/adc/v3.rs | 7 +-- examples/stm32h5/src/bin/adc_dma.rs | 94 +++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 examples/stm32h5/src/bin/adc_dma.rs diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 301c20055..da8bce0e2 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - fix: Fix vrefbuf building with log feature - fix: Fix performing a hash after performing a hmac - chore: Updated stm32-metapac and stm32-data dependencies +- feat: stm32/adc/v3: allow DMA reads to loop through enable channels ## 0.3.0 - 2025-08-12 diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index a2e42fe52..dc1faa4d1 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -296,7 +296,8 @@ impl<'d, T: Instance> Adc<'d, T> { /// Read one or multiple ADC channels using DMA. /// - /// `sequence` iterator and `readings` must have the same length. + /// `readings` must have a length that is a multiple of the length of the + /// `sequence` iterator. /// /// Note: The order of values in `readings` is defined by the pin ADC /// channel number and not the pin order in `sequence`. @@ -330,8 +331,8 @@ impl<'d, T: Instance> Adc<'d, T> { ) { assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty"); assert!( - sequence.len() == readings.len(), - "Sequence length must be equal to readings length" + readings.len() % sequence.len() == 0, + "Readings length must be a multiple of sequence length" ); assert!( sequence.len() <= 16, diff --git a/examples/stm32h5/src/bin/adc_dma.rs b/examples/stm32h5/src/bin/adc_dma.rs new file mode 100644 index 000000000..20073e22f --- /dev/null +++ b/examples/stm32h5/src/bin/adc_dma.rs @@ -0,0 +1,94 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::adc::{self, Adc, AdcChannel, RxDma, SampleTime}; +use embassy_stm32::peripherals::{ADC1, ADC2, GPDMA1_CH0, GPDMA1_CH1, PA0, PA1, PA2, PA3}; +use embassy_stm32::{Config, Peri}; +use embassy_time::Instant; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let mut config = Config::default(); + { + use embassy_stm32::rcc::*; + config.rcc.hsi = Some(HSIPrescaler::DIV1); + config.rcc.csi = true; + config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL25, + divp: Some(PllDiv::DIV2), + divq: Some(PllDiv::DIV4), // SPI1 cksel defaults to pll1_q + divr: None, + }); + config.rcc.pll2 = Some(Pll { + source: PllSource::HSI, + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL25, + divp: None, + divq: None, + divr: Some(PllDiv::DIV4), // 100mhz + }); + config.rcc.sys = Sysclk::PLL1_P; // 200 Mhz + config.rcc.ahb_pre = AHBPrescaler::DIV1; // 200 Mhz + config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz + config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz + config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz + config.rcc.voltage_scale = VoltageScale::Scale1; + config.rcc.mux.adcdacsel = mux::Adcdacsel::PLL2_R; + } + let p = embassy_stm32::init(config); + + spawner.must_spawn(adc1_task(p.ADC1, p.GPDMA1_CH0, p.PA0, p.PA2)); + spawner.must_spawn(adc2_task(p.ADC2, p.GPDMA1_CH1, p.PA1, p.PA3)); +} + +#[embassy_executor::task] +async fn adc1_task( + adc: Peri<'static, ADC1>, + dma: Peri<'static, GPDMA1_CH0>, + pin1: Peri<'static, PA0>, + pin2: Peri<'static, PA2>, +) { + adc_task(adc, dma, pin1, pin2).await; +} + +#[embassy_executor::task] +async fn adc2_task( + adc: Peri<'static, ADC2>, + dma: Peri<'static, GPDMA1_CH1>, + pin1: Peri<'static, PA1>, + pin2: Peri<'static, PA3>, +) { + adc_task(adc, dma, pin1, pin2).await; +} + +async fn adc_task<'a, T: adc::Instance>( + adc: Peri<'a, T>, + mut dma: Peri<'a, impl RxDma>, + pin1: impl AdcChannel, + pin2: impl AdcChannel, +) { + let mut adc = Adc::new(adc); + let mut pin1 = pin1.degrade_adc(); + let mut pin2 = pin2.degrade_adc(); + + let mut tic = Instant::now(); + let mut buffer = [0u16; 512]; + loop { + // This is not a true continuous read as there is downtime between each + // call to `Adc::read` where the ADC is sitting idle. + adc.read( + dma.reborrow(), + [(&mut pin1, SampleTime::CYCLES2_5), (&mut pin2, SampleTime::CYCLES2_5)].into_iter(), + &mut buffer, + ) + .await; + let toc = Instant::now(); + info!("\n adc1: {} dt = {}", buffer[0..16], (toc - tic).as_micros()); + tic = toc; + } +} -- cgit From 0396787e19f7ef36bb8e1b881ad1d5d23d9c71af Mon Sep 17 00:00:00 2001 From: Ike Date: Mon, 25 Aug 2025 19:16:41 +0400 Subject: Replace SAADC input pins with correct mappings --- embassy-nrf/src/chips/nrf5340_app.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs index 99cf29487..c0290b7a4 100644 --- a/embassy-nrf/src/chips/nrf5340_app.rs +++ b/embassy-nrf/src/chips/nrf5340_app.rs @@ -463,14 +463,14 @@ impl_ppi_channel!(PPI_CH29, 29 => configurable); impl_ppi_channel!(PPI_CH30, 30 => configurable); impl_ppi_channel!(PPI_CH31, 31 => configurable); -impl_saadc_input!(P0_13, ANALOG_INPUT0); -impl_saadc_input!(P0_14, ANALOG_INPUT1); -impl_saadc_input!(P0_15, ANALOG_INPUT2); -impl_saadc_input!(P0_16, ANALOG_INPUT3); -impl_saadc_input!(P0_17, ANALOG_INPUT4); -impl_saadc_input!(P0_18, ANALOG_INPUT5); -impl_saadc_input!(P0_19, ANALOG_INPUT6); -impl_saadc_input!(P0_20, ANALOG_INPUT7); +impl_saadc_input!(P0_04, ANALOG_INPUT0); +impl_saadc_input!(P0_05, ANALOG_INPUT1); +impl_saadc_input!(P0_06, ANALOG_INPUT2); +impl_saadc_input!(P0_07, ANALOG_INPUT3); +impl_saadc_input!(P0_25, ANALOG_INPUT4); +impl_saadc_input!(P0_26, ANALOG_INPUT5); +impl_saadc_input!(P0_27, ANALOG_INPUT6); +impl_saadc_input!(P0_28, ANALOG_INPUT7); impl_egu!(EGU0, EGU0, EGU0); impl_egu!(EGU1, EGU1, EGU1); -- cgit From dfa6485f99ff523f10239ef9ac40d6412d867d13 Mon Sep 17 00:00:00 2001 From: Ike Date: Mon, 25 Aug 2025 20:50:19 +0400 Subject: Fix SAADC pins for nrf5340 in CHANGELOG --- embassy-nrf/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index 5709b28b5..12e3850c0 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- bugfix: use correct analog input SAADC pins on nrf5340 + ## 0.6.0 - 2025-08-04 - changed: update to latest embassy-time-queue-utils -- cgit From 6a347f1f09b0076af868dcd63d9139081c92172b Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Thu, 14 Aug 2025 13:36:39 +0200 Subject: feat: add semver checks and releasing to releaser * List dependencies of a crate * List dependents of a crate * Perform semver-checks of a crate * Prepare a release for a crate and all dependents * Use a single release.toml for cargo-release * Add changelogs where missing --- cyw43-pio/release.toml | 5 - cyw43/release.toml | 5 - embassy-boot/CHANGELOG.md | 11 + embassy-embedded-hal/release.toml | 5 - embassy-executor/release.toml | 5 - embassy-futures/release.toml | 5 - embassy-net-adin1110/CHANGELOG.md | 11 + embassy-net-driver-channel/release.toml | 5 - embassy-net-driver/CHANGELOG.md | 3 + embassy-net-esp-hosted/CHANGELOG.md | 11 + embassy-net-nrf91/CHANGELOG.md | 13 + embassy-net-nrf91/Cargo.toml | 4 +- embassy-net-ppp/CHANGELOG.md | 3 + embassy-net-wiznet/CHANGELOG.md | 13 + embassy-net/CHANGELOG.md | 3 +- embassy-nrf/release.toml | 5 - embassy-release/Cargo.toml | 12 - embassy-release/src/main.rs | 303 ------------------- embassy-rp/release.toml | 5 - embassy-stm32/release.toml | 5 - embassy-sync/CHANGELOG.md | 3 +- embassy-time-driver/release.toml | 5 - embassy-time-queue-utils/CHANGELOG.md | 3 +- embassy-time/release.toml | 5 - embassy-usb-dfu/CHANGELOG.md | 11 + embassy-usb-driver/release.toml | 5 - embassy-usb-logger/CHANGELOG.md | 3 +- embassy-usb-synopsys-otg/CHANGELOG.md | 3 +- embassy-usb/release.toml | 5 - release/Cargo.toml | 15 + release/config.toml | 45 +++ release/release.toml | 5 + release/src/main.rs | 519 ++++++++++++++++++++++++++++++++ 33 files changed, 672 insertions(+), 387 deletions(-) delete mode 100644 cyw43-pio/release.toml delete mode 100644 cyw43/release.toml create mode 100644 embassy-boot/CHANGELOG.md delete mode 100644 embassy-embedded-hal/release.toml delete mode 100644 embassy-executor/release.toml delete mode 100644 embassy-futures/release.toml create mode 100644 embassy-net-adin1110/CHANGELOG.md delete mode 100644 embassy-net-driver-channel/release.toml create mode 100644 embassy-net-esp-hosted/CHANGELOG.md create mode 100644 embassy-net-nrf91/CHANGELOG.md create mode 100644 embassy-net-wiznet/CHANGELOG.md delete mode 100644 embassy-nrf/release.toml delete mode 100644 embassy-release/Cargo.toml delete mode 100644 embassy-release/src/main.rs delete mode 100644 embassy-rp/release.toml delete mode 100644 embassy-stm32/release.toml delete mode 100644 embassy-time-driver/release.toml delete mode 100644 embassy-time/release.toml create mode 100644 embassy-usb-dfu/CHANGELOG.md delete mode 100644 embassy-usb-driver/release.toml delete mode 100644 embassy-usb/release.toml create mode 100644 release/Cargo.toml create mode 100644 release/release.toml create mode 100644 release/src/main.rs diff --git a/cyw43-pio/release.toml b/cyw43-pio/release.toml deleted file mode 100644 index fb6feaf21..000000000 --- a/cyw43-pio/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -pre-release-replacements = [ - {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, - {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, - {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, -] diff --git a/cyw43/release.toml b/cyw43/release.toml deleted file mode 100644 index fb6feaf21..000000000 --- a/cyw43/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -pre-release-replacements = [ - {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, - {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, - {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, -] diff --git a/embassy-boot/CHANGELOG.md b/embassy-boot/CHANGELOG.md new file mode 100644 index 000000000..7042ad14c --- /dev/null +++ b/embassy-boot/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +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). + + +## Unreleased - ReleaseDate + +- First release with changelog. diff --git a/embassy-embedded-hal/release.toml b/embassy-embedded-hal/release.toml deleted file mode 100644 index fb6feaf21..000000000 --- a/embassy-embedded-hal/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -pre-release-replacements = [ - {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, - {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, - {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, -] diff --git a/embassy-executor/release.toml b/embassy-executor/release.toml deleted file mode 100644 index fb6feaf21..000000000 --- a/embassy-executor/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -pre-release-replacements = [ - {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, - {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, - {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, -] diff --git a/embassy-futures/release.toml b/embassy-futures/release.toml deleted file mode 100644 index fb6feaf21..000000000 --- a/embassy-futures/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -pre-release-replacements = [ - {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, - {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, - {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, -] diff --git a/embassy-net-adin1110/CHANGELOG.md b/embassy-net-adin1110/CHANGELOG.md new file mode 100644 index 000000000..7042ad14c --- /dev/null +++ b/embassy-net-adin1110/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +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). + + +## Unreleased - ReleaseDate + +- First release with changelog. diff --git a/embassy-net-driver-channel/release.toml b/embassy-net-driver-channel/release.toml deleted file mode 100644 index fb6feaf21..000000000 --- a/embassy-net-driver-channel/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -pre-release-replacements = [ - {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, - {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, - {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, -] diff --git a/embassy-net-driver/CHANGELOG.md b/embassy-net-driver/CHANGELOG.md index 165461eff..0c7c27d6e 100644 --- a/embassy-net-driver/CHANGELOG.md +++ b/embassy-net-driver/CHANGELOG.md @@ -5,6 +5,9 @@ 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). + +## Unreleased - ReleaseDate + ## 0.2.0 - 2023-10-18 - Added support for IEEE 802.15.4 mediums. diff --git a/embassy-net-esp-hosted/CHANGELOG.md b/embassy-net-esp-hosted/CHANGELOG.md new file mode 100644 index 000000000..7042ad14c --- /dev/null +++ b/embassy-net-esp-hosted/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +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). + + +## Unreleased - ReleaseDate + +- First release with changelog. diff --git a/embassy-net-nrf91/CHANGELOG.md b/embassy-net-nrf91/CHANGELOG.md new file mode 100644 index 000000000..52cbf5ef3 --- /dev/null +++ b/embassy-net-nrf91/CHANGELOG.md @@ -0,0 +1,13 @@ +# Changelog + +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). + + +## Unreleased - ReleaseDate + +## 0.1.1 - 2025-08-14 + +- First release with changelog. diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml index 9201dc84c..387627491 100644 --- a/embassy-net-nrf91/Cargo.toml +++ b/embassy-net-nrf91/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-net-nrf91" -version = "0.1.0" +version = "0.1.1" edition = "2021" description = "embassy-net driver for Nordic nRF91-series cellular modems" keywords = ["embedded", "nrf91", "embassy-net", "cellular"] @@ -36,4 +36,4 @@ target = "thumbv7em-none-eabi" features = ["defmt", "nrf-pac/nrf9160"] [package.metadata.docs.rs] -features = ["defmt"] +features = ["defmt", "nrf-pac/nrf9160"] diff --git a/embassy-net-ppp/CHANGELOG.md b/embassy-net-ppp/CHANGELOG.md index 6ce64ddcb..b364608d2 100644 --- a/embassy-net-ppp/CHANGELOG.md +++ b/embassy-net-ppp/CHANGELOG.md @@ -5,6 +5,9 @@ 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). + +## Unreleased - ReleaseDate + ## 0.2.0 - 2025-01-12 - Update `ppproto` to v0.2. diff --git a/embassy-net-wiznet/CHANGELOG.md b/embassy-net-wiznet/CHANGELOG.md new file mode 100644 index 000000000..52cbf5ef3 --- /dev/null +++ b/embassy-net-wiznet/CHANGELOG.md @@ -0,0 +1,13 @@ +# Changelog + +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). + + +## Unreleased - ReleaseDate + +## 0.1.1 - 2025-08-14 + +- First release with changelog. diff --git a/embassy-net/CHANGELOG.md b/embassy-net/CHANGELOG.md index 8773772ce..39bc6c0f0 100644 --- a/embassy-net/CHANGELOG.md +++ b/embassy-net/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate No unreleased changes yet... Quick, go send a PR! diff --git a/embassy-nrf/release.toml b/embassy-nrf/release.toml deleted file mode 100644 index fb6feaf21..000000000 --- a/embassy-nrf/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -pre-release-replacements = [ - {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, - {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, - {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, -] diff --git a/embassy-release/Cargo.toml b/embassy-release/Cargo.toml deleted file mode 100644 index de548e650..000000000 --- a/embassy-release/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "embassy-release" -version = "0.1.0" -edition = "2021" - -[dependencies] -clap = { version = "4.5.1", features = ["derive"] } -walkdir = "2.5.0" -toml = "0.8.8" -toml_edit = { version = "0.23.1", features = ["serde"] } -serde = { version = "1.0.198", features = ["derive"] } -regex = "1.10.4" diff --git a/embassy-release/src/main.rs b/embassy-release/src/main.rs deleted file mode 100644 index 321d3872c..000000000 --- a/embassy-release/src/main.rs +++ /dev/null @@ -1,303 +0,0 @@ -use std::collections::{HashMap, HashSet}; -use std::fs; -use std::path::{Path, PathBuf}; -use std::process::Command as ProcessCommand; - -use clap::{Parser, Subcommand, ValueEnum}; -use regex::Regex; -use serde::Deserialize; -use toml_edit::{DocumentMut, Item, Value}; -use walkdir::WalkDir; - -/// Tool to traverse and operate on intra-repo Rust crate dependencies -#[derive(Parser, Debug)] -#[command(author, version, about)] -struct Args { - /// Path to the root crate - #[arg(value_name = "CRATE_PATH")] - crate_path: PathBuf, - - /// Command to perform on each crate - #[command(subcommand)] - command: Command, - - /// Traversal order - #[arg(short, long, default_value = "post")] - order: TraversalOrder, -} - -#[derive(Debug, Clone, ValueEnum, PartialEq)] -enum TraversalOrder { - Pre, - Post, -} - -#[derive(Debug, Subcommand)] -enum Command { - /// Print all dependencies - Dependencies, - - /// Release crate - Release { - #[command(subcommand)] - kind: ReleaseKind, - }, -} - -#[derive(Debug, Subcommand, Clone, Copy, PartialEq)] -enum ReleaseKind { - Patch, - Minor, -} - -#[derive(Debug, Deserialize)] -struct CargoToml { - package: Option, - dependencies: Option, -} - -#[derive(Debug, Deserialize)] -struct Package { - name: String, - version: Option, -} - -#[derive(Debug, Deserialize)] -#[serde(untagged)] -enum Dep { - Version(String), - DetailedTable(HashMap), -} - -type Deps = std::collections::HashMap; - -#[derive(Debug, Deserialize)] -struct CrateConfig { - features: Option>, - target: Option, -} - -type ReleaseConfig = HashMap; - -fn find_path_deps(cargo_path: &Path) -> Vec { - let content = fs::read_to_string(cargo_path).unwrap_or_else(|_| { - panic!("Failed to read {:?}", cargo_path); - }); - let parsed: CargoToml = toml::from_str(&content).unwrap_or_else(|e| { - panic!("Failed to parse {:?}: {}", cargo_path, e); - }); - - let mut paths = vec![]; - if let Some(deps) = parsed.dependencies { - for (_name, dep) in deps { - match dep { - Dep::Version(_) => { - // External dependency — skip - } - Dep::DetailedTable(table) => { - if let Some(toml::Value::String(path)) = table.get("path") { - let dep_path = cargo_path.parent().unwrap().join(path).canonicalize().unwrap(); - paths.push(dep_path); - } - } - } - } - } - - paths -} - -fn visit_recursive( - root_crate: &Path, - visited: &mut HashSet, - output: &mut Vec, - order: &TraversalOrder, -) { - if !visited.insert(root_crate.to_path_buf()) { - return; - } - - let cargo_toml = root_crate.join("Cargo.toml"); - let deps = find_path_deps(&cargo_toml); - - if *order == TraversalOrder::Pre { - output.push(root_crate.to_path_buf()); - } - - let mut deps_sorted = deps; - deps_sorted.sort(); - for dep in deps_sorted { - visit_recursive(&dep, visited, output, order); - } - - if *order == TraversalOrder::Post { - output.push(root_crate.to_path_buf()); - } -} - -fn get_crate_metadata(crate_path: &Path) -> Option<(String, String)> { - let cargo_toml = crate_path.join("Cargo.toml"); - let content = fs::read_to_string(&cargo_toml).ok()?; - let parsed: CargoToml = toml::from_str(&content).ok()?; - let pkg = parsed.package?; - let name = pkg.name; - let version = pkg.version?; - Some((name, version)) -} - -fn load_release_config() -> ReleaseConfig { - let config_path = PathBuf::from("release/config.toml"); - if !config_path.exists() { - return HashMap::new(); - } - let content = fs::read_to_string(&config_path).expect("Failed to read release/config.toml"); - toml::from_str(&content).expect("Invalid TOML format in release/config.toml") -} - -fn bump_dependency_versions(crate_name: &str, new_version: &str) -> Result<(), String> { - let mut cargo_files: Vec = WalkDir::new(".") - .into_iter() - .filter_map(Result::ok) - .filter(|e| e.file_name() == "Cargo.toml") - .map(|e| e.into_path()) - .collect(); - - cargo_files.sort(); - - for path in cargo_files { - let content = fs::read_to_string(&path).map_err(|e| format!("Failed to read {}: {}", path.display(), e))?; - - let mut doc: DocumentMut = content - .parse() - .map_err(|e| format!("Failed to parse TOML in {}: {}", path.display(), e))?; - - let mut changed = false; - - for section in ["dependencies", "dev-dependencies", "build-dependencies"] { - if let Some(Item::Table(dep_table)) = doc.get_mut(section) { - if let Some(item) = dep_table.get_mut(crate_name) { - match item { - // e.g., foo = "0.1.0" - Item::Value(Value::String(_)) => { - *item = Item::Value(Value::from(new_version)); - changed = true; - } - // e.g., foo = { version = "...", ... } - Item::Value(Value::InlineTable(inline)) => { - if inline.contains_key("version") { - inline["version"] = Value::from(new_version); - changed = true; - } - } - _ => {} // Leave unusual formats untouched - } - } - } - } - - if changed { - fs::write(&path, doc.to_string()).map_err(|e| format!("Failed to write {}: {}", path.display(), e))?; - println!("🔧 Updated {} to {} in {}", crate_name, new_version, path.display()); - } - } - - Ok(()) -} - -fn run_release_command( - crate_path: &Path, - crate_name: &str, - version: &str, - kind: &ReleaseKind, - config: Option<&CrateConfig>, -) -> Result<(), String> { - let kind_str = match kind { - ReleaseKind::Patch => "patch", - ReleaseKind::Minor => "minor", - }; - - if *kind == ReleaseKind::Minor { - bump_dependency_versions(crate_name, version)?; - } - - let mut args: Vec = vec!["release".into(), kind_str.into()]; - - if let Some(cfg) = config { - if let Some(features) = &cfg.features { - args.push("--features".into()); - args.push(features.join(",")); - } - if let Some(target) = &cfg.target { - args.push("--target".into()); - args.push(target.clone()); - } - } - - let status = ProcessCommand::new("cargo") - .args(&args) - .current_dir(crate_path) - .status() - .map_err(|e| format!("Failed to run cargo release: {}", e))?; - - if !status.success() { - return Err(format!("`cargo release {}` failed in crate {}", kind_str, crate_name)); - } - - //args.push("--execute".into()); - //let status = ProcessCommand::new("cargo") - // .args(&args) - // .current_dir(crate_path) - // .status() - // .map_err(|e| format!("Failed to run cargo release --execute: {}", e))?; - - //if !status.success() { - // return Err(format!( - // "`cargo release {kind_str} --execute` failed in crate {crate_name}" - // )); - //} - - Ok(()) -} - -fn main() { - let args = Args::parse(); - let root = args.crate_path.canonicalize().expect("Invalid root crate path"); - - match args.command { - Command::Dependencies => { - let mut visited = HashSet::new(); - let mut ordered = vec![]; - visit_recursive(&root, &mut visited, &mut ordered, &args.order); - for path in ordered { - if let Some((name, _)) = get_crate_metadata(&path) { - println!("{name}"); - } else { - eprintln!("Warning: could not read crate name from {:?}", path); - } - } - } - Command::Release { kind } => { - let config = load_release_config(); - let path = root; - match get_crate_metadata(&path) { - Some((name, version)) => { - println!("🚀 Releasing {name}..."); - let crate_cfg = config.get(&name); - match run_release_command(&path, &name, &version, &kind, crate_cfg) { - Ok(_) => { - println!("✅ Released {name}"); - } - Err(e) => { - eprintln!("❌ Error releasing {name}:\n{e}"); - eprintln!("\nYou may retry with: `cargo run -- {path:?} release {kind:?}`"); - std::process::exit(1); - } - } - } - None => { - eprintln!("Warning: Could not parse crate metadata in {:?}", path); - } - } - } - } -} diff --git a/embassy-rp/release.toml b/embassy-rp/release.toml deleted file mode 100644 index fb6feaf21..000000000 --- a/embassy-rp/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -pre-release-replacements = [ - {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, - {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, - {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, -] diff --git a/embassy-stm32/release.toml b/embassy-stm32/release.toml deleted file mode 100644 index fb6feaf21..000000000 --- a/embassy-stm32/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -pre-release-replacements = [ - {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, - {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, - {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, -] diff --git a/embassy-sync/CHANGELOG.md b/embassy-sync/CHANGELOG.md index fa0340c68..7418ead8d 100644 --- a/embassy-sync/CHANGELOG.md +++ b/embassy-sync/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate - Add `get_mut` to `LazyLock` - Add more `Debug` impls to `embassy-sync`, particularly on `OnceLock` diff --git a/embassy-time-driver/release.toml b/embassy-time-driver/release.toml deleted file mode 100644 index fb6feaf21..000000000 --- a/embassy-time-driver/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -pre-release-replacements = [ - {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, - {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, - {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, -] diff --git a/embassy-time-queue-utils/CHANGELOG.md b/embassy-time-queue-utils/CHANGELOG.md index 26200503c..510c29d58 100644 --- a/embassy-time-queue-utils/CHANGELOG.md +++ b/embassy-time-queue-utils/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate - Removed the embassy-executor dependency diff --git a/embassy-time/release.toml b/embassy-time/release.toml deleted file mode 100644 index fb6feaf21..000000000 --- a/embassy-time/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -pre-release-replacements = [ - {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, - {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, - {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, -] diff --git a/embassy-usb-dfu/CHANGELOG.md b/embassy-usb-dfu/CHANGELOG.md new file mode 100644 index 000000000..7042ad14c --- /dev/null +++ b/embassy-usb-dfu/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +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). + + +## Unreleased - ReleaseDate + +- First release with changelog. diff --git a/embassy-usb-driver/release.toml b/embassy-usb-driver/release.toml deleted file mode 100644 index fb6feaf21..000000000 --- a/embassy-usb-driver/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -pre-release-replacements = [ - {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, - {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, - {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, -] diff --git a/embassy-usb-logger/CHANGELOG.md b/embassy-usb-logger/CHANGELOG.md index 79ea25839..c88b3ed6a 100644 --- a/embassy-usb-logger/CHANGELOG.md +++ b/embassy-usb-logger/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate ## 0.5.0 - 2025-07-22 diff --git a/embassy-usb-synopsys-otg/CHANGELOG.md b/embassy-usb-synopsys-otg/CHANGELOG.md index 9913ee533..55eef0a1e 100644 --- a/embassy-usb-synopsys-otg/CHANGELOG.md +++ b/embassy-usb-synopsys-otg/CHANGELOG.md @@ -5,7 +5,8 @@ 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). -## Unreleased + +## Unreleased - ReleaseDate ## 0.3.0 - 2025-07-22 diff --git a/embassy-usb/release.toml b/embassy-usb/release.toml deleted file mode 100644 index fb6feaf21..000000000 --- a/embassy-usb/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -pre-release-replacements = [ - {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, - {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, - {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, -] diff --git a/release/Cargo.toml b/release/Cargo.toml new file mode 100644 index 000000000..cc1b155e2 --- /dev/null +++ b/release/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "embassy-release" +version = "0.1.0" +edition = "2021" + +[dependencies] +clap = { version = "4.5.1", features = ["derive"] } +walkdir = "2.5.0" +toml = "0.8.8" +toml_edit = { version = "0.23.1", features = ["serde"] } +serde = { version = "1.0.198", features = ["derive"] } +regex = "1.10.4" +anyhow = "1" +petgraph = "0.8.2" +semver = "1.0.26" diff --git a/release/config.toml b/release/config.toml index 2292f4077..6b23217fa 100644 --- a/release/config.toml +++ b/release/config.toml @@ -1 +1,46 @@ + +embassy-stm32 = { features = ["defmt", "unstable-pac", "exti", "time-driver-any", "time", "stm32h755zi-cm7", "dual-bank"], target = "thumbv7em-none-eabi" } +embassy-nrf = { features = ["nrf52840", "time", "defmt", "unstable-pac", "gpiote", "time-driver-rtc1"], target = "thumbv7em-none-eabihf" } + embassy-rp = { features = ["defmt", "unstable-pac", "time-driver", "rp2040"], target = "thumbv6m-none-eabi" } +cyw43 = { features = ["defmt", "firmware-logs"], target = "thumbv6m-none-eabi" } +#cyw43-pio = { features = ["defmt", "embassy-rp/rp2040"], target = "thumbv6m-none-eabi" } + +embassy-boot = { features = ["defmt"] } +#embassy-boot-nrf = { features = ["defmt", "embassy-nrf/nrf52840"], target = "thumbv7em-none-eabihf" } +#embassy-boot-rp = { features = ["defmt", "embassy-rp/rp2040"], target = "thumbv6m-none-eabi" } +#embassy-boot-stm32 = { features = ["defmt", "embassy-stm32/stm32f429zi"], target = "thumbv7em-none-eabi" } + +embassy-time = { features = ["defmt", "std"] } +embassy-time-driver = { } +embassy-time-queue-utils = { features = ["defmt"] } + +embassy-futures = { } +embassy-embedded-hal = { features = ["time"] } +embassy-hal-internal = { } +embassy-executor = { features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"], target = "thumbv7em-none-eabi" } +embassy-executor-macros = { } +embassy-sync = { } + +embassy-net = { features = ["defmt", "tcp", "udp", "raw", "dns", "icmp", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "medium-ieee802154", "multicast", "dhcpv4-hostname"] } +embassy-net-ppp = { } +embassy-net-esp-hosted = {} +embassy-net-driver-channel = {} +embassy-net-wiznet = {} +embassy-net-nrf91 = { features = ["defmt", "nrf9160"] } +embassy-net-driver = {} +embassy-net-tuntap = {} +embassy-net-adin1110 = {} +embassy-net-enc28j60 = {} + +embassy-usb-driver = { } +embassy-usb-dfu = { features = ["dfu"] } +embassy-usb-synopsys-otg = { } +embassy-usb = { features = ["defmt", "usbd-hid"] } +embassy-usb-logger = { } + +# Unreleased +# embassy-stm32-wpan = {} +# embassy-imxrt = {} +# embassy-nxp = {} +# embassy-mspm0 = {} diff --git a/release/release.toml b/release/release.toml new file mode 100644 index 000000000..fb6feaf21 --- /dev/null +++ b/release/release.toml @@ -0,0 +1,5 @@ +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## Unreleased - ReleaseDate\n", exactly=1}, +] diff --git a/release/src/main.rs b/release/src/main.rs new file mode 100644 index 000000000..38bb728a8 --- /dev/null +++ b/release/src/main.rs @@ -0,0 +1,519 @@ +use std::collections::{BTreeMap, HashMap}; +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::Command as ProcessCommand; + +use anyhow::{anyhow, Result}; +use clap::{Parser, Subcommand}; +use petgraph::graph::{Graph, NodeIndex}; +use petgraph::visit::Bfs; +use petgraph::{Directed, Direction}; +use serde::Deserialize; +use toml_edit::{DocumentMut, Item, Value}; + +/// Tool to traverse and operate on intra-repo Rust crate dependencies +#[derive(Parser, Debug)] +#[command(author, version, about)] +struct Args { + /// Path to embassy repository + #[arg(short, long)] + repo: PathBuf, + + /// Command to perform on each crate + #[command(subcommand)] + command: Command, +} + +#[derive(Debug, Subcommand)] +enum Command { + /// All crates and their direct dependencies + List, + /// List all dependencies for a crate + Dependencies { + /// Crate name to print dependencies for. + #[arg(value_name = "CRATE")] + crate_name: String, + }, + /// List all dependencies for a crate + Dependents { + /// Crate name to print dependencies for. + #[arg(value_name = "CRATE")] + crate_name: String, + }, + + /// SemverCheck + SemverCheck { + /// Crate to check. Will traverse that crate an it's dependents. If not specified checks all crates. + #[arg(value_name = "CRATE")] + crate_name: String, + }, + /// Prepare to release a crate and all dependents that needs updating + /// - Semver checks + /// - Bump versions and commit + /// - Create tag. + PrepareRelease { + /// Crate to release. Will traverse that crate an it's dependents. If not specified checks all crates. + #[arg(value_name = "CRATE")] + crate_name: String, + }, +} + +#[derive(Debug, Subcommand, Clone, Copy, PartialEq)] +enum ReleaseKind { + Patch, + Minor, +} + +#[derive(Debug, Deserialize)] +struct CargoToml { + package: Option, + dependencies: Option, +} + +#[derive(Debug, Deserialize)] +struct Package { + name: String, + version: Option, +} + +#[derive(Debug, Deserialize)] +#[serde(untagged)] +enum Dep { + Version(String), + DetailedTable(BTreeMap), +} + +type Deps = std::collections::BTreeMap; + +#[derive(Debug, Clone, Deserialize)] +struct CrateConfig { + features: Option>, + target: Option, +} + +type ReleaseConfig = HashMap; + +fn load_release_config(repo: &Path) -> ReleaseConfig { + let config_path = repo.join("release/config.toml"); + if !config_path.exists() { + return HashMap::new(); + } + let content = fs::read_to_string(&config_path).expect("Failed to read release/config.toml"); + toml::from_str(&content).expect("Invalid TOML format in release/config.toml") +} + +fn update_version(c: &mut Crate, new_version: &str) -> Result<()> { + let path = &c.path; + c.id.version = new_version.to_string(); + let content = fs::read_to_string(&path)?; + let mut doc: DocumentMut = content.parse()?; + for section in ["package"] { + if let Some(Item::Table(dep_table)) = doc.get_mut(section) { + dep_table.insert("version", Item::Value(Value::from(new_version))); + } + } + fs::write(&path, doc.to_string())?; + Ok(()) +} + +fn update_versions(to_update: &Crate, dep: &CrateId, new_version: &str) -> Result<()> { + let path = &to_update.path; + let content = fs::read_to_string(&path)?; + let mut doc: DocumentMut = content.parse()?; + let mut changed = false; + for section in ["dependencies", "dev-dependencies", "build-dependencies"] { + if let Some(Item::Table(dep_table)) = doc.get_mut(section) { + if let Some(item) = dep_table.get_mut(&dep.name) { + match item { + // e.g., foo = "0.1.0" + Item::Value(Value::String(_)) => { + *item = Item::Value(Value::from(new_version)); + changed = true; + } + // e.g., foo = { version = "...", ... } + Item::Value(Value::InlineTable(inline)) => { + if inline.contains_key("version") { + inline["version"] = Value::from(new_version); + changed = true; + } + } + _ => {} // Leave unusual formats untouched + } + } + } + } + + if changed { + fs::write(&path, doc.to_string())?; + println!("🔧 Updated {} to {} in {}", dep.name, new_version, path.display()); + } + Ok(()) +} + +#[derive(Debug, Clone)] +struct Crate { + id: CrateId, + path: PathBuf, + config: CrateConfig, + dependencies: Vec, +} + +#[derive(Debug, Clone, PartialOrd, Ord)] +struct CrateId { + name: String, + version: String, +} + +impl PartialEq for CrateId { + fn eq(&self, other: &CrateId) -> bool { + self.name == other.name + } +} + +impl Eq for CrateId {} +impl std::hash::Hash for CrateId { + fn hash(&self, state: &mut H) { + self.name.hash(state) + } +} + +fn list_crates(path: &PathBuf) -> Result> { + let d = std::fs::read_dir(path)?; + let release_config = load_release_config(path); + let mut crates = BTreeMap::new(); + for c in d { + let entry = c?; + let name = entry.file_name().to_str().unwrap().to_string(); + if entry.file_type()?.is_dir() && name.starts_with("embassy-") { + let entry = entry.path().join("Cargo.toml"); + if entry.exists() { + let content = fs::read_to_string(&entry).unwrap_or_else(|_| { + panic!("Failed to read {:?}", entry); + }); + let parsed: CargoToml = toml::from_str(&content).unwrap_or_else(|e| { + panic!("Failed to parse {:?}: {}", entry, e); + }); + let p = parsed.package.unwrap(); + let id = CrateId { + name: p.name.clone(), + version: p.version.unwrap(), + }; + + let mut dependencies = Vec::new(); + if let Some(deps) = parsed.dependencies { + for (k, v) in deps { + if k.starts_with("embassy-") { + dependencies.push(CrateId { + name: k, + version: match v { + Dep::Version(v) => v, + Dep::DetailedTable(table) => { + table.get("version").unwrap().as_str().unwrap().to_string() + } + }, + }); + } + } + } + + let path = path.join(entry); + if let Some(config) = release_config.get(&p.name) { + crates.insert( + id.clone(), + Crate { + id, + path, + dependencies, + config: config.clone(), + }, + ); + } + } + } + } + Ok(crates) +} + +fn build_graph(crates: &BTreeMap) -> (Graph, HashMap) { + let mut graph = Graph::::new(); + let mut node_indices: HashMap = HashMap::new(); + + // Helper to insert or get existing node + let get_or_insert_node = |id: CrateId, graph: &mut Graph, map: &mut HashMap| { + if let Some(&idx) = map.get(&id) { + idx + } else { + let idx = graph.add_node(id.clone()); + map.insert(id, idx); + idx + } + }; + + for krate in crates.values() { + get_or_insert_node(krate.id.clone(), &mut graph, &mut node_indices); + } + + for krate in crates.values() { + // Insert crate node if not exists + let crate_idx = get_or_insert_node(krate.id.clone(), &mut graph, &mut node_indices); + + // Insert dependencies and connect edges + for dep in krate.dependencies.iter() { + let dep_idx = get_or_insert_node(dep.clone(), &mut graph, &mut node_indices); + graph.add_edge(crate_idx, dep_idx, ()); + } + } + + (graph, node_indices) +} + +fn main() -> Result<()> { + let args = Args::parse(); + + let root = args.repo.canonicalize()?; //.expect("Invalid root crate path"); + let mut crates = list_crates(&root)?; + //println!("Crates: {:?}", crates); + let (mut graph, indices) = build_graph(&crates); + + // use petgraph::dot::{Config, Dot}; + // println!("{:?}", Dot::with_config(&graph, &[Config::EdgeNoLabel])); + + match args.command { + Command::List => { + let ordered = petgraph::algo::toposort(&graph, None).unwrap(); + for node in ordered.iter() { + if graph.neighbors_directed(*node, Direction::Incoming).count() == 0 { + let start = graph.node_weight(*node).unwrap(); + let mut bfs = Bfs::new(&graph, *node); + while let Some(node) = bfs.next(&graph) { + let weight = graph.node_weight(node).unwrap(); + if weight.name == start.name { + println!("+ {}-{}", weight.name, weight.version); + } else { + println!("|- {}-{}", weight.name, weight.version); + } + } + println!(""); + } + } + } + Command::Dependencies { crate_name } => { + let idx = indices + .get(&CrateId { + name: crate_name.clone(), + version: "".to_string(), + }) + .expect("unable to find crate in tree"); + let mut bfs = Bfs::new(&graph, *idx); + while let Some(node) = bfs.next(&graph) { + let weight = graph.node_weight(node).unwrap(); + if weight.name == crate_name { + println!("+ {}-{}", weight.name, weight.version); + } else { + println!("|- {}-{}", weight.name, weight.version); + } + } + } + Command::Dependents { crate_name } => { + let idx = indices + .get(&CrateId { + name: crate_name.clone(), + version: "".to_string(), + }) + .expect("unable to find crate in tree"); + let node = graph.node_weight(*idx).unwrap(); + println!("+ {}-{}", node.name, node.version); + for parent in graph.neighbors_directed(*idx, Direction::Incoming) { + let weight = graph.node_weight(parent).unwrap(); + println!("|- {}-{}", weight.name, weight.version); + } + } + Command::SemverCheck { crate_name } => { + let c = crates + .get(&CrateId { + name: crate_name.to_string(), + version: "".to_string(), + }) + .unwrap(); + check_semver(&c)?; + } + Command::PrepareRelease { crate_name } => { + let start = indices + .get(&CrateId { + name: crate_name.clone(), + version: "".to_string(), + }) + .expect("unable to find crate in tree"); + + graph.reverse(); + + let mut bfs = Bfs::new(&graph, *start); + + while let Some(node) = bfs.next(&graph) { + let weight = graph.node_weight(node).unwrap(); + println!("Preparing {}", weight.name); + let mut c = crates.get_mut(weight).unwrap(); + let ver = semver::Version::parse(&c.id.version)?; + let newver = if let Err(_) = check_semver(&c) { + println!("Semver check failed, bumping minor!"); + semver::Version::new(ver.major, ver.minor + 1, 0) + } else { + semver::Version::new(ver.major, ver.minor, ver.patch + 1) + }; + + println!( + "Updating {} from {} -> {}", + weight.name, + c.id.version, + newver.to_string() + ); + let newver = newver.to_string(); + + update_version(&mut c, &newver)?; + let c = crates.get(weight).unwrap(); + + // Update all nodes further down the tree + let mut bfs = Bfs::new(&graph, node); + while let Some(dep_node) = bfs.next(&graph) { + let dep_weight = graph.node_weight(dep_node).unwrap(); + let dep = crates.get(dep_weight).unwrap(); + update_versions(dep, &c.id, &newver)?; + } + + // Update changelog + update_changelog(&root, &c)?; + } + + let weight = graph.node_weight(*start).unwrap(); + let c = crates.get(weight).unwrap(); + publish_release(&root, &c, false)?; + + println!("# Please inspect changes and run the following commands when happy:"); + + println!("git commit -a -m 'chore: prepare crate releases'"); + let mut bfs = Bfs::new(&graph, *start); + while let Some(node) = bfs.next(&graph) { + let weight = graph.node_weight(node).unwrap(); + println!("git tag {}-v{}", weight.name, weight.version); + } + + println!(""); + println!("# Run these commands to publish the crate and dependents:"); + + let mut bfs = Bfs::new(&graph, *start); + while let Some(node) = bfs.next(&graph) { + let weight = graph.node_weight(node).unwrap(); + let c = crates.get(weight).unwrap(); + + let mut args: Vec = vec![ + "publish".to_string(), + "--manifest-path".to_string(), + c.path.display().to_string(), + ]; + + if let Some(features) = &c.config.features { + args.push("--features".into()); + args.push(features.join(",")); + } + + if let Some(target) = &c.config.target { + args.push("--target".into()); + args.push(target.clone()); + } + + /* + let mut dry_run = args.clone(); + dry_run.push("--dry-run".to_string()); + + println!("cargo {}", dry_run.join(" ")); + */ + println!("cargo {}", args.join(" ")); + } + + println!(""); + println!("# Run this command to push changes and tags:"); + println!("git push --tags"); + } + } + Ok(()) +} + +fn check_semver(c: &Crate) -> Result<()> { + let mut args: Vec = vec![ + "semver-checks".to_string(), + "--manifest-path".to_string(), + c.path.display().to_string(), + "--default-features".to_string(), + ]; + if let Some(features) = &c.config.features { + args.push("--features".into()); + args.push(features.join(",")); + } + + let status = ProcessCommand::new("cargo").args(&args).output()?; + + println!("{}", core::str::from_utf8(&status.stdout).unwrap()); + eprintln!("{}", core::str::from_utf8(&status.stderr).unwrap()); + if !status.status.success() { + return Err(anyhow!("semver check failed")); + } else { + Ok(()) + } +} + +fn update_changelog(repo: &Path, c: &Crate) -> Result<()> { + let args: Vec = vec![ + "release".to_string(), + "replace".to_string(), + "--config".to_string(), + repo.join("release").join("release.toml").display().to_string(), + "--manifest-path".to_string(), + c.path.display().to_string(), + "--execute".to_string(), + "--no-confirm".to_string(), + ]; + + let status = ProcessCommand::new("cargo").args(&args).output()?; + + println!("{}", core::str::from_utf8(&status.stdout).unwrap()); + eprintln!("{}", core::str::from_utf8(&status.stderr).unwrap()); + if !status.status.success() { + return Err(anyhow!("release replace failed")); + } else { + Ok(()) + } +} + +fn publish_release(_repo: &Path, c: &Crate, push: bool) -> Result<()> { + let mut args: Vec = vec![ + "publish".to_string(), + "--manifest-path".to_string(), + c.path.display().to_string(), + ]; + + if let Some(features) = &c.config.features { + args.push("--features".into()); + args.push(features.join(",")); + } + + if let Some(target) = &c.config.target { + args.push("--target".into()); + args.push(target.clone()); + } + + if !push { + args.push("--dry-run".to_string()); + args.push("--allow-dirty".to_string()); + args.push("--keep-going".to_string()); + } + + let status = ProcessCommand::new("cargo").args(&args).output()?; + + println!("{}", core::str::from_utf8(&status.stdout).unwrap()); + eprintln!("{}", core::str::from_utf8(&status.stderr).unwrap()); + if !status.status.success() { + return Err(anyhow!("publish failed")); + } else { + Ok(()) + } +} -- cgit From 3d004734a2a1db07d0e990462bb3fd5f04d3c7a0 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 15 Aug 2025 09:39:32 +0200 Subject: chore: cleanup --- release/Cargo.toml | 3 +- release/src/main.rs | 184 ++++++++++++--------------------------------------- release/src/types.rs | 33 +++++++++ 3 files changed, 76 insertions(+), 144 deletions(-) create mode 100644 release/src/types.rs diff --git a/release/Cargo.toml b/release/Cargo.toml index cc1b155e2..52ca01c2e 100644 --- a/release/Cargo.toml +++ b/release/Cargo.toml @@ -6,10 +6,11 @@ edition = "2021" [dependencies] clap = { version = "4.5.1", features = ["derive"] } walkdir = "2.5.0" -toml = "0.8.8" +toml = "0.9.5" toml_edit = { version = "0.23.1", features = ["serde"] } serde = { version = "1.0.198", features = ["derive"] } regex = "1.10.4" anyhow = "1" petgraph = "0.8.2" semver = "1.0.26" +cargo-semver-checks = "0.43.0" diff --git a/release/src/main.rs b/release/src/main.rs index 38bb728a8..769611c78 100644 --- a/release/src/main.rs +++ b/release/src/main.rs @@ -8,8 +8,10 @@ use clap::{Parser, Subcommand}; use petgraph::graph::{Graph, NodeIndex}; use petgraph::visit::Bfs; use petgraph::{Directed, Direction}; -use serde::Deserialize; use toml_edit::{DocumentMut, Item, Value}; +use types::*; + +mod types; /// Tool to traverse and operate on intra-repo Rust crate dependencies #[derive(Parser, Debug)] @@ -58,41 +60,6 @@ enum Command { }, } -#[derive(Debug, Subcommand, Clone, Copy, PartialEq)] -enum ReleaseKind { - Patch, - Minor, -} - -#[derive(Debug, Deserialize)] -struct CargoToml { - package: Option, - dependencies: Option, -} - -#[derive(Debug, Deserialize)] -struct Package { - name: String, - version: Option, -} - -#[derive(Debug, Deserialize)] -#[serde(untagged)] -enum Dep { - Version(String), - DetailedTable(BTreeMap), -} - -type Deps = std::collections::BTreeMap; - -#[derive(Debug, Clone, Deserialize)] -struct CrateConfig { - features: Option>, - target: Option, -} - -type ReleaseConfig = HashMap; - fn load_release_config(repo: &Path) -> ReleaseConfig { let config_path = repo.join("release/config.toml"); if !config_path.exists() { @@ -104,7 +71,7 @@ fn load_release_config(repo: &Path) -> ReleaseConfig { fn update_version(c: &mut Crate, new_version: &str) -> Result<()> { let path = &c.path; - c.id.version = new_version.to_string(); + c.version = new_version.to_string(); let content = fs::read_to_string(&path)?; let mut doc: DocumentMut = content.parse()?; for section in ["package"] { @@ -123,7 +90,7 @@ fn update_versions(to_update: &Crate, dep: &CrateId, new_version: &str) -> Resul let mut changed = false; for section in ["dependencies", "dev-dependencies", "build-dependencies"] { if let Some(Item::Table(dep_table)) = doc.get_mut(section) { - if let Some(item) = dep_table.get_mut(&dep.name) { + if let Some(item) = dep_table.get_mut(&dep) { match item { // e.g., foo = "0.1.0" Item::Value(Value::String(_)) => { @@ -145,38 +112,11 @@ fn update_versions(to_update: &Crate, dep: &CrateId, new_version: &str) -> Resul if changed { fs::write(&path, doc.to_string())?; - println!("🔧 Updated {} to {} in {}", dep.name, new_version, path.display()); + println!("🔧 Updated {} to {} in {}", dep, new_version, path.display()); } Ok(()) } -#[derive(Debug, Clone)] -struct Crate { - id: CrateId, - path: PathBuf, - config: CrateConfig, - dependencies: Vec, -} - -#[derive(Debug, Clone, PartialOrd, Ord)] -struct CrateId { - name: String, - version: String, -} - -impl PartialEq for CrateId { - fn eq(&self, other: &CrateId) -> bool { - self.name == other.name - } -} - -impl Eq for CrateId {} -impl std::hash::Hash for CrateId { - fn hash(&self, state: &mut H) { - self.name.hash(state) - } -} - fn list_crates(path: &PathBuf) -> Result> { let d = std::fs::read_dir(path)?; let release_config = load_release_config(path); @@ -187,41 +127,24 @@ fn list_crates(path: &PathBuf) -> Result> { if entry.file_type()?.is_dir() && name.starts_with("embassy-") { let entry = entry.path().join("Cargo.toml"); if entry.exists() { - let content = fs::read_to_string(&entry).unwrap_or_else(|_| { - panic!("Failed to read {:?}", entry); - }); - let parsed: CargoToml = toml::from_str(&content).unwrap_or_else(|e| { - panic!("Failed to parse {:?}: {}", entry, e); - }); - let p = parsed.package.unwrap(); - let id = CrateId { - name: p.name.clone(), - version: p.version.unwrap(), - }; + let content = fs::read_to_string(&entry)?; + let parsed: ParsedCrate = toml::from_str(&content)?; + let id = parsed.package.name; let mut dependencies = Vec::new(); - if let Some(deps) = parsed.dependencies { - for (k, v) in deps { - if k.starts_with("embassy-") { - dependencies.push(CrateId { - name: k, - version: match v { - Dep::Version(v) => v, - Dep::DetailedTable(table) => { - table.get("version").unwrap().as_str().unwrap().to_string() - } - }, - }); - } + for (k, _) in parsed.dependencies { + if k.starts_with("embassy-") { + dependencies.push(k); } } let path = path.join(entry); - if let Some(config) = release_config.get(&p.name) { + if let Some(config) = release_config.get(&id) { crates.insert( id.clone(), Crate { - id, + name: id, + version: parsed.package.version, path, dependencies, config: config.clone(), @@ -250,12 +173,12 @@ fn build_graph(crates: &BTreeMap) -> (Graph, HashMa }; for krate in crates.values() { - get_or_insert_node(krate.id.clone(), &mut graph, &mut node_indices); + get_or_insert_node(krate.name.clone(), &mut graph, &mut node_indices); } for krate in crates.values() { // Insert crate node if not exists - let crate_idx = get_or_insert_node(krate.id.clone(), &mut graph, &mut node_indices); + let crate_idx = get_or_insert_node(krate.name.clone(), &mut graph, &mut node_indices); // Insert dependencies and connect edges for dep in krate.dependencies.iter() { @@ -270,14 +193,10 @@ fn build_graph(crates: &BTreeMap) -> (Graph, HashMa fn main() -> Result<()> { let args = Args::parse(); - let root = args.repo.canonicalize()?; //.expect("Invalid root crate path"); + let root = args.repo.canonicalize()?; let mut crates = list_crates(&root)?; - //println!("Crates: {:?}", crates); let (mut graph, indices) = build_graph(&crates); - // use petgraph::dot::{Config, Dot}; - // println!("{:?}", Dot::with_config(&graph, &[Config::EdgeNoLabel])); - match args.command { Command::List => { let ordered = petgraph::algo::toposort(&graph, None).unwrap(); @@ -287,10 +206,11 @@ fn main() -> Result<()> { let mut bfs = Bfs::new(&graph, *node); while let Some(node) = bfs.next(&graph) { let weight = graph.node_weight(node).unwrap(); - if weight.name == start.name { - println!("+ {}-{}", weight.name, weight.version); + let c = crates.get(weight).unwrap(); + if weight == start { + println!("+ {}-{}", weight, c.version); } else { - println!("|- {}-{}", weight.name, weight.version); + println!("|- {}-{}", weight, c.version); } } println!(""); @@ -298,62 +218,44 @@ fn main() -> Result<()> { } } Command::Dependencies { crate_name } => { - let idx = indices - .get(&CrateId { - name: crate_name.clone(), - version: "".to_string(), - }) - .expect("unable to find crate in tree"); + let idx = indices.get(&crate_name).expect("unable to find crate in tree"); let mut bfs = Bfs::new(&graph, *idx); while let Some(node) = bfs.next(&graph) { let weight = graph.node_weight(node).unwrap(); - if weight.name == crate_name { - println!("+ {}-{}", weight.name, weight.version); + let crt = crates.get(weight).unwrap(); + if *weight == crate_name { + println!("+ {}-{}", weight, crt.version); } else { - println!("|- {}-{}", weight.name, weight.version); + println!("|- {}-{}", weight, crt.version); } } } Command::Dependents { crate_name } => { - let idx = indices - .get(&CrateId { - name: crate_name.clone(), - version: "".to_string(), - }) - .expect("unable to find crate in tree"); - let node = graph.node_weight(*idx).unwrap(); - println!("+ {}-{}", node.name, node.version); + let idx = indices.get(&crate_name).expect("unable to find crate in tree"); + let weight = graph.node_weight(*idx).unwrap(); + let crt = crates.get(weight).unwrap(); + println!("+ {}-{}", weight, crt.version); for parent in graph.neighbors_directed(*idx, Direction::Incoming) { let weight = graph.node_weight(parent).unwrap(); - println!("|- {}-{}", weight.name, weight.version); + let crt = crates.get(weight).unwrap(); + println!("|- {}-{}", weight, crt.version); } } Command::SemverCheck { crate_name } => { - let c = crates - .get(&CrateId { - name: crate_name.to_string(), - version: "".to_string(), - }) - .unwrap(); + let c = crates.get(&crate_name).unwrap(); check_semver(&c)?; } Command::PrepareRelease { crate_name } => { - let start = indices - .get(&CrateId { - name: crate_name.clone(), - version: "".to_string(), - }) - .expect("unable to find crate in tree"); - + let start = indices.get(&crate_name).expect("unable to find crate in tree"); graph.reverse(); let mut bfs = Bfs::new(&graph, *start); while let Some(node) = bfs.next(&graph) { let weight = graph.node_weight(node).unwrap(); - println!("Preparing {}", weight.name); + println!("Preparing {}", weight); let mut c = crates.get_mut(weight).unwrap(); - let ver = semver::Version::parse(&c.id.version)?; + let ver = semver::Version::parse(&c.version)?; let newver = if let Err(_) = check_semver(&c) { println!("Semver check failed, bumping minor!"); semver::Version::new(ver.major, ver.minor + 1, 0) @@ -361,12 +263,7 @@ fn main() -> Result<()> { semver::Version::new(ver.major, ver.minor, ver.patch + 1) }; - println!( - "Updating {} from {} -> {}", - weight.name, - c.id.version, - newver.to_string() - ); + println!("Updating {} from {} -> {}", weight, c.version, newver.to_string()); let newver = newver.to_string(); update_version(&mut c, &newver)?; @@ -377,7 +274,7 @@ fn main() -> Result<()> { while let Some(dep_node) = bfs.next(&graph) { let dep_weight = graph.node_weight(dep_node).unwrap(); let dep = crates.get(dep_weight).unwrap(); - update_versions(dep, &c.id, &newver)?; + update_versions(dep, &c.name, &newver)?; } // Update changelog @@ -394,7 +291,8 @@ fn main() -> Result<()> { let mut bfs = Bfs::new(&graph, *start); while let Some(node) = bfs.next(&graph) { let weight = graph.node_weight(node).unwrap(); - println!("git tag {}-v{}", weight.name, weight.version); + let c = crates.get(weight).unwrap(); + println!("git tag {}-v{}", weight, c.version); } println!(""); diff --git a/release/src/types.rs b/release/src/types.rs new file mode 100644 index 000000000..56a886e6f --- /dev/null +++ b/release/src/types.rs @@ -0,0 +1,33 @@ +use serde::Deserialize; +use std::collections::{BTreeMap, HashMap}; +use std::path::PathBuf; + +#[derive(Debug, Deserialize)] +pub struct ParsedCrate { + pub package: ParsedPackage, + pub dependencies: BTreeMap, +} + +#[derive(Debug, Deserialize)] +pub struct ParsedPackage { + pub name: String, + pub version: String, +} + +#[derive(Debug, Clone, Deserialize)] +pub struct CrateConfig { + pub features: Option>, + pub target: Option, +} + +pub type ReleaseConfig = HashMap; +pub type CrateId = String; + +#[derive(Debug, Clone)] +pub struct Crate { + pub name: String, + pub version: String, + pub path: PathBuf, + pub config: CrateConfig, + pub dependencies: Vec, +} -- cgit From 864d29bfe1475d52e7da6385ee8123b41184c833 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 15 Aug 2025 13:30:21 +0200 Subject: fix: update --- release/Cargo.toml | 7 ++ release/config.toml | 2 +- release/src/cargo.rs | 194 ++++++++++++++++++++++++++++++++++++++++++++ release/src/main.rs | 52 +++++------- release/src/semver_check.rs | 110 +++++++++++++++++++++++++ 5 files changed, 334 insertions(+), 31 deletions(-) create mode 100644 release/src/cargo.rs create mode 100644 release/src/semver_check.rs diff --git a/release/Cargo.toml b/release/Cargo.toml index 52ca01c2e..461021e0a 100644 --- a/release/Cargo.toml +++ b/release/Cargo.toml @@ -14,3 +14,10 @@ anyhow = "1" petgraph = "0.8.2" semver = "1.0.26" cargo-semver-checks = "0.43.0" +log = "0.4" +simple_logger = "5.0.0" +temp-file = "0.1.9" +flate2 = "1.1.1" + +[patch.crates-io] +cargo-semver-checks = { path = "../../cargo-semver-checks" } diff --git a/release/config.toml b/release/config.toml index 6b23217fa..f572b450c 100644 --- a/release/config.toml +++ b/release/config.toml @@ -27,7 +27,7 @@ embassy-net-ppp = { } embassy-net-esp-hosted = {} embassy-net-driver-channel = {} embassy-net-wiznet = {} -embassy-net-nrf91 = { features = ["defmt", "nrf9160"] } +embassy-net-nrf91 = { features = ["defmt", "nrf-pac/nrf9160"] } embassy-net-driver = {} embassy-net-tuntap = {} embassy-net-adin1110 = {} diff --git a/release/src/cargo.rs b/release/src/cargo.rs new file mode 100644 index 000000000..1a4f79f20 --- /dev/null +++ b/release/src/cargo.rs @@ -0,0 +1,194 @@ +//! Tools for working with Cargo. + +use std::{ + ffi::OsStr, + path::{Path, PathBuf}, + process::{Command, Stdio}, +}; + +use anyhow::{bail, Context as _, Result}; +use clap::ValueEnum as _; +use serde::{Deserialize, Serialize}; +use toml_edit::{DocumentMut, Formatted, Item, Value}; + +use crate::{windows_safe_path, Crate}; + +#[derive(Clone, Debug, PartialEq)] +pub enum CargoAction { + Build(PathBuf), + Run, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Artifact { + pub executable: PathBuf, +} + +/// Execute cargo with the given arguments and from the specified directory. +pub fn run(args: &[String], cwd: &Path) -> Result<()> { + run_with_env::<[(&str, &str); 0], _, _>(args, cwd, [], false)?; + Ok(()) +} + +/// Execute cargo with the given arguments and from the specified directory. +pub fn run_with_env(args: &[String], cwd: &Path, envs: I, capture: bool) -> Result +where + I: IntoIterator + core::fmt::Debug, + K: AsRef, + V: AsRef, +{ + if !cwd.is_dir() { + bail!("The `cwd` argument MUST be a directory"); + } + + // Make sure to not use a UNC as CWD! + // That would make `OUT_DIR` a UNC which will trigger things like the one fixed in https://github.com/dtolnay/rustversion/pull/51 + // While it's fixed in `rustversion` it's not fixed for other crates we are + // using now or in future! + let cwd = windows_safe_path(cwd); + + println!( + "Running `cargo {}` in {:?} - Environment {:?}", + args.join(" "), + cwd, + envs + ); + + let mut command = Command::new(get_cargo()); + + command + .args(args) + .current_dir(cwd) + .envs(envs) + .stdout(if capture { Stdio::piped() } else { Stdio::inherit() }) + .stderr(if capture { Stdio::piped() } else { Stdio::inherit() }); + + if args.iter().any(|a| a.starts_with('+')) { + // Make sure the right cargo runs + command.env_remove("CARGO"); + } + + let output = command.stdin(Stdio::inherit()).output()?; + + // Make sure that we return an appropriate exit code here, as Github Actions + // requires this in order to function correctly: + if output.status.success() { + Ok(String::from_utf8_lossy(&output.stdout).to_string()) + } else { + bail!("Failed to execute cargo subcommand `cargo {}`", args.join(" "),) + } +} + +fn get_cargo() -> String { + // On Windows when executed via `cargo run` (e.g. via the xtask alias) the + // `cargo` on the search path is NOT the cargo-wrapper but the `cargo` from the + // toolchain - that one doesn't understand `+toolchain` + #[cfg(target_os = "windows")] + let cargo = if let Ok(cargo) = std::env::var("CARGO_HOME") { + format!("{cargo}/bin/cargo") + } else { + String::from("cargo") + }; + + #[cfg(not(target_os = "windows"))] + let cargo = String::from("cargo"); + + cargo +} + +#[derive(Debug, Default)] +pub struct CargoArgsBuilder { + toolchain: Option, + subcommand: String, + target: Option, + features: Vec, + args: Vec, +} + +impl CargoArgsBuilder { + #[must_use] + pub fn toolchain(mut self, toolchain: S) -> Self + where + S: Into, + { + self.toolchain = Some(toolchain.into()); + self + } + + #[must_use] + pub fn subcommand(mut self, subcommand: S) -> Self + where + S: Into, + { + self.subcommand = subcommand.into(); + self + } + + #[must_use] + pub fn target(mut self, target: S) -> Self + where + S: Into, + { + self.target = Some(target.into()); + self + } + + #[must_use] + pub fn features(mut self, features: &[String]) -> Self { + self.features = features.to_vec(); + self + } + + #[must_use] + pub fn arg(mut self, arg: S) -> Self + where + S: Into, + { + self.args.push(arg.into()); + self + } + + #[must_use] + pub fn args(mut self, args: &[S]) -> Self + where + S: Clone + Into, + { + for arg in args { + self.args.push(arg.clone().into()); + } + self + } + + pub fn add_arg(&mut self, arg: S) -> &mut Self + where + S: Into, + { + self.args.push(arg.into()); + self + } + + #[must_use] + pub fn build(&self) -> Vec { + let mut args = vec![]; + + if let Some(ref toolchain) = self.toolchain { + args.push(format!("+{toolchain}")); + } + + args.push(self.subcommand.clone()); + + if let Some(ref target) = self.target { + args.push(format!("--target={target}")); + } + + if !self.features.is_empty() { + args.push(format!("--features={}", self.features.join(","))); + } + + for arg in self.args.iter() { + args.push(arg.clone()); + } + + args + } +} diff --git a/release/src/main.rs b/release/src/main.rs index 769611c78..0dbcc5d45 100644 --- a/release/src/main.rs +++ b/release/src/main.rs @@ -1,3 +1,4 @@ +use simple_logger::SimpleLogger; use std::collections::{BTreeMap, HashMap}; use std::fs; use std::path::{Path, PathBuf}; @@ -11,6 +12,8 @@ use petgraph::{Directed, Direction}; use toml_edit::{DocumentMut, Item, Value}; use types::*; +mod cargo; +mod semver_check; mod types; /// Tool to traverse and operate on intra-repo Rust crate dependencies @@ -70,7 +73,7 @@ fn load_release_config(repo: &Path) -> ReleaseConfig { } fn update_version(c: &mut Crate, new_version: &str) -> Result<()> { - let path = &c.path; + let path = c.path.join("Cargo.toml"); c.version = new_version.to_string(); let content = fs::read_to_string(&path)?; let mut doc: DocumentMut = content.parse()?; @@ -84,7 +87,7 @@ fn update_version(c: &mut Crate, new_version: &str) -> Result<()> { } fn update_versions(to_update: &Crate, dep: &CrateId, new_version: &str) -> Result<()> { - let path = &to_update.path; + let path = to_update.path.join("Cargo.toml"); let content = fs::read_to_string(&path)?; let mut doc: DocumentMut = content.parse()?; let mut changed = false; @@ -117,15 +120,16 @@ fn update_versions(to_update: &Crate, dep: &CrateId, new_version: &str) -> Resul Ok(()) } -fn list_crates(path: &PathBuf) -> Result> { - let d = std::fs::read_dir(path)?; - let release_config = load_release_config(path); +fn list_crates(root: &PathBuf) -> Result> { + let d = std::fs::read_dir(root)?; + let release_config = load_release_config(root); let mut crates = BTreeMap::new(); for c in d { let entry = c?; let name = entry.file_name().to_str().unwrap().to_string(); if entry.file_type()?.is_dir() && name.starts_with("embassy-") { - let entry = entry.path().join("Cargo.toml"); + let path = root.join(entry.path()); + let entry = path.join("Cargo.toml"); if entry.exists() { let content = fs::read_to_string(&entry)?; let parsed: ParsedCrate = toml::from_str(&content)?; @@ -138,7 +142,6 @@ fn list_crates(path: &PathBuf) -> Result> { } } - let path = path.join(entry); if let Some(config) = release_config.get(&id) { crates.insert( id.clone(), @@ -191,6 +194,7 @@ fn build_graph(crates: &BTreeMap) -> (Graph, HashMa } fn main() -> Result<()> { + SimpleLogger::new().init().unwrap(); let args = Args::parse(); let root = args.repo.canonicalize()?; @@ -306,7 +310,7 @@ fn main() -> Result<()> { let mut args: Vec = vec![ "publish".to_string(), "--manifest-path".to_string(), - c.path.display().to_string(), + c.path.join("Cargo.toml").display().to_string(), ]; if let Some(features) = &c.config.features { @@ -337,26 +341,9 @@ fn main() -> Result<()> { } fn check_semver(c: &Crate) -> Result<()> { - let mut args: Vec = vec![ - "semver-checks".to_string(), - "--manifest-path".to_string(), - c.path.display().to_string(), - "--default-features".to_string(), - ]; - if let Some(features) = &c.config.features { - args.push("--features".into()); - args.push(features.join(",")); - } - - let status = ProcessCommand::new("cargo").args(&args).output()?; - - println!("{}", core::str::from_utf8(&status.stdout).unwrap()); - eprintln!("{}", core::str::from_utf8(&status.stderr).unwrap()); - if !status.status.success() { - return Err(anyhow!("semver check failed")); - } else { - Ok(()) - } + let min_version = semver_check::minimum_update(c)?; + println!("Version should be bumped to {:?}", min_version); + Ok(()) } fn update_changelog(repo: &Path, c: &Crate) -> Result<()> { @@ -366,7 +353,7 @@ fn update_changelog(repo: &Path, c: &Crate) -> Result<()> { "--config".to_string(), repo.join("release").join("release.toml").display().to_string(), "--manifest-path".to_string(), - c.path.display().to_string(), + c.path.join("Cargo.toml").display().to_string(), "--execute".to_string(), "--no-confirm".to_string(), ]; @@ -386,7 +373,7 @@ fn publish_release(_repo: &Path, c: &Crate, push: bool) -> Result<()> { let mut args: Vec = vec![ "publish".to_string(), "--manifest-path".to_string(), - c.path.display().to_string(), + c.path.join("Cargo.toml").display().to_string(), ]; if let Some(features) = &c.config.features { @@ -415,3 +402,8 @@ fn publish_release(_repo: &Path, c: &Crate, push: bool) -> Result<()> { Ok(()) } } + +/// Make the path "Windows"-safe +pub fn windows_safe_path(path: &Path) -> PathBuf { + PathBuf::from(path.to_str().unwrap().to_string().replace("\\\\?\\", "")) +} diff --git a/release/src/semver_check.rs b/release/src/semver_check.rs new file mode 100644 index 000000000..b43164334 --- /dev/null +++ b/release/src/semver_check.rs @@ -0,0 +1,110 @@ +use std::fs; +use std::io::Write; +use std::path::{Path, PathBuf}; + +use cargo_semver_checks::{Check, GlobalConfig, ReleaseType, Rustdoc}; + +use crate::cargo::CargoArgsBuilder; +use crate::types::Crate; +use crate::windows_safe_path; + +/// Return the minimum required bump for the next release. +/// Even if nothing changed this will be [ReleaseType::Patch] +pub fn minimum_update(krate: &Crate) -> Result { + println!("Crate = {:?}", krate); + + let package_name = krate.name.clone(); + let package_path = krate.path.clone(); + let current_path = build_doc_json(krate)?; + + let baseline = Rustdoc::from_registry_latest_crate_version(); + let doc = Rustdoc::from_path(¤t_path); + let mut semver_check = Check::new(doc); + semver_check.with_default_features(); + semver_check.set_baseline(baseline); + semver_check.set_packages(vec![package_name]); + if let Some(features) = &krate.config.features { + let extra_current_features = features.clone(); + let extra_baseline_features = features.clone(); + semver_check.set_extra_features(extra_current_features, extra_baseline_features); + } + if let Some(target) = &krate.config.target { + semver_check.set_build_target(target.clone()); + } + let mut cfg = GlobalConfig::new(); + cfg.set_log_level(Some(log::Level::Trace)); + let result = semver_check.check_release(&mut cfg)?; + log::info!("Result {:?}", result); + + let mut min_required_update = ReleaseType::Patch; + for (_, report) in result.crate_reports() { + if let Some(required_bump) = report.required_bump() { + let required_is_stricter = + (min_required_update == ReleaseType::Patch) || (required_bump == ReleaseType::Major); + if required_is_stricter { + min_required_update = required_bump; + } + } + } + + Ok(min_required_update) +} + +pub(crate) fn build_doc_json(krate: &Crate) -> Result { + let target_dir = std::env::var("CARGO_TARGET_DIR"); + + let target_path = if let Ok(target) = target_dir { + PathBuf::from(target) + } else { + PathBuf::from(&krate.path).join("target") + }; + + let current_path = target_path; + let current_path = if let Some(target) = &krate.config.target { + current_path.join(target.clone()) + } else { + current_path + }; + let current_path = current_path + .join("doc") + .join(format!("{}.json", krate.name.to_string().replace("-", "_"))); + + std::fs::remove_file(¤t_path).ok(); + let features = if let Some(features) = &krate.config.features { + features.clone() + } else { + vec![] + }; + + log::info!("Building doc json for {} with features: {:?}", krate.name, features); + + let envs = vec![( + "RUSTDOCFLAGS", + "--cfg docsrs --cfg not_really_docsrs --cfg semver_checks", + )]; + + // always use `specific nightly` toolchain so we don't have to deal with potentially + // different versions of the doc-json + let cargo_builder = CargoArgsBuilder::default() + .toolchain("nightly-2025-06-29") + .subcommand("rustdoc") + .features(&features); + let cargo_builder = if let Some(target) = &krate.config.target { + cargo_builder.target(target.clone()) + } else { + cargo_builder + }; + + let cargo_builder = cargo_builder + .arg("-Zunstable-options") + .arg("-Zhost-config") + .arg("-Ztarget-applies-to-host") + .arg("--lib") + .arg("--output-format=json") + .arg("-Zbuild-std=alloc,core") + .arg("--config=host.rustflags=[\"--cfg=instability_disable_unstable_docs\"]"); + let cargo_args = cargo_builder.build(); + log::debug!("{cargo_args:#?}"); + crate::cargo::run_with_env(&cargo_args, &krate.path, envs, false)?; + Ok(current_path) +} -- cgit From a434401322e4e7af64ea7077ce2e4af685eac3d5 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 15 Aug 2025 14:28:02 +0200 Subject: fix: reference project dir --- release/src/semver_check.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/src/semver_check.rs b/release/src/semver_check.rs index b43164334..7b2e50672 100644 --- a/release/src/semver_check.rs +++ b/release/src/semver_check.rs @@ -18,7 +18,7 @@ pub fn minimum_update(krate: &Crate) -> Result { let current_path = build_doc_json(krate)?; let baseline = Rustdoc::from_registry_latest_crate_version(); - let doc = Rustdoc::from_path(¤t_path); + let doc = Rustdoc::from_root(&package_path); let mut semver_check = Check::new(doc); semver_check.with_default_features(); semver_check.set_baseline(baseline); -- cgit From 7579ca4ac7de39a4d48cfa3dca0011ebe56eeb35 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 15 Aug 2025 14:29:13 +0200 Subject: fix: reenable --- release/config.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/release/config.toml b/release/config.toml index f572b450c..014c73a91 100644 --- a/release/config.toml +++ b/release/config.toml @@ -4,12 +4,12 @@ embassy-nrf = { features = ["nrf52840", "time", "defmt", "unstable-pac", "gpiote embassy-rp = { features = ["defmt", "unstable-pac", "time-driver", "rp2040"], target = "thumbv6m-none-eabi" } cyw43 = { features = ["defmt", "firmware-logs"], target = "thumbv6m-none-eabi" } -#cyw43-pio = { features = ["defmt", "embassy-rp/rp2040"], target = "thumbv6m-none-eabi" } +cyw43-pio = { features = ["defmt", "embassy-rp/rp2040"], target = "thumbv6m-none-eabi" } embassy-boot = { features = ["defmt"] } -#embassy-boot-nrf = { features = ["defmt", "embassy-nrf/nrf52840"], target = "thumbv7em-none-eabihf" } -#embassy-boot-rp = { features = ["defmt", "embassy-rp/rp2040"], target = "thumbv6m-none-eabi" } -#embassy-boot-stm32 = { features = ["defmt", "embassy-stm32/stm32f429zi"], target = "thumbv7em-none-eabi" } +embassy-boot-nrf = { features = ["defmt", "embassy-nrf/nrf52840"], target = "thumbv7em-none-eabihf" } +embassy-boot-rp = { features = ["defmt", "embassy-rp/rp2040"], target = "thumbv6m-none-eabi" } +embassy-boot-stm32 = { features = ["defmt", "embassy-stm32/stm32f429zi"], target = "thumbv7em-none-eabi" } embassy-time = { features = ["defmt", "std"] } embassy-time-driver = { } -- cgit From 3f21c9022396fb2f77b4521dda67728520b999a9 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 15 Aug 2025 14:34:29 +0200 Subject: add missing changelogs --- embassy-boot-nrf/CHANGELOG.md | 13 +++++++++++++ embassy-boot-rp/CHANGELOG.md | 13 +++++++++++++ embassy-boot-stm32/CHANGELOG.md | 13 +++++++++++++ embassy-hal-internal/CHANGELOG.md | 13 +++++++++++++ 4 files changed, 52 insertions(+) create mode 100644 embassy-boot-nrf/CHANGELOG.md create mode 100644 embassy-boot-rp/CHANGELOG.md create mode 100644 embassy-boot-stm32/CHANGELOG.md create mode 100644 embassy-hal-internal/CHANGELOG.md diff --git a/embassy-boot-nrf/CHANGELOG.md b/embassy-boot-nrf/CHANGELOG.md new file mode 100644 index 000000000..c78923a93 --- /dev/null +++ b/embassy-boot-nrf/CHANGELOG.md @@ -0,0 +1,13 @@ +# Changelog + +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). + + +## Unreleased - ReleaseDate + +## 0.1.1 - 2025-08-15 + +- First release with changelog. diff --git a/embassy-boot-rp/CHANGELOG.md b/embassy-boot-rp/CHANGELOG.md new file mode 100644 index 000000000..c78923a93 --- /dev/null +++ b/embassy-boot-rp/CHANGELOG.md @@ -0,0 +1,13 @@ +# Changelog + +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). + + +## Unreleased - ReleaseDate + +## 0.1.1 - 2025-08-15 + +- First release with changelog. diff --git a/embassy-boot-stm32/CHANGELOG.md b/embassy-boot-stm32/CHANGELOG.md new file mode 100644 index 000000000..c78923a93 --- /dev/null +++ b/embassy-boot-stm32/CHANGELOG.md @@ -0,0 +1,13 @@ +# Changelog + +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). + + +## Unreleased - ReleaseDate + +## 0.1.1 - 2025-08-15 + +- First release with changelog. diff --git a/embassy-hal-internal/CHANGELOG.md b/embassy-hal-internal/CHANGELOG.md new file mode 100644 index 000000000..c78923a93 --- /dev/null +++ b/embassy-hal-internal/CHANGELOG.md @@ -0,0 +1,13 @@ +# Changelog + +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). + + +## Unreleased - ReleaseDate + +## 0.1.1 - 2025-08-15 + +- First release with changelog. -- cgit From 9f12852c389d65a8b2e252e027f69dfef2383736 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 15 Aug 2025 15:30:14 +0200 Subject: Read crate configs from metadata. --- cyw43-pio/Cargo.toml | 5 ++ cyw43/Cargo.toml | 11 +++++ embassy-boot-nrf/Cargo.toml | 11 +++++ embassy-boot-rp/Cargo.toml | 6 +++ embassy-boot-stm32/Cargo.toml | 6 +++ embassy-embedded-hal/Cargo.toml | 7 +++ embassy-executor/Cargo.toml | 20 ++++++++ embassy-imxrt/Cargo.toml | 6 +++ embassy-mspm0/Cargo.toml | 16 +++++++ embassy-net/Cargo.toml | 15 ++++++ embassy-nrf/Cargo.toml | 30 ++++++++++++ embassy-nxp/Cargo.toml | 7 +++ embassy-rp/Cargo.toml | 11 +++++ embassy-stm32/Cargo.toml | 93 +++++++++++++++++++++++++++++++++++++ embassy-sync/Cargo.toml | 5 ++ embassy-time-queue-utils/Cargo.toml | 6 +++ embassy-time/Cargo.toml | 6 +++ embassy-usb/Cargo.toml | 11 +++++ release/Cargo.toml | 7 ++- release/config.toml | 46 ------------------ release/src/main.rs | 55 +++++++++------------- release/src/semver_check.rs | 14 ++---- release/src/types.rs | 27 +++++++++-- 23 files changed, 325 insertions(+), 96 deletions(-) delete mode 100644 release/config.toml diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index a45adeccb..91b1df5fa 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -15,6 +15,11 @@ embassy-rp = { version = "0.7.0", path = "../embassy-rp" } fixed = "1.23.1" defmt = { version = "1.0.1", optional = true } +[package.metadata.embassy] +build = [ + {target = "thumbv6m-none-eabi", features = ["embassy-rp/rp2040"]}, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/cyw43-pio-v$VERSION/cyw43-pio/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/cyw43-pio/src/" diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index 94d9ef3eb..74660b1d9 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -38,6 +38,17 @@ heapless = "0.8.0" embedded-io-async = { version = "0.6.0", optional = true } bt-hci = { version = "0.4.0", optional = true } +[package.metadata.embassy] +build = [ + {target = "thumbv6m-none-eabi", features = []}, + {target = "thumbv6m-none-eabi", features = ["log"]}, + {target = "thumbv6m-none-eabi", features = ["defmt"]}, + {target = "thumbv6m-none-eabi", features = ["firmware-logs", "log"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "firmware-logs"]}, + {target = "thumbv6m-none-eabi", features = ["bluetooth", "firmware-logs", "log"]}, + {target = "thumbv6m-none-eabi", features = ["bluetooth", "defmt", "firmware-logs"]}, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/cyw43-v$VERSION/cyw43/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/cyw43/src/" diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index f89561066..017eadab9 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -12,6 +12,17 @@ categories = [ "asynchronous", ] +[package.metadata.embassy] +build = [ + {target = "thumbv7em-none-eabi", features = ["embassy-nrf/nrf52840"]}, + {target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf5340-app-s"]}, + {target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns"]}, + {target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns"]}, + {target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns"]}, + {target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns"]}, +] + + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-nrf-v$VERSION/embassy-boot-nrf/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-boot-nrf/src/" diff --git a/embassy-boot-rp/Cargo.toml b/embassy-boot-rp/Cargo.toml index 5fe376645..aee5d670d 100644 --- a/embassy-boot-rp/Cargo.toml +++ b/embassy-boot-rp/Cargo.toml @@ -12,6 +12,12 @@ categories = [ "asynchronous", ] +[package.metadata.embassy] +build = [ + {target = "thumbv6m-none-eabi", features = ["embassy-rp/rp2040"]}, +] + + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-rp-v$VERSION/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-boot-rp/src/" diff --git a/embassy-boot-stm32/Cargo.toml b/embassy-boot-stm32/Cargo.toml index b1087da1c..c2cf0c596 100644 --- a/embassy-boot-stm32/Cargo.toml +++ b/embassy-boot-stm32/Cargo.toml @@ -12,6 +12,12 @@ categories = [ "asynchronous", ] +[package.metadata.embassy] +build = [ + {target = "thumbv7em-none-eabi", features = ["embassy-stm32/stm32l496zg"]}, +] + + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-stm32-v$VERSION/embassy-boot-stm32/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-boot-stm32/src/" diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index 73eb19c39..a1f9e168b 100644 --- a/embassy-embedded-hal/Cargo.toml +++ b/embassy-embedded-hal/Cargo.toml @@ -12,6 +12,13 @@ categories = [ "asynchronous", ] +[package.metadata.embassy] +build = [ + {target = "thumbv7em-none-eabi", features = []}, + {target = "thumbv7em-none-eabi", features = ["time"]}, +] + + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-embedded-hal-v$VERSION/embassy-embedded-hal/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-embedded-hal/src/" diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index bff13de56..7da807906 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -12,6 +12,26 @@ categories = [ "asynchronous", ] +[package.metadata.embassy] +build = [ + {target = "thumbv7em-none-eabi", features = []}, + {target = "thumbv7em-none-eabi", features = ["log"]}, + {target = "thumbv7em-none-eabi", features = ["defmt"]}, + {target = "thumbv6m-none-eabi", features = ["defmt"]}, + {target = "thumbv6m-none-eabi", features = ["arch-cortex-m", "defmt", "executor-interrupt", "executor-thread"]}, + {target = "thumbv7em-none-eabi", features = ["arch-cortex-m"]}, + {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "rtos-trace"]}, + {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-thread"]}, + {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt"]}, + {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread"]}, + {target = "armv7a-none-eabi", features = ["arch-cortex-ar", "executor-thread"]}, + {target = "armv7r-none-eabi", features = ["arch-cortex-ar", "executor-thread"]}, + {target = "armv7r-none-eabihf", features = ["arch-cortex-ar", "executor-thread"]}, + {target = "riscv32imac-unknown-none-elf", features = ["arch-riscv32"]}, + {target = "riscv32imac-unknown-none-elf", features = ["arch-riscv32", "executor-thread"]}, +] + + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-v$VERSION/embassy-executor/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor/src/" diff --git a/embassy-imxrt/Cargo.toml b/embassy-imxrt/Cargo.toml index 466d5dc2c..5e94dbbc4 100644 --- a/embassy-imxrt/Cargo.toml +++ b/embassy-imxrt/Cargo.toml @@ -9,6 +9,12 @@ categories = ["embedded", "hardware-support", "no-std", "asynchronous"] repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/embassy-imxrt" +[package.metadata.embassy] +build = [ + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "mimxrt633s", "time", "time-driver-rtc", "unstable-pac"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "mimxrt685s", "time", "time-driver-rtc", "unstable-pac"]}, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-imxrt-v$VERSION/embassy-imxrt/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-imxrt/src/" diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index 221026b26..d13f16eff 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -9,6 +9,22 @@ categories = ["embedded", "hardware-support", "no-std", "asynchronous"] repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/embassy-mspm0" +[package.metadata.embassy] +build = [ + {target = "thumbv6m-none-eabi", features = ["defmt", "mspm0c1104dgs20", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "mspm0g3507pm", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "mspm0g3519pz", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "mspm0l1306rhb", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "mspm0l2228pn", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "mspm0l1345dgs28", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "mspm0l1106dgs28", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "mspm0l1228pm", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "mspm0g1107ycj", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "mspm0g3105rhb", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "mspm0g1505pt", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "mspm0g1519rhb", "time-driver-any"]}, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-mspm0-v$VERSION/embassy-mspm0/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-mspm0/src/" diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index babd63157..446e58489 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -13,6 +13,21 @@ categories = [ "network-programming", ] +[package.metadata.embassy] +build = [ + {target = "thumbv7em-none-eabi", features = ["defmt", "dns", "medium-ethernet", "packet-trace", "proto-ipv4", "tcp", "udp"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "dns", "medium-ethernet", "multicast", "proto-ipv4", "tcp", "udp"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "dhcpv4", "dns", "medium-ethernet", "tcp", "udp"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "dhcpv4", "dhcpv4-hostname", "dns", "medium-ethernet", "tcp", "udp"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "dns", "medium-ethernet", "proto-ipv6", "tcp", "udp"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "dns", "medium-ieee802154", "proto-ipv6", "tcp", "udp"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "dns", "medium-ethernet", "medium-ieee802154", "proto-ipv6", "tcp", "udp"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "dns", "medium-ethernet", "proto-ipv4", "proto-ipv6", "tcp", "udp"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "dns", "medium-ip", "proto-ipv4", "proto-ipv6", "tcp", "udp"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "dns", "medium-ethernet", "medium-ip", "proto-ipv4", "proto-ipv6", "tcp", "udp"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "dns", "medium-ethernet", "medium-ieee802154", "medium-ip", "proto-ipv4", "proto-ipv6", "tcp", "udp"]}, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-v$VERSION/embassy-net/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net/src/" diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 98013aa5b..ed701dac8 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -9,6 +9,36 @@ categories = ["embedded", "hardware-support", "no-std", "asynchronous"] repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/embassy-nrf" +[package.metadata.embassy] +build = [ + {target = "thumbv6m-none-eabi", features = ["gpiote", "nrf51", "time", "time-driver-rtc1"]}, + {target = "thumbv7em-none-eabi", features = ["gpiote", "nrf52805", "time", "time-driver-rtc1"]}, + {target = "thumbv7em-none-eabi", features = ["gpiote", "nrf52810", "time", "time-driver-rtc1"]}, + {target = "thumbv7em-none-eabi", features = ["gpiote", "nrf52811", "time", "time-driver-rtc1"]}, + {target = "thumbv7em-none-eabi", features = ["gpiote", "nrf52820", "time", "time-driver-rtc1"]}, + {target = "thumbv7em-none-eabi", features = ["gpiote", "nrf52832", "reset-pin-as-gpio", "time", "time-driver-rtc1"]}, + {target = "thumbv7em-none-eabi", features = ["gpiote", "nfc-pins-as-gpio", "nrf52833", "time", "time-driver-rtc1"]}, + {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf9160-s", "time", "time-driver-rtc1"]}, + {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf9160-ns", "time", "time-driver-rtc1"]}, + {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf5340-app-s", "time", "time-driver-rtc1"]}, + {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf5340-app-ns", "time", "time-driver-rtc1"]}, + {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf5340-net", "time", "time-driver-rtc1"]}, + {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf54l15-app-s", "time", "time-driver-rtc1"]}, + {target = "thumbv8m.main-none-eabihf", features = ["gpiote", "nrf54l15-app-ns", "time", "time-driver-rtc1"]}, + {target = "thumbv7em-none-eabi", features = ["gpiote", "nrf52840", "time"]}, + {target = "thumbv7em-none-eabi", features = ["gpiote", "nrf52840", "time-driver-rtc1"]}, + {target = "thumbv7em-none-eabi", features = ["gpiote", "nrf52840", "time", "time-driver-rtc1"]}, + {target = "thumbv7em-none-eabi", features = ["gpiote", "log", "nrf52840", "time"]}, + {target = "thumbv7em-none-eabi", features = ["gpiote", "log", "nrf52840", "time-driver-rtc1"]}, + {target = "thumbv7em-none-eabi", features = ["gpiote", "log", "nrf52840", "time", "time-driver-rtc1"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "gpiote", "nrf52840", "time"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "gpiote", "nrf52840", "time-driver-rtc1"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "gpiote", "nrf52840", "time", "time-driver-rtc1"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "nrf51", "time", "time-driver-rtc1"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "nrf51", "time"]}, + {target = "thumbv6m-none-eabi", features = ["nrf51", "time"]}, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-nrf-v$VERSION/embassy-nrf/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-nrf/src/" diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 3303cabdb..68f5c98b2 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -3,6 +3,13 @@ name = "embassy-nxp" version = "0.1.0" edition = "2021" +[package.metadata.embassy] +build = [ + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "lpc55"]}, + {target = "thumbv7em-none-eabihf", features = ["defmt", "mimxrt1011", "rt", "time-driver-pit"]}, + {target = "thumbv7em-none-eabihf", features = ["defmt", "mimxrt1062", "rt", "time-driver-pit"]}, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-nxp-v$VERSION/embassy-nxp/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-nxp/src/" diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 7f2167f90..a5f84944e 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -9,6 +9,17 @@ categories = ["embedded", "hardware-support", "no-std", "asynchronous"] repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/embassy-rp" +[package.metadata.embassy] +build = [ + {target = "thumbv6m-none-eabi", features = ["defmt", "rp2040", "time-driver"]}, + {target = "thumbv6m-none-eabi", features = ["log", "rp2040", "time-driver"]}, + {target = "thumbv6m-none-eabi", features = ["intrinsics", "rp2040", "time-driver"]}, + {target = "thumbv6m-none-eabi", features = ["qspi-as-gpio", "rp2040", "time-driver"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "rp235xa", "time-driver"]}, + {target = "thumbv8m.main-none-eabihf", features = ["log", "rp235xa", "time-driver"]}, + {target = "thumbv8m.main-none-eabihf", features = ["binary-info", "rp235xa", "time-driver"]}, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-rp-v$VERSION/embassy-rp/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-rp/src/" diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 45b351acf..92d2e7fda 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -9,6 +9,99 @@ categories = ["embedded", "hardware-support", "no-std", "asynchronous"] repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/embassy-stm32" +[package.metadata.embassy] +build = [ + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "dual-bank", "exti", "stm32l552ze", "time", "time-driver-any"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "dual-bank", "stm32l552ze", "time", "time-driver-any"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "dual-bank", "exti", "stm32l552ze", "time"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "dual-bank", "stm32l552ze", "time"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "dual-bank", "exti", "stm32l552ze"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "dual-bank", "stm32l552ze"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "single-bank", "stm32l552ze"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32c071rb", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32c051f6", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32c091gb", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32c092rc", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32f038f6", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32f030c6", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32f058t8", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32f030r8", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32f031k6", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32f030rc", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32f070f6", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32f078vb", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32f042g4", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32f072c8", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f401ve", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f405zg", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f407zg", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f401ve", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f405zg", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f407zg", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f410tb", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f411ce", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f412zg", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f413vh", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f415zg", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f417zg", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f423zh", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f427zi", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["exti", "log", "stm32f429zi", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["exti", "log", "stm32f437zi", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f439zi", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f446ze", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f469zi", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f479zi", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f730i8", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32h753zi", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32h735zg", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "split-pc2", "split-pc3", "stm32h755zi-cm7", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32h725re", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32h7b3ai", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32h7b3ai", "time", "time-driver-tim1"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32h7r3z8", "time", "time-driver-tim1"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32h7r7a8", "time", "time-driver-tim1"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32h7s3a8", "time", "time-driver-tim1"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32h7s7z8", "time", "time-driver-tim1"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32l431cb", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32l476vg", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32l422cb", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32wb15cc", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32l072cz", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32l041f6", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32l051k8", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "low-power", "stm32l073cz", "time", "time-driver-any"]}, + {target = "thumbv7m-none-eabi", features = ["defmt", "exti", "stm32l151cb-a", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f303c8", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f398ve", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32f378cc", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32g0b0ce", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32g0c1ve", "time", "time-driver-any"]}, + {target = "thumbv7m-none-eabi", features = ["defmt", "exti", "stm32f217zg", "time", "time-driver-any"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "dual-bank", "exti", "low-power", "stm32l552ze", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32wl54jc-cm0p", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32wle5jb", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32g431kb", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "dual-bank", "exti", "stm32g474pe", "time", "time-driver-any"]}, + {target = "thumbv7m-none-eabi", features = ["defmt", "exti", "stm32f107vc", "time", "time-driver-any"]}, + {target = "thumbv7m-none-eabi", features = ["defmt", "exti", "stm32f103re", "time", "time-driver-any"]}, + {target = "thumbv7m-none-eabi", features = ["defmt", "exti", "stm32f100c4", "time", "time-driver-any"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32h503rb", "time", "time-driver-any"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32h523cc", "time", "time-driver-any"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32h562ag", "time", "time-driver-any"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32wba50ke", "time", "time-driver-any"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32wba55ug", "time", "time-driver-any"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32wba62cg", "time", "time-driver-any"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "low-power", "stm32wba65ri", "time", "time-driver-any"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32u5f9zj", "time", "time-driver-any"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32u5g9nj", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32wb35ce", "time", "time-driver-any"]}, + {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "low-power", "stm32wb55rg", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32u031r8", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32u073mb", "time", "time-driver-any"]}, + {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32u083rc", "time", "time-driver-any"]}, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-v$VERSION/embassy-stm32/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32/src/" diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml index e60f5e34c..e31c9a674 100644 --- a/embassy-sync/Cargo.toml +++ b/embassy-sync/Cargo.toml @@ -14,6 +14,11 @@ categories = [ "asynchronous", ] +[package.metadata.embassy] +build = [ + {target = "thumbv6m-none-eabi", features = ["defmt"]}, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-sync-v$VERSION/embassy-sync/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-sync/src/" diff --git a/embassy-time-queue-utils/Cargo.toml b/embassy-time-queue-utils/Cargo.toml index 8991da66c..2a659548e 100644 --- a/embassy-time-queue-utils/Cargo.toml +++ b/embassy-time-queue-utils/Cargo.toml @@ -52,6 +52,12 @@ generic-queue-128 = ["_generic-queue"] _generic-queue = [] +[package.metadata.embassy] +build = [ + {target = "thumbv6m-none-eabi", features = []}, + {target = "thumbv6m-none-eabi", features = ["generic-queue-8"]}, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-time-queue-utils-v$VERSION/embassy-time-queue-utils/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-time-queue-utils/src/" diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index 163dbe95f..eff8e2975 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml @@ -14,6 +14,12 @@ categories = [ "asynchronous", ] +[package.metadata.embassy] +build = [ + {target = "thumbv6m-none-eabi", features = ["defmt", "defmt-timestamp-uptime", "mock-driver"]}, + {features = ["defmt", "std"]}, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-time-v$VERSION/embassy-time/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-time/src/" diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml index 93e3e1e31..89b3c318d 100644 --- a/embassy-usb/Cargo.toml +++ b/embassy-usb/Cargo.toml @@ -9,6 +9,17 @@ categories = ["embedded", "hardware-support", "no-std", "asynchronous"] repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/embassy-usb" +[package.metadata.embassy] +build = [ + {target = "thumbv6m-none-eabi", features = []}, + {target = "thumbv6m-none-eabi", features = ["log"]}, + {target = "thumbv6m-none-eabi", features = ["defmt"]}, + {target = "thumbv6m-none-eabi", features = ["usbd-hid"]}, + {target = "thumbv6m-none-eabi", features = ["max-interface-count-1"]}, + {target = "thumbv6m-none-eabi", features = ["max-interface-count-8"]}, + {target = "thumbv6m-none-eabi", features = ["max-handler-count-8"]}, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-usb-v$VERSION/embassy-usb/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb/src/" diff --git a/release/Cargo.toml b/release/Cargo.toml index 461021e0a..3e4094eed 100644 --- a/release/Cargo.toml +++ b/release/Cargo.toml @@ -19,5 +19,8 @@ simple_logger = "5.0.0" temp-file = "0.1.9" flate2 = "1.1.1" -[patch.crates-io] -cargo-semver-checks = { path = "../../cargo-semver-checks" } +#[patch.crates-io] +#cargo-semver-checks = { path = "../../cargo-semver-checks" } + +[package.metadata.embassy] +skip = true diff --git a/release/config.toml b/release/config.toml deleted file mode 100644 index 014c73a91..000000000 --- a/release/config.toml +++ /dev/null @@ -1,46 +0,0 @@ - -embassy-stm32 = { features = ["defmt", "unstable-pac", "exti", "time-driver-any", "time", "stm32h755zi-cm7", "dual-bank"], target = "thumbv7em-none-eabi" } -embassy-nrf = { features = ["nrf52840", "time", "defmt", "unstable-pac", "gpiote", "time-driver-rtc1"], target = "thumbv7em-none-eabihf" } - -embassy-rp = { features = ["defmt", "unstable-pac", "time-driver", "rp2040"], target = "thumbv6m-none-eabi" } -cyw43 = { features = ["defmt", "firmware-logs"], target = "thumbv6m-none-eabi" } -cyw43-pio = { features = ["defmt", "embassy-rp/rp2040"], target = "thumbv6m-none-eabi" } - -embassy-boot = { features = ["defmt"] } -embassy-boot-nrf = { features = ["defmt", "embassy-nrf/nrf52840"], target = "thumbv7em-none-eabihf" } -embassy-boot-rp = { features = ["defmt", "embassy-rp/rp2040"], target = "thumbv6m-none-eabi" } -embassy-boot-stm32 = { features = ["defmt", "embassy-stm32/stm32f429zi"], target = "thumbv7em-none-eabi" } - -embassy-time = { features = ["defmt", "std"] } -embassy-time-driver = { } -embassy-time-queue-utils = { features = ["defmt"] } - -embassy-futures = { } -embassy-embedded-hal = { features = ["time"] } -embassy-hal-internal = { } -embassy-executor = { features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"], target = "thumbv7em-none-eabi" } -embassy-executor-macros = { } -embassy-sync = { } - -embassy-net = { features = ["defmt", "tcp", "udp", "raw", "dns", "icmp", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "medium-ieee802154", "multicast", "dhcpv4-hostname"] } -embassy-net-ppp = { } -embassy-net-esp-hosted = {} -embassy-net-driver-channel = {} -embassy-net-wiznet = {} -embassy-net-nrf91 = { features = ["defmt", "nrf-pac/nrf9160"] } -embassy-net-driver = {} -embassy-net-tuntap = {} -embassy-net-adin1110 = {} -embassy-net-enc28j60 = {} - -embassy-usb-driver = { } -embassy-usb-dfu = { features = ["dfu"] } -embassy-usb-synopsys-otg = { } -embassy-usb = { features = ["defmt", "usbd-hid"] } -embassy-usb-logger = { } - -# Unreleased -# embassy-stm32-wpan = {} -# embassy-imxrt = {} -# embassy-nxp = {} -# embassy-mspm0 = {} diff --git a/release/src/main.rs b/release/src/main.rs index 0dbcc5d45..a49d8f36c 100644 --- a/release/src/main.rs +++ b/release/src/main.rs @@ -1,4 +1,3 @@ -use simple_logger::SimpleLogger; use std::collections::{BTreeMap, HashMap}; use std::fs; use std::path::{Path, PathBuf}; @@ -6,9 +5,11 @@ use std::process::Command as ProcessCommand; use anyhow::{anyhow, Result}; use clap::{Parser, Subcommand}; +use log::info; use petgraph::graph::{Graph, NodeIndex}; use petgraph::visit::Bfs; use petgraph::{Directed, Direction}; +use simple_logger::SimpleLogger; use toml_edit::{DocumentMut, Item, Value}; use types::*; @@ -63,15 +64,6 @@ enum Command { }, } -fn load_release_config(repo: &Path) -> ReleaseConfig { - let config_path = repo.join("release/config.toml"); - if !config_path.exists() { - return HashMap::new(); - } - let content = fs::read_to_string(&config_path).expect("Failed to read release/config.toml"); - toml::from_str(&content).expect("Invalid TOML format in release/config.toml") -} - fn update_version(c: &mut Crate, new_version: &str) -> Result<()> { let path = c.path.join("Cargo.toml"); c.version = new_version.to_string(); @@ -122,12 +114,10 @@ fn update_versions(to_update: &Crate, dep: &CrateId, new_version: &str) -> Resul fn list_crates(root: &PathBuf) -> Result> { let d = std::fs::read_dir(root)?; - let release_config = load_release_config(root); let mut crates = BTreeMap::new(); for c in d { let entry = c?; - let name = entry.file_name().to_str().unwrap().to_string(); - if entry.file_type()?.is_dir() && name.starts_with("embassy-") { + if entry.file_type()?.is_dir() { let path = root.join(entry.path()); let entry = path.join("Cargo.toml"); if entry.exists() { @@ -135,6 +125,8 @@ fn list_crates(root: &PathBuf) -> Result> { let parsed: ParsedCrate = toml::from_str(&content)?; let id = parsed.package.name; + let metadata = &parsed.package.metadata.embassy; + let mut dependencies = Vec::new(); for (k, _) in parsed.dependencies { if k.starts_with("embassy-") { @@ -142,18 +134,19 @@ fn list_crates(root: &PathBuf) -> Result> { } } - if let Some(config) = release_config.get(&id) { - crates.insert( - id.clone(), - Crate { - name: id, - version: parsed.package.version, - path, - dependencies, - config: config.clone(), - }, - ); - } + crates.insert( + id.clone(), + Crate { + name: id, + version: parsed.package.version, + path, + dependencies, + config: metadata.build.first().cloned().unwrap_or_else(|| BuildConfig { + features: vec![], + target: None, + }), + }, + ); } } } @@ -313,10 +306,8 @@ fn main() -> Result<()> { c.path.join("Cargo.toml").display().to_string(), ]; - if let Some(features) = &c.config.features { - args.push("--features".into()); - args.push(features.join(",")); - } + args.push("--features".into()); + args.push(c.config.features.join(",")); if let Some(target) = &c.config.target { args.push("--target".into()); @@ -376,10 +367,8 @@ fn publish_release(_repo: &Path, c: &Crate, push: bool) -> Result<()> { c.path.join("Cargo.toml").display().to_string(), ]; - if let Some(features) = &c.config.features { - args.push("--features".into()); - args.push(features.join(",")); - } + args.push("--features".into()); + args.push(c.config.features.join(",")); if let Some(target) = &c.config.target { args.push("--target".into()); diff --git a/release/src/semver_check.rs b/release/src/semver_check.rs index 7b2e50672..96f8ebe2e 100644 --- a/release/src/semver_check.rs +++ b/release/src/semver_check.rs @@ -23,11 +23,9 @@ pub fn minimum_update(krate: &Crate) -> Result { semver_check.with_default_features(); semver_check.set_baseline(baseline); semver_check.set_packages(vec![package_name]); - if let Some(features) = &krate.config.features { - let extra_current_features = features.clone(); - let extra_baseline_features = features.clone(); - semver_check.set_extra_features(extra_current_features, extra_baseline_features); - } + let extra_current_features = krate.config.features.clone(); + let extra_baseline_features = krate.config.features.clone(); + semver_check.set_extra_features(extra_current_features, extra_baseline_features); if let Some(target) = &krate.config.target { semver_check.set_build_target(target.clone()); } @@ -70,11 +68,7 @@ pub(crate) fn build_doc_json(krate: &Crate) -> Result { .join(format!("{}.json", krate.name.to_string().replace("-", "_"))); std::fs::remove_file(¤t_path).ok(); - let features = if let Some(features) = &krate.config.features { - features.clone() - } else { - vec![] - }; + let features = krate.config.features.clone(); log::info!("Building doc json for {} with features: {:?}", krate.name, features); diff --git a/release/src/types.rs b/release/src/types.rs index 56a886e6f..39e8e9f48 100644 --- a/release/src/types.rs +++ b/release/src/types.rs @@ -1,7 +1,8 @@ -use serde::Deserialize; use std::collections::{BTreeMap, HashMap}; use std::path::PathBuf; +use serde::Deserialize; + #[derive(Debug, Deserialize)] pub struct ParsedCrate { pub package: ParsedPackage, @@ -12,15 +13,31 @@ pub struct ParsedCrate { pub struct ParsedPackage { pub name: String, pub version: String, + #[serde(default)] + pub metadata: Metadata, +} + +#[derive(Debug, Deserialize, Default)] +pub struct Metadata { + #[serde(default)] + pub embassy: MetadataEmbassy, +} + +#[derive(Debug, Deserialize, Default)] +pub struct MetadataEmbassy { + #[serde(default)] + pub skip: bool, + #[serde(default)] + pub build: Vec, } #[derive(Debug, Clone, Deserialize)] -pub struct CrateConfig { - pub features: Option>, +pub struct BuildConfig { + #[serde(default)] + pub features: Vec, pub target: Option, } -pub type ReleaseConfig = HashMap; pub type CrateId = String; #[derive(Debug, Clone)] @@ -28,6 +45,6 @@ pub struct Crate { pub name: String, pub version: String, pub path: PathBuf, - pub config: CrateConfig, pub dependencies: Vec, + pub config: BuildConfig, // TODO make this a vec. } -- cgit From 6df077be0663cf4e45d9573ea8fc685a9f9dcd99 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 15 Aug 2025 15:32:26 +0200 Subject: Revert "fix: reference project dir" This reverts commit 1605a71c11aa9cd995206867abb6ba7409223b18. --- release/src/semver_check.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/src/semver_check.rs b/release/src/semver_check.rs index 96f8ebe2e..e20bc8574 100644 --- a/release/src/semver_check.rs +++ b/release/src/semver_check.rs @@ -18,7 +18,7 @@ pub fn minimum_update(krate: &Crate) -> Result { let current_path = build_doc_json(krate)?; let baseline = Rustdoc::from_registry_latest_crate_version(); - let doc = Rustdoc::from_root(&package_path); + let doc = Rustdoc::from_path(¤t_path); let mut semver_check = Check::new(doc); semver_check.with_default_features(); semver_check.set_baseline(baseline); -- cgit From 2f540a4d2449234367e8d18c9e3fc8dc740d3ee5 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 15 Aug 2025 16:11:35 +0200 Subject: Add Context struct. --- release/src/build.rs | 5 ++ release/src/main.rs | 130 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 83 insertions(+), 52 deletions(-) create mode 100644 release/src/build.rs diff --git a/release/src/build.rs b/release/src/build.rs new file mode 100644 index 000000000..adf251b4d --- /dev/null +++ b/release/src/build.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub(crate) fn build(ctx: &crate::Context) -> Result<()> { + todo!() +} diff --git a/release/src/main.rs b/release/src/main.rs index a49d8f36c..25f31486a 100644 --- a/release/src/main.rs +++ b/release/src/main.rs @@ -13,6 +13,7 @@ use simple_logger::SimpleLogger; use toml_edit::{DocumentMut, Item, Value}; use types::*; +mod build; mod cargo; mod semver_check; mod types; @@ -47,6 +48,12 @@ enum Command { crate_name: String, }, + /// Build + Build { + /// Crate to check. If not specified checks all crates. + #[arg(value_name = "CRATE")] + crate_name: Option, + }, /// SemverCheck SemverCheck { /// Crate to check. Will traverse that crate an it's dependents. If not specified checks all crates. @@ -186,40 +193,55 @@ fn build_graph(crates: &BTreeMap) -> (Graph, HashMa (graph, node_indices) } +struct Context { + root: PathBuf, + crates: BTreeMap, + graph: Graph, + indices: HashMap, +} + +fn load_context(args: &Args) -> Result { + let root = args.repo.canonicalize()?; + let crates = list_crates(&root)?; + let (graph, indices) = build_graph(&crates); + + Ok(Context { + root, + crates, + graph, + indices, + }) +} + fn main() -> Result<()> { SimpleLogger::new().init().unwrap(); let args = Args::parse(); - - let root = args.repo.canonicalize()?; - let mut crates = list_crates(&root)?; - let (mut graph, indices) = build_graph(&crates); + let mut ctx = load_context(&args)?; match args.command { Command::List => { - let ordered = petgraph::algo::toposort(&graph, None).unwrap(); + let ordered = petgraph::algo::toposort(&ctx.graph, None).unwrap(); for node in ordered.iter() { - if graph.neighbors_directed(*node, Direction::Incoming).count() == 0 { - let start = graph.node_weight(*node).unwrap(); - let mut bfs = Bfs::new(&graph, *node); - while let Some(node) = bfs.next(&graph) { - let weight = graph.node_weight(node).unwrap(); - let c = crates.get(weight).unwrap(); - if weight == start { - println!("+ {}-{}", weight, c.version); - } else { - println!("|- {}-{}", weight, c.version); - } + let start = ctx.graph.node_weight(*node).unwrap(); + let mut bfs = Bfs::new(&ctx.graph, *node); + while let Some(node) = bfs.next(&ctx.graph) { + let weight = ctx.graph.node_weight(node).unwrap(); + let c = ctx.crates.get(weight).unwrap(); + if weight == start { + println!("+ {}-{}", weight, c.version); + } else { + println!("|- {}-{}", weight, c.version); } - println!(""); } + println!(""); } } Command::Dependencies { crate_name } => { - let idx = indices.get(&crate_name).expect("unable to find crate in tree"); - let mut bfs = Bfs::new(&graph, *idx); - while let Some(node) = bfs.next(&graph) { - let weight = graph.node_weight(node).unwrap(); - let crt = crates.get(weight).unwrap(); + let idx = ctx.indices.get(&crate_name).expect("unable to find crate in tree"); + let mut bfs = Bfs::new(&ctx.graph, *idx); + while let Some(node) = bfs.next(&ctx.graph) { + let weight = ctx.graph.node_weight(node).unwrap(); + let crt = ctx.crates.get(weight).unwrap(); if *weight == crate_name { println!("+ {}-{}", weight, crt.version); } else { @@ -228,30 +250,34 @@ fn main() -> Result<()> { } } Command::Dependents { crate_name } => { - let idx = indices.get(&crate_name).expect("unable to find crate in tree"); - let weight = graph.node_weight(*idx).unwrap(); - let crt = crates.get(weight).unwrap(); + let idx = ctx.indices.get(&crate_name).expect("unable to find crate in tree"); + let weight = ctx.graph.node_weight(*idx).unwrap(); + let crt = ctx.crates.get(weight).unwrap(); println!("+ {}-{}", weight, crt.version); - for parent in graph.neighbors_directed(*idx, Direction::Incoming) { - let weight = graph.node_weight(parent).unwrap(); - let crt = crates.get(weight).unwrap(); + for parent in ctx.graph.neighbors_directed(*idx, Direction::Incoming) { + let weight = ctx.graph.node_weight(parent).unwrap(); + let crt = ctx.crates.get(weight).unwrap(); println!("|- {}-{}", weight, crt.version); } } + Command::Build { crate_name } => { + build::build(&ctx)?; + } Command::SemverCheck { crate_name } => { - let c = crates.get(&crate_name).unwrap(); + let c = ctx.crates.get(&crate_name).unwrap(); check_semver(&c)?; } Command::PrepareRelease { crate_name } => { - let start = indices.get(&crate_name).expect("unable to find crate in tree"); - graph.reverse(); + let start = ctx.indices.get(&crate_name).expect("unable to find crate in tree"); + let mut rgraph = ctx.graph.clone(); + rgraph.reverse(); - let mut bfs = Bfs::new(&graph, *start); + let mut bfs = Bfs::new(&rgraph, *start); - while let Some(node) = bfs.next(&graph) { - let weight = graph.node_weight(node).unwrap(); + while let Some(node) = bfs.next(&rgraph) { + let weight = rgraph.node_weight(node).unwrap(); println!("Preparing {}", weight); - let mut c = crates.get_mut(weight).unwrap(); + let mut c = ctx.crates.get_mut(weight).unwrap(); let ver = semver::Version::parse(&c.version)?; let newver = if let Err(_) = check_semver(&c) { println!("Semver check failed, bumping minor!"); @@ -264,41 +290,41 @@ fn main() -> Result<()> { let newver = newver.to_string(); update_version(&mut c, &newver)?; - let c = crates.get(weight).unwrap(); + let c = ctx.crates.get(weight).unwrap(); // Update all nodes further down the tree - let mut bfs = Bfs::new(&graph, node); - while let Some(dep_node) = bfs.next(&graph) { - let dep_weight = graph.node_weight(dep_node).unwrap(); - let dep = crates.get(dep_weight).unwrap(); + let mut bfs = Bfs::new(&rgraph, node); + while let Some(dep_node) = bfs.next(&rgraph) { + let dep_weight = rgraph.node_weight(dep_node).unwrap(); + let dep = ctx.crates.get(dep_weight).unwrap(); update_versions(dep, &c.name, &newver)?; } // Update changelog - update_changelog(&root, &c)?; + update_changelog(&ctx.root, &c)?; } - let weight = graph.node_weight(*start).unwrap(); - let c = crates.get(weight).unwrap(); - publish_release(&root, &c, false)?; + let weight = rgraph.node_weight(*start).unwrap(); + let c = ctx.crates.get(weight).unwrap(); + publish_release(&ctx.root, &c, false)?; println!("# Please inspect changes and run the following commands when happy:"); println!("git commit -a -m 'chore: prepare crate releases'"); - let mut bfs = Bfs::new(&graph, *start); - while let Some(node) = bfs.next(&graph) { - let weight = graph.node_weight(node).unwrap(); - let c = crates.get(weight).unwrap(); + let mut bfs = Bfs::new(&rgraph, *start); + while let Some(node) = bfs.next(&rgraph) { + let weight = rgraph.node_weight(node).unwrap(); + let c = ctx.crates.get(weight).unwrap(); println!("git tag {}-v{}", weight, c.version); } println!(""); println!("# Run these commands to publish the crate and dependents:"); - let mut bfs = Bfs::new(&graph, *start); - while let Some(node) = bfs.next(&graph) { - let weight = graph.node_weight(node).unwrap(); - let c = crates.get(weight).unwrap(); + let mut bfs = Bfs::new(&rgraph, *start); + while let Some(node) = bfs.next(&rgraph) { + let weight = rgraph.node_weight(node).unwrap(); + let c = ctx.crates.get(weight).unwrap(); let mut args: Vec = vec![ "publish".to_string(), -- cgit From 648938b6623954a71ecee2990d57ce9df2e197b7 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 15 Aug 2025 16:14:34 +0200 Subject: Make crate configs a vec. --- release/src/main.rs | 24 ++++++++++++++++-------- release/src/semver_check.rs | 25 ++++++++++++------------- release/src/types.rs | 2 +- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/release/src/main.rs b/release/src/main.rs index 25f31486a..7850bbb8d 100644 --- a/release/src/main.rs +++ b/release/src/main.rs @@ -141,6 +141,14 @@ fn list_crates(root: &PathBuf) -> Result> { } } + let mut configs = metadata.build.clone(); + if configs.is_empty() { + configs.push(BuildConfig { + features: vec![], + target: None, + }) + } + crates.insert( id.clone(), Crate { @@ -148,10 +156,7 @@ fn list_crates(root: &PathBuf) -> Result> { version: parsed.package.version, path, dependencies, - config: metadata.build.first().cloned().unwrap_or_else(|| BuildConfig { - features: vec![], - target: None, - }), + configs, }, ); } @@ -332,10 +337,11 @@ fn main() -> Result<()> { c.path.join("Cargo.toml").display().to_string(), ]; + let config = c.configs.first().unwrap(); // TODO args.push("--features".into()); - args.push(c.config.features.join(",")); + args.push(config.features.join(",")); - if let Some(target) = &c.config.target { + if let Some(target) = &config.target { args.push("--target".into()); args.push(target.clone()); } @@ -387,6 +393,8 @@ fn update_changelog(repo: &Path, c: &Crate) -> Result<()> { } fn publish_release(_repo: &Path, c: &Crate, push: bool) -> Result<()> { + let config = c.configs.first().unwrap(); // TODO + let mut args: Vec = vec![ "publish".to_string(), "--manifest-path".to_string(), @@ -394,9 +402,9 @@ fn publish_release(_repo: &Path, c: &Crate, push: bool) -> Result<()> { ]; args.push("--features".into()); - args.push(c.config.features.join(",")); + args.push(config.features.join(",")); - if let Some(target) = &c.config.target { + if let Some(target) = &config.target { args.push("--target".into()); args.push(target.clone()); } diff --git a/release/src/semver_check.rs b/release/src/semver_check.rs index e20bc8574..a70c56376 100644 --- a/release/src/semver_check.rs +++ b/release/src/semver_check.rs @@ -1,21 +1,20 @@ -use std::fs; -use std::io::Write; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use cargo_semver_checks::{Check, GlobalConfig, ReleaseType, Rustdoc}; use crate::cargo::CargoArgsBuilder; -use crate::types::Crate; -use crate::windows_safe_path; +use crate::types::{BuildConfig, Crate}; /// Return the minimum required bump for the next release. /// Even if nothing changed this will be [ReleaseType::Patch] pub fn minimum_update(krate: &Crate) -> Result { println!("Crate = {:?}", krate); + let config = krate.configs.first().unwrap(); // TODO + let package_name = krate.name.clone(); let package_path = krate.path.clone(); - let current_path = build_doc_json(krate)?; + let current_path = build_doc_json(krate, config)?; let baseline = Rustdoc::from_registry_latest_crate_version(); let doc = Rustdoc::from_path(¤t_path); @@ -23,10 +22,10 @@ pub fn minimum_update(krate: &Crate) -> Result { semver_check.with_default_features(); semver_check.set_baseline(baseline); semver_check.set_packages(vec![package_name]); - let extra_current_features = krate.config.features.clone(); - let extra_baseline_features = krate.config.features.clone(); + let extra_current_features = config.features.clone(); + let extra_baseline_features = config.features.clone(); semver_check.set_extra_features(extra_current_features, extra_baseline_features); - if let Some(target) = &krate.config.target { + if let Some(target) = &config.target { semver_check.set_build_target(target.clone()); } let mut cfg = GlobalConfig::new(); @@ -48,7 +47,7 @@ pub fn minimum_update(krate: &Crate) -> Result { Ok(min_required_update) } -pub(crate) fn build_doc_json(krate: &Crate) -> Result { +pub(crate) fn build_doc_json(krate: &Crate, config: &BuildConfig) -> Result { let target_dir = std::env::var("CARGO_TARGET_DIR"); let target_path = if let Ok(target) = target_dir { @@ -58,7 +57,7 @@ pub(crate) fn build_doc_json(krate: &Crate) -> Result { }; let current_path = target_path; - let current_path = if let Some(target) = &krate.config.target { + let current_path = if let Some(target) = &config.target { current_path.join(target.clone()) } else { current_path @@ -68,7 +67,7 @@ pub(crate) fn build_doc_json(krate: &Crate) -> Result { .join(format!("{}.json", krate.name.to_string().replace("-", "_"))); std::fs::remove_file(¤t_path).ok(); - let features = krate.config.features.clone(); + let features = config.features.clone(); log::info!("Building doc json for {} with features: {:?}", krate.name, features); @@ -83,7 +82,7 @@ pub(crate) fn build_doc_json(krate: &Crate) -> Result { .toolchain("nightly-2025-06-29") .subcommand("rustdoc") .features(&features); - let cargo_builder = if let Some(target) = &krate.config.target { + let cargo_builder = if let Some(target) = &config.target { cargo_builder.target(target.clone()) } else { cargo_builder diff --git a/release/src/types.rs b/release/src/types.rs index 39e8e9f48..c5b774977 100644 --- a/release/src/types.rs +++ b/release/src/types.rs @@ -46,5 +46,5 @@ pub struct Crate { pub version: String, pub path: PathBuf, pub dependencies: Vec, - pub config: BuildConfig, // TODO make this a vec. + pub configs: Vec, } -- cgit From a34e0b1ec57350cfa1d61aa6fc2eced077be5623 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 15 Aug 2025 17:05:45 +0200 Subject: Add build command. --- embassy-net-nrf91/Cargo.toml | 5 ++++ embassy-stm32-wpan/Cargo.toml | 5 ++++ embassy-usb-dfu/Cargo.toml | 6 +++++ release/src/build.rs | 45 ++++++++++++++++++++++++++++++++++-- release/src/cargo.rs | 54 +++++++++++++++++++++++++++++++++++++++---- release/src/main.rs | 6 ++++- 6 files changed, 113 insertions(+), 8 deletions(-) diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml index 387627491..76b812efc 100644 --- a/embassy-net-nrf91/Cargo.toml +++ b/embassy-net-nrf91/Cargo.toml @@ -29,6 +29,11 @@ heapless = "0.8" embedded-io = "0.6.1" at-commands = "0.5.4" +[package.metadata.embassy] +build = [ + {target = "thumbv7em-none-eabi", features = ["defmt", "nrf-pac/nrf9160"]} +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-nrf91-v$VERSION/embassy-net-nrf91/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-nrf91/src/" diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 0932e4739..f7b20cedc 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -9,6 +9,11 @@ categories = ["embedded", "hardware-support", "no-std", "asynchronous"] repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/embassy-stm32-wpan" +[package.metadata.embassy] +build = [ + {target = "thumbv7em-none-eabi", features = ["stm32wb55rg"]}, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-wpan-v$VERSION/embassy-stm32-wpan/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32-wpan/src/" diff --git a/embassy-usb-dfu/Cargo.toml b/embassy-usb-dfu/Cargo.toml index 8d1f231ed..ce2f80b31 100644 --- a/embassy-usb-dfu/Cargo.toml +++ b/embassy-usb-dfu/Cargo.toml @@ -12,6 +12,12 @@ categories = [ "asynchronous" ] +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", features = [ "defmt", "cortex-m", "dfu" ] }, + { target = "thumbv7em-none-eabi", features = [ "defmt", "cortex-m", "application" ] }, +] + [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-usb-v$VERSION/embassy-usb-dfu/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-dfu/src/" diff --git a/release/src/build.rs b/release/src/build.rs index adf251b4d..d1abb2aa1 100644 --- a/release/src/build.rs +++ b/release/src/build.rs @@ -1,5 +1,46 @@ use anyhow::Result; -pub(crate) fn build(ctx: &crate::Context) -> Result<()> { - todo!() +use crate::cargo::{CargoArgsBuilder, CargoBatchBuilder}; + +pub(crate) fn build(ctx: &crate::Context, crate_name: Option<&str>) -> Result<()> { + let mut batch_builder = CargoBatchBuilder::new(); + + // Process either specific crate or all crates + let crates_to_build: Vec<_> = if let Some(name) = crate_name { + // Build only the specified crate + if let Some(krate) = ctx.crates.get(name) { + vec![krate] + } else { + return Err(anyhow::anyhow!("Crate '{}' not found", name)); + } + } else { + // Build all crates + ctx.crates.values().collect() + }; + + // Process selected crates and add their build configurations to the batch + for krate in crates_to_build { + for config in &krate.configs { + let mut args_builder = CargoArgsBuilder::new() + .subcommand("build") + .arg("--release") + .arg(format!("--manifest-path={}/Cargo.toml", krate.path.to_string_lossy())); + + if let Some(ref target) = config.target { + args_builder = args_builder.target(target); + } + + if !config.features.is_empty() { + args_builder = args_builder.features(&config.features); + } + + batch_builder.add_command(args_builder.build()); + } + } + + // Execute the cargo batch command + let batch_args = batch_builder.build(); + crate::cargo::run(&batch_args, &ctx.root)?; + + Ok(()) } diff --git a/release/src/cargo.rs b/release/src/cargo.rs index 1a4f79f20..0b28458e9 100644 --- a/release/src/cargo.rs +++ b/release/src/cargo.rs @@ -1,10 +1,8 @@ //! Tools for working with Cargo. -use std::{ - ffi::OsStr, - path::{Path, PathBuf}, - process::{Command, Stdio}, -}; +use std::ffi::OsStr; +use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; use anyhow::{bail, Context as _, Result}; use clap::ValueEnum as _; @@ -106,6 +104,17 @@ pub struct CargoArgsBuilder { } impl CargoArgsBuilder { + #[must_use] + pub fn new() -> Self { + Self { + toolchain: None, + subcommand: String::new(), + target: None, + features: vec![], + args: vec![], + } + } + #[must_use] pub fn toolchain(mut self, toolchain: S) -> Self where @@ -192,3 +201,38 @@ impl CargoArgsBuilder { args } } + +#[derive(Debug, Default)] +pub struct CargoBatchBuilder { + commands: Vec>, +} + +impl CargoBatchBuilder { + #[must_use] + pub fn new() -> Self { + Self { commands: vec![] } + } + + #[must_use] + pub fn command(mut self, args: Vec) -> Self { + self.commands.push(args); + self + } + + pub fn add_command(&mut self, args: Vec) -> &mut Self { + self.commands.push(args); + self + } + + #[must_use] + pub fn build(&self) -> Vec { + let mut args = vec!["batch".to_string()]; + + for command in &self.commands { + args.push("---".to_string()); + args.extend(command.clone()); + } + + args + } +} diff --git a/release/src/main.rs b/release/src/main.rs index 7850bbb8d..b1bc17255 100644 --- a/release/src/main.rs +++ b/release/src/main.rs @@ -134,6 +134,10 @@ fn list_crates(root: &PathBuf) -> Result> { let metadata = &parsed.package.metadata.embassy; + if metadata.skip { + continue; + } + let mut dependencies = Vec::new(); for (k, _) in parsed.dependencies { if k.starts_with("embassy-") { @@ -266,7 +270,7 @@ fn main() -> Result<()> { } } Command::Build { crate_name } => { - build::build(&ctx)?; + build::build(&ctx, crate_name.as_deref())?; } Command::SemverCheck { crate_name } => { let c = ctx.crates.get(&crate_name).unwrap(); -- cgit From 3a6ea3a31c90179fb3cbd30c18e3a310e2ee647c Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 15 Aug 2025 19:01:56 +0200 Subject: Load all crates in the graph, honor the "publish" flag to prevent publishing examples/tests. --- docs/examples/basic/Cargo.toml | 6 + .../layer-by-layer/blinky-async/Cargo.toml | 6 + docs/examples/layer-by-layer/blinky-hal/Cargo.toml | 6 + docs/examples/layer-by-layer/blinky-irq/Cargo.toml | 6 + docs/examples/layer-by-layer/blinky-pac/Cargo.toml | 6 + examples/boot/application/nrf/Cargo.toml | 10 ++ examples/boot/application/rp/Cargo.toml | 6 + examples/boot/application/stm32f3/Cargo.toml | 6 + examples/boot/application/stm32f7/Cargo.toml | 6 + examples/boot/application/stm32h7/Cargo.toml | 6 + examples/boot/application/stm32l0/Cargo.toml | 6 + examples/boot/application/stm32l1/Cargo.toml | 6 + examples/boot/application/stm32l4/Cargo.toml | 6 + examples/boot/application/stm32wb-dfu/Cargo.toml | 6 + examples/boot/application/stm32wba-dfu/Cargo.toml | 6 + examples/boot/application/stm32wl/Cargo.toml | 6 + examples/boot/bootloader/nrf/Cargo.toml | 10 ++ examples/boot/bootloader/rp/Cargo.toml | 6 + .../boot/bootloader/stm32-dual-bank/Cargo.toml | 6 + examples/boot/bootloader/stm32/Cargo.toml | 6 + examples/boot/bootloader/stm32wb-dfu/Cargo.toml | 7 ++ examples/boot/bootloader/stm32wba-dfu/Cargo.toml | 6 + examples/lpc55s69/Cargo.toml | 6 + examples/mimxrt1011/Cargo.toml | 6 + examples/mimxrt1062-evk/Cargo.toml | 6 + examples/mimxrt6/Cargo.toml | 6 + examples/mspm0c1104/Cargo.toml | 7 ++ examples/mspm0g3507/Cargo.toml | 6 + examples/mspm0g3519/Cargo.toml | 6 + examples/mspm0l1306/Cargo.toml | 6 + examples/mspm0l2228/Cargo.toml | 6 + examples/nrf-rtos-trace/Cargo.toml | 6 + examples/nrf-rtos-trace/build.rs | 2 - examples/nrf51/Cargo.toml | 6 + examples/nrf52810/Cargo.toml | 6 + examples/nrf52840-rtic/Cargo.toml | 6 + examples/nrf52840/Cargo.toml | 6 + examples/nrf5340/Cargo.toml | 6 + examples/nrf54l15/Cargo.toml | 6 + examples/nrf9151/ns/Cargo.toml | 6 + examples/nrf9151/s/Cargo.toml | 6 + examples/nrf9160/Cargo.toml | 6 + examples/rp/Cargo.toml | 6 + examples/rp235x/Cargo.toml | 6 + examples/std/Cargo.toml | 6 + examples/stm32c0/Cargo.toml | 6 + examples/stm32f0/Cargo.toml | 6 + examples/stm32f1/Cargo.toml | 6 + examples/stm32f2/Cargo.toml | 6 + examples/stm32f3/Cargo.toml | 6 + examples/stm32f334/Cargo.toml | 6 + examples/stm32f4/Cargo.toml | 6 + examples/stm32f469/Cargo.toml | 6 + examples/stm32f7/Cargo.toml | 6 + examples/stm32g0/Cargo.toml | 6 + examples/stm32g4/Cargo.toml | 6 + examples/stm32h5/Cargo.toml | 6 + examples/stm32h7/Cargo.toml | 6 + examples/stm32h723/Cargo.toml | 6 + examples/stm32h735/Cargo.toml | 6 + examples/stm32h742/Cargo.toml | 6 + examples/stm32h755cm4/Cargo.toml | 6 + examples/stm32h755cm7/Cargo.toml | 6 + examples/stm32h7b0/Cargo.toml | 6 + examples/stm32h7rs/Cargo.toml | 6 + examples/stm32l0/Cargo.toml | 6 + examples/stm32l1/Cargo.toml | 6 + examples/stm32l4/Cargo.toml | 6 + examples/stm32l432/Cargo.toml | 6 + examples/stm32l5/Cargo.toml | 6 + examples/stm32u0/Cargo.toml | 6 + examples/stm32u5/Cargo.toml | 6 + examples/stm32wb/Cargo.toml | 6 + examples/stm32wba/Cargo.toml | 6 + examples/stm32wba6/Cargo.toml | 6 + examples/stm32wl/Cargo.toml | 6 + examples/wasm/Cargo.toml | 6 + release/src/build.rs | 4 + release/src/cargo.rs | 9 ++ release/src/main.rs | 130 +++++++++++++++------ release/src/types.rs | 9 ++ tests/mspm0/Cargo.toml | 6 + tests/nrf/Cargo.toml | 11 ++ tests/perf-client/Cargo.toml | 1 + tests/perf-server/Cargo.toml | 1 + tests/riscv32/Cargo.toml | 6 + tests/rp/Cargo.toml | 7 ++ tests/stm32/Cargo.toml | 34 ++++++ tests/utils/Cargo.toml | 1 + tests/utils/src/bin/saturate_serial.rs | 7 +- 90 files changed, 651 insertions(+), 43 deletions(-) diff --git a/docs/examples/basic/Cargo.toml b/docs/examples/basic/Cargo.toml index 15fd42703..5fb137898 100644 --- a/docs/examples/basic/Cargo.toml +++ b/docs/examples/basic/Cargo.toml @@ -5,6 +5,7 @@ name = "embassy-basic-example" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-executor = { version = "0.8.0", path = "../../../embassy-executor", features = ["defmt", "arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt"] } @@ -16,3 +17,8 @@ defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" panic-probe = { version = "1.0.0", features = ["print-defmt"] } + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi" } +] diff --git a/docs/examples/layer-by-layer/blinky-async/Cargo.toml b/docs/examples/layer-by-layer/blinky-async/Cargo.toml index dd0adf938..f1f678df3 100644 --- a/docs/examples/layer-by-layer/blinky-async/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-async/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" license = "MIT OR Apache-2.0" +publish = false [dependencies] cortex-m = { version = "0.7", features = ["critical-section-single-core"] } cortex-m-rt = "0.7" @@ -13,3 +14,8 @@ embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", f defmt = "1.0.1" defmt-rtt = "1.0.0" panic-probe = { version = "1.0.0", features = ["print-defmt"] } + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi" } +] diff --git a/docs/examples/layer-by-layer/blinky-hal/Cargo.toml b/docs/examples/layer-by-layer/blinky-hal/Cargo.toml index 55795e4e2..cdfc4b850 100644 --- a/docs/examples/layer-by-layer/blinky-hal/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-hal/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" license = "MIT OR Apache-2.0" +publish = false [dependencies] cortex-m-rt = "0.7" cortex-m = { version = "0.7", features = ["critical-section-single-core"] } @@ -12,3 +13,8 @@ embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", feature defmt = "1.0.1" defmt-rtt = "1.0.0" panic-probe = { version = "1.0.0", features = ["print-defmt"] } + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi" } +] diff --git a/docs/examples/layer-by-layer/blinky-irq/Cargo.toml b/docs/examples/layer-by-layer/blinky-irq/Cargo.toml index 4a4bda4c4..b15b228fc 100644 --- a/docs/examples/layer-by-layer/blinky-irq/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-irq/Cargo.toml @@ -6,6 +6,7 @@ version = "0.1.0" edition = "2021" license = "MIT OR Apache-2.0" +publish = false [dependencies] cortex-m = { version = "0.7", features = ["critical-section-single-core"] } cortex-m-rt = { version = "0.7" } @@ -14,3 +15,8 @@ embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", feature defmt = "1.0.1" defmt-rtt = "1.0.0" panic-probe = { version = "1.0.0", features = ["print-defmt"] } + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi" } +] diff --git a/docs/examples/layer-by-layer/blinky-pac/Cargo.toml b/docs/examples/layer-by-layer/blinky-pac/Cargo.toml index 4e7e2f2ff..0d4711da2 100644 --- a/docs/examples/layer-by-layer/blinky-pac/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-pac/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" license = "MIT OR Apache-2.0" +publish = false [dependencies] cortex-m = { version = "0.7", features = ["critical-section-single-core"] } cortex-m-rt = "0.7" @@ -12,3 +13,8 @@ stm32-metapac = { version = "16", features = ["stm32l475vg"] } defmt = "1.0.1" defmt-rtt = "1.0.0" panic-probe = { version = "1.0.0", features = ["print-defmt"] } + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi" } +] diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index c8e1def4a..f55b14f38 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-boot-nrf-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } @@ -32,3 +33,12 @@ defmt = [ "embassy-boot-nrf/defmt", "embassy-sync/defmt", ] + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", features = ["embassy-nrf/nrf52840", "skip-include"], artifact-dir = "out/examples/boot/nrf52840" }, + { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9160" }, + { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9120" }, + { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9151" }, + { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9161" } +] diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index 7fd6f8f97..c60f2b9a8 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-boot-rp-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } @@ -34,3 +35,8 @@ skip-include = [] [profile.release] debug = true + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/rp" } +] diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index f9d5922b1..004050d40 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-boot-stm32f3-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } @@ -29,3 +30,8 @@ defmt = [ "embassy-sync/defmt", ] skip-include = [] + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32f3" } +] diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index f831e7f68..74a1d498e 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-boot-stm32f7-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } @@ -30,3 +31,8 @@ defmt = [ "embassy-sync/defmt", ] skip-include = [] + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32f7" } +] diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index 29d54c47f..acf1da96d 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-boot-stm32h7-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } @@ -30,3 +31,8 @@ defmt = [ "embassy-sync/defmt", ] skip-include = [] + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32h7" } +] diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 7c6c1dc78..0f5e8ac08 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-boot-stm32l0-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } @@ -29,3 +30,8 @@ defmt = [ "embassy-sync/defmt", ] skip-include = [] + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32l0" } +] diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index ecb498325..eb7279fb0 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-boot-stm32l1-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } @@ -29,3 +30,8 @@ defmt = [ "embassy-sync/defmt", ] skip-include = [] + +[package.metadata.embassy] +build = [ + { target = "thumbv7m-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32l1" } +] diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index 075f7b986..1d1830ba0 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-boot-stm32l4-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } @@ -29,3 +30,8 @@ defmt = [ "embassy-sync/defmt", ] skip-include = [] + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32l4" } +] diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index 65fac6062..5aa48c31b 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-boot-stm32wb-dfu-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } @@ -30,3 +31,8 @@ defmt = [ "embassy-boot-stm32/defmt", "embassy-sync/defmt", ] + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/boot/stm32wb-dfu" } +] diff --git a/examples/boot/application/stm32wba-dfu/Cargo.toml b/examples/boot/application/stm32wba-dfu/Cargo.toml index 469924422..880551ad7 100644 --- a/examples/boot/application/stm32wba-dfu/Cargo.toml +++ b/examples/boot/application/stm32wba-dfu/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-boot-stm32wba-dfu-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } @@ -30,3 +31,8 @@ defmt = [ "embassy-boot-stm32/defmt", "embassy-sync/defmt", ] + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/boot/stm32wba-dfu" } +] diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index fb8112edf..ee9ab0729 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-boot-stm32wl-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } @@ -29,3 +30,8 @@ defmt = [ "embassy-sync/defmt", ] skip-include = [] + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32wl" } +] diff --git a/examples/boot/bootloader/nrf/Cargo.toml b/examples/boot/bootloader/nrf/Cargo.toml index 157448054..2b54bbec8 100644 --- a/examples/boot/bootloader/nrf/Cargo.toml +++ b/examples/boot/bootloader/nrf/Cargo.toml @@ -4,6 +4,7 @@ name = "nrf-bootloader-example" version = "0.1.0" description = "Bootloader for nRF chips" license = "MIT OR Apache-2.0" +publish = false [dependencies] defmt = { version = "1.0.1", optional = true } @@ -57,3 +58,12 @@ debug = false debug-assertions = false opt-level = 0 overflow-checks = false + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", features = ["embassy-nrf/nrf52840"] }, + { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns"] }, + { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns"] }, + { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns"] }, + { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns"] } +] diff --git a/examples/boot/bootloader/rp/Cargo.toml b/examples/boot/bootloader/rp/Cargo.toml index 034043274..b89332f0b 100644 --- a/examples/boot/bootloader/rp/Cargo.toml +++ b/examples/boot/bootloader/rp/Cargo.toml @@ -4,6 +4,7 @@ name = "rp-bootloader-example" version = "0.1.0" description = "Example bootloader for RP2040 chips" license = "MIT OR Apache-2.0" +publish = false [dependencies] defmt = { version = "1.0.1", optional = true } @@ -31,3 +32,8 @@ defmt = [ [profile.release] debug = true opt-level = 's' + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi" } +] diff --git a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml index 75c7783b8..82fbee9f1 100644 --- a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml +++ b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml @@ -4,6 +4,7 @@ name = "stm32-bootloader-dual-bank-flash-example" version = "0.1.0" description = "Example bootloader for dual-bank flash STM32 chips" license = "MIT OR Apache-2.0" +publish = false [dependencies] defmt = { version = "1.0.1", optional = true } @@ -54,3 +55,8 @@ debug = false debug-assertions = false opt-level = 0 overflow-checks = false + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", features = ["embassy-stm32/stm32h743zi"] } +] diff --git a/examples/boot/bootloader/stm32/Cargo.toml b/examples/boot/bootloader/stm32/Cargo.toml index 3f54b823b..a9a4aa95a 100644 --- a/examples/boot/bootloader/stm32/Cargo.toml +++ b/examples/boot/bootloader/stm32/Cargo.toml @@ -4,6 +4,7 @@ name = "stm32-bootloader-example" version = "0.1.0" description = "Example bootloader for STM32 chips" license = "MIT OR Apache-2.0" +publish = false [dependencies] defmt = { version = "1.0.1", optional = true } @@ -56,3 +57,8 @@ debug = false debug-assertions = false opt-level = 0 overflow-checks = false + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", features = ["embassy-stm32/stm32l496zg"] } +] diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml index 1aad71ebc..75783d66e 100644 --- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml @@ -4,6 +4,7 @@ name = "stm32wb-dfu-bootloader-example" version = "0.1.0" description = "Example USB DFUbootloader for the STM32WB series of chips" license = "MIT OR Apache-2.0" +publish = false [dependencies] defmt = { version = "1.0.1", optional = true } @@ -62,3 +63,9 @@ debug = false debug-assertions = false opt-level = 0 overflow-checks = false + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", features = ["embassy-stm32/stm32wb55rg"] }, + { target = "thumbv7em-none-eabi", features = ["embassy-stm32/stm32wb55rg", "verify"] } +] diff --git a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml index e31edb699..773060ab3 100644 --- a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml @@ -4,6 +4,7 @@ name = "stm32wba6-dfu-bootloader-example" version = "0.1.0" description = "Example USB DFUbootloader for the STM32WBA series of chips" license = "MIT OR Apache-2.0" +publish = false [dependencies] defmt = { version = "1.0.1", optional = true } @@ -62,3 +63,8 @@ debug = false debug-assertions = false opt-level = 0 overflow-checks = false + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", features = ["embassy-stm32/stm32wba65ri", "verify"] } +] diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index d66e3e2ec..bf28ee20f 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml @@ -4,6 +4,7 @@ name = "embassy-nxp-lpc55s69-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55", "rt", "defmt", "time-driver-rtc"] } @@ -20,3 +21,8 @@ panic-semihosting = "0.6.0" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/lpc55s69" } +] diff --git a/examples/mimxrt1011/Cargo.toml b/examples/mimxrt1011/Cargo.toml index 59b1eaa10..49d628811 100644 --- a/examples/mimxrt1011/Cargo.toml +++ b/examples/mimxrt1011/Cargo.toml @@ -3,6 +3,7 @@ name = "embassy-imxrt1011-examples" version = "0.1.0" edition = "2021" license = "MIT or Apache-2.0" +publish = false [dependencies] cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } @@ -27,3 +28,8 @@ imxrt-rt = { version = "0.1.7", features = ["device"] } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabihf", artifact-dir = "out/examples/mimxrt1011" } +] diff --git a/examples/mimxrt1062-evk/Cargo.toml b/examples/mimxrt1062-evk/Cargo.toml index bfa06f608..816695a32 100644 --- a/examples/mimxrt1062-evk/Cargo.toml +++ b/examples/mimxrt1062-evk/Cargo.toml @@ -3,6 +3,7 @@ name = "embassy-imxrt1062-evk-examples" version = "0.1.0" edition = "2021" license = "MIT or Apache-2.0" +publish = false [dependencies] cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } @@ -27,3 +28,8 @@ imxrt-rt = { version = "0.1.7", features = ["device"] } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabihf", artifact-dir = "out/examples/mimxrt1062-evk" } +] diff --git a/examples/mimxrt6/Cargo.toml b/examples/mimxrt6/Cargo.toml index 2667ec089..8ae636921 100644 --- a/examples/mimxrt6/Cargo.toml +++ b/examples/mimxrt6/Cargo.toml @@ -3,6 +3,7 @@ name = "embassy-imxrt-examples" version = "0.1.0" edition = "2021" license = "MIT or Apache-2.0" +publish = false [dependencies] cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } @@ -58,3 +59,8 @@ incremental = false lto = 'fat' opt-level = 3 # <- overflow-checks = false # <- + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/mimxrt6" } +] diff --git a/examples/mspm0c1104/Cargo.toml b/examples/mspm0c1104/Cargo.toml index 93ae4913a..decb1a6e2 100644 --- a/examples/mspm0c1104/Cargo.toml +++ b/examples/mspm0c1104/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-mspm0-c1104-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0c1104dgs20", "defmt", "rt", "time-driver-any"] } @@ -30,3 +31,9 @@ debug = 0 opt-level = "z" lto = true codegen-units = 1 + +[package.metadata.embassy] +skip = true # TODO: remove when we find a way to decrease the defmt buffer size in ci. +build = [ + { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0c1104" } +] diff --git a/examples/mspm0g3507/Cargo.toml b/examples/mspm0g3507/Cargo.toml index 7544db230..04efb681c 100644 --- a/examples/mspm0g3507/Cargo.toml +++ b/examples/mspm0g3507/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-mspm0-g3507-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3507pm", "defmt", "rt", "time-driver-any"] } @@ -21,3 +22,8 @@ embedded-io-async = "0.6.1" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0g3507" } +] diff --git a/examples/mspm0g3519/Cargo.toml b/examples/mspm0g3519/Cargo.toml index 145a67b96..bb31b52ff 100644 --- a/examples/mspm0g3519/Cargo.toml +++ b/examples/mspm0g3519/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-mspm0-g3519-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3519pz", "defmt", "rt", "time-driver-any"] } @@ -19,3 +20,8 @@ panic-semihosting = "0.6.0" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0g3519" } +] diff --git a/examples/mspm0l1306/Cargo.toml b/examples/mspm0l1306/Cargo.toml index 724ca58a0..c41017e17 100644 --- a/examples/mspm0l1306/Cargo.toml +++ b/examples/mspm0l1306/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-mspm0-l1306-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l1306rhb", "defmt", "rt", "time-driver-any"] } @@ -23,3 +24,8 @@ debug = 2 [profile.dev] debug = 2 opt-level = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0l1306" } +] diff --git a/examples/mspm0l2228/Cargo.toml b/examples/mspm0l2228/Cargo.toml index 0bec500db..7295eb599 100644 --- a/examples/mspm0l2228/Cargo.toml +++ b/examples/mspm0l2228/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-mspm0-l2228-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l2228pn", "defmt", "rt", "time-driver-any"] } @@ -19,3 +20,8 @@ panic-semihosting = "0.6.0" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0l2228" } +] diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index 4ef986d96..60875f434 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-nrf-rtos-trace-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [features] default = ["log"] @@ -34,3 +35,8 @@ name = "rtos_trace" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf-rtos-trace" } +] diff --git a/examples/nrf-rtos-trace/build.rs b/examples/nrf-rtos-trace/build.rs index 36cdb65a8..cd1a264c4 100644 --- a/examples/nrf-rtos-trace/build.rs +++ b/examples/nrf-rtos-trace/build.rs @@ -31,6 +31,4 @@ fn main() { println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=-Tlink.x"); - #[cfg(feature = "defmt")] - println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); } diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml index 524feca38..93acdab8a 100644 --- a/examples/nrf51/Cargo.toml +++ b/examples/nrf51/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-nrf51-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } @@ -18,3 +19,8 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/nrf51" } +] diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index 2b4612a51..000521265 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-nrf52810-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } @@ -22,3 +23,8 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf52810" } +] diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index d5fddd46e..5e37913a9 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-nrf52840-rtic-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] rtic = { version = "2", features = ["thumbv7-backend"] } @@ -22,3 +23,8 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf52840-rtic" } +] diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index b28ee0f4f..026681822 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-nrf52840-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } @@ -37,3 +38,8 @@ microfft = "0.5.0" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf52840" } +] diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 19c5e707f..36f74e4b1 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-nrf5340-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } @@ -27,3 +28,8 @@ serde = { version = "1.0.136", default-features = false } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf5340" } +] diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index 5f1ee50a0..b794b217c 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-nrf54l15-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } @@ -20,3 +21,8 @@ embedded-storage = "0.3.1" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf54l15" } +] diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml index e7551723d..35550b8c5 100644 --- a/examples/nrf9151/ns/Cargo.toml +++ b/examples/nrf9151/ns/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-nrf9151-non-secure-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-executor = { version = "0.8.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } @@ -18,3 +19,8 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf9151/ns" } +] diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml index 7f675c5e1..3ef8b33fd 100644 --- a/examples/nrf9151/s/Cargo.toml +++ b/examples/nrf9151/s/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-nrf9151-secure-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-executor = { version = "0.8.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } @@ -18,3 +19,8 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf9151/s" } +] diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml index 263986c4e..245232c1f 100644 --- a/examples/nrf9160/Cargo.toml +++ b/examples/nrf9160/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-nrf9160-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } @@ -24,3 +25,8 @@ embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf9160" } +] diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index afe8a90d8..d97ebf43e 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -4,6 +4,7 @@ name = "embassy-rp-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal", features = ["defmt"] } @@ -60,3 +61,8 @@ embedded-sdmmc = "0.7.0" [profile.release] # Enable generation of debug symbols even on release builds debug = true + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/rp" } +] diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 9087c4c83..2c279d7e1 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -4,6 +4,7 @@ name = "embassy-rp2350-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal", features = ["defmt"] } @@ -60,3 +61,8 @@ embedded-sdmmc = "0.7.0" [profile.release] # Enable generation of debug symbols even on release builds debug = true + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/rp235x" } +] diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 9b0ff8be2..6d56d97af 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-std-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["log"] } @@ -27,3 +28,8 @@ static_cell = "2" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { artifact-dir = "out/examples/std" } +] diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index 0a8d4ff2d..56b966d49 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32c0-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32c031c6 to your chip name, if necessary. @@ -23,3 +24,8 @@ chrono = { version = "^0.4", default-features = false} [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32c0" } +] diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index c3d1b99e5..6cc6eac46 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -3,6 +3,7 @@ name = "embassy-stm32f0-examples" version = "0.1.0" edition = "2021" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32f091rc to your chip name, if necessary. @@ -20,3 +21,8 @@ portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32f0" } +] diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index b91c781db..3cb7bd5e3 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32f1-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32f103c8 to your chip name, if necessary. @@ -29,3 +30,8 @@ opt-level = "s" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7m-none-eabi", artifact-dir = "out/examples/stm32f1" } +] diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index 74ecb141d..9c5a7cd7f 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32f2-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32f207zg to your chip name, if necessary. @@ -23,3 +24,8 @@ nb = "1.0.0" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7m-none-eabi", artifact-dir = "out/examples/stm32f2" } +] diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 2cea5028a..690bcb00d 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32f3-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32f303ze to your chip name, if necessary. @@ -27,3 +28,8 @@ static_cell = "2" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f3" } +] diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml index 8d015eae7..709da6ed6 100644 --- a/examples/stm32f334/Cargo.toml +++ b/examples/stm32f334/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32f334-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } @@ -23,3 +24,8 @@ heapless = { version = "0.8", default-features = false } nb = "1.0.0" embedded-storage = "0.3.1" static_cell = "2" + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f334" } +] diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 3139bdf71..52b48e744 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32f4-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32f429zi to your chip name, if necessary. @@ -37,3 +38,8 @@ chrono = { version = "^0.4", default-features = false} [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f4" } +] diff --git a/examples/stm32f469/Cargo.toml b/examples/stm32f469/Cargo.toml index a35a811e2..612081242 100644 --- a/examples/stm32f469/Cargo.toml +++ b/examples/stm32f469/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32f469-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Specific examples only for stm32f469 @@ -20,3 +21,8 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f469" } +] diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 261524bc1..1e5ea8d33 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32f7-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32f777zi to your chip name, if necessary. @@ -33,3 +34,8 @@ aes-gcm = { version = "0.10.3", default-features = false, features = ["aes", "he [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f7" } +] diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index 61e20168c..7b0da5077 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32g0-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32g0b1re to your chip name, if necessary. @@ -27,3 +28,8 @@ embedded-io-async = { version = "0.6.1" } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32g0" } +] diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index c25df6ea8..15292725f 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32g4-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32g491re to your chip name, if necessary. @@ -27,3 +28,8 @@ static_cell = "2.0.0" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32g4" } +] diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 68563dba0..7f9a77e85 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32h5-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32h563zi to your chip name, if necessary. @@ -69,3 +70,8 @@ incremental = false lto = 'fat' opt-level = 3 # <- overflow-checks = false # <- + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32h5" } +] diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 04c9b5bda..be0e46938 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32h7-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32h743bi to your chip name, if necessary. @@ -72,3 +73,8 @@ incremental = false lto = 'fat' opt-level = 3 # <- overflow-checks = false # <- + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h7" } +] diff --git a/examples/stm32h723/Cargo.toml b/examples/stm32h723/Cargo.toml index f7d819867..5a762259b 100644 --- a/examples/stm32h723/Cargo.toml +++ b/examples/stm32h723/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32h723-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32h723zg to your chip name, if necessary. @@ -66,3 +67,8 @@ incremental = false lto = 'fat' opt-level = 3 # <- overflow-checks = false # <- + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h723" } +] diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml index 946daf550..0b55424e8 100644 --- a/examples/stm32h735/Cargo.toml +++ b/examples/stm32h735/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32h735-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } @@ -59,3 +60,8 @@ incremental = false lto = 'fat' opt-level = 3 # <- overflow-checks = false # <- + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h735" } +] diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml index 8448c2c7a..067663538 100644 --- a/examples/stm32h742/Cargo.toml +++ b/examples/stm32h742/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32f7-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32f777zi to your chip name, if necessary. @@ -63,3 +64,8 @@ aes-gcm = { version = "0.10.3", default-features = false, features = [ [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h742" } +] diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index e1ddf59be..6cd1893d2 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32h755cm4-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32h755zi-cm4 to your chip name, if necessary. @@ -64,3 +65,8 @@ incremental = false lto = 'fat' opt-level = 3 # <- overflow-checks = false # <- + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h755cm4" } +] diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index b09095ea1..48783fc7a 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32h755cm7-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32h743bi to your chip name, if necessary. @@ -62,3 +63,8 @@ incremental = false lto = 'fat' opt-level = 3 # <- overflow-checks = false # <- + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h755cm7" } +] diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml index dc876159a..c0d047bd4 100644 --- a/examples/stm32h7b0/Cargo.toml +++ b/examples/stm32h7b0/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32h7b0-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } @@ -71,3 +72,8 @@ incremental = false lto = 'fat' opt-level = 3 # <- overflow-checks = false # <- + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h7b0" } +] diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml index 4068fa5df..dcd5b078d 100644 --- a/examples/stm32h7rs/Cargo.toml +++ b/examples/stm32h7rs/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32h7rs-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32h743bi to your chip name, if necessary. @@ -70,3 +71,8 @@ incremental = false lto = 'fat' opt-level = 3 # <- overflow-checks = false # <- + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h7rs" } +] diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index b76f6765f..47ccedeb0 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32l0-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32l072cz to your chip name, if necessary. @@ -28,3 +29,8 @@ portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32l0" } +] diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 442a5c795..659524cb3 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32l1-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } @@ -24,3 +25,8 @@ embedded-storage = "0.3.1" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7m-none-eabi", artifact-dir = "out/examples/stm32l1" } +] diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index bbe592212..02fd4ce93 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32l4-examples" version = "0.1.1" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32l4s5vi to your chip name, if necessary. @@ -36,3 +37,8 @@ micromath = "2.0.0" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32l4" } +] diff --git a/examples/stm32l432/Cargo.toml b/examples/stm32l432/Cargo.toml index 483403b1d..14db1fb2f 100644 --- a/examples/stm32l432/Cargo.toml +++ b/examples/stm32l432/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32l4-examples" version = "0.1.1" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32l4s5vi to your chip name, if necessary. @@ -28,3 +29,8 @@ debug = 2 name = "qspi_mmap" path = "src/bin/qspi_mmap.rs" test = false + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32l432" } +] diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 1739f0889..42b46ee0f 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32l5-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32l552ze to your chip name, if necessary. @@ -32,3 +33,8 @@ debug = 2 [[bin]] name = "stop" default-features = ["embassy-stm32/low-power"] + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32l5" } +] diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml index 1362aa422..09e5eb20c 100644 --- a/examples/stm32u0/Cargo.toml +++ b/examples/stm32u0/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32u0-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32u083rc to your chip name, if necessary. @@ -27,3 +28,8 @@ chrono = { version = "0.4.38", default-features = false } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32u0" } +] diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index 53f4ee618..8b5d52aa4 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32u5-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32u5g9zj to your chip name, if necessary. @@ -32,3 +33,8 @@ trustzone-secure = ["embassy-stm32/trustzone-secure"] [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32u5" } +] diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 1b2fb9cbd..14e6dfa15 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32wb-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32wb55rg to your chip name in both dependencies, if necessary. @@ -54,3 +55,8 @@ required-features = ["ble"] [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32wb" } +] diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml index a6ea433cf..9c11528cd 100644 --- a/examples/stm32wba/Cargo.toml +++ b/examples/stm32wba/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32wba-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] } @@ -23,3 +24,8 @@ static_cell = "2" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32wba" } +] diff --git a/examples/stm32wba6/Cargo.toml b/examples/stm32wba6/Cargo.toml index 980091eaf..f1f9cf88b 100644 --- a/examples/stm32wba6/Cargo.toml +++ b/examples/stm32wba6/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32wba-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba65ri", "time-driver-any", "memory-x", "exti"] } @@ -24,3 +25,8 @@ static_cell = "2" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32wba6" } +] diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 31729565d..a75e4ed30 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-stm32wl-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # Change stm32wl55jc-cm4 to your chip name, if necessary. @@ -25,3 +26,8 @@ chrono = { version = "^0.4", default-features = false } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32wl" } +] diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml index af139fdbd..28b4f1c30 100644 --- a/examples/wasm/Cargo.toml +++ b/examples/wasm/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-wasm-example" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [lib] crate-type = ["cdylib"] @@ -19,3 +20,8 @@ log = "0.4.11" [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "wasm32-unknown-unknown", artifact-dir = "out/examples/wasm" } +] diff --git a/release/src/build.rs b/release/src/build.rs index d1abb2aa1..7c777d36c 100644 --- a/release/src/build.rs +++ b/release/src/build.rs @@ -34,6 +34,10 @@ pub(crate) fn build(ctx: &crate::Context, crate_name: Option<&str>) -> Result<() args_builder = args_builder.features(&config.features); } + if let Some(ref artifact_dir) = config.artifact_dir { + args_builder = args_builder.artifact_dir(artifact_dir); + } + batch_builder.add_command(args_builder.build()); } } diff --git a/release/src/cargo.rs b/release/src/cargo.rs index 0b28458e9..826a3a8b2 100644 --- a/release/src/cargo.rs +++ b/release/src/cargo.rs @@ -148,6 +148,15 @@ impl CargoArgsBuilder { self } + #[must_use] + pub fn artifact_dir(mut self, artifact_dir: S) -> Self + where + S: Into, + { + self.args.push(format!("--artifact-dir={}", artifact_dir.into())); + self + } + #[must_use] pub fn arg(mut self, arg: S) -> Self where diff --git a/release/src/main.rs b/release/src/main.rs index b1bc17255..5605ca332 100644 --- a/release/src/main.rs +++ b/release/src/main.rs @@ -3,7 +3,7 @@ use std::fs; use std::path::{Path, PathBuf}; use std::process::Command as ProcessCommand; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, bail, Result}; use clap::{Parser, Subcommand}; use log::info; use petgraph::graph::{Graph, NodeIndex}; @@ -13,6 +13,25 @@ use simple_logger::SimpleLogger; use toml_edit::{DocumentMut, Item, Value}; use types::*; +fn check_publish_dependencies(ctx: &Context) -> Result<()> { + for krate in ctx.crates.values() { + if krate.publish { + for dep_name in &krate.dependencies { + if let Some(dep_crate) = ctx.crates.get(dep_name) { + if !dep_crate.publish { + return Err(anyhow!( + "Publishable crate '{}' depends on non-publishable crate '{}'. This is not allowed.", + krate.name, + dep_name + )); + } + } + } + } + } + Ok(()) +} + mod build; mod cargo; mod semver_check; @@ -56,7 +75,7 @@ enum Command { }, /// SemverCheck SemverCheck { - /// Crate to check. Will traverse that crate an it's dependents. If not specified checks all crates. + /// Specific crate name to check #[arg(value_name = "CRATE")] crate_name: String, }, @@ -120,53 +139,72 @@ fn update_versions(to_update: &Crate, dep: &CrateId, new_version: &str) -> Resul } fn list_crates(root: &PathBuf) -> Result> { - let d = std::fs::read_dir(root)?; let mut crates = BTreeMap::new(); + discover_crates(root, &mut crates)?; + Ok(crates) +} + +fn discover_crates(dir: &PathBuf, crates: &mut BTreeMap) -> Result<()> { + let d = std::fs::read_dir(dir)?; for c in d { let entry = c?; if entry.file_type()?.is_dir() { - let path = root.join(entry.path()); - let entry = path.join("Cargo.toml"); - if entry.exists() { - let content = fs::read_to_string(&entry)?; - let parsed: ParsedCrate = toml::from_str(&content)?; - let id = parsed.package.name; + let path = dir.join(entry.path()); + let cargo_toml = path.join("Cargo.toml"); - let metadata = &parsed.package.metadata.embassy; + if cargo_toml.exists() { + let content = fs::read_to_string(&cargo_toml)?; - if metadata.skip { - continue; - } + // Try to parse as a crate, skip if it's a workspace + let parsed: Result = toml::from_str(&content); + if let Ok(parsed) = parsed { + let id = parsed.package.name; - let mut dependencies = Vec::new(); - for (k, _) in parsed.dependencies { - if k.starts_with("embassy-") { - dependencies.push(k); + let metadata = &parsed.package.metadata.embassy; + + if metadata.skip { + continue; } - } - let mut configs = metadata.build.clone(); - if configs.is_empty() { - configs.push(BuildConfig { - features: vec![], - target: None, - }) - } + let mut dependencies = Vec::new(); + for (k, _) in parsed.dependencies { + if k.starts_with("embassy-") { + dependencies.push(k); + } + } + + let mut configs = metadata.build.clone(); + if configs.is_empty() { + configs.push(BuildConfig { + features: vec![], + target: None, + artifact_dir: None, + }) + } - crates.insert( - id.clone(), - Crate { - name: id, - version: parsed.package.version, - path, - dependencies, - configs, - }, - ); + crates.insert( + id.clone(), + Crate { + name: id, + version: parsed.package.version, + path, + dependencies, + configs, + publish: parsed.package.publish, + }, + ); + } + } else { + // Recursively search subdirectories, but only for examples, tests, and docs + let file_name = entry.file_name(); + let dir_name = file_name.to_string_lossy(); + if dir_name == "examples" || dir_name == "tests" || dir_name == "docs" { + discover_crates(&path, crates)?; + } } } } - Ok(crates) + Ok(()) } fn build_graph(crates: &BTreeMap) -> (Graph, HashMap) { @@ -214,12 +252,17 @@ fn load_context(args: &Args) -> Result { let crates = list_crates(&root)?; let (graph, indices) = build_graph(&crates); - Ok(Context { + let ctx = Context { root, crates, graph, indices, - }) + }; + + // Check for publish dependency conflicts + check_publish_dependencies(&ctx)?; + + Ok(ctx) } fn main() -> Result<()> { @@ -274,10 +317,21 @@ fn main() -> Result<()> { } Command::SemverCheck { crate_name } => { let c = ctx.crates.get(&crate_name).unwrap(); + if !c.publish { + bail!("Cannot run semver-check on non-publishable crate '{}'", crate_name); + } check_semver(&c)?; } Command::PrepareRelease { crate_name } => { let start = ctx.indices.get(&crate_name).expect("unable to find crate in tree"); + + // Check if the target crate is publishable + let start_weight = ctx.graph.node_weight(*start).unwrap(); + let start_crate = ctx.crates.get(start_weight).unwrap(); + if !start_crate.publish { + bail!("Cannot prepare release for non-publishable crate '{}'", crate_name); + } + let mut rgraph = ctx.graph.clone(); rgraph.reverse(); diff --git a/release/src/types.rs b/release/src/types.rs index c5b774977..4d9d440d8 100644 --- a/release/src/types.rs +++ b/release/src/types.rs @@ -13,10 +13,16 @@ pub struct ParsedCrate { pub struct ParsedPackage { pub name: String, pub version: String, + #[serde(default = "default_publish")] + pub publish: bool, #[serde(default)] pub metadata: Metadata, } +fn default_publish() -> bool { + true +} + #[derive(Debug, Deserialize, Default)] pub struct Metadata { #[serde(default)] @@ -36,6 +42,8 @@ pub struct BuildConfig { #[serde(default)] pub features: Vec, pub target: Option, + #[serde(rename = "artifact-dir")] + pub artifact_dir: Option, } pub type CrateId = String; @@ -47,4 +55,5 @@ pub struct Crate { pub path: PathBuf, pub dependencies: Vec, pub configs: Vec, + pub publish: bool, } diff --git a/tests/mspm0/Cargo.toml b/tests/mspm0/Cargo.toml index e4033b8b7..5cf1b0ed1 100644 --- a/tests/mspm0/Cargo.toml +++ b/tests/mspm0/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-mspm0-tests" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [features] mspm0g3507 = [ "embassy-mspm0/mspm0g3507pm" ] @@ -60,3 +61,8 @@ debug = false debug-assertions = false opt-level = 0 overflow-checks = false + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", features = ["mspm0g3507"], artifact-dir = "out/tests/mspm0g3507" } +] diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index ef7dc96ec..b94b54f4e 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-nrf-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] teleprobe-meta = "1" @@ -112,3 +113,13 @@ path = "src/bin/wifi_esp_hosted_perf.rs" required-features = [ "nrf52840",] # END TESTS + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", features = ["nrf51422"], artifact-dir = "out/tests/nrf51422-dk" }, + { target = "thumbv7em-none-eabi", features = ["nrf52832"], artifact-dir = "out/tests/nrf52832-dk" }, + { target = "thumbv7em-none-eabi", features = ["nrf52833"], artifact-dir = "out/tests/nrf52833-dk" }, + { target = "thumbv7em-none-eabi", features = ["nrf52840"], artifact-dir = "out/tests/nrf52840-dk" }, + { target = "thumbv8m.main-none-eabihf", features = ["nrf5340"], artifact-dir = "out/tests/nrf5340-dk" }, + { target = "thumbv8m.main-none-eabihf", features = ["nrf9160"], artifact-dir = "out/tests/nrf9160-dk" } +] diff --git a/tests/perf-client/Cargo.toml b/tests/perf-client/Cargo.toml index e31d6361b..ea0663b6f 100644 --- a/tests/perf-client/Cargo.toml +++ b/tests/perf-client/Cargo.toml @@ -2,6 +2,7 @@ name = "perf-client" version = "0.1.0" edition = "2021" +publish = false [dependencies] embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4"] } diff --git a/tests/perf-server/Cargo.toml b/tests/perf-server/Cargo.toml index 532039050..22614a33a 100644 --- a/tests/perf-server/Cargo.toml +++ b/tests/perf-server/Cargo.toml @@ -2,6 +2,7 @@ name = "perf-server" version = "0.1.0" edition = "2021" +publish = false [dependencies] log = "0.4.17" diff --git a/tests/riscv32/Cargo.toml b/tests/riscv32/Cargo.toml index 283ea5033..781fec62f 100644 --- a/tests/riscv32/Cargo.toml +++ b/tests/riscv32/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-riscv-tests" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] critical-section = { version = "1.1.1", features = ["restore-state-bool"] } @@ -44,3 +45,8 @@ debug = false debug-assertions = false opt-level = 0 overflow-checks = false + +[package.metadata.embassy] +build = [ + { target = "riscv32imac-unknown-none-elf" } +] diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index eef6c47ae..088195a75 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-rp-tests" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [features] rp2040 = ["embassy-rp/rp2040"] @@ -92,3 +93,9 @@ debug = false debug-assertions = false opt-level = 0 overflow-checks = false + +[package.metadata.embassy] +build = [ + { target = "thumbv6m-none-eabi", features = ["rp2040"], artifact-dir = "out/tests/rpi-pico" }, + { target = "thumbv8m.main-none-eabihf", features = ["rp235xb"], artifact-dir = "out/tests/pimoroni-pico-plus-2" } +] diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index c011a6d7d..37d5161f8 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -4,6 +4,7 @@ name = "embassy-stm32-tests" version = "0.1.0" license = "MIT OR Apache-2.0" autobins = false +publish = false [features] stm32c031c6 = ["embassy-stm32/stm32c031c6", "cm0", "not-gpdma"] @@ -243,3 +244,36 @@ debug = false debug-assertions = false opt-level = 0 overflow-checks = false + +[package.metadata.embassy] +build = [ + { target = "thumbv7m-none-eabi", features = ["stm32f103c8"], artifact-dir = "out/tests/stm32f103c8" }, + { target = "thumbv7em-none-eabi", features = ["stm32f429zi"], artifact-dir = "out/tests/stm32f429zi" }, + { target = "thumbv7em-none-eabi", features = ["stm32f446re"], artifact-dir = "out/tests/stm32f446re" }, + { target = "thumbv7em-none-eabi", features = ["stm32g491re"], artifact-dir = "out/tests/stm32g491re" }, + { target = "thumbv6m-none-eabi", features = ["stm32g071rb"], artifact-dir = "out/tests/stm32g071rb" }, + { target = "thumbv6m-none-eabi", features = ["stm32c031c6"], artifact-dir = "out/tests/stm32c031c6" }, + { target = "thumbv6m-none-eabi", features = ["stm32c071rb"], artifact-dir = "out/tests/stm32c071rb" }, + { target = "thumbv7em-none-eabi", features = ["stm32h755zi"], artifact-dir = "out/tests/stm32h755zi" }, + { target = "thumbv7em-none-eabi", features = ["stm32h753zi"], artifact-dir = "out/tests/stm32h753zi" }, + { target = "thumbv7em-none-eabi", features = ["stm32h7a3zi"], artifact-dir = "out/tests/stm32h7a3zi" }, + { target = "thumbv7em-none-eabi", features = ["stm32wb55rg"], artifact-dir = "out/tests/stm32wb55rg" }, + { target = "thumbv8m.main-none-eabihf", features = ["stm32h563zi"], artifact-dir = "out/tests/stm32h563zi" }, + { target = "thumbv8m.main-none-eabihf", features = ["stm32u585ai"], artifact-dir = "out/tests/stm32u585ai" }, + { target = "thumbv8m.main-none-eabihf", features = ["stm32u5a5zj"], artifact-dir = "out/tests/stm32u5a5zj" }, + { target = "thumbv8m.main-none-eabihf", features = ["stm32wba52cg"], artifact-dir = "out/tests/stm32wba52cg" }, + { target = "thumbv6m-none-eabi", features = ["stm32l073rz"], artifact-dir = "out/tests/stm32l073rz" }, + { target = "thumbv7m-none-eabi", features = ["stm32l152re"], artifact-dir = "out/tests/stm32l152re" }, + { target = "thumbv7em-none-eabi", features = ["stm32l4a6zg"], artifact-dir = "out/tests/stm32l4a6zg" }, + { target = "thumbv7em-none-eabi", features = ["stm32l4r5zi"], artifact-dir = "out/tests/stm32l4r5zi" }, + { target = "thumbv8m.main-none-eabihf", features = ["stm32l552ze"], artifact-dir = "out/tests/stm32l552ze" }, + { target = "thumbv7em-none-eabi", features = ["stm32f767zi"], artifact-dir = "out/tests/stm32f767zi" }, + { target = "thumbv7m-none-eabi", features = ["stm32f207zg"], artifact-dir = "out/tests/stm32f207zg" }, + { target = "thumbv7em-none-eabi", features = ["stm32f303ze"], artifact-dir = "out/tests/stm32f303ze" }, + { target = "thumbv7em-none-eabi", features = ["stm32l496zg"], artifact-dir = "out/tests/stm32l496zg" }, + { target = "thumbv7em-none-eabi", features = ["stm32wl55jc"], artifact-dir = "out/tests/stm32wl55jc" }, + { target = "thumbv7em-none-eabi", features = ["stm32h7s3l8"], artifact-dir = "out/tests/stm32h7s3l8" }, + { target = "thumbv6m-none-eabi", features = ["stm32f091rc"], artifact-dir = "out/tests/stm32f091rc" }, + { target = "thumbv8m.main-none-eabihf", features = ["stm32h503rb"], artifact-dir = "out/tests/stm32h503rb" }, + { target = "thumbv6m-none-eabi", features = ["stm32u083rc"], artifact-dir = "out/tests/stm32u083rc" } +] diff --git a/tests/utils/Cargo.toml b/tests/utils/Cargo.toml index bda55ad32..f76feaa20 100644 --- a/tests/utils/Cargo.toml +++ b/tests/utils/Cargo.toml @@ -2,6 +2,7 @@ name = "test-utils" version = "0.1.0" edition = "2021" +publish = false [dependencies] rand = "0.9" diff --git a/tests/utils/src/bin/saturate_serial.rs b/tests/utils/src/bin/saturate_serial.rs index 18ca12fb7..85676b106 100644 --- a/tests/utils/src/bin/saturate_serial.rs +++ b/tests/utils/src/bin/saturate_serial.rs @@ -2,7 +2,7 @@ use std::path::Path; use std::time::Duration; use std::{env, io, process, thread}; -use rand::random; +use rand::{rng, Rng}; use serial::SerialPort; pub fn main() { @@ -34,14 +34,15 @@ fn saturate(port: &mut T, idles: bool) -> io::Result<()> { })?; let mut written = 0; + let mut rng = rng(); loop { - let len = random::() % 0x1000; + let len = rng.random_range(1..=0x1000); let buf: Vec = (written..written + len).map(|x| x as u8).collect(); port.write_all(&buf)?; if idles { - let micros = (random::() % 1000) as u64; + let micros = rng.random_range(1..=1000) as u64; println!("Sleeping {}us", micros); port.flush().unwrap(); thread::sleep(Duration::from_micros(micros)); -- cgit From 0d8f9614a1af5a45b695e6f63b0337fc3bccba76 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 15 Aug 2025 19:06:51 +0200 Subject: Autodetect repo root. --- release/src/main.rs | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/release/src/main.rs b/release/src/main.rs index 5605ca332..f1949dd37 100644 --- a/release/src/main.rs +++ b/release/src/main.rs @@ -41,10 +41,6 @@ mod types; #[derive(Parser, Debug)] #[command(author, version, about)] struct Args { - /// Path to embassy repository - #[arg(short, long)] - repo: PathBuf, - /// Command to perform on each crate #[command(subcommand)] command: Command, @@ -247,8 +243,29 @@ struct Context { indices: HashMap, } -fn load_context(args: &Args) -> Result { - let root = args.repo.canonicalize()?; +fn find_repo_root() -> Result { + let mut path = std::env::current_dir()?.canonicalize()?; + + loop { + // Check if this directory contains a .git directory + if path.join(".git").exists() { + return Ok(path); + } + + // Move to parent directory + match path.parent() { + Some(parent) => path = parent.to_path_buf(), + None => break, + } + } + + Err(anyhow!( + "Could not find repository root. Make sure you're running this tool from within the embassy repository." + )) +} + +fn load_context() -> Result { + let root = find_repo_root()?; let crates = list_crates(&root)?; let (graph, indices) = build_graph(&crates); @@ -268,7 +285,7 @@ fn load_context(args: &Args) -> Result { fn main() -> Result<()> { SimpleLogger::new().init().unwrap(); let args = Args::parse(); - let mut ctx = load_context(&args)?; + let mut ctx = load_context()?; match args.command { Command::List => { -- cgit From 1f229f745c0ccee926ae5c4cf6732d41c4beb531 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Sat, 16 Aug 2025 11:14:15 +0200 Subject: fix: use patched versions --- release/Cargo.toml | 4 ++-- release/src/cargo.rs | 37 ++----------------------------------- release/src/main.rs | 1 - release/src/semver_check.rs | 11 ++++++----- release/src/types.rs | 3 ++- 5 files changed, 12 insertions(+), 44 deletions(-) diff --git a/release/Cargo.toml b/release/Cargo.toml index 3e4094eed..452e39ca6 100644 --- a/release/Cargo.toml +++ b/release/Cargo.toml @@ -19,8 +19,8 @@ simple_logger = "5.0.0" temp-file = "0.1.9" flate2 = "1.1.1" -#[patch.crates-io] -#cargo-semver-checks = { path = "../../cargo-semver-checks" } +[patch.crates-io] +cargo-semver-checks = { git = "https://github.com/lulf/cargo-semver-checks.git", rev="385f274edcbb6bf5156e30a94315852b27a527e6" } [package.metadata.embassy] skip = true diff --git a/release/src/cargo.rs b/release/src/cargo.rs index 826a3a8b2..498dfeb97 100644 --- a/release/src/cargo.rs +++ b/release/src/cargo.rs @@ -4,30 +4,16 @@ use std::ffi::OsStr; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; -use anyhow::{bail, Context as _, Result}; -use clap::ValueEnum as _; +use anyhow::{bail, Result}; use serde::{Deserialize, Serialize}; -use toml_edit::{DocumentMut, Formatted, Item, Value}; -use crate::{windows_safe_path, Crate}; - -#[derive(Clone, Debug, PartialEq)] -pub enum CargoAction { - Build(PathBuf), - Run, -} +use crate::windows_safe_path; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Artifact { pub executable: PathBuf, } -/// Execute cargo with the given arguments and from the specified directory. -pub fn run(args: &[String], cwd: &Path) -> Result<()> { - run_with_env::<[(&str, &str); 0], _, _>(args, cwd, [], false)?; - Ok(()) -} - /// Execute cargo with the given arguments and from the specified directory. pub fn run_with_env(args: &[String], cwd: &Path, envs: I, capture: bool) -> Result where @@ -166,25 +152,6 @@ impl CargoArgsBuilder { self } - #[must_use] - pub fn args(mut self, args: &[S]) -> Self - where - S: Clone + Into, - { - for arg in args { - self.args.push(arg.clone().into()); - } - self - } - - pub fn add_arg(&mut self, arg: S) -> &mut Self - where - S: Into, - { - self.args.push(arg.into()); - self - } - #[must_use] pub fn build(&self) -> Vec { let mut args = vec![]; diff --git a/release/src/main.rs b/release/src/main.rs index f1949dd37..cd3e094f1 100644 --- a/release/src/main.rs +++ b/release/src/main.rs @@ -5,7 +5,6 @@ use std::process::Command as ProcessCommand; use anyhow::{anyhow, bail, Result}; use clap::{Parser, Subcommand}; -use log::info; use petgraph::graph::{Graph, NodeIndex}; use petgraph::visit::Bfs; use petgraph::{Directed, Direction}; diff --git a/release/src/semver_check.rs b/release/src/semver_check.rs index a70c56376..9a4edd09a 100644 --- a/release/src/semver_check.rs +++ b/release/src/semver_check.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; -use cargo_semver_checks::{Check, GlobalConfig, ReleaseType, Rustdoc}; +use cargo_semver_checks::{Check, GlobalConfig, LintConfig, LintLevel, ReleaseType, RequiredSemverUpdate, Rustdoc}; use crate::cargo::CargoArgsBuilder; use crate::types::{BuildConfig, Crate}; @@ -8,12 +8,9 @@ use crate::types::{BuildConfig, Crate}; /// Return the minimum required bump for the next release. /// Even if nothing changed this will be [ReleaseType::Patch] pub fn minimum_update(krate: &Crate) -> Result { - println!("Crate = {:?}", krate); - let config = krate.configs.first().unwrap(); // TODO let package_name = krate.name.clone(); - let package_path = krate.path.clone(); let current_path = build_doc_json(krate, config)?; let baseline = Rustdoc::from_registry_latest_crate_version(); @@ -30,8 +27,12 @@ pub fn minimum_update(krate: &Crate) -> Result { } let mut cfg = GlobalConfig::new(); cfg.set_log_level(Some(log::Level::Trace)); + + let mut lint_cfg = LintConfig::new(); + // Disable this lint because we provide the rustdoc json only, so it can't do feature comparison. + lint_cfg.set("feature_missing", LintLevel::Allow, RequiredSemverUpdate::Minor, 0); + cfg.set_lint_config(lint_cfg); let result = semver_check.check_release(&mut cfg)?; - log::info!("Result {:?}", result); let mut min_required_update = ReleaseType::Patch; for (_, report) in result.crate_reports() { diff --git a/release/src/types.rs b/release/src/types.rs index 4d9d440d8..be0a883f1 100644 --- a/release/src/types.rs +++ b/release/src/types.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; use std::path::PathBuf; use serde::Deserialize; @@ -29,6 +29,7 @@ pub struct Metadata { pub embassy: MetadataEmbassy, } +#[allow(dead_code)] #[derive(Debug, Deserialize, Default)] pub struct MetadataEmbassy { #[serde(default)] -- cgit From cd7a7f97c0a5e928bac7299019d4320f4efc9ba6 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Sat, 16 Aug 2025 11:16:38 +0200 Subject: fix: add back missing --- release/src/cargo.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/release/src/cargo.rs b/release/src/cargo.rs index 498dfeb97..c1ed4118f 100644 --- a/release/src/cargo.rs +++ b/release/src/cargo.rs @@ -14,6 +14,12 @@ pub struct Artifact { pub executable: PathBuf, } +/// Execute cargo with the given arguments and from the specified directory. +pub fn run(args: &[String], cwd: &Path) -> Result<()> { + run_with_env::<[(&str, &str); 0], _, _>(args, cwd, [], false)?; + Ok(()) +} + /// Execute cargo with the given arguments and from the specified directory. pub fn run_with_env(args: &[String], cwd: &Path, envs: I, capture: bool) -> Result where -- cgit From 1f9452e0763613ab9fa3c42425f0835e9f7c8201 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Sat, 16 Aug 2025 12:24:14 +0200 Subject: fix: add workaround for current compiler version --- release/Cargo.toml | 1 + release/src/semver_check.rs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/release/Cargo.toml b/release/Cargo.toml index 452e39ca6..7875d088a 100644 --- a/release/Cargo.toml +++ b/release/Cargo.toml @@ -21,6 +21,7 @@ flate2 = "1.1.1" [patch.crates-io] cargo-semver-checks = { git = "https://github.com/lulf/cargo-semver-checks.git", rev="385f274edcbb6bf5156e30a94315852b27a527e6" } +#cargo-semver-checks = { path = "../../cargo-semver-checks" } [package.metadata.embassy] skip = true diff --git a/release/src/semver_check.rs b/release/src/semver_check.rs index 9a4edd09a..a4a9e77b5 100644 --- a/release/src/semver_check.rs +++ b/release/src/semver_check.rs @@ -13,6 +13,9 @@ pub fn minimum_update(krate: &Crate) -> Result { let package_name = krate.name.clone(); let current_path = build_doc_json(krate, config)?; + // TODO: Prevent compiler panic on current compiler version + std::env::set_var("RUSTFLAGS", "--cap-lints=warn"); + let baseline = Rustdoc::from_registry_latest_crate_version(); let doc = Rustdoc::from_path(¤t_path); let mut semver_check = Check::new(doc); -- cgit From ce42dd5da5b4495195778e57eeac324c3ca8c54f Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Sat, 16 Aug 2025 13:13:07 +0200 Subject: update version only for un-publishable crates --- release/src/main.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/release/src/main.rs b/release/src/main.rs index cd3e094f1..4d4cd37ed 100644 --- a/release/src/main.rs +++ b/release/src/main.rs @@ -368,19 +368,23 @@ fn main() -> Result<()> { println!("Updating {} from {} -> {}", weight, c.version, newver.to_string()); let newver = newver.to_string(); - update_version(&mut c, &newver)?; - let c = ctx.crates.get(weight).unwrap(); + if c.publish { + update_version(&mut c, &newver)?; + let c = ctx.crates.get(weight).unwrap(); - // Update all nodes further down the tree - let mut bfs = Bfs::new(&rgraph, node); - while let Some(dep_node) = bfs.next(&rgraph) { - let dep_weight = rgraph.node_weight(dep_node).unwrap(); - let dep = ctx.crates.get(dep_weight).unwrap(); - update_versions(dep, &c.name, &newver)?; - } + // Update all nodes further down the tree + let mut bfs = Bfs::new(&rgraph, node); + while let Some(dep_node) = bfs.next(&rgraph) { + let dep_weight = rgraph.node_weight(dep_node).unwrap(); + let dep = ctx.crates.get(dep_weight).unwrap(); + update_versions(dep, &c.name, &newver)?; + } - // Update changelog - update_changelog(&ctx.root, &c)?; + // Update changelog + update_changelog(&ctx.root, &c)?; + } else { + update_version(&mut c, &newver)?; + } } let weight = rgraph.node_weight(*start).unwrap(); -- cgit From 7357810814225e961eced5d0f2b0fe54f46e3970 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Sat, 16 Aug 2025 13:17:54 +0200 Subject: only semvercheck for publishable --- release/src/main.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/release/src/main.rs b/release/src/main.rs index 4d4cd37ed..9c650b697 100644 --- a/release/src/main.rs +++ b/release/src/main.rs @@ -357,18 +357,18 @@ fn main() -> Result<()> { let weight = rgraph.node_weight(node).unwrap(); println!("Preparing {}", weight); let mut c = ctx.crates.get_mut(weight).unwrap(); - let ver = semver::Version::parse(&c.version)?; - let newver = if let Err(_) = check_semver(&c) { - println!("Semver check failed, bumping minor!"); - semver::Version::new(ver.major, ver.minor + 1, 0) - } else { - semver::Version::new(ver.major, ver.minor, ver.patch + 1) - }; + if c.publish { + let ver = semver::Version::parse(&c.version)?; + let newver = if let Err(_) = check_semver(&c) { + println!("Semver check failed, bumping minor!"); + semver::Version::new(ver.major, ver.minor + 1, 0) + } else { + semver::Version::new(ver.major, ver.minor, ver.patch + 1) + }; - println!("Updating {} from {} -> {}", weight, c.version, newver.to_string()); - let newver = newver.to_string(); + println!("Updating {} from {} -> {}", weight, c.version, newver.to_string()); + let newver = newver.to_string(); - if c.publish { update_version(&mut c, &newver)?; let c = ctx.crates.get(weight).unwrap(); @@ -382,8 +382,6 @@ fn main() -> Result<()> { // Update changelog update_changelog(&ctx.root, &c)?; - } else { - update_version(&mut c, &newver)?; } } -- cgit From 85c66be61826b03b509f9223d9f4d0b99798fa88 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Sat, 16 Aug 2025 13:20:03 +0200 Subject: fix: add more missing changelogs --- embassy-imxrt/CHANGELOG.md | 11 +++++++++++ embassy-mspm0/CHANGELOG.md | 1 + embassy-nxp/CHANGELOG.md | 11 +++++++++++ 3 files changed, 23 insertions(+) create mode 100644 embassy-imxrt/CHANGELOG.md create mode 100644 embassy-nxp/CHANGELOG.md diff --git a/embassy-imxrt/CHANGELOG.md b/embassy-imxrt/CHANGELOG.md new file mode 100644 index 000000000..7042ad14c --- /dev/null +++ b/embassy-imxrt/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +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). + + +## Unreleased - ReleaseDate + +- First release with changelog. diff --git a/embassy-mspm0/CHANGELOG.md b/embassy-mspm0/CHANGELOG.md index cf8aeb046..145f678cd 100644 --- a/embassy-mspm0/CHANGELOG.md +++ b/embassy-mspm0/CHANGELOG.md @@ -5,6 +5,7 @@ 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). + ## Unreleased - ReleaseDate - feat: Add I2C Controller (blocking & async) + examples for mspm0l1306, mspm0g3507 (tested MCUs) (#4435) diff --git a/embassy-nxp/CHANGELOG.md b/embassy-nxp/CHANGELOG.md new file mode 100644 index 000000000..7042ad14c --- /dev/null +++ b/embassy-nxp/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +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). + + +## Unreleased - ReleaseDate + +- First release with changelog. -- cgit From a716489ef28e25c351c2eab08b6ab76439531082 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Sat, 16 Aug 2025 13:23:08 +0200 Subject: add missing --- embassy-stm32-wpan/CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 embassy-stm32-wpan/CHANGELOG.md diff --git a/embassy-stm32-wpan/CHANGELOG.md b/embassy-stm32-wpan/CHANGELOG.md new file mode 100644 index 000000000..7042ad14c --- /dev/null +++ b/embassy-stm32-wpan/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +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). + + +## Unreleased - ReleaseDate + +- First release with changelog. -- cgit From fb2741fb8493b27af3becaaaca1589bdde92ff76 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Sat, 16 Aug 2025 13:26:49 +0200 Subject: add missing --- embassy-net-enc28j60/CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 embassy-net-enc28j60/CHANGELOG.md diff --git a/embassy-net-enc28j60/CHANGELOG.md b/embassy-net-enc28j60/CHANGELOG.md new file mode 100644 index 000000000..84f144f99 --- /dev/null +++ b/embassy-net-enc28j60/CHANGELOG.md @@ -0,0 +1,13 @@ +# Changelog + +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). + + +## Unreleased - ReleaseDate + +## 0.1.1 - 2025-08-16 + +- First release with changelog. -- cgit From 90baa19b591b5d09f7fefe6273f1d1337e7c41df Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Sat, 16 Aug 2025 17:50:50 +0200 Subject: fix: version bump --- release/src/main.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/release/src/main.rs b/release/src/main.rs index 9c650b697..488dc9b6a 100644 --- a/release/src/main.rs +++ b/release/src/main.rs @@ -4,6 +4,7 @@ use std::path::{Path, PathBuf}; use std::process::Command as ProcessCommand; use anyhow::{anyhow, bail, Result}; +use cargo_semver_checks::ReleaseType; use clap::{Parser, Subcommand}; use petgraph::graph::{Graph, NodeIndex}; use petgraph::visit::Bfs; @@ -359,11 +360,10 @@ fn main() -> Result<()> { let mut c = ctx.crates.get_mut(weight).unwrap(); if c.publish { let ver = semver::Version::parse(&c.version)?; - let newver = if let Err(_) = check_semver(&c) { - println!("Semver check failed, bumping minor!"); - semver::Version::new(ver.major, ver.minor + 1, 0) - } else { - semver::Version::new(ver.major, ver.minor, ver.patch + 1) + let newver = match check_semver(&c)? { + ReleaseType::Major | ReleaseType::Minor => semver::Version::new(ver.major, ver.minor + 1, 0), + ReleaseType::Patch => semver::Version::new(ver.major, ver.minor, ver.patch + 1), + _ => unreachable!(), }; println!("Updating {} from {} -> {}", weight, c.version, newver.to_string()); @@ -439,10 +439,10 @@ fn main() -> Result<()> { Ok(()) } -fn check_semver(c: &Crate) -> Result<()> { +fn check_semver(c: &Crate) -> Result { let min_version = semver_check::minimum_update(c)?; println!("Version should be bumped to {:?}", min_version); - Ok(()) + Ok(min_version) } fn update_changelog(repo: &Path, c: &Crate) -> Result<()> { -- cgit From bda6368b9be2f24631315c27b71213dbef333341 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Sat, 16 Aug 2025 17:56:17 +0200 Subject: fix: skip publish for now --- embassy-mspm0/Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index d13f16eff..08e0fa9b3 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -9,6 +9,9 @@ categories = ["embedded", "hardware-support", "no-std", "asynchronous"] repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/embassy-mspm0" +# TODO: Remove to publish initial version +publish = false + [package.metadata.embassy] build = [ {target = "thumbv6m-none-eabi", features = ["defmt", "mspm0c1104dgs20", "time-driver-any"]}, -- cgit From a672861f6953119d41ae26597851371514d6cc0b Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Sat, 16 Aug 2025 17:57:19 +0200 Subject: fix: skip publish on a few more --- embassy-nxp/Cargo.toml | 2 ++ embassy-stm32-wpan/Cargo.toml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 68f5c98b2..70e6da076 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -3,6 +3,8 @@ name = "embassy-nxp" version = "0.1.0" edition = "2021" +publish = false + [package.metadata.embassy] build = [ {target = "thumbv8m.main-none-eabihf", features = ["defmt", "lpc55"]}, diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index f7b20cedc..2bdb0d6c4 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -9,6 +9,8 @@ categories = ["embedded", "hardware-support", "no-std", "asynchronous"] repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/embassy-stm32-wpan" +publish = false + [package.metadata.embassy] build = [ {target = "thumbv7em-none-eabi", features = ["stm32wb55rg"]}, -- cgit From 650319f0af0e0edf31155fcc27ada662e5898f46 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Sat, 16 Aug 2025 18:04:56 +0200 Subject: fix: skip another publish --- embassy-imxrt/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-imxrt/Cargo.toml b/embassy-imxrt/Cargo.toml index 5e94dbbc4..006096e99 100644 --- a/embassy-imxrt/Cargo.toml +++ b/embassy-imxrt/Cargo.toml @@ -9,6 +9,7 @@ categories = ["embedded", "hardware-support", "no-std", "asynchronous"] repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/embassy-imxrt" +publish = false [package.metadata.embassy] build = [ {target = "thumbv8m.main-none-eabihf", features = ["defmt", "mimxrt633s", "time", "time-driver-rtc", "unstable-pac"]}, -- cgit From 1c2f87b4fef0377afb47a09b0c51a08cb73d349e Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 18 Aug 2025 14:21:02 +0200 Subject: fix: build rustdoc for baseline as well --- release/Cargo.toml | 8 ++-- release/src/semver_check.rs | 93 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 86 insertions(+), 15 deletions(-) diff --git a/release/Cargo.toml b/release/Cargo.toml index 7875d088a..9701a76e5 100644 --- a/release/Cargo.toml +++ b/release/Cargo.toml @@ -18,10 +18,10 @@ log = "0.4" simple_logger = "5.0.0" temp-file = "0.1.9" flate2 = "1.1.1" - -[patch.crates-io] -cargo-semver-checks = { git = "https://github.com/lulf/cargo-semver-checks.git", rev="385f274edcbb6bf5156e30a94315852b27a527e6" } -#cargo-semver-checks = { path = "../../cargo-semver-checks" } +crates-index = "3.11.0" +tar = "0.4" +reqwest = { version = "0.12", features = ["blocking"] } +cargo-manifest = "0.19.1" [package.metadata.embassy] skip = true diff --git a/release/src/semver_check.rs b/release/src/semver_check.rs index a4a9e77b5..4cfa26ec0 100644 --- a/release/src/semver_check.rs +++ b/release/src/semver_check.rs @@ -1,6 +1,11 @@ +use std::collections::HashSet; use std::path::PathBuf; +use std::{env, fs}; -use cargo_semver_checks::{Check, GlobalConfig, LintConfig, LintLevel, ReleaseType, RequiredSemverUpdate, Rustdoc}; +use anyhow::anyhow; +use cargo_semver_checks::{Check, GlobalConfig, ReleaseType, RequiredSemverUpdate, Rustdoc}; +use flate2::read::GzDecoder; +use tar::Archive; use crate::cargo::CargoArgsBuilder; use crate::types::{BuildConfig, Crate}; @@ -11,12 +16,18 @@ pub fn minimum_update(krate: &Crate) -> Result { let config = krate.configs.first().unwrap(); // TODO let package_name = krate.name.clone(); - let current_path = build_doc_json(krate, config)?; + let baseline_path = download_baseline(&package_name, &krate.version)?; + let mut baseline_krate = krate.clone(); + baseline_krate.path = baseline_path; - // TODO: Prevent compiler panic on current compiler version - std::env::set_var("RUSTFLAGS", "--cap-lints=warn"); + // Compare features as it's not covered by semver-checks + if compare_features(&baseline_krate, &krate)? { + return Ok(ReleaseType::Minor); + } + let baseline_path = build_doc_json(&baseline_krate, config)?; + let current_path = build_doc_json(krate, config)?; - let baseline = Rustdoc::from_registry_latest_crate_version(); + let baseline = Rustdoc::from_path(&baseline_path); let doc = Rustdoc::from_path(¤t_path); let mut semver_check = Check::new(doc); semver_check.with_default_features(); @@ -29,12 +40,8 @@ pub fn minimum_update(krate: &Crate) -> Result { semver_check.set_build_target(target.clone()); } let mut cfg = GlobalConfig::new(); - cfg.set_log_level(Some(log::Level::Trace)); + cfg.set_log_level(Some(log::Level::Info)); - let mut lint_cfg = LintConfig::new(); - // Disable this lint because we provide the rustdoc json only, so it can't do feature comparison. - lint_cfg.set("feature_missing", LintLevel::Allow, RequiredSemverUpdate::Minor, 0); - cfg.set_lint_config(lint_cfg); let result = semver_check.check_release(&mut cfg)?; let mut min_required_update = ReleaseType::Patch; @@ -51,7 +58,71 @@ pub fn minimum_update(krate: &Crate) -> Result { Ok(min_required_update) } -pub(crate) fn build_doc_json(krate: &Crate, config: &BuildConfig) -> Result { +fn compare_features(old: &Crate, new: &Crate) -> Result { + let mut old = read_features(&old.path)?; + let new = read_features(&new.path)?; + + old.retain(|r| !new.contains(r)); + log::info!("Features removed in new: {:?}", old); + Ok(!old.is_empty()) +} + +fn download_baseline(name: &str, version: &str) -> Result { + let config = crates_index::IndexConfig { + dl: "https://crates.io/api/v1/crates".to_string(), + api: Some("https://crates.io".to_string()), + }; + + let url = + config + .download_url(name, version) + .ok_or(anyhow!("unable to download baseline for {}-{}", name, version))?; + + let parent_dir = env::var("RELEASER_CACHE").map_err(|_| anyhow!("RELEASER_CACHE not set"))?; + + let extract_path = PathBuf::from(&parent_dir).join(format!("{}-{}", name, version)); + + if extract_path.exists() { + return Ok(extract_path); + } + + let response = reqwest::blocking::get(url)?; + let bytes = response.bytes()?; + + let decoder = GzDecoder::new(&bytes[..]); + let mut archive = Archive::new(decoder); + archive.unpack(&parent_dir)?; + + Ok(extract_path) +} + +fn read_features(crate_path: &PathBuf) -> Result, anyhow::Error> { + let cargo_toml_path = crate_path.join("Cargo.toml"); + + if !cargo_toml_path.exists() { + return Err(anyhow!("Cargo.toml not found at {:?}", cargo_toml_path)); + } + + let manifest = cargo_manifest::Manifest::from_path(&cargo_toml_path)?; + + let mut set = HashSet::new(); + if let Some(features) = manifest.features { + for f in features.keys() { + set.insert(f.clone()); + } + } + if let Some(deps) = manifest.dependencies { + for (k, v) in deps.iter() { + if v.optional() { + set.insert(k.clone()); + } + } + } + + Ok(set) +} + +fn build_doc_json(krate: &Crate, config: &BuildConfig) -> Result { let target_dir = std::env::var("CARGO_TARGET_DIR"); let target_path = if let Ok(target) = target_dir { -- cgit From 5cab79d817759e50a051d05e245067dd07c81362 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 18 Aug 2025 14:42:27 +0200 Subject: fix: remove unpublished --- embassy-net-nrf91/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml index 76b812efc..feb6eb7a2 100644 --- a/embassy-net-nrf91/Cargo.toml +++ b/embassy-net-nrf91/Cargo.toml @@ -8,6 +8,7 @@ categories = ["embedded", "hardware-support", "no-std", "network-programming", " license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/embassy-net-nrf91" +publish = false [features] defmt = ["dep:defmt", "heapless/defmt-03"] -- cgit From b00496fd299ca1dbc122476f0477b4032d5727c7 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 18 Aug 2025 15:00:22 +0200 Subject: fix: write instructions only for publishing crates --- release/src/main.rs | 14 ++++++++++---- release/src/semver_check.rs | 4 ++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/release/src/main.rs b/release/src/main.rs index 488dc9b6a..22c926b86 100644 --- a/release/src/main.rs +++ b/release/src/main.rs @@ -396,7 +396,9 @@ fn main() -> Result<()> { while let Some(node) = bfs.next(&rgraph) { let weight = rgraph.node_weight(node).unwrap(); let c = ctx.crates.get(weight).unwrap(); - println!("git tag {}-v{}", weight, c.version); + if c.publish { + println!("git tag {}-v{}", weight, c.version); + } } println!(""); @@ -414,8 +416,10 @@ fn main() -> Result<()> { ]; let config = c.configs.first().unwrap(); // TODO - args.push("--features".into()); - args.push(config.features.join(",")); + if !config.features.is_empty() { + args.push("--features".into()); + args.push(config.features.join(",")); + } if let Some(target) = &config.target { args.push("--target".into()); @@ -428,7 +432,9 @@ fn main() -> Result<()> { println!("cargo {}", dry_run.join(" ")); */ - println!("cargo {}", args.join(" ")); + if c.publish { + println!("cargo {}", args.join(" ")); + } } println!(""); diff --git a/release/src/semver_check.rs b/release/src/semver_check.rs index 4cfa26ec0..6255260f3 100644 --- a/release/src/semver_check.rs +++ b/release/src/semver_check.rs @@ -1,9 +1,9 @@ use std::collections::HashSet; +use std::env; use std::path::PathBuf; -use std::{env, fs}; use anyhow::anyhow; -use cargo_semver_checks::{Check, GlobalConfig, ReleaseType, RequiredSemverUpdate, Rustdoc}; +use cargo_semver_checks::{Check, GlobalConfig, ReleaseType, Rustdoc}; use flate2::read::GzDecoder; use tar::Archive; -- cgit From d835b5385734d6211e247b13b7f4b3c53c6b6fff Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 19 Aug 2025 13:58:25 +0200 Subject: chore: move tool to separate repo --- release/Cargo.toml | 27 --- release/src/build.rs | 50 ----- release/src/cargo.rs | 220 ------------------- release/src/main.rs | 514 -------------------------------------------- release/src/semver_check.rs | 178 --------------- release/src/types.rs | 60 ------ 6 files changed, 1049 deletions(-) delete mode 100644 release/Cargo.toml delete mode 100644 release/src/build.rs delete mode 100644 release/src/cargo.rs delete mode 100644 release/src/main.rs delete mode 100644 release/src/semver_check.rs delete mode 100644 release/src/types.rs diff --git a/release/Cargo.toml b/release/Cargo.toml deleted file mode 100644 index 9701a76e5..000000000 --- a/release/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "embassy-release" -version = "0.1.0" -edition = "2021" - -[dependencies] -clap = { version = "4.5.1", features = ["derive"] } -walkdir = "2.5.0" -toml = "0.9.5" -toml_edit = { version = "0.23.1", features = ["serde"] } -serde = { version = "1.0.198", features = ["derive"] } -regex = "1.10.4" -anyhow = "1" -petgraph = "0.8.2" -semver = "1.0.26" -cargo-semver-checks = "0.43.0" -log = "0.4" -simple_logger = "5.0.0" -temp-file = "0.1.9" -flate2 = "1.1.1" -crates-index = "3.11.0" -tar = "0.4" -reqwest = { version = "0.12", features = ["blocking"] } -cargo-manifest = "0.19.1" - -[package.metadata.embassy] -skip = true diff --git a/release/src/build.rs b/release/src/build.rs deleted file mode 100644 index 7c777d36c..000000000 --- a/release/src/build.rs +++ /dev/null @@ -1,50 +0,0 @@ -use anyhow::Result; - -use crate::cargo::{CargoArgsBuilder, CargoBatchBuilder}; - -pub(crate) fn build(ctx: &crate::Context, crate_name: Option<&str>) -> Result<()> { - let mut batch_builder = CargoBatchBuilder::new(); - - // Process either specific crate or all crates - let crates_to_build: Vec<_> = if let Some(name) = crate_name { - // Build only the specified crate - if let Some(krate) = ctx.crates.get(name) { - vec![krate] - } else { - return Err(anyhow::anyhow!("Crate '{}' not found", name)); - } - } else { - // Build all crates - ctx.crates.values().collect() - }; - - // Process selected crates and add their build configurations to the batch - for krate in crates_to_build { - for config in &krate.configs { - let mut args_builder = CargoArgsBuilder::new() - .subcommand("build") - .arg("--release") - .arg(format!("--manifest-path={}/Cargo.toml", krate.path.to_string_lossy())); - - if let Some(ref target) = config.target { - args_builder = args_builder.target(target); - } - - if !config.features.is_empty() { - args_builder = args_builder.features(&config.features); - } - - if let Some(ref artifact_dir) = config.artifact_dir { - args_builder = args_builder.artifact_dir(artifact_dir); - } - - batch_builder.add_command(args_builder.build()); - } - } - - // Execute the cargo batch command - let batch_args = batch_builder.build(); - crate::cargo::run(&batch_args, &ctx.root)?; - - Ok(()) -} diff --git a/release/src/cargo.rs b/release/src/cargo.rs deleted file mode 100644 index c1ed4118f..000000000 --- a/release/src/cargo.rs +++ /dev/null @@ -1,220 +0,0 @@ -//! Tools for working with Cargo. - -use std::ffi::OsStr; -use std::path::{Path, PathBuf}; -use std::process::{Command, Stdio}; - -use anyhow::{bail, Result}; -use serde::{Deserialize, Serialize}; - -use crate::windows_safe_path; - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct Artifact { - pub executable: PathBuf, -} - -/// Execute cargo with the given arguments and from the specified directory. -pub fn run(args: &[String], cwd: &Path) -> Result<()> { - run_with_env::<[(&str, &str); 0], _, _>(args, cwd, [], false)?; - Ok(()) -} - -/// Execute cargo with the given arguments and from the specified directory. -pub fn run_with_env(args: &[String], cwd: &Path, envs: I, capture: bool) -> Result -where - I: IntoIterator + core::fmt::Debug, - K: AsRef, - V: AsRef, -{ - if !cwd.is_dir() { - bail!("The `cwd` argument MUST be a directory"); - } - - // Make sure to not use a UNC as CWD! - // That would make `OUT_DIR` a UNC which will trigger things like the one fixed in https://github.com/dtolnay/rustversion/pull/51 - // While it's fixed in `rustversion` it's not fixed for other crates we are - // using now or in future! - let cwd = windows_safe_path(cwd); - - println!( - "Running `cargo {}` in {:?} - Environment {:?}", - args.join(" "), - cwd, - envs - ); - - let mut command = Command::new(get_cargo()); - - command - .args(args) - .current_dir(cwd) - .envs(envs) - .stdout(if capture { Stdio::piped() } else { Stdio::inherit() }) - .stderr(if capture { Stdio::piped() } else { Stdio::inherit() }); - - if args.iter().any(|a| a.starts_with('+')) { - // Make sure the right cargo runs - command.env_remove("CARGO"); - } - - let output = command.stdin(Stdio::inherit()).output()?; - - // Make sure that we return an appropriate exit code here, as Github Actions - // requires this in order to function correctly: - if output.status.success() { - Ok(String::from_utf8_lossy(&output.stdout).to_string()) - } else { - bail!("Failed to execute cargo subcommand `cargo {}`", args.join(" "),) - } -} - -fn get_cargo() -> String { - // On Windows when executed via `cargo run` (e.g. via the xtask alias) the - // `cargo` on the search path is NOT the cargo-wrapper but the `cargo` from the - // toolchain - that one doesn't understand `+toolchain` - #[cfg(target_os = "windows")] - let cargo = if let Ok(cargo) = std::env::var("CARGO_HOME") { - format!("{cargo}/bin/cargo") - } else { - String::from("cargo") - }; - - #[cfg(not(target_os = "windows"))] - let cargo = String::from("cargo"); - - cargo -} - -#[derive(Debug, Default)] -pub struct CargoArgsBuilder { - toolchain: Option, - subcommand: String, - target: Option, - features: Vec, - args: Vec, -} - -impl CargoArgsBuilder { - #[must_use] - pub fn new() -> Self { - Self { - toolchain: None, - subcommand: String::new(), - target: None, - features: vec![], - args: vec![], - } - } - - #[must_use] - pub fn toolchain(mut self, toolchain: S) -> Self - where - S: Into, - { - self.toolchain = Some(toolchain.into()); - self - } - - #[must_use] - pub fn subcommand(mut self, subcommand: S) -> Self - where - S: Into, - { - self.subcommand = subcommand.into(); - self - } - - #[must_use] - pub fn target(mut self, target: S) -> Self - where - S: Into, - { - self.target = Some(target.into()); - self - } - - #[must_use] - pub fn features(mut self, features: &[String]) -> Self { - self.features = features.to_vec(); - self - } - - #[must_use] - pub fn artifact_dir(mut self, artifact_dir: S) -> Self - where - S: Into, - { - self.args.push(format!("--artifact-dir={}", artifact_dir.into())); - self - } - - #[must_use] - pub fn arg(mut self, arg: S) -> Self - where - S: Into, - { - self.args.push(arg.into()); - self - } - - #[must_use] - pub fn build(&self) -> Vec { - let mut args = vec![]; - - if let Some(ref toolchain) = self.toolchain { - args.push(format!("+{toolchain}")); - } - - args.push(self.subcommand.clone()); - - if let Some(ref target) = self.target { - args.push(format!("--target={target}")); - } - - if !self.features.is_empty() { - args.push(format!("--features={}", self.features.join(","))); - } - - for arg in self.args.iter() { - args.push(arg.clone()); - } - - args - } -} - -#[derive(Debug, Default)] -pub struct CargoBatchBuilder { - commands: Vec>, -} - -impl CargoBatchBuilder { - #[must_use] - pub fn new() -> Self { - Self { commands: vec![] } - } - - #[must_use] - pub fn command(mut self, args: Vec) -> Self { - self.commands.push(args); - self - } - - pub fn add_command(&mut self, args: Vec) -> &mut Self { - self.commands.push(args); - self - } - - #[must_use] - pub fn build(&self) -> Vec { - let mut args = vec!["batch".to_string()]; - - for command in &self.commands { - args.push("---".to_string()); - args.extend(command.clone()); - } - - args - } -} diff --git a/release/src/main.rs b/release/src/main.rs deleted file mode 100644 index 22c926b86..000000000 --- a/release/src/main.rs +++ /dev/null @@ -1,514 +0,0 @@ -use std::collections::{BTreeMap, HashMap}; -use std::fs; -use std::path::{Path, PathBuf}; -use std::process::Command as ProcessCommand; - -use anyhow::{anyhow, bail, Result}; -use cargo_semver_checks::ReleaseType; -use clap::{Parser, Subcommand}; -use petgraph::graph::{Graph, NodeIndex}; -use petgraph::visit::Bfs; -use petgraph::{Directed, Direction}; -use simple_logger::SimpleLogger; -use toml_edit::{DocumentMut, Item, Value}; -use types::*; - -fn check_publish_dependencies(ctx: &Context) -> Result<()> { - for krate in ctx.crates.values() { - if krate.publish { - for dep_name in &krate.dependencies { - if let Some(dep_crate) = ctx.crates.get(dep_name) { - if !dep_crate.publish { - return Err(anyhow!( - "Publishable crate '{}' depends on non-publishable crate '{}'. This is not allowed.", - krate.name, - dep_name - )); - } - } - } - } - } - Ok(()) -} - -mod build; -mod cargo; -mod semver_check; -mod types; - -/// Tool to traverse and operate on intra-repo Rust crate dependencies -#[derive(Parser, Debug)] -#[command(author, version, about)] -struct Args { - /// Command to perform on each crate - #[command(subcommand)] - command: Command, -} - -#[derive(Debug, Subcommand)] -enum Command { - /// All crates and their direct dependencies - List, - /// List all dependencies for a crate - Dependencies { - /// Crate name to print dependencies for. - #[arg(value_name = "CRATE")] - crate_name: String, - }, - /// List all dependencies for a crate - Dependents { - /// Crate name to print dependencies for. - #[arg(value_name = "CRATE")] - crate_name: String, - }, - - /// Build - Build { - /// Crate to check. If not specified checks all crates. - #[arg(value_name = "CRATE")] - crate_name: Option, - }, - /// SemverCheck - SemverCheck { - /// Specific crate name to check - #[arg(value_name = "CRATE")] - crate_name: String, - }, - /// Prepare to release a crate and all dependents that needs updating - /// - Semver checks - /// - Bump versions and commit - /// - Create tag. - PrepareRelease { - /// Crate to release. Will traverse that crate an it's dependents. If not specified checks all crates. - #[arg(value_name = "CRATE")] - crate_name: String, - }, -} - -fn update_version(c: &mut Crate, new_version: &str) -> Result<()> { - let path = c.path.join("Cargo.toml"); - c.version = new_version.to_string(); - let content = fs::read_to_string(&path)?; - let mut doc: DocumentMut = content.parse()?; - for section in ["package"] { - if let Some(Item::Table(dep_table)) = doc.get_mut(section) { - dep_table.insert("version", Item::Value(Value::from(new_version))); - } - } - fs::write(&path, doc.to_string())?; - Ok(()) -} - -fn update_versions(to_update: &Crate, dep: &CrateId, new_version: &str) -> Result<()> { - let path = to_update.path.join("Cargo.toml"); - let content = fs::read_to_string(&path)?; - let mut doc: DocumentMut = content.parse()?; - let mut changed = false; - for section in ["dependencies", "dev-dependencies", "build-dependencies"] { - if let Some(Item::Table(dep_table)) = doc.get_mut(section) { - if let Some(item) = dep_table.get_mut(&dep) { - match item { - // e.g., foo = "0.1.0" - Item::Value(Value::String(_)) => { - *item = Item::Value(Value::from(new_version)); - changed = true; - } - // e.g., foo = { version = "...", ... } - Item::Value(Value::InlineTable(inline)) => { - if inline.contains_key("version") { - inline["version"] = Value::from(new_version); - changed = true; - } - } - _ => {} // Leave unusual formats untouched - } - } - } - } - - if changed { - fs::write(&path, doc.to_string())?; - println!("🔧 Updated {} to {} in {}", dep, new_version, path.display()); - } - Ok(()) -} - -fn list_crates(root: &PathBuf) -> Result> { - let mut crates = BTreeMap::new(); - discover_crates(root, &mut crates)?; - Ok(crates) -} - -fn discover_crates(dir: &PathBuf, crates: &mut BTreeMap) -> Result<()> { - let d = std::fs::read_dir(dir)?; - for c in d { - let entry = c?; - if entry.file_type()?.is_dir() { - let path = dir.join(entry.path()); - let cargo_toml = path.join("Cargo.toml"); - - if cargo_toml.exists() { - let content = fs::read_to_string(&cargo_toml)?; - - // Try to parse as a crate, skip if it's a workspace - let parsed: Result = toml::from_str(&content); - if let Ok(parsed) = parsed { - let id = parsed.package.name; - - let metadata = &parsed.package.metadata.embassy; - - if metadata.skip { - continue; - } - - let mut dependencies = Vec::new(); - for (k, _) in parsed.dependencies { - if k.starts_with("embassy-") { - dependencies.push(k); - } - } - - let mut configs = metadata.build.clone(); - if configs.is_empty() { - configs.push(BuildConfig { - features: vec![], - target: None, - artifact_dir: None, - }) - } - - crates.insert( - id.clone(), - Crate { - name: id, - version: parsed.package.version, - path, - dependencies, - configs, - publish: parsed.package.publish, - }, - ); - } - } else { - // Recursively search subdirectories, but only for examples, tests, and docs - let file_name = entry.file_name(); - let dir_name = file_name.to_string_lossy(); - if dir_name == "examples" || dir_name == "tests" || dir_name == "docs" { - discover_crates(&path, crates)?; - } - } - } - } - Ok(()) -} - -fn build_graph(crates: &BTreeMap) -> (Graph, HashMap) { - let mut graph = Graph::::new(); - let mut node_indices: HashMap = HashMap::new(); - - // Helper to insert or get existing node - let get_or_insert_node = |id: CrateId, graph: &mut Graph, map: &mut HashMap| { - if let Some(&idx) = map.get(&id) { - idx - } else { - let idx = graph.add_node(id.clone()); - map.insert(id, idx); - idx - } - }; - - for krate in crates.values() { - get_or_insert_node(krate.name.clone(), &mut graph, &mut node_indices); - } - - for krate in crates.values() { - // Insert crate node if not exists - let crate_idx = get_or_insert_node(krate.name.clone(), &mut graph, &mut node_indices); - - // Insert dependencies and connect edges - for dep in krate.dependencies.iter() { - let dep_idx = get_or_insert_node(dep.clone(), &mut graph, &mut node_indices); - graph.add_edge(crate_idx, dep_idx, ()); - } - } - - (graph, node_indices) -} - -struct Context { - root: PathBuf, - crates: BTreeMap, - graph: Graph, - indices: HashMap, -} - -fn find_repo_root() -> Result { - let mut path = std::env::current_dir()?.canonicalize()?; - - loop { - // Check if this directory contains a .git directory - if path.join(".git").exists() { - return Ok(path); - } - - // Move to parent directory - match path.parent() { - Some(parent) => path = parent.to_path_buf(), - None => break, - } - } - - Err(anyhow!( - "Could not find repository root. Make sure you're running this tool from within the embassy repository." - )) -} - -fn load_context() -> Result { - let root = find_repo_root()?; - let crates = list_crates(&root)?; - let (graph, indices) = build_graph(&crates); - - let ctx = Context { - root, - crates, - graph, - indices, - }; - - // Check for publish dependency conflicts - check_publish_dependencies(&ctx)?; - - Ok(ctx) -} - -fn main() -> Result<()> { - SimpleLogger::new().init().unwrap(); - let args = Args::parse(); - let mut ctx = load_context()?; - - match args.command { - Command::List => { - let ordered = petgraph::algo::toposort(&ctx.graph, None).unwrap(); - for node in ordered.iter() { - let start = ctx.graph.node_weight(*node).unwrap(); - let mut bfs = Bfs::new(&ctx.graph, *node); - while let Some(node) = bfs.next(&ctx.graph) { - let weight = ctx.graph.node_weight(node).unwrap(); - let c = ctx.crates.get(weight).unwrap(); - if weight == start { - println!("+ {}-{}", weight, c.version); - } else { - println!("|- {}-{}", weight, c.version); - } - } - println!(""); - } - } - Command::Dependencies { crate_name } => { - let idx = ctx.indices.get(&crate_name).expect("unable to find crate in tree"); - let mut bfs = Bfs::new(&ctx.graph, *idx); - while let Some(node) = bfs.next(&ctx.graph) { - let weight = ctx.graph.node_weight(node).unwrap(); - let crt = ctx.crates.get(weight).unwrap(); - if *weight == crate_name { - println!("+ {}-{}", weight, crt.version); - } else { - println!("|- {}-{}", weight, crt.version); - } - } - } - Command::Dependents { crate_name } => { - let idx = ctx.indices.get(&crate_name).expect("unable to find crate in tree"); - let weight = ctx.graph.node_weight(*idx).unwrap(); - let crt = ctx.crates.get(weight).unwrap(); - println!("+ {}-{}", weight, crt.version); - for parent in ctx.graph.neighbors_directed(*idx, Direction::Incoming) { - let weight = ctx.graph.node_weight(parent).unwrap(); - let crt = ctx.crates.get(weight).unwrap(); - println!("|- {}-{}", weight, crt.version); - } - } - Command::Build { crate_name } => { - build::build(&ctx, crate_name.as_deref())?; - } - Command::SemverCheck { crate_name } => { - let c = ctx.crates.get(&crate_name).unwrap(); - if !c.publish { - bail!("Cannot run semver-check on non-publishable crate '{}'", crate_name); - } - check_semver(&c)?; - } - Command::PrepareRelease { crate_name } => { - let start = ctx.indices.get(&crate_name).expect("unable to find crate in tree"); - - // Check if the target crate is publishable - let start_weight = ctx.graph.node_weight(*start).unwrap(); - let start_crate = ctx.crates.get(start_weight).unwrap(); - if !start_crate.publish { - bail!("Cannot prepare release for non-publishable crate '{}'", crate_name); - } - - let mut rgraph = ctx.graph.clone(); - rgraph.reverse(); - - let mut bfs = Bfs::new(&rgraph, *start); - - while let Some(node) = bfs.next(&rgraph) { - let weight = rgraph.node_weight(node).unwrap(); - println!("Preparing {}", weight); - let mut c = ctx.crates.get_mut(weight).unwrap(); - if c.publish { - let ver = semver::Version::parse(&c.version)?; - let newver = match check_semver(&c)? { - ReleaseType::Major | ReleaseType::Minor => semver::Version::new(ver.major, ver.minor + 1, 0), - ReleaseType::Patch => semver::Version::new(ver.major, ver.minor, ver.patch + 1), - _ => unreachable!(), - }; - - println!("Updating {} from {} -> {}", weight, c.version, newver.to_string()); - let newver = newver.to_string(); - - update_version(&mut c, &newver)?; - let c = ctx.crates.get(weight).unwrap(); - - // Update all nodes further down the tree - let mut bfs = Bfs::new(&rgraph, node); - while let Some(dep_node) = bfs.next(&rgraph) { - let dep_weight = rgraph.node_weight(dep_node).unwrap(); - let dep = ctx.crates.get(dep_weight).unwrap(); - update_versions(dep, &c.name, &newver)?; - } - - // Update changelog - update_changelog(&ctx.root, &c)?; - } - } - - let weight = rgraph.node_weight(*start).unwrap(); - let c = ctx.crates.get(weight).unwrap(); - publish_release(&ctx.root, &c, false)?; - - println!("# Please inspect changes and run the following commands when happy:"); - - println!("git commit -a -m 'chore: prepare crate releases'"); - let mut bfs = Bfs::new(&rgraph, *start); - while let Some(node) = bfs.next(&rgraph) { - let weight = rgraph.node_weight(node).unwrap(); - let c = ctx.crates.get(weight).unwrap(); - if c.publish { - println!("git tag {}-v{}", weight, c.version); - } - } - - println!(""); - println!("# Run these commands to publish the crate and dependents:"); - - let mut bfs = Bfs::new(&rgraph, *start); - while let Some(node) = bfs.next(&rgraph) { - let weight = rgraph.node_weight(node).unwrap(); - let c = ctx.crates.get(weight).unwrap(); - - let mut args: Vec = vec![ - "publish".to_string(), - "--manifest-path".to_string(), - c.path.join("Cargo.toml").display().to_string(), - ]; - - let config = c.configs.first().unwrap(); // TODO - if !config.features.is_empty() { - args.push("--features".into()); - args.push(config.features.join(",")); - } - - if let Some(target) = &config.target { - args.push("--target".into()); - args.push(target.clone()); - } - - /* - let mut dry_run = args.clone(); - dry_run.push("--dry-run".to_string()); - - println!("cargo {}", dry_run.join(" ")); - */ - if c.publish { - println!("cargo {}", args.join(" ")); - } - } - - println!(""); - println!("# Run this command to push changes and tags:"); - println!("git push --tags"); - } - } - Ok(()) -} - -fn check_semver(c: &Crate) -> Result { - let min_version = semver_check::minimum_update(c)?; - println!("Version should be bumped to {:?}", min_version); - Ok(min_version) -} - -fn update_changelog(repo: &Path, c: &Crate) -> Result<()> { - let args: Vec = vec![ - "release".to_string(), - "replace".to_string(), - "--config".to_string(), - repo.join("release").join("release.toml").display().to_string(), - "--manifest-path".to_string(), - c.path.join("Cargo.toml").display().to_string(), - "--execute".to_string(), - "--no-confirm".to_string(), - ]; - - let status = ProcessCommand::new("cargo").args(&args).output()?; - - println!("{}", core::str::from_utf8(&status.stdout).unwrap()); - eprintln!("{}", core::str::from_utf8(&status.stderr).unwrap()); - if !status.status.success() { - return Err(anyhow!("release replace failed")); - } else { - Ok(()) - } -} - -fn publish_release(_repo: &Path, c: &Crate, push: bool) -> Result<()> { - let config = c.configs.first().unwrap(); // TODO - - let mut args: Vec = vec![ - "publish".to_string(), - "--manifest-path".to_string(), - c.path.join("Cargo.toml").display().to_string(), - ]; - - args.push("--features".into()); - args.push(config.features.join(",")); - - if let Some(target) = &config.target { - args.push("--target".into()); - args.push(target.clone()); - } - - if !push { - args.push("--dry-run".to_string()); - args.push("--allow-dirty".to_string()); - args.push("--keep-going".to_string()); - } - - let status = ProcessCommand::new("cargo").args(&args).output()?; - - println!("{}", core::str::from_utf8(&status.stdout).unwrap()); - eprintln!("{}", core::str::from_utf8(&status.stderr).unwrap()); - if !status.status.success() { - return Err(anyhow!("publish failed")); - } else { - Ok(()) - } -} - -/// Make the path "Windows"-safe -pub fn windows_safe_path(path: &Path) -> PathBuf { - PathBuf::from(path.to_str().unwrap().to_string().replace("\\\\?\\", "")) -} diff --git a/release/src/semver_check.rs b/release/src/semver_check.rs deleted file mode 100644 index 6255260f3..000000000 --- a/release/src/semver_check.rs +++ /dev/null @@ -1,178 +0,0 @@ -use std::collections::HashSet; -use std::env; -use std::path::PathBuf; - -use anyhow::anyhow; -use cargo_semver_checks::{Check, GlobalConfig, ReleaseType, Rustdoc}; -use flate2::read::GzDecoder; -use tar::Archive; - -use crate::cargo::CargoArgsBuilder; -use crate::types::{BuildConfig, Crate}; - -/// Return the minimum required bump for the next release. -/// Even if nothing changed this will be [ReleaseType::Patch] -pub fn minimum_update(krate: &Crate) -> Result { - let config = krate.configs.first().unwrap(); // TODO - - let package_name = krate.name.clone(); - let baseline_path = download_baseline(&package_name, &krate.version)?; - let mut baseline_krate = krate.clone(); - baseline_krate.path = baseline_path; - - // Compare features as it's not covered by semver-checks - if compare_features(&baseline_krate, &krate)? { - return Ok(ReleaseType::Minor); - } - let baseline_path = build_doc_json(&baseline_krate, config)?; - let current_path = build_doc_json(krate, config)?; - - let baseline = Rustdoc::from_path(&baseline_path); - let doc = Rustdoc::from_path(¤t_path); - let mut semver_check = Check::new(doc); - semver_check.with_default_features(); - semver_check.set_baseline(baseline); - semver_check.set_packages(vec![package_name]); - let extra_current_features = config.features.clone(); - let extra_baseline_features = config.features.clone(); - semver_check.set_extra_features(extra_current_features, extra_baseline_features); - if let Some(target) = &config.target { - semver_check.set_build_target(target.clone()); - } - let mut cfg = GlobalConfig::new(); - cfg.set_log_level(Some(log::Level::Info)); - - let result = semver_check.check_release(&mut cfg)?; - - let mut min_required_update = ReleaseType::Patch; - for (_, report) in result.crate_reports() { - if let Some(required_bump) = report.required_bump() { - let required_is_stricter = - (min_required_update == ReleaseType::Patch) || (required_bump == ReleaseType::Major); - if required_is_stricter { - min_required_update = required_bump; - } - } - } - - Ok(min_required_update) -} - -fn compare_features(old: &Crate, new: &Crate) -> Result { - let mut old = read_features(&old.path)?; - let new = read_features(&new.path)?; - - old.retain(|r| !new.contains(r)); - log::info!("Features removed in new: {:?}", old); - Ok(!old.is_empty()) -} - -fn download_baseline(name: &str, version: &str) -> Result { - let config = crates_index::IndexConfig { - dl: "https://crates.io/api/v1/crates".to_string(), - api: Some("https://crates.io".to_string()), - }; - - let url = - config - .download_url(name, version) - .ok_or(anyhow!("unable to download baseline for {}-{}", name, version))?; - - let parent_dir = env::var("RELEASER_CACHE").map_err(|_| anyhow!("RELEASER_CACHE not set"))?; - - let extract_path = PathBuf::from(&parent_dir).join(format!("{}-{}", name, version)); - - if extract_path.exists() { - return Ok(extract_path); - } - - let response = reqwest::blocking::get(url)?; - let bytes = response.bytes()?; - - let decoder = GzDecoder::new(&bytes[..]); - let mut archive = Archive::new(decoder); - archive.unpack(&parent_dir)?; - - Ok(extract_path) -} - -fn read_features(crate_path: &PathBuf) -> Result, anyhow::Error> { - let cargo_toml_path = crate_path.join("Cargo.toml"); - - if !cargo_toml_path.exists() { - return Err(anyhow!("Cargo.toml not found at {:?}", cargo_toml_path)); - } - - let manifest = cargo_manifest::Manifest::from_path(&cargo_toml_path)?; - - let mut set = HashSet::new(); - if let Some(features) = manifest.features { - for f in features.keys() { - set.insert(f.clone()); - } - } - if let Some(deps) = manifest.dependencies { - for (k, v) in deps.iter() { - if v.optional() { - set.insert(k.clone()); - } - } - } - - Ok(set) -} - -fn build_doc_json(krate: &Crate, config: &BuildConfig) -> Result { - let target_dir = std::env::var("CARGO_TARGET_DIR"); - - let target_path = if let Ok(target) = target_dir { - PathBuf::from(target) - } else { - PathBuf::from(&krate.path).join("target") - }; - - let current_path = target_path; - let current_path = if let Some(target) = &config.target { - current_path.join(target.clone()) - } else { - current_path - }; - let current_path = current_path - .join("doc") - .join(format!("{}.json", krate.name.to_string().replace("-", "_"))); - - std::fs::remove_file(¤t_path).ok(); - let features = config.features.clone(); - - log::info!("Building doc json for {} with features: {:?}", krate.name, features); - - let envs = vec![( - "RUSTDOCFLAGS", - "--cfg docsrs --cfg not_really_docsrs --cfg semver_checks", - )]; - - // always use `specific nightly` toolchain so we don't have to deal with potentially - // different versions of the doc-json - let cargo_builder = CargoArgsBuilder::default() - .toolchain("nightly-2025-06-29") - .subcommand("rustdoc") - .features(&features); - let cargo_builder = if let Some(target) = &config.target { - cargo_builder.target(target.clone()) - } else { - cargo_builder - }; - - let cargo_builder = cargo_builder - .arg("-Zunstable-options") - .arg("-Zhost-config") - .arg("-Ztarget-applies-to-host") - .arg("--lib") - .arg("--output-format=json") - .arg("-Zbuild-std=alloc,core") - .arg("--config=host.rustflags=[\"--cfg=instability_disable_unstable_docs\"]"); - let cargo_args = cargo_builder.build(); - log::debug!("{cargo_args:#?}"); - crate::cargo::run_with_env(&cargo_args, &krate.path, envs, false)?; - Ok(current_path) -} diff --git a/release/src/types.rs b/release/src/types.rs deleted file mode 100644 index be0a883f1..000000000 --- a/release/src/types.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::collections::BTreeMap; -use std::path::PathBuf; - -use serde::Deserialize; - -#[derive(Debug, Deserialize)] -pub struct ParsedCrate { - pub package: ParsedPackage, - pub dependencies: BTreeMap, -} - -#[derive(Debug, Deserialize)] -pub struct ParsedPackage { - pub name: String, - pub version: String, - #[serde(default = "default_publish")] - pub publish: bool, - #[serde(default)] - pub metadata: Metadata, -} - -fn default_publish() -> bool { - true -} - -#[derive(Debug, Deserialize, Default)] -pub struct Metadata { - #[serde(default)] - pub embassy: MetadataEmbassy, -} - -#[allow(dead_code)] -#[derive(Debug, Deserialize, Default)] -pub struct MetadataEmbassy { - #[serde(default)] - pub skip: bool, - #[serde(default)] - pub build: Vec, -} - -#[derive(Debug, Clone, Deserialize)] -pub struct BuildConfig { - #[serde(default)] - pub features: Vec, - pub target: Option, - #[serde(rename = "artifact-dir")] - pub artifact_dir: Option, -} - -pub type CrateId = String; - -#[derive(Debug, Clone)] -pub struct Crate { - pub name: String, - pub version: String, - pub path: PathBuf, - pub dependencies: Vec, - pub configs: Vec, - pub publish: bool, -} -- cgit From 462245b0fecf148e376efeedee943fd70590550e Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 19 Aug 2025 14:12:56 +0200 Subject: fix: use the cargo-embassy-devtool --- ci.sh | 335 ++---------------------------------------------------------------- 1 file changed, 10 insertions(+), 325 deletions(-) diff --git a/ci.sh b/ci.sh index 4fdce65d2..f8a06c6fa 100755 --- a/ci.sh +++ b/ci.sh @@ -10,6 +10,14 @@ if ! command -v cargo-batch &> /dev/null; then exit 1 fi +if ! command -v cargo-embassy-devtool &> /dev/null; then + echo "cargo-embassy-devtool could not be found. Install it with the following command:" + echo "" + echo " cargo install --git https://github.com/embassy-rs/cargo-embassy-devtool --bin cargo-embassy-devtool --locked" + echo "" + exit 1 +fi + export RUSTFLAGS=-Dwarnings export DEFMT_LOG=trace,embassy_hal_internal=debug,embassy_net_esp_hosted=debug,cyw43=info,cyw43_pio=info,smoltcp=info if [[ -z "${CARGO_TARGET_DIR}" ]]; then @@ -23,331 +31,8 @@ if [ $TARGET = "x86_64-unknown-linux-gnu" ] || [ $TARGET = "aarch64-unknown-linu BUILD_EXTRA="--- build --release --manifest-path examples/std/Cargo.toml --target $TARGET --artifact-dir out/examples/std" fi -# CI intentionally does not use -eabihf on thumbv7em to minimize dep compile time. -cargo batch \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features log \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features defmt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt,arch-cortex-m,executor-thread,executor-interrupt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,rtos-trace \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread,executor-interrupt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7a-none-eabi --features arch-cortex-ar,executor-thread \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7r-none-eabi --features arch-cortex-ar,executor-thread \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7r-none-eabihf --features arch-cortex-ar,executor-thread \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32 \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32,executor-thread \ - --- build --release --manifest-path embassy-embedded-hal/Cargo.toml --target thumbv7em-none-eabi \ - --- build --release --manifest-path embassy-embedded-hal/Cargo.toml --target thumbv7em-none-eabi --features time \ - --- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features defmt \ - --- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features defmt,defmt-timestamp-uptime,mock-driver \ - --- build --release --manifest-path embassy-time/Cargo.toml --features defmt,std \ - --- build --release --manifest-path embassy-time-queue-utils/Cargo.toml --target thumbv6m-none-eabi \ - --- build --release --manifest-path embassy-time-queue-utils/Cargo.toml --target thumbv6m-none-eabi --features generic-queue-8 \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet,packet-trace \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,multicast,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,dhcpv4-hostname \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ieee802154 \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,medium-ieee802154 \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip,medium-ethernet,medium-ieee802154 \ - --- build --release --manifest-path embassy-imxrt/Cargo.toml --target thumbv8m.main-none-eabihf --features mimxrt633s,defmt,unstable-pac,time,time-driver-rtc \ - --- build --release --manifest-path embassy-imxrt/Cargo.toml --target thumbv8m.main-none-eabihf --features mimxrt685s,defmt,unstable-pac,time,time-driver-rtc \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52805,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52810,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52811,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52820,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52832,gpiote,time,time-driver-rtc1,reset-pin-as-gpio \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52833,gpiote,time,time-driver-rtc1,nfc-pins-as-gpio \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf9160-s,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf9160-ns,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-app-s,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-app-ns,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-net,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf54l15-app-s,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf54l15-app-ns,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,log,time \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,log,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,log,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,defmt,time \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,defmt,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,defmt,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51,defmt,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51,defmt,time \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51,time \ - --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features time-driver,defmt,rp2040 \ - --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features time-driver,log,rp2040 \ - --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features time-driver,intrinsics,rp2040 \ - --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features time-driver,qspi-as-gpio,rp2040 \ - --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv8m.main-none-eabihf --features time-driver,defmt,rp235xa \ - --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv8m.main-none-eabihf --features time-driver,log,rp235xa \ - --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv8m.main-none-eabihf --features time-driver,rp235xa,binary-info \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,single-bank,defmt \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c071rb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c051f6,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c091gb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c092rc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f038f6,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f030c6,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f058t8,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f030r8,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f031k6,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f030rc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f070f6,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f078vb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f042g4,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f072c8,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f401ve,defmt,exti,time-driver-any \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f405zg,defmt,exti,time-driver-any \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f407zg,defmt,exti,time-driver-any \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f401ve,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f405zg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f407zg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f410tb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f411ce,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f412zg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f413vh,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f415zg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f417zg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f423zh,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f427zi,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f437zi,log,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f439zi,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446ze,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f469zi,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f479zi,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f730i8,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h753zi,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h735zg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,time,split-pc2,split-pc3 \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h725re,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-tim1,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7r3z8,defmt,exti,time-driver-tim1,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7r7a8,defmt,exti,time-driver-tim1,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s3a8,log,exti,time-driver-tim1,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s7z8,defmt,exti,time-driver-tim1,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l431cb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l422cb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb15cc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l041f6,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l051k8,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l073cz,defmt,exti,time-driver-any,low-power,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303c8,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f398ve,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f378cc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g0b0ce,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g0c1ve,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time-driver-any,low-power,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32wl54jc-cm0p,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wle5jb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g431kb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g474pe,dual-bank,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f107vc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f103re,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f100c4,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h503rb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h523cc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h562ag,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba50ke,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba55ug,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba62cg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba65ri,defmt,exti,time-driver-any,low-power,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u5f9zj,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u5g9nj,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb35ce,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55rg,defmt,exti,time-driver-any,low-power,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u031r8,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u073mb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u083rc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv8m.main-none-eabihf --features lpc55,defmt \ - --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv7em-none-eabihf --features mimxrt1011,rt,defmt,time-driver-pit \ - --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv7em-none-eabihf --features mimxrt1062,rt,defmt,time-driver-pit \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0c1104dgs20,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3507pm,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3519pz,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1306rhb,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l2228pn,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1345dgs28,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1106dgs28,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1228pm,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1107ycj,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3105rhb,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1505pt,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1519rhb,defmt,time-driver-any \ - --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features ''\ - --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log' \ - --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt' \ - --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log,firmware-logs' \ - --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt,firmware-logs' \ - --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log,firmware-logs,bluetooth' \ - --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt,firmware-logs,bluetooth' \ - --- build --release --manifest-path cyw43-pio/Cargo.toml --target thumbv6m-none-eabi --features 'embassy-rp/rp2040' \ - --- build --release --manifest-path cyw43-pio/Cargo.toml --target thumbv6m-none-eabi --features 'embassy-rp/rp2040' \ - --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \ - --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf5340-app-s \ - --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns \ - --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9120-ns \ - --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9151-ns \ - --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9161-ns \ - --- build --release --manifest-path embassy-boot-rp/Cargo.toml --target thumbv6m-none-eabi --features embassy-rp/rp2040 \ - --- build --release --manifest-path embassy-boot-stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32l496zg \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --no-default-features \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features log \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features defmt \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features usbd-hid \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features max-interface-count-1 \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features max-interface-count-8 \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features max-handler-count-8 \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features max-handler-count-8 \ - --- build --release --manifest-path docs/examples/basic/Cargo.toml --target thumbv7em-none-eabi \ - --- build --release --manifest-path docs/examples/layer-by-layer/blinky-pac/Cargo.toml --target thumbv7em-none-eabi \ - --- build --release --manifest-path docs/examples/layer-by-layer/blinky-hal/Cargo.toml --target thumbv7em-none-eabi \ - --- build --release --manifest-path docs/examples/layer-by-layer/blinky-irq/Cargo.toml --target thumbv7em-none-eabi \ - --- build --release --manifest-path docs/examples/layer-by-layer/blinky-async/Cargo.toml --target thumbv7em-none-eabi \ - --- build --release --manifest-path examples/nrf52810/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/nrf52810 \ - --- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/nrf52840 \ - --- build --release --manifest-path examples/nrf5340/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf5340 \ - --- build --release --manifest-path examples/nrf54l15/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf54l15 \ - --- build --release --manifest-path examples/nrf9160/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf9160 \ - --- build --release --manifest-path examples/nrf9151/s/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf9151/s \ - --- build --release --manifest-path examples/nrf9151/ns/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf9151/ns \ - --- build --release --manifest-path examples/nrf51/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/nrf51 \ - --- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/rp \ - --- build --release --manifest-path examples/rp235x/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/rp235x \ - --- build --release --manifest-path examples/stm32f0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32f0 \ - --- build --release --manifest-path examples/stm32f1/Cargo.toml --target thumbv7m-none-eabi --artifact-dir out/examples/stm32f1 \ - --- build --release --manifest-path examples/stm32f2/Cargo.toml --target thumbv7m-none-eabi --artifact-dir out/examples/stm32f2 \ - --- build --release --manifest-path examples/stm32f3/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f3 \ - --- build --release --manifest-path examples/stm32f334/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f334 \ - --- build --release --manifest-path examples/stm32f4/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f4 \ - --- build --release --manifest-path examples/stm32f469/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f469 \ - --- build --release --manifest-path examples/stm32f7/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f7 \ - --- build --release --manifest-path examples/stm32c0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32c0 \ - --- build --release --manifest-path examples/stm32g0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32g0 \ - --- build --release --manifest-path examples/stm32g4/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32g4 \ - --- build --release --manifest-path examples/stm32h5/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32h5 \ - --- build --release --manifest-path examples/stm32h7/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h7 \ - --- build --release --manifest-path examples/stm32h7b0/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h7b0 \ - --- build --release --manifest-path examples/stm32h723/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h723 \ - --- build --release --manifest-path examples/stm32h735/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h735 \ - --- build --release --manifest-path examples/stm32h755cm4/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h755cm4 \ - --- build --release --manifest-path examples/stm32h755cm7/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h755cm7 \ - --- build --release --manifest-path examples/stm32h7rs/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h7rs \ - --- build --release --manifest-path examples/stm32l0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32l0 \ - --- build --release --manifest-path examples/stm32l1/Cargo.toml --target thumbv7m-none-eabi --artifact-dir out/examples/stm32l1 \ - --- build --release --manifest-path examples/stm32l4/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32l4 \ - --- build --release --manifest-path examples/stm32l432/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32l432 \ - --- build --release --manifest-path examples/stm32l5/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32l5 \ - --- build --release --manifest-path examples/stm32u0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32u0 \ - --- build --release --manifest-path examples/stm32u5/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32u5 \ - --- build --release --manifest-path examples/stm32wb/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32wb \ - --- build --release --manifest-path examples/stm32wba/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32wba \ - --- build --release --manifest-path examples/stm32wba6/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32wba6 \ - --- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32wl \ - --- build --release --manifest-path examples/lpc55s69/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/lpc55s69 \ - --- build --release --manifest-path examples/mimxrt1011/Cargo.toml --target thumbv7em-none-eabihf --artifact-dir out/examples/mimxrt1011 \ - --- build --release --manifest-path examples/mimxrt1062-evk/Cargo.toml --target thumbv7em-none-eabihf --artifact-dir out/examples/mimxrt1062-evk \ - --- build --release --manifest-path examples/mspm0g3507/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3507 \ - --- build --release --manifest-path examples/mspm0g3519/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3519 \ - --- build --release --manifest-path examples/mspm0l1306/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0l1306 \ - --- build --release --manifest-path examples/mspm0l2228/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0l2228 \ - --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840,skip-include --artifact-dir out/examples/boot/nrf52840 \ - --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns,skip-include --artifact-dir out/examples/boot/nrf9160 \ - --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9120-ns,skip-include --artifact-dir out/examples/boot/nrf9120 \ - --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9151-ns,skip-include --artifact-dir out/examples/boot/nrf9151 \ - --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9161-ns,skip-include --artifact-dir out/examples/boot/nrf9161 \ - --- build --release --manifest-path examples/boot/application/rp/Cargo.toml --target thumbv6m-none-eabi --features skip-include --artifact-dir out/examples/boot/rp \ - --- build --release --manifest-path examples/boot/application/stm32f3/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32f3 \ - --- build --release --manifest-path examples/boot/application/stm32f7/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32f7 \ - --- build --release --manifest-path examples/boot/application/stm32h7/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32h7 \ - --- build --release --manifest-path examples/boot/application/stm32l0/Cargo.toml --target thumbv6m-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32l0 \ - --- build --release --manifest-path examples/boot/application/stm32l1/Cargo.toml --target thumbv7m-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32l1 \ - --- build --release --manifest-path examples/boot/application/stm32l4/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32l4 \ - --- build --release --manifest-path examples/boot/application/stm32wl/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32wl \ - --- build --release --manifest-path examples/boot/application/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/boot/stm32wb-dfu \ - --- build --release --manifest-path examples/boot/application/stm32wba-dfu/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/boot/stm32wba-dfu \ - --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \ - --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns \ - --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9120-ns \ - --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9151-ns \ - --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9161-ns \ - --- build --release --manifest-path examples/boot/bootloader/rp/Cargo.toml --target thumbv6m-none-eabi \ - --- build --release --manifest-path examples/boot/bootloader/stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32l496zg \ - --- build --release --manifest-path examples/boot/bootloader/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wb55rg \ - --- build --release --manifest-path examples/boot/bootloader/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wb55rg,verify \ - --- build --release --manifest-path examples/boot/bootloader/stm32wba-dfu/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-stm32/stm32wba65ri,verify \ - --- build --release --manifest-path examples/boot/bootloader/stm32-dual-bank/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32h743zi \ - --- build --release --manifest-path examples/wasm/Cargo.toml --target wasm32-unknown-unknown --artifact-dir out/examples/wasm \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f103c8 --artifact-dir out/tests/stm32f103c8 \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi --artifact-dir out/tests/stm32f429zi \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446re --artifact-dir out/tests/stm32f446re \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g491re --artifact-dir out/tests/stm32g491re \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g071rb --artifact-dir out/tests/stm32g071rb \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c031c6 --artifact-dir out/tests/stm32c031c6 \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c071rb --artifact-dir out/tests/stm32c071rb \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi --artifact-dir out/tests/stm32h755zi \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h753zi --artifact-dir out/tests/stm32h753zi \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7a3zi --artifact-dir out/tests/stm32h7a3zi \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55rg --artifact-dir out/tests/stm32wb55rg \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h563zi --artifact-dir out/tests/stm32h563zi \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u585ai --artifact-dir out/tests/stm32u585ai \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u5a5zj --artifact-dir out/tests/stm32u5a5zj \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba52cg --artifact-dir out/tests/stm32wba52cg \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l073rz --artifact-dir out/tests/stm32l073rz \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l152re --artifact-dir out/tests/stm32l152re \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4a6zg --artifact-dir out/tests/stm32l4a6zg \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4r5zi --artifact-dir out/tests/stm32l4r5zi \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze --artifact-dir out/tests/stm32l552ze \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f767zi --artifact-dir out/tests/stm32f767zi \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f207zg --artifact-dir out/tests/stm32f207zg \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303ze --artifact-dir out/tests/stm32f303ze \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l496zg --artifact-dir out/tests/stm32l496zg \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55jc --artifact-dir out/tests/stm32wl55jc \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s3l8 --artifact-dir out/tests/stm32h7s3l8 \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f091rc --artifact-dir out/tests/stm32f091rc \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h503rb --artifact-dir out/tests/stm32h503rb \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u083rc --artifact-dir out/tests/stm32u083rc \ - --- build --release --manifest-path tests/rp/Cargo.toml --target thumbv6m-none-eabi --features rp2040 --artifact-dir out/tests/rpi-pico \ - --- build --release --manifest-path tests/rp/Cargo.toml --target thumbv8m.main-none-eabihf --features rp235xb --artifact-dir out/tests/pimoroni-pico-plus-2 \ - --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51422 --artifact-dir out/tests/nrf51422-dk \ - --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52832 --artifact-dir out/tests/nrf52832-dk \ - --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52833 --artifact-dir out/tests/nrf52833-dk \ - --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840 --artifact-dir out/tests/nrf52840-dk \ - --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340 --artifact-dir out/tests/nrf5340-dk \ - --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf9160 --artifact-dir out/tests/nrf9160-dk \ - --- build --release --manifest-path tests/mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3507 --artifact-dir out/tests/mspm0g3507 \ - --- build --release --manifest-path tests/riscv32/Cargo.toml --target riscv32imac-unknown-none-elf \ - $BUILD_EXTRA - +# Use devtool to build all combinations defined in the Cargo.tomls +cargo embassy-devtool build # MSPM0C1104 must be built seperately since cargo batch does not consider env vars set in `.cargo/config.toml`. # Since the target has 1KB of ram, we need to limit defmt's buffer size. -- cgit From ce4ffe52da4ec042c44f6073e036b363c9f89189 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 25 Aug 2025 19:47:08 +0200 Subject: add metadata for embassy-executor-time-queue --- embassy-executor-timer-queue/Cargo.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/embassy-executor-timer-queue/Cargo.toml b/embassy-executor-timer-queue/Cargo.toml index 0db327ba9..a0ac44420 100644 --- a/embassy-executor-timer-queue/Cargo.toml +++ b/embassy-executor-timer-queue/Cargo.toml @@ -33,3 +33,9 @@ timer-item-size-8-words = [] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-timer-queue-v$VERSION/embassy-executor-timer-queue/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor-timer-queue/src/" target = "x86_64-unknown-linux-gnu" + +[package.metadata.embassy] +build = [ + {target = "thumbv7em-none-eabi", features = []}, + {target = "thumbv6m-none-eabi", features = []}, +] -- cgit From a416aac9c25c6aad226d8b7bdaefaab0015c5718 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 25 Aug 2025 19:48:34 +0200 Subject: fix: revert changes to ci.sh for now --- ci.sh | 336 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 325 insertions(+), 11 deletions(-) diff --git a/ci.sh b/ci.sh index f8a06c6fa..68bf38881 100755 --- a/ci.sh +++ b/ci.sh @@ -10,14 +10,6 @@ if ! command -v cargo-batch &> /dev/null; then exit 1 fi -if ! command -v cargo-embassy-devtool &> /dev/null; then - echo "cargo-embassy-devtool could not be found. Install it with the following command:" - echo "" - echo " cargo install --git https://github.com/embassy-rs/cargo-embassy-devtool --bin cargo-embassy-devtool --locked" - echo "" - exit 1 -fi - export RUSTFLAGS=-Dwarnings export DEFMT_LOG=trace,embassy_hal_internal=debug,embassy_net_esp_hosted=debug,cyw43=info,cyw43_pio=info,smoltcp=info if [[ -z "${CARGO_TARGET_DIR}" ]]; then @@ -31,8 +23,331 @@ if [ $TARGET = "x86_64-unknown-linux-gnu" ] || [ $TARGET = "aarch64-unknown-linu BUILD_EXTRA="--- build --release --manifest-path examples/std/Cargo.toml --target $TARGET --artifact-dir out/examples/std" fi -# Use devtool to build all combinations defined in the Cargo.tomls -cargo embassy-devtool build +# CI intentionally does not use -eabihf on thumbv7em to minimize dep compile time. +cargo batch \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features log \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features defmt \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt,arch-cortex-m,executor-thread,executor-interrupt \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,rtos-trace \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread,executor-interrupt \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7a-none-eabi --features arch-cortex-ar,executor-thread \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7r-none-eabi --features arch-cortex-ar,executor-thread \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7r-none-eabihf --features arch-cortex-ar,executor-thread \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32 \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32,executor-thread \ + --- build --release --manifest-path embassy-embedded-hal/Cargo.toml --target thumbv7em-none-eabi \ + --- build --release --manifest-path embassy-embedded-hal/Cargo.toml --target thumbv7em-none-eabi --features time \ + --- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features defmt \ + --- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features defmt,defmt-timestamp-uptime,mock-driver \ + --- build --release --manifest-path embassy-time/Cargo.toml --features defmt,std \ + --- build --release --manifest-path embassy-time-queue-utils/Cargo.toml --target thumbv6m-none-eabi \ + --- build --release --manifest-path embassy-time-queue-utils/Cargo.toml --target thumbv6m-none-eabi --features generic-queue-8 \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet,packet-trace \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,multicast,medium-ethernet \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,dhcpv4-hostname \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ieee802154 \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,medium-ieee802154 \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ethernet \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip,medium-ethernet \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip,medium-ethernet,medium-ieee802154 \ + --- build --release --manifest-path embassy-imxrt/Cargo.toml --target thumbv8m.main-none-eabihf --features mimxrt633s,defmt,unstable-pac,time,time-driver-rtc \ + --- build --release --manifest-path embassy-imxrt/Cargo.toml --target thumbv8m.main-none-eabihf --features mimxrt685s,defmt,unstable-pac,time,time-driver-rtc \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51,gpiote,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52805,gpiote,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52810,gpiote,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52811,gpiote,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52820,gpiote,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52832,gpiote,time,time-driver-rtc1,reset-pin-as-gpio \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52833,gpiote,time,time-driver-rtc1,nfc-pins-as-gpio \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf9160-s,gpiote,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf9160-ns,gpiote,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-app-s,gpiote,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-app-ns,gpiote,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-net,gpiote,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf54l15-app-s,gpiote,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf54l15-app-ns,gpiote,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,log,time \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,log,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,log,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,defmt,time \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,defmt,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,defmt,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51,defmt,time,time-driver-rtc1 \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51,defmt,time \ + --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51,time \ + --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features time-driver,defmt,rp2040 \ + --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features time-driver,log,rp2040 \ + --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features time-driver,intrinsics,rp2040 \ + --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features time-driver,qspi-as-gpio,rp2040 \ + --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv8m.main-none-eabihf --features time-driver,defmt,rp235xa \ + --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv8m.main-none-eabihf --features time-driver,log,rp235xa \ + --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv8m.main-none-eabihf --features time-driver,rp235xa,binary-info \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,single-bank,defmt \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c071rb,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c051f6,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c091gb,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c092rc,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f038f6,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f030c6,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f058t8,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f030r8,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f031k6,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f030rc,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f070f6,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f078vb,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f042g4,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f072c8,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f401ve,defmt,exti,time-driver-any \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f405zg,defmt,exti,time-driver-any \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f407zg,defmt,exti,time-driver-any \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f401ve,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f405zg,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f407zg,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f410tb,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f411ce,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f412zg,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f413vh,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f415zg,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f417zg,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f423zh,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f427zi,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f437zi,log,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f439zi,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446ze,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f469zi,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f479zi,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f730i8,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h753zi,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h735zg,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,time,split-pc2,split-pc3 \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h725re,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-tim1,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7r3z8,defmt,exti,time-driver-tim1,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7r7a8,defmt,exti,time-driver-tim1,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s3a8,defmt,exti,time-driver-tim1,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s7z8,defmt,exti,time-driver-tim1,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l431cb,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l422cb,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb15cc,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l041f6,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l051k8,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l073cz,defmt,exti,time-driver-any,low-power,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303c8,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f398ve,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f378cc,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g0b0ce,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g0c1ve,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time-driver-any,low-power,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32wl54jc-cm0p,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wle5jb,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g431kb,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g474pe,dual-bank,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f107vc,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f103re,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f100c4,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h503rb,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h523cc,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h562ag,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba50ke,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba55ug,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba62cg,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba65ri,defmt,exti,time-driver-any,low-power,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u5f9zj,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u5g9nj,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb35ce,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55rg,defmt,exti,time-driver-any,low-power,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u031r8,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u073mb,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u083rc,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv8m.main-none-eabihf --features lpc55,defmt \ + --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv7em-none-eabihf --features mimxrt1011,rt,defmt,time-driver-pit \ + --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv7em-none-eabihf --features mimxrt1062,rt,defmt,time-driver-pit \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0c1104dgs20,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3507pm,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3519pz,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1306rhb,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l2228pn,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1345dgs28,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1106dgs28,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1228pm,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1107ycj,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3105rhb,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1505pt,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1519rhb,defmt,time-driver-any \ + --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features ''\ + --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log' \ + --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt' \ + --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log,firmware-logs' \ + --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt,firmware-logs' \ + --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log,firmware-logs,bluetooth' \ + --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt,firmware-logs,bluetooth' \ + --- build --release --manifest-path cyw43-pio/Cargo.toml --target thumbv6m-none-eabi --features 'embassy-rp/rp2040' \ + --- build --release --manifest-path cyw43-pio/Cargo.toml --target thumbv6m-none-eabi --features 'embassy-rp/rp2040' \ + --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \ + --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf5340-app-s \ + --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns \ + --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9120-ns \ + --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9151-ns \ + --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9161-ns \ + --- build --release --manifest-path embassy-boot-rp/Cargo.toml --target thumbv6m-none-eabi --features embassy-rp/rp2040 \ + --- build --release --manifest-path embassy-boot-stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32l496zg \ + --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --no-default-features \ + --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi \ + --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features log \ + --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features defmt \ + --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features usbd-hid \ + --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features max-interface-count-1 \ + --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features max-interface-count-8 \ + --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features max-handler-count-8 \ + --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features max-handler-count-8 \ + --- build --release --manifest-path docs/examples/basic/Cargo.toml --target thumbv7em-none-eabi \ + --- build --release --manifest-path docs/examples/layer-by-layer/blinky-pac/Cargo.toml --target thumbv7em-none-eabi \ + --- build --release --manifest-path docs/examples/layer-by-layer/blinky-hal/Cargo.toml --target thumbv7em-none-eabi \ + --- build --release --manifest-path docs/examples/layer-by-layer/blinky-irq/Cargo.toml --target thumbv7em-none-eabi \ + --- build --release --manifest-path docs/examples/layer-by-layer/blinky-async/Cargo.toml --target thumbv7em-none-eabi \ + --- build --release --manifest-path examples/nrf52810/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/nrf52810 \ + --- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/nrf52840 \ + --- build --release --manifest-path examples/nrf5340/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf5340 \ + --- build --release --manifest-path examples/nrf54l15/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf54l15 \ + --- build --release --manifest-path examples/nrf9160/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf9160 \ + --- build --release --manifest-path examples/nrf9151/s/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf9151/s \ + --- build --release --manifest-path examples/nrf9151/ns/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf9151/ns \ + --- build --release --manifest-path examples/nrf51/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/nrf51 \ + --- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/rp \ + --- build --release --manifest-path examples/rp235x/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/rp235x \ + --- build --release --manifest-path examples/stm32f0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32f0 \ + --- build --release --manifest-path examples/stm32f1/Cargo.toml --target thumbv7m-none-eabi --artifact-dir out/examples/stm32f1 \ + --- build --release --manifest-path examples/stm32f2/Cargo.toml --target thumbv7m-none-eabi --artifact-dir out/examples/stm32f2 \ + --- build --release --manifest-path examples/stm32f3/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f3 \ + --- build --release --manifest-path examples/stm32f334/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f334 \ + --- build --release --manifest-path examples/stm32f4/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f4 \ + --- build --release --manifest-path examples/stm32f469/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f469 \ + --- build --release --manifest-path examples/stm32f7/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f7 \ + --- build --release --manifest-path examples/stm32c0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32c0 \ + --- build --release --manifest-path examples/stm32g0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32g0 \ + --- build --release --manifest-path examples/stm32g4/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32g4 \ + --- build --release --manifest-path examples/stm32h5/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32h5 \ + --- build --release --manifest-path examples/stm32h7/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h7 \ + --- build --release --manifest-path examples/stm32h7b0/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h7b0 \ + --- build --release --manifest-path examples/stm32h723/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h723 \ + --- build --release --manifest-path examples/stm32h735/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h735 \ + --- build --release --manifest-path examples/stm32h755cm4/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h755cm4 \ + --- build --release --manifest-path examples/stm32h755cm7/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h755cm7 \ + --- build --release --manifest-path examples/stm32h7rs/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h7rs \ + --- build --release --manifest-path examples/stm32l0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32l0 \ + --- build --release --manifest-path examples/stm32l1/Cargo.toml --target thumbv7m-none-eabi --artifact-dir out/examples/stm32l1 \ + --- build --release --manifest-path examples/stm32l4/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32l4 \ + --- build --release --manifest-path examples/stm32l432/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32l432 \ + --- build --release --manifest-path examples/stm32l5/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32l5 \ + --- build --release --manifest-path examples/stm32u0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32u0 \ + --- build --release --manifest-path examples/stm32u5/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32u5 \ + --- build --release --manifest-path examples/stm32wb/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32wb \ + --- build --release --manifest-path examples/stm32wba/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32wba \ + --- build --release --manifest-path examples/stm32wba6/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32wba6 \ + --- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32wl \ + --- build --release --manifest-path examples/lpc55s69/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/lpc55s69 \ + --- build --release --manifest-path examples/mimxrt1011/Cargo.toml --target thumbv7em-none-eabihf --artifact-dir out/examples/mimxrt1011 \ + --- build --release --manifest-path examples/mimxrt1062-evk/Cargo.toml --target thumbv7em-none-eabihf --artifact-dir out/examples/mimxrt1062-evk \ + --- build --release --manifest-path examples/mspm0g3507/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3507 \ + --- build --release --manifest-path examples/mspm0g3519/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3519 \ + --- build --release --manifest-path examples/mspm0l1306/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0l1306 \ + --- build --release --manifest-path examples/mspm0l2228/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0l2228 \ + --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840,skip-include --artifact-dir out/examples/boot/nrf52840 \ + --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns,skip-include --artifact-dir out/examples/boot/nrf9160 \ + --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9120-ns,skip-include --artifact-dir out/examples/boot/nrf9120 \ + --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9151-ns,skip-include --artifact-dir out/examples/boot/nrf9151 \ + --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9161-ns,skip-include --artifact-dir out/examples/boot/nrf9161 \ + --- build --release --manifest-path examples/boot/application/rp/Cargo.toml --target thumbv6m-none-eabi --features skip-include --artifact-dir out/examples/boot/rp \ + --- build --release --manifest-path examples/boot/application/stm32f3/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32f3 \ + --- build --release --manifest-path examples/boot/application/stm32f7/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32f7 \ + --- build --release --manifest-path examples/boot/application/stm32h7/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32h7 \ + --- build --release --manifest-path examples/boot/application/stm32l0/Cargo.toml --target thumbv6m-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32l0 \ + --- build --release --manifest-path examples/boot/application/stm32l1/Cargo.toml --target thumbv7m-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32l1 \ + --- build --release --manifest-path examples/boot/application/stm32l4/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32l4 \ + --- build --release --manifest-path examples/boot/application/stm32wl/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32wl \ + --- build --release --manifest-path examples/boot/application/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/boot/stm32wb-dfu \ + --- build --release --manifest-path examples/boot/application/stm32wba-dfu/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/boot/stm32wba-dfu \ + --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \ + --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns \ + --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9120-ns \ + --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9151-ns \ + --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9161-ns \ + --- build --release --manifest-path examples/boot/bootloader/rp/Cargo.toml --target thumbv6m-none-eabi \ + --- build --release --manifest-path examples/boot/bootloader/stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32l496zg \ + --- build --release --manifest-path examples/boot/bootloader/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wb55rg \ + --- build --release --manifest-path examples/boot/bootloader/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wb55rg,verify \ + --- build --release --manifest-path examples/boot/bootloader/stm32wba-dfu/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-stm32/stm32wba65ri,verify \ + --- build --release --manifest-path examples/boot/bootloader/stm32-dual-bank/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32h743zi \ + --- build --release --manifest-path examples/wasm/Cargo.toml --target wasm32-unknown-unknown --artifact-dir out/examples/wasm \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f103c8 --artifact-dir out/tests/stm32f103c8 \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi --artifact-dir out/tests/stm32f429zi \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446re --artifact-dir out/tests/stm32f446re \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g491re --artifact-dir out/tests/stm32g491re \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g071rb --artifact-dir out/tests/stm32g071rb \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c031c6 --artifact-dir out/tests/stm32c031c6 \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c071rb --artifact-dir out/tests/stm32c071rb \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi --artifact-dir out/tests/stm32h755zi \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h753zi --artifact-dir out/tests/stm32h753zi \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7a3zi --artifact-dir out/tests/stm32h7a3zi \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55rg --artifact-dir out/tests/stm32wb55rg \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h563zi --artifact-dir out/tests/stm32h563zi \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u585ai --artifact-dir out/tests/stm32u585ai \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u5a5zj --artifact-dir out/tests/stm32u5a5zj \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba52cg --artifact-dir out/tests/stm32wba52cg \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l073rz --artifact-dir out/tests/stm32l073rz \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l152re --artifact-dir out/tests/stm32l152re \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4a6zg --artifact-dir out/tests/stm32l4a6zg \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4r5zi --artifact-dir out/tests/stm32l4r5zi \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze --artifact-dir out/tests/stm32l552ze \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f767zi --artifact-dir out/tests/stm32f767zi \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f207zg --artifact-dir out/tests/stm32f207zg \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303ze --artifact-dir out/tests/stm32f303ze \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l496zg --artifact-dir out/tests/stm32l496zg \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55jc --artifact-dir out/tests/stm32wl55jc \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s3l8 --artifact-dir out/tests/stm32h7s3l8 \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f091rc --artifact-dir out/tests/stm32f091rc \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h503rb --artifact-dir out/tests/stm32h503rb \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u083rc --artifact-dir out/tests/stm32u083rc \ + --- build --release --manifest-path tests/rp/Cargo.toml --target thumbv6m-none-eabi --features rp2040 --artifact-dir out/tests/rpi-pico \ + --- build --release --manifest-path tests/rp/Cargo.toml --target thumbv8m.main-none-eabihf --features rp235xb --artifact-dir out/tests/pimoroni-pico-plus-2 \ + --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51422 --artifact-dir out/tests/nrf51422-dk \ + --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52832 --artifact-dir out/tests/nrf52832-dk \ + --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52833 --artifact-dir out/tests/nrf52833-dk \ + --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840 --artifact-dir out/tests/nrf52840-dk \ + --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340 --artifact-dir out/tests/nrf5340-dk \ + --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf9160 --artifact-dir out/tests/nrf9160-dk \ + --- build --release --manifest-path tests/mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3507 --artifact-dir out/tests/mspm0g3507 \ + --- build --release --manifest-path tests/riscv32/Cargo.toml --target riscv32imac-unknown-none-elf \ + $BUILD_EXTRA + # MSPM0C1104 must be built seperately since cargo batch does not consider env vars set in `.cargo/config.toml`. # Since the target has 1KB of ram, we need to limit defmt's buffer size. @@ -43,7 +358,6 @@ DEFMT_RTT_BUFFER_SIZE="72" cargo batch \ rm -rf out/tests/stm32f103c8 rm -rf out/tests/nrf52840-dk rm -rf out/tests/nrf52833-dk -rm -rf out/tests/nrf5340-dk # disabled because these boards are not on the shelf rm -rf out/tests/mspm0g3507 -- cgit From eb672cdbfe7c4f38124715ddb034e6dc9fc997b4 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 25 Aug 2025 20:11:22 +0200 Subject: fix: re-remove nrf53 dk --- ci.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci.sh b/ci.sh index 68bf38881..94bf83675 100755 --- a/ci.sh +++ b/ci.sh @@ -358,6 +358,7 @@ DEFMT_RTT_BUFFER_SIZE="72" cargo batch \ rm -rf out/tests/stm32f103c8 rm -rf out/tests/nrf52840-dk rm -rf out/tests/nrf52833-dk +rm -rf out/tests/nrf5340-dk # disabled because these boards are not on the shelf rm -rf out/tests/mspm0g3507 -- cgit From c1116d68c9b4e62c3636f83bcfa8478535fc9df6 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 25 Aug 2025 20:14:37 +0200 Subject: fix: bump metapac version --- embassy-stm32/Cargo.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 92d2e7fda..dc8ee5d43 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -173,8 +173,8 @@ cortex-m = "0.7.6" futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" -# stm32-metapac = { version = "17" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ecb93d42a6cbcd9e09cab74873908a2ca22327f7" } +stm32-metapac = { version = "18" } +#stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ecb93d42a6cbcd9e09cab74873908a2ca22327f7" } vcell = "0.1.3" nb = "1.0.0" @@ -202,8 +202,8 @@ proptest-state-machine = "0.3.0" proc-macro2 = "1.0.36" quote = "1.0.15" -# stm32-metapac = { version = "17", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ecb93d42a6cbcd9e09cab74873908a2ca22327f7", default-features = false, features = ["metadata"] } +stm32-metapac = { version = "18", default-features = false, features = ["metadata"]} +#stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ecb93d42a6cbcd9e09cab74873908a2ca22327f7", default-features = false, features = ["metadata"] } [features] default = ["rt"] -- cgit From c40c20563664a62607f754fc734c7473d28ee955 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 25 Aug 2025 20:36:35 +0200 Subject: fix: stm32 wb sai --- embassy-stm32/src/sai/mod.rs | 50 +++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 0c9c27797..524e01be7 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -48,7 +48,7 @@ pub enum Mode { } impl Mode { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn mode(&self, tx_rx: TxRx) -> vals::Mode { match tx_rx { TxRx::Transmitter => match self { @@ -83,7 +83,7 @@ pub enum SlotSize { } impl SlotSize { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn slotsz(&self) -> vals::Slotsz { match self { SlotSize::DataSize => vals::Slotsz::DATA_SIZE, @@ -106,7 +106,7 @@ pub enum DataSize { } impl DataSize { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn ds(&self) -> vals::Ds { match self { DataSize::Data8 => vals::Ds::BIT8, @@ -131,7 +131,7 @@ pub enum FifoThreshold { } impl FifoThreshold { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn fth(&self) -> vals::Fth { match self { FifoThreshold::Empty => vals::Fth::EMPTY, @@ -152,7 +152,7 @@ pub enum MuteValue { } impl MuteValue { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn muteval(&self) -> vals::Muteval { match self { MuteValue::Zero => vals::Muteval::SEND_ZERO, @@ -171,7 +171,7 @@ pub enum Protocol { } impl Protocol { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn prtcfg(&self) -> vals::Prtcfg { match self { Protocol::Free => vals::Prtcfg::FREE, @@ -229,7 +229,7 @@ pub enum StereoMono { } impl StereoMono { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn mono(&self) -> vals::Mono { match self { StereoMono::Stereo => vals::Mono::STEREO, @@ -248,7 +248,7 @@ pub enum BitOrder { } impl BitOrder { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn lsbfirst(&self) -> vals::Lsbfirst { match self { BitOrder::LsbFirst => vals::Lsbfirst::LSB_FIRST, @@ -267,7 +267,7 @@ pub enum FrameSyncOffset { } impl FrameSyncOffset { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn fsoff(&self) -> vals::Fsoff { match self { FrameSyncOffset::OnFirstBit => vals::Fsoff::ON_FIRST, @@ -286,7 +286,7 @@ pub enum FrameSyncPolarity { } impl FrameSyncPolarity { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn fspol(&self) -> vals::Fspol { match self { FrameSyncPolarity::ActiveLow => vals::Fspol::FALLING_EDGE, @@ -304,7 +304,7 @@ pub enum FrameSyncDefinition { } impl FrameSyncDefinition { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn fsdef(&self) -> bool { match self { FrameSyncDefinition::StartOfFrame => false, @@ -322,7 +322,7 @@ pub enum ClockStrobe { } impl ClockStrobe { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn ckstr(&self) -> vals::Ckstr { match self { ClockStrobe::Falling => vals::Ckstr::FALLING_EDGE, @@ -340,7 +340,7 @@ pub enum ComplementFormat { } impl ComplementFormat { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn cpl(&self) -> vals::Cpl { match self { ComplementFormat::OnesComplement => vals::Cpl::ONES_COMPLEMENT, @@ -359,7 +359,7 @@ pub enum Companding { } impl Companding { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn comp(&self) -> vals::Comp { match self { Companding::None => vals::Comp::NO_COMPANDING, @@ -378,7 +378,7 @@ pub enum OutputDrive { } impl OutputDrive { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn outdriv(&self) -> vals::Outdriv { match self { OutputDrive::OnStart => vals::Outdriv::ON_START, @@ -390,7 +390,7 @@ impl OutputDrive { /// Master clock divider. #[derive(Copy, Clone, PartialEq)] #[allow(missing_docs)] -#[cfg(any(sai_v1, sai_v2))] +#[cfg(any(sai_v1, sai_v1_4pdm, sai_v2))] pub enum MasterClockDivider { MasterClockDisabled, Div1, @@ -483,7 +483,7 @@ pub enum MasterClockDivider { } impl MasterClockDivider { - #[cfg(any(sai_v1, sai_v2))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2))] const fn mckdiv(&self) -> u8 { match self { MasterClockDivider::MasterClockDisabled => 0, @@ -704,7 +704,7 @@ fn update_synchronous_config(config: &mut Config) { config.mode = Mode::Slave; config.sync_output = false; - #[cfg(any(sai_v1, sai_v2))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2))] { config.sync_input = SyncInput::Internal; } @@ -858,7 +858,7 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { ) -> Self { let ch = T::REGS.ch(sub_block as usize); - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] { ch.cr1().modify(|w| w.set_saien(false)); } @@ -884,7 +884,7 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { } } - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] { ch.cr1().modify(|w| { w.set_mode(config.mode.mode(if Self::is_transmitter(&ring_buffer) { @@ -899,14 +899,8 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { w.set_syncen(config.sync_input.syncen()); w.set_mono(config.stereo_mono.mono()); w.set_outdriv(config.output_drive.outdriv()); - w.set_mckdiv(config.master_clock_divider.mckdiv()); - w.set_nodiv( - if config.master_clock_divider == MasterClockDivider::MasterClockDisabled { - vals::Nodiv::NO_DIV - } else { - vals::Nodiv::MASTER_CLOCK - }, - ); + w.set_mckdiv(config.master_clock_divider.mckdiv().into()); + w.set_nodiv(config.master_clock_divider == MasterClockDivider::MasterClockDisabled); w.set_dmaen(true); }); -- cgit From 5e6669349c580e7c10d46fa0e4e0c62cd0fee124 Mon Sep 17 00:00:00 2001 From: tomaz-suller Date: Tue, 26 Aug 2025 10:52:04 +0200 Subject: stm32/sai: fix WB MCKDIV WB MCKDIV has a width of 6 bits (RM0434 Rev 14, p. 1269). --- embassy-stm32/src/sai/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 524e01be7..a42b0c350 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -390,7 +390,7 @@ impl OutputDrive { /// Master clock divider. #[derive(Copy, Clone, PartialEq)] #[allow(missing_docs)] -#[cfg(any(sai_v1, sai_v1_4pdm, sai_v2))] +#[cfg(any(sai_v1, sai_v2))] pub enum MasterClockDivider { MasterClockDisabled, Div1, @@ -414,7 +414,7 @@ pub enum MasterClockDivider { /// Master clock divider. #[derive(Copy, Clone, PartialEq)] #[allow(missing_docs)] -#[cfg(any(sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] +#[cfg(any(sai_v1_4pdm, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] pub enum MasterClockDivider { MasterClockDisabled, Div1, @@ -483,7 +483,7 @@ pub enum MasterClockDivider { } impl MasterClockDivider { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2))] + #[cfg(any(sai_v1, sai_v2))] const fn mckdiv(&self) -> u8 { match self { MasterClockDivider::MasterClockDisabled => 0, @@ -506,7 +506,7 @@ impl MasterClockDivider { } } - #[cfg(any(sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1_4pdm, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn mckdiv(&self) -> u8 { match self { MasterClockDivider::MasterClockDisabled => 0, -- cgit From 621c394f25bfde56ffb2ba450782a02ae5febe68 Mon Sep 17 00:00:00 2001 From: tomaz-suller Date: Tue, 26 Aug 2025 11:08:57 +0200 Subject: stm32/sai: make NODIV independent of MCKDIV --- embassy-stm32/src/sai/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 524e01be7..2f6160cb1 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -602,6 +602,7 @@ pub struct Config { pub clock_strobe: ClockStrobe, pub output_drive: OutputDrive, pub master_clock_divider: MasterClockDivider, + pub nodiv: bool, pub is_high_impedance_on_inactive_slot: bool, pub fifo_threshold: FifoThreshold, pub companding: Companding, @@ -631,6 +632,7 @@ impl Default for Config { frame_sync_definition: FrameSyncDefinition::ChannelIdentification, frame_length: 32, master_clock_divider: MasterClockDivider::MasterClockDisabled, + nodiv: false, clock_strobe: ClockStrobe::Rising, output_drive: OutputDrive::Immediately, is_high_impedance_on_inactive_slot: false, @@ -900,7 +902,7 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { w.set_mono(config.stereo_mono.mono()); w.set_outdriv(config.output_drive.outdriv()); w.set_mckdiv(config.master_clock_divider.mckdiv().into()); - w.set_nodiv(config.master_clock_divider == MasterClockDivider::MasterClockDisabled); + w.set_nodiv(config.nodiv); w.set_dmaen(true); }); -- cgit From f2bc5b7c8e68e4f6893de9943db0c160c6e160d1 Mon Sep 17 00:00:00 2001 From: tomaz-suller Date: Tue, 26 Aug 2025 11:21:34 +0200 Subject: Update changelog --- embassy-stm32/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index dd82613d9..36fabdbf4 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- feat: stm32/sai: make NODIV independent of MCKDIV - fix: stm32/i2c: pull-down was enabled instead of pull-none when no internal pull-up was needed. - feat: Improve blocking hash speed - fix: Fix vrefbuf building with log feature -- cgit From 541de3f4b41dc92a87afc758a525886fc2342fc0 Mon Sep 17 00:00:00 2001 From: tomaz-suller Date: Tue, 26 Aug 2025 11:22:57 +0200 Subject: Update changelog --- embassy-stm32/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index dd82613d9..1e9e59231 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- fix: stm32/sai: fix WB MCKDIV - fix: stm32/i2c: pull-down was enabled instead of pull-none when no internal pull-up was needed. - feat: Improve blocking hash speed - fix: Fix vrefbuf building with log feature -- cgit From 83f2557eacd657070a84a9baf2da6e3aff03b2b7 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 26 Aug 2025 16:04:00 +0200 Subject: chore: prepare embassy crate releases --- cyw43-pio/CHANGELOG.md | 2 ++ cyw43-pio/Cargo.toml | 4 ++-- cyw43/CHANGELOG.md | 2 ++ cyw43/Cargo.toml | 10 +++++----- docs/examples/basic/Cargo.toml | 6 +++--- docs/examples/layer-by-layer/blinky-async/Cargo.toml | 4 ++-- docs/examples/layer-by-layer/blinky-hal/Cargo.toml | 2 +- docs/examples/layer-by-layer/blinky-irq/Cargo.toml | 2 +- embassy-boot-nrf/CHANGELOG.md | 2 ++ embassy-boot-nrf/Cargo.toml | 8 ++++---- embassy-boot-rp/CHANGELOG.md | 2 ++ embassy-boot-rp/Cargo.toml | 10 +++++----- embassy-boot-stm32/CHANGELOG.md | 2 ++ embassy-boot-stm32/Cargo.toml | 8 ++++---- embassy-boot/CHANGELOG.md | 2 ++ embassy-boot/Cargo.toml | 6 +++--- embassy-embedded-hal/CHANGELOG.md | 2 ++ embassy-embedded-hal/Cargo.toml | 8 ++++---- embassy-executor/CHANGELOG.md | 2 ++ embassy-executor/Cargo.toml | 4 ++-- embassy-futures/CHANGELOG.md | 2 ++ embassy-futures/Cargo.toml | 2 +- embassy-imxrt/Cargo.toml | 12 ++++++------ embassy-mspm0/Cargo.toml | 14 +++++++------- embassy-net-adin1110/CHANGELOG.md | 2 ++ embassy-net-adin1110/Cargo.toml | 8 ++++---- embassy-net-driver-channel/CHANGELOG.md | 2 ++ embassy-net-driver-channel/Cargo.toml | 6 +++--- embassy-net-enc28j60/CHANGELOG.md | 2 ++ embassy-net-enc28j60/Cargo.toml | 6 +++--- embassy-net-esp-hosted/CHANGELOG.md | 2 ++ embassy-net-esp-hosted/Cargo.toml | 10 +++++----- embassy-net-nrf91/Cargo.toml | 8 ++++---- embassy-net-ppp/CHANGELOG.md | 2 ++ embassy-net-ppp/Cargo.toml | 8 ++++---- embassy-net-wiznet/CHANGELOG.md | 2 ++ embassy-net-wiznet/Cargo.toml | 8 ++++---- embassy-net/CHANGELOG.md | 2 ++ embassy-net/Cargo.toml | 6 +++--- embassy-nrf/CHANGELOG.md | 2 ++ embassy-nrf/Cargo.toml | 12 ++++++------ embassy-nxp/Cargo.toml | 8 ++++---- embassy-rp/CHANGELOG.md | 4 ++++ embassy-rp/Cargo.toml | 16 ++++++++-------- embassy-stm32-wpan/Cargo.toml | 10 +++++----- embassy-stm32/CHANGELOG.md | 2 ++ embassy-stm32/Cargo.toml | 18 +++++++++--------- embassy-sync/CHANGELOG.md | 2 ++ embassy-sync/Cargo.toml | 2 +- embassy-time-driver/CHANGELOG.md | 2 ++ embassy-time-driver/Cargo.toml | 4 ++-- embassy-time-queue-utils/CHANGELOG.md | 4 ++++ embassy-time-queue-utils/Cargo.toml | 2 +- embassy-time/CHANGELOG.md | 2 ++ embassy-time/Cargo.toml | 9 ++++----- embassy-usb-dfu/CHANGELOG.md | 2 ++ embassy-usb-dfu/Cargo.toml | 12 ++++++------ embassy-usb-logger/CHANGELOG.md | 2 ++ embassy-usb-logger/Cargo.toml | 8 ++++---- embassy-usb-synopsys-otg/CHANGELOG.md | 2 ++ embassy-usb-synopsys-otg/Cargo.toml | 4 ++-- embassy-usb/CHANGELOG.md | 2 ++ embassy-usb/Cargo.toml | 8 ++++---- examples/boot/application/nrf/Cargo.toml | 14 +++++++------- examples/boot/application/rp/Cargo.toml | 12 ++++++------ examples/boot/application/stm32f3/Cargo.toml | 12 ++++++------ examples/boot/application/stm32f7/Cargo.toml | 12 ++++++------ examples/boot/application/stm32h7/Cargo.toml | 12 ++++++------ examples/boot/application/stm32l0/Cargo.toml | 12 ++++++------ examples/boot/application/stm32l1/Cargo.toml | 12 ++++++------ examples/boot/application/stm32l4/Cargo.toml | 12 ++++++------ examples/boot/application/stm32wb-dfu/Cargo.toml | 16 ++++++++-------- examples/boot/application/stm32wba-dfu/Cargo.toml | 16 ++++++++-------- examples/boot/application/stm32wl/Cargo.toml | 12 ++++++------ examples/boot/bootloader/nrf/Cargo.toml | 2 +- examples/boot/bootloader/rp/Cargo.toml | 2 +- examples/boot/bootloader/stm32-dual-bank/Cargo.toml | 2 +- examples/boot/bootloader/stm32/Cargo.toml | 2 +- examples/boot/bootloader/stm32wb-dfu/Cargo.toml | 8 ++++---- examples/boot/bootloader/stm32wba-dfu/Cargo.toml | 8 ++++---- examples/lpc55s69/Cargo.toml | 6 +++--- examples/mimxrt1011/Cargo.toml | 8 ++++---- examples/mimxrt1062-evk/Cargo.toml | 8 ++++---- examples/mimxrt6/Cargo.toml | 8 ++++---- examples/mspm0c1104/Cargo.toml | 6 +++--- examples/mspm0g3507/Cargo.toml | 6 +++--- examples/mspm0g3519/Cargo.toml | 6 +++--- examples/mspm0l1306/Cargo.toml | 6 +++--- examples/mspm0l2228/Cargo.toml | 6 +++--- examples/nrf-rtos-trace/Cargo.toml | 8 ++++---- examples/nrf51/Cargo.toml | 6 +++--- examples/nrf52810/Cargo.toml | 10 +++++----- examples/nrf52840-rtic/Cargo.toml | 10 +++++----- examples/nrf52840/Cargo.toml | 18 +++++++++--------- examples/nrf5340/Cargo.toml | 14 +++++++------- examples/nrf54l15/Cargo.toml | 6 +++--- examples/nrf9151/ns/Cargo.toml | 6 +++--- examples/nrf9151/s/Cargo.toml | 6 +++--- examples/nrf9160/Cargo.toml | 8 ++++---- examples/rp/Cargo.toml | 20 ++++++++++---------- examples/rp235x/Cargo.toml | 20 ++++++++++---------- examples/std/Cargo.toml | 10 +++++----- examples/stm32c0/Cargo.toml | 8 ++++---- examples/stm32f0/Cargo.toml | 8 ++++---- examples/stm32f1/Cargo.toml | 12 ++++++------ examples/stm32f2/Cargo.toml | 8 ++++---- examples/stm32f3/Cargo.toml | 12 ++++++------ examples/stm32f334/Cargo.toml | 12 ++++++------ examples/stm32f4/Cargo.toml | 16 ++++++++-------- examples/stm32f469/Cargo.toml | 6 +++--- examples/stm32f7/Cargo.toml | 10 +++++----- examples/stm32g0/Cargo.toml | 12 ++++++------ examples/stm32g4/Cargo.toml | 12 ++++++------ examples/stm32h5/Cargo.toml | 14 +++++++------- examples/stm32h7/Cargo.toml | 16 ++++++++-------- examples/stm32h723/Cargo.toml | 10 +++++----- examples/stm32h735/Cargo.toml | 12 ++++++------ examples/stm32h742/Cargo.toml | 17 ++++++++--------- examples/stm32h755cm4/Cargo.toml | 16 ++++++++-------- examples/stm32h755cm7/Cargo.toml | 16 ++++++++-------- examples/stm32h7b0/Cargo.toml | 16 ++++++++-------- examples/stm32h7rs/Cargo.toml | 14 +++++++------- examples/stm32l0/Cargo.toml | 8 ++++---- examples/stm32l1/Cargo.toml | 12 ++++++------ examples/stm32l4/Cargo.toml | 14 +++++++------- examples/stm32l432/Cargo.toml | 10 +++++----- examples/stm32l5/Cargo.toml | 14 +++++++------- examples/stm32u0/Cargo.toml | 12 ++++++------ examples/stm32u5/Cargo.toml | 12 ++++++------ examples/stm32wb/Cargo.toml | 10 +++++----- examples/stm32wba/Cargo.toml | 10 +++++----- examples/stm32wba6/Cargo.toml | 14 +++++++------- examples/stm32wl/Cargo.toml | 10 +++++----- examples/wasm/Cargo.toml | 6 +++--- tests/mspm0/Cargo.toml | 10 +++++----- tests/nrf/Cargo.toml | 16 ++++++++-------- tests/perf-client/Cargo.toml | 6 +++--- tests/riscv32/Cargo.toml | 8 ++++---- tests/rp/Cargo.toml | 16 ++++++++-------- tests/stm32/Cargo.toml | 12 ++++++------ 140 files changed, 601 insertions(+), 545 deletions(-) diff --git a/cyw43-pio/CHANGELOG.md b/cyw43-pio/CHANGELOG.md index 3b792948b..9f1c6deab 100644 --- a/cyw43-pio/CHANGELOG.md +++ b/cyw43-pio/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.6.1 - 2025-08-26 + ## 0.6.0 - 2025-08-04 ## 0.5.1 - 2025-07-16 diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index 91b1df5fa..5878d64ba 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cyw43-pio" -version = "0.6.0" +version = "0.6.1" edition = "2021" description = "RP2040 PIO SPI implementation for cyw43" keywords = ["embedded", "cyw43", "embassy-net", "embedded-hal-async", "wifi"] @@ -11,7 +11,7 @@ documentation = "https://docs.embassy.dev/cyw43-pio" [dependencies] cyw43 = { version = "0.4.0", path = "../cyw43" } -embassy-rp = { version = "0.7.0", path = "../embassy-rp" } +embassy-rp = { version = "0.8.0", path = "../embassy-rp" } fixed = "1.23.1" defmt = { version = "1.0.1", optional = true } diff --git a/cyw43/CHANGELOG.md b/cyw43/CHANGELOG.md index 7de0073b6..2f54d6988 100644 --- a/cyw43/CHANGELOG.md +++ b/cyw43/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.4.1 - 2025-08-26 + - bump bt-hci to 0.4.0 ## 0.4.0 - 2025-07-15 diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index 74660b1d9..aa054a41d 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cyw43" -version = "0.4.0" +version = "0.4.1" edition = "2021" description = "Rust driver for the CYW43439 WiFi chip, used in the Raspberry Pi Pico W." keywords = ["embedded", "cyw43", "embassy-net", "embedded-hal-async", "wifi"] @@ -18,10 +18,10 @@ bluetooth = ["dep:bt-hci", "dep:embedded-io-async"] firmware-logs = [] [dependencies] -embassy-time = { version = "0.4.0", path = "../embassy-time"} -embassy-sync = { version = "0.7.1", path = "../embassy-sync"} -embassy-futures = { version = "0.1.0", path = "../embassy-futures"} -embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel"} +embassy-time = { version = "0.5.0", path = "../embassy-time"} +embassy-sync = { version = "0.7.2", path = "../embassy-sync"} +embassy-futures = { version = "0.1.2", path = "../embassy-futures"} +embassy-net-driver-channel = { version = "0.3.2", path = "../embassy-net-driver-channel"} defmt = { version = "1.0.1", optional = true } log = { version = "0.4.17", optional = true } diff --git a/docs/examples/basic/Cargo.toml b/docs/examples/basic/Cargo.toml index 5fb137898..b6dbeda2a 100644 --- a/docs/examples/basic/Cargo.toml +++ b/docs/examples/basic/Cargo.toml @@ -7,9 +7,9 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-executor = { version = "0.8.0", path = "../../../embassy-executor", features = ["defmt", "arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt"] } -embassy-nrf = { version = "0.6.0", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } +embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["defmt", "arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt"] } +embassy-nrf = { version = "0.7.0", path = "../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/docs/examples/layer-by-layer/blinky-async/Cargo.toml b/docs/examples/layer-by-layer/blinky-async/Cargo.toml index f1f678df3..ec718022c 100644 --- a/docs/examples/layer-by-layer/blinky-async/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-async/Cargo.toml @@ -8,8 +8,8 @@ publish = false [dependencies] cortex-m = { version = "0.7", features = ["critical-section-single-core"] } cortex-m-rt = "0.7" -embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x", "exti"] } -embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x", "exti"] } +embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/docs/examples/layer-by-layer/blinky-hal/Cargo.toml b/docs/examples/layer-by-layer/blinky-hal/Cargo.toml index cdfc4b850..4a0b03a83 100644 --- a/docs/examples/layer-by-layer/blinky-hal/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-hal/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] cortex-m-rt = "0.7" cortex-m = { version = "0.7", features = ["critical-section-single-core"] } -embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x"] } +embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/docs/examples/layer-by-layer/blinky-irq/Cargo.toml b/docs/examples/layer-by-layer/blinky-irq/Cargo.toml index b15b228fc..3c4bf8446 100644 --- a/docs/examples/layer-by-layer/blinky-irq/Cargo.toml +++ b/docs/examples/layer-by-layer/blinky-irq/Cargo.toml @@ -10,7 +10,7 @@ publish = false [dependencies] cortex-m = { version = "0.7", features = ["critical-section-single-core"] } cortex-m-rt = { version = "0.7" } -embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x", "unstable-pac"] } +embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "memory-x", "unstable-pac"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/embassy-boot-nrf/CHANGELOG.md b/embassy-boot-nrf/CHANGELOG.md index c78923a93..9263f8e60 100644 --- a/embassy-boot-nrf/CHANGELOG.md +++ b/embassy-boot-nrf/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.7.1 - 2025-08-26 + ## 0.1.1 - 2025-08-15 - First release with changelog. diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index 017eadab9..beefee0c8 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-nrf" -version = "0.7.0" +version = "0.7.1" description = "Bootloader lib for nRF chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" @@ -35,9 +35,9 @@ target = "thumbv7em-none-eabi" defmt = { version = "1.0.1", optional = true } log = { version = "0.4.17", optional = true } -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } -embassy-nrf = { version = "0.6.0", path = "../embassy-nrf", default-features = false } -embassy-boot = { version = "0.6.0", path = "../embassy-boot" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } +embassy-nrf = { version = "0.7.0", path = "../embassy-nrf", default-features = false } +embassy-boot = { version = "0.6.1", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" diff --git a/embassy-boot-rp/CHANGELOG.md b/embassy-boot-rp/CHANGELOG.md index c78923a93..9263f8e60 100644 --- a/embassy-boot-rp/CHANGELOG.md +++ b/embassy-boot-rp/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.7.1 - 2025-08-26 + ## 0.1.1 - 2025-08-15 - First release with changelog. diff --git a/embassy-boot-rp/Cargo.toml b/embassy-boot-rp/Cargo.toml index aee5d670d..3b9e9dd8e 100644 --- a/embassy-boot-rp/Cargo.toml +++ b/embassy-boot-rp/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-rp" -version = "0.7.0" +version = "0.7.1" description = "Bootloader lib for RP2040 chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" @@ -30,10 +30,10 @@ features = ["embassy-rp/rp2040"] defmt = { version = "1.0.1", optional = true } log = { version = "0.4", optional = true } -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } -embassy-rp = { version = "0.7.0", path = "../embassy-rp", default-features = false } -embassy-boot = { version = "0.6.0", path = "../embassy-boot" } -embassy-time = { version = "0.4.0", path = "../embassy-time" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } +embassy-rp = { version = "0.8.0", path = "../embassy-rp", default-features = false } +embassy-boot = { version = "0.6.1", path = "../embassy-boot" } +embassy-time = { version = "0.5.0", path = "../embassy-time" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } diff --git a/embassy-boot-stm32/CHANGELOG.md b/embassy-boot-stm32/CHANGELOG.md index c78923a93..e263ee436 100644 --- a/embassy-boot-stm32/CHANGELOG.md +++ b/embassy-boot-stm32/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.5.1 - 2025-08-26 + ## 0.1.1 - 2025-08-15 - First release with changelog. diff --git a/embassy-boot-stm32/Cargo.toml b/embassy-boot-stm32/Cargo.toml index c2cf0c596..b1a71d813 100644 --- a/embassy-boot-stm32/Cargo.toml +++ b/embassy-boot-stm32/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-stm32" -version = "0.5.0" +version = "0.5.1" description = "Bootloader lib for STM32 chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" @@ -30,9 +30,9 @@ target = "thumbv7em-none-eabi" defmt = { version = "1.0.1", optional = true } log = { version = "0.4", optional = true } -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } -embassy-stm32 = { version = "0.3.0", path = "../embassy-stm32", default-features = false } -embassy-boot = { version = "0.6.0", path = "../embassy-boot" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } +embassy-stm32 = { version = "0.4.0", path = "../embassy-stm32", default-features = false } +embassy-boot = { version = "0.6.1", path = "../embassy-boot" } cortex-m = { version = "0.7.6" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" diff --git a/embassy-boot/CHANGELOG.md b/embassy-boot/CHANGELOG.md index 7042ad14c..8d6395357 100644 --- a/embassy-boot/CHANGELOG.md +++ b/embassy-boot/CHANGELOG.md @@ -8,4 +8,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.6.1 - 2025-08-26 + - First release with changelog. diff --git a/embassy-boot/Cargo.toml b/embassy-boot/Cargo.toml index 632e60c35..e1f539962 100644 --- a/embassy-boot/Cargo.toml +++ b/embassy-boot/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot" -version = "0.6.0" +version = "0.6.1" description = "A lightweight bootloader supporting firmware updates in a power-fail-safe way, with trial boots and rollbacks." license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" @@ -28,8 +28,8 @@ defmt = { version = "1.0.1", optional = true } digest = "0.10" log = { version = "0.4", optional = true } ed25519-dalek = { version = "2", default-features = false, features = ["digest"], optional = true } -embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal" } -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } +embassy-embedded-hal = { version = "0.4.1", path = "../embassy-embedded-hal" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } embedded-storage = "0.3.1" embedded-storage-async = { version = "0.4.1" } salty = { version = "0.3", optional = true } diff --git a/embassy-embedded-hal/CHANGELOG.md b/embassy-embedded-hal/CHANGELOG.md index 86eab3357..9a410fcd2 100644 --- a/embassy-embedded-hal/CHANGELOG.md +++ b/embassy-embedded-hal/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.4.1 - 2025-08-26 + ## 0.4.0 - 2025-08-03 - `SpiDevice` cancel safety: always set CS pin to high on drop diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index a1f9e168b..aa7b53dff 100644 --- a/embassy-embedded-hal/Cargo.toml +++ b/embassy-embedded-hal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-embedded-hal" -version = "0.4.0" +version = "0.4.1" edition = "2021" license = "MIT OR Apache-2.0" description = "Collection of utilities to use `embedded-hal` and `embedded-storage` traits with Embassy." @@ -29,9 +29,9 @@ time = ["dep:embassy-time"] [dependencies] embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal" } -embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } -embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } +embassy-time = { version = "0.5.0", path = "../embassy-time", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [ "unproven", ] } diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 91a1448c2..f301429c0 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.9.0 - 2025-08-26 + - Added `extern "Rust" fn __embassy_time_queue_item_from_waker` - Removed `TaskRef::dangling` - Added `embassy_time_queue_utils` as a dependency diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 7da807906..d89e85cb7 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-executor" -version = "0.8.0" +version = "0.9.0" edition = "2021" license = "MIT OR Apache-2.0" description = "async/await executor designed for embedded usage" @@ -54,7 +54,7 @@ log = { version = "0.4.14", optional = true } rtos-trace = { version = "0.1.3", optional = true } embassy-executor-macros = { version = "0.7.0", path = "../embassy-executor-macros" } -embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } +embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver", optional = true } embassy-executor-timer-queue = { version = "0.1", path = "../embassy-executor-timer-queue" } critical-section = "1.1" diff --git a/embassy-futures/CHANGELOG.md b/embassy-futures/CHANGELOG.md index eb76cdc4a..7d4ee93fa 100644 --- a/embassy-futures/CHANGELOG.md +++ b/embassy-futures/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.1.2 - 2025-08-26 + - Preserve location information for `defmt` in `fmt` calls ([#3085](https://github.com/embassy-rs/embassy/pull/3085)) - Fixed soundness issue in `select_slice` ([#3328](https://github.com/embassy-rs/embassy/pull/3328)) - Added `select5` and `select6` ([#3430](https://github.com/embassy-rs/embassy/pull/3430)) diff --git a/embassy-futures/Cargo.toml b/embassy-futures/Cargo.toml index 0deab0165..2d62b28e5 100644 --- a/embassy-futures/Cargo.toml +++ b/embassy-futures/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-futures" -version = "0.1.1" +version = "0.1.2" edition = "2021" description = "no-std, no-alloc utilities for working with futures" repository = "https://github.com/embassy-rs/embassy" diff --git a/embassy-imxrt/Cargo.toml b/embassy-imxrt/Cargo.toml index 006096e99..35b37d07c 100644 --- a/embassy-imxrt/Cargo.toml +++ b/embassy-imxrt/Cargo.toml @@ -70,13 +70,13 @@ mimxrt685s = ["mimxrt685s-pac", "_mimxrt685s"] mimxrt633s = ["mimxrt633s-pac", "_mimxrt633s"] [dependencies] -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } -embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } -embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } -embassy-time = { version = "0.4", path = "../embassy-time", optional = true } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } +embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver", optional = true } +embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-utils", optional = true } +embassy-time = { version = "0.5.0", path = "../embassy-time", optional = true } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } -embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal", default-features = false } -embassy-futures = { version = "0.1.1", path = "../embassy-futures" } +embassy-embedded-hal = { version = "0.4.1", path = "../embassy-embedded-hal", default-features = false } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index 08e0fa9b3..69900d812 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -44,15 +44,15 @@ features = ["defmt", "unstable-pac", "time-driver-any", "time", "mspm0g3507"] rustdoc-args = ["--cfg", "docsrs"] [dependencies] -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } -embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } +embassy-time = { version = "0.5.0", path = "../embassy-time", optional = true } # TODO: Support other tick rates -embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true, features = ["tick-hz-32_768"] } -embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } -embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver", optional = true, features = ["tick-hz-32_768"] } +embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-utils", optional = true } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } -embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal", default-features = false } -embassy-executor = { version = "0.8.0", path = "../embassy-executor", optional = true } +embassy-embedded-hal = { version = "0.4.1", path = "../embassy-embedded-hal", default-features = false } +embassy-executor = { version = "0.9.0", path = "../embassy-executor", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal = { version = "1.0" } diff --git a/embassy-net-adin1110/CHANGELOG.md b/embassy-net-adin1110/CHANGELOG.md index 7042ad14c..1804d1313 100644 --- a/embassy-net-adin1110/CHANGELOG.md +++ b/embassy-net-adin1110/CHANGELOG.md @@ -8,4 +8,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.3.1 - 2025-08-26 + - First release with changelog. diff --git a/embassy-net-adin1110/Cargo.toml b/embassy-net-adin1110/Cargo.toml index 9cda4dc5b..587c69eb7 100644 --- a/embassy-net-adin1110/Cargo.toml +++ b/embassy-net-adin1110/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-net-adin1110" -version = "0.3.0" +version = "0.3.1" description = "embassy-net driver for the ADIN1110 ethernet chip" keywords = ["embedded", "ADIN1110", "embassy-net", "embedded-hal-async", "ethernet"] categories = ["embedded", "hardware-support", "no-std", "network-programming", "asynchronous"] @@ -16,9 +16,9 @@ log = { version = "0.4", default-features = false, optional = true } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-hal-bus = { version = "0.1", features = ["async"] } -embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel" } -embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +embassy-net-driver-channel = { version = "0.3.2", path = "../embassy-net-driver-channel" } +embassy-time = { version = "0.5.0", path = "../embassy-time" } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } bitfield = "0.14.0" [dev-dependencies] diff --git a/embassy-net-driver-channel/CHANGELOG.md b/embassy-net-driver-channel/CHANGELOG.md index 1189e50c3..dfd4fb0ed 100644 --- a/embassy-net-driver-channel/CHANGELOG.md +++ b/embassy-net-driver-channel/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.3.2 - 2025-08-26 + ## 0.3.1 - 2025-07-16 - Update `embassy-sync` to v0.7.0 diff --git a/embassy-net-driver-channel/Cargo.toml b/embassy-net-driver-channel/Cargo.toml index c3a9f79a7..cf498c59f 100644 --- a/embassy-net-driver-channel/Cargo.toml +++ b/embassy-net-driver-channel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-net-driver-channel" -version = "0.3.1" +version = "0.3.2" edition = "2021" license = "MIT OR Apache-2.0" description = "High-level channel-based driver for the `embassy-net` async TCP/IP network stack." @@ -25,6 +25,6 @@ features = ["defmt"] defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } -embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } diff --git a/embassy-net-enc28j60/CHANGELOG.md b/embassy-net-enc28j60/CHANGELOG.md index 84f144f99..a6819e280 100644 --- a/embassy-net-enc28j60/CHANGELOG.md +++ b/embassy-net-enc28j60/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.2.1 - 2025-08-26 + ## 0.1.1 - 2025-08-16 - First release with changelog. diff --git a/embassy-net-enc28j60/Cargo.toml b/embassy-net-enc28j60/Cargo.toml index b26be1420..a3e3285a3 100644 --- a/embassy-net-enc28j60/Cargo.toml +++ b/embassy-net-enc28j60/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-net-enc28j60" -version = "0.2.0" +version = "0.2.1" description = "embassy-net driver for the ENC28J60 ethernet chip" keywords = ["embedded", "enc28j60", "embassy-net", "embedded-hal-async", "ethernet"] categories = ["embedded", "hardware-support", "no-std", "network-programming", "asynchronous"] @@ -13,8 +13,8 @@ documentation = "https://docs.embassy.dev/embassy-net-enc28j60" embedded-hal = { version = "1.0" } embedded-hal-async = { version = "1.0" } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } -embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +embassy-time = { version = "0.5.0", path = "../embassy-time" } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } diff --git a/embassy-net-esp-hosted/CHANGELOG.md b/embassy-net-esp-hosted/CHANGELOG.md index 7042ad14c..5153e3799 100644 --- a/embassy-net-esp-hosted/CHANGELOG.md +++ b/embassy-net-esp-hosted/CHANGELOG.md @@ -8,4 +8,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.2.1 - 2025-08-26 + - First release with changelog. diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml index f76998d1a..149ff2bb2 100644 --- a/embassy-net-esp-hosted/Cargo.toml +++ b/embassy-net-esp-hosted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-net-esp-hosted" -version = "0.2.0" +version = "0.2.1" edition = "2021" description = "embassy-net driver for ESP-Hosted" keywords = ["embedded", "esp-hosted", "embassy-net", "embedded-hal-async", "wifi"] @@ -17,10 +17,10 @@ log = ["dep:log"] defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } -embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-sync = { version = "0.7.1", path = "../embassy-sync"} -embassy-futures = { version = "0.1.0", path = "../embassy-futures"} -embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel"} +embassy-time = { version = "0.5.0", path = "../embassy-time" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync"} +embassy-futures = { version = "0.1.2", path = "../embassy-futures"} +embassy-net-driver-channel = { version = "0.3.2", path = "../embassy-net-driver-channel"} embedded-hal = { version = "1.0" } embedded-hal-async = { version = "1.0" } diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml index feb6eb7a2..35fbef3f6 100644 --- a/embassy-net-nrf91/Cargo.toml +++ b/embassy-net-nrf91/Cargo.toml @@ -21,10 +21,10 @@ log = { version = "0.4.14", optional = true } nrf-pac = "0.1.0" cortex-m = "0.7.7" -embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } -embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel" } +embassy-time = { version = "0.5.0", path = "../embassy-time" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } +embassy-net-driver-channel = { version = "0.3.2", path = "../embassy-net-driver-channel" } heapless = "0.8" embedded-io = "0.6.1" diff --git a/embassy-net-ppp/CHANGELOG.md b/embassy-net-ppp/CHANGELOG.md index b364608d2..946206143 100644 --- a/embassy-net-ppp/CHANGELOG.md +++ b/embassy-net-ppp/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.2.1 - 2025-08-26 + ## 0.2.0 - 2025-01-12 - Update `ppproto` to v0.2. diff --git a/embassy-net-ppp/Cargo.toml b/embassy-net-ppp/Cargo.toml index 33ef5230e..644f5b827 100644 --- a/embassy-net-ppp/Cargo.toml +++ b/embassy-net-ppp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-net-ppp" -version = "0.2.0" +version = "0.2.1" description = "embassy-net driver for PPP over Serial" keywords = ["embedded", "ppp", "embassy-net", "embedded-hal-async", "async"] categories = ["embedded", "hardware-support", "no-std", "network-programming", "asynchronous"] @@ -18,10 +18,10 @@ defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } embedded-io-async = { version = "0.6.1" } -embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel" } -embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +embassy-net-driver-channel = { version = "0.3.2", path = "../embassy-net-driver-channel" } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } ppproto = { version = "0.2.1"} -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-ppp-v$VERSION/embassy-net-ppp/src/" diff --git a/embassy-net-wiznet/CHANGELOG.md b/embassy-net-wiznet/CHANGELOG.md index 52cbf5ef3..e464efa69 100644 --- a/embassy-net-wiznet/CHANGELOG.md +++ b/embassy-net-wiznet/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.2.1 - 2025-08-26 + ## 0.1.1 - 2025-08-14 - First release with changelog. diff --git a/embassy-net-wiznet/Cargo.toml b/embassy-net-wiznet/Cargo.toml index 3ff01f72b..36c349df1 100644 --- a/embassy-net-wiznet/Cargo.toml +++ b/embassy-net-wiznet/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-net-wiznet" -version = "0.2.0" +version = "0.2.1" description = "embassy-net driver for WIZnet SPI Ethernet chips" keywords = ["embedded", "embassy-net", "embedded-hal-async", "ethernet", "async"] categories = ["embedded", "hardware-support", "no-std", "network-programming", "asynchronous"] @@ -12,9 +12,9 @@ documentation = "https://docs.embassy.dev/embassy-net-wiznet" [dependencies] embedded-hal = { version = "1.0" } embedded-hal-async = { version = "1.0" } -embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel" } -embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +embassy-net-driver-channel = { version = "0.3.2", path = "../embassy-net-driver-channel" } +embassy-time = { version = "0.5.0", path = "../embassy-time" } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } defmt = { version = "1.0.1", optional = true } [package.metadata.embassy_docs] diff --git a/embassy-net/CHANGELOG.md b/embassy-net/CHANGELOG.md index 39bc6c0f0..1ae4f2a68 100644 --- a/embassy-net/CHANGELOG.md +++ b/embassy-net/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.7.1 - 2025-08-26 + No unreleased changes yet... Quick, go send a PR! ## 0.7 - 2025-05-06 diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index 446e58489..245626c14 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-net" -version = "0.7.0" +version = "0.7.1" edition = "2021" license = "MIT OR Apache-2.0" description = "Async TCP/IP network stack for embedded systems" @@ -92,8 +92,8 @@ smoltcp = { version = "0.12.0", default-features = false, features = [ ] } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } -embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } +embassy-time = { version = "0.5.0", path = "../embassy-time" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } embedded-io-async = { version = "0.6.1" } managed = { version = "0.8.0", default-features = false, features = [ "map" ] } diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index 12e3850c0..4e0887b0d 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.7.0 - 2025-08-26 + - bugfix: use correct analog input SAADC pins on nrf5340 ## 0.6.0 - 2025-08-04 diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index ed701dac8..92dd78b85 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-nrf" -version = "0.6.0" +version = "0.7.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Embassy Hardware Abstraction Layer (HAL) for nRF series microcontrollers" @@ -170,12 +170,12 @@ _nrf52832_anomaly_109 = [] _multi_wdt = [] [dependencies] -embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } -embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } -embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } +embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver", optional = true } +embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-utils", optional = true } +embassy-time = { version = "0.5.0", path = "../embassy-time", optional = true } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } -embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal", default-features = false } +embassy-embedded-hal = { version = "0.4.1", path = "../embassy-embedded-hal", default-features = false } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 70e6da076..ab0bfbfd7 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -27,12 +27,12 @@ cortex-m = "0.7.7" cortex-m-rt = "0.7.0" critical-section = "1.1.2" embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } defmt = { version = "1", optional = true } log = { version = "0.4.27", optional = true } -embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } -embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } -embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } +embassy-time = { version = "0.5.0", path = "../embassy-time", optional = true } +embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver", optional = true } +embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-utils", optional = true } embedded-io = "0.6.1" embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } ## Chip dependencies diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md index 5482f277f..ebdc3e1c8 100644 --- a/embassy-rp/CHANGELOG.md +++ b/embassy-rp/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate + +## 0.8.0 - 2025-08-26 + +## 0.7.1 - 2025-08-26 - add `i2c` internal pullup options ([#4564](https://github.com/embassy-rs/embassy/pull/4564)) ## 0.7.0 - 2025-08-04 diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index a5f84944e..e9541295c 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-rp" -version = "0.7.0" +version = "0.8.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Embassy Hardware Abstraction Layer (HAL) for the Raspberry Pi RP2040 or RP235x microcontroller" @@ -147,13 +147,13 @@ _test = [] binary-info = ["rt", "dep:rp-binary-info", "rp-binary-info?/binary-info"] [dependencies] -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } -embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } -embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } -embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } +embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver", optional = true } +embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-utils", optional = true } +embassy-time = { version = "0.5.0", path = "../embassy-time" } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } -embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.1", path = "../embassy-embedded-hal" } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } atomic-polyfill = "1.0.1" defmt = { version = "1.0.1", optional = true } @@ -188,5 +188,5 @@ rp-binary-info = { version = "0.1.0", optional = true } smart-leds = "0.4.0" [dev-dependencies] -embassy-executor = { version = "0.8.0", path = "../embassy-executor", features = ["arch-std", "executor-thread"] } +embassy-executor = { version = "0.9.0", path = "../embassy-executor", features = ["arch-std", "executor-thread"] } static_cell = { version = "2" } diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 2bdb0d6c4..ceda440d4 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -26,12 +26,12 @@ features = ["stm32wb55rg", "ble", "mac"] features = ["stm32wb55rg", "ble", "mac"] [dependencies] -embassy-stm32 = { version = "0.3.0", path = "../embassy-stm32" } -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } -embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } -embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../embassy-stm32" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } +embassy-time = { version = "0.5.0", path = "../embassy-time", optional = true } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal" } -embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.4.1", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver", optional=true } defmt = { version = "1.0.1", optional = true } diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 82a253ff6..d8706ee39 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.4.0 - 2025-08-26 + - feat: stm32/sai: make NODIV independent of MCKDIV - fix: stm32/sai: fix WB MCKDIV - fix: stm32/i2c: pull-down was enabled instead of pull-none when no internal pull-up was needed. diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index dc8ee5d43..391c32761 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-stm32" -version = "0.3.0" +version = "0.4.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Embassy Hardware Abstraction Layer (HAL) for ST STM32 series microcontrollers" @@ -141,17 +141,17 @@ features = ["defmt", "unstable-pac", "exti", "time-driver-any", "time", "stm32h7 rustdoc-args = ["--cfg", "docsrs"] [dependencies] -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } -embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true } -embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } -embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true } -embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } +embassy-time = { version = "0.5.0", path = "../embassy-time", optional = true } +embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver", optional = true } +embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-utils", optional = true } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } -embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal", default-features = false } +embassy-embedded-hal = { version = "0.4.1", path = "../embassy-embedded-hal", default-features = false } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } -embassy-usb-synopsys-otg = { version = "0.3.0", path = "../embassy-usb-synopsys-otg" } -embassy-executor = { version = "0.8.0", path = "../embassy-executor", optional = true } +embassy-usb-synopsys-otg = { version = "0.3.1", path = "../embassy-usb-synopsys-otg" } +embassy-executor = { version = "0.9.0", path = "../embassy-executor", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } diff --git a/embassy-sync/CHANGELOG.md b/embassy-sync/CHANGELOG.md index 7418ead8d..593396586 100644 --- a/embassy-sync/CHANGELOG.md +++ b/embassy-sync/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.7.2 - 2025-08-26 + - Add `get_mut` to `LazyLock` - Add more `Debug` impls to `embassy-sync`, particularly on `OnceLock` diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml index e31c9a674..30a27c13f 100644 --- a/embassy-sync/Cargo.toml +++ b/embassy-sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-sync" -version = "0.7.1" +version = "0.7.2" edition = "2021" description = "no-std, no-alloc synchronization primitives with async support" repository = "https://github.com/embassy-rs/embassy" diff --git a/embassy-time-driver/CHANGELOG.md b/embassy-time-driver/CHANGELOG.md index b61a10bf6..cdd432437 100644 --- a/embassy-time-driver/CHANGELOG.md +++ b/embassy-time-driver/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.2.1 - 2025-08-26 + - Allow inlining on time driver boundary - add 133MHz tick rate to support PR2040 @ 133MHz when `TIMERx`'s `SOURCE` is set to `SYSCLK` diff --git a/embassy-time-driver/Cargo.toml b/embassy-time-driver/Cargo.toml index 16213cb75..56ef3d15f 100644 --- a/embassy-time-driver/Cargo.toml +++ b/embassy-time-driver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-time-driver" -version = "0.2.0" +version = "0.2.1" edition = "2021" description = "Driver trait for embassy-time" repository = "https://github.com/embassy-rs/embassy" @@ -373,4 +373,4 @@ document-features = "0.2.7" [dev-dependencies] critical-section = "1" -embassy-time-queue-utils = { path = "../embassy-time-queue-utils" } \ No newline at end of file +embassy-time-queue-utils = { path = "../embassy-time-queue-utils" } diff --git a/embassy-time-queue-utils/CHANGELOG.md b/embassy-time-queue-utils/CHANGELOG.md index 510c29d58..03d89f9a7 100644 --- a/embassy-time-queue-utils/CHANGELOG.md +++ b/embassy-time-queue-utils/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.3.0 - 2025-08-26 + +## 0.2.1 - 2025-08-26 + - Removed the embassy-executor dependency ## 0.2.0 - 2025-08-04 diff --git a/embassy-time-queue-utils/Cargo.toml b/embassy-time-queue-utils/Cargo.toml index 2a659548e..e1abf1cd8 100644 --- a/embassy-time-queue-utils/Cargo.toml +++ b/embassy-time-queue-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-time-queue-utils" -version = "0.2.0" +version = "0.3.0" edition = "2021" description = "Timer queue driver trait for embassy-time" repository = "https://github.com/embassy-rs/embassy" diff --git a/embassy-time/CHANGELOG.md b/embassy-time/CHANGELOG.md index 2e94e0112..572571215 100644 --- a/embassy-time/CHANGELOG.md +++ b/embassy-time/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.5.0 - 2025-08-26 + - Allow inlining on time driver boundary - Add `saturating_add` and `saturating_sub` to `Instant` - Add `Instant::try_from_*` constructor functions diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index eff8e2975..6ebf0a468 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-time" -version = "0.4.0" +version = "0.5.0" edition = "2021" description = "Instant and Duration for embedded no-std systems, with async timer support" repository = "https://github.com/embassy-rs/embassy" @@ -17,7 +17,6 @@ categories = [ [package.metadata.embassy] build = [ {target = "thumbv6m-none-eabi", features = ["defmt", "defmt-timestamp-uptime", "mock-driver"]}, - {features = ["defmt", "std"]}, ] [package.metadata.embassy_docs] @@ -423,8 +422,8 @@ tick-hz-5_242_880_000 = ["embassy-time-driver/tick-hz-5_242_880_000"] #! [dependencies] -embassy-time-driver = { version = "0.2", path = "../embassy-time-driver" } -embassy-time-queue-utils = { version = "0.2", path = "../embassy-time-queue-utils", optional = true} +embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver" } +embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-utils", optional = true} defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } @@ -447,4 +446,4 @@ wasm-timer = { version = "0.2.5", optional = true } [dev-dependencies] serial_test = "0.9" critical-section = { version = "1.1", features = ["std"] } -embassy-executor = { version = "0.8.0", path = "../embassy-executor" } +embassy-executor = { version = "0.9.0", path = "../embassy-executor" } diff --git a/embassy-usb-dfu/CHANGELOG.md b/embassy-usb-dfu/CHANGELOG.md index 7042ad14c..9a399c5c7 100644 --- a/embassy-usb-dfu/CHANGELOG.md +++ b/embassy-usb-dfu/CHANGELOG.md @@ -8,4 +8,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.1.1 - 2025-08-26 + - First release with changelog. diff --git a/embassy-usb-dfu/Cargo.toml b/embassy-usb-dfu/Cargo.toml index ce2f80b31..1bf39641f 100644 --- a/embassy-usb-dfu/Cargo.toml +++ b/embassy-usb-dfu/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-usb-dfu" -version = "0.1.0" +version = "0.1.1" description = "An implementation of the USB DFU 1.1 protocol, using embassy-boot" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" @@ -37,11 +37,11 @@ log = { version = "0.4.17", optional = true } bitflags = "2.4.1" cortex-m = { version = "0.7.7", features = ["inline-asm"], optional = true } -embassy-boot = { version = "0.6.0", path = "../embassy-boot" } -embassy-futures = { version = "0.1.1", path = "../embassy-futures" } -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } -embassy-time = { version = "0.4.0", path = "../embassy-time" } -embassy-usb = { version = "0.5.0", path = "../embassy-usb", default-features = false } +embassy-boot = { version = "0.6.1", path = "../embassy-boot" } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } +embassy-time = { version = "0.5.0", path = "../embassy-time" } +embassy-usb = { version = "0.5.1", path = "../embassy-usb", default-features = false } embedded-storage = { version = "0.3.1" } esp32c3-hal = { version = "0.13.0", optional = true, default-features = false } diff --git a/embassy-usb-logger/CHANGELOG.md b/embassy-usb-logger/CHANGELOG.md index c88b3ed6a..4ea0e8871 100644 --- a/embassy-usb-logger/CHANGELOG.md +++ b/embassy-usb-logger/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.5.1 - 2025-08-26 + ## 0.5.0 - 2025-07-22 - Update `embassy-usb` to 0.5.0 diff --git a/embassy-usb-logger/Cargo.toml b/embassy-usb-logger/Cargo.toml index 810accf76..6d13653bf 100644 --- a/embassy-usb-logger/Cargo.toml +++ b/embassy-usb-logger/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-usb-logger" -version = "0.5.0" +version = "0.5.1" edition = "2021" license = "MIT OR Apache-2.0" description = "`log` implementation for USB serial using `embassy-usb`." @@ -15,7 +15,7 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-l target = "thumbv7em-none-eabi" [dependencies] -embassy-usb = { version = "0.5.0", path = "../embassy-usb" } -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } -embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +embassy-usb = { version = "0.5.1", path = "../embassy-usb" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } log = "0.4" diff --git a/embassy-usb-synopsys-otg/CHANGELOG.md b/embassy-usb-synopsys-otg/CHANGELOG.md index 55eef0a1e..9ca90f5e9 100644 --- a/embassy-usb-synopsys-otg/CHANGELOG.md +++ b/embassy-usb-synopsys-otg/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.3.1 - 2025-08-26 + ## 0.3.0 - 2025-07-22 - Bump `embassy-usb-driver` to v0.2.0 diff --git a/embassy-usb-synopsys-otg/Cargo.toml b/embassy-usb-synopsys-otg/Cargo.toml index e9ec8d330..ec518ac93 100644 --- a/embassy-usb-synopsys-otg/Cargo.toml +++ b/embassy-usb-synopsys-otg/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-usb-synopsys-otg" -version = "0.3.0" +version = "0.3.1" edition = "2021" license = "MIT OR Apache-2.0" description = "`embassy-usb-driver` implementation for Synopsys OTG USB controllers" @@ -18,7 +18,7 @@ target = "thumbv7em-none-eabi" [dependencies] critical-section = "1.1" -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } defmt = { version = "1.0.1", optional = true } diff --git a/embassy-usb/CHANGELOG.md b/embassy-usb/CHANGELOG.md index 3ee75e226..0a30bc24b 100644 --- a/embassy-usb/CHANGELOG.md +++ b/embassy-usb/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.5.1 - 2025-08-26 + ## 0.5.0 - 2025-07-16 - `UAC1`: unmute by default ([#3992](https://github.com/embassy-rs/embassy/pull/3992)) diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml index 89b3c318d..e309eec93 100644 --- a/embassy-usb/Cargo.toml +++ b/embassy-usb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-usb" -version = "0.5.0" +version = "0.5.1" edition = "2021" license = "MIT OR Apache-2.0" description = "Async USB device stack for embedded devices in Rust." @@ -57,10 +57,10 @@ max-handler-count-8 = [] # END AUTOGENERATED CONFIG FEATURES [dependencies] -embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +embassy-futures = { version = "0.1.2", path = "../embassy-futures" } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } -embassy-sync = { version = "0.7.1", path = "../embassy-sync" } -embassy-net-driver-channel = { version = "0.3.1", path = "../embassy-net-driver-channel" } +embassy-sync = { version = "0.7.2", path = "../embassy-sync" } +embassy-net-driver-channel = { version = "0.3.2", path = "../embassy-net-driver-channel" } defmt = { version = "1", optional = true } log = { version = "0.4.14", optional = true } diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index f55b14f38..f2951c9d6 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -6,13 +6,13 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } -embassy-nrf = { version = "0.6.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } -embassy-boot = { version = "0.6.0", path = "../../../../embassy-boot", features = [] } -embassy-boot-nrf = { version = "0.7.0", path = "../../../../embassy-boot-nrf", features = [] } -embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } +embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] } +embassy-nrf = { version = "0.7.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } +embassy-boot = { version = "0.6.1", path = "../../../../embassy-boot", features = [] } +embassy-boot-nrf = { version = "0.7.1", path = "../../../../embassy-boot-nrf", features = [] } +embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index c60f2b9a8..ffdeaaba6 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } -embassy-rp = { version = "0.7.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } -embassy-boot-rp = { version = "0.7.0", path = "../../../../embassy-boot-rp", features = [] } -embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } +embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] } +embassy-rp = { version = "0.8.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } +embassy-boot-rp = { version = "0.7.1", path = "../../../../embassy-boot-rp", features = [] } +embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index 004050d40..77c1ddd4e 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32" } -embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } +embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } +embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32" } +embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index 74a1d498e..0c03da08d 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } -embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } +embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } +embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index acf1da96d..4a9ea12fa 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } +embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } +embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 0f5e8ac08..92d611a27 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } -embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } +embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } +embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index eb7279fb0..60c2ff5e4 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } +embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } +embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index 1d1830ba0..90a6cfdfd 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } +embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } +embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index 5aa48c31b..9a7489864 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -6,14 +6,14 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } -embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb" } -embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } +embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } +embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } +embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb" } +embassy-usb-dfu = { version = "0.1.1", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32wba-dfu/Cargo.toml b/examples/boot/application/stm32wba-dfu/Cargo.toml index 880551ad7..294c9b955 100644 --- a/examples/boot/application/stm32wba-dfu/Cargo.toml +++ b/examples/boot/application/stm32wba-dfu/Cargo.toml @@ -6,14 +6,14 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32wba65ri", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } -embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb" } -embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } +embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wba65ri", "time-driver-any", "exti"] } +embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } +embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb" } +embassy-usb-dfu = { version = "0.1.1", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index ee9ab0729..cb744e81f 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } -embassy-executor = { version = "0.8.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } -embassy-stm32 = { version = "0.3.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.5.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.0", path = "../../../../embassy-embedded-hal" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } +embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } +embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } +embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/bootloader/nrf/Cargo.toml b/examples/boot/bootloader/nrf/Cargo.toml index 2b54bbec8..72b7114d4 100644 --- a/examples/boot/bootloader/nrf/Cargo.toml +++ b/examples/boot/bootloader/nrf/Cargo.toml @@ -13,7 +13,7 @@ defmt-rtt = { version = "1.0.0", optional = true } embassy-nrf = { path = "../../../../embassy-nrf", features = [] } embassy-boot-nrf = { path = "../../../../embassy-boot-nrf" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } cortex-m-rt = { version = "0.7" } cfg-if = "1.0.0" diff --git a/examples/boot/bootloader/rp/Cargo.toml b/examples/boot/bootloader/rp/Cargo.toml index b89332f0b..93a1c4edf 100644 --- a/examples/boot/bootloader/rp/Cargo.toml +++ b/examples/boot/bootloader/rp/Cargo.toml @@ -12,7 +12,7 @@ defmt-rtt = { version = "1.0.0", optional = true } embassy-rp = { path = "../../../../embassy-rp", features = ["rp2040"] } embassy-boot-rp = { path = "../../../../embassy-boot-rp" } -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } embassy-time = { path = "../../../../embassy-time", features = [] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } diff --git a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml index 82fbee9f1..95ca20a59 100644 --- a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml +++ b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml @@ -16,7 +16,7 @@ cortex-m = { version = "0.7.6", features = [ "inline-asm", "critical-section-single-core", ] } -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" diff --git a/examples/boot/bootloader/stm32/Cargo.toml b/examples/boot/bootloader/stm32/Cargo.toml index a9a4aa95a..526637f37 100644 --- a/examples/boot/bootloader/stm32/Cargo.toml +++ b/examples/boot/bootloader/stm32/Cargo.toml @@ -13,7 +13,7 @@ defmt-rtt = { version = "1.0.0", optional = true } embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml index 75783d66e..bc59fd3df 100644 --- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml @@ -13,14 +13,14 @@ defmt-rtt = { version = "1.0.0", optional = true } embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" cfg-if = "1.0.0" -embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } -embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb", default-features = false } -embassy-futures = { version = "0.1.1", path = "../../../../embassy-futures" } +embassy-usb-dfu = { version = "0.1.1", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } +embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb", default-features = false } +embassy-futures = { version = "0.1.2", path = "../../../../embassy-futures" } [features] defmt = [ diff --git a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml index 773060ab3..e1cf364fd 100644 --- a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml @@ -13,14 +13,14 @@ defmt-rtt = { version = "1.0.0", optional = true } embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } -embassy-sync = { version = "0.7.1", path = "../../../../embassy-sync" } +embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" cfg-if = "1.0.0" -embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } -embassy-usb = { version = "0.5.0", path = "../../../../embassy-usb", default-features = false } -embassy-futures = { version = "0.1.1", path = "../../../../embassy-futures" } +embassy-usb-dfu = { version = "0.1.1", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } +embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb", default-features = false } +embassy-futures = { version = "0.1.2", path = "../../../../embassy-futures" } [features] defmt = [ diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index bf28ee20f..79b27f269 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml @@ -8,9 +8,9 @@ publish = false [dependencies] embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55", "rt", "defmt", "time-driver-rtc"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = { version = "0.7.0"} diff --git a/examples/mimxrt1011/Cargo.toml b/examples/mimxrt1011/Cargo.toml index 49d628811..488f3167b 100644 --- a/examples/mimxrt1011/Cargo.toml +++ b/examples/mimxrt1011/Cargo.toml @@ -11,11 +11,11 @@ cortex-m-rt = "0.7.3" defmt = "1.0.1" defmt-rtt = "1.0.0" -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["defmt", "mimxrt1011", "unstable-pac", "time-driver-pit"] } -embassy-time = { version = "0.4", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime" # RT1011 hard faults currently with this enabled. -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime" # RT1011 hard faults currently with this enabled. +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = "1.0.0" diff --git a/examples/mimxrt1062-evk/Cargo.toml b/examples/mimxrt1062-evk/Cargo.toml index 816695a32..ec6c5c872 100644 --- a/examples/mimxrt1062-evk/Cargo.toml +++ b/examples/mimxrt1062-evk/Cargo.toml @@ -11,11 +11,11 @@ cortex-m-rt = "0.7.3" defmt = "1.0.1" defmt-rtt = "1.0.0" -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["defmt", "mimxrt1062", "unstable-pac", "time-driver-pit"] } -embassy-time = { version = "0.4", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime" -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime" +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = "1.0.0" diff --git a/examples/mimxrt6/Cargo.toml b/examples/mimxrt6/Cargo.toml index 8ae636921..28de9d273 100644 --- a/examples/mimxrt6/Cargo.toml +++ b/examples/mimxrt6/Cargo.toml @@ -11,11 +11,11 @@ cortex-m-rt = "0.7.3" defmt = "1.0.1" defmt-rtt = "1.0.0" -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-imxrt = { version = "0.1.0", path = "../../embassy-imxrt", features = ["defmt", "mimxrt685s", "unstable-pac", "time", "time-driver-os-timer"] } -embassy-time = { version = "0.4", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = "1.0.0" diff --git a/examples/mspm0c1104/Cargo.toml b/examples/mspm0c1104/Cargo.toml index decb1a6e2..4daddbbb4 100644 --- a/examples/mspm0c1104/Cargo.toml +++ b/examples/mspm0c1104/Cargo.toml @@ -7,9 +7,9 @@ publish = false [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0c1104dgs20", "defmt", "rt", "time-driver-any"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = { version = "0.7.0"} diff --git a/examples/mspm0g3507/Cargo.toml b/examples/mspm0g3507/Cargo.toml index 04efb681c..616b82adb 100644 --- a/examples/mspm0g3507/Cargo.toml +++ b/examples/mspm0g3507/Cargo.toml @@ -7,9 +7,9 @@ publish = false [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3507pm", "defmt", "rt", "time-driver-any"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = { version = "0.7.0"} diff --git a/examples/mspm0g3519/Cargo.toml b/examples/mspm0g3519/Cargo.toml index bb31b52ff..ae699d6f4 100644 --- a/examples/mspm0g3519/Cargo.toml +++ b/examples/mspm0g3519/Cargo.toml @@ -7,9 +7,9 @@ publish = false [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3519pz", "defmt", "rt", "time-driver-any"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = { version = "0.7.0"} diff --git a/examples/mspm0l1306/Cargo.toml b/examples/mspm0l1306/Cargo.toml index c41017e17..8100e11da 100644 --- a/examples/mspm0l1306/Cargo.toml +++ b/examples/mspm0l1306/Cargo.toml @@ -7,9 +7,9 @@ publish = false [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l1306rhb", "defmt", "rt", "time-driver-any"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = { version = "0.7.0"} diff --git a/examples/mspm0l2228/Cargo.toml b/examples/mspm0l2228/Cargo.toml index 7295eb599..3add7b8e8 100644 --- a/examples/mspm0l2228/Cargo.toml +++ b/examples/mspm0l2228/Cargo.toml @@ -7,9 +7,9 @@ publish = false [dependencies] embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l2228pn", "defmt", "rt", "time-driver-any"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] } panic-halt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = { version = "0.7.0"} diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index 60875f434..a2dc0c7ad 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -16,10 +16,10 @@ log = [ ] [dependencies] -embassy-sync = { version = "0.7.1", path = "../../embassy-sync" } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time" } -embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync" } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time" } +embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml index 93acdab8a..dded6de59 100644 --- a/examples/nrf51/Cargo.toml +++ b/examples/nrf51/Cargo.toml @@ -6,9 +6,9 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml index 000521265..aa1a4bf73 100644 --- a/examples/nrf52810/Cargo.toml +++ b/examples/nrf52810/Cargo.toml @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index 5e37913a9..f6937c263 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml @@ -8,11 +8,11 @@ publish = false [dependencies] rtic = { version = "2", features = ["thumbv7-backend"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } -embassy-time-queue-utils = { version = "0.2", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } -embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } +embassy-time-queue-utils = { version = "0.3.0", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } +embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 026681822..a9339bcd3 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -6,17 +6,17 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } embedded-io = { version = "0.6.0", features = ["defmt-03"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } -embassy-net-esp-hosted = { version = "0.2.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } -embassy-net-enc28j60 = { version = "0.2.0", path = "../../embassy-net-enc28j60", features = ["defmt"] } +embassy-net-esp-hosted = { version = "0.2.1", path = "../../embassy-net-esp-hosted", features = ["defmt"] } +embassy-net-enc28j60 = { version = "0.2.1", path = "../../embassy-net-enc28j60", features = ["defmt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index 36f74e4b1..425015667 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -6,13 +6,13 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } embedded-io-async = { version = "0.6.1" } defmt = "1.0.1" diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml index b794b217c..7f67b41f6 100644 --- a/examples/nrf54l15/Cargo.toml +++ b/examples/nrf54l15/Cargo.toml @@ -6,9 +6,9 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml index 35550b8c5..8e420477f 100644 --- a/examples/nrf9151/ns/Cargo.toml +++ b/examples/nrf9151/ns/Cargo.toml @@ -6,9 +6,9 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-executor = { version = "0.8.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.6.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.7.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml index 3ef8b33fd..e4ca85553 100644 --- a/examples/nrf9151/s/Cargo.toml +++ b/examples/nrf9151/s/Cargo.toml @@ -6,9 +6,9 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-executor = { version = "0.8.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.6.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.7.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml index 245232c1f..d7b63a7ac 100644 --- a/examples/nrf9160/Cargo.toml +++ b/examples/nrf9160/Cargo.toml @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index d97ebf43e..45c309494 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -7,16 +7,16 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal", features = ["defmt"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-rp = { version = "0.7.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] } -embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-usb-logger = { version = "0.5.0", path = "../../embassy-usb-logger" } +embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal", features = ["defmt"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-rp = { version = "0.8.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] } +embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } +embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { version = "0.6.0", path = "../../cyw43-pio", features = ["defmt"] } diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 2c279d7e1..3ebafad3e 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -7,16 +7,16 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal", features = ["defmt"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-rp = { version = "0.7.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } -embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-usb-logger = { version = "0.5.0", path = "../../embassy-usb-logger" } +embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal", features = ["defmt"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-rp = { version = "0.8.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } +embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } +embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { version = "0.6.0", path = "../../cyw43-pio", features = ["defmt"] } diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 6d56d97af..449c5ddca 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["log"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["log", "std", ] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features=[ "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["log"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["log", "std", ] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features=[ "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" } -embassy-net-ppp = { version = "0.2.0", path = "../../embassy-net-ppp", features = ["log"]} +embassy-net-ppp = { version = "0.2.1", path = "../../embassy-net-ppp", features = ["log"]} embedded-io-async = { version = "0.6.1" } embedded-io-adapters = { version = "0.6.1", features = ["futures-03"] } critical-section = { version = "1.1", features = ["std"] } diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index 56b966d49..bb7b57496 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml @@ -7,10 +7,10 @@ publish = false [dependencies] # Change stm32c031c6 to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti", "chrono"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti", "chrono"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index 6cc6eac46..11ecbe3c2 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -7,15 +7,15 @@ publish = false [dependencies] # Change stm32f091rc to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "memory-x", "stm32f091rc", "time-driver-tim2", "exti", "unstable-pac"] } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "memory-x", "stm32f091rc", "time-driver-tim2", "exti", "unstable-pac"] } cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" defmt = "1.0.1" defmt-rtt = "1.0.0" panic-probe = { version = "1.0.0", features = ["print-defmt"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } static_cell = "2" portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 3cb7bd5e3..dcb58796b 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -7,12 +7,12 @@ publish = false [dependencies] # Change stm32f103c8 to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index 9c5a7cd7f..498c20d84 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml @@ -7,10 +7,10 @@ publish = false [dependencies] # Change stm32f207zg to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 690bcb00d..23025ef0b 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -7,12 +7,12 @@ publish = false [dependencies] # Change stm32f303ze to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-tim2", "exti"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-tim2", "exti"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml index 709da6ed6..3495b118c 100644 --- a/examples/stm32f334/Cargo.toml +++ b/examples/stm32f334/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 52b48e744..fb5f86aac 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -7,14 +7,14 @@ publish = false [dependencies] # Change stm32f429zi to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-tim4", "exti", "chrono"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt" ] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } -embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-tim4", "exti", "chrono"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt" ] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } +embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32f469/Cargo.toml b/examples/stm32f469/Cargo.toml index 612081242..f1d0e411a 100644 --- a/examples/stm32f469/Cargo.toml +++ b/examples/stm32f469/Cargo.toml @@ -7,9 +7,9 @@ publish = false [dependencies] # Specific examples only for stm32f469 -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32f469ni", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32f469ni", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 1e5ea8d33..5d7763334 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -7,11 +7,11 @@ publish = false [dependencies] # Change stm32f777zi to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32f777zi", "memory-x", "unstable-pac", "time-driver-any", "exti", "single-bank"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32f777zi", "memory-x", "unstable-pac", "time-driver-any", "exti", "single-bank"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } embedded-io-async = { version = "0.6.1" } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index 7b0da5077..1c9451469 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml @@ -7,12 +7,12 @@ publish = false [dependencies] # Change stm32g0b1re to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g0b1re", "memory-x", "unstable-pac", "exti"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g0b1re", "memory-x", "unstable-pac", "exti"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", default-features = false, features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index 15292725f..102960980 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -7,12 +7,12 @@ publish = false [dependencies] # Change stm32g491re to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } usbd-hid = "0.8.1" defmt = "1.0.1" diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 7f9a77e85..66680c027 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -7,13 +7,13 @@ publish = false [dependencies] # Change stm32h563zi to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index be0e46938..5d845837f 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -7,14 +7,14 @@ publish = false [dependencies] # Change stm32h743bi to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal" } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32h723/Cargo.toml b/examples/stm32h723/Cargo.toml index 5a762259b..7e4ccc528 100644 --- a/examples/stm32h723/Cargo.toml +++ b/examples/stm32h723/Cargo.toml @@ -7,11 +7,11 @@ publish = false [dependencies] # Change stm32h723zg to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h723zg", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h723zg", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml index 0b55424e8..ffaee2115 100644 --- a/examples/stm32h735/Cargo.toml +++ b/examples/stm32h735/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal" } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml index 067663538..c76340b5f 100644 --- a/examples/stm32h742/Cargo.toml +++ b/examples/stm32h742/Cargo.toml @@ -1,13 +1,12 @@ [package] edition = "2021" -name = "embassy-stm32f7-examples" +name = "embassy-stm32h742-examples" version = "0.1.0" license = "MIT OR Apache-2.0" publish = false [dependencies] -# Change stm32f777zi to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32h742vi", "memory-x", @@ -15,30 +14,30 @@ embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "time-driver-any", "exti", ] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = [ +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = [ "defmt", ] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = [ +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt", ] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = [ +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = [ "defmt", "tcp", "dhcpv4", "medium-ethernet", ] } embedded-io-async = { version = "0.6.1" } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = [ +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = [ "defmt", ] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index 6cd1893d2..d34f566e3 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -7,14 +7,14 @@ publish = false [dependencies] # Change stm32h755zi-cm4 to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal" } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index 48783fc7a..22c0cf70e 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -7,14 +7,14 @@ publish = false [dependencies] # Change stm32h743bi to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal" } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml index c0d047bd4..3b21d59df 100644 --- a/examples/stm32h7b0/Cargo.toml +++ b/examples/stm32h7b0/Cargo.toml @@ -6,14 +6,14 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal" } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml index dcd5b078d..bfe59b68d 100644 --- a/examples/stm32h7rs/Cargo.toml +++ b/examples/stm32h7rs/Cargo.toml @@ -7,13 +7,13 @@ publish = false [dependencies] # Change stm32h743bi to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ethernet", "medium-ip", "proto-ipv4"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "medium-ethernet", "medium-ip", "proto-ipv4"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 47ccedeb0..90f57a2d8 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -7,10 +7,10 @@ publish = false [dependencies] # Change stm32l072cz to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32l073rz", "unstable-pac", "time-driver-any", "exti", "memory-x"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32l073rz", "unstable-pac", "time-driver-any", "exti", "memory-x"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 659524cb3..76ceade9c 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 02fd4ce93..4b764a3e6 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -7,15 +7,15 @@ publish = false [dependencies] # Change stm32l4s5vi to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4r5zi", "memory-x", "time-driver-any", "exti", "chrono", "dual-bank"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4r5zi", "memory-x", "time-driver-any", "exti", "chrono", "dual-bank"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-net-adin1110 = { version = "0.3.0", path = "../../embassy-net-adin1110" } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-net-adin1110 = { version = "0.3.1", path = "../../embassy-net-adin1110" } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } embedded-io = { version = "0.6.0", features = ["defmt-03"] } diff --git a/examples/stm32l432/Cargo.toml b/examples/stm32l432/Cargo.toml index 14db1fb2f..f173c651e 100644 --- a/examples/stm32l432/Cargo.toml +++ b/examples/stm32l432/Cargo.toml @@ -1,16 +1,16 @@ [package] edition = "2021" -name = "embassy-stm32l4-examples" +name = "embassy-stm32l432-examples" version = "0.1.1" license = "MIT OR Apache-2.0" publish = false [dependencies] # Change stm32l4s5vi to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l432kc", "memory-x", "time-driver-any", "exti", "chrono"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = [ "defmt" ] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "tick-hz-32_768" ] } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l432kc", "memory-x", "time-driver-any", "exti", "chrono"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = [ "defmt" ] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", "tick-hz-32_768" ] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 42b46ee0f..9999300b8 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -7,13 +7,13 @@ publish = false [dependencies] # Change stm32l552ze to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x", "low-power", "dual-bank"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x", "low-power", "dual-bank"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } usbd-hid = "0.8.1" defmt = "1.0.1" diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml index 09e5eb20c..9318414a5 100644 --- a/examples/stm32u0/Cargo.toml +++ b/examples/stm32u0/Cargo.toml @@ -7,12 +7,12 @@ publish = false [dependencies] # Change stm32u083rc to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", default-features = false, features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index 8b5d52aa4..f2ffe52c5 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -7,12 +7,12 @@ publish = false [dependencies] # Change stm32u5g9zj to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u5g9zj", "time-driver-any", "memory-x" ] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u5g9zj", "time-driver-any", "memory-x" ] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 14e6dfa15..7ab13c290 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -7,12 +7,12 @@ publish = false [dependencies] # Change stm32wb55rg to your chip name in both dependencies, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml index 9c11528cd..e1196614a 100644 --- a/examples/stm32wba/Cargo.toml +++ b/examples/stm32wba/Cargo.toml @@ -6,11 +6,11 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32wba6/Cargo.toml b/examples/stm32wba6/Cargo.toml index f1f9cf88b..f98317846 100644 --- a/examples/stm32wba6/Cargo.toml +++ b/examples/stm32wba6/Cargo.toml @@ -1,17 +1,17 @@ [package] edition = "2021" -name = "embassy-stm32wba-examples" +name = "embassy-stm32wba6-examples" version = "0.1.0" license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba65ri", "time-driver-any", "memory-x", "exti"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba65ri", "time-driver-any", "memory-x", "exti"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index a75e4ed30..6ad57a85e 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -7,11 +7,11 @@ publish = false [dependencies] # Change stm32wl55jc-cm4 to your chip name, if necessary. -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml index 28b4f1c30..e8897506c 100644 --- a/examples/wasm/Cargo.toml +++ b/examples/wasm/Cargo.toml @@ -9,9 +9,9 @@ publish = false crate-type = ["cdylib"] [dependencies] -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["log"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["log", "wasm", ] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["log"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["log", "wasm", ] } wasm-logger = "0.2.0" wasm-bindgen = "0.2" diff --git a/tests/mspm0/Cargo.toml b/tests/mspm0/Cargo.toml index 5cf1b0ed1..07fe779a0 100644 --- a/tests/mspm0/Cargo.toml +++ b/tests/mspm0/Cargo.toml @@ -12,12 +12,12 @@ mspm0g3519 = [ "embassy-mspm0/mspm0g3519pz" ] [dependencies] teleprobe-meta = "1.1" -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = [ "defmt" ] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt" ] } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = [ "defmt" ] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = [ "defmt" ] } embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = [ "rt", "defmt", "unstable-pac", "time-driver-any" ] } -embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal/"} +embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal/"} defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index b94b54f4e..efc297ccf 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -8,15 +8,15 @@ publish = false [dependencies] teleprobe-meta = "1" -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt", ] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.6.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt", ] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } -embassy-net-esp-hosted = { version = "0.2.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } -embassy-net-enc28j60 = { version = "0.2.0", path = "../../embassy-net-enc28j60", features = ["defmt"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } +embassy-net-esp-hosted = { version = "0.2.1", path = "../../embassy-net-esp-hosted", features = ["defmt"] } +embassy-net-enc28j60 = { version = "0.2.1", path = "../../embassy-net-enc28j60", features = ["defmt"] } embedded-hal-async = { version = "1.0" } embedded-hal-bus = { version = "0.1", features = ["async"] } static_cell = "2" diff --git a/tests/perf-client/Cargo.toml b/tests/perf-client/Cargo.toml index ea0663b6f..581b60d6f 100644 --- a/tests/perf-client/Cargo.toml +++ b/tests/perf-client/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" publish = false [dependencies] -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", ] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", ] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" diff --git a/tests/riscv32/Cargo.toml b/tests/riscv32/Cargo.toml index 781fec62f..c441e8ed3 100644 --- a/tests/riscv32/Cargo.toml +++ b/tests/riscv32/Cargo.toml @@ -7,10 +7,10 @@ publish = false [dependencies] critical-section = { version = "1.1.1", features = ["restore-state-bool"] } -embassy-sync = { version = "0.7.1", path = "../../embassy-sync" } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-riscv32", "executor-thread"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time" } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync" } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-riscv32", "executor-thread"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time" } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } riscv-rt = "0.12.2" riscv = { version = "0.11.1", features = ["critical-section-single-hart"] } diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 088195a75..5afb0d110 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -13,14 +13,14 @@ rp235xb = ["embassy-rp/rp235xb"] [dependencies] teleprobe-meta = "1.1" -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", ] } -embassy-rp = { version = "0.7.0", path = "../../embassy-rp", features = [ "defmt", "unstable-pac", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } -embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } -embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal/"} +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", ] } +embassy-rp = { version = "0.8.0", path = "../../embassy-rp", features = [ "defmt", "unstable-pac", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } +embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } +embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal/"} cyw43 = { path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { path = "../../cyw43-pio", features = ["defmt"] } perf-client = { path = "../perf-client" } diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 37d5161f8..aeca67659 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -65,13 +65,13 @@ cm0 = ["portable-atomic/unsafe-assume-single-core"] [dependencies] teleprobe-meta = "1" -embassy-sync = { version = "0.7.1", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.8.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "tick-hz-131_072", "defmt-timestamp-uptime"] } -embassy-stm32 = { version = "0.3.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "memory-x", "time-driver-any"] } -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "tick-hz-131_072", "defmt-timestamp-uptime"] } +embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "memory-x", "time-driver-any"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg", "ble"] } -embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } perf-client = { path = "../perf-client" } defmt = "1.0.1" -- cgit From f77693092a59970ac3b3594c53e53099295cbbff Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Tue, 26 Aug 2025 16:26:41 +0200 Subject: Fix changelog --- embassy-executor-timer-queue/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-executor-timer-queue/CHANGELOG.md b/embassy-executor-timer-queue/CHANGELOG.md index d43e0060d..b4a462b66 100644 --- a/embassy-executor-timer-queue/CHANGELOG.md +++ b/embassy-executor-timer-queue/CHANGELOG.md @@ -1,10 +1,10 @@ -# Changelog for embassy-time-queue-utils +# Changelog for embassy-executor-timer-queue 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). -## Unreeased +## 0.1.0 - 2025-08-25 - Initial implementation -- cgit From 426bc84e66b4d4a26fe9a73b7d78d8491e722eba Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 26 Aug 2025 19:20:01 +0200 Subject: chore: fix example crate names --- examples/stm32h742/Cargo.toml | 2 +- examples/stm32l432/Cargo.toml | 2 +- examples/stm32wba6/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml index 067663538..21b132b98 100644 --- a/examples/stm32h742/Cargo.toml +++ b/examples/stm32h742/Cargo.toml @@ -1,6 +1,6 @@ [package] edition = "2021" -name = "embassy-stm32f7-examples" +name = "embassy-stm32h742-examples" version = "0.1.0" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/stm32l432/Cargo.toml b/examples/stm32l432/Cargo.toml index 14db1fb2f..2822d5a02 100644 --- a/examples/stm32l432/Cargo.toml +++ b/examples/stm32l432/Cargo.toml @@ -1,6 +1,6 @@ [package] edition = "2021" -name = "embassy-stm32l4-examples" +name = "embassy-stm32l432-examples" version = "0.1.1" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/stm32wba6/Cargo.toml b/examples/stm32wba6/Cargo.toml index f1f9cf88b..617bcf326 100644 --- a/examples/stm32wba6/Cargo.toml +++ b/examples/stm32wba6/Cargo.toml @@ -1,6 +1,6 @@ [package] edition = "2021" -name = "embassy-stm32wba-examples" +name = "embassy-stm32wba6-examples" version = "0.1.0" license = "MIT OR Apache-2.0" publish = false -- cgit From df112a83f05d08dc01607083211bdc2ac1e11cfa Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 26 Aug 2025 22:06:52 +0200 Subject: fix: remaining versions --- cyw43-pio/CHANGELOG.md | 2 ++ cyw43-pio/Cargo.toml | 2 +- embassy-boot-nrf/CHANGELOG.md | 4 ++++ embassy-boot-nrf/Cargo.toml | 2 +- embassy-boot-rp/CHANGELOG.md | 2 ++ embassy-boot-rp/Cargo.toml | 2 +- embassy-boot-stm32/CHANGELOG.md | 2 ++ embassy-boot-stm32/Cargo.toml | 2 +- examples/boot/application/nrf/Cargo.toml | 2 +- examples/boot/application/rp/Cargo.toml | 2 +- examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wb-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wba-dfu/Cargo.toml | 2 +- examples/boot/application/stm32wl/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- 21 files changed, 27 insertions(+), 17 deletions(-) diff --git a/cyw43-pio/CHANGELOG.md b/cyw43-pio/CHANGELOG.md index 9f1c6deab..048e2bd8e 100644 --- a/cyw43-pio/CHANGELOG.md +++ b/cyw43-pio/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.7.0 - 2025-08-26 + ## 0.6.1 - 2025-08-26 ## 0.6.0 - 2025-08-04 diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index 5878d64ba..d7dd21453 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cyw43-pio" -version = "0.6.1" +version = "0.7.0" edition = "2021" description = "RP2040 PIO SPI implementation for cyw43" keywords = ["embedded", "cyw43", "embassy-net", "embedded-hal-async", "wifi"] diff --git a/embassy-boot-nrf/CHANGELOG.md b/embassy-boot-nrf/CHANGELOG.md index 9263f8e60..3092b129d 100644 --- a/embassy-boot-nrf/CHANGELOG.md +++ b/embassy-boot-nrf/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.8.0 - 2025-08-26 + +## 0.7.0 - 2025-08-26 + ## 0.7.1 - 2025-08-26 ## 0.1.1 - 2025-08-15 diff --git a/embassy-boot-nrf/Cargo.toml b/embassy-boot-nrf/Cargo.toml index beefee0c8..3b631ef0c 100644 --- a/embassy-boot-nrf/Cargo.toml +++ b/embassy-boot-nrf/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-nrf" -version = "0.7.1" +version = "0.8.0" description = "Bootloader lib for nRF chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" diff --git a/embassy-boot-rp/CHANGELOG.md b/embassy-boot-rp/CHANGELOG.md index 9263f8e60..782bb066c 100644 --- a/embassy-boot-rp/CHANGELOG.md +++ b/embassy-boot-rp/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.8.0 - 2025-08-26 + ## 0.7.1 - 2025-08-26 ## 0.1.1 - 2025-08-15 diff --git a/embassy-boot-rp/Cargo.toml b/embassy-boot-rp/Cargo.toml index 3b9e9dd8e..894b77595 100644 --- a/embassy-boot-rp/Cargo.toml +++ b/embassy-boot-rp/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-rp" -version = "0.7.1" +version = "0.8.0" description = "Bootloader lib for RP2040 chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" diff --git a/embassy-boot-stm32/CHANGELOG.md b/embassy-boot-stm32/CHANGELOG.md index e263ee436..6044249e9 100644 --- a/embassy-boot-stm32/CHANGELOG.md +++ b/embassy-boot-stm32/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.6.0 - 2025-08-26 + ## 0.5.1 - 2025-08-26 ## 0.1.1 - 2025-08-15 diff --git a/embassy-boot-stm32/Cargo.toml b/embassy-boot-stm32/Cargo.toml index b1a71d813..24eafcdbf 100644 --- a/embassy-boot-stm32/Cargo.toml +++ b/embassy-boot-stm32/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-boot-stm32" -version = "0.5.1" +version = "0.6.0" description = "Bootloader lib for STM32 chips" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index f2951c9d6..03a390497 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -11,7 +11,7 @@ embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] } embassy-nrf = { version = "0.7.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } embassy-boot = { version = "0.6.1", path = "../../../../embassy-boot", features = [] } -embassy-boot-nrf = { version = "0.7.1", path = "../../../../embassy-boot-nrf", features = [] } +embassy-boot-nrf = { version = "0.8.0", path = "../../../../embassy-boot-nrf", features = [] } embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index ffdeaaba6..e022e4ad7 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -10,7 +10,7 @@ embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] } embassy-rp = { version = "0.8.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } -embassy-boot-rp = { version = "0.7.1", path = "../../../../embassy-boot-rp", features = [] } +embassy-boot-rp = { version = "0.8.0", path = "../../../../embassy-boot-rp", features = [] } embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = "1.0.1" diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index 77c1ddd4e..03a65fdd8 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -10,7 +10,7 @@ embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32" } +embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32" } embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index 0c03da08d..e41bdf3dd 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -10,7 +10,7 @@ embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } -embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index 4a9ea12fa..644bd70d1 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -10,7 +10,7 @@ embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 92d611a27..184245998 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -10,7 +10,7 @@ embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } -embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 60c2ff5e4..9a286e6a9 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -10,7 +10,7 @@ embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index 90a6cfdfd..02617d2c2 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -10,7 +10,7 @@ embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index 9a7489864..7a0435579 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -10,7 +10,7 @@ embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb" } embassy-usb-dfu = { version = "0.1.1", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } diff --git a/examples/boot/application/stm32wba-dfu/Cargo.toml b/examples/boot/application/stm32wba-dfu/Cargo.toml index 294c9b955..5d00021e6 100644 --- a/examples/boot/application/stm32wba-dfu/Cargo.toml +++ b/examples/boot/application/stm32wba-dfu/Cargo.toml @@ -10,7 +10,7 @@ embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wba65ri", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb" } embassy-usb-dfu = { version = "0.1.1", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index cb744e81f..a26d6f8d9 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -10,7 +10,7 @@ embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } -embassy-boot-stm32 = { version = "0.5.1", path = "../../../../embassy-boot-stm32", features = [] } +embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 45c309494..204a1cca7 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -18,7 +18,7 @@ embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", fea embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } -cyw43-pio = { version = "0.6.0", path = "../../cyw43-pio", features = ["defmt"] } +cyw43-pio = { version = "0.7.0", path = "../../cyw43-pio", features = ["defmt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 3ebafad3e..bc95ab629 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -18,7 +18,7 @@ embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", fea embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } -cyw43-pio = { version = "0.6.0", path = "../../cyw43-pio", features = ["defmt"] } +cyw43-pio = { version = "0.7.0", path = "../../cyw43-pio", features = ["defmt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" -- cgit From 2454b3cc7e450e28a3d354a1940c4913828a27e9 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 26 Aug 2025 22:07:44 +0200 Subject: fix: changelogs --- cyw43-pio/CHANGELOG.md | 2 -- embassy-boot-nrf/CHANGELOG.md | 4 ---- embassy-boot-rp/CHANGELOG.md | 2 -- embassy-boot-stm32/CHANGELOG.md | 2 -- 4 files changed, 10 deletions(-) diff --git a/cyw43-pio/CHANGELOG.md b/cyw43-pio/CHANGELOG.md index 048e2bd8e..9b76f601d 100644 --- a/cyw43-pio/CHANGELOG.md +++ b/cyw43-pio/CHANGELOG.md @@ -10,8 +10,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 0.7.0 - 2025-08-26 -## 0.6.1 - 2025-08-26 - ## 0.6.0 - 2025-08-04 ## 0.5.1 - 2025-07-16 diff --git a/embassy-boot-nrf/CHANGELOG.md b/embassy-boot-nrf/CHANGELOG.md index 3092b129d..8cc1e73c0 100644 --- a/embassy-boot-nrf/CHANGELOG.md +++ b/embassy-boot-nrf/CHANGELOG.md @@ -10,10 +10,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 0.8.0 - 2025-08-26 -## 0.7.0 - 2025-08-26 - -## 0.7.1 - 2025-08-26 - ## 0.1.1 - 2025-08-15 - First release with changelog. diff --git a/embassy-boot-rp/CHANGELOG.md b/embassy-boot-rp/CHANGELOG.md index 782bb066c..8cc1e73c0 100644 --- a/embassy-boot-rp/CHANGELOG.md +++ b/embassy-boot-rp/CHANGELOG.md @@ -10,8 +10,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 0.8.0 - 2025-08-26 -## 0.7.1 - 2025-08-26 - ## 0.1.1 - 2025-08-15 - First release with changelog. diff --git a/embassy-boot-stm32/CHANGELOG.md b/embassy-boot-stm32/CHANGELOG.md index 6044249e9..e7f1d0929 100644 --- a/embassy-boot-stm32/CHANGELOG.md +++ b/embassy-boot-stm32/CHANGELOG.md @@ -10,8 +10,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 0.6.0 - 2025-08-26 -## 0.5.1 - 2025-08-26 - ## 0.1.1 - 2025-08-15 - First release with changelog. -- cgit From 3e8d8fec15286eb25b8bba7d103c8fc279544551 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 27 Aug 2025 08:44:05 +0200 Subject: fix: update more minor versions --- embassy-boot/Cargo.toml | 2 +- embassy-embedded-hal/CHANGELOG.md | 2 +- embassy-embedded-hal/Cargo.toml | 2 +- embassy-imxrt/Cargo.toml | 2 +- embassy-mspm0/Cargo.toml | 2 +- embassy-nrf/Cargo.toml | 2 +- embassy-rp/Cargo.toml | 2 +- embassy-stm32-wpan/Cargo.toml | 2 +- embassy-stm32/Cargo.toml | 2 +- embassy-usb-dfu/CHANGELOG.md | 2 +- embassy-usb-dfu/Cargo.toml | 2 +- examples/boot/application/nrf/Cargo.toml | 2 +- examples/boot/application/rp/Cargo.toml | 2 +- examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wb-dfu/Cargo.toml | 4 ++-- examples/boot/application/stm32wba-dfu/Cargo.toml | 4 ++-- examples/boot/application/stm32wl/Cargo.toml | 2 +- examples/boot/bootloader/stm32wb-dfu/Cargo.toml | 2 +- examples/boot/bootloader/stm32wba-dfu/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- examples/stm32h7/Cargo.toml | 2 +- examples/stm32h735/Cargo.toml | 2 +- examples/stm32h755cm4/Cargo.toml | 2 +- examples/stm32h755cm7/Cargo.toml | 2 +- examples/stm32h7b0/Cargo.toml | 2 +- examples/stm32l4/Cargo.toml | 2 +- examples/stm32wl/Cargo.toml | 2 +- tests/mspm0/Cargo.toml | 2 +- tests/rp/Cargo.toml | 2 +- 35 files changed, 37 insertions(+), 37 deletions(-) diff --git a/embassy-boot/Cargo.toml b/embassy-boot/Cargo.toml index e1f539962..ed0242c13 100644 --- a/embassy-boot/Cargo.toml +++ b/embassy-boot/Cargo.toml @@ -28,7 +28,7 @@ defmt = { version = "1.0.1", optional = true } digest = "0.10" log = { version = "0.4", optional = true } ed25519-dalek = { version = "2", default-features = false, features = ["digest"], optional = true } -embassy-embedded-hal = { version = "0.4.1", path = "../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal" } embassy-sync = { version = "0.7.2", path = "../embassy-sync" } embedded-storage = "0.3.1" embedded-storage-async = { version = "0.4.1" } diff --git a/embassy-embedded-hal/CHANGELOG.md b/embassy-embedded-hal/CHANGELOG.md index 9a410fcd2..ec79a5c81 100644 --- a/embassy-embedded-hal/CHANGELOG.md +++ b/embassy-embedded-hal/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate -## 0.4.1 - 2025-08-26 +## 0.5.0 - 2025-08-27 ## 0.4.0 - 2025-08-03 diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index aa7b53dff..a66e01717 100644 --- a/embassy-embedded-hal/Cargo.toml +++ b/embassy-embedded-hal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-embedded-hal" -version = "0.4.1" +version = "0.5.0" edition = "2021" license = "MIT OR Apache-2.0" description = "Collection of utilities to use `embedded-hal` and `embedded-storage` traits with Embassy." diff --git a/embassy-imxrt/Cargo.toml b/embassy-imxrt/Cargo.toml index 35b37d07c..8a9c1252e 100644 --- a/embassy-imxrt/Cargo.toml +++ b/embassy-imxrt/Cargo.toml @@ -75,7 +75,7 @@ embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver", opti embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-utils", optional = true } embassy-time = { version = "0.5.0", path = "../embassy-time", optional = true } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } -embassy-embedded-hal = { version = "0.4.1", path = "../embassy-embedded-hal", default-features = false } +embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal", default-features = false } embassy-futures = { version = "0.1.2", path = "../embassy-futures" } defmt = { version = "1.0.1", optional = true } diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index 69900d812..eaed8d2fa 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -51,7 +51,7 @@ embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver", opti embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-utils", optional = true } embassy-futures = { version = "0.1.2", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } -embassy-embedded-hal = { version = "0.4.1", path = "../embassy-embedded-hal", default-features = false } +embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal", default-features = false } embassy-executor = { version = "0.9.0", path = "../embassy-executor", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 92dd78b85..2ce75cfac 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -175,7 +175,7 @@ embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-ut embassy-time = { version = "0.5.0", path = "../embassy-time", optional = true } embassy-sync = { version = "0.7.2", path = "../embassy-sync" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } -embassy-embedded-hal = { version = "0.4.1", path = "../embassy-embedded-hal", default-features = false } +embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal", default-features = false } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index e9541295c..101914a36 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -153,7 +153,7 @@ embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-ut embassy-time = { version = "0.5.0", path = "../embassy-time" } embassy-futures = { version = "0.1.2", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } -embassy-embedded-hal = { version = "0.4.1", path = "../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal" } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } atomic-polyfill = "1.0.1" defmt = { version = "1.0.1", optional = true } diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index ceda440d4..d7c7a284c 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -31,7 +31,7 @@ embassy-sync = { version = "0.7.2", path = "../embassy-sync" } embassy-time = { version = "0.5.0", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.2", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal" } -embassy-embedded-hal = { version = "0.4.1", path = "../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver", optional=true } defmt = { version = "1.0.1", optional = true } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 391c32761..cdb4e07d1 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -147,7 +147,7 @@ embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver", opti embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-utils", optional = true } embassy-futures = { version = "0.1.2", path = "../embassy-futures" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } -embassy-embedded-hal = { version = "0.4.1", path = "../embassy-embedded-hal", default-features = false } +embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal", default-features = false } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } embassy-usb-synopsys-otg = { version = "0.3.1", path = "../embassy-usb-synopsys-otg" } diff --git a/embassy-usb-dfu/CHANGELOG.md b/embassy-usb-dfu/CHANGELOG.md index 9a399c5c7..466eff211 100644 --- a/embassy-usb-dfu/CHANGELOG.md +++ b/embassy-usb-dfu/CHANGELOG.md @@ -8,6 +8,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate -## 0.1.1 - 2025-08-26 +## 0.2.0 - 2025-08-27 - First release with changelog. diff --git a/embassy-usb-dfu/Cargo.toml b/embassy-usb-dfu/Cargo.toml index 1bf39641f..4a65c6895 100644 --- a/embassy-usb-dfu/Cargo.toml +++ b/embassy-usb-dfu/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "embassy-usb-dfu" -version = "0.1.1" +version = "0.2.0" description = "An implementation of the USB DFU 1.1 protocol, using embassy-boot" license = "MIT OR Apache-2.0" repository = "https://github.com/embassy-rs/embassy" diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index 03a390497..b0cc63a6c 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -12,7 +12,7 @@ embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features embassy-nrf = { version = "0.7.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } embassy-boot = { version = "0.6.1", path = "../../../../embassy-boot", features = [] } embassy-boot-nrf = { version = "0.8.0", path = "../../../../embassy-boot-nrf", features = [] } -embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index e022e4ad7..d86386b00 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml @@ -11,7 +11,7 @@ embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] } embassy-rp = { version = "0.8.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } embassy-boot-rp = { version = "0.8.0", path = "../../../../embassy-boot-rp", features = [] } -embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index 03a65fdd8..cd5f422fc 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -11,7 +11,7 @@ embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32" } -embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index e41bdf3dd..c3921a166 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -11,7 +11,7 @@ embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index 644bd70d1..ca186d4d9 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -11,7 +11,7 @@ embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 184245998..be08956f1 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -11,7 +11,7 @@ embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 9a286e6a9..207eed733 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -11,7 +11,7 @@ embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index 02617d2c2..22b9642d8 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -11,7 +11,7 @@ embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml index 7a0435579..e2be4f470 100644 --- a/examples/boot/application/stm32wb-dfu/Cargo.toml +++ b/examples/boot/application/stm32wb-dfu/Cargo.toml @@ -11,9 +11,9 @@ embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb" } -embassy-usb-dfu = { version = "0.1.1", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } +embassy-usb-dfu = { version = "0.2.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32wba-dfu/Cargo.toml b/examples/boot/application/stm32wba-dfu/Cargo.toml index 5d00021e6..6f4213b2c 100644 --- a/examples/boot/application/stm32wba-dfu/Cargo.toml +++ b/examples/boot/application/stm32wba-dfu/Cargo.toml @@ -11,9 +11,9 @@ embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wba65ri", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb" } -embassy-usb-dfu = { version = "0.1.1", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } +embassy-usb-dfu = { version = "0.2.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index a26d6f8d9..8d1446ba9 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -11,7 +11,7 @@ embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", f embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] } -embassy-embedded-hal = { version = "0.4.1", path = "../../../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "1.0.1", optional = true } defmt-rtt = { version = "1.0.0", optional = true } diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml index bc59fd3df..ef10aeabf 100644 --- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml @@ -18,7 +18,7 @@ cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" cfg-if = "1.0.0" -embassy-usb-dfu = { version = "0.1.1", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } +embassy-usb-dfu = { version = "0.2.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb", default-features = false } embassy-futures = { version = "0.1.2", path = "../../../../embassy-futures" } diff --git a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml index e1cf364fd..16de7684e 100644 --- a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml +++ b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml @@ -18,7 +18,7 @@ cortex-m-rt = { version = "0.7" } embedded-storage = "0.3.1" embedded-storage-async = "0.4.0" cfg-if = "1.0.0" -embassy-usb-dfu = { version = "0.1.1", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } +embassy-usb-dfu = { version = "0.2.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb", default-features = false } embassy-futures = { version = "0.1.2", path = "../../../../embassy-futures" } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 204a1cca7..a5b192e0a 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal", features = ["defmt"] } +embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal", features = ["defmt"] } embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index bc95ab629..6418f1915 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal", features = ["defmt"] } +embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal", features = ["defmt"] } embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 5d845837f..9a2080013 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -9,7 +9,7 @@ publish = false # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml index ffaee2115..22b7ad96a 100644 --- a/examples/stm32h735/Cargo.toml +++ b/examples/stm32h735/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml index d34f566e3..c73f9df79 100644 --- a/examples/stm32h755cm4/Cargo.toml +++ b/examples/stm32h755cm4/Cargo.toml @@ -9,7 +9,7 @@ publish = false # Change stm32h755zi-cm4 to your chip name, if necessary. embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml index 22c0cf70e..c34d4e45c 100644 --- a/examples/stm32h755cm7/Cargo.toml +++ b/examples/stm32h755cm7/Cargo.toml @@ -9,7 +9,7 @@ publish = false # Change stm32h743bi to your chip name, if necessary. embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml index 3b21d59df..1917749c5 100644 --- a/examples/stm32h7b0/Cargo.toml +++ b/examples/stm32h7b0/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } -embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 4b764a3e6..1b7f15b1d 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -11,7 +11,7 @@ embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } -embassy-embedded-hal = { version = "0.4.0", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net-adin1110 = { version = "0.3.1", path = "../../embassy-net-adin1110" } embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] } diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 6ad57a85e..825d25c0d 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -11,7 +11,7 @@ embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [" embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal" } +embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/tests/mspm0/Cargo.toml b/tests/mspm0/Cargo.toml index 07fe779a0..227d898d5 100644 --- a/tests/mspm0/Cargo.toml +++ b/tests/mspm0/Cargo.toml @@ -17,7 +17,7 @@ embassy-executor = { version = "0.9.0", path = "../../embassy-executor", feature embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = [ "defmt" ] } embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = [ "rt", "defmt", "unstable-pac", "time-driver-any" ] } -embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal/"} +embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal/"} defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 5afb0d110..809346bed 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -20,7 +20,7 @@ embassy-rp = { version = "0.8.0", path = "../../embassy-rp", features = [ "defmt embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } -embassy-embedded-hal = { version = "0.4.1", path = "../../embassy-embedded-hal/"} +embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal/"} cyw43 = { path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { path = "../../cyw43-pio", features = ["defmt"] } perf-client = { path = "../perf-client" } -- cgit From 55eea8b02984c3b917a98037565473078be824e0 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Thu, 21 Aug 2025 09:29:22 +0200 Subject: mspm0-watchdog: add main implementation --- embassy-mspm0/build.rs | 1 + embassy-mspm0/src/lib.rs | 1 + embassy-mspm0/src/watchdog.rs | 345 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 347 insertions(+) create mode 100644 embassy-mspm0/src/watchdog.rs diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs index efbe6645f..256192f8b 100644 --- a/embassy-mspm0/build.rs +++ b/embassy-mspm0/build.rs @@ -554,6 +554,7 @@ fn generate_peripheral_instances() -> TokenStream { let tokens = match peripheral.kind { "uart" => Some(quote! { impl_uart_instance!(#peri); }), "i2c" => Some(quote! { impl_i2c_instance!(#peri, #fifo_size); }), + "wwdt" => Some(quote! { impl_wwdt_instance!(#peri); }), _ => None, }; diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index 6217669d2..8ee182c12 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -18,6 +18,7 @@ pub mod gpio; pub mod i2c; pub mod timer; pub mod uart; +pub mod watchdog; /// Operating modes for peripherals. pub mod mode { diff --git a/embassy-mspm0/src/watchdog.rs b/embassy-mspm0/src/watchdog.rs new file mode 100644 index 000000000..95e5b97f3 --- /dev/null +++ b/embassy-mspm0/src/watchdog.rs @@ -0,0 +1,345 @@ +//! Window Watchdog Timer (WWDT) driver. +//! +//! This HAL implements a basic window watchdog timer with handles. + +#![macro_use] + +use core::marker::PhantomData; + +use embassy_hal_internal::PeripheralType; + +use crate::pac::wwdt::{vals, Wwdt as Regs}; +use crate::pac::{self}; +use crate::Peri; + +/// Possible watchdog timeout values. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Timeout { + USec1950, + USec3910, + USec5860, + USec7810, + USec9770, + USec11720, + USec13670, + USec15630, + USec23440, + USec31250, + USec32250, + USec39060, + USec46880, + USec54690, + USec62500, + USec93750, + USec125000, + USec156250, + USec187500, + USec218750, + MSec130, + MSec250, + MSec380, + MSec500, + MSec630, + MSec750, + MSec880, + Sec1, + Sec2, + Sec3, + Sec4, + Sec5, + Sec6, + Sec7, + Sec8, + Sec16, + Sec24, + Sec32, + Sec40, + Sec48, + Sec56, + Sec64, + Sec128, // 2.13 min + Sec192, // 3.20 min + Sec256, // 4.27 min + Sec320, // 5.33 min + Sec384, // 6.40 min + Sec448, // 7.47 min + Sec512, // 8.53 min + Sec1024, // 17.07 min + Sec2048, // 34.13 min + Sec3072, // 51.20 min + Sec4096, // 68.27 min + Sec5120, // 85.33 min + Sec6144, // 102.40 min + Sec7168, // 119.47 min + Sec8192, // 136.53 min +} + +impl Timeout { + fn get_period(self) -> vals::Per { + match self { + // period count is 2**25 + Self::Sec1024 + | Self::Sec2048 + | Self::Sec3072 + | Self::Sec4096 + | Self::Sec5120 + | Self::Sec6144 + | Self::Sec7168 + | Self::Sec8192 => vals::Per::EN_25, + // period count is 2**21 + Self::Sec64 + | Self::Sec128 + | Self::Sec192 + | Self::Sec256 + | Self::Sec320 + | Self::Sec384 + | Self::Sec448 + | Self::Sec512 => vals::Per::EN_21, + // period count is 2**18 + Self::Sec8 | Self::Sec16 | Self::Sec24 | Self::Sec32 | Self::Sec40 | Self::Sec48 | Self::Sec56 => { + vals::Per::EN_18 + } + // period count is 2**15 + Self::Sec1 | Self::Sec2 | Self::Sec3 | Self::Sec4 | Self::Sec5 | Self::Sec6 | Self::Sec7 => { + vals::Per::EN_15 + } + // period count is 2**12 + Self::MSec130 + | Self::MSec250 + | Self::MSec380 + | Self::MSec500 + | Self::MSec630 + | Self::MSec750 + | Self::MSec880 => vals::Per::EN_12, + // period count is 2**10 + Self::USec31250 + | Self::USec62500 + | Self::USec93750 + | Self::USec125000 + | Self::USec156250 + | Self::USec187500 + | Self::USec218750 => vals::Per::EN_10, + // period count is 2**8 + Self::USec7810 + | Self::USec15630 + | Self::USec23440 + | Self::USec32250 + | Self::USec39060 + | Self::USec46880 + | Self::USec54690 => vals::Per::EN_8, + // period count is 2**6 + Self::USec1950 | Self::USec3910 | Self::USec5860 | Self::USec9770 | Self::USec11720 | Self::USec13670 => { + vals::Per::EN_6 + } + } + } + + fn get_clkdiv(self) -> u8 { + match self { + // divide by 1 + Self::USec1950 + | Self::USec7810 + | Self::USec31250 + | Self::MSec130 + | Self::Sec1 + | Self::Sec8 + | Self::Sec64 + | Self::Sec1024 => 0u8, + // divide by 2 + Self::USec3910 + | Self::USec15630 + | Self::USec62500 + | Self::MSec250 + | Self::Sec2 + | Self::Sec16 + | Self::Sec128 + | Self::Sec2048 => 1u8, + // divide by 3 + Self::USec5860 + | Self::USec23440 + | Self::USec93750 + | Self::MSec380 + | Self::Sec3 + | Self::Sec24 + | Self::Sec192 + | Self::Sec3072 => 2u8, + // divide by 4 + Self::USec32250 + | Self::USec125000 + | Self::MSec500 + | Self::Sec4 + | Self::Sec32 + | Self::Sec256 + | Self::Sec4096 => 3u8, + // divide by 5 + Self::USec9770 + | Self::USec39060 + | Self::USec156250 + | Self::MSec630 + | Self::Sec5 + | Self::Sec40 + | Self::Sec320 + | Self::Sec5120 => 4u8, + // divide by 6 + Self::USec11720 + | Self::USec46880 + | Self::USec187500 + | Self::MSec750 + | Self::Sec6 + | Self::Sec48 + | Self::Sec384 + | Self::Sec6144 => 5u8, + // divide by 7 + Self::USec13670 + | Self::USec54690 + | Self::USec218750 + | Self::MSec880 + | Self::Sec7 + | Self::Sec56 + | Self::Sec448 + | Self::Sec7168 => 6u8, + // divide by 8 + Self::Sec512 | Self::Sec8192 => 7u8, + } + } +} + +/// Timeout percentage that is treated as "too early" and generates violation. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ClosedWindowPercentage { + // window period is not used + Zero, + // 12.5% percents + Twelve, + // 18.75% percents + Eighteen, + // 25% percents + TwentyFive, + // 50% percents + Fifty, + // 75% percents + SeventyFive, + // 81.25% percents + EightyOne, + // 87.5% percents + EightySeven, +} + +impl ClosedWindowPercentage { + fn get_native_size(self) -> vals::Window { + match self { + Self::Zero => vals::Window::SIZE_0, + Self::Twelve => vals::Window::SIZE_12, + Self::Eighteen => vals::Window::SIZE_18, + Self::TwentyFive => vals::Window::SIZE_25, + Self::Fifty => vals::Window::SIZE_50, + Self::SeventyFive => vals::Window::SIZE_75, + Self::EightyOne => vals::Window::SIZE_81, + Self::EightySeven => vals::Window::SIZE_87, + } + } +} + +#[non_exhaustive] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +/// Watchdog Config +pub struct Config { + /// Watchdog timeout + pub timeout: Timeout, + + /// closed window percentage + pub closed_window: ClosedWindowPercentage, +} + +impl Default for Config { + fn default() -> Self { + Self { + timeout: Timeout::Sec1, + closed_window: ClosedWindowPercentage::Zero, + } + } +} + +pub struct Watchdog<'d, T: Instance> { + wdt: PhantomData<&'d mut T>, +} + +impl<'d, T: Instance> Watchdog<'d, T> { + /// Watchdog initialization. + pub fn new(_instance: Peri<'d, T>, config: Config) -> Self { + // Init power for watchdog + T::REGS.gprcm(0).rstctl().write(|w| { + w.set_resetstkyclr(true); + w.set_resetassert(true); + w.set_key(vals::ResetKey::KEY); + }); + + // Enable power for watchdog + T::REGS.gprcm(0).pwren().write(|w| { + w.set_enable(true); + w.set_key(vals::PwrenKey::KEY); + }); + + // init delay, 16 cycles + cortex_m::asm::delay(16); + + //init watchdog + T::REGS.wwdtctl0().write(|w| { + w.set_clkdiv(config.timeout.get_clkdiv()); + w.set_per(config.timeout.get_period()); + w.set_mode(vals::Mode::WINDOW); + w.set_window0(config.closed_window.get_native_size()); + w.set_window1(vals::Window::SIZE_0); + w.set_key(vals::Wwdtctl0Key::KEY); + }); + + // Set Window0 as active window + T::REGS.wwdtctl1().write(|w| { + w.set_winsel(vals::Winsel::WIN0); + w.set_key(vals::Wwdtctl1Key::KEY); + }); + + critical_section::with(|_| { + // make sure watchdog triggers BOOTRST + pac::SYSCTL.systemcfg().write(|w| { + if T::REGS == pac::WWDT0 { + w.set_wwdtlp0rstdis(false); + } + + #[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))] + if T::REGS == pac::WWDT1 { + w.set_wwdtlp1rstdis(false); + } + }); + }); + + Watchdog { wdt: PhantomData } + } + + /// Pet (reload, refresh) the watchdog. + pub fn pet(&mut self) { + T::REGS.wwdtcntrst().write(|w| { + w.set_restart(vals::WwdtcntrstRestart::RESTART); + }); + } +} + +pub(crate) trait SealedInstance { + const REGS: Regs; +} + +/// WWDT instance trait +#[allow(private_bounds)] +pub trait Instance: SealedInstance + PeripheralType {} + +macro_rules! impl_wwdt_instance { + ($instance: ident) => { + impl crate::watchdog::SealedInstance for crate::peripherals::$instance { + const REGS: crate::pac::wwdt::Wwdt = crate::pac::$instance; + } + + impl crate::watchdog::Instance for crate::peripherals::$instance {} + }; +} -- cgit From 93ba2c9c95721f1fe16269f09c219b161b2969cb Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Thu, 21 Aug 2025 09:32:05 +0200 Subject: mspm0-watchdog: add watchdog examples for all chips --- examples/mspm0c1104/src/bin/wwdt.rs | 54 +++++++++++++++++++++++++++++++++++++ examples/mspm0g3507/src/bin/wwdt.rs | 54 +++++++++++++++++++++++++++++++++++++ examples/mspm0g3519/src/bin/wwdt.rs | 54 +++++++++++++++++++++++++++++++++++++ examples/mspm0l1306/src/bin/wwdt.rs | 54 +++++++++++++++++++++++++++++++++++++ examples/mspm0l2228/src/bin/wwdt.rs | 54 +++++++++++++++++++++++++++++++++++++ 5 files changed, 270 insertions(+) create mode 100644 examples/mspm0c1104/src/bin/wwdt.rs create mode 100644 examples/mspm0g3507/src/bin/wwdt.rs create mode 100644 examples/mspm0g3519/src/bin/wwdt.rs create mode 100644 examples/mspm0l1306/src/bin/wwdt.rs create mode 100644 examples/mspm0l2228/src/bin/wwdt.rs diff --git a/examples/mspm0c1104/src/bin/wwdt.rs b/examples/mspm0c1104/src/bin/wwdt.rs new file mode 100644 index 000000000..4aa3caca9 --- /dev/null +++ b/examples/mspm0c1104/src/bin/wwdt.rs @@ -0,0 +1,54 @@ +//! Example of using window watchdog timer in the MSPM0C1104 chip. +//! +//! It tests the use case when watchdog timer is expired and when watchdog is pet too early. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_mspm0::gpio::{Level, Output}; +use embassy_mspm0::watchdog::{ClosedWindowPercentage, Config, Timeout, Watchdog}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_halt as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + info!("Hello world!"); + + let p = embassy_mspm0::init(Default::default()); + let mut conf = Config::default(); + conf.timeout = Timeout::Sec1; + + // watchdog also resets the system if the pet comes too early, + // less than 250 msec == 25% from 1 sec + conf.closed_window = ClosedWindowPercentage::TwentyFive; + let mut wdt = Watchdog::new(p.WWDT0, conf); + info!("Started the watchdog timer"); + + let mut led1 = Output::new(p.PA0, Level::High); + led1.set_inversion(true); + Timer::after_millis(900).await; + + for _ in 1..=5 { + info!("pet watchdog"); + led1.toggle(); + wdt.pet(); + Timer::after_millis(500).await; + } + + // watchdog timeout test + info!("Stopped the pet command, device will reset in less than 1 second"); + loop { + led1.toggle(); + Timer::after_millis(500).await; + } + + // watchdog "too early" test + // info!("Device will reset when the pet comes too early"); + // loop { + // led1.toggle(); + // wdt.pet(); + // Timer::after_millis(200).await; + // } +} diff --git a/examples/mspm0g3507/src/bin/wwdt.rs b/examples/mspm0g3507/src/bin/wwdt.rs new file mode 100644 index 000000000..6d3240ff7 --- /dev/null +++ b/examples/mspm0g3507/src/bin/wwdt.rs @@ -0,0 +1,54 @@ +//! Example of using window watchdog timer in the MSPM0G3507 chip. +//! +//! It tests the use case when watchdog timer is expired and when watchdog is pet too early. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_mspm0::gpio::{Level, Output}; +use embassy_mspm0::watchdog::{ClosedWindowPercentage, Config, Timeout, Watchdog}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_halt as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + info!("Hello world!"); + + let p = embassy_mspm0::init(Default::default()); + let mut conf = Config::default(); + conf.timeout = Timeout::Sec1; + + // watchdog also resets the system if the pet comes too early, + // less than 250 msec == 25% from 1 sec + conf.closed_window = ClosedWindowPercentage::TwentyFive; + let mut wdt = Watchdog::new(p.WWDT0, conf); + info!("Started the watchdog timer"); + + let mut led1 = Output::new(p.PA0, Level::High); + led1.set_inversion(true); + Timer::after_millis(900).await; + + for _ in 1..=5 { + info!("pet watchdog"); + led1.toggle(); + wdt.pet(); + Timer::after_millis(500).await; + } + + // watchdog timeout test + info!("Stopped the pet command, device will reset in less than 1 second"); + loop { + led1.toggle(); + Timer::after_millis(500).await; + } + + // watchdog "too early" test + // info!("Device will reset when the pet comes too early"); + // loop { + // led1.toggle(); + // wdt.pet(); + // Timer::after_millis(200).await; + // } +} diff --git a/examples/mspm0g3519/src/bin/wwdt.rs b/examples/mspm0g3519/src/bin/wwdt.rs new file mode 100644 index 000000000..dee941274 --- /dev/null +++ b/examples/mspm0g3519/src/bin/wwdt.rs @@ -0,0 +1,54 @@ +//! Example of using window watchdog timer in the MSPM0G3519 chip. +//! +//! It tests the use case when watchdog timer is expired and when watchdog is pet too early. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_mspm0::gpio::{Level, Output}; +use embassy_mspm0::watchdog::{ClosedWindowPercentage, Config, Timeout, Watchdog}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_halt as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + info!("Hello world!"); + + let p = embassy_mspm0::init(Default::default()); + let mut conf = Config::default(); + conf.timeout = Timeout::Sec1; + + // watchdog also resets the system if the pet comes too early, + // less than 250 msec == 25% from 1 sec + conf.closed_window = ClosedWindowPercentage::TwentyFive; + let mut wdt = Watchdog::new(p.WWDT0, conf); + info!("Started the watchdog timer"); + + let mut led1 = Output::new(p.PA0, Level::High); + led1.set_inversion(true); + Timer::after_millis(900).await; + + for _ in 1..=5 { + info!("pet watchdog"); + led1.toggle(); + wdt.pet(); + Timer::after_millis(500).await; + } + + // watchdog timeout test + info!("Stopped the pet command, device will reset in less than 1 second"); + loop { + led1.toggle(); + Timer::after_millis(500).await; + } + + // watchdog "too early" test + // info!("Device will reset when the pet comes too early"); + // loop { + // led1.toggle(); + // wdt.pet(); + // Timer::after_millis(200).await; + // } +} diff --git a/examples/mspm0l1306/src/bin/wwdt.rs b/examples/mspm0l1306/src/bin/wwdt.rs new file mode 100644 index 000000000..f2bbe5701 --- /dev/null +++ b/examples/mspm0l1306/src/bin/wwdt.rs @@ -0,0 +1,54 @@ +//! Example of using window watchdog timer in the MSPM0L1306 chip. +//! +//! It tests the use case when watchdog timer is expired and when watchdog is pet too early. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_mspm0::gpio::{Level, Output}; +use embassy_mspm0::watchdog::{ClosedWindowPercentage, Config, Timeout, Watchdog}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_halt as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + info!("Hello world!"); + + let p = embassy_mspm0::init(Default::default()); + let mut conf = Config::default(); + conf.timeout = Timeout::Sec1; + + // watchdog also resets the system if the pet comes too early, + // less than 250 msec == 25% from 1 sec + conf.closed_window = ClosedWindowPercentage::TwentyFive; + let mut wdt = Watchdog::new(p.WWDT0, conf); + info!("Started the watchdog timer"); + + let mut led1 = Output::new(p.PA0, Level::High); + led1.set_inversion(true); + Timer::after_millis(900).await; + + for _ in 1..=5 { + info!("pet watchdog"); + led1.toggle(); + wdt.pet(); + Timer::after_millis(500).await; + } + + // watchdog timeout test + info!("Stopped the pet command, device will reset in less than 1 second"); + loop { + led1.toggle(); + Timer::after_millis(500).await; + } + + // watchdog "too early" test + // info!("Device will reset when the pet comes too early"); + // loop { + // led1.toggle(); + // wdt.pet(); + // Timer::after_millis(200).await; + // } +} diff --git a/examples/mspm0l2228/src/bin/wwdt.rs b/examples/mspm0l2228/src/bin/wwdt.rs new file mode 100644 index 000000000..6fd18247a --- /dev/null +++ b/examples/mspm0l2228/src/bin/wwdt.rs @@ -0,0 +1,54 @@ +//! Example of using window watchdog timer in the MSPM0L2228 chip. +//! +//! It tests the use case when watchdog timer is expired and when watchdog is pet too early. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_mspm0::gpio::{Level, Output}; +use embassy_mspm0::watchdog::{ClosedWindowPercentage, Config, Timeout, Watchdog}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_halt as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + info!("Hello world!"); + + let p = embassy_mspm0::init(Default::default()); + let mut conf = Config::default(); + conf.timeout = Timeout::Sec1; + + // watchdog also resets the system if the pet comes too early, + // less than 250 msec == 25% from 1 sec + conf.closed_window = ClosedWindowPercentage::TwentyFive; + let mut wdt = Watchdog::new(p.WWDT0, conf); + info!("Started the watchdog timer"); + + let mut led1 = Output::new(p.PA0, Level::High); + led1.set_inversion(true); + Timer::after_millis(900).await; + + for _ in 1..=5 { + info!("pet watchdog"); + led1.toggle(); + wdt.pet(); + Timer::after_millis(500).await; + } + + // watchdog timeout test + info!("Stopped the pet command, device will reset in less than 1 second"); + loop { + led1.toggle(); + Timer::after_millis(500).await; + } + + // watchdog "too early" test + // info!("Device will reset when the pet comes too early"); + // loop { + // led1.toggle(); + // wdt.pet(); + // Timer::after_millis(200).await; + // } +} -- cgit From 2eb643bac66844dccddc11065c3debbaef468595 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Tue, 26 Aug 2025 08:19:12 +0200 Subject: mspm0-watchdog: rename mod watchdog to wwdt --- embassy-mspm0/src/lib.rs | 2 +- embassy-mspm0/src/watchdog.rs | 345 ------------------------------------ embassy-mspm0/src/wwdt.rs | 345 ++++++++++++++++++++++++++++++++++++ examples/mspm0c1104/src/bin/wwdt.rs | 2 +- examples/mspm0g3507/src/bin/wwdt.rs | 2 +- examples/mspm0g3519/src/bin/wwdt.rs | 2 +- examples/mspm0l1306/src/bin/wwdt.rs | 2 +- examples/mspm0l2228/src/bin/wwdt.rs | 2 +- 8 files changed, 351 insertions(+), 351 deletions(-) delete mode 100644 embassy-mspm0/src/watchdog.rs create mode 100644 embassy-mspm0/src/wwdt.rs diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index 8ee182c12..0cb19a379 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -18,7 +18,7 @@ pub mod gpio; pub mod i2c; pub mod timer; pub mod uart; -pub mod watchdog; +pub mod wwdt; /// Operating modes for peripherals. pub mod mode { diff --git a/embassy-mspm0/src/watchdog.rs b/embassy-mspm0/src/watchdog.rs deleted file mode 100644 index 95e5b97f3..000000000 --- a/embassy-mspm0/src/watchdog.rs +++ /dev/null @@ -1,345 +0,0 @@ -//! Window Watchdog Timer (WWDT) driver. -//! -//! This HAL implements a basic window watchdog timer with handles. - -#![macro_use] - -use core::marker::PhantomData; - -use embassy_hal_internal::PeripheralType; - -use crate::pac::wwdt::{vals, Wwdt as Regs}; -use crate::pac::{self}; -use crate::Peri; - -/// Possible watchdog timeout values. -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum Timeout { - USec1950, - USec3910, - USec5860, - USec7810, - USec9770, - USec11720, - USec13670, - USec15630, - USec23440, - USec31250, - USec32250, - USec39060, - USec46880, - USec54690, - USec62500, - USec93750, - USec125000, - USec156250, - USec187500, - USec218750, - MSec130, - MSec250, - MSec380, - MSec500, - MSec630, - MSec750, - MSec880, - Sec1, - Sec2, - Sec3, - Sec4, - Sec5, - Sec6, - Sec7, - Sec8, - Sec16, - Sec24, - Sec32, - Sec40, - Sec48, - Sec56, - Sec64, - Sec128, // 2.13 min - Sec192, // 3.20 min - Sec256, // 4.27 min - Sec320, // 5.33 min - Sec384, // 6.40 min - Sec448, // 7.47 min - Sec512, // 8.53 min - Sec1024, // 17.07 min - Sec2048, // 34.13 min - Sec3072, // 51.20 min - Sec4096, // 68.27 min - Sec5120, // 85.33 min - Sec6144, // 102.40 min - Sec7168, // 119.47 min - Sec8192, // 136.53 min -} - -impl Timeout { - fn get_period(self) -> vals::Per { - match self { - // period count is 2**25 - Self::Sec1024 - | Self::Sec2048 - | Self::Sec3072 - | Self::Sec4096 - | Self::Sec5120 - | Self::Sec6144 - | Self::Sec7168 - | Self::Sec8192 => vals::Per::EN_25, - // period count is 2**21 - Self::Sec64 - | Self::Sec128 - | Self::Sec192 - | Self::Sec256 - | Self::Sec320 - | Self::Sec384 - | Self::Sec448 - | Self::Sec512 => vals::Per::EN_21, - // period count is 2**18 - Self::Sec8 | Self::Sec16 | Self::Sec24 | Self::Sec32 | Self::Sec40 | Self::Sec48 | Self::Sec56 => { - vals::Per::EN_18 - } - // period count is 2**15 - Self::Sec1 | Self::Sec2 | Self::Sec3 | Self::Sec4 | Self::Sec5 | Self::Sec6 | Self::Sec7 => { - vals::Per::EN_15 - } - // period count is 2**12 - Self::MSec130 - | Self::MSec250 - | Self::MSec380 - | Self::MSec500 - | Self::MSec630 - | Self::MSec750 - | Self::MSec880 => vals::Per::EN_12, - // period count is 2**10 - Self::USec31250 - | Self::USec62500 - | Self::USec93750 - | Self::USec125000 - | Self::USec156250 - | Self::USec187500 - | Self::USec218750 => vals::Per::EN_10, - // period count is 2**8 - Self::USec7810 - | Self::USec15630 - | Self::USec23440 - | Self::USec32250 - | Self::USec39060 - | Self::USec46880 - | Self::USec54690 => vals::Per::EN_8, - // period count is 2**6 - Self::USec1950 | Self::USec3910 | Self::USec5860 | Self::USec9770 | Self::USec11720 | Self::USec13670 => { - vals::Per::EN_6 - } - } - } - - fn get_clkdiv(self) -> u8 { - match self { - // divide by 1 - Self::USec1950 - | Self::USec7810 - | Self::USec31250 - | Self::MSec130 - | Self::Sec1 - | Self::Sec8 - | Self::Sec64 - | Self::Sec1024 => 0u8, - // divide by 2 - Self::USec3910 - | Self::USec15630 - | Self::USec62500 - | Self::MSec250 - | Self::Sec2 - | Self::Sec16 - | Self::Sec128 - | Self::Sec2048 => 1u8, - // divide by 3 - Self::USec5860 - | Self::USec23440 - | Self::USec93750 - | Self::MSec380 - | Self::Sec3 - | Self::Sec24 - | Self::Sec192 - | Self::Sec3072 => 2u8, - // divide by 4 - Self::USec32250 - | Self::USec125000 - | Self::MSec500 - | Self::Sec4 - | Self::Sec32 - | Self::Sec256 - | Self::Sec4096 => 3u8, - // divide by 5 - Self::USec9770 - | Self::USec39060 - | Self::USec156250 - | Self::MSec630 - | Self::Sec5 - | Self::Sec40 - | Self::Sec320 - | Self::Sec5120 => 4u8, - // divide by 6 - Self::USec11720 - | Self::USec46880 - | Self::USec187500 - | Self::MSec750 - | Self::Sec6 - | Self::Sec48 - | Self::Sec384 - | Self::Sec6144 => 5u8, - // divide by 7 - Self::USec13670 - | Self::USec54690 - | Self::USec218750 - | Self::MSec880 - | Self::Sec7 - | Self::Sec56 - | Self::Sec448 - | Self::Sec7168 => 6u8, - // divide by 8 - Self::Sec512 | Self::Sec8192 => 7u8, - } - } -} - -/// Timeout percentage that is treated as "too early" and generates violation. -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum ClosedWindowPercentage { - // window period is not used - Zero, - // 12.5% percents - Twelve, - // 18.75% percents - Eighteen, - // 25% percents - TwentyFive, - // 50% percents - Fifty, - // 75% percents - SeventyFive, - // 81.25% percents - EightyOne, - // 87.5% percents - EightySeven, -} - -impl ClosedWindowPercentage { - fn get_native_size(self) -> vals::Window { - match self { - Self::Zero => vals::Window::SIZE_0, - Self::Twelve => vals::Window::SIZE_12, - Self::Eighteen => vals::Window::SIZE_18, - Self::TwentyFive => vals::Window::SIZE_25, - Self::Fifty => vals::Window::SIZE_50, - Self::SeventyFive => vals::Window::SIZE_75, - Self::EightyOne => vals::Window::SIZE_81, - Self::EightySeven => vals::Window::SIZE_87, - } - } -} - -#[non_exhaustive] -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -/// Watchdog Config -pub struct Config { - /// Watchdog timeout - pub timeout: Timeout, - - /// closed window percentage - pub closed_window: ClosedWindowPercentage, -} - -impl Default for Config { - fn default() -> Self { - Self { - timeout: Timeout::Sec1, - closed_window: ClosedWindowPercentage::Zero, - } - } -} - -pub struct Watchdog<'d, T: Instance> { - wdt: PhantomData<&'d mut T>, -} - -impl<'d, T: Instance> Watchdog<'d, T> { - /// Watchdog initialization. - pub fn new(_instance: Peri<'d, T>, config: Config) -> Self { - // Init power for watchdog - T::REGS.gprcm(0).rstctl().write(|w| { - w.set_resetstkyclr(true); - w.set_resetassert(true); - w.set_key(vals::ResetKey::KEY); - }); - - // Enable power for watchdog - T::REGS.gprcm(0).pwren().write(|w| { - w.set_enable(true); - w.set_key(vals::PwrenKey::KEY); - }); - - // init delay, 16 cycles - cortex_m::asm::delay(16); - - //init watchdog - T::REGS.wwdtctl0().write(|w| { - w.set_clkdiv(config.timeout.get_clkdiv()); - w.set_per(config.timeout.get_period()); - w.set_mode(vals::Mode::WINDOW); - w.set_window0(config.closed_window.get_native_size()); - w.set_window1(vals::Window::SIZE_0); - w.set_key(vals::Wwdtctl0Key::KEY); - }); - - // Set Window0 as active window - T::REGS.wwdtctl1().write(|w| { - w.set_winsel(vals::Winsel::WIN0); - w.set_key(vals::Wwdtctl1Key::KEY); - }); - - critical_section::with(|_| { - // make sure watchdog triggers BOOTRST - pac::SYSCTL.systemcfg().write(|w| { - if T::REGS == pac::WWDT0 { - w.set_wwdtlp0rstdis(false); - } - - #[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))] - if T::REGS == pac::WWDT1 { - w.set_wwdtlp1rstdis(false); - } - }); - }); - - Watchdog { wdt: PhantomData } - } - - /// Pet (reload, refresh) the watchdog. - pub fn pet(&mut self) { - T::REGS.wwdtcntrst().write(|w| { - w.set_restart(vals::WwdtcntrstRestart::RESTART); - }); - } -} - -pub(crate) trait SealedInstance { - const REGS: Regs; -} - -/// WWDT instance trait -#[allow(private_bounds)] -pub trait Instance: SealedInstance + PeripheralType {} - -macro_rules! impl_wwdt_instance { - ($instance: ident) => { - impl crate::watchdog::SealedInstance for crate::peripherals::$instance { - const REGS: crate::pac::wwdt::Wwdt = crate::pac::$instance; - } - - impl crate::watchdog::Instance for crate::peripherals::$instance {} - }; -} diff --git a/embassy-mspm0/src/wwdt.rs b/embassy-mspm0/src/wwdt.rs new file mode 100644 index 000000000..9864b3d94 --- /dev/null +++ b/embassy-mspm0/src/wwdt.rs @@ -0,0 +1,345 @@ +//! Window Watchdog Timer (WWDT) driver. +//! +//! This HAL implements a basic window watchdog timer with handles. + +#![macro_use] + +use core::marker::PhantomData; + +use embassy_hal_internal::PeripheralType; + +use crate::pac::wwdt::{vals, Wwdt as Regs}; +use crate::pac::{self}; +use crate::Peri; + +/// Possible watchdog timeout values. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Timeout { + USec1950, + USec3910, + USec5860, + USec7810, + USec9770, + USec11720, + USec13670, + USec15630, + USec23440, + USec31250, + USec32250, + USec39060, + USec46880, + USec54690, + USec62500, + USec93750, + USec125000, + USec156250, + USec187500, + USec218750, + MSec130, + MSec250, + MSec380, + MSec500, + MSec630, + MSec750, + MSec880, + Sec1, + Sec2, + Sec3, + Sec4, + Sec5, + Sec6, + Sec7, + Sec8, + Sec16, + Sec24, + Sec32, + Sec40, + Sec48, + Sec56, + Sec64, + Sec128, // 2.13 min + Sec192, // 3.20 min + Sec256, // 4.27 min + Sec320, // 5.33 min + Sec384, // 6.40 min + Sec448, // 7.47 min + Sec512, // 8.53 min + Sec1024, // 17.07 min + Sec2048, // 34.13 min + Sec3072, // 51.20 min + Sec4096, // 68.27 min + Sec5120, // 85.33 min + Sec6144, // 102.40 min + Sec7168, // 119.47 min + Sec8192, // 136.53 min +} + +impl Timeout { + fn get_period(self) -> vals::Per { + match self { + // period count is 2**25 + Self::Sec1024 + | Self::Sec2048 + | Self::Sec3072 + | Self::Sec4096 + | Self::Sec5120 + | Self::Sec6144 + | Self::Sec7168 + | Self::Sec8192 => vals::Per::EN_25, + // period count is 2**21 + Self::Sec64 + | Self::Sec128 + | Self::Sec192 + | Self::Sec256 + | Self::Sec320 + | Self::Sec384 + | Self::Sec448 + | Self::Sec512 => vals::Per::EN_21, + // period count is 2**18 + Self::Sec8 | Self::Sec16 | Self::Sec24 | Self::Sec32 | Self::Sec40 | Self::Sec48 | Self::Sec56 => { + vals::Per::EN_18 + } + // period count is 2**15 + Self::Sec1 | Self::Sec2 | Self::Sec3 | Self::Sec4 | Self::Sec5 | Self::Sec6 | Self::Sec7 => { + vals::Per::EN_15 + } + // period count is 2**12 + Self::MSec130 + | Self::MSec250 + | Self::MSec380 + | Self::MSec500 + | Self::MSec630 + | Self::MSec750 + | Self::MSec880 => vals::Per::EN_12, + // period count is 2**10 + Self::USec31250 + | Self::USec62500 + | Self::USec93750 + | Self::USec125000 + | Self::USec156250 + | Self::USec187500 + | Self::USec218750 => vals::Per::EN_10, + // period count is 2**8 + Self::USec7810 + | Self::USec15630 + | Self::USec23440 + | Self::USec32250 + | Self::USec39060 + | Self::USec46880 + | Self::USec54690 => vals::Per::EN_8, + // period count is 2**6 + Self::USec1950 | Self::USec3910 | Self::USec5860 | Self::USec9770 | Self::USec11720 | Self::USec13670 => { + vals::Per::EN_6 + } + } + } + + fn get_clkdiv(self) -> u8 { + match self { + // divide by 1 + Self::USec1950 + | Self::USec7810 + | Self::USec31250 + | Self::MSec130 + | Self::Sec1 + | Self::Sec8 + | Self::Sec64 + | Self::Sec1024 => 0u8, + // divide by 2 + Self::USec3910 + | Self::USec15630 + | Self::USec62500 + | Self::MSec250 + | Self::Sec2 + | Self::Sec16 + | Self::Sec128 + | Self::Sec2048 => 1u8, + // divide by 3 + Self::USec5860 + | Self::USec23440 + | Self::USec93750 + | Self::MSec380 + | Self::Sec3 + | Self::Sec24 + | Self::Sec192 + | Self::Sec3072 => 2u8, + // divide by 4 + Self::USec32250 + | Self::USec125000 + | Self::MSec500 + | Self::Sec4 + | Self::Sec32 + | Self::Sec256 + | Self::Sec4096 => 3u8, + // divide by 5 + Self::USec9770 + | Self::USec39060 + | Self::USec156250 + | Self::MSec630 + | Self::Sec5 + | Self::Sec40 + | Self::Sec320 + | Self::Sec5120 => 4u8, + // divide by 6 + Self::USec11720 + | Self::USec46880 + | Self::USec187500 + | Self::MSec750 + | Self::Sec6 + | Self::Sec48 + | Self::Sec384 + | Self::Sec6144 => 5u8, + // divide by 7 + Self::USec13670 + | Self::USec54690 + | Self::USec218750 + | Self::MSec880 + | Self::Sec7 + | Self::Sec56 + | Self::Sec448 + | Self::Sec7168 => 6u8, + // divide by 8 + Self::Sec512 | Self::Sec8192 => 7u8, + } + } +} + +/// Timeout percentage that is treated as "too early" and generates violation. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ClosedWindowPercentage { + // window period is not used + Zero, + // 12.5% percents + Twelve, + // 18.75% percents + Eighteen, + // 25% percents + TwentyFive, + // 50% percents + Fifty, + // 75% percents + SeventyFive, + // 81.25% percents + EightyOne, + // 87.5% percents + EightySeven, +} + +impl ClosedWindowPercentage { + fn get_native_size(self) -> vals::Window { + match self { + Self::Zero => vals::Window::SIZE_0, + Self::Twelve => vals::Window::SIZE_12, + Self::Eighteen => vals::Window::SIZE_18, + Self::TwentyFive => vals::Window::SIZE_25, + Self::Fifty => vals::Window::SIZE_50, + Self::SeventyFive => vals::Window::SIZE_75, + Self::EightyOne => vals::Window::SIZE_81, + Self::EightySeven => vals::Window::SIZE_87, + } + } +} + +#[non_exhaustive] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +/// Watchdog Config +pub struct Config { + /// Watchdog timeout + pub timeout: Timeout, + + /// closed window percentage + pub closed_window: ClosedWindowPercentage, +} + +impl Default for Config { + fn default() -> Self { + Self { + timeout: Timeout::Sec1, + closed_window: ClosedWindowPercentage::Zero, + } + } +} + +pub struct Watchdog<'d, T: Instance> { + wdt: PhantomData<&'d mut T>, +} + +impl<'d, T: Instance> Watchdog<'d, T> { + /// Watchdog initialization. + pub fn new(_instance: Peri<'d, T>, config: Config) -> Self { + // Init power for watchdog + T::REGS.gprcm(0).rstctl().write(|w| { + w.set_resetstkyclr(true); + w.set_resetassert(true); + w.set_key(vals::ResetKey::KEY); + }); + + // Enable power for watchdog + T::REGS.gprcm(0).pwren().write(|w| { + w.set_enable(true); + w.set_key(vals::PwrenKey::KEY); + }); + + // init delay, 16 cycles + cortex_m::asm::delay(16); + + //init watchdog + T::REGS.wwdtctl0().write(|w| { + w.set_clkdiv(config.timeout.get_clkdiv()); + w.set_per(config.timeout.get_period()); + w.set_mode(vals::Mode::WINDOW); + w.set_window0(config.closed_window.get_native_size()); + w.set_window1(vals::Window::SIZE_0); + w.set_key(vals::Wwdtctl0Key::KEY); + }); + + // Set Window0 as active window + T::REGS.wwdtctl1().write(|w| { + w.set_winsel(vals::Winsel::WIN0); + w.set_key(vals::Wwdtctl1Key::KEY); + }); + + critical_section::with(|_| { + // make sure watchdog triggers BOOTRST + pac::SYSCTL.systemcfg().write(|w| { + if T::REGS == pac::WWDT0 { + w.set_wwdtlp0rstdis(false); + } + + #[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))] + if T::REGS == pac::WWDT1 { + w.set_wwdtlp1rstdis(false); + } + }); + }); + + Watchdog { wdt: PhantomData } + } + + /// Pet (reload, refresh) the watchdog. + pub fn pet(&mut self) { + T::REGS.wwdtcntrst().write(|w| { + w.set_restart(vals::WwdtcntrstRestart::RESTART); + }); + } +} + +pub(crate) trait SealedInstance { + const REGS: Regs; +} + +/// WWDT instance trait +#[allow(private_bounds)] +pub trait Instance: SealedInstance + PeripheralType {} + +macro_rules! impl_wwdt_instance { + ($instance: ident) => { + impl crate::wwdt::SealedInstance for crate::peripherals::$instance { + const REGS: crate::pac::wwdt::Wwdt = crate::pac::$instance; + } + + impl crate::wwdt::Instance for crate::peripherals::$instance {} + }; +} diff --git a/examples/mspm0c1104/src/bin/wwdt.rs b/examples/mspm0c1104/src/bin/wwdt.rs index 4aa3caca9..2859ccd5e 100644 --- a/examples/mspm0c1104/src/bin/wwdt.rs +++ b/examples/mspm0c1104/src/bin/wwdt.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_mspm0::gpio::{Level, Output}; -use embassy_mspm0::watchdog::{ClosedWindowPercentage, Config, Timeout, Watchdog}; +use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog}; use embassy_time::Timer; use {defmt_rtt as _, panic_halt as _}; diff --git a/examples/mspm0g3507/src/bin/wwdt.rs b/examples/mspm0g3507/src/bin/wwdt.rs index 6d3240ff7..d10451448 100644 --- a/examples/mspm0g3507/src/bin/wwdt.rs +++ b/examples/mspm0g3507/src/bin/wwdt.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_mspm0::gpio::{Level, Output}; -use embassy_mspm0::watchdog::{ClosedWindowPercentage, Config, Timeout, Watchdog}; +use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog}; use embassy_time::Timer; use {defmt_rtt as _, panic_halt as _}; diff --git a/examples/mspm0g3519/src/bin/wwdt.rs b/examples/mspm0g3519/src/bin/wwdt.rs index dee941274..fede95fa2 100644 --- a/examples/mspm0g3519/src/bin/wwdt.rs +++ b/examples/mspm0g3519/src/bin/wwdt.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_mspm0::gpio::{Level, Output}; -use embassy_mspm0::watchdog::{ClosedWindowPercentage, Config, Timeout, Watchdog}; +use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog}; use embassy_time::Timer; use {defmt_rtt as _, panic_halt as _}; diff --git a/examples/mspm0l1306/src/bin/wwdt.rs b/examples/mspm0l1306/src/bin/wwdt.rs index f2bbe5701..b8fb1a1cd 100644 --- a/examples/mspm0l1306/src/bin/wwdt.rs +++ b/examples/mspm0l1306/src/bin/wwdt.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_mspm0::gpio::{Level, Output}; -use embassy_mspm0::watchdog::{ClosedWindowPercentage, Config, Timeout, Watchdog}; +use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog}; use embassy_time::Timer; use {defmt_rtt as _, panic_halt as _}; diff --git a/examples/mspm0l2228/src/bin/wwdt.rs b/examples/mspm0l2228/src/bin/wwdt.rs index 6fd18247a..487d09820 100644 --- a/examples/mspm0l2228/src/bin/wwdt.rs +++ b/examples/mspm0l2228/src/bin/wwdt.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_mspm0::gpio::{Level, Output}; -use embassy_mspm0::watchdog::{ClosedWindowPercentage, Config, Timeout, Watchdog}; +use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog}; use embassy_time::Timer; use {defmt_rtt as _, panic_halt as _}; -- cgit From b618b6bfcdb42263639e8b348838b764a9ef7a04 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Wed, 27 Aug 2025 12:08:18 +0200 Subject: mspm0-watchdog: remove template from watchdog struct --- embassy-mspm0/src/wwdt.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/embassy-mspm0/src/wwdt.rs b/embassy-mspm0/src/wwdt.rs index 9864b3d94..38d76ed56 100644 --- a/embassy-mspm0/src/wwdt.rs +++ b/embassy-mspm0/src/wwdt.rs @@ -4,8 +4,6 @@ #![macro_use] -use core::marker::PhantomData; - use embassy_hal_internal::PeripheralType; use crate::pac::wwdt::{vals, Wwdt as Regs}; @@ -262,22 +260,22 @@ impl Default for Config { } } -pub struct Watchdog<'d, T: Instance> { - wdt: PhantomData<&'d mut T>, +pub struct Watchdog { + regs: &'static Regs, } -impl<'d, T: Instance> Watchdog<'d, T> { +impl Watchdog { /// Watchdog initialization. - pub fn new(_instance: Peri<'d, T>, config: Config) -> Self { + pub fn new(_instance: Peri, config: Config) -> Self { // Init power for watchdog - T::REGS.gprcm(0).rstctl().write(|w| { + T::regs().gprcm(0).rstctl().write(|w| { w.set_resetstkyclr(true); w.set_resetassert(true); w.set_key(vals::ResetKey::KEY); }); // Enable power for watchdog - T::REGS.gprcm(0).pwren().write(|w| { + T::regs().gprcm(0).pwren().write(|w| { w.set_enable(true); w.set_key(vals::PwrenKey::KEY); }); @@ -286,7 +284,7 @@ impl<'d, T: Instance> Watchdog<'d, T> { cortex_m::asm::delay(16); //init watchdog - T::REGS.wwdtctl0().write(|w| { + T::regs().wwdtctl0().write(|w| { w.set_clkdiv(config.timeout.get_clkdiv()); w.set_per(config.timeout.get_period()); w.set_mode(vals::Mode::WINDOW); @@ -296,7 +294,7 @@ impl<'d, T: Instance> Watchdog<'d, T> { }); // Set Window0 as active window - T::REGS.wwdtctl1().write(|w| { + T::regs().wwdtctl1().write(|w| { w.set_winsel(vals::Winsel::WIN0); w.set_key(vals::Wwdtctl1Key::KEY); }); @@ -304,30 +302,30 @@ impl<'d, T: Instance> Watchdog<'d, T> { critical_section::with(|_| { // make sure watchdog triggers BOOTRST pac::SYSCTL.systemcfg().write(|w| { - if T::REGS == pac::WWDT0 { + if *T::regs() == pac::WWDT0 { w.set_wwdtlp0rstdis(false); } #[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))] - if T::REGS == pac::WWDT1 { + if *T::regs() == pac::WWDT1 { w.set_wwdtlp1rstdis(false); } }); }); - Watchdog { wdt: PhantomData } + Self { regs: T::regs() } } /// Pet (reload, refresh) the watchdog. pub fn pet(&mut self) { - T::REGS.wwdtcntrst().write(|w| { + self.regs.wwdtcntrst().write(|w| { w.set_restart(vals::WwdtcntrstRestart::RESTART); }); } } pub(crate) trait SealedInstance { - const REGS: Regs; + fn regs() -> &'static Regs; } /// WWDT instance trait @@ -337,7 +335,9 @@ pub trait Instance: SealedInstance + PeripheralType {} macro_rules! impl_wwdt_instance { ($instance: ident) => { impl crate::wwdt::SealedInstance for crate::peripherals::$instance { - const REGS: crate::pac::wwdt::Wwdt = crate::pac::$instance; + fn regs() -> &'static crate::pac::wwdt::Wwdt { + &crate::pac::$instance + } } impl crate::wwdt::Instance for crate::peripherals::$instance {} -- cgit From 0a45a4663c1ced10c96e38efe7ebd1aa9b9e2130 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Thu, 28 Aug 2025 10:14:43 +0200 Subject: msmp0-watchdog: reorder system initialization --- embassy-mspm0/src/wwdt.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/embassy-mspm0/src/wwdt.rs b/embassy-mspm0/src/wwdt.rs index 38d76ed56..e5c62c660 100644 --- a/embassy-mspm0/src/wwdt.rs +++ b/embassy-mspm0/src/wwdt.rs @@ -283,6 +283,20 @@ impl Watchdog { // init delay, 16 cycles cortex_m::asm::delay(16); + critical_section::with(|_| { + // make sure watchdog triggers BOOTRST + pac::SYSCTL.systemcfg().modify(|w| { + if *T::regs() == pac::WWDT0 { + w.set_wwdtlp0rstdis(false); + } + + #[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))] + if *T::regs() == pac::WWDT1 { + w.set_wwdtlp1rstdis(false); + } + }); + }); + //init watchdog T::regs().wwdtctl0().write(|w| { w.set_clkdiv(config.timeout.get_clkdiv()); @@ -299,20 +313,6 @@ impl Watchdog { w.set_key(vals::Wwdtctl1Key::KEY); }); - critical_section::with(|_| { - // make sure watchdog triggers BOOTRST - pac::SYSCTL.systemcfg().write(|w| { - if *T::regs() == pac::WWDT0 { - w.set_wwdtlp0rstdis(false); - } - - #[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))] - if *T::regs() == pac::WWDT1 { - w.set_wwdtlp1rstdis(false); - } - }); - }); - Self { regs: T::regs() } } -- cgit From cdb2354418a3ef7eda64d364e61c0ce9da437f15 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Thu, 21 Aug 2025 11:44:30 +0200 Subject: msmp0-watchdog: reflect changes in CHANGELOG.md --- embassy-mspm0/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-mspm0/CHANGELOG.md b/embassy-mspm0/CHANGELOG.md index cf8aeb046..5585fd261 100644 --- a/embassy-mspm0/CHANGELOG.md +++ b/embassy-mspm0/CHANGELOG.md @@ -9,3 +9,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - feat: Add I2C Controller (blocking & async) + examples for mspm0l1306, mspm0g3507 (tested MCUs) (#4435) - fix gpio interrupt not being set for mspm0l110x +- feat: Add window watchdog implementation based on WWDT0, WWDT1 peripherals (#4574) -- cgit From 9245a3a99189e5b155f1c36b6a1cefdc60edd63d Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Thu, 28 Aug 2025 12:23:39 +0200 Subject: chore: prepare cyw43 0.5.0 --- cyw43/CHANGELOG.md | 6 +++++- cyw43/Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cyw43/CHANGELOG.md b/cyw43/CHANGELOG.md index 2f54d6988..be7212afd 100644 --- a/cyw43/CHANGELOG.md +++ b/cyw43/CHANGELOG.md @@ -8,7 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate -## 0.4.1 - 2025-08-26 +## 0.5.0 - 2025-08-28 + +- bump bt-hci to 0.4.0 + +## 0.4.1 - 2025-08-26 (yanked) - bump bt-hci to 0.4.0 diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index aa054a41d..4d3a43733 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cyw43" -version = "0.4.1" +version = "0.5.0" edition = "2021" description = "Rust driver for the CYW43439 WiFi chip, used in the Raspberry Pi Pico W." keywords = ["embedded", "cyw43", "embassy-net", "embedded-hal-async", "wifi"] -- cgit From a527905be4a4e44aac5fb2aed70a1f0f5b18d0ed Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Thu, 28 Aug 2025 12:25:43 +0200 Subject: fix: version bumps --- cyw43-pio/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index d7dd21453..97acf8bd3 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/embassy-rs/embassy" documentation = "https://docs.embassy.dev/cyw43-pio" [dependencies] -cyw43 = { version = "0.4.0", path = "../cyw43" } +cyw43 = { version = "0.5.0", path = "../cyw43" } embassy-rp = { version = "0.8.0", path = "../embassy-rp" } fixed = "1.23.1" defmt = { version = "1.0.1", optional = true } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index a5b192e0a..9c43223d5 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -17,7 +17,7 @@ embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defm embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } -cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } +cyw43 = { version = "0.5.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { version = "0.7.0", path = "../../cyw43-pio", features = ["defmt"] } defmt = "1.0.1" diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index 6418f1915..e62903d3c 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -17,7 +17,7 @@ embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defm embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } -cyw43 = { version = "0.4.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } +cyw43 = { version = "0.5.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } cyw43-pio = { version = "0.7.0", path = "../../cyw43-pio", features = ["defmt"] } defmt = "1.0.1" -- cgit From 1f945bcebd3b0018b3b5541ede767583df3545d8 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Thu, 28 Aug 2025 12:27:14 +0200 Subject: chore: prepare cyw43-pio release --- cyw43-pio/CHANGELOG.md | 4 ++++ cyw43-pio/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/rp235x/Cargo.toml | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cyw43-pio/CHANGELOG.md b/cyw43-pio/CHANGELOG.md index 9b76f601d..ec38989e3 100644 --- a/cyw43-pio/CHANGELOG.md +++ b/cyw43-pio/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +## 0.8.0 - 2025-08-28 + +- Bump cyw43 version + ## 0.7.0 - 2025-08-26 ## 0.6.0 - 2025-08-04 diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index 97acf8bd3..40dd02f61 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cyw43-pio" -version = "0.7.0" +version = "0.8.0" edition = "2021" description = "RP2040 PIO SPI implementation for cyw43" keywords = ["embedded", "cyw43", "embassy-net", "embedded-hal-async", "wifi"] diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 9c43223d5..97e019cdf 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -18,7 +18,7 @@ embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", fea embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } cyw43 = { version = "0.5.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } -cyw43-pio = { version = "0.7.0", path = "../../cyw43-pio", features = ["defmt"] } +cyw43-pio = { version = "0.8.0", path = "../../cyw43-pio", features = ["defmt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml index e62903d3c..40fbb5798 100644 --- a/examples/rp235x/Cargo.toml +++ b/examples/rp235x/Cargo.toml @@ -18,7 +18,7 @@ embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", fea embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } cyw43 = { version = "0.5.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } -cyw43-pio = { version = "0.7.0", path = "../../cyw43-pio", features = ["defmt"] } +cyw43-pio = { version = "0.8.0", path = "../../cyw43-pio", features = ["defmt"] } defmt = "1.0.1" defmt-rtt = "1.0.0" -- cgit From fcf659fbe5c0cd6acf328281089c35c999f5514a Mon Sep 17 00:00:00 2001 From: Matthew Tran <0e4ef622@gmail.com> Date: Thu, 28 Aug 2025 10:35:27 -0500 Subject: embassy-sync: Don't drop wakers in Signal::reset --- embassy-sync/CHANGELOG.md | 1 + embassy-sync/src/signal.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/embassy-sync/CHANGELOG.md b/embassy-sync/CHANGELOG.md index 593396586..a53d5f5b1 100644 --- a/embassy-sync/CHANGELOG.md +++ b/embassy-sync/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- Fix wakers getting dropped by `Signal::reset` ## 0.7.2 - 2025-08-26 diff --git a/embassy-sync/src/signal.rs b/embassy-sync/src/signal.rs index d96e36245..229b1fa99 100644 --- a/embassy-sync/src/signal.rs +++ b/embassy-sync/src/signal.rs @@ -83,7 +83,7 @@ where /// Remove the queued value in this `Signal`, if any. pub fn reset(&self) { - self.state.lock(|cell| cell.set(State::None)); + self.try_take(); } fn poll_wait(&self, cx: &mut Context<'_>) -> Poll { -- cgit From 338227c21abea9621887ed428c2272d7bdeeafdd Mon Sep 17 00:00:00 2001 From: i509VCB Date: Thu, 28 Aug 2025 15:00:46 -0500 Subject: mspm0: add mspm0c1105/6 --- ci.sh | 25 +++++++++++++------------ embassy-mspm0/CHANGELOG.md | 3 ++- embassy-mspm0/Cargo.toml | 22 ++++++++++++++++++++-- embassy-mspm0/build.rs | 8 +++++++- embassy-mspm0/src/gpio.rs | 14 ++++++++++---- embassy-mspm0/src/i2c.rs | 2 +- 6 files changed, 53 insertions(+), 21 deletions(-) diff --git a/ci.sh b/ci.sh index 94bf83675..2361759b6 100755 --- a/ci.sh +++ b/ci.sh @@ -190,18 +190,19 @@ cargo batch \ --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv8m.main-none-eabihf --features lpc55,defmt \ --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv7em-none-eabihf --features mimxrt1011,rt,defmt,time-driver-pit \ --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv7em-none-eabihf --features mimxrt1062,rt,defmt,time-driver-pit \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0c1104dgs20,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3507pm,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3519pz,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1306rhb,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l2228pn,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1345dgs28,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1106dgs28,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1228pm,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1107ycj,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3105rhb,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1505pt,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1519rhb,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0c1104dgs20,rt,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0c1106rgz,rt,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3507pm,rt,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3519pz,rt,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1306rhb,rt,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l2228pn,rt,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1345dgs28,rt,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1106dgs28,rt,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1228pm,rt,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1107ycj,rt,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3105rhb,rt,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1505pt,rt,defmt,time-driver-any \ + --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1519rhb,rt,defmt,time-driver-any \ --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features ''\ --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log' \ --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt' \ diff --git a/embassy-mspm0/CHANGELOG.md b/embassy-mspm0/CHANGELOG.md index eca0defd7..c7da4eb33 100644 --- a/embassy-mspm0/CHANGELOG.md +++ b/embassy-mspm0/CHANGELOG.md @@ -7,7 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate - + - feat: Add I2C Controller (blocking & async) + examples for mspm0l1306, mspm0g3507 (tested MCUs) (#4435) - fix gpio interrupt not being set for mspm0l110x - feat: Add window watchdog implementation based on WWDT0, WWDT1 peripherals (#4574) +- feat: Add MSPM0C1105/C1106 support diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index 92f7a2655..1b32c4d43 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -69,7 +69,7 @@ cortex-m = "0.7.6" critical-section = "1.2.0" # mspm0-metapac = { version = "" } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-fe17d879548757ca29821da66a1bebf2debd4846" } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-d7bf3d01ac0780e716a45b0474234d39443dc5cf" } [build-dependencies] proc-macro2 = "1.0.94" @@ -77,7 +77,7 @@ quote = "1.0.40" cfg_aliases = "0.2.1" # mspm0-metapac = { version = "", default-features = false, features = ["metadata"] } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-fe17d879548757ca29821da66a1bebf2debd4846", default-features = false, features = ["metadata"] } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-d7bf3d01ac0780e716a45b0474234d39443dc5cf", default-features = false, features = ["metadata"] } [features] default = ["rt"] @@ -159,6 +159,24 @@ mspm0c1104dsg = ["mspm0-metapac/mspm0c1104dsg"] mspm0c1104dyy = ["mspm0-metapac/mspm0c1104dyy"] mspm0c1104ruk = ["mspm0-metapac/mspm0c1104ruk"] mspm0c1104ycj = ["mspm0-metapac/mspm0c1104ycj"] +mspm0c1105pt = ["mspm0-metapac/mspm0c1105pt"] +mspm0c1105rgz = ["mspm0-metapac/mspm0c1105rgz"] +mspm0c1105rhb = ["mspm0-metapac/mspm0c1105rhb"] +mspm0c1105dgs32 = ["mspm0-metapac/mspm0c1105dgs32"] +mspm0c1105dgs28 = ["mspm0-metapac/mspm0c1105dgs28"] +mspm0c1105rge = ["mspm0-metapac/mspm0c1105rge"] +mspm0c1105dgs20 = ["mspm0-metapac/mspm0c1105dgs20"] +mspm0c1105ruk = ["mspm0-metapac/mspm0c1105ruk"] +mspm0c1105zcm = ["mspm0-metapac/mspm0c1105zcm"] +mspm0c1106pt = ["mspm0-metapac/mspm0c1106pt"] +mspm0c1106rgz = ["mspm0-metapac/mspm0c1106rgz"] +mspm0c1106rhb = ["mspm0-metapac/mspm0c1106rhb"] +mspm0c1106dgs32 = ["mspm0-metapac/mspm0c1106dgs32"] +mspm0c1106dgs28 = ["mspm0-metapac/mspm0c1106dgs28"] +mspm0c1106rge = ["mspm0-metapac/mspm0c1106rge"] +mspm0c1106dgs20 = ["mspm0-metapac/mspm0c1106dgs20"] +mspm0c1106ruk = ["mspm0-metapac/mspm0c1106ruk"] +mspm0c1106zcm = ["mspm0-metapac/mspm0c1106zcm"] mspm0g1105dgs28 = ["mspm0-metapac/mspm0g1105dgs28"] mspm0g1105pm = ["mspm0-metapac/mspm0g1105pm"] mspm0g1105pt = ["mspm0-metapac/mspm0g1105pt"] diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs index 256192f8b..e8364e31a 100644 --- a/embassy-mspm0/build.rs +++ b/embassy-mspm0/build.rs @@ -79,10 +79,14 @@ fn get_chip_cfgs(chip_name: &str) -> Vec { let mut cfgs = Vec::new(); // GPIO on C110x is special as it does not belong to an interrupt group. - if chip_name.starts_with("mspm0c110") || chip_name.starts_with("msps003f") { + if chip_name.starts_with("mspm0c1103") || chip_name.starts_with("mspm0c1104") || chip_name.starts_with("msps003f") { cfgs.push("mspm0c110x".to_string()); } + if chip_name.starts_with("mspm0c1105") || chip_name.starts_with("mspm0c1106") { + cfgs.push("mspm0c1105_c1106".to_string()); + } + // Family ranges (temporary until int groups are generated) // // TODO: Remove this once int group stuff is generated. @@ -537,6 +541,8 @@ fn generate_interrupts() -> TokenStream { pub fn enable_group_interrupts(_cs: critical_section::CriticalSection) { use crate::interrupt::typelevel::Interrupt; + // This is empty for C1105/6 + #[allow(unused_unsafe)] unsafe { #(#group_interrupt_enables)* } diff --git a/embassy-mspm0/src/gpio.rs b/embassy-mspm0/src/gpio.rs index f77848888..d5fd36dbf 100644 --- a/embassy-mspm0/src/gpio.rs +++ b/embassy-mspm0/src/gpio.rs @@ -10,7 +10,7 @@ use embassy_sync::waitqueue::AtomicWaker; use crate::pac::gpio::vals::*; use crate::pac::gpio::{self}; -#[cfg(all(feature = "rt", any(mspm0c110x, mspm0l110x)))] +#[cfg(all(feature = "rt", any(mspm0c110x, mspm0c1105_c1106, mspm0l110x)))] use crate::pac::interrupt; use crate::pac::{self}; @@ -1108,24 +1108,30 @@ fn irq_handler(gpio: gpio::Gpio, wakers: &[AtomicWaker; 32]) { // C110x and L110x have a dedicated interrupts just for GPIOA. // // These chips do not have a GROUP1 interrupt. -#[cfg(all(feature = "rt", any(mspm0c110x, mspm0l110x)))] +#[cfg(all(feature = "rt", any(mspm0c110x, mspm0c1105_c1106, mspm0l110x)))] #[interrupt] fn GPIOA() { irq_handler(pac::GPIOA, &PORTA_WAKERS); } +#[cfg(all(feature = "rt", mspm0c1105_c1106))] +#[interrupt] +fn GPIOB() { + irq_handler(pac::GPIOB, &PORTB_WAKERS); +} + // These symbols are weakly defined as DefaultHandler and are called by the interrupt group implementation. // // Defining these as no_mangle is required so that the linker will pick these over the default handler. -#[cfg(all(feature = "rt", not(any(mspm0c110x, mspm0l110x))))] +#[cfg(all(feature = "rt", not(any(mspm0c110x, mspm0c1105_c1106, mspm0l110x))))] #[no_mangle] #[allow(non_snake_case)] fn GPIOA() { irq_handler(pac::GPIOA, &PORTA_WAKERS); } -#[cfg(all(feature = "rt", gpio_pb))] +#[cfg(all(feature = "rt", gpio_pb, not(mspm0c1105_c1106)))] #[no_mangle] #[allow(non_snake_case)] fn GPIOB() { diff --git a/embassy-mspm0/src/i2c.rs b/embassy-mspm0/src/i2c.rs index 7e22bb724..1906e37ba 100644 --- a/embassy-mspm0/src/i2c.rs +++ b/embassy-mspm0/src/i2c.rs @@ -195,7 +195,7 @@ impl Config { .unwrap(); } - #[cfg(any(mspm0c110x))] + #[cfg(any(mspm0c110x, mspm0c1105_c1106))] fn calculate_clock_source(&self) -> u32 { // Assume that BusClk has default value. // TODO: calculate BusClk more precisely. -- cgit From 13fc222ef45e16980aca221044ae41d106065ce1 Mon Sep 17 00:00:00 2001 From: Rogan Morrow Date: Fri, 29 Aug 2025 16:08:50 +1000 Subject: set XSPI clock source to HSI and reset after clock init; dont reset SYSCFG --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/src/lib.rs | 2 +- embassy-stm32/src/rcc/h.rs | 19 ++++++++++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index dd82613d9..bf451da79 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - chore: Updated stm32-metapac and stm32-data dependencies - feat: stm32/adc/v3: allow DMA reads to loop through enable channels - fix: Fix XSPI not disabling alternate bytes when they were previously enabled +- fix: Fix stm32h7rs init when using external flash via XSPI ## 0.3.0 - 2025-08-12 diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index e4a8ff0ab..3be98c462 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -526,7 +526,7 @@ fn init_hw(config: Config) -> Peripherals { } }); - #[cfg(not(any(stm32f1, stm32wb, stm32wl)))] + #[cfg(not(any(stm32f1, stm32wb, stm32wl, stm32h7rs)))] rcc::enable_and_reset_with_cs::(cs); #[cfg(not(any(stm32h5, stm32h7, stm32h7rs, stm32wb, stm32wl)))] rcc::enable_and_reset_with_cs::(cs); diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index 837210b6a..331db1968 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs @@ -1,7 +1,7 @@ use core::ops::RangeInclusive; #[cfg(stm32h7rs)] -use stm32_metapac::rcc::vals::Plldivst; +use stm32_metapac::rcc::vals::{Plldivst, Xspisel}; use crate::pac; pub use crate::pac::rcc::vals::{ @@ -430,6 +430,16 @@ pub(crate) unsafe fn init(config: Config) { } while !RCC.cr().read().hsirdy() {} + #[cfg(stm32h7rs)] + let (xspi1sel, xspi2sel) = { + // Save XSPI clock source settings and switch the clock source so it will use HSI + let xspi1sel = RCC.ahbperckselr().read().xspi1sel(); + let xspi2sel = RCC.ahbperckselr().read().xspi2sel(); + RCC.ahbperckselr().modify(|w| w.set_xspi1sel(Xspisel::HCLK5)); + RCC.ahbperckselr().modify(|w| w.set_xspi2sel(Xspisel::HCLK5)); + (xspi1sel, xspi2sel) + }; + // Use the HSI clock as system clock during the actual clock setup RCC.cfgr().modify(|w| w.set_sw(Sysclk::HSI)); while RCC.cfgr().read().sws() != Sysclk::HSI {} @@ -678,6 +688,13 @@ pub(crate) unsafe fn init(config: Config) { config.mux.init(); + #[cfg(stm32h7rs)] + { + // Set the XSPI clock source back to what it was originally + RCC.ahbperckselr().modify(|w| w.set_xspi1sel(xspi1sel)); + RCC.ahbperckselr().modify(|w| w.set_xspi2sel(xspi2sel)); + } + set_clocks!( sys: Some(sys), hclk1: Some(hclk), -- cgit From 5fb4bbfc3e954bca5eba334dbd9224469d8984b4 Mon Sep 17 00:00:00 2001 From: Rogan Morrow Date: Fri, 29 Aug 2025 17:51:52 +1000 Subject: don't save and reset XSPI clock source; let mux config handle it --- embassy-stm32/src/rcc/h.rs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index 331db1968..331bab7a0 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs @@ -431,13 +431,10 @@ pub(crate) unsafe fn init(config: Config) { while !RCC.cr().read().hsirdy() {} #[cfg(stm32h7rs)] - let (xspi1sel, xspi2sel) = { - // Save XSPI clock source settings and switch the clock source so it will use HSI - let xspi1sel = RCC.ahbperckselr().read().xspi1sel(); - let xspi2sel = RCC.ahbperckselr().read().xspi2sel(); + { + // Switch the XSPI clock source so it will use HSI RCC.ahbperckselr().modify(|w| w.set_xspi1sel(Xspisel::HCLK5)); RCC.ahbperckselr().modify(|w| w.set_xspi2sel(Xspisel::HCLK5)); - (xspi1sel, xspi2sel) }; // Use the HSI clock as system clock during the actual clock setup @@ -688,13 +685,6 @@ pub(crate) unsafe fn init(config: Config) { config.mux.init(); - #[cfg(stm32h7rs)] - { - // Set the XSPI clock source back to what it was originally - RCC.ahbperckselr().modify(|w| w.set_xspi1sel(xspi1sel)); - RCC.ahbperckselr().modify(|w| w.set_xspi2sel(xspi2sel)); - } - set_clocks!( sys: Some(sys), hclk1: Some(hclk), -- cgit From 658a52fb99e47d3d2f08ebf66335774930ad35ac Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 8 Jul 2025 23:29:31 +0200 Subject: executor: do not store task IDs in RAM, we can get it from the pointer every time. --- ci.sh | 2 ++ embassy-executor/src/metadata.rs | 1 + embassy-executor/src/raw/mod.rs | 10 ++++++---- embassy-executor/src/raw/trace.rs | 17 ----------------- embassy-executor/src/spawner.rs | 10 ++++------ 5 files changed, 13 insertions(+), 27 deletions(-) create mode 100644 embassy-executor/src/metadata.rs diff --git a/ci.sh b/ci.sh index 94bf83675..4934c6d8e 100755 --- a/ci.sh +++ b/ci.sh @@ -31,7 +31,9 @@ cargo batch \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt,arch-cortex-m,executor-thread,executor-interrupt \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,trace \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,rtos-trace \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,trace,rtos-trace \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread,executor-interrupt \ diff --git a/embassy-executor/src/metadata.rs b/embassy-executor/src/metadata.rs new file mode 100644 index 000000000..957417f6b --- /dev/null +++ b/embassy-executor/src/metadata.rs @@ -0,0 +1 @@ +pub struct Metadata {} diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 4b17d4982..bcd4ee432 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -97,8 +97,6 @@ pub(crate) struct TaskHeader { #[cfg(feature = "trace")] pub(crate) name: Option<&'static str>, #[cfg(feature = "trace")] - pub(crate) id: u32, - #[cfg(feature = "trace")] all_tasks_next: AtomicPtr, } @@ -148,6 +146,12 @@ impl TaskRef { pub(crate) fn as_ptr(self) -> *const TaskHeader { self.ptr.as_ptr() } + + /// Returns the task ID. + /// This can be used in combination with rtos-trace to match task names with IDs + pub fn id(&self) -> u32 { + self.as_ptr() as u32 + } } /// Raw storage in which a task can be spawned. @@ -192,8 +196,6 @@ impl TaskStorage { #[cfg(feature = "trace")] name: None, #[cfg(feature = "trace")] - id: 0, - #[cfg(feature = "trace")] all_tasks_next: AtomicPtr::new(core::ptr::null_mut()), }, future: UninitCell::uninit(), diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index f484abf58..e769d63da 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -176,12 +176,6 @@ pub trait TaskRefTrace { /// Set the name for a task fn set_name(&self, name: Option<&'static str>); - - /// Get the ID for a task - fn id(&self) -> u32; - - /// Set the ID for a task - fn set_id(&self, id: u32); } impl TaskRefTrace for TaskRef { @@ -195,17 +189,6 @@ impl TaskRefTrace for TaskRef { (*header_ptr).name = name; } } - - fn id(&self) -> u32 { - self.header().id - } - - fn set_id(&self, id: u32) { - unsafe { - let header_ptr = self.ptr.as_ptr() as *mut TaskHeader; - (*header_ptr).id = id; - } - } } #[cfg(not(feature = "rtos-trace"))] diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index 2909d19a0..7550e8ea4 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -36,12 +36,12 @@ impl SpawnToken { } } - /// Returns the task id if available, otherwise 0 - /// This can be used in combination with rtos-trace to match task names with id's + /// Returns the task ID if available, otherwise 0 + /// This can be used in combination with rtos-trace to match task names with IDs pub fn id(&self) -> u32 { match self.raw_task { None => 0, - Some(t) => t.as_ptr() as u32, + Some(t) => t.id(), } } @@ -223,10 +223,8 @@ impl SpawnerTraceExt for Spawner { match task { Some(task) => { - // Set the name and ID when trace is enabled + // Set the name when trace is enabled task.set_name(Some(name)); - let task_id = task.as_ptr() as u32; - task.set_id(task_id); unsafe { self.executor.spawn(task) }; Ok(()) -- cgit From 2ba34ce2178d576f339f0b0dac70ac125f81cc5b Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 8 Jul 2025 23:36:51 +0200 Subject: executor: allow trace and rtos-trace to coexist additively. Before, enabling `trace` would enable embassy-native tracing, and enabling *both* would *disable* embassy-native tracing. --- embassy-executor/Cargo.toml | 23 ++++++++++++++++++++--- embassy-executor/src/raw/mod.rs | 26 +++++++++++++------------- embassy-executor/src/raw/trace.rs | 25 +++++++++++++++---------- 3 files changed, 48 insertions(+), 26 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index d89e85cb7..a36a61885 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -115,7 +115,24 @@ arch-spin = ["_arch"] executor-thread = [] ## Enable the interrupt-mode executor (available in Cortex-M only) executor-interrupt = [] -## Enable tracing support (adds some overhead) -trace = [] +## Enable tracing hooks +trace = ["_any_trace"] ## Enable support for rtos-trace framework -rtos-trace = ["dep:rtos-trace", "trace", "dep:embassy-time-driver"] +rtos-trace = ["dep:rtos-trace", "_any_trace", "dep:embassy-time-driver"] +_any_trace = [] + +#! ### Timer Item Payload Size +#! Sets the size of the payload for timer items, allowing integrated timer implementors to store +#! additional data in the timer item. The payload field will be aligned to this value as well. +#! If these features are not defined, the timer item will contain no payload field. + +_timer-item-payload = [] # A size was picked + +## 1 bytes +timer-item-payload-size-1 = ["_timer-item-payload"] +## 2 bytes +timer-item-payload-size-2 = ["_timer-item-payload"] +## 4 bytes +timer-item-payload-size-4 = ["_timer-item-payload"] +## 8 bytes +timer-item-payload-size-8 = ["_timer-item-payload"] diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index bcd4ee432..87328df5a 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -16,7 +16,7 @@ mod run_queue; #[cfg_attr(not(target_has_atomic = "8"), path = "state_critical_section.rs")] mod state; -#[cfg(feature = "trace")] +#[cfg(feature = "_any_trace")] pub mod trace; pub(crate) mod util; #[cfg_attr(feature = "turbowakers", path = "waker_turbo.rs")] @@ -94,9 +94,9 @@ pub(crate) struct TaskHeader { /// Integrated timer queue storage. This field should not be accessed outside of the timer queue. pub(crate) timer_queue_item: TimerQueueItem, - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] pub(crate) name: Option<&'static str>, - #[cfg(feature = "trace")] + #[cfg(feature = "rtos-trace")] all_tasks_next: AtomicPtr, } @@ -193,9 +193,9 @@ impl TaskStorage { poll_fn: SyncUnsafeCell::new(None), timer_queue_item: TimerQueueItem::new(), - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] name: None, - #[cfg(feature = "trace")] + #[cfg(feature = "rtos-trace")] all_tasks_next: AtomicPtr::new(core::ptr::null_mut()), }, future: UninitCell::uninit(), @@ -231,7 +231,7 @@ impl TaskStorage { let mut cx = Context::from_waker(&waker); match future.poll(&mut cx) { Poll::Ready(_) => { - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] let exec_ptr: *const SyncExecutor = this.raw.executor.load(Ordering::Relaxed); // As the future has finished and this function will not be called @@ -246,7 +246,7 @@ impl TaskStorage { // after we're done with it. this.raw.state.despawn(); - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] trace::task_end(exec_ptr, &p); } Poll::Pending => {} @@ -419,7 +419,7 @@ impl SyncExecutor { /// - `task` must NOT be already enqueued (in this executor or another one). #[inline(always)] unsafe fn enqueue(&self, task: TaskRef, l: state::Token) { - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] trace::task_ready_begin(self, &task); if self.run_queue.enqueue(task, l) { @@ -432,7 +432,7 @@ impl SyncExecutor { .executor .store((self as *const Self).cast_mut(), Ordering::Relaxed); - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] trace::task_new(self, &task); state::locked(|l| { @@ -444,23 +444,23 @@ impl SyncExecutor { /// /// Same as [`Executor::poll`], plus you must only call this on the thread this executor was created. pub(crate) unsafe fn poll(&'static self) { - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] trace::poll_start(self); self.run_queue.dequeue_all(|p| { let task = p.header(); - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] trace::task_exec_begin(self, &p); // Run the task task.poll_fn.get().unwrap_unchecked()(p); - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] trace::task_exec_end(self, &p); }); - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] trace::executor_idle(self) } } diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index e769d63da..636608d02 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -95,17 +95,20 @@ use crate::spawner::{SpawnError, SpawnToken, Spawner}; /// This static provides access to the global task tracker which maintains /// a list of all tasks in the system. It's automatically updated by the /// task lifecycle hooks in the trace module. -pub static TASK_TRACKER: TaskTracker = TaskTracker::new(); +#[cfg(feature = "rtos-trace")] +pub(crate) static TASK_TRACKER: TaskTracker = TaskTracker::new(); /// A thread-safe tracker for all tasks in the system /// /// This struct uses an intrusive linked list approach to track all tasks /// without additional memory allocations. It maintains a global list of /// tasks that can be traversed to find all currently existing tasks. -pub struct TaskTracker { +#[cfg(feature = "rtos-trace")] +pub(crate) struct TaskTracker { head: AtomicPtr, } +#[cfg(feature = "rtos-trace")] impl TaskTracker { /// Creates a new empty task tracker /// @@ -191,7 +194,7 @@ impl TaskRefTrace for TaskRef { } } -#[cfg(not(feature = "rtos-trace"))] +#[cfg(feature = "trace")] extern "Rust" { /// This callback is called when the executor begins polling. This will always /// be paired with a later call to `_embassy_trace_executor_idle`. @@ -253,7 +256,7 @@ extern "Rust" { #[inline] pub(crate) fn poll_start(executor: &SyncExecutor) { - #[cfg(not(feature = "rtos-trace"))] + #[cfg(feature = "trace")] unsafe { _embassy_trace_poll_start(executor as *const _ as u32) } @@ -261,7 +264,7 @@ pub(crate) fn poll_start(executor: &SyncExecutor) { #[inline] pub(crate) fn task_new(executor: &SyncExecutor, task: &TaskRef) { - #[cfg(not(feature = "rtos-trace"))] + #[cfg(feature = "trace")] unsafe { _embassy_trace_task_new(executor as *const _ as u32, task.as_ptr() as u32) } @@ -285,7 +288,7 @@ pub(crate) fn task_new(executor: &SyncExecutor, task: &TaskRef) { #[inline] pub(crate) fn task_end(executor: *const SyncExecutor, task: &TaskRef) { - #[cfg(not(feature = "rtos-trace"))] + #[cfg(feature = "trace")] unsafe { _embassy_trace_task_end(executor as u32, task.as_ptr() as u32) } @@ -293,7 +296,7 @@ pub(crate) fn task_end(executor: *const SyncExecutor, task: &TaskRef) { #[inline] pub(crate) fn task_ready_begin(executor: &SyncExecutor, task: &TaskRef) { - #[cfg(not(feature = "rtos-trace"))] + #[cfg(feature = "trace")] unsafe { _embassy_trace_task_ready_begin(executor as *const _ as u32, task.as_ptr() as u32) } @@ -303,7 +306,7 @@ pub(crate) fn task_ready_begin(executor: &SyncExecutor, task: &TaskRef) { #[inline] pub(crate) fn task_exec_begin(executor: &SyncExecutor, task: &TaskRef) { - #[cfg(not(feature = "rtos-trace"))] + #[cfg(feature = "trace")] unsafe { _embassy_trace_task_exec_begin(executor as *const _ as u32, task.as_ptr() as u32) } @@ -313,7 +316,7 @@ pub(crate) fn task_exec_begin(executor: &SyncExecutor, task: &TaskRef) { #[inline] pub(crate) fn task_exec_end(executor: &SyncExecutor, task: &TaskRef) { - #[cfg(not(feature = "rtos-trace"))] + #[cfg(feature = "trace")] unsafe { _embassy_trace_task_exec_end(executor as *const _ as u32, task.as_ptr() as u32) } @@ -323,7 +326,7 @@ pub(crate) fn task_exec_end(executor: &SyncExecutor, task: &TaskRef) { #[inline] pub(crate) fn executor_idle(executor: &SyncExecutor) { - #[cfg(not(feature = "rtos-trace"))] + #[cfg(feature = "trace")] unsafe { _embassy_trace_executor_idle(executor as *const _ as u32) } @@ -339,6 +342,7 @@ pub(crate) fn executor_idle(executor: &SyncExecutor) { /// /// # Returns /// An iterator that yields `TaskRef` items for each task +#[cfg(feature = "rtos-trace")] fn get_all_active_tasks() -> impl Iterator + 'static { struct TaskIterator<'a> { tracker: &'a TaskTracker, @@ -367,6 +371,7 @@ fn get_all_active_tasks() -> impl Iterator + 'static { } /// Perform an action on each active task +#[cfg(feature = "rtos-trace")] fn with_all_active_tasks(f: F) where F: FnMut(TaskRef), -- cgit From da9cdf0c536ec4fa7bdfb649750c44f70ef1cd55 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 9 Jul 2025 01:18:04 +0200 Subject: executor: add "task metadata" concept, make name a task metadata. --- .github/ci/test.sh | 2 +- ci.sh | 1 + embassy-executor/Cargo.toml | 7 ++++- embassy-executor/src/lib.rs | 3 ++ embassy-executor/src/metadata.rs | 56 ++++++++++++++++++++++++++++++++- embassy-executor/src/raw/mod.rs | 14 ++++++--- embassy-executor/src/raw/trace.rs | 29 +---------------- embassy-executor/src/spawner.rs | 66 ++++++++------------------------------- embassy-executor/tests/test.rs | 31 ++++++++++++++++++ 9 files changed, 121 insertions(+), 88 deletions(-) diff --git a/.github/ci/test.sh b/.github/ci/test.sh index c9b332cf8..33dfa48c9 100755 --- a/.github/ci/test.sh +++ b/.github/ci/test.sh @@ -12,7 +12,7 @@ export CARGO_TARGET_DIR=/ci/cache/target # used when pointing stm32-metapac to a CI-built one. export CARGO_NET_GIT_FETCH_WITH_CLI=true -cargo test --manifest-path ./embassy-executor/Cargo.toml +cargo test --manifest-path ./embassy-executor/Cargo.toml --features metadata-name cargo test --manifest-path ./embassy-futures/Cargo.toml cargo test --manifest-path ./embassy-sync/Cargo.toml cargo test --manifest-path ./embassy-embedded-hal/Cargo.toml diff --git a/ci.sh b/ci.sh index 4934c6d8e..a585a3ab8 100755 --- a/ci.sh +++ b/ci.sh @@ -31,6 +31,7 @@ cargo batch \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt,arch-cortex-m,executor-thread,executor-interrupt \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,metadata-name \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,trace \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,rtos-trace \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,trace,rtos-trace \ diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index a36a61885..79680ae74 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -109,6 +109,11 @@ arch-avr = ["_arch", "dep:portable-atomic", "dep:avr-device"] ## spin (architecture agnostic; never sleeps) arch-spin = ["_arch"] +#! ### Metadata + +## Enable the `name` field in task metadata. +metadata-name = [] + #! ### Executor ## Enable the thread-mode executor (using WFE/SEV in Cortex-M, WFI in other embedded archs) @@ -118,7 +123,7 @@ executor-interrupt = [] ## Enable tracing hooks trace = ["_any_trace"] ## Enable support for rtos-trace framework -rtos-trace = ["dep:rtos-trace", "_any_trace", "dep:embassy-time-driver"] +rtos-trace = ["_any_trace", "metadata-name", "dep:rtos-trace", "dep:embassy-time-driver"] _any_trace = [] #! ### Timer Item Payload Size diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index 0747db032..e47b8eb9f 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -54,6 +54,9 @@ pub mod raw; mod spawner; pub use spawner::*; +mod metadata; +pub use metadata::*; + /// Implementation details for embassy macros. /// Do not use. Used for macros and HALs only. Not covered by semver guarantees. #[doc(hidden)] diff --git a/embassy-executor/src/metadata.rs b/embassy-executor/src/metadata.rs index 957417f6b..f92c9b37c 100644 --- a/embassy-executor/src/metadata.rs +++ b/embassy-executor/src/metadata.rs @@ -1 +1,55 @@ -pub struct Metadata {} +#[cfg(feature = "metadata-name")] +use core::cell::Cell; +use core::future::{poll_fn, Future}; +use core::task::Poll; + +#[cfg(feature = "metadata-name")] +use critical_section::Mutex; + +use crate::raw; + +/// Metadata associated with a task. +pub struct Metadata { + #[cfg(feature = "metadata-name")] + name: Mutex>>, +} + +impl Metadata { + pub(crate) const fn new() -> Self { + Self { + #[cfg(feature = "metadata-name")] + name: Mutex::new(Cell::new(None)), + } + } + + pub(crate) fn reset(&self) { + #[cfg(feature = "metadata-name")] + critical_section::with(|cs| self.name.borrow(cs).set(None)); + } + + /// Get the metadata for the current task. + /// + /// You can use this to read or modify the current task's metadata. + /// + /// This function is `async` just to get access to the current async + /// context. It returns instantly, it does not block/yield. + pub fn for_current_task() -> impl Future { + poll_fn(|cx| Poll::Ready(raw::task_from_waker(cx.waker()).metadata())) + } + + /// Get this task's name + /// + /// NOTE: this takes a critical section. + #[cfg(feature = "metadata-name")] + pub fn name(&self) -> Option<&'static str> { + critical_section::with(|cs| self.name.borrow(cs).get()) + } + + /// Set this task's name + /// + /// NOTE: this takes a critical section. + #[cfg(feature = "metadata-name")] + pub fn set_name(&self, name: &'static str) { + critical_section::with(|cs| self.name.borrow(cs).set(Some(name))) + } +} diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 87328df5a..a7e65360d 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -41,6 +41,7 @@ use self::state::State; use self::util::{SyncUnsafeCell, UninitCell}; pub use self::waker::task_from_waker; use super::SpawnToken; +use crate::Metadata; #[no_mangle] extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static mut TimerQueueItem { @@ -94,8 +95,9 @@ pub(crate) struct TaskHeader { /// Integrated timer queue storage. This field should not be accessed outside of the timer queue. pub(crate) timer_queue_item: TimerQueueItem, - #[cfg(feature = "_any_trace")] - pub(crate) name: Option<&'static str>, + + pub(crate) metadata: Metadata, + #[cfg(feature = "rtos-trace")] all_tasks_next: AtomicPtr, } @@ -127,6 +129,10 @@ impl TaskRef { unsafe { self.ptr.as_ref() } } + pub(crate) fn metadata(self) -> &'static Metadata { + unsafe { &self.ptr.as_ref().metadata } + } + /// Returns a reference to the executor that the task is currently running on. pub unsafe fn executor(self) -> Option<&'static Executor> { let executor = self.header().executor.load(Ordering::Relaxed); @@ -193,8 +199,7 @@ impl TaskStorage { poll_fn: SyncUnsafeCell::new(None), timer_queue_item: TimerQueueItem::new(), - #[cfg(feature = "_any_trace")] - name: None, + metadata: Metadata::new(), #[cfg(feature = "rtos-trace")] all_tasks_next: AtomicPtr::new(core::ptr::null_mut()), }, @@ -281,6 +286,7 @@ impl AvailableTask { fn initialize_impl(self, future: impl FnOnce() -> F) -> SpawnToken { unsafe { + self.task.raw.metadata.reset(); self.task.raw.poll_fn.set(Some(TaskStorage::::poll)); self.task.future.write_in_place(future); diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index 636608d02..ab0c1b8b6 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -168,32 +168,6 @@ impl TaskTracker { } } -/// Extension trait for `TaskRef` that provides tracing functionality. -/// -/// This trait is only available when the `trace` feature is enabled. -/// It extends `TaskRef` with methods for accessing and modifying task identifiers -/// and names, which are useful for debugging, logging, and performance analysis. -pub trait TaskRefTrace { - /// Get the name for a task - fn name(&self) -> Option<&'static str>; - - /// Set the name for a task - fn set_name(&self, name: Option<&'static str>); -} - -impl TaskRefTrace for TaskRef { - fn name(&self) -> Option<&'static str> { - self.header().name - } - - fn set_name(&self, name: Option<&'static str>) { - unsafe { - let header_ptr = self.ptr.as_ptr() as *mut TaskHeader; - (*header_ptr).name = name; - } - } -} - #[cfg(feature = "trace")] extern "Rust" { /// This callback is called when the executor begins polling. This will always @@ -383,9 +357,8 @@ where impl rtos_trace::RtosTraceOSCallbacks for crate::raw::SyncExecutor { fn task_list() { with_all_active_tasks(|task| { - let name = task.name().unwrap_or("unnamed task\0"); let info = rtos_trace::TaskInfo { - name, + name: task.metadata().name().unwrap_or("unnamed task\0"), priority: 0, stack_base: 0, stack_size: 0, diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index 7550e8ea4..cd2113a28 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -5,8 +5,7 @@ use core::sync::atomic::Ordering; use core::task::Poll; use super::raw; -#[cfg(feature = "trace")] -use crate::raw::trace::TaskRefTrace; +use crate::Metadata; /// Token to spawn a newly-created task in an executor. /// @@ -36,6 +35,14 @@ impl SpawnToken { } } + /// Return a SpawnToken that represents a failed spawn. + pub fn new_failed() -> Self { + Self { + raw_task: None, + phantom: PhantomData, + } + } + /// Returns the task ID if available, otherwise 0 /// This can be used in combination with rtos-trace to match task names with IDs pub fn id(&self) -> u32 { @@ -45,12 +52,10 @@ impl SpawnToken { } } - /// Return a SpawnToken that represents a failed spawn. - pub fn new_failed() -> Self { - Self { - raw_task: None, - phantom: PhantomData, - } + /// Get the metadata for this task. You can use this to set metadata fields + /// prior to spawning it. + pub fn metadata(&self) -> &Metadata { + self.raw_task.unwrap().metadata() } } @@ -198,51 +203,6 @@ impl Spawner { } } -/// Extension trait adding tracing capabilities to the Spawner -/// -/// This trait provides an additional method to spawn tasks with an associated name, -/// which can be useful for debugging and tracing purposes. -pub trait SpawnerTraceExt { - /// Spawns a new task with a specified name. - /// - /// # Arguments - /// * `name` - Static string name to associate with the task - /// * `token` - Token representing the task to spawn - /// - /// # Returns - /// Result indicating whether the spawn was successful - fn spawn_named(&self, name: &'static str, token: SpawnToken) -> Result<(), SpawnError>; -} - -/// Implementation of the SpawnerTraceExt trait for Spawner when trace is enabled -#[cfg(feature = "trace")] -impl SpawnerTraceExt for Spawner { - fn spawn_named(&self, name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { - let task = token.raw_task; - core::mem::forget(token); - - match task { - Some(task) => { - // Set the name when trace is enabled - task.set_name(Some(name)); - - unsafe { self.executor.spawn(task) }; - Ok(()) - } - None => Err(SpawnError::Busy), - } - } -} - -/// Implementation of the SpawnerTraceExt trait for Spawner when trace is disabled -#[cfg(not(feature = "trace"))] -impl SpawnerTraceExt for Spawner { - fn spawn_named(&self, _name: &'static str, token: SpawnToken) -> Result<(), SpawnError> { - // When trace is disabled, just forward to regular spawn and ignore the name - self.spawn(token) - } -} - /// Handle to spawn tasks into an executor from any thread. /// /// This Spawner can be used from any thread (it is Send), but it can diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs index b84d3785a..530314ac3 100644 --- a/embassy-executor/tests/test.rs +++ b/embassy-executor/tests/test.rs @@ -326,3 +326,34 @@ fn recursive_task() { spawner.spawn(task1()); } } + +#[cfg(feature = "metadata-name")] +#[test] +fn task_metadata() { + #[task] + async fn task1(expected_name: Option<&'static str>) { + use embassy_executor::Metadata; + assert_eq!(Metadata::for_current_task().await.name(), expected_name); + } + + // check no task name + let (executor, _) = setup(); + executor.spawner().spawn(task1(None)).unwrap(); + unsafe { executor.poll() }; + + // check setting task name + let token = task1(Some("foo")); + token.metadata().set_name("foo"); + executor.spawner().spawn(token).unwrap(); + unsafe { executor.poll() }; + + let token = task1(Some("bar")); + token.metadata().set_name("bar"); + executor.spawner().spawn(token).unwrap(); + unsafe { executor.poll() }; + + // check name is cleared if the task pool slot is recycled. + let (executor, _) = setup(); + executor.spawner().spawn(task1(None)).unwrap(); + unsafe { executor.poll() }; +} -- cgit From 34ff67cdbf25e278ff99bd4a05b6b8c6a30fa5d1 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 9 Jul 2025 01:18:47 +0200 Subject: executor: do not deref a mut ptr to the entire taskheader. --- embassy-executor/src/raw/trace.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index ab0c1b8b6..e52960dc7 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -128,7 +128,7 @@ impl TaskTracker { /// # Arguments /// * `task` - The task reference to add to the tracker pub fn add(&self, task: TaskRef) { - let task_ptr = task.as_ptr() as *mut TaskHeader; + let task_ptr = task.as_ptr(); loop { let current_head = self.head.load(Ordering::Acquire); @@ -138,7 +138,7 @@ impl TaskTracker { if self .head - .compare_exchange(current_head, task_ptr, Ordering::Release, Ordering::Relaxed) + .compare_exchange(current_head, task_ptr.cast_mut(), Ordering::Release, Ordering::Relaxed) .is_ok() { break; -- cgit From 8aec341f28a00012e1771d5c35d2647e11830755 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 9 Jul 2025 01:49:31 +0200 Subject: executor: return error when creating the spawntoken, not when spawning. --- README.md | 2 +- docs/examples/basic/src/main.rs | 2 +- docs/pages/sharing_peripherals.adoc | 8 +-- embassy-executor-macros/src/macros/main.rs | 4 +- embassy-executor-macros/src/macros/task.rs | 4 +- embassy-executor/src/raw/mod.rs | 18 +++--- embassy-executor/src/spawner.rs | 65 +++------------------- embassy-executor/tests/test.rs | 29 +++++----- .../tests/ui/return_impl_future_nonsend.rs | 2 +- .../tests/ui/return_impl_future_nonsend.stderr | 6 +- embassy-executor/tests/ui/return_impl_send.stderr | 2 +- embassy-executor/tests/ui/spawn_nonsend.rs | 2 +- embassy-executor/tests/ui/spawn_nonsend.stderr | 10 ++-- embassy-net/src/lib.rs | 2 +- embassy-rp/src/multicore.rs | 4 +- embassy-stm32/src/low_power.rs | 2 +- examples/mimxrt6/src/bin/uart-async.rs | 4 +- examples/mimxrt6/src/bin/uart.rs | 4 +- examples/nrf-rtos-trace/src/bin/rtos_trace.rs | 6 +- examples/nrf52840/src/bin/channel.rs | 2 +- .../nrf52840/src/bin/channel_sender_receiver.rs | 4 +- examples/nrf52840/src/bin/ethernet_enc28j60.rs | 2 +- .../nrf52840/src/bin/executor_fairness_test.rs | 6 +- examples/nrf52840/src/bin/gpiote_port.rs | 8 +-- .../nrf52840/src/bin/manually_create_executor.rs | 4 +- examples/nrf52840/src/bin/multiprio.rs | 6 +- examples/nrf52840/src/bin/mutex.rs | 2 +- examples/nrf52840/src/bin/pubsub.rs | 6 +- examples/nrf52840/src/bin/raw_spawn.rs | 4 +- examples/nrf52840/src/bin/self_spawn.rs | 4 +- .../src/bin/self_spawn_current_executor.rs | 4 +- examples/nrf52840/src/bin/timer.rs | 4 +- examples/nrf52840/src/bin/uart_split.rs | 2 +- examples/nrf52840/src/bin/usb_ethernet.rs | 6 +- examples/nrf52840/src/bin/usb_serial_multitask.rs | 4 +- examples/nrf52840/src/bin/wifi_esp_hosted.rs | 4 +- examples/nrf9160/src/bin/modem_tcp_client.rs | 10 ++-- examples/rp/src/bin/assign_resources.rs | 6 +- examples/rp/src/bin/blinky_two_channels.rs | 4 +- examples/rp/src/bin/blinky_two_tasks.rs | 4 +- examples/rp/src/bin/ethernet_w5500_icmp.rs | 4 +- examples/rp/src/bin/ethernet_w5500_icmp_ping.rs | 4 +- examples/rp/src/bin/ethernet_w5500_multisocket.rs | 8 +-- examples/rp/src/bin/ethernet_w5500_tcp_client.rs | 4 +- examples/rp/src/bin/ethernet_w5500_tcp_server.rs | 4 +- examples/rp/src/bin/ethernet_w5500_udp.rs | 4 +- examples/rp/src/bin/i2c_slave.rs | 4 +- examples/rp/src/bin/interrupt.rs | 2 +- examples/rp/src/bin/multicore.rs | 4 +- examples/rp/src/bin/multiprio.rs | 6 +- examples/rp/src/bin/orchestrate_tasks.rs | 14 ++--- examples/rp/src/bin/pio_async.rs | 6 +- examples/rp/src/bin/pio_rotary_encoder.rs | 4 +- examples/rp/src/bin/pwm.rs | 4 +- examples/rp/src/bin/shared_bus.rs | 8 +-- examples/rp/src/bin/sharing.rs | 6 +- examples/rp/src/bin/uart_buffered_split.rs | 2 +- examples/rp/src/bin/uart_unidir.rs | 2 +- examples/rp/src/bin/usb_ethernet.rs | 6 +- examples/rp/src/bin/usb_logger.rs | 2 +- examples/rp/src/bin/usb_serial.rs | 2 +- examples/rp/src/bin/usb_serial_with_handler.rs | 2 +- examples/rp/src/bin/wifi_ap_tcp_server.rs | 4 +- examples/rp/src/bin/wifi_blinky.rs | 2 +- examples/rp/src/bin/wifi_scan.rs | 2 +- examples/rp/src/bin/wifi_tcp_server.rs | 4 +- examples/rp/src/bin/wifi_webrequest.rs | 4 +- examples/rp/src/bin/zerocopy.rs | 4 +- examples/rp235x/src/bin/assign_resources.rs | 6 +- examples/rp235x/src/bin/blinky_two_channels.rs | 4 +- examples/rp235x/src/bin/blinky_two_tasks.rs | 4 +- examples/rp235x/src/bin/blinky_wifi.rs | 2 +- examples/rp235x/src/bin/blinky_wifi_pico_plus_2.rs | 2 +- examples/rp235x/src/bin/i2c_slave.rs | 4 +- examples/rp235x/src/bin/interrupt.rs | 2 +- examples/rp235x/src/bin/multicore.rs | 4 +- examples/rp235x/src/bin/multiprio.rs | 6 +- examples/rp235x/src/bin/pio_async.rs | 6 +- examples/rp235x/src/bin/pio_rotary_encoder.rs | 4 +- examples/rp235x/src/bin/pwm.rs | 4 +- examples/rp235x/src/bin/shared_bus.rs | 8 +-- examples/rp235x/src/bin/sharing.rs | 6 +- examples/rp235x/src/bin/uart_buffered_split.rs | 2 +- examples/rp235x/src/bin/uart_unidir.rs | 2 +- examples/rp235x/src/bin/zerocopy.rs | 4 +- examples/std/src/bin/net.rs | 4 +- examples/std/src/bin/net_dns.rs | 4 +- examples/std/src/bin/net_ppp.rs | 6 +- examples/std/src/bin/net_udp.rs | 4 +- examples/std/src/bin/serial.rs | 2 +- examples/std/src/bin/tcp_accept.rs | 4 +- examples/std/src/bin/tick.rs | 2 +- .../stm32f0/src/bin/button_controlled_blink.rs | 2 +- examples/stm32f0/src/bin/multiprio.rs | 6 +- examples/stm32f1/src/bin/input_capture.rs | 2 +- examples/stm32f1/src/bin/pwm_input.rs | 2 +- examples/stm32f3/src/bin/button_events.rs | 4 +- examples/stm32f3/src/bin/multiprio.rs | 6 +- examples/stm32f4/src/bin/adc_dma.rs | 2 +- examples/stm32f4/src/bin/eth.rs | 2 +- examples/stm32f4/src/bin/eth_w5500.rs | 4 +- examples/stm32f4/src/bin/flash_async.rs | 2 +- examples/stm32f4/src/bin/input_capture.rs | 2 +- examples/stm32f4/src/bin/multiprio.rs | 6 +- examples/stm32f4/src/bin/pwm_input.rs | 2 +- examples/stm32f4/src/bin/usb_ethernet.rs | 6 +- examples/stm32f4/src/bin/usb_uac_speaker.rs | 10 ++-- examples/stm32f7/src/bin/can.rs | 2 +- examples/stm32f7/src/bin/eth.rs | 2 +- examples/stm32g0/src/bin/input_capture.rs | 2 +- examples/stm32g0/src/bin/pwm_input.rs | 2 +- examples/stm32g4/src/bin/i2c_slave.rs | 4 +- examples/stm32h5/src/bin/eth.rs | 2 +- examples/stm32h5/src/bin/stop.rs | 6 +- examples/stm32h5/src/bin/usart.rs | 2 +- examples/stm32h5/src/bin/usart_dma.rs | 2 +- examples/stm32h5/src/bin/usart_split.rs | 2 +- examples/stm32h5/src/bin/usb_uac_speaker.rs | 10 ++-- examples/stm32h7/src/bin/dac_dma.rs | 4 +- examples/stm32h7/src/bin/eth.rs | 2 +- examples/stm32h7/src/bin/eth_client.rs | 2 +- examples/stm32h7/src/bin/eth_client_mii.rs | 2 +- examples/stm32h7/src/bin/i2c_shared.rs | 4 +- examples/stm32h7/src/bin/multiprio.rs | 6 +- examples/stm32h7/src/bin/signal.rs | 2 +- examples/stm32h7/src/bin/spi.rs | 2 +- examples/stm32h7/src/bin/spi_bdma.rs | 2 +- examples/stm32h7/src/bin/spi_dma.rs | 2 +- examples/stm32h7/src/bin/usart.rs | 2 +- examples/stm32h7/src/bin/usart_dma.rs | 2 +- examples/stm32h7/src/bin/usart_split.rs | 2 +- examples/stm32h735/src/bin/ltdc.rs | 2 +- examples/stm32h7rs/src/bin/eth.rs | 2 +- examples/stm32h7rs/src/bin/multiprio.rs | 6 +- examples/stm32h7rs/src/bin/signal.rs | 2 +- examples/stm32h7rs/src/bin/spi.rs | 2 +- examples/stm32h7rs/src/bin/spi_dma.rs | 2 +- examples/stm32h7rs/src/bin/usart.rs | 2 +- examples/stm32h7rs/src/bin/usart_dma.rs | 2 +- examples/stm32h7rs/src/bin/usart_split.rs | 2 +- examples/stm32l0/src/bin/raw_spawn.rs | 4 +- examples/stm32l4/src/bin/dac_dma.rs | 4 +- .../stm32l4/src/bin/spe_adin1110_http_server.rs | 8 +-- examples/stm32l5/src/bin/stop.rs | 6 +- examples/stm32l5/src/bin/usb_ethernet.rs | 6 +- examples/stm32u5/src/bin/ltdc.rs | 2 +- examples/stm32wb/src/bin/mac_ffd.rs | 2 +- examples/stm32wb/src/bin/mac_ffd_net.rs | 4 +- examples/stm32wb/src/bin/mac_rfd.rs | 2 +- examples/stm32wb/src/bin/tl_mbox_mac.rs | 2 +- examples/wasm/src/lib.rs | 2 +- tests/nrf/src/bin/ethernet_enc28j60_perf.rs | 2 +- tests/nrf/src/bin/wifi_esp_hosted_perf.rs | 4 +- tests/rp/src/bin/cyw43-perf.rs | 4 +- tests/rp/src/bin/ethernet_w5100s_perf.rs | 4 +- tests/rp/src/bin/gpio_multicore.rs | 4 +- tests/rp/src/bin/i2c.rs | 2 +- tests/rp/src/bin/multicore.rs | 4 +- tests/rp/src/bin/spinlock_mutex_multicore.rs | 4 +- tests/stm32/src/bin/eth.rs | 2 +- tests/stm32/src/bin/stop.rs | 6 +- tests/stm32/src/bin/usart_rx_ringbuffered.rs | 4 +- tests/stm32/src/bin/wpan_ble.rs | 2 +- tests/stm32/src/bin/wpan_mac.rs | 2 +- 164 files changed, 337 insertions(+), 389 deletions(-) diff --git a/README.md b/README.md index 68d8460d3..de6b3bb59 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ async fn main(spawner: Spawner) { let p = embassy_nrf::init(Default::default()); // Spawned tasks run in the background, concurrently. - spawner.spawn(blink(p.P0_13.into())).unwrap(); + spawner.spawn(blink(p.P0_13.into()).unwrap()); let mut button = Input::new(p.P0_11, Pull::Up); loop { diff --git a/docs/examples/basic/src/main.rs b/docs/examples/basic/src/main.rs index 4412712c8..6e274bacb 100644 --- a/docs/examples/basic/src/main.rs +++ b/docs/examples/basic/src/main.rs @@ -22,5 +22,5 @@ async fn main(spawner: Spawner) { let p = embassy_nrf::init(Default::default()); let led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); - unwrap!(spawner.spawn(blinker(led, Duration::from_millis(300)))); + spawner.spawn(unwrap!(blinker(led, Duration::from_millis(300)))); } diff --git a/docs/pages/sharing_peripherals.adoc b/docs/pages/sharing_peripherals.adoc index dfb8c1ffe..70b4210e6 100644 --- a/docs/pages/sharing_peripherals.adoc +++ b/docs/pages/sharing_peripherals.adoc @@ -36,8 +36,8 @@ async fn main(spawner: Spawner) { let dt = 100 * 1_000_000; let k = 1.003; - unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos(dt)))); - unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64)))); + spawner.spawn(unwrap!(toggle_led(&LED, Duration::from_nanos(dt)))); + spawner.spawn(unwrap!(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64)))); } // A pool size of 2 means you can spawn two instances of this task. @@ -103,8 +103,8 @@ async fn main(spawner: Spawner) { let dt = 100 * 1_000_000; let k = 1.003; - unwrap!(spawner.spawn(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt)))); - unwrap!(spawner.spawn(toggle_led(CHANNEL.sender(), Duration::from_nanos((dt as f64 * k) as u64)))); + spawner.spawn(unwrap!(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt)))); + spawner.spawn(unwrap!(toggle_led(CHANNEL.sender(), Duration::from_nanos((dt as f64 * k) as u64)))); loop { match CHANNEL.receive().await { diff --git a/embassy-executor-macros/src/macros/main.rs b/embassy-executor-macros/src/macros/main.rs index a0e7b3401..fcc04d9c0 100644 --- a/embassy-executor-macros/src/macros/main.rs +++ b/embassy-executor-macros/src/macros/main.rs @@ -181,7 +181,7 @@ For example: `#[embassy_executor::main(entry = ..., executor = \"some_crate::Exe let mut executor = #executor::new(); let executor = unsafe { __make_static(&mut executor) }; executor.run(|spawner| { - spawner.must_spawn(__embassy_main(spawner)); + spawner.spawn(__embassy_main(spawner).unwrap()); }) }, ), @@ -191,7 +191,7 @@ For example: `#[embassy_executor::main(entry = ..., executor = \"some_crate::Exe let executor = ::std::boxed::Box::leak(::std::boxed::Box::new(#executor::new())); executor.start(|spawner| { - spawner.must_spawn(__embassy_main(spawner)); + spawner.spawn(__embassy_main(spawner).unwrap()); }); Ok(()) diff --git a/embassy-executor-macros/src/macros/task.rs b/embassy-executor-macros/src/macros/task.rs index fc8673743..755948882 100644 --- a/embassy-executor-macros/src/macros/task.rs +++ b/embassy-executor-macros/src/macros/task.rs @@ -234,7 +234,7 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { if !errors.is_empty() { task_outer_body = quote! { #![allow(unused_variables, unreachable_code)] - let _x: #embassy_executor::SpawnToken<()> = ::core::todo!(); + let _x: ::core::result::Result<#embassy_executor::SpawnToken<()>, #embassy_executor::SpawnError> = ::core::todo!(); _x }; } @@ -248,7 +248,7 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream { #task_inner #(#task_outer_attrs)* - #visibility #unsafety fn #task_ident #generics (#fargs) -> #embassy_executor::SpawnToken #where_clause{ + #visibility #unsafety fn #task_ident #generics (#fargs) -> ::core::result::Result<#embassy_executor::SpawnToken, #embassy_executor::SpawnError> #where_clause{ #task_outer_body } diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index a7e65360d..bdaa32951 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -41,7 +41,7 @@ use self::state::State; use self::util::{SyncUnsafeCell, UninitCell}; pub use self::waker::task_from_waker; use super::SpawnToken; -use crate::Metadata; +use crate::{Metadata, SpawnError}; #[no_mangle] extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static mut TimerQueueItem { @@ -220,11 +220,11 @@ impl TaskStorage { /// /// Once the task has finished running, you may spawn it again. It is allowed to spawn it /// on a different executor. - pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken { + pub fn spawn(&'static self, future: impl FnOnce() -> F) -> Result, SpawnError> { let task = AvailableTask::claim(self); match task { - Some(task) => task.initialize(future), - None => SpawnToken::new_failed(), + Some(task) => Ok(task.initialize(future)), + None => Err(SpawnError::Busy), } } @@ -353,10 +353,10 @@ impl TaskPool { } } - fn spawn_impl(&'static self, future: impl FnOnce() -> F) -> SpawnToken { + fn spawn_impl(&'static self, future: impl FnOnce() -> F) -> Result, SpawnError> { match self.pool.iter().find_map(AvailableTask::claim) { - Some(task) => task.initialize_impl::(future), - None => SpawnToken::new_failed(), + Some(task) => Ok(task.initialize_impl::(future)), + None => Err(SpawnError::Busy), } } @@ -367,7 +367,7 @@ impl TaskPool { /// This will loop over the pool and spawn the task in the first storage that /// is currently free. If none is free, a "poisoned" SpawnToken is returned, /// which will cause [`Spawner::spawn()`](super::Spawner::spawn) to return the error. - pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken { + pub fn spawn(&'static self, future: impl FnOnce() -> F) -> Result, SpawnError> { self.spawn_impl::(future) } @@ -380,7 +380,7 @@ impl TaskPool { /// SAFETY: `future` must be a closure of the form `move || my_async_fn(args)`, where `my_async_fn` /// is an `async fn`, NOT a hand-written `Future`. #[doc(hidden)] - pub unsafe fn _spawn_async_fn(&'static self, future: FutFn) -> SpawnToken + pub unsafe fn _spawn_async_fn(&'static self, future: FutFn) -> Result, SpawnError> where FutFn: FnOnce() -> F, { diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index cd2113a28..83d896b76 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs @@ -23,39 +23,28 @@ use crate::Metadata; /// Once you've invoked a task function and obtained a SpawnToken, you *must* spawn it. #[must_use = "Calling a task function does nothing on its own. You must spawn the returned SpawnToken, typically with Spawner::spawn()"] pub struct SpawnToken { - pub(crate) raw_task: Option, + pub(crate) raw_task: raw::TaskRef, phantom: PhantomData<*mut S>, } impl SpawnToken { pub(crate) unsafe fn new(raw_task: raw::TaskRef) -> Self { Self { - raw_task: Some(raw_task), + raw_task, phantom: PhantomData, } } - /// Return a SpawnToken that represents a failed spawn. - pub fn new_failed() -> Self { - Self { - raw_task: None, - phantom: PhantomData, - } - } - - /// Returns the task ID if available, otherwise 0 + /// Returns the task ID. /// This can be used in combination with rtos-trace to match task names with IDs pub fn id(&self) -> u32 { - match self.raw_task { - None => 0, - Some(t) => t.id(), - } + self.raw_task.id() } /// Get the metadata for this task. You can use this to set metadata fields /// prior to spawning it. pub fn metadata(&self) -> &Metadata { - self.raw_task.unwrap().metadata() + self.raw_task.metadata() } } @@ -164,30 +153,10 @@ impl Spawner { /// Spawn a task into an executor. /// /// You obtain the `token` by calling a task function (i.e. one marked with `#[embassy_executor::task]`). - pub fn spawn(&self, token: SpawnToken) -> Result<(), SpawnError> { + pub fn spawn(&self, token: SpawnToken) { let task = token.raw_task; mem::forget(token); - - match task { - Some(task) => { - unsafe { self.executor.spawn(task) }; - Ok(()) - } - None => Err(SpawnError::Busy), - } - } - - // Used by the `embassy_executor_macros::main!` macro to throw an error when spawn - // fails. This is here to allow conditional use of `defmt::unwrap!` - // without introducing a `defmt` feature in the `embassy_executor_macros` package, - // which would require use of `-Z namespaced-features`. - /// Spawn a task into an executor, panicking on failure. - /// - /// # Panics - /// - /// Panics if the spawning fails. - pub fn must_spawn(&self, token: SpawnToken) { - unwrap!(self.spawn(token)); + unsafe { self.executor.spawn(task) } } /// Convert this Spawner to a SendSpawner. This allows you to send the @@ -245,25 +214,9 @@ impl SendSpawner { /// Spawn a task into an executor. /// /// You obtain the `token` by calling a task function (i.e. one marked with `#[embassy_executor::task]`). - pub fn spawn(&self, token: SpawnToken) -> Result<(), SpawnError> { + pub fn spawn(&self, token: SpawnToken) { let header = token.raw_task; mem::forget(token); - - match header { - Some(header) => { - unsafe { self.executor.spawn(header) }; - Ok(()) - } - None => Err(SpawnError::Busy), - } - } - - /// Spawn a task into an executor, panicking on failure. - /// - /// # Panics - /// - /// Panics if the spawning fails. - pub fn must_spawn(&self, token: SpawnToken) { - unwrap!(self.spawn(token)); + unsafe { self.executor.spawn(header) } } } diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs index 530314ac3..85c5dc1d9 100644 --- a/embassy-executor/tests/test.rs +++ b/embassy-executor/tests/test.rs @@ -65,7 +65,7 @@ fn executor_task() { } let (executor, trace) = setup(); - executor.spawner().spawn(task1(trace.clone())).unwrap(); + executor.spawner().spawn(task1(trace.clone()).unwrap()); unsafe { executor.poll() }; unsafe { executor.poll() }; @@ -93,7 +93,7 @@ fn executor_task_rpit() { } let (executor, trace) = setup(); - executor.spawner().spawn(task1(trace.clone())).unwrap(); + executor.spawner().spawn(task1(trace.clone()).unwrap()); unsafe { executor.poll() }; unsafe { executor.poll() }; @@ -120,7 +120,7 @@ fn executor_task_self_wake() { } let (executor, trace) = setup(); - executor.spawner().spawn(task1(trace.clone())).unwrap(); + executor.spawner().spawn(task1(trace.clone()).unwrap()); unsafe { executor.poll() }; unsafe { executor.poll() }; @@ -152,7 +152,7 @@ fn executor_task_self_wake_twice() { } let (executor, trace) = setup(); - executor.spawner().spawn(task1(trace.clone())).unwrap(); + executor.spawner().spawn(task1(trace.clone()).unwrap()); unsafe { executor.poll() }; unsafe { executor.poll() }; @@ -188,7 +188,7 @@ fn waking_after_completion_does_not_poll() { let waker = Box::leak(Box::new(AtomicWaker::new())); let (executor, trace) = setup(); - executor.spawner().spawn(task1(trace.clone(), waker)).unwrap(); + executor.spawner().spawn(task1(trace.clone(), waker).unwrap()); unsafe { executor.poll() }; waker.wake(); @@ -200,7 +200,7 @@ fn waking_after_completion_does_not_poll() { unsafe { executor.poll() }; // Clears running status // Can respawn waken-but-dead task - executor.spawner().spawn(task1(trace.clone(), waker)).unwrap(); + executor.spawner().spawn(task1(trace.clone(), waker).unwrap()); unsafe { executor.poll() }; @@ -250,7 +250,7 @@ fn waking_with_old_waker_after_respawn() { let waker = Box::leak(Box::new(AtomicWaker::new())); let (executor, trace) = setup(); - executor.spawner().spawn(task1(trace.clone(), waker)).unwrap(); + executor.spawner().spawn(task1(trace.clone(), waker).unwrap()); unsafe { executor.poll() }; unsafe { executor.poll() }; // progress to registering the waker @@ -273,8 +273,7 @@ fn waking_with_old_waker_after_respawn() { let (other_executor, other_trace) = setup(); other_executor .spawner() - .spawn(task1(other_trace.clone(), waker)) - .unwrap(); + .spawn(task1(other_trace.clone(), waker).unwrap()); unsafe { other_executor.poll() }; // just run to the yield_now waker.wake(); // trigger old waker registration @@ -338,22 +337,22 @@ fn task_metadata() { // check no task name let (executor, _) = setup(); - executor.spawner().spawn(task1(None)).unwrap(); + executor.spawner().spawn(task1(None).unwrap()); unsafe { executor.poll() }; // check setting task name - let token = task1(Some("foo")); + let token = task1(Some("foo")).unwrap(); token.metadata().set_name("foo"); - executor.spawner().spawn(token).unwrap(); + executor.spawner().spawn(token); unsafe { executor.poll() }; - let token = task1(Some("bar")); + let token = task1(Some("bar")).unwrap(); token.metadata().set_name("bar"); - executor.spawner().spawn(token).unwrap(); + executor.spawner().spawn(token); unsafe { executor.poll() }; // check name is cleared if the task pool slot is recycled. let (executor, _) = setup(); - executor.spawner().spawn(task1(None)).unwrap(); + executor.spawner().spawn(task1(None).unwrap()); unsafe { executor.poll() }; } diff --git a/embassy-executor/tests/ui/return_impl_future_nonsend.rs b/embassy-executor/tests/ui/return_impl_future_nonsend.rs index b8c184b21..77b3119d6 100644 --- a/embassy-executor/tests/ui/return_impl_future_nonsend.rs +++ b/embassy-executor/tests/ui/return_impl_future_nonsend.rs @@ -15,7 +15,7 @@ fn task() -> impl Future { } fn send_spawn(s: SendSpawner) { - s.spawn(task()).unwrap(); + s.spawn(task().unwrap()); } fn main() {} diff --git a/embassy-executor/tests/ui/return_impl_future_nonsend.stderr b/embassy-executor/tests/ui/return_impl_future_nonsend.stderr index 8aeb9738a..51944ad65 100644 --- a/embassy-executor/tests/ui/return_impl_future_nonsend.stderr +++ b/embassy-executor/tests/ui/return_impl_future_nonsend.stderr @@ -1,8 +1,8 @@ error: future cannot be sent between threads safely --> tests/ui/return_impl_future_nonsend.rs:18:13 | -18 | s.spawn(task()).unwrap(); - | ^^^^^^ future created by async block is not `Send` +18 | s.spawn(task().unwrap()); + | ^^^^^^^^^^^^^^^ future created by async block is not `Send` | = help: within `impl Sized`, the trait `Send` is not implemented for `*mut ()` note: captured value is not `Send` @@ -13,5 +13,5 @@ note: captured value is not `Send` note: required by a bound in `SendSpawner::spawn` --> src/spawner.rs | - | pub fn spawn(&self, token: SpawnToken) -> Result<(), SpawnError> { + | pub fn spawn(&self, token: SpawnToken) { | ^^^^ required by this bound in `SendSpawner::spawn` diff --git a/embassy-executor/tests/ui/return_impl_send.stderr b/embassy-executor/tests/ui/return_impl_send.stderr index 759be1cde..5d19465ec 100644 --- a/embassy-executor/tests/ui/return_impl_send.stderr +++ b/embassy-executor/tests/ui/return_impl_send.stderr @@ -97,7 +97,7 @@ note: required by a bound in `TaskPool::::spawn` | impl TaskPool { | ^^^^^^ required by this bound in `TaskPool::::spawn` ... - | pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken { + | pub fn spawn(&'static self, future: impl FnOnce() -> F) -> Result, SpawnError> { | ----- required by a bound in this associated function = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/embassy-executor/tests/ui/spawn_nonsend.rs b/embassy-executor/tests/ui/spawn_nonsend.rs index 4c4cc7697..601041941 100644 --- a/embassy-executor/tests/ui/spawn_nonsend.rs +++ b/embassy-executor/tests/ui/spawn_nonsend.rs @@ -10,7 +10,7 @@ async fn task(non_send: *mut ()) { } fn send_spawn(s: SendSpawner) { - s.spawn(task(core::ptr::null_mut())).unwrap(); + s.spawn(task(core::ptr::null_mut()).unwrap()); } fn main() {} diff --git a/embassy-executor/tests/ui/spawn_nonsend.stderr b/embassy-executor/tests/ui/spawn_nonsend.stderr index 2a06c8b94..25bd7d78d 100644 --- a/embassy-executor/tests/ui/spawn_nonsend.stderr +++ b/embassy-executor/tests/ui/spawn_nonsend.stderr @@ -12,8 +12,8 @@ error[E0277]: `*mut ()` cannot be sent between threads safely 7 | #[embassy_executor::task] | ------------------------- within this `impl Sized` ... -13 | s.spawn(task(core::ptr::null_mut())).unwrap(); - | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be sent between threads safely +13 | s.spawn(task(core::ptr::null_mut()).unwrap()); + | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be sent between threads safely | | | required by a bound introduced by this call | @@ -26,8 +26,8 @@ note: required because it's used within this closure note: required because it appears within the type `impl Sized` --> src/raw/mod.rs | - | pub unsafe fn _spawn_async_fn(&'static self, future: FutFn) -> SpawnToken - | ^^^^^^^^^^ + | pub unsafe fn _spawn_async_fn(&'static self, future: FutFn) -> Result, SpawnError> + | ^^^^^^^^^^ note: required because it appears within the type `impl Sized` --> tests/ui/spawn_nonsend.rs:7:1 | @@ -36,6 +36,6 @@ note: required because it appears within the type `impl Sized` note: required by a bound in `SendSpawner::spawn` --> src/spawner.rs | - | pub fn spawn(&self, token: SpawnToken) -> Result<(), SpawnError> { + | pub fn spawn(&self, token: SpawnToken) { | ^^^^ required by this bound in `SendSpawner::spawn` = note: this error originates in the attribute macro `embassy_executor::task` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 0bc6ffe6c..3f0634849 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -464,7 +464,7 @@ impl<'d> Stack<'d> { /// seed /// ); /// // Launch network task that runs `runner.run().await` - /// spawner.spawn(net_task(runner)).unwrap(); + /// spawner.spawn(net_task(runner).unwrap()); /// // Wait for DHCP config /// stack.wait_config_up().await; /// // use the network stack diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs index 64065fcba..adedc98ad 100644 --- a/embassy-rp/src/multicore.rs +++ b/embassy-rp/src/multicore.rs @@ -38,11 +38,11 @@ //! //! embassy_rp::multicore::spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { //! let executor1 = EXECUTOR1.init(Executor::new()); -//! executor1.run(|spawner| spawner.spawn(core1_task()).unwrap()); +//! executor1.run(|spawner| spawner.spawn(core1_task().unwrap())); //! }); //! //! let executor0 = EXECUTOR0.init(Executor::new()); -//! executor0.run(|spawner| spawner.spawn(core0_task()).unwrap()) +//! executor0.run(|spawner| spawner.spawn(core0_task().unwrap())) //! } //! ``` diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index d13df5a6b..342f73bc8 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -29,7 +29,7 @@ //! #[cortex_m_rt::entry] //! fn main() -> ! { //! Executor::take().run(|spawner| { -//! unwrap!(spawner.spawn(async_main(spawner))); +//! spawner.spawn(unwrap!(async_main(spawner))); //! }); //! } //! diff --git a/examples/mimxrt6/src/bin/uart-async.rs b/examples/mimxrt6/src/bin/uart-async.rs index 58e31f379..d808d755c 100644 --- a/examples/mimxrt6/src/bin/uart-async.rs +++ b/examples/mimxrt6/src/bin/uart-async.rs @@ -69,7 +69,7 @@ async fn main(spawner: Spawner) { Default::default(), ) .unwrap(); - spawner.must_spawn(usart4_task(usart4)); + spawner.spawn(usart4_task(usart4).unwrap()); let usart2 = Uart::new_with_rtscts( p.FLEXCOMM2, @@ -83,5 +83,5 @@ async fn main(spawner: Spawner) { Default::default(), ) .unwrap(); - spawner.must_spawn(usart2_task(usart2)); + spawner.spawn(usart2_task(usart2).unwrap()); } diff --git a/examples/mimxrt6/src/bin/uart.rs b/examples/mimxrt6/src/bin/uart.rs index d6a75f85d..1636c958f 100644 --- a/examples/mimxrt6/src/bin/uart.rs +++ b/examples/mimxrt6/src/bin/uart.rs @@ -48,8 +48,8 @@ async fn main(spawner: Spawner) { let usart4 = Uart::new_blocking(p.FLEXCOMM4, p.PIO0_29, p.PIO0_30, Default::default()).unwrap(); let (_, usart4) = usart4.split(); - spawner.must_spawn(usart4_task(usart4)); + spawner.spawn(usart4_task(usart4).unwrap()); let usart2 = UartTx::new_blocking(p.FLEXCOMM2, p.PIO0_15, Default::default()).unwrap(); - spawner.must_spawn(usart2_task(usart2)); + spawner.spawn(usart2_task(usart2).unwrap()); } diff --git a/examples/nrf-rtos-trace/src/bin/rtos_trace.rs b/examples/nrf-rtos-trace/src/bin/rtos_trace.rs index 41cc06417..c1e7f8f58 100644 --- a/examples/nrf-rtos-trace/src/bin/rtos_trace.rs +++ b/examples/nrf-rtos-trace/src/bin/rtos_trace.rs @@ -63,7 +63,7 @@ async fn main(spawner: Spawner) { ::log::set_max_level(::log::LevelFilter::Trace); } - spawner.spawn(run1()).unwrap(); - spawner.spawn(run2()).unwrap(); - spawner.spawn(run3()).unwrap(); + spawner.spawn(run1().unwrap()); + spawner.spawn(run2().unwrap()); + spawner.spawn(run3().unwrap()); } diff --git a/examples/nrf52840/src/bin/channel.rs b/examples/nrf52840/src/bin/channel.rs index e06ba1c73..ffa539808 100644 --- a/examples/nrf52840/src/bin/channel.rs +++ b/examples/nrf52840/src/bin/channel.rs @@ -31,7 +31,7 @@ async fn main(spawner: Spawner) { let p = embassy_nrf::init(Default::default()); let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); - unwrap!(spawner.spawn(my_task())); + spawner.spawn(unwrap!(my_task())); loop { match CHANNEL.receive().await { diff --git a/examples/nrf52840/src/bin/channel_sender_receiver.rs b/examples/nrf52840/src/bin/channel_sender_receiver.rs index 74c62ca20..09050db68 100644 --- a/examples/nrf52840/src/bin/channel_sender_receiver.rs +++ b/examples/nrf52840/src/bin/channel_sender_receiver.rs @@ -45,6 +45,6 @@ async fn main(spawner: Spawner) { let p = embassy_nrf::init(Default::default()); let channel = CHANNEL.init(Channel::new()); - unwrap!(spawner.spawn(send_task(channel.sender()))); - unwrap!(spawner.spawn(recv_task(p.P0_13.into(), channel.receiver()))); + spawner.spawn(unwrap!(send_task(channel.sender()))); + spawner.spawn(unwrap!(recv_task(p.P0_13.into(), channel.receiver()))); } diff --git a/examples/nrf52840/src/bin/ethernet_enc28j60.rs b/examples/nrf52840/src/bin/ethernet_enc28j60.rs index 0946492fe..3bb255a72 100644 --- a/examples/nrf52840/src/bin/ethernet_enc28j60.rs +++ b/examples/nrf52840/src/bin/ethernet_enc28j60.rs @@ -70,7 +70,7 @@ async fn main(spawner: Spawner) { static RESOURCES: StaticCell> = StaticCell::new(); let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); // And now we can use it! diff --git a/examples/nrf52840/src/bin/executor_fairness_test.rs b/examples/nrf52840/src/bin/executor_fairness_test.rs index df6e7af3f..70c9405f0 100644 --- a/examples/nrf52840/src/bin/executor_fairness_test.rs +++ b/examples/nrf52840/src/bin/executor_fairness_test.rs @@ -36,7 +36,7 @@ async fn run3() { #[embassy_executor::main] async fn main(spawner: Spawner) { let _p = embassy_nrf::init(Default::default()); - unwrap!(spawner.spawn(run1())); - unwrap!(spawner.spawn(run2())); - unwrap!(spawner.spawn(run3())); + spawner.spawn(unwrap!(run1())); + spawner.spawn(unwrap!(run2())); + spawner.spawn(unwrap!(run3())); } diff --git a/examples/nrf52840/src/bin/gpiote_port.rs b/examples/nrf52840/src/bin/gpiote_port.rs index 0dddb1a97..66dbd32dc 100644 --- a/examples/nrf52840/src/bin/gpiote_port.rs +++ b/examples/nrf52840/src/bin/gpiote_port.rs @@ -26,8 +26,8 @@ async fn main(spawner: Spawner) { let btn3 = Input::new(p.P0_24, Pull::Up); let btn4 = Input::new(p.P0_25, Pull::Up); - unwrap!(spawner.spawn(button_task(1, btn1))); - unwrap!(spawner.spawn(button_task(2, btn2))); - unwrap!(spawner.spawn(button_task(3, btn3))); - unwrap!(spawner.spawn(button_task(4, btn4))); + spawner.spawn(unwrap!(button_task(1, btn1))); + spawner.spawn(unwrap!(button_task(2, btn2))); + spawner.spawn(unwrap!(button_task(3, btn3))); + spawner.spawn(unwrap!(button_task(4, btn4))); } diff --git a/examples/nrf52840/src/bin/manually_create_executor.rs b/examples/nrf52840/src/bin/manually_create_executor.rs index 7ca39348e..f0639eb23 100644 --- a/examples/nrf52840/src/bin/manually_create_executor.rs +++ b/examples/nrf52840/src/bin/manually_create_executor.rs @@ -42,7 +42,7 @@ fn main() -> ! { // `run` calls the closure then runs the executor forever. It never returns. executor.run(|spawner| { // Here we get access to a spawner to spawn the initial tasks. - unwrap!(spawner.spawn(run1())); - unwrap!(spawner.spawn(run2())); + spawner.spawn(unwrap!(run1())); + spawner.spawn(unwrap!(run2())); }); } diff --git a/examples/nrf52840/src/bin/multiprio.rs b/examples/nrf52840/src/bin/multiprio.rs index d58613da4..4d9b986d4 100644 --- a/examples/nrf52840/src/bin/multiprio.rs +++ b/examples/nrf52840/src/bin/multiprio.rs @@ -130,16 +130,16 @@ fn main() -> ! { // High-priority executor: EGU1_SWI1, priority level 6 interrupt::EGU1_SWI1.set_priority(Priority::P6); let spawner = EXECUTOR_HIGH.start(interrupt::EGU1_SWI1); - unwrap!(spawner.spawn(run_high())); + spawner.spawn(unwrap!(run_high())); // Medium-priority executor: EGU0_SWI0, priority level 7 interrupt::EGU0_SWI0.set_priority(Priority::P7); let spawner = EXECUTOR_MED.start(interrupt::EGU0_SWI0); - unwrap!(spawner.spawn(run_med())); + spawner.spawn(unwrap!(run_med())); // Low priority executor: runs in thread mode, using WFE/SEV let executor = EXECUTOR_LOW.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(run_low())); + spawner.spawn(unwrap!(run_low())); }); } diff --git a/examples/nrf52840/src/bin/mutex.rs b/examples/nrf52840/src/bin/mutex.rs index 5c22279b5..a8e9a82cc 100644 --- a/examples/nrf52840/src/bin/mutex.rs +++ b/examples/nrf52840/src/bin/mutex.rs @@ -30,7 +30,7 @@ async fn my_task() { #[embassy_executor::main] async fn main(spawner: Spawner) { let _p = embassy_nrf::init(Default::default()); - unwrap!(spawner.spawn(my_task())); + spawner.spawn(unwrap!(my_task())); loop { Timer::after_millis(300).await; diff --git a/examples/nrf52840/src/bin/pubsub.rs b/examples/nrf52840/src/bin/pubsub.rs index 5ebea9220..c0392b18c 100644 --- a/examples/nrf52840/src/bin/pubsub.rs +++ b/examples/nrf52840/src/bin/pubsub.rs @@ -26,9 +26,9 @@ async fn main(spawner: Spawner) { // It's good to set up the subscribers before publishing anything. // A subscriber will only yield messages that have been published after its creation. - spawner.must_spawn(fast_logger(unwrap!(MESSAGE_BUS.subscriber()))); - spawner.must_spawn(slow_logger(unwrap!(MESSAGE_BUS.dyn_subscriber()))); - spawner.must_spawn(slow_logger_pure(unwrap!(MESSAGE_BUS.dyn_subscriber()))); + spawner.spawn(fast_logger(unwrap!(MESSAGE_BUS.subscriber())).unwrap()); + spawner.spawn(slow_logger(unwrap!(MESSAGE_BUS.dyn_subscriber())).unwrap()); + spawner.spawn(slow_logger_pure(unwrap!(MESSAGE_BUS.dyn_subscriber())).unwrap()); // Get a publisher let message_publisher = unwrap!(MESSAGE_BUS.publisher()); diff --git a/examples/nrf52840/src/bin/raw_spawn.rs b/examples/nrf52840/src/bin/raw_spawn.rs index 717b0faa6..b80954408 100644 --- a/examples/nrf52840/src/bin/raw_spawn.rs +++ b/examples/nrf52840/src/bin/raw_spawn.rs @@ -42,8 +42,8 @@ fn main() -> ! { let run2_task = unsafe { make_static(&run2_task) }; executor.run(|spawner| { - unwrap!(spawner.spawn(run1_task.spawn(|| run1()))); - unwrap!(spawner.spawn(run2_task.spawn(|| run2()))); + spawner.spawn(unwrap!(run1_task.spawn(|| run1()))); + spawner.spawn(unwrap!(run2_task.spawn(|| run2()))); }); } diff --git a/examples/nrf52840/src/bin/self_spawn.rs b/examples/nrf52840/src/bin/self_spawn.rs index 5bfefc2af..acb44f98b 100644 --- a/examples/nrf52840/src/bin/self_spawn.rs +++ b/examples/nrf52840/src/bin/self_spawn.rs @@ -14,12 +14,12 @@ mod config { async fn my_task(spawner: Spawner, n: u32) { Timer::after_secs(1).await; info!("Spawning self! {}", n); - unwrap!(spawner.spawn(my_task(spawner, n + 1))); + spawner.spawn(unwrap!(my_task(spawner, n + 1))); } #[embassy_executor::main] async fn main(spawner: Spawner) { let _p = embassy_nrf::init(Default::default()); info!("Hello World!"); - unwrap!(spawner.spawn(my_task(spawner, 0))); + spawner.spawn(unwrap!(my_task(spawner, 0))); } diff --git a/examples/nrf52840/src/bin/self_spawn_current_executor.rs b/examples/nrf52840/src/bin/self_spawn_current_executor.rs index ddb40dc53..d93067592 100644 --- a/examples/nrf52840/src/bin/self_spawn_current_executor.rs +++ b/examples/nrf52840/src/bin/self_spawn_current_executor.rs @@ -11,12 +11,12 @@ async fn my_task(n: u32) { Timer::after_secs(1).await; info!("Spawning self! {}", n); let spawner = unsafe { Spawner::for_current_executor().await }; - unwrap!(spawner.spawn(my_task(n + 1))); + spawner.spawn(unwrap!(my_task(n + 1))); } #[embassy_executor::main] async fn main(spawner: Spawner) { let _p = embassy_nrf::init(Default::default()); info!("Hello World!"); - unwrap!(spawner.spawn(my_task(0))); + spawner.spawn(unwrap!(my_task(0))); } diff --git a/examples/nrf52840/src/bin/timer.rs b/examples/nrf52840/src/bin/timer.rs index 365695a20..5331ac246 100644 --- a/examples/nrf52840/src/bin/timer.rs +++ b/examples/nrf52840/src/bin/timer.rs @@ -25,6 +25,6 @@ async fn run2() { #[embassy_executor::main] async fn main(spawner: Spawner) { let _p = embassy_nrf::init(Default::default()); - unwrap!(spawner.spawn(run1())); - unwrap!(spawner.spawn(run2())); + spawner.spawn(unwrap!(run1())); + spawner.spawn(unwrap!(run2())); } diff --git a/examples/nrf52840/src/bin/uart_split.rs b/examples/nrf52840/src/bin/uart_split.rs index 46be8f636..51af90727 100644 --- a/examples/nrf52840/src/bin/uart_split.rs +++ b/examples/nrf52840/src/bin/uart_split.rs @@ -30,7 +30,7 @@ async fn main(spawner: Spawner) { // Spawn a task responsible purely for reading - unwrap!(spawner.spawn(reader(rx))); + spawner.spawn(unwrap!(reader(rx))); // Message must be in SRAM { diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs index 49856012d..87aa4c6c5 100644 --- a/examples/nrf52840/src/bin/usb_ethernet.rs +++ b/examples/nrf52840/src/bin/usb_ethernet.rs @@ -86,11 +86,11 @@ async fn main(spawner: Spawner) { // Build the builder. let usb = builder.build(); - unwrap!(spawner.spawn(usb_task(usb))); + spawner.spawn(unwrap!(usb_task(usb))); static NET_STATE: StaticCell> = StaticCell::new(); let (runner, device) = class.into_embassy_net_device::(NET_STATE.init(NetState::new()), our_mac_addr); - unwrap!(spawner.spawn(usb_ncm_task(runner))); + spawner.spawn(unwrap!(usb_ncm_task(runner))); let config = embassy_net::Config::dhcpv4(Default::default()); // let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { @@ -109,7 +109,7 @@ async fn main(spawner: Spawner) { static RESOURCES: StaticCell> = StaticCell::new(); let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); // And now we can use it! diff --git a/examples/nrf52840/src/bin/usb_serial_multitask.rs b/examples/nrf52840/src/bin/usb_serial_multitask.rs index 5e5b4de35..00a91a233 100644 --- a/examples/nrf52840/src/bin/usb_serial_multitask.rs +++ b/examples/nrf52840/src/bin/usb_serial_multitask.rs @@ -76,8 +76,8 @@ async fn main(spawner: Spawner) { // Build the builder. let usb = builder.build(); - unwrap!(spawner.spawn(usb_task(usb))); - unwrap!(spawner.spawn(echo_task(class))); + spawner.spawn(unwrap!(usb_task(usb))); + spawner.spawn(unwrap!(echo_task(class))); } struct Disconnected {} diff --git a/examples/nrf52840/src/bin/wifi_esp_hosted.rs b/examples/nrf52840/src/bin/wifi_esp_hosted.rs index 26eaf485e..2dd9abfaa 100644 --- a/examples/nrf52840/src/bin/wifi_esp_hosted.rs +++ b/examples/nrf52840/src/bin/wifi_esp_hosted.rs @@ -70,7 +70,7 @@ async fn main(spawner: Spawner) { ) .await; - unwrap!(spawner.spawn(wifi_task(runner))); + spawner.spawn(unwrap!(wifi_task(runner))); unwrap!(control.init().await); unwrap!(control.connect(WIFI_NETWORK, WIFI_PASSWORD).await); @@ -92,7 +92,7 @@ async fn main(spawner: Spawner) { static RESOURCES: StaticCell> = StaticCell::new(); let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); // And now we can use it! diff --git a/examples/nrf9160/src/bin/modem_tcp_client.rs b/examples/nrf9160/src/bin/modem_tcp_client.rs index a36b14626..7d4815699 100644 --- a/examples/nrf9160/src/bin/modem_tcp_client.rs +++ b/examples/nrf9160/src/bin/modem_tcp_client.rs @@ -112,7 +112,7 @@ async fn main(spawner: Spawner) { info!("Hello World!"); - unwrap!(spawner.spawn(blink_task(p.P0_02.into()))); + spawner.spawn(unwrap!(blink_task(p.P0_02.into()))); let ipc_mem = unsafe { let ipc_start = &__start_ipc as *const u8 as *mut MaybeUninit; @@ -138,8 +138,8 @@ async fn main(spawner: Spawner) { static TRACE: StaticCell = StaticCell::new(); let (device, control, runner, tracer) = embassy_net_nrf91::new_with_trace(STATE.init(State::new()), ipc_mem, TRACE.init(TraceBuffer::new())).await; - unwrap!(spawner.spawn(modem_task(runner))); - unwrap!(spawner.spawn(trace_task(uart, tracer))); + spawner.spawn(unwrap!(modem_task(runner))); + spawner.spawn(unwrap!(trace_task(uart, tracer))); let config = embassy_net::Config::default(); @@ -150,12 +150,12 @@ async fn main(spawner: Spawner) { static RESOURCES: StaticCell> = StaticCell::new(); let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::<2>::new()), seed); - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); static CONTROL: StaticCell> = StaticCell::new(); let control = CONTROL.init(context::Control::new(control, 0).await); - unwrap!(spawner.spawn(control_task( + spawner.spawn(unwrap!(control_task( control, context::Config { apn: b"iot.nat.es", diff --git a/examples/rp/src/bin/assign_resources.rs b/examples/rp/src/bin/assign_resources.rs index 341f54d22..4ee4278b5 100644 --- a/examples/rp/src/bin/assign_resources.rs +++ b/examples/rp/src/bin/assign_resources.rs @@ -26,15 +26,13 @@ async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); // 1) Assigning a resource to a task by passing parts of the peripherals. - spawner - .spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21)) - .unwrap(); + spawner.spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21).unwrap()); // 2) Using the assign-resources macro to assign resources to a task. // we perform the split, see further below for the definition of the resources struct let r = split_resources!(p); // and then we can use them - spawner.spawn(double_blinky_macro_assigned(spawner, r.leds)).unwrap(); + spawner.spawn(double_blinky_macro_assigned(spawner, r.leds).unwrap()); } // 1) Assigning a resource to a task by passing parts of the peripherals. diff --git a/examples/rp/src/bin/blinky_two_channels.rs b/examples/rp/src/bin/blinky_two_channels.rs index 51e139e94..87f3a3545 100644 --- a/examples/rp/src/bin/blinky_two_channels.rs +++ b/examples/rp/src/bin/blinky_two_channels.rs @@ -27,8 +27,8 @@ async fn main(spawner: Spawner) { let dt = 100 * 1_000_000; let k = 1.003; - unwrap!(spawner.spawn(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt)))); - unwrap!(spawner.spawn(toggle_led( + spawner.spawn(unwrap!(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt)))); + spawner.spawn(unwrap!(toggle_led( CHANNEL.sender(), Duration::from_nanos((dt as f64 * k) as u64) ))); diff --git a/examples/rp/src/bin/blinky_two_tasks.rs b/examples/rp/src/bin/blinky_two_tasks.rs index 67a9108c0..aac7d928b 100644 --- a/examples/rp/src/bin/blinky_two_tasks.rs +++ b/examples/rp/src/bin/blinky_two_tasks.rs @@ -30,8 +30,8 @@ async fn main(spawner: Spawner) { let dt = 100 * 1_000_000; let k = 1.003; - unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos(dt)))); - unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64)))); + spawner.spawn(unwrap!(toggle_led(&LED, Duration::from_nanos(dt)))); + spawner.spawn(unwrap!(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64)))); } #[embassy_executor::task(pool_size = 2)] diff --git a/examples/rp/src/bin/ethernet_w5500_icmp.rs b/examples/rp/src/bin/ethernet_w5500_icmp.rs index e434b3bbc..8c684a791 100644 --- a/examples/rp/src/bin/ethernet_w5500_icmp.rs +++ b/examples/rp/src/bin/ethernet_w5500_icmp.rs @@ -61,7 +61,7 @@ async fn main(spawner: Spawner) { ) .await .unwrap(); - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); // Generate random seed let seed = rng.next_u64(); @@ -76,7 +76,7 @@ async fn main(spawner: Spawner) { ); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); info!("Waiting for DHCP..."); let cfg = wait_for_config(stack).await; diff --git a/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs b/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs index 0ec594fd5..49d28071a 100644 --- a/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs +++ b/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs @@ -63,7 +63,7 @@ async fn main(spawner: Spawner) { ) .await .unwrap(); - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); // Generate random seed let seed = rng.next_u64(); @@ -78,7 +78,7 @@ async fn main(spawner: Spawner) { ); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); info!("Waiting for DHCP..."); let cfg = wait_for_config(stack).await; diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index 27e2f3c30..5c049ddca 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) { ) .await .unwrap(); - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); // Generate random seed let seed = rng.next_u64(); @@ -79,7 +79,7 @@ async fn main(spawner: Spawner) { ); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); info!("Waiting for DHCP..."); let cfg = wait_for_config(stack).await; @@ -87,8 +87,8 @@ async fn main(spawner: Spawner) { info!("IP address: {:?}", local_addr); // Create two sockets listening to the same port, to handle simultaneous connections - unwrap!(spawner.spawn(listen_task(stack, 0, 1234))); - unwrap!(spawner.spawn(listen_task(stack, 1, 1234))); + spawner.spawn(unwrap!(listen_task(stack, 0, 1234))); + spawner.spawn(unwrap!(listen_task(stack, 1, 1234))); } #[embassy_executor::task(pool_size = 2)] diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index ba82f2a60..7552e4f9b 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -67,7 +67,7 @@ async fn main(spawner: Spawner) { ) .await .unwrap(); - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); // Generate random seed let seed = rng.next_u64(); @@ -82,7 +82,7 @@ async fn main(spawner: Spawner) { ); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); info!("Waiting for DHCP..."); let cfg = wait_for_config(stack).await; diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index 5c56dcafa..7b6fecad4 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -66,7 +66,7 @@ async fn main(spawner: Spawner) { ) .await .unwrap(); - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); // Generate random seed let seed = rng.next_u64(); @@ -81,7 +81,7 @@ async fn main(spawner: Spawner) { ); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); info!("Waiting for DHCP..."); let cfg = wait_for_config(stack).await; diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index c5fc8de1d..f099490f5 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) { ) .await .unwrap(); - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); // Generate random seed let seed = rng.next_u64(); @@ -79,7 +79,7 @@ async fn main(spawner: Spawner) { ); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); info!("Waiting for DHCP..."); let cfg = wait_for_config(stack).await; diff --git a/examples/rp/src/bin/i2c_slave.rs b/examples/rp/src/bin/i2c_slave.rs index 08f31001b..e2b8b0d06 100644 --- a/examples/rp/src/bin/i2c_slave.rs +++ b/examples/rp/src/bin/i2c_slave.rs @@ -105,7 +105,7 @@ async fn main(spawner: Spawner) { config.addr = DEV_ADDR as u16; let device = i2c_slave::I2cSlave::new(p.I2C1, d_scl, d_sda, Irqs, config); - unwrap!(spawner.spawn(device_task(device))); + spawner.spawn(unwrap!(device_task(device))); let c_sda = p.PIN_0; let c_scl = p.PIN_1; @@ -113,5 +113,5 @@ async fn main(spawner: Spawner) { config.frequency = 1_000_000; let controller = i2c::I2c::new_async(p.I2C0, c_scl, c_sda, Irqs, config); - unwrap!(spawner.spawn(controller_task(controller))); + spawner.spawn(unwrap!(controller_task(controller))); } diff --git a/examples/rp/src/bin/interrupt.rs b/examples/rp/src/bin/interrupt.rs index 787cdc112..2748f778a 100644 --- a/examples/rp/src/bin/interrupt.rs +++ b/examples/rp/src/bin/interrupt.rs @@ -51,7 +51,7 @@ async fn main(spawner: Spawner) { // No Mutex needed when sharing within the same executor/prio level static AVG: StaticCell> = StaticCell::new(); let avg = AVG.init(Default::default()); - spawner.must_spawn(processing(avg)); + spawner.spawn(processing(avg).unwrap()); let mut ticker = Ticker::every(Duration::from_secs(1)); loop { diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs index 7cb546c91..3a6367420 100644 --- a/examples/rp/src/bin/multicore.rs +++ b/examples/rp/src/bin/multicore.rs @@ -35,12 +35,12 @@ fn main() -> ! { unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, move || { let executor1 = EXECUTOR1.init(Executor::new()); - executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led)))); + executor1.run(|spawner| spawner.spawn(unwrap!(core1_task(led)))); }, ); let executor0 = EXECUTOR0.init(Executor::new()); - executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); + executor0.run(|spawner| spawner.spawn(unwrap!(core0_task()))); } #[embassy_executor::task] diff --git a/examples/rp/src/bin/multiprio.rs b/examples/rp/src/bin/multiprio.rs index 2b397f97d..96cdf8fb1 100644 --- a/examples/rp/src/bin/multiprio.rs +++ b/examples/rp/src/bin/multiprio.rs @@ -130,16 +130,16 @@ fn main() -> ! { // High-priority executor: SWI_IRQ_1, priority level 2 interrupt::SWI_IRQ_1.set_priority(Priority::P2); let spawner = EXECUTOR_HIGH.start(interrupt::SWI_IRQ_1); - unwrap!(spawner.spawn(run_high())); + spawner.spawn(unwrap!(run_high())); // Medium-priority executor: SWI_IRQ_0, priority level 3 interrupt::SWI_IRQ_0.set_priority(Priority::P3); let spawner = EXECUTOR_MED.start(interrupt::SWI_IRQ_0); - unwrap!(spawner.spawn(run_med())); + spawner.spawn(unwrap!(run_med())); // Low priority executor: runs in thread mode, using WFE/SEV let executor = EXECUTOR_LOW.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(run_low())); + spawner.spawn(unwrap!(run_low())); }); } diff --git a/examples/rp/src/bin/orchestrate_tasks.rs b/examples/rp/src/bin/orchestrate_tasks.rs index c35679251..9f25e1087 100644 --- a/examples/rp/src/bin/orchestrate_tasks.rs +++ b/examples/rp/src/bin/orchestrate_tasks.rs @@ -129,13 +129,13 @@ async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); let r = split_resources! {p}; - spawner.spawn(orchestrate(spawner)).unwrap(); - spawner.spawn(random_60s(spawner)).unwrap(); - spawner.spawn(random_90s(spawner)).unwrap(); + spawner.spawn(orchestrate(spawner).unwrap()); + spawner.spawn(random_60s(spawner).unwrap()); + spawner.spawn(random_90s(spawner).unwrap()); // `random_30s` is not spawned here, butin the orchestrate task depending on state - spawner.spawn(usb_power(spawner, r.vbus)).unwrap(); - spawner.spawn(vsys_voltage(spawner, r.vsys)).unwrap(); - spawner.spawn(consumer(spawner)).unwrap(); + spawner.spawn(usb_power(spawner, r.vbus).unwrap()); + spawner.spawn(vsys_voltage(spawner, r.vsys).unwrap()); + spawner.spawn(consumer(spawner).unwrap()); } /// Main task that processes all events and updates system state. @@ -198,7 +198,7 @@ async fn orchestrate(spawner: Spawner) { drop(state); if respawn_first_random_seed_task { info!("(Re)-Starting the first random signal task"); - spawner.spawn(random_30s(spawner)).unwrap(); + spawner.spawn(random_30s(spawner).unwrap()); } } _ => {} diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index bf6dbee69..1743a417e 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -125,7 +125,7 @@ async fn main(spawner: Spawner) { setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); setup_pio_task_sm1(&mut common, &mut sm1); setup_pio_task_sm2(&mut common, &mut sm2); - spawner.spawn(pio_task_sm0(sm0)).unwrap(); - spawner.spawn(pio_task_sm1(sm1)).unwrap(); - spawner.spawn(pio_task_sm2(irq3, sm2)).unwrap(); + spawner.spawn(pio_task_sm0(sm0).unwrap()); + spawner.spawn(pio_task_sm1(sm1).unwrap()); + spawner.spawn(pio_task_sm2(irq3, sm2).unwrap()); } diff --git a/examples/rp/src/bin/pio_rotary_encoder.rs b/examples/rp/src/bin/pio_rotary_encoder.rs index 2750f61ae..2fc19970b 100644 --- a/examples/rp/src/bin/pio_rotary_encoder.rs +++ b/examples/rp/src/bin/pio_rotary_encoder.rs @@ -50,6 +50,6 @@ async fn main(spawner: Spawner) { let encoder0 = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5, &prg); let encoder1 = PioEncoder::new(&mut common, sm1, p.PIN_6, p.PIN_7, &prg); - spawner.must_spawn(encoder_0(encoder0)); - spawner.must_spawn(encoder_1(encoder1)); + spawner.spawn(encoder_0(encoder0).unwrap()); + spawner.spawn(encoder_1(encoder1).unwrap()); } diff --git a/examples/rp/src/bin/pwm.rs b/examples/rp/src/bin/pwm.rs index 04374323d..9dd07ab6e 100644 --- a/examples/rp/src/bin/pwm.rs +++ b/examples/rp/src/bin/pwm.rs @@ -18,8 +18,8 @@ use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); - spawner.spawn(pwm_set_config(p.PWM_SLICE4, p.PIN_25)).unwrap(); - spawner.spawn(pwm_set_dutycycle(p.PWM_SLICE2, p.PIN_4)).unwrap(); + spawner.spawn(pwm_set_config(p.PWM_SLICE4, p.PIN_25).unwrap()); + spawner.spawn(pwm_set_dutycycle(p.PWM_SLICE2, p.PIN_4).unwrap()); } /// Demonstrate PWM by modifying & applying the config diff --git a/examples/rp/src/bin/shared_bus.rs b/examples/rp/src/bin/shared_bus.rs index 9267dfccb..db7566b1a 100644 --- a/examples/rp/src/bin/shared_bus.rs +++ b/examples/rp/src/bin/shared_bus.rs @@ -35,8 +35,8 @@ async fn main(spawner: Spawner) { static I2C_BUS: StaticCell = StaticCell::new(); let i2c_bus = I2C_BUS.init(Mutex::new(i2c)); - spawner.must_spawn(i2c_task_a(i2c_bus)); - spawner.must_spawn(i2c_task_b(i2c_bus)); + spawner.spawn(i2c_task_a(i2c_bus).unwrap()); + spawner.spawn(i2c_task_b(i2c_bus).unwrap()); // Shared SPI bus let spi_cfg = spi::Config::default(); @@ -48,8 +48,8 @@ async fn main(spawner: Spawner) { let cs_a = Output::new(p.PIN_0, Level::High); let cs_b = Output::new(p.PIN_1, Level::High); - spawner.must_spawn(spi_task_a(spi_bus, cs_a)); - spawner.must_spawn(spi_task_b(spi_bus, cs_b)); + spawner.spawn(spi_task_a(spi_bus, cs_a).unwrap()); + spawner.spawn(spi_task_b(spi_bus, cs_b).unwrap()); } #[embassy_executor::task] diff --git a/examples/rp/src/bin/sharing.rs b/examples/rp/src/bin/sharing.rs index 856be6ace..d4c89946b 100644 --- a/examples/rp/src/bin/sharing.rs +++ b/examples/rp/src/bin/sharing.rs @@ -68,7 +68,7 @@ fn main() -> ! { // High-priority executor: runs in interrupt mode interrupt::SWI_IRQ_0.set_priority(Priority::P3); let spawner = EXECUTOR_HI.start(interrupt::SWI_IRQ_0); - spawner.must_spawn(task_a(uart)); + spawner.spawn(task_a(uart).unwrap()); // Low priority executor: runs in thread mode let executor = EXECUTOR_LOW.init(Executor::new()); @@ -83,8 +83,8 @@ fn main() -> ! { static REF_CELL: ConstStaticCell> = ConstStaticCell::new(RefCell::new(MyType { inner: 0 })); let ref_cell = REF_CELL.take(); - spawner.must_spawn(task_b(uart, cell, ref_cell)); - spawner.must_spawn(task_c(cell, ref_cell)); + spawner.spawn(task_b(uart, cell, ref_cell).unwrap()); + spawner.spawn(task_c(cell, ref_cell).unwrap()); }); } diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs index 3adbc18ab..820daed96 100644 --- a/examples/rp/src/bin/uart_buffered_split.rs +++ b/examples/rp/src/bin/uart_buffered_split.rs @@ -33,7 +33,7 @@ async fn main(spawner: Spawner) { let uart = BufferedUart::new(uart, tx_pin, rx_pin, Irqs, tx_buf, rx_buf, Config::default()); let (mut tx, rx) = uart.split(); - unwrap!(spawner.spawn(reader(rx))); + spawner.spawn(unwrap!(reader(rx))); info!("Writing..."); loop { diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs index c2c8dfad8..573b45b51 100644 --- a/examples/rp/src/bin/uart_unidir.rs +++ b/examples/rp/src/bin/uart_unidir.rs @@ -27,7 +27,7 @@ async fn main(spawner: Spawner) { let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default()); - unwrap!(spawner.spawn(reader(uart_rx))); + spawner.spawn(unwrap!(reader(uart_rx))); info!("Writing..."); loop { diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 171f21a75..912e52e96 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -84,11 +84,11 @@ async fn main(spawner: Spawner) { // Build the builder. let usb = builder.build(); - unwrap!(spawner.spawn(usb_task(usb))); + spawner.spawn(unwrap!(usb_task(usb))); static NET_STATE: StaticCell> = StaticCell::new(); let (runner, device) = class.into_embassy_net_device::(NET_STATE.init(NetState::new()), our_mac_addr); - unwrap!(spawner.spawn(usb_ncm_task(runner))); + spawner.spawn(unwrap!(usb_ncm_task(runner))); let config = embassy_net::Config::dhcpv4(Default::default()); //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { @@ -104,7 +104,7 @@ async fn main(spawner: Spawner) { static RESOURCES: StaticCell> = StaticCell::new(); let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); // And now we can use it! diff --git a/examples/rp/src/bin/usb_logger.rs b/examples/rp/src/bin/usb_logger.rs index af401ed63..ed2333efc 100644 --- a/examples/rp/src/bin/usb_logger.rs +++ b/examples/rp/src/bin/usb_logger.rs @@ -25,7 +25,7 @@ async fn logger_task(driver: Driver<'static, USB>) { async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); let driver = Driver::new(p.USB, Irqs); - spawner.spawn(logger_task(driver)).unwrap(); + spawner.spawn(logger_task(driver).unwrap()); let mut counter = 0; loop { diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index 5e3f0f378..b79012acb 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs @@ -69,7 +69,7 @@ async fn main(spawner: Spawner) { let usb = builder.build(); // Run the USB device. - unwrap!(spawner.spawn(usb_task(usb))); + spawner.spawn(unwrap!(usb_task(usb))); // Do stuff with the class! loop { diff --git a/examples/rp/src/bin/usb_serial_with_handler.rs b/examples/rp/src/bin/usb_serial_with_handler.rs index a9e65be70..b85c9029b 100644 --- a/examples/rp/src/bin/usb_serial_with_handler.rs +++ b/examples/rp/src/bin/usb_serial_with_handler.rs @@ -53,7 +53,7 @@ async fn logger_task(driver: Driver<'static, USB>) { async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); let driver = Driver::new(p.USB, Irqs); - spawner.spawn(logger_task(driver)).unwrap(); + spawner.spawn(logger_task(driver).unwrap()); let mut counter = 0; loop { diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index 856838a8c..128599e0d 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs @@ -70,7 +70,7 @@ async fn main(spawner: Spawner) { static STATE: StaticCell = StaticCell::new(); let state = STATE.init(cyw43::State::new()); let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; - unwrap!(spawner.spawn(cyw43_task(runner))); + spawner.spawn(unwrap!(cyw43_task(runner))); control.init(clm).await; control @@ -91,7 +91,7 @@ async fn main(spawner: Spawner) { static RESOURCES: StaticCell> = StaticCell::new(); let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); //control.start_ap_open("cyw43", 5).await; control.start_ap_wpa2("cyw43", "password", 5).await; diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs index 6e91ce167..b2e08c517 100644 --- a/examples/rp/src/bin/wifi_blinky.rs +++ b/examples/rp/src/bin/wifi_blinky.rs @@ -55,7 +55,7 @@ async fn main(spawner: Spawner) { static STATE: StaticCell = StaticCell::new(); let state = STATE.init(cyw43::State::new()); let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; - unwrap!(spawner.spawn(cyw43_task(runner))); + spawner.spawn(unwrap!(cyw43_task(runner))); control.init(clm).await; control diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index fe9c363d9..c884aa2ba 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs @@ -59,7 +59,7 @@ async fn main(spawner: Spawner) { static STATE: StaticCell = StaticCell::new(); let state = STATE.init(cyw43::State::new()); let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; - unwrap!(spawner.spawn(cyw43_task(runner))); + spawner.spawn(unwrap!(cyw43_task(runner))); control.init(clm).await; control diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index ed1a03fcf..126475779 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -74,7 +74,7 @@ async fn main(spawner: Spawner) { static STATE: StaticCell = StaticCell::new(); let state = STATE.init(cyw43::State::new()); let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; - unwrap!(spawner.spawn(cyw43_task(runner))); + spawner.spawn(unwrap!(cyw43_task(runner))); control.init(clm).await; control @@ -95,7 +95,7 @@ async fn main(spawner: Spawner) { static RESOURCES: StaticCell> = StaticCell::new(); let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); while let Err(err) = control .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) diff --git a/examples/rp/src/bin/wifi_webrequest.rs b/examples/rp/src/bin/wifi_webrequest.rs index a75253bb0..079def370 100644 --- a/examples/rp/src/bin/wifi_webrequest.rs +++ b/examples/rp/src/bin/wifi_webrequest.rs @@ -76,7 +76,7 @@ async fn main(spawner: Spawner) { static STATE: StaticCell = StaticCell::new(); let state = STATE.init(cyw43::State::new()); let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; - unwrap!(spawner.spawn(cyw43_task(runner))); + spawner.spawn(unwrap!(cyw43_task(runner))); control.init(clm).await; control @@ -98,7 +98,7 @@ async fn main(spawner: Spawner) { static RESOURCES: StaticCell> = StaticCell::new(); let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); while let Err(err) = control .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) diff --git a/examples/rp/src/bin/zerocopy.rs b/examples/rp/src/bin/zerocopy.rs index d1fb0eb00..d603e1ed3 100644 --- a/examples/rp/src/bin/zerocopy.rs +++ b/examples/rp/src/bin/zerocopy.rs @@ -52,8 +52,8 @@ async fn main(spawner: Spawner) { let channel = CHANNEL.init(Channel::new(buf)); let (sender, receiver) = channel.split(); - spawner.must_spawn(consumer(receiver)); - spawner.must_spawn(producer(sender, adc_parts)); + spawner.spawn(consumer(receiver).unwrap()); + spawner.spawn(producer(sender, adc_parts).unwrap()); let mut ticker = Ticker::every(Duration::from_secs(1)); loop { diff --git a/examples/rp235x/src/bin/assign_resources.rs b/examples/rp235x/src/bin/assign_resources.rs index 341f54d22..4ee4278b5 100644 --- a/examples/rp235x/src/bin/assign_resources.rs +++ b/examples/rp235x/src/bin/assign_resources.rs @@ -26,15 +26,13 @@ async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); // 1) Assigning a resource to a task by passing parts of the peripherals. - spawner - .spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21)) - .unwrap(); + spawner.spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21).unwrap()); // 2) Using the assign-resources macro to assign resources to a task. // we perform the split, see further below for the definition of the resources struct let r = split_resources!(p); // and then we can use them - spawner.spawn(double_blinky_macro_assigned(spawner, r.leds)).unwrap(); + spawner.spawn(double_blinky_macro_assigned(spawner, r.leds).unwrap()); } // 1) Assigning a resource to a task by passing parts of the peripherals. diff --git a/examples/rp235x/src/bin/blinky_two_channels.rs b/examples/rp235x/src/bin/blinky_two_channels.rs index 51e139e94..87f3a3545 100644 --- a/examples/rp235x/src/bin/blinky_two_channels.rs +++ b/examples/rp235x/src/bin/blinky_two_channels.rs @@ -27,8 +27,8 @@ async fn main(spawner: Spawner) { let dt = 100 * 1_000_000; let k = 1.003; - unwrap!(spawner.spawn(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt)))); - unwrap!(spawner.spawn(toggle_led( + spawner.spawn(unwrap!(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt)))); + spawner.spawn(unwrap!(toggle_led( CHANNEL.sender(), Duration::from_nanos((dt as f64 * k) as u64) ))); diff --git a/examples/rp235x/src/bin/blinky_two_tasks.rs b/examples/rp235x/src/bin/blinky_two_tasks.rs index 67a9108c0..aac7d928b 100644 --- a/examples/rp235x/src/bin/blinky_two_tasks.rs +++ b/examples/rp235x/src/bin/blinky_two_tasks.rs @@ -30,8 +30,8 @@ async fn main(spawner: Spawner) { let dt = 100 * 1_000_000; let k = 1.003; - unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos(dt)))); - unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64)))); + spawner.spawn(unwrap!(toggle_led(&LED, Duration::from_nanos(dt)))); + spawner.spawn(unwrap!(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64)))); } #[embassy_executor::task(pool_size = 2)] diff --git a/examples/rp235x/src/bin/blinky_wifi.rs b/examples/rp235x/src/bin/blinky_wifi.rs index ef6057a1c..b2201f0ae 100644 --- a/examples/rp235x/src/bin/blinky_wifi.rs +++ b/examples/rp235x/src/bin/blinky_wifi.rs @@ -71,7 +71,7 @@ async fn main(spawner: Spawner) { static STATE: StaticCell = StaticCell::new(); let state = STATE.init(cyw43::State::new()); let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; - unwrap!(spawner.spawn(cyw43_task(runner))); + spawner.spawn(unwrap!(cyw43_task(runner))); control.init(clm).await; control diff --git a/examples/rp235x/src/bin/blinky_wifi_pico_plus_2.rs b/examples/rp235x/src/bin/blinky_wifi_pico_plus_2.rs index 0a5bccfb3..e6d6f687b 100644 --- a/examples/rp235x/src/bin/blinky_wifi_pico_plus_2.rs +++ b/examples/rp235x/src/bin/blinky_wifi_pico_plus_2.rs @@ -68,7 +68,7 @@ async fn main(spawner: Spawner) { static STATE: StaticCell = StaticCell::new(); let state = STATE.init(cyw43::State::new()); let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; - unwrap!(spawner.spawn(cyw43_task(runner))); + spawner.spawn(unwrap!(cyw43_task(runner))); control.init(clm).await; control diff --git a/examples/rp235x/src/bin/i2c_slave.rs b/examples/rp235x/src/bin/i2c_slave.rs index 9fffb4646..02ad9a003 100644 --- a/examples/rp235x/src/bin/i2c_slave.rs +++ b/examples/rp235x/src/bin/i2c_slave.rs @@ -105,7 +105,7 @@ async fn main(spawner: Spawner) { config.addr = DEV_ADDR as u16; let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config); - unwrap!(spawner.spawn(device_task(device))); + spawner.spawn(unwrap!(device_task(device))); let c_sda = p.PIN_1; let c_scl = p.PIN_0; @@ -113,5 +113,5 @@ async fn main(spawner: Spawner) { config.frequency = 1_000_000; let controller = i2c::I2c::new_async(p.I2C0, c_sda, c_scl, Irqs, config); - unwrap!(spawner.spawn(controller_task(controller))); + spawner.spawn(unwrap!(controller_task(controller))); } diff --git a/examples/rp235x/src/bin/interrupt.rs b/examples/rp235x/src/bin/interrupt.rs index e9ac76486..88513180c 100644 --- a/examples/rp235x/src/bin/interrupt.rs +++ b/examples/rp235x/src/bin/interrupt.rs @@ -51,7 +51,7 @@ async fn main(spawner: Spawner) { // No Mutex needed when sharing within the same executor/prio level static AVG: StaticCell> = StaticCell::new(); let avg = AVG.init(Default::default()); - spawner.must_spawn(processing(avg)); + spawner.spawn(processing(avg).unwrap()); let mut ticker = Ticker::every(Duration::from_secs(1)); loop { diff --git a/examples/rp235x/src/bin/multicore.rs b/examples/rp235x/src/bin/multicore.rs index f02dc3876..4f82801d6 100644 --- a/examples/rp235x/src/bin/multicore.rs +++ b/examples/rp235x/src/bin/multicore.rs @@ -35,12 +35,12 @@ fn main() -> ! { unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, move || { let executor1 = EXECUTOR1.init(Executor::new()); - executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led)))); + executor1.run(|spawner| spawner.spawn(unwrap!(core1_task(led)))); }, ); let executor0 = EXECUTOR0.init(Executor::new()); - executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); + executor0.run(|spawner| spawner.spawn(unwrap!(core0_task()))); } #[embassy_executor::task] diff --git a/examples/rp235x/src/bin/multiprio.rs b/examples/rp235x/src/bin/multiprio.rs index 2b397f97d..96cdf8fb1 100644 --- a/examples/rp235x/src/bin/multiprio.rs +++ b/examples/rp235x/src/bin/multiprio.rs @@ -130,16 +130,16 @@ fn main() -> ! { // High-priority executor: SWI_IRQ_1, priority level 2 interrupt::SWI_IRQ_1.set_priority(Priority::P2); let spawner = EXECUTOR_HIGH.start(interrupt::SWI_IRQ_1); - unwrap!(spawner.spawn(run_high())); + spawner.spawn(unwrap!(run_high())); // Medium-priority executor: SWI_IRQ_0, priority level 3 interrupt::SWI_IRQ_0.set_priority(Priority::P3); let spawner = EXECUTOR_MED.start(interrupt::SWI_IRQ_0); - unwrap!(spawner.spawn(run_med())); + spawner.spawn(unwrap!(run_med())); // Low priority executor: runs in thread mode, using WFE/SEV let executor = EXECUTOR_LOW.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(run_low())); + spawner.spawn(unwrap!(run_low())); }); } diff --git a/examples/rp235x/src/bin/pio_async.rs b/examples/rp235x/src/bin/pio_async.rs index a519b8a50..d76930f5c 100644 --- a/examples/rp235x/src/bin/pio_async.rs +++ b/examples/rp235x/src/bin/pio_async.rs @@ -125,7 +125,7 @@ async fn main(spawner: Spawner) { setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); setup_pio_task_sm1(&mut common, &mut sm1); setup_pio_task_sm2(&mut common, &mut sm2); - spawner.spawn(pio_task_sm0(sm0)).unwrap(); - spawner.spawn(pio_task_sm1(sm1)).unwrap(); - spawner.spawn(pio_task_sm2(irq3, sm2)).unwrap(); + spawner.spawn(pio_task_sm0(sm0).unwrap()); + spawner.spawn(pio_task_sm1(sm1).unwrap()); + spawner.spawn(pio_task_sm2(irq3, sm2).unwrap()); } diff --git a/examples/rp235x/src/bin/pio_rotary_encoder.rs b/examples/rp235x/src/bin/pio_rotary_encoder.rs index e820d316d..610d1a40b 100644 --- a/examples/rp235x/src/bin/pio_rotary_encoder.rs +++ b/examples/rp235x/src/bin/pio_rotary_encoder.rs @@ -50,6 +50,6 @@ async fn main(spawner: Spawner) { let encoder0 = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5, &prg); let encoder1 = PioEncoder::new(&mut common, sm1, p.PIN_6, p.PIN_7, &prg); - spawner.must_spawn(encoder_0(encoder0)); - spawner.must_spawn(encoder_1(encoder1)); + spawner.spawn(encoder_0(encoder0).unwrap()); + spawner.spawn(encoder_1(encoder1).unwrap()); } diff --git a/examples/rp235x/src/bin/pwm.rs b/examples/rp235x/src/bin/pwm.rs index da1acc18a..289480c85 100644 --- a/examples/rp235x/src/bin/pwm.rs +++ b/examples/rp235x/src/bin/pwm.rs @@ -18,8 +18,8 @@ use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); - spawner.spawn(pwm_set_config(p.PWM_SLICE4, p.PIN_25)).unwrap(); - spawner.spawn(pwm_set_dutycycle(p.PWM_SLICE2, p.PIN_4)).unwrap(); + spawner.spawn(pwm_set_config(p.PWM_SLICE4, p.PIN_25).unwrap()); + spawner.spawn(pwm_set_dutycycle(p.PWM_SLICE2, p.PIN_4).unwrap()); } /// Demonstrate PWM by modifying & applying the config diff --git a/examples/rp235x/src/bin/shared_bus.rs b/examples/rp235x/src/bin/shared_bus.rs index 9267dfccb..db7566b1a 100644 --- a/examples/rp235x/src/bin/shared_bus.rs +++ b/examples/rp235x/src/bin/shared_bus.rs @@ -35,8 +35,8 @@ async fn main(spawner: Spawner) { static I2C_BUS: StaticCell = StaticCell::new(); let i2c_bus = I2C_BUS.init(Mutex::new(i2c)); - spawner.must_spawn(i2c_task_a(i2c_bus)); - spawner.must_spawn(i2c_task_b(i2c_bus)); + spawner.spawn(i2c_task_a(i2c_bus).unwrap()); + spawner.spawn(i2c_task_b(i2c_bus).unwrap()); // Shared SPI bus let spi_cfg = spi::Config::default(); @@ -48,8 +48,8 @@ async fn main(spawner: Spawner) { let cs_a = Output::new(p.PIN_0, Level::High); let cs_b = Output::new(p.PIN_1, Level::High); - spawner.must_spawn(spi_task_a(spi_bus, cs_a)); - spawner.must_spawn(spi_task_b(spi_bus, cs_b)); + spawner.spawn(spi_task_a(spi_bus, cs_a).unwrap()); + spawner.spawn(spi_task_b(spi_bus, cs_b).unwrap()); } #[embassy_executor::task] diff --git a/examples/rp235x/src/bin/sharing.rs b/examples/rp235x/src/bin/sharing.rs index 856be6ace..d4c89946b 100644 --- a/examples/rp235x/src/bin/sharing.rs +++ b/examples/rp235x/src/bin/sharing.rs @@ -68,7 +68,7 @@ fn main() -> ! { // High-priority executor: runs in interrupt mode interrupt::SWI_IRQ_0.set_priority(Priority::P3); let spawner = EXECUTOR_HI.start(interrupt::SWI_IRQ_0); - spawner.must_spawn(task_a(uart)); + spawner.spawn(task_a(uart).unwrap()); // Low priority executor: runs in thread mode let executor = EXECUTOR_LOW.init(Executor::new()); @@ -83,8 +83,8 @@ fn main() -> ! { static REF_CELL: ConstStaticCell> = ConstStaticCell::new(RefCell::new(MyType { inner: 0 })); let ref_cell = REF_CELL.take(); - spawner.must_spawn(task_b(uart, cell, ref_cell)); - spawner.must_spawn(task_c(cell, ref_cell)); + spawner.spawn(task_b(uart, cell, ref_cell).unwrap()); + spawner.spawn(task_c(cell, ref_cell).unwrap()); }); } diff --git a/examples/rp235x/src/bin/uart_buffered_split.rs b/examples/rp235x/src/bin/uart_buffered_split.rs index 7cad09f9b..061be873d 100644 --- a/examples/rp235x/src/bin/uart_buffered_split.rs +++ b/examples/rp235x/src/bin/uart_buffered_split.rs @@ -33,7 +33,7 @@ async fn main(spawner: Spawner) { let uart = BufferedUart::new(uart, tx_pin, rx_pin, Irqs, tx_buf, rx_buf, Config::default()); let (mut tx, rx) = uart.split(); - unwrap!(spawner.spawn(reader(rx))); + spawner.spawn(unwrap!(reader(rx))); info!("Writing..."); loop { diff --git a/examples/rp235x/src/bin/uart_unidir.rs b/examples/rp235x/src/bin/uart_unidir.rs index 45c9c8407..0c80d24c9 100644 --- a/examples/rp235x/src/bin/uart_unidir.rs +++ b/examples/rp235x/src/bin/uart_unidir.rs @@ -27,7 +27,7 @@ async fn main(spawner: Spawner) { let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default()); - unwrap!(spawner.spawn(reader(uart_rx))); + spawner.spawn(unwrap!(reader(uart_rx))); info!("Writing..."); loop { diff --git a/examples/rp235x/src/bin/zerocopy.rs b/examples/rp235x/src/bin/zerocopy.rs index 086c86cac..62ba4cfb8 100644 --- a/examples/rp235x/src/bin/zerocopy.rs +++ b/examples/rp235x/src/bin/zerocopy.rs @@ -52,8 +52,8 @@ async fn main(spawner: Spawner) { let channel = CHANNEL.init(Channel::new(buf)); let (sender, receiver) = channel.split(); - spawner.must_spawn(consumer(receiver)); - spawner.must_spawn(producer(sender, adc_parts)); + spawner.spawn(consumer(receiver).unwrap()); + spawner.spawn(producer(sender, adc_parts).unwrap()); let mut ticker = Ticker::every(Duration::from_secs(1)); loop { diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs index 232cf494b..fd7b6c930 100644 --- a/examples/std/src/bin/net.rs +++ b/examples/std/src/bin/net.rs @@ -56,7 +56,7 @@ async fn main_task(spawner: Spawner) { let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task - spawner.spawn(net_task(runner)).unwrap(); + spawner.spawn(net_task(runner).unwrap()); // Then we can use it! let mut rx_buffer = [0; 4096]; @@ -95,6 +95,6 @@ fn main() { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - spawner.spawn(main_task(spawner)).unwrap(); + spawner.spawn(main_task(spawner).unwrap()); }); } diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs index cf90731dd..dff704b86 100644 --- a/examples/std/src/bin/net_dns.rs +++ b/examples/std/src/bin/net_dns.rs @@ -53,7 +53,7 @@ async fn main_task(spawner: Spawner) { let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task - spawner.spawn(net_task(runner)).unwrap(); + spawner.spawn(net_task(runner).unwrap()); let host = "example.com"; info!("querying host {:?}...", host); @@ -78,6 +78,6 @@ fn main() { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - spawner.spawn(main_task(spawner)).unwrap(); + spawner.spawn(main_task(spawner).unwrap()); }); } diff --git a/examples/std/src/bin/net_ppp.rs b/examples/std/src/bin/net_ppp.rs index ac3aea6ff..82272c798 100644 --- a/examples/std/src/bin/net_ppp.rs +++ b/examples/std/src/bin/net_ppp.rs @@ -102,8 +102,8 @@ async fn main_task(spawner: Spawner) { ); // Launch network task - spawner.spawn(net_task(net_runner)).unwrap(); - spawner.spawn(ppp_task(stack, runner, port)).unwrap(); + spawner.spawn(net_task(net_runner).unwrap()); + spawner.spawn(ppp_task(stack, runner, port).unwrap()); // Then we can use it! let mut rx_buffer = [0; 4096]; @@ -160,6 +160,6 @@ fn main() { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - spawner.spawn(main_task(spawner)).unwrap(); + spawner.spawn(main_task(spawner).unwrap()); }); } diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs index 53632a5b4..c5c4da65f 100644 --- a/examples/std/src/bin/net_udp.rs +++ b/examples/std/src/bin/net_udp.rs @@ -52,7 +52,7 @@ async fn main_task(spawner: Spawner) { let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task - spawner.spawn(net_task(runner)).unwrap(); + spawner.spawn(net_task(runner).unwrap()); // Then we can use it! let mut rx_meta = [PacketMetadata::EMPTY; 16]; @@ -86,6 +86,6 @@ fn main() { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - spawner.spawn(main_task(spawner)).unwrap(); + spawner.spawn(main_task(spawner).unwrap()); }); } diff --git a/examples/std/src/bin/serial.rs b/examples/std/src/bin/serial.rs index 10c85511d..1ed9997c4 100644 --- a/examples/std/src/bin/serial.rs +++ b/examples/std/src/bin/serial.rs @@ -50,6 +50,6 @@ fn main() { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - spawner.spawn(run()).unwrap(); + spawner.spawn(run().unwrap()); }); } diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs index 961c20e2d..77886f471 100644 --- a/examples/std/src/bin/tcp_accept.rs +++ b/examples/std/src/bin/tcp_accept.rs @@ -54,7 +54,7 @@ async fn main_task(spawner: Spawner) { let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task - spawner.spawn(net_task(runner)).unwrap(); + spawner.spawn(net_task(runner).unwrap()); // Then we can use it! let mut rx_buffer = [0; 4096]; @@ -101,6 +101,6 @@ fn main() { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - spawner.spawn(main_task(spawner)).unwrap(); + spawner.spawn(main_task(spawner).unwrap()); }); } diff --git a/examples/std/src/bin/tick.rs b/examples/std/src/bin/tick.rs index f23cf3549..16b82c82b 100644 --- a/examples/std/src/bin/tick.rs +++ b/examples/std/src/bin/tick.rs @@ -17,5 +17,5 @@ async fn main(spawner: Spawner) { .format_timestamp_nanos() .init(); - spawner.spawn(run()).unwrap(); + spawner.spawn(run().unwrap()); } diff --git a/examples/stm32f0/src/bin/button_controlled_blink.rs b/examples/stm32f0/src/bin/button_controlled_blink.rs index 744df3e3b..f232e3290 100644 --- a/examples/stm32f0/src/bin/button_controlled_blink.rs +++ b/examples/stm32f0/src/bin/button_controlled_blink.rs @@ -46,7 +46,7 @@ async fn main(spawner: Spawner) { BLINK_MS.store(del_var, Ordering::Relaxed); // Spawn LED blinking task - spawner.spawn(led_task(p.PA5.into())).unwrap(); + spawner.spawn(led_task(p.PA5.into()).unwrap()); loop { // Check if button got pressed diff --git a/examples/stm32f0/src/bin/multiprio.rs b/examples/stm32f0/src/bin/multiprio.rs index 84e4077ef..b5244afc8 100644 --- a/examples/stm32f0/src/bin/multiprio.rs +++ b/examples/stm32f0/src/bin/multiprio.rs @@ -134,16 +134,16 @@ fn main() -> ! { // High-priority executor: USART1, priority level 6 interrupt::USART1.set_priority(Priority::P6); let spawner = EXECUTOR_HIGH.start(interrupt::USART1); - unwrap!(spawner.spawn(run_high())); + spawner.spawn(unwrap!(run_high())); // Medium-priority executor: USART2, priority level 7 interrupt::USART2.set_priority(Priority::P7); let spawner = EXECUTOR_MED.start(interrupt::USART2); - unwrap!(spawner.spawn(run_med())); + spawner.spawn(unwrap!(run_med())); // Low priority executor: runs in thread mode, using WFE/SEV let executor = EXECUTOR_LOW.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(run_low())); + spawner.spawn(unwrap!(run_low())); }); } diff --git a/examples/stm32f1/src/bin/input_capture.rs b/examples/stm32f1/src/bin/input_capture.rs index 84811fb95..d747a43c2 100644 --- a/examples/stm32f1/src/bin/input_capture.rs +++ b/examples/stm32f1/src/bin/input_capture.rs @@ -37,7 +37,7 @@ async fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - unwrap!(spawner.spawn(blinky(p.PC13))); + spawner.spawn(unwrap!(blinky(p.PC13))); let ch3 = CapturePin::new(p.PA2, Pull::None); let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs index aa6a11ff8..63b899767 100644 --- a/examples/stm32f1/src/bin/pwm_input.rs +++ b/examples/stm32f1/src/bin/pwm_input.rs @@ -36,7 +36,7 @@ async fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - unwrap!(spawner.spawn(blinky(p.PC13))); + spawner.spawn(unwrap!(blinky(p.PC13))); let mut pwm_input = PwmInput::new_ch1(p.TIM2, p.PA0, Pull::None, khz(10)); pwm_input.enable(); diff --git a/examples/stm32f3/src/bin/button_events.rs b/examples/stm32f3/src/bin/button_events.rs index f5ed5d2c9..a54d03212 100644 --- a/examples/stm32f3/src/bin/button_events.rs +++ b/examples/stm32f3/src/bin/button_events.rs @@ -113,8 +113,8 @@ async fn main(spawner: Spawner) { ]; let leds = Leds::new(leds); - spawner.spawn(button_waiter(button)).unwrap(); - spawner.spawn(led_blinker(leds)).unwrap(); + spawner.spawn(button_waiter(button).unwrap()); + spawner.spawn(led_blinker(leds).unwrap()); } #[embassy_executor::task] diff --git a/examples/stm32f3/src/bin/multiprio.rs b/examples/stm32f3/src/bin/multiprio.rs index b4620888f..2f2ffdea2 100644 --- a/examples/stm32f3/src/bin/multiprio.rs +++ b/examples/stm32f3/src/bin/multiprio.rs @@ -135,16 +135,16 @@ fn main() -> ! { // High-priority executor: UART4, priority level 6 interrupt::UART4.set_priority(Priority::P6); let spawner = EXECUTOR_HIGH.start(interrupt::UART4); - unwrap!(spawner.spawn(run_high())); + spawner.spawn(unwrap!(run_high())); // Medium-priority executor: UART5, priority level 7 interrupt::UART5.set_priority(Priority::P7); let spawner = EXECUTOR_MED.start(interrupt::UART5); - unwrap!(spawner.spawn(run_med())); + spawner.spawn(unwrap!(run_med())); // Low priority executor: runs in thread mode, using WFE/SEV let executor = EXECUTOR_LOW.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(run_low())); + spawner.spawn(unwrap!(run_low())); }); } diff --git a/examples/stm32f4/src/bin/adc_dma.rs b/examples/stm32f4/src/bin/adc_dma.rs index 43a761e6d..2ec48640e 100644 --- a/examples/stm32f4/src/bin/adc_dma.rs +++ b/examples/stm32f4/src/bin/adc_dma.rs @@ -11,7 +11,7 @@ use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - spawner.must_spawn(adc_task(p)); + spawner.spawn(adc_task(p).unwrap()); } #[embassy_executor::task] diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs index 634d8e2c6..f41a60529 100644 --- a/examples/stm32f4/src/bin/eth.rs +++ b/examples/stm32f4/src/bin/eth.rs @@ -91,7 +91,7 @@ async fn main(spawner: Spawner) -> ! { let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); // Ensure DHCP configuration is up before trying connect stack.wait_config_up().await; diff --git a/examples/stm32f4/src/bin/eth_w5500.rs b/examples/stm32f4/src/bin/eth_w5500.rs index 6e6bef08c..7ce3bfe75 100644 --- a/examples/stm32f4/src/bin/eth_w5500.rs +++ b/examples/stm32f4/src/bin/eth_w5500.rs @@ -83,7 +83,7 @@ async fn main(spawner: Spawner) -> ! { let (device, runner) = embassy_net_wiznet::new(mac_addr, state, spi, w5500_int, w5500_reset) .await .unwrap(); - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); let config = embassy_net::Config::dhcpv4(Default::default()); //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { @@ -96,7 +96,7 @@ async fn main(spawner: Spawner) -> ! { let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); // Ensure DHCP configuration is up before trying connect stack.wait_config_up().await; diff --git a/examples/stm32f4/src/bin/flash_async.rs b/examples/stm32f4/src/bin/flash_async.rs index 755713542..2feb9de09 100644 --- a/examples/stm32f4/src/bin/flash_async.rs +++ b/examples/stm32f4/src/bin/flash_async.rs @@ -21,7 +21,7 @@ async fn main(spawner: Spawner) { let mut f = Flash::new(p.FLASH, Irqs); // Led should blink uninterrupted during ~2sec erase operation - spawner.spawn(blinky(p.PB7.into())).unwrap(); + spawner.spawn(blinky(p.PB7.into()).unwrap()); // Test on bank 2 in order not to stall CPU. test_flash(&mut f, 1024 * 1024, 128 * 1024).await; diff --git a/examples/stm32f4/src/bin/input_capture.rs b/examples/stm32f4/src/bin/input_capture.rs index e15b4d26e..9998c4733 100644 --- a/examples/stm32f4/src/bin/input_capture.rs +++ b/examples/stm32f4/src/bin/input_capture.rs @@ -37,7 +37,7 @@ async fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - unwrap!(spawner.spawn(blinky(p.PB2))); + spawner.spawn(unwrap!(blinky(p.PB2))); let ch3 = CapturePin::new(p.PB10, Pull::None); let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs index b4620888f..2f2ffdea2 100644 --- a/examples/stm32f4/src/bin/multiprio.rs +++ b/examples/stm32f4/src/bin/multiprio.rs @@ -135,16 +135,16 @@ fn main() -> ! { // High-priority executor: UART4, priority level 6 interrupt::UART4.set_priority(Priority::P6); let spawner = EXECUTOR_HIGH.start(interrupt::UART4); - unwrap!(spawner.spawn(run_high())); + spawner.spawn(unwrap!(run_high())); // Medium-priority executor: UART5, priority level 7 interrupt::UART5.set_priority(Priority::P7); let spawner = EXECUTOR_MED.start(interrupt::UART5); - unwrap!(spawner.spawn(run_med())); + spawner.spawn(unwrap!(run_med())); // Low priority executor: runs in thread mode, using WFE/SEV let executor = EXECUTOR_LOW.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(run_low())); + spawner.spawn(unwrap!(run_low())); }); } diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f4/src/bin/pwm_input.rs index 74167cbf2..e8bfa524f 100644 --- a/examples/stm32f4/src/bin/pwm_input.rs +++ b/examples/stm32f4/src/bin/pwm_input.rs @@ -36,7 +36,7 @@ async fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - unwrap!(spawner.spawn(blinky(p.PB2))); + spawner.spawn(unwrap!(blinky(p.PB2))); let mut pwm_input = PwmInput::new_ch1(p.TIM3, p.PA6, Pull::None, khz(10)); pwm_input.enable(); diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs index 322cb90c7..7abbe8719 100644 --- a/examples/stm32f4/src/bin/usb_ethernet.rs +++ b/examples/stm32f4/src/bin/usb_ethernet.rs @@ -118,11 +118,11 @@ async fn main(spawner: Spawner) { // Build the builder. let usb = builder.build(); - unwrap!(spawner.spawn(usb_task(usb))); + spawner.spawn(unwrap!(usb_task(usb))); static NET_STATE: StaticCell> = StaticCell::new(); let (runner, device) = class.into_embassy_net_device::(NET_STATE.init(NetState::new()), our_mac_addr); - unwrap!(spawner.spawn(usb_ncm_task(runner))); + spawner.spawn(unwrap!(usb_ncm_task(runner))); let config = embassy_net::Config::dhcpv4(Default::default()); //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { @@ -141,7 +141,7 @@ async fn main(spawner: Spawner) { static RESOURCES: StaticCell> = StaticCell::new(); let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); // And now we can use it! diff --git a/examples/stm32f4/src/bin/usb_uac_speaker.rs b/examples/stm32f4/src/bin/usb_uac_speaker.rs index 654bec498..79bd2d914 100644 --- a/examples/stm32f4/src/bin/usb_uac_speaker.rs +++ b/examples/stm32f4/src/bin/usb_uac_speaker.rs @@ -375,9 +375,9 @@ async fn main(spawner: Spawner) { } // Launch USB audio tasks. - unwrap!(spawner.spawn(usb_control_task(control_monitor))); - unwrap!(spawner.spawn(usb_streaming_task(stream, sender))); - unwrap!(spawner.spawn(usb_feedback_task(feedback))); - unwrap!(spawner.spawn(usb_task(usb_device))); - unwrap!(spawner.spawn(audio_receiver_task(receiver))); + spawner.spawn(unwrap!(usb_control_task(control_monitor))); + spawner.spawn(unwrap!(usb_streaming_task(stream, sender))); + spawner.spawn(unwrap!(usb_feedback_task(feedback))); + spawner.spawn(unwrap!(usb_task(usb_device))); + spawner.spawn(unwrap!(audio_receiver_task(receiver))); } diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs index 58ba940a8..9a91ac814 100644 --- a/examples/stm32f7/src/bin/can.rs +++ b/examples/stm32f7/src/bin/can.rs @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) { static CAN_TX: StaticCell> = StaticCell::new(); let tx = CAN_TX.init(tx); - spawner.spawn(send_can_message(tx)).unwrap(); + spawner.spawn(send_can_message(tx).unwrap()); loop { let envelope = rx.read().await.unwrap(); diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index 67a2b34bb..b13b7bdda 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs @@ -91,7 +91,7 @@ async fn main(spawner: Spawner) -> ! { let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); // Ensure DHCP configuration is up before trying connect stack.wait_config_up().await; diff --git a/examples/stm32g0/src/bin/input_capture.rs b/examples/stm32g0/src/bin/input_capture.rs index df339d541..5501a6941 100644 --- a/examples/stm32g0/src/bin/input_capture.rs +++ b/examples/stm32g0/src/bin/input_capture.rs @@ -44,7 +44,7 @@ async fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - unwrap!(spawner.spawn(blinky(p.PB1))); + spawner.spawn(unwrap!(blinky(p.PB1))); // Connect PB1 and PA8 with a 1k Ohm resistor let ch1_pin = PwmPin::new(p.PA8, OutputType::PushPull); diff --git a/examples/stm32g0/src/bin/pwm_input.rs b/examples/stm32g0/src/bin/pwm_input.rs index fd4f53f1e..72aa07c03 100644 --- a/examples/stm32g0/src/bin/pwm_input.rs +++ b/examples/stm32g0/src/bin/pwm_input.rs @@ -40,7 +40,7 @@ bind_interrupts!(struct Irqs { async fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - unwrap!(spawner.spawn(blinky(p.PB1))); + spawner.spawn(unwrap!(blinky(p.PB1))); // Connect PA8 and PA6 with a 1k Ohm resistor let ch1_pin = PwmPin::new(p.PA8, OutputType::PushPull); let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default()); diff --git a/examples/stm32g4/src/bin/i2c_slave.rs b/examples/stm32g4/src/bin/i2c_slave.rs index 8b255b0e6..65aca1c1b 100644 --- a/examples/stm32g4/src/bin/i2c_slave.rs +++ b/examples/stm32g4/src/bin/i2c_slave.rs @@ -139,11 +139,11 @@ async fn main(spawner: Spawner) { let device = i2c::I2c::new(p.I2C2, d_scl, d_sda, Irqs, p.DMA1_CH1, p.DMA1_CH2, config).into_slave_multimaster(d_addr_config); - unwrap!(spawner.spawn(device_task(device))); + spawner.spawn(unwrap!(device_task(device))); let c_sda = p.PB8; let c_scl = p.PB7; let controller = i2c::I2c::new(p.I2C1, c_sda, c_scl, Irqs, p.DMA1_CH3, p.DMA1_CH4, config); - unwrap!(spawner.spawn(controller_task(controller))); + spawner.spawn(unwrap!(controller_task(controller))); } diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 1d85cc1e7..a84fe358b 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs @@ -94,7 +94,7 @@ async fn main(spawner: Spawner) -> ! { let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); // Ensure DHCP configuration is up before trying connect stack.wait_config_up().await; diff --git a/examples/stm32h5/src/bin/stop.rs b/examples/stm32h5/src/bin/stop.rs index e650791c5..3c4f49f64 100644 --- a/examples/stm32h5/src/bin/stop.rs +++ b/examples/stm32h5/src/bin/stop.rs @@ -18,7 +18,7 @@ use {defmt_rtt as _, panic_probe as _}; #[cortex_m_rt::entry] fn main() -> ! { Executor::take().run(|spawner| { - unwrap!(spawner.spawn(async_main(spawner))); + spawner.spawn(unwrap!(async_main(spawner))); }) } @@ -43,8 +43,8 @@ async fn async_main(spawner: Spawner) { let rtc = RTC.init(rtc); embassy_stm32::low_power::stop_with_rtc(rtc); - unwrap!(spawner.spawn(blinky(p.PB4.into()))); - unwrap!(spawner.spawn(timeout())); + spawner.spawn(unwrap!(blinky(p.PB4.into()))); + spawner.spawn(unwrap!(timeout())); } #[embassy_executor::task] diff --git a/examples/stm32h5/src/bin/usart.rs b/examples/stm32h5/src/bin/usart.rs index cc49c2fdb..264e7d582 100644 --- a/examples/stm32h5/src/bin/usart.rs +++ b/examples/stm32h5/src/bin/usart.rs @@ -34,6 +34,6 @@ fn main() -> ! { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(main_task())); + spawner.spawn(unwrap!(main_task())); }) } diff --git a/examples/stm32h5/src/bin/usart_dma.rs b/examples/stm32h5/src/bin/usart_dma.rs index c644e84bd..ea48515d7 100644 --- a/examples/stm32h5/src/bin/usart_dma.rs +++ b/examples/stm32h5/src/bin/usart_dma.rs @@ -42,6 +42,6 @@ fn main() -> ! { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(main_task())); + spawner.spawn(unwrap!(main_task())); }) } diff --git a/examples/stm32h5/src/bin/usart_split.rs b/examples/stm32h5/src/bin/usart_split.rs index d26c5003c..f56c1c57d 100644 --- a/examples/stm32h5/src/bin/usart_split.rs +++ b/examples/stm32h5/src/bin/usart_split.rs @@ -27,7 +27,7 @@ async fn main(spawner: Spawner) -> ! { let (mut tx, rx) = usart.split(); - unwrap!(spawner.spawn(reader(rx))); + spawner.spawn(unwrap!(reader(rx))); loop { let buf = CHANNEL.receive().await; diff --git a/examples/stm32h5/src/bin/usb_uac_speaker.rs b/examples/stm32h5/src/bin/usb_uac_speaker.rs index 5d007261c..86873cabd 100644 --- a/examples/stm32h5/src/bin/usb_uac_speaker.rs +++ b/examples/stm32h5/src/bin/usb_uac_speaker.rs @@ -366,9 +366,9 @@ async fn main(spawner: Spawner) { } // Launch USB audio tasks. - unwrap!(spawner.spawn(usb_control_task(control_monitor))); - unwrap!(spawner.spawn(usb_streaming_task(stream, sender))); - unwrap!(spawner.spawn(usb_feedback_task(feedback))); - unwrap!(spawner.spawn(usb_task(usb_device))); - unwrap!(spawner.spawn(audio_receiver_task(receiver))); + spawner.spawn(unwrap!(usb_control_task(control_monitor))); + spawner.spawn(unwrap!(usb_streaming_task(stream, sender))); + spawner.spawn(unwrap!(usb_feedback_task(feedback))); + spawner.spawn(unwrap!(usb_task(usb_device))); + spawner.spawn(unwrap!(audio_receiver_task(receiver))); } diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs index 8314754bc..df37e9d78 100644 --- a/examples/stm32h7/src/bin/dac_dma.rs +++ b/examples/stm32h7/src/bin/dac_dma.rs @@ -53,8 +53,8 @@ async fn main(spawner: Spawner) { // Obtain two independent channels (p.DAC1 can only be consumed once, though!) let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); - spawner.spawn(dac_task1(p.TIM6, dac_ch1)).ok(); - spawner.spawn(dac_task2(p.TIM7, dac_ch2)).ok(); + spawner.spawn(dac_task1(p.TIM6, dac_ch1).unwrap()); + spawner.spawn(dac_task2(p.TIM7, dac_ch2).unwrap()); } #[embassy_executor::task] diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index fc14c1a70..6c215362d 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -93,7 +93,7 @@ async fn main(spawner: Spawner) -> ! { let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); // Ensure DHCP configuration is up before trying connect stack.wait_config_up().await; diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 46301a478..10ac57fc9 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs @@ -95,7 +95,7 @@ async fn main(spawner: Spawner) -> ! { let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); // Ensure DHCP configuration is up before trying connect stack.wait_config_up().await; diff --git a/examples/stm32h7/src/bin/eth_client_mii.rs b/examples/stm32h7/src/bin/eth_client_mii.rs index 99cd1a158..c6a108471 100644 --- a/examples/stm32h7/src/bin/eth_client_mii.rs +++ b/examples/stm32h7/src/bin/eth_client_mii.rs @@ -101,7 +101,7 @@ async fn main(spawner: Spawner) -> ! { let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); // Ensure DHCP configuration is up before trying connect stack.wait_config_up().await; diff --git a/examples/stm32h7/src/bin/i2c_shared.rs b/examples/stm32h7/src/bin/i2c_shared.rs index 560f97aa3..9e45d845f 100644 --- a/examples/stm32h7/src/bin/i2c_shared.rs +++ b/examples/stm32h7/src/bin/i2c_shared.rs @@ -95,9 +95,9 @@ async fn main(spawner: Spawner) { // Device 1, using embedded-hal-async compatible driver for TMP117 let i2c_dev1 = I2cDevice::new(i2c_bus); - spawner.spawn(temperature(i2c_dev1)).unwrap(); + spawner.spawn(temperature(i2c_dev1).unwrap()); // Device 2, using embedded-hal-async compatible driver for SHTC3 let i2c_dev2 = I2cDevice::new(i2c_bus); - spawner.spawn(humidity(i2c_dev2)).unwrap(); + spawner.spawn(humidity(i2c_dev2).unwrap()); } diff --git a/examples/stm32h7/src/bin/multiprio.rs b/examples/stm32h7/src/bin/multiprio.rs index b4620888f..2f2ffdea2 100644 --- a/examples/stm32h7/src/bin/multiprio.rs +++ b/examples/stm32h7/src/bin/multiprio.rs @@ -135,16 +135,16 @@ fn main() -> ! { // High-priority executor: UART4, priority level 6 interrupt::UART4.set_priority(Priority::P6); let spawner = EXECUTOR_HIGH.start(interrupt::UART4); - unwrap!(spawner.spawn(run_high())); + spawner.spawn(unwrap!(run_high())); // Medium-priority executor: UART5, priority level 7 interrupt::UART5.set_priority(Priority::P7); let spawner = EXECUTOR_MED.start(interrupt::UART5); - unwrap!(spawner.spawn(run_med())); + spawner.spawn(unwrap!(run_med())); // Low priority executor: runs in thread mode, using WFE/SEV let executor = EXECUTOR_LOW.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(run_low())); + spawner.spawn(unwrap!(run_low())); }); } diff --git a/examples/stm32h7/src/bin/signal.rs b/examples/stm32h7/src/bin/signal.rs index b73360f32..97309798e 100644 --- a/examples/stm32h7/src/bin/signal.rs +++ b/examples/stm32h7/src/bin/signal.rs @@ -26,7 +26,7 @@ async fn my_sending_task() { #[embassy_executor::main] async fn main(spawner: Spawner) { let _p = embassy_stm32::init(Default::default()); - unwrap!(spawner.spawn(my_sending_task())); + spawner.spawn(unwrap!(my_sending_task())); loop { let received_counter = SIGNAL.wait().await; diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs index ad4a8aaf7..dce30a4a7 100644 --- a/examples/stm32h7/src/bin/spi.rs +++ b/examples/stm32h7/src/bin/spi.rs @@ -66,6 +66,6 @@ fn main() -> ! { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(main_task(spi))); + spawner.spawn(unwrap!(main_task(spi))); }) } diff --git a/examples/stm32h7/src/bin/spi_bdma.rs b/examples/stm32h7/src/bin/spi_bdma.rs index 5a7dff572..828f687b8 100644 --- a/examples/stm32h7/src/bin/spi_bdma.rs +++ b/examples/stm32h7/src/bin/spi_bdma.rs @@ -80,6 +80,6 @@ fn main() -> ! { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(main_task(spi))); + spawner.spawn(unwrap!(main_task(spi))); }) } diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs index 731c7fef5..2197fabce 100644 --- a/examples/stm32h7/src/bin/spi_dma.rs +++ b/examples/stm32h7/src/bin/spi_dma.rs @@ -63,6 +63,6 @@ fn main() -> ! { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(main_task(spi))); + spawner.spawn(unwrap!(main_task(spi))); }) } diff --git a/examples/stm32h7/src/bin/usart.rs b/examples/stm32h7/src/bin/usart.rs index cc49c2fdb..264e7d582 100644 --- a/examples/stm32h7/src/bin/usart.rs +++ b/examples/stm32h7/src/bin/usart.rs @@ -34,6 +34,6 @@ fn main() -> ! { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(main_task())); + spawner.spawn(unwrap!(main_task())); }) } diff --git a/examples/stm32h7/src/bin/usart_dma.rs b/examples/stm32h7/src/bin/usart_dma.rs index 6f340d40a..23d7f193a 100644 --- a/examples/stm32h7/src/bin/usart_dma.rs +++ b/examples/stm32h7/src/bin/usart_dma.rs @@ -42,6 +42,6 @@ fn main() -> ! { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(main_task())); + spawner.spawn(unwrap!(main_task())); }) } diff --git a/examples/stm32h7/src/bin/usart_split.rs b/examples/stm32h7/src/bin/usart_split.rs index 2bb58be5e..464ce8d72 100644 --- a/examples/stm32h7/src/bin/usart_split.rs +++ b/examples/stm32h7/src/bin/usart_split.rs @@ -27,7 +27,7 @@ async fn main(spawner: Spawner) -> ! { let (mut tx, rx) = usart.split(); - unwrap!(spawner.spawn(reader(rx))); + spawner.spawn(unwrap!(reader(rx))); loop { let buf = CHANNEL.receive().await; diff --git a/examples/stm32h735/src/bin/ltdc.rs b/examples/stm32h735/src/bin/ltdc.rs index a36fdef2c..8a99f745d 100644 --- a/examples/stm32h735/src/bin/ltdc.rs +++ b/examples/stm32h735/src/bin/ltdc.rs @@ -47,7 +47,7 @@ async fn main(spawner: Spawner) { // blink the led on another task let led = Output::new(p.PC3, Level::High, Speed::Low); - unwrap!(spawner.spawn(led_task(led))); + spawner.spawn(unwrap!(led_task(led))); // numbers from STMicroelectronics/STM32CubeH7 STM32H735G-DK C-based example const RK043FN48H_HSYNC: u16 = 41; // Horizontal synchronization diff --git a/examples/stm32h7rs/src/bin/eth.rs b/examples/stm32h7rs/src/bin/eth.rs index d8002e9ba..67f541564 100644 --- a/examples/stm32h7rs/src/bin/eth.rs +++ b/examples/stm32h7rs/src/bin/eth.rs @@ -94,7 +94,7 @@ async fn main(spawner: Spawner) -> ! { let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); // Ensure DHCP configuration is up before trying connect //stack.wait_config_up().await; diff --git a/examples/stm32h7rs/src/bin/multiprio.rs b/examples/stm32h7rs/src/bin/multiprio.rs index b4620888f..2f2ffdea2 100644 --- a/examples/stm32h7rs/src/bin/multiprio.rs +++ b/examples/stm32h7rs/src/bin/multiprio.rs @@ -135,16 +135,16 @@ fn main() -> ! { // High-priority executor: UART4, priority level 6 interrupt::UART4.set_priority(Priority::P6); let spawner = EXECUTOR_HIGH.start(interrupt::UART4); - unwrap!(spawner.spawn(run_high())); + spawner.spawn(unwrap!(run_high())); // Medium-priority executor: UART5, priority level 7 interrupt::UART5.set_priority(Priority::P7); let spawner = EXECUTOR_MED.start(interrupt::UART5); - unwrap!(spawner.spawn(run_med())); + spawner.spawn(unwrap!(run_med())); // Low priority executor: runs in thread mode, using WFE/SEV let executor = EXECUTOR_LOW.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(run_low())); + spawner.spawn(unwrap!(run_low())); }); } diff --git a/examples/stm32h7rs/src/bin/signal.rs b/examples/stm32h7rs/src/bin/signal.rs index b73360f32..97309798e 100644 --- a/examples/stm32h7rs/src/bin/signal.rs +++ b/examples/stm32h7rs/src/bin/signal.rs @@ -26,7 +26,7 @@ async fn my_sending_task() { #[embassy_executor::main] async fn main(spawner: Spawner) { let _p = embassy_stm32::init(Default::default()); - unwrap!(spawner.spawn(my_sending_task())); + spawner.spawn(unwrap!(my_sending_task())); loop { let received_counter = SIGNAL.wait().await; diff --git a/examples/stm32h7rs/src/bin/spi.rs b/examples/stm32h7rs/src/bin/spi.rs index 8d6ccc58b..8c280fdae 100644 --- a/examples/stm32h7rs/src/bin/spi.rs +++ b/examples/stm32h7rs/src/bin/spi.rs @@ -44,6 +44,6 @@ fn main() -> ! { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(main_task(spi))); + spawner.spawn(unwrap!(main_task(spi))); }) } diff --git a/examples/stm32h7rs/src/bin/spi_dma.rs b/examples/stm32h7rs/src/bin/spi_dma.rs index cb305351b..3fa69fd15 100644 --- a/examples/stm32h7rs/src/bin/spi_dma.rs +++ b/examples/stm32h7rs/src/bin/spi_dma.rs @@ -41,6 +41,6 @@ fn main() -> ! { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(main_task(spi))); + spawner.spawn(unwrap!(main_task(spi))); }) } diff --git a/examples/stm32h7rs/src/bin/usart.rs b/examples/stm32h7rs/src/bin/usart.rs index cc49c2fdb..264e7d582 100644 --- a/examples/stm32h7rs/src/bin/usart.rs +++ b/examples/stm32h7rs/src/bin/usart.rs @@ -34,6 +34,6 @@ fn main() -> ! { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(main_task())); + spawner.spawn(unwrap!(main_task())); }) } diff --git a/examples/stm32h7rs/src/bin/usart_dma.rs b/examples/stm32h7rs/src/bin/usart_dma.rs index c644e84bd..ea48515d7 100644 --- a/examples/stm32h7rs/src/bin/usart_dma.rs +++ b/examples/stm32h7rs/src/bin/usart_dma.rs @@ -42,6 +42,6 @@ fn main() -> ! { let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { - unwrap!(spawner.spawn(main_task())); + spawner.spawn(unwrap!(main_task())); }) } diff --git a/examples/stm32h7rs/src/bin/usart_split.rs b/examples/stm32h7rs/src/bin/usart_split.rs index d26c5003c..f56c1c57d 100644 --- a/examples/stm32h7rs/src/bin/usart_split.rs +++ b/examples/stm32h7rs/src/bin/usart_split.rs @@ -27,7 +27,7 @@ async fn main(spawner: Spawner) -> ! { let (mut tx, rx) = usart.split(); - unwrap!(spawner.spawn(reader(rx))); + spawner.spawn(unwrap!(reader(rx))); loop { let buf = CHANNEL.receive().await; diff --git a/examples/stm32l0/src/bin/raw_spawn.rs b/examples/stm32l0/src/bin/raw_spawn.rs index 29c7e0dc7..6385e3c8f 100644 --- a/examples/stm32l0/src/bin/raw_spawn.rs +++ b/examples/stm32l0/src/bin/raw_spawn.rs @@ -42,8 +42,8 @@ fn main() -> ! { let run2_task = unsafe { make_static(&run2_task) }; executor.run(|spawner| { - unwrap!(spawner.spawn(run1_task.spawn(|| run1()))); - unwrap!(spawner.spawn(run2_task.spawn(|| run2()))); + spawner.spawn(unwrap!(run1_task.spawn(|| run1()))); + spawner.spawn(unwrap!(run2_task.spawn(|| run2()))); }); } diff --git a/examples/stm32l4/src/bin/dac_dma.rs b/examples/stm32l4/src/bin/dac_dma.rs index cde24f411..44edec728 100644 --- a/examples/stm32l4/src/bin/dac_dma.rs +++ b/examples/stm32l4/src/bin/dac_dma.rs @@ -24,8 +24,8 @@ async fn main(spawner: Spawner) { // Obtain two independent channels (p.DAC1 can only be consumed once, though!) let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); - spawner.spawn(dac_task1(p.TIM6, dac_ch1)).ok(); - spawner.spawn(dac_task2(p.TIM7, dac_ch2)).ok(); + spawner.spawn(dac_task1(p.TIM6, dac_ch1).unwrap()); + spawner.spawn(dac_task2(p.TIM7, dac_ch2).unwrap()); } #[embassy_executor::task] diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index 516badcb2..24efe526f 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs @@ -181,11 +181,11 @@ async fn main(spawner: Spawner) { .await; // Start task blink_led - unwrap!(spawner.spawn(heartbeat_led(led_uc3_yellow))); + spawner.spawn(unwrap!(heartbeat_led(led_uc3_yellow))); // Start task temperature measurement - unwrap!(spawner.spawn(temp_task(temp_sens_i2c, led_uc4_blue))); + spawner.spawn(unwrap!(temp_task(temp_sens_i2c, led_uc4_blue))); // Start ethernet task - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); let mut rng = Rng::new(dp.RNG, Irqs); // Generate random seed @@ -208,7 +208,7 @@ async fn main(spawner: Spawner) { let (stack, runner) = embassy_net::new(device, ip_cfg, RESOURCES.init(StackResources::new()), seed); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); let cfg = wait_for_config(stack).await; let local_addr = cfg.address.address(); diff --git a/examples/stm32l5/src/bin/stop.rs b/examples/stm32l5/src/bin/stop.rs index d7a1efea9..c34053190 100644 --- a/examples/stm32l5/src/bin/stop.rs +++ b/examples/stm32l5/src/bin/stop.rs @@ -15,7 +15,7 @@ use {defmt_rtt as _, panic_probe as _}; #[cortex_m_rt::entry] fn main() -> ! { Executor::take().run(|spawner| { - unwrap!(spawner.spawn(async_main(spawner))); + spawner.spawn(unwrap!(async_main(spawner))); }) } @@ -34,8 +34,8 @@ async fn async_main(spawner: Spawner) { let rtc = RTC.init(rtc); embassy_stm32::low_power::stop_with_rtc(rtc); - unwrap!(spawner.spawn(blinky(p.PC7.into()))); - unwrap!(spawner.spawn(timeout())); + spawner.spawn(unwrap!(blinky(p.PC7.into()))); + spawner.spawn(unwrap!(timeout())); } #[embassy_executor::task] diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index 6c72132c6..25aa9ef69 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs @@ -96,11 +96,11 @@ async fn main(spawner: Spawner) { // Build the builder. let usb = builder.build(); - unwrap!(spawner.spawn(usb_task(usb))); + spawner.spawn(unwrap!(usb_task(usb))); static NET_STATE: StaticCell> = StaticCell::new(); let (runner, device) = class.into_embassy_net_device::(NET_STATE.init(NetState::new()), our_mac_addr); - unwrap!(spawner.spawn(usb_ncm_task(runner))); + spawner.spawn(unwrap!(usb_ncm_task(runner))); let config = embassy_net::Config::dhcpv4(Default::default()); //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { @@ -117,7 +117,7 @@ async fn main(spawner: Spawner) { static RESOURCES: StaticCell> = StaticCell::new(); let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); // And now we can use it! diff --git a/examples/stm32u5/src/bin/ltdc.rs b/examples/stm32u5/src/bin/ltdc.rs index bd59a9148..46d1c120f 100644 --- a/examples/stm32u5/src/bin/ltdc.rs +++ b/examples/stm32u5/src/bin/ltdc.rs @@ -50,7 +50,7 @@ async fn main(spawner: Spawner) { // blink the led on another task let led = Output::new(p.PD2, Level::High, Speed::Low); - unwrap!(spawner.spawn(led_task(led))); + spawner.spawn(unwrap!(led_task(led))); // numbers from STM32U5G9J-DK2.ioc const RK050HR18H_HSYNC: u16 = 5; // Horizontal synchronization diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index d139aa61b..ede6cf4b9 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -56,7 +56,7 @@ async fn main(spawner: Spawner) { let config = Config::default(); let mbox = TlMbox::init(p.IPCC, Irqs, config); - spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs index 6a97daf4d..cc3b21e2e 100644 --- a/examples/stm32wb/src/bin/mac_ffd_net.rs +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs @@ -62,7 +62,7 @@ async fn main(spawner: Spawner) { let config = Config::default(); let mbox = TlMbox::init(p.IPCC, Irqs, config); - spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); @@ -168,7 +168,7 @@ async fn main(spawner: Spawner) { static RUNNER: StaticCell = StaticCell::new(); let runner = RUNNER.init(Runner::new(mbox.mac_subsystem, tx_queue)); - spawner.spawn(run_mac(runner)).unwrap(); + spawner.spawn(run_mac(runner).unwrap()); let (driver, control) = mac::new(runner).await; diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index 9062bdcd2..d872104a8 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -58,7 +58,7 @@ async fn main(spawner: Spawner) { let config = Config::default(); let mbox = TlMbox::init(p.IPCC, Irqs, config); - spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); diff --git a/examples/stm32wb/src/bin/tl_mbox_mac.rs b/examples/stm32wb/src/bin/tl_mbox_mac.rs index 9224e626d..95c73872b 100644 --- a/examples/stm32wb/src/bin/tl_mbox_mac.rs +++ b/examples/stm32wb/src/bin/tl_mbox_mac.rs @@ -53,7 +53,7 @@ async fn main(spawner: Spawner) { let config = Config::default(); let mbox = TlMbox::init(p.IPCC, Irqs, config); - spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); diff --git a/examples/wasm/src/lib.rs b/examples/wasm/src/lib.rs index 71cf980dd..170c97fb7 100644 --- a/examples/wasm/src/lib.rs +++ b/examples/wasm/src/lib.rs @@ -24,5 +24,5 @@ async fn ticker() { #[embassy_executor::main] async fn main(spawner: Spawner) { wasm_logger::init(wasm_logger::Config::default()); - spawner.spawn(ticker()).unwrap(); + spawner.spawn(ticker().unwrap()); } diff --git a/tests/nrf/src/bin/ethernet_enc28j60_perf.rs b/tests/nrf/src/bin/ethernet_enc28j60_perf.rs index ed58627f1..5f3fa1fd3 100644 --- a/tests/nrf/src/bin/ethernet_enc28j60_perf.rs +++ b/tests/nrf/src/bin/ethernet_enc28j60_perf.rs @@ -68,7 +68,7 @@ async fn main(spawner: Spawner) { static RESOURCES: StaticCell> = StaticCell::new(); let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); perf_client::run( stack, diff --git a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs index 34fb8103b..34c33a4ad 100644 --- a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs +++ b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs @@ -74,7 +74,7 @@ async fn main(spawner: Spawner) { ) .await; - unwrap!(spawner.spawn(wifi_task(runner))); + spawner.spawn(unwrap!(wifi_task(runner))); unwrap!(control.init().await); unwrap!(control.connect(WIFI_NETWORK, WIFI_PASSWORD).await); @@ -94,7 +94,7 @@ async fn main(spawner: Spawner) { seed, ); - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); perf_client::run( stack, diff --git a/tests/rp/src/bin/cyw43-perf.rs b/tests/rp/src/bin/cyw43-perf.rs index dba1058a8..555134ffd 100644 --- a/tests/rp/src/bin/cyw43-perf.rs +++ b/tests/rp/src/bin/cyw43-perf.rs @@ -70,7 +70,7 @@ async fn main(spawner: Spawner) { static STATE: StaticCell = StaticCell::new(); let state = STATE.init(cyw43::State::new()); let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; - unwrap!(spawner.spawn(wifi_task(runner))); + spawner.spawn(unwrap!(wifi_task(runner))); control.init(clm).await; control @@ -89,7 +89,7 @@ async fn main(spawner: Spawner) { seed, ); - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); loop { match control diff --git a/tests/rp/src/bin/ethernet_w5100s_perf.rs b/tests/rp/src/bin/ethernet_w5100s_perf.rs index 89e0ad32e..3f2bc728d 100644 --- a/tests/rp/src/bin/ethernet_w5100s_perf.rs +++ b/tests/rp/src/bin/ethernet_w5100s_perf.rs @@ -60,7 +60,7 @@ async fn main(spawner: Spawner) { ) .await .unwrap(); - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); // Generate random seed let seed = rng.next_u64(); @@ -75,7 +75,7 @@ async fn main(spawner: Spawner) { ); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); perf_client::run( stack, diff --git a/tests/rp/src/bin/gpio_multicore.rs b/tests/rp/src/bin/gpio_multicore.rs index 857f36975..f48dd207b 100644 --- a/tests/rp/src/bin/gpio_multicore.rs +++ b/tests/rp/src/bin/gpio_multicore.rs @@ -30,11 +30,11 @@ fn main() -> ! { unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, move || { let executor1 = EXECUTOR1.init(Executor::new()); - executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(p.PIN_1)))); + executor1.run(|spawner| spawner.spawn(unwrap!(core1_task(p.PIN_1)))); }, ); let executor0 = EXECUTOR0.init(Executor::new()); - executor0.run(|spawner| unwrap!(spawner.spawn(core0_task(p.PIN_0)))); + executor0.run(|spawner| spawner.spawn(unwrap!(core0_task(p.PIN_0)))); } #[embassy_executor::task] diff --git a/tests/rp/src/bin/i2c.rs b/tests/rp/src/bin/i2c.rs index 2c835bd5a..21761b98b 100644 --- a/tests/rp/src/bin/i2c.rs +++ b/tests/rp/src/bin/i2c.rs @@ -208,7 +208,7 @@ async fn controller_task(con: &mut i2c::I2c<'static, I2C0, i2c::Async>) { config.addr = DEV_ADDR as u16; let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config); - spawner.must_spawn(device_task(device)); + spawner.spawn(device_task(device).unwrap()); let c_sda = p.PIN_21; let c_scl = p.PIN_20; diff --git a/tests/rp/src/bin/multicore.rs b/tests/rp/src/bin/multicore.rs index 902169c40..11b03cfea 100644 --- a/tests/rp/src/bin/multicore.rs +++ b/tests/rp/src/bin/multicore.rs @@ -27,11 +27,11 @@ fn main() -> ! { unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, move || { let executor1 = EXECUTOR1.init(Executor::new()); - executor1.run(|spawner| unwrap!(spawner.spawn(core1_task()))); + executor1.run(|spawner| spawner.spawn(unwrap!(core1_task()))); }, ); let executor0 = EXECUTOR0.init(Executor::new()); - executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); + executor0.run(|spawner| spawner.spawn(unwrap!(core0_task()))); } #[embassy_executor::task] diff --git a/tests/rp/src/bin/spinlock_mutex_multicore.rs b/tests/rp/src/bin/spinlock_mutex_multicore.rs index ebcf1ca32..c56d43ade 100644 --- a/tests/rp/src/bin/spinlock_mutex_multicore.rs +++ b/tests/rp/src/bin/spinlock_mutex_multicore.rs @@ -27,11 +27,11 @@ fn main() -> ! { unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, move || { let executor1 = EXECUTOR1.init(Executor::new()); - executor1.run(|spawner| unwrap!(spawner.spawn(core1_task()))); + executor1.run(|spawner| spawner.spawn(unwrap!(core1_task()))); }, ); let executor0 = EXECUTOR0.init(Executor::new()); - executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); + executor0.run(|spawner| spawner.spawn(unwrap!(core0_task()))); } #[embassy_executor::task] diff --git a/tests/stm32/src/bin/eth.rs b/tests/stm32/src/bin/eth.rs index bcb362b42..a65682a02 100644 --- a/tests/stm32/src/bin/eth.rs +++ b/tests/stm32/src/bin/eth.rs @@ -101,7 +101,7 @@ async fn main(spawner: Spawner) { let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); perf_client::run( stack, diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs index 772bc527c..8119c1f39 100644 --- a/tests/stm32/src/bin/stop.rs +++ b/tests/stm32/src/bin/stop.rs @@ -19,7 +19,7 @@ use static_cell::StaticCell; #[entry] fn main() -> ! { Executor::take().run(|spawner| { - unwrap!(spawner.spawn(async_main(spawner))); + spawner.spawn(unwrap!(async_main(spawner))); }); } @@ -75,6 +75,6 @@ async fn async_main(spawner: Spawner) { stop_with_rtc(rtc); - spawner.spawn(task_1()).unwrap(); - spawner.spawn(task_2()).unwrap(); + spawner.spawn(task_1().unwrap()); + spawner.spawn(task_2().unwrap()); } diff --git a/tests/stm32/src/bin/usart_rx_ringbuffered.rs b/tests/stm32/src/bin/usart_rx_ringbuffered.rs index 83c0887ac..15a0b0d60 100644 --- a/tests/stm32/src/bin/usart_rx_ringbuffered.rs +++ b/tests/stm32/src/bin/usart_rx_ringbuffered.rs @@ -46,8 +46,8 @@ async fn main(spawner: Spawner) { let rx = rx.into_ring_buffered(unsafe { &mut *core::ptr::addr_of_mut!(DMA_BUF) }); info!("Spawning tasks"); - spawner.spawn(transmit_task(tx)).unwrap(); - spawner.spawn(receive_task(rx)).unwrap(); + spawner.spawn(transmit_task(tx).unwrap()); + spawner.spawn(receive_task(rx).unwrap()); } #[embassy_executor::task] diff --git a/tests/stm32/src/bin/wpan_ble.rs b/tests/stm32/src/bin/wpan_ble.rs index fde1dfa9b..8957bfc04 100644 --- a/tests/stm32/src/bin/wpan_ble.rs +++ b/tests/stm32/src/bin/wpan_ble.rs @@ -47,7 +47,7 @@ async fn main(spawner: Spawner) { let config = Config::default(); let mut mbox = TlMbox::init(p.IPCC, Irqs, config); - spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); diff --git a/tests/stm32/src/bin/wpan_mac.rs b/tests/stm32/src/bin/wpan_mac.rs index b65ace40f..79e13d524 100644 --- a/tests/stm32/src/bin/wpan_mac.rs +++ b/tests/stm32/src/bin/wpan_mac.rs @@ -40,7 +40,7 @@ async fn main(spawner: Spawner) { let config = Config::default(); let mbox = TlMbox::init(p.IPCC, Irqs, config); - spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); -- cgit From 48c2deb8f3322bdb3e60440d594c238190a3be8a Mon Sep 17 00:00:00 2001 From: diondokter Date: Fri, 29 Aug 2025 12:36:17 +0200 Subject: Fix examples --- examples/rp235x/src/bin/ethernet_w5500_icmp.rs | 4 ++-- examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs | 4 ++-- examples/rp235x/src/bin/ethernet_w5500_multisocket.rs | 8 ++++---- examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs | 4 ++-- examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs | 4 ++-- examples/rp235x/src/bin/ethernet_w5500_udp.rs | 4 ++-- examples/stm32h5/src/bin/adc_dma.rs | 4 ++-- examples/stm32h755cm4/src/bin/intercore.rs | 2 +- examples/stm32wb/src/bin/gatt_server.rs | 2 +- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/rp235x/src/bin/ethernet_w5500_icmp.rs b/examples/rp235x/src/bin/ethernet_w5500_icmp.rs index f1abd311c..f012c9589 100644 --- a/examples/rp235x/src/bin/ethernet_w5500_icmp.rs +++ b/examples/rp235x/src/bin/ethernet_w5500_icmp.rs @@ -61,7 +61,7 @@ async fn main(spawner: Spawner) { ) .await .unwrap(); - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); // Generate random seed let seed = rng.next_u64(); @@ -76,7 +76,7 @@ async fn main(spawner: Spawner) { ); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); info!("Waiting for DHCP..."); let cfg = wait_for_config(stack).await; diff --git a/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs b/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs index 1f799a6b0..309d3e4f7 100644 --- a/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs +++ b/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs @@ -63,7 +63,7 @@ async fn main(spawner: Spawner) { ) .await .unwrap(); - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); // Generate random seed let seed = rng.next_u64(); @@ -78,7 +78,7 @@ async fn main(spawner: Spawner) { ); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); info!("Waiting for DHCP..."); let cfg = wait_for_config(stack).await; diff --git a/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs b/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs index fd8bc5c7a..7cfc00776 100644 --- a/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) { ) .await .unwrap(); - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); // Generate random seed let seed = rng.next_u64(); @@ -79,7 +79,7 @@ async fn main(spawner: Spawner) { ); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); info!("Waiting for DHCP..."); let cfg = wait_for_config(stack).await; @@ -87,8 +87,8 @@ async fn main(spawner: Spawner) { info!("IP address: {:?}", local_addr); // Create two sockets listening to the same port, to handle simultaneous connections - unwrap!(spawner.spawn(listen_task(stack, 0, 1234))); - unwrap!(spawner.spawn(listen_task(stack, 1, 1234))); + spawner.spawn(unwrap!(listen_task(stack, 0, 1234))); + spawner.spawn(unwrap!(listen_task(stack, 1, 1234))); } #[embassy_executor::task(pool_size = 2)] diff --git a/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs index b726b9cc6..254aada9a 100644 --- a/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs @@ -67,7 +67,7 @@ async fn main(spawner: Spawner) { ) .await .unwrap(); - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); // Generate random seed let seed = rng.next_u64(); @@ -82,7 +82,7 @@ async fn main(spawner: Spawner) { ); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); info!("Waiting for DHCP..."); let cfg = wait_for_config(stack).await; diff --git a/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs index 32b3880f6..ba812f4fd 100644 --- a/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs @@ -66,7 +66,7 @@ async fn main(spawner: Spawner) { ) .await .unwrap(); - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); // Generate random seed let seed = rng.next_u64(); @@ -81,7 +81,7 @@ async fn main(spawner: Spawner) { ); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); info!("Waiting for DHCP..."); let cfg = wait_for_config(stack).await; diff --git a/examples/rp235x/src/bin/ethernet_w5500_udp.rs b/examples/rp235x/src/bin/ethernet_w5500_udp.rs index cd0824df1..ae74ad518 100644 --- a/examples/rp235x/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp235x/src/bin/ethernet_w5500_udp.rs @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) { ) .await .unwrap(); - unwrap!(spawner.spawn(ethernet_task(runner))); + spawner.spawn(unwrap!(ethernet_task(runner))); // Generate random seed let seed = rng.next_u64(); @@ -79,7 +79,7 @@ async fn main(spawner: Spawner) { ); // Launch network task - unwrap!(spawner.spawn(net_task(runner))); + spawner.spawn(unwrap!(net_task(runner))); info!("Waiting for DHCP..."); let cfg = wait_for_config(stack).await; diff --git a/examples/stm32h5/src/bin/adc_dma.rs b/examples/stm32h5/src/bin/adc_dma.rs index 20073e22f..fb9fcbc5c 100644 --- a/examples/stm32h5/src/bin/adc_dma.rs +++ b/examples/stm32h5/src/bin/adc_dma.rs @@ -42,8 +42,8 @@ async fn main(spawner: Spawner) { } let p = embassy_stm32::init(config); - spawner.must_spawn(adc1_task(p.ADC1, p.GPDMA1_CH0, p.PA0, p.PA2)); - spawner.must_spawn(adc2_task(p.ADC2, p.GPDMA1_CH1, p.PA1, p.PA3)); + spawner.spawn(unwrap!(adc1_task(p.ADC1, p.GPDMA1_CH0, p.PA0, p.PA2))); + spawner.spawn(unwrap!(adc2_task(p.ADC2, p.GPDMA1_CH1, p.PA1, p.PA3))); } #[embassy_executor::task] diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs index d5e3e7648..f584e31e9 100644 --- a/examples/stm32h755cm4/src/bin/intercore.rs +++ b/examples/stm32h755cm4/src/bin/intercore.rs @@ -128,7 +128,7 @@ async fn main(spawner: Spawner) -> ! { let red_led = Output::new(p.PB14, Level::Low, Speed::Low); // LD3 (heartbeat) // Start heartbeat task - unwrap!(spawner.spawn(blink_heartbeat(red_led))); + spawner.spawn(unwrap!(blink_heartbeat(red_led))); // Track previous values to detect changes let mut prev_green = false; diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs index 9864fa026..5d927bc00 100644 --- a/examples/stm32wb/src/bin/gatt_server.rs +++ b/examples/stm32wb/src/bin/gatt_server.rs @@ -71,7 +71,7 @@ async fn main(spawner: Spawner) { let config = Config::default(); let mut mbox = TlMbox::init(p.IPCC, Irqs, config); - spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); -- cgit From 916dce55ea9f8341422eb6d55c17d0a0fcfedce0 Mon Sep 17 00:00:00 2001 From: diondokter Date: Fri, 29 Aug 2025 13:30:11 +0200 Subject: Fix test & rtos-trace --- embassy-executor/src/raw/trace.rs | 2 +- embassy-executor/tests/test.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs index e52960dc7..b3086948c 100644 --- a/embassy-executor/src/raw/trace.rs +++ b/embassy-executor/src/raw/trace.rs @@ -246,7 +246,7 @@ pub(crate) fn task_new(executor: &SyncExecutor, task: &TaskRef) { #[cfg(feature = "rtos-trace")] { rtos_trace::trace::task_new(task.as_ptr() as u32); - let name = task.name().unwrap_or("unnamed task\0"); + let name = task.metadata().name().unwrap_or("unnamed task\0"); let info = rtos_trace::TaskInfo { name, priority: 0, diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs index 85c5dc1d9..6baf3dc21 100644 --- a/embassy-executor/tests/test.rs +++ b/embassy-executor/tests/test.rs @@ -322,7 +322,7 @@ fn recursive_task() { #[embassy_executor::task(pool_size = 2)] async fn task1() { let spawner = unsafe { Spawner::for_current_executor().await }; - spawner.spawn(task1()); + spawner.spawn(task1().unwrap()); } } -- cgit From e2c34ac735888d25d57d3ea07e8915c2e112048c Mon Sep 17 00:00:00 2001 From: diondokter Date: Fri, 29 Aug 2025 13:58:16 +0200 Subject: Add to changelog --- embassy-executor/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index f301429c0..f2db46ef9 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- Added new metadata API for tasks + ## 0.9.0 - 2025-08-26 - Added `extern "Rust" fn __embassy_time_queue_item_from_waker` -- cgit From fb8757c690c7265c46bbf04f8172b338a310ee30 Mon Sep 17 00:00:00 2001 From: Gabriel Smith Date: Fri, 29 Aug 2025 10:46:33 -0400 Subject: fix: stm32/usb: Fixed STM32H5 build requiring time feature A busy loop has been added for when the "time" feature is not enabled. --- embassy-stm32/CHANGELOG.md | 2 ++ embassy-stm32/src/usb/usb.rs | 11 ++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index c8ae7a357..dfb8ca066 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- fix: Fixed STM32H5 builds requiring time feature + ## 0.4.0 - 2025-08-26 - feat: stm32/sai: make NODIV independent of MCKDIV diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index 92c1601cc..54596aeae 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -912,7 +912,16 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { // Software should ensure that a small delay is included before accessing the SRAM contents. This delay should be // 800 ns in Full Speed mode and 6.4 μs in Low Speed mode. #[cfg(stm32h5)] - embassy_time::block_for(embassy_time::Duration::from_nanos(800)); + { + #[cfg(feature = "time")] + embassy_time::block_for(embassy_time::Duration::from_nanos(800)); + #[cfg(not(feature = "time"))] + { + let freq = unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 as u64; + let cycles = freq * 800 / 1_000_000; + cortex_m::asm::delay(cycles as u32); + } + } RX_COMPLETE[index].store(false, Ordering::Relaxed); -- cgit From 6dc06d47bf76e32096d5e42914cd0269476f5855 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 29 Aug 2025 14:32:12 -0700 Subject: feat: add helper to read/write full transfer blocks instead of always transferring only USB packets, add a provided method to transmit an entire data block by using a simple loop construct. Signed-off-by: Felipe Balbi --- embassy-usb-driver/CHANGELOG.md | 2 ++ embassy-usb-driver/src/lib.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/embassy-usb-driver/CHANGELOG.md b/embassy-usb-driver/CHANGELOG.md index 15875e087..71768d7e5 100644 --- a/embassy-usb-driver/CHANGELOG.md +++ b/embassy-usb-driver/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- Add `EndpointOut::read_data()` and `EndpointIn::write_data()` provided methods. + ## 0.2.0 - 2025-07-16 - Make USB endpoint allocator methods accept an optional `EndpointAddress`. diff --git a/embassy-usb-driver/src/lib.rs b/embassy-usb-driver/src/lib.rs index 99616f1ec..789d6de93 100644 --- a/embassy-usb-driver/src/lib.rs +++ b/embassy-usb-driver/src/lib.rs @@ -236,6 +236,22 @@ pub trait EndpointOut: Endpoint { /// /// This should also clear any NAK flags and prepare the endpoint to receive the next packet. async fn read(&mut self, buf: &mut [u8]) -> Result; + + /// Read until the buffer is full or we receive a short packet from the USB host returning the + /// actual length of the entire data block. + /// + /// This should also clear any NAK flags and prepare the endpoint to receive the next packet or + /// data block. + async fn read_data(&mut self, buf: &mut [u8]) -> Result { + let mut n = 0; + loop { + let i = self.read(&mut buf[n..]).await?; + n += i; + if i < self.info().max_packet_size as usize { + return Ok(n); + } + } + } } /// USB control pipe trait. @@ -349,6 +365,20 @@ pub trait ControlPipe { pub trait EndpointIn: Endpoint { /// Write a single packet of data to the endpoint. async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError>; + + /// Write all the data from buf to the endpoint one wMaxPacketSize chunk at a time. + /// + /// If the buffer size is evenly divisible by wMaxPacketSize, this will also ensure the + /// terminating zero-length-packet is transmitted. + async fn write_data(&mut self, buf: &[u8]) -> Result<(), EndpointError> { + for chunk in buf.chunks(self.info().max_packet_size as usize) { + self.write(chunk).await?; + } + if buf.len() % self.info().max_packet_size as usize == 0 { + self.write(&[]).await?; + } + Ok(()) + } } #[derive(Copy, Clone, Eq, PartialEq, Debug)] -- cgit From ba5a75cd7d0b97bafd02d3b95baf40fd36522fac Mon Sep 17 00:00:00 2001 From: Florian Grandel Date: Sat, 5 Jul 2025 18:25:53 +0200 Subject: executor: rtos-trace: name main task Assigns a name to the main task when (rtos-)tracing is active. This improves tracing usability with the SystemView backend. Signed-off-by: Florian Grandel --- embassy-executor-macros/src/macros/main.rs | 16 ++++++++++++++-- embassy-executor/CHANGELOG.md | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/embassy-executor-macros/src/macros/main.rs b/embassy-executor-macros/src/macros/main.rs index fcc04d9c0..f043ff7f6 100644 --- a/embassy-executor-macros/src/macros/main.rs +++ b/embassy-executor-macros/src/macros/main.rs @@ -170,6 +170,14 @@ For example: `#[embassy_executor::main(entry = ..., executor = \"some_crate::Exe let f_body = f.body; let out = &f.sig.output; + let name_main_task = if cfg!(feature = "rtos-trace") { + quote!( + main_task.metadata().set_name("main\0"); + ) + } else { + quote!() + }; + let (main_ret, mut main_body) = match arch.flavor { Flavor::Standard => ( quote!(!), @@ -181,7 +189,9 @@ For example: `#[embassy_executor::main(entry = ..., executor = \"some_crate::Exe let mut executor = #executor::new(); let executor = unsafe { __make_static(&mut executor) }; executor.run(|spawner| { - spawner.spawn(__embassy_main(spawner).unwrap()); + let main_task = __embassy_main(spawner).unwrap(); + #name_main_task + spawner.spawn(main_task); }) }, ), @@ -191,7 +201,9 @@ For example: `#[embassy_executor::main(entry = ..., executor = \"some_crate::Exe let executor = ::std::boxed::Box::leak(::std::boxed::Box::new(#executor::new())); executor.start(|spawner| { - spawner.spawn(__embassy_main(spawner).unwrap()); + let main_task = __embassy_main(spawner).unwrap(); + #name_main_task + spawner.spawn(main_task); }); Ok(()) diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index f2db46ef9..999c77a83 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate - Added new metadata API for tasks +- Named main task when rtos-trace feature is enabled. ## 0.9.0 - 2025-08-26 -- cgit From 47e45c982126d52559353308ebe328301ebbf1c6 Mon Sep 17 00:00:00 2001 From: Florian Grandel Date: Thu, 3 Apr 2025 22:46:35 +0200 Subject: rtos-trace: upgraded feature support Upgrade rtos-trace for start/stop and marker support. These methods are not used in embassy code but can be useful in client code. Signed-off-by: Florian Grandel --- embassy-executor/CHANGELOG.md | 1 + embassy-executor/Cargo.toml | 2 +- examples/nrf-rtos-trace/Cargo.toml | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index f2db46ef9..e093aaf98 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate - Added new metadata API for tasks +- Upgraded rtos-trace ## 0.9.0 - 2025-08-26 diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 79680ae74..dc423aba2 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -51,7 +51,7 @@ features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"] [dependencies] defmt = { version = "1.0.1", optional = true } log = { version = "0.4.14", optional = true } -rtos-trace = { version = "0.1.3", optional = true } +rtos-trace = { version = "0.2", optional = true } embassy-executor-macros = { version = "0.7.0", path = "../embassy-executor-macros" } embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver", optional = true } diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index a2dc0c7ad..c9eeaaac7 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -25,8 +25,8 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing cortex-m-rt = "0.7.0" panic-probe = "1.0.0" serde = { version = "1.0.136", default-features = false } -rtos-trace = "0.1.3" -systemview-target = { version = "0.1.2", features = ["callbacks-app", "callbacks-os", "log", "cortex-m"] } +rtos-trace = "0.2" +systemview-target = { version = "0.2", features = ["callbacks-app", "callbacks-os", "log", "cortex-m"] } log = { version = "0.4.17", optional = true } [[bin]] -- cgit From 629d224a7614989d79448a1cf17e345be79a0d4b Mon Sep 17 00:00:00 2001 From: Florian Grandel Date: Sat, 30 Aug 2025 18:00:49 +0200 Subject: fix(ci): executor macros changelog Changes to executor macros are expected in the executor changelog. There is now separate changelog for the macros crate. Signed-off-by: Florian Grandel --- .github/workflows/changelog.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 13e04d954..8ee143cad 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -161,9 +161,9 @@ jobs: if: steps.changes.outputs.embassy-executor-macros == 'true' uses: dangoslen/changelog-enforcer@v3 with: - changeLogPath: embassy-executor-macros/CHANGELOG.md + changeLogPath: embassy-executor/CHANGELOG.md skipLabels: "skip-changelog" - missingUpdateErrorMessage: "Please add a changelog entry in the embassy-executor-macros/CHANGELOG.md file." + missingUpdateErrorMessage: "Please add a changelog entry in the embassy-executor/CHANGELOG.md file." - name: Check that changelog updated (embassy-executor-timer-queue) if: steps.changes.outputs.embassy-executor-timer-queue == 'true' uses: dangoslen/changelog-enforcer@v3 -- cgit From a548d7efe3ad963b95183d92c2841fde744cc373 Mon Sep 17 00:00:00 2001 From: Per Rosengren Date: Mon, 25 Aug 2025 23:05:30 +0200 Subject: Add Adc::new_with_clock() to configure analog clock Required on STM32WL with default HAL initialization. The function is only available for adc_g0, but all that have clock config should add implementations. --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/src/adc/v3.rs | 87 +++++++++++++++++++++++++++- examples/stm32g0/src/bin/adc.rs | 4 +- examples/stm32g0/src/bin/adc_dma.rs | 4 +- examples/stm32g0/src/bin/adc_oversampling.rs | 4 +- examples/stm32wl/src/bin/adc.rs | 39 +++++++++++++ 6 files changed, 132 insertions(+), 7 deletions(-) create mode 100644 examples/stm32wl/src/bin/adc.rs diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index c8ae7a357..5142596e8 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - feat: stm32/adc/v3: allow DMA reads to loop through enable channels - fix: Fix XSPI not disabling alternate bytes when they were previously enabled - fix: Fix stm32h7rs init when using external flash via XSPI +- feat: Add Adc::new_with_clock() to configure analog clock ## 0.3.0 - 2025-08-12 diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index dc1faa4d1..77f24c87f 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -107,8 +107,50 @@ pub enum Averaging { Samples128, Samples256, } + +cfg_if! { if #[cfg(adc_g0)] { + +/// Synchronous PCLK prescaler +/// * ADC_CFGR2:CKMODE in STM32WL5x +#[repr(u8)] +pub enum CkModePclk { + DIV1 = 3, + DIV2 = 1, + DIV4 = 2, +} + +/// Asynchronous ADCCLK prescaler +/// * ADC_CCR:PRESC in STM32WL5x +#[repr(u8)] +pub enum Presc { + DIV1, + DIV2, + DIV4, + DIV6, + DIV8, + DIV10, + DIV12, + DIV16, + DIV32, + DIV64, + DIV128, + DIV256, +} + +/// The analog clock is either the synchronous prescaled PCLK or +/// the asynchronous prescaled ADCCLK configured by the RCC mux. +/// The data sheet states the maximum analog clock frequency - +/// for STM32WL55CC it is 36 MHz. +pub enum Clock { + Sync { div: CkModePclk }, + Async { div: Presc }, +} + +}} + impl<'d, T: Instance> Adc<'d, T> { - pub fn new(adc: Peri<'d, T>) -> Self { + /// Enable the voltage regulator + fn init_regulator() { rcc::enable_and_reset::(); T::regs().cr().modify(|reg| { #[cfg(not(any(adc_g0, adc_u0)))] @@ -117,13 +159,17 @@ impl<'d, T: Instance> Adc<'d, T> { }); // If this is false then each ADC_CHSELR bit enables an input channel. + // This is the reset value, so has no effect. #[cfg(any(adc_g0, adc_u0))] T::regs().cfgr1().modify(|reg| { reg.set_chselrmod(false); }); blocking_delay_us(20); + } + /// Calibrate to remove conversion offset + fn init_calibrate() { T::regs().cr().modify(|reg| { reg.set_adcal(true); }); @@ -133,6 +179,45 @@ impl<'d, T: Instance> Adc<'d, T> { } blocking_delay_us(1); + } + + /// Initialize the ADC leaving any analog clock at reset value. + /// For G0 and WL, this is the async clock without prescaler. + pub fn new(adc: Peri<'d, T>) -> Self { + Self::init_regulator(); + Self::init_calibrate(); + Self { + adc, + sample_time: SampleTime::from_bits(0), + } + } + + #[cfg(adc_g0)] + /// Initialize ADC with explicit clock for the analog ADC + pub fn new_with_clock(adc: Peri<'d, T>, clock: Clock) -> Self { + Self::init_regulator(); + + #[cfg(any(stm32wl5x))] + { + // Reset value 0 is actually _No clock selected_ in the STM32WL5x reference manual + let async_clock_available = pac::RCC.ccipr().read().adcsel() != pac::rcc::vals::Adcsel::_RESERVED_0; + match clock { + Clock::Async { div: _ } => { + assert!(async_clock_available); + } + Clock::Sync { div: _ } => { + if async_clock_available { + warn!("Not using configured ADC clock"); + } + } + } + } + match clock { + Clock::Async { div } => T::regs().ccr().modify(|reg| reg.set_presc(div as u8)), + Clock::Sync { div } => T::regs().cfgr2().modify(|reg| reg.set_ckmode(div as u8)), + } + + Self::init_calibrate(); Self { adc, diff --git a/examples/stm32g0/src/bin/adc.rs b/examples/stm32g0/src/bin/adc.rs index 6c7f3b48a..7d8653ef2 100644 --- a/examples/stm32g0/src/bin/adc.rs +++ b/examples/stm32g0/src/bin/adc.rs @@ -3,7 +3,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::adc::{Adc, SampleTime}; +use embassy_stm32::adc::{Adc, Clock, Presc, SampleTime}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; @@ -12,7 +12,7 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let mut adc = Adc::new(p.ADC1); + let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); adc.set_sample_time(SampleTime::CYCLES79_5); let mut pin = p.PA1; diff --git a/examples/stm32g0/src/bin/adc_dma.rs b/examples/stm32g0/src/bin/adc_dma.rs index d7515933c..8266a6d83 100644 --- a/examples/stm32g0/src/bin/adc_dma.rs +++ b/examples/stm32g0/src/bin/adc_dma.rs @@ -3,7 +3,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::adc::{Adc, AdcChannel as _, SampleTime}; +use embassy_stm32::adc::{Adc, AdcChannel as _, Clock, Presc, SampleTime}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; @@ -17,7 +17,7 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); - let mut adc = Adc::new(p.ADC1); + let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); let mut dma = p.DMA1_CH1; let mut vrefint_channel = adc.enable_vrefint().degrade_adc(); diff --git a/examples/stm32g0/src/bin/adc_oversampling.rs b/examples/stm32g0/src/bin/adc_oversampling.rs index 9c5dd872a..bc49fac83 100644 --- a/examples/stm32g0/src/bin/adc_oversampling.rs +++ b/examples/stm32g0/src/bin/adc_oversampling.rs @@ -7,7 +7,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::adc::{Adc, SampleTime}; +use embassy_stm32::adc::{Adc, Clock, Presc, SampleTime}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; @@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Adc oversample test"); - let mut adc = Adc::new(p.ADC1); + let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); adc.set_sample_time(SampleTime::CYCLES1_5); let mut pin = p.PA1; diff --git a/examples/stm32wl/src/bin/adc.rs b/examples/stm32wl/src/bin/adc.rs new file mode 100644 index 000000000..118f02ae1 --- /dev/null +++ b/examples/stm32wl/src/bin/adc.rs @@ -0,0 +1,39 @@ +#![no_std] +#![no_main] + +use core::mem::MaybeUninit; + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::adc::{Adc, CkModePclk, Clock, SampleTime}; +use embassy_stm32::SharedData; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +static SHARED_DATA: MaybeUninit = MaybeUninit::uninit(); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA); + info!("Hello World!"); + + let mut adc = Adc::new_with_clock(p.ADC1, Clock::Sync { div: CkModePclk::DIV1 }); + adc.set_sample_time(SampleTime::CYCLES79_5); + let mut pin = p.PB2; + + let mut vrefint = adc.enable_vrefint(); + let vrefint_sample = adc.blocking_read(&mut vrefint); + let convert_to_millivolts = |sample| { + // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf + // 6.3.3 Embedded internal reference voltage + const VREFINT_MV: u32 = 1212; // mV + + (u32::from(sample) * VREFINT_MV / u32::from(vrefint_sample)) as u16 + }; + + loop { + let v = adc.blocking_read(&mut pin); + info!("--> {} - {} mV", v, convert_to_millivolts(v)); + Timer::after_millis(100).await; + } +} -- cgit From 3fb6a9191c3d132bca5984a1ad79ad211e533912 Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Sun, 31 Aug 2025 10:20:03 +0200 Subject: Prefer pointer-sized atomic operations --- embassy-executor/CHANGELOG.md | 1 + embassy-executor/src/raw/mod.rs | 10 ++++++++-- embassy-executor/src/raw/state_atomics.rs | 21 ++++++++++++++++----- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index f2db46ef9..477ea972c 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate - Added new metadata API for tasks +- Fixed performance regression on some ESP32 MCUs. ## 0.9.0 - 2025-08-26 diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index bdaa32951..4280c5750 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -12,8 +12,14 @@ mod run_queue; #[cfg_attr(all(cortex_m, target_has_atomic = "32"), path = "state_atomics_arm.rs")] -#[cfg_attr(all(not(cortex_m), target_has_atomic = "8"), path = "state_atomics.rs")] -#[cfg_attr(not(target_has_atomic = "8"), path = "state_critical_section.rs")] +#[cfg_attr( + all(not(cortex_m), any(target_has_atomic = "8", target_has_atomic = "32")), + path = "state_atomics.rs" +)] +#[cfg_attr( + not(any(target_has_atomic = "8", target_has_atomic = "32")), + path = "state_critical_section.rs" +)] mod state; #[cfg(feature = "_any_trace")] diff --git a/embassy-executor/src/raw/state_atomics.rs b/embassy-executor/src/raw/state_atomics.rs index e813548ae..6675875be 100644 --- a/embassy-executor/src/raw/state_atomics.rs +++ b/embassy-executor/src/raw/state_atomics.rs @@ -1,4 +1,15 @@ -use core::sync::atomic::{AtomicU8, Ordering}; +// Prefer pointer-width atomic operations, as narrower ones may be slower. +#[cfg(all(target_pointer_width = "32", target_has_atomic = "32"))] +type AtomicState = core::sync::atomic::AtomicU32; +#[cfg(not(all(target_pointer_width = "32", target_has_atomic = "32")))] +type AtomicState = core::sync::atomic::AtomicU8; + +#[cfg(all(target_pointer_width = "32", target_has_atomic = "32"))] +type StateBits = u32; +#[cfg(not(all(target_pointer_width = "32", target_has_atomic = "32")))] +type StateBits = u8; + +use core::sync::atomic::Ordering; #[derive(Clone, Copy)] pub(crate) struct Token(()); @@ -11,18 +22,18 @@ pub(crate) fn locked(f: impl FnOnce(Token) -> R) -> R { } /// Task is spawned (has a future) -pub(crate) const STATE_SPAWNED: u8 = 1 << 0; +pub(crate) const STATE_SPAWNED: StateBits = 1 << 0; /// Task is in the executor run queue -pub(crate) const STATE_RUN_QUEUED: u8 = 1 << 1; +pub(crate) const STATE_RUN_QUEUED: StateBits = 1 << 1; pub(crate) struct State { - state: AtomicU8, + state: AtomicState, } impl State { pub const fn new() -> State { Self { - state: AtomicU8::new(0), + state: AtomicState::new(0), } } -- cgit From fb531da007bad7129bfd247a901286b27de0c509 Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Sun, 31 Aug 2025 10:39:04 +0200 Subject: Prefer word-sized state in CS impl --- embassy-executor/src/raw/state_critical_section.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/embassy-executor/src/raw/state_critical_section.rs b/embassy-executor/src/raw/state_critical_section.rs index ec08f2f58..b69a6ac66 100644 --- a/embassy-executor/src/raw/state_critical_section.rs +++ b/embassy-executor/src/raw/state_critical_section.rs @@ -3,13 +3,18 @@ use core::cell::Cell; pub(crate) use critical_section::{with as locked, CriticalSection as Token}; use critical_section::{CriticalSection, Mutex}; +#[cfg(target_arch = "avr")] +type StateBits = u8; +#[cfg(not(target_arch = "avr"))] +type StateBits = usize; + /// Task is spawned (has a future) -pub(crate) const STATE_SPAWNED: u8 = 1 << 0; +pub(crate) const STATE_SPAWNED: StateBits = 1 << 0; /// Task is in the executor run queue -pub(crate) const STATE_RUN_QUEUED: u8 = 1 << 1; +pub(crate) const STATE_RUN_QUEUED: StateBits = 1 << 1; pub(crate) struct State { - state: Mutex>, + state: Mutex>, } impl State { @@ -19,11 +24,11 @@ impl State { } } - fn update(&self, f: impl FnOnce(&mut u8) -> R) -> R { + fn update(&self, f: impl FnOnce(&mut StateBits) -> R) -> R { critical_section::with(|cs| self.update_with_cs(cs, f)) } - fn update_with_cs(&self, cs: CriticalSection<'_>, f: impl FnOnce(&mut u8) -> R) -> R { + fn update_with_cs(&self, cs: CriticalSection<'_>, f: impl FnOnce(&mut StateBits) -> R) -> R { let s = self.state.borrow(cs); let mut val = s.get(); let r = f(&mut val); -- cgit From 0962b09603248d5ab76baa95746593ae50994eac Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 31 Aug 2025 23:09:31 +0200 Subject: Add changelog for embassy-executor v0.9.1 --- embassy-executor/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 69c82653b..3e6c180c6 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added new metadata API for tasks - Named main task when rtos-trace feature is enabled. - Upgraded rtos-trace + +## 0.9.1 - 2025-08-31 + - Fixed performance regression on some ESP32 MCUs. ## 0.9.0 - 2025-08-26 -- cgit From 67ba38e1966a934517ceb641b2dcd4c1c68c02ee Mon Sep 17 00:00:00 2001 From: Ole Bauck Date: Sun, 31 Aug 2025 09:27:47 +0200 Subject: nrf54l: Disable glitch detection and enable DC/DC in init. --- embassy-nrf/CHANGELOG.md | 2 ++ embassy-nrf/src/lib.rs | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index 4e0887b0d..5dc941b25 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- changed: nrf54l: Disable glitch detection and enable DC/DC in init. + ## 0.7.0 - 2025-08-26 - bugfix: use correct analog input SAADC pins on nrf5340 diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 2b72debeb..aa4801897 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -707,6 +707,14 @@ pub fn init(config: config::Config) -> Peripherals { } } + // GLITCHDET is only accessible for secure code + #[cfg(all(feature = "_nrf54l", feature = "_s"))] + { + // The voltage glitch detectors are automatically enabled after reset. + // To save power, the glitch detectors must be disabled when not in use. + pac::GLITCHDET.config().write(|w| w.set_enable(false)); + } + // Setup debug protection. #[cfg(not(feature = "_nrf51"))] match config.debug { @@ -1083,6 +1091,15 @@ pub fn init(config: config::Config) -> Peripherals { reg.vregradio().dcdcen().write(|w| w.set_dcdcen(true)); } } + #[cfg(feature = "_nrf54l")] + { + // Turn on DCDC + // From Product specification: + // "Once the device starts, the DC/DC regulator must be enabled using register VREGMAIN.DCDCEN. + // When enabling the DC/DC regulator, the device checks if an inductor is connected to the DCC pin. + // If an inductor is not detected, the device remains in LDO mode" + pac::REGULATORS.vregmain().dcdcen().write(|w| w.set_val(true)); + } // Init GPIOTE #[cfg(not(feature = "_nrf54l"))] // TODO -- cgit From 160ee7f8054b374ce4c14b6877e6a05f5a5614b7 Mon Sep 17 00:00:00 2001 From: Patrick Gansterer Date: Mon, 1 Sep 2025 17:26:41 +0200 Subject: stm32/l0: Add usb serial example --- examples/stm32l0/Cargo.toml | 2 + examples/stm32l0/src/bin/usb_serial.rs | 95 ++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 examples/stm32l0/src/bin/usb_serial.rs diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 90f57a2d8..d42cdac15 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -11,6 +11,8 @@ embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [" embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } defmt = "1.0.1" defmt-rtt = "1.0.0" diff --git a/examples/stm32l0/src/bin/usb_serial.rs b/examples/stm32l0/src/bin/usb_serial.rs new file mode 100644 index 000000000..fdb1aeb59 --- /dev/null +++ b/examples/stm32l0/src/bin/usb_serial.rs @@ -0,0 +1,95 @@ +#![no_std] +#![no_main] + +use defmt::{panic, *}; +use embassy_executor::Spawner; +use embassy_futures::join::join; +use embassy_stm32::usb::{self, Driver, Instance}; +use embassy_stm32::{bind_interrupts, peripherals}; +use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; +use embassy_usb::driver::EndpointError; +use embassy_usb::Builder; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + USB => usb::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = embassy_stm32::Config::default(); + { + use embassy_stm32::rcc::*; + config.rcc.hsi = true; + config.rcc.pll = Some(Pll { + source: PllSource::HSI, + mul: PllMul::MUL6, // PLLVCO = 16*6 = 96Mhz + div: PllDiv::DIV3, // 32Mhz clock (16 * 6 / 3) + }); + config.rcc.sys = Sysclk::PLL1_R; + } + + let p = embassy_stm32::init(config); + + info!("Hello World!"); + + let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); + + let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Embassy"); + config.product = Some("USB-Serial Example"); + config.serial_number = Some("123456"); + + let mut config_descriptor = [0; 256]; + let mut bos_descriptor = [0; 256]; + let mut control_buf = [0; 64]; + + let mut state = State::new(); + + let mut builder = Builder::new( + driver, + config, + &mut config_descriptor, + &mut bos_descriptor, + &mut [], // no msos descriptors + &mut control_buf, + ); + + let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); + + let mut usb = builder.build(); + + let usb_fut = usb.run(); + + let echo_fut = async { + loop { + class.wait_connection().await; + info!("Connected"); + let _ = echo(&mut class).await; + info!("Disconnected"); + } + }; + + join(usb_fut, echo_fut).await; +} + +struct Disconnected {} + +impl From for Disconnected { + fn from(val: EndpointError) -> Self { + match val { + EndpointError::BufferOverflow => panic!("Buffer overflow"), + EndpointError::Disabled => Disconnected {}, + } + } +} + +async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> { + let mut buf = [0; 64]; + loop { + let n = class.read_packet(&mut buf).await?; + let data = &buf[..n]; + info!("data: {:x}", data); + class.write_packet(data).await?; + } +} -- cgit From c00efd485c0d422188badddde13613ea50668080 Mon Sep 17 00:00:00 2001 From: Patrick Gansterer Date: Mon, 1 Sep 2025 18:07:31 +0200 Subject: embassy-dfu-usb: Allow `application` and `dfu` feature at the same time Since there is no technical reason to disallow the use of both features at the same time, remove the artifical contraint to give developers more freedom with their implementations. --- embassy-usb-dfu/CHANGELOG.md | 2 ++ embassy-usb-dfu/src/application.rs | 1 + embassy-usb-dfu/src/dfu.rs | 1 + embassy-usb-dfu/src/lib.rs | 14 ++++---------- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/embassy-usb-dfu/CHANGELOG.md b/embassy-usb-dfu/CHANGELOG.md index 466eff211..ef842945d 100644 --- a/embassy-usb-dfu/CHANGELOG.md +++ b/embassy-usb-dfu/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- Allow enabling the `application` and `dfu` feature at the same time + ## 0.2.0 - 2025-08-27 - First release with changelog. diff --git a/embassy-usb-dfu/src/application.rs b/embassy-usb-dfu/src/application.rs index 4b7b72073..78eb2c083 100644 --- a/embassy-usb-dfu/src/application.rs +++ b/embassy-usb-dfu/src/application.rs @@ -1,3 +1,4 @@ +//! Application part of DFU logic use embassy_boot::BlockingFirmwareState; use embassy_time::{Duration, Instant}; use embassy_usb::control::{InResponse, OutResponse, Recipient, RequestType}; diff --git a/embassy-usb-dfu/src/dfu.rs b/embassy-usb-dfu/src/dfu.rs index 9a2f125fb..be28890bb 100644 --- a/embassy-usb-dfu/src/dfu.rs +++ b/embassy-usb-dfu/src/dfu.rs @@ -1,3 +1,4 @@ +//! DFU bootloader part of DFU logic use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterError}; use embassy_usb::control::{InResponse, OutResponse, Recipient, RequestType}; use embassy_usb::driver::Driver; diff --git a/embassy-usb-dfu/src/lib.rs b/embassy-usb-dfu/src/lib.rs index 54ffa7276..e9f4278b6 100644 --- a/embassy-usb-dfu/src/lib.rs +++ b/embassy-usb-dfu/src/lib.rs @@ -6,21 +6,15 @@ mod fmt; pub mod consts; #[cfg(feature = "dfu")] -mod dfu; -#[cfg(feature = "dfu")] +pub mod dfu; +#[cfg(all(feature = "dfu", not(feature = "application")))] pub use self::dfu::*; #[cfg(feature = "application")] -mod application; -#[cfg(feature = "application")] +pub mod application; +#[cfg(all(feature = "application", not(feature = "dfu")))] pub use self::application::*; -#[cfg(any( - all(feature = "dfu", feature = "application"), - not(any(feature = "dfu", feature = "application")) -))] -compile_error!("usb-dfu must be compiled with exactly one of `dfu`, or `application` features"); - /// Provides a platform-agnostic interface for initiating a system reset. /// /// This crate exposes `ResetImmediate` when compiled with cortex-m or esp32c3 support, which immediately issues a -- cgit From 219cf09aab41cff9f2682a6b1e00610f96d25b1f Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Tue, 2 Sep 2025 08:33:00 +0200 Subject: Remove features, fix changelog --- embassy-executor/CHANGELOG.md | 4 ++-- embassy-executor/Cargo.toml | 16 ---------------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 3e6c180c6..a36d270ba 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -20,8 +20,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `extern "Rust" fn __embassy_time_queue_item_from_waker` - Removed `TaskRef::dangling` -- Added `embassy_time_queue_utils` as a dependency -- Moved the `TimeQueueItem` struct and `timer-item-payload-size-*` features into embassy-time-queue-utils +- Added `embassy-executor-timer-queue` as a dependency +- Moved the `TimeQueueItem` struct and `timer-item-payload-size-*` features (as `timer-item-size-X-words`) into `embassy-executor-timer-queue` ## 0.8.0 - 2025-07-31 diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index dc423aba2..ed72a585f 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -125,19 +125,3 @@ trace = ["_any_trace"] ## Enable support for rtos-trace framework rtos-trace = ["_any_trace", "metadata-name", "dep:rtos-trace", "dep:embassy-time-driver"] _any_trace = [] - -#! ### Timer Item Payload Size -#! Sets the size of the payload for timer items, allowing integrated timer implementors to store -#! additional data in the timer item. The payload field will be aligned to this value as well. -#! If these features are not defined, the timer item will contain no payload field. - -_timer-item-payload = [] # A size was picked - -## 1 bytes -timer-item-payload-size-1 = ["_timer-item-payload"] -## 2 bytes -timer-item-payload-size-2 = ["_timer-item-payload"] -## 4 bytes -timer-item-payload-size-4 = ["_timer-item-payload"] -## 8 bytes -timer-item-payload-size-8 = ["_timer-item-payload"] -- cgit From 698109acfe263e9441f6aa501b2649b16d19b115 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Tue, 2 Sep 2025 23:20:01 +0800 Subject: derive Clone, Copy for qspi config --- embassy-stm32/src/qspi/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index 1e20d7cd3..bdc3b7f34 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -46,6 +46,7 @@ impl Default for TransferConfig { } /// QSPI driver configuration. +#[derive(Clone, Copy)] pub struct Config { /// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen. /// If you need other value the whose predefined use `Other` variant. -- cgit From 91e33015c3cabb19f818d8fc7ea51d33a71621c5 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Tue, 2 Sep 2025 23:23:01 +0800 Subject: update changelog --- embassy-stm32/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index dfb8ca066..133defcc6 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate - fix: Fixed STM32H5 builds requiring time feature +- feat: Derive Clone, Copy for QSPI Config ## 0.4.0 - 2025-08-26 -- cgit From 010f4b08aa6846ffdbf906398caaceb4eb9c1c39 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Tue, 2 Sep 2025 23:41:25 +0800 Subject: derive Clone, Copy for qspi transfer config --- embassy-stm32/src/qspi/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index bdc3b7f34..c0cd216f0 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -17,6 +17,7 @@ use crate::rcc::{self, RccPeripheral}; use crate::{peripherals, Peri}; /// QSPI transfer configuration. +#[derive(Clone, Copy)] pub struct TransferConfig { /// Instruction width (IMODE) pub iwidth: QspiWidth, -- cgit From 56f3c7a8c72356d9e21d5ef13e60d869ffd8cdf2 Mon Sep 17 00:00:00 2001 From: Fabian Wolter Date: Tue, 2 Sep 2025 21:17:47 +0200 Subject: stm32/i2c: fix failure of subsequent transmissions after NACK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a slave responds with a NACK in blocking I²C master mode, all subsequent transmissions send only the address followed immediately by a STOP. This happens because the current implementation sets I2C_CR2.STOP = 1 whenever any error (including a NACK) occurs. As a result, the STOP bit is already set when the next transmission starts. According to the reference manual: "If a NACK is received: […] a STOP condition is automatically sent […]" This bug was not triggered until #4454 was merged. --- embassy-stm32/src/i2c/v2.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 3b09f1b34..6b20a601b 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -454,7 +454,8 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { // (START has been ACKed or last byte when // through) if let Err(err) = self.wait_txis(timeout) { - if send_stop { + if send_stop && err != Error::Nack { + // STOP is sent automatically if a NACK was received self.master_stop(); } return Err(err); @@ -548,7 +549,9 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { (idx != last_slice_index) || (slice_len > 255), timeout, ) { - self.master_stop(); + if err != Error::Nack { + self.master_stop(); + } return Err(err); } } @@ -561,7 +564,9 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { (number != last_chunk_idx) || (idx != last_slice_index), timeout, ) { - self.master_stop(); + if err != Error::Nack { + self.master_stop(); + } return Err(err); } } @@ -571,7 +576,9 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { // (START has been ACKed or last byte when // through) if let Err(err) = self.wait_txis(timeout) { - self.master_stop(); + if err != Error::Nack { + self.master_stop(); + } return Err(err); } -- cgit From 0835b58deb24482ec7831c2d04d7f73d1abd197b Mon Sep 17 00:00:00 2001 From: Fabian Wolter Date: Tue, 2 Sep 2025 21:25:42 +0200 Subject: Update changelog --- embassy-stm32/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 133defcc6..c9be259ea 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - fix: Fixed STM32H5 builds requiring time feature - feat: Derive Clone, Copy for QSPI Config +- fix: stm32/i2c in master mode (blocking): subsequent transmissions failed after a NACK was received ## 0.4.0 - 2025-08-26 -- cgit From d17f4d71781e016f44b081a981a79fdccddabb33 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 2 Sep 2025 15:44:44 -0700 Subject: Fix comments - rename read_data to read_transfer - rename write_data to write_transfer - add needs_zlp argument Signed-off-by: Felipe Balbi --- embassy-usb-driver/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-usb-driver/src/lib.rs b/embassy-usb-driver/src/lib.rs index 789d6de93..3ad96c61d 100644 --- a/embassy-usb-driver/src/lib.rs +++ b/embassy-usb-driver/src/lib.rs @@ -242,7 +242,7 @@ pub trait EndpointOut: Endpoint { /// /// This should also clear any NAK flags and prepare the endpoint to receive the next packet or /// data block. - async fn read_data(&mut self, buf: &mut [u8]) -> Result { + async fn read_transfer(&mut self, buf: &mut [u8]) -> Result { let mut n = 0; loop { let i = self.read(&mut buf[n..]).await?; @@ -370,11 +370,11 @@ pub trait EndpointIn: Endpoint { /// /// If the buffer size is evenly divisible by wMaxPacketSize, this will also ensure the /// terminating zero-length-packet is transmitted. - async fn write_data(&mut self, buf: &[u8]) -> Result<(), EndpointError> { + async fn write_transfer(&mut self, buf: &[u8], needs_zlp: bool) -> Result<(), EndpointError> { for chunk in buf.chunks(self.info().max_packet_size as usize) { self.write(chunk).await?; } - if buf.len() % self.info().max_packet_size as usize == 0 { + if needs_zlp && buf.len() % self.info().max_packet_size as usize == 0 { self.write(&[]).await?; } Ok(()) -- cgit From 089b6722c6c58a023beccdd8f15695f1df0fe117 Mon Sep 17 00:00:00 2001 From: "r.marple" Date: Wed, 3 Sep 2025 15:53:50 +1000 Subject: Added timer set polarity functions for main and complementary outputs individually --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/src/timer/complementary_pwm.rs | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index c9be259ea..4cc48ed97 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - fix: Fixed STM32H5 builds requiring time feature - feat: Derive Clone, Copy for QSPI Config - fix: stm32/i2c in master mode (blocking): subsequent transmissions failed after a NACK was received +- feat: stm32/timer: add set_polarity functions for main and complementary outputs in complementary_pwm ## 0.4.0 - 2025-08-26 diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index b291fc155..7d6c2273e 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -185,6 +185,16 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { self.inner.set_complementary_output_polarity(channel, polarity); } + /// Set the main output polarity for a given channel. + pub fn set_main_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { + self.inner.set_output_polarity(channel, polarity); + } + + /// Set the complementary output polarity for a given channel. + pub fn set_complementary_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { + self.inner.set_complementary_output_polarity(channel, polarity); + } + /// Set the dead time as a proportion of max_duty pub fn set_dead_time(&mut self, value: u16) { let (ckd, value) = compute_dead_time_value(value); -- cgit From d1429868cefa319217089f6501cbafa503d6d6ba Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 6 Dec 2024 11:34:30 +0100 Subject: nrf: add NFCT NDEF example. --- examples/nrf52840/src/bin/nfct.rs | 274 +++++++++++++++++++++++++++++++++++--- 1 file changed, 259 insertions(+), 15 deletions(-) diff --git a/examples/nrf52840/src/bin/nfct.rs b/examples/nrf52840/src/bin/nfct.rs index d559d006a..0b128c3bd 100644 --- a/examples/nrf52840/src/bin/nfct.rs +++ b/examples/nrf52840/src/bin/nfct.rs @@ -1,11 +1,12 @@ #![no_std] #![no_main] -use defmt::*; +use defmt::{todo, *}; use embassy_executor::Spawner; use embassy_nrf::config::HfclkSource; use embassy_nrf::nfct::{Config as NfcConfig, NfcId, NfcT}; use embassy_nrf::{bind_interrupts, nfct}; +use iso14443_4::{Card, IsoDep}; use {defmt_rtt as _, embassy_nrf as _, panic_probe as _}; bind_interrupts!(struct Irqs { @@ -30,12 +31,28 @@ async fn main(_spawner: Spawner) { let mut buf = [0u8; 256]; + let cc = &[ + 0x00, 0x0f, /* CCEN_HI, CCEN_LOW */ + 0x20, /* VERSION */ + 0x00, 0x7f, /* MLe_HI, MLe_LOW */ + 0x00, 0x7f, /* MLc_HI, MLc_LOW */ + /* TLV */ + 0x04, 0x06, 0xe1, 0x04, 0x00, 0x7f, 0x00, 0x00, + ]; + + let ndef = &[ + 0x00, 0x10, 0xd1, 0x1, 0xc, 0x55, 0x4, 0x65, 0x6d, 0x62, 0x61, 0x73, 0x73, 0x79, 0x2e, 0x64, 0x65, 0x76, + ]; + let mut selected: &[u8] = cc; + loop { info!("activating"); nfc.activate().await; + info!("activated!"); + + let mut nfc = IsoDep::new(iso14443_3::Logger(&mut nfc)); loop { - info!("rxing"); let n = match nfc.receive(&mut buf).await { Ok(n) => n, Err(e) => { @@ -44,25 +61,51 @@ async fn main(_spawner: Spawner) { } }; let req = &buf[..n]; - info!("received frame {:02x}", req); + info!("iso-dep rx {:02x}", req); - let mut deselect = false; - let resp = match req { - [0xe0, ..] => { - info!("Got RATS, tx'ing ATS"); - &[0x06, 0x77, 0x77, 0x81, 0x02, 0x80][..] + let Ok(apdu) = Apdu::parse(req) else { + error!("apdu parse error"); + break; + }; + + info!("apdu: {:?}", apdu); + + let resp = match (apdu.cla, apdu.ins, apdu.p1, apdu.p2) { + (0, 0xa4, 4, 0) => { + info!("select app"); + &[0x90, 0x00][..] } - [0xc2] => { - info!("Got deselect!"); - deselect = true; - &[0xc2] + (0, 0xa4, 0, 12) => { + info!("select df"); + match apdu.data { + [0xe1, 0x03] => { + selected = cc; + &[0x90, 0x00][..] + } + [0xe1, 0x04] => { + selected = ndef; + &[0x90, 0x00][..] + } + _ => todo!(), // return NOT FOUND + } + } + (0, 0xb0, p1, p2) => { + info!("read"); + let offs = u16::from_be_bytes([p1 & 0xef, p2]) as usize; + let len = if apdu.le == 0 { usize::MAX } else { apdu.le as usize }; + let n = len.min(selected.len() - offs); + buf[..n].copy_from_slice(&selected[offs..][..n]); + buf[n..][..2].copy_from_slice(&[0x90, 0x00]); + &buf[..n + 2] } _ => { info!("Got unknown command!"); - &[0xFF] + &[0xFF, 0xFF] } }; + info!("iso-dep tx {:02x}", resp); + match nfc.transmit(resp).await { Ok(()) => {} Err(e) => { @@ -70,10 +113,211 @@ async fn main(_spawner: Spawner) { break; } } + } + } +} - if deselect { - break; +#[derive(Debug, Clone, defmt::Format)] +struct Apdu<'a> { + pub cla: u8, + pub ins: u8, + pub p1: u8, + pub p2: u8, + pub data: &'a [u8], + pub le: u16, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)] +struct ApduParseError; + +impl<'a> Apdu<'a> { + pub fn parse(apdu: &'a [u8]) -> Result { + if apdu.len() < 4 { + return Err(ApduParseError); + } + + let (data, le) = match apdu.len() - 4 { + 0 => (&[][..], 0), + 1 => (&[][..], apdu[4]), + n if n == 1 + apdu[4] as usize && apdu[4] != 0 => (&apdu[5..][..apdu[4] as usize], 0), + n if n == 2 + apdu[4] as usize && apdu[4] != 0 => (&apdu[5..][..apdu[4] as usize], apdu[apdu.len() - 1]), + _ => return Err(ApduParseError), + }; + + Ok(Apdu { + cla: apdu[0], + ins: apdu[1], + p1: apdu[2], + p2: apdu[3], + data, + le: le as _, + }) + } +} + +mod iso14443_3 { + use core::future::Future; + + use defmt::info; + use embassy_nrf::nfct::{Error, NfcT}; + + pub trait Card { + type Error; + async fn receive(&mut self, buf: &mut [u8]) -> Result; + async fn transmit(&mut self, buf: &[u8]) -> Result<(), Self::Error>; + } + + impl<'a, T: Card> Card for &'a mut T { + type Error = T::Error; + + fn receive(&mut self, buf: &mut [u8]) -> impl Future> { + T::receive(self, buf) + } + + fn transmit(&mut self, buf: &[u8]) -> impl Future> { + T::transmit(self, buf) + } + } + + impl<'a> Card for NfcT<'a> { + type Error = Error; + + fn receive(&mut self, buf: &mut [u8]) -> impl Future> { + self.receive(buf) + } + + fn transmit(&mut self, buf: &[u8]) -> impl Future> { + self.transmit(buf) + } + } + + pub struct Logger(pub T); + + impl Card for Logger { + type Error = T::Error; + + async fn receive(&mut self, buf: &mut [u8]) -> Result { + let n = T::receive(&mut self.0, buf).await?; + info!("<- {:02x}", &buf[..n]); + Ok(n) + } + + fn transmit(&mut self, buf: &[u8]) -> impl Future> { + info!("-> {:02x}", buf); + T::transmit(&mut self.0, buf) + } + } +} + +mod iso14443_4 { + use defmt::info; + + use crate::iso14443_3; + + #[derive(defmt::Format)] + pub enum Error { + Deselected, + Protocol, + Lower(T), + } + + pub trait Card { + type Error; + async fn receive(&mut self, buf: &mut [u8]) -> Result; + async fn transmit(&mut self, buf: &[u8]) -> Result<(), Self::Error>; + } + + pub struct IsoDep { + nfc: T, + + /// Block count spin bit: 0 or 1 + block_num: u8, + + /// true if deselected. This is permanent, you must create another IsoDep + /// instance if we get selected again. + deselected: bool, + + /// last response, in case we need to retransmit. + resp: [u8; 256], + resp_len: usize, + } + + impl IsoDep { + pub fn new(nfc: T) -> Self { + Self { + nfc, + block_num: 1, + deselected: false, + resp: [0u8; 256], + resp_len: 0, } } } + + impl Card for IsoDep { + type Error = Error; + + async fn receive(&mut self, buf: &mut [u8]) -> Result { + if self.deselected { + return Err(Error::Deselected); + } + + let mut temp = [0u8; 256]; + + loop { + let n = self.nfc.receive(&mut temp).await.map_err(Error::Lower)?; + assert!(n != 0); + match temp[0] { + 0x02 | 0x03 => { + self.block_num ^= 0x01; + assert!(temp[0] == 0x02 | self.block_num); + buf[..n - 1].copy_from_slice(&temp[1..n]); + return Ok(n - 1); + } + 0xb2 | 0xb3 => { + if temp[0] & 0x01 != self.block_num { + info!("Got NAK, transmitting ACK."); + let resp = &[0xA2 | self.block_num]; + self.nfc.transmit(resp).await.map_err(Error::Lower)?; + } else { + info!("Got NAK, retransmitting."); + let resp: &[u8] = &self.resp[..self.resp_len]; + self.nfc.transmit(resp).await.map_err(Error::Lower)?; + } + } + 0xe0 => { + info!("Got RATS, tx'ing ATS"); + let resp = &[0x06, 0x77, 0x77, 0x81, 0x02, 0x80]; + self.nfc.transmit(resp).await.map_err(Error::Lower)?; + } + 0xc2 => { + info!("Got deselect!"); + self.deselected = true; + let resp = &[0xC2]; + self.nfc.transmit(resp).await.map_err(Error::Lower)?; + return Err(Error::Deselected); + } + _ => { + info!("Got unknown command {:02x}!", temp[0]); + return Err(Error::Protocol); + } + }; + } + } + + async fn transmit(&mut self, buf: &[u8]) -> Result<(), Self::Error> { + if self.deselected { + return Err(Error::Deselected); + } + + self.resp[0] = 0x02 | self.block_num; + self.resp[1..][..buf.len()].copy_from_slice(buf); + self.resp_len = 1 + buf.len(); + + let resp: &[u8] = &self.resp[..self.resp_len]; + self.nfc.transmit(resp).await.map_err(Error::Lower)?; + + Ok(()) + } + } } -- cgit From 9ac8944478d43693da7dce41762c92e9d5777e06 Mon Sep 17 00:00:00 2001 From: wackazong Date: Fri, 10 Jan 2025 11:50:40 +0100 Subject: Fix offset calculation --- examples/nrf52840/src/bin/nfct.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nrf52840/src/bin/nfct.rs b/examples/nrf52840/src/bin/nfct.rs index 0b128c3bd..fafa37f48 100644 --- a/examples/nrf52840/src/bin/nfct.rs +++ b/examples/nrf52840/src/bin/nfct.rs @@ -91,7 +91,7 @@ async fn main(_spawner: Spawner) { } (0, 0xb0, p1, p2) => { info!("read"); - let offs = u16::from_be_bytes([p1 & 0xef, p2]) as usize; + let offs = u16::from_be_bytes([p1 & 0x7f, p2]) as usize; let len = if apdu.le == 0 { usize::MAX } else { apdu.le as usize }; let n = len.min(selected.len() - offs); buf[..n].copy_from_slice(&selected[offs..][..n]); -- cgit From 3c3b43fb00355a5db64a34416dc2f19042a3fc5a Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: feat: GPDAM linked-list + ringbuffer support --- embassy-stm32/src/dma/gpdma.rs | 339 ----------------- embassy-stm32/src/dma/gpdma/linked_list.rs | 236 ++++++++++++ embassy-stm32/src/dma/gpdma/mod.rs | 572 +++++++++++++++++++++++++++++ embassy-stm32/src/dma/gpdma/ringbuffer.rs | 283 ++++++++++++++ embassy-stm32/src/dma/ringbuffer/mod.rs | 2 - embassy-stm32/src/sai/mod.rs | 9 - 6 files changed, 1091 insertions(+), 350 deletions(-) delete mode 100644 embassy-stm32/src/dma/gpdma.rs create mode 100644 embassy-stm32/src/dma/gpdma/linked_list.rs create mode 100644 embassy-stm32/src/dma/gpdma/mod.rs create mode 100644 embassy-stm32/src/dma/gpdma/ringbuffer.rs diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs deleted file mode 100644 index 151e4ab9f..000000000 --- a/embassy-stm32/src/dma/gpdma.rs +++ /dev/null @@ -1,339 +0,0 @@ -#![macro_use] - -use core::future::Future; -use core::pin::Pin; -use core::sync::atomic::{fence, Ordering}; -use core::task::{Context, Poll}; - -use embassy_hal_internal::Peri; -use embassy_sync::waitqueue::AtomicWaker; - -use super::word::{Word, WordSize}; -use super::{AnyChannel, Channel, Dir, Request, STATE}; -use crate::interrupt::typelevel::Interrupt; -use crate::interrupt::Priority; -use crate::pac; -use crate::pac::gpdma::vals; - -pub(crate) struct ChannelInfo { - pub(crate) dma: pac::gpdma::Gpdma, - pub(crate) num: usize, - #[cfg(feature = "_dual-core")] - pub(crate) irq: pac::Interrupt, -} - -/// GPDMA transfer options. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -#[non_exhaustive] -pub struct TransferOptions {} - -impl Default for TransferOptions { - fn default() -> Self { - Self {} - } -} - -impl From for vals::Dw { - fn from(raw: WordSize) -> Self { - match raw { - WordSize::OneByte => Self::BYTE, - WordSize::TwoBytes => Self::HALF_WORD, - WordSize::FourBytes => Self::WORD, - } - } -} - -pub(crate) struct ChannelState { - waker: AtomicWaker, -} - -impl ChannelState { - pub(crate) const NEW: Self = Self { - waker: AtomicWaker::new(), - }; -} - -/// safety: must be called only once -pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: Priority) { - foreach_interrupt! { - ($peri:ident, gpdma, $block:ident, $signal_name:ident, $irq:ident) => { - crate::interrupt::typelevel::$irq::set_priority_with_cs(cs, irq_priority); - #[cfg(not(feature = "_dual-core"))] - crate::interrupt::typelevel::$irq::enable(); - }; - } - crate::_generated::init_gpdma(); -} - -impl AnyChannel { - /// Safety: Must be called with a matching set of parameters for a valid dma channel - pub(crate) unsafe fn on_irq(&self) { - let info = self.info(); - #[cfg(feature = "_dual-core")] - { - use embassy_hal_internal::interrupt::InterruptExt as _; - info.irq.enable(); - } - - let state = &STATE[self.id as usize]; - - let ch = info.dma.ch(info.num); - let sr = ch.sr().read(); - - if sr.dtef() { - panic!( - "DMA: data transfer error on DMA@{:08x} channel {}", - info.dma.as_ptr() as u32, - info.num - ); - } - if sr.usef() { - panic!( - "DMA: user settings error on DMA@{:08x} channel {}", - info.dma.as_ptr() as u32, - info.num - ); - } - - if sr.suspf() || sr.tcf() { - // disable all xxIEs to prevent the irq from firing again. - ch.cr().write(|_| {}); - - // Wake the future. It'll look at tcf and see it's set. - state.waker.wake(); - } - } -} - -/// DMA transfer. -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct Transfer<'a> { - channel: Peri<'a, AnyChannel>, -} - -impl<'a> Transfer<'a> { - /// Create a new read DMA transfer (peripheral to memory). - pub unsafe fn new_read( - channel: Peri<'a, impl Channel>, - request: Request, - peri_addr: *mut W, - buf: &'a mut [W], - options: TransferOptions, - ) -> Self { - Self::new_read_raw(channel, request, peri_addr, buf, options) - } - - /// Create a new read DMA transfer (peripheral to memory), using raw pointers. - pub unsafe fn new_read_raw( - channel: Peri<'a, impl Channel>, - request: Request, - peri_addr: *mut PW, - buf: *mut [MW], - options: TransferOptions, - ) -> Self { - Self::new_inner( - channel.into(), - request, - Dir::PeripheralToMemory, - peri_addr as *const u32, - buf as *mut MW as *mut u32, - buf.len(), - true, - PW::size(), - MW::size(), - options, - ) - } - - /// Create a new write DMA transfer (memory to peripheral). - pub unsafe fn new_write( - channel: Peri<'a, impl Channel>, - request: Request, - buf: &'a [MW], - peri_addr: *mut PW, - options: TransferOptions, - ) -> Self { - Self::new_write_raw(channel, request, buf, peri_addr, options) - } - - /// Create a new write DMA transfer (memory to peripheral), using raw pointers. - pub unsafe fn new_write_raw( - channel: Peri<'a, impl Channel>, - request: Request, - buf: *const [MW], - peri_addr: *mut PW, - options: TransferOptions, - ) -> Self { - Self::new_inner( - channel.into(), - request, - Dir::MemoryToPeripheral, - peri_addr as *const u32, - buf as *const MW as *mut u32, - buf.len(), - true, - MW::size(), - PW::size(), - options, - ) - } - - /// Create a new write DMA transfer (memory to peripheral), writing the same value repeatedly. - pub unsafe fn new_write_repeated( - channel: Peri<'a, impl Channel>, - request: Request, - repeated: &'a MW, - count: usize, - peri_addr: *mut PW, - options: TransferOptions, - ) -> Self { - Self::new_inner( - channel.into(), - request, - Dir::MemoryToPeripheral, - peri_addr as *const u32, - repeated as *const MW as *mut u32, - count, - false, - MW::size(), - PW::size(), - options, - ) - } - - unsafe fn new_inner( - channel: Peri<'a, AnyChannel>, - request: Request, - dir: Dir, - peri_addr: *const u32, - mem_addr: *mut u32, - mem_len: usize, - incr_mem: bool, - data_size: WordSize, - dst_size: WordSize, - _options: TransferOptions, - ) -> Self { - // BNDT is specified as bytes, not as number of transfers. - let Ok(bndt) = (mem_len * data_size.bytes()).try_into() else { - panic!("DMA transfers may not be larger than 65535 bytes."); - }; - - let info = channel.info(); - let ch = info.dma.ch(info.num); - - // "Preceding reads and writes cannot be moved past subsequent writes." - fence(Ordering::SeqCst); - - let this = Self { channel }; - - ch.cr().write(|w| w.set_reset(true)); - ch.fcr().write(|w| w.0 = 0xFFFF_FFFF); // clear all irqs - ch.llr().write(|_| {}); // no linked list - ch.tr1().write(|w| { - w.set_sdw(data_size.into()); - w.set_ddw(dst_size.into()); - w.set_sinc(dir == Dir::MemoryToPeripheral && incr_mem); - w.set_dinc(dir == Dir::PeripheralToMemory && incr_mem); - }); - ch.tr2().write(|w| { - w.set_dreq(match dir { - Dir::MemoryToPeripheral => vals::Dreq::DESTINATION_PERIPHERAL, - Dir::PeripheralToMemory => vals::Dreq::SOURCE_PERIPHERAL, - }); - w.set_reqsel(request); - }); - ch.tr3().write(|_| {}); // no address offsets. - ch.br1().write(|w| w.set_bndt(bndt)); - - match dir { - Dir::MemoryToPeripheral => { - ch.sar().write_value(mem_addr as _); - ch.dar().write_value(peri_addr as _); - } - Dir::PeripheralToMemory => { - ch.sar().write_value(peri_addr as _); - ch.dar().write_value(mem_addr as _); - } - } - - ch.cr().write(|w| { - // Enable interrupts - w.set_tcie(true); - w.set_useie(true); - w.set_dteie(true); - w.set_suspie(true); - - // Start it - w.set_en(true); - }); - - this - } - - /// Request the transfer to stop. - /// - /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_stop(&mut self) { - let info = self.channel.info(); - let ch = info.dma.ch(info.num); - - ch.cr().modify(|w| w.set_susp(true)) - } - - /// Return whether this transfer is still running. - /// - /// If this returns `false`, it can be because either the transfer finished, or - /// it was requested to stop early with [`request_stop`](Self::request_stop). - pub fn is_running(&mut self) -> bool { - let info = self.channel.info(); - let ch = info.dma.ch(info.num); - - let sr = ch.sr().read(); - !sr.tcf() && !sr.suspf() - } - - /// Gets the total remaining transfers for the channel - /// Note: this will be zero for transfers that completed without cancellation. - pub fn get_remaining_transfers(&self) -> u16 { - let info = self.channel.info(); - let ch = info.dma.ch(info.num); - - ch.br1().read().bndt() - } - - /// Blocking wait until the transfer finishes. - pub fn blocking_wait(mut self) { - while self.is_running() {} - - // "Subsequent reads and writes cannot be moved ahead of preceding reads." - fence(Ordering::SeqCst); - - core::mem::forget(self); - } -} - -impl<'a> Drop for Transfer<'a> { - fn drop(&mut self) { - self.request_stop(); - while self.is_running() {} - - // "Subsequent reads and writes cannot be moved ahead of preceding reads." - fence(Ordering::SeqCst); - } -} - -impl<'a> Unpin for Transfer<'a> {} -impl<'a> Future for Transfer<'a> { - type Output = (); - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let state = &STATE[self.channel.id as usize]; - state.waker.register(cx.waker()); - - if self.is_running() { - Poll::Pending - } else { - Poll::Ready(()) - } - } -} diff --git a/embassy-stm32/src/dma/gpdma/linked_list.rs b/embassy-stm32/src/dma/gpdma/linked_list.rs new file mode 100644 index 000000000..b24b2e7eb --- /dev/null +++ b/embassy-stm32/src/dma/gpdma/linked_list.rs @@ -0,0 +1,236 @@ +//! Implementation of the GPDMA linked list and linked list items. +#![macro_use] + +use stm32_metapac::gpdma::{regs, vals::Dreq}; + +use super::TransferOptions; +use crate::dma::{ + word::{Word, WordSize}, + Dir, Request, +}; +use core::{ + ptr, + sync::atomic::{AtomicUsize, Ordering}, +}; + +/// The mode in which to run the linked list. +#[derive(Debug)] +pub enum RunMode { + /// List items are not linked together. + Unlinked, + /// The list is linked sequentially and only run once. + Once, + /// The list is linked sequentially, and the end of the list is linked to the beginning. + Repeat, +} + +/// A linked-list item for linear GPDMA transfers. +/// +/// Also works for 2D-capable GPDMA channels, but does not use 2D capabilities. +#[derive(Debug, Copy, Clone, Default)] +#[repr(C)] +pub struct LinearItem { + /// Transfer register 1. + pub tr1: u32, + /// Transfer register 2. + pub tr2: u32, + /// Block register 2. + pub br1: u32, + /// Source address register. + pub sar: u32, + /// Destination address register. + pub dar: u32, + /// Linked-list address register. + pub llr: u32, +} + +impl LinearItem { + /// Create a new read DMA transfer (peripheral to memory). + pub unsafe fn new_read<'d, W: Word>( + request: Request, + peri_addr: *mut W, + buf: &'d mut [W], + options: TransferOptions, + ) -> Self { + Self::new_inner( + request, + Dir::PeripheralToMemory, + peri_addr as *const u32, + buf as *mut [W] as *mut W as *mut u32, + buf.len(), + true, + W::size(), + W::size(), + options, + ) + } + + /// Create a new write DMA transfer (memory to peripheral). + pub unsafe fn new_write<'d, MW: Word, PW: Word>( + request: Request, + buf: &'d [MW], + peri_addr: *mut PW, + options: TransferOptions, + ) -> Self { + Self::new_inner( + request, + Dir::MemoryToPeripheral, + peri_addr as *const u32, + buf as *const [MW] as *const MW as *mut u32, + buf.len(), + true, + MW::size(), + PW::size(), + options, + ) + } + + unsafe fn new_inner( + request: Request, + dir: Dir, + peri_addr: *const u32, + mem_addr: *mut u32, + mem_len: usize, + incr_mem: bool, + data_size: WordSize, + dst_size: WordSize, + _options: TransferOptions, + ) -> Self { + // BNDT is specified as bytes, not as number of transfers. + let Ok(bndt) = (mem_len * data_size.bytes()).try_into() else { + panic!("DMA transfers may not be larger than 65535 bytes."); + }; + + let mut br1 = regs::ChBr1(0); + br1.set_bndt(bndt); + + let mut tr1 = regs::ChTr1(0); + tr1.set_sdw(data_size.into()); + tr1.set_ddw(dst_size.into()); + tr1.set_sinc(dir == Dir::MemoryToPeripheral && incr_mem); + tr1.set_dinc(dir == Dir::PeripheralToMemory && incr_mem); + + let mut tr2 = regs::ChTr2(0); + tr2.set_dreq(match dir { + Dir::MemoryToPeripheral => Dreq::DESTINATION_PERIPHERAL, + Dir::PeripheralToMemory => Dreq::SOURCE_PERIPHERAL, + }); + tr2.set_reqsel(request); + + let (sar, dar) = match dir { + Dir::MemoryToPeripheral => (mem_addr as _, peri_addr as _), + Dir::PeripheralToMemory => (peri_addr as _, mem_addr as _), + }; + + let llr = regs::ChLlr(0); + + Self { + tr1: tr1.0, + tr2: tr2.0, + br1: br1.0, + sar, + dar, + llr: llr.0, + } + } + + /// Link to the next linear item at the given address. + /// + /// Enables channel update bits. + fn link_to(&mut self, next: u16) { + let mut llr = regs::ChLlr(0); + + llr.set_ut1(true); + llr.set_ut2(true); + llr.set_ub1(true); + llr.set_usa(true); + llr.set_uda(true); + llr.set_ull(true); + llr.set_la(next); + + self.llr = llr.0; + } + + /// Unlink the next linear item. + /// + /// Disables channel update bits. + fn unlink(&mut self) { + self.llr = regs::ChLlr(0).0; + } +} + +pub struct Table { + current_index: AtomicUsize, + items: [LinearItem; ITEM_COUNT], +} + +impl Table { + /// Create a new table. + pub fn new(items: [LinearItem; ITEM_COUNT], run_mode: RunMode) -> Self { + assert!(!items.is_empty()); + + let mut this = Self { + current_index: AtomicUsize::new(0), + items, + }; + + if matches!(run_mode, RunMode::Once | RunMode::Repeat) { + this.link_sequential(); + } + + if matches!(run_mode, RunMode::Repeat) { + this.link_repeat(); + } + + this + } + + pub fn len(&self) -> usize { + self.items.len() + } + + /// Items are linked together sequentially. + pub fn link_sequential(&mut self) { + if self.items.len() > 1 { + for index in 0..(self.items.len() - 1) { + let next = ptr::addr_of!(self.items[index + 1]) as u16; + self.items[index].link_to(next); + } + } + } + + /// Last item links to first item. + pub fn link_repeat(&mut self) { + let first_item = self.items.first().unwrap(); + let first_address = ptr::addr_of!(first_item) as u16; + self.items.last_mut().unwrap().link_to(first_address); + } + + /// The index of the next item. + pub fn next_index(&self) -> usize { + let mut next_index = self.current_index.load(Ordering::Relaxed) + 1; + if next_index >= self.len() { + next_index = 0; + } + + next_index + } + + /// Unlink the next item. + pub fn unlink_next(&mut self) { + let next_index = self.next_index(); + self.items[next_index].unlink(); + } + + /// Linked list base address (upper 16 address bits). + pub fn base_address(&self) -> u16 { + ((ptr::addr_of!(self.items) as u32) >> 16) as _ + } + + /// Linked list offset address (lower 16 address bits) at the selected index. + pub fn offset_address(&self, index: usize) -> u16 { + assert!(self.items.len() > index); + + (ptr::addr_of!(self.items[index]) as u32) as _ + } +} diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs new file mode 100644 index 000000000..07acd2cf0 --- /dev/null +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -0,0 +1,572 @@ +#![macro_use] + +use core::future::Future; +use core::pin::Pin; +use core::sync::atomic::{fence, AtomicUsize, Ordering}; +use core::task::{Context, Poll}; + +use embassy_hal_internal::Peri; +use embassy_sync::waitqueue::AtomicWaker; +use linked_list::Table; +use stm32_metapac::gpdma::regs; + +use super::word::{Word, WordSize}; +use super::{AnyChannel, Channel, Dir, Request, STATE}; +use crate::interrupt::typelevel::Interrupt; +use crate::pac; +use crate::pac::gpdma::vals; + +mod linked_list; +mod ringbuffer; + +pub(crate) struct ChannelInfo { + pub(crate) dma: pac::gpdma::Gpdma, + pub(crate) num: usize, + #[cfg(feature = "_dual-core")] + pub(crate) irq: pac::Interrupt, +} + +/// DMA request priority +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Priority { + /// Low Priority + Low, + /// Medium Priority + Medium, + /// High Priority + High, + /// Very High Priority + VeryHigh, +} + +impl From for pac::gpdma::vals::Prio { + fn from(value: Priority) -> Self { + match value { + Priority::Low => pac::gpdma::vals::Prio::LOW_WITH_LOWH_WEIGHT, + Priority::Medium => pac::gpdma::vals::Prio::LOW_WITH_MID_WEIGHT, + Priority::High => pac::gpdma::vals::Prio::LOW_WITH_HIGH_WEIGHT, + Priority::VeryHigh => pac::gpdma::vals::Prio::HIGH, + } + } +} + +/// GPDMA transfer options. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub struct TransferOptions { + priority: Priority, + half_transfer_ir: bool, + complete_transfer_ir: bool, +} + +impl Default for TransferOptions { + fn default() -> Self { + Self { + priority: Priority::VeryHigh, + half_transfer_ir: false, + complete_transfer_ir: true, + } + } +} + +impl From for vals::Dw { + fn from(raw: WordSize) -> Self { + match raw { + WordSize::OneByte => Self::BYTE, + WordSize::TwoBytes => Self::HALF_WORD, + WordSize::FourBytes => Self::WORD, + } + } +} + +pub(crate) struct ChannelState { + waker: AtomicWaker, + complete_count: AtomicUsize, +} + +impl ChannelState { + pub(crate) const NEW: Self = Self { + waker: AtomicWaker::new(), + complete_count: AtomicUsize::new(0), + }; +} + +/// safety: must be called only once +pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: Priority) { + foreach_interrupt! { + ($peri:ident, gpdma, $block:ident, $signal_name:ident, $irq:ident) => { + crate::interrupt::typelevel::$irq::set_priority_with_cs(cs, irq_priority); + #[cfg(not(feature = "_dual-core"))] + crate::interrupt::typelevel::$irq::enable(); + }; + } + crate::_generated::init_gpdma(); +} + +impl AnyChannel { + /// Safety: Must be called with a matching set of parameters for a valid dma channel + pub(crate) unsafe fn on_irq(&self) { + let info = self.info(); + #[cfg(feature = "_dual-core")] + { + use embassy_hal_internal::interrupt::InterruptExt as _; + info.irq.enable(); + } + + let state = &STATE[self.id as usize]; + + let ch = info.dma.ch(info.num); + let sr = ch.sr().read(); + + if sr.dtef() { + panic!( + "DMA: data transfer error on DMA@{:08x} channel {}", + info.dma.as_ptr() as u32, + info.num + ); + } + if sr.usef() { + panic!( + "DMA: user settings error on DMA@{:08x} channel {}", + info.dma.as_ptr() as u32, + info.num + ); + } + if sr.ulef() { + panic!( + "DMA: link transfer error on DMA@{:08x} channel {}", + info.dma.as_ptr() as u32, + info.num + ); + } + + if sr.tcf() { + state.complete_count.fetch_add(1, Ordering::Release); + } + + if sr.suspf() || sr.tcf() { + // disable all xxIEs to prevent the irq from firing again. + ch.cr().write(|_| {}); + + // Wake the future. It'll look at tcf and see it's set. + state.waker.wake(); + } + } + + fn get_remaining_transfers(&self) -> u16 { + let info = self.info(); + let ch = info.dma.ch(info.num); + + ch.br1().read().bndt() + } + + unsafe fn configure( + &self, + request: Request, + dir: Dir, + peri_addr: *const u32, + mem_addr: *mut u32, + mem_len: usize, + incr_mem: bool, + data_size: WordSize, + dst_size: WordSize, + options: TransferOptions, + ) { + // BNDT is specified as bytes, not as number of transfers. + let Ok(bndt) = (mem_len * data_size.bytes()).try_into() else { + panic!("DMA transfers may not be larger than 65535 bytes."); + }; + + let info = self.info(); + let ch = info.dma.ch(info.num); + + // "Preceding reads and writes cannot be moved past subsequent writes." + fence(Ordering::SeqCst); + + ch.cr().write(|w| w.set_reset(true)); + ch.fcr().write(|w| w.0 = 0xFFFF_FFFF); // clear all irqs + ch.llr().write(|_| {}); // no linked list + ch.tr1().write(|w| { + w.set_sdw(data_size.into()); + w.set_ddw(dst_size.into()); + w.set_sinc(dir == Dir::MemoryToPeripheral && incr_mem); + w.set_dinc(dir == Dir::PeripheralToMemory && incr_mem); + }); + ch.tr2().write(|w| { + w.set_dreq(match dir { + Dir::MemoryToPeripheral => vals::Dreq::DESTINATION_PERIPHERAL, + Dir::PeripheralToMemory => vals::Dreq::SOURCE_PERIPHERAL, + }); + w.set_reqsel(request); + }); + ch.tr3().write(|_| {}); // no address offsets. + ch.br1().write(|w| w.set_bndt(bndt)); + + match dir { + Dir::MemoryToPeripheral => { + ch.sar().write_value(mem_addr as _); + ch.dar().write_value(peri_addr as _); + } + Dir::PeripheralToMemory => { + ch.sar().write_value(peri_addr as _); + ch.dar().write_value(mem_addr as _); + } + } + + ch.cr().write(|w| { + w.set_prio(options.priority.into()); + w.set_htie(options.half_transfer_ir); + w.set_tcie(options.complete_transfer_ir); + w.set_useie(true); + w.set_dteie(true); + w.set_suspie(true); + }); + } + + unsafe fn configure_linked_list( + &self, + table: &Table, + options: TransferOptions, + ) { + let info = self.info(); + let ch = info.dma.ch(info.num); + + // "Preceding reads and writes cannot be moved past subsequent writes." + fence(Ordering::SeqCst); + + ch.cr().write(|w| w.set_reset(true)); + ch.fcr().write(|w| w.0 = 0xFFFF_FFFF); // clear all irqs + + ch.lbar().write(|reg| reg.set_lba(table.base_address())); + + // Enable all linked-list field updates. + let mut llr = regs::ChLlr(0); + llr.set_ut1(true); + llr.set_ut2(true); + llr.set_ub1(true); + llr.set_usa(true); + llr.set_uda(true); + llr.set_ull(true); + + llr.set_la(table.offset_address(0)); + + ch.llr().write(|_| llr.0); + + ch.tr3().write(|_| {}); // no address offsets. + + ch.cr().write(|w| { + w.set_prio(options.priority.into()); + w.set_htie(options.half_transfer_ir); + w.set_tcie(options.complete_transfer_ir); + w.set_useie(true); + w.set_uleie(true); + w.set_dteie(true); + w.set_suspie(true); + }); + } + + fn start(&self) { + let info = self.info(); + let ch = info.dma.ch(info.num); + + ch.cr().modify(|w| w.set_en(true)); + } + + fn request_stop(&self) { + let info = self.info(); + let ch = info.dma.ch(info.num); + + ch.cr().modify(|w| w.set_susp(true)) + } + + fn is_running(&self) -> bool { + let info = self.info(); + let ch = info.dma.ch(info.num); + + let sr = ch.sr().read(); + !sr.tcf() && !sr.suspf() + } + + fn poll_stop(&self) -> Poll<()> { + use core::sync::atomic::compiler_fence; + compiler_fence(Ordering::SeqCst); + + if !self.is_running() { + Poll::Ready(()) + } else { + Poll::Pending + } + } +} + +/// Linked-list DMA transfer. +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct LinkedListTransfer<'a, const ITEM_COUNT: usize> { + channel: PeripheralRef<'a, AnyChannel>, + table: Table, +} + +impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { + /// Create a new linked-list transfer. + pub unsafe fn new_linked_list( + channel: impl Peripheral

+ 'a, + table: Table, + options: TransferOptions, + ) -> Self { + into_ref!(channel); + + Self::new_inner_linked_list(channel.map_into(), table, options) + } + + unsafe fn new_inner_linked_list( + channel: PeripheralRef<'a, AnyChannel>, + table: Table, + options: TransferOptions, + ) -> Self { + channel.configure_linked_list(&table, options); + channel.start(); + + Self { channel, table } + } + + /// Request the transfer to stop. + /// + /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. + pub fn request_stop(&mut self) { + self.channel.request_stop() + } + + /// Return whether this transfer is still running. + /// + /// If this returns `false`, it can be because either the transfer finished, or + /// it was requested to stop early with [`request_stop`](Self::request_stop). + pub fn is_running(&mut self) -> bool { + self.channel.is_running() + } + + /// Gets the total remaining transfers for the channel + /// Note: this will be zero for transfers that completed without cancellation. + pub fn get_remaining_transfers(&self) -> u16 { + self.channel.get_remaining_transfers() + } + + /// Blocking wait until the transfer finishes. + pub fn blocking_wait(mut self) { + while self.is_running() {} + + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + fence(Ordering::SeqCst); + + core::mem::forget(self); + } +} + +impl<'a, const ITEM_COUNT: usize> Drop for LinkedListTransfer<'a, ITEM_COUNT> { + fn drop(&mut self) { + self.request_stop(); + while self.is_running() {} + + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + fence(Ordering::SeqCst); + } +} + +impl<'a, const ITEM_COUNT: usize> Unpin for LinkedListTransfer<'a, ITEM_COUNT> {} +impl<'a, const ITEM_COUNT: usize> Future for LinkedListTransfer<'a, ITEM_COUNT> { + type Output = (); + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let state = &STATE[self.channel.id as usize]; + state.waker.register(cx.waker()); + + if self.is_running() { + Poll::Pending + } else { + Poll::Ready(()) + } + } +} + +/// DMA transfer. +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Transfer<'a> { + channel: Peri<'a, AnyChannel>, +} + +impl<'a> Transfer<'a> { + /// Create a new read DMA transfer (peripheral to memory). + pub unsafe fn new_read( + channel: Peri<'a, impl Channel>, + request: Request, + peri_addr: *mut W, + buf: &'a mut [W], + options: TransferOptions, + ) -> Self { + Self::new_read_raw(channel, request, peri_addr, buf, options) + } + + /// Create a new read DMA transfer (peripheral to memory), using raw pointers. + pub unsafe fn new_read_raw( + channel: Peri<'a, impl Channel>, + request: Request, + peri_addr: *mut PW, + buf: *mut [MW], + options: TransferOptions, + ) -> Self { + Self::new_inner( + channel.into(), + request, + Dir::PeripheralToMemory, + peri_addr as *const u32, + buf as *mut MW as *mut u32, + buf.len(), + true, + PW::size(), + MW::size(), + options, + ) + } + + /// Create a new write DMA transfer (memory to peripheral). + pub unsafe fn new_write( + channel: Peri<'a, impl Channel>, + request: Request, + buf: &'a [MW], + peri_addr: *mut PW, + options: TransferOptions, + ) -> Self { + Self::new_write_raw(channel, request, buf, peri_addr, options) + } + + /// Create a new write DMA transfer (memory to peripheral), using raw pointers. + pub unsafe fn new_write_raw( + channel: Peri<'a, impl Channel>, + request: Request, + buf: *const [MW], + peri_addr: *mut PW, + options: TransferOptions, + ) -> Self { + Self::new_inner( + channel.into(), + request, + Dir::MemoryToPeripheral, + peri_addr as *const u32, + buf as *const MW as *mut u32, + buf.len(), + true, + MW::size(), + PW::size(), + options, + ) + } + + /// Create a new write DMA transfer (memory to peripheral), writing the same value repeatedly. + pub unsafe fn new_write_repeated( + channel: Peri<'a, impl Channel>, + request: Request, + repeated: &'a MW, + count: usize, + peri_addr: *mut PW, + options: TransferOptions, + ) -> Self { + Self::new_inner( + channel.into(), + request, + Dir::MemoryToPeripheral, + peri_addr as *const u32, + repeated as *const MW as *mut u32, + count, + false, + MW::size(), + PW::size(), + options, + ) + } + + unsafe fn new_inner( + channel: Peri<'a, AnyChannel>, + request: Request, + dir: Dir, + peri_addr: *const u32, + mem_addr: *mut u32, + mem_len: usize, + incr_mem: bool, + data_size: WordSize, + peripheral_size: WordSize, + options: TransferOptions, + ) -> Self { + assert!(mem_len > 0 && mem_len <= 0xFFFF); + + channel.configure( + _request, + dir, + peri_addr, + mem_addr, + mem_len, + incr_mem, + data_size, + peripheral_size, + options, + ); + channel.start(); + + Self { channel } + } + + /// Request the transfer to stop. + /// + /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. + pub fn request_stop(&mut self) { + self.channel.request_stop() + } + + /// Return whether this transfer is still running. + /// + /// If this returns `false`, it can be because either the transfer finished, or + /// it was requested to stop early with [`request_stop`](Self::request_stop). + pub fn is_running(&mut self) -> bool { + self.channel.is_running() + } + + /// Gets the total remaining transfers for the channel + /// Note: this will be zero for transfers that completed without cancellation. + pub fn get_remaining_transfers(&self) -> u16 { + self.channel.get_remaining_transfers() + } + + /// Blocking wait until the transfer finishes. + pub fn blocking_wait(mut self) { + while self.is_running() {} + + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + fence(Ordering::SeqCst); + + core::mem::forget(self); + } +} + +impl<'a> Drop for Transfer<'a> { + fn drop(&mut self) { + self.request_stop(); + while self.is_running() {} + + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + fence(Ordering::SeqCst); + } +} + +impl<'a> Unpin for Transfer<'a> {} +impl<'a> Future for Transfer<'a> { + type Output = (); + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let state = &STATE[self.channel.id as usize]; + state.waker.register(cx.waker()); + + if self.is_running() { + Poll::Pending + } else { + Poll::Ready(()) + } + } +} diff --git a/embassy-stm32/src/dma/gpdma/ringbuffer.rs b/embassy-stm32/src/dma/gpdma/ringbuffer.rs new file mode 100644 index 000000000..c327e811e --- /dev/null +++ b/embassy-stm32/src/dma/gpdma/ringbuffer.rs @@ -0,0 +1,283 @@ +//! GPDMA ring buffer implementation. +//! +//! FIXME: add request_pause functionality? +use core::{ + sync::atomic::{fence, Ordering}, + task::Waker, +}; + +use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; + +use crate::dma::{ + gpdma::linked_list::{LinearItem, RunMode, Table}, + ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}, + word::Word, + Channel, Dir, Request, +}; + +use super::{AnyChannel, TransferOptions, STATE}; + +struct DmaCtrlImpl<'a>(PeripheralRef<'a, AnyChannel>); + +impl<'a> DmaCtrl for DmaCtrlImpl<'a> { + fn get_remaining_transfers(&self) -> usize { + self.0.get_remaining_transfers() as _ + } + + fn reset_complete_count(&mut self) -> usize { + let state = &STATE[self.0.id as usize]; + + return state.complete_count.swap(0, Ordering::AcqRel); + } + + fn set_waker(&mut self, waker: &Waker) { + STATE[self.0.id as usize].waker.register(waker); + } +} + +/// Ringbuffer for receiving data using GPDMA linked-list mode. +pub struct ReadableRingBuffer<'a, W: Word> { + channel: PeripheralRef<'a, AnyChannel>, + ringbuf: ReadableDmaRingBuffer<'a, W>, + table: Table<2>, +} + +impl<'a, W: Word> ReadableRingBuffer<'a, W> { + /// Create a new ring buffer. + pub unsafe fn new( + channel: impl Peripheral

+ 'a, + request: Request, + peri_addr: *mut W, + buffer: &'a mut [W], + mut options: TransferOptions, + ) -> Self { + into_ref!(channel); + let channel: PeripheralRef<'a, AnyChannel> = channel.map_into(); + + let half_len = buffer.len() / 2; + assert_eq!(half_len * 2, buffer.len()); + + options.half_transfer_ir = false; + options.complete_transfer_ir = true; + + let items = [ + LinearItem::new_read(request, peri_addr, &mut buffer[..half_len], options), + LinearItem::new_read(request, peri_addr, &mut buffer[half_len..], options), + ]; + + let table = Table::new(items, RunMode::Once); + + let this = Self { + channel, + ringbuf: ReadableDmaRingBuffer::new(buffer), + table, + }; + + this.channel.configure_linked_list(&this.table, options); + + this + } + + /// Start the ring buffer operation. + /// + /// You must call this after creating it for it to work. + pub fn start(&mut self) { + self.channel.start(); + } + + /// Clear all data in the ring buffer. + pub fn clear(&mut self) { + self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow())); + } + + /// Read elements from the ring buffer + /// Return a tuple of the length read and the length remaining in the buffer + /// If not all of the elements were read, then there will be some elements in the buffer remaining + /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read + /// Error is returned if the portion to be read was overwritten by the DMA controller. + pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), Error> { + self.ringbuf.read(&mut DmaCtrlImpl(self.channel.reborrow()), buf) + } + + /// Read an exact number of elements from the ringbuffer. + /// + /// Returns the remaining number of elements available for immediate reading. + /// Error is returned if the portion to be read was overwritten by the DMA controller. + /// + /// Async/Wake Behavior: + /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point, + /// and when it wraps around. This means that when called with a buffer of length 'M', when this + /// ring buffer was created with a buffer of size 'N': + /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source. + /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning. + pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result { + self.ringbuf + .read_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) + .await + } + + /// The current length of the ringbuffer + pub fn len(&mut self) -> Result { + Ok(self.ringbuf.len(&mut DmaCtrlImpl(self.channel.reborrow()))?) + } + + /// The capacity of the ringbuffer + pub const fn capacity(&self) -> usize { + self.ringbuf.cap() + } + + /// Set a waker to be woken when at least one byte is received. + pub fn set_waker(&mut self, waker: &Waker) { + DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); + } + + /// Request the DMA to stop. + /// The configuration for this channel will **not be preserved**. If you need to restart the transfer + /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. + /// + /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. + pub fn request_stop(&mut self) { + self.channel.request_stop() + } + + /// Return whether DMA is still running. + /// + /// If this returns `false`, it can be because either the transfer finished, or + /// it was requested to stop early with [`request_stop`](Self::request_stop). + pub fn is_running(&mut self) -> bool { + self.channel.is_running() + } +} + +impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { + fn drop(&mut self) { + self.request_stop(); + while self.is_running() {} + + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + fence(Ordering::SeqCst); + } +} + +/// Ringbuffer for writing data using DMA circular mode. +pub struct WritableRingBuffer<'a, W: Word> { + channel: PeripheralRef<'a, AnyChannel>, + ringbuf: WritableDmaRingBuffer<'a, W>, +} + +impl<'a, W: Word> WritableRingBuffer<'a, W> { + /// Create a new ring buffer. + pub unsafe fn new( + channel: impl Peripheral

+ 'a, + _request: Request, + peri_addr: *mut W, + buffer: &'a mut [W], + mut options: TransferOptions, + ) -> Self { + into_ref!(channel); + let channel: PeripheralRef<'a, AnyChannel> = channel.map_into(); + + let len = buffer.len(); + let dir = Dir::MemoryToPeripheral; + let data_size = W::size(); + let buffer_ptr = buffer.as_mut_ptr(); + + options.half_transfer_ir = true; + options.complete_transfer_ir = true; + + channel.configure( + _request, + dir, + peri_addr as *mut u32, + buffer_ptr as *mut u32, + len, + true, + data_size, + data_size, + options, + ); + + Self { + channel, + ringbuf: WritableDmaRingBuffer::new(buffer), + } + } + + /// Start the ring buffer operation. + /// + /// You must call this after creating it for it to work. + pub fn start(&mut self) { + self.channel.start(); + } + + /// Clear all data in the ring buffer. + pub fn clear(&mut self) { + self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow())); + } + + /// Write elements directly to the raw buffer. + /// This can be used to fill the buffer before starting the DMA transfer. + pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), Error> { + self.ringbuf.write_immediate(buf) + } + + /// Write elements from the ring buffer + /// Return a tuple of the length written and the length remaining in the buffer + pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), Error> { + self.ringbuf.write(&mut DmaCtrlImpl(self.channel.reborrow()), buf) + } + + /// Write an exact number of elements to the ringbuffer. + pub async fn write_exact(&mut self, buffer: &[W]) -> Result { + self.ringbuf + .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) + .await + } + + /// Wait for any ring buffer write error. + pub async fn wait_write_error(&mut self) -> Result { + self.ringbuf + .wait_write_error(&mut DmaCtrlImpl(self.channel.reborrow())) + .await + } + + /// The current length of the ringbuffer + pub fn len(&mut self) -> Result { + Ok(self.ringbuf.len(&mut DmaCtrlImpl(self.channel.reborrow()))?) + } + + /// The capacity of the ringbuffer + pub const fn capacity(&self) -> usize { + self.ringbuf.cap() + } + + /// Set a waker to be woken when at least one byte is received. + pub fn set_waker(&mut self, waker: &Waker) { + DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); + } + + /// Request the DMA to stop. + /// + /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. + pub fn request_stop(&mut self) { + self.channel.request_stop() + } + + /// Return whether DMA is still running. + /// + /// If this returns `false`, it can be because either the transfer finished, or + /// it was requested to stop early with [`request_stop`](Self::request_stop). + pub fn is_running(&mut self) -> bool { + self.channel.is_running() + } +} + +impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { + fn drop(&mut self) { + self.request_stop(); + while self.is_running() {} + + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + fence(Ordering::SeqCst); + } +} diff --git a/embassy-stm32/src/dma/ringbuffer/mod.rs b/embassy-stm32/src/dma/ringbuffer/mod.rs index 44ea497fe..e462c71d4 100644 --- a/embassy-stm32/src/dma/ringbuffer/mod.rs +++ b/embassy-stm32/src/dma/ringbuffer/mod.rs @@ -1,5 +1,3 @@ -#![cfg_attr(gpdma, allow(unused))] - use core::future::poll_fn; use core::task::{Poll, Waker}; diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 4965f8b04..88cc225dd 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -1,13 +1,11 @@ //! Serial Audio Interface (SAI) #![macro_use] -#![cfg_attr(gpdma, allow(unused))] use core::marker::PhantomData; use embassy_hal_internal::PeripheralType; pub use crate::dma::word; -#[cfg(not(gpdma))] use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed}; use crate::pac::sai::{vals, Sai as Regs}; @@ -26,7 +24,6 @@ pub enum Error { Overrun, } -#[cfg(not(gpdma))] impl From for Error { fn from(#[allow(unused)] err: ringbuffer::Error) -> Self { #[cfg(feature = "defmt")] @@ -652,7 +649,6 @@ impl Config { } } -#[cfg(not(gpdma))] enum RingBuffer<'d, W: word::Word> { Writable(WritableRingBuffer<'d, W>), Readable(ReadableRingBuffer<'d, W>), @@ -679,7 +675,6 @@ fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AfType, AfType) { ) } -#[cfg(not(gpdma))] fn get_ring_buffer<'d, T: Instance, W: word::Word>( dma: Peri<'d, impl Channel>, dma_buf: &'d mut [W], @@ -750,14 +745,10 @@ pub struct Sai<'d, T: Instance, W: word::Word> { fs: Option>, sck: Option>, mclk: Option>, - #[cfg(gpdma)] - ring_buffer: PhantomData, - #[cfg(not(gpdma))] ring_buffer: RingBuffer<'d, W>, sub_block: WhichSubBlock, } -#[cfg(not(gpdma))] impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { /// Create a new SAI driver in asynchronous mode with MCLK. /// -- cgit From cf5b1ea9f593d1d80b718b88330f041b59d071f1 Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: feat: gpdma support (wip) --- embassy-stm32/src/cryp/mod.rs | 3 - embassy-stm32/src/dma/gpdma/linked_list.rs | 77 ++--- embassy-stm32/src/dma/gpdma/mod.rs | 91 ++++-- embassy-stm32/src/dma/gpdma/ringbuffer.rs | 283 ------------------ embassy-stm32/src/dma/gpdma/ringbuffered.rs | 433 ++++++++++++++++++++++++++++ embassy-stm32/src/dma/mod.rs | 2 + embassy-stm32/src/dma/ringbuffer/mod.rs | 20 ++ embassy-stm32/src/spdifrx/mod.rs | 4 - embassy-stm32/src/usart/mod.rs | 2 - 9 files changed, 561 insertions(+), 354 deletions(-) delete mode 100644 embassy-stm32/src/dma/gpdma/ringbuffer.rs create mode 100644 embassy-stm32/src/dma/gpdma/ringbuffered.rs diff --git a/embassy-stm32/src/cryp/mod.rs b/embassy-stm32/src/cryp/mod.rs index 35d9f8cce..0173b2b5d 100644 --- a/embassy-stm32/src/cryp/mod.rs +++ b/embassy-stm32/src/cryp/mod.rs @@ -1814,7 +1814,6 @@ impl<'d, T: Instance> Cryp<'d, T, Async> { // Configure DMA to transfer input to crypto core. let dst_ptr: *mut u32 = T::regs().din().as_ptr(); let options = TransferOptions { - #[cfg(not(gpdma))] priority: crate::dma::Priority::High, ..Default::default() }; @@ -1834,7 +1833,6 @@ impl<'d, T: Instance> Cryp<'d, T, Async> { // Configure DMA to transfer input to crypto core. let dst_ptr: *mut u32 = T::regs().din().as_ptr(); let options = TransferOptions { - #[cfg(not(gpdma))] priority: crate::dma::Priority::High, ..Default::default() }; @@ -1853,7 +1851,6 @@ impl<'d, T: Instance> Cryp<'d, T, Async> { // Configure DMA to get output from crypto core. let src_ptr = T::regs().dout().as_ptr(); let options = TransferOptions { - #[cfg(not(gpdma))] priority: crate::dma::Priority::VeryHigh, ..Default::default() }; diff --git a/embassy-stm32/src/dma/gpdma/linked_list.rs b/embassy-stm32/src/dma/gpdma/linked_list.rs index b24b2e7eb..7de9a1441 100644 --- a/embassy-stm32/src/dma/gpdma/linked_list.rs +++ b/embassy-stm32/src/dma/gpdma/linked_list.rs @@ -8,10 +8,6 @@ use crate::dma::{ word::{Word, WordSize}, Dir, Request, }; -use core::{ - ptr, - sync::atomic::{AtomicUsize, Ordering}, -}; /// The mode in which to run the linked list. #[derive(Debug)] @@ -28,6 +24,7 @@ pub enum RunMode { /// /// Also works for 2D-capable GPDMA channels, but does not use 2D capabilities. #[derive(Debug, Copy, Clone, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(C)] pub struct LinearItem { /// Transfer register 1. @@ -146,7 +143,9 @@ impl LinearItem { llr.set_usa(true); llr.set_uda(true); llr.set_ull(true); - llr.set_la(next); + + // Lower two bits are ignored: 32 bit aligned. + llr.set_la(next >> 2); self.llr = llr.0; } @@ -159,78 +158,82 @@ impl LinearItem { } } +/// A table of linked list items. +#[repr(C)] pub struct Table { - current_index: AtomicUsize, - items: [LinearItem; ITEM_COUNT], + /// The items. + pub items: [LinearItem; ITEM_COUNT], } impl Table { /// Create a new table. - pub fn new(items: [LinearItem; ITEM_COUNT], run_mode: RunMode) -> Self { + pub fn new(items: [LinearItem; ITEM_COUNT]) -> Self { assert!(!items.is_empty()); - let mut this = Self { - current_index: AtomicUsize::new(0), - items, - }; + Self { items } + } + pub fn link(&mut self, run_mode: RunMode) { if matches!(run_mode, RunMode::Once | RunMode::Repeat) { - this.link_sequential(); + self.link_sequential(); } if matches!(run_mode, RunMode::Repeat) { - this.link_repeat(); + self.link_repeat(); } - - this } + /// The number of linked list items.s pub fn len(&self) -> usize { self.items.len() } - /// Items are linked together sequentially. + /// Link items of given indices together: first -> second. + pub fn link_indices(&mut self, first: usize, second: usize) { + assert!(first < self.len()); + assert!(second < self.len()); + + let second_item = self.offset_address(second); + self.items[first].link_to(second_item); + } + + /// Link items sequentially. pub fn link_sequential(&mut self) { - if self.items.len() > 1 { + if self.len() > 1 { for index in 0..(self.items.len() - 1) { - let next = ptr::addr_of!(self.items[index + 1]) as u16; + let next = self.offset_address(index + 1); self.items[index].link_to(next); } } } - /// Last item links to first item. + /// Link last to first item. pub fn link_repeat(&mut self) { - let first_item = self.items.first().unwrap(); - let first_address = ptr::addr_of!(first_item) as u16; + let first_address = self.offset_address(0); self.items.last_mut().unwrap().link_to(first_address); } - /// The index of the next item. - pub fn next_index(&self) -> usize { - let mut next_index = self.current_index.load(Ordering::Relaxed) + 1; - if next_index >= self.len() { - next_index = 0; + /// Unlink all items. + pub fn unlink(&mut self) { + for item in self.items.iter_mut() { + item.unlink(); } - - next_index - } - - /// Unlink the next item. - pub fn unlink_next(&mut self) { - let next_index = self.next_index(); - self.items[next_index].unlink(); } /// Linked list base address (upper 16 address bits). pub fn base_address(&self) -> u16 { - ((ptr::addr_of!(self.items) as u32) >> 16) as _ + ((&raw const self.items as u32) >> 16) as _ } /// Linked list offset address (lower 16 address bits) at the selected index. pub fn offset_address(&self, index: usize) -> u16 { assert!(self.items.len() > index); - (ptr::addr_of!(self.items[index]) as u32) as _ + let address = &raw const self.items[index] as _; + + // Ensure 32 bit address alignment. + assert_eq!(address & 0b11, 0); + + address } } diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index 07acd2cf0..f65048d1f 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -8,7 +8,6 @@ use core::task::{Context, Poll}; use embassy_hal_internal::Peri; use embassy_sync::waitqueue::AtomicWaker; use linked_list::Table; -use stm32_metapac::gpdma::regs; use super::word::{Word, WordSize}; use super::{AnyChannel, Channel, Dir, Request, STATE}; @@ -16,8 +15,8 @@ use crate::interrupt::typelevel::Interrupt; use crate::pac; use crate::pac::gpdma::vals; -mod linked_list; -mod ringbuffer; +pub mod linked_list; +pub mod ringbuffered; pub(crate) struct ChannelInfo { pub(crate) dma: pac::gpdma::Gpdma, @@ -56,9 +55,12 @@ impl From for pac::gpdma::vals::Prio { #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub struct TransferOptions { - priority: Priority, - half_transfer_ir: bool, - complete_transfer_ir: bool, + /// Request priority level. + pub priority: Priority, + /// Enable half transfer interrupt. + pub half_transfer_ir: bool, + /// Enable transfer complete interrupt. + pub complete_transfer_ir: bool, } impl Default for TransferOptions { @@ -81,6 +83,17 @@ impl From for vals::Dw { } } +impl From for WordSize { + fn from(raw: vals::Dw) -> Self { + match raw { + vals::Dw::BYTE => Self::OneByte, + vals::Dw::HALF_WORD => Self::TwoBytes, + vals::Dw::WORD => Self::FourBytes, + _ => panic!("Invalid word size"), + } + } +} + pub(crate) struct ChannelState { waker: AtomicWaker, complete_count: AtomicUsize, @@ -94,7 +107,7 @@ impl ChannelState { } /// safety: must be called only once -pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: Priority) { +pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: crate::interrupt::Priority) { foreach_interrupt! { ($peri:ident, gpdma, $block:ident, $signal_name:ident, $irq:ident) => { crate::interrupt::typelevel::$irq::set_priority_with_cs(cs, irq_priority); @@ -142,24 +155,30 @@ impl AnyChannel { ); } + if sr.htf() { + ch.fcr().write(|w| w.set_htf(true)); + } + if sr.tcf() { + ch.fcr().write(|w| w.set_tcf(true)); state.complete_count.fetch_add(1, Ordering::Release); } - if sr.suspf() || sr.tcf() { + if sr.suspf() { // disable all xxIEs to prevent the irq from firing again. ch.cr().write(|_| {}); // Wake the future. It'll look at tcf and see it's set. - state.waker.wake(); } + state.waker.wake(); } fn get_remaining_transfers(&self) -> u16 { let info = self.info(); let ch = info.dma.ch(info.num); + let word_size: WordSize = ch.tr1().read().ddw().into(); - ch.br1().read().bndt() + ch.br1().read().bndt() / word_size.bytes() as u16 } unsafe fn configure( @@ -238,21 +257,23 @@ impl AnyChannel { ch.cr().write(|w| w.set_reset(true)); ch.fcr().write(|w| w.0 = 0xFFFF_FFFF); // clear all irqs - ch.lbar().write(|reg| reg.set_lba(table.base_address())); - // Enable all linked-list field updates. - let mut llr = regs::ChLlr(0); - llr.set_ut1(true); - llr.set_ut2(true); - llr.set_ub1(true); - llr.set_usa(true); - llr.set_uda(true); - llr.set_ull(true); - - llr.set_la(table.offset_address(0)); + // Empty LLI0. + ch.br1().write(|w| w.set_bndt(0)); - ch.llr().write(|_| llr.0); + // Enable all linked-list field updates. + ch.llr().write(|w| { + w.set_ut1(true); + w.set_ut2(true); + w.set_ub1(true); + w.set_usa(true); + w.set_uda(true); + w.set_ull(true); + + // Lower two bits are ignored: 32 bit aligned. + w.set_la(table.offset_address(0) >> 2); + }); ch.tr3().write(|_| {}); // no address offsets. @@ -281,12 +302,23 @@ impl AnyChannel { ch.cr().modify(|w| w.set_susp(true)) } + fn request_pause(&self) { + let info = self.info(); + let ch = info.dma.ch(info.num); + + // Disable the channel without overwriting the existing configuration + ch.cr().modify(|w| { + w.set_en(false); + }); + } + fn is_running(&self) -> bool { let info = self.info(); let ch = info.dma.ch(info.num); let sr = ch.sr().read(); - !sr.tcf() && !sr.suspf() + + !sr.tcf() && !sr.suspf() && !sr.idlef() } fn poll_stop(&self) -> Poll<()> { @@ -305,7 +337,6 @@ impl AnyChannel { #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct LinkedListTransfer<'a, const ITEM_COUNT: usize> { channel: PeripheralRef<'a, AnyChannel>, - table: Table, } impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { @@ -328,7 +359,7 @@ impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { channel.configure_linked_list(&table, options); channel.start(); - Self { channel, table } + Self { channel } } /// Request the transfer to stop. @@ -515,12 +546,22 @@ impl<'a> Transfer<'a> { } /// Request the transfer to stop. + /// The configuration for this channel will **not be preserved**. If you need to restart the transfer + /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. pub fn request_stop(&mut self) { self.channel.request_stop() } + /// Request the transfer to pause, keeping the existing configuration for this channel. + /// To restart the transfer, call [`start`](Self::start) again. + /// + /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. + pub fn request_pause(&mut self) { + self.channel.request_pause() + } + /// Return whether this transfer is still running. /// /// If this returns `false`, it can be because either the transfer finished, or diff --git a/embassy-stm32/src/dma/gpdma/ringbuffer.rs b/embassy-stm32/src/dma/gpdma/ringbuffer.rs deleted file mode 100644 index c327e811e..000000000 --- a/embassy-stm32/src/dma/gpdma/ringbuffer.rs +++ /dev/null @@ -1,283 +0,0 @@ -//! GPDMA ring buffer implementation. -//! -//! FIXME: add request_pause functionality? -use core::{ - sync::atomic::{fence, Ordering}, - task::Waker, -}; - -use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; - -use crate::dma::{ - gpdma::linked_list::{LinearItem, RunMode, Table}, - ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}, - word::Word, - Channel, Dir, Request, -}; - -use super::{AnyChannel, TransferOptions, STATE}; - -struct DmaCtrlImpl<'a>(PeripheralRef<'a, AnyChannel>); - -impl<'a> DmaCtrl for DmaCtrlImpl<'a> { - fn get_remaining_transfers(&self) -> usize { - self.0.get_remaining_transfers() as _ - } - - fn reset_complete_count(&mut self) -> usize { - let state = &STATE[self.0.id as usize]; - - return state.complete_count.swap(0, Ordering::AcqRel); - } - - fn set_waker(&mut self, waker: &Waker) { - STATE[self.0.id as usize].waker.register(waker); - } -} - -/// Ringbuffer for receiving data using GPDMA linked-list mode. -pub struct ReadableRingBuffer<'a, W: Word> { - channel: PeripheralRef<'a, AnyChannel>, - ringbuf: ReadableDmaRingBuffer<'a, W>, - table: Table<2>, -} - -impl<'a, W: Word> ReadableRingBuffer<'a, W> { - /// Create a new ring buffer. - pub unsafe fn new( - channel: impl Peripheral

+ 'a, - request: Request, - peri_addr: *mut W, - buffer: &'a mut [W], - mut options: TransferOptions, - ) -> Self { - into_ref!(channel); - let channel: PeripheralRef<'a, AnyChannel> = channel.map_into(); - - let half_len = buffer.len() / 2; - assert_eq!(half_len * 2, buffer.len()); - - options.half_transfer_ir = false; - options.complete_transfer_ir = true; - - let items = [ - LinearItem::new_read(request, peri_addr, &mut buffer[..half_len], options), - LinearItem::new_read(request, peri_addr, &mut buffer[half_len..], options), - ]; - - let table = Table::new(items, RunMode::Once); - - let this = Self { - channel, - ringbuf: ReadableDmaRingBuffer::new(buffer), - table, - }; - - this.channel.configure_linked_list(&this.table, options); - - this - } - - /// Start the ring buffer operation. - /// - /// You must call this after creating it for it to work. - pub fn start(&mut self) { - self.channel.start(); - } - - /// Clear all data in the ring buffer. - pub fn clear(&mut self) { - self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow())); - } - - /// Read elements from the ring buffer - /// Return a tuple of the length read and the length remaining in the buffer - /// If not all of the elements were read, then there will be some elements in the buffer remaining - /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read - /// Error is returned if the portion to be read was overwritten by the DMA controller. - pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), Error> { - self.ringbuf.read(&mut DmaCtrlImpl(self.channel.reborrow()), buf) - } - - /// Read an exact number of elements from the ringbuffer. - /// - /// Returns the remaining number of elements available for immediate reading. - /// Error is returned if the portion to be read was overwritten by the DMA controller. - /// - /// Async/Wake Behavior: - /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point, - /// and when it wraps around. This means that when called with a buffer of length 'M', when this - /// ring buffer was created with a buffer of size 'N': - /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source. - /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning. - pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result { - self.ringbuf - .read_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) - .await - } - - /// The current length of the ringbuffer - pub fn len(&mut self) -> Result { - Ok(self.ringbuf.len(&mut DmaCtrlImpl(self.channel.reborrow()))?) - } - - /// The capacity of the ringbuffer - pub const fn capacity(&self) -> usize { - self.ringbuf.cap() - } - - /// Set a waker to be woken when at least one byte is received. - pub fn set_waker(&mut self, waker: &Waker) { - DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); - } - - /// Request the DMA to stop. - /// The configuration for this channel will **not be preserved**. If you need to restart the transfer - /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. - /// - /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_stop(&mut self) { - self.channel.request_stop() - } - - /// Return whether DMA is still running. - /// - /// If this returns `false`, it can be because either the transfer finished, or - /// it was requested to stop early with [`request_stop`](Self::request_stop). - pub fn is_running(&mut self) -> bool { - self.channel.is_running() - } -} - -impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { - fn drop(&mut self) { - self.request_stop(); - while self.is_running() {} - - // "Subsequent reads and writes cannot be moved ahead of preceding reads." - fence(Ordering::SeqCst); - } -} - -/// Ringbuffer for writing data using DMA circular mode. -pub struct WritableRingBuffer<'a, W: Word> { - channel: PeripheralRef<'a, AnyChannel>, - ringbuf: WritableDmaRingBuffer<'a, W>, -} - -impl<'a, W: Word> WritableRingBuffer<'a, W> { - /// Create a new ring buffer. - pub unsafe fn new( - channel: impl Peripheral

+ 'a, - _request: Request, - peri_addr: *mut W, - buffer: &'a mut [W], - mut options: TransferOptions, - ) -> Self { - into_ref!(channel); - let channel: PeripheralRef<'a, AnyChannel> = channel.map_into(); - - let len = buffer.len(); - let dir = Dir::MemoryToPeripheral; - let data_size = W::size(); - let buffer_ptr = buffer.as_mut_ptr(); - - options.half_transfer_ir = true; - options.complete_transfer_ir = true; - - channel.configure( - _request, - dir, - peri_addr as *mut u32, - buffer_ptr as *mut u32, - len, - true, - data_size, - data_size, - options, - ); - - Self { - channel, - ringbuf: WritableDmaRingBuffer::new(buffer), - } - } - - /// Start the ring buffer operation. - /// - /// You must call this after creating it for it to work. - pub fn start(&mut self) { - self.channel.start(); - } - - /// Clear all data in the ring buffer. - pub fn clear(&mut self) { - self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow())); - } - - /// Write elements directly to the raw buffer. - /// This can be used to fill the buffer before starting the DMA transfer. - pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), Error> { - self.ringbuf.write_immediate(buf) - } - - /// Write elements from the ring buffer - /// Return a tuple of the length written and the length remaining in the buffer - pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), Error> { - self.ringbuf.write(&mut DmaCtrlImpl(self.channel.reborrow()), buf) - } - - /// Write an exact number of elements to the ringbuffer. - pub async fn write_exact(&mut self, buffer: &[W]) -> Result { - self.ringbuf - .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) - .await - } - - /// Wait for any ring buffer write error. - pub async fn wait_write_error(&mut self) -> Result { - self.ringbuf - .wait_write_error(&mut DmaCtrlImpl(self.channel.reborrow())) - .await - } - - /// The current length of the ringbuffer - pub fn len(&mut self) -> Result { - Ok(self.ringbuf.len(&mut DmaCtrlImpl(self.channel.reborrow()))?) - } - - /// The capacity of the ringbuffer - pub const fn capacity(&self) -> usize { - self.ringbuf.cap() - } - - /// Set a waker to be woken when at least one byte is received. - pub fn set_waker(&mut self, waker: &Waker) { - DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); - } - - /// Request the DMA to stop. - /// - /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_stop(&mut self) { - self.channel.request_stop() - } - - /// Return whether DMA is still running. - /// - /// If this returns `false`, it can be because either the transfer finished, or - /// it was requested to stop early with [`request_stop`](Self::request_stop). - pub fn is_running(&mut self) -> bool { - self.channel.is_running() - } -} - -impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { - fn drop(&mut self) { - self.request_stop(); - while self.is_running() {} - - // "Subsequent reads and writes cannot be moved ahead of preceding reads." - fence(Ordering::SeqCst); - } -} diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs new file mode 100644 index 000000000..fd0a98e23 --- /dev/null +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -0,0 +1,433 @@ +//! GPDMA ring buffer implementation. +//! +//! FIXME: add request_pause functionality? +use core::{ + future::poll_fn, + sync::atomic::{fence, Ordering}, + task::Waker, +}; + +use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; + +use crate::dma::{ + gpdma::linked_list::{LinearItem, RunMode, Table}, + ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}, + word::Word, + Channel, Request, +}; + +use super::{AnyChannel, TransferOptions, STATE}; + +struct DmaCtrlImpl<'a>(PeripheralRef<'a, AnyChannel>); + +impl<'a> DmaCtrl for DmaCtrlImpl<'a> { + fn get_remaining_transfers(&self) -> usize { + self.0.get_remaining_transfers() as _ + } + + fn reset_complete_count(&mut self) -> usize { + let state = &STATE[self.0.id as usize]; + + state.complete_count.swap(0, Ordering::AcqRel) + } + + fn set_waker(&mut self, waker: &Waker) { + STATE[self.0.id as usize].waker.register(waker); + } +} + +/// The current buffer half (e.g. for DMA or the user application). +#[derive(Debug, PartialEq, PartialOrd)] +enum BufferHalf { + First, + Second, +} + +impl BufferHalf { + fn toggle(&mut self) { + *self = match *self { + Self::First => Self::Second, + Self::Second => Self::First, + }; + } +} + +/// Ringbuffer for receiving data using GPDMA linked-list mode. +pub struct ReadableRingBuffer<'a, W: Word> { + channel: PeripheralRef<'a, AnyChannel>, + ringbuf: ReadableDmaRingBuffer<'a, W>, + table: Table<1>, + user_buffer_half: BufferHalf, +} + +impl<'a, W: Word> ReadableRingBuffer<'a, W> { + /// Create a new ring buffer. + pub unsafe fn new( + channel: impl Peripheral

+ 'a, + request: Request, + peri_addr: *mut W, + buffer: &'a mut [W], + mut options: TransferOptions, + ) -> Self { + into_ref!(channel); + let channel: PeripheralRef<'a, AnyChannel> = channel.map_into(); + + let half_len = buffer.len() / 2; + assert_eq!(half_len * 2, buffer.len()); + + options.half_transfer_ir = true; + options.complete_transfer_ir = true; + + // let items = [ + // LinearItem::new_read(request, peri_addr, &mut buffer[..half_len], options), + // LinearItem::new_read(request, peri_addr, &mut buffer[half_len..], options), + // ]; + let items = [LinearItem::new_read(request, peri_addr, buffer, options)]; + + let table = Table::new(items); + + let this = Self { + channel, + ringbuf: ReadableDmaRingBuffer::new(buffer), + table, + user_buffer_half: BufferHalf::First, + }; + + this.channel.configure_linked_list(&this.table, options); + + this + } + + /// Start the ring buffer operation. + /// + /// You must call this after creating it for it to work. + pub fn start(&mut self) { + self.channel.start(); + } + + /// Clear all data in the ring buffer. + pub fn clear(&mut self) { + self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow())); + } + + /// Read elements from the ring buffer + /// Return a tuple of the length read and the length remaining in the buffer + /// If not all of the elements were read, then there will be some elements in the buffer remaining + /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read + /// Error is returned if the portion to be read was overwritten by the DMA controller. + pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), Error> { + self.ringbuf.read(&mut DmaCtrlImpl(self.channel.reborrow()), buf) + } + + /// Read an exact number of elements from the ringbuffer. + /// + /// Returns the remaining number of elements available for immediate reading. + /// Error is returned if the portion to be read was overwritten by the DMA controller. + /// + /// Async/Wake Behavior: + /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point, + /// and when it wraps around. This means that when called with a buffer of length 'M', when this + /// ring buffer was created with a buffer of size 'N': + /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source. + /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning. + pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result { + self.ringbuf + .read_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) + .await + } + + /// The current length of the ringbuffer + pub fn len(&mut self) -> Result { + Ok(self.ringbuf.len(&mut DmaCtrlImpl(self.channel.reborrow()))?) + } + + /// The capacity of the ringbuffer + pub const fn capacity(&self) -> usize { + self.ringbuf.cap() + } + + /// Set a waker to be woken when at least one byte is received. + pub fn set_waker(&mut self, waker: &Waker) { + DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); + } + + /// Request the DMA to stop. + /// The configuration for this channel will **not be preserved**. If you need to restart the transfer + /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. + /// + /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. + pub fn request_stop(&mut self) { + self.channel.request_stop() + } + + /// Request the transfer to pause, keeping the existing configuration for this channel. + /// To restart the transfer, call [`start`](Self::start) again. + /// + /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. + pub fn request_pause(&mut self) { + self.channel.request_pause() + } + + /// Return whether DMA is still running. + /// + /// If this returns `false`, it can be because either the transfer finished, or + /// it was requested to stop early with [`request_stop`](Self::request_stop). + pub fn is_running(&mut self) -> bool { + self.channel.is_running() + } + + /// Stop the DMA transfer and await until the buffer is full. + /// + /// This disables the DMA transfer's circular mode so that the transfer + /// stops when the buffer is full. + /// + /// This is designed to be used with streaming input data such as the + /// I2S/SAI or ADC. + /// + /// When using the UART, you probably want `request_stop()`. + pub async fn stop(&mut self) { + // wait until cr.susp reads as true + poll_fn(|cx| { + self.set_waker(cx.waker()); + self.channel.poll_stop() + }) + .await + } +} + +impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { + fn drop(&mut self) { + self.request_stop(); + while self.is_running() {} + + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + fence(Ordering::SeqCst); + } +} + +/// Ringbuffer for writing data using DMA circular mode. +pub struct WritableRingBuffer<'a, W: Word> { + channel: PeripheralRef<'a, AnyChannel>, + ringbuf: WritableDmaRingBuffer<'a, W>, + table: Table<1>, + user_buffer_half: BufferHalf, +} + +impl<'a, W: Word> WritableRingBuffer<'a, W> { + /// Create a new ring buffer. + pub unsafe fn new( + channel: impl Peripheral

+ 'a, + request: Request, + peri_addr: *mut W, + buffer: &'a mut [W], + mut options: TransferOptions, + ) -> Self { + into_ref!(channel); + let channel: PeripheralRef<'a, AnyChannel> = channel.map_into(); + + let half_len = buffer.len() / 2; + assert_eq!(half_len * 2, buffer.len()); + + options.half_transfer_ir = true; + options.complete_transfer_ir = true; + + // let items = [ + // LinearItem::new_write(request, &mut buffer[..half_len], peri_addr, options), + // LinearItem::new_write(request, &mut buffer[half_len..], peri_addr, options), + // ]; + let items = [LinearItem::new_write(request, buffer, peri_addr, options)]; + let table = Table::new(items); + + let this = Self { + channel, + ringbuf: WritableDmaRingBuffer::new(buffer), + table, + user_buffer_half: BufferHalf::First, + }; + + this + } + + fn dma_buffer_half(&self) -> BufferHalf { + if self.ringbuf.read_index(0) < self.ringbuf.cap() / 2 { + BufferHalf::First + } else { + BufferHalf::Second + } + } + + fn link_next_buffer(&mut self) { + self.table.unlink(); + + match self.user_buffer_half { + BufferHalf::First => self.table.link_indices(0, 1), + BufferHalf::Second => self.table.link_indices(1, 0), + } + + self.user_buffer_half.toggle(); + } + + /// Start the ring buffer operation. + /// + /// You must call this after creating it for it to work. + pub fn start(&mut self) { + unsafe { + self.channel.configure_linked_list( + &self.table, + TransferOptions { + half_transfer_ir: true, + complete_transfer_ir: true, + ..Default::default() + }, + ) + }; + self.table.link(RunMode::Repeat); + self.channel.start(); + } + + /// Clear all data in the ring buffer. + pub fn clear(&mut self) { + self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow())); + } + + /// Write elements directly to the raw buffer. + /// This can be used to fill the buffer before starting the DMA transfer. + pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), Error> { + self.ringbuf.write_immediate(buf) + } + + /// Write elements from the ring buffer + /// Return a tuple of the length written and the length remaining in the buffer + pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), Error> { + self.ringbuf.write(&mut DmaCtrlImpl(self.channel.reborrow()), buf) + } + + /// Write an exact number of elements to the ringbuffer. + pub async fn write_exact(&mut self, buffer: &[W]) -> Result { + return self + .ringbuf + .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) + .await; + + let mut remaining = buffer.len(); + + let mut remaining_cap = 0; + let cap = self.ringbuf.cap(); + + while remaining > 0 { + let dma_buffer_half = self.dma_buffer_half(); + if dma_buffer_half == self.user_buffer_half { + self.link_next_buffer(); + } + + let write_index = self.ringbuf.write_index(0); + let len = match dma_buffer_half { + BufferHalf::First => { + // if write_index < cap / 2 { + // error!("write index: {}", write_index); + // panic!() + // } + info!("Write second"); + + // Fill up second buffer half when DMA reads the first. + cap - write_index + } + BufferHalf::Second => { + // if write_index >= cap / 2 { + // error!("write index: {}", write_index); + // panic!() + // } + info!("Write first"); + + // Fill up first buffer half when DMA reads the second. + cap / 2 - write_index + } + } + .min(remaining); + + remaining_cap = self + .ringbuf + .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) + .await?; + + remaining -= len; + } + + Ok(remaining_cap) + } + + /// Wait for any ring buffer write error. + pub async fn wait_write_error(&mut self) -> Result { + self.ringbuf + .wait_write_error(&mut DmaCtrlImpl(self.channel.reborrow())) + .await + } + + /// The current length of the ringbuffer + pub fn len(&mut self) -> Result { + Ok(self.ringbuf.len(&mut DmaCtrlImpl(self.channel.reborrow()))?) + } + + /// The capacity of the ringbuffer + pub const fn capacity(&self) -> usize { + self.ringbuf.cap() + } + + /// Set a waker to be woken when at least one byte is received. + pub fn set_waker(&mut self, waker: &Waker) { + DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); + } + + /// Request the DMA to stop. + /// The configuration for this channel will **not be preserved**. If you need to restart the transfer + /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. + /// + /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. + pub fn request_stop(&mut self) { + self.channel.request_stop() + } + + /// Request the transfer to pause, keeping the existing configuration for this channel. + /// To restart the transfer, call [`start`](Self::start) again. + /// + /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. + pub fn request_pause(&mut self) { + self.channel.request_pause() + } + + /// Return whether DMA is still running. + /// + /// If this returns `false`, it can be because either the transfer finished, or + /// it was requested to stop early with [`request_stop`](Self::request_stop). + pub fn is_running(&mut self) -> bool { + self.channel.is_running() + } + + /// Stop the DMA transfer and await until the buffer is full. + /// + /// This disables the DMA transfer's circular mode so that the transfer + /// stops when the buffer is full. + /// + /// This is designed to be used with streaming input data such as the + /// I2S/SAI or ADC. + /// + /// When using the UART, you probably want `request_stop()`. + pub async fn stop(&mut self) { + // wait until cr.susp reads as true + poll_fn(|cx| { + self.set_waker(cx.waker()); + self.channel.poll_stop() + }) + .await + } +} + +impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { + fn drop(&mut self) { + self.request_stop(); + while self.is_running() {} + + // "Subsequent reads and writes cannot be moved ahead of preceding reads." + fence(Ordering::SeqCst); + } +} diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index d3b070a6d..030f906d2 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs @@ -9,6 +9,8 @@ pub use dma_bdma::*; #[cfg(gpdma)] pub(crate) mod gpdma; #[cfg(gpdma)] +pub use gpdma::ringbuffered::*; +#[cfg(gpdma)] pub use gpdma::*; #[cfg(dmamux)] diff --git a/embassy-stm32/src/dma/ringbuffer/mod.rs b/embassy-stm32/src/dma/ringbuffer/mod.rs index e462c71d4..99960bc74 100644 --- a/embassy-stm32/src/dma/ringbuffer/mod.rs +++ b/embassy-stm32/src/dma/ringbuffer/mod.rs @@ -92,6 +92,16 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> { } } + /// The current ring-buffer read index. + pub fn read_index(&self, offset: usize) -> usize { + self.read_index.as_index(self.cap(), offset) + } + + /// The current ring-buffer write index. + pub fn write_index(&self, offset: usize) -> usize { + self.write_index.as_index(self.cap(), offset) + } + /// Reset the ring buffer to its initial state. pub fn reset(&mut self, dma: &mut impl DmaCtrl) { dma.reset_complete_count(); @@ -208,6 +218,16 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> { } } + /// The current ring-buffer read index. + pub fn read_index(&self, offset: usize) -> usize { + self.read_index.as_index(self.cap(), offset) + } + + /// The current ring-buffer write index. + pub fn write_index(&self, offset: usize) -> usize { + self.write_index.as_index(self.cap(), offset) + } + /// Reset the ring buffer to its initial state. The buffer after the reset will be full. pub fn reset(&mut self, dma: &mut impl DmaCtrl) { dma.reset_complete_count(); diff --git a/embassy-stm32/src/spdifrx/mod.rs b/embassy-stm32/src/spdifrx/mod.rs index 9c42217f0..d3b4a0b10 100644 --- a/embassy-stm32/src/spdifrx/mod.rs +++ b/embassy-stm32/src/spdifrx/mod.rs @@ -8,7 +8,6 @@ use embassy_sync::waitqueue::AtomicWaker; use crate::dma::ringbuffer::Error as RingbufferError; pub use crate::dma::word; -#[cfg(not(gpdma))] use crate::dma::ReadableRingBuffer; use crate::dma::{Channel, TransferOptions}; use crate::gpio::{AfType, AnyPin, Pull, SealedPin as _}; @@ -58,7 +57,6 @@ macro_rules! impl_spdifrx_pin { /// Ring-buffered SPDIFRX driver. /// /// Data is read by DMAs and stored in a ring buffer. -#[cfg(not(gpdma))] pub struct Spdifrx<'d, T: Instance> { _peri: Peri<'d, T>, spdifrx_in: Option>, @@ -118,7 +116,6 @@ impl Default for Config { } } -#[cfg(not(gpdma))] impl<'d, T: Instance> Spdifrx<'d, T> { fn dma_opts() -> TransferOptions { TransferOptions { @@ -236,7 +233,6 @@ impl<'d, T: Instance> Spdifrx<'d, T> { } } -#[cfg(not(gpdma))] impl<'d, T: Instance> Drop for Spdifrx<'d, T> { fn drop(&mut self) { T::info().regs.cr().modify(|cr| cr.set_spdifen(0x00)); diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 5bece6d66..3d95de897 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -1965,9 +1965,7 @@ pub use buffered::*; pub use crate::usart::buffered::InterruptHandler as BufferedInterruptHandler; mod buffered; -#[cfg(not(gpdma))] mod ringbuffered; -#[cfg(not(gpdma))] pub use ringbuffered::RingBufferedUartRx; #[cfg(any(usart_v1, usart_v2))] -- cgit From 4155adbf8ad2aa8acbc6e94d059739c9f373323b Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: feat: ping-pong buffers --- embassy-stm32/src/dma/gpdma/linked_list.rs | 22 ++++++++++++- embassy-stm32/src/dma/gpdma/mod.rs | 49 ++++++++++++++++++++++++++++- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 37 +++++++++++++--------- 3 files changed, 92 insertions(+), 16 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/linked_list.rs b/embassy-stm32/src/dma/gpdma/linked_list.rs index 7de9a1441..3d2114282 100644 --- a/embassy-stm32/src/dma/gpdma/linked_list.rs +++ b/embassy-stm32/src/dma/gpdma/linked_list.rs @@ -156,6 +156,15 @@ impl LinearItem { fn unlink(&mut self) { self.llr = regs::ChLlr(0).0; } + + /// The item's transfer count in number of words. + fn transfer_count(&self) -> usize { + let br1 = regs::ChBr1(self.br1); + let tr1 = regs::ChTr1(self.tr1); + let word_size: WordSize = tr1.ddw().into(); + + br1.bndt() as usize / word_size.bytes() + } } /// A table of linked list items. @@ -173,6 +182,7 @@ impl Table { Self { items } } + /// Link the table as given by the run mode. pub fn link(&mut self, run_mode: RunMode) { if matches!(run_mode, RunMode::Once | RunMode::Repeat) { self.link_sequential(); @@ -183,11 +193,21 @@ impl Table { } } - /// The number of linked list items.s + /// The number of linked list items. pub fn len(&self) -> usize { self.items.len() } + /// The total transfer count of the table in number of words. + pub fn transfer_count(&self) -> usize { + let mut count = 0; + for item in self.items { + count += item.transfer_count() as usize + } + + count + } + /// Link items of given indices together: first -> second. pub fn link_indices(&mut self, first: usize, second: usize) { assert!(first < self.len()); diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index f65048d1f..1d2811ab4 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -94,15 +94,31 @@ impl From for WordSize { } } +pub(crate) struct LLiState { + /// The number of linked-list items. + count: AtomicUsize, + /// The index of the current linked-list item. + index: AtomicUsize, + /// The total transfer count of all linked-list items in number of words. + transfer_count: AtomicUsize, +} + pub(crate) struct ChannelState { waker: AtomicWaker, complete_count: AtomicUsize, + lli_state: LLiState, } impl ChannelState { pub(crate) const NEW: Self = Self { waker: AtomicWaker::new(), complete_count: AtomicUsize::new(0), + + lli_state: LLiState { + count: AtomicUsize::new(0), + index: AtomicUsize::new(0), + transfer_count: AtomicUsize::new(0), + }, }; } @@ -161,7 +177,25 @@ impl AnyChannel { if sr.tcf() { ch.fcr().write(|w| w.set_tcf(true)); - state.complete_count.fetch_add(1, Ordering::Release); + + let lli_count = state.lli_state.count.load(Ordering::Relaxed); + let complete = if lli_count > 0 { + let next_lli_index = state.lli_state.index.load(Ordering::Relaxed) + 1; + let complete = next_lli_index >= lli_count; + + state + .lli_state + .index + .store(if complete { 0 } else { next_lli_index }, Ordering::Relaxed); + + complete + } else { + true + }; + + if complete { + state.complete_count.fetch_add(1, Ordering::Release); + } } if sr.suspf() { @@ -242,6 +276,11 @@ impl AnyChannel { w.set_dteie(true); w.set_suspie(true); }); + + let state = &STATE[self.id as usize]; + state.lli_state.count.store(0, Ordering::Relaxed); + state.lli_state.index.store(0, Ordering::Relaxed); + state.lli_state.transfer_count.store(0, Ordering::Relaxed) } unsafe fn configure_linked_list( @@ -286,6 +325,14 @@ impl AnyChannel { w.set_dteie(true); w.set_suspie(true); }); + + let state = &STATE[self.id as usize]; + state.lli_state.count.store(ITEM_COUNT, Ordering::Relaxed); + state.lli_state.index.store(0, Ordering::Relaxed); + state + .lli_state + .transfer_count + .store(table.transfer_count(), Ordering::Relaxed) } fn start(&self) { diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index fd0a98e23..65ba00b3a 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -22,7 +22,19 @@ struct DmaCtrlImpl<'a>(PeripheralRef<'a, AnyChannel>); impl<'a> DmaCtrl for DmaCtrlImpl<'a> { fn get_remaining_transfers(&self) -> usize { - self.0.get_remaining_transfers() as _ + let state = &STATE[self.0.id as usize]; + let current_remaining = self.0.get_remaining_transfers() as usize; + + let lli_count = state.lli_state.count.load(Ordering::Relaxed); + + if lli_count > 0 { + let lli_index = state.lli_state.index.load(Ordering::Relaxed); + let single_transfer_count = state.lli_state.transfer_count.load(Ordering::Relaxed) / lli_count; + + (lli_count - lli_index - 1) * single_transfer_count + current_remaining + } else { + current_remaining + } } fn reset_complete_count(&mut self) -> usize { @@ -56,7 +68,7 @@ impl BufferHalf { pub struct ReadableRingBuffer<'a, W: Word> { channel: PeripheralRef<'a, AnyChannel>, ringbuf: ReadableDmaRingBuffer<'a, W>, - table: Table<1>, + table: Table<2>, user_buffer_half: BufferHalf, } @@ -78,12 +90,10 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { options.half_transfer_ir = true; options.complete_transfer_ir = true; - // let items = [ - // LinearItem::new_read(request, peri_addr, &mut buffer[..half_len], options), - // LinearItem::new_read(request, peri_addr, &mut buffer[half_len..], options), - // ]; - let items = [LinearItem::new_read(request, peri_addr, buffer, options)]; - + let items = [ + LinearItem::new_read(request, peri_addr, &mut buffer[..half_len], options), + LinearItem::new_read(request, peri_addr, &mut buffer[half_len..], options), + ]; let table = Table::new(items); let this = Self { @@ -209,7 +219,7 @@ impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { pub struct WritableRingBuffer<'a, W: Word> { channel: PeripheralRef<'a, AnyChannel>, ringbuf: WritableDmaRingBuffer<'a, W>, - table: Table<1>, + table: Table<2>, user_buffer_half: BufferHalf, } @@ -231,11 +241,10 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { options.half_transfer_ir = true; options.complete_transfer_ir = true; - // let items = [ - // LinearItem::new_write(request, &mut buffer[..half_len], peri_addr, options), - // LinearItem::new_write(request, &mut buffer[half_len..], peri_addr, options), - // ]; - let items = [LinearItem::new_write(request, buffer, peri_addr, options)]; + let items = [ + LinearItem::new_write(request, &mut buffer[..half_len], peri_addr, options), + LinearItem::new_write(request, &mut buffer[half_len..], peri_addr, options), + ]; let table = Table::new(items); let this = Self { -- cgit From 51b28aaa3162391bcccef1a0fc99f686471d515f Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: style: formatting --- embassy-stm32/src/dma/gpdma/linked_list.rs | 9 ++++----- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 19 +++++++------------ embassy-stm32/src/spdifrx/mod.rs | 3 +-- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/linked_list.rs b/embassy-stm32/src/dma/gpdma/linked_list.rs index 3d2114282..b0c0dffad 100644 --- a/embassy-stm32/src/dma/gpdma/linked_list.rs +++ b/embassy-stm32/src/dma/gpdma/linked_list.rs @@ -1,13 +1,12 @@ //! Implementation of the GPDMA linked list and linked list items. #![macro_use] -use stm32_metapac::gpdma::{regs, vals::Dreq}; +use stm32_metapac::gpdma::regs; +use stm32_metapac::gpdma::vals::Dreq; use super::TransferOptions; -use crate::dma::{ - word::{Word, WordSize}, - Dir, Request, -}; +use crate::dma::word::{Word, WordSize}; +use crate::dma::{Dir, Request}; /// The mode in which to run the linked list. #[derive(Debug)] diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 65ba00b3a..c5c18930b 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -1,22 +1,17 @@ //! GPDMA ring buffer implementation. //! //! FIXME: add request_pause functionality? -use core::{ - future::poll_fn, - sync::atomic::{fence, Ordering}, - task::Waker, -}; +use core::future::poll_fn; +use core::sync::atomic::{fence, Ordering}; +use core::task::Waker; use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; -use crate::dma::{ - gpdma::linked_list::{LinearItem, RunMode, Table}, - ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}, - word::Word, - Channel, Request, -}; - use super::{AnyChannel, TransferOptions, STATE}; +use crate::dma::gpdma::linked_list::{LinearItem, RunMode, Table}; +use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; +use crate::dma::word::Word; +use crate::dma::{Channel, Request}; struct DmaCtrlImpl<'a>(PeripheralRef<'a, AnyChannel>); diff --git a/embassy-stm32/src/spdifrx/mod.rs b/embassy-stm32/src/spdifrx/mod.rs index d3b4a0b10..466639e83 100644 --- a/embassy-stm32/src/spdifrx/mod.rs +++ b/embassy-stm32/src/spdifrx/mod.rs @@ -8,8 +8,7 @@ use embassy_sync::waitqueue::AtomicWaker; use crate::dma::ringbuffer::Error as RingbufferError; pub use crate::dma::word; -use crate::dma::ReadableRingBuffer; -use crate::dma::{Channel, TransferOptions}; +use crate::dma::{Channel, ReadableRingBuffer, TransferOptions}; use crate::gpio::{AfType, AnyPin, Pull, SealedPin as _}; use crate::interrupt::typelevel::Interrupt; use crate::pac::spdifrx::Spdifrx as Regs; -- cgit From f0fc1a15da774f2cc6338697e40f9d1fc7975eb5 Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: disable half-complete interrupt --- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index c5c18930b..6bd48258b 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -82,7 +82,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { let half_len = buffer.len() / 2; assert_eq!(half_len * 2, buffer.len()); - options.half_transfer_ir = true; + options.half_transfer_ir = false; options.complete_transfer_ir = true; let items = [ @@ -233,7 +233,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { let half_len = buffer.len() / 2; assert_eq!(half_len * 2, buffer.len()); - options.half_transfer_ir = true; + options.half_transfer_ir = false; options.complete_transfer_ir = true; let items = [ -- cgit From be881875917b93a8cdb7a4ab07876e1239fbe1be Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: transfer options --- embassy-stm32/src/dma/gpdma/mod.rs | 3 +++ embassy-stm32/src/dma/gpdma/ringbuffered.rs | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index 1d2811ab4..b23c22dfb 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -283,6 +283,9 @@ impl AnyChannel { state.lli_state.transfer_count.store(0, Ordering::Relaxed) } + /// Configure a linked-list transfer. + /// + /// Transfer options apply only to the base register transfer, not the linked-list items. unsafe fn configure_linked_list( &self, table: &Table, diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 6bd48258b..a5b127d08 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -69,6 +69,8 @@ pub struct ReadableRingBuffer<'a, W: Word> { impl<'a, W: Word> ReadableRingBuffer<'a, W> { /// Create a new ring buffer. + /// + /// Transfer options are applied to the individual linked list items. pub unsafe fn new( channel: impl Peripheral

+ 'a, request: Request, @@ -220,6 +222,8 @@ pub struct WritableRingBuffer<'a, W: Word> { impl<'a, W: Word> WritableRingBuffer<'a, W> { /// Create a new ring buffer. + /// + /// Transfer options are applied to the individual linked list items. pub unsafe fn new( channel: impl Peripheral

+ 'a, request: Request, @@ -279,7 +283,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { self.channel.configure_linked_list( &self.table, TransferOptions { - half_transfer_ir: true, + half_transfer_ir: false, complete_transfer_ir: true, ..Default::default() }, -- cgit From 1541f1e0c2c3b2f8d5e5764966393eedac95ebf0 Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: chore: clean up transfer options --- embassy-stm32/src/dma/gpdma/linked_list.rs | 18 ++---------------- embassy-stm32/src/dma/gpdma/mod.rs | 2 -- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 22 ++++------------------ 3 files changed, 6 insertions(+), 36 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/linked_list.rs b/embassy-stm32/src/dma/gpdma/linked_list.rs index b0c0dffad..b0cf96f96 100644 --- a/embassy-stm32/src/dma/gpdma/linked_list.rs +++ b/embassy-stm32/src/dma/gpdma/linked_list.rs @@ -4,7 +4,6 @@ use stm32_metapac::gpdma::regs; use stm32_metapac::gpdma::vals::Dreq; -use super::TransferOptions; use crate::dma::word::{Word, WordSize}; use crate::dma::{Dir, Request}; @@ -42,12 +41,7 @@ pub struct LinearItem { impl LinearItem { /// Create a new read DMA transfer (peripheral to memory). - pub unsafe fn new_read<'d, W: Word>( - request: Request, - peri_addr: *mut W, - buf: &'d mut [W], - options: TransferOptions, - ) -> Self { + pub unsafe fn new_read<'d, W: Word>(request: Request, peri_addr: *mut W, buf: &'d mut [W]) -> Self { Self::new_inner( request, Dir::PeripheralToMemory, @@ -57,17 +51,11 @@ impl LinearItem { true, W::size(), W::size(), - options, ) } /// Create a new write DMA transfer (memory to peripheral). - pub unsafe fn new_write<'d, MW: Word, PW: Word>( - request: Request, - buf: &'d [MW], - peri_addr: *mut PW, - options: TransferOptions, - ) -> Self { + pub unsafe fn new_write<'d, MW: Word, PW: Word>(request: Request, buf: &'d [MW], peri_addr: *mut PW) -> Self { Self::new_inner( request, Dir::MemoryToPeripheral, @@ -77,7 +65,6 @@ impl LinearItem { true, MW::size(), PW::size(), - options, ) } @@ -90,7 +77,6 @@ impl LinearItem { incr_mem: bool, data_size: WordSize, dst_size: WordSize, - _options: TransferOptions, ) -> Self { // BNDT is specified as bytes, not as number of transfers. let Ok(bndt) = (mem_len * data_size.bytes()).try_into() else { diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index b23c22dfb..e906c7559 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -284,8 +284,6 @@ impl AnyChannel { } /// Configure a linked-list transfer. - /// - /// Transfer options apply only to the base register transfer, not the linked-list items. unsafe fn configure_linked_list( &self, table: &Table, diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index a5b127d08..9bee12d99 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -222,14 +222,12 @@ pub struct WritableRingBuffer<'a, W: Word> { impl<'a, W: Word> WritableRingBuffer<'a, W> { /// Create a new ring buffer. - /// - /// Transfer options are applied to the individual linked list items. pub unsafe fn new( channel: impl Peripheral

+ 'a, request: Request, peri_addr: *mut W, buffer: &'a mut [W], - mut options: TransferOptions, + _options: TransferOptions, ) -> Self { into_ref!(channel); let channel: PeripheralRef<'a, AnyChannel> = channel.map_into(); @@ -237,12 +235,9 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { let half_len = buffer.len() / 2; assert_eq!(half_len * 2, buffer.len()); - options.half_transfer_ir = false; - options.complete_transfer_ir = true; - let items = [ - LinearItem::new_write(request, &mut buffer[..half_len], peri_addr, options), - LinearItem::new_write(request, &mut buffer[half_len..], peri_addr, options), + LinearItem::new_write(request, &mut buffer[..half_len], peri_addr), + LinearItem::new_write(request, &mut buffer[half_len..], peri_addr), ]; let table = Table::new(items); @@ -279,16 +274,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { /// /// You must call this after creating it for it to work. pub fn start(&mut self) { - unsafe { - self.channel.configure_linked_list( - &self.table, - TransferOptions { - half_transfer_ir: false, - complete_transfer_ir: true, - ..Default::default() - }, - ) - }; + unsafe { self.channel.configure_linked_list(&self.table, Default::default()) }; self.table.link(RunMode::Repeat); self.channel.start(); } -- cgit From bfd82ff82c1a1cc5159fc07997af2ca87622a679 Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: read transfer options --- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 9bee12d99..c49c6c73d 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -76,7 +76,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { request: Request, peri_addr: *mut W, buffer: &'a mut [W], - mut options: TransferOptions, + _options: TransferOptions, ) -> Self { into_ref!(channel); let channel: PeripheralRef<'a, AnyChannel> = channel.map_into(); @@ -84,31 +84,26 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { let half_len = buffer.len() / 2; assert_eq!(half_len * 2, buffer.len()); - options.half_transfer_ir = false; - options.complete_transfer_ir = true; - let items = [ - LinearItem::new_read(request, peri_addr, &mut buffer[..half_len], options), - LinearItem::new_read(request, peri_addr, &mut buffer[half_len..], options), + LinearItem::new_read(request, peri_addr, &mut buffer[..half_len]), + LinearItem::new_read(request, peri_addr, &mut buffer[half_len..]), ]; let table = Table::new(items); - let this = Self { + Self { channel, ringbuf: ReadableDmaRingBuffer::new(buffer), table, user_buffer_half: BufferHalf::First, - }; - - this.channel.configure_linked_list(&this.table, options); - - this + } } /// Start the ring buffer operation. /// /// You must call this after creating it for it to work. pub fn start(&mut self) { + unsafe { self.channel.configure_linked_list(&self.table, Default::default()) }; + self.table.link(RunMode::Repeat); self.channel.start(); } -- cgit From 50224583db79fcbfe340056eef855414c884f281 Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: load/store ordering --- embassy-stm32/src/dma/gpdma/mod.rs | 6 +++--- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index e906c7559..a158d30b8 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -178,15 +178,15 @@ impl AnyChannel { if sr.tcf() { ch.fcr().write(|w| w.set_tcf(true)); - let lli_count = state.lli_state.count.load(Ordering::Relaxed); + let lli_count = state.lli_state.count.load(Ordering::Acquire); let complete = if lli_count > 0 { - let next_lli_index = state.lli_state.index.load(Ordering::Relaxed) + 1; + let next_lli_index = state.lli_state.index.load(Ordering::Acquire) + 1; let complete = next_lli_index >= lli_count; state .lli_state .index - .store(if complete { 0 } else { next_lli_index }, Ordering::Relaxed); + .store(if complete { 0 } else { next_lli_index }, Ordering::Release); complete } else { diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index c49c6c73d..20f46b103 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -20,11 +20,11 @@ impl<'a> DmaCtrl for DmaCtrlImpl<'a> { let state = &STATE[self.0.id as usize]; let current_remaining = self.0.get_remaining_transfers() as usize; - let lli_count = state.lli_state.count.load(Ordering::Relaxed); + let lli_count = state.lli_state.count.load(Ordering::Acquire); if lli_count > 0 { - let lli_index = state.lli_state.index.load(Ordering::Relaxed); - let single_transfer_count = state.lli_state.transfer_count.load(Ordering::Relaxed) / lli_count; + let lli_index = state.lli_state.index.load(Ordering::Acquire); + let single_transfer_count = state.lli_state.transfer_count.load(Ordering::Acquire) / lli_count; (lli_count - lli_index - 1) * single_transfer_count + current_remaining } else { -- cgit From 2baa4399a7dc4c38ed478f723bbf3b7417dcc0f5 Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: wip gpdma --- embassy-stm32/src/dma/gpdma/mod.rs | 6 ++---- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 25 ++++++++++++++----------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index a158d30b8..9868ce52d 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -199,10 +199,8 @@ impl AnyChannel { } if sr.suspf() { - // disable all xxIEs to prevent the irq from firing again. + // Disable all xxIEs to prevent the irq from firing again. ch.cr().write(|_| {}); - - // Wake the future. It'll look at tcf and see it's set. } state.waker.wake(); } @@ -366,7 +364,7 @@ impl AnyChannel { let sr = ch.sr().read(); - !sr.tcf() && !sr.suspf() && !sr.idlef() + !sr.suspf() && !sr.idlef() } fn poll_stop(&self) -> Poll<()> { diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 20f46b103..5ba45358b 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -23,11 +23,14 @@ impl<'a> DmaCtrl for DmaCtrlImpl<'a> { let lli_count = state.lli_state.count.load(Ordering::Acquire); if lli_count > 0 { + // In linked-list mode, the remaining transfers are the sum of the full lengths of LLIs that follow, + // and the remaining transfers for the current LLI. let lli_index = state.lli_state.index.load(Ordering::Acquire); let single_transfer_count = state.lli_state.transfer_count.load(Ordering::Acquire) / lli_count; (lli_count - lli_index - 1) * single_transfer_count + current_remaining } else { + // No linked-list mode. current_remaining } } @@ -81,6 +84,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { into_ref!(channel); let channel: PeripheralRef<'a, AnyChannel> = channel.map_into(); + // Buffer halves should be the same length. let half_len = buffer.len() / 2; assert_eq!(half_len * 2, buffer.len()); @@ -227,6 +231,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { into_ref!(channel); let channel: PeripheralRef<'a, AnyChannel> = channel.map_into(); + // Buffer halves should be the same length. let half_len = buffer.len() / 2; assert_eq!(half_len * 2, buffer.len()); @@ -258,8 +263,8 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { self.table.unlink(); match self.user_buffer_half { - BufferHalf::First => self.table.link_indices(0, 1), - BufferHalf::Second => self.table.link_indices(1, 0), + BufferHalf::First => self.table.link_indices(1, 0), + BufferHalf::Second => self.table.link_indices(0, 1), } self.user_buffer_half.toggle(); @@ -298,48 +303,46 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) .await; - let mut remaining = buffer.len(); + let mut writable_length = buffer.len(); let mut remaining_cap = 0; let cap = self.ringbuf.cap(); - while remaining > 0 { + while writable_length > 0 { let dma_buffer_half = self.dma_buffer_half(); if dma_buffer_half == self.user_buffer_half { self.link_next_buffer(); } let write_index = self.ringbuf.write_index(0); - let len = match dma_buffer_half { + let write_length = match dma_buffer_half { BufferHalf::First => { // if write_index < cap / 2 { // error!("write index: {}", write_index); // panic!() // } - info!("Write second"); // Fill up second buffer half when DMA reads the first. - cap - write_index + cap / 2 - write_index } BufferHalf::Second => { // if write_index >= cap / 2 { // error!("write index: {}", write_index); // panic!() // } - info!("Write first"); // Fill up first buffer half when DMA reads the second. - cap / 2 - write_index + cap - write_index } } - .min(remaining); + .min(writable_length); remaining_cap = self .ringbuf .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) .await?; - remaining -= len; + writable_length -= write_length; } Ok(remaining_cap) -- cgit From 78364b966eb76c071d5450c2a13cc788d7e5be80 Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: chore: change naming --- embassy-stm32/src/dma/gpdma/linked_list.rs | 6 +- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 92 +++++++++++++---------------- embassy-stm32/src/dma/ringbuffer/mod.rs | 46 +++++++++++++-- 3 files changed, 87 insertions(+), 57 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/linked_list.rs b/embassy-stm32/src/dma/gpdma/linked_list.rs index b0cf96f96..a95e5590e 100644 --- a/embassy-stm32/src/dma/gpdma/linked_list.rs +++ b/embassy-stm32/src/dma/gpdma/linked_list.rs @@ -15,7 +15,7 @@ pub enum RunMode { /// The list is linked sequentially and only run once. Once, /// The list is linked sequentially, and the end of the list is linked to the beginning. - Repeat, + Circular, } /// A linked-list item for linear GPDMA transfers. @@ -169,11 +169,11 @@ impl Table { /// Link the table as given by the run mode. pub fn link(&mut self, run_mode: RunMode) { - if matches!(run_mode, RunMode::Once | RunMode::Repeat) { + if matches!(run_mode, RunMode::Once | RunMode::Circular) { self.link_sequential(); } - if matches!(run_mode, RunMode::Repeat) { + if matches!(run_mode, RunMode::Circular) { self.link_repeat(); } } diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 5ba45358b..99c85a221 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -48,6 +48,7 @@ impl<'a> DmaCtrl for DmaCtrlImpl<'a> { /// The current buffer half (e.g. for DMA or the user application). #[derive(Debug, PartialEq, PartialOrd)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] enum BufferHalf { First, Second, @@ -107,7 +108,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { /// You must call this after creating it for it to work. pub fn start(&mut self) { unsafe { self.channel.configure_linked_list(&self.table, Default::default()) }; - self.table.link(RunMode::Repeat); + self.table.link(RunMode::Circular); self.channel.start(); } @@ -251,31 +252,12 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { this } - fn dma_buffer_half(&self) -> BufferHalf { - if self.ringbuf.read_index(0) < self.ringbuf.cap() / 2 { - BufferHalf::First - } else { - BufferHalf::Second - } - } - - fn link_next_buffer(&mut self) { - self.table.unlink(); - - match self.user_buffer_half { - BufferHalf::First => self.table.link_indices(1, 0), - BufferHalf::Second => self.table.link_indices(0, 1), - } - - self.user_buffer_half.toggle(); - } - /// Start the ring buffer operation. /// /// You must call this after creating it for it to work. pub fn start(&mut self) { unsafe { self.channel.configure_linked_list(&self.table, Default::default()) }; - self.table.link(RunMode::Repeat); + self.table.link(RunMode::Circular); self.channel.start(); } @@ -303,47 +285,57 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) .await; - let mut writable_length = buffer.len(); + let mut written_len = 0; + let len = buffer.len(); let mut remaining_cap = 0; let cap = self.ringbuf.cap(); - while writable_length > 0 { - let dma_buffer_half = self.dma_buffer_half(); - if dma_buffer_half == self.user_buffer_half { - self.link_next_buffer(); - } - - let write_index = self.ringbuf.write_index(0); - let write_length = match dma_buffer_half { + let dma = &mut DmaCtrlImpl(self.channel.reborrow()); + let user_buffer_half = &mut self.user_buffer_half; + let ringbuf = &mut self.ringbuf; + let table = &mut self.table; + + while written_len != len { + // info!( + // "read {}, write {}, cap {}", + // ringbuf.read_index(0), + // ringbuf.write_index(0), + // ringbuf.cap() + // ); + + let dma_buffer_half = if ringbuf.read_index(0) < ringbuf.cap() / 2 { + BufferHalf::First + } else { + BufferHalf::Second + }; + + // if dma_buffer_half == *user_buffer_half { + // info!("swap user from {}", user_buffer_half); + // table.unlink(); + + // match user_buffer_half { + // BufferHalf::First => table.link_indices(1, 0), + // BufferHalf::Second => table.link_indices(0, 1), + // } + + // user_buffer_half.toggle(); + // } + + let index = match dma_buffer_half { BufferHalf::First => { - // if write_index < cap / 2 { - // error!("write index: {}", write_index); - // panic!() - // } - // Fill up second buffer half when DMA reads the first. - cap / 2 - write_index + cap - 1 } BufferHalf::Second => { - // if write_index >= cap / 2 { - // error!("write index: {}", write_index); - // panic!() - // } - // Fill up first buffer half when DMA reads the second. - cap - write_index + cap / 2 - 1 } - } - .min(writable_length); - - remaining_cap = self - .ringbuf - .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) - .await?; + }; - writable_length -= write_length; + (written_len, remaining_cap) = ringbuf.write_until(dma, &buffer, index).await?; } + info!("done"); Ok(remaining_cap) } diff --git a/embassy-stm32/src/dma/ringbuffer/mod.rs b/embassy-stm32/src/dma/ringbuffer/mod.rs index 99960bc74..c4bf4dd60 100644 --- a/embassy-stm32/src/dma/ringbuffer/mod.rs +++ b/embassy-stm32/src/dma/ringbuffer/mod.rs @@ -303,17 +303,19 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> { } /// Write an exact number of elements to the ringbuffer. + /// + /// Returns the remaining write capacity in the buffer. pub async fn write_exact(&mut self, dma: &mut impl DmaCtrl, buffer: &[W]) -> Result { - let mut written_data = 0; + let mut written_len = 0; let buffer_len = buffer.len(); poll_fn(|cx| { dma.set_waker(cx.waker()); - match self.write(dma, &buffer[written_data..buffer_len]) { + match self.write(dma, &buffer[written_len..buffer_len]) { Ok((len, remaining)) => { - written_data += len; - if written_data == buffer_len { + written_len += len; + if written_len == buffer_len { Poll::Ready(Ok(remaining)) } else { Poll::Pending @@ -325,6 +327,42 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> { .await } + /// Write until a given write index. + /// + /// Returns a tuple of the written length, and the remaining write capacity in the buffer. + pub async fn write_until( + &mut self, + dma: &mut impl DmaCtrl, + buffer: &[W], + index: usize, + ) -> Result<(usize, usize), Error> { + let mut written_len = 0; + let write_len = index + .saturating_sub(self.write_index.as_index(self.cap(), 0)) + .min(buffer.len()); + + if write_len == 0 { + return Err(Error::Overrun); + } + + poll_fn(|cx| { + dma.set_waker(cx.waker()); + + match self.write(dma, &buffer[written_len..write_len]) { + Ok((len, remaining)) => { + written_len += len; + if written_len == write_len { + Poll::Ready(Ok((written_len, remaining))) + } else { + Poll::Pending + } + } + Err(e) => Poll::Ready(Err(e)), + } + }) + .await + } + fn write_raw(&mut self, dma: &mut impl DmaCtrl, buf: &[W]) -> Result<(usize, usize), Error> { let writable = self.len(dma)?.min(buf.len()); for i in 0..writable { -- cgit From a4d3b4b6ae3f3265ea372e446a6e7b5d3685ea3a Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: feat: wip, write buffer in halves --- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 84 ++++------------------------- embassy-stm32/src/dma/ringbuffer/mod.rs | 76 ++++++++++++++------------ embassy-stm32/src/usart/ringbuffered.rs | 2 +- 3 files changed, 54 insertions(+), 108 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 99c85a221..a5d2c700c 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -46,29 +46,11 @@ impl<'a> DmaCtrl for DmaCtrlImpl<'a> { } } -/// The current buffer half (e.g. for DMA or the user application). -#[derive(Debug, PartialEq, PartialOrd)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -enum BufferHalf { - First, - Second, -} - -impl BufferHalf { - fn toggle(&mut self) { - *self = match *self { - Self::First => Self::Second, - Self::Second => Self::First, - }; - } -} - /// Ringbuffer for receiving data using GPDMA linked-list mode. pub struct ReadableRingBuffer<'a, W: Word> { channel: PeripheralRef<'a, AnyChannel>, ringbuf: ReadableDmaRingBuffer<'a, W>, table: Table<2>, - user_buffer_half: BufferHalf, } impl<'a, W: Word> ReadableRingBuffer<'a, W> { @@ -99,7 +81,6 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { channel, ringbuf: ReadableDmaRingBuffer::new(buffer), table, - user_buffer_half: BufferHalf::First, } } @@ -217,7 +198,6 @@ pub struct WritableRingBuffer<'a, W: Word> { channel: PeripheralRef<'a, AnyChannel>, ringbuf: WritableDmaRingBuffer<'a, W>, table: Table<2>, - user_buffer_half: BufferHalf, } impl<'a, W: Word> WritableRingBuffer<'a, W> { @@ -246,7 +226,6 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { channel, ringbuf: WritableDmaRingBuffer::new(buffer), table, - user_buffer_half: BufferHalf::First, }; this @@ -280,62 +259,21 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { /// Write an exact number of elements to the ringbuffer. pub async fn write_exact(&mut self, buffer: &[W]) -> Result { - return self - .ringbuf - .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) - .await; + // return self + // .ringbuf + // .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) + // .await; + let mut remaining_cap = 0; let mut written_len = 0; - let len = buffer.len(); - let mut remaining_cap = 0; - let cap = self.ringbuf.cap(); - - let dma = &mut DmaCtrlImpl(self.channel.reborrow()); - let user_buffer_half = &mut self.user_buffer_half; - let ringbuf = &mut self.ringbuf; - let table = &mut self.table; - - while written_len != len { - // info!( - // "read {}, write {}, cap {}", - // ringbuf.read_index(0), - // ringbuf.write_index(0), - // ringbuf.cap() - // ); - - let dma_buffer_half = if ringbuf.read_index(0) < ringbuf.cap() / 2 { - BufferHalf::First - } else { - BufferHalf::Second - }; - - // if dma_buffer_half == *user_buffer_half { - // info!("swap user from {}", user_buffer_half); - // table.unlink(); - - // match user_buffer_half { - // BufferHalf::First => table.link_indices(1, 0), - // BufferHalf::Second => table.link_indices(0, 1), - // } - - // user_buffer_half.toggle(); - // } - - let index = match dma_buffer_half { - BufferHalf::First => { - // Fill up second buffer half when DMA reads the first. - cap - 1 - } - BufferHalf::Second => { - // Fill up first buffer half when DMA reads the second. - cap / 2 - 1 - } - }; - - (written_len, remaining_cap) = ringbuf.write_until(dma, &buffer, index).await?; + while written_len < buffer.len() { + (written_len, remaining_cap) = self + .ringbuf + .write_half(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) + .await?; + // info!("Written: {}/{}", written_len, buffer.len()); } - info!("done"); Ok(remaining_cap) } diff --git a/embassy-stm32/src/dma/ringbuffer/mod.rs b/embassy-stm32/src/dma/ringbuffer/mod.rs index c4bf4dd60..8d00d822d 100644 --- a/embassy-stm32/src/dma/ringbuffer/mod.rs +++ b/embassy-stm32/src/dma/ringbuffer/mod.rs @@ -3,6 +3,14 @@ use core::task::{Poll, Waker}; use crate::dma::word::Word; +/// The current buffer half (e.g. for DMA or the user application). +#[derive(Debug, PartialEq, PartialOrd)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +enum BufferHalf { + First, + Second, +} + pub trait DmaCtrl { /// Get the NDTR register value, i.e. the space left in the underlying /// buffer until the dma writer wraps. @@ -92,16 +100,6 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> { } } - /// The current ring-buffer read index. - pub fn read_index(&self, offset: usize) -> usize { - self.read_index.as_index(self.cap(), offset) - } - - /// The current ring-buffer write index. - pub fn write_index(&self, offset: usize) -> usize { - self.write_index.as_index(self.cap(), offset) - } - /// Reset the ring buffer to its initial state. pub fn reset(&mut self, dma: &mut impl DmaCtrl) { dma.reset_complete_count(); @@ -218,14 +216,13 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> { } } - /// The current ring-buffer read index. - pub fn read_index(&self, offset: usize) -> usize { - self.read_index.as_index(self.cap(), offset) - } - - /// The current ring-buffer write index. - pub fn write_index(&self, offset: usize) -> usize { - self.write_index.as_index(self.cap(), offset) + /// The buffer half that is in use by the DMA. + fn dma_half(&self) -> BufferHalf { + if self.read_index.as_index(self.cap(), 0) < self.cap() / 2 { + BufferHalf::First + } else { + BufferHalf::Second + } } /// Reset the ring buffer to its initial state. The buffer after the reset will be full. @@ -305,6 +302,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> { /// Write an exact number of elements to the ringbuffer. /// /// Returns the remaining write capacity in the buffer. + #[allow(dead_code)] pub async fn write_exact(&mut self, dma: &mut impl DmaCtrl, buffer: &[W]) -> Result { let mut written_len = 0; let buffer_len = buffer.len(); @@ -327,31 +325,41 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> { .await } - /// Write until a given write index. + /// Write the user's current buffer half - not used by the DMA. /// /// Returns a tuple of the written length, and the remaining write capacity in the buffer. - pub async fn write_until( - &mut self, - dma: &mut impl DmaCtrl, - buffer: &[W], - index: usize, - ) -> Result<(usize, usize), Error> { + #[allow(dead_code)] + pub async fn write_half(&mut self, dma: &mut impl DmaCtrl, buffer: &[W]) -> Result<(usize, usize), Error> { let mut written_len = 0; - let write_len = index - .saturating_sub(self.write_index.as_index(self.cap(), 0)) - .min(buffer.len()); - - if write_len == 0 { - return Err(Error::Overrun); - } + let buffer_len = buffer.len(); poll_fn(|cx| { dma.set_waker(cx.waker()); - match self.write(dma, &buffer[written_len..write_len]) { + let dma_half = self.dma_half(); + // let user_half = self.user_half(); + + // if dma_half == user_half { + // info!("ups"); + // return Poll::Ready(Err(Error::Overrun)); + // } + + let write_index = self.write_index.as_index(self.cap(), 0); + let target_write_len = match dma_half { + BufferHalf::First => self.cap().saturating_sub(write_index), + BufferHalf::Second => (self.cap() / 2).saturating_sub(write_index), + }; + let write_end_index = (target_write_len + written_len).min(buffer_len); + + // info!( + // "buf_len: {}, write_len: {}, write_index: {}", + // buffer_len, target_write_len, write_index + // ); + + match self.write(dma, &buffer[written_len..write_end_index]) { Ok((len, remaining)) => { written_len += len; - if written_len == write_len { + if written_len == write_end_index { Poll::Ready(Ok((written_len, remaining))) } else { Poll::Pending diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index 1d4a44896..5f4e87834 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs @@ -381,7 +381,7 @@ impl ReadReady for RingBufferedUartRx<'_> { crate::dma::ringbuffer::Error::Overrun => Self::Error::Overrun, crate::dma::ringbuffer::Error::DmaUnsynced => { error!( - "Ringbuffer error: DmaUNsynced, driver implementation is + "Ringbuffer error: DmaUNsynced, driver implementation is probably bugged please open an issue" ); // we report this as overrun since its recoverable in the same way -- cgit From 7a62b8eee8f2f466fbe1878aab42d63aa171ddaa Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: build issues --- embassy-stm32/src/dma/gpdma/mod.rs | 12 +++++------- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 18 ++++++++---------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index 9868ce52d..2132f070a 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -382,23 +382,21 @@ impl AnyChannel { /// Linked-list DMA transfer. #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct LinkedListTransfer<'a, const ITEM_COUNT: usize> { - channel: PeripheralRef<'a, AnyChannel>, + channel: Peri<'a, AnyChannel>, } impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { /// Create a new linked-list transfer. pub unsafe fn new_linked_list( - channel: impl Peripheral

+ 'a, + channel: Peri<'a, impl Channel>, table: Table, options: TransferOptions, ) -> Self { - into_ref!(channel); - - Self::new_inner_linked_list(channel.map_into(), table, options) + Self::new_inner_linked_list(channel.into(), table, options) } unsafe fn new_inner_linked_list( - channel: PeripheralRef<'a, AnyChannel>, + channel: Peri<'a, AnyChannel>, table: Table, options: TransferOptions, ) -> Self { @@ -576,7 +574,7 @@ impl<'a> Transfer<'a> { assert!(mem_len > 0 && mem_len <= 0xFFFF); channel.configure( - _request, + request, dir, peri_addr, mem_addr, diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index a5d2c700c..88ec666dc 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -5,7 +5,7 @@ use core::future::poll_fn; use core::sync::atomic::{fence, Ordering}; use core::task::Waker; -use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; +use embassy_hal_internal::Peri; use super::{AnyChannel, TransferOptions, STATE}; use crate::dma::gpdma::linked_list::{LinearItem, RunMode, Table}; @@ -13,7 +13,7 @@ use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaR use crate::dma::word::Word; use crate::dma::{Channel, Request}; -struct DmaCtrlImpl<'a>(PeripheralRef<'a, AnyChannel>); +struct DmaCtrlImpl<'a>(Peri<'a, AnyChannel>); impl<'a> DmaCtrl for DmaCtrlImpl<'a> { fn get_remaining_transfers(&self) -> usize { @@ -48,7 +48,7 @@ impl<'a> DmaCtrl for DmaCtrlImpl<'a> { /// Ringbuffer for receiving data using GPDMA linked-list mode. pub struct ReadableRingBuffer<'a, W: Word> { - channel: PeripheralRef<'a, AnyChannel>, + channel: Peri<'a, AnyChannel>, ringbuf: ReadableDmaRingBuffer<'a, W>, table: Table<2>, } @@ -58,14 +58,13 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { /// /// Transfer options are applied to the individual linked list items. pub unsafe fn new( - channel: impl Peripheral

+ 'a, + channel: Peri<'a, impl Channel>, request: Request, peri_addr: *mut W, buffer: &'a mut [W], _options: TransferOptions, ) -> Self { - into_ref!(channel); - let channel: PeripheralRef<'a, AnyChannel> = channel.map_into(); + let channel: Peri<'a, AnyChannel> = channel.into(); // Buffer halves should be the same length. let half_len = buffer.len() / 2; @@ -195,7 +194,7 @@ impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { /// Ringbuffer for writing data using DMA circular mode. pub struct WritableRingBuffer<'a, W: Word> { - channel: PeripheralRef<'a, AnyChannel>, + channel: Peri<'a, AnyChannel>, ringbuf: WritableDmaRingBuffer<'a, W>, table: Table<2>, } @@ -203,14 +202,13 @@ pub struct WritableRingBuffer<'a, W: Word> { impl<'a, W: Word> WritableRingBuffer<'a, W> { /// Create a new ring buffer. pub unsafe fn new( - channel: impl Peripheral

+ 'a, + channel: Peri<'a, impl Channel>, request: Request, peri_addr: *mut W, buffer: &'a mut [W], _options: TransferOptions, ) -> Self { - into_ref!(channel); - let channel: PeripheralRef<'a, AnyChannel> = channel.map_into(); + let channel: Peri<'a, AnyChannel> = channel.into(); // Buffer halves should be the same length. let half_len = buffer.len() / 2; -- cgit From 3d161e98a1a56d6d73473c40431480d53ee67b70 Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: simplify --- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 23 +++--------- embassy-stm32/src/dma/ringbuffer/mod.rs | 55 ----------------------------- 2 files changed, 5 insertions(+), 73 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 88ec666dc..f9d77ab73 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -1,6 +1,7 @@ //! GPDMA ring buffer implementation. //! -//! FIXME: add request_pause functionality? +//! FIXME: Add request_pause functionality? +//! FIXME: Stop the DMA, if a user does not queue new transfers (chain of linked-list items ends automatically). use core::future::poll_fn; use core::sync::atomic::{fence, Ordering}; use core::task::Waker; @@ -257,23 +258,9 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { /// Write an exact number of elements to the ringbuffer. pub async fn write_exact(&mut self, buffer: &[W]) -> Result { - // return self - // .ringbuf - // .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) - // .await; - - let mut remaining_cap = 0; - let mut written_len = 0; - - while written_len < buffer.len() { - (written_len, remaining_cap) = self - .ringbuf - .write_half(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) - .await?; - // info!("Written: {}/{}", written_len, buffer.len()); - } - - Ok(remaining_cap) + self.ringbuf + .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) + .await } /// Wait for any ring buffer write error. diff --git a/embassy-stm32/src/dma/ringbuffer/mod.rs b/embassy-stm32/src/dma/ringbuffer/mod.rs index 8d00d822d..2d61204a2 100644 --- a/embassy-stm32/src/dma/ringbuffer/mod.rs +++ b/embassy-stm32/src/dma/ringbuffer/mod.rs @@ -216,15 +216,6 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> { } } - /// The buffer half that is in use by the DMA. - fn dma_half(&self) -> BufferHalf { - if self.read_index.as_index(self.cap(), 0) < self.cap() / 2 { - BufferHalf::First - } else { - BufferHalf::Second - } - } - /// Reset the ring buffer to its initial state. The buffer after the reset will be full. pub fn reset(&mut self, dma: &mut impl DmaCtrl) { dma.reset_complete_count(); @@ -325,52 +316,6 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> { .await } - /// Write the user's current buffer half - not used by the DMA. - /// - /// Returns a tuple of the written length, and the remaining write capacity in the buffer. - #[allow(dead_code)] - pub async fn write_half(&mut self, dma: &mut impl DmaCtrl, buffer: &[W]) -> Result<(usize, usize), Error> { - let mut written_len = 0; - let buffer_len = buffer.len(); - - poll_fn(|cx| { - dma.set_waker(cx.waker()); - - let dma_half = self.dma_half(); - // let user_half = self.user_half(); - - // if dma_half == user_half { - // info!("ups"); - // return Poll::Ready(Err(Error::Overrun)); - // } - - let write_index = self.write_index.as_index(self.cap(), 0); - let target_write_len = match dma_half { - BufferHalf::First => self.cap().saturating_sub(write_index), - BufferHalf::Second => (self.cap() / 2).saturating_sub(write_index), - }; - let write_end_index = (target_write_len + written_len).min(buffer_len); - - // info!( - // "buf_len: {}, write_len: {}, write_index: {}", - // buffer_len, target_write_len, write_index - // ); - - match self.write(dma, &buffer[written_len..write_end_index]) { - Ok((len, remaining)) => { - written_len += len; - if written_len == write_end_index { - Poll::Ready(Ok((written_len, remaining))) - } else { - Poll::Pending - } - } - Err(e) => Poll::Ready(Err(e)), - } - }) - .await - } - fn write_raw(&mut self, dma: &mut impl DmaCtrl, buf: &[W]) -> Result<(usize, usize), Error> { let writable = self.len(dma)?.min(buf.len()); for i in 0..writable { -- cgit From 40a0d5d8f2fc7e2cfc216eb31b47729dd95a24cd Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: build warnings --- embassy-stm32/src/dma/ringbuffer/mod.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/embassy-stm32/src/dma/ringbuffer/mod.rs b/embassy-stm32/src/dma/ringbuffer/mod.rs index 2d61204a2..659ffa9e5 100644 --- a/embassy-stm32/src/dma/ringbuffer/mod.rs +++ b/embassy-stm32/src/dma/ringbuffer/mod.rs @@ -3,14 +3,6 @@ use core::task::{Poll, Waker}; use crate::dma::word::Word; -/// The current buffer half (e.g. for DMA or the user application). -#[derive(Debug, PartialEq, PartialOrd)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -enum BufferHalf { - First, - Second, -} - pub trait DmaCtrl { /// Get the NDTR register value, i.e. the space left in the underlying /// buffer until the dma writer wraps. -- cgit From 7d224d94c47e4e457aed7c4832be8b4a52dfcef8 Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: docstring --- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index f9d77ab73..87c482bfb 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -193,7 +193,7 @@ impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { } } -/// Ringbuffer for writing data using DMA circular mode. +/// Ringbuffer for writing data using GPDMA linked-list mode. pub struct WritableRingBuffer<'a, W: Word> { channel: Peri<'a, AnyChannel>, ringbuf: WritableDmaRingBuffer<'a, W>, -- cgit From fec14213ea7b79badc14eae38c4a0b0197499f3f Mon Sep 17 00:00:00 2001 From: etiennecollin Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: modified dma channel state management See https://github.com/embassy-rs/embassy/pull/3923#discussion_r2094570176 --- embassy-stm32/src/dma/gpdma/mod.rs | 66 ++++++++++++++++++++--------- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 54 +++++++++++++---------- embassy-stm32/src/ucpd.rs | 4 +- embassy-stm32/src/usart/ringbuffered.rs | 2 +- 4 files changed, 80 insertions(+), 46 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index 2132f070a..d06eac60e 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -341,21 +341,25 @@ impl AnyChannel { ch.cr().modify(|w| w.set_en(true)); } - fn request_stop(&self) { + fn request_suspend(&self) { let info = self.info(); let ch = info.dma.ch(info.num); ch.cr().modify(|w| w.set_susp(true)) } - fn request_pause(&self) { + fn request_resume(&self) { let info = self.info(); let ch = info.dma.ch(info.num); - // Disable the channel without overwriting the existing configuration - ch.cr().modify(|w| { - w.set_en(false); - }); + ch.cr().modify(|w| w.set_susp(false)); + } + + fn request_reset(&self) { + let info = self.info(); + let ch = info.dma.ch(info.num); + + ch.cr().modify(|w| w.set_reset(true)); } fn is_running(&self) -> bool { @@ -406,11 +410,26 @@ impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { Self { channel } } - /// Request the transfer to stop. + /// Request the transfer to suspend. + /// + /// To resume the transfer, call [`request_resume`](Self::request_resume) again. /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_stop(&mut self) { - self.channel.request_stop() + pub fn request_suspend(&mut self) { + self.channel.request_suspend() + } + + /// Request the transfer to resume after being suspended. + pub fn request_resume(&mut self) { + self.channel.request_resume() + } + + /// Request the DMA to reset. + /// + /// The configuration for this channel will **not be preserved**. If you need to restart the transfer + /// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead. + pub fn request_reset(&mut self) { + self.channel.request_reset() } /// Return whether this transfer is still running. @@ -440,7 +459,7 @@ impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { impl<'a, const ITEM_COUNT: usize> Drop for LinkedListTransfer<'a, ITEM_COUNT> { fn drop(&mut self) { - self.request_stop(); + self.request_suspend(); while self.is_running() {} // "Subsequent reads and writes cannot be moved ahead of preceding reads." @@ -589,21 +608,26 @@ impl<'a> Transfer<'a> { Self { channel } } - /// Request the transfer to stop. - /// The configuration for this channel will **not be preserved**. If you need to restart the transfer - /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. + /// Request the transfer to suspend. + /// + /// To resume the transfer, call [`request_resume`](Self::request_resume) again. /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_stop(&mut self) { - self.channel.request_stop() + pub fn request_suspend(&mut self) { + self.channel.request_suspend() } - /// Request the transfer to pause, keeping the existing configuration for this channel. - /// To restart the transfer, call [`start`](Self::start) again. + /// Request the transfer to resume after being suspended. + pub fn request_resume(&mut self) { + self.channel.request_resume() + } + + /// Request the DMA to reset. /// - /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_pause(&mut self) { - self.channel.request_pause() + /// The configuration for this channel will **not be preserved**. If you need to restart the transfer + /// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead. + pub fn request_reset(&mut self) { + self.channel.request_reset() } /// Return whether this transfer is still running. @@ -633,7 +657,7 @@ impl<'a> Transfer<'a> { impl<'a> Drop for Transfer<'a> { fn drop(&mut self) { - self.request_stop(); + self.request_suspend(); while self.is_running() {} // "Subsequent reads and writes cannot be moved ahead of preceding reads." diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 87c482bfb..4532bda57 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -139,21 +139,26 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); } - /// Request the DMA to stop. - /// The configuration for this channel will **not be preserved**. If you need to restart the transfer - /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. + /// Request the DMA to suspend. + /// + /// To resume the transfer, call [`request_resume`](Self::request_resume) again. /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_stop(&mut self) { - self.channel.request_stop() + pub fn request_suspend(&mut self) { + self.channel.request_suspend() + } + + /// Request the DMA to resume transfers after being suspended. + pub fn request_resume(&mut self) { + self.channel.request_resume() } - /// Request the transfer to pause, keeping the existing configuration for this channel. - /// To restart the transfer, call [`start`](Self::start) again. + /// Request the DMA to reset. /// - /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_pause(&mut self) { - self.channel.request_pause() + /// The configuration for this channel will **not be preserved**. If you need to restart the transfer + /// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead. + pub fn request_reset(&mut self) { + self.channel.request_reset() } /// Return whether DMA is still running. @@ -185,7 +190,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { fn drop(&mut self) { - self.request_stop(); + self.request_suspend(); while self.is_running() {} // "Subsequent reads and writes cannot be moved ahead of preceding reads." @@ -285,21 +290,26 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); } - /// Request the DMA to stop. - /// The configuration for this channel will **not be preserved**. If you need to restart the transfer - /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. + /// Request the DMA to suspend. + /// + /// To resume the transfer, call [`request_resume`](Self::request_resume) again. /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_stop(&mut self) { - self.channel.request_stop() + pub fn request_suspend(&mut self) { + self.channel.request_suspend() + } + + /// Request the DMA to resume transfers after being suspended. + pub fn request_resume(&mut self) { + self.channel.request_resume() } - /// Request the transfer to pause, keeping the existing configuration for this channel. - /// To restart the transfer, call [`start`](Self::start) again. + /// Request the DMA to reset. /// - /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_pause(&mut self) { - self.channel.request_pause() + /// The configuration for this channel will **not be preserved**. If you need to restart the transfer + /// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead. + pub fn request_reset(&mut self) { + self.channel.request_reset() } /// Return whether DMA is still running. @@ -331,7 +341,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { fn drop(&mut self) { - self.request_stop(); + self.request_suspend(); while self.is_running() {} // "Subsequent reads and writes cannot be moved ahead of preceding reads." diff --git a/embassy-stm32/src/ucpd.rs b/embassy-stm32/src/ucpd.rs index 0a80adb8f..967e43a8a 100644 --- a/embassy-stm32/src/ucpd.rs +++ b/embassy-stm32/src/ucpd.rs @@ -490,14 +490,14 @@ impl<'d, T: Instance> PdPhy<'d, T> { let sr = r.sr().read(); if sr.rxhrstdet() { - dma.request_stop(); + dma.request_suspend(); // Clean and re-enable hard reset receive interrupt. r.icr().write(|w| w.set_rxhrstdetcf(true)); r.imr().modify(|w| w.set_rxhrstdetie(true)); Poll::Ready(Err(RxError::HardReset)) } else if sr.rxmsgend() { - dma.request_stop(); + dma.request_suspend(); // Should be read immediately on interrupt. rxpaysz = r.rx_payszr().read().rxpaysz().into(); diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index 5f4e87834..bea56c991 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs @@ -165,7 +165,7 @@ impl<'d> RingBufferedUartRx<'d> { /// Stop DMA backed UART receiver fn stop_uart(&mut self) { - self.ring_buf.request_pause(); + self.ring_buf.request_suspend(); let r = self.info.regs; // clear all interrupts and DMA Rx Request -- cgit From c0b8e9c7e5002a424e9ade711b085c2451a58b97 Mon Sep 17 00:00:00 2001 From: etiennecollin Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: writing reserved bits --- embassy-stm32/src/dma/gpdma/mod.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index d06eac60e..7c05715ee 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -237,7 +237,16 @@ impl AnyChannel { fence(Ordering::SeqCst); ch.cr().write(|w| w.set_reset(true)); - ch.fcr().write(|w| w.0 = 0xFFFF_FFFF); // clear all irqs + ch.fcr().write(|w| { + // Clear all irqs + w.set_dtef(true); + w.set_htf(true); + w.set_suspf(true); + w.set_tcf(true); + w.set_tof(true); + w.set_ulef(true); + w.set_usef(true); + }); ch.llr().write(|_| {}); // no linked list ch.tr1().write(|w| { w.set_sdw(data_size.into()); @@ -294,7 +303,16 @@ impl AnyChannel { fence(Ordering::SeqCst); ch.cr().write(|w| w.set_reset(true)); - ch.fcr().write(|w| w.0 = 0xFFFF_FFFF); // clear all irqs + ch.fcr().write(|w| { + // Clear all irqs + w.set_dtef(true); + w.set_htf(true); + w.set_suspf(true); + w.set_tcf(true); + w.set_tof(true); + w.set_ulef(true); + w.set_usef(true); + }); ch.lbar().write(|reg| reg.set_lba(table.base_address())); // Empty LLI0. -- cgit From 277c59857bc577e8565c920861feb5b6721ac9ae Mon Sep 17 00:00:00 2001 From: etiennecollin Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: feat: custom DMA channel configuration See https://github.com/embassy-rs/embassy/pull/3923#issuecomment-2888810087 The default configuration of the channel which was done in `start()` is now done in `new()` this allows overriding some settings through the new `get_dma_channel` function. Only ringbuffers support this; `LinkedListTransfer` and `Transfer` do not support that yet. --- embassy-stm32/src/dma/gpdma/mod.rs | 5 +++++ embassy-stm32/src/dma/gpdma/ringbuffered.rs | 28 ++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index 7c05715ee..752b39416 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -352,6 +352,11 @@ impl AnyChannel { .store(table.transfer_count(), Ordering::Relaxed) } + fn get_dma_channel(&self) -> pac::gpdma::Channel { + let info = self.info(); + info.dma.ch(info.num) + } + fn start(&self) { let info = self.info(); let ch = info.dma.ch(info.num); diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 4532bda57..66c4b74ec 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -77,6 +77,9 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { ]; let table = Table::new(items); + // Apply the default configuration to the channel. + unsafe { channel.configure_linked_list(&table, Default::default()) }; + Self { channel, ringbuf: ReadableDmaRingBuffer::new(buffer), @@ -85,14 +88,19 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { } /// Start the ring buffer operation. - /// - /// You must call this after creating it for it to work. pub fn start(&mut self) { - unsafe { self.channel.configure_linked_list(&self.table, Default::default()) }; self.table.link(RunMode::Circular); self.channel.start(); } + /// Get a handle to the GPDMA channel for configuring the DMA. + /// + /// Usually, **this is not needed** as a default configuration is already + /// applied, but it may be useful to setup trigger sources, etc. + pub fn get_dma_channel(&mut self) -> stm32_metapac::gpdma::Channel { + self.channel.get_dma_channel() + } + /// Clear all data in the ring buffer. pub fn clear(&mut self) { self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow())); @@ -226,6 +234,9 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { ]; let table = Table::new(items); + // Apply the default configuration to the channel. + unsafe { channel.configure_linked_list(&table, Default::default()) }; + let this = Self { channel, ringbuf: WritableDmaRingBuffer::new(buffer), @@ -236,14 +247,19 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { } /// Start the ring buffer operation. - /// - /// You must call this after creating it for it to work. pub fn start(&mut self) { - unsafe { self.channel.configure_linked_list(&self.table, Default::default()) }; self.table.link(RunMode::Circular); self.channel.start(); } + /// Get a handle to the GPDMA channel for configuring the DMA. + /// + /// Usually, **this is not needed** as a default configuration is already + /// applied, but it may be useful to setup trigger sources, etc. + pub fn get_dma_channel(&mut self) -> stm32_metapac::gpdma::Channel { + self.channel.get_dma_channel() + } + /// Clear all data in the ring buffer. pub fn clear(&mut self) { self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow())); -- cgit From 49990691985c8814500bf518bdec446bb85587e3 Mon Sep 17 00:00:00 2001 From: etiennecollin Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: feat: use provided TransferOptions instead of defaults --- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 66c4b74ec..c74c7bd2b 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -63,7 +63,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { request: Request, peri_addr: *mut W, buffer: &'a mut [W], - _options: TransferOptions, + options: TransferOptions, ) -> Self { let channel: Peri<'a, AnyChannel> = channel.into(); @@ -78,7 +78,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { let table = Table::new(items); // Apply the default configuration to the channel. - unsafe { channel.configure_linked_list(&table, Default::default()) }; + unsafe { channel.configure_linked_list(&table, options) }; Self { channel, @@ -220,7 +220,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { request: Request, peri_addr: *mut W, buffer: &'a mut [W], - _options: TransferOptions, + options: TransferOptions, ) -> Self { let channel: Peri<'a, AnyChannel> = channel.into(); @@ -235,7 +235,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { let table = Table::new(items); // Apply the default configuration to the channel. - unsafe { channel.configure_linked_list(&table, Default::default()) }; + unsafe { channel.configure_linked_list(&table, options) }; let this = Self { channel, -- cgit From f67365a067634b62747c819253fb461624c29568 Mon Sep 17 00:00:00 2001 From: etiennecollin Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: suspend before reset This follows the procedure outlined in the STM32U5 reference manual at page 696. --- embassy-stm32/src/dma/gpdma/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index 752b39416..604db2852 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -382,6 +382,9 @@ impl AnyChannel { let info = self.info(); let ch = info.dma.ch(info.num); + self.request_suspend(); + while self.is_running() {} + ch.cr().modify(|w| w.set_reset(true)); } -- cgit From 2f24568de08e846d4bfafff90a5b9ba352d86431 Mon Sep 17 00:00:00 2001 From: etiennecollin Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: feat: custom dma configuration using RegisterUpdaters struct See this PR comment: https://github.com/embassy-rs/embassy/pull/3923#issuecomment-2889283939 --- embassy-stm32/src/dma/gpdma/linked_list.rs | 20 ++++++++++++++++++-- embassy-stm32/src/dma/gpdma/mod.rs | 22 ++++++++++++++++++++++ embassy-stm32/src/dma/gpdma/ringbuffered.rs | 16 +++++++++++----- embassy-stm32/src/sai/mod.rs | 5 +++-- embassy-stm32/src/usart/ringbuffered.rs | 3 ++- 5 files changed, 56 insertions(+), 10 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/linked_list.rs b/embassy-stm32/src/dma/gpdma/linked_list.rs index a95e5590e..76381def3 100644 --- a/embassy-stm32/src/dma/gpdma/linked_list.rs +++ b/embassy-stm32/src/dma/gpdma/linked_list.rs @@ -4,6 +4,7 @@ use stm32_metapac::gpdma::regs; use stm32_metapac::gpdma::vals::Dreq; +use super::RegisterUpdaters; use crate::dma::word::{Word, WordSize}; use crate::dma::{Dir, Request}; @@ -41,7 +42,12 @@ pub struct LinearItem { impl LinearItem { /// Create a new read DMA transfer (peripheral to memory). - pub unsafe fn new_read<'d, W: Word>(request: Request, peri_addr: *mut W, buf: &'d mut [W]) -> Self { + pub unsafe fn new_read<'d, W: Word>( + request: Request, + peri_addr: *mut W, + buf: &'d mut [W], + register_updaters: &RegisterUpdaters, + ) -> Self { Self::new_inner( request, Dir::PeripheralToMemory, @@ -51,11 +57,17 @@ impl LinearItem { true, W::size(), W::size(), + register_updaters, ) } /// Create a new write DMA transfer (memory to peripheral). - pub unsafe fn new_write<'d, MW: Word, PW: Word>(request: Request, buf: &'d [MW], peri_addr: *mut PW) -> Self { + pub unsafe fn new_write<'d, MW: Word, PW: Word>( + request: Request, + buf: &'d [MW], + peri_addr: *mut PW, + register_updaters: &RegisterUpdaters, + ) -> Self { Self::new_inner( request, Dir::MemoryToPeripheral, @@ -65,6 +77,7 @@ impl LinearItem { true, MW::size(), PW::size(), + register_updaters, ) } @@ -77,6 +90,7 @@ impl LinearItem { incr_mem: bool, data_size: WordSize, dst_size: WordSize, + register_updaters: &RegisterUpdaters, ) -> Self { // BNDT is specified as bytes, not as number of transfers. let Ok(bndt) = (mem_len * data_size.bytes()).try_into() else { @@ -91,6 +105,7 @@ impl LinearItem { tr1.set_ddw(dst_size.into()); tr1.set_sinc(dir == Dir::MemoryToPeripheral && incr_mem); tr1.set_dinc(dir == Dir::PeripheralToMemory && incr_mem); + (register_updaters.tr1)(&mut tr1); let mut tr2 = regs::ChTr2(0); tr2.set_dreq(match dir { @@ -98,6 +113,7 @@ impl LinearItem { Dir::PeripheralToMemory => Dreq::SOURCE_PERIPHERAL, }); tr2.set_reqsel(request); + (register_updaters.tr2)(&mut tr2); let (sar, dar) = match dir { Dir::MemoryToPeripheral => (mem_addr as _, peri_addr as _), diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index 604db2852..58f93ffb0 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -73,6 +73,28 @@ impl Default for TransferOptions { } } +/// GPDMA linked-list item register updater functions. +#[derive(Debug, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct RegisterUpdaters { + /// Function used to overwrite transfer register 1. + pub tr1: fn(&mut pac::gpdma::regs::ChTr1), + /// Function used to overwrite transfer register 2. + pub tr2: fn(&mut pac::gpdma::regs::ChTr2), + /// Function used to overwrite transfer register 3. + pub tr3: fn(&mut pac::gpdma::regs::ChTr3), +} + +impl Default for RegisterUpdaters { + fn default() -> Self { + Self { + tr1: |_| {}, + tr2: |_| {}, + tr3: |_| {}, + } + } +} + impl From for vals::Dw { fn from(raw: WordSize) -> Self { match raw { diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index c74c7bd2b..dfc031627 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -8,7 +8,7 @@ use core::task::Waker; use embassy_hal_internal::Peri; -use super::{AnyChannel, TransferOptions, STATE}; +use super::{AnyChannel, RegisterUpdaters, TransferOptions, STATE}; use crate::dma::gpdma::linked_list::{LinearItem, RunMode, Table}; use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; use crate::dma::word::Word; @@ -52,6 +52,7 @@ pub struct ReadableRingBuffer<'a, W: Word> { channel: Peri<'a, AnyChannel>, ringbuf: ReadableDmaRingBuffer<'a, W>, table: Table<2>, + options: TransferOptions, } impl<'a, W: Word> ReadableRingBuffer<'a, W> { @@ -64,6 +65,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { peri_addr: *mut W, buffer: &'a mut [W], options: TransferOptions, + register_updaters: RegisterUpdaters, ) -> Self { let channel: Peri<'a, AnyChannel> = channel.into(); @@ -72,8 +74,8 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { assert_eq!(half_len * 2, buffer.len()); let items = [ - LinearItem::new_read(request, peri_addr, &mut buffer[..half_len]), - LinearItem::new_read(request, peri_addr, &mut buffer[half_len..]), + LinearItem::new_read(request, peri_addr, &mut buffer[..half_len], ®ister_updaters), + LinearItem::new_read(request, peri_addr, &mut buffer[half_len..], ®ister_updaters), ]; let table = Table::new(items); @@ -84,6 +86,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { channel, ringbuf: ReadableDmaRingBuffer::new(buffer), table, + options, } } @@ -211,6 +214,7 @@ pub struct WritableRingBuffer<'a, W: Word> { channel: Peri<'a, AnyChannel>, ringbuf: WritableDmaRingBuffer<'a, W>, table: Table<2>, + options: TransferOptions, } impl<'a, W: Word> WritableRingBuffer<'a, W> { @@ -221,6 +225,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { peri_addr: *mut W, buffer: &'a mut [W], options: TransferOptions, + register_updaters: RegisterUpdaters, ) -> Self { let channel: Peri<'a, AnyChannel> = channel.into(); @@ -229,8 +234,8 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { assert_eq!(half_len * 2, buffer.len()); let items = [ - LinearItem::new_write(request, &mut buffer[..half_len], peri_addr), - LinearItem::new_write(request, &mut buffer[half_len..], peri_addr), + LinearItem::new_write(request, &mut buffer[..half_len], peri_addr, ®ister_updaters), + LinearItem::new_write(request, &mut buffer[half_len..], peri_addr, ®ister_updaters), ]; let table = Table::new(items); @@ -241,6 +246,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { channel, ringbuf: WritableDmaRingBuffer::new(buffer), table, + options, }; this diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 88cc225dd..ac1ab2505 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -687,12 +687,13 @@ fn get_ring_buffer<'d, T: Instance, W: word::Word>( //the new_write() and new_read() always use circular mode ..Default::default() }; + let updaters = Default::default(); match tx_rx { TxRx::Transmitter => RingBuffer::Writable(unsafe { - WritableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts) + WritableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts, updaters) }), TxRx::Receiver => RingBuffer::Readable(unsafe { - ReadableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts) + ReadableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts, updaters) }), } } diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index bea56c991..78bf4b72f 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs @@ -103,6 +103,7 @@ impl<'d> UartRx<'d, Async> { assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); let opts = Default::default(); + let updaters = Default::default(); // Safety: we forget the struct before this function returns. let rx_dma = self.rx_dma.as_mut().unwrap(); @@ -112,7 +113,7 @@ impl<'d> UartRx<'d, Async> { let info = self.info; let state = self.state; let kernel_clock = self.kernel_clock; - let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(info.regs), dma_buf, opts) }; + let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(info.regs), dma_buf, opts, updaters) }; let rx = unsafe { self.rx.as_ref().map(|x| x.clone_unchecked()) }; let rts = unsafe { self.rts.as_ref().map(|x| x.clone_unchecked()) }; -- cgit From a2daa9739f375301425a4581601b65470ba5f459 Mon Sep 17 00:00:00 2001 From: etiennecollin Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: removed functions exposing channel registers These functions could be used to cause UB. --- embassy-stm32/src/dma/gpdma/mod.rs | 5 ----- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 16 ---------------- 2 files changed, 21 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index 58f93ffb0..4893fed94 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -374,11 +374,6 @@ impl AnyChannel { .store(table.transfer_count(), Ordering::Relaxed) } - fn get_dma_channel(&self) -> pac::gpdma::Channel { - let info = self.info(); - info.dma.ch(info.num) - } - fn start(&self) { let info = self.info(); let ch = info.dma.ch(info.num); diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index dfc031627..3a7ceb292 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -96,14 +96,6 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { self.channel.start(); } - /// Get a handle to the GPDMA channel for configuring the DMA. - /// - /// Usually, **this is not needed** as a default configuration is already - /// applied, but it may be useful to setup trigger sources, etc. - pub fn get_dma_channel(&mut self) -> stm32_metapac::gpdma::Channel { - self.channel.get_dma_channel() - } - /// Clear all data in the ring buffer. pub fn clear(&mut self) { self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow())); @@ -258,14 +250,6 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { self.channel.start(); } - /// Get a handle to the GPDMA channel for configuring the DMA. - /// - /// Usually, **this is not needed** as a default configuration is already - /// applied, but it may be useful to setup trigger sources, etc. - pub fn get_dma_channel(&mut self) -> stm32_metapac::gpdma::Channel { - self.channel.get_dma_channel() - } - /// Clear all data in the ring buffer. pub fn clear(&mut self) { self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow())); -- cgit From 4291a092bedb0f45d236a1847a9b85fd093d3af9 Mon Sep 17 00:00:00 2001 From: etiennecollin Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: moved channel configuration from new() to start() See this PR comment explaining why configuration in `new()` is a bad idea: https://github.com/embassy-rs/embassy/pull/3923#issuecomment-2889193736 --- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 3a7ceb292..359bc83b3 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -79,9 +79,6 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { ]; let table = Table::new(items); - // Apply the default configuration to the channel. - unsafe { channel.configure_linked_list(&table, options) }; - Self { channel, ringbuf: ReadableDmaRingBuffer::new(buffer), @@ -92,6 +89,8 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { /// Start the ring buffer operation. pub fn start(&mut self) { + // Apply the default configuration to the channel. + unsafe { self.channel.configure_linked_list(&self.table, self.options) }; self.table.link(RunMode::Circular); self.channel.start(); } @@ -231,9 +230,6 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { ]; let table = Table::new(items); - // Apply the default configuration to the channel. - unsafe { channel.configure_linked_list(&table, options) }; - let this = Self { channel, ringbuf: WritableDmaRingBuffer::new(buffer), @@ -246,6 +242,8 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { /// Start the ring buffer operation. pub fn start(&mut self) { + // Apply the default configuration to the channel. + unsafe { self.channel.configure_linked_list(&self.table, self.options) }; self.table.link(RunMode::Circular); self.channel.start(); } -- cgit From 50e2e2ec60ca32a2da53b91f4a30c3a71d4e9f30 Mon Sep 17 00:00:00 2001 From: etiennecollin Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: feat: add new_with_table() initializer for ring-buffers and removal of RegisterUpdaters - It is now possible to pass a linked-list table to the ring-buffer with the `new_with_table()` function or use the `new()` function for a basic ring-buffer setup. - A `simple_ring_buffer_table()` function was added to the read and write ring-buffers to generate the same table as the one created by `new()` in case the user only wants to customize the default table options. - RegisterUpdaters have been removed as the user now has direct access to the table and its items if needed. See: https://github.com/elagil/embassy/pull/1#issuecomment-2891997294 --- embassy-stm32/src/dma/gpdma/linked_list.rs | 21 +----- embassy-stm32/src/dma/gpdma/mod.rs | 22 ------ embassy-stm32/src/dma/gpdma/ringbuffered.rs | 112 ++++++++++++++++++++-------- embassy-stm32/src/sai/mod.rs | 9 +-- embassy-stm32/src/usart/ringbuffered.rs | 5 +- 5 files changed, 90 insertions(+), 79 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/linked_list.rs b/embassy-stm32/src/dma/gpdma/linked_list.rs index 76381def3..ca2d4fb7f 100644 --- a/embassy-stm32/src/dma/gpdma/linked_list.rs +++ b/embassy-stm32/src/dma/gpdma/linked_list.rs @@ -4,7 +4,6 @@ use stm32_metapac::gpdma::regs; use stm32_metapac::gpdma::vals::Dreq; -use super::RegisterUpdaters; use crate::dma::word::{Word, WordSize}; use crate::dma::{Dir, Request}; @@ -23,7 +22,6 @@ pub enum RunMode { /// /// Also works for 2D-capable GPDMA channels, but does not use 2D capabilities. #[derive(Debug, Copy, Clone, Default)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(C)] pub struct LinearItem { /// Transfer register 1. @@ -42,12 +40,7 @@ pub struct LinearItem { impl LinearItem { /// Create a new read DMA transfer (peripheral to memory). - pub unsafe fn new_read<'d, W: Word>( - request: Request, - peri_addr: *mut W, - buf: &'d mut [W], - register_updaters: &RegisterUpdaters, - ) -> Self { + pub unsafe fn new_read<'d, W: Word>(request: Request, peri_addr: *mut W, buf: &'d mut [W]) -> Self { Self::new_inner( request, Dir::PeripheralToMemory, @@ -57,17 +50,11 @@ impl LinearItem { true, W::size(), W::size(), - register_updaters, ) } /// Create a new write DMA transfer (memory to peripheral). - pub unsafe fn new_write<'d, MW: Word, PW: Word>( - request: Request, - buf: &'d [MW], - peri_addr: *mut PW, - register_updaters: &RegisterUpdaters, - ) -> Self { + pub unsafe fn new_write<'d, MW: Word, PW: Word>(request: Request, buf: &'d [MW], peri_addr: *mut PW) -> Self { Self::new_inner( request, Dir::MemoryToPeripheral, @@ -77,7 +64,6 @@ impl LinearItem { true, MW::size(), PW::size(), - register_updaters, ) } @@ -90,7 +76,6 @@ impl LinearItem { incr_mem: bool, data_size: WordSize, dst_size: WordSize, - register_updaters: &RegisterUpdaters, ) -> Self { // BNDT is specified as bytes, not as number of transfers. let Ok(bndt) = (mem_len * data_size.bytes()).try_into() else { @@ -105,7 +90,6 @@ impl LinearItem { tr1.set_ddw(dst_size.into()); tr1.set_sinc(dir == Dir::MemoryToPeripheral && incr_mem); tr1.set_dinc(dir == Dir::PeripheralToMemory && incr_mem); - (register_updaters.tr1)(&mut tr1); let mut tr2 = regs::ChTr2(0); tr2.set_dreq(match dir { @@ -113,7 +97,6 @@ impl LinearItem { Dir::PeripheralToMemory => Dreq::SOURCE_PERIPHERAL, }); tr2.set_reqsel(request); - (register_updaters.tr2)(&mut tr2); let (sar, dar) = match dir { Dir::MemoryToPeripheral => (mem_addr as _, peri_addr as _), diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index 4893fed94..074447148 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -73,28 +73,6 @@ impl Default for TransferOptions { } } -/// GPDMA linked-list item register updater functions. -#[derive(Debug, Copy, Clone)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct RegisterUpdaters { - /// Function used to overwrite transfer register 1. - pub tr1: fn(&mut pac::gpdma::regs::ChTr1), - /// Function used to overwrite transfer register 2. - pub tr2: fn(&mut pac::gpdma::regs::ChTr2), - /// Function used to overwrite transfer register 3. - pub tr3: fn(&mut pac::gpdma::regs::ChTr3), -} - -impl Default for RegisterUpdaters { - fn default() -> Self { - Self { - tr1: |_| {}, - tr2: |_| {}, - tr3: |_| {}, - } - } -} - impl From for vals::Dw { fn from(raw: WordSize) -> Self { match raw { diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 359bc83b3..d7451285e 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -8,7 +8,7 @@ use core::task::Waker; use embassy_hal_internal::Peri; -use super::{AnyChannel, RegisterUpdaters, TransferOptions, STATE}; +use super::{AnyChannel, TransferOptions, STATE}; use crate::dma::gpdma::linked_list::{LinearItem, RunMode, Table}; use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; use crate::dma::word::Word; @@ -48,14 +48,14 @@ impl<'a> DmaCtrl for DmaCtrlImpl<'a> { } /// Ringbuffer for receiving data using GPDMA linked-list mode. -pub struct ReadableRingBuffer<'a, W: Word> { +pub struct ReadableRingBuffer<'a, W: Word, const L: usize> { channel: Peri<'a, AnyChannel>, ringbuf: ReadableDmaRingBuffer<'a, W>, - table: Table<2>, + table: Table, options: TransferOptions, } -impl<'a, W: Word> ReadableRingBuffer<'a, W> { +impl<'a, W: Word> ReadableRingBuffer<'a, W, 2> { /// Create a new ring buffer. /// /// Transfer options are applied to the individual linked list items. @@ -65,19 +65,30 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { peri_addr: *mut W, buffer: &'a mut [W], options: TransferOptions, - register_updaters: RegisterUpdaters, ) -> Self { let channel: Peri<'a, AnyChannel> = channel.into(); + let table = Self::simple_ring_buffer_table(request, peri_addr, buffer); - // Buffer halves should be the same length. - let half_len = buffer.len() / 2; - assert_eq!(half_len * 2, buffer.len()); + Self { + channel, + ringbuf: ReadableDmaRingBuffer::new(buffer), + table, + options, + } + } +} - let items = [ - LinearItem::new_read(request, peri_addr, &mut buffer[..half_len], ®ister_updaters), - LinearItem::new_read(request, peri_addr, &mut buffer[half_len..], ®ister_updaters), - ]; - let table = Table::new(items); +impl<'a, W: Word, const L: usize> ReadableRingBuffer<'a, W, L> { + /// Create a new ring buffer with a provided linked-list table. + /// + /// Transfer options are applied to the individual linked list items. + pub fn new_with_table( + channel: Peri<'a, impl Channel>, + buffer: &'a mut [W], + options: TransferOptions, + table: Table, + ) -> Self { + let channel: Peri<'a, AnyChannel> = channel.into(); Self { channel, @@ -87,6 +98,21 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { } } + /// Create a new simple linked-list table. + /// + /// This uses two linked-list items, one for each half of the buffer. + pub unsafe fn simple_ring_buffer_table(request: Request, peri_addr: *mut W, buffer: &mut [W]) -> Table<2> { + // Buffer halves should be the same length. + let half_len = buffer.len() / 2; + assert_eq!(half_len * 2, buffer.len()); + + let items = [ + LinearItem::new_read(request, peri_addr, &mut buffer[..half_len]), + LinearItem::new_read(request, peri_addr, &mut buffer[half_len..]), + ]; + Table::new(items) + } + /// Start the ring buffer operation. pub fn start(&mut self) { // Apply the default configuration to the channel. @@ -190,7 +216,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { } } -impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { +impl<'a, W: Word, const L: usize> Drop for ReadableRingBuffer<'a, W, L> { fn drop(&mut self) { self.request_suspend(); while self.is_running() {} @@ -201,43 +227,69 @@ impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { } /// Ringbuffer for writing data using GPDMA linked-list mode. -pub struct WritableRingBuffer<'a, W: Word> { +pub struct WritableRingBuffer<'a, W: Word, const L: usize> { channel: Peri<'a, AnyChannel>, ringbuf: WritableDmaRingBuffer<'a, W>, - table: Table<2>, + table: Table, options: TransferOptions, } -impl<'a, W: Word> WritableRingBuffer<'a, W> { +impl<'a, W: Word> WritableRingBuffer<'a, W, 2> { /// Create a new ring buffer. + /// + /// Transfer options are applied to the individual linked list items. pub unsafe fn new( channel: Peri<'a, impl Channel>, request: Request, peri_addr: *mut W, buffer: &'a mut [W], options: TransferOptions, - register_updaters: RegisterUpdaters, ) -> Self { let channel: Peri<'a, AnyChannel> = channel.into(); + let table = Self::simple_ring_buffer_table(request, peri_addr, buffer); - // Buffer halves should be the same length. - let half_len = buffer.len() / 2; - assert_eq!(half_len * 2, buffer.len()); + Self { + channel, + ringbuf: WritableDmaRingBuffer::new(buffer), + table, + options, + } + } +} - let items = [ - LinearItem::new_write(request, &mut buffer[..half_len], peri_addr, ®ister_updaters), - LinearItem::new_write(request, &mut buffer[half_len..], peri_addr, ®ister_updaters), - ]; - let table = Table::new(items); +impl<'a, W: Word, const L: usize> WritableRingBuffer<'a, W, L> { + /// Create a new ring buffer with a provided linked-list table. + /// + /// Transfer options are applied to the individual linked list items. + pub fn new_with_table( + channel: Peri<'a, impl Channel>, + buffer: &'a mut [W], + options: TransferOptions, + table: Table, + ) -> Self { + let channel: Peri<'a, AnyChannel> = channel.into(); - let this = Self { + Self { channel, ringbuf: WritableDmaRingBuffer::new(buffer), table, options, - }; + } + } - this + /// Create a new simple linked-list table. + /// + /// This uses two linked-list items, one for each half of the buffer. + pub unsafe fn simple_ring_buffer_table(request: Request, peri_addr: *mut W, buffer: &mut [W]) -> Table<2> { + // Buffer halves should be the same length. + let half_len = buffer.len() / 2; + assert_eq!(half_len * 2, buffer.len()); + + let items = [ + LinearItem::new_write(request, &mut buffer[..half_len], peri_addr), + LinearItem::new_write(request, &mut buffer[half_len..], peri_addr), + ]; + Table::new(items) } /// Start the ring buffer operation. @@ -343,7 +395,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { } } -impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { +impl<'a, W: Word, const L: usize> Drop for WritableRingBuffer<'a, W, L> { fn drop(&mut self) { self.request_suspend(); while self.is_running() {} diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index ac1ab2505..410b2243c 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -650,8 +650,8 @@ impl Config { } enum RingBuffer<'d, W: word::Word> { - Writable(WritableRingBuffer<'d, W>), - Readable(ReadableRingBuffer<'d, W>), + Writable(WritableRingBuffer<'d, W, 2>), + Readable(ReadableRingBuffer<'d, W, 2>), } fn dr(w: crate::pac::sai::Sai, sub_block: WhichSubBlock) -> *mut W { @@ -687,13 +687,12 @@ fn get_ring_buffer<'d, T: Instance, W: word::Word>( //the new_write() and new_read() always use circular mode ..Default::default() }; - let updaters = Default::default(); match tx_rx { TxRx::Transmitter => RingBuffer::Writable(unsafe { - WritableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts, updaters) + WritableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts) }), TxRx::Receiver => RingBuffer::Readable(unsafe { - ReadableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts, updaters) + ReadableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts) }), } } diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index 78bf4b72f..8a607a31a 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs @@ -83,7 +83,7 @@ pub struct RingBufferedUartRx<'d> { kernel_clock: Hertz, rx: Option>, rts: Option>, - ring_buf: ReadableRingBuffer<'d, u8>, + ring_buf: ReadableRingBuffer<'d, u8, 2>, } impl<'d> SetConfig for RingBufferedUartRx<'d> { @@ -103,7 +103,6 @@ impl<'d> UartRx<'d, Async> { assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); let opts = Default::default(); - let updaters = Default::default(); // Safety: we forget the struct before this function returns. let rx_dma = self.rx_dma.as_mut().unwrap(); @@ -113,7 +112,7 @@ impl<'d> UartRx<'d, Async> { let info = self.info; let state = self.state; let kernel_clock = self.kernel_clock; - let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(info.regs), dma_buf, opts, updaters) }; + let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(info.regs), dma_buf, opts) }; let rx = unsafe { self.rx.as_ref().map(|x| x.clone_unchecked()) }; let rts = unsafe { self.rts.as_ref().map(|x| x.clone_unchecked()) }; -- cgit From 47bb14514f63a713600d7fa1c6cec2cbd1493591 Mon Sep 17 00:00:00 2001 From: etiennecollin Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: feat: use register wrappers instead of u32 for LinearItem Since the register structs are no-field structs with `repr(transparent)`, we can use them in the LinearItem with `repr(C)`. This allows the user to call the convenient named setter functions for the registers instead of manually changing the bits of the u32. --- embassy-stm32/src/dma/gpdma/linked_list.rs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/linked_list.rs b/embassy-stm32/src/dma/gpdma/linked_list.rs index ca2d4fb7f..f494bd5f5 100644 --- a/embassy-stm32/src/dma/gpdma/linked_list.rs +++ b/embassy-stm32/src/dma/gpdma/linked_list.rs @@ -25,17 +25,17 @@ pub enum RunMode { #[repr(C)] pub struct LinearItem { /// Transfer register 1. - pub tr1: u32, + pub tr1: regs::ChTr1, /// Transfer register 2. - pub tr2: u32, + pub tr2: regs::ChTr2, /// Block register 2. - pub br1: u32, + pub br1: regs::ChBr1, /// Source address register. pub sar: u32, /// Destination address register. pub dar: u32, /// Linked-list address register. - pub llr: u32, + pub llr: regs::ChLlr, } impl LinearItem { @@ -106,12 +106,12 @@ impl LinearItem { let llr = regs::ChLlr(0); Self { - tr1: tr1.0, - tr2: tr2.0, - br1: br1.0, + tr1, + tr2, + br1, sar, dar, - llr: llr.0, + llr, } } @@ -131,23 +131,20 @@ impl LinearItem { // Lower two bits are ignored: 32 bit aligned. llr.set_la(next >> 2); - self.llr = llr.0; + self.llr = llr; } /// Unlink the next linear item. /// /// Disables channel update bits. fn unlink(&mut self) { - self.llr = regs::ChLlr(0).0; + self.llr = regs::ChLlr(0); } /// The item's transfer count in number of words. fn transfer_count(&self) -> usize { - let br1 = regs::ChBr1(self.br1); - let tr1 = regs::ChTr1(self.tr1); - let word_size: WordSize = tr1.ddw().into(); - - br1.bndt() as usize / word_size.bytes() + let word_size: WordSize = self.tr1.ddw().into(); + self.br1.bndt() as usize / word_size.bytes() } } -- cgit From 51e7fafc3c9f5dfd432a7b4d112cd8e54092b9ef Mon Sep 17 00:00:00 2001 From: etiennecollin Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: removed unnecessary mut reference --- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index d7451285e..c98f2bb80 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -280,14 +280,14 @@ impl<'a, W: Word, const L: usize> WritableRingBuffer<'a, W, L> { /// Create a new simple linked-list table. /// /// This uses two linked-list items, one for each half of the buffer. - pub unsafe fn simple_ring_buffer_table(request: Request, peri_addr: *mut W, buffer: &mut [W]) -> Table<2> { + pub unsafe fn simple_ring_buffer_table(request: Request, peri_addr: *mut W, buffer: &[W]) -> Table<2> { // Buffer halves should be the same length. let half_len = buffer.len() / 2; assert_eq!(half_len * 2, buffer.len()); let items = [ - LinearItem::new_write(request, &mut buffer[..half_len], peri_addr), - LinearItem::new_write(request, &mut buffer[half_len..], peri_addr), + LinearItem::new_write(request, &buffer[..half_len], peri_addr), + LinearItem::new_write(request, &buffer[half_len..], peri_addr), ]; Table::new(items) } -- cgit From d3718c6d4e0a8485cdef8ecf6deb05c3eff5af08 Mon Sep 17 00:00:00 2001 From: etiennecollin Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: renamed simple table as per ST nomenclature Co-authored-by: elagil --- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index c98f2bb80..136eca1c3 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -67,7 +67,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W, 2> { options: TransferOptions, ) -> Self { let channel: Peri<'a, AnyChannel> = channel.into(); - let table = Self::simple_ring_buffer_table(request, peri_addr, buffer); + let table = Self::new_ping_pong_table(request, peri_addr, buffer); Self { channel, @@ -101,7 +101,7 @@ impl<'a, W: Word, const L: usize> ReadableRingBuffer<'a, W, L> { /// Create a new simple linked-list table. /// /// This uses two linked-list items, one for each half of the buffer. - pub unsafe fn simple_ring_buffer_table(request: Request, peri_addr: *mut W, buffer: &mut [W]) -> Table<2> { + pub unsafe fn new_ping_pong_table(request: Request, peri_addr: *mut W, buffer: &mut [W]) -> Table<2> { // Buffer halves should be the same length. let half_len = buffer.len() / 2; assert_eq!(half_len * 2, buffer.len()); @@ -246,7 +246,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W, 2> { options: TransferOptions, ) -> Self { let channel: Peri<'a, AnyChannel> = channel.into(); - let table = Self::simple_ring_buffer_table(request, peri_addr, buffer); + let table = Self::new_ping_pong_table(request, peri_addr, buffer); Self { channel, @@ -280,7 +280,7 @@ impl<'a, W: Word, const L: usize> WritableRingBuffer<'a, W, L> { /// Create a new simple linked-list table. /// /// This uses two linked-list items, one for each half of the buffer. - pub unsafe fn simple_ring_buffer_table(request: Request, peri_addr: *mut W, buffer: &[W]) -> Table<2> { + pub unsafe fn new_ping_pong_table(request: Request, peri_addr: *mut W, buffer: &[W]) -> Table<2> { // Buffer halves should be the same length. let half_len = buffer.len() / 2; assert_eq!(half_len * 2, buffer.len()); -- cgit From e9783ee28e9bdd89ffaeffb24bbff207c1ceb837 Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: build --- embassy-stm32/src/dma/gpdma/linked_list.rs | 15 +++++ embassy-stm32/src/dma/gpdma/ringbuffered.rs | 100 ++++------------------------ embassy-stm32/src/sai/mod.rs | 4 +- embassy-stm32/src/ucpd.rs | 4 +- embassy-stm32/src/usart/ringbuffered.rs | 4 +- 5 files changed, 35 insertions(+), 92 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/linked_list.rs b/embassy-stm32/src/dma/gpdma/linked_list.rs index f494bd5f5..627da0055 100644 --- a/embassy-stm32/src/dma/gpdma/linked_list.rs +++ b/embassy-stm32/src/dma/gpdma/linked_list.rs @@ -163,6 +163,21 @@ impl Table { Self { items } } + /// Create a ping-pong linked-list table. + /// + /// This uses two linked-list items, one for each half of the buffer. + pub unsafe fn new_ping_pong(request: Request, peri_addr: *mut W, buffer: &mut [W]) -> Table<2> { + // Buffer halves should be the same length. + let half_len = buffer.len() / 2; + assert_eq!(half_len * 2, buffer.len()); + + let items = [ + LinearItem::new_read(request, peri_addr, &mut buffer[..half_len]), + LinearItem::new_read(request, peri_addr, &mut buffer[half_len..]), + ]; + Table::new(items) + } + /// Link the table as given by the run mode. pub fn link(&mut self, run_mode: RunMode) { if matches!(run_mode, RunMode::Once | RunMode::Circular) { diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 136eca1c3..2f17a0587 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -9,7 +9,7 @@ use core::task::Waker; use embassy_hal_internal::Peri; use super::{AnyChannel, TransferOptions, STATE}; -use crate::dma::gpdma::linked_list::{LinearItem, RunMode, Table}; +use crate::dma::gpdma::linked_list::{RunMode, Table}; use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; use crate::dma::word::Word; use crate::dma::{Channel, Request}; @@ -48,14 +48,14 @@ impl<'a> DmaCtrl for DmaCtrlImpl<'a> { } /// Ringbuffer for receiving data using GPDMA linked-list mode. -pub struct ReadableRingBuffer<'a, W: Word, const L: usize> { +pub struct ReadableRingBuffer<'a, W: Word> { channel: Peri<'a, AnyChannel>, ringbuf: ReadableDmaRingBuffer<'a, W>, - table: Table, + table: Table<2>, options: TransferOptions, } -impl<'a, W: Word> ReadableRingBuffer<'a, W, 2> { +impl<'a, W: Word> ReadableRingBuffer<'a, W> { /// Create a new ring buffer. /// /// Transfer options are applied to the individual linked list items. @@ -67,28 +67,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W, 2> { options: TransferOptions, ) -> Self { let channel: Peri<'a, AnyChannel> = channel.into(); - let table = Self::new_ping_pong_table(request, peri_addr, buffer); - - Self { - channel, - ringbuf: ReadableDmaRingBuffer::new(buffer), - table, - options, - } - } -} - -impl<'a, W: Word, const L: usize> ReadableRingBuffer<'a, W, L> { - /// Create a new ring buffer with a provided linked-list table. - /// - /// Transfer options are applied to the individual linked list items. - pub fn new_with_table( - channel: Peri<'a, impl Channel>, - buffer: &'a mut [W], - options: TransferOptions, - table: Table, - ) -> Self { - let channel: Peri<'a, AnyChannel> = channel.into(); + let table = Table::<2>::new_ping_pong::(request, peri_addr, buffer); Self { channel, @@ -98,21 +77,6 @@ impl<'a, W: Word, const L: usize> ReadableRingBuffer<'a, W, L> { } } - /// Create a new simple linked-list table. - /// - /// This uses two linked-list items, one for each half of the buffer. - pub unsafe fn new_ping_pong_table(request: Request, peri_addr: *mut W, buffer: &mut [W]) -> Table<2> { - // Buffer halves should be the same length. - let half_len = buffer.len() / 2; - assert_eq!(half_len * 2, buffer.len()); - - let items = [ - LinearItem::new_read(request, peri_addr, &mut buffer[..half_len]), - LinearItem::new_read(request, peri_addr, &mut buffer[half_len..]), - ]; - Table::new(items) - } - /// Start the ring buffer operation. pub fn start(&mut self) { // Apply the default configuration to the channel. @@ -172,7 +136,7 @@ impl<'a, W: Word, const L: usize> ReadableRingBuffer<'a, W, L> { /// To resume the transfer, call [`request_resume`](Self::request_resume) again. /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_suspend(&mut self) { + pub fn request_pause(&mut self) { self.channel.request_suspend() } @@ -216,9 +180,9 @@ impl<'a, W: Word, const L: usize> ReadableRingBuffer<'a, W, L> { } } -impl<'a, W: Word, const L: usize> Drop for ReadableRingBuffer<'a, W, L> { +impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { fn drop(&mut self) { - self.request_suspend(); + self.request_pause(); while self.is_running() {} // "Subsequent reads and writes cannot be moved ahead of preceding reads." @@ -227,14 +191,14 @@ impl<'a, W: Word, const L: usize> Drop for ReadableRingBuffer<'a, W, L> { } /// Ringbuffer for writing data using GPDMA linked-list mode. -pub struct WritableRingBuffer<'a, W: Word, const L: usize> { +pub struct WritableRingBuffer<'a, W: Word> { channel: Peri<'a, AnyChannel>, ringbuf: WritableDmaRingBuffer<'a, W>, - table: Table, + table: Table<2>, options: TransferOptions, } -impl<'a, W: Word> WritableRingBuffer<'a, W, 2> { +impl<'a, W: Word> WritableRingBuffer<'a, W> { /// Create a new ring buffer. /// /// Transfer options are applied to the individual linked list items. @@ -246,7 +210,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W, 2> { options: TransferOptions, ) -> Self { let channel: Peri<'a, AnyChannel> = channel.into(); - let table = Self::new_ping_pong_table(request, peri_addr, buffer); + let table = Table::<2>::new_ping_pong::(request, peri_addr, buffer); Self { channel, @@ -255,42 +219,6 @@ impl<'a, W: Word> WritableRingBuffer<'a, W, 2> { options, } } -} - -impl<'a, W: Word, const L: usize> WritableRingBuffer<'a, W, L> { - /// Create a new ring buffer with a provided linked-list table. - /// - /// Transfer options are applied to the individual linked list items. - pub fn new_with_table( - channel: Peri<'a, impl Channel>, - buffer: &'a mut [W], - options: TransferOptions, - table: Table, - ) -> Self { - let channel: Peri<'a, AnyChannel> = channel.into(); - - Self { - channel, - ringbuf: WritableDmaRingBuffer::new(buffer), - table, - options, - } - } - - /// Create a new simple linked-list table. - /// - /// This uses two linked-list items, one for each half of the buffer. - pub unsafe fn new_ping_pong_table(request: Request, peri_addr: *mut W, buffer: &[W]) -> Table<2> { - // Buffer halves should be the same length. - let half_len = buffer.len() / 2; - assert_eq!(half_len * 2, buffer.len()); - - let items = [ - LinearItem::new_write(request, &buffer[..half_len], peri_addr), - LinearItem::new_write(request, &buffer[half_len..], peri_addr), - ]; - Table::new(items) - } /// Start the ring buffer operation. pub fn start(&mut self) { @@ -351,7 +279,7 @@ impl<'a, W: Word, const L: usize> WritableRingBuffer<'a, W, L> { /// To resume the transfer, call [`request_resume`](Self::request_resume) again. /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_suspend(&mut self) { + pub fn request_pause(&mut self) { self.channel.request_suspend() } @@ -395,7 +323,7 @@ impl<'a, W: Word, const L: usize> WritableRingBuffer<'a, W, L> { } } -impl<'a, W: Word, const L: usize> Drop for WritableRingBuffer<'a, W, L> { +impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { fn drop(&mut self) { self.request_suspend(); while self.is_running() {} diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 410b2243c..88cc225dd 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -650,8 +650,8 @@ impl Config { } enum RingBuffer<'d, W: word::Word> { - Writable(WritableRingBuffer<'d, W, 2>), - Readable(ReadableRingBuffer<'d, W, 2>), + Writable(WritableRingBuffer<'d, W>), + Readable(ReadableRingBuffer<'d, W>), } fn dr(w: crate::pac::sai::Sai, sub_block: WhichSubBlock) -> *mut W { diff --git a/embassy-stm32/src/ucpd.rs b/embassy-stm32/src/ucpd.rs index 967e43a8a..18aff4fbd 100644 --- a/embassy-stm32/src/ucpd.rs +++ b/embassy-stm32/src/ucpd.rs @@ -490,14 +490,14 @@ impl<'d, T: Instance> PdPhy<'d, T> { let sr = r.sr().read(); if sr.rxhrstdet() { - dma.request_suspend(); + dma.request_pause(); // Clean and re-enable hard reset receive interrupt. r.icr().write(|w| w.set_rxhrstdetcf(true)); r.imr().modify(|w| w.set_rxhrstdetie(true)); Poll::Ready(Err(RxError::HardReset)) } else if sr.rxmsgend() { - dma.request_suspend(); + dma.request_pause(); // Should be read immediately on interrupt. rxpaysz = r.rx_payszr().read().rxpaysz().into(); diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index 8a607a31a..5f4e87834 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs @@ -83,7 +83,7 @@ pub struct RingBufferedUartRx<'d> { kernel_clock: Hertz, rx: Option>, rts: Option>, - ring_buf: ReadableRingBuffer<'d, u8, 2>, + ring_buf: ReadableRingBuffer<'d, u8>, } impl<'d> SetConfig for RingBufferedUartRx<'d> { @@ -165,7 +165,7 @@ impl<'d> RingBufferedUartRx<'d> { /// Stop DMA backed UART receiver fn stop_uart(&mut self) { - self.ring_buf.request_suspend(); + self.ring_buf.request_pause(); let r = self.info.regs; // clear all interrupts and DMA Rx Request -- cgit From db7828538f43d4ebf39ca4291057bd67876bbfb3 Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: fix: consolidate naming --- embassy-stm32/src/dma/gpdma/mod.rs | 20 ++++++++++---------- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 10 +++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index 074447148..7b317d4bb 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -359,7 +359,7 @@ impl AnyChannel { ch.cr().modify(|w| w.set_en(true)); } - fn request_suspend(&self) { + fn request_pause(&self) { let info = self.info(); let ch = info.dma.ch(info.num); @@ -377,7 +377,7 @@ impl AnyChannel { let info = self.info(); let ch = info.dma.ch(info.num); - self.request_suspend(); + self.request_pause(); while self.is_running() {} ch.cr().modify(|w| w.set_reset(true)); @@ -436,8 +436,8 @@ impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { /// To resume the transfer, call [`request_resume`](Self::request_resume) again. /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_suspend(&mut self) { - self.channel.request_suspend() + pub fn request_pause(&mut self) { + self.channel.request_pause() } /// Request the transfer to resume after being suspended. @@ -448,7 +448,7 @@ impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { /// Request the DMA to reset. /// /// The configuration for this channel will **not be preserved**. If you need to restart the transfer - /// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead. + /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. pub fn request_reset(&mut self) { self.channel.request_reset() } @@ -480,7 +480,7 @@ impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { impl<'a, const ITEM_COUNT: usize> Drop for LinkedListTransfer<'a, ITEM_COUNT> { fn drop(&mut self) { - self.request_suspend(); + self.request_pause(); while self.is_running() {} // "Subsequent reads and writes cannot be moved ahead of preceding reads." @@ -634,8 +634,8 @@ impl<'a> Transfer<'a> { /// To resume the transfer, call [`request_resume`](Self::request_resume) again. /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_suspend(&mut self) { - self.channel.request_suspend() + pub fn request_pause(&mut self) { + self.channel.request_pause() } /// Request the transfer to resume after being suspended. @@ -646,7 +646,7 @@ impl<'a> Transfer<'a> { /// Request the DMA to reset. /// /// The configuration for this channel will **not be preserved**. If you need to restart the transfer - /// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead. + /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. pub fn request_reset(&mut self) { self.channel.request_reset() } @@ -678,7 +678,7 @@ impl<'a> Transfer<'a> { impl<'a> Drop for Transfer<'a> { fn drop(&mut self) { - self.request_suspend(); + self.request_pause(); while self.is_running() {} // "Subsequent reads and writes cannot be moved ahead of preceding reads." diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 2f17a0587..0f1c42a8b 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -137,7 +137,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. pub fn request_pause(&mut self) { - self.channel.request_suspend() + self.channel.request_pause() } /// Request the DMA to resume transfers after being suspended. @@ -148,7 +148,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { /// Request the DMA to reset. /// /// The configuration for this channel will **not be preserved**. If you need to restart the transfer - /// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead. + /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. pub fn request_reset(&mut self) { self.channel.request_reset() } @@ -280,7 +280,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. pub fn request_pause(&mut self) { - self.channel.request_suspend() + self.channel.request_pause() } /// Request the DMA to resume transfers after being suspended. @@ -291,7 +291,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { /// Request the DMA to reset. /// /// The configuration for this channel will **not be preserved**. If you need to restart the transfer - /// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead. + /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. pub fn request_reset(&mut self) { self.channel.request_reset() } @@ -325,7 +325,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { fn drop(&mut self) { - self.request_suspend(); + self.request_pause(); while self.is_running() {} // "Subsequent reads and writes cannot be moved ahead of preceding reads." -- cgit From 1e627cab29297be5be81d1033ca3a87b92e0c746 Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: refactor: make dma implementations match in interface --- embassy-stm32/src/dma/dma_bdma.rs | 102 ++++++++++++++++------------ embassy-stm32/src/dma/gpdma/mod.rs | 17 ++--- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 11 ++- embassy-stm32/src/i2c/v2.rs | 2 +- 4 files changed, 70 insertions(+), 62 deletions(-) diff --git a/embassy-stm32/src/dma/dma_bdma.rs b/embassy-stm32/src/dma/dma_bdma.rs index 464823bfc..73ecab070 100644 --- a/embassy-stm32/src/dma/dma_bdma.rs +++ b/embassy-stm32/src/dma/dma_bdma.rs @@ -498,46 +498,52 @@ impl AnyChannel { } } - fn request_stop(&self) { + fn request_pause(&self) { let info = self.info(); match self.info().dma { #[cfg(dma)] DmaInfo::Dma(r) => { - // Disable the channel. Keep the IEs enabled so the irqs still fire. - r.st(info.num).cr().write(|w| { - w.set_teie(true); - w.set_tcie(true); + // Disable the channel without overwriting the existing configuration + r.st(info.num).cr().modify(|w| { + w.set_en(false); }); } #[cfg(bdma)] DmaInfo::Bdma(r) => { - // Disable the channel. Keep the IEs enabled so the irqs still fire. - r.ch(info.num).cr().write(|w| { - w.set_teie(true); - w.set_tcie(true); + // Disable the channel without overwriting the existing configuration + r.ch(info.num).cr().modify(|w| { + w.set_en(false); }); } } } - fn request_pause(&self) { + fn request_resume(&self) { + self.start() + } + + fn request_reset(&self) { let info = self.info(); match self.info().dma { #[cfg(dma)] DmaInfo::Dma(r) => { - // Disable the channel without overwriting the existing configuration - r.st(info.num).cr().modify(|w| { - w.set_en(false); + // Disable the channel. Keep the IEs enabled so the irqs still fire. + r.st(info.num).cr().write(|w| { + w.set_teie(true); + w.set_tcie(true); }); } #[cfg(bdma)] DmaInfo::Bdma(r) => { - // Disable the channel without overwriting the existing configuration - r.ch(info.num).cr().modify(|w| { - w.set_en(false); + // Disable the channel. Keep the IEs enabled so the irqs still fire. + r.ch(info.num).cr().write(|w| { + w.set_teie(true); + w.set_tcie(true); }); } } + + while self.is_running() {} } fn is_running(&self) -> bool { @@ -710,27 +716,31 @@ impl<'a> Transfer<'a> { Self { channel } } - /// Request the transfer to stop. - /// The configuration for this channel will **not be preserved**. If you need to restart the transfer - /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. - /// - /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_stop(&mut self) { - self.channel.request_stop() - } - /// Request the transfer to pause, keeping the existing configuration for this channel. - /// To restart the transfer, call [`start`](Self::start) again. /// + /// To resume the transfer, call [`request_resume`](Self::request_resume) again. /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. pub fn request_pause(&mut self) { self.channel.request_pause() } + /// Request the transfer to resume after having been paused. + pub fn request_resume(&mut self) { + self.channel.request_resume() + } + + /// Request the DMA to reset. + /// + /// The configuration for this channel will **not be preserved**. If you need to restart the transfer + /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. + pub fn request_reset(&mut self) { + self.channel.request_reset() + } + /// Return whether this transfer is still running. /// /// If this returns `false`, it can be because either the transfer finished, or - /// it was requested to stop early with [`request_stop`](Self::request_stop). + /// it was requested to stop early with [`request_pause`](Self::request_pause). pub fn is_running(&mut self) -> bool { self.channel.is_running() } @@ -754,7 +764,7 @@ impl<'a> Transfer<'a> { impl<'a> Drop for Transfer<'a> { fn drop(&mut self) { - self.request_stop(); + self.request_reset(); while self.is_running() {} // "Subsequent reads and writes cannot be moved ahead of preceding reads." @@ -901,15 +911,6 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); } - /// Request the DMA to stop. - /// The configuration for this channel will **not be preserved**. If you need to restart the transfer - /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. - /// - /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_stop(&mut self) { - self.channel.request_stop() - } - /// Request the transfer to pause, keeping the existing configuration for this channel. /// To restart the transfer, call [`start`](Self::start) again. /// @@ -918,10 +919,23 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { self.channel.request_pause() } + /// Request the transfer to resume after having been paused. + pub fn request_resume(&mut self) { + self.channel.request_resume() + } + + /// Request the DMA to reset. + /// + /// The configuration for this channel will **not be preserved**. If you need to restart the transfer + /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. + pub fn request_reset(&mut self) { + self.channel.request_reset() + } + /// Return whether DMA is still running. /// /// If this returns `false`, it can be because either the transfer finished, or - /// it was requested to stop early with [`request_stop`](Self::request_stop). + /// it was requested to stop early with [`request_reset`](Self::request_reset). pub fn is_running(&mut self) -> bool { self.channel.is_running() } @@ -934,7 +948,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { /// This is designed to be used with streaming input data such as the /// I2S/SAI or ADC. /// - /// When using the UART, you probably want `request_stop()`. + /// When using the UART, you probably want `request_reset()`. pub async fn stop(&mut self) { self.channel.disable_circular_mode(); //wait until cr.susp reads as true @@ -948,7 +962,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { fn drop(&mut self) { - self.request_stop(); + self.request_reset(); while self.is_running() {} // "Subsequent reads and writes cannot be moved ahead of preceding reads." @@ -1058,8 +1072,8 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. - pub fn request_stop(&mut self) { - self.channel.request_stop() + pub fn request_reset(&mut self) { + self.channel.request_reset() } /// Request the transfer to pause, keeping the existing configuration for this channel. @@ -1073,7 +1087,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { /// Return whether DMA is still running. /// /// If this returns `false`, it can be because either the transfer finished, or - /// it was requested to stop early with [`request_stop`](Self::request_stop). + /// it was requested to stop early with [`request_reset`](Self::request_reset). pub fn is_running(&mut self) -> bool { self.channel.is_running() } @@ -1098,7 +1112,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { fn drop(&mut self) { - self.request_stop(); + self.request_reset(); while self.is_running() {} // "Subsequent reads and writes cannot be moved ahead of preceding reads." diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index 7b317d4bb..4a14c2a8e 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs @@ -431,16 +431,15 @@ impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { Self { channel } } - /// Request the transfer to suspend. + /// Request the transfer to pause, keeping the existing configuration for this channel. /// /// To resume the transfer, call [`request_resume`](Self::request_resume) again. - /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. pub fn request_pause(&mut self) { self.channel.request_pause() } - /// Request the transfer to resume after being suspended. + /// Request the transfer to resume after having been paused. pub fn request_resume(&mut self) { self.channel.request_resume() } @@ -456,7 +455,7 @@ impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { /// Return whether this transfer is still running. /// /// If this returns `false`, it can be because either the transfer finished, or - /// it was requested to stop early with [`request_stop`](Self::request_stop). + /// it was requested to stop early with [`request_pause`](Self::request_pause). pub fn is_running(&mut self) -> bool { self.channel.is_running() } @@ -480,8 +479,7 @@ impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { impl<'a, const ITEM_COUNT: usize> Drop for LinkedListTransfer<'a, ITEM_COUNT> { fn drop(&mut self) { - self.request_pause(); - while self.is_running() {} + self.request_reset(); // "Subsequent reads and writes cannot be moved ahead of preceding reads." fence(Ordering::SeqCst); @@ -629,9 +627,8 @@ impl<'a> Transfer<'a> { Self { channel } } - /// Request the transfer to suspend. - /// - /// To resume the transfer, call [`request_resume`](Self::request_resume) again. + /// Request the transfer to pause, keeping the existing configuration for this channel. + /// To restart the transfer, call [`start`](Self::start) again. /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. pub fn request_pause(&mut self) { @@ -654,7 +651,7 @@ impl<'a> Transfer<'a> { /// Return whether this transfer is still running. /// /// If this returns `false`, it can be because either the transfer finished, or - /// it was requested to stop early with [`request_stop`](Self::request_stop). + /// it was requested to stop early with [`request_pause`](Self::request_pause). pub fn is_running(&mut self) -> bool { self.channel.is_running() } diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 0f1c42a8b..55486d5cc 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -131,16 +131,15 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); } - /// Request the DMA to suspend. + /// Request the transfer to pause, keeping the existing configuration for this channel. /// /// To resume the transfer, call [`request_resume`](Self::request_resume) again. - /// /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. pub fn request_pause(&mut self) { self.channel.request_pause() } - /// Request the DMA to resume transfers after being suspended. + /// Request the transfer to resume after having been paused. pub fn request_resume(&mut self) { self.channel.request_resume() } @@ -153,10 +152,10 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { self.channel.request_reset() } - /// Return whether DMA is still running. + /// Return whether this transfer is still running. /// /// If this returns `false`, it can be because either the transfer finished, or - /// it was requested to stop early with [`request_stop`](Self::request_stop). + /// it was requested to stop early with [`request_pause`](Self::request_pause). pub fn is_running(&mut self) -> bool { self.channel.is_running() } @@ -168,8 +167,6 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { /// /// This is designed to be used with streaming input data such as the /// I2S/SAI or ADC. - /// - /// When using the UART, you probably want `request_stop()`. pub async fn stop(&mut self) { // wait until cr.susp reads as true poll_fn(|cx| { diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 6b20a601b..0bfc795ac 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -1283,7 +1283,7 @@ impl<'d> I2c<'d, Async, MultiMaster> { } else if isr.stopf() { self.info.regs.icr().write(|reg| reg.set_stopcf(true)); if remaining_len > 0 { - dma_transfer.request_stop(); + dma_transfer.request_pause(); Poll::Ready(Ok(SendStatus::LeftoverBytes(remaining_len as usize))) } else { Poll::Ready(Ok(SendStatus::Done)) -- cgit From 40eb5576824d45dfbe2a0609e69743a230475253 Mon Sep 17 00:00:00 2001 From: Adrian Figueroa Date: Mon, 25 Aug 2025 21:10:59 +0200 Subject: feat: SAI example --- examples/stm32h5/src/bin/sai.rs | 53 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 examples/stm32h5/src/bin/sai.rs diff --git a/examples/stm32h5/src/bin/sai.rs b/examples/stm32h5/src/bin/sai.rs new file mode 100644 index 000000000..086a847f7 --- /dev/null +++ b/examples/stm32h5/src/bin/sai.rs @@ -0,0 +1,53 @@ +#![no_std] +#![no_main] + +use defmt::info; +use embassy_executor::Spawner; + +use embassy_stm32::{sai, Config}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + info!("Hello world."); + + let mut config = Config::default(); + { + use embassy_stm32::rcc::*; + + config.rcc.pll2 = Some(Pll { + source: PllSource::HSI, + prediv: PllPreDiv::DIV16, + mul: PllMul::MUL32, + divp: Some(PllDiv::DIV16), // 8 MHz SAI clock + divq: None, + divr: None, + }); + + config.rcc.mux.sai1sel = mux::Saisel::PLL2_P; + } + let p = embassy_stm32::init(config); + + let mut write_buffer = [0u16; 1024]; + let (_, sai_b) = sai::split_subblocks(p.SAI1); + + let mut sai_b = sai::Sai::new_asynchronous( + sai_b, + p.PF8, + p.PE3, + p.PF9, + p.GPDMA1_CH0, + &mut write_buffer, + Default::default(), + ); + + // Populate arbitrary data. + let mut data = [0u16; 256]; + for (index, sample) in data.iter_mut().enumerate() { + *sample = index as u16; + } + + loop { + sai_b.write(&data).await.unwrap(); + } +} -- cgit From 1e54841632fc12399f9e54f54a6190c6a4b6eb7e Mon Sep 17 00:00:00 2001 From: Adrian Figueroa Date: Mon, 25 Aug 2025 21:14:16 +0200 Subject: chore: add changelog entry --- embassy-stm32/CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 4cc48ed97..8ed4dbd65 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - feat: stm32/adc/v3: allow DMA reads to loop through enable channels - fix: Fix XSPI not disabling alternate bytes when they were previously enabled - fix: Fix stm32h7rs init when using external flash via XSPI +- feat: Add GPDMA linked-list + ringbuffer support ([#3923](https://github.com/embassy-rs/embassy/pull/3923)) ## 0.3.0 - 2025-08-12 @@ -135,7 +136,7 @@ GPIO: - Refactor AfType ([#3031](https://github.com/embassy-rs/embassy/pull/3031)) - Gpiov1: Do not call set_speed for AFType::Input ([#2996](https://github.com/embassy-rs/embassy/pull/2996)) -UART: +UART: - Add embedded-io impls ([#2739](https://github.com/embassy-rs/embassy/pull/2739)) - Add support for changing baud rate ([#3512](https://github.com/embassy-rs/embassy/pull/3512)) - Add split_ref ([#3500](https://github.com/embassy-rs/embassy/pull/3500)) @@ -159,7 +160,7 @@ UART: - Wake receive task for each received byte ([#2722](https://github.com/embassy-rs/embassy/pull/2722)) - Fix dma and idle line detection in ringbuffereduartrx ([#3319](https://github.com/embassy-rs/embassy/pull/3319)) -SPI: +SPI: - Add MISO pullup configuration option ([#2943](https://github.com/embassy-rs/embassy/pull/2943)) - Add slew rate configuration options ([#3669](https://github.com/embassy-rs/embassy/pull/3669)) - Fix blocking_write on nosck spi. ([#3035](https://github.com/embassy-rs/embassy/pull/3035)) -- cgit From c487034dc707282497f4ff2450493a07f76d3027 Mon Sep 17 00:00:00 2001 From: Adrian Figueroa Date: Mon, 25 Aug 2025 21:21:54 +0200 Subject: style: formatting --- examples/stm32h5/src/bin/sai.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/stm32h5/src/bin/sai.rs b/examples/stm32h5/src/bin/sai.rs index 086a847f7..0e182f9cf 100644 --- a/examples/stm32h5/src/bin/sai.rs +++ b/examples/stm32h5/src/bin/sai.rs @@ -3,7 +3,6 @@ use defmt::info; use embassy_executor::Spawner; - use embassy_stm32::{sai, Config}; use {defmt_rtt as _, panic_probe as _}; -- cgit From 2e2562d8dc38844b9907e282f6c098e6ac2fd096 Mon Sep 17 00:00:00 2001 From: Adrian Figueroa Date: Tue, 26 Aug 2025 23:11:18 +0200 Subject: fix: ping-pong helper DMA direction --- embassy-stm32/src/dma/gpdma/linked_list.rs | 22 +++++++++++++++++----- embassy-stm32/src/dma/gpdma/ringbuffered.rs | 7 ++++--- embassy-stm32/src/dma/mod.rs | 5 ++++- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/embassy-stm32/src/dma/gpdma/linked_list.rs b/embassy-stm32/src/dma/gpdma/linked_list.rs index 627da0055..f7c1fbbed 100644 --- a/embassy-stm32/src/dma/gpdma/linked_list.rs +++ b/embassy-stm32/src/dma/gpdma/linked_list.rs @@ -166,15 +166,27 @@ impl Table { /// Create a ping-pong linked-list table. /// /// This uses two linked-list items, one for each half of the buffer. - pub unsafe fn new_ping_pong(request: Request, peri_addr: *mut W, buffer: &mut [W]) -> Table<2> { + pub unsafe fn new_ping_pong( + request: Request, + peri_addr: *mut W, + buffer: &mut [W], + direction: Dir, + ) -> Table<2> { // Buffer halves should be the same length. let half_len = buffer.len() / 2; assert_eq!(half_len * 2, buffer.len()); - let items = [ - LinearItem::new_read(request, peri_addr, &mut buffer[..half_len]), - LinearItem::new_read(request, peri_addr, &mut buffer[half_len..]), - ]; + let items = match direction { + Dir::MemoryToPeripheral => [ + LinearItem::new_write(request, &mut buffer[..half_len], peri_addr), + LinearItem::new_write(request, &mut buffer[half_len..], peri_addr), + ], + Dir::PeripheralToMemory => [ + LinearItem::new_read(request, peri_addr, &mut buffer[..half_len]), + LinearItem::new_read(request, peri_addr, &mut buffer[half_len..]), + ], + }; + Table::new(items) } diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 55486d5cc..9ee52193b 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs @@ -12,7 +12,7 @@ use super::{AnyChannel, TransferOptions, STATE}; use crate::dma::gpdma::linked_list::{RunMode, Table}; use crate::dma::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer}; use crate::dma::word::Word; -use crate::dma::{Channel, Request}; +use crate::dma::{Channel, Dir, Request}; struct DmaCtrlImpl<'a>(Peri<'a, AnyChannel>); @@ -67,7 +67,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { options: TransferOptions, ) -> Self { let channel: Peri<'a, AnyChannel> = channel.into(); - let table = Table::<2>::new_ping_pong::(request, peri_addr, buffer); + let table = Table::<2>::new_ping_pong::(request, peri_addr, buffer, Dir::PeripheralToMemory); Self { channel, @@ -207,7 +207,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { options: TransferOptions, ) -> Self { let channel: Peri<'a, AnyChannel> = channel.into(); - let table = Table::<2>::new_ping_pong::(request, peri_addr, buffer); + let table = Table::<2>::new_ping_pong::(request, peri_addr, buffer, Dir::MemoryToPeripheral); Self { channel, @@ -222,6 +222,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { // Apply the default configuration to the channel. unsafe { self.channel.configure_linked_list(&self.table, self.options) }; self.table.link(RunMode::Circular); + self.channel.start(); } diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 030f906d2..5989bfd7c 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs @@ -28,10 +28,13 @@ use embassy_hal_internal::{impl_peripheral, PeripheralType}; use crate::interrupt; +/// The direction of a DMA transfer. #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -enum Dir { +pub enum Dir { + /// Transfer from memory to a peripheral. MemoryToPeripheral, + /// Transfer from a peripheral to memory. PeripheralToMemory, } -- cgit From 286d887529c66d8d1b4c7b56849e7a95386d79db Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 5 Sep 2025 14:57:05 +0200 Subject: executor: always name main task `main`, not just with rtos-trace. Also fixes the warning about the `rtos-trace` feature not existing in embassy-executor-macros. --- embassy-executor-macros/Cargo.toml | 1 + embassy-executor-macros/src/macros/main.rs | 2 +- embassy-executor/CHANGELOG.md | 4 ++-- embassy-executor/Cargo.toml | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/embassy-executor-macros/Cargo.toml b/embassy-executor-macros/Cargo.toml index f803e6644..9c2b40d03 100644 --- a/embassy-executor-macros/Cargo.toml +++ b/embassy-executor-macros/Cargo.toml @@ -23,3 +23,4 @@ proc-macro = true [features] nightly = [] +metadata-name = [] diff --git a/embassy-executor-macros/src/macros/main.rs b/embassy-executor-macros/src/macros/main.rs index f043ff7f6..dc470e51c 100644 --- a/embassy-executor-macros/src/macros/main.rs +++ b/embassy-executor-macros/src/macros/main.rs @@ -170,7 +170,7 @@ For example: `#[embassy_executor::main(entry = ..., executor = \"some_crate::Exe let f_body = f.body; let out = &f.sig.output; - let name_main_task = if cfg!(feature = "rtos-trace") { + let name_main_task = if cfg!(feature = "metadata-name") { quote!( main_task.metadata().set_name("main\0"); ) diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index a36d270ba..dd462608b 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -8,8 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate -- Added new metadata API for tasks -- Named main task when rtos-trace feature is enabled. +- Added new metadata API for tasks. +- Main task automatically gets a name of `main` when the `metadata-name` feature is enabled. - Upgraded rtos-trace ## 0.9.1 - 2025-08-31 diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index ed72a585f..7763adbe5 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -112,7 +112,7 @@ arch-spin = ["_arch"] #! ### Metadata ## Enable the `name` field in task metadata. -metadata-name = [] +metadata-name = ["embassy-executor-macros/metadata-name"] #! ### Executor -- cgit From 60b640bd977ac2d056061e0c0b7a497f815417f4 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 25 Aug 2025 17:31:38 +0200 Subject: stm32/sai: update for new metapac, simplify cfgs. --- embassy-stm32/src/sai/mod.rs | 318 ++++++---------------------------- examples/stm32h7/src/bin/sai.rs | 72 +------- examples/stm32h723/src/bin/spdifrx.rs | 2 +- 3 files changed, 56 insertions(+), 336 deletions(-) diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 88cc225dd..ff81dabed 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -8,6 +8,7 @@ use embassy_hal_internal::PeripheralType; pub use crate::dma::word; use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed}; +pub use crate::pac::sai::vals::Mckdiv as MasterClockDivider; use crate::pac::sai::{vals, Sai as Regs}; use crate::rcc::{self, RccPeripheral}; use crate::{peripherals, Peri}; @@ -45,7 +46,6 @@ pub enum Mode { } impl Mode { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn mode(&self, tx_rx: TxRx) -> vals::Mode { match tx_rx { TxRx::Transmitter => match self { @@ -80,7 +80,6 @@ pub enum SlotSize { } impl SlotSize { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn slotsz(&self) -> vals::Slotsz { match self { SlotSize::DataSize => vals::Slotsz::DATA_SIZE, @@ -103,7 +102,6 @@ pub enum DataSize { } impl DataSize { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn ds(&self) -> vals::Ds { match self { DataSize::Data8 => vals::Ds::BIT8, @@ -128,7 +126,6 @@ pub enum FifoThreshold { } impl FifoThreshold { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn fth(&self) -> vals::Fth { match self { FifoThreshold::Empty => vals::Fth::EMPTY, @@ -149,7 +146,6 @@ pub enum MuteValue { } impl MuteValue { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn muteval(&self) -> vals::Muteval { match self { MuteValue::Zero => vals::Muteval::SEND_ZERO, @@ -168,7 +164,6 @@ pub enum Protocol { } impl Protocol { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn prtcfg(&self) -> vals::Prtcfg { match self { Protocol::Free => vals::Prtcfg::FREE, @@ -226,7 +221,6 @@ pub enum StereoMono { } impl StereoMono { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn mono(&self) -> vals::Mono { match self { StereoMono::Stereo => vals::Mono::STEREO, @@ -245,7 +239,6 @@ pub enum BitOrder { } impl BitOrder { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn lsbfirst(&self) -> vals::Lsbfirst { match self { BitOrder::LsbFirst => vals::Lsbfirst::LSB_FIRST, @@ -264,7 +257,6 @@ pub enum FrameSyncOffset { } impl FrameSyncOffset { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn fsoff(&self) -> vals::Fsoff { match self { FrameSyncOffset::OnFirstBit => vals::Fsoff::ON_FIRST, @@ -283,7 +275,6 @@ pub enum FrameSyncPolarity { } impl FrameSyncPolarity { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn fspol(&self) -> vals::Fspol { match self { FrameSyncPolarity::ActiveLow => vals::Fspol::FALLING_EDGE, @@ -301,7 +292,6 @@ pub enum FrameSyncDefinition { } impl FrameSyncDefinition { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn fsdef(&self) -> bool { match self { FrameSyncDefinition::StartOfFrame => false, @@ -319,7 +309,6 @@ pub enum ClockStrobe { } impl ClockStrobe { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn ckstr(&self) -> vals::Ckstr { match self { ClockStrobe::Falling => vals::Ckstr::FALLING_EDGE, @@ -337,7 +326,6 @@ pub enum ComplementFormat { } impl ComplementFormat { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn cpl(&self) -> vals::Cpl { match self { ComplementFormat::OnesComplement => vals::Cpl::ONES_COMPLEMENT, @@ -356,7 +344,6 @@ pub enum Companding { } impl Companding { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn comp(&self) -> vals::Comp { match self { Companding::None => vals::Comp::NO_COMPANDING, @@ -375,7 +362,6 @@ pub enum OutputDrive { } impl OutputDrive { - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] const fn outdriv(&self) -> vals::Outdriv { match self { OutputDrive::OnStart => vals::Outdriv::ON_START, @@ -384,196 +370,6 @@ impl OutputDrive { } } -/// Master clock divider. -#[derive(Copy, Clone, PartialEq)] -#[allow(missing_docs)] -#[cfg(any(sai_v1, sai_v2))] -pub enum MasterClockDivider { - MasterClockDisabled, - Div1, - Div2, - Div4, - Div6, - Div8, - Div10, - Div12, - Div14, - Div16, - Div18, - Div20, - Div22, - Div24, - Div26, - Div28, - Div30, -} - -/// Master clock divider. -#[derive(Copy, Clone, PartialEq)] -#[allow(missing_docs)] -#[cfg(any(sai_v1_4pdm, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] -pub enum MasterClockDivider { - MasterClockDisabled, - Div1, - Div2, - Div3, - Div4, - Div5, - Div6, - Div7, - Div8, - Div9, - Div10, - Div11, - Div12, - Div13, - Div14, - Div15, - Div16, - Div17, - Div18, - Div19, - Div20, - Div21, - Div22, - Div23, - Div24, - Div25, - Div26, - Div27, - Div28, - Div29, - Div30, - Div31, - Div32, - Div33, - Div34, - Div35, - Div36, - Div37, - Div38, - Div39, - Div40, - Div41, - Div42, - Div43, - Div44, - Div45, - Div46, - Div47, - Div48, - Div49, - Div50, - Div51, - Div52, - Div53, - Div54, - Div55, - Div56, - Div57, - Div58, - Div59, - Div60, - Div61, - Div62, - Div63, -} - -impl MasterClockDivider { - #[cfg(any(sai_v1, sai_v2))] - const fn mckdiv(&self) -> u8 { - match self { - MasterClockDivider::MasterClockDisabled => 0, - MasterClockDivider::Div1 => 0, - MasterClockDivider::Div2 => 1, - MasterClockDivider::Div4 => 2, - MasterClockDivider::Div6 => 3, - MasterClockDivider::Div8 => 4, - MasterClockDivider::Div10 => 5, - MasterClockDivider::Div12 => 6, - MasterClockDivider::Div14 => 7, - MasterClockDivider::Div16 => 8, - MasterClockDivider::Div18 => 9, - MasterClockDivider::Div20 => 10, - MasterClockDivider::Div22 => 11, - MasterClockDivider::Div24 => 12, - MasterClockDivider::Div26 => 13, - MasterClockDivider::Div28 => 14, - MasterClockDivider::Div30 => 15, - } - } - - #[cfg(any(sai_v1_4pdm, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] - const fn mckdiv(&self) -> u8 { - match self { - MasterClockDivider::MasterClockDisabled => 0, - MasterClockDivider::Div1 => 1, - MasterClockDivider::Div2 => 2, - MasterClockDivider::Div3 => 3, - MasterClockDivider::Div4 => 4, - MasterClockDivider::Div5 => 5, - MasterClockDivider::Div6 => 6, - MasterClockDivider::Div7 => 7, - MasterClockDivider::Div8 => 8, - MasterClockDivider::Div9 => 9, - MasterClockDivider::Div10 => 10, - MasterClockDivider::Div11 => 11, - MasterClockDivider::Div12 => 12, - MasterClockDivider::Div13 => 13, - MasterClockDivider::Div14 => 14, - MasterClockDivider::Div15 => 15, - MasterClockDivider::Div16 => 16, - MasterClockDivider::Div17 => 17, - MasterClockDivider::Div18 => 18, - MasterClockDivider::Div19 => 19, - MasterClockDivider::Div20 => 20, - MasterClockDivider::Div21 => 21, - MasterClockDivider::Div22 => 22, - MasterClockDivider::Div23 => 23, - MasterClockDivider::Div24 => 24, - MasterClockDivider::Div25 => 25, - MasterClockDivider::Div26 => 26, - MasterClockDivider::Div27 => 27, - MasterClockDivider::Div28 => 28, - MasterClockDivider::Div29 => 29, - MasterClockDivider::Div30 => 30, - MasterClockDivider::Div31 => 31, - MasterClockDivider::Div32 => 32, - MasterClockDivider::Div33 => 33, - MasterClockDivider::Div34 => 34, - MasterClockDivider::Div35 => 35, - MasterClockDivider::Div36 => 36, - MasterClockDivider::Div37 => 37, - MasterClockDivider::Div38 => 38, - MasterClockDivider::Div39 => 39, - MasterClockDivider::Div40 => 40, - MasterClockDivider::Div41 => 41, - MasterClockDivider::Div42 => 42, - MasterClockDivider::Div43 => 43, - MasterClockDivider::Div44 => 44, - MasterClockDivider::Div45 => 45, - MasterClockDivider::Div46 => 46, - MasterClockDivider::Div47 => 47, - MasterClockDivider::Div48 => 48, - MasterClockDivider::Div49 => 49, - MasterClockDivider::Div50 => 50, - MasterClockDivider::Div51 => 51, - MasterClockDivider::Div52 => 52, - MasterClockDivider::Div53 => 53, - MasterClockDivider::Div54 => 54, - MasterClockDivider::Div55 => 55, - MasterClockDivider::Div56 => 56, - MasterClockDivider::Div57 => 57, - MasterClockDivider::Div58 => 58, - MasterClockDivider::Div59 => 59, - MasterClockDivider::Div60 => 60, - MasterClockDivider::Div61 => 61, - MasterClockDivider::Div62 => 62, - MasterClockDivider::Div63 => 63, - } - } -} - /// [`SAI`] configuration. #[allow(missing_docs)] #[non_exhaustive] @@ -598,8 +394,7 @@ pub struct Config { pub frame_length: u8, pub clock_strobe: ClockStrobe, pub output_drive: OutputDrive, - pub master_clock_divider: MasterClockDivider, - pub nodiv: bool, + pub master_clock_divider: Option, pub is_high_impedance_on_inactive_slot: bool, pub fifo_threshold: FifoThreshold, pub companding: Companding, @@ -628,8 +423,7 @@ impl Default for Config { frame_sync_active_level_length: word::U7(16), frame_sync_definition: FrameSyncDefinition::ChannelIdentification, frame_length: 32, - master_clock_divider: MasterClockDivider::MasterClockDisabled, - nodiv: false, + master_clock_divider: None, clock_strobe: ClockStrobe::Rising, output_drive: OutputDrive::Immediately, is_high_impedance_on_inactive_slot: false, @@ -761,15 +555,11 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { mclk: Peri<'d, impl MclkPin>, dma: Peri<'d, impl Channel + Dma>, dma_buf: &'d mut [W], - mut config: Config, + config: Config, ) -> Self { let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); mclk.set_as_af(mclk.af_num(), ck_af_type); - if config.master_clock_divider == MasterClockDivider::MasterClockDisabled { - config.master_clock_divider = MasterClockDivider::Div1; - } - Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config) } @@ -851,10 +641,7 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { ) -> Self { let ch = T::REGS.ch(sub_block as usize); - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] - { - ch.cr1().modify(|w| w.set_saien(false)); - } + ch.cr1().modify(|w| w.set_saien(false)); ch.cr2().modify(|w| w.set_fflush(true)); @@ -877,55 +664,52 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { } } - #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] - { - ch.cr1().modify(|w| { - w.set_mode(config.mode.mode(if Self::is_transmitter(&ring_buffer) { - TxRx::Transmitter - } else { - TxRx::Receiver - })); - w.set_prtcfg(config.protocol.prtcfg()); - w.set_ds(config.data_size.ds()); - w.set_lsbfirst(config.bit_order.lsbfirst()); - w.set_ckstr(config.clock_strobe.ckstr()); - w.set_syncen(config.sync_input.syncen()); - w.set_mono(config.stereo_mono.mono()); - w.set_outdriv(config.output_drive.outdriv()); - w.set_mckdiv(config.master_clock_divider.mckdiv().into()); - w.set_nodiv(config.nodiv); - w.set_dmaen(true); - }); - - ch.cr2().modify(|w| { - w.set_fth(config.fifo_threshold.fth()); - w.set_comp(config.companding.comp()); - w.set_cpl(config.complement_format.cpl()); - w.set_muteval(config.mute_value.muteval()); - w.set_mutecnt(config.mute_detection_counter.0 as u8); - w.set_tris(config.is_high_impedance_on_inactive_slot); - }); - - ch.frcr().modify(|w| { - w.set_fsoff(config.frame_sync_offset.fsoff()); - w.set_fspol(config.frame_sync_polarity.fspol()); - w.set_fsdef(config.frame_sync_definition.fsdef()); - w.set_fsall(config.frame_sync_active_level_length.0 as u8 - 1); - w.set_frl(config.frame_length - 1); - }); - - ch.slotr().modify(|w| { - w.set_nbslot(config.slot_count.0 as u8 - 1); - w.set_slotsz(config.slot_size.slotsz()); - w.set_fboff(config.first_bit_offset.0 as u8); - w.set_sloten(vals::Sloten::from_bits(config.slot_enable as u16)); - }); - - ch.cr1().modify(|w| w.set_saien(true)); - - if ch.cr1().read().saien() == false { - panic!("SAI failed to enable. Check that config is valid (frame length, slot count, etc)"); - } + ch.cr1().modify(|w| { + w.set_mode(config.mode.mode(if Self::is_transmitter(&ring_buffer) { + TxRx::Transmitter + } else { + TxRx::Receiver + })); + w.set_prtcfg(config.protocol.prtcfg()); + w.set_ds(config.data_size.ds()); + w.set_lsbfirst(config.bit_order.lsbfirst()); + w.set_ckstr(config.clock_strobe.ckstr()); + w.set_syncen(config.sync_input.syncen()); + w.set_mono(config.stereo_mono.mono()); + w.set_outdriv(config.output_drive.outdriv()); + w.set_mckdiv(config.master_clock_divider.unwrap_or(MasterClockDivider::DIV1)); + w.set_nodiv(config.master_clock_divider.is_none()); + w.set_dmaen(true); + }); + + ch.cr2().modify(|w| { + w.set_fth(config.fifo_threshold.fth()); + w.set_comp(config.companding.comp()); + w.set_cpl(config.complement_format.cpl()); + w.set_muteval(config.mute_value.muteval()); + w.set_mutecnt(config.mute_detection_counter.0 as u8); + w.set_tris(config.is_high_impedance_on_inactive_slot); + }); + + ch.frcr().modify(|w| { + w.set_fsoff(config.frame_sync_offset.fsoff()); + w.set_fspol(config.frame_sync_polarity.fspol()); + w.set_fsdef(config.frame_sync_definition.fsdef()); + w.set_fsall(config.frame_sync_active_level_length.0 as u8 - 1); + w.set_frl(config.frame_length - 1); + }); + + ch.slotr().modify(|w| { + w.set_nbslot(config.slot_count.0 as u8 - 1); + w.set_slotsz(config.slot_size.slotsz()); + w.set_fboff(config.first_bit_offset.0 as u8); + w.set_sloten(vals::Sloten::from_bits(config.slot_enable as u16)); + }); + + ch.cr1().modify(|w| w.set_saien(true)); + + if ch.cr1().read().saien() == false { + panic!("SAI failed to enable. Check that config is valid (frame length, slot count, etc)"); } Self { diff --git a/examples/stm32h7/src/bin/sai.rs b/examples/stm32h7/src/bin/sai.rs index 01937593a..847b70c85 100644 --- a/examples/stm32h7/src/bin/sai.rs +++ b/examples/stm32h7/src/bin/sai.rs @@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) { tx_config.tx_rx = TxRx::Transmitter; tx_config.sync_output = true; tx_config.clock_strobe = ClockStrobe::Falling; - tx_config.master_clock_divider = mclk_div; + tx_config.master_clock_divider = Some(mclk_div); tx_config.stereo_mono = StereoMono::Stereo; tx_config.data_size = DataSize::Data24; tx_config.bit_order = BitOrder::MsbFirst; @@ -119,71 +119,7 @@ async fn main(_spawner: Spawner) { } } -const fn mclk_div_from_u8(v: u8) -> MasterClockDivider { - match v { - 1 => MasterClockDivider::Div1, - 2 => MasterClockDivider::Div2, - 3 => MasterClockDivider::Div3, - 4 => MasterClockDivider::Div4, - 5 => MasterClockDivider::Div5, - 6 => MasterClockDivider::Div6, - 7 => MasterClockDivider::Div7, - 8 => MasterClockDivider::Div8, - 9 => MasterClockDivider::Div9, - 10 => MasterClockDivider::Div10, - 11 => MasterClockDivider::Div11, - 12 => MasterClockDivider::Div12, - 13 => MasterClockDivider::Div13, - 14 => MasterClockDivider::Div14, - 15 => MasterClockDivider::Div15, - 16 => MasterClockDivider::Div16, - 17 => MasterClockDivider::Div17, - 18 => MasterClockDivider::Div18, - 19 => MasterClockDivider::Div19, - 20 => MasterClockDivider::Div20, - 21 => MasterClockDivider::Div21, - 22 => MasterClockDivider::Div22, - 23 => MasterClockDivider::Div23, - 24 => MasterClockDivider::Div24, - 25 => MasterClockDivider::Div25, - 26 => MasterClockDivider::Div26, - 27 => MasterClockDivider::Div27, - 28 => MasterClockDivider::Div28, - 29 => MasterClockDivider::Div29, - 30 => MasterClockDivider::Div30, - 31 => MasterClockDivider::Div31, - 32 => MasterClockDivider::Div32, - 33 => MasterClockDivider::Div33, - 34 => MasterClockDivider::Div34, - 35 => MasterClockDivider::Div35, - 36 => MasterClockDivider::Div36, - 37 => MasterClockDivider::Div37, - 38 => MasterClockDivider::Div38, - 39 => MasterClockDivider::Div39, - 40 => MasterClockDivider::Div40, - 41 => MasterClockDivider::Div41, - 42 => MasterClockDivider::Div42, - 43 => MasterClockDivider::Div43, - 44 => MasterClockDivider::Div44, - 45 => MasterClockDivider::Div45, - 46 => MasterClockDivider::Div46, - 47 => MasterClockDivider::Div47, - 48 => MasterClockDivider::Div48, - 49 => MasterClockDivider::Div49, - 50 => MasterClockDivider::Div50, - 51 => MasterClockDivider::Div51, - 52 => MasterClockDivider::Div52, - 53 => MasterClockDivider::Div53, - 54 => MasterClockDivider::Div54, - 55 => MasterClockDivider::Div55, - 56 => MasterClockDivider::Div56, - 57 => MasterClockDivider::Div57, - 58 => MasterClockDivider::Div58, - 59 => MasterClockDivider::Div59, - 60 => MasterClockDivider::Div60, - 61 => MasterClockDivider::Div61, - 62 => MasterClockDivider::Div62, - 63 => MasterClockDivider::Div63, - _ => panic!(), - } +fn mclk_div_from_u8(v: u8) -> MasterClockDivider { + assert!((1..=63).contains(&v)); + MasterClockDivider::from_bits(v) } diff --git a/examples/stm32h723/src/bin/spdifrx.rs b/examples/stm32h723/src/bin/spdifrx.rs index 6d29e8a4d..b75a03ae8 100644 --- a/examples/stm32h723/src/bin/spdifrx.rs +++ b/examples/stm32h723/src/bin/spdifrx.rs @@ -168,7 +168,7 @@ fn new_sai_transmitter<'d>( sai_config.slot_enable = 0xFFFF; // All slots sai_config.data_size = sai::DataSize::Data32; sai_config.frame_length = (CHANNEL_COUNT * 32) as u8; - sai_config.master_clock_divider = hal::sai::MasterClockDivider::MasterClockDisabled; + sai_config.master_clock_divider = None; let (sub_block_tx, _) = hal::sai::split_subblocks(sai); Sai::new_asynchronous(sub_block_tx, sck, sd, fs, dma, buf, sai_config) -- cgit From 90d403fd0a33ac7a3cde4fe9c417b5976b924020 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 31 Aug 2025 23:48:51 +0200 Subject: stm32: peri_v1_bar now enables cfgs peri_v1 and peri_v1_bar. --- embassy-stm32/build.rs | 29 +++++++++++++++++++++++++++-- embassy-stm32/src/sai/mod.rs | 10 +++++----- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index deefb13c1..b731012c6 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -16,6 +16,27 @@ use stm32_metapac::metadata::{ #[path = "./build_common.rs"] mod common; +/// Helper function to handle peripheral versions with underscores. +/// For a version like "v1_foo_bar", this generates all prefix combinations: +/// - "kind_v1" +/// - "kind_v1_foo" +/// - "kind_v1_foo_bar" +fn foreach_version_cfg( + cfgs: &mut common::CfgSet, + kind: &str, + version: &str, + mut cfg_fn: impl FnMut(&mut common::CfgSet, &str), +) { + let parts: Vec<&str> = version.split('_').collect(); + + // Generate all possible prefix combinations + for i in 1..=parts.len() { + let partial_version = parts[0..i].join("_"); + let cfg_name = format!("{}_{}", kind, partial_version); + cfg_fn(cfgs, &cfg_name); + } +} + fn main() { let mut cfgs = common::CfgSet::new(); common::set_target_cfgs(&mut cfgs); @@ -38,14 +59,18 @@ fn main() { for p in METADATA.peripherals { if let Some(r) = &p.registers { cfgs.enable(r.kind); - cfgs.enable(format!("{}_{}", r.kind, r.version)); + foreach_version_cfg(&mut cfgs, r.kind, r.version, |cfgs, cfg_name| { + cfgs.enable(cfg_name); + }); } } for &(kind, versions) in ALL_PERIPHERAL_VERSIONS.iter() { cfgs.declare(kind); for &version in versions.iter() { - cfgs.declare(format!("{}_{}", kind, version)); + foreach_version_cfg(&mut cfgs, kind, version, |cfgs, cfg_name| { + cfgs.declare(cfg_name); + }); } } diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index ff81dabed..cde2a56c2 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -182,7 +182,7 @@ pub enum SyncInput { /// Syncs with the other A/B sub-block within the SAI unit Internal, /// Syncs with a sub-block in the other SAI unit - #[cfg(any(sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v3, sai_v4))] External(SyncInputInstance), } @@ -191,14 +191,14 @@ impl SyncInput { match self { SyncInput::None => vals::Syncen::ASYNCHRONOUS, SyncInput::Internal => vals::Syncen::INTERNAL, - #[cfg(any(sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v3, sai_v4))] SyncInput::External(_) => vals::Syncen::EXTERNAL, } } } /// SAI instance to sync from. -#[cfg(any(sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] +#[cfg(any(sai_v3, sai_v4))] #[derive(Copy, Clone, PartialEq)] #[allow(missing_docs)] pub enum SyncInputInstance { @@ -500,7 +500,7 @@ fn update_synchronous_config(config: &mut Config) { config.sync_input = SyncInput::Internal; } - #[cfg(any(sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v3, sai_v4))] { //this must either be Internal or External //The asynchronous sub-block on the same SAI needs to enable sync_output @@ -645,7 +645,7 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { ch.cr2().modify(|w| w.set_fflush(true)); - #[cfg(any(sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v3, sai_v4))] { if let SyncInput::External(i) = config.sync_input { T::REGS.gcr().modify(|w| { -- cgit From 683ca6595ff7f4c6f0e70e90d3cdeab13d0b1c07 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 1 Sep 2025 00:05:20 +0200 Subject: stm32/spi: update for new version numbering, add i2s support for all versions. --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/Cargo.toml | 8 +- embassy-stm32/src/adc/mod.rs | 68 +++++----------- embassy-stm32/src/i2s.rs | 183 +++++++++++++++++++++---------------------- embassy-stm32/src/lib.rs | 2 +- embassy-stm32/src/spi/mod.rs | 134 +++++++++++++++---------------- 6 files changed, 181 insertions(+), 215 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 8ed4dbd65..5545fc454 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - feat: Derive Clone, Copy for QSPI Config - fix: stm32/i2c in master mode (blocking): subsequent transmissions failed after a NACK was received - feat: stm32/timer: add set_polarity functions for main and complementary outputs in complementary_pwm +- Add I2S support for STM32F1, STM32C0, STM32F0, STM32F3, STM32F7, STM32G0, STM32WL, STM32H5, STM32H7RS ## 0.4.0 - 2025-08-26 diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index cdb4e07d1..9c2ba1f53 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -173,8 +173,8 @@ cortex-m = "0.7.6" futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" -stm32-metapac = { version = "18" } -#stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ecb93d42a6cbcd9e09cab74873908a2ca22327f7" } +#stm32-metapac = { version = "18" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d8432edd0406495adec19d31923584e80b8e03cb" } vcell = "0.1.3" nb = "1.0.0" @@ -202,8 +202,8 @@ proptest-state-machine = "0.3.0" proc-macro2 = "1.0.36" quote = "1.0.15" -stm32-metapac = { version = "18", default-features = false, features = ["metadata"]} -#stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ecb93d42a6cbcd9e09cab74873908a2ca22327f7", default-features = false, features = ["metadata"] } +#stm32-metapac = { version = "18", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d8432edd0406495adec19d31923584e80b8e03cb", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index 778edc6f6..ea986f4cf 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -2,12 +2,12 @@ #![macro_use] #![allow(missing_docs)] // TODO -#![cfg_attr(adc_f3_v2, allow(unused))] +#![cfg_attr(adc_f3v3, allow(unused))] -#[cfg(not(any(adc_f3_v2, adc_wba)))] +#[cfg(not(any(adc_f3v3, adc_wba)))] #[cfg_attr(adc_f1, path = "f1.rs")] -#[cfg_attr(adc_f3, path = "f3.rs")] -#[cfg_attr(adc_f3_v1_1, path = "f3_v1_1.rs")] +#[cfg_attr(adc_f3v1, path = "f3.rs")] +#[cfg_attr(adc_f3v2, path = "f3_v1_1.rs")] #[cfg_attr(adc_v1, path = "v1.rs")] #[cfg_attr(adc_l0, path = "v1.rs")] #[cfg_attr(adc_v2, path = "v2.rs")] @@ -20,10 +20,10 @@ mod _version; use core::marker::PhantomData; #[allow(unused)] -#[cfg(not(any(adc_f3_v2, adc_wba)))] +#[cfg(not(any(adc_f3v3, adc_wba)))] pub use _version::*; use embassy_hal_internal::{impl_peripheral, PeripheralType}; -#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] +#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] use embassy_sync::waitqueue::AtomicWaker; #[cfg(any(adc_u5, adc_wba))] @@ -31,7 +31,7 @@ use embassy_sync::waitqueue::AtomicWaker; pub mod adc4; pub use crate::pac::adc::vals; -#[cfg(not(any(adc_f1, adc_f3_v2)))] +#[cfg(not(any(adc_f1, adc_f3v3)))] pub use crate::pac::adc::vals::Res as Resolution; pub use crate::pac::adc::vals::SampleTime; use crate::peripherals; @@ -47,16 +47,16 @@ dma_trait!(RxDma4, adc4::Instance); pub struct Adc<'d, T: Instance> { #[allow(unused)] adc: crate::Peri<'d, T>, - #[cfg(not(any(adc_f3_v2, adc_f3_v1_1, adc_wba)))] + #[cfg(not(any(adc_f3v3, adc_f3v2, adc_wba)))] sample_time: SampleTime, } -#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] +#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] pub struct State { pub waker: AtomicWaker, } -#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] +#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] impl State { pub const fn new() -> Self { Self { @@ -69,10 +69,10 @@ trait SealedInstance { #[cfg(not(adc_wba))] #[allow(unused)] fn regs() -> crate::pac::adc::Adc; - #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))] + #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3v3, adc_f3v2, adc_g0)))] #[allow(unused)] fn common_regs() -> crate::pac::adccommon::AdcCommon; - #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] + #[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] fn state() -> &'static State; } @@ -100,22 +100,8 @@ pub(crate) fn blocking_delay_us(us: u32) { /// ADC instance. #[cfg(not(any( - adc_f1, - adc_v1, - adc_l0, - adc_v2, - adc_v3, - adc_v4, - adc_g4, - adc_f3, - adc_f3_v1_1, - adc_g0, - adc_u0, - adc_h5, - adc_h7rs, - adc_u5, - adc_c0, - adc_wba, + adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs, + adc_u5, adc_c0, adc_wba, )))] #[allow(private_bounds)] pub trait Instance: SealedInstance + crate::PeripheralType { @@ -123,22 +109,8 @@ pub trait Instance: SealedInstance + crate::PeripheralType { } /// ADC instance. #[cfg(any( - adc_f1, - adc_v1, - adc_l0, - adc_v2, - adc_v3, - adc_v4, - adc_g4, - adc_f3, - adc_f3_v1_1, - adc_g0, - adc_u0, - adc_h5, - adc_h7rs, - adc_u5, - adc_c0, - adc_wba, + adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs, + adc_u5, adc_c0, adc_wba, ))] #[allow(private_bounds)] pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral { @@ -258,12 +230,12 @@ foreach_adc!( crate::pac::$inst } - #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0, adc_u5, adc_wba)))] + #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3v3, adc_f3v2, adc_g0, adc_u5, adc_wba)))] fn common_regs() -> crate::pac::adccommon::AdcCommon { return crate::pac::$common_inst } - #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] + #[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] fn state() -> &'static State { static STATE: State = State::new(); &STATE @@ -295,7 +267,7 @@ macro_rules! impl_adc_pin { /// Get the maximum reading value for this resolution. /// /// This is `2**n - 1`. -#[cfg(not(any(adc_f1, adc_f3_v2)))] +#[cfg(not(any(adc_f1, adc_f3v3)))] pub const fn resolution_to_max_count(res: Resolution) -> u32 { match res { #[cfg(adc_v4)] @@ -309,7 +281,7 @@ pub const fn resolution_to_max_count(res: Resolution) -> u32 { Resolution::BITS12 => (1 << 12) - 1, Resolution::BITS10 => (1 << 10) - 1, Resolution::BITS8 => (1 << 8) - 1, - #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_c0, adc_g0, adc_f3, adc_f3_v1_1, adc_h5))] + #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_c0, adc_g0, adc_f3v1, adc_f3v2, adc_h5))] Resolution::BITS6 => (1 << 6) - 1, #[allow(unreachable_patterns)] _ => core::unreachable!(), diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index a51d21bb0..0c4ab56e3 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs @@ -27,7 +27,8 @@ enum Function { Transmit, /// Receive audio data Receive, - #[cfg(spi_v3)] + #[cfg(any(spi_v4, spi_v5))] + /// Transmit and Receive audio data FullDuplex, } @@ -72,7 +73,6 @@ impl From for Error { } impl Standard { - #[cfg(any(spi_v1, spi_v3, spi_f1))] const fn i2sstd(&self) -> vals::I2sstd { match self { Standard::Philips => vals::I2sstd::PHILIPS, @@ -83,7 +83,6 @@ impl Standard { } } - #[cfg(any(spi_v1, spi_v3, spi_f1))] const fn pcmsync(&self) -> vals::Pcmsync { match self { Standard::PcmLongSync => vals::Pcmsync::LONG, @@ -106,7 +105,6 @@ pub enum Format { } impl Format { - #[cfg(any(spi_v1, spi_v3, spi_f1))] const fn datlen(&self) -> vals::Datlen { match self { Format::Data16Channel16 => vals::Datlen::BITS16, @@ -116,7 +114,6 @@ impl Format { } } - #[cfg(any(spi_v1, spi_v3, spi_f1))] const fn chlen(&self) -> vals::Chlen { match self { Format::Data16Channel16 => vals::Chlen::BITS16, @@ -137,7 +134,6 @@ pub enum ClockPolarity { } impl ClockPolarity { - #[cfg(any(spi_v1, spi_v3, spi_f1))] const fn ckpol(&self) -> vals::Ckpol { match self { ClockPolarity::IdleHigh => vals::Ckpol::IDLE_HIGH, @@ -314,7 +310,8 @@ impl<'d, W: Word> I2S<'d, W> { ) } - #[cfg(spi_v3)] + #[cfg(any(spi_v4, spi_v5))] + /// Create a full duplex driver. pub fn new_full_duplex( peri: Peri<'d, T>, @@ -357,7 +354,7 @@ impl<'d, W: Word> I2S<'d, W> { if let Some(rx_ring_buffer) = &mut self.rx_ring_buffer { rx_ring_buffer.start(); // SPIv3 clears rxfifo on SPE=0 - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] flush_rx_fifo(self.spi.info.regs); set_rxdmaen(self.spi.info.regs, true); @@ -365,7 +362,7 @@ impl<'d, W: Word> I2S<'d, W> { self.spi.info.regs.cr1().modify(|w| { w.set_spe(true); }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] self.spi.info.regs.cr1().modify(|w| { w.set_cstart(true); }); @@ -404,7 +401,7 @@ impl<'d, W: Word> I2S<'d, W> { join(rx_f, tx_f).await; - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] { if let Mode::Master = self.mode { regs.cr1().modify(|w| { @@ -492,103 +489,98 @@ impl<'d, W: Word> I2S<'d, W> { let (odd, div) = compute_baud_rate(pclk, config.frequency, config.master_clock, config.format); - #[cfg(any(spi_v1, spi_v3, spi_f1))] + #[cfg(any(spi_v4, spi_v5))] { - #[cfg(spi_v3)] - { - regs.cr1().modify(|w| w.set_spe(false)); + regs.cr1().modify(|w| w.set_spe(false)); - reset_incompatible_bitfields::(); - } + reset_incompatible_bitfields::(); + } - use stm32_metapac::spi::vals::{I2scfg, Odd}; - - // 1. Select the I2SDIV[7:0] bits in the SPI_I2SPR/SPI_I2SCFGR register to define the serial clock baud - // rate to reach the proper audio sample frequency. The ODD bit in the - // SPI_I2SPR/SPI_I2SCFGR register also has to be defined. - - // 2. Select the CKPOL bit to define the steady level for the communication clock. Set the - // MCKOE bit in the SPI_I2SPR/SPI_I2SCFGR register if the master clock MCK needs to be provided to - // the external DAC/ADC audio component (the I2SDIV and ODD values should be - // computed depending on the state of the MCK output, for more details refer to - // Section 28.4.4: Clock generator). - - // 3. Set the I2SMOD bit in SPI_I2SCFGR to activate the I2S functionalities and choose the - // I2S standard through the I2SSTD[1:0] and PCMSYNC bits, the data length through the - // DATLEN[1:0] bits and the number of bits per channel by configuring the CHLEN bit. - // Select also the I2S master mode and direction (Transmitter or Receiver) through the - // I2SCFG[1:0] bits in the SPI_I2SCFGR register. - - // 4. If needed, select all the potential interruption sources and the DMA capabilities by - // writing the SPI_CR2 register. - - // 5. The I2SE bit in SPI_I2SCFGR register must be set. - - let clk_reg = { - #[cfg(any(spi_v1, spi_f1))] - { - regs.i2spr() - } - #[cfg(spi_v3)] - { - regs.i2scfgr() - } - }; - - clk_reg.modify(|w| { - w.set_i2sdiv(div); - w.set_odd(match odd { - true => Odd::ODD, - false => Odd::EVEN, - }); + use stm32_metapac::spi::vals::{I2scfg, Odd}; + + // 1. Select the I2SDIV[7:0] bits in the SPI_I2SPR/SPI_I2SCFGR register to define the serial clock baud + // rate to reach the proper audio sample frequency. The ODD bit in the + // SPI_I2SPR/SPI_I2SCFGR register also has to be defined. - w.set_mckoe(config.master_clock); + // 2. Select the CKPOL bit to define the steady level for the communication clock. Set the + // MCKOE bit in the SPI_I2SPR/SPI_I2SCFGR register if the master clock MCK needs to be provided to + // the external DAC/ADC audio component (the I2SDIV and ODD values should be + // computed depending on the state of the MCK output, for more details refer to + // Section 28.4.4: Clock generator). + + // 3. Set the I2SMOD bit in SPI_I2SCFGR to activate the I2S functionalities and choose the + // I2S standard through the I2SSTD[1:0] and PCMSYNC bits, the data length through the + // DATLEN[1:0] bits and the number of bits per channel by configuring the CHLEN bit. + // Select also the I2S master mode and direction (Transmitter or Receiver) through the + // I2SCFG[1:0] bits in the SPI_I2SCFGR register. + + // 4. If needed, select all the potential interruption sources and the DMA capabilities by + // writing the SPI_CR2 register. + + // 5. The I2SE bit in SPI_I2SCFGR register must be set. + + let clk_reg = { + #[cfg(any(spi_v1, spi_v2, spi_v3))] + { + regs.i2spr() + } + #[cfg(any(spi_v4, spi_v5))] + { + regs.i2scfgr() + } + }; + + clk_reg.modify(|w| { + w.set_i2sdiv(div); + w.set_odd(match odd { + true => Odd::ODD, + false => Odd::EVEN, }); - regs.i2scfgr().modify(|w| { - w.set_ckpol(config.clock_polarity.ckpol()); + w.set_mckoe(config.master_clock); + }); - w.set_i2smod(true); + regs.i2scfgr().modify(|w| { + w.set_ckpol(config.clock_polarity.ckpol()); - w.set_i2sstd(config.standard.i2sstd()); - w.set_pcmsync(config.standard.pcmsync()); + w.set_i2smod(true); - w.set_datlen(config.format.datlen()); - w.set_chlen(config.format.chlen()); + w.set_i2sstd(config.standard.i2sstd()); + w.set_pcmsync(config.standard.pcmsync()); - w.set_i2scfg(match (config.mode, function) { - (Mode::Master, Function::Transmit) => I2scfg::MASTER_TX, - (Mode::Master, Function::Receive) => I2scfg::MASTER_RX, - #[cfg(spi_v3)] - (Mode::Master, Function::FullDuplex) => I2scfg::MASTER_FULL_DUPLEX, - (Mode::Slave, Function::Transmit) => I2scfg::SLAVE_TX, - (Mode::Slave, Function::Receive) => I2scfg::SLAVE_RX, - #[cfg(spi_v3)] - (Mode::Slave, Function::FullDuplex) => I2scfg::SLAVE_FULL_DUPLEX, - }); + w.set_datlen(config.format.datlen()); + w.set_chlen(config.format.chlen()); - #[cfg(any(spi_v1, spi_f1))] - w.set_i2se(true); + w.set_i2scfg(match (config.mode, function) { + (Mode::Master, Function::Transmit) => I2scfg::MASTER_TX, + (Mode::Master, Function::Receive) => I2scfg::MASTER_RX, + #[cfg(any(spi_v4, spi_v5))] + (Mode::Master, Function::FullDuplex) => I2scfg::MASTER_FULL_DUPLEX, + (Mode::Slave, Function::Transmit) => I2scfg::SLAVE_TX, + (Mode::Slave, Function::Receive) => I2scfg::SLAVE_RX, + #[cfg(any(spi_v4, spi_v5))] + (Mode::Slave, Function::FullDuplex) => I2scfg::SLAVE_FULL_DUPLEX, }); - let mut opts = TransferOptions::default(); - opts.half_transfer_ir = true; - - Self { - mode: config.mode, - spi, - txsd: txsd.map(|w| w.into()), - rxsd: rxsd.map(|w| w.into()), - ws: Some(ws.into()), - ck: Some(ck.into()), - mck: mck.map(|w| w.into()), - tx_ring_buffer: txdma.map(|(ch, buf)| unsafe { - WritableRingBuffer::new(ch.channel, ch.request, regs.tx_ptr(), buf, opts) - }), - rx_ring_buffer: rxdma.map(|(ch, buf)| unsafe { - ReadableRingBuffer::new(ch.channel, ch.request, regs.rx_ptr(), buf, opts) - }), - } + #[cfg(any(spi_v1, spi_v2, spi_v3))] + w.set_i2se(true); + }); + + let mut opts = TransferOptions::default(); + opts.half_transfer_ir = true; + + Self { + mode: config.mode, + spi, + txsd: txsd.map(|w| w.into()), + rxsd: rxsd.map(|w| w.into()), + ws: Some(ws.into()), + ck: Some(ck.into()), + mck: mck.map(|w| w.into()), + tx_ring_buffer: txdma + .map(|(ch, buf)| unsafe { WritableRingBuffer::new(ch.channel, ch.request, regs.tx_ptr(), buf, opts) }), + rx_ring_buffer: rxdma + .map(|(ch, buf)| unsafe { ReadableRingBuffer::new(ch.channel, ch.request, regs.rx_ptr(), buf, opts) }), } } } @@ -639,7 +631,8 @@ fn compute_baud_rate(i2s_clock: Hertz, request_freq: Hertz, mclk: bool, data_for } } -#[cfg(spi_v3)] +#[cfg(any(spi_v4, spi_v5))] + // The STM32H7 reference manual specifies that any incompatible bitfields should be reset // to their reset values while operating in I2S mode. fn reset_incompatible_bitfields() { diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 3be98c462..7e0f7884e 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -87,7 +87,7 @@ pub mod hsem; pub mod hspi; #[cfg(i2c)] pub mod i2c; -#[cfg(any(all(spi_v1, rcc_f4), spi_v3))] +#[cfg(any(spi_v1_i2s, spi_v2_i2s, spi_v3_i2s, spi_v4_i2s, spi_v5_i2s))] pub mod i2s; #[cfg(stm32wb)] pub mod ipcc; diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 4c5308eba..a49ebcbee 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -174,7 +174,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { self.info.rcc.enable_and_reset(); let regs = self.info.regs; - #[cfg(any(spi_v1, spi_f1))] + #[cfg(any(spi_v1, spi_v2))] { regs.cr2().modify(|w| { w.set_ssoe(false); @@ -198,7 +198,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { w.set_dff(::CONFIG) }); } - #[cfg(spi_v2)] + #[cfg(spi_v3)] { regs.cr2().modify(|w| { let (ds, frxth) = ::CONFIG; @@ -220,7 +220,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { w.set_spe(true); }); } - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] { regs.ifcr().write(|w| w.0 = 0xffff_ffff); regs.cfg2().modify(|w| { @@ -274,7 +274,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { } } - #[cfg(any(spi_v1, spi_f1, spi_v2))] + #[cfg(any(spi_v1, spi_v2, spi_v3))] self.info.regs.cr1().modify(|w| { w.set_cpha(cpha); w.set_cpol(cpol); @@ -282,7 +282,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { w.set_lsbfirst(lsbfirst); }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] { self.info.regs.cr1().modify(|w| { w.set_spe(false); @@ -306,11 +306,11 @@ impl<'d, M: PeriMode> Spi<'d, M> { /// Get current SPI configuration. pub fn get_current_config(&self) -> Config { - #[cfg(any(spi_v1, spi_f1, spi_v2))] + #[cfg(any(spi_v1, spi_v2, spi_v3))] let cfg = self.info.regs.cr1().read(); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] let cfg = self.info.regs.cfg2().read(); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] let cfg1 = self.info.regs.cfg1().read(); let polarity = if cfg.cpol() == vals::Cpol::IDLE_LOW { @@ -335,9 +335,9 @@ impl<'d, M: PeriMode> Spi<'d, M> { Some(pin) => pin.pull(), }; - #[cfg(any(spi_v1, spi_f1, spi_v2))] + #[cfg(any(spi_v1, spi_v2, spi_v3))] let br = cfg.br(); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] let br = cfg1.mbr(); let frequency = compute_frequency(self.kernel_clock, br); @@ -360,16 +360,16 @@ impl<'d, M: PeriMode> Spi<'d, M> { w.set_spe(false); }); - #[cfg(any(spi_v1, spi_f1))] + #[cfg(any(spi_v1, spi_v2))] self.info.regs.cr1().modify(|reg| { reg.set_dff(word_size); }); - #[cfg(spi_v2)] + #[cfg(spi_v3)] self.info.regs.cr2().modify(|w| { w.set_frxth(word_size.1); w.set_ds(word_size.0); }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] self.info.regs.cfg1().modify(|w| { w.set_dsize(word_size); }); @@ -380,7 +380,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { /// Blocking write. pub fn blocking_write(&mut self, words: &[W]) -> Result<(), Error> { // needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...? - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] self.info.regs.cr1().modify(|w| w.set_spe(false)); self.set_word_size(W::CONFIG); self.info.regs.cr1().modify(|w| w.set_spe(true)); @@ -391,7 +391,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { // This is the case when the SPI has been created with `new_(blocking_?)txonly_nosck`. // See https://github.com/embassy-rs/embassy/issues/2902 // This is not documented as an errata by ST, and I've been unable to find anything online... - #[cfg(not(any(spi_v1, spi_f1)))] + #[cfg(not(any(spi_v1, spi_v2)))] write_word(self.info.regs, *word)?; // if we're doing tx only, after writing the last byte to FIFO we have to wait @@ -401,14 +401,14 @@ impl<'d, M: PeriMode> Spi<'d, M> { // Luckily this doesn't affect SPIv2+. // See http://efton.sk/STM32/gotcha/g68.html // ST doesn't seem to document this in errata sheets (?) - #[cfg(any(spi_v1, spi_f1))] + #[cfg(any(spi_v1, spi_v2))] transfer_word(self.info.regs, *word)?; } // wait until last word is transmitted. (except on v1, see above) - #[cfg(not(any(spi_v1, spi_f1, spi_v2)))] + #[cfg(not(any(spi_v1, spi_v2, spi_v3)))] while !self.info.regs.sr().read().txc() {} - #[cfg(spi_v2)] + #[cfg(spi_v3)] while self.info.regs.sr().read().bsy() {} Ok(()) @@ -417,7 +417,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { /// Blocking read. pub fn blocking_read(&mut self, words: &mut [W]) -> Result<(), Error> { // needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...? - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] self.info.regs.cr1().modify(|w| w.set_spe(false)); self.set_word_size(W::CONFIG); self.info.regs.cr1().modify(|w| w.set_spe(true)); @@ -433,7 +433,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { /// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time. pub fn blocking_transfer_in_place(&mut self, words: &mut [W]) -> Result<(), Error> { // needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...? - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] self.info.regs.cr1().modify(|w| w.set_spe(false)); self.set_word_size(W::CONFIG); self.info.regs.cr1().modify(|w| w.set_spe(true)); @@ -452,7 +452,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { /// If `write` is shorter it is padded with zero bytes. pub fn blocking_transfer(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> { // needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...? - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] self.info.regs.cr1().modify(|w| w.set_spe(false)); self.set_word_size(W::CONFIG); self.info.regs.cr1().modify(|w| w.set_spe(true)); @@ -572,7 +572,7 @@ impl<'d> Spi<'d, Async> { peri: Peri<'d, T>, sck: Peri<'d, impl SckPin>, miso: Peri<'d, impl MisoPin>, - #[cfg(any(spi_v1, spi_f1, spi_v2))] tx_dma: Peri<'d, impl TxDma>, + #[cfg(any(spi_v1, spi_v2, spi_v3))] tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, config: Config, ) -> Self { @@ -581,9 +581,9 @@ impl<'d> Spi<'d, Async> { new_pin!(sck, config.sck_af()), None, new_pin!(miso, AfType::input(config.miso_pull)), - #[cfg(any(spi_v1, spi_f1, spi_v2))] + #[cfg(any(spi_v1, spi_v2, spi_v3))] new_dma!(tx_dma), - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] None, new_dma!(rx_dma), config, @@ -677,7 +677,7 @@ impl<'d> Spi<'d, Async> { self.info.regs.cr1().modify(|w| { w.set_spe(true); }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] self.info.regs.cr1().modify(|w| { w.set_cstart(true); }); @@ -690,7 +690,7 @@ impl<'d> Spi<'d, Async> { } /// SPI read, using DMA. - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] pub async fn read(&mut self, data: &mut [W]) -> Result<(), Error> { if data.is_empty() { return Ok(()); @@ -710,7 +710,7 @@ impl<'d> Spi<'d, Async> { prev }); - #[cfg(spi_v3)] + #[cfg(spi_v4)] let i2scfg = regs.i2scfgr().modify(|w| { w.i2smod().then(|| { let prev = w.i2scfg(); @@ -766,7 +766,7 @@ impl<'d> Spi<'d, Async> { w.set_tsize(0); }); - #[cfg(spi_v3)] + #[cfg(spi_v4)] if let Some(i2scfg) = i2scfg { regs.i2scfgr().modify(|w| { w.set_i2scfg(i2scfg); @@ -777,7 +777,7 @@ impl<'d> Spi<'d, Async> { } /// SPI read, using DMA. - #[cfg(any(spi_v1, spi_f1, spi_v2))] + #[cfg(any(spi_v1, spi_v2, spi_v3))] pub async fn read(&mut self, data: &mut [W]) -> Result<(), Error> { if data.is_empty() { return Ok(()); @@ -790,7 +790,7 @@ impl<'d> Spi<'d, Async> { self.set_word_size(W::CONFIG); // SPIv3 clears rxfifo on SPE=0 - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] flush_rx_fifo(self.info.regs); set_rxdmaen(self.info.regs, true); @@ -813,7 +813,7 @@ impl<'d> Spi<'d, Async> { self.info.regs.cr1().modify(|w| { w.set_spe(true); }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] self.info.regs.cr1().modify(|w| { w.set_cstart(true); }); @@ -838,7 +838,7 @@ impl<'d> Spi<'d, Async> { self.set_word_size(W::CONFIG); // SPIv3 clears rxfifo on SPE=0 - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] flush_rx_fifo(self.info.regs); set_rxdmaen(self.info.regs, true); @@ -858,7 +858,7 @@ impl<'d> Spi<'d, Async> { self.info.regs.cr1().modify(|w| { w.set_spe(true); }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] self.info.regs.cr1().modify(|w| { w.set_cstart(true); }); @@ -898,9 +898,9 @@ impl<'d, M: PeriMode> Drop for Spi<'d, M> { } } -#[cfg(not(any(spi_v3, spi_v4, spi_v5)))] +#[cfg(not(any(spi_v4, spi_v5, spi_v6)))] use vals::Br; -#[cfg(any(spi_v3, spi_v4, spi_v5))] +#[cfg(any(spi_v4, spi_v5, spi_v6))] use vals::Mbr as Br; fn compute_baud_rate(kernel_clock: Hertz, freq: Hertz) -> Br { @@ -941,21 +941,21 @@ pub(crate) trait RegsExt { impl RegsExt for Regs { fn tx_ptr(&self) -> *mut W { - #[cfg(any(spi_v1, spi_f1))] + #[cfg(any(spi_v1, spi_v2))] let dr = self.dr(); - #[cfg(spi_v2)] + #[cfg(spi_v3)] let dr = self.dr16(); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] let dr = self.txdr32(); dr.as_ptr() as *mut W } fn rx_ptr(&self) -> *mut W { - #[cfg(any(spi_v1, spi_f1))] + #[cfg(any(spi_v1, spi_v2))] let dr = self.dr(); - #[cfg(spi_v2)] + #[cfg(spi_v3)] let dr = self.dr16(); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] let dr = self.rxdr32(); dr.as_ptr() as *mut W } @@ -965,22 +965,22 @@ fn check_error_flags(sr: regs::Sr, ovr: bool) -> Result<(), Error> { if sr.ovr() && ovr { return Err(Error::Overrun); } - #[cfg(not(any(spi_f1, spi_v3, spi_v4, spi_v5)))] + #[cfg(not(any(spi_v1, spi_v4, spi_v5, spi_v6)))] if sr.fre() { return Err(Error::Framing); } - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] if sr.tifre() { return Err(Error::Framing); } if sr.modf() { return Err(Error::ModeFault); } - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] if sr.crcerr() { return Err(Error::Crc); } - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] if sr.crce() { return Err(Error::Crc); } @@ -994,11 +994,11 @@ fn spin_until_tx_ready(regs: Regs, ovr: bool) -> Result<(), Error> { check_error_flags(sr, ovr)?; - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] if sr.txe() { return Ok(()); } - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] if sr.txp() { return Ok(()); } @@ -1011,11 +1011,11 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> { check_error_flags(sr, true)?; - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] if sr.rxne() { return Ok(()); } - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] if sr.rxp() { return Ok(()); } @@ -1023,46 +1023,46 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> { } pub(crate) fn flush_rx_fifo(regs: Regs) { - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] while regs.sr().read().rxne() { - #[cfg(not(spi_v2))] + #[cfg(not(spi_v3))] let _ = regs.dr().read(); - #[cfg(spi_v2)] + #[cfg(spi_v3)] let _ = regs.dr16().read(); } - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] while regs.sr().read().rxp() { let _ = regs.rxdr32().read(); } } pub(crate) fn set_txdmaen(regs: Regs, val: bool) { - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] regs.cr2().modify(|reg| { reg.set_txdmaen(val); }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] regs.cfg1().modify(|reg| { reg.set_txdmaen(val); }); } pub(crate) fn set_rxdmaen(regs: Regs, val: bool) { - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] regs.cr2().modify(|reg| { reg.set_rxdmaen(val); }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] regs.cfg1().modify(|reg| { reg.set_rxdmaen(val); }); } fn finish_dma(regs: Regs) { - #[cfg(spi_v2)] + #[cfg(spi_v3)] while regs.sr().read().ftlvl().to_bits() > 0 {} - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] { if regs.cr2().read().tsize() == 0 { while !regs.sr().read().txc() {} @@ -1070,7 +1070,7 @@ fn finish_dma(regs: Regs) { while !regs.sr().read().eot() {} } } - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] while regs.sr().read().bsy() {} // Disable the spi peripheral @@ -1080,12 +1080,12 @@ fn finish_dma(regs: Regs) { // The peripheral automatically disables the DMA stream on completion without error, // but it does not clear the RXDMAEN/TXDMAEN flag in CR2. - #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] + #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] regs.cr2().modify(|reg| { reg.set_txdmaen(false); reg.set_rxdmaen(false); }); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] regs.cfg1().modify(|reg| { reg.set_txdmaen(false); reg.set_rxdmaen(false); @@ -1098,7 +1098,7 @@ fn transfer_word(regs: Regs, tx_word: W) -> Result { unsafe { ptr::write_volatile(regs.tx_ptr(), tx_word); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] regs.cr1().modify(|reg| reg.set_cstart(true)); } @@ -1117,7 +1117,7 @@ fn write_word(regs: Regs, tx_word: W) -> Result<(), Error> { unsafe { ptr::write_volatile(regs.tx_ptr(), tx_word); - #[cfg(any(spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v4, spi_v5, spi_v6))] regs.cr1().modify(|reg| reg.set_cstart(true)); } Ok(()) @@ -1225,7 +1225,7 @@ macro_rules! impl_word { }; } -#[cfg(any(spi_v1, spi_f1))] +#[cfg(any(spi_v1, spi_v2))] mod word_impl { use super::*; @@ -1235,7 +1235,7 @@ mod word_impl { impl_word!(u16, vals::Dff::BITS16); } -#[cfg(spi_v2)] +#[cfg(spi_v3)] mod word_impl { use super::*; @@ -1256,7 +1256,7 @@ mod word_impl { impl_word!(u16, (vals::Ds::BITS16, vals::Frxth::HALF)); } -#[cfg(any(spi_v3, spi_v4, spi_v5))] +#[cfg(any(spi_v4, spi_v5, spi_v6))] mod word_impl { use super::*; -- cgit From b8577a31338358d10b1fdb7dd374b0c7eafe86b5 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 5 Sep 2025 16:27:48 +0200 Subject: Use merge=union for changelogs to avoid constant conflicts. --- .gitattributes | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitattributes b/.gitattributes index a51376f0d..2850eb3b1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -17,6 +17,13 @@ .vscode/*.json linguist-language=JSON-with-Comments +# Configure changelog files to use union merge strategy +# This prevents merge conflicts by automatically combining changes from both branches +CHANGELOG.md merge=union +changelog.md merge=union +CHANGELOG.txt merge=union +changelog.txt merge=union + *.raw binary *.bin binary *.png binary -- cgit From d264c8ab31d6361a3fb76443ae80630d123d68fb Mon Sep 17 00:00:00 2001 From: Francisco José Gómez Date: Thu, 28 Aug 2025 10:36:07 -0400 Subject: fix(embassy-stm32): Prevent dropped DacChannel from disabling Dac peripheral if another DacChannel is still in scope Fix #4577 by counting references to DacChannel. Modeled after similar code in the `can` module. --- embassy-stm32/src/dac/mod.rs | 55 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index d8f1f96f2..bc6c3cd34 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs @@ -12,6 +12,7 @@ use crate::{peripherals, Peri}; mod tsel; use embassy_hal_internal::PeripheralType; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; pub use tsel::TriggerSel; /// Operating mode for DAC channel @@ -96,6 +97,41 @@ pub enum ValueArray<'a> { Bit12Right(&'a [u16]), } +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +enum ChannelEvent { + Enable, + Disable, +} + +struct InnerState { + channel_count: usize, +} + +type SharedState = embassy_sync::blocking_mutex::Mutex>; +struct State { + state: SharedState, +} + +impl State { + /// Adjusts the channel count in response to a `ChannelEvent`, returning the updated value. + pub fn adjust_channel_count(&self, event: ChannelEvent) -> usize { + self.state.lock(|state| { + { + let mut mut_state = state.borrow_mut(); + match event { + ChannelEvent::Enable => { + mut_state.channel_count += 1; + } + ChannelEvent::Disable => { + mut_state.channel_count -= 1; + } + }; + } + state.borrow().channel_count + }) + } +} /// Driver for a single DAC channel. /// /// If you want to use both channels, either together or independently, @@ -249,6 +285,16 @@ impl<'d, T: Instance, C: Channel, M: PeriMode> DacChannel<'d, T, C, M> { reg.set_en(C::IDX, on); }); }); + let event = if on { + ChannelEvent::Enable + } else { + ChannelEvent::Disable + }; + let channel_count = T::state().adjust_channel_count(event); + // Disable the DAC only if no more channels are using it. + if channel_count == 0 { + rcc::disable::(); + } } /// Enable this channel. @@ -354,7 +400,7 @@ impl<'d, T: Instance, C: Channel, M: PeriMode> DacChannel<'d, T, C, M> { impl<'d, T: Instance, C: Channel, M: PeriMode> Drop for DacChannel<'d, T, C, M> { fn drop(&mut self) { - rcc::disable::(); + self.disable(); } } @@ -597,6 +643,13 @@ impl<'d, T: Instance, M: PeriMode> Dac<'d, T, M> { trait SealedInstance { fn regs() -> crate::pac::dac::Dac; + + fn state() -> &'static State { + static STATE: State = State { + state: embassy_sync::blocking_mutex::Mutex::new(core::cell::RefCell::new(InnerState { channel_count: 0 })), + }; + &STATE + } } /// DAC instance. -- cgit From 46ce5ab6973f62c48a4de0e69a0a6c5d57d9dbb5 Mon Sep 17 00:00:00 2001 From: Francisco José Gómez Date: Thu, 28 Aug 2025 12:19:14 -0400 Subject: chore(embassy-stm32): Update changelog Refs: #4577 --- embassy-stm32/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 50bdc1072..69f15013d 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -13,6 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - fix: stm32/i2c in master mode (blocking): subsequent transmissions failed after a NACK was received - feat: stm32/timer: add set_polarity functions for main and complementary outputs in complementary_pwm - Add I2S support for STM32F1, STM32C0, STM32F0, STM32F3, STM32F7, STM32G0, STM32WL, STM32H5, STM32H7RS +### Fixed + +- STM32: Prevent dropped DacChannel from disabling Dac peripheral if another DacChannel is still in scope ([#4577](https://github.com/embassy-rs/embassy/pull/4577)) ## 0.4.0 - 2025-08-26 -- cgit From 525c7fe1eb77e3aa7440a14d6a6decfc0b0ca576 Mon Sep 17 00:00:00 2001 From: jake-taf Date: Sat, 23 Aug 2025 18:05:47 -0400 Subject: OSPI RAM Support - Make DQSE / SIOO configurable - Make write instruction configurable - Fix bug where the address DTR was using the config for the instruction DTR instead of its own - Configure DQS pin --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/src/ospi/mod.rs | 109 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 101 insertions(+), 9 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 69f15013d..a473834dd 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - STM32: Prevent dropped DacChannel from disabling Dac peripheral if another DacChannel is still in scope ([#4577](https://github.com/embassy-rs/embassy/pull/4577)) +- feat: Added support for more OctoSPI configurations (e.g. APS6408 RAM) ([#4581](https://github.com/embassy-rs/embassy/pull/4581)) ## 0.4.0 - 2025-08-26 diff --git a/embassy-stm32/src/ospi/mod.rs b/embassy-stm32/src/ospi/mod.rs index 74edfd5e4..8384f4fc4 100644 --- a/embassy-stm32/src/ospi/mod.rs +++ b/embassy-stm32/src/ospi/mod.rs @@ -118,6 +118,11 @@ pub struct TransferConfig { /// Number of dummy cycles (DCYC) pub dummy: DummyCycles, + + /// Data strobe (DQS) management enable + pub dqse: bool, + /// Send instruction only once (SIOO) mode enable + pub sioo: bool, } impl Default for TransferConfig { @@ -142,6 +147,9 @@ impl Default for TransferConfig { ddtr: false, dummy: DummyCycles::_0, + + dqse: false, + sioo: true, } } } @@ -192,26 +200,27 @@ impl<'d, T: Instance, M: PeriMode> Ospi<'d, T, M> { let reg = T::REGS; while reg.sr().read().busy() {} - reg.ccr().modify(|r| { - r.set_dqse(false); - r.set_sioo(true); - }); + if let Some(instruction) = write_config.instruction { + reg.wir().write(|r| { + r.set_instruction(instruction); + }); + } - // Set wrting configurations, there are separate registers for write configurations in memory mapped mode + // Set writing configurations, there are separate registers for write configurations in memory mapped mode reg.wccr().modify(|w| { w.set_imode(PhaseMode::from_bits(write_config.iwidth.into())); w.set_idtr(write_config.idtr); w.set_isize(SizeInBits::from_bits(write_config.isize.into())); w.set_admode(PhaseMode::from_bits(write_config.adwidth.into())); - w.set_addtr(write_config.idtr); + w.set_addtr(write_config.addtr); w.set_adsize(SizeInBits::from_bits(write_config.adsize.into())); w.set_dmode(PhaseMode::from_bits(write_config.dwidth.into())); w.set_ddtr(write_config.ddtr); w.set_abmode(PhaseMode::from_bits(write_config.abwidth.into())); - w.set_dqse(true); + w.set_dqse(write_config.dqse); }); reg.wtcr().modify(|w| w.set_dcyc(write_config.dummy.into())); @@ -465,18 +474,21 @@ impl<'d, T: Instance, M: PeriMode> Ospi<'d, T, M> { }) } - // Configure instruction/address/data modes + // Configure instruction/address/data/communication modes T::REGS.ccr().modify(|w| { w.set_imode(PhaseMode::from_bits(command.iwidth.into())); w.set_idtr(command.idtr); w.set_isize(SizeInBits::from_bits(command.isize.into())); w.set_admode(PhaseMode::from_bits(command.adwidth.into())); - w.set_addtr(command.idtr); + w.set_addtr(command.addtr); w.set_adsize(SizeInBits::from_bits(command.adsize.into())); w.set_dmode(PhaseMode::from_bits(command.dwidth.into())); w.set_ddtr(command.ddtr); + + w.set_dqse(command.dqse); + w.set_sioo(command.sioo); }); // Set informationrequired to initiate transaction @@ -854,6 +866,45 @@ impl<'d, T: Instance> Ospi<'d, T, Blocking> { false, ) } + + /// Create new blocking OSPI driver for octospi external chips with DQS support + pub fn new_blocking_octospi_with_dqs( + peri: Peri<'d, T>, + sck: Peri<'d, impl SckPin>, + d0: Peri<'d, impl D0Pin>, + d1: Peri<'d, impl D1Pin>, + d2: Peri<'d, impl D2Pin>, + d3: Peri<'d, impl D3Pin>, + d4: Peri<'d, impl D4Pin>, + d5: Peri<'d, impl D5Pin>, + d6: Peri<'d, impl D6Pin>, + d7: Peri<'d, impl D7Pin>, + nss: Peri<'d, impl NSSPin>, + dqs: Peri<'d, impl DQSPin>, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!( + nss, + AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up) + ), + new_pin!(dqs, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + None, + config, + OspiWidth::OCTO, + false, + ) + } } impl<'d, T: Instance> Ospi<'d, T, Async> { @@ -1036,6 +1087,46 @@ impl<'d, T: Instance> Ospi<'d, T, Async> { ) } + /// Create new blocking OSPI driver for octospi external chips with DQS support + pub fn new_octospi_with_dqs( + peri: Peri<'d, T>, + sck: Peri<'d, impl SckPin>, + d0: Peri<'d, impl D0Pin>, + d1: Peri<'d, impl D1Pin>, + d2: Peri<'d, impl D2Pin>, + d3: Peri<'d, impl D3Pin>, + d4: Peri<'d, impl D4Pin>, + d5: Peri<'d, impl D5Pin>, + d6: Peri<'d, impl D6Pin>, + d7: Peri<'d, impl D7Pin>, + nss: Peri<'d, impl NSSPin>, + dqs: Peri<'d, impl DQSPin>, + dma: Peri<'d, impl OctoDma>, + config: Config, + ) -> Self { + Self::new_inner( + peri, + new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d4, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d5, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d6, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d7, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!( + nss, + AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up) + ), + new_pin!(dqs, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_dma!(dma), + config, + OspiWidth::OCTO, + false, + ) + } + /// Blocking read with DMA transfer pub fn blocking_read_dma(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> { if buf.is_empty() { -- cgit From bc448985d50827bd5c6211739563817795f925ab Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Mon, 11 Aug 2025 15:18:31 +0800 Subject: otg: Simplify chunks_exact for tx The last chunk doesn't need to be created first, instead borrow the iterator so it can be used later for the remainder. --- embassy-usb-synopsys-otg/src/lib.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/embassy-usb-synopsys-otg/src/lib.rs b/embassy-usb-synopsys-otg/src/lib.rs index 9d74c046d..b226bc8af 100644 --- a/embassy-usb-synopsys-otg/src/lib.rs +++ b/embassy-usb-synopsys-otg/src/lib.rs @@ -1229,23 +1229,19 @@ impl<'d> embassy_usb_driver::EndpointIn for Endpoint<'d, In> { }); // Write data to FIFO - let chunks = buf.chunks_exact(4); - // Stash the last partial chunk - let rem = chunks.remainder(); - let last_chunk = (!rem.is_empty()).then(|| { - let mut tmp = [0u8; 4]; - tmp[0..rem.len()].copy_from_slice(rem); - u32::from_ne_bytes(tmp) - }); - let fifo = self.regs.fifo(index); - for chunk in chunks { + let mut chunks = buf.chunks_exact(4); + for chunk in &mut chunks { let val = u32::from_ne_bytes(chunk.try_into().unwrap()); fifo.write_value(regs::Fifo(val)); } // Write any last chunk - if let Some(val) = last_chunk { - fifo.write_value(regs::Fifo(val)); + let rem = chunks.remainder(); + if !rem.is_empty() { + let mut tmp = [0u8; 4]; + tmp[0..rem.len()].copy_from_slice(rem); + let tmp = u32::from_ne_bytes(tmp); + fifo.write_value(regs::Fifo(tmp)); } }); -- cgit From cac396425228464602ab9ee0816f4f9f07d53d77 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Mon, 11 Aug 2025 15:19:51 +0800 Subject: otg: Use chunks_exact for more efficient rx copy --- embassy-usb-synopsys-otg/CHANGELOG.md | 2 ++ embassy-usb-synopsys-otg/src/lib.rs | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/embassy-usb-synopsys-otg/CHANGELOG.md b/embassy-usb-synopsys-otg/CHANGELOG.md index 9ca90f5e9..45353d907 100644 --- a/embassy-usb-synopsys-otg/CHANGELOG.md +++ b/embassy-usb-synopsys-otg/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 0.3.1 - 2025-08-26 +- Improve receive performance, more efficient copy from FIFO + ## 0.3.0 - 2025-07-22 - Bump `embassy-usb-driver` to v0.2.0 diff --git a/embassy-usb-synopsys-otg/src/lib.rs b/embassy-usb-synopsys-otg/src/lib.rs index b226bc8af..6b4a87bdf 100644 --- a/embassy-usb-synopsys-otg/src/lib.rs +++ b/embassy-usb-synopsys-otg/src/lib.rs @@ -76,10 +76,16 @@ pub unsafe fn on_interrupt(r: Otg, state: &State Date: Wed, 2 Jul 2025 20:31:45 -0500 Subject: rp: add new pio dma apis This commit adds StateMachineRx::dma_pull_repeated and StateMachineTx::dma_push_repeated which allow you to discard reads or send dummy writes to the state machine using the DMA hardware --- embassy-rp/src/pio/mod.rs | 67 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/embassy-rp/src/pio/mod.rs b/embassy-rp/src/pio/mod.rs index 0d8a94776..f46e664e4 100644 --- a/embassy-rp/src/pio/mod.rs +++ b/embassy-rp/src/pio/mod.rs @@ -12,7 +12,7 @@ use fixed::types::extra::U8; use fixed::FixedU32; use pio::{Program, SideSet, Wrap}; -use crate::dma::{Channel, Transfer, Word}; +use crate::dma::{self, Channel, Transfer, Word}; use crate::gpio::{self, AnyPin, Drive, Level, Pull, SealedPin, SlewRate}; use crate::interrupt::typelevel::{Binding, Handler, Interrupt}; use crate::relocate::RelocatedProgram; @@ -281,6 +281,18 @@ impl<'l, PIO: Instance> Pin<'l, PIO> { }); } + /// Configure the output logic inversion of this pin. + #[inline] + pub fn set_output_inversion(&mut self, invert: bool) { + self.pin.gpio().ctrl().modify(|w| { + w.set_outover(if invert { + pac::io::vals::Outover::INVERT + } else { + pac::io::vals::Outover::NORMAL + }) + }); + } + /// Set the pin's input sync bypass. pub fn set_input_sync_bypass(&mut self, bypass: bool) { let mask = 1 << self.pin(); @@ -360,6 +372,10 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> { FifoInFuture::new(self) } + fn dreq() -> crate::pac::dma::vals::TreqSel { + crate::pac::dma::vals::TreqSel::from(PIO::PIO_NO * 8 + SM as u8 + 4) + } + /// Prepare DMA transfer from RX FIFO. pub fn dma_pull<'a, C: Channel, W: Word>( &'a mut self, @@ -367,7 +383,6 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> { data: &'a mut [W], bswap: bool, ) -> Transfer<'a, C> { - let pio_no = PIO::PIO_NO; let p = ch.regs(); p.write_addr().write_value(data.as_ptr() as u32); p.read_addr().write_value(PIO::PIO.rxf(SM).as_ptr() as u32); @@ -377,8 +392,7 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> { p.trans_count().write(|w| w.set_count(data.len() as u32)); compiler_fence(Ordering::SeqCst); p.ctrl_trig().write(|w| { - // Set RX DREQ for this statemachine - w.set_treq_sel(crate::pac::dma::vals::TreqSel::from(pio_no * 8 + SM as u8 + 4)); + w.set_treq_sel(Self::dreq()); w.set_data_size(W::size()); w.set_chain_to(ch.number()); w.set_incr_read(false); @@ -389,6 +403,36 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> { compiler_fence(Ordering::SeqCst); Transfer::new(ch) } + + /// Prepare a repeated DMA transfer from RX FIFO. + pub fn dma_pull_repeated<'a, C: Channel, W: Word>(&'a mut self, ch: Peri<'a, C>, len: usize) -> Transfer<'a, C> { + // This is the read version of dma::write_repeated. This allows us to + // discard reads from the RX FIFO through DMA. + + // static mut so it gets allocated in RAM + static mut DUMMY: u32 = 0; + + let p = ch.regs(); + p.write_addr().write_value(core::ptr::addr_of_mut!(DUMMY) as u32); + p.read_addr().write_value(PIO::PIO.rxf(SM).as_ptr() as u32); + + #[cfg(feature = "rp2040")] + p.trans_count().write(|w| *w = len as u32); + #[cfg(feature = "_rp235x")] + p.trans_count().write(|w| w.set_count(len as u32)); + + compiler_fence(Ordering::SeqCst); + p.ctrl_trig().write(|w| { + w.set_treq_sel(Self::dreq()); + w.set_data_size(W::size()); + w.set_chain_to(ch.number()); + w.set_incr_read(false); + w.set_incr_write(false); + w.set_en(true); + }); + compiler_fence(Ordering::SeqCst); + Transfer::new(ch) + } } /// Type representing a state machine TX FIFO. @@ -412,7 +456,7 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> { (PIO::PIO.flevel().read().0 >> (SM * 8)) as u8 & 0x0f } - /// Check state machine has stalled on empty TX FIFO. + /// Check if state machine has stalled on empty TX FIFO. pub fn stalled(&self) -> bool { let fdebug = PIO::PIO.fdebug(); let ret = fdebug.read().txstall() & (1 << SM) != 0; @@ -451,6 +495,10 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> { FifoOutFuture::new(self, value) } + fn dreq() -> crate::pac::dma::vals::TreqSel { + crate::pac::dma::vals::TreqSel::from(PIO::PIO_NO * 8 + SM as u8) + } + /// Prepare a DMA transfer to TX FIFO. pub fn dma_push<'a, C: Channel, W: Word>( &'a mut self, @@ -458,7 +506,6 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> { data: &'a [W], bswap: bool, ) -> Transfer<'a, C> { - let pio_no = PIO::PIO_NO; let p = ch.regs(); p.read_addr().write_value(data.as_ptr() as u32); p.write_addr().write_value(PIO::PIO.txf(SM).as_ptr() as u32); @@ -468,8 +515,7 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> { p.trans_count().write(|w| w.set_count(data.len() as u32)); compiler_fence(Ordering::SeqCst); p.ctrl_trig().write(|w| { - // Set TX DREQ for this statemachine - w.set_treq_sel(crate::pac::dma::vals::TreqSel::from(pio_no * 8 + SM as u8)); + w.set_treq_sel(Self::dreq()); w.set_data_size(W::size()); w.set_chain_to(ch.number()); w.set_incr_read(true); @@ -480,6 +526,11 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> { compiler_fence(Ordering::SeqCst); Transfer::new(ch) } + + /// Prepare a repeated DMA transfer to TX FIFO. + pub fn dma_push_repeated<'a, C: Channel, W: Word>(&'a mut self, ch: Peri<'a, C>, len: usize) -> Transfer<'a, C> { + unsafe { dma::write_repeated(ch, PIO::PIO.txf(SM).as_ptr(), len, Self::dreq()) } + } } /// A type representing a single PIO state machine. -- cgit From 4cac3ac1d24d6b651d79bfca8401824c28f5102c Mon Sep 17 00:00:00 2001 From: Adrian Wowk Date: Wed, 2 Jul 2025 20:35:18 -0500 Subject: rp: add new pio spi program This commit adds a new PIO program which implements SPI. This allows you to drive more than 2 SPI buses by using PIO state machines as additional duplex SPI interfaces. The driver supports both blocking and async modes of operation and exclusively uses the DMA for async IO. --- embassy-rp/src/pio_programs/mod.rs | 1 + embassy-rp/src/pio_programs/spi.rs | 433 +++++++++++++++++++++++++++++++++++++ 2 files changed, 434 insertions(+) create mode 100644 embassy-rp/src/pio_programs/spi.rs diff --git a/embassy-rp/src/pio_programs/mod.rs b/embassy-rp/src/pio_programs/mod.rs index 8eac328b3..d05ba3884 100644 --- a/embassy-rp/src/pio_programs/mod.rs +++ b/embassy-rp/src/pio_programs/mod.rs @@ -6,6 +6,7 @@ pub mod i2s; pub mod onewire; pub mod pwm; pub mod rotary_encoder; +pub mod spi; pub mod stepper; pub mod uart; pub mod ws2812; diff --git a/embassy-rp/src/pio_programs/spi.rs b/embassy-rp/src/pio_programs/spi.rs new file mode 100644 index 000000000..27d401fc9 --- /dev/null +++ b/embassy-rp/src/pio_programs/spi.rs @@ -0,0 +1,433 @@ +//! PIO backed SPi drivers + +use core::marker::PhantomData; + +use embassy_futures::join::join; +use embassy_hal_internal::Peri; +use embedded_hal_02::spi::{Phase, Polarity}; +use fixed::{traits::ToFixed, types::extra::U8}; + +use crate::{ + clocks::clk_sys_freq, + dma::{AnyChannel, Channel}, + gpio::Level, + pio::{Common, Direction, Instance, LoadedProgram, PioPin, ShiftDirection, StateMachine}, + spi::{Async, Blocking, Mode}, +}; + +/// This struct represents a uart tx program loaded into pio instruction memory. +pub struct PioSpiProgram<'d, PIO: crate::pio::Instance> { + prg: LoadedProgram<'d, PIO>, +} + +impl<'d, PIO: crate::pio::Instance> PioSpiProgram<'d, PIO> { + /// Load the spi program into the given pio + pub fn new(common: &mut crate::pio::Common<'d, PIO>, phase: Phase) -> Self { + // These PIO programs are taken straight from the datasheet (3.6.1 in + // RP2040 datasheet, 11.6.1 in RP2350 datasheet) + + // Pin assignments: + // - SCK is side-set pin 0 + // - MOSI is OUT pin 0 + // - MISO is IN pin 0 + // + // Autopush and autopull must be enabled, and the serial frame size is set by + // configuring the push/pull threshold. Shift left/right is fine, but you must + // justify the data yourself. This is done most conveniently for frame sizes of + // 8 or 16 bits by using the narrow store replication and narrow load byte + // picking behaviour of RP2040's IO fabric. + + let prg = match phase { + Phase::CaptureOnFirstTransition => { + let prg = pio::pio_asm!( + r#" + .side_set 1 + + ; Clock phase = 0: data is captured on the leading edge of each SCK pulse, and + ; transitions on the trailing edge, or some time before the first leading edge. + + out pins, 1 side 0 [1] ; Stall here on empty (sideset proceeds even if + in pins, 1 side 1 [1] ; instruction stalls, so we stall with SCK low) + "# + ); + + common.load_program(&prg.program) + } + Phase::CaptureOnSecondTransition => { + let prg = pio::pio_asm!( + r#" + .side_set 1 + + ; Clock phase = 1: data transitions on the leading edge of each SCK pulse, and + ; is captured on the trailing edge. + + out x, 1 side 0 ; Stall here on empty (keep SCK deasserted) + mov pins, x side 1 [1] ; Output data, assert SCK (mov pins uses OUT mapping) + in pins, 1 side 0 ; Input data, deassert SCK + "# + ); + + common.load_program(&prg.program) + } + }; + + Self { prg } + } +} + +/// PIO SPI errors. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub enum Error { + // No errors for now +} + +/// PIO based Spi driver. +/// +/// This driver is less flexible than the hardware backed one. Configuration can +/// not be changed at runtime. +pub struct Spi<'d, PIO: Instance, const SM: usize, M: Mode> { + sm: StateMachine<'d, PIO, SM>, + tx_dma: Option>, + rx_dma: Option>, + phantom: PhantomData, +} + +/// PIO SPI configuration. +#[non_exhaustive] +#[derive(Clone)] +pub struct Config { + /// Frequency (Hz). + pub frequency: u32, + /// Polarity. + pub polarity: Polarity, +} + +impl Default for Config { + fn default() -> Self { + Self { + frequency: 1_000_000, + polarity: Polarity::IdleLow, + } + } +} + +impl<'d, PIO: Instance, const SM: usize, M: Mode> Spi<'d, PIO, SM, M> { + #[allow(clippy::too_many_arguments)] + fn new_inner( + pio: &mut Common<'d, PIO>, + mut sm: StateMachine<'d, PIO, SM>, + clk_pin: Peri<'d, impl PioPin>, + mosi_pin: Peri<'d, impl PioPin>, + miso_pin: Peri<'d, impl PioPin>, + tx_dma: Option>, + rx_dma: Option>, + program: &PioSpiProgram<'d, PIO>, + config: Config, + ) -> Self { + let mut clk_pin = pio.make_pio_pin(clk_pin); + let mosi_pin = pio.make_pio_pin(mosi_pin); + let miso_pin = pio.make_pio_pin(miso_pin); + + if let Polarity::IdleHigh = config.polarity { + clk_pin.set_output_inversion(true); + } else { + clk_pin.set_output_inversion(false); + } + + sm.set_pins(Level::Low, &[&clk_pin, &mosi_pin]); + sm.set_pin_dirs(Direction::Out, &[&clk_pin, &mosi_pin]); + sm.set_pin_dirs(Direction::In, &[&miso_pin]); + + let mut cfg = crate::pio::Config::default(); + + cfg.use_program(&program.prg, &[&clk_pin]); + cfg.set_out_pins(&[&mosi_pin]); + cfg.set_in_pins(&[&miso_pin]); + + cfg.shift_in.auto_fill = true; + cfg.shift_in.direction = ShiftDirection::Left; + cfg.shift_in.threshold = 8; + + cfg.shift_out.auto_fill = true; + cfg.shift_out.direction = ShiftDirection::Left; + cfg.shift_out.threshold = 8; + + let sys_freq = clk_sys_freq().to_fixed::>(); + let target_freq = (config.frequency * 4).to_fixed::>(); + cfg.clock_divider = (sys_freq / target_freq).to_fixed(); + + sm.set_config(&cfg); + sm.set_enable(true); + + Self { + sm, + tx_dma, + rx_dma, + phantom: PhantomData, + } + } + + fn blocking_read_u8(&mut self) -> Result { + while self.sm.rx().empty() {} + let value = self.sm.rx().pull() as u8; + + Ok(value) + } + + fn blocking_write_u8(&mut self, v: u8) -> Result<(), Error> { + let value = u32::from_be_bytes([v, 0, 0, 0]); + + while !self.sm.tx().try_push(value) {} + + // need to clear here for flush to work correctly + self.sm.tx().stalled(); + + Ok(()) + } + + /// Read data from SPI blocking execution until done. + pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<(), Error> { + for v in data { + self.blocking_write_u8(0)?; + *v = self.blocking_read_u8()?; + } + self.flush()?; + Ok(()) + } + + /// Write data to SPI blocking execution until done. + pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> { + for v in data { + self.blocking_write_u8(*v)?; + let _ = self.blocking_read_u8()?; + } + self.flush()?; + Ok(()) + } + + /// Transfer data to SPI blocking execution until done. + pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> { + let len = read.len().max(write.len()); + for i in 0..len { + let wb = write.get(i).copied().unwrap_or(0); + self.blocking_write_u8(wb)?; + + let rb = self.blocking_read_u8()?; + if let Some(r) = read.get_mut(i) { + *r = rb; + } + } + self.flush()?; + Ok(()) + } + + /// Transfer data in place to SPI blocking execution until done. + pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> { + for v in data { + self.blocking_write_u8(*v)?; + *v = self.blocking_read_u8()?; + } + self.flush()?; + Ok(()) + } + + /// Block execution until SPI is done. + pub fn flush(&mut self) -> Result<(), Error> { + // Wait for all words in the FIFO to have been pulled by the SM + while !self.sm.tx().empty() {} + + // Wait for last value to be written out to the wire + while !self.sm.tx().stalled() {} + + Ok(()) + } +} + +impl<'d, PIO: Instance, const SM: usize> Spi<'d, PIO, SM, Blocking> { + /// Create an SPI driver in blocking mode. + pub fn new_blocking( + pio: &mut Common<'d, PIO>, + sm: StateMachine<'d, PIO, SM>, + clk: Peri<'d, impl PioPin>, + mosi: Peri<'d, impl PioPin>, + miso: Peri<'d, impl PioPin>, + program: &PioSpiProgram<'d, PIO>, + config: Config, + ) -> Self { + Self::new_inner(pio, sm, clk, mosi, miso, None, None, program, config) + } +} + +impl<'d, PIO: Instance, const SM: usize> Spi<'d, PIO, SM, Async> { + /// Create an SPI driver in async mode supporting DMA operations. + #[allow(clippy::too_many_arguments)] + pub fn new( + pio: &mut Common<'d, PIO>, + sm: StateMachine<'d, PIO, SM>, + clk: Peri<'d, impl PioPin>, + mosi: Peri<'d, impl PioPin>, + miso: Peri<'d, impl PioPin>, + tx_dma: Peri<'d, impl Channel>, + rx_dma: Peri<'d, impl Channel>, + program: &PioSpiProgram<'d, PIO>, + config: Config, + ) -> Self { + Self::new_inner( + pio, + sm, + clk, + mosi, + miso, + Some(tx_dma.into()), + Some(rx_dma.into()), + program, + config, + ) + } + + /// Read data from SPI using DMA. + pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { + let (rx, tx) = self.sm.rx_tx(); + + let len = buffer.len(); + + let rx_ch = self.rx_dma.as_mut().unwrap().reborrow(); + let rx_transfer = rx.dma_pull(rx_ch, buffer, false); + + let tx_ch = self.tx_dma.as_mut().unwrap().reborrow(); + let tx_transfer = tx.dma_push_repeated::<_, u8>(tx_ch, len); + + join(tx_transfer, rx_transfer).await; + + Ok(()) + } + + /// Write data to SPI using DMA. + pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { + let (rx, tx) = self.sm.rx_tx(); + + let rx_ch = self.rx_dma.as_mut().unwrap().reborrow(); + let rx_transfer = rx.dma_pull_repeated::<_, u8>(rx_ch, buffer.len()); + + let tx_ch = self.tx_dma.as_mut().unwrap().reborrow(); + let tx_transfer = tx.dma_push(tx_ch, buffer, false); + + join(tx_transfer, rx_transfer).await; + + Ok(()) + } + + /// Transfer data to SPI using DMA. + pub async fn transfer(&mut self, rx_buffer: &mut [u8], tx_buffer: &[u8]) -> Result<(), Error> { + self.transfer_inner(rx_buffer, tx_buffer).await + } + + /// Transfer data in place to SPI using DMA. + pub async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> { + self.transfer_inner(words, words).await + } + + async fn transfer_inner(&mut self, rx_buffer: *mut [u8], tx_buffer: *const [u8]) -> Result<(), Error> { + let (rx, tx) = self.sm.rx_tx(); + + let mut rx_ch = self.rx_dma.as_mut().unwrap().reborrow(); + let rx_transfer = async { + rx.dma_pull(rx_ch.reborrow(), unsafe { &mut *rx_buffer }, false).await; + + if tx_buffer.len() > rx_buffer.len() { + let read_bytes_len = tx_buffer.len() - rx_buffer.len(); + + rx.dma_pull_repeated::<_, u8>(rx_ch, read_bytes_len).await; + } + }; + + let mut tx_ch = self.tx_dma.as_mut().unwrap().reborrow(); + let tx_transfer = async { + tx.dma_push(tx_ch.reborrow(), unsafe { &*tx_buffer }, false).await; + + if rx_buffer.len() > tx_buffer.len() { + let write_bytes_len = rx_buffer.len() - tx_buffer.len(); + + tx.dma_push_repeated::<_, u8>(tx_ch, write_bytes_len).await; + } + }; + + join(tx_transfer, rx_transfer).await; + + Ok(()) + } +} + +// ==================== + +impl<'d, PIO: Instance, const SM: usize, M: Mode> embedded_hal_02::blocking::spi::Transfer for Spi<'d, PIO, SM, M> { + type Error = Error; + fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { + self.blocking_transfer_in_place(words)?; + Ok(words) + } +} + +impl<'d, PIO: Instance, const SM: usize, M: Mode> embedded_hal_02::blocking::spi::Write for Spi<'d, PIO, SM, M> { + type Error = Error; + + fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(words) + } +} + +impl embedded_hal_1::spi::Error for Error { + fn kind(&self) -> embedded_hal_1::spi::ErrorKind { + match *self {} + } +} + +impl<'d, PIO: Instance, const SM: usize, M: Mode> embedded_hal_1::spi::ErrorType for Spi<'d, PIO, SM, M> { + type Error = Error; +} + +impl<'d, PIO: Instance, const SM: usize, M: Mode> embedded_hal_1::spi::SpiBus for Spi<'d, PIO, SM, M> { + fn flush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + + fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_transfer(words, &[]) + } + + fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(words) + } + + fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { + self.blocking_transfer(read, write) + } + + fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_transfer_in_place(words) + } +} + +impl<'d, PIO: Instance, const SM: usize> embedded_hal_async::spi::SpiBus for Spi<'d, PIO, SM, Async> { + async fn flush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + + async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { + self.write(words).await + } + + async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { + self.read(words).await + } + + async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { + self.transfer(read, write).await + } + + async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { + self.transfer_in_place(words).await + } +} -- cgit From 236662c748eab43a701bf4f43570b191ec2c1158 Mon Sep 17 00:00:00 2001 From: Adrian Wowk Date: Wed, 2 Jul 2025 20:53:26 -0500 Subject: rp: add pio spi examples --- examples/rp/src/bin/pio_spi.rs | 63 ++++++++++++++++++++++++++++++++++ examples/rp/src/bin/pio_spi_async.rs | 65 ++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 examples/rp/src/bin/pio_spi.rs create mode 100644 examples/rp/src/bin/pio_spi_async.rs diff --git a/examples/rp/src/bin/pio_spi.rs b/examples/rp/src/bin/pio_spi.rs new file mode 100644 index 000000000..1fbe235e5 --- /dev/null +++ b/examples/rp/src/bin/pio_spi.rs @@ -0,0 +1,63 @@ +//! This example shows how to use a PIO state machine as an additional SPI +//! (Serial Peripheral Interface) on the RP2040 chip. No specific hardware is +//! specified in this example. +//! +//! If you connect pin 6 and 7 you should get the same data back. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::{ + bind_interrupts, + peripherals::PIO0, + pio, + pio_programs::spi::{Config, PioSpiProgram, Spi}, + spi::Phase, +}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => pio::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + info!("Hello World!"); + + // These pins are routed to differnet hardware SPI peripherals, but we can + // use them together regardless + let mosi = p.PIN_6; // SPI0 SCLK + let miso = p.PIN_7; // SPI0 MOSI + let clk = p.PIN_8; // SPI1 MISO + + let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs); + + // The PIO program must be configured with the clock phase + let program = PioSpiProgram::new(&mut common, Phase::CaptureOnFirstTransition); + + // Construct an SPI driver backed by a PIO state machine + let mut spi = Spi::new_blocking( + &mut common, + sm0, + clk, + mosi, + miso, + &program, + // Only the frequency and polarity are set here + Config::default(), + ); + + loop { + let tx_buf = [1_u8, 2, 3, 4, 5, 6]; + let mut rx_buf = [0_u8; 6]; + + spi.blocking_transfer(&mut rx_buf, &tx_buf).unwrap(); + info!("{:?}", rx_buf); + + Timer::after_secs(1).await; + } +} diff --git a/examples/rp/src/bin/pio_spi_async.rs b/examples/rp/src/bin/pio_spi_async.rs new file mode 100644 index 000000000..5abf6fc71 --- /dev/null +++ b/examples/rp/src/bin/pio_spi_async.rs @@ -0,0 +1,65 @@ +//! This example shows how to use a PIO state machine as an additional SPI +//! (Serial Peripheral Interface) on the RP2040 chip. No specific hardware is +//! specified in this example. +//! +//! If you connect pin 6 and 7 you should get the same data back. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::{ + bind_interrupts, + peripherals::PIO0, + pio, + pio_programs::spi::{Config, PioSpiProgram, Spi}, + spi::Phase, +}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => pio::InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + info!("Hello World!"); + + // These pins are routed to differnet hardware SPI peripherals, but we can + // use them together regardless + let mosi = p.PIN_6; // SPI0 SCLK + let miso = p.PIN_7; // SPI0 MOSI + let clk = p.PIN_8; // SPI1 MISO + + let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs); + + // The PIO program must be configured with the clock phase + let program = PioSpiProgram::new(&mut common, Phase::CaptureOnFirstTransition); + + // Construct an SPI driver backed by a PIO state machine + let mut spi = Spi::new( + &mut common, + sm0, + clk, + mosi, + miso, + p.DMA_CH0, + p.DMA_CH1, + &program, + // Only the frequency and polarity are set here + Config::default(), + ); + + loop { + let tx_buf = [1_u8, 2, 3, 4, 5, 6]; + let mut rx_buf = [0_u8; 6]; + + spi.transfer(&mut rx_buf, &tx_buf).await.unwrap(); + info!("{:?}", rx_buf); + + Timer::after_secs(1).await; + } +} -- cgit From 83b42e0db620b7fc2364763b452b346b711e8d9f Mon Sep 17 00:00:00 2001 From: Adrian Wowk Date: Wed, 2 Jul 2025 21:18:44 -0500 Subject: style: cleanup with rustfmt --- embassy-rp/src/pio_programs/spi.rs | 21 ++++++++++----------- examples/rp/src/bin/pio_spi.rs | 11 ++++------- examples/rp/src/bin/pio_spi_async.rs | 13 +++++-------- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/embassy-rp/src/pio_programs/spi.rs b/embassy-rp/src/pio_programs/spi.rs index 27d401fc9..a1b36c1c8 100644 --- a/embassy-rp/src/pio_programs/spi.rs +++ b/embassy-rp/src/pio_programs/spi.rs @@ -5,24 +5,23 @@ use core::marker::PhantomData; use embassy_futures::join::join; use embassy_hal_internal::Peri; use embedded_hal_02::spi::{Phase, Polarity}; -use fixed::{traits::ToFixed, types::extra::U8}; +use fixed::traits::ToFixed; +use fixed::types::extra::U8; -use crate::{ - clocks::clk_sys_freq, - dma::{AnyChannel, Channel}, - gpio::Level, - pio::{Common, Direction, Instance, LoadedProgram, PioPin, ShiftDirection, StateMachine}, - spi::{Async, Blocking, Mode}, -}; +use crate::clocks::clk_sys_freq; +use crate::dma::{AnyChannel, Channel}; +use crate::gpio::Level; +use crate::pio::{Common, Direction, Instance, LoadedProgram, PioPin, ShiftDirection, StateMachine}; +use crate::spi::{Async, Blocking, Mode}; /// This struct represents a uart tx program loaded into pio instruction memory. -pub struct PioSpiProgram<'d, PIO: crate::pio::Instance> { +pub struct PioSpiProgram<'d, PIO: Instance> { prg: LoadedProgram<'d, PIO>, } -impl<'d, PIO: crate::pio::Instance> PioSpiProgram<'d, PIO> { +impl<'d, PIO: Instance> PioSpiProgram<'d, PIO> { /// Load the spi program into the given pio - pub fn new(common: &mut crate::pio::Common<'d, PIO>, phase: Phase) -> Self { + pub fn new(common: &mut Common<'d, PIO>, phase: Phase) -> Self { // These PIO programs are taken straight from the datasheet (3.6.1 in // RP2040 datasheet, 11.6.1 in RP2350 datasheet) diff --git a/examples/rp/src/bin/pio_spi.rs b/examples/rp/src/bin/pio_spi.rs index 1fbe235e5..0164e4c81 100644 --- a/examples/rp/src/bin/pio_spi.rs +++ b/examples/rp/src/bin/pio_spi.rs @@ -9,13 +9,10 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::{ - bind_interrupts, - peripherals::PIO0, - pio, - pio_programs::spi::{Config, PioSpiProgram, Spi}, - spi::Phase, -}; +use embassy_rp::peripherals::PIO0; +use embassy_rp::pio_programs::spi::{Config, PioSpiProgram, Spi}; +use embassy_rp::spi::Phase; +use embassy_rp::{bind_interrupts, pio}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/pio_spi_async.rs b/examples/rp/src/bin/pio_spi_async.rs index 5abf6fc71..1dbdff609 100644 --- a/examples/rp/src/bin/pio_spi_async.rs +++ b/examples/rp/src/bin/pio_spi_async.rs @@ -9,13 +9,10 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::{ - bind_interrupts, - peripherals::PIO0, - pio, - pio_programs::spi::{Config, PioSpiProgram, Spi}, - spi::Phase, -}; +use embassy_rp::peripherals::PIO0; +use embassy_rp::pio_programs::spi::{Config, PioSpiProgram, Spi}; +use embassy_rp::spi::Phase; +use embassy_rp::{bind_interrupts, pio}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; @@ -32,7 +29,7 @@ async fn main(_spawner: Spawner) { // use them together regardless let mosi = p.PIN_6; // SPI0 SCLK let miso = p.PIN_7; // SPI0 MOSI - let clk = p.PIN_8; // SPI1 MISO + let clk = p.PIN_8; // SPI1 MISO let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs); -- cgit From 62ff0194f4b7413b17dbc69813ec205638248aa7 Mon Sep 17 00:00:00 2001 From: Adrian Wowk Date: Fri, 18 Jul 2025 19:19:27 -0500 Subject: rp: add pio spi runtime reconfiguration --- embassy-rp/src/pio_programs/spi.rs | 119 +++++++++++++++++++++++------------ examples/rp/src/bin/pio_spi.rs | 20 ++---- examples/rp/src/bin/pio_spi_async.rs | 10 +-- 3 files changed, 87 insertions(+), 62 deletions(-) diff --git a/embassy-rp/src/pio_programs/spi.rs b/embassy-rp/src/pio_programs/spi.rs index a1b36c1c8..6b97cd0f3 100644 --- a/embassy-rp/src/pio_programs/spi.rs +++ b/embassy-rp/src/pio_programs/spi.rs @@ -11,12 +11,13 @@ use fixed::types::extra::U8; use crate::clocks::clk_sys_freq; use crate::dma::{AnyChannel, Channel}; use crate::gpio::Level; -use crate::pio::{Common, Direction, Instance, LoadedProgram, PioPin, ShiftDirection, StateMachine}; -use crate::spi::{Async, Blocking, Mode}; +use crate::pio::{Common, Direction, Instance, LoadedProgram, Pin, PioPin, ShiftDirection, StateMachine}; +use crate::spi::{Async, Blocking, Config, Mode}; -/// This struct represents a uart tx program loaded into pio instruction memory. -pub struct PioSpiProgram<'d, PIO: Instance> { +/// This struct represents an SPI program loaded into pio instruction memory. +struct PioSpiProgram<'d, PIO: Instance> { prg: LoadedProgram<'d, PIO>, + phase: Phase, } impl<'d, PIO: Instance> PioSpiProgram<'d, PIO> { @@ -30,11 +31,11 @@ impl<'d, PIO: Instance> PioSpiProgram<'d, PIO> { // - MOSI is OUT pin 0 // - MISO is IN pin 0 // - // Autopush and autopull must be enabled, and the serial frame size is set by + // Auto-push and auto-pull must be enabled, and the serial frame size is set by // configuring the push/pull threshold. Shift left/right is fine, but you must // justify the data yourself. This is done most conveniently for frame sizes of // 8 or 16 bits by using the narrow store replication and narrow load byte - // picking behaviour of RP2040's IO fabric. + // picking behavior of RP2040's IO fabric. let prg = match phase { Phase::CaptureOnFirstTransition => { @@ -60,9 +61,9 @@ impl<'d, PIO: Instance> PioSpiProgram<'d, PIO> { ; Clock phase = 1: data transitions on the leading edge of each SCK pulse, and ; is captured on the trailing edge. - out x, 1 side 0 ; Stall here on empty (keep SCK deasserted) + out x, 1 side 0 ; Stall here on empty (keep SCK de-asserted) mov pins, x side 1 [1] ; Output data, assert SCK (mov pins uses OUT mapping) - in pins, 1 side 0 ; Input data, deassert SCK + in pins, 1 side 0 ; Input data, de-assert SCK "# ); @@ -70,7 +71,7 @@ impl<'d, PIO: Instance> PioSpiProgram<'d, PIO> { } }; - Self { prg } + Self { prg, phase } } } @@ -83,35 +84,19 @@ pub enum Error { } /// PIO based Spi driver. -/// -/// This driver is less flexible than the hardware backed one. Configuration can -/// not be changed at runtime. +/// Unlike other PIO programs, the PIO SPI driver owns and holds a reference to +/// the PIO memory it uses. This is so that it can be reconfigured at runtime if +/// desired. pub struct Spi<'d, PIO: Instance, const SM: usize, M: Mode> { sm: StateMachine<'d, PIO, SM>, + cfg: crate::pio::Config<'d, PIO>, + program: Option>, + clk_pin: Pin<'d, PIO>, tx_dma: Option>, rx_dma: Option>, phantom: PhantomData, } -/// PIO SPI configuration. -#[non_exhaustive] -#[derive(Clone)] -pub struct Config { - /// Frequency (Hz). - pub frequency: u32, - /// Polarity. - pub polarity: Polarity, -} - -impl Default for Config { - fn default() -> Self { - Self { - frequency: 1_000_000, - polarity: Polarity::IdleLow, - } - } -} - impl<'d, PIO: Instance, const SM: usize, M: Mode> Spi<'d, PIO, SM, M> { #[allow(clippy::too_many_arguments)] fn new_inner( @@ -122,9 +107,10 @@ impl<'d, PIO: Instance, const SM: usize, M: Mode> Spi<'d, PIO, SM, M> { miso_pin: Peri<'d, impl PioPin>, tx_dma: Option>, rx_dma: Option>, - program: &PioSpiProgram<'d, PIO>, config: Config, ) -> Self { + let program = PioSpiProgram::new(pio, config.phase); + let mut clk_pin = pio.make_pio_pin(clk_pin); let mosi_pin = pio.make_pio_pin(mosi_pin); let miso_pin = pio.make_pio_pin(miso_pin); @@ -153,15 +139,16 @@ impl<'d, PIO: Instance, const SM: usize, M: Mode> Spi<'d, PIO, SM, M> { cfg.shift_out.direction = ShiftDirection::Left; cfg.shift_out.threshold = 8; - let sys_freq = clk_sys_freq().to_fixed::>(); - let target_freq = (config.frequency * 4).to_fixed::>(); - cfg.clock_divider = (sys_freq / target_freq).to_fixed(); + cfg.clock_divider = calculate_clock_divider(config.frequency); sm.set_config(&cfg); sm.set_enable(true); Self { sm, + program: Some(program), + cfg, + clk_pin, tx_dma, rx_dma, phantom: PhantomData, @@ -242,6 +229,63 @@ impl<'d, PIO: Instance, const SM: usize, M: Mode> Spi<'d, PIO, SM, M> { Ok(()) } + + /// Set SPI frequency. + pub fn set_frequency(&mut self, freq: u32) { + self.sm.set_enable(false); + + let divider = calculate_clock_divider(freq); + + // save into the config for later but dont use sm.set_config() since + // that operation is relatively more expensive than just setting the + // clock divider + self.cfg.clock_divider = divider; + self.sm.set_clock_divider(divider); + + self.sm.set_enable(true); + } + + /// Set SPI config. + /// + /// This operation will panic if the PIO program needs to be reloaded and + /// there is insufficient room. This is unlikely since the programs for each + /// phase only differ in size by a single instruction. + pub fn set_config(&mut self, pio: &mut Common<'d, PIO>, config: &Config) { + self.sm.set_enable(false); + + self.cfg.clock_divider = calculate_clock_divider(config.frequency); + + if let Polarity::IdleHigh = config.polarity { + self.clk_pin.set_output_inversion(true); + } else { + self.clk_pin.set_output_inversion(false); + } + + if self.program.as_ref().unwrap().phase != config.phase { + let old_program = self.program.take().unwrap(); + + // SAFETY: the state machine is disabled while this happens + unsafe { pio.free_instr(old_program.prg.used_memory) }; + + let new_program = PioSpiProgram::new(pio, config.phase); + + self.cfg.use_program(&new_program.prg, &[&self.clk_pin]); + self.program = Some(new_program); + } + + self.sm.set_config(&self.cfg); + self.sm.restart(); + + self.sm.set_enable(true); + } +} + +fn calculate_clock_divider(frequency_hz: u32) -> fixed::FixedU32 { + // we multiply by 4 since each clock period is equal to 4 instructions + + let sys_freq = clk_sys_freq().to_fixed::>(); + let target_freq = (frequency_hz * 4).to_fixed::>(); + (sys_freq / target_freq).to_fixed() } impl<'d, PIO: Instance, const SM: usize> Spi<'d, PIO, SM, Blocking> { @@ -252,10 +296,9 @@ impl<'d, PIO: Instance, const SM: usize> Spi<'d, PIO, SM, Blocking> { clk: Peri<'d, impl PioPin>, mosi: Peri<'d, impl PioPin>, miso: Peri<'d, impl PioPin>, - program: &PioSpiProgram<'d, PIO>, config: Config, ) -> Self { - Self::new_inner(pio, sm, clk, mosi, miso, None, None, program, config) + Self::new_inner(pio, sm, clk, mosi, miso, None, None, config) } } @@ -270,7 +313,6 @@ impl<'d, PIO: Instance, const SM: usize> Spi<'d, PIO, SM, Async> { miso: Peri<'d, impl PioPin>, tx_dma: Peri<'d, impl Channel>, rx_dma: Peri<'d, impl Channel>, - program: &PioSpiProgram<'d, PIO>, config: Config, ) -> Self { Self::new_inner( @@ -281,7 +323,6 @@ impl<'d, PIO: Instance, const SM: usize> Spi<'d, PIO, SM, Async> { miso, Some(tx_dma.into()), Some(rx_dma.into()), - program, config, ) } diff --git a/examples/rp/src/bin/pio_spi.rs b/examples/rp/src/bin/pio_spi.rs index 0164e4c81..4218327ec 100644 --- a/examples/rp/src/bin/pio_spi.rs +++ b/examples/rp/src/bin/pio_spi.rs @@ -10,8 +10,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio_programs::spi::{Config, PioSpiProgram, Spi}; -use embassy_rp::spi::Phase; +use embassy_rp::pio_programs::spi::Spi; +use embassy_rp::spi::Config; use embassy_rp::{bind_interrupts, pio}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; @@ -25,7 +25,7 @@ async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); info!("Hello World!"); - // These pins are routed to differnet hardware SPI peripherals, but we can + // These pins are routed to different hardware SPI peripherals, but we can // use them together regardless let mosi = p.PIN_6; // SPI0 SCLK let miso = p.PIN_7; // SPI0 MOSI @@ -33,20 +33,8 @@ async fn main(_spawner: Spawner) { let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs); - // The PIO program must be configured with the clock phase - let program = PioSpiProgram::new(&mut common, Phase::CaptureOnFirstTransition); - // Construct an SPI driver backed by a PIO state machine - let mut spi = Spi::new_blocking( - &mut common, - sm0, - clk, - mosi, - miso, - &program, - // Only the frequency and polarity are set here - Config::default(), - ); + let mut spi = Spi::new_blocking(&mut common, sm0, clk, mosi, miso, Config::default()); loop { let tx_buf = [1_u8, 2, 3, 4, 5, 6]; diff --git a/examples/rp/src/bin/pio_spi_async.rs b/examples/rp/src/bin/pio_spi_async.rs index 1dbdff609..74a2dd11b 100644 --- a/examples/rp/src/bin/pio_spi_async.rs +++ b/examples/rp/src/bin/pio_spi_async.rs @@ -10,8 +10,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio_programs::spi::{Config, PioSpiProgram, Spi}; -use embassy_rp::spi::Phase; +use embassy_rp::pio_programs::spi::Spi; +use embassy_rp::spi::Config; use embassy_rp::{bind_interrupts, pio}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; @@ -25,7 +25,7 @@ async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); info!("Hello World!"); - // These pins are routed to differnet hardware SPI peripherals, but we can + // These pins are routed to different hardware SPI peripherals, but we can // use them together regardless let mosi = p.PIN_6; // SPI0 SCLK let miso = p.PIN_7; // SPI0 MOSI @@ -33,9 +33,6 @@ async fn main(_spawner: Spawner) { let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs); - // The PIO program must be configured with the clock phase - let program = PioSpiProgram::new(&mut common, Phase::CaptureOnFirstTransition); - // Construct an SPI driver backed by a PIO state machine let mut spi = Spi::new( &mut common, @@ -46,7 +43,6 @@ async fn main(_spawner: Spawner) { p.DMA_CH0, p.DMA_CH1, &program, - // Only the frequency and polarity are set here Config::default(), ); -- cgit From 451625ff559661c0cc30ca8a70dd0ccee79ba07b Mon Sep 17 00:00:00 2001 From: Adrian Wowk Date: Fri, 18 Jul 2025 19:23:49 -0500 Subject: rp: fix pio spi async example --- examples/rp/src/bin/pio_spi_async.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/rp/src/bin/pio_spi_async.rs b/examples/rp/src/bin/pio_spi_async.rs index 74a2dd11b..18b57d26e 100644 --- a/examples/rp/src/bin/pio_spi_async.rs +++ b/examples/rp/src/bin/pio_spi_async.rs @@ -42,7 +42,6 @@ async fn main(_spawner: Spawner) { miso, p.DMA_CH0, p.DMA_CH1, - &program, Config::default(), ); -- cgit From 51373065752693c1e49d8d9df7c4452d0f62b7f3 Mon Sep 17 00:00:00 2001 From: Adrian Wowk Date: Wed, 20 Aug 2025 13:40:14 -0500 Subject: rp: move pio pin configs after set_config This is needed for the program to work correctly on rp235xb when using the higher pin numbers. --- embassy-rp/src/pio_programs/spi.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/embassy-rp/src/pio_programs/spi.rs b/embassy-rp/src/pio_programs/spi.rs index 6b97cd0f3..b10fc6628 100644 --- a/embassy-rp/src/pio_programs/spi.rs +++ b/embassy-rp/src/pio_programs/spi.rs @@ -121,10 +121,6 @@ impl<'d, PIO: Instance, const SM: usize, M: Mode> Spi<'d, PIO, SM, M> { clk_pin.set_output_inversion(false); } - sm.set_pins(Level::Low, &[&clk_pin, &mosi_pin]); - sm.set_pin_dirs(Direction::Out, &[&clk_pin, &mosi_pin]); - sm.set_pin_dirs(Direction::In, &[&miso_pin]); - let mut cfg = crate::pio::Config::default(); cfg.use_program(&program.prg, &[&clk_pin]); @@ -142,6 +138,11 @@ impl<'d, PIO: Instance, const SM: usize, M: Mode> Spi<'d, PIO, SM, M> { cfg.clock_divider = calculate_clock_divider(config.frequency); sm.set_config(&cfg); + + sm.set_pins(Level::Low, &[&clk_pin, &mosi_pin]); + sm.set_pin_dirs(Direction::Out, &[&clk_pin, &mosi_pin]); + sm.set_pin_dirs(Direction::In, &[&miso_pin]); + sm.set_enable(true); Self { -- cgit From 815ba8aa7507d0aa27dfb3f3823793e3567719f8 Mon Sep 17 00:00:00 2001 From: Adrian Wowk Date: Wed, 20 Aug 2025 13:44:56 -0500 Subject: rp: read pio gpiobase in set_pins and set_pin_dirs --- embassy-rp/src/pio/mod.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/embassy-rp/src/pio/mod.rs b/embassy-rp/src/pio/mod.rs index f46e664e4..5f554dfe3 100644 --- a/embassy-rp/src/pio/mod.rs +++ b/embassy-rp/src/pio/mod.rs @@ -977,13 +977,27 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { self.set_enable(enabled); } + #[cfg(feature = "rp2040")] + fn pin_base() -> u8 { + 0 + } + + #[cfg(feature = "_rp235x")] + fn pin_base() -> u8 { + if PIO::PIO.gpiobase().read().gpiobase() { + 16 + } else { + 0 + } + } + /// Sets pin directions. This pauses the current state machine to run `SET` commands /// and temporarily unsets the `OUT_STICKY` bit. pub fn set_pin_dirs(&mut self, dir: Direction, pins: &[&Pin<'d, PIO>]) { self.with_paused(|sm| { for pin in pins { Self::this_sm().pinctrl().write(|w| { - w.set_set_base(pin.pin()); + w.set_set_base(pin.pin() - Self::pin_base()); w.set_set_count(1); }); // SET PINDIRS, (dir) @@ -998,7 +1012,7 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { self.with_paused(|sm| { for pin in pins { Self::this_sm().pinctrl().write(|w| { - w.set_set_base(pin.pin()); + w.set_set_base(pin.pin() - Self::pin_base()); w.set_set_count(1); }); // SET PINS, (dir) @@ -1361,6 +1375,7 @@ impl<'d, PIO: Instance> Pio<'d, PIO> { PIO::state().users.store(5, Ordering::Release); PIO::state().used_pins.store(0, Ordering::Release); PIO::Interrupt::unpend(); + unsafe { PIO::Interrupt::enable() }; Self { common: Common { -- cgit From 241129c569023dc71d0025cdc41bcfe40418e7b8 Mon Sep 17 00:00:00 2001 From: Thor McAvenia Date: Fri, 16 May 2025 00:09:10 -0700 Subject: Add PioI2sIn, PioI2sInProgram, and example binary --- embassy-rp/CHANGELOG.md | 3 ++ embassy-rp/src/pio_programs/i2s.rs | 96 +++++++++++++++++++++++++++++++++-- examples/rp235x/src/bin/pio_i2s_rx.rs | 81 +++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 examples/rp235x/src/bin/pio_i2s_rx.rs diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md index ebdc3e1c8..b50d41dd1 100644 --- a/embassy-rp/CHANGELOG.md +++ b/embassy-rp/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- Add PIO SPI +- Add PIO I2S input + ## 0.8.0 - 2025-08-26 ## 0.7.1 - 2025-08-26 diff --git a/embassy-rp/src/pio_programs/i2s.rs b/embassy-rp/src/pio_programs/i2s.rs index 7ceed3fa6..2382a3f9f 100644 --- a/embassy-rp/src/pio_programs/i2s.rs +++ b/embassy-rp/src/pio_programs/i2s.rs @@ -1,13 +1,101 @@ -//! Pio backed I2s output +//! Pio backed I2s output and output drivers use fixed::traits::ToFixed; use crate::dma::{AnyChannel, Channel, Transfer}; +use crate::gpio::Pull; use crate::pio::{ Common, Config, Direction, FifoJoin, Instance, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, StateMachine, }; use crate::Peri; +/// This struct represents an i2s receiver & controller driver program +pub struct PioI2sInProgram<'d, PIO: Instance> { + prg: LoadedProgram<'d, PIO>, +} + +impl<'d, PIO: Instance> PioI2sInProgram<'d, PIO> { + /// Load the input program into the given pio + pub fn new(common: &mut Common<'d, PIO>) -> Self { + let prg = pio::pio_asm! { + ".side_set 2", + " set x, 14 side 0b01", + "left_data:", + " in pins, 1 side 0b00", // read one left-channel bit from SD + " jmp x-- left_data side 0b01", + " in pins, 1 side 0b10", // ws changes 1 clock before MSB + " set x, 14 side 0b11", + "right_data:", + " in pins, 1 side 0b10", + " jmp x-- right_data side 0b11", + " in pins, 1 side 0b00" // ws changes 1 clock before ms + }; + let prg = common.load_program(&prg.program); + Self { prg } + } +} + +/// Pio backed I2s input driver +pub struct PioI2sIn<'d, P: Instance, const S: usize> { + dma: Peri<'d, AnyChannel>, + sm: StateMachine<'d, P, S>, +} + +impl<'d, P: Instance, const S: usize> PioI2sIn<'d, P, S> { + /// Configure a state machine to act as both the controller (provider of SCK and WS) and receiver (of SD) for an I2S signal + pub fn new( + common: &mut Common<'d, P>, + mut sm: StateMachine<'d, P, S>, + dma: Peri<'d, impl Channel>, + // Whether or not to use the MCU's internal pull-down resistor, as the + // Pico 2 is known to have problems with the inbuilt pulldowns, many + // opt to just use an external pull down resistor to meet requirements of common + // i2s microphones such as the INMP441 + data_pulldown: bool, + data_pin: Peri<'d, impl PioPin>, + bit_clock_pin: Peri<'d, impl PioPin>, + lr_clock_pin: Peri<'d, impl PioPin>, + sample_rate: u32, + bit_depth: u32, + channels: u32, + program: &PioI2sInProgram<'d, P>, + ) -> Self { + let mut data_pin = common.make_pio_pin(data_pin); + if data_pulldown { + data_pin.set_pull(Pull::Down); + } + let bit_clock_pin = common.make_pio_pin(bit_clock_pin); + let left_right_clock_pin = common.make_pio_pin(lr_clock_pin); + + let cfg = { + let mut cfg = Config::default(); + cfg.use_program(&program.prg, &[&bit_clock_pin, &left_right_clock_pin]); + cfg.set_in_pins(&[&data_pin]); + let clock_frequency = sample_rate * bit_depth * channels; + cfg.clock_divider = (crate::clocks::clk_sys_freq() as f64 / clock_frequency as f64 / 2.).to_fixed(); + cfg.shift_in = ShiftConfig { + threshold: 32, + direction: ShiftDirection::Left, + auto_fill: true, + }; + // join fifos to have twice the time to start the next dma transfer + cfg.fifo_join = FifoJoin::RxOnly; // both control signals are sent via side-setting + cfg + }; + sm.set_config(&cfg); + sm.set_pin_dirs(Direction::In, &[&data_pin]); + sm.set_pin_dirs(Direction::Out, &[&left_right_clock_pin, &bit_clock_pin]); + sm.set_enable(true); + + Self { dma: dma.into(), sm } + } + + /// Return an in-prograss dma transfer future. Awaiting it will guarentee a complete transfer. + pub fn read<'b>(&'b mut self, buff: &'b mut [u32]) -> Transfer<'b, AnyChannel> { + self.sm.rx().dma_pull(self.dma.reborrow(), buff, false) + } +} + /// This struct represents an i2s output driver program /// /// The sample bit-depth is set through scratch register `Y`. @@ -26,12 +114,12 @@ impl<'d, PIO: Instance> PioI2sOutProgram<'d, PIO> { "left_data:", " out pins, 1 side 0b00", " jmp x-- left_data side 0b01", - " out pins 1 side 0b10", + " out pins, 1 side 0b10", " mov x, y side 0b11", "right_data:", - " out pins 1 side 0b10", + " out pins, 1 side 0b10", " jmp x-- right_data side 0b11", - " out pins 1 side 0b00", + " out pins, 1 side 0b00", ); let prg = common.load_program(&prg.program); diff --git a/examples/rp235x/src/bin/pio_i2s_rx.rs b/examples/rp235x/src/bin/pio_i2s_rx.rs new file mode 100644 index 000000000..c3f505b13 --- /dev/null +++ b/examples/rp235x/src/bin/pio_i2s_rx.rs @@ -0,0 +1,81 @@ +//! This example shows receiving audio from a connected I2S microphone (or other audio source) +//! using the PIO module of the RP235x. +//! +//! +//! Connect the i2s microphone as follows: +//! bclk : GPIO 18 +//! lrc : GPIO 19 +//! din : GPIO 20 +//! Then hold down the boot select button to begin receiving audio. Received I2S words will be written to +//! buffers for the left and right channels for use in your application, whether that's storage or +//! further processing +//! +//! Note the const USE_ONBOARD_PULLDOWN is by default set to false, meaning an external +//! pull-down resistor is being used on the data pin if required by the mic being used. + +#![no_std] +#![no_main] +use core::mem; + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::bind_interrupts; +use embassy_rp::peripherals::PIO0; +use embassy_rp::pio::{InterruptHandler, Pio}; +use embassy_rp::pio_programs::i2s::{PioI2sIn, PioI2sInProgram}; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + +const SAMPLE_RATE: u32 = 48_000; +const BIT_DEPTH: u32 = 16; +const CHANNELS: u32 = 2; +const USE_ONBOARD_PULLDOWN: bool = false; // whether or not to use the onboard pull-down resistor, + // which has documented issues on many RP235x boards +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + + // Setup pio state machine for i2s input + let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs); + + let bit_clock_pin = p.PIN_18; + let left_right_clock_pin = p.PIN_19; + let data_pin = p.PIN_20; + + let program = PioI2sInProgram::new(&mut common); + let mut i2s = PioI2sIn::new( + &mut common, + sm0, + p.DMA_CH0, + USE_ONBOARD_PULLDOWN, + data_pin, + bit_clock_pin, + left_right_clock_pin, + SAMPLE_RATE, + BIT_DEPTH, + CHANNELS, + &program, + ); + + // create two audio buffers (back and front) which will take turns being + // filled with new audio data from the PIO fifo using DMA + const BUFFER_SIZE: usize = 960; + static DMA_BUFFER: StaticCell<[u32; BUFFER_SIZE * 2]> = StaticCell::new(); + let dma_buffer = DMA_BUFFER.init_with(|| [0u32; BUFFER_SIZE * 2]); + let (mut back_buffer, mut front_buffer) = dma_buffer.split_at_mut(BUFFER_SIZE); + + loop { + // trigger transfer of front buffer data to the pio fifo + // but don't await the returned future, yet + let dma_future = i2s.read(front_buffer); + // now await the dma future. once the dma finishes, the next buffer needs to be queued + // within DMA_DEPTH / SAMPLE_RATE = 8 / 48000 seconds = 166us + dma_future.await; + info!("Received I2S data word: {:?}", &front_buffer); + mem::swap(&mut back_buffer, &mut front_buffer); + } +} -- cgit From a6562c4f033432e40970aafe82f33c5138adf84e Mon Sep 17 00:00:00 2001 From: Fabian Wolter Date: Mon, 21 Jul 2025 07:57:49 +0200 Subject: Add STM32F1 AFIO remap --- ci.sh | 6 +- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/build.rs | 125 ++- embassy-stm32/src/can/bxcan/mod.rs | 12 +- embassy-stm32/src/eth/mod.rs | 32 +- embassy-stm32/src/eth/v1/mod.rs | 54 +- embassy-stm32/src/eth/v2/mod.rs | 50 +- embassy-stm32/src/gpio.rs | 11 + embassy-stm32/src/i2c/mod.rs | 16 +- embassy-stm32/src/i2s.rs | 46 +- embassy-stm32/src/macros.rs | 63 +- embassy-stm32/src/spi/mod.rs | 62 +- embassy-stm32/src/timer/complementary_pwm.rs | 34 +- embassy-stm32/src/timer/input_capture.rs | 21 +- embassy-stm32/src/timer/mod.rs | 31 +- embassy-stm32/src/timer/one_pulse.rs | 10 +- embassy-stm32/src/timer/pwm_input.rs | 4 + embassy-stm32/src/timer/qei.rs | 12 +- embassy-stm32/src/timer/simple_pwm.rs | 23 +- embassy-stm32/src/usart/buffered.rs | 48 +- embassy-stm32/src/usart/mod.rs | 116 +-- tests/stm32/Cargo.toml | 12 +- tests/stm32/src/bin/afio.rs | 1156 ++++++++++++++++++++++++++ tests/stm32/src/common.rs | 2 +- 24 files changed, 1679 insertions(+), 268 deletions(-) create mode 100644 tests/stm32/src/bin/afio.rs diff --git a/ci.sh b/ci.sh index e1197f397..50fb3e13d 100755 --- a/ci.sh +++ b/ci.sh @@ -311,7 +311,9 @@ cargo batch \ --- build --release --manifest-path examples/boot/bootloader/stm32wba-dfu/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-stm32/stm32wba65ri,verify \ --- build --release --manifest-path examples/boot/bootloader/stm32-dual-bank/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32h743zi \ --- build --release --manifest-path examples/wasm/Cargo.toml --target wasm32-unknown-unknown --artifact-dir out/examples/wasm \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f100rd --artifact-dir out/tests/stm32f100rd \ --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f103c8 --artifact-dir out/tests/stm32f103c8 \ + --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f107vc --artifact-dir out/tests/stm32f107vc \ --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi --artifact-dir out/tests/stm32f429zi \ --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446re --artifact-dir out/tests/stm32f446re \ --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g491re --artifact-dir out/tests/stm32g491re \ @@ -398,8 +400,10 @@ rm out/tests/pimoroni-pico-plus-2/pwm rm out/tests/rpi-pico/pwm rm out/tests/rpi-pico/cyw43-perf -# tests are implemented but the HIL test farm doesn't actually have this board yet +# tests are implemented but the HIL test farm doesn't actually have these boards, yet rm -rf out/tests/stm32c071rb +rm -rf out/tests/stm32f100rd +rm -rf out/tests/stm32f107vc if [[ -z "${TELEPROBE_TOKEN-}" ]]; then echo No teleprobe token found, skipping running HIL tests diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index a473834dd..db0c1e89c 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - fix: Fix stm32h7rs init when using external flash via XSPI - feat: Add Adc::new_with_clock() to configure analog clock - feat: Add GPDMA linked-list + ringbuffer support ([#3923](https://github.com/embassy-rs/embassy/pull/3923)) +- feat: Added support for STM32F1 peripheral pin remapping (AFIO) ([#4430](https://github.com/embassy-rs/embassy/pull/4430)) ## 0.3.0 - 2025-08-12 diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index b731012c6..f55e1e0c9 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1391,9 +1391,60 @@ fn main() { }) } - g.extend(quote! { - pin_trait_impl!(#tr, #peri, #pin_name, #af); - }) + let pin_trait_impl = p + .afio + .as_ref() + .and_then(|afio| { + if p.name.starts_with("TIM") { + // timers are handled by timer_afio_impl!() + return None; + } + + let values = afio + .values + .iter() + .filter(|v| v.pins.contains(&pin.pin)) + .map(|v| v.value) + .collect::>(); + + if values.is_empty() { + None + } else { + let setter = format_ident!("set_{}", afio.field.to_lowercase()); + let type_and_values = if is_bool_field("AFIO", afio.register, afio.field) { + let values = values.iter().map(|&v| v > 0); + quote!(AfioRemapBool, [#(#values),*]) + } else { + quote!(AfioRemap, [#(#values),*]) + }; + + Some(quote! { + pin_trait_afio_impl!(#tr, #peri, #pin_name, {#setter, #type_and_values}); + }) + } + }) + .unwrap_or_else(|| { + let peripherals_with_afio = [ + "CAN", + "CEC", + "ETH", + "I2C", + "SPI", + "SUBGHZSPI", + "USART", + "UART", + "LPUART", + ]; + let af_or_not_applicable = if peripherals_with_afio.iter().any(|&x| p.name.starts_with(x)) { + quote!(0, crate::gpio::AfioRemapNotApplicable) + } else { + quote!(#af) + }; + + quote!(pin_trait_impl!(#tr, #peri, #pin_name, #af_or_not_applicable);) + }); + + g.extend(pin_trait_impl); } // ADC is special @@ -1588,17 +1639,7 @@ fn main() { let register = format_ident!("{}", remap_info.register.to_lowercase()); let setter = format_ident!("set_{}", remap_info.field.to_lowercase()); - let field_metadata = METADATA - .peripherals - .iter() - .filter(|p| p.name == "SYSCFG") - .flat_map(|p| p.registers.as_ref().unwrap().ir.fieldsets.iter()) - .filter(|f| f.name.eq_ignore_ascii_case(remap_info.register)) - .flat_map(|f| f.fields.iter()) - .find(|f| f.name.eq_ignore_ascii_case(remap_info.field)) - .unwrap(); - - let value = if field_metadata.bit_size == 1 { + let value = if is_bool_field("SYSCFG", &remap_info.register, &remap_info.field) { let bool_value = format_ident!("{}", remap_info.value > 0); quote!(#bool_value) } else { @@ -1928,6 +1969,48 @@ fn main() { pub(crate) const DMA_CHANNELS: &[crate::dma::ChannelInfo] = &[#dmas]; }); + // ======== + // Generate timer AFIO impls + + for p in METADATA.peripherals { + if p.name.starts_with("TIM") { + let pname = format_ident!("{}", p.name); + let afio = if let Some(afio) = &p.afio { + let register = format_ident!("{}", afio.register.to_lowercase()); + let setter = format_ident!("set_{}", afio.field.to_lowercase()); + + let swj_cfg = if afio.register == "MAPR" { + quote!(w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP);) + } else { + quote!() + }; + let bool_eval = if is_bool_field("AFIO", &afio.register, &afio.field) { + quote!(> 0) + } else { + quote!() + }; + + let values = afio.values.iter().map(|v| { + let mapr_value = v.value; + let pin = v.pins.iter().map(|p| { + let port_num = p.chars().nth(1).unwrap() as u8 - b'A'; + let pin_num = p[2..].parse::().unwrap(); + port_num * 16 + pin_num + }); + quote!(#mapr_value, [#(#pin),*]) + }); + + quote! { + , |v| crate::pac::AFIO.#register().modify(|w| { #swj_cfg w.#setter(v #bool_eval); }), #({#values}),* + } + } else { + quote!() + }; + + g.extend(quote!(timer_afio_impl!(#pname #afio);)); + } + } + // ======== // Generate gpio_block() function @@ -2300,3 +2383,17 @@ fn gcd(a: u32, b: u32) -> u32 { } gcd(b, a % b) } + +fn is_bool_field(peripheral: &str, register: &str, field: &str) -> bool { + let field_metadata = METADATA + .peripherals + .iter() + .filter(|p| p.name == peripheral) + .flat_map(|p| p.registers.as_ref().unwrap().ir.fieldsets.iter()) + .filter(|f| f.name.eq_ignore_ascii_case(register)) + .flat_map(|f| f.fields.iter()) + .find(|f| f.name.eq_ignore_ascii_case(field)) + .unwrap(); + + field_metadata.bit_size == 1 +} diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs index 4c0795a2a..9ebfeb42f 100644 --- a/embassy-stm32/src/can/bxcan/mod.rs +++ b/embassy-stm32/src/can/bxcan/mod.rs @@ -181,10 +181,10 @@ pub enum TryWriteError { impl<'d> Can<'d> { /// Creates a new Bxcan instance, keeping the peripheral in sleep mode. /// You must call [Can::enable_non_blocking] to use the peripheral. - pub fn new( + pub fn new( _peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, + rx: Peri<'d, impl RxPin>, + tx: Peri<'d, impl TxPin>, _irqs: impl interrupt::typelevel::Binding> + interrupt::typelevel::Binding> + interrupt::typelevel::Binding> @@ -195,6 +195,8 @@ impl<'d> Can<'d> { let regs = &T::info().regs; rx.set_as_af(rx.af_num(), AfType::input(Pull::None)); + #[cfg(afio)] + rx.afio_remap(); tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); rcc::enable_and_reset::(); @@ -1218,8 +1220,8 @@ foreach_peripheral!( }; ); -pin_trait!(RxPin, Instance); -pin_trait!(TxPin, Instance); +pin_trait!(RxPin, Instance, @A); +pin_trait!(TxPin, Instance, @A); trait Index { fn index(&self) -> usize; diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index 97d7b4347..10b3a0517 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs @@ -209,19 +209,19 @@ impl SealedInstance for crate::peripherals::ETH { } impl Instance for crate::peripherals::ETH {} -pin_trait!(RXClkPin, Instance); -pin_trait!(TXClkPin, Instance); -pin_trait!(RefClkPin, Instance); -pin_trait!(MDIOPin, Instance); -pin_trait!(MDCPin, Instance); -pin_trait!(RXDVPin, Instance); -pin_trait!(CRSPin, Instance); -pin_trait!(RXD0Pin, Instance); -pin_trait!(RXD1Pin, Instance); -pin_trait!(RXD2Pin, Instance); -pin_trait!(RXD3Pin, Instance); -pin_trait!(TXD0Pin, Instance); -pin_trait!(TXD1Pin, Instance); -pin_trait!(TXD2Pin, Instance); -pin_trait!(TXD3Pin, Instance); -pin_trait!(TXEnPin, Instance); +pin_trait!(RXClkPin, Instance, @A); +pin_trait!(TXClkPin, Instance, @A); +pin_trait!(RefClkPin, Instance, @A); +pin_trait!(MDIOPin, Instance, @A); +pin_trait!(MDCPin, Instance, @A); +pin_trait!(RXDVPin, Instance, @A); +pin_trait!(CRSPin, Instance, @A); +pin_trait!(RXD0Pin, Instance, @A); +pin_trait!(RXD1Pin, Instance, @A); +pin_trait!(RXD2Pin, Instance, @A); +pin_trait!(RXD3Pin, Instance, @A); +pin_trait!(TXD0Pin, Instance, @A); +pin_trait!(TXD1Pin, Instance, @A); +pin_trait!(TXD2Pin, Instance, @A); +pin_trait!(TXD3Pin, Instance, @A); +pin_trait!(TXEnPin, Instance, @A); diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index b9746231f..45be65c5f 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -99,19 +99,19 @@ macro_rules! config_pins { impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { /// safety: the returned instance is not leak-safe - pub fn new( + pub fn new( queue: &'d mut PacketQueue, peri: Peri<'d, T>, irq: impl interrupt::typelevel::Binding + 'd, - ref_clk: Peri<'d, impl RefClkPin>, - mdio: Peri<'d, impl MDIOPin>, - mdc: Peri<'d, impl MDCPin>, - crs: Peri<'d, impl CRSPin>, - rx_d0: Peri<'d, impl RXD0Pin>, - rx_d1: Peri<'d, impl RXD1Pin>, - tx_d0: Peri<'d, impl TXD0Pin>, - tx_d1: Peri<'d, impl TXD1Pin>, - tx_en: Peri<'d, impl TXEnPin>, + ref_clk: Peri<'d, impl RefClkPin>, + mdio: Peri<'d, impl MDIOPin>, + mdc: Peri<'d, impl MDCPin>, + crs: Peri<'d, impl CRSPin>, + rx_d0: Peri<'d, impl RXD0Pin>, + rx_d1: Peri<'d, impl RXD1Pin>, + tx_d0: Peri<'d, impl TXD0Pin>, + tx_d1: Peri<'d, impl TXD1Pin>, + tx_en: Peri<'d, impl TXEnPin>, phy: P, mac_addr: [u8; 6], ) -> Self { @@ -150,6 +150,8 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { { config_in_pins!(ref_clk, rx_d0, rx_d1); config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_en); + #[cfg(afio)] + rx_d0.afio_remap(); } #[cfg(any(eth_v1b, eth_v1c))] @@ -289,24 +291,24 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { } /// Create a new MII ethernet driver using 14 pins. - pub fn new_mii( + pub fn new_mii( queue: &'d mut PacketQueue, peri: Peri<'d, T>, irq: impl interrupt::typelevel::Binding + 'd, - rx_clk: Peri<'d, impl RXClkPin>, - tx_clk: Peri<'d, impl TXClkPin>, - mdio: Peri<'d, impl MDIOPin>, - mdc: Peri<'d, impl MDCPin>, - rxdv: Peri<'d, impl RXDVPin>, - rx_d0: Peri<'d, impl RXD0Pin>, - rx_d1: Peri<'d, impl RXD1Pin>, - rx_d2: Peri<'d, impl RXD2Pin>, - rx_d3: Peri<'d, impl RXD3Pin>, - tx_d0: Peri<'d, impl TXD0Pin>, - tx_d1: Peri<'d, impl TXD1Pin>, - tx_d2: Peri<'d, impl TXD2Pin>, - tx_d3: Peri<'d, impl TXD3Pin>, - tx_en: Peri<'d, impl TXEnPin>, + rx_clk: Peri<'d, impl RXClkPin>, + tx_clk: Peri<'d, impl TXClkPin>, + mdio: Peri<'d, impl MDIOPin>, + mdc: Peri<'d, impl MDCPin>, + rxdv: Peri<'d, impl RXDVPin>, + rx_d0: Peri<'d, impl RXD0Pin>, + rx_d1: Peri<'d, impl RXD1Pin>, + rx_d2: Peri<'d, impl RXD2Pin>, + rx_d3: Peri<'d, impl RXD3Pin>, + tx_d0: Peri<'d, impl TXD0Pin>, + tx_d1: Peri<'d, impl TXD1Pin>, + tx_d2: Peri<'d, impl TXD2Pin>, + tx_d3: Peri<'d, impl TXD3Pin>, + tx_en: Peri<'d, impl TXEnPin>, phy: P, mac_addr: [u8; 6], ) -> Self { @@ -347,6 +349,8 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { { config_in_pins!(rx_clk, tx_clk, rx_d0, rx_d1, rx_d2, rx_d3, rxdv); config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_d2, tx_d3, tx_en); + #[cfg(afio)] + rx_d0.afio_remap(); } #[cfg(any(eth_v1b, eth_v1c))] diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 034c5dd88..96ad42c7f 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs @@ -65,19 +65,19 @@ macro_rules! config_pins { impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { /// Create a new RMII ethernet driver using 9 pins. - pub fn new( + pub fn new( queue: &'d mut PacketQueue, peri: Peri<'d, T>, irq: impl interrupt::typelevel::Binding + 'd, - ref_clk: Peri<'d, impl RefClkPin>, - mdio: Peri<'d, impl MDIOPin>, - mdc: Peri<'d, impl MDCPin>, - crs: Peri<'d, impl CRSPin>, - rx_d0: Peri<'d, impl RXD0Pin>, - rx_d1: Peri<'d, impl RXD1Pin>, - tx_d0: Peri<'d, impl TXD0Pin>, - tx_d1: Peri<'d, impl TXD1Pin>, - tx_en: Peri<'d, impl TXEnPin>, + ref_clk: Peri<'d, impl RefClkPin>, + mdio: Peri<'d, impl MDIOPin>, + mdc: Peri<'d, impl MDCPin>, + crs: Peri<'d, impl CRSPin>, + rx_d0: Peri<'d, impl RXD0Pin>, + rx_d1: Peri<'d, impl RXD1Pin>, + tx_d0: Peri<'d, impl TXD0Pin>, + tx_d1: Peri<'d, impl TXD1Pin>, + tx_en: Peri<'d, impl TXEnPin>, phy: P, mac_addr: [u8; 6], ) -> Self { @@ -110,24 +110,24 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { } /// Create a new MII ethernet driver using 14 pins. - pub fn new_mii( + pub fn new_mii( queue: &'d mut PacketQueue, peri: Peri<'d, T>, irq: impl interrupt::typelevel::Binding + 'd, - rx_clk: Peri<'d, impl RXClkPin>, - tx_clk: Peri<'d, impl TXClkPin>, - mdio: Peri<'d, impl MDIOPin>, - mdc: Peri<'d, impl MDCPin>, - rxdv: Peri<'d, impl RXDVPin>, - rx_d0: Peri<'d, impl RXD0Pin>, - rx_d1: Peri<'d, impl RXD1Pin>, - rx_d2: Peri<'d, impl RXD2Pin>, - rx_d3: Peri<'d, impl RXD3Pin>, - tx_d0: Peri<'d, impl TXD0Pin>, - tx_d1: Peri<'d, impl TXD1Pin>, - tx_d2: Peri<'d, impl TXD2Pin>, - tx_d3: Peri<'d, impl TXD3Pin>, - tx_en: Peri<'d, impl TXEnPin>, + rx_clk: Peri<'d, impl RXClkPin>, + tx_clk: Peri<'d, impl TXClkPin>, + mdio: Peri<'d, impl MDIOPin>, + mdc: Peri<'d, impl MDCPin>, + rxdv: Peri<'d, impl RXDVPin>, + rx_d0: Peri<'d, impl RXD0Pin>, + rx_d1: Peri<'d, impl RXD1Pin>, + rx_d2: Peri<'d, impl RXD2Pin>, + rx_d3: Peri<'d, impl RXD3Pin>, + tx_d0: Peri<'d, impl TXD0Pin>, + tx_d1: Peri<'d, impl TXD1Pin>, + tx_d2: Peri<'d, impl TXD2Pin>, + tx_d3: Peri<'d, impl TXD3Pin>, + tx_en: Peri<'d, impl TXEnPin>, phy: P, mac_addr: [u8; 6], ) -> Self { diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index bb37c4194..ef631bbdc 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs @@ -710,6 +710,17 @@ fn get_pull(pin_port: u8) -> Pull { }; } +#[cfg(afio)] +/// Holds the AFIO remap value for a peripheral's pin +pub struct AfioRemap; + +#[cfg(afio)] +/// Holds the AFIO remap value for a peripheral's pin +pub struct AfioRemapBool; + +/// Placeholder for a peripheral's pin which cannot be remapped via AFIO. +pub struct AfioRemapNotApplicable; + pub(crate) trait SealedPin { fn pin_port(&self) -> u8; diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 5fb49f943..be0ae2f5f 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -149,10 +149,10 @@ pub struct I2c<'d, M: Mode, IM: MasterMode> { impl<'d> I2c<'d, Async, Master> { /// Create a new I2C driver. - pub fn new( + pub fn new( peri: Peri<'d, T>, - scl: Peri<'d, impl SclPin>, - sda: Peri<'d, impl SdaPin>, + scl: Peri<'d, impl SclPin>, + sda: Peri<'d, impl SdaPin>, _irq: impl interrupt::typelevel::Binding> + interrupt::typelevel::Binding> + 'd, @@ -173,10 +173,10 @@ impl<'d> I2c<'d, Async, Master> { impl<'d> I2c<'d, Blocking, Master> { /// Create a new blocking I2C driver. - pub fn new_blocking( + pub fn new_blocking( peri: Peri<'d, T>, - scl: Peri<'d, impl SclPin>, - sda: Peri<'d, impl SdaPin>, + scl: Peri<'d, impl SclPin>, + sda: Peri<'d, impl SdaPin>, config: Config, ) -> Self { Self::new_inner( @@ -296,8 +296,8 @@ peri_trait!( irqs: [EventInterrupt, ErrorInterrupt], ); -pin_trait!(SclPin, Instance); -pin_trait!(SdaPin, Instance); +pin_trait!(SclPin, Instance, @A); +pin_trait!(SdaPin, Instance, @A); dma_trait!(RxDma, Instance); dma_trait!(TxDma, Instance); diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index 0c4ab56e3..4c634aa17 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs @@ -237,12 +237,12 @@ pub struct I2S<'d, W: Word> { impl<'d, W: Word> I2S<'d, W> { /// Create a transmitter driver. - pub fn new_txonly( + pub fn new_txonly( peri: Peri<'d, T>, - sd: Peri<'d, impl MosiPin>, - ws: Peri<'d, impl WsPin>, - ck: Peri<'d, impl CkPin>, - mck: Peri<'d, impl MckPin>, + sd: Peri<'d, impl MosiPin>, + ws: Peri<'d, impl WsPin>, + ck: Peri<'d, impl CkPin>, + mck: Peri<'d, impl MckPin>, txdma: Peri<'d, impl TxDma>, txdma_buf: &'d mut [W], config: Config, @@ -262,11 +262,11 @@ impl<'d, W: Word> I2S<'d, W> { } /// Create a transmitter driver without a master clock pin. - pub fn new_txonly_nomck( + pub fn new_txonly_nomck( peri: Peri<'d, T>, - sd: Peri<'d, impl MosiPin>, - ws: Peri<'d, impl WsPin>, - ck: Peri<'d, impl CkPin>, + sd: Peri<'d, impl MosiPin>, + ws: Peri<'d, impl WsPin>, + ck: Peri<'d, impl CkPin>, txdma: Peri<'d, impl TxDma>, txdma_buf: &'d mut [W], config: Config, @@ -286,12 +286,12 @@ impl<'d, W: Word> I2S<'d, W> { } /// Create a receiver driver. - pub fn new_rxonly( + pub fn new_rxonly( peri: Peri<'d, T>, - sd: Peri<'d, impl MisoPin>, - ws: Peri<'d, impl WsPin>, - ck: Peri<'d, impl CkPin>, - mck: Peri<'d, impl MckPin>, + sd: Peri<'d, impl MisoPin>, + ws: Peri<'d, impl WsPin>, + ck: Peri<'d, impl CkPin>, + mck: Peri<'d, impl MckPin>, rxdma: Peri<'d, impl RxDma>, rxdma_buf: &'d mut [W], config: Config, @@ -313,13 +313,13 @@ impl<'d, W: Word> I2S<'d, W> { #[cfg(any(spi_v4, spi_v5))] /// Create a full duplex driver. - pub fn new_full_duplex( + pub fn new_full_duplex( peri: Peri<'d, T>, - txsd: Peri<'d, impl MosiPin>, - rxsd: Peri<'d, impl MisoPin>, - ws: Peri<'d, impl WsPin>, - ck: Peri<'d, impl CkPin>, - mck: Peri<'d, impl MckPin>, + txsd: Peri<'d, impl MosiPin>, + rxsd: Peri<'d, impl MisoPin>, + ws: Peri<'d, impl WsPin>, + ck: Peri<'d, impl CkPin>, + mck: Peri<'d, impl MckPin>, txdma: Peri<'d, impl TxDma>, txdma_buf: &'d mut [W], rxdma: Peri<'d, impl RxDma>, @@ -459,12 +459,12 @@ impl<'d, W: Word> I2S<'d, W> { } } - fn new_inner( + fn new_inner( peri: Peri<'d, T>, txsd: Option>, rxsd: Option>, - ws: Peri<'d, impl WsPin>, - ck: Peri<'d, impl CkPin>, + ws: Peri<'d, impl WsPin>, + ck: Peri<'d, impl CkPin>, mck: Option>, txdma: Option<(ChannelAndRequest<'d>, &'d mut [W])>, rxdma: Option<(ChannelAndRequest<'d>, &'d mut [W])>, diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs index 3a0b490ba..f97843a7d 100644 --- a/embassy-stm32/src/macros.rs +++ b/embassy-stm32/src/macros.rs @@ -41,25 +41,54 @@ macro_rules! peri_trait_impl { } macro_rules! pin_trait { - ($signal:ident, $instance:path $(, $mode:path)?) => { + ($signal:ident, $instance:path $(, $mode:path)? $(, @$afio:ident)?) => { #[doc = concat!(stringify!($signal), " pin trait")] - pub trait $signal: crate::gpio::Pin { + pub trait $signal: crate::gpio::Pin { #[doc = concat!("Get the AF number needed to use this pin as ", stringify!($signal))] fn af_num(&self) -> u8; + + #[cfg(afio)] + #[doc = concat!("Configures AFIO_MAPR to use this pin as ", stringify!($signal))] + fn afio_remap(&self); } }; } macro_rules! pin_trait_impl { - (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $af:expr) => { - impl crate::$mod::$trait for crate::peripherals::$pin { + (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $af:expr $(, $afio:path)?) => { + impl crate::$mod::$trait for crate::peripherals::$pin { fn af_num(&self) -> u8 { $af } + + #[cfg(afio)] + fn afio_remap(&self) { + // nothing + } } }; } +#[cfg(afio)] +macro_rules! pin_trait_afio_impl { + (crate::$mod:ident::$trait:ident, $instance:ident, $pin:ident, {$setter:ident, $type:ident, [$($val:expr),+]}) => { + $( + impl crate::$mod::$trait> for crate::peripherals::$pin { + fn af_num(&self) -> u8 { + 0 + } + + fn afio_remap(&self) { + crate::pac::AFIO.mapr().modify(|w| { + w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP); + w.$setter($val); + }); + } + } + )+ + }; +} + #[allow(unused_macros)] macro_rules! sel_trait_impl { (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $sel:expr) => { @@ -73,6 +102,30 @@ macro_rules! sel_trait_impl { // ==================== +macro_rules! timer_afio_impl { + ($instance:ident $(, $set_afio:expr)? $(,{$mapr_value:literal, [$($pin:literal),*]})*) => { + impl crate::timer::Afio for crate::peripherals::$instance { + fn afio_mappings() -> &'static [crate::timer::AfioMapping] { + &[ + $( + crate::timer::AfioMapping { + value: $mapr_value, + pins: &[$($pin),*], + } + ),* + ] + } + + #[allow(unused)] + fn set_afio(value: u8) { + $($set_afio(value);)? + } + } + }; +} + +// ==================== + macro_rules! dma_trait { ($signal:ident, $instance:path$(, $mode:path)?) => { #[doc = concat!(stringify!($signal), " DMA request trait")] @@ -134,6 +187,8 @@ macro_rules! new_dma { macro_rules! new_pin { ($name:ident, $af_type:expr) => {{ let pin = $name; + #[cfg(afio)] + pin.afio_remap(); pin.set_as_af(pin.af_num(), $af_type); Some(pin.into()) }}; diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index a49ebcbee..105c617d8 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -471,11 +471,11 @@ impl<'d, M: PeriMode> Spi<'d, M> { impl<'d> Spi<'d, Blocking> { /// Create a new blocking SPI driver. - pub fn new_blocking( + pub fn new_blocking( peri: Peri<'d, T>, - sck: Peri<'d, impl SckPin>, - mosi: Peri<'d, impl MosiPin>, - miso: Peri<'d, impl MisoPin>, + sck: Peri<'d, impl SckPin>, + mosi: Peri<'d, impl MosiPin>, + miso: Peri<'d, impl MisoPin>, config: Config, ) -> Self { Self::new_inner( @@ -490,10 +490,10 @@ impl<'d> Spi<'d, Blocking> { } /// Create a new blocking SPI driver, in RX-only mode (only MISO pin, no MOSI). - pub fn new_blocking_rxonly( + pub fn new_blocking_rxonly( peri: Peri<'d, T>, - sck: Peri<'d, impl SckPin>, - miso: Peri<'d, impl MisoPin>, + sck: Peri<'d, impl SckPin>, + miso: Peri<'d, impl MisoPin>, config: Config, ) -> Self { Self::new_inner( @@ -508,10 +508,10 @@ impl<'d> Spi<'d, Blocking> { } /// Create a new blocking SPI driver, in TX-only mode (only MOSI pin, no MISO). - pub fn new_blocking_txonly( + pub fn new_blocking_txonly( peri: Peri<'d, T>, - sck: Peri<'d, impl SckPin>, - mosi: Peri<'d, impl MosiPin>, + sck: Peri<'d, impl SckPin>, + mosi: Peri<'d, impl MosiPin>, config: Config, ) -> Self { Self::new_inner( @@ -528,9 +528,9 @@ impl<'d> Spi<'d, Blocking> { /// Create a new SPI driver, in TX-only mode, without SCK pin. /// /// This can be useful for bit-banging non-SPI protocols. - pub fn new_blocking_txonly_nosck( + pub fn new_blocking_txonly_nosck( peri: Peri<'d, T>, - mosi: Peri<'d, impl MosiPin>, + mosi: Peri<'d, impl MosiPin>, config: Config, ) -> Self { Self::new_inner( @@ -547,11 +547,11 @@ impl<'d> Spi<'d, Blocking> { impl<'d> Spi<'d, Async> { /// Create a new SPI driver. - pub fn new( + pub fn new( peri: Peri<'d, T>, - sck: Peri<'d, impl SckPin>, - mosi: Peri<'d, impl MosiPin>, - miso: Peri<'d, impl MisoPin>, + sck: Peri<'d, impl SckPin>, + mosi: Peri<'d, impl MosiPin>, + miso: Peri<'d, impl MisoPin>, tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, config: Config, @@ -568,10 +568,10 @@ impl<'d> Spi<'d, Async> { } /// Create a new SPI driver, in RX-only mode (only MISO pin, no MOSI). - pub fn new_rxonly( + pub fn new_rxonly( peri: Peri<'d, T>, - sck: Peri<'d, impl SckPin>, - miso: Peri<'d, impl MisoPin>, + sck: Peri<'d, impl SckPin>, + miso: Peri<'d, impl MisoPin>, #[cfg(any(spi_v1, spi_v2, spi_v3))] tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, config: Config, @@ -591,10 +591,10 @@ impl<'d> Spi<'d, Async> { } /// Create a new SPI driver, in TX-only mode (only MOSI pin, no MISO). - pub fn new_txonly( + pub fn new_txonly( peri: Peri<'d, T>, - sck: Peri<'d, impl SckPin>, - mosi: Peri<'d, impl MosiPin>, + sck: Peri<'d, impl SckPin>, + mosi: Peri<'d, impl MosiPin>, tx_dma: Peri<'d, impl TxDma>, config: Config, ) -> Self { @@ -612,9 +612,9 @@ impl<'d> Spi<'d, Async> { /// Create a new SPI driver, in TX-only mode, without SCK pin. /// /// This can be useful for bit-banging non-SPI protocols. - pub fn new_txonly_nosck( + pub fn new_txonly_nosck( peri: Peri<'d, T>, - mosi: Peri<'d, impl MosiPin>, + mosi: Peri<'d, impl MosiPin>, tx_dma: Peri<'d, impl TxDma>, config: Config, ) -> Self { @@ -1309,13 +1309,13 @@ impl State { peri_trait!(); -pin_trait!(SckPin, Instance); -pin_trait!(MosiPin, Instance); -pin_trait!(MisoPin, Instance); -pin_trait!(CsPin, Instance); -pin_trait!(MckPin, Instance); -pin_trait!(CkPin, Instance); -pin_trait!(WsPin, Instance); +pin_trait!(SckPin, Instance, @A); +pin_trait!(MosiPin, Instance, @A); +pin_trait!(MisoPin, Instance, @A); +pin_trait!(CsPin, Instance, @A); +pin_trait!(MckPin, Instance, @A); +pin_trait!(CkPin, Instance, @A); +pin_trait!(WsPin, Instance, @A); dma_trait!(RxDma, Instance); dma_trait!(TxDma, Instance); diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 68cdec302..08404cdd6 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -17,7 +17,8 @@ use crate::Peri; /// /// This wraps a pin to make it usable with PWM. pub struct ComplementaryPwmPin<'d, T, C> { - _pin: Peri<'d, AnyPin>, + #[allow(unused)] + pin: Peri<'d, AnyPin>, phantom: PhantomData<(T, C)>, } @@ -32,7 +33,7 @@ impl<'d, T: AdvancedInstance4Channel, C: TimerChannel> ComplementaryPwmPin<'d, T ); }); ComplementaryPwmPin { - _pin: pin.into(), + pin: pin.into(), phantom: PhantomData, } } @@ -54,20 +55,31 @@ pub enum IdlePolarity { impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { /// Create a new complementary PWM driver. - #[allow(clippy::too_many_arguments)] + #[allow(clippy::too_many_arguments, unused)] pub fn new( tim: Peri<'d, T>, - _ch1: Option>, - _ch1n: Option>, - _ch2: Option>, - _ch2n: Option>, - _ch3: Option>, - _ch3n: Option>, - _ch4: Option>, - _ch4n: Option>, + ch1: Option>, + ch1n: Option>, + ch2: Option>, + ch2n: Option>, + ch3: Option>, + ch3n: Option>, + ch4: Option>, + ch4n: Option>, freq: Hertz, counting_mode: CountingMode, ) -> Self { + #[cfg(afio)] + super::set_afio::(&[ + ch1.map(|p| p.pin), + ch1n.map(|p| p.pin), + ch2.map(|p| p.pin), + ch2n.map(|p| p.pin), + ch3.map(|p| p.pin), + ch3n.map(|p| p.pin), + ch4.map(|p| p.pin), + ch4n.map(|p| p.pin), + ]); Self::new_inner(tim, freq, counting_mode) } diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index dda33e7f1..b717e6eac 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -18,7 +18,8 @@ use crate::Peri; /// /// This wraps a pin to make it usable with capture. pub struct CapturePin<'d, T, C> { - _pin: Peri<'d, AnyPin>, + #[allow(unused)] + pin: Peri<'d, AnyPin>, phantom: PhantomData<(T, C)>, } impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> { @@ -26,7 +27,7 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> { pub fn new(pin: Peri<'d, impl TimerPin>, pull: Pull) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); CapturePin { - _pin: pin.into(), + pin: pin.into(), phantom: PhantomData, } } @@ -39,16 +40,24 @@ pub struct InputCapture<'d, T: GeneralInstance4Channel> { impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { /// Create a new input capture driver. + #[allow(unused)] pub fn new( tim: Peri<'d, T>, - _ch1: Option>, - _ch2: Option>, - _ch3: Option>, - _ch4: Option>, + ch1: Option>, + ch2: Option>, + ch3: Option>, + ch4: Option>, _irq: impl Binding> + 'd, freq: Hertz, counting_mode: CountingMode, ) -> Self { + #[cfg(afio)] + super::set_afio::(&[ + ch1.map(|p| p.pin), + ch2.map(|p| p.pin), + ch3.map(|p| p.pin), + ch4.map(|p| p.pin), + ]); Self::new_inner(tim, freq, counting_mode) } diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 7062f5f4c..38f4a1a51 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -14,6 +14,8 @@ pub mod pwm_input; pub mod qei; pub mod simple_pwm; +#[cfg(afio)] +use crate::gpio::SealedPin; use crate::interrupt; use crate::rcc::RccPeripheral; @@ -155,9 +157,15 @@ trait SealedInstance: RccPeripheral + PeripheralType { fn state() -> &'static State; } +#[allow(unused)] +pub(crate) trait Afio { + fn afio_mappings() -> &'static [AfioMapping]; + fn set_afio(value: u8); +} + /// Core timer instance. #[allow(private_bounds)] -pub trait CoreInstance: SealedInstance + 'static { +pub trait CoreInstance: SealedInstance + Afio + 'static { /// Update Interrupt for this timer. type UpdateInterrupt: interrupt::typelevel::Interrupt; @@ -450,3 +458,24 @@ impl interrupt::typelevel::Handler(pins: &[Option>]) { + let mapping = T::afio_mappings() + .iter() + .find(|m| { + pins.iter() + .flatten() + .map(|p| (*p).pin_port()) + .all(|p| m.pins.contains(&p)) + }) + .expect("Should be called with a combination of timer pins supported by the hardware"); + + T::set_afio(mapping.value); +} diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs index 498d9c082..0267749e1 100644 --- a/embassy-stm32/src/timer/one_pulse.rs +++ b/embassy-stm32/src/timer/one_pulse.rs @@ -42,7 +42,8 @@ impl From for Etp { /// /// This wraps a pin to make it usable as a timer trigger. pub struct TriggerPin<'d, T, C> { - _pin: Peri<'d, AnyPin>, + #[allow(unused)] + pin: Peri<'d, AnyPin>, phantom: PhantomData<(T, C)>, } @@ -113,7 +114,7 @@ impl<'d, T: GeneralInstance4Channel, C: TriggerSource> TriggerPin<'d, T, C> { pub fn new(pin: Peri<'d, impl TimerTriggerPin>, pull: Pull) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); TriggerPin { - _pin: pin.into(), + pin: pin.into(), phantom: PhantomData, } } @@ -131,14 +132,17 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// /// The pulse is triggered by a channel 1 input pin on both rising and /// falling edges. Channel 1 will unusable as an output. + #[allow(unused)] pub fn new_ch1_edge_detect( tim: Peri<'d, T>, - _pin: TriggerPin<'d, T, Ch1>, + pin: TriggerPin<'d, T, Ch1>, _irq: impl Binding> + 'd, freq: Hertz, pulse_end: u32, counting_mode: CountingMode, ) -> Self { + #[cfg(afio)] + super::set_afio::(&[Some(pin.pin)]); let mut this = Self { inner: Timer::new(tim) }; this.inner.set_trigger_source(Ts::TI1F_ED); diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index 1e55f2919..c537e5268 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -20,6 +20,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { /// Create a new PWM input driver. pub fn new_ch1(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); + #[cfg(afio)] + super::set_afio::(&[Some(pin.into())]); Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2) } @@ -27,6 +29,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { /// Create a new PWM input driver. pub fn new_ch2(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); + #[cfg(afio)] + super::set_afio::(&[Some(pin.into())]); Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1) } diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index eabe1b22a..4e5a309ac 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -21,19 +21,20 @@ pub enum Direction { /// Wrapper for using a pin with QEI. pub struct QeiPin<'d, T, Channel> { - _pin: Peri<'d, AnyPin>, + #[allow(unused)] + pin: Peri<'d, AnyPin>, phantom: PhantomData<(T, Channel)>, } impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> { - /// Create a new QEI pin instance. + /// Create a new QEI pin instance. pub fn new(pin: Peri<'d, impl TimerPin>) -> Self { critical_section::with(|_| { pin.set_low(); pin.set_as_af(pin.af_num(), AfType::input(Pull::None)); }); QeiPin { - _pin: pin.into(), + pin: pin.into(), phantom: PhantomData, } } @@ -58,7 +59,10 @@ pub struct Qei<'d, T: GeneralInstance4Channel> { impl<'d, T: GeneralInstance4Channel> Qei<'d, T> { /// Create a new quadrature decoder driver. - pub fn new(tim: Peri<'d, T>, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self { + #[allow(unused)] + pub fn new(tim: Peri<'d, T>, ch1: QeiPin<'d, T, Ch1>, ch2: QeiPin<'d, T, Ch2>) -> Self { + #[cfg(afio)] + super::set_afio::(&[Some(ch1.pin), Some(ch2.pin)]); Self::new_inner(tim) } diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index c04b1ab97..df86859fe 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -15,7 +15,8 @@ use crate::Peri; /// /// This wraps a pin to make it usable with PWM. pub struct PwmPin<'d, T, C> { - _pin: Peri<'d, AnyPin>, + #[allow(unused)] + pub(crate) pin: Peri<'d, AnyPin>, phantom: PhantomData<(T, C)>, } @@ -42,7 +43,7 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> { pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh)); }); PwmPin { - _pin: pin.into(), + pin: pin.into(), phantom: PhantomData, } } @@ -60,7 +61,7 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> { ); }); PwmPin { - _pin: pin.into(), + pin: pin.into(), phantom: PhantomData, } } @@ -178,15 +179,23 @@ pub struct SimplePwm<'d, T: GeneralInstance4Channel> { impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// Create a new simple PWM driver. + #[allow(unused)] pub fn new( tim: Peri<'d, T>, - _ch1: Option>, - _ch2: Option>, - _ch3: Option>, - _ch4: Option>, + ch1: Option>, + ch2: Option>, + ch3: Option>, + ch4: Option>, freq: Hertz, counting_mode: CountingMode, ) -> Self { + #[cfg(afio)] + super::set_afio::(&[ + ch1.map(|p| p.pin), + ch2.map(|p| p.pin), + ch3.map(|p| p.pin), + ch4.map(|p| p.pin), + ]); Self::new_inner(tim, freq, counting_mode) } diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 729440c46..72aeb8357 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -208,10 +208,10 @@ impl<'d> SetConfig for BufferedUartTx<'d> { impl<'d> BufferedUart<'d> { /// Create a new bidirectional buffered UART driver - pub fn new( + pub fn new( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, + rx: Peri<'d, impl RxPin>, + tx: Peri<'d, impl TxPin>, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], _irq: impl interrupt::typelevel::Binding> + 'd, @@ -231,12 +231,12 @@ impl<'d> BufferedUart<'d> { } /// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins - pub fn new_with_rtscts( + pub fn new_with_rtscts( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, - rts: Peri<'d, impl RtsPin>, - cts: Peri<'d, impl CtsPin>, + rx: Peri<'d, impl RxPin>, + tx: Peri<'d, impl TxPin>, + rts: Peri<'d, impl RtsPin>, + cts: Peri<'d, impl CtsPin>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], @@ -256,11 +256,11 @@ impl<'d> BufferedUart<'d> { } /// Create a new bidirectional buffered UART driver with only the RTS pin as the DE pin - pub fn new_with_rts_as_de( + pub fn new_with_rts_as_de( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, - rts: Peri<'d, impl RtsPin>, + rx: Peri<'d, impl RxPin>, + tx: Peri<'d, impl TxPin>, + rts: Peri<'d, impl RtsPin>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], @@ -280,11 +280,11 @@ impl<'d> BufferedUart<'d> { } /// Create a new bidirectional buffered UART driver with only the request-to-send pin - pub fn new_with_rts( + pub fn new_with_rts( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, - rts: Peri<'d, impl RtsPin>, + rx: Peri<'d, impl RxPin>, + tx: Peri<'d, impl TxPin>, + rts: Peri<'d, impl RtsPin>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], @@ -305,11 +305,11 @@ impl<'d> BufferedUart<'d> { /// Create a new bidirectional buffered UART driver with a driver-enable pin #[cfg(not(any(usart_v1, usart_v2)))] - pub fn new_with_de( + pub fn new_with_de( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, - de: Peri<'d, impl DePin>, + rx: Peri<'d, impl RxPin>, + tx: Peri<'d, impl TxPin>, + de: Peri<'d, impl DePin>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], @@ -340,9 +340,9 @@ impl<'d> BufferedUart<'d> { /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict /// on the line must be managed by software (for instance by using a centralized arbiter). #[doc(alias("HDSEL"))] - pub fn new_half_duplex( + pub fn new_half_duplex( peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, + tx: Peri<'d, impl TxPin>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], @@ -379,9 +379,9 @@ impl<'d> BufferedUart<'d> { /// on the line must be managed by software (for instance by using a centralized arbiter). #[cfg(not(any(usart_v1, usart_v2)))] #[doc(alias("HDSEL"))] - pub fn new_half_duplex_on_rx( + pub fn new_half_duplex_on_rx( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, + rx: Peri<'d, impl RxPin>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 3d95de897..21d174bf0 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -429,9 +429,9 @@ impl<'d, M: Mode> SetConfig for UartRx<'d, M> { impl<'d> UartTx<'d, Async> { /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. - pub fn new( + pub fn new( peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, + tx: Peri<'d, impl TxPin>, tx_dma: Peri<'d, impl TxDma>, config: Config, ) -> Result { @@ -439,10 +439,10 @@ impl<'d> UartTx<'d, Async> { } /// Create a new tx-only UART with a clear-to-send pin - pub fn new_with_cts( + pub fn new_with_cts( peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, - cts: Peri<'d, impl CtsPin>, + tx: Peri<'d, impl TxPin>, + cts: Peri<'d, impl CtsPin>, tx_dma: Peri<'d, impl TxDma>, config: Config, ) -> Result { @@ -482,19 +482,19 @@ impl<'d> UartTx<'d, Blocking> { /// Create a new blocking tx-only UART with no hardware flow control. /// /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. - pub fn new_blocking( + pub fn new_blocking( peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, + tx: Peri<'d, impl TxPin>, config: Config, ) -> Result { Self::new_inner(peri, new_pin!(tx, config.tx_af()), None, None, config) } /// Create a new blocking tx-only UART with a clear-to-send pin - pub fn new_blocking_with_cts( + pub fn new_blocking_with_cts( peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, - cts: Peri<'d, impl CtsPin>, + tx: Peri<'d, impl TxPin>, + cts: Peri<'d, impl CtsPin>, config: Config, ) -> Result { Self::new_inner( @@ -662,10 +662,10 @@ impl<'d> UartRx<'d, Async> { /// Create a new rx-only UART with no hardware flow control. /// /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. - pub fn new( + pub fn new( peri: Peri<'d, T>, _irq: impl interrupt::typelevel::Binding> + 'd, - rx: Peri<'d, impl RxPin>, + rx: Peri<'d, impl RxPin>, rx_dma: Peri<'d, impl RxDma>, config: Config, ) -> Result { @@ -673,11 +673,11 @@ impl<'d> UartRx<'d, Async> { } /// Create a new rx-only UART with a request-to-send pin - pub fn new_with_rts( + pub fn new_with_rts( peri: Peri<'d, T>, _irq: impl interrupt::typelevel::Binding> + 'd, - rx: Peri<'d, impl RxPin>, - rts: Peri<'d, impl RtsPin>, + rx: Peri<'d, impl RxPin>, + rts: Peri<'d, impl RtsPin>, rx_dma: Peri<'d, impl RxDma>, config: Config, ) -> Result { @@ -913,19 +913,19 @@ impl<'d> UartRx<'d, Blocking> { /// Create a new rx-only UART with no hardware flow control. /// /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. - pub fn new_blocking( + pub fn new_blocking( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, + rx: Peri<'d, impl RxPin>, config: Config, ) -> Result { Self::new_inner(peri, new_pin!(rx, config.rx_af()), None, None, config) } /// Create a new rx-only UART with a request-to-send pin - pub fn new_blocking_with_rts( + pub fn new_blocking_with_rts( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - rts: Peri<'d, impl RtsPin>, + rx: Peri<'d, impl RxPin>, + rts: Peri<'d, impl RtsPin>, config: Config, ) -> Result { Self::new_inner( @@ -1109,10 +1109,10 @@ fn drop_tx_rx(info: &Info, state: &State) { impl<'d> Uart<'d, Async> { /// Create a new bidirectional UART - pub fn new( + pub fn new( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, + rx: Peri<'d, impl RxPin>, + tx: Peri<'d, impl TxPin>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, @@ -1132,13 +1132,13 @@ impl<'d> Uart<'d, Async> { } /// Create a new bidirectional UART with request-to-send and clear-to-send pins - pub fn new_with_rtscts( + pub fn new_with_rtscts( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, + rx: Peri<'d, impl RxPin>, + tx: Peri<'d, impl TxPin>, _irq: impl interrupt::typelevel::Binding> + 'd, - rts: Peri<'d, impl RtsPin>, - cts: Peri<'d, impl CtsPin>, + rts: Peri<'d, impl RtsPin>, + cts: Peri<'d, impl CtsPin>, tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, config: Config, @@ -1158,12 +1158,12 @@ impl<'d> Uart<'d, Async> { #[cfg(not(any(usart_v1, usart_v2)))] /// Create a new bidirectional UART with a driver-enable pin - pub fn new_with_de( + pub fn new_with_de( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, + rx: Peri<'d, impl RxPin>, + tx: Peri<'d, impl TxPin>, _irq: impl interrupt::typelevel::Binding> + 'd, - de: Peri<'d, impl DePin>, + de: Peri<'d, impl DePin>, tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, config: Config, @@ -1193,9 +1193,9 @@ impl<'d> Uart<'d, Async> { /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict /// on the line must be managed by software (for instance by using a centralized arbiter). #[doc(alias("HDSEL"))] - pub fn new_half_duplex( + pub fn new_half_duplex( peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, + tx: Peri<'d, impl TxPin>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, @@ -1232,9 +1232,9 @@ impl<'d> Uart<'d, Async> { /// on the line must be managed by software (for instance by using a centralized arbiter). #[cfg(not(any(usart_v1, usart_v2)))] #[doc(alias("HDSEL"))] - pub fn new_half_duplex_on_rx( + pub fn new_half_duplex_on_rx( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, + rx: Peri<'d, impl RxPin>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, @@ -1280,10 +1280,10 @@ impl<'d> Uart<'d, Async> { impl<'d> Uart<'d, Blocking> { /// Create a new blocking bidirectional UART. - pub fn new_blocking( + pub fn new_blocking( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, + rx: Peri<'d, impl RxPin>, + tx: Peri<'d, impl TxPin>, config: Config, ) -> Result { Self::new_inner( @@ -1300,12 +1300,12 @@ impl<'d> Uart<'d, Blocking> { } /// Create a new bidirectional UART with request-to-send and clear-to-send pins - pub fn new_blocking_with_rtscts( + pub fn new_blocking_with_rtscts( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, - rts: Peri<'d, impl RtsPin>, - cts: Peri<'d, impl CtsPin>, + rx: Peri<'d, impl RxPin>, + tx: Peri<'d, impl TxPin>, + rts: Peri<'d, impl RtsPin>, + cts: Peri<'d, impl CtsPin>, config: Config, ) -> Result { Self::new_inner( @@ -1323,11 +1323,11 @@ impl<'d> Uart<'d, Blocking> { #[cfg(not(any(usart_v1, usart_v2)))] /// Create a new bidirectional UART with a driver-enable pin - pub fn new_blocking_with_de( + pub fn new_blocking_with_de( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, - de: Peri<'d, impl DePin>, + rx: Peri<'d, impl RxPin>, + tx: Peri<'d, impl TxPin>, + de: Peri<'d, impl DePin>, config: Config, ) -> Result { Self::new_inner( @@ -1354,9 +1354,9 @@ impl<'d> Uart<'d, Blocking> { /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict /// on the line must be managed by software (for instance by using a centralized arbiter). #[doc(alias("HDSEL"))] - pub fn new_blocking_half_duplex( + pub fn new_blocking_half_duplex( peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, + tx: Peri<'d, impl TxPin>, mut config: Config, readback: HalfDuplexReadback, ) -> Result { @@ -1390,9 +1390,9 @@ impl<'d> Uart<'d, Blocking> { /// on the line must be managed by software (for instance by using a centralized arbiter). #[cfg(not(any(usart_v1, usart_v2)))] #[doc(alias("HDSEL"))] - pub fn new_blocking_half_duplex_on_rx( + pub fn new_blocking_half_duplex_on_rx( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, + rx: Peri<'d, impl RxPin>, mut config: Config, readback: HalfDuplexReadback, ) -> Result { @@ -2055,12 +2055,12 @@ pub trait Instance: SealedInstance + PeripheralType + 'static + Send { type Interrupt: interrupt::typelevel::Interrupt; } -pin_trait!(RxPin, Instance); -pin_trait!(TxPin, Instance); -pin_trait!(CtsPin, Instance); -pin_trait!(RtsPin, Instance); -pin_trait!(CkPin, Instance); -pin_trait!(DePin, Instance); +pin_trait!(RxPin, Instance, @A); +pin_trait!(TxPin, Instance, @A); +pin_trait!(CtsPin, Instance, @A); +pin_trait!(RtsPin, Instance, @A); +pin_trait!(CkPin, Instance, @A); +pin_trait!(DePin, Instance, @A); dma_trait!(TxDma, Instance); dma_trait!(RxDma, Instance); diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index aeca67659..891ec93fd 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -9,7 +9,9 @@ publish = false [features] stm32c031c6 = ["embassy-stm32/stm32c031c6", "cm0", "not-gpdma"] stm32c071rb = ["embassy-stm32/stm32c071rb", "cm0", "not-gpdma"] -stm32f103c8 = ["embassy-stm32/stm32f103c8", "spi-v1", "not-gpdma"] +stm32f100rd = ["embassy-stm32/stm32f100rd", "spi-v1", "not-gpdma", "afio", "afio-value-line"] +stm32f103c8 = ["embassy-stm32/stm32f103c8", "spi-v1", "not-gpdma", "afio"] +stm32f107vc = ["embassy-stm32/stm32f107vc", "spi-v1", "not-gpdma", "afio", "afio-connectivity-line"] stm32f207zg = ["embassy-stm32/stm32f207zg", "spi-v1", "chrono", "not-gpdma", "eth", "rng"] stm32f303ze = ["embassy-stm32/stm32f303ze", "chrono", "not-gpdma"] stm32f429zi = ["embassy-stm32/stm32f429zi", "spi-v1", "chrono", "eth", "stop", "can", "not-gpdma", "dac", "rng"] @@ -59,6 +61,9 @@ cordic = ["dep:num-traits"] dual-bank = ["embassy-stm32/dual-bank"] single-bank = ["embassy-stm32/single-bank"] eeprom = [] +afio = [] +afio-connectivity-line = [] +afio-value-line = [] cm0 = ["portable-atomic/unsafe-assume-single-core"] @@ -98,6 +103,11 @@ num-traits = { version="0.2", default-features = false,features = ["libm"], opti # BEGIN TESTS # Generated by gen_test.py. DO NOT EDIT. +[[bin]] +name = "afio" +path = "src/bin/afio.rs" +required-features = [ "afio",] + [[bin]] name = "can" path = "src/bin/can.rs" diff --git a/tests/stm32/src/bin/afio.rs b/tests/stm32/src/bin/afio.rs new file mode 100644 index 000000000..c684b7b3e --- /dev/null +++ b/tests/stm32/src/bin/afio.rs @@ -0,0 +1,1156 @@ +// required-features: afio +#![no_std] +#![no_main] +#[path = "../common.rs"] +mod common; + +use common::*; +use embassy_executor::Spawner; +use embassy_stm32::gpio::{OutputType, Pull}; +use embassy_stm32::pac::AFIO; +use embassy_stm32::time::khz; +use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; +use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; +use embassy_stm32::timer::pwm_input::PwmInput; +use embassy_stm32::timer::qei::{Qei, QeiPin}; +use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; +use embassy_stm32::usart::{Uart, UartRx, UartTx}; +use embassy_stm32::{bind_interrupts, Peripherals}; + +#[cfg(not(feature = "afio-connectivity-line"))] +bind_interrupts!(struct Irqs { + USART3 => embassy_stm32::usart::InterruptHandler; + TIM1_CC => embassy_stm32::timer::CaptureCompareInterruptHandler; +}); + +#[cfg(feature = "afio-connectivity-line")] +bind_interrupts!(struct Irqs { + CAN1_RX0 => embassy_stm32::can::Rx0InterruptHandler; + CAN1_RX1 => embassy_stm32::can::Rx1InterruptHandler; + CAN1_SCE => embassy_stm32::can::SceInterruptHandler; + CAN1_TX => embassy_stm32::can::TxInterruptHandler; + + CAN2_RX0 => embassy_stm32::can::Rx0InterruptHandler; + CAN2_RX1 => embassy_stm32::can::Rx1InterruptHandler; + CAN2_SCE => embassy_stm32::can::SceInterruptHandler; + CAN2_TX => embassy_stm32::can::TxInterruptHandler; + + ETH => embassy_stm32::eth::InterruptHandler; + USART3 => embassy_stm32::usart::InterruptHandler; + TIM1_CC => embassy_stm32::timer::CaptureCompareInterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut p = init(); + info!("Hello World!"); + + // USART3 + { + // no remap RX/TX/RTS/CTS + afio_registers_set_remap(); + Uart::new_blocking_with_rtscts( + p.USART3.reborrow(), + p.PB11.reborrow(), + p.PB10.reborrow(), + p.PB14.reborrow(), + p.PB13.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0); + } + { + // no remap RX/TX + afio_registers_set_remap(); + Uart::new_blocking( + p.USART3.reborrow(), + p.PB11.reborrow(), + p.PB10.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0); + } + { + // no remap TX + afio_registers_set_remap(); + Uart::new_blocking_half_duplex( + p.USART3.reborrow(), + p.PB10.reborrow(), + Default::default(), + embassy_stm32::usart::HalfDuplexReadback::NoReadback, + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0); + } + { + // no remap TX async + afio_registers_set_remap(); + UartTx::new( + p.USART3.reborrow(), + p.PB10.reborrow(), + p.DMA1_CH2.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0); + } + { + // no remap TX/CTS async + afio_registers_set_remap(); + UartTx::new_with_cts( + p.USART3.reborrow(), + p.PB10.reborrow(), + p.PB13.reborrow(), + p.DMA1_CH2.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0); + } + { + // no remap RX async + afio_registers_set_remap(); + UartRx::new( + p.USART3.reborrow(), + Irqs, + p.PB11.reborrow(), + p.DMA1_CH3.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0); + } + { + // no remap RX async + afio_registers_set_remap(); + UartRx::new_with_rts( + p.USART3.reborrow(), + Irqs, + p.PB11.reborrow(), + p.PB14.reborrow(), + p.DMA1_CH3.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0); + } + { + // no remap RX/TX async + afio_registers_set_remap(); + Uart::new( + p.USART3.reborrow(), + p.PB11.reborrow(), + p.PB10.reborrow(), + Irqs, + p.DMA1_CH2.reborrow(), + p.DMA1_CH3.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0); + } + { + // no remap RX/TX/RTS/CTS async + afio_registers_set_remap(); + Uart::new_with_rtscts( + p.USART3.reborrow(), + p.PB11.reborrow(), + p.PB10.reborrow(), + Irqs, + p.PB14.reborrow(), + p.PB13.reborrow(), + p.DMA1_CH2.reborrow(), + p.DMA1_CH3.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0); + } + + // TIM1 + { + // no remap + afio_registers_set_remap(); + SimplePwm::new( + p.TIM1.reborrow(), + Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PA9.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PA10.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PA11.reborrow(), OutputType::PushPull)), + khz(10), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 0); + } + { + // no remap + afio_registers_set_remap(); + SimplePwm::new( + p.TIM1.reborrow(), + Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)), + None, + None, + None, + khz(10), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 0); + } + { + // partial remap + reset_afio_registers(); + ComplementaryPwm::new( + p.TIM1.reborrow(), + Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)), + None, + None, + None, + None, + None, + None, + None, + khz(10), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 1); + } + { + // partial remap + reset_afio_registers(); + ComplementaryPwm::new( + p.TIM1.reborrow(), + Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)), + Some(ComplementaryPwmPin::new(p.PA7.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PA9.reborrow(), OutputType::PushPull)), + Some(ComplementaryPwmPin::new(p.PB0.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PA10.reborrow(), OutputType::PushPull)), + None, // pin does not exist on medium-density devices + Some(PwmPin::new(p.PA11.reborrow(), OutputType::PushPull)), + None, // signal does not exist + khz(10), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 1); + } + { + // partial remap + reset_afio_registers(); + InputCapture::new( + p.TIM1.reborrow(), + Some(CapturePin::new(p.PA8.reborrow(), Pull::Down)), + None, + None, + None, + Irqs, + khz(10), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 1); + } + { + // partial remap + reset_afio_registers(); + PwmInput::new_ch1(p.TIM1.reborrow(), p.PA8.reborrow(), Pull::Down, khz(10)); + defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 1); + } + { + // partial remap + reset_afio_registers(); + Qei::new( + p.TIM1.reborrow(), + QeiPin::new(p.PA8.reborrow()), + QeiPin::new(p.PA9.reborrow()), + ); + defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 1); + } + + // TIM2 + { + // no remap + afio_registers_set_remap(); + SimplePwm::new( + p.TIM2.reborrow(), + Some(PwmPin::new(p.PA0.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PA1.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PA2.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PA3.reborrow(), OutputType::PushPull)), + khz(10), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().tim2_remap(), 0); + } + { + // partial remap 1 + reset_afio_registers(); + SimplePwm::new( + p.TIM2.reborrow(), + Some(PwmPin::new(p.PA15.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PB3.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PA2.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PA3.reborrow(), OutputType::PushPull)), + khz(10), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().tim2_remap(), 1); + } + { + // partial remap 2 + reset_afio_registers(); + SimplePwm::new( + p.TIM2.reborrow(), + Some(PwmPin::new(p.PA0.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PA1.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PB10.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PB11.reborrow(), OutputType::PushPull)), + khz(10), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().tim2_remap(), 2); + } + { + // full remap + reset_afio_registers(); + SimplePwm::new( + p.TIM2.reborrow(), + Some(PwmPin::new(p.PA15.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PB3.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PB10.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PB11.reborrow(), OutputType::PushPull)), + khz(10), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().tim2_remap(), 3); + } + + connectivity_line::run(&mut p); + value_line::run(&mut p); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} + +#[cfg(feature = "afio-connectivity-line")] +mod connectivity_line { + use embassy_stm32::can::Can; + use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; + use embassy_stm32::i2s::I2S; + use embassy_stm32::spi::Spi; + + use super::*; + + pub fn run(p: &mut Peripherals) { + // USART3 + { + // partial remap RX/TX/RTS/CTS + reset_afio_registers(); + Uart::new_blocking_with_rtscts( + p.USART3.reborrow(), + p.PC11.reborrow(), + p.PC10.reborrow(), + p.PB14.reborrow(), + p.PB13.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1); + } + { + // partial remap RX/TX + reset_afio_registers(); + Uart::new_blocking( + p.USART3.reborrow(), + p.PC11.reborrow(), + p.PC10.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1); + } + { + // partial remap TX + reset_afio_registers(); + Uart::new_blocking_half_duplex( + p.USART3.reborrow(), + p.PC10.reborrow(), + Default::default(), + embassy_stm32::usart::HalfDuplexReadback::NoReadback, + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1); + } + { + // partial remap TX async + reset_afio_registers(); + UartTx::new( + p.USART3.reborrow(), + p.PC10.reborrow(), + p.DMA1_CH2.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1); + } + { + // partial remap TX/CTS async + reset_afio_registers(); + UartTx::new_with_cts( + p.USART3.reborrow(), + p.PC10.reborrow(), + p.PB13.reborrow(), + p.DMA1_CH2.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1); + } + { + // partial remap RX async + reset_afio_registers(); + UartRx::new( + p.USART3.reborrow(), + Irqs, + p.PC11.reborrow(), + p.DMA1_CH3.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1); + } + { + // partial remap RX async + reset_afio_registers(); + UartRx::new_with_rts( + p.USART3.reborrow(), + Irqs, + p.PC11.reborrow(), + p.PB14.reborrow(), + p.DMA1_CH3.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1); + } + { + // partial remap RX/TX async + reset_afio_registers(); + Uart::new( + p.USART3.reborrow(), + p.PC11.reborrow(), + p.PC10.reborrow(), + Irqs, + p.DMA1_CH2.reborrow(), + p.DMA1_CH3.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1); + } + { + // partial remap RX/TX/RTS/CTS async + reset_afio_registers(); + Uart::new_with_rtscts( + p.USART3.reborrow(), + p.PC11.reborrow(), + p.PC10.reborrow(), + Irqs, + p.PB14.reborrow(), + p.PB13.reborrow(), + p.DMA1_CH2.reborrow(), + p.DMA1_CH3.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1); + } + { + // full remap RX/TX/RTS/CTS + reset_afio_registers(); + Uart::new_blocking_with_rtscts( + p.USART3.reborrow(), + p.PD9.reborrow(), + p.PD8.reborrow(), + p.PD12.reborrow(), + p.PD11.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3); + } + { + // full remap RX/TX + reset_afio_registers(); + Uart::new_blocking( + p.USART3.reborrow(), + p.PD9.reborrow(), + p.PD8.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3); + } + { + // full remap TX + reset_afio_registers(); + Uart::new_blocking_half_duplex( + p.USART3.reborrow(), + p.PD8.reborrow(), + Default::default(), + embassy_stm32::usart::HalfDuplexReadback::NoReadback, + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3); + } + { + // full remap TX async + reset_afio_registers(); + UartTx::new( + p.USART3.reborrow(), + p.PD8.reborrow(), + p.DMA1_CH2.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3); + } + { + // full remap TX/CTS async + reset_afio_registers(); + UartTx::new_with_cts( + p.USART3.reborrow(), + p.PD8.reborrow(), + p.PD11.reborrow(), + p.DMA1_CH2.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3); + } + { + // full remap RX async + reset_afio_registers(); + UartRx::new( + p.USART3.reborrow(), + Irqs, + p.PD9.reborrow(), + p.DMA1_CH3.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3); + } + { + // full remap RX async + reset_afio_registers(); + UartRx::new_with_rts( + p.USART3.reborrow(), + Irqs, + p.PD9.reborrow(), + p.PD12.reborrow(), + p.DMA1_CH3.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3); + } + { + // full remap RX/TX async + reset_afio_registers(); + Uart::new( + p.USART3.reborrow(), + p.PD9.reborrow(), + p.PD8.reborrow(), + Irqs, + p.DMA1_CH2.reborrow(), + p.DMA1_CH3.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3); + } + { + // full remap RX/TX/RTS/CTS async + reset_afio_registers(); + Uart::new_with_rtscts( + p.USART3.reborrow(), + p.PD9.reborrow(), + p.PD8.reborrow(), + Irqs, + p.PD12.reborrow(), + p.PD11.reborrow(), + p.DMA1_CH2.reborrow(), + p.DMA1_CH3.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3); + } + + // SPI3 + { + // no remap SCK/MISO/MOSI + afio_registers_set_remap(); + Spi::new_blocking( + p.SPI3.reborrow(), + p.PB3.reborrow(), + p.PB5.reborrow(), + p.PB4.reborrow(), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), false); + } + { + // no remap SCK/MOSI + afio_registers_set_remap(); + Spi::new_blocking_txonly( + p.SPI3.reborrow(), + p.PB3.reborrow(), + p.PB5.reborrow(), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), false); + } + { + // no remap MOSI + afio_registers_set_remap(); + Spi::new_blocking_txonly_nosck(p.SPI3.reborrow(), p.PB5.reborrow(), Default::default()); + defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), false); + } + { + // no remap SCK/MISO + afio_registers_set_remap(); + Spi::new_blocking_rxonly( + p.SPI3.reborrow(), + p.PB3.reborrow(), + p.PB4.reborrow(), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), false); + } + { + // remap SCK/MISO/MOSI + reset_afio_registers(); + Spi::new_blocking( + p.SPI3.reborrow(), + p.PC10.reborrow(), + p.PC12.reborrow(), + p.PC11.reborrow(), + Default::default(), + ); + + defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true); + } + { + // remap SCK/MOSI + reset_afio_registers(); + Spi::new_blocking_txonly( + p.SPI3.reborrow(), + p.PC10.reborrow(), + p.PC12.reborrow(), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true); + } + { + // remap MOSI + reset_afio_registers(); + Spi::new_blocking_txonly_nosck(p.SPI3.reborrow(), p.PB5.reborrow(), Default::default()); + defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true); + } + { + // remap SCK/MISO + reset_afio_registers(); + Spi::new_blocking_rxonly( + p.SPI3.reborrow(), + p.PC10.reborrow(), + p.PC11.reborrow(), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true); + } + + // I2S3 + { + // no remap SD/WS/CK/MCK + afio_registers_set_remap(); + I2S::new_txonly( + p.SPI3.reborrow(), + p.PB5.reborrow(), + p.PA15.reborrow(), + p.PB3.reborrow(), + p.PC7.reborrow(), + p.DMA2_CH2.reborrow(), + &mut [0u16; 0], + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), false); + } + { + // no remap SD/WS/CK + afio_registers_set_remap(); + I2S::new_txonly_nomck( + p.SPI3.reborrow(), + p.PB5.reborrow(), + p.PA15.reborrow(), + p.PB3.reborrow(), + p.DMA2_CH2.reborrow(), + &mut [0u16; 0], + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), false); + } + { + // no remap SD/WS/CK/MCK + afio_registers_set_remap(); + I2S::new_rxonly( + p.SPI3.reborrow(), + p.PB4.reborrow(), + p.PA15.reborrow(), + p.PB3.reborrow(), + p.PC7.reborrow(), + p.DMA2_CH1.reborrow(), + &mut [0u16; 0], + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true); + } + { + // remap SD/WS/CK/MCK + reset_afio_registers(); + I2S::new_txonly( + p.SPI3.reborrow(), + p.PC12.reborrow(), + p.PA4.reborrow(), + p.PC10.reborrow(), + p.PC7.reborrow(), + p.DMA2_CH2.reborrow(), + &mut [0u16; 0], + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true); + } + { + // remap SD/WS/CK + reset_afio_registers(); + I2S::new_txonly_nomck( + p.SPI3.reborrow(), + p.PC12.reborrow(), + p.PA4.reborrow(), + p.PC10.reborrow(), + p.DMA2_CH2.reborrow(), + &mut [0u16; 0], + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true); + } + { + // remap SD/WS/CK/MCK + reset_afio_registers(); + I2S::new_rxonly( + p.SPI3.reborrow(), + p.PC11.reborrow(), + p.PA4.reborrow(), + p.PC10.reborrow(), + p.PC7.reborrow(), + p.DMA2_CH1.reborrow(), + &mut [0u16; 0], + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true); + } + + // CAN2 + { + // no remap + afio_registers_set_remap(); + Can::new(p.CAN2.reborrow(), p.PB12.reborrow(), p.PB13.reborrow(), Irqs); + defmt::assert_eq!(AFIO.mapr().read().can2_remap(), false); + } + { + // remap + reset_afio_registers(); + Can::new(p.CAN2.reborrow(), p.PB5.reborrow(), p.PB6.reborrow(), Irqs); + defmt::assert_eq!(AFIO.mapr().read().can2_remap(), true); + } + + // Ethernet + { + // no remap RMII + afio_registers_set_remap(); + Ethernet::new( + &mut PacketQueue::<1, 1>::new(), + p.ETH.reborrow(), + Irqs, + p.PA1.reborrow(), + p.PA2.reborrow(), + p.PC1.reborrow(), + p.PA7.reborrow(), + p.PC4.reborrow(), + p.PC5.reborrow(), + p.PB12.reborrow(), + p.PB13.reborrow(), + p.PB11.reborrow(), + GenericPhy::new_auto(), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().eth_remap(), false); + } + { + // no remap MII + afio_registers_set_remap(); + Ethernet::new_mii( + &mut PacketQueue::<1, 1>::new(), + p.ETH.reborrow(), + Irqs, + p.PA1.reborrow(), + p.PC3.reborrow(), + p.PA2.reborrow(), + p.PC1.reborrow(), + p.PA7.reborrow(), + p.PC4.reborrow(), + p.PC5.reborrow(), + p.PB0.reborrow(), + p.PB1.reborrow(), + p.PB12.reborrow(), + p.PB13.reborrow(), + p.PC2.reborrow(), + p.PB8.reborrow(), + p.PB11.reborrow(), + GenericPhy::new_auto(), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().eth_remap(), false); + } + { + // remap RMII + reset_afio_registers(); + Ethernet::new( + &mut PacketQueue::<1, 1>::new(), + p.ETH.reborrow(), + Irqs, + p.PA1.reborrow(), + p.PA2.reborrow(), + p.PC1.reborrow(), + p.PD8.reborrow(), + p.PD9.reborrow(), + p.PD10.reborrow(), + p.PB12.reborrow(), + p.PB13.reborrow(), + p.PB11.reborrow(), + GenericPhy::new_auto(), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().eth_remap(), true); + } + { + // remap MII + reset_afio_registers(); + Ethernet::new_mii( + &mut PacketQueue::<1, 1>::new(), + p.ETH.reborrow(), + Irqs, + p.PA1.reborrow(), + p.PC3.reborrow(), + p.PA2.reborrow(), + p.PC1.reborrow(), + p.PD8.reborrow(), + p.PD9.reborrow(), + p.PD10.reborrow(), + p.PD11.reborrow(), + p.PD12.reborrow(), + p.PB12.reborrow(), + p.PB13.reborrow(), + p.PC2.reborrow(), + p.PB8.reborrow(), + p.PB11.reborrow(), + GenericPhy::new_auto(), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().eth_remap(), true); + } + + // CAN1 + { + // no remap + afio_registers_set_remap(); + Can::new(p.CAN1.reborrow(), p.PA11.reborrow(), p.PA12.reborrow(), Irqs); + defmt::assert_eq!(AFIO.mapr().read().can1_remap(), 0); + } + { + // partial remap + reset_afio_registers(); + Can::new(p.CAN1.reborrow(), p.PB8.reborrow(), p.PB9.reborrow(), Irqs); + defmt::assert_eq!(AFIO.mapr().read().can1_remap(), 2); + } + { + // full remap + reset_afio_registers(); + Can::new(p.CAN1.reborrow(), p.PD0.reborrow(), p.PD1.reborrow(), Irqs); + defmt::assert_eq!(AFIO.mapr().read().can1_remap(), 3); + } + + // USART2 + { + // no remap RX/TX/RTS/CTS + afio_registers_set_remap(); + Uart::new_blocking_with_rtscts( + p.USART2.reborrow(), + p.PA3.reborrow(), + p.PA2.reborrow(), + p.PA1.reborrow(), + p.PA0.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart2_remap(), false); + } + { + // no remap RX/TX + afio_registers_set_remap(); + Uart::new_blocking( + p.USART2.reborrow(), + p.PA3.reborrow(), + p.PA2.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart2_remap(), false); + } + { + // no remap TX + afio_registers_set_remap(); + Uart::new_blocking_half_duplex( + p.USART2.reborrow(), + p.PA2.reborrow(), + Default::default(), + embassy_stm32::usart::HalfDuplexReadback::NoReadback, + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart2_remap(), false); + } + { + // full remap RX/TX/RTS/CTS + reset_afio_registers(); + Uart::new_blocking_with_rtscts( + p.USART2.reborrow(), + p.PD6.reborrow(), + p.PD5.reborrow(), + p.PD4.reborrow(), + p.PD3.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart2_remap(), false); + } + { + // full remap RX/TX + reset_afio_registers(); + Uart::new_blocking( + p.USART2.reborrow(), + p.PD6.reborrow(), + p.PD5.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart2_remap(), false); + } + { + // full remap TX + reset_afio_registers(); + Uart::new_blocking_half_duplex( + p.USART2.reborrow(), + p.PD5.reborrow(), + Default::default(), + embassy_stm32::usart::HalfDuplexReadback::NoReadback, + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart2_remap(), true); + } + + // USART1 + { + // no remap RX/TX/RTS/CTS + afio_registers_set_remap(); + Uart::new_blocking_with_rtscts( + p.USART1.reborrow(), + p.PA10.reborrow(), + p.PA9.reborrow(), + p.PA12.reborrow(), + p.PA11.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart1_remap(), false); + } + { + // no remap RX/TX + afio_registers_set_remap(); + Uart::new_blocking( + p.USART1.reborrow(), + p.PA10.reborrow(), + p.PA9.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart1_remap(), false); + } + { + // no remap TX + afio_registers_set_remap(); + Uart::new_blocking_half_duplex( + p.USART1.reborrow(), + p.PA9.reborrow(), + Default::default(), + embassy_stm32::usart::HalfDuplexReadback::NoReadback, + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart1_remap(), false); + } + { + // remap RX/TX/RTS/CTS + reset_afio_registers(); + Uart::new_blocking_with_rtscts( + p.USART1.reborrow(), + p.PB7.reborrow(), + p.PB6.reborrow(), + p.PA12.reborrow(), + p.PA11.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart1_remap(), true); + } + { + // remap RX/TX + reset_afio_registers(); + Uart::new_blocking( + p.USART1.reborrow(), + p.PB7.reborrow(), + p.PB6.reborrow(), + Default::default(), + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart1_remap(), true); + } + { + // remap TX + reset_afio_registers(); + Uart::new_blocking_half_duplex( + p.USART1.reborrow(), + p.PB6.reborrow(), + Default::default(), + embassy_stm32::usart::HalfDuplexReadback::NoReadback, + ) + .unwrap(); + defmt::assert_eq!(AFIO.mapr().read().usart1_remap(), true); + } + + // TIM1 + { + // full remap + reset_afio_registers(); + SimplePwm::new( + p.TIM1.reborrow(), + Some(PwmPin::new(p.PE9.reborrow(), OutputType::PushPull)), + Some(PwmPin::new(p.PE11.reborrow(), OutputType::PushPull)), + None, + None, + khz(10), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 3); + } + } +} + +#[cfg(feature = "afio-value-line")] +mod value_line { + use super::*; + + pub fn run(p: &mut Peripherals) { + // TIM13 + { + // no remap + reset_afio_registers(); + SimplePwm::new( + p.TIM13.reborrow(), + Some(PwmPin::new(p.PC8.reborrow(), OutputType::PushPull)), + None, + None, + None, + khz(10), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr2().read().tim13_remap(), false); + } + { + // remap + reset_afio_registers(); + SimplePwm::new( + p.TIM13.reborrow(), + Some(PwmPin::new(p.PB0.reborrow(), OutputType::PushPull)), + None, + None, + None, + khz(10), + Default::default(), + ); + defmt::assert_eq!(AFIO.mapr2().read().tim13_remap(), true); + } + } +} + +#[cfg(not(feature = "afio-connectivity-line"))] +mod connectivity_line { + use super::*; + + pub fn run(_: &mut Peripherals) {} +} + +#[cfg(not(feature = "afio-value-line"))] +mod value_line { + use super::*; + + pub fn run(_: &mut Peripherals) {} +} + +fn reset_afio_registers() { + set_afio_registers(false, 0); +} + +fn afio_registers_set_remap() { + set_afio_registers(true, 1); +} + +fn set_afio_registers(bool_val: bool, num_val: u8) { + AFIO.mapr().modify(|w| { + w.set_swj_cfg(embassy_stm32::pac::afio::vals::SwjCfg::NO_OP); + w.set_can1_remap(num_val); + w.set_can2_remap(bool_val); + w.set_eth_remap(bool_val); + w.set_i2c1_remap(bool_val); + w.set_spi1_remap(bool_val); + w.set_spi3_remap(bool_val); + w.set_tim1_remap(num_val); + w.set_tim2_remap(num_val); + w.set_tim3_remap(num_val); + w.set_tim4_remap(bool_val); + w.set_usart1_remap(bool_val); + w.set_usart2_remap(bool_val); + w.set_usart3_remap(num_val); + }); + + AFIO.mapr2().modify(|w| { + w.set_cec_remap(bool_val); + w.set_tim9_remap(bool_val); + w.set_tim10_remap(bool_val); + w.set_tim11_remap(bool_val); + w.set_tim12_remap(bool_val); + w.set_tim13_remap(bool_val); + w.set_tim14_remap(bool_val); + w.set_tim15_remap(bool_val); + w.set_tim16_remap(bool_val); + w.set_tim17_remap(bool_val); + }); +} diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index cb63b3374..f800769ab 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs @@ -103,7 +103,7 @@ define_peris!( SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH3, SPI_RX_DMA = DMA1_CH2, @irq UART = {USART1 => embassy_stm32::usart::InterruptHandler;}, ); -#[cfg(feature = "stm32f103c8")] +#[cfg(any(feature = "stm32f100rd", feature = "stm32f103c8", feature = "stm32f107vc"))] define_peris!( UART = USART1, UART_TX = PA9, UART_RX = PA10, UART_TX_DMA = DMA1_CH4, UART_RX_DMA = DMA1_CH5, SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH3, SPI_RX_DMA = DMA1_CH2, -- cgit From 59af53d53ee99ea133790ad41a85d67cdb1d78b6 Mon Sep 17 00:00:00 2001 From: Francisco José Gómez Date: Fri, 5 Sep 2025 15:20:15 -0400 Subject: fix(embassy-stm32): Remove duplicate fn call, vestigial from earlier refcount implementation Refs: #4577 --- embassy-stm32/CHANGELOG.md | 4 +--- embassy-stm32/src/dac/mod.rs | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index a473834dd..5635481fa 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -13,9 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - fix: stm32/i2c in master mode (blocking): subsequent transmissions failed after a NACK was received - feat: stm32/timer: add set_polarity functions for main and complementary outputs in complementary_pwm - Add I2S support for STM32F1, STM32C0, STM32F0, STM32F3, STM32F7, STM32G0, STM32WL, STM32H5, STM32H7RS -### Fixed - -- STM32: Prevent dropped DacChannel from disabling Dac peripheral if another DacChannel is still in scope ([#4577](https://github.com/embassy-rs/embassy/pull/4577)) +- fix: STM32: Prevent dropped DacChannel from disabling Dac peripheral if another DacChannel is still in scope ([#4577](https://github.com/embassy-rs/embassy/pull/4577)) - feat: Added support for more OctoSPI configurations (e.g. APS6408 RAM) ([#4581](https://github.com/embassy-rs/embassy/pull/4581)) ## 0.4.0 - 2025-08-26 diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index bc6c3cd34..08e001337 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs @@ -575,8 +575,6 @@ impl<'d, T: Instance, M: PeriMode> Dac<'d, T, M> { dma_ch2: Option>, #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] mode: Mode, ) -> Self { - // Enable twice to increment the DAC refcount for each channel. - rcc::enable_and_reset::(); rcc::enable_and_reset::(); let mut ch1 = DacCh1 { -- cgit From 7419b398bf7cc5c1ff164c504f4a4027cd6bcd3b Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 5 Sep 2025 23:00:31 +0200 Subject: stm32/afio: use type inference for timer remaps as well. --- embassy-stm32/build.rs | 131 +++++++++------------------ embassy-stm32/src/macros.rs | 55 ++++++----- embassy-stm32/src/timer/complementary_pwm.rs | 39 +++----- embassy-stm32/src/timer/input_capture.rs | 25 ++--- embassy-stm32/src/timer/mod.rs | 43 ++------- embassy-stm32/src/timer/one_pulse.rs | 66 ++++---------- embassy-stm32/src/timer/pwm_input.rs | 8 +- embassy-stm32/src/timer/qei.rs | 14 +-- embassy-stm32/src/timer/simple_pwm.rs | 31 +++---- examples/stm32f1/src/bin/input_capture.rs | 5 +- examples/stm32f1/src/bin/pwm_input.rs | 4 +- tests/stm32/src/bin/afio.rs | 24 ++--- 12 files changed, 156 insertions(+), 289 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index f55e1e0c9..0d3582c9d 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1391,58 +1391,51 @@ fn main() { }) } - let pin_trait_impl = p - .afio - .as_ref() - .and_then(|afio| { - if p.name.starts_with("TIM") { - // timers are handled by timer_afio_impl!() - return None; - } - - let values = afio - .values - .iter() - .filter(|v| v.pins.contains(&pin.pin)) - .map(|v| v.value) - .collect::>(); + let pin_trait_impl = if let Some(afio) = &p.afio { + let values = afio + .values + .iter() + .filter(|v| v.pins.contains(&pin.pin)) + .map(|v| v.value) + .collect::>(); - if values.is_empty() { - None - } else { - let setter = format_ident!("set_{}", afio.field.to_lowercase()); - let type_and_values = if is_bool_field("AFIO", afio.register, afio.field) { - let values = values.iter().map(|&v| v > 0); - quote!(AfioRemapBool, [#(#values),*]) - } else { - quote!(AfioRemap, [#(#values),*]) - }; - - Some(quote! { - pin_trait_afio_impl!(#tr, #peri, #pin_name, {#setter, #type_and_values}); - }) - } - }) - .unwrap_or_else(|| { - let peripherals_with_afio = [ - "CAN", - "CEC", - "ETH", - "I2C", - "SPI", - "SUBGHZSPI", - "USART", - "UART", - "LPUART", - ]; - let af_or_not_applicable = if peripherals_with_afio.iter().any(|&x| p.name.starts_with(x)) { - quote!(0, crate::gpio::AfioRemapNotApplicable) + if values.is_empty() { + None + } else { + let reg = format_ident!("{}", afio.register.to_lowercase()); + let setter = format_ident!("set_{}", afio.field.to_lowercase()); + let type_and_values = if is_bool_field("AFIO", afio.register, afio.field) { + let values = values.iter().map(|&v| v > 0); + quote!(AfioRemapBool, [#(#values),*]) } else { - quote!(#af) + quote!(AfioRemap, [#(#values),*]) }; - quote!(pin_trait_impl!(#tr, #peri, #pin_name, #af_or_not_applicable);) - }); + Some(quote! { + pin_trait_afio_impl!(#tr, #peri, #pin_name, {#reg, #setter, #type_and_values}); + }) + } + } else { + let peripherals_with_afio = [ + "CAN", + "CEC", + "ETH", + "I2C", + "SPI", + "SUBGHZSPI", + "USART", + "UART", + "LPUART", + "TIM", + ]; + let af_or_not_applicable = if peripherals_with_afio.iter().any(|&x| p.name.starts_with(x)) { + quote!(0, crate::gpio::AfioRemapNotApplicable) + } else { + quote!(#af) + }; + + Some(quote!(pin_trait_impl!(#tr, #peri, #pin_name, #af_or_not_applicable);)) + }; g.extend(pin_trait_impl); } @@ -1969,48 +1962,6 @@ fn main() { pub(crate) const DMA_CHANNELS: &[crate::dma::ChannelInfo] = &[#dmas]; }); - // ======== - // Generate timer AFIO impls - - for p in METADATA.peripherals { - if p.name.starts_with("TIM") { - let pname = format_ident!("{}", p.name); - let afio = if let Some(afio) = &p.afio { - let register = format_ident!("{}", afio.register.to_lowercase()); - let setter = format_ident!("set_{}", afio.field.to_lowercase()); - - let swj_cfg = if afio.register == "MAPR" { - quote!(w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP);) - } else { - quote!() - }; - let bool_eval = if is_bool_field("AFIO", &afio.register, &afio.field) { - quote!(> 0) - } else { - quote!() - }; - - let values = afio.values.iter().map(|v| { - let mapr_value = v.value; - let pin = v.pins.iter().map(|p| { - let port_num = p.chars().nth(1).unwrap() as u8 - b'A'; - let pin_num = p[2..].parse::().unwrap(); - port_num * 16 + pin_num - }); - quote!(#mapr_value, [#(#pin),*]) - }); - - quote! { - , |v| crate::pac::AFIO.#register().modify(|w| { #swj_cfg w.#setter(v #bool_eval); }), #({#values}),* - } - } else { - quote!() - }; - - g.extend(quote!(timer_afio_impl!(#pname #afio);)); - } - } - // ======== // Generate gpio_block() function diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs index f97843a7d..8a3abe1ee 100644 --- a/embassy-stm32/src/macros.rs +++ b/embassy-stm32/src/macros.rs @@ -71,7 +71,31 @@ macro_rules! pin_trait_impl { #[cfg(afio)] macro_rules! pin_trait_afio_impl { - (crate::$mod:ident::$trait:ident, $instance:ident, $pin:ident, {$setter:ident, $type:ident, [$($val:expr),+]}) => { + (@set mapr, $setter:ident, $val:expr) => { + crate::pac::AFIO.mapr().modify(|w| { + w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP); + w.$setter($val); + }); + }; + (@set mapr2, $setter:ident, $val:expr) => { + crate::pac::AFIO.mapr2().modify(|w| { + w.$setter($val); + }); + }; + (crate::$mod:ident::$trait:ident<$mode:ident>, $instance:ident, $pin:ident, {$reg:ident, $setter:ident, $type:ident, [$($val:expr),+]}) => { + $( + impl crate::$mod::$trait> for crate::peripherals::$pin { + fn af_num(&self) -> u8 { + 0 + } + + fn afio_remap(&self) { + pin_trait_afio_impl!(@set $reg, $setter, $val); + } + } + )+ + }; + (crate::$mod:ident::$trait:ident, $instance:ident, $pin:ident, {$reg:ident, $setter:ident, $type:ident, [$($val:expr),+]}) => { $( impl crate::$mod::$trait> for crate::peripherals::$pin { fn af_num(&self) -> u8 { @@ -79,10 +103,7 @@ macro_rules! pin_trait_afio_impl { } fn afio_remap(&self) { - crate::pac::AFIO.mapr().modify(|w| { - w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP); - w.$setter($val); - }); + pin_trait_afio_impl!(@set $reg, $setter, $val); } } )+ @@ -102,30 +123,6 @@ macro_rules! sel_trait_impl { // ==================== -macro_rules! timer_afio_impl { - ($instance:ident $(, $set_afio:expr)? $(,{$mapr_value:literal, [$($pin:literal),*]})*) => { - impl crate::timer::Afio for crate::peripherals::$instance { - fn afio_mappings() -> &'static [crate::timer::AfioMapping] { - &[ - $( - crate::timer::AfioMapping { - value: $mapr_value, - pins: &[$($pin),*], - } - ),* - ] - } - - #[allow(unused)] - fn set_afio(value: u8) { - $($set_afio(value);)? - } - } - }; -} - -// ==================== - macro_rules! dma_trait { ($signal:ident, $instance:path$(, $mode:path)?) => { #[doc = concat!(stringify!($signal), " DMA request trait")] diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 08404cdd6..d3b84ed16 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -16,21 +16,23 @@ use crate::Peri; /// Complementary PWM pin wrapper. /// /// This wraps a pin to make it usable with PWM. -pub struct ComplementaryPwmPin<'d, T, C> { +pub struct ComplementaryPwmPin<'d, T, C, A> { #[allow(unused)] pin: Peri<'d, AnyPin>, - phantom: PhantomData<(T, C)>, + phantom: PhantomData<(T, C, A)>, } -impl<'d, T: AdvancedInstance4Channel, C: TimerChannel> ComplementaryPwmPin<'d, T, C> { +impl<'d, T: AdvancedInstance4Channel, C: TimerChannel, A> ComplementaryPwmPin<'d, T, C, A> { /// Create a new complementary PWM pin instance. - pub fn new(pin: Peri<'d, impl TimerComplementaryPin>, output_type: OutputType) -> Self { + pub fn new(pin: Peri<'d, impl TimerComplementaryPin>, output_type: OutputType) -> Self { critical_section::with(|_| { pin.set_low(); pin.set_as_af( pin.af_num(), crate::gpio::AfType::output(output_type, crate::gpio::Speed::VeryHigh), ); + #[cfg(afio)] + pin.afio_remap(); }); ComplementaryPwmPin { pin: pin.into(), @@ -56,30 +58,19 @@ pub enum IdlePolarity { impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { /// Create a new complementary PWM driver. #[allow(clippy::too_many_arguments, unused)] - pub fn new( + pub fn new( tim: Peri<'d, T>, - ch1: Option>, - ch1n: Option>, - ch2: Option>, - ch2n: Option>, - ch3: Option>, - ch3n: Option>, - ch4: Option>, - ch4n: Option>, + ch1: Option>, + ch1n: Option>, + ch2: Option>, + ch2n: Option>, + ch3: Option>, + ch3n: Option>, + ch4: Option>, + ch4n: Option>, freq: Hertz, counting_mode: CountingMode, ) -> Self { - #[cfg(afio)] - super::set_afio::(&[ - ch1.map(|p| p.pin), - ch1n.map(|p| p.pin), - ch2.map(|p| p.pin), - ch2n.map(|p| p.pin), - ch3.map(|p| p.pin), - ch3n.map(|p| p.pin), - ch4.map(|p| p.pin), - ch4n.map(|p| p.pin), - ]); Self::new_inner(tim, freq, counting_mode) } diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index b717e6eac..262f9d067 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -17,14 +17,14 @@ use crate::Peri; /// Capture pin wrapper. /// /// This wraps a pin to make it usable with capture. -pub struct CapturePin<'d, T, C> { +pub struct CapturePin<'d, T, C, A> { #[allow(unused)] pin: Peri<'d, AnyPin>, - phantom: PhantomData<(T, C)>, + phantom: PhantomData<(T, C, A)>, } -impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> { +impl<'d, T: GeneralInstance4Channel, C: TimerChannel, A> CapturePin<'d, T, C, A> { /// Create a new capture pin instance. - pub fn new(pin: Peri<'d, impl TimerPin>, pull: Pull) -> Self { + pub fn new(pin: Peri<'d, impl TimerPin>, pull: Pull) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); CapturePin { pin: pin.into(), @@ -41,23 +41,16 @@ pub struct InputCapture<'d, T: GeneralInstance4Channel> { impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { /// Create a new input capture driver. #[allow(unused)] - pub fn new( + pub fn new( tim: Peri<'d, T>, - ch1: Option>, - ch2: Option>, - ch3: Option>, - ch4: Option>, + ch1: Option>, + ch2: Option>, + ch3: Option>, + ch4: Option>, _irq: impl Binding> + 'd, freq: Hertz, counting_mode: CountingMode, ) -> Self { - #[cfg(afio)] - super::set_afio::(&[ - ch1.map(|p| p.pin), - ch2.map(|p| p.pin), - ch3.map(|p| p.pin), - ch4.map(|p| p.pin), - ]); Self::new_inner(tim, freq, counting_mode) } diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 38f4a1a51..b09bc7166 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -14,8 +14,6 @@ pub mod pwm_input; pub mod qei; pub mod simple_pwm; -#[cfg(afio)] -use crate::gpio::SealedPin; use crate::interrupt; use crate::rcc::RccPeripheral; @@ -157,15 +155,9 @@ trait SealedInstance: RccPeripheral + PeripheralType { fn state() -> &'static State; } -#[allow(unused)] -pub(crate) trait Afio { - fn afio_mappings() -> &'static [AfioMapping]; - fn set_afio(value: u8); -} - /// Core timer instance. #[allow(private_bounds)] -pub trait CoreInstance: SealedInstance + Afio + 'static { +pub trait CoreInstance: SealedInstance + 'static { /// Update Interrupt for this timer. type UpdateInterrupt: interrupt::typelevel::Interrupt; @@ -231,15 +223,15 @@ pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + Ad /// Advanced 16-bit timer with 4 channels instance. pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {} -pin_trait!(TimerPin, GeneralInstance4Channel, TimerChannel); -pin_trait!(ExternalTriggerPin, GeneralInstance4Channel); +pin_trait!(TimerPin, GeneralInstance4Channel, TimerChannel, @A); +pin_trait!(ExternalTriggerPin, GeneralInstance4Channel, @A); -pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, TimerChannel); +pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, TimerChannel, @A); -pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput); +pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput, @A); -pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel, BreakInput); -pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput); +pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel, BreakInput, @A); +pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput, @A); // Update Event trigger DMA for every timer dma_trait!(UpDma, BasicInstance); @@ -458,24 +450,3 @@ impl interrupt::typelevel::Handler(pins: &[Option>]) { - let mapping = T::afio_mappings() - .iter() - .find(|m| { - pins.iter() - .flatten() - .map(|p| (*p).pin_port()) - .all(|p| m.pins.contains(&p)) - }) - .expect("Should be called with a combination of timer pins supported by the hardware"); - - T::set_afio(mapping.value); -} diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs index 0267749e1..b15cea679 100644 --- a/embassy-stm32/src/timer/one_pulse.rs +++ b/embassy-stm32/src/timer/one_pulse.rs @@ -15,6 +15,7 @@ use crate::gpio::{AfType, AnyPin, Pull}; use crate::interrupt::typelevel::{Binding, Interrupt}; use crate::pac::timer::vals::Etp; use crate::time::Hertz; +use crate::timer::TimerChannel; use crate::Peri; /// External input marker type. @@ -61,58 +62,25 @@ impl SealedTriggerSource for Ch1 {} impl SealedTriggerSource for Ch2 {} impl SealedTriggerSource for Ext {} -trait SealedTimerTriggerPin: crate::gpio::Pin {} - -/// Marker trait for a trigger pin. -#[expect(private_bounds)] -// TODO: find better naming scheme than prefixing all pin traits with "Timer". -// The trait name cannot conflict with the corresponding type's name. -// Applies to other timer submodules as well. -pub trait TimerTriggerPin: SealedTimerTriggerPin { - /// Get the AF number needed to use this pin as a trigger source. - fn af_num(&self) -> u8; -} - -impl TimerTriggerPin for P -where - T: GeneralInstance4Channel, - P: TimerPin, - C: super::TimerChannel + TriggerSource, -{ - fn af_num(&self) -> u8 { - TimerPin::af_num(self) - } -} - -impl TimerTriggerPin for P -where - T: GeneralInstance4Channel, - P: ExternalTriggerPin, -{ - fn af_num(&self) -> u8 { - ExternalTriggerPin::af_num(self) +impl<'d, T: GeneralInstance4Channel, C: TriggerSource + TimerChannel> TriggerPin<'d, T, C> { + /// Create a new Channel trigger pin instance. + pub fn new(pin: Peri<'d, impl TimerPin>, pull: Pull) -> Self { + pin.set_as_af(pin.af_num(), AfType::input(pull)); + #[cfg(afio)] + pin.afio_remap(); + TriggerPin { + pin: pin.into(), + phantom: PhantomData, + } } } -impl SealedTimerTriggerPin for P -where - T: GeneralInstance4Channel, - P: TimerPin, - C: super::TimerChannel + TriggerSource, -{ -} - -impl SealedTimerTriggerPin for P -where - T: GeneralInstance4Channel, - P: ExternalTriggerPin, -{ -} - -impl<'d, T: GeneralInstance4Channel, C: TriggerSource> TriggerPin<'d, T, C> { - /// "Create a new Ch1 trigger pin instance. - pub fn new(pin: Peri<'d, impl TimerTriggerPin>, pull: Pull) -> Self { +impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ext> { + /// Create a new external trigger pin instance. + pub fn new_external(pin: Peri<'d, impl ExternalTriggerPin>, pull: Pull) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); + #[cfg(afio)] + pin.afio_remap(); TriggerPin { pin: pin.into(), phantom: PhantomData, @@ -141,8 +109,6 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { pulse_end: u32, counting_mode: CountingMode, ) -> Self { - #[cfg(afio)] - super::set_afio::(&[Some(pin.pin)]); let mut this = Self { inner: Timer::new(tim) }; this.inner.set_trigger_source(Ts::TI1F_ED); diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index c537e5268..62d7a8550 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -18,19 +18,19 @@ pub struct PwmInput<'d, T: GeneralInstance4Channel> { impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { /// Create a new PWM input driver. - pub fn new_ch1(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { + pub fn new_ch1(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); #[cfg(afio)] - super::set_afio::(&[Some(pin.into())]); + pin.afio_remap(); Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2) } /// Create a new PWM input driver. - pub fn new_ch2(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { + pub fn new_ch2(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); #[cfg(afio)] - super::set_afio::(&[Some(pin.into())]); + pin.afio_remap(); Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1) } diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index 4e5a309ac..39d051294 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -20,18 +20,20 @@ pub enum Direction { } /// Wrapper for using a pin with QEI. -pub struct QeiPin<'d, T, Channel> { +pub struct QeiPin<'d, T, Channel, A> { #[allow(unused)] pin: Peri<'d, AnyPin>, - phantom: PhantomData<(T, Channel)>, + phantom: PhantomData<(T, Channel, A)>, } -impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> { +impl<'d, T: GeneralInstance4Channel, C: QeiChannel, A> QeiPin<'d, T, C, A> { /// Create a new QEI pin instance. - pub fn new(pin: Peri<'d, impl TimerPin>) -> Self { + pub fn new(pin: Peri<'d, impl TimerPin>) -> Self { critical_section::with(|_| { pin.set_low(); pin.set_as_af(pin.af_num(), AfType::input(Pull::None)); + #[cfg(afio)] + pin.afio_remap(); }); QeiPin { pin: pin.into(), @@ -60,9 +62,7 @@ pub struct Qei<'d, T: GeneralInstance4Channel> { impl<'d, T: GeneralInstance4Channel> Qei<'d, T> { /// Create a new quadrature decoder driver. #[allow(unused)] - pub fn new(tim: Peri<'d, T>, ch1: QeiPin<'d, T, Ch1>, ch2: QeiPin<'d, T, Ch2>) -> Self { - #[cfg(afio)] - super::set_afio::(&[Some(ch1.pin), Some(ch2.pin)]); + pub fn new(tim: Peri<'d, T>, ch1: QeiPin<'d, T, Ch1, A>, ch2: QeiPin<'d, T, Ch2, A>) -> Self { Self::new_inner(tim) } diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index df86859fe..53f7cdd22 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -14,10 +14,10 @@ use crate::Peri; /// PWM pin wrapper. /// /// This wraps a pin to make it usable with PWM. -pub struct PwmPin<'d, T, C> { +pub struct PwmPin<'d, T, C, A> { #[allow(unused)] pub(crate) pin: Peri<'d, AnyPin>, - phantom: PhantomData<(T, C)>, + phantom: PhantomData<(T, C, A)>, } /// PWM pin config @@ -35,12 +35,14 @@ pub struct PwmPinConfig { pub pull: Pull, } -impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> { +impl<'d, T: GeneralInstance4Channel, C: TimerChannel, A> PwmPin<'d, T, C, A> { /// Create a new PWM pin instance. - pub fn new(pin: Peri<'d, impl TimerPin>, output_type: OutputType) -> Self { + pub fn new(pin: Peri<'d, impl TimerPin>, output_type: OutputType) -> Self { critical_section::with(|_| { pin.set_low(); pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh)); + #[cfg(afio)] + pin.afio_remap(); }); PwmPin { pin: pin.into(), @@ -49,7 +51,7 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> { } /// Create a new PWM pin instance with config. - pub fn new_with_config(pin: Peri<'d, impl TimerPin>, pin_config: PwmPinConfig) -> Self { + pub fn new_with_config(pin: Peri<'d, impl TimerPin>, pin_config: PwmPinConfig) -> Self { critical_section::with(|_| { pin.set_low(); pin.set_as_af( @@ -59,6 +61,8 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> { #[cfg(gpio_v2)] AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull), ); + #[cfg(afio)] + pin.afio_remap(); }); PwmPin { pin: pin.into(), @@ -180,22 +184,15 @@ pub struct SimplePwm<'d, T: GeneralInstance4Channel> { impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// Create a new simple PWM driver. #[allow(unused)] - pub fn new( + pub fn new( tim: Peri<'d, T>, - ch1: Option>, - ch2: Option>, - ch3: Option>, - ch4: Option>, + ch1: Option>, + ch2: Option>, + ch3: Option>, + ch4: Option>, freq: Hertz, counting_mode: CountingMode, ) -> Self { - #[cfg(afio)] - super::set_afio::(&[ - ch1.map(|p| p.pin), - ch2.map(|p| p.pin), - ch3.map(|p| p.pin), - ch4.map(|p| p.pin), - ]); Self::new_inner(tim, freq, counting_mode) } diff --git a/examples/stm32f1/src/bin/input_capture.rs b/examples/stm32f1/src/bin/input_capture.rs index d747a43c2..b5b26938d 100644 --- a/examples/stm32f1/src/bin/input_capture.rs +++ b/examples/stm32f1/src/bin/input_capture.rs @@ -3,7 +3,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::gpio::{Level, Output, Pull, Speed}; +use embassy_stm32::gpio::{AfioRemap, Level, Output, Pull, Speed}; use embassy_stm32::time::khz; use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; use embassy_stm32::timer::{self, Channel}; @@ -40,7 +40,8 @@ async fn main(spawner: Spawner) { spawner.spawn(unwrap!(blinky(p.PC13))); let ch3 = CapturePin::new(p.PA2, Pull::None); - let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); + let mut ic = + InputCapture::new::>(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); loop { info!("wait for rising edge"); diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs index 63b899767..9ae747018 100644 --- a/examples/stm32f1/src/bin/pwm_input.rs +++ b/examples/stm32f1/src/bin/pwm_input.rs @@ -3,7 +3,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::gpio::{Level, Output, Pull, Speed}; +use embassy_stm32::gpio::{AfioRemap, Level, Output, Pull, Speed}; use embassy_stm32::time::khz; use embassy_stm32::timer::pwm_input::PwmInput; use embassy_stm32::{bind_interrupts, peripherals, timer, Peri}; @@ -38,7 +38,7 @@ async fn main(spawner: Spawner) { spawner.spawn(unwrap!(blinky(p.PC13))); - let mut pwm_input = PwmInput::new_ch1(p.TIM2, p.PA0, Pull::None, khz(10)); + let mut pwm_input = PwmInput::new_ch1::>(p.TIM2, p.PA0, Pull::None, khz(10)); pwm_input.enable(); loop { diff --git a/tests/stm32/src/bin/afio.rs b/tests/stm32/src/bin/afio.rs index c684b7b3e..cc44dc59c 100644 --- a/tests/stm32/src/bin/afio.rs +++ b/tests/stm32/src/bin/afio.rs @@ -6,7 +6,7 @@ mod common; use common::*; use embassy_executor::Spawner; -use embassy_stm32::gpio::{OutputType, Pull}; +use embassy_stm32::gpio::{AfioRemap, OutputType, Pull}; use embassy_stm32::pac::AFIO; use embassy_stm32::time::khz; use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; @@ -173,7 +173,7 @@ async fn main(_spawner: Spawner) { { // no remap afio_registers_set_remap(); - SimplePwm::new( + SimplePwm::new::>( p.TIM1.reborrow(), Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)), Some(PwmPin::new(p.PA9.reborrow(), OutputType::PushPull)), @@ -187,7 +187,7 @@ async fn main(_spawner: Spawner) { { // no remap afio_registers_set_remap(); - SimplePwm::new( + SimplePwm::new::>( p.TIM1.reborrow(), Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)), None, @@ -201,7 +201,7 @@ async fn main(_spawner: Spawner) { { // partial remap reset_afio_registers(); - ComplementaryPwm::new( + ComplementaryPwm::new::>( p.TIM1.reborrow(), Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)), None, @@ -219,7 +219,7 @@ async fn main(_spawner: Spawner) { { // partial remap reset_afio_registers(); - ComplementaryPwm::new( + ComplementaryPwm::new::>( p.TIM1.reborrow(), Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)), Some(ComplementaryPwmPin::new(p.PA7.reborrow(), OutputType::PushPull)), @@ -237,7 +237,7 @@ async fn main(_spawner: Spawner) { { // partial remap reset_afio_registers(); - InputCapture::new( + InputCapture::new::>( p.TIM1.reborrow(), Some(CapturePin::new(p.PA8.reborrow(), Pull::Down)), None, @@ -252,13 +252,13 @@ async fn main(_spawner: Spawner) { { // partial remap reset_afio_registers(); - PwmInput::new_ch1(p.TIM1.reborrow(), p.PA8.reborrow(), Pull::Down, khz(10)); + PwmInput::new_ch1::>(p.TIM1.reborrow(), p.PA8.reborrow(), Pull::Down, khz(10)); defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 1); } { // partial remap reset_afio_registers(); - Qei::new( + Qei::new::>( p.TIM1.reborrow(), QeiPin::new(p.PA8.reborrow()), QeiPin::new(p.PA9.reborrow()), @@ -270,7 +270,7 @@ async fn main(_spawner: Spawner) { { // no remap afio_registers_set_remap(); - SimplePwm::new( + SimplePwm::new::>( p.TIM2.reborrow(), Some(PwmPin::new(p.PA0.reborrow(), OutputType::PushPull)), Some(PwmPin::new(p.PA1.reborrow(), OutputType::PushPull)), @@ -284,7 +284,7 @@ async fn main(_spawner: Spawner) { { // partial remap 1 reset_afio_registers(); - SimplePwm::new( + SimplePwm::new::>( p.TIM2.reborrow(), Some(PwmPin::new(p.PA15.reborrow(), OutputType::PushPull)), Some(PwmPin::new(p.PB3.reborrow(), OutputType::PushPull)), @@ -298,7 +298,7 @@ async fn main(_spawner: Spawner) { { // partial remap 2 reset_afio_registers(); - SimplePwm::new( + SimplePwm::new::>( p.TIM2.reborrow(), Some(PwmPin::new(p.PA0.reborrow(), OutputType::PushPull)), Some(PwmPin::new(p.PA1.reborrow(), OutputType::PushPull)), @@ -312,7 +312,7 @@ async fn main(_spawner: Spawner) { { // full remap reset_afio_registers(); - SimplePwm::new( + SimplePwm::new::>( p.TIM2.reborrow(), Some(PwmPin::new(p.PA15.reborrow(), OutputType::PushPull)), Some(PwmPin::new(p.PB3.reborrow(), OutputType::PushPull)), -- cgit From 35f4ae378cbc9a1263e46baaeac536cae2337896 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 5 Sep 2025 23:44:25 +0200 Subject: stm32/afio: make the A generic param only appear in chips with AFIO. --- embassy-stm32/src/can/bxcan/mod.rs | 6 +- embassy-stm32/src/eth/v1/mod.rs | 50 ++++++------- embassy-stm32/src/eth/v2/mod.rs | 50 ++++++------- embassy-stm32/src/gpio.rs | 1 + embassy-stm32/src/i2c/mod.rs | 12 ++-- embassy-stm32/src/i2s.rs | 46 ++++++------ embassy-stm32/src/macros.rs | 54 +++++++++++++- embassy-stm32/src/spi/mod.rs | 48 ++++++------- embassy-stm32/src/timer/complementary_pwm.rs | 26 +++---- embassy-stm32/src/timer/input_capture.rs | 18 ++--- embassy-stm32/src/timer/one_pulse.rs | 4 +- embassy-stm32/src/timer/pwm_input.rs | 14 +++- embassy-stm32/src/timer/qei.rs | 14 ++-- embassy-stm32/src/timer/simple_pwm.rs | 22 +++--- embassy-stm32/src/usart/buffered.rs | 48 ++++++------- embassy-stm32/src/usart/mod.rs | 104 +++++++++++++-------------- 16 files changed, 291 insertions(+), 226 deletions(-) diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs index 9ebfeb42f..663b34501 100644 --- a/embassy-stm32/src/can/bxcan/mod.rs +++ b/embassy-stm32/src/can/bxcan/mod.rs @@ -181,10 +181,10 @@ pub enum TryWriteError { impl<'d> Can<'d> { /// Creates a new Bxcan instance, keeping the peripheral in sleep mode. /// You must call [Can::enable_non_blocking] to use the peripheral. - pub fn new( + pub fn new( _peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, + tx: Peri<'d, if_afio!(impl TxPin)>, _irqs: impl interrupt::typelevel::Binding> + interrupt::typelevel::Binding> + interrupt::typelevel::Binding> diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index 45be65c5f..2ae451902 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -99,19 +99,19 @@ macro_rules! config_pins { impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { /// safety: the returned instance is not leak-safe - pub fn new( + pub fn new( queue: &'d mut PacketQueue, peri: Peri<'d, T>, irq: impl interrupt::typelevel::Binding + 'd, - ref_clk: Peri<'d, impl RefClkPin>, - mdio: Peri<'d, impl MDIOPin>, - mdc: Peri<'d, impl MDCPin>, - crs: Peri<'d, impl CRSPin>, - rx_d0: Peri<'d, impl RXD0Pin>, - rx_d1: Peri<'d, impl RXD1Pin>, - tx_d0: Peri<'d, impl TXD0Pin>, - tx_d1: Peri<'d, impl TXD1Pin>, - tx_en: Peri<'d, impl TXEnPin>, + ref_clk: Peri<'d, if_afio!(impl RefClkPin)>, + mdio: Peri<'d, if_afio!(impl MDIOPin)>, + mdc: Peri<'d, if_afio!(impl MDCPin)>, + crs: Peri<'d, if_afio!(impl CRSPin)>, + rx_d0: Peri<'d, if_afio!(impl RXD0Pin)>, + rx_d1: Peri<'d, if_afio!(impl RXD1Pin)>, + tx_d0: Peri<'d, if_afio!(impl TXD0Pin)>, + tx_d1: Peri<'d, if_afio!(impl TXD1Pin)>, + tx_en: Peri<'d, if_afio!(impl TXEnPin)>, phy: P, mac_addr: [u8; 6], ) -> Self { @@ -291,24 +291,24 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { } /// Create a new MII ethernet driver using 14 pins. - pub fn new_mii( + pub fn new_mii( queue: &'d mut PacketQueue, peri: Peri<'d, T>, irq: impl interrupt::typelevel::Binding + 'd, - rx_clk: Peri<'d, impl RXClkPin>, - tx_clk: Peri<'d, impl TXClkPin>, - mdio: Peri<'d, impl MDIOPin>, - mdc: Peri<'d, impl MDCPin>, - rxdv: Peri<'d, impl RXDVPin>, - rx_d0: Peri<'d, impl RXD0Pin>, - rx_d1: Peri<'d, impl RXD1Pin>, - rx_d2: Peri<'d, impl RXD2Pin>, - rx_d3: Peri<'d, impl RXD3Pin>, - tx_d0: Peri<'d, impl TXD0Pin>, - tx_d1: Peri<'d, impl TXD1Pin>, - tx_d2: Peri<'d, impl TXD2Pin>, - tx_d3: Peri<'d, impl TXD3Pin>, - tx_en: Peri<'d, impl TXEnPin>, + rx_clk: Peri<'d, if_afio!(impl RXClkPin)>, + tx_clk: Peri<'d, if_afio!(impl TXClkPin)>, + mdio: Peri<'d, if_afio!(impl MDIOPin)>, + mdc: Peri<'d, if_afio!(impl MDCPin)>, + rxdv: Peri<'d, if_afio!(impl RXDVPin)>, + rx_d0: Peri<'d, if_afio!(impl RXD0Pin)>, + rx_d1: Peri<'d, if_afio!(impl RXD1Pin)>, + rx_d2: Peri<'d, if_afio!(impl RXD2Pin)>, + rx_d3: Peri<'d, if_afio!(impl RXD3Pin)>, + tx_d0: Peri<'d, if_afio!(impl TXD0Pin)>, + tx_d1: Peri<'d, if_afio!(impl TXD1Pin)>, + tx_d2: Peri<'d, if_afio!(impl TXD2Pin)>, + tx_d3: Peri<'d, if_afio!(impl TXD3Pin)>, + tx_en: Peri<'d, if_afio!(impl TXEnPin)>, phy: P, mac_addr: [u8; 6], ) -> Self { diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 96ad42c7f..034c5dd88 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs @@ -65,19 +65,19 @@ macro_rules! config_pins { impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { /// Create a new RMII ethernet driver using 9 pins. - pub fn new( + pub fn new( queue: &'d mut PacketQueue, peri: Peri<'d, T>, irq: impl interrupt::typelevel::Binding + 'd, - ref_clk: Peri<'d, impl RefClkPin>, - mdio: Peri<'d, impl MDIOPin>, - mdc: Peri<'d, impl MDCPin>, - crs: Peri<'d, impl CRSPin>, - rx_d0: Peri<'d, impl RXD0Pin>, - rx_d1: Peri<'d, impl RXD1Pin>, - tx_d0: Peri<'d, impl TXD0Pin>, - tx_d1: Peri<'d, impl TXD1Pin>, - tx_en: Peri<'d, impl TXEnPin>, + ref_clk: Peri<'d, impl RefClkPin>, + mdio: Peri<'d, impl MDIOPin>, + mdc: Peri<'d, impl MDCPin>, + crs: Peri<'d, impl CRSPin>, + rx_d0: Peri<'d, impl RXD0Pin>, + rx_d1: Peri<'d, impl RXD1Pin>, + tx_d0: Peri<'d, impl TXD0Pin>, + tx_d1: Peri<'d, impl TXD1Pin>, + tx_en: Peri<'d, impl TXEnPin>, phy: P, mac_addr: [u8; 6], ) -> Self { @@ -110,24 +110,24 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { } /// Create a new MII ethernet driver using 14 pins. - pub fn new_mii( + pub fn new_mii( queue: &'d mut PacketQueue, peri: Peri<'d, T>, irq: impl interrupt::typelevel::Binding + 'd, - rx_clk: Peri<'d, impl RXClkPin>, - tx_clk: Peri<'d, impl TXClkPin>, - mdio: Peri<'d, impl MDIOPin>, - mdc: Peri<'d, impl MDCPin>, - rxdv: Peri<'d, impl RXDVPin>, - rx_d0: Peri<'d, impl RXD0Pin>, - rx_d1: Peri<'d, impl RXD1Pin>, - rx_d2: Peri<'d, impl RXD2Pin>, - rx_d3: Peri<'d, impl RXD3Pin>, - tx_d0: Peri<'d, impl TXD0Pin>, - tx_d1: Peri<'d, impl TXD1Pin>, - tx_d2: Peri<'d, impl TXD2Pin>, - tx_d3: Peri<'d, impl TXD3Pin>, - tx_en: Peri<'d, impl TXEnPin>, + rx_clk: Peri<'d, impl RXClkPin>, + tx_clk: Peri<'d, impl TXClkPin>, + mdio: Peri<'d, impl MDIOPin>, + mdc: Peri<'d, impl MDCPin>, + rxdv: Peri<'d, impl RXDVPin>, + rx_d0: Peri<'d, impl RXD0Pin>, + rx_d1: Peri<'d, impl RXD1Pin>, + rx_d2: Peri<'d, impl RXD2Pin>, + rx_d3: Peri<'d, impl RXD3Pin>, + tx_d0: Peri<'d, impl TXD0Pin>, + tx_d1: Peri<'d, impl TXD1Pin>, + tx_d2: Peri<'d, impl TXD2Pin>, + tx_d3: Peri<'d, impl TXD3Pin>, + tx_en: Peri<'d, impl TXEnPin>, phy: P, mac_addr: [u8; 6], ) -> Self { diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index ef631bbdc..83fd08e23 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs @@ -718,6 +718,7 @@ pub struct AfioRemap; /// Holds the AFIO remap value for a peripheral's pin pub struct AfioRemapBool; +#[cfg(afio)] /// Placeholder for a peripheral's pin which cannot be remapped via AFIO. pub struct AfioRemapNotApplicable; diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index be0ae2f5f..249bac41c 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -149,10 +149,10 @@ pub struct I2c<'d, M: Mode, IM: MasterMode> { impl<'d> I2c<'d, Async, Master> { /// Create a new I2C driver. - pub fn new( + pub fn new( peri: Peri<'d, T>, - scl: Peri<'d, impl SclPin>, - sda: Peri<'d, impl SdaPin>, + scl: Peri<'d, if_afio!(impl SclPin)>, + sda: Peri<'d, if_afio!(impl SdaPin)>, _irq: impl interrupt::typelevel::Binding> + interrupt::typelevel::Binding> + 'd, @@ -173,10 +173,10 @@ impl<'d> I2c<'d, Async, Master> { impl<'d> I2c<'d, Blocking, Master> { /// Create a new blocking I2C driver. - pub fn new_blocking( + pub fn new_blocking( peri: Peri<'d, T>, - scl: Peri<'d, impl SclPin>, - sda: Peri<'d, impl SdaPin>, + scl: Peri<'d, if_afio!(impl SclPin)>, + sda: Peri<'d, if_afio!(impl SdaPin)>, config: Config, ) -> Self { Self::new_inner( diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index 4c634aa17..1b885ec54 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs @@ -237,12 +237,12 @@ pub struct I2S<'d, W: Word> { impl<'d, W: Word> I2S<'d, W> { /// Create a transmitter driver. - pub fn new_txonly( + pub fn new_txonly( peri: Peri<'d, T>, - sd: Peri<'d, impl MosiPin>, - ws: Peri<'d, impl WsPin>, - ck: Peri<'d, impl CkPin>, - mck: Peri<'d, impl MckPin>, + sd: Peri<'d, if_afio!(impl MosiPin)>, + ws: Peri<'d, if_afio!(impl WsPin)>, + ck: Peri<'d, if_afio!(impl CkPin)>, + mck: Peri<'d, if_afio!(impl MckPin)>, txdma: Peri<'d, impl TxDma>, txdma_buf: &'d mut [W], config: Config, @@ -262,11 +262,11 @@ impl<'d, W: Word> I2S<'d, W> { } /// Create a transmitter driver without a master clock pin. - pub fn new_txonly_nomck( + pub fn new_txonly_nomck( peri: Peri<'d, T>, - sd: Peri<'d, impl MosiPin>, - ws: Peri<'d, impl WsPin>, - ck: Peri<'d, impl CkPin>, + sd: Peri<'d, if_afio!(impl MosiPin)>, + ws: Peri<'d, if_afio!(impl WsPin)>, + ck: Peri<'d, if_afio!(impl CkPin)>, txdma: Peri<'d, impl TxDma>, txdma_buf: &'d mut [W], config: Config, @@ -286,12 +286,12 @@ impl<'d, W: Word> I2S<'d, W> { } /// Create a receiver driver. - pub fn new_rxonly( + pub fn new_rxonly( peri: Peri<'d, T>, - sd: Peri<'d, impl MisoPin>, - ws: Peri<'d, impl WsPin>, - ck: Peri<'d, impl CkPin>, - mck: Peri<'d, impl MckPin>, + sd: Peri<'d, if_afio!(impl MisoPin)>, + ws: Peri<'d, if_afio!(impl WsPin)>, + ck: Peri<'d, if_afio!(impl CkPin)>, + mck: Peri<'d, if_afio!(impl MckPin)>, rxdma: Peri<'d, impl RxDma>, rxdma_buf: &'d mut [W], config: Config, @@ -313,13 +313,13 @@ impl<'d, W: Word> I2S<'d, W> { #[cfg(any(spi_v4, spi_v5))] /// Create a full duplex driver. - pub fn new_full_duplex( + pub fn new_full_duplex( peri: Peri<'d, T>, - txsd: Peri<'d, impl MosiPin>, - rxsd: Peri<'d, impl MisoPin>, - ws: Peri<'d, impl WsPin>, - ck: Peri<'d, impl CkPin>, - mck: Peri<'d, impl MckPin>, + txsd: Peri<'d, if_afio!(impl MosiPin)>, + rxsd: Peri<'d, if_afio!(impl MisoPin)>, + ws: Peri<'d, if_afio!(impl WsPin)>, + ck: Peri<'d, if_afio!(impl CkPin)>, + mck: Peri<'d, if_afio!(impl MckPin)>, txdma: Peri<'d, impl TxDma>, txdma_buf: &'d mut [W], rxdma: Peri<'d, impl RxDma>, @@ -459,12 +459,12 @@ impl<'d, W: Word> I2S<'d, W> { } } - fn new_inner( + fn new_inner( peri: Peri<'d, T>, txsd: Option>, rxsd: Option>, - ws: Peri<'d, impl WsPin>, - ck: Peri<'d, impl CkPin>, + ws: Peri<'d, if_afio!(impl WsPin)>, + ck: Peri<'d, if_afio!(impl CkPin)>, mck: Option>, txdma: Option<(ChannelAndRequest<'d>, &'d mut [W])>, rxdma: Option<(ChannelAndRequest<'d>, &'d mut [W])>, diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs index 8a3abe1ee..def8dcf49 100644 --- a/embassy-stm32/src/macros.rs +++ b/embassy-stm32/src/macros.rs @@ -43,7 +43,7 @@ macro_rules! peri_trait_impl { macro_rules! pin_trait { ($signal:ident, $instance:path $(, $mode:path)? $(, @$afio:ident)?) => { #[doc = concat!(stringify!($signal), " pin trait")] - pub trait $signal: crate::gpio::Pin { + pub trait $signal: crate::gpio::Pin { #[doc = concat!("Get the AF number needed to use this pin as ", stringify!($signal))] fn af_num(&self) -> u8; @@ -56,16 +56,23 @@ macro_rules! pin_trait { macro_rules! pin_trait_impl { (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $af:expr $(, $afio:path)?) => { + #[cfg(afio)] impl crate::$mod::$trait for crate::peripherals::$pin { fn af_num(&self) -> u8 { $af } - #[cfg(afio)] fn afio_remap(&self) { // nothing } } + + #[cfg(not(afio))] + impl crate::$mod::$trait for crate::peripherals::$pin { + fn af_num(&self) -> u8 { + $af + } + } }; } @@ -190,3 +197,46 @@ macro_rules! new_pin { Some(pin.into()) }}; } + +#[cfg(afio)] +macro_rules! if_afio { + ($($t:tt)*) => { + $($t)* + } +} +#[cfg(not(afio))] +macro_rules! if_afio { + (($a:ty, A)) => { + ($a,) + }; + (($a:ty, $b:ty, A)) => { + ($a,$b) + }; + (($a:ty, $b:ty, $c:ty, A)) => { + ($a,$b, $c) + }; + ($type:ident<$lt:lifetime, $a:ty, $b:ty, A>) => { + $type<$lt, $a, $b> + }; + ($type:ident<$lt:lifetime, $a:ty, $b:ty, $c:ty, A>) => { + $type<$lt, $a, $b, $c> + }; + ($type:ident<$a:ty, A>) => { + $type<$a> + }; + ($type:ident<$a:ty, $b:ty, A>) => { + $type<$a, $b> + }; + ($type:ident<$a:ty, $b:ty, $c:ty, A>) => { + $type<$a, $b, $c> + }; + (impl $trait:ident<$a:ty, A>) => { + impl $trait<$a> + }; + (impl $trait:ident<$a:ty, $b:ty, A>) => { + impl $trait<$a, $b> + }; + (impl $trait:ident<$a:ty, $b:ty, $c:ty, A>) => { + impl $trait<$a, $b, $c> + }; +} diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 105c617d8..c5373a54d 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -471,11 +471,11 @@ impl<'d, M: PeriMode> Spi<'d, M> { impl<'d> Spi<'d, Blocking> { /// Create a new blocking SPI driver. - pub fn new_blocking( + pub fn new_blocking( peri: Peri<'d, T>, - sck: Peri<'d, impl SckPin>, - mosi: Peri<'d, impl MosiPin>, - miso: Peri<'d, impl MisoPin>, + sck: Peri<'d, if_afio!(impl SckPin)>, + mosi: Peri<'d, if_afio!(impl MosiPin)>, + miso: Peri<'d, if_afio!(impl MisoPin)>, config: Config, ) -> Self { Self::new_inner( @@ -490,10 +490,10 @@ impl<'d> Spi<'d, Blocking> { } /// Create a new blocking SPI driver, in RX-only mode (only MISO pin, no MOSI). - pub fn new_blocking_rxonly( + pub fn new_blocking_rxonly( peri: Peri<'d, T>, - sck: Peri<'d, impl SckPin>, - miso: Peri<'d, impl MisoPin>, + sck: Peri<'d, if_afio!(impl SckPin)>, + miso: Peri<'d, if_afio!(impl MisoPin)>, config: Config, ) -> Self { Self::new_inner( @@ -508,10 +508,10 @@ impl<'d> Spi<'d, Blocking> { } /// Create a new blocking SPI driver, in TX-only mode (only MOSI pin, no MISO). - pub fn new_blocking_txonly( + pub fn new_blocking_txonly( peri: Peri<'d, T>, - sck: Peri<'d, impl SckPin>, - mosi: Peri<'d, impl MosiPin>, + sck: Peri<'d, if_afio!(impl SckPin)>, + mosi: Peri<'d, if_afio!(impl MosiPin)>, config: Config, ) -> Self { Self::new_inner( @@ -528,9 +528,9 @@ impl<'d> Spi<'d, Blocking> { /// Create a new SPI driver, in TX-only mode, without SCK pin. /// /// This can be useful for bit-banging non-SPI protocols. - pub fn new_blocking_txonly_nosck( + pub fn new_blocking_txonly_nosck( peri: Peri<'d, T>, - mosi: Peri<'d, impl MosiPin>, + mosi: Peri<'d, if_afio!(impl MosiPin)>, config: Config, ) -> Self { Self::new_inner( @@ -547,11 +547,11 @@ impl<'d> Spi<'d, Blocking> { impl<'d> Spi<'d, Async> { /// Create a new SPI driver. - pub fn new( + pub fn new( peri: Peri<'d, T>, - sck: Peri<'d, impl SckPin>, - mosi: Peri<'d, impl MosiPin>, - miso: Peri<'d, impl MisoPin>, + sck: Peri<'d, if_afio!(impl SckPin)>, + mosi: Peri<'d, if_afio!(impl MosiPin)>, + miso: Peri<'d, if_afio!(impl MisoPin)>, tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, config: Config, @@ -568,10 +568,10 @@ impl<'d> Spi<'d, Async> { } /// Create a new SPI driver, in RX-only mode (only MISO pin, no MOSI). - pub fn new_rxonly( + pub fn new_rxonly( peri: Peri<'d, T>, - sck: Peri<'d, impl SckPin>, - miso: Peri<'d, impl MisoPin>, + sck: Peri<'d, if_afio!(impl SckPin)>, + miso: Peri<'d, if_afio!(impl MisoPin)>, #[cfg(any(spi_v1, spi_v2, spi_v3))] tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, config: Config, @@ -591,10 +591,10 @@ impl<'d> Spi<'d, Async> { } /// Create a new SPI driver, in TX-only mode (only MOSI pin, no MISO). - pub fn new_txonly( + pub fn new_txonly( peri: Peri<'d, T>, - sck: Peri<'d, impl SckPin>, - mosi: Peri<'d, impl MosiPin>, + sck: Peri<'d, if_afio!(impl SckPin)>, + mosi: Peri<'d, if_afio!(impl MosiPin)>, tx_dma: Peri<'d, impl TxDma>, config: Config, ) -> Self { @@ -612,9 +612,9 @@ impl<'d> Spi<'d, Async> { /// Create a new SPI driver, in TX-only mode, without SCK pin. /// /// This can be useful for bit-banging non-SPI protocols. - pub fn new_txonly_nosck( + pub fn new_txonly_nosck( peri: Peri<'d, T>, - mosi: Peri<'d, impl MosiPin>, + mosi: Peri<'d, if_afio!(impl MosiPin)>, tx_dma: Peri<'d, impl TxDma>, config: Config, ) -> Self { diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index d3b84ed16..693eb3456 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -16,15 +16,15 @@ use crate::Peri; /// Complementary PWM pin wrapper. /// /// This wraps a pin to make it usable with PWM. -pub struct ComplementaryPwmPin<'d, T, C, A> { +pub struct ComplementaryPwmPin<'d, T, C, #[cfg(afio)] A> { #[allow(unused)] pin: Peri<'d, AnyPin>, - phantom: PhantomData<(T, C, A)>, + phantom: PhantomData, } -impl<'d, T: AdvancedInstance4Channel, C: TimerChannel, A> ComplementaryPwmPin<'d, T, C, A> { +impl<'d, T: AdvancedInstance4Channel, C: TimerChannel, #[cfg(afio)] A> if_afio!(ComplementaryPwmPin<'d, T, C, A>) { /// Create a new complementary PWM pin instance. - pub fn new(pin: Peri<'d, impl TimerComplementaryPin>, output_type: OutputType) -> Self { + pub fn new(pin: Peri<'d, if_afio!(impl TimerComplementaryPin)>, output_type: OutputType) -> Self { critical_section::with(|_| { pin.set_low(); pin.set_as_af( @@ -58,16 +58,16 @@ pub enum IdlePolarity { impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { /// Create a new complementary PWM driver. #[allow(clippy::too_many_arguments, unused)] - pub fn new( + pub fn new<#[cfg(afio)] A>( tim: Peri<'d, T>, - ch1: Option>, - ch1n: Option>, - ch2: Option>, - ch2n: Option>, - ch3: Option>, - ch3n: Option>, - ch4: Option>, - ch4n: Option>, + ch1: Option)>, + ch1n: Option)>, + ch2: Option)>, + ch2n: Option)>, + ch3: Option)>, + ch3n: Option)>, + ch4: Option)>, + ch4n: Option)>, freq: Hertz, counting_mode: CountingMode, ) -> Self { diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index 262f9d067..41391bd6d 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -17,14 +17,14 @@ use crate::Peri; /// Capture pin wrapper. /// /// This wraps a pin to make it usable with capture. -pub struct CapturePin<'d, T, C, A> { +pub struct CapturePin<'d, T, C, #[cfg(afio)] A> { #[allow(unused)] pin: Peri<'d, AnyPin>, - phantom: PhantomData<(T, C, A)>, + phantom: PhantomData, } -impl<'d, T: GeneralInstance4Channel, C: TimerChannel, A> CapturePin<'d, T, C, A> { +impl<'d, T: GeneralInstance4Channel, C: TimerChannel, #[cfg(afio)] A> if_afio!(CapturePin<'d, T, C, A>) { /// Create a new capture pin instance. - pub fn new(pin: Peri<'d, impl TimerPin>, pull: Pull) -> Self { + pub fn new(pin: Peri<'d, if_afio!(impl TimerPin)>, pull: Pull) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); CapturePin { pin: pin.into(), @@ -41,12 +41,12 @@ pub struct InputCapture<'d, T: GeneralInstance4Channel> { impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { /// Create a new input capture driver. #[allow(unused)] - pub fn new( + pub fn new<#[cfg(afio)] A>( tim: Peri<'d, T>, - ch1: Option>, - ch2: Option>, - ch3: Option>, - ch4: Option>, + ch1: Option)>, + ch2: Option)>, + ch3: Option)>, + ch4: Option)>, _irq: impl Binding> + 'd, freq: Hertz, counting_mode: CountingMode, diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs index b15cea679..edab38022 100644 --- a/embassy-stm32/src/timer/one_pulse.rs +++ b/embassy-stm32/src/timer/one_pulse.rs @@ -64,7 +64,7 @@ impl SealedTriggerSource for Ext {} impl<'d, T: GeneralInstance4Channel, C: TriggerSource + TimerChannel> TriggerPin<'d, T, C> { /// Create a new Channel trigger pin instance. - pub fn new(pin: Peri<'d, impl TimerPin>, pull: Pull) -> Self { + pub fn new<#[cfg(afio)] A>(pin: Peri<'d, if_afio!(impl TimerPin)>, pull: Pull) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); #[cfg(afio)] pin.afio_remap(); @@ -77,7 +77,7 @@ impl<'d, T: GeneralInstance4Channel, C: TriggerSource + TimerChannel> TriggerPin impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ext> { /// Create a new external trigger pin instance. - pub fn new_external(pin: Peri<'d, impl ExternalTriggerPin>, pull: Pull) -> Self { + pub fn new_external<#[cfg(afio)] A>(pin: Peri<'d, if_afio!(impl ExternalTriggerPin)>, pull: Pull) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); #[cfg(afio)] pin.afio_remap(); diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index 62d7a8550..4c1df0316 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -18,7 +18,12 @@ pub struct PwmInput<'d, T: GeneralInstance4Channel> { impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { /// Create a new PWM input driver. - pub fn new_ch1(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { + pub fn new_ch1<#[cfg(afio)] A>( + tim: Peri<'d, T>, + pin: Peri<'d, if_afio!(impl TimerPin)>, + pull: Pull, + freq: Hertz, + ) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); #[cfg(afio)] pin.afio_remap(); @@ -27,7 +32,12 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { } /// Create a new PWM input driver. - pub fn new_ch2(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { + pub fn new_ch2<#[cfg(afio)] A>( + tim: Peri<'d, T>, + pin: Peri<'d, if_afio!(impl TimerPin)>, + pull: Pull, + freq: Hertz, + ) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); #[cfg(afio)] pin.afio_remap(); diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index 39d051294..528c4a904 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -20,15 +20,15 @@ pub enum Direction { } /// Wrapper for using a pin with QEI. -pub struct QeiPin<'d, T, Channel, A> { +pub struct QeiPin<'d, T, Channel, #[cfg(afio)] A> { #[allow(unused)] pin: Peri<'d, AnyPin>, - phantom: PhantomData<(T, Channel, A)>, + phantom: PhantomData, } -impl<'d, T: GeneralInstance4Channel, C: QeiChannel, A> QeiPin<'d, T, C, A> { +impl<'d, T: GeneralInstance4Channel, C: QeiChannel, #[cfg(afio)] A> if_afio!(QeiPin<'d, T, C, A>) { /// Create a new QEI pin instance. - pub fn new(pin: Peri<'d, impl TimerPin>) -> Self { + pub fn new(pin: Peri<'d, if_afio!(impl TimerPin)>) -> Self { critical_section::with(|_| { pin.set_low(); pin.set_as_af(pin.af_num(), AfType::input(Pull::None)); @@ -62,7 +62,11 @@ pub struct Qei<'d, T: GeneralInstance4Channel> { impl<'d, T: GeneralInstance4Channel> Qei<'d, T> { /// Create a new quadrature decoder driver. #[allow(unused)] - pub fn new(tim: Peri<'d, T>, ch1: QeiPin<'d, T, Ch1, A>, ch2: QeiPin<'d, T, Ch2, A>) -> Self { + pub fn new<#[cfg(afio)] A>( + tim: Peri<'d, T>, + ch1: if_afio!(QeiPin<'d, T, Ch1, A>), + ch2: if_afio!(QeiPin<'d, T, Ch2, A>), + ) -> Self { Self::new_inner(tim) } diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 53f7cdd22..c08a3939f 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -14,10 +14,10 @@ use crate::Peri; /// PWM pin wrapper. /// /// This wraps a pin to make it usable with PWM. -pub struct PwmPin<'d, T, C, A> { +pub struct PwmPin<'d, T, C, #[cfg(afio)] A> { #[allow(unused)] pub(crate) pin: Peri<'d, AnyPin>, - phantom: PhantomData<(T, C, A)>, + phantom: PhantomData, } /// PWM pin config @@ -35,9 +35,9 @@ pub struct PwmPinConfig { pub pull: Pull, } -impl<'d, T: GeneralInstance4Channel, C: TimerChannel, A> PwmPin<'d, T, C, A> { +impl<'d, T: GeneralInstance4Channel, C: TimerChannel, #[cfg(afio)] A> if_afio!(PwmPin<'d, T, C, A>) { /// Create a new PWM pin instance. - pub fn new(pin: Peri<'d, impl TimerPin>, output_type: OutputType) -> Self { + pub fn new(pin: Peri<'d, if_afio!(impl TimerPin)>, output_type: OutputType) -> Self { critical_section::with(|_| { pin.set_low(); pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh)); @@ -50,8 +50,8 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel, A> PwmPin<'d, T, C, A> { } } - /// Create a new PWM pin instance with config. - pub fn new_with_config(pin: Peri<'d, impl TimerPin>, pin_config: PwmPinConfig) -> Self { + /// Create a new PWM pin instance with a specific configuration. + pub fn new_with_config(pin: Peri<'d, if_afio!(impl TimerPin)>, pin_config: PwmPinConfig) -> Self { critical_section::with(|_| { pin.set_low(); pin.set_as_af( @@ -184,12 +184,12 @@ pub struct SimplePwm<'d, T: GeneralInstance4Channel> { impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// Create a new simple PWM driver. #[allow(unused)] - pub fn new( + pub fn new<#[cfg(afio)] A>( tim: Peri<'d, T>, - ch1: Option>, - ch2: Option>, - ch3: Option>, - ch4: Option>, + ch1: Option)>, + ch2: Option)>, + ch3: Option)>, + ch4: Option)>, freq: Hertz, counting_mode: CountingMode, ) -> Self { diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 72aeb8357..890c8a80e 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -208,10 +208,10 @@ impl<'d> SetConfig for BufferedUartTx<'d> { impl<'d> BufferedUart<'d> { /// Create a new bidirectional buffered UART driver - pub fn new( + pub fn new( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, + tx: Peri<'d, if_afio!(impl TxPin)>, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], _irq: impl interrupt::typelevel::Binding> + 'd, @@ -231,12 +231,12 @@ impl<'d> BufferedUart<'d> { } /// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins - pub fn new_with_rtscts( + pub fn new_with_rtscts( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, - rts: Peri<'d, impl RtsPin>, - cts: Peri<'d, impl CtsPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, + tx: Peri<'d, if_afio!(impl TxPin)>, + rts: Peri<'d, if_afio!(impl RtsPin)>, + cts: Peri<'d, if_afio!(impl CtsPin)>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], @@ -256,11 +256,11 @@ impl<'d> BufferedUart<'d> { } /// Create a new bidirectional buffered UART driver with only the RTS pin as the DE pin - pub fn new_with_rts_as_de( + pub fn new_with_rts_as_de( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, - rts: Peri<'d, impl RtsPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, + tx: Peri<'d, if_afio!(impl TxPin)>, + rts: Peri<'d, if_afio!(impl RtsPin)>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], @@ -280,11 +280,11 @@ impl<'d> BufferedUart<'d> { } /// Create a new bidirectional buffered UART driver with only the request-to-send pin - pub fn new_with_rts( + pub fn new_with_rts( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, - rts: Peri<'d, impl RtsPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, + tx: Peri<'d, if_afio!(impl TxPin)>, + rts: Peri<'d, if_afio!(impl RtsPin)>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], @@ -305,11 +305,11 @@ impl<'d> BufferedUart<'d> { /// Create a new bidirectional buffered UART driver with a driver-enable pin #[cfg(not(any(usart_v1, usart_v2)))] - pub fn new_with_de( + pub fn new_with_de( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, - de: Peri<'d, impl DePin>, + rx: Peri<'d, if_afio!(impl RxPin)>, + tx: Peri<'d, if_afio!(impl TxPin)>, + de: Peri<'d, if_afio!(impl DePin)>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], @@ -340,9 +340,9 @@ impl<'d> BufferedUart<'d> { /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict /// on the line must be managed by software (for instance by using a centralized arbiter). #[doc(alias("HDSEL"))] - pub fn new_half_duplex( + pub fn new_half_duplex( peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, + tx: Peri<'d, if_afio!(impl TxPin)>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], @@ -379,9 +379,9 @@ impl<'d> BufferedUart<'d> { /// on the line must be managed by software (for instance by using a centralized arbiter). #[cfg(not(any(usart_v1, usart_v2)))] #[doc(alias("HDSEL"))] - pub fn new_half_duplex_on_rx( + pub fn new_half_duplex_on_rx( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 21d174bf0..ff211e0c9 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -429,9 +429,9 @@ impl<'d, M: Mode> SetConfig for UartRx<'d, M> { impl<'d> UartTx<'d, Async> { /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. - pub fn new( + pub fn new( peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, + tx: Peri<'d, if_afio!(impl TxPin)>, tx_dma: Peri<'d, impl TxDma>, config: Config, ) -> Result { @@ -439,10 +439,10 @@ impl<'d> UartTx<'d, Async> { } /// Create a new tx-only UART with a clear-to-send pin - pub fn new_with_cts( + pub fn new_with_cts( peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, - cts: Peri<'d, impl CtsPin>, + tx: Peri<'d, if_afio!(impl TxPin)>, + cts: Peri<'d, if_afio!(impl CtsPin)>, tx_dma: Peri<'d, impl TxDma>, config: Config, ) -> Result { @@ -482,19 +482,19 @@ impl<'d> UartTx<'d, Blocking> { /// Create a new blocking tx-only UART with no hardware flow control. /// /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. - pub fn new_blocking( + pub fn new_blocking( peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, + tx: Peri<'d, if_afio!(impl TxPin)>, config: Config, ) -> Result { Self::new_inner(peri, new_pin!(tx, config.tx_af()), None, None, config) } /// Create a new blocking tx-only UART with a clear-to-send pin - pub fn new_blocking_with_cts( + pub fn new_blocking_with_cts( peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, - cts: Peri<'d, impl CtsPin>, + tx: Peri<'d, if_afio!(impl TxPin)>, + cts: Peri<'d, if_afio!(impl CtsPin)>, config: Config, ) -> Result { Self::new_inner( @@ -662,10 +662,10 @@ impl<'d> UartRx<'d, Async> { /// Create a new rx-only UART with no hardware flow control. /// /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. - pub fn new( + pub fn new( peri: Peri<'d, T>, _irq: impl interrupt::typelevel::Binding> + 'd, - rx: Peri<'d, impl RxPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, rx_dma: Peri<'d, impl RxDma>, config: Config, ) -> Result { @@ -673,11 +673,11 @@ impl<'d> UartRx<'d, Async> { } /// Create a new rx-only UART with a request-to-send pin - pub fn new_with_rts( + pub fn new_with_rts( peri: Peri<'d, T>, _irq: impl interrupt::typelevel::Binding> + 'd, - rx: Peri<'d, impl RxPin>, - rts: Peri<'d, impl RtsPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, + rts: Peri<'d, if_afio!(impl RtsPin)>, rx_dma: Peri<'d, impl RxDma>, config: Config, ) -> Result { @@ -913,19 +913,19 @@ impl<'d> UartRx<'d, Blocking> { /// Create a new rx-only UART with no hardware flow control. /// /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. - pub fn new_blocking( + pub fn new_blocking( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, config: Config, ) -> Result { Self::new_inner(peri, new_pin!(rx, config.rx_af()), None, None, config) } /// Create a new rx-only UART with a request-to-send pin - pub fn new_blocking_with_rts( + pub fn new_blocking_with_rts( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - rts: Peri<'d, impl RtsPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, + rts: Peri<'d, if_afio!(impl RtsPin)>, config: Config, ) -> Result { Self::new_inner( @@ -1109,10 +1109,10 @@ fn drop_tx_rx(info: &Info, state: &State) { impl<'d> Uart<'d, Async> { /// Create a new bidirectional UART - pub fn new( + pub fn new( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, + tx: Peri<'d, if_afio!(impl TxPin)>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, @@ -1132,13 +1132,13 @@ impl<'d> Uart<'d, Async> { } /// Create a new bidirectional UART with request-to-send and clear-to-send pins - pub fn new_with_rtscts( + pub fn new_with_rtscts( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, + tx: Peri<'d, if_afio!(impl TxPin)>, _irq: impl interrupt::typelevel::Binding> + 'd, - rts: Peri<'d, impl RtsPin>, - cts: Peri<'d, impl CtsPin>, + rts: Peri<'d, if_afio!(impl RtsPin)>, + cts: Peri<'d, if_afio!(impl CtsPin)>, tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, config: Config, @@ -1158,12 +1158,12 @@ impl<'d> Uart<'d, Async> { #[cfg(not(any(usart_v1, usart_v2)))] /// Create a new bidirectional UART with a driver-enable pin - pub fn new_with_de( + pub fn new_with_de( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, + tx: Peri<'d, if_afio!(impl TxPin)>, _irq: impl interrupt::typelevel::Binding> + 'd, - de: Peri<'d, impl DePin>, + de: Peri<'d, if_afio!(impl DePin)>, tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, config: Config, @@ -1193,9 +1193,9 @@ impl<'d> Uart<'d, Async> { /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict /// on the line must be managed by software (for instance by using a centralized arbiter). #[doc(alias("HDSEL"))] - pub fn new_half_duplex( + pub fn new_half_duplex( peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, + tx: Peri<'d, if_afio!(impl TxPin)>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, @@ -1232,9 +1232,9 @@ impl<'d> Uart<'d, Async> { /// on the line must be managed by software (for instance by using a centralized arbiter). #[cfg(not(any(usart_v1, usart_v2)))] #[doc(alias("HDSEL"))] - pub fn new_half_duplex_on_rx( + pub fn new_half_duplex_on_rx( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, _irq: impl interrupt::typelevel::Binding> + 'd, tx_dma: Peri<'d, impl TxDma>, rx_dma: Peri<'d, impl RxDma>, @@ -1280,10 +1280,10 @@ impl<'d> Uart<'d, Async> { impl<'d> Uart<'d, Blocking> { /// Create a new blocking bidirectional UART. - pub fn new_blocking( + pub fn new_blocking( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, + tx: Peri<'d, if_afio!(impl TxPin)>, config: Config, ) -> Result { Self::new_inner( @@ -1300,12 +1300,12 @@ impl<'d> Uart<'d, Blocking> { } /// Create a new bidirectional UART with request-to-send and clear-to-send pins - pub fn new_blocking_with_rtscts( + pub fn new_blocking_with_rtscts( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, - rts: Peri<'d, impl RtsPin>, - cts: Peri<'d, impl CtsPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, + tx: Peri<'d, if_afio!(impl TxPin)>, + rts: Peri<'d, if_afio!(impl RtsPin)>, + cts: Peri<'d, if_afio!(impl CtsPin)>, config: Config, ) -> Result { Self::new_inner( @@ -1323,11 +1323,11 @@ impl<'d> Uart<'d, Blocking> { #[cfg(not(any(usart_v1, usart_v2)))] /// Create a new bidirectional UART with a driver-enable pin - pub fn new_blocking_with_de( + pub fn new_blocking_with_de( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, - tx: Peri<'d, impl TxPin>, - de: Peri<'d, impl DePin>, + rx: Peri<'d, if_afio!(impl RxPin)>, + tx: Peri<'d, if_afio!(impl TxPin)>, + de: Peri<'d, if_afio!(impl DePin)>, config: Config, ) -> Result { Self::new_inner( @@ -1354,9 +1354,9 @@ impl<'d> Uart<'d, Blocking> { /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict /// on the line must be managed by software (for instance by using a centralized arbiter). #[doc(alias("HDSEL"))] - pub fn new_blocking_half_duplex( + pub fn new_blocking_half_duplex( peri: Peri<'d, T>, - tx: Peri<'d, impl TxPin>, + tx: Peri<'d, if_afio!(impl TxPin)>, mut config: Config, readback: HalfDuplexReadback, ) -> Result { @@ -1390,9 +1390,9 @@ impl<'d> Uart<'d, Blocking> { /// on the line must be managed by software (for instance by using a centralized arbiter). #[cfg(not(any(usart_v1, usart_v2)))] #[doc(alias("HDSEL"))] - pub fn new_blocking_half_duplex_on_rx( + pub fn new_blocking_half_duplex_on_rx( peri: Peri<'d, T>, - rx: Peri<'d, impl RxPin>, + rx: Peri<'d, if_afio!(impl RxPin)>, mut config: Config, readback: HalfDuplexReadback, ) -> Result { -- cgit From a23c4b7bca15bc00f4b5c4af200f17eb0097e94b Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 6 Sep 2025 00:11:59 +0200 Subject: stm32/afio: make af_num() unavailable in afio chips. --- .vscode/settings.json | 2 +- embassy-stm32/src/can/bxcan/mod.rs | 10 ++-- embassy-stm32/src/can/fdcan.rs | 4 +- embassy-stm32/src/dcmi.rs | 2 +- embassy-stm32/src/dsihost.rs | 2 +- embassy-stm32/src/eth/v1/mod.rs | 10 ++-- embassy-stm32/src/eth/v2/mod.rs | 2 +- embassy-stm32/src/fmc.rs | 2 +- embassy-stm32/src/gpio.rs | 19 +++++-- embassy-stm32/src/hrtim/mod.rs | 10 +--- embassy-stm32/src/i2s.rs | 4 +- embassy-stm32/src/lptim/pwm.rs | 17 +++---- embassy-stm32/src/macros.rs | 36 ++++++++----- embassy-stm32/src/rcc/mco.rs | 2 +- embassy-stm32/src/sai/mod.rs | 10 ++-- embassy-stm32/src/sdmmc/mod.rs | 76 ++++++++++++++-------------- embassy-stm32/src/spdifrx/mod.rs | 2 +- embassy-stm32/src/timer/complementary_pwm.rs | 8 ++- embassy-stm32/src/timer/input_capture.rs | 2 +- embassy-stm32/src/timer/one_pulse.rs | 8 +-- embassy-stm32/src/timer/pwm_input.rs | 8 +-- embassy-stm32/src/timer/qei.rs | 4 +- embassy-stm32/src/timer/simple_pwm.rs | 18 +++---- embassy-stm32/src/tsc/pin_groups.rs | 2 +- embassy-stm32/src/usb/otg.rs | 10 ++-- embassy-stm32/src/usb/usb.rs | 6 +-- 26 files changed, 132 insertions(+), 144 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 6edd9312a..c504f3ccd 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -17,7 +17,7 @@ //"rust-analyzer.cargo.target": "thumbv8m.main-none-eabihf", "rust-analyzer.cargo.features": [ // Comment out these features when working on the examples. Most example crates do not have any cargo features. - "stm32f446re", + "stm32f107rb", "time-driver-any", "unstable-pac", "exti", diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs index 663b34501..8eb188560 100644 --- a/embassy-stm32/src/can/bxcan/mod.rs +++ b/embassy-stm32/src/can/bxcan/mod.rs @@ -194,10 +194,8 @@ impl<'d> Can<'d> { let info = T::info(); let regs = &T::info().regs; - rx.set_as_af(rx.af_num(), AfType::input(Pull::None)); - #[cfg(afio)] - rx.afio_remap(); - tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!(rx, AfType::input(Pull::None)); + set_as_af!(tx, AfType::output(OutputType::PushPull, Speed::VeryHigh)); rcc::enable_and_reset::(); @@ -231,8 +229,8 @@ impl<'d> Can<'d> { info.sce_interrupt.enable(); } - rx.set_as_af(rx.af_num(), AfType::input(Pull::None)); - tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!(rx, AfType::input(Pull::None)); + set_as_af!(tx, AfType::output(OutputType::PushPull, Speed::VeryHigh)); Registers(T::regs()).leave_init_mode(); diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index 99e40ba62..d8f71e03e 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs @@ -185,8 +185,8 @@ impl<'d> CanConfigurator<'d> { + interrupt::typelevel::Binding> + 'd, ) -> CanConfigurator<'d> { - rx.set_as_af(rx.af_num(), AfType::input(Pull::None)); - tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!(rx, AfType::input(Pull::None)); + set_as_af!(tx, AfType::output(OutputType::PushPull, Speed::VeryHigh)); rcc::enable_and_reset::(); diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs index d05faee21..bd03f1e00 100644 --- a/embassy-stm32/src/dcmi.rs +++ b/embassy-stm32/src/dcmi.rs @@ -108,7 +108,7 @@ macro_rules! config_pins { ($($pin:ident),*) => { critical_section::with(|_| { $( - $pin.set_as_af($pin.af_num(), AfType::input(Pull::None)); + set_as_af!($pin, AfType::input(Pull::None)); )* }) }; diff --git a/embassy-stm32/src/dsihost.rs b/embassy-stm32/src/dsihost.rs index e97ccd9d0..deda956af 100644 --- a/embassy-stm32/src/dsihost.rs +++ b/embassy-stm32/src/dsihost.rs @@ -78,7 +78,7 @@ impl<'d, T: Instance> DsiHost<'d, T> { rcc::enable_and_reset::(); // Set Tearing Enable pin according to CubeMx example - te.set_as_af(te.af_num(), AfType::output(OutputType::PushPull, Speed::Low)); + set_as_af!(te, AfType::output(OutputType::PushPull, Speed::Low)); /* T::regs().wcr().modify(|w| { w.set_dsien(true); diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index 2ae451902..5be1c9739 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -69,7 +69,7 @@ macro_rules! config_in_pins { critical_section::with(|_| { $( // TODO properly create a set_as_input function - $pin.set_as_af($pin.af_num(), AfType::input(Pull::None)); + set_as_af!($pin, AfType::input(Pull::None)); )* }) } @@ -80,7 +80,7 @@ macro_rules! config_af_pins { ($($pin:ident),*) => { critical_section::with(|_| { $( - $pin.set_as_af($pin.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!($pin, AfType::output(OutputType::PushPull, Speed::VeryHigh)); )* }) }; @@ -91,7 +91,7 @@ macro_rules! config_pins { ($($pin:ident),*) => { critical_section::with(|_| { $( - $pin.set_as_af($pin.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!($pin, AfType::output(OutputType::PushPull, Speed::VeryHigh)); )* }) }; @@ -150,8 +150,6 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { { config_in_pins!(ref_clk, rx_d0, rx_d1); config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_en); - #[cfg(afio)] - rx_d0.afio_remap(); } #[cfg(any(eth_v1b, eth_v1c))] @@ -349,8 +347,6 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { { config_in_pins!(rx_clk, tx_clk, rx_d0, rx_d1, rx_d2, rx_d3, rxdv); config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_d2, tx_d3, tx_en); - #[cfg(afio)] - rx_d0.afio_remap(); } #[cfg(any(eth_v1b, eth_v1c))] diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 034c5dd88..cf7a9901b 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs @@ -57,7 +57,7 @@ macro_rules! config_pins { critical_section::with(|_| { $( // TODO: shouldn't some pins be configured as inputs? - $pin.set_as_af($pin.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!($pin, AfType::output(OutputType::PushPull, Speed::VeryHigh)); )* }) }; diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs index 71ca775cb..ff18a8bee 100644 --- a/embassy-stm32/src/fmc.rs +++ b/embassy-stm32/src/fmc.rs @@ -75,7 +75,7 @@ where macro_rules! config_pins { ($($pin:ident),*) => { $( - $pin.set_as_af($pin.af_num(), AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)); + set_as_af!($pin, AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up)); )* }; } diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index 83fd08e23..5a8d23183 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs @@ -150,9 +150,13 @@ impl<'d> Flex<'d> { /// This puts the pin into the AF mode, with the requested number and AF type. This is /// completely unchecked, it can attach the pin to literally any peripheral, so use with care. #[inline] - pub fn set_as_af_unchecked(&mut self, af_num: u8, af_type: AfType) { + pub fn set_as_af_unchecked(&mut self, #[cfg(not(afio))] af_num: u8, af_type: AfType) { critical_section::with(|_| { - self.pin.set_as_af(af_num, af_type); + self.pin.set_as_af( + #[cfg(not(afio))] + af_num, + af_type, + ); }); } @@ -588,7 +592,7 @@ impl AfType { #[inline(never)] #[cfg(gpio_v1)] -fn set_as_af(pin_port: u8, _af_num: u8, af_type: AfType) { +fn set_as_af(pin_port: u8, af_type: AfType) { let pin = unsafe { AnyPin::steal(pin_port) }; let r = pin.block(); let n = pin._pin() as usize; @@ -755,8 +759,13 @@ pub(crate) trait SealedPin { } #[inline] - fn set_as_af(&self, af_num: u8, af_type: AfType) { - set_as_af(self.pin_port(), af_num, af_type) + fn set_as_af(&self, #[cfg(not(afio))] af_num: u8, af_type: AfType) { + set_as_af( + self.pin_port(), + #[cfg(not(afio))] + af_num, + af_type, + ) } #[inline] diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs index 1d0594125..6fece5eb2 100644 --- a/embassy-stm32/src/hrtim/mod.rs +++ b/embassy-stm32/src/hrtim/mod.rs @@ -79,10 +79,7 @@ macro_rules! advanced_channel_impl { pub fn $new_chx(pin: Peri<'d, impl $pin_trait>) -> Self { critical_section::with(|_| { pin.set_low(); - pin.set_as_af( - pin.af_num(), - AfType::output(OutputType::PushPull, Speed::VeryHigh), - ); + set_as_af!(pin, AfType::output(OutputType::PushPull, Speed::VeryHigh)); }); PwmPin { _pin: pin.into(), @@ -96,10 +93,7 @@ macro_rules! advanced_channel_impl { pub fn $new_chx(pin: Peri<'d, impl $complementary_pin_trait>) -> Self { critical_section::with(|_| { pin.set_low(); - pin.set_as_af( - pin.af_num(), - AfType::output(OutputType::PushPull, Speed::VeryHigh), - ); + set_as_af!(pin, AfType::output(OutputType::PushPull, Speed::VeryHigh)); }); ComplementaryPwmPin { _pin: pin.into(), diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index 1b885ec54..b6d3daf54 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs @@ -471,8 +471,8 @@ impl<'d, W: Word> I2S<'d, W> { config: Config, function: Function, ) -> Self { - ws.set_as_af(ws.af_num(), AfType::output(OutputType::PushPull, config.gpio_speed)); - ck.set_as_af(ck.af_num(), AfType::output(OutputType::PushPull, config.gpio_speed)); + set_as_af!(ws, AfType::output(OutputType::PushPull, config.gpio_speed)); + set_as_af!(ck, AfType::output(OutputType::PushPull, config.gpio_speed)); let spi = Spi::new_internal(peri, None, None, { let mut spi_config = SpiConfig::default(); diff --git a/embassy-stm32/src/lptim/pwm.rs b/embassy-stm32/src/lptim/pwm.rs index 2f2d7ba01..96af9f4d9 100644 --- a/embassy-stm32/src/lptim/pwm.rs +++ b/embassy-stm32/src/lptim/pwm.rs @@ -50,10 +50,7 @@ macro_rules! channel_impl { pub fn $new_chx(pin: Peri<'d, impl $pin_trait>) -> Self { critical_section::with(|_| { pin.set_low(); - pin.set_as_af( - pin.af_num(), - AfType::output(OutputType::PushPull, Speed::VeryHigh), - ); + set_as_af!(pin, AfType::output(OutputType::PushPull, Speed::VeryHigh)); }); PwmPin { _pin: pin.into(), @@ -64,12 +61,12 @@ macro_rules! channel_impl { pub fn $new_chx_with_config(pin: Peri<'d, impl $pin_trait>, pin_config: PwmPinConfig) -> Self { critical_section::with(|_| { pin.set_low(); - pin.set_as_af( - pin.af_num(), - #[cfg(gpio_v1)] - AfType::output(pin_config.output_type, pin_config.speed), - #[cfg(gpio_v2)] - AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull), + #[cfg(gpio_v1)] + set_as_af!(pin, AfType::output(pin_config.output_type, pin_config.speed)); + #[cfg(gpio_v2)] + set_as_af!( + pin, + AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull) ); }); PwmPin { diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs index def8dcf49..22cc2e049 100644 --- a/embassy-stm32/src/macros.rs +++ b/embassy-stm32/src/macros.rs @@ -44,6 +44,7 @@ macro_rules! pin_trait { ($signal:ident, $instance:path $(, $mode:path)? $(, @$afio:ident)?) => { #[doc = concat!(stringify!($signal), " pin trait")] pub trait $signal: crate::gpio::Pin { + #[cfg(not(afio))] #[doc = concat!("Get the AF number needed to use this pin as ", stringify!($signal))] fn af_num(&self) -> u8; @@ -58,10 +59,6 @@ macro_rules! pin_trait_impl { (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $af:expr $(, $afio:path)?) => { #[cfg(afio)] impl crate::$mod::$trait for crate::peripherals::$pin { - fn af_num(&self) -> u8 { - $af - } - fn afio_remap(&self) { // nothing } @@ -92,10 +89,6 @@ macro_rules! pin_trait_afio_impl { (crate::$mod:ident::$trait:ident<$mode:ident>, $instance:ident, $pin:ident, {$reg:ident, $setter:ident, $type:ident, [$($val:expr),+]}) => { $( impl crate::$mod::$trait> for crate::peripherals::$pin { - fn af_num(&self) -> u8 { - 0 - } - fn afio_remap(&self) { pin_trait_afio_impl!(@set $reg, $setter, $val); } @@ -105,10 +98,6 @@ macro_rules! pin_trait_afio_impl { (crate::$mod:ident::$trait:ident, $instance:ident, $pin:ident, {$reg:ident, $setter:ident, $type:ident, [$($val:expr),+]}) => { $( impl crate::$mod::$trait> for crate::peripherals::$pin { - fn af_num(&self) -> u8 { - 0 - } - fn afio_remap(&self) { pin_trait_afio_impl!(@set $reg, $setter, $val); } @@ -193,11 +182,32 @@ macro_rules! new_pin { let pin = $name; #[cfg(afio)] pin.afio_remap(); - pin.set_as_af(pin.af_num(), $af_type); + pin.set_as_af( + #[cfg(not(afio))] + pin.af_num(), + $af_type, + ); Some(pin.into()) }}; } +/// Macro to configure a pin for alternate function use. +/// For AFIO chips (STM32F1), it calls afio_remap(). +/// For non-AFIO chips, it calls set_as_af() with the pin's af_num(). +macro_rules! set_as_af { + ($pin:expr, $af_type:expr) => { + #[cfg(afio)] + { + $pin.set_as_af($af_type); + $pin.afio_remap(); + } + #[cfg(not(afio))] + { + $pin.set_as_af($pin.af_num(), $af_type); + } + }; +} + #[cfg(afio)] macro_rules! if_afio { ($($t:tt)*) => { diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs index 96e628b1a..59ccc8cb5 100644 --- a/embassy-stm32/src/rcc/mco.rs +++ b/embassy-stm32/src/rcc/mco.rs @@ -94,7 +94,7 @@ impl<'d, T: McoInstance> Mco<'d, T> { pub fn new(_peri: Peri<'d, T>, pin: Peri<'d, impl McoPin>, source: T::Source, prescaler: McoPrescaler) -> Self { critical_section::with(|_| unsafe { T::_apply_clock_settings(source, prescaler); - pin.set_as_af(pin.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!(pin, AfType::output(OutputType::PushPull, Speed::VeryHigh)); }); Self { phantom: PhantomData } diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index cde2a56c2..fb8b23b79 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -558,7 +558,7 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { config: Config, ) -> Self { let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); - mclk.set_as_af(mclk.af_num(), ck_af_type); + set_as_af!(mclk, ck_af_type); Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config) } @@ -578,9 +578,9 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { let peri = peri.peri; let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); - sd.set_as_af(sd.af_num(), sd_af_type); - sck.set_as_af(sck.af_num(), ck_af_type); - fs.set_as_af(fs.af_num(), ck_af_type); + set_as_af!(sd, sd_af_type); + set_as_af!(sck, ck_af_type); + set_as_af!(fs, ck_af_type); let sub_block = S::WHICH; let request = dma.request(); @@ -612,7 +612,7 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> { let peri = peri.peri; let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx); - sd.set_as_af(sd.af_num(), sd_af_type); + set_as_af!(sd, sd_af_type); let sub_block = S::WHICH; let request = dma.request(); diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 6e5d735d7..ccbd16cbf 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs @@ -428,9 +428,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> { config: Config, ) -> Self { critical_section::with(|_| { - clk.set_as_af(clk.af_num(), CLK_AF); - cmd.set_as_af(cmd.af_num(), CMD_AF); - d0.set_as_af(d0.af_num(), DATA_AF); + set_as_af!(clk, CLK_AF); + set_as_af!(cmd, CMD_AF); + set_as_af!(d0, DATA_AF); }); Self::new_inner( @@ -464,12 +464,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> { config: Config, ) -> Self { critical_section::with(|_| { - clk.set_as_af(clk.af_num(), CLK_AF); - cmd.set_as_af(cmd.af_num(), CMD_AF); - d0.set_as_af(d0.af_num(), DATA_AF); - d1.set_as_af(d1.af_num(), DATA_AF); - d2.set_as_af(d2.af_num(), DATA_AF); - d3.set_as_af(d3.af_num(), DATA_AF); + set_as_af!(clk, CLK_AF); + set_as_af!(cmd, CMD_AF); + set_as_af!(d0, DATA_AF); + set_as_af!(d1, DATA_AF); + set_as_af!(d2, DATA_AF); + set_as_af!(d3, DATA_AF); }); Self::new_inner( @@ -510,16 +510,16 @@ impl<'d, T: Instance> Sdmmc<'d, T> { config: Config, ) -> Self { critical_section::with(|_| { - clk.set_as_af(clk.af_num(), CLK_AF); - cmd.set_as_af(cmd.af_num(), CMD_AF); - d0.set_as_af(d0.af_num(), DATA_AF); - d1.set_as_af(d1.af_num(), DATA_AF); - d2.set_as_af(d2.af_num(), DATA_AF); - d3.set_as_af(d3.af_num(), DATA_AF); - d4.set_as_af(d4.af_num(), DATA_AF); - d5.set_as_af(d5.af_num(), DATA_AF); - d6.set_as_af(d6.af_num(), DATA_AF); - d7.set_as_af(d7.af_num(), DATA_AF); + set_as_af!(clk, CLK_AF); + set_as_af!(cmd, CMD_AF); + set_as_af!(d0, DATA_AF); + set_as_af!(d1, DATA_AF); + set_as_af!(d2, DATA_AF); + set_as_af!(d3, DATA_AF); + set_as_af!(d4, DATA_AF); + set_as_af!(d5, DATA_AF); + set_as_af!(d6, DATA_AF); + set_as_af!(d7, DATA_AF); }); Self::new_inner( @@ -552,9 +552,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> { config: Config, ) -> Self { critical_section::with(|_| { - clk.set_as_af(clk.af_num(), CLK_AF); - cmd.set_as_af(cmd.af_num(), CMD_AF); - d0.set_as_af(d0.af_num(), DATA_AF); + set_as_af!(clk, CLK_AF); + set_as_af!(cmd, CMD_AF); + set_as_af!(d0, DATA_AF); }); Self::new_inner( @@ -586,12 +586,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> { config: Config, ) -> Self { critical_section::with(|_| { - clk.set_as_af(clk.af_num(), CLK_AF); - cmd.set_as_af(cmd.af_num(), CMD_AF); - d0.set_as_af(d0.af_num(), DATA_AF); - d1.set_as_af(d1.af_num(), DATA_AF); - d2.set_as_af(d2.af_num(), DATA_AF); - d3.set_as_af(d3.af_num(), DATA_AF); + set_as_af!(clk, CLK_AF); + set_as_af!(cmd, CMD_AF); + set_as_af!(d0, DATA_AF); + set_as_af!(d1, DATA_AF); + set_as_af!(d2, DATA_AF); + set_as_af!(d3, DATA_AF); }); Self::new_inner( @@ -630,16 +630,16 @@ impl<'d, T: Instance> Sdmmc<'d, T> { config: Config, ) -> Self { critical_section::with(|_| { - clk.set_as_af(clk.af_num(), CLK_AF); - cmd.set_as_af(cmd.af_num(), CMD_AF); - d0.set_as_af(d0.af_num(), DATA_AF); - d1.set_as_af(d1.af_num(), DATA_AF); - d2.set_as_af(d2.af_num(), DATA_AF); - d3.set_as_af(d3.af_num(), DATA_AF); - d4.set_as_af(d4.af_num(), DATA_AF); - d5.set_as_af(d5.af_num(), DATA_AF); - d6.set_as_af(d6.af_num(), DATA_AF); - d7.set_as_af(d7.af_num(), DATA_AF); + set_as_af!(clk, CLK_AF); + set_as_af!(cmd, CMD_AF); + set_as_af!(d0, DATA_AF); + set_as_af!(d1, DATA_AF); + set_as_af!(d2, DATA_AF); + set_as_af!(d3, DATA_AF); + set_as_af!(d4, DATA_AF); + set_as_af!(d5, DATA_AF); + set_as_af!(d6, DATA_AF); + set_as_af!(d7, DATA_AF); }); Self::new_inner( diff --git a/embassy-stm32/src/spdifrx/mod.rs b/embassy-stm32/src/spdifrx/mod.rs index 466639e83..b0a32d5d1 100644 --- a/embassy-stm32/src/spdifrx/mod.rs +++ b/embassy-stm32/src/spdifrx/mod.rs @@ -35,7 +35,7 @@ macro_rules! new_spdifrx_pin { ($name:ident, $af_type:expr) => {{ let pin = $name; let input_sel = pin.input_sel(); - pin.set_as_af(pin.af_num(), $af_type); + set_as_af!(pin, $af_type); (Some(pin.into()), input_sel) }}; } diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 693eb3456..484aae1d0 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -27,12 +27,10 @@ impl<'d, T: AdvancedInstance4Channel, C: TimerChannel, #[cfg(afio)] A> if_afio!( pub fn new(pin: Peri<'d, if_afio!(impl TimerComplementaryPin)>, output_type: OutputType) -> Self { critical_section::with(|_| { pin.set_low(); - pin.set_as_af( - pin.af_num(), - crate::gpio::AfType::output(output_type, crate::gpio::Speed::VeryHigh), + set_as_af!( + pin, + crate::gpio::AfType::output(output_type, crate::gpio::Speed::VeryHigh) ); - #[cfg(afio)] - pin.afio_remap(); }); ComplementaryPwmPin { pin: pin.into(), diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index 41391bd6d..7a25e6c21 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -25,7 +25,7 @@ pub struct CapturePin<'d, T, C, #[cfg(afio)] A> { impl<'d, T: GeneralInstance4Channel, C: TimerChannel, #[cfg(afio)] A> if_afio!(CapturePin<'d, T, C, A>) { /// Create a new capture pin instance. pub fn new(pin: Peri<'d, if_afio!(impl TimerPin)>, pull: Pull) -> Self { - pin.set_as_af(pin.af_num(), AfType::input(pull)); + set_as_af!(pin, AfType::input(pull)); CapturePin { pin: pin.into(), phantom: PhantomData, diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs index edab38022..a75b41bd7 100644 --- a/embassy-stm32/src/timer/one_pulse.rs +++ b/embassy-stm32/src/timer/one_pulse.rs @@ -65,9 +65,7 @@ impl SealedTriggerSource for Ext {} impl<'d, T: GeneralInstance4Channel, C: TriggerSource + TimerChannel> TriggerPin<'d, T, C> { /// Create a new Channel trigger pin instance. pub fn new<#[cfg(afio)] A>(pin: Peri<'d, if_afio!(impl TimerPin)>, pull: Pull) -> Self { - pin.set_as_af(pin.af_num(), AfType::input(pull)); - #[cfg(afio)] - pin.afio_remap(); + set_as_af!(pin, AfType::input(pull)); TriggerPin { pin: pin.into(), phantom: PhantomData, @@ -78,9 +76,7 @@ impl<'d, T: GeneralInstance4Channel, C: TriggerSource + TimerChannel> TriggerPin impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ext> { /// Create a new external trigger pin instance. pub fn new_external<#[cfg(afio)] A>(pin: Peri<'d, if_afio!(impl ExternalTriggerPin)>, pull: Pull) -> Self { - pin.set_as_af(pin.af_num(), AfType::input(pull)); - #[cfg(afio)] - pin.afio_remap(); + set_as_af!(pin, AfType::input(pull)); TriggerPin { pin: pin.into(), phantom: PhantomData, diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index 4c1df0316..159b5a177 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -24,9 +24,7 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { pull: Pull, freq: Hertz, ) -> Self { - pin.set_as_af(pin.af_num(), AfType::input(pull)); - #[cfg(afio)] - pin.afio_remap(); + set_as_af!(pin, AfType::input(pull)); Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2) } @@ -38,9 +36,7 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { pull: Pull, freq: Hertz, ) -> Self { - pin.set_as_af(pin.af_num(), AfType::input(pull)); - #[cfg(afio)] - pin.afio_remap(); + set_as_af!(pin, AfType::input(pull)); Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1) } diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index 528c4a904..82b5968b0 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -31,9 +31,7 @@ impl<'d, T: GeneralInstance4Channel, C: QeiChannel, #[cfg(afio)] A> if_afio!(Qei pub fn new(pin: Peri<'d, if_afio!(impl TimerPin)>) -> Self { critical_section::with(|_| { pin.set_low(); - pin.set_as_af(pin.af_num(), AfType::input(Pull::None)); - #[cfg(afio)] - pin.afio_remap(); + set_as_af!(pin, AfType::input(Pull::None)); }); QeiPin { pin: pin.into(), diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index c08a3939f..e6165e42b 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -40,9 +40,7 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel, #[cfg(afio)] A> if_afio!(P pub fn new(pin: Peri<'d, if_afio!(impl TimerPin)>, output_type: OutputType) -> Self { critical_section::with(|_| { pin.set_low(); - pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh)); - #[cfg(afio)] - pin.afio_remap(); + set_as_af!(pin, AfType::output(output_type, Speed::VeryHigh)); }); PwmPin { pin: pin.into(), @@ -54,15 +52,13 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel, #[cfg(afio)] A> if_afio!(P pub fn new_with_config(pin: Peri<'d, if_afio!(impl TimerPin)>, pin_config: PwmPinConfig) -> Self { critical_section::with(|_| { pin.set_low(); - pin.set_as_af( - pin.af_num(), - #[cfg(gpio_v1)] - AfType::output(pin_config.output_type, pin_config.speed), - #[cfg(gpio_v2)] - AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull), + #[cfg(gpio_v1)] + set_as_af!(pin, AfType::output(pin_config.output_type, pin_config.speed)); + #[cfg(gpio_v2)] + set_as_af!( + pin, + AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull) ); - #[cfg(afio)] - pin.afio_remap(); }); PwmPin { pin: pin.into(), diff --git a/embassy-stm32/src/tsc/pin_groups.rs b/embassy-stm32/src/tsc/pin_groups.rs index 6f914a94e..84421f7ff 100644 --- a/embassy-stm32/src/tsc/pin_groups.rs +++ b/embassy-stm32/src/tsc/pin_groups.rs @@ -427,7 +427,7 @@ macro_rules! impl_set_io { pub fn $method(&mut self, pin: Peri<'d, impl $trait>) -> IOPinWithRole<$group, Role> { critical_section::with(|_| { pin.set_low(); - pin.set_as_af(pin.af_num(), AfType::output(Role::output_type(), Speed::VeryHigh)); + set_as_af!(pin, AfType::output(Role::output_type(), Speed::VeryHigh)); let tsc_io_pin = trait_to_io_pin!($trait); let new_pin = Pin { _pin: pin.into(), diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index 1c3b99b93..5ce81b131 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -34,7 +34,7 @@ macro_rules! config_ulpi_pins { ($($pin:ident),*) => { critical_section::with(|_| { $( - $pin.set_as_af($pin.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!($pin, AfType::output(OutputType::PushPull, Speed::VeryHigh)); )* }) }; @@ -68,8 +68,8 @@ impl<'d, T: Instance> Driver<'d, T> { ep_out_buffer: &'d mut [u8], config: Config, ) -> Self { - dp.set_as_af(dp.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); - dm.set_as_af(dm.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!(dp, AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!(dm, AfType::output(OutputType::PushPull, Speed::VeryHigh)); let regs = T::regs(); @@ -107,8 +107,8 @@ impl<'d, T: Instance> Driver<'d, T> { // For STM32U5 High speed pins need to be left in analog mode #[cfg(not(any(all(stm32u5, peri_usb_otg_hs), all(stm32wba, peri_usb_otg_hs))))] { - _dp.set_as_af(_dp.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); - _dm.set_as_af(_dm.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!(_dp, AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!(_dm, AfType::output(OutputType::PushPull, Speed::VeryHigh)); } let instance = OtgInstance { diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index 54596aeae..9e08d99b3 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -298,7 +298,7 @@ impl<'d, T: Instance> Driver<'d, T> { ) -> Self { { use crate::gpio::{AfType, OutputType, Speed}; - sof.set_as_af(sof.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!(sof, AfType::output(OutputType::PushPull, Speed::VeryHigh)); } Self::new(_usb, _irq, dp, dm) @@ -329,8 +329,8 @@ impl<'d, T: Instance> Driver<'d, T> { #[cfg(not(stm32l1))] { use crate::gpio::{AfType, OutputType, Speed}; - dp.set_as_af(dp.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); - dm.set_as_af(dm.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!(dp, AfType::output(OutputType::PushPull, Speed::VeryHigh)); + set_as_af!(dm, AfType::output(OutputType::PushPull, Speed::VeryHigh)); } #[cfg(stm32l1)] let _ = (dp, dm); // suppress "unused" warnings. -- cgit From 23d5c7efd99e7422c63c6e12143856257d1ee651 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 6 Sep 2025 00:39:18 +0200 Subject: stm32/afio: fix accidentally always using AF number 0 on non-AFIO chips. --- embassy-stm32/build.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 0d3582c9d..b5f1261fe 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1428,13 +1428,13 @@ fn main() { "LPUART", "TIM", ]; - let af_or_not_applicable = if peripherals_with_afio.iter().any(|&x| p.name.starts_with(x)) { - quote!(0, crate::gpio::AfioRemapNotApplicable) + let not_applicable = if peripherals_with_afio.iter().any(|&x| p.name.starts_with(x)) { + quote!(, crate::gpio::AfioRemapNotApplicable) } else { - quote!(#af) + quote!() }; - Some(quote!(pin_trait_impl!(#tr, #peri, #pin_name, #af_or_not_applicable);)) + Some(quote!(pin_trait_impl!(#tr, #peri, #pin_name, #af #not_applicable);)) }; g.extend(pin_trait_impl); -- cgit From 224d6b03125dd9c799611883914dd99c5431e749 Mon Sep 17 00:00:00 2001 From: Remmirad Date: Sat, 6 Sep 2025 11:32:23 +0200 Subject: nrf: 802.15.4 embassy-net-driver --- embassy-net/README.md | 1 + embassy-nrf/CHANGELOG.md | 1 + embassy-nrf/Cargo.toml | 7 ++ embassy-nrf/README.md | 4 + embassy-nrf/src/embassy_net_802154_driver.rs | 96 +++++++++++++++++++++ embassy-nrf/src/lib.rs | 11 +++ examples/nrf52840/Cargo.toml | 4 +- examples/nrf52840/src/bin/sixlowpan.rs | 120 +++++++++++++++++++++++++++ 8 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 embassy-nrf/src/embassy_net_802154_driver.rs create mode 100644 examples/nrf52840/src/bin/sixlowpan.rs diff --git a/embassy-net/README.md b/embassy-net/README.md index 1722ffc7b..1c5b30a9c 100644 --- a/embassy-net/README.md +++ b/embassy-net/README.md @@ -25,6 +25,7 @@ unimplemented features of the network protocols. - [`embassy-stm32`](https://github.com/embassy-rs/embassy/tree/main/embassy-stm32) for the builtin Ethernet MAC in all STM32 chips (STM32F1, STM32F2, STM32F4, STM32F7, STM32H7, STM32H5). - [`embassy-net-wiznet`](https://github.com/embassy-rs/embassy/tree/main/embassy-net-wiznet) for Wiznet SPI Ethernet MAC+PHY chips (W5100S, W5500) - [`embassy-net-esp-hosted`](https://github.com/embassy-rs/embassy/tree/main/embassy-net-esp-hosted) for using ESP32 chips with the [`esp-hosted`](https://github.com/espressif/esp-hosted) firmware as WiFi adapters for another non-ESP32 MCU. +- [`embassy-nrf`](https://github.com/embassy-rs/embassy/tree/main/embassy-nrf) for IEEE 802.15.4 support on nrf chips. ## Examples diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index 5dc941b25..befa34ecf 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate - changed: nrf54l: Disable glitch detection and enable DC/DC in init. +- changed: Add embassy-net-driver-channel implementation for IEEE 802.15.4 ## 0.7.0 - 2025-08-26 diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 2ce75cfac..4afd28fbd 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -79,6 +79,9 @@ gpiote = [] ## Use RTC1 as the time driver for `embassy-time`, with a tick rate of 32.768khz time-driver-rtc1 = ["_time-driver"] +## Enable embassy-net 802.15.4 driver +net-driver = ["_net-driver"] + ## Allow using the NFC pins as regular GPIO pins (P0_09/P0_10 on nRF52, P0_02/P0_03 on nRF53) nfc-pins-as-gpio = [] @@ -154,6 +157,8 @@ _nrf91 = [] _time-driver = ["dep:embassy-time-driver", "embassy-time-driver?/tick-hz-32_768", "dep:embassy-time-queue-utils", "embassy-embedded-hal/time"] +_net-driver = ["dep:embassy-net-driver-channel","dep:embassy-futures"] + # trustzone state. _s = [] _ns = [] @@ -177,6 +182,8 @@ embassy-sync = { version = "0.7.2", path = "../embassy-sync" } embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal", default-features = false } embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } +embassy-net-driver-channel = { version = "0.3.2", path = "../embassy-net-driver-channel", optional = true} +embassy-futures = { version = "0.1.2", path = "../embassy-futures", optional = true} embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal-1 = { package = "embedded-hal", version = "1.0" } diff --git a/embassy-nrf/README.md b/embassy-nrf/README.md index 3df5f1fa5..26b1fa5ea 100644 --- a/embassy-nrf/README.md +++ b/embassy-nrf/README.md @@ -28,6 +28,10 @@ allows running Rust code without a SPM or TF-M binary, saving flash space and si If the `time-driver-rtc1` feature is enabled, the HAL uses the RTC peripheral as a global time driver for [embassy-time](https://crates.io/crates/embassy-time), with a tick rate of 32768 Hz. +## Embassy-net-driver + +If the board supports IEEE 802.15.4 (see `src/radio/mod.rs`) the corresponding [embassy-net-driver](https://crates.io/crates/embassy-net-driver) implementation can be enabled with the feature `net-driver`. + ## Embedded-hal The `embassy-nrf` HAL implements the traits from [embedded-hal](https://crates.io/crates/embedded-hal) (v0.2 and 1.0) and [embedded-hal-async](https://crates.io/crates/embedded-hal-async), as well as [embedded-io](https://crates.io/crates/embedded-io) and [embedded-io-async](https://crates.io/crates/embedded-io-async). diff --git a/embassy-nrf/src/embassy_net_802154_driver.rs b/embassy-nrf/src/embassy_net_802154_driver.rs new file mode 100644 index 000000000..8662be787 --- /dev/null +++ b/embassy-nrf/src/embassy_net_802154_driver.rs @@ -0,0 +1,96 @@ +//! embassy-net IEEE 802.15.4 driver + +use embassy_futures::select::{select3, Either3}; +use embassy_net_driver_channel::driver::LinkState; +use embassy_net_driver_channel::{self as ch}; +use embassy_time::{Duration, Ticker}; + +use crate::radio::ieee802154::{Packet, Radio}; +use crate::radio::InterruptHandler; +use crate::{self as nrf, interrupt}; + +/// MTU for the nrf radio. +pub const MTU: usize = Packet::CAPACITY as usize; + +/// embassy-net device for the driver. +pub type Device<'d> = embassy_net_driver_channel::Device<'d, MTU>; + +/// Internal state for the embassy-net driver. +pub struct State { + ch_state: ch::State, +} + +impl State { + /// Create a new `State`. + pub const fn new() -> Self { + Self { + ch_state: ch::State::new(), + } + } +} + +/// Background runner for the driver. +/// +/// You must call `.run()` in a background task for the driver to operate. +pub struct Runner<'d, T: nrf::radio::Instance> { + radio: nrf::radio::ieee802154::Radio<'d, T>, + ch: ch::Runner<'d, MTU>, +} + +impl<'d, T: nrf::radio::Instance> Runner<'d, T> { + /// Drives the radio. Needs to run to use the driver. + pub async fn run(mut self) -> ! { + let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split(); + let mut tick = Ticker::every(Duration::from_millis(500)); + let mut packet = Packet::new(); + state_chan.set_link_state(LinkState::Up); + loop { + match select3( + async { + let rx_buf = rx_chan.rx_buf().await; + self.radio.receive(&mut packet).await.ok().map(|_| rx_buf) + }, + tx_chan.tx_buf(), + tick.next(), + ) + .await + { + Either3::First(Some(rx_buf)) => { + let len = rx_buf.len().min(packet.len() as usize); + (&mut rx_buf[..len]).copy_from_slice(&*packet); + rx_chan.rx_done(len); + } + Either3::Second(tx_buf) => { + let len = tx_buf.len().min(Packet::CAPACITY as usize); + packet.copy_from_slice(&tx_buf[..len]); + self.radio.try_send(&mut packet).await.ok().unwrap(); + tx_chan.tx_done(); + } + _ => {} + } + } + } +} + +/// Make sure to use `HfclkSource::ExternalXtal` as the `hfclk_source` +/// to use the radio (nrf52840 product spec v1.11 5.4.1) +/// ``` +/// # use embassy_nrf::config::*; +/// let mut config = Config::default(); +/// config.hfclk_source = HfclkSource::ExternalXtal; +/// ``` +pub async fn new<'a, const N_RX: usize, const N_TX: usize, T: nrf::radio::Instance, Irq>( + mac_addr: [u8; 8], + radio: nrf::Peri<'a, T>, + irq: Irq, + state: &'a mut State, +) -> Result<(Device<'a>, Runner<'a, T>), ()> +where + Irq: interrupt::typelevel::Binding> + 'a, +{ + let radio = Radio::new(radio, irq); + + let (runner, device) = ch::new(&mut state.ch_state, ch::driver::HardwareAddress::Ieee802154(mac_addr)); + + Ok((device, Runner { ch: runner, radio })) +} diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index aa4801897..897e660b8 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -137,6 +137,17 @@ pub mod qspi; #[cfg(not(feature = "_nrf54l"))] // TODO #[cfg(not(any(feature = "_nrf91", feature = "_nrf5340-app")))] pub mod radio; + +#[cfg(any( + feature = "nrf52811", + feature = "nrf52820", + feature = "nrf52833", + feature = "nrf52840", + feature = "_nrf5340-net" +))] +#[cfg(feature = "_net-driver")] +pub mod embassy_net_802154_driver; + #[cfg(not(feature = "_nrf54l"))] // TODO #[cfg(feature = "_nrf5340")] pub mod reset; diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index a9339bcd3..452e83b7e 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -10,8 +10,8 @@ embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } -embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } +embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time", "net-driver"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet","udp", "medium-ieee802154", "proto-ipv6"] } embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } embedded-io = { version = "0.6.0", features = ["defmt-03"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } diff --git a/examples/nrf52840/src/bin/sixlowpan.rs b/examples/nrf52840/src/bin/sixlowpan.rs new file mode 100644 index 000000000..00a597366 --- /dev/null +++ b/examples/nrf52840/src/bin/sixlowpan.rs @@ -0,0 +1,120 @@ +#![no_std] +#![no_main] + +use core::net::Ipv6Addr; + +use defmt::{info, unwrap, warn}; +use embassy_executor::Spawner; +use embassy_net::udp::{PacketMetadata, UdpMetadata, UdpSocket}; +use embassy_net::{IpAddress, IpEndpoint, IpListenEndpoint, Ipv6Cidr, StackResources, StaticConfigV6}; +use embassy_nrf::config::{Config, HfclkSource}; +use embassy_nrf::rng::Rng; +use embassy_nrf::{bind_interrupts, embassy_net_802154_driver as net, peripherals, radio}; +use embassy_time::Delay; +use embedded_hal_async::delay::DelayNs; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + RADIO => radio::InterruptHandler; + RNG => embassy_nrf::rng::InterruptHandler; +}); + +#[embassy_executor::task] +async fn ieee802154_task(runner: net::Runner<'static, peripherals::RADIO>) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(mut runner: embassy_net::Runner<'static, net::Device<'static>>) -> ! { + runner.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let mut config = Config::default(); + // Necessary to run the radio nrf52840 v1.11 5.4.1 + config.hfclk_source = HfclkSource::ExternalXtal; + let p = embassy_nrf::init(config); + + let mac_addr: [u8; 8] = [2, 3, 4, 5, 6, 7, 8, 9]; + static NRF802154_STATE: StaticCell> = StaticCell::new(); + let (device, runner) = net::new(mac_addr, p.RADIO, Irqs, NRF802154_STATE.init(net::State::new())) + .await + .unwrap(); + + spawner.spawn(unwrap!(ieee802154_task(runner))); + + // Swap these when flashing a second board + let peer = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xd701, 0xda3f, 0x3955, 0x82a4); + let local = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xd701, 0xda3f, 0x3955, 0x82a5); + + let config = embassy_net::Config::ipv6_static(StaticConfigV6 { + address: Ipv6Cidr::new(local, 64), + gateway: None, + dns_servers: Default::default(), + }); + + // Generate random seed + let mut rng = Rng::new(p.RNG, Irqs); + let mut seed = [0; 8]; + rng.blocking_fill_bytes(&mut seed); + let seed = u64::from_le_bytes(seed); + + // Init network stack + static RESOURCES: StaticCell> = StaticCell::new(); + let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); + + spawner.spawn(unwrap!(net_task(runner))); + + let mut rx_buffer = [0; 2096]; + let mut tx_buffer = [0; 2096]; + let mut tx_m_buffer = [PacketMetadata::EMPTY; 5]; + let mut rx_m_buffer = [PacketMetadata::EMPTY; 5]; + + let mut delay = Delay; + loop { + let mut socket = UdpSocket::new( + stack, + &mut tx_m_buffer, + &mut rx_buffer, + &mut rx_m_buffer, + &mut tx_buffer, + ); + socket + .bind(IpListenEndpoint { + addr: Some(IpAddress::Ipv6(local)), + port: 1234, + }) + .unwrap(); + let rep = UdpMetadata { + endpoint: IpEndpoint { + addr: IpAddress::Ipv6(peer), + port: 1234, + }, + local_address: Some(IpAddress::Ipv6(local)), + meta: Default::default(), + }; + + info!("Listening on {:?} UDP:1234...", local); + + let mut recv_buf = [0; 12]; + loop { + delay.delay_ms(2000).await; + if socket.may_recv() { + let n = match socket.recv_from(&mut recv_buf).await { + Ok((0, _)) => panic!(), + Ok((n, _)) => n, + Err(e) => { + warn!("read error: {:?}", e); + break; + } + }; + info!("Received {:02x}", &recv_buf[..n]); + } + + info!("Sending"); + socket.send_to(b"Hello World", rep).await.unwrap(); + } + } +} -- cgit From c101acbdc3593936f6e966cb33e8ba72698a1a31 Mon Sep 17 00:00:00 2001 From: Carl Kadie Date: Sat, 6 Sep 2025 14:05:45 -0700 Subject: Update Embassy in the Wild with no_std Raspberry Pi Pico clock demonstrating layered Embassy tasks (I also added a note that newer entries are at the top. If this isn't right, let me know or change.) --- docs/pages/embassy_in_the_wild.adoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/pages/embassy_in_the_wild.adoc b/docs/pages/embassy_in_the_wild.adoc index 620794c31..cedbedada 100644 --- a/docs/pages/embassy_in_the_wild.adoc +++ b/docs/pages/embassy_in_the_wild.adoc @@ -2,6 +2,10 @@ Here are known examples of real-world projects which make use of Embassy. Feel free to link:https://github.com/embassy-rs/embassy/blob/main/docs/pages/embassy_in_the_wild.adoc[add more]! +_newer entries at the top_ + +* link:https://github.com/CarlKCarlK/clock[Embassy Clock: Layered, modular bare-metal clock with emulation] +** A `no_std` Raspberry Pi Pico clock demonstrating layered Embassy tasks (Display->Blinker->Clock) for clean separation of multiplexing, blinking, and UI logic. Features single-button HH:MM/MM:SS time-set UI, heapless data structures, and a Renode emulator for hardware-free testing. See link:https://medium.com/@carlmkadie/how-rust-embassy-shine-on-embedded-devices-part-2-aad1adfccf72[this article] for details. * link:https://github.com/1-rafael-1/simple-robot[A simple tracked robot based on Raspberry Pi Pico 2] ** A hobbyist project building a tracked robot with basic autonomous and manual drive mode. * link:https://github.com/1-rafael-1/pi-pico-alarmclock-rust[A Raspberry Pi Pico W Alarmclock] -- cgit From 86aff0e63e21bd01fa14ad3ad5470b0cf433009d Mon Sep 17 00:00:00 2001 From: Gabriel Smith Date: Tue, 2 Sep 2025 17:00:34 -0400 Subject: chore: bump embassy-executor to 0.9.1 to match released version --- embassy-executor/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 7763adbe5..41636a26f 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-executor" -version = "0.9.0" +version = "0.9.1" edition = "2021" license = "MIT OR Apache-2.0" description = "async/await executor designed for embedded usage" -- cgit From b9023296f66ae8663485c37e8139c9832aae4849 Mon Sep 17 00:00:00 2001 From: Chris Dell Date: Mon, 8 Sep 2025 22:15:16 +0100 Subject: Add Wiznet W6100 driver --- embassy-net-wiznet/src/chip/mod.rs | 3 ++ embassy-net-wiznet/src/chip/w5100s.rs | 1 + embassy-net-wiznet/src/chip/w5500.rs | 1 + embassy-net-wiznet/src/chip/w6100.rs | 83 +++++++++++++++++++++++++++++++++++ embassy-net-wiznet/src/device.rs | 2 +- 5 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 embassy-net-wiznet/src/chip/w6100.rs diff --git a/embassy-net-wiznet/src/chip/mod.rs b/embassy-net-wiznet/src/chip/mod.rs index 2e7a9ed6c..6e6e5cb78 100644 --- a/embassy-net-wiznet/src/chip/mod.rs +++ b/embassy-net-wiznet/src/chip/mod.rs @@ -4,6 +4,8 @@ pub use w5500::W5500; mod w5100s; use embedded_hal_async::spi::SpiDevice; pub use w5100s::W5100S; +mod w6100; +pub use w6100::W6100; pub(crate) trait SealedChip { type Address; @@ -29,6 +31,7 @@ pub(crate) trait SealedChip { const SOCKET_RX_DATA_READ_PTR: Self::Address; const SOCKET_INTR_MASK: Self::Address; const SOCKET_INTR: Self::Address; + const SOCKET_INTR_CLR: Self::Address; const SOCKET_MODE_VALUE: u8; diff --git a/embassy-net-wiznet/src/chip/w5100s.rs b/embassy-net-wiznet/src/chip/w5100s.rs index 4c4b7ab16..1eef2369e 100644 --- a/embassy-net-wiznet/src/chip/w5100s.rs +++ b/embassy-net-wiznet/src/chip/w5100s.rs @@ -29,6 +29,7 @@ impl super::SealedChip for W5100S { const SOCKET_RX_DATA_READ_PTR: Self::Address = SOCKET_BASE + 0x28; const SOCKET_INTR_MASK: Self::Address = SOCKET_BASE + 0x2C; const SOCKET_INTR: Self::Address = SOCKET_BASE + 0x02; + const SOCKET_INTR_CLR: Self::Address = SOCKET_BASE + 0x02; const SOCKET_MODE_VALUE: u8 = (1 << 2) | (1 << 6); diff --git a/embassy-net-wiznet/src/chip/w5500.rs b/embassy-net-wiznet/src/chip/w5500.rs index 5cfcb94e4..198ba3226 100644 --- a/embassy-net-wiznet/src/chip/w5500.rs +++ b/embassy-net-wiznet/src/chip/w5500.rs @@ -33,6 +33,7 @@ impl super::SealedChip for W5500 { const SOCKET_RX_DATA_READ_PTR: Self::Address = (RegisterBlock::Socket0, 0x28); const SOCKET_INTR_MASK: Self::Address = (RegisterBlock::Socket0, 0x2C); const SOCKET_INTR: Self::Address = (RegisterBlock::Socket0, 0x02); + const SOCKET_INTR_CLR: Self::Address = (RegisterBlock::Socket0, 0x02); const SOCKET_MODE_VALUE: u8 = (1 << 2) | (1 << 7); diff --git a/embassy-net-wiznet/src/chip/w6100.rs b/embassy-net-wiznet/src/chip/w6100.rs new file mode 100644 index 000000000..740b0edaf --- /dev/null +++ b/embassy-net-wiznet/src/chip/w6100.rs @@ -0,0 +1,83 @@ +use embedded_hal_async::spi::{Operation, SpiDevice}; + +#[repr(u8)] +pub enum RegisterBlock { + Common = 0x00, + Socket0 = 0x01, + TxBuf = 0x02, + RxBuf = 0x03, +} + +/// Wiznet W6100 chip. +pub enum W6100 {} + +impl super::Chip for W6100 {} +impl super::SealedChip for W6100 { + type Address = (RegisterBlock, u16); + + const CHIP_VERSION: u8 = 0x46; + + const COMMON_MODE: Self::Address = (RegisterBlock::Common, 0x2004); + const COMMON_MAC: Self::Address = (RegisterBlock::Common, 0x4120); + // SIMR (SOCKET Interrupt Mask Register) + const COMMON_SOCKET_INTR: Self::Address = (RegisterBlock::Common, 0x2114); + const COMMON_PHY_CFG: Self::Address = (RegisterBlock::Common, 0x3000); + const COMMON_VERSION: Self::Address = (RegisterBlock::Common, 0x0002); + + const SOCKET_MODE: Self::Address = (RegisterBlock::Socket0, 0x0000); + const SOCKET_COMMAND: Self::Address = (RegisterBlock::Socket0, 0x0010); + const SOCKET_RXBUF_SIZE: Self::Address = (RegisterBlock::Socket0, 0x0220); + const SOCKET_TXBUF_SIZE: Self::Address = (RegisterBlock::Socket0, 0x0200); + const SOCKET_TX_FREE_SIZE: Self::Address = (RegisterBlock::Socket0, 0x0204); + const SOCKET_TX_DATA_WRITE_PTR: Self::Address = (RegisterBlock::Socket0, 0x020C); + const SOCKET_RECVD_SIZE: Self::Address = (RegisterBlock::Socket0, 0x0224); + const SOCKET_RX_DATA_READ_PTR: Self::Address = (RegisterBlock::Socket0, 0x0228); + // Sn_IMR (SOCKET n Interrupt Mask Register) + const SOCKET_INTR_MASK: Self::Address = (RegisterBlock::Socket0, 0x0024); + // Sn_IR (SOCKET n Interrupt Register) + const SOCKET_INTR: Self::Address = (RegisterBlock::Socket0, 0x0020); + // Sn_IRCLR (Sn_IR Clear Register) + const SOCKET_INTR_CLR: Self::Address = (RegisterBlock::Socket0, 0x0028); + + // MACRAW mode. See Page 57 of https://docs.wiznet.io/img/products/w6100/w6100_ds_v105e.pdf + // Note: Bit 7 is MAC filter. On the W5500 this is normally turned ON however the W6100 will not successfully retrieve an IP address with this enabled. Disabling for now and will have live with the extra noise. + const SOCKET_MODE_VALUE: u8 = 0b0000_0111; + + const BUF_SIZE: u16 = 0x1000; + const AUTO_WRAP: bool = true; + + fn rx_addr(addr: u16) -> Self::Address { + (RegisterBlock::RxBuf, addr) + } + + fn tx_addr(addr: u16) -> Self::Address { + (RegisterBlock::TxBuf, addr) + } + + async fn bus_read( + spi: &mut SPI, + address: Self::Address, + data: &mut [u8], + ) -> Result<(), SPI::Error> { + let address_phase = address.1.to_be_bytes(); + let control_phase = [(address.0 as u8) << 3]; + let operations = &mut [ + Operation::Write(&address_phase), + Operation::Write(&control_phase), + Operation::TransferInPlace(data), + ]; + spi.transaction(operations).await + } + + async fn bus_write(spi: &mut SPI, address: Self::Address, data: &[u8]) -> Result<(), SPI::Error> { + let address_phase = address.1.to_be_bytes(); + let control_phase = [(address.0 as u8) << 3 | 0b0000_0100]; + let data_phase = data; + let operations = &mut [ + Operation::Write(&address_phase[..]), + Operation::Write(&control_phase), + Operation::Write(&data_phase), + ]; + spi.transaction(operations).await + } +} diff --git a/embassy-net-wiznet/src/device.rs b/embassy-net-wiznet/src/device.rs index d2b6bb0c3..8ef92b022 100644 --- a/embassy-net-wiznet/src/device.rs +++ b/embassy-net-wiznet/src/device.rs @@ -125,7 +125,7 @@ impl WiznetDevice { async fn reset_interrupt(&mut self, code: Interrupt) -> Result<(), SPI::Error> { let data = [code as u8]; - self.bus_write(C::SOCKET_INTR, &data).await + self.bus_write(C::SOCKET_INTR_CLR, &data).await } async fn get_tx_write_ptr(&mut self) -> Result { -- cgit From bed230095d11ee32939ee51f2f298817691bb6aa Mon Sep 17 00:00:00 2001 From: Chris Dell Date: Wed, 10 Sep 2025 11:24:29 +0100 Subject: Update changelog with new W6100 (unreleased) --- embassy-net-wiznet/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/embassy-net-wiznet/CHANGELOG.md b/embassy-net-wiznet/CHANGELOG.md index e464efa69..a74dc3125 100644 --- a/embassy-net-wiznet/CHANGELOG.md +++ b/embassy-net-wiznet/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- Added experimental W6100 driver with disabled MAC filter (does not currently work with it enabled) +- Introduced `SOCKET_INTR_CLR` register which is needed on W6100 and later models (on W5100/W5500 this is shared with `SOCKET_INTR` and the address is the same) + ## 0.2.1 - 2025-08-26 ## 0.1.1 - 2025-08-14 -- cgit From 88c4274547db9fe6e6e720c69e61c4912fe03abd Mon Sep 17 00:00:00 2001 From: Birk Tjelmeland Date: Mon, 8 Sep 2025 13:48:48 +0200 Subject: stm32/usart: fix blocking flush The PR in #2416 fixes buffered usart flushing, but only for the async functions. This commit introduces the same fixes to the blocking functions. --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/src/usart/buffered.rs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index ba565f663..4ea11b664 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add I2S support for STM32F1, STM32C0, STM32F0, STM32F3, STM32F7, STM32G0, STM32WL, STM32H5, STM32H7RS - fix: STM32: Prevent dropped DacChannel from disabling Dac peripheral if another DacChannel is still in scope ([#4577](https://github.com/embassy-rs/embassy/pull/4577)) - feat: Added support for more OctoSPI configurations (e.g. APS6408 RAM) ([#4581](https://github.com/embassy-rs/embassy/pull/4581)) +- fix: stm32/usart: fix bug with blocking flush in buffered uart ([#4648](https://github.com/embassy-rs/embassy/pull/4648)) ## 0.4.0 - 2025-08-26 diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 890c8a80e..c734eed49 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -692,6 +692,8 @@ impl<'d> BufferedUartTx<'d> { fn blocking_write(&self, buf: &[u8]) -> Result { loop { let state = self.state; + state.tx_done.store(false, Ordering::Release); + let empty = state.tx_buf.is_empty(); let mut tx_writer = unsafe { state.tx_buf.writer() }; @@ -713,7 +715,7 @@ impl<'d> BufferedUartTx<'d> { fn blocking_flush(&self) -> Result<(), Error> { loop { let state = self.state; - if state.tx_buf.is_empty() { + if state.tx_done.load(Ordering::Acquire) { return Ok(()); } } -- cgit From 535c80e61f17e4ee4605e00623aabeda2181352d Mon Sep 17 00:00:00 2001 From: James Munns Date: Thu, 20 Mar 2025 09:47:56 +0100 Subject: Add initial DRS scheduler placeholder * Start hacking in cordyceps This adds a third kind of runqueue, for now it should work the same as the current "atomics" runqueue, but uses a cordyceps TransferStack instead of the existing home-rolled linked list. * Clean up, use new cordyceps feature * A bit more cleanup * Update docs to be more clear --- embassy-executor/Cargo.toml | 9 ++++ embassy-executor/src/raw/mod.rs | 64 +++++++++++++++++++++-- embassy-executor/src/raw/run_queue_drs_atomics.rs | 47 +++++++++++++++++ 3 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 embassy-executor/src/raw/run_queue_drs_atomics.rs diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 41636a26f..1cd732dfa 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -76,6 +76,12 @@ js-sys = { version = "0.3", optional = true } # arch-avr dependencies avr-device = { version = "0.7.0", optional = true } +[dependencies.cordyceps] +version = "0.3" +git = "https://github.com/hawkw/mycelium" +rev = "aaad19480d175bfc290f1d4dc2d435c6eb3d9fc5" +optional = true + [dev-dependencies] critical-section = { version = "1.1", features = ["std"] } trybuild = "1.0" @@ -125,3 +131,6 @@ trace = ["_any_trace"] ## Enable support for rtos-trace framework rtos-trace = ["_any_trace", "metadata-name", "dep:rtos-trace", "dep:embassy-time-driver"] _any_trace = [] + +## Enable "Deadline Rank Scheduler" +drs-scheduler = ["dep:cordyceps"] diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 4280c5750..894a996ec 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -7,7 +7,14 @@ //! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe //! [executor wrappers](crate::Executor) and the [`embassy_executor::task`](embassy_executor_macros::task) macro, which are fully safe. -#[cfg_attr(target_has_atomic = "ptr", path = "run_queue_atomics.rs")] +#[cfg_attr( + all(not(feature = "drs-scheduler"), target_has_atomic = "ptr"), + path = "run_queue_atomics.rs", +)] +#[cfg_attr( + all(feature = "drs-scheduler", target_has_atomic = "ptr"), + path = "run_queue_drs_atomics.rs", +)] #[cfg_attr(not(target_has_atomic = "ptr"), path = "run_queue_critical_section.rs")] mod run_queue; @@ -33,6 +40,8 @@ use core::marker::PhantomData; use core::mem; use core::pin::Pin; use core::ptr::NonNull; +#[cfg(feature = "drs-scheduler")] +use core::ptr::addr_of_mut; #[cfg(not(feature = "arch-avr"))] use core::sync::atomic::AtomicPtr; use core::sync::atomic::Ordering; @@ -42,7 +51,9 @@ use embassy_executor_timer_queue::TimerQueueItem; #[cfg(feature = "arch-avr")] use portable_atomic::AtomicPtr; -use self::run_queue::{RunQueue, RunQueueItem}; +use self::run_queue::RunQueue; +#[cfg(not(feature = "drs-scheduler"))] +use self::run_queue::RunQueueItem; use self::state::State; use self::util::{SyncUnsafeCell, UninitCell}; pub use self::waker::task_from_waker; @@ -54,6 +65,9 @@ extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static unsafe { task_from_waker(waker).timer_queue_item() } } +#[cfg(feature = "drs-scheduler")] +use cordyceps::{stack, Linked}; + /// Raw task header for use in task pointers. /// /// A task can be in one of the following states: @@ -93,9 +107,29 @@ extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static /// - 4: A run-queued task exits - `TaskStorage::poll -> Poll::Ready` /// - 5: Task is dequeued. The task's future is not polled, because exiting the task replaces its `poll_fn`. /// - 6: A task is waken when it is not spawned - `wake_task -> State::run_enqueue` +#[cfg_attr(feature = "drs-scheduler", repr(C))] pub(crate) struct TaskHeader { - pub(crate) state: State, + // TODO(AJM): Make a decision whether we want to support the spicier "pointer recast"/"type punning" + // method of implementing the `cordyceps::Linked` trait or not. + // + // Currently, I do the safer version with `addr_of_mut!`, which doesn't REQUIRE that the first + // element is the `links` field, at the potential cost of a little extra pointer math. + // + // The optimizer *might* (total guess) notice that we are always doing an offset of zero in the + // call to `addr_of_mut` in the `impl Linked for TaskHeader` below, and get the best of both worlds, + // but right now this is maybe a little over cautious. + // + // See https://docs.rs/cordyceps/latest/cordyceps/trait.Linked.html#implementing-linkedlinks for + // more context on the choices here. + #[cfg(feature = "drs-scheduler")] + pub(crate) links: stack::Links, + + // TODO(AJM): We could potentially replace RunQueueItem for other runqueue impls, though + // right now cordyceps doesn't work on non-atomic systems + #[cfg(not(feature = "drs-scheduler"))] pub(crate) run_queue_item: RunQueueItem, + + pub(crate) state: State, pub(crate) executor: AtomicPtr, poll_fn: SyncUnsafeCell>, @@ -108,6 +142,25 @@ pub(crate) struct TaskHeader { all_tasks_next: AtomicPtr, } +#[cfg(feature = "drs-scheduler")] +unsafe impl Linked> for TaskHeader { + type Handle = TaskRef; + + fn into_ptr(r: Self::Handle) -> NonNull { + r.ptr.cast() + } + + unsafe fn from_ptr(ptr: NonNull) -> Self::Handle { + let ptr: NonNull = ptr; + TaskRef { ptr } + } + + unsafe fn links(ptr: NonNull) -> NonNull> { + let ptr: *mut TaskHeader = ptr.as_ptr(); + NonNull::new_unchecked(addr_of_mut!((*ptr).links)) + } +} + /// This is essentially a `&'static TaskStorage` where the type of the future has been erased. #[derive(Debug, Clone, Copy, PartialEq)] pub struct TaskRef { @@ -198,8 +251,11 @@ impl TaskStorage { pub const fn new() -> Self { Self { raw: TaskHeader { - state: State::new(), + #[cfg(not(feature = "drs-scheduler"))] run_queue_item: RunQueueItem::new(), + #[cfg(feature = "drs-scheduler")] + links: stack::Links::new(), + state: State::new(), executor: AtomicPtr::new(core::ptr::null_mut()), // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss` poll_fn: SyncUnsafeCell::new(None), diff --git a/embassy-executor/src/raw/run_queue_drs_atomics.rs b/embassy-executor/src/raw/run_queue_drs_atomics.rs new file mode 100644 index 000000000..53ada1b14 --- /dev/null +++ b/embassy-executor/src/raw/run_queue_drs_atomics.rs @@ -0,0 +1,47 @@ +use super::{TaskHeader, TaskRef}; +use cordyceps::TransferStack; + + +/// Atomic task queue using a very, very simple lock-free linked-list queue: +/// +/// To enqueue a task, task.next is set to the old head, and head is atomically set to task. +/// +/// Dequeuing is done in batches: the queue is emptied by atomically replacing head with +/// null. Then the batch is iterated following the next pointers until null is reached. +/// +/// Note that batches will be iterated in the reverse order as they were enqueued. This is OK +/// for our purposes: it can't create fairness problems since the next batch won't run until the +/// current batch is completely processed, so even if a task enqueues itself instantly (for example +/// by waking its own waker) can't prevent other tasks from running. +pub(crate) struct RunQueue { + stack: TransferStack, +} + +impl RunQueue { + pub const fn new() -> Self { + Self { + stack: TransferStack::new(), + } + } + + /// Enqueues an item. Returns true if the queue was empty. + /// + /// # Safety + /// + /// `item` must NOT be already enqueued in any queue. + #[inline(always)] + pub(crate) unsafe fn enqueue(&self, task: TaskRef, _: super::state::Token) -> bool { + self.stack.push_was_empty(task) + } + + /// Empty the queue, then call `on_task` for each task that was in the queue. + /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue + /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. + pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { + let taken = self.stack.take_all(); + for taskref in taken { + taskref.header().state.run_dequeue(); + on_task(taskref); + } + } +} -- cgit From 1f50e4d496458dbc7fccd9d028217ebfa7735471 Mon Sep 17 00:00:00 2001 From: James Munns Date: Thu, 20 Mar 2025 14:32:14 +0100 Subject: Implement Deadline Ranked Scheduling This implements a minimal version of Deadline Rank Scheduling, as well as ways to access and set Deadlines. This still needs some UX improvements, but is likely Enough for testing. --- embassy-executor/Cargo.toml | 3 +- embassy-executor/src/raw/mod.rs | 12 ++ embassy-executor/src/raw/run_queue_drs_atomics.rs | 141 +++++++++++++++++++++- 3 files changed, 150 insertions(+), 6 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 1cd732dfa..db664a819 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -89,7 +89,6 @@ embassy-sync = { path = "../embassy-sync" } rustversion = "1.0.21" [features] - ## Enable nightly-only features nightly = ["embassy-executor-macros/nightly"] @@ -133,4 +132,4 @@ rtos-trace = ["_any_trace", "metadata-name", "dep:rtos-trace", "dep:embassy-time _any_trace = [] ## Enable "Deadline Rank Scheduler" -drs-scheduler = ["dep:cordyceps"] +drs-scheduler = ["dep:cordyceps", "dep:embassy-time-driver"] diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 894a996ec..9b8a4ea8a 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -68,6 +68,9 @@ extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static #[cfg(feature = "drs-scheduler")] use cordyceps::{stack, Linked}; +#[cfg(feature = "drs-scheduler")] +pub use run_queue::Deadline; + /// Raw task header for use in task pointers. /// /// A task can be in one of the following states: @@ -124,6 +127,9 @@ pub(crate) struct TaskHeader { #[cfg(feature = "drs-scheduler")] pub(crate) links: stack::Links, + #[cfg(feature = "drs-scheduler")] + pub(crate) deadline: SyncUnsafeCell, + // TODO(AJM): We could potentially replace RunQueueItem for other runqueue impls, though // right now cordyceps doesn't work on non-atomic systems #[cfg(not(feature = "drs-scheduler"))] @@ -255,6 +261,8 @@ impl TaskStorage { run_queue_item: RunQueueItem::new(), #[cfg(feature = "drs-scheduler")] links: stack::Links::new(), + #[cfg(feature = "drs-scheduler")] + deadline: SyncUnsafeCell::new(0u64), state: State::new(), executor: AtomicPtr::new(core::ptr::null_mut()), // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss` @@ -352,6 +360,10 @@ impl AvailableTask { self.task.raw.poll_fn.set(Some(TaskStorage::::poll)); self.task.future.write_in_place(future); + // TODO(AJM): Some other way of setting this? Just a placeholder + #[cfg(feature = "drs-scheduler")] + self.task.raw.deadline.set(u64::MAX); + let task = TaskRef::new(self.task); SpawnToken::new(task) diff --git a/embassy-executor/src/raw/run_queue_drs_atomics.rs b/embassy-executor/src/raw/run_queue_drs_atomics.rs index 53ada1b14..69b7b3bf0 100644 --- a/embassy-executor/src/raw/run_queue_drs_atomics.rs +++ b/embassy-executor/src/raw/run_queue_drs_atomics.rs @@ -1,6 +1,7 @@ use super::{TaskHeader, TaskRef}; -use cordyceps::TransferStack; - +use cordyceps::{SortedList, TransferStack}; +use core::future::{Future, poll_fn}; +use core::task::Poll; /// Atomic task queue using a very, very simple lock-free linked-list queue: /// @@ -38,10 +39,142 @@ impl RunQueue { /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { - let taken = self.stack.take_all(); - for taskref in taken { + let mut sorted = SortedList::::new(|lhs, rhs| unsafe { + // TODO: Do we need any kind of access control here? Not if we say that + // tasks can only set their own priority, which they can't do if we're in + // the scheduler + lhs.deadline.get().cmp(&rhs.deadline.get()) + }); + + loop { + // For each loop, grab any newly pended items + let taken = self.stack.take_all(); + + // Sort these into the list - this is potentially expensive! We do an + // insertion sort of new items, which iterates the linked list. + // + // Something on the order of `O(n * m)`, where `n` is the number + // of new tasks, and `m` is the number of already pending tasks. + sorted.extend(taken); + + // Pop the task with the SOONEST deadline. If there are no tasks + // pending, then we are done. + let Some(taskref) = sorted.pop_front() else { + return; + }; + + // We got one task, mark it as dequeued, and process the task. taskref.header().state.run_dequeue(); on_task(taskref); } } } + +/// A type for interacting with the deadline of the current task +pub struct Deadline { + /// Deadline value in ticks, same time base and ticks as `embassy-time` + pub instant_ticks: u64, +} + +impl Deadline { + /// Set the current task's deadline at exactly `instant_ticks` + /// + /// This method is a future in order to access the currently executing task's + /// header which contains the deadline. + /// + /// Analogous to `Timer::at`. + /// + /// TODO: Should we check/panic if the deadline is in the past? + #[must_use = "Setting deadline must be polled to be effective"] + pub fn set_current_task_deadline(instant_ticks: u64) -> impl Future { + poll_fn(move |cx| { + let task = super::task_from_waker(cx.waker()); + // SAFETY: A task can only modify its own deadline, while the task is being + // polled, meaning that there cannot be concurrent access to the deadline. + unsafe { + task.header().deadline.set(instant_ticks); + } + Poll::Ready(()) + }) + } + + /// Set the current task's deadline `duration_ticks` in the future from when + /// this future is polled. + /// + /// This method is a future in order to access the currently executing task's + /// header which contains the deadline + /// + /// Analogous to `Timer::after` + /// + /// TODO: Do we want to return what the deadline is? + #[must_use = "Setting deadline must be polled to be effective"] + pub fn set_current_task_deadline_after(duration_ticks: u64) -> impl Future { + poll_fn(move |cx| { + let task = super::task_from_waker(cx.waker()); + let now = embassy_time_driver::now(); + + // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave + // it for now, we can probably make this wrapping_add for performance + // reasons later. + let deadline = now.saturating_add(duration_ticks); + + // SAFETY: A task can only modify its own deadline, while the task is being + // polled, meaning that there cannot be concurrent access to the deadline. + unsafe { + task.header().deadline.set(deadline); + } + Poll::Ready(()) + }) + } + + /// Set the current task's deadline `increment_ticks` from the previous deadline. + /// + /// Note that by default (unless otherwise set), tasks start life with the deadline + /// u64::MAX, which means this method will have no effect. + /// + /// This method is a future in order to access the currently executing task's + /// header which contains the deadline + /// + /// Analogous to one increment of `Ticker::every().next()`. + /// + /// TODO: Do we want to return what the deadline is? + #[must_use = "Setting deadline must be polled to be effective"] + pub fn increment_current_task_deadline(increment_ticks: u64) -> impl Future { + poll_fn(move |cx| { + let task = super::task_from_waker(cx.waker()); + + // SAFETY: A task can only modify its own deadline, while the task is being + // polled, meaning that there cannot be concurrent access to the deadline. + unsafe { + // Get the last value + let last = task.header().deadline.get(); + + // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave + // it for now, we can probably make this wrapping_add for performance + // reasons later. + let deadline = last.saturating_add(increment_ticks); + + // Store the new value + task.header().deadline.set(deadline); + } + Poll::Ready(()) + }) + } + + /// Get the current task's deadline as a tick value. + /// + /// This method is a future in order to access the currently executing task's + /// header which contains the deadline + pub fn get_current_task_deadline() -> impl Future { + poll_fn(move |cx| { + let task = super::task_from_waker(cx.waker()); + + // SAFETY: A task can only modify its own deadline, while the task is being + // polled, meaning that there cannot be concurrent access to the deadline. + let deadline = unsafe { + task.header().deadline.get() + }; + Poll::Ready(Self { instant_ticks: deadline }) + }) + } +} -- cgit From 8c70aafd4be63ff7af895f116444fb81438ae6e0 Mon Sep 17 00:00:00 2001 From: James Munns Date: Tue, 1 Apr 2025 18:35:41 +0200 Subject: Make some things more consistent --- embassy-executor/Cargo.toml | 4 +- embassy-executor/src/raw/mod.rs | 53 ++--------------------- embassy-executor/src/raw/run_queue_drs_atomics.rs | 31 +++++++++++-- 3 files changed, 34 insertions(+), 54 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index db664a819..80b5867c9 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -77,9 +77,11 @@ js-sys = { version = "0.3", optional = true } avr-device = { version = "0.7.0", optional = true } [dependencies.cordyceps] +# note: targeting v0.3.3, to be released when +# https://github.com/hawkw/mycelium/pull/520 is merged version = "0.3" git = "https://github.com/hawkw/mycelium" -rev = "aaad19480d175bfc290f1d4dc2d435c6eb3d9fc5" +rev = "9649db0525b9972b95937d83d52d3f51cc486281" optional = true [dev-dependencies] diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 9b8a4ea8a..2e5941ef7 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -40,7 +40,6 @@ use core::marker::PhantomData; use core::mem; use core::pin::Pin; use core::ptr::NonNull; -#[cfg(feature = "drs-scheduler")] use core::ptr::addr_of_mut; #[cfg(not(feature = "arch-avr"))] use core::sync::atomic::AtomicPtr; @@ -51,9 +50,7 @@ use embassy_executor_timer_queue::TimerQueueItem; #[cfg(feature = "arch-avr")] use portable_atomic::AtomicPtr; -use self::run_queue::RunQueue; -#[cfg(not(feature = "drs-scheduler"))] -use self::run_queue::RunQueueItem; +use self::run_queue::{RunQueue, RunQueueItem}; use self::state::State; use self::util::{SyncUnsafeCell, UninitCell}; pub use self::waker::task_from_waker; @@ -65,9 +62,6 @@ extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static unsafe { task_from_waker(waker).timer_queue_item() } } -#[cfg(feature = "drs-scheduler")] -use cordyceps::{stack, Linked}; - #[cfg(feature = "drs-scheduler")] pub use run_queue::Deadline; @@ -110,31 +104,14 @@ pub use run_queue::Deadline; /// - 4: A run-queued task exits - `TaskStorage::poll -> Poll::Ready` /// - 5: Task is dequeued. The task's future is not polled, because exiting the task replaces its `poll_fn`. /// - 6: A task is waken when it is not spawned - `wake_task -> State::run_enqueue` -#[cfg_attr(feature = "drs-scheduler", repr(C))] pub(crate) struct TaskHeader { - // TODO(AJM): Make a decision whether we want to support the spicier "pointer recast"/"type punning" - // method of implementing the `cordyceps::Linked` trait or not. - // - // Currently, I do the safer version with `addr_of_mut!`, which doesn't REQUIRE that the first - // element is the `links` field, at the potential cost of a little extra pointer math. - // - // The optimizer *might* (total guess) notice that we are always doing an offset of zero in the - // call to `addr_of_mut` in the `impl Linked for TaskHeader` below, and get the best of both worlds, - // but right now this is maybe a little over cautious. - // - // See https://docs.rs/cordyceps/latest/cordyceps/trait.Linked.html#implementing-linkedlinks for - // more context on the choices here. - #[cfg(feature = "drs-scheduler")] - pub(crate) links: stack::Links, + pub(crate) run_queue_item: RunQueueItem, #[cfg(feature = "drs-scheduler")] + /// Deadline Rank Scheduler Deadline. This field should not be accessed outside the context of + /// the task itself as it being polled by the executor. pub(crate) deadline: SyncUnsafeCell, - // TODO(AJM): We could potentially replace RunQueueItem for other runqueue impls, though - // right now cordyceps doesn't work on non-atomic systems - #[cfg(not(feature = "drs-scheduler"))] - pub(crate) run_queue_item: RunQueueItem, - pub(crate) state: State, pub(crate) executor: AtomicPtr, poll_fn: SyncUnsafeCell>, @@ -148,25 +125,6 @@ pub(crate) struct TaskHeader { all_tasks_next: AtomicPtr, } -#[cfg(feature = "drs-scheduler")] -unsafe impl Linked> for TaskHeader { - type Handle = TaskRef; - - fn into_ptr(r: Self::Handle) -> NonNull { - r.ptr.cast() - } - - unsafe fn from_ptr(ptr: NonNull) -> Self::Handle { - let ptr: NonNull = ptr; - TaskRef { ptr } - } - - unsafe fn links(ptr: NonNull) -> NonNull> { - let ptr: *mut TaskHeader = ptr.as_ptr(); - NonNull::new_unchecked(addr_of_mut!((*ptr).links)) - } -} - /// This is essentially a `&'static TaskStorage` where the type of the future has been erased. #[derive(Debug, Clone, Copy, PartialEq)] pub struct TaskRef { @@ -257,11 +215,8 @@ impl TaskStorage { pub const fn new() -> Self { Self { raw: TaskHeader { - #[cfg(not(feature = "drs-scheduler"))] run_queue_item: RunQueueItem::new(), #[cfg(feature = "drs-scheduler")] - links: stack::Links::new(), - #[cfg(feature = "drs-scheduler")] deadline: SyncUnsafeCell::new(0u64), state: State::new(), executor: AtomicPtr::new(core::ptr::null_mut()), diff --git a/embassy-executor/src/raw/run_queue_drs_atomics.rs b/embassy-executor/src/raw/run_queue_drs_atomics.rs index 69b7b3bf0..047265954 100644 --- a/embassy-executor/src/raw/run_queue_drs_atomics.rs +++ b/embassy-executor/src/raw/run_queue_drs_atomics.rs @@ -2,6 +2,29 @@ use super::{TaskHeader, TaskRef}; use cordyceps::{SortedList, TransferStack}; use core::future::{Future, poll_fn}; use core::task::Poll; +use core::ptr::{addr_of_mut, NonNull}; +use cordyceps::sorted_list::Links; +use cordyceps::Linked; + +pub(crate) type RunQueueItem = Links; + +unsafe impl Linked> for super::TaskHeader { + type Handle = TaskRef; + + fn into_ptr(r: Self::Handle) -> NonNull { + r.ptr.cast() + } + + unsafe fn from_ptr(ptr: NonNull) -> Self::Handle { + let ptr: NonNull = ptr; + TaskRef { ptr } + } + + unsafe fn links(ptr: NonNull) -> NonNull> { + let ptr: *mut TaskHeader = ptr.as_ptr(); + NonNull::new_unchecked(addr_of_mut!((*ptr).run_queue_item)) + } +} /// Atomic task queue using a very, very simple lock-free linked-list queue: /// @@ -39,10 +62,10 @@ impl RunQueue { /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { - let mut sorted = SortedList::::new(|lhs, rhs| unsafe { - // TODO: Do we need any kind of access control here? Not if we say that - // tasks can only set their own priority, which they can't do if we're in - // the scheduler + // SAFETY: `deadline` can only be set through the `Deadline` interface, which + // only allows access to this value while the given task is being polled. + // This acts as mutual exclusion for access. + let mut sorted = SortedList::::new_custom(|lhs, rhs| unsafe { lhs.deadline.get().cmp(&rhs.deadline.get()) }); -- cgit From ba0426f767bb602750bed4fae87a156b661c0e92 Mon Sep 17 00:00:00 2001 From: James Munns Date: Tue, 1 Apr 2025 18:50:12 +0200 Subject: Combine DRS and non-DRS atomic scheduler, using cordyceps --- embassy-executor/src/raw/deadline.rs | 111 ++++++++++++ embassy-executor/src/raw/mod.rs | 18 +- embassy-executor/src/raw/run_queue_atomics.rs | 110 +++++++----- embassy-executor/src/raw/run_queue_drs_atomics.rs | 203 ---------------------- 4 files changed, 186 insertions(+), 256 deletions(-) create mode 100644 embassy-executor/src/raw/deadline.rs delete mode 100644 embassy-executor/src/raw/run_queue_drs_atomics.rs diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs new file mode 100644 index 000000000..3f60936cc --- /dev/null +++ b/embassy-executor/src/raw/deadline.rs @@ -0,0 +1,111 @@ +use core::future::{poll_fn, Future}; +use core::task::Poll; + +/// A type for interacting with the deadline of the current task +pub struct Deadline { + /// Deadline value in ticks, same time base and ticks as `embassy-time` + pub instant_ticks: u64, +} + +impl Deadline { + /// Set the current task's deadline at exactly `instant_ticks` + /// + /// This method is a future in order to access the currently executing task's + /// header which contains the deadline. + /// + /// Analogous to `Timer::at`. + /// + /// TODO: Should we check/panic if the deadline is in the past? + #[must_use = "Setting deadline must be polled to be effective"] + pub fn set_current_task_deadline(instant_ticks: u64) -> impl Future { + poll_fn(move |cx| { + let task = super::task_from_waker(cx.waker()); + // SAFETY: A task can only modify its own deadline, while the task is being + // polled, meaning that there cannot be concurrent access to the deadline. + unsafe { + task.header().deadline.set(instant_ticks); + } + Poll::Ready(()) + }) + } + + /// Set the current task's deadline `duration_ticks` in the future from when + /// this future is polled. + /// + /// This method is a future in order to access the currently executing task's + /// header which contains the deadline + /// + /// Analogous to `Timer::after` + /// + /// TODO: Do we want to return what the deadline is? + #[must_use = "Setting deadline must be polled to be effective"] + pub fn set_current_task_deadline_after(duration_ticks: u64) -> impl Future { + poll_fn(move |cx| { + let task = super::task_from_waker(cx.waker()); + let now = embassy_time_driver::now(); + + // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave + // it for now, we can probably make this wrapping_add for performance + // reasons later. + let deadline = now.saturating_add(duration_ticks); + + // SAFETY: A task can only modify its own deadline, while the task is being + // polled, meaning that there cannot be concurrent access to the deadline. + unsafe { + task.header().deadline.set(deadline); + } + Poll::Ready(()) + }) + } + + /// Set the current task's deadline `increment_ticks` from the previous deadline. + /// + /// Note that by default (unless otherwise set), tasks start life with the deadline + /// u64::MAX, which means this method will have no effect. + /// + /// This method is a future in order to access the currently executing task's + /// header which contains the deadline + /// + /// Analogous to one increment of `Ticker::every().next()`. + /// + /// TODO: Do we want to return what the deadline is? + #[must_use = "Setting deadline must be polled to be effective"] + pub fn increment_current_task_deadline(increment_ticks: u64) -> impl Future { + poll_fn(move |cx| { + let task = super::task_from_waker(cx.waker()); + + // SAFETY: A task can only modify its own deadline, while the task is being + // polled, meaning that there cannot be concurrent access to the deadline. + unsafe { + // Get the last value + let last = task.header().deadline.get(); + + // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave + // it for now, we can probably make this wrapping_add for performance + // reasons later. + let deadline = last.saturating_add(increment_ticks); + + // Store the new value + task.header().deadline.set(deadline); + } + Poll::Ready(()) + }) + } + + /// Get the current task's deadline as a tick value. + /// + /// This method is a future in order to access the currently executing task's + /// header which contains the deadline + pub fn get_current_task_deadline() -> impl Future { + poll_fn(move |cx| { + let task = super::task_from_waker(cx.waker()); + + // SAFETY: A task can only modify its own deadline, while the task is being + // polled, meaning that there cannot be concurrent access to the deadline. + let deadline = unsafe { task.header().deadline.get() }; + Poll::Ready(Self { + instant_ticks: deadline, + }) + }) + } +} diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 2e5941ef7..0dd247d30 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -7,14 +7,7 @@ //! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe //! [executor wrappers](crate::Executor) and the [`embassy_executor::task`](embassy_executor_macros::task) macro, which are fully safe. -#[cfg_attr( - all(not(feature = "drs-scheduler"), target_has_atomic = "ptr"), - path = "run_queue_atomics.rs", -)] -#[cfg_attr( - all(feature = "drs-scheduler", target_has_atomic = "ptr"), - path = "run_queue_drs_atomics.rs", -)] +#[cfg_attr(target_has_atomic = "ptr", path = "run_queue_atomics.rs")] #[cfg_attr(not(target_has_atomic = "ptr"), path = "run_queue_critical_section.rs")] mod run_queue; @@ -35,6 +28,9 @@ pub(crate) mod util; #[cfg_attr(feature = "turbowakers", path = "waker_turbo.rs")] mod waker; +#[cfg(feature = "drs-scheduler")] +mod deadline; + use core::future::Future; use core::marker::PhantomData; use core::mem; @@ -50,6 +46,9 @@ use embassy_executor_timer_queue::TimerQueueItem; #[cfg(feature = "arch-avr")] use portable_atomic::AtomicPtr; +#[cfg(feature = "drs-scheduler")] +pub use deadline::Deadline; + use self::run_queue::{RunQueue, RunQueueItem}; use self::state::State; use self::util::{SyncUnsafeCell, UninitCell}; @@ -62,9 +61,6 @@ extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static unsafe { task_from_waker(waker).timer_queue_item() } } -#[cfg(feature = "drs-scheduler")] -pub use run_queue::Deadline; - /// Raw task header for use in task pointers. /// /// A task can be in one of the following states: diff --git a/embassy-executor/src/raw/run_queue_atomics.rs b/embassy-executor/src/raw/run_queue_atomics.rs index ce511d79a..bc5d38250 100644 --- a/embassy-executor/src/raw/run_queue_atomics.rs +++ b/embassy-executor/src/raw/run_queue_atomics.rs @@ -1,19 +1,36 @@ -use core::ptr; -use core::ptr::NonNull; -use core::sync::atomic::{AtomicPtr, Ordering}; +use core::ptr::{addr_of_mut, NonNull}; + +use cordyceps::sorted_list::Links; +use cordyceps::{Linked, SortedList, TransferStack}; use super::{TaskHeader, TaskRef}; -use crate::raw::util::SyncUnsafeCell; -pub(crate) struct RunQueueItem { - next: SyncUnsafeCell>, -} +/// Use `cordyceps::sorted_list::Links` as the singly linked list +/// for RunQueueItems. +pub(crate) type RunQueueItem = Links; -impl RunQueueItem { - pub const fn new() -> Self { - Self { - next: SyncUnsafeCell::new(None), - } +/// Implements the `Linked` trait, allowing for singly linked list usage +/// of any of cordyceps' `TransferStack` (used for the atomic runqueue), +/// `SortedList` (used with the DRS scheduler), or `Stack`, which is +/// popped atomically from the `TransferStack`. +unsafe impl Linked> for TaskHeader { + type Handle = TaskRef; + + // Convert a TaskRef into a TaskHeader ptr + fn into_ptr(r: TaskRef) -> NonNull { + r.ptr + } + + // Convert a TaskHeader into a TaskRef + unsafe fn from_ptr(ptr: NonNull) -> TaskRef { + TaskRef { ptr } + } + + // Given a pointer to a TaskHeader, obtain a pointer to the Links structure, + // which can be used to traverse to other TaskHeader nodes in the linked list + unsafe fn links(ptr: NonNull) -> NonNull> { + let ptr: *mut TaskHeader = ptr.as_ptr(); + NonNull::new_unchecked(addr_of_mut!((*ptr).run_queue_item)) } } @@ -29,13 +46,13 @@ impl RunQueueItem { /// current batch is completely processed, so even if a task enqueues itself instantly (for example /// by waking its own waker) can't prevent other tasks from running. pub(crate) struct RunQueue { - head: AtomicPtr, + stack: TransferStack, } impl RunQueue { pub const fn new() -> Self { Self { - head: AtomicPtr::new(ptr::null_mut()), + stack: TransferStack::new(), } } @@ -46,43 +63,52 @@ impl RunQueue { /// `item` must NOT be already enqueued in any queue. #[inline(always)] pub(crate) unsafe fn enqueue(&self, task: TaskRef, _: super::state::Token) -> bool { - let mut was_empty = false; - - self.head - .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |prev| { - was_empty = prev.is_null(); - unsafe { - // safety: the pointer is either null or valid - let prev = NonNull::new(prev).map(|ptr| TaskRef::from_ptr(ptr.as_ptr())); - // safety: there are no concurrent accesses to `next` - task.header().run_queue_item.next.set(prev); - } - Some(task.as_ptr() as *mut _) - }) - .ok(); - - was_empty + self.stack.push_was_empty(task) } /// Empty the queue, then call `on_task` for each task that was in the queue. /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. + #[cfg(not(feature = "drs-scheduler"))] pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { - // Atomically empty the queue. - let ptr = self.head.swap(ptr::null_mut(), Ordering::AcqRel); + let taken = self.stack.take_all(); + for taskref in taken { + taskref.header().state.run_dequeue(); + on_task(taskref); + } + } + + /// Empty the queue, then call `on_task` for each task that was in the queue. + /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue + /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. + #[cfg(feature = "drs-scheduler")] + pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { + // SAFETY: `deadline` can only be set through the `Deadline` interface, which + // only allows access to this value while the given task is being polled. + // This acts as mutual exclusion for access. + let mut sorted = + SortedList::::new_custom(|lhs, rhs| unsafe { lhs.deadline.get().cmp(&rhs.deadline.get()) }); + + loop { + // For each loop, grab any newly pended items + let taken = self.stack.take_all(); - // safety: the pointer is either null or valid - let mut next = unsafe { NonNull::new(ptr).map(|ptr| TaskRef::from_ptr(ptr.as_ptr())) }; + // Sort these into the list - this is potentially expensive! We do an + // insertion sort of new items, which iterates the linked list. + // + // Something on the order of `O(n * m)`, where `n` is the number + // of new tasks, and `m` is the number of already pending tasks. + sorted.extend(taken); - // Iterate the linked list of tasks that were previously in the queue. - while let Some(task) = next { - // If the task re-enqueues itself, the `next` pointer will get overwritten. - // Therefore, first read the next pointer, and only then process the task. - // safety: there are no concurrent accesses to `next` - next = unsafe { task.header().run_queue_item.next.get() }; + // Pop the task with the SOONEST deadline. If there are no tasks + // pending, then we are done. + let Some(taskref) = sorted.pop_front() else { + return; + }; - task.header().state.run_dequeue(); - on_task(task); + // We got one task, mark it as dequeued, and process the task. + taskref.header().state.run_dequeue(); + on_task(taskref); } } } diff --git a/embassy-executor/src/raw/run_queue_drs_atomics.rs b/embassy-executor/src/raw/run_queue_drs_atomics.rs deleted file mode 100644 index 047265954..000000000 --- a/embassy-executor/src/raw/run_queue_drs_atomics.rs +++ /dev/null @@ -1,203 +0,0 @@ -use super::{TaskHeader, TaskRef}; -use cordyceps::{SortedList, TransferStack}; -use core::future::{Future, poll_fn}; -use core::task::Poll; -use core::ptr::{addr_of_mut, NonNull}; -use cordyceps::sorted_list::Links; -use cordyceps::Linked; - -pub(crate) type RunQueueItem = Links; - -unsafe impl Linked> for super::TaskHeader { - type Handle = TaskRef; - - fn into_ptr(r: Self::Handle) -> NonNull { - r.ptr.cast() - } - - unsafe fn from_ptr(ptr: NonNull) -> Self::Handle { - let ptr: NonNull = ptr; - TaskRef { ptr } - } - - unsafe fn links(ptr: NonNull) -> NonNull> { - let ptr: *mut TaskHeader = ptr.as_ptr(); - NonNull::new_unchecked(addr_of_mut!((*ptr).run_queue_item)) - } -} - -/// Atomic task queue using a very, very simple lock-free linked-list queue: -/// -/// To enqueue a task, task.next is set to the old head, and head is atomically set to task. -/// -/// Dequeuing is done in batches: the queue is emptied by atomically replacing head with -/// null. Then the batch is iterated following the next pointers until null is reached. -/// -/// Note that batches will be iterated in the reverse order as they were enqueued. This is OK -/// for our purposes: it can't create fairness problems since the next batch won't run until the -/// current batch is completely processed, so even if a task enqueues itself instantly (for example -/// by waking its own waker) can't prevent other tasks from running. -pub(crate) struct RunQueue { - stack: TransferStack, -} - -impl RunQueue { - pub const fn new() -> Self { - Self { - stack: TransferStack::new(), - } - } - - /// Enqueues an item. Returns true if the queue was empty. - /// - /// # Safety - /// - /// `item` must NOT be already enqueued in any queue. - #[inline(always)] - pub(crate) unsafe fn enqueue(&self, task: TaskRef, _: super::state::Token) -> bool { - self.stack.push_was_empty(task) - } - - /// Empty the queue, then call `on_task` for each task that was in the queue. - /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue - /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. - pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { - // SAFETY: `deadline` can only be set through the `Deadline` interface, which - // only allows access to this value while the given task is being polled. - // This acts as mutual exclusion for access. - let mut sorted = SortedList::::new_custom(|lhs, rhs| unsafe { - lhs.deadline.get().cmp(&rhs.deadline.get()) - }); - - loop { - // For each loop, grab any newly pended items - let taken = self.stack.take_all(); - - // Sort these into the list - this is potentially expensive! We do an - // insertion sort of new items, which iterates the linked list. - // - // Something on the order of `O(n * m)`, where `n` is the number - // of new tasks, and `m` is the number of already pending tasks. - sorted.extend(taken); - - // Pop the task with the SOONEST deadline. If there are no tasks - // pending, then we are done. - let Some(taskref) = sorted.pop_front() else { - return; - }; - - // We got one task, mark it as dequeued, and process the task. - taskref.header().state.run_dequeue(); - on_task(taskref); - } - } -} - -/// A type for interacting with the deadline of the current task -pub struct Deadline { - /// Deadline value in ticks, same time base and ticks as `embassy-time` - pub instant_ticks: u64, -} - -impl Deadline { - /// Set the current task's deadline at exactly `instant_ticks` - /// - /// This method is a future in order to access the currently executing task's - /// header which contains the deadline. - /// - /// Analogous to `Timer::at`. - /// - /// TODO: Should we check/panic if the deadline is in the past? - #[must_use = "Setting deadline must be polled to be effective"] - pub fn set_current_task_deadline(instant_ticks: u64) -> impl Future { - poll_fn(move |cx| { - let task = super::task_from_waker(cx.waker()); - // SAFETY: A task can only modify its own deadline, while the task is being - // polled, meaning that there cannot be concurrent access to the deadline. - unsafe { - task.header().deadline.set(instant_ticks); - } - Poll::Ready(()) - }) - } - - /// Set the current task's deadline `duration_ticks` in the future from when - /// this future is polled. - /// - /// This method is a future in order to access the currently executing task's - /// header which contains the deadline - /// - /// Analogous to `Timer::after` - /// - /// TODO: Do we want to return what the deadline is? - #[must_use = "Setting deadline must be polled to be effective"] - pub fn set_current_task_deadline_after(duration_ticks: u64) -> impl Future { - poll_fn(move |cx| { - let task = super::task_from_waker(cx.waker()); - let now = embassy_time_driver::now(); - - // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave - // it for now, we can probably make this wrapping_add for performance - // reasons later. - let deadline = now.saturating_add(duration_ticks); - - // SAFETY: A task can only modify its own deadline, while the task is being - // polled, meaning that there cannot be concurrent access to the deadline. - unsafe { - task.header().deadline.set(deadline); - } - Poll::Ready(()) - }) - } - - /// Set the current task's deadline `increment_ticks` from the previous deadline. - /// - /// Note that by default (unless otherwise set), tasks start life with the deadline - /// u64::MAX, which means this method will have no effect. - /// - /// This method is a future in order to access the currently executing task's - /// header which contains the deadline - /// - /// Analogous to one increment of `Ticker::every().next()`. - /// - /// TODO: Do we want to return what the deadline is? - #[must_use = "Setting deadline must be polled to be effective"] - pub fn increment_current_task_deadline(increment_ticks: u64) -> impl Future { - poll_fn(move |cx| { - let task = super::task_from_waker(cx.waker()); - - // SAFETY: A task can only modify its own deadline, while the task is being - // polled, meaning that there cannot be concurrent access to the deadline. - unsafe { - // Get the last value - let last = task.header().deadline.get(); - - // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave - // it for now, we can probably make this wrapping_add for performance - // reasons later. - let deadline = last.saturating_add(increment_ticks); - - // Store the new value - task.header().deadline.set(deadline); - } - Poll::Ready(()) - }) - } - - /// Get the current task's deadline as a tick value. - /// - /// This method is a future in order to access the currently executing task's - /// header which contains the deadline - pub fn get_current_task_deadline() -> impl Future { - poll_fn(move |cx| { - let task = super::task_from_waker(cx.waker()); - - // SAFETY: A task can only modify its own deadline, while the task is being - // polled, meaning that there cannot be concurrent access to the deadline. - let deadline = unsafe { - task.header().deadline.get() - }; - Poll::Ready(Self { instant_ticks: deadline }) - }) - } -} -- cgit From ed2e51bfa4f92b422233343a0c5b1af98fb36537 Mon Sep 17 00:00:00 2001 From: James Munns Date: Tue, 1 Apr 2025 19:32:12 +0200 Subject: Dependency enablement trickery --- embassy-executor/Cargo.toml | 18 ++++++++++++------ embassy-executor/src/raw/deadline.rs | 2 ++ embassy-executor/src/raw/mod.rs | 11 +++++++---- embassy-executor/src/raw/run_queue_atomics.rs | 19 ++++++++++++++++--- 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 80b5867c9..06e12ae7e 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -46,7 +46,7 @@ flavors = [ [package.metadata.docs.rs] default-target = "thumbv7em-none-eabi" targets = ["thumbv7em-none-eabi"] -features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"] +features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt", "drs-scheduler"] [dependencies] defmt = { version = "1.0.1", optional = true } @@ -76,13 +76,17 @@ js-sys = { version = "0.3", optional = true } # arch-avr dependencies avr-device = { version = "0.7.0", optional = true } -[dependencies.cordyceps] -# note: targeting v0.3.3, to be released when +# Note: this is ONLY a dependency when the target has atomics, this is +# used for `run_queue_atomics`. We need to be conditional because +# cordyceps *requires* the use of atomics, so we pull it in when +# `run_queue_atomics` would be enabled, and NOT when `run_queue_critical_section` +# would be enabled. +[target.'cfg(target_has_atomic="ptr")'.dependencies.cordyceps] +# TODO: targeting v0.3.3, to be released when # https://github.com/hawkw/mycelium/pull/520 is merged version = "0.3" git = "https://github.com/hawkw/mycelium" rev = "9649db0525b9972b95937d83d52d3f51cc486281" -optional = true [dev-dependencies] critical-section = { version = "1.1", features = ["std"] } @@ -133,5 +137,7 @@ trace = ["_any_trace"] rtos-trace = ["_any_trace", "metadata-name", "dep:rtos-trace", "dep:embassy-time-driver"] _any_trace = [] -## Enable "Deadline Rank Scheduler" -drs-scheduler = ["dep:cordyceps", "dep:embassy-time-driver"] +## Enable "Deadline Rank Sorted" Scheduler, using soft-realtime "deadlines" to prioritize +## tasks based on the remaining time before their deadline. Adds some overhead. Requires +## hardware atomic support +drs-scheduler = ["dep:embassy-time-driver"] diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs index 3f60936cc..c8cc94c52 100644 --- a/embassy-executor/src/raw/deadline.rs +++ b/embassy-executor/src/raw/deadline.rs @@ -2,6 +2,8 @@ use core::future::{poll_fn, Future}; use core::task::Poll; /// A type for interacting with the deadline of the current task +/// +/// Requires the `drs-scheduler` feature pub struct Deadline { /// Deadline value in ticks, same time base and ticks as `embassy-time` pub instant_ticks: u64, diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 0dd247d30..f4fbe1bfc 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -101,14 +101,14 @@ extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static /// - 5: Task is dequeued. The task's future is not polled, because exiting the task replaces its `poll_fn`. /// - 6: A task is waken when it is not spawned - `wake_task -> State::run_enqueue` pub(crate) struct TaskHeader { + pub(crate) state: State, pub(crate) run_queue_item: RunQueueItem, - #[cfg(feature = "drs-scheduler")] /// Deadline Rank Scheduler Deadline. This field should not be accessed outside the context of /// the task itself as it being polled by the executor. + #[cfg(feature = "drs-scheduler")] pub(crate) deadline: SyncUnsafeCell, - pub(crate) state: State, pub(crate) executor: AtomicPtr, poll_fn: SyncUnsafeCell>, @@ -211,10 +211,12 @@ impl TaskStorage { pub const fn new() -> Self { Self { raw: TaskHeader { + state: State::new(), run_queue_item: RunQueueItem::new(), + // NOTE: The deadline is set to zero to allow the initializer to reside in `.bss`. This + // will be lazily initalized in `initialize_impl` #[cfg(feature = "drs-scheduler")] deadline: SyncUnsafeCell::new(0u64), - state: State::new(), executor: AtomicPtr::new(core::ptr::null_mut()), // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss` poll_fn: SyncUnsafeCell::new(None), @@ -311,7 +313,8 @@ impl AvailableTask { self.task.raw.poll_fn.set(Some(TaskStorage::::poll)); self.task.future.write_in_place(future); - // TODO(AJM): Some other way of setting this? Just a placeholder + // By default, deadlines are set to the maximum value, so that any task WITH + // a set deadline will ALWAYS be scheduled BEFORE a task WITHOUT a set deadline #[cfg(feature = "drs-scheduler")] self.task.raw.deadline.set(u64::MAX); diff --git a/embassy-executor/src/raw/run_queue_atomics.rs b/embassy-executor/src/raw/run_queue_atomics.rs index bc5d38250..3715fc658 100644 --- a/embassy-executor/src/raw/run_queue_atomics.rs +++ b/embassy-executor/src/raw/run_queue_atomics.rs @@ -66,6 +66,8 @@ impl RunQueue { self.stack.push_was_empty(task) } + /// # Standard atomic runqueue + /// /// Empty the queue, then call `on_task` for each task that was in the queue. /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. @@ -78,9 +80,20 @@ impl RunQueue { } } - /// Empty the queue, then call `on_task` for each task that was in the queue. - /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue - /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. + /// # Deadline Ranked Sorted Scheduler + /// + /// This algorithm will loop until all enqueued tasks are processed. + /// + /// Before polling a task, all currently enqueued tasks will be popped from the + /// runqueue, and will be added to the working `sorted` list, a linked-list that + /// sorts tasks by their deadline, with nearest deadline items in the front, and + /// furthest deadline items in the back. + /// + /// After popping and sorting all pending tasks, the SOONEST task will be popped + /// from the front of the queue, and polled by calling `on_task` on it. + /// + /// This process will repeat until the local `sorted` queue AND the global + /// runqueue are both empty, at which point this function will return. #[cfg(feature = "drs-scheduler")] pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { // SAFETY: `deadline` can only be set through the `Deadline` interface, which -- cgit From 2a068c528383b3ddc1213b9a5da5445498962bd2 Mon Sep 17 00:00:00 2001 From: James Munns Date: Tue, 1 Apr 2025 19:41:19 +0200 Subject: Conditional import --- embassy-executor/src/raw/run_queue_atomics.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-executor/src/raw/run_queue_atomics.rs b/embassy-executor/src/raw/run_queue_atomics.rs index 3715fc658..a63f0d116 100644 --- a/embassy-executor/src/raw/run_queue_atomics.rs +++ b/embassy-executor/src/raw/run_queue_atomics.rs @@ -1,7 +1,9 @@ use core::ptr::{addr_of_mut, NonNull}; use cordyceps::sorted_list::Links; -use cordyceps::{Linked, SortedList, TransferStack}; +#[cfg(feature = "drs-scheduler")] +use cordyceps::SortedList; +use cordyceps::{Linked, TransferStack}; use super::{TaskHeader, TaskRef}; -- cgit From 08a57b1cb0c3c4a40bd03e6e6ea1c97777300cf4 Mon Sep 17 00:00:00 2001 From: James Munns Date: Wed, 2 Apr 2025 23:30:40 +0200 Subject: Update with changes from the PR --- embassy-executor/Cargo.toml | 5 ++--- embassy-executor/src/raw/run_queue_atomics.rs | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 06e12ae7e..ab95b2939 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -82,11 +82,10 @@ avr-device = { version = "0.7.0", optional = true } # `run_queue_atomics` would be enabled, and NOT when `run_queue_critical_section` # would be enabled. [target.'cfg(target_has_atomic="ptr")'.dependencies.cordyceps] -# TODO: targeting v0.3.3, to be released when -# https://github.com/hawkw/mycelium/pull/520 is merged +# TODO: targeting v0.3.3, to be released soon version = "0.3" git = "https://github.com/hawkw/mycelium" -rev = "9649db0525b9972b95937d83d52d3f51cc486281" +rev = "1dad987b483078b248ac3e2e7a75f1ff2b463cc4" [dev-dependencies] critical-section = { version = "1.1", features = ["std"] } diff --git a/embassy-executor/src/raw/run_queue_atomics.rs b/embassy-executor/src/raw/run_queue_atomics.rs index a63f0d116..08765e06b 100644 --- a/embassy-executor/src/raw/run_queue_atomics.rs +++ b/embassy-executor/src/raw/run_queue_atomics.rs @@ -102,7 +102,7 @@ impl RunQueue { // only allows access to this value while the given task is being polled. // This acts as mutual exclusion for access. let mut sorted = - SortedList::::new_custom(|lhs, rhs| unsafe { lhs.deadline.get().cmp(&rhs.deadline.get()) }); + SortedList::::new_with_cmp(|lhs, rhs| unsafe { lhs.deadline.get().cmp(&rhs.deadline.get()) }); loop { // For each loop, grab any newly pended items -- cgit From b65a3a301a29c737f336ca344f671d4e9793fda8 Mon Sep 17 00:00:00 2001 From: James Munns Date: Thu, 3 Apr 2025 10:27:26 +0200 Subject: Clean up some TODOs --- embassy-executor/src/raw/deadline.rs | 62 ++++++++++++++++++++++++++++++------ embassy-executor/src/raw/mod.rs | 2 +- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs index c8cc94c52..0b88ee2d6 100644 --- a/embassy-executor/src/raw/deadline.rs +++ b/embassy-executor/src/raw/deadline.rs @@ -10,6 +10,16 @@ pub struct Deadline { } impl Deadline { + /// Sentinel value representing an "unset" deadline, which has lower priority + /// than any other set deadline value + pub const UNSET_DEADLINE_TICKS: u64 = u64::MAX; + + /// Does the given Deadline represent an "unset" deadline? + #[inline] + pub fn is_unset(&self) -> bool { + self.instant_ticks == Self::UNSET_DEADLINE_TICKS + } + /// Set the current task's deadline at exactly `instant_ticks` /// /// This method is a future in order to access the currently executing task's @@ -17,7 +27,7 @@ impl Deadline { /// /// Analogous to `Timer::at`. /// - /// TODO: Should we check/panic if the deadline is in the past? + /// This method does NOT check whether the deadline has already passed. #[must_use = "Setting deadline must be polled to be effective"] pub fn set_current_task_deadline(instant_ticks: u64) -> impl Future { poll_fn(move |cx| { @@ -32,16 +42,16 @@ impl Deadline { } /// Set the current task's deadline `duration_ticks` in the future from when - /// this future is polled. + /// this future is polled. This deadline is saturated to the max tick value. /// /// This method is a future in order to access the currently executing task's - /// header which contains the deadline + /// header which contains the deadline. /// - /// Analogous to `Timer::after` + /// Analogous to `Timer::after`. /// - /// TODO: Do we want to return what the deadline is? + /// Returns the deadline that was set. #[must_use = "Setting deadline must be polled to be effective"] - pub fn set_current_task_deadline_after(duration_ticks: u64) -> impl Future { + pub fn set_current_task_deadline_after(duration_ticks: u64) -> impl Future { poll_fn(move |cx| { let task = super::task_from_waker(cx.waker()); let now = embassy_time_driver::now(); @@ -56,12 +66,16 @@ impl Deadline { unsafe { task.header().deadline.set(deadline); } - Poll::Ready(()) + Poll::Ready(Deadline { + instant_ticks: deadline, + }) }) } /// Set the current task's deadline `increment_ticks` from the previous deadline. /// + /// This deadline is saturated to the max tick value. + /// /// Note that by default (unless otherwise set), tasks start life with the deadline /// u64::MAX, which means this method will have no effect. /// @@ -70,9 +84,9 @@ impl Deadline { /// /// Analogous to one increment of `Ticker::every().next()`. /// - /// TODO: Do we want to return what the deadline is? + /// Returns the deadline that was set. #[must_use = "Setting deadline must be polled to be effective"] - pub fn increment_current_task_deadline(increment_ticks: u64) -> impl Future { + pub fn increment_current_task_deadline(increment_ticks: u64) -> impl Future { poll_fn(move |cx| { let task = super::task_from_waker(cx.waker()); @@ -89,8 +103,11 @@ impl Deadline { // Store the new value task.header().deadline.set(deadline); + + Poll::Ready(Deadline { + instant_ticks: deadline, + }) } - Poll::Ready(()) }) } @@ -110,4 +127,29 @@ impl Deadline { }) }) } + + /// Clear the current task's deadline, returning the previous value. + /// + /// This sets the deadline to the default value of `u64::MAX`, meaning all + /// tasks with set deadlines will be scheduled BEFORE this task. + pub fn clear_current_task_deadline() -> impl Future { + poll_fn(move |cx| { + let task = super::task_from_waker(cx.waker()); + + // SAFETY: A task can only modify its own deadline, while the task is being + // polled, meaning that there cannot be concurrent access to the deadline. + let deadline = unsafe { + // get the old value + let d = task.header().deadline.get(); + // Store the default value + task.header().deadline.set(Self::UNSET_DEADLINE_TICKS); + // return the old value + d + }; + + Poll::Ready(Self { + instant_ticks: deadline, + }) + }) + } } diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index f4fbe1bfc..a0890a864 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -316,7 +316,7 @@ impl AvailableTask { // By default, deadlines are set to the maximum value, so that any task WITH // a set deadline will ALWAYS be scheduled BEFORE a task WITHOUT a set deadline #[cfg(feature = "drs-scheduler")] - self.task.raw.deadline.set(u64::MAX); + self.task.raw.deadline.set(deadline::Deadline::UNSET_DEADLINE_TICKS); let task = TaskRef::new(self.task); -- cgit From b1b2955b604f558d8bd2fcca07b8fd8da3e236fa Mon Sep 17 00:00:00 2001 From: James Munns Date: Tue, 8 Apr 2025 10:05:55 +0200 Subject: Switch to released version of `cordyceps`, add error if used w/o atomics --- embassy-executor/Cargo.toml | 5 +---- embassy-executor/src/raw/deadline.rs | 3 +++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index ab95b2939..e740f9ccf 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -82,10 +82,7 @@ avr-device = { version = "0.7.0", optional = true } # `run_queue_atomics` would be enabled, and NOT when `run_queue_critical_section` # would be enabled. [target.'cfg(target_has_atomic="ptr")'.dependencies.cordyceps] -# TODO: targeting v0.3.3, to be released soon -version = "0.3" -git = "https://github.com/hawkw/mycelium" -rev = "1dad987b483078b248ac3e2e7a75f1ff2b463cc4" +version = "0.3.3" [dev-dependencies] critical-section = { version = "1.1", features = ["std"] } diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs index 0b88ee2d6..da07d1aac 100644 --- a/embassy-executor/src/raw/deadline.rs +++ b/embassy-executor/src/raw/deadline.rs @@ -1,6 +1,9 @@ use core::future::{poll_fn, Future}; use core::task::Poll; +#[cfg(not(target_has_atomic = "ptr"))] +compile_error!("The `drs-scheduler` feature is currently only supported on targets with atomics."); + /// A type for interacting with the deadline of the current task /// /// Requires the `drs-scheduler` feature -- cgit From 3929142f4c08028ea1982e79fd912e1a44900892 Mon Sep 17 00:00:00 2001 From: James Munns Date: Tue, 8 Apr 2025 10:11:07 +0200 Subject: One more must_use --- embassy-executor/src/raw/deadline.rs | 1 + embassy-executor/src/raw/mod.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs index da07d1aac..ae6394822 100644 --- a/embassy-executor/src/raw/deadline.rs +++ b/embassy-executor/src/raw/deadline.rs @@ -135,6 +135,7 @@ impl Deadline { /// /// This sets the deadline to the default value of `u64::MAX`, meaning all /// tasks with set deadlines will be scheduled BEFORE this task. + #[must_use = "Clearing deadline must be polled to be effective"] pub fn clear_current_task_deadline() -> impl Future { poll_fn(move |cx| { let task = super::task_from_waker(cx.waker()); diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index a0890a864..21dc67b7e 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -36,7 +36,6 @@ use core::marker::PhantomData; use core::mem; use core::pin::Pin; use core::ptr::NonNull; -use core::ptr::addr_of_mut; #[cfg(not(feature = "arch-avr"))] use core::sync::atomic::AtomicPtr; use core::sync::atomic::Ordering; @@ -48,6 +47,8 @@ use portable_atomic::AtomicPtr; #[cfg(feature = "drs-scheduler")] pub use deadline::Deadline; +#[cfg(feature = "arch-avr")] +use portable_atomic::AtomicPtr; use self::run_queue::{RunQueue, RunQueueItem}; use self::state::State; -- cgit From 0e28ba1091257111f71b76a664d7038dbfcf9b5e Mon Sep 17 00:00:00 2001 From: James Munns Date: Wed, 16 Apr 2025 15:59:28 +0200 Subject: "Deadline Rank Sorted Scheduler" -> "Earliest Deadline First Scheduler" --- embassy-executor/Cargo.toml | 7 ++++--- embassy-executor/src/raw/deadline.rs | 4 ++-- embassy-executor/src/raw/mod.rs | 14 +++++++------- embassy-executor/src/raw/run_queue_atomics.rs | 8 ++++---- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index e740f9ccf..17315eaa3 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -46,7 +46,7 @@ flavors = [ [package.metadata.docs.rs] default-target = "thumbv7em-none-eabi" targets = ["thumbv7em-none-eabi"] -features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt", "drs-scheduler"] +features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt", "edf-scheduler"] [dependencies] defmt = { version = "1.0.1", optional = true } @@ -91,6 +91,7 @@ embassy-sync = { path = "../embassy-sync" } rustversion = "1.0.21" [features] + ## Enable nightly-only features nightly = ["embassy-executor-macros/nightly"] @@ -133,7 +134,7 @@ trace = ["_any_trace"] rtos-trace = ["_any_trace", "metadata-name", "dep:rtos-trace", "dep:embassy-time-driver"] _any_trace = [] -## Enable "Deadline Rank Sorted" Scheduler, using soft-realtime "deadlines" to prioritize +## Enable "Earliest Deadline First" Scheduler, using soft-realtime "deadlines" to prioritize ## tasks based on the remaining time before their deadline. Adds some overhead. Requires ## hardware atomic support -drs-scheduler = ["dep:embassy-time-driver"] +edf-scheduler = ["dep:embassy-time-driver"] diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs index ae6394822..006c7caf1 100644 --- a/embassy-executor/src/raw/deadline.rs +++ b/embassy-executor/src/raw/deadline.rs @@ -2,11 +2,11 @@ use core::future::{poll_fn, Future}; use core::task::Poll; #[cfg(not(target_has_atomic = "ptr"))] -compile_error!("The `drs-scheduler` feature is currently only supported on targets with atomics."); +compile_error!("The `edf-scheduler` feature is currently only supported on targets with atomics."); /// A type for interacting with the deadline of the current task /// -/// Requires the `drs-scheduler` feature +/// Requires the `edf-scheduler` feature pub struct Deadline { /// Deadline value in ticks, same time base and ticks as `embassy-time` pub instant_ticks: u64, diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 21dc67b7e..96e7fda74 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -28,7 +28,7 @@ pub(crate) mod util; #[cfg_attr(feature = "turbowakers", path = "waker_turbo.rs")] mod waker; -#[cfg(feature = "drs-scheduler")] +#[cfg(feature = "edf-scheduler")] mod deadline; use core::future::Future; @@ -45,7 +45,7 @@ use embassy_executor_timer_queue::TimerQueueItem; #[cfg(feature = "arch-avr")] use portable_atomic::AtomicPtr; -#[cfg(feature = "drs-scheduler")] +#[cfg(feature = "edf-scheduler")] pub use deadline::Deadline; #[cfg(feature = "arch-avr")] use portable_atomic::AtomicPtr; @@ -105,9 +105,9 @@ pub(crate) struct TaskHeader { pub(crate) state: State, pub(crate) run_queue_item: RunQueueItem, - /// Deadline Rank Scheduler Deadline. This field should not be accessed outside the context of - /// the task itself as it being polled by the executor. - #[cfg(feature = "drs-scheduler")] + /// Earliest Deadline First scheduler Deadline. This field should not be accessed + /// outside the context of the task itself as it being polled by the executor. + #[cfg(feature = "edf-scheduler")] pub(crate) deadline: SyncUnsafeCell, pub(crate) executor: AtomicPtr, @@ -216,7 +216,7 @@ impl TaskStorage { run_queue_item: RunQueueItem::new(), // NOTE: The deadline is set to zero to allow the initializer to reside in `.bss`. This // will be lazily initalized in `initialize_impl` - #[cfg(feature = "drs-scheduler")] + #[cfg(feature = "edf-scheduler")] deadline: SyncUnsafeCell::new(0u64), executor: AtomicPtr::new(core::ptr::null_mut()), // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss` @@ -316,7 +316,7 @@ impl AvailableTask { // By default, deadlines are set to the maximum value, so that any task WITH // a set deadline will ALWAYS be scheduled BEFORE a task WITHOUT a set deadline - #[cfg(feature = "drs-scheduler")] + #[cfg(feature = "edf-scheduler")] self.task.raw.deadline.set(deadline::Deadline::UNSET_DEADLINE_TICKS); let task = TaskRef::new(self.task); diff --git a/embassy-executor/src/raw/run_queue_atomics.rs b/embassy-executor/src/raw/run_queue_atomics.rs index 08765e06b..65a9b7859 100644 --- a/embassy-executor/src/raw/run_queue_atomics.rs +++ b/embassy-executor/src/raw/run_queue_atomics.rs @@ -1,7 +1,7 @@ use core::ptr::{addr_of_mut, NonNull}; use cordyceps::sorted_list::Links; -#[cfg(feature = "drs-scheduler")] +#[cfg(feature = "edf-scheduler")] use cordyceps::SortedList; use cordyceps::{Linked, TransferStack}; @@ -73,7 +73,7 @@ impl RunQueue { /// Empty the queue, then call `on_task` for each task that was in the queue. /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. - #[cfg(not(feature = "drs-scheduler"))] + #[cfg(not(feature = "edf-scheduler"))] pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { let taken = self.stack.take_all(); for taskref in taken { @@ -82,7 +82,7 @@ impl RunQueue { } } - /// # Deadline Ranked Sorted Scheduler + /// # Earliest Deadline First Scheduler /// /// This algorithm will loop until all enqueued tasks are processed. /// @@ -96,7 +96,7 @@ impl RunQueue { /// /// This process will repeat until the local `sorted` queue AND the global /// runqueue are both empty, at which point this function will return. - #[cfg(feature = "drs-scheduler")] + #[cfg(feature = "edf-scheduler")] pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { // SAFETY: `deadline` can only be set through the `Deadline` interface, which // only allows access to this value while the given task is being polled. -- cgit From 0cb1ffe0258380a3dd25c1037fdfb6ceca3149d9 Mon Sep 17 00:00:00 2001 From: James Munns Date: Wed, 16 Apr 2025 17:58:45 +0200 Subject: Add EDF example --- examples/nrf52840-edf/.cargo/config.toml | 9 ++ examples/nrf52840-edf/Cargo.toml | 21 ++++ examples/nrf52840-edf/build.rs | 35 ++++++ examples/nrf52840-edf/memory.x | 12 ++ examples/nrf52840-edf/src/bin/basic.rs | 191 +++++++++++++++++++++++++++++++ 5 files changed, 268 insertions(+) create mode 100644 examples/nrf52840-edf/.cargo/config.toml create mode 100644 examples/nrf52840-edf/Cargo.toml create mode 100644 examples/nrf52840-edf/build.rs create mode 100644 examples/nrf52840-edf/memory.x create mode 100644 examples/nrf52840-edf/src/bin/basic.rs diff --git a/examples/nrf52840-edf/.cargo/config.toml b/examples/nrf52840-edf/.cargo/config.toml new file mode 100644 index 000000000..e0b9ce59e --- /dev/null +++ b/examples/nrf52840-edf/.cargo/config.toml @@ -0,0 +1,9 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +# replace nRF82840_xxAA with your chip as listed in `probe-rs chip list` +runner = "probe-rs run --chip nRF52840_xxAA" + +[build] +target = "thumbv7em-none-eabi" + +[env] +DEFMT_LOG = "debug" diff --git a/examples/nrf52840-edf/Cargo.toml b/examples/nrf52840-edf/Cargo.toml new file mode 100644 index 000000000..c7147d1af --- /dev/null +++ b/examples/nrf52840-edf/Cargo.toml @@ -0,0 +1,21 @@ +[package] +edition = "2021" +name = "embassy-nrf52840-edf-examples" +version = "0.1.0" +license = "MIT OR Apache-2.0" + +[dependencies] +# NOTE: "edf-scheduler" feature is enabled +embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "edf-scheduler"] } +embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } + +defmt = "0.3" +defmt-rtt = "0.4" + +cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } +cortex-m-rt = "0.7.0" +panic-probe = { version = "0.3", features = ["print-defmt"] } + +[profile.release] +debug = 2 diff --git a/examples/nrf52840-edf/build.rs b/examples/nrf52840-edf/build.rs new file mode 100644 index 000000000..30691aa97 --- /dev/null +++ b/examples/nrf52840-edf/build.rs @@ -0,0 +1,35 @@ +//! This build script copies the `memory.x` file from the crate root into +//! a directory where the linker can always find it at build time. +//! For many projects this is optional, as the linker always searches the +//! project root directory -- wherever `Cargo.toml` is. However, if you +//! are using a workspace or have a more complicated build setup, this +//! build script becomes required. Additionally, by requesting that +//! Cargo re-run the build script whenever `memory.x` is changed, +//! updating `memory.x` ensures a rebuild of the application with the +//! new memory settings. + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put `memory.x` in our output directory and ensure it's + // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // By default, Cargo will re-run a build script whenever + // any file in the project changes. By specifying `memory.x` + // here, we ensure the build script is only re-run when + // `memory.x` is changed. + println!("cargo:rerun-if-changed=memory.x"); + + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); +} diff --git a/examples/nrf52840-edf/memory.x b/examples/nrf52840-edf/memory.x new file mode 100644 index 000000000..15b492bce --- /dev/null +++ b/examples/nrf52840-edf/memory.x @@ -0,0 +1,12 @@ +MEMORY +{ + /* NOTE 1 K = 1 KiBi = 1024 bytes */ + FLASH : ORIGIN = 0x00000000, LENGTH = 1024K + RAM : ORIGIN = 0x20000000, LENGTH = 256K + + /* These values correspond to the NRF52840 with Softdevices S140 7.3.0 */ + /* + FLASH : ORIGIN = 0x00027000, LENGTH = 868K + RAM : ORIGIN = 0x20020000, LENGTH = 128K + */ +} diff --git a/examples/nrf52840-edf/src/bin/basic.rs b/examples/nrf52840-edf/src/bin/basic.rs new file mode 100644 index 000000000..6a7eb3c4b --- /dev/null +++ b/examples/nrf52840-edf/src/bin/basic.rs @@ -0,0 +1,191 @@ +//! Basic side-by-side example of the Earliest Deadline First scheduler +//! +//! This test spawns a number of background "ambient system load" workers +//! that are constantly working, and runs two sets of trials. +//! +//! The first trial runs with no deadline set, so our trial task is at the +//! same prioritization level as the background worker tasks. +//! +//! The second trial sets a deadline, meaning that it will be given higher +//! scheduling priority than background tasks, that have no deadline set + +#![no_std] +#![no_main] + +use core::sync::atomic::{compiler_fence, Ordering}; +use embassy_executor::{raw::Deadline, Spawner}; +use embassy_time::{Duration, Instant, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + embassy_nrf::init(Default::default()); + + // Enable flash cache to remove some flash latency jitter + compiler_fence(Ordering::SeqCst); + embassy_nrf::pac::NVMC.icachecnf().write(|w| { + w.set_cacheen(true); + }); + compiler_fence(Ordering::SeqCst); + + // + // Baseline system load tunables + // + + // how many load tasks? More load tasks means more tasks contending + // for the runqueue + let tasks = 32; + // how long should each task work for? The longer the working time, + // the longer the max jitter possible, even when a task is prioritized, + // as EDF is still cooperative and not pre-emptive + // + // 33 ticks ~= 1ms + let work_time_ticks = 33; + // what fraction, 1/denominator, should the system be busy? + // bigger number means **less** busy + // + // 2 => 50% + // 4 => 25% + // 10 => 10% + let denominator = 2; + + // Total time window, so each worker is working 1/denominator + // amount of the total time + let time_window = work_time_ticks * u64::from(tasks) * denominator; + + // Spawn all of our load workers! + for i in 0..tasks { + spawner.must_spawn(load_task(i, work_time_ticks, time_window)); + } + + // Let all the tasks spin up + defmt::println!("Spinning up load tasks..."); + Timer::after_secs(1).await; + + // + // Trial task worker tunables + // + + // How many steps should the workers under test run? + // More steps means more chances to have to wait for other tasks + // in line ahead of us. + let num_steps = 100; + + // How many ticks should the worker take working on each step? + // + // 33 ticks ~= 1ms + let work_ticks = 33; + // How many ticks should the worker wait on each step? + // + // 66 ticks ~= 2ms + let idle_ticks = 66; + + // How many times to repeat each trial? + let trials = 3; + + // The total time a trial would take, in a perfect unloaded system + let theoretical = (num_steps * work_ticks) + (num_steps * idle_ticks); + + defmt::println!(""); + defmt::println!("Starting UNPRIORITIZED worker trials"); + for _ in 0..trials { + // + // UNPRIORITIZED worker + // + defmt::println!(""); + defmt::println!("Starting unprioritized worker"); + let start = Instant::now(); + for _ in 0..num_steps { + let now = Instant::now(); + while now.elapsed().as_ticks() < work_ticks {} + Timer::after_ticks(idle_ticks).await; + } + let elapsed = start.elapsed().as_ticks(); + defmt::println!( + "Trial complete, theoretical ticks: {=u64}, actual ticks: {=u64}", + theoretical, + elapsed + ); + let ratio = ((elapsed as f32) / (theoretical as f32)) * 100.0; + defmt::println!("Took {=f32}% of ideal time", ratio); + Timer::after_millis(500).await; + } + + Timer::after_secs(1).await; + + defmt::println!(""); + defmt::println!("Starting PRIORITIZED worker trials"); + for _ in 0..trials { + // + // PRIORITIZED worker + // + defmt::println!(""); + defmt::println!("Starting prioritized worker"); + let start = Instant::now(); + // Set the deadline to ~2x the theoretical time. In practice, setting any deadline + // here elevates the current task above all other worker tasks. + Deadline::set_current_task_deadline_after(theoretical * 2).await; + + // Perform the trial + for _ in 0..num_steps { + let now = Instant::now(); + while now.elapsed().as_ticks() < work_ticks {} + Timer::after_ticks(idle_ticks).await; + } + + let elapsed = start.elapsed().as_ticks(); + defmt::println!( + "Trial complete, theoretical ticks: {=u64}, actual ticks: {=u64}", + theoretical, + elapsed + ); + let ratio = ((elapsed as f32) / (theoretical as f32)) * 100.0; + defmt::println!("Took {=f32}% of ideal time", ratio); + + // Unset the deadline, deadlines are not automatically cleared, and if our + // deadline is in the past, then we get very high priority! + Deadline::clear_current_task_deadline().await; + + Timer::after_millis(500).await; + } + + defmt::println!(""); + defmt::println!("Trials Complete."); +} + +#[embassy_executor::task(pool_size = 32)] +async fn load_task(id: u32, ticks_on: u64, ttl_ticks: u64) { + let mut last_print = Instant::now(); + let mut last_tick = last_print; + let mut variance = 0; + let mut max_variance = 0; + loop { + let tgt = last_tick + Duration::from_ticks(ttl_ticks); + assert!(tgt > Instant::now(), "fell too behind!"); + + Timer::at(tgt).await; + let now = Instant::now(); + // How late are we from the target? + let var = now.duration_since(tgt).as_ticks(); + max_variance = max_variance.max(var); + variance += var; + + // blocking work + while now.elapsed().as_ticks() < ticks_on {} + + if last_print.elapsed() >= Duration::from_secs(1) { + defmt::trace!( + "Task {=u32} variance ticks (1s): {=u64}, max: {=u64}, act: {=u64}", + id, + variance, + max_variance, + ticks_on, + ); + max_variance = 0; + variance = 0; + last_print = Instant::now(); + } + + last_tick = tgt; + } +} -- cgit From 67ed473973dae6d60aed8b88b8b854b224660e8d Mon Sep 17 00:00:00 2001 From: James Munns Date: Wed, 16 Apr 2025 18:01:11 +0200 Subject: rustfmt --- examples/nrf52840-edf/src/bin/basic.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/nrf52840-edf/src/bin/basic.rs b/examples/nrf52840-edf/src/bin/basic.rs index 6a7eb3c4b..c270c67b9 100644 --- a/examples/nrf52840-edf/src/bin/basic.rs +++ b/examples/nrf52840-edf/src/bin/basic.rs @@ -13,7 +13,9 @@ #![no_main] use core::sync::atomic::{compiler_fence, Ordering}; -use embassy_executor::{raw::Deadline, Spawner}; + +use embassy_executor::raw::Deadline; +use embassy_executor::Spawner; use embassy_time::{Duration, Instant, Timer}; use {defmt_rtt as _, panic_probe as _}; -- cgit From 7af8f35a50c631802615044e12cc9c74614f78bb Mon Sep 17 00:00:00 2001 From: James Munns Date: Tue, 3 Jun 2025 16:34:12 +0200 Subject: There can be only one (run queue) --- embassy-executor/Cargo.toml | 20 +-- embassy-executor/src/raw/deadline.rs | 3 - embassy-executor/src/raw/mod.rs | 2 - embassy-executor/src/raw/run_queue.rs | 151 +++++++++++++++++++++ embassy-executor/src/raw/run_queue_atomics.rs | 129 ------------------ .../src/raw/run_queue_critical_section.rs | 74 ---------- 6 files changed, 162 insertions(+), 217 deletions(-) create mode 100644 embassy-executor/src/raw/run_queue.rs delete mode 100644 embassy-executor/src/raw/run_queue_atomics.rs delete mode 100644 embassy-executor/src/raw/run_queue_critical_section.rs diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 17315eaa3..34468e4f9 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -76,13 +76,16 @@ js-sys = { version = "0.3", optional = true } # arch-avr dependencies avr-device = { version = "0.7.0", optional = true } -# Note: this is ONLY a dependency when the target has atomics, this is -# used for `run_queue_atomics`. We need to be conditional because -# cordyceps *requires* the use of atomics, so we pull it in when -# `run_queue_atomics` would be enabled, and NOT when `run_queue_critical_section` -# would be enabled. -[target.'cfg(target_has_atomic="ptr")'.dependencies.cordyceps] -version = "0.3.3" + +[dependencies.cordyceps] +# version = "0.3.3" +# todo: update after https://github.com/hawkw/mycelium/pull/537 is merged +git = "https://github.com/hawkw/mycelium" +rev = "86c428eecfd37ee24dd81f14c4a9f5c8ecefcf17" + +# Note: this is ONLY a dependency when the target does NOT have atomics +[target.'cfg(not(target_has_atomic="ptr"))'.dependencies.mutex] +version = "1.0" [dev-dependencies] critical-section = { version = "1.1", features = ["std"] } @@ -135,6 +138,5 @@ rtos-trace = ["_any_trace", "metadata-name", "dep:rtos-trace", "dep:embassy-time _any_trace = [] ## Enable "Earliest Deadline First" Scheduler, using soft-realtime "deadlines" to prioritize -## tasks based on the remaining time before their deadline. Adds some overhead. Requires -## hardware atomic support +## tasks based on the remaining time before their deadline. Adds some overhead. edf-scheduler = ["dep:embassy-time-driver"] diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs index 006c7caf1..0fb22a7ce 100644 --- a/embassy-executor/src/raw/deadline.rs +++ b/embassy-executor/src/raw/deadline.rs @@ -1,9 +1,6 @@ use core::future::{poll_fn, Future}; use core::task::Poll; -#[cfg(not(target_has_atomic = "ptr"))] -compile_error!("The `edf-scheduler` feature is currently only supported on targets with atomics."); - /// A type for interacting with the deadline of the current task /// /// Requires the `edf-scheduler` feature diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 96e7fda74..cc43690cb 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -7,8 +7,6 @@ //! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe //! [executor wrappers](crate::Executor) and the [`embassy_executor::task`](embassy_executor_macros::task) macro, which are fully safe. -#[cfg_attr(target_has_atomic = "ptr", path = "run_queue_atomics.rs")] -#[cfg_attr(not(target_has_atomic = "ptr"), path = "run_queue_critical_section.rs")] mod run_queue; #[cfg_attr(all(cortex_m, target_has_atomic = "32"), path = "state_atomics_arm.rs")] diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs new file mode 100644 index 000000000..f630041e0 --- /dev/null +++ b/embassy-executor/src/raw/run_queue.rs @@ -0,0 +1,151 @@ +use core::ptr::{addr_of_mut, NonNull}; + +use cordyceps::sorted_list::Links; +use cordyceps::Linked; +#[cfg(feature = "edf-scheduler")] +use cordyceps::SortedList; + +#[cfg(target_has_atomic = "ptr")] +type TransferStack = cordyceps::TransferStack; + +#[cfg(not(target_has_atomic = "ptr"))] +type TransferStack = cordyceps::TransferStack; + +use super::{TaskHeader, TaskRef}; + +/// Use `cordyceps::sorted_list::Links` as the singly linked list +/// for RunQueueItems. +pub(crate) type RunQueueItem = Links; + +/// Implements the `Linked` trait, allowing for singly linked list usage +/// of any of cordyceps' `TransferStack` (used for the atomic runqueue), +/// `SortedList` (used with the DRS scheduler), or `Stack`, which is +/// popped atomically from the `TransferStack`. +unsafe impl Linked> for TaskHeader { + type Handle = TaskRef; + + // Convert a TaskRef into a TaskHeader ptr + fn into_ptr(r: TaskRef) -> NonNull { + r.ptr + } + + // Convert a TaskHeader into a TaskRef + unsafe fn from_ptr(ptr: NonNull) -> TaskRef { + TaskRef { ptr } + } + + // Given a pointer to a TaskHeader, obtain a pointer to the Links structure, + // which can be used to traverse to other TaskHeader nodes in the linked list + unsafe fn links(ptr: NonNull) -> NonNull> { + let ptr: *mut TaskHeader = ptr.as_ptr(); + NonNull::new_unchecked(addr_of_mut!((*ptr).run_queue_item)) + } +} + +/// Atomic task queue using a very, very simple lock-free linked-list queue: +/// +/// To enqueue a task, task.next is set to the old head, and head is atomically set to task. +/// +/// Dequeuing is done in batches: the queue is emptied by atomically replacing head with +/// null. Then the batch is iterated following the next pointers until null is reached. +/// +/// Note that batches will be iterated in the reverse order as they were enqueued. This is OK +/// for our purposes: it can't create fairness problems since the next batch won't run until the +/// current batch is completely processed, so even if a task enqueues itself instantly (for example +/// by waking its own waker) can't prevent other tasks from running. +pub(crate) struct RunQueue { + stack: TransferStack, +} + +impl RunQueue { + pub const fn new() -> Self { + Self { + stack: TransferStack::new(), + } + } + + /// Enqueues an item. Returns true if the queue was empty. + /// + /// # Safety + /// + /// `item` must NOT be already enqueued in any queue. + #[inline(always)] + pub(crate) unsafe fn enqueue(&self, task: TaskRef, _: super::state::Token) -> bool { + self.stack.push_was_empty(task) + } + + /// # Standard atomic runqueue + /// + /// Empty the queue, then call `on_task` for each task that was in the queue. + /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue + /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. + #[cfg(not(feature = "edf-scheduler"))] + pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { + let taken = self.stack.take_all(); + for taskref in taken { + run_dequeue(&taskref); + on_task(taskref); + } + } + + /// # Earliest Deadline First Scheduler + /// + /// This algorithm will loop until all enqueued tasks are processed. + /// + /// Before polling a task, all currently enqueued tasks will be popped from the + /// runqueue, and will be added to the working `sorted` list, a linked-list that + /// sorts tasks by their deadline, with nearest deadline items in the front, and + /// furthest deadline items in the back. + /// + /// After popping and sorting all pending tasks, the SOONEST task will be popped + /// from the front of the queue, and polled by calling `on_task` on it. + /// + /// This process will repeat until the local `sorted` queue AND the global + /// runqueue are both empty, at which point this function will return. + #[cfg(feature = "edf-scheduler")] + pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { + // SAFETY: `deadline` can only be set through the `Deadline` interface, which + // only allows access to this value while the given task is being polled. + // This acts as mutual exclusion for access. + let mut sorted = + SortedList::::new_with_cmp(|lhs, rhs| unsafe { lhs.deadline.get().cmp(&rhs.deadline.get()) }); + + loop { + // For each loop, grab any newly pended items + let taken = self.stack.take_all(); + + // Sort these into the list - this is potentially expensive! We do an + // insertion sort of new items, which iterates the linked list. + // + // Something on the order of `O(n * m)`, where `n` is the number + // of new tasks, and `m` is the number of already pending tasks. + sorted.extend(taken); + + // Pop the task with the SOONEST deadline. If there are no tasks + // pending, then we are done. + let Some(taskref) = sorted.pop_front() else { + return; + }; + + // We got one task, mark it as dequeued, and process the task. + run_dequeue(&taskref); + on_task(taskref); + } + } +} + +/// atomic state does not require a cs... +#[cfg(target_has_atomic = "ptr")] +#[inline(always)] +fn run_dequeue(taskref: &TaskRef) { + taskref.header().state.run_dequeue(); +} + +/// ...while non-atomic state does +#[cfg(not(target_has_atomic = "ptr"))] +#[inline(always)] +fn run_dequeue(taskref: &TaskRef) { + critical_section::with(|cs| { + taskref.header().state.run_dequeue(cs); + }) +} diff --git a/embassy-executor/src/raw/run_queue_atomics.rs b/embassy-executor/src/raw/run_queue_atomics.rs deleted file mode 100644 index 65a9b7859..000000000 --- a/embassy-executor/src/raw/run_queue_atomics.rs +++ /dev/null @@ -1,129 +0,0 @@ -use core::ptr::{addr_of_mut, NonNull}; - -use cordyceps::sorted_list::Links; -#[cfg(feature = "edf-scheduler")] -use cordyceps::SortedList; -use cordyceps::{Linked, TransferStack}; - -use super::{TaskHeader, TaskRef}; - -/// Use `cordyceps::sorted_list::Links` as the singly linked list -/// for RunQueueItems. -pub(crate) type RunQueueItem = Links; - -/// Implements the `Linked` trait, allowing for singly linked list usage -/// of any of cordyceps' `TransferStack` (used for the atomic runqueue), -/// `SortedList` (used with the DRS scheduler), or `Stack`, which is -/// popped atomically from the `TransferStack`. -unsafe impl Linked> for TaskHeader { - type Handle = TaskRef; - - // Convert a TaskRef into a TaskHeader ptr - fn into_ptr(r: TaskRef) -> NonNull { - r.ptr - } - - // Convert a TaskHeader into a TaskRef - unsafe fn from_ptr(ptr: NonNull) -> TaskRef { - TaskRef { ptr } - } - - // Given a pointer to a TaskHeader, obtain a pointer to the Links structure, - // which can be used to traverse to other TaskHeader nodes in the linked list - unsafe fn links(ptr: NonNull) -> NonNull> { - let ptr: *mut TaskHeader = ptr.as_ptr(); - NonNull::new_unchecked(addr_of_mut!((*ptr).run_queue_item)) - } -} - -/// Atomic task queue using a very, very simple lock-free linked-list queue: -/// -/// To enqueue a task, task.next is set to the old head, and head is atomically set to task. -/// -/// Dequeuing is done in batches: the queue is emptied by atomically replacing head with -/// null. Then the batch is iterated following the next pointers until null is reached. -/// -/// Note that batches will be iterated in the reverse order as they were enqueued. This is OK -/// for our purposes: it can't create fairness problems since the next batch won't run until the -/// current batch is completely processed, so even if a task enqueues itself instantly (for example -/// by waking its own waker) can't prevent other tasks from running. -pub(crate) struct RunQueue { - stack: TransferStack, -} - -impl RunQueue { - pub const fn new() -> Self { - Self { - stack: TransferStack::new(), - } - } - - /// Enqueues an item. Returns true if the queue was empty. - /// - /// # Safety - /// - /// `item` must NOT be already enqueued in any queue. - #[inline(always)] - pub(crate) unsafe fn enqueue(&self, task: TaskRef, _: super::state::Token) -> bool { - self.stack.push_was_empty(task) - } - - /// # Standard atomic runqueue - /// - /// Empty the queue, then call `on_task` for each task that was in the queue. - /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue - /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. - #[cfg(not(feature = "edf-scheduler"))] - pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { - let taken = self.stack.take_all(); - for taskref in taken { - taskref.header().state.run_dequeue(); - on_task(taskref); - } - } - - /// # Earliest Deadline First Scheduler - /// - /// This algorithm will loop until all enqueued tasks are processed. - /// - /// Before polling a task, all currently enqueued tasks will be popped from the - /// runqueue, and will be added to the working `sorted` list, a linked-list that - /// sorts tasks by their deadline, with nearest deadline items in the front, and - /// furthest deadline items in the back. - /// - /// After popping and sorting all pending tasks, the SOONEST task will be popped - /// from the front of the queue, and polled by calling `on_task` on it. - /// - /// This process will repeat until the local `sorted` queue AND the global - /// runqueue are both empty, at which point this function will return. - #[cfg(feature = "edf-scheduler")] - pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { - // SAFETY: `deadline` can only be set through the `Deadline` interface, which - // only allows access to this value while the given task is being polled. - // This acts as mutual exclusion for access. - let mut sorted = - SortedList::::new_with_cmp(|lhs, rhs| unsafe { lhs.deadline.get().cmp(&rhs.deadline.get()) }); - - loop { - // For each loop, grab any newly pended items - let taken = self.stack.take_all(); - - // Sort these into the list - this is potentially expensive! We do an - // insertion sort of new items, which iterates the linked list. - // - // Something on the order of `O(n * m)`, where `n` is the number - // of new tasks, and `m` is the number of already pending tasks. - sorted.extend(taken); - - // Pop the task with the SOONEST deadline. If there are no tasks - // pending, then we are done. - let Some(taskref) = sorted.pop_front() else { - return; - }; - - // We got one task, mark it as dequeued, and process the task. - taskref.header().state.run_dequeue(); - on_task(taskref); - } - } -} diff --git a/embassy-executor/src/raw/run_queue_critical_section.rs b/embassy-executor/src/raw/run_queue_critical_section.rs deleted file mode 100644 index 86c4085ed..000000000 --- a/embassy-executor/src/raw/run_queue_critical_section.rs +++ /dev/null @@ -1,74 +0,0 @@ -use core::cell::Cell; - -use critical_section::{CriticalSection, Mutex}; - -use super::TaskRef; - -pub(crate) struct RunQueueItem { - next: Mutex>>, -} - -impl RunQueueItem { - pub const fn new() -> Self { - Self { - next: Mutex::new(Cell::new(None)), - } - } -} - -/// Atomic task queue using a very, very simple lock-free linked-list queue: -/// -/// To enqueue a task, task.next is set to the old head, and head is atomically set to task. -/// -/// Dequeuing is done in batches: the queue is emptied by atomically replacing head with -/// null. Then the batch is iterated following the next pointers until null is reached. -/// -/// Note that batches will be iterated in the reverse order as they were enqueued. This is OK -/// for our purposes: it can't create fairness problems since the next batch won't run until the -/// current batch is completely processed, so even if a task enqueues itself instantly (for example -/// by waking its own waker) can't prevent other tasks from running. -pub(crate) struct RunQueue { - head: Mutex>>, -} - -impl RunQueue { - pub const fn new() -> Self { - Self { - head: Mutex::new(Cell::new(None)), - } - } - - /// Enqueues an item. Returns true if the queue was empty. - /// - /// # Safety - /// - /// `item` must NOT be already enqueued in any queue. - #[inline(always)] - pub(crate) unsafe fn enqueue(&self, task: TaskRef, cs: CriticalSection<'_>) -> bool { - let prev = self.head.borrow(cs).replace(Some(task)); - task.header().run_queue_item.next.borrow(cs).set(prev); - - prev.is_none() - } - - /// Empty the queue, then call `on_task` for each task that was in the queue. - /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue - /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. - pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { - // Atomically empty the queue. - let mut next = critical_section::with(|cs| self.head.borrow(cs).take()); - - // Iterate the linked list of tasks that were previously in the queue. - while let Some(task) = next { - // If the task re-enqueues itself, the `next` pointer will get overwritten. - // Therefore, first read the next pointer, and only then process the task. - - critical_section::with(|cs| { - next = task.header().run_queue_item.next.borrow(cs).get(); - task.header().state.run_dequeue(cs); - }); - - on_task(task); - } - } -} -- cgit From d88ea8dd2adefba42489173d5119e888ffa73f07 Mon Sep 17 00:00:00 2001 From: James Munns Date: Wed, 4 Jun 2025 12:22:32 +0200 Subject: Update with cordyceps changes --- embassy-executor/Cargo.toml | 2 +- embassy-executor/src/raw/run_queue.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 34468e4f9..0ea18acbc 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -81,7 +81,7 @@ avr-device = { version = "0.7.0", optional = true } # version = "0.3.3" # todo: update after https://github.com/hawkw/mycelium/pull/537 is merged git = "https://github.com/hawkw/mycelium" -rev = "86c428eecfd37ee24dd81f14c4a9f5c8ecefcf17" +rev = "e21f9756e7d787a023f2ef1bc7f2159cc7dd26e0" # Note: this is ONLY a dependency when the target does NOT have atomics [target.'cfg(not(target_has_atomic="ptr"))'.dependencies.mutex] diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index f630041e0..c6c7d7109 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs @@ -9,7 +9,7 @@ use cordyceps::SortedList; type TransferStack = cordyceps::TransferStack; #[cfg(not(target_has_atomic = "ptr"))] -type TransferStack = cordyceps::TransferStack; +type TransferStack = cordyceps::MutexTransferStack; use super::{TaskHeader, TaskRef}; -- cgit From db063945e76a9b62672377ed71e6e833a295a054 Mon Sep 17 00:00:00 2001 From: James Munns Date: Wed, 2 Jul 2025 13:48:32 +0200 Subject: Inline the "MutexTransferStack" impl as it is unclear whether it will be merged upstream --- embassy-executor/Cargo.toml | 6 ++---- embassy-executor/src/raw/run_queue.rs | 31 ++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 0ea18acbc..01c028704 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -78,10 +78,8 @@ avr-device = { version = "0.7.0", optional = true } [dependencies.cordyceps] -# version = "0.3.3" -# todo: update after https://github.com/hawkw/mycelium/pull/537 is merged -git = "https://github.com/hawkw/mycelium" -rev = "e21f9756e7d787a023f2ef1bc7f2159cc7dd26e0" +version = "0.3.4" +features = ["no-cache-pad"] # Note: this is ONLY a dependency when the target does NOT have atomics [target.'cfg(not(target_has_atomic="ptr"))'.dependencies.mutex] diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index c6c7d7109..5fd703aad 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs @@ -9,7 +9,7 @@ use cordyceps::SortedList; type TransferStack = cordyceps::TransferStack; #[cfg(not(target_has_atomic = "ptr"))] -type TransferStack = cordyceps::MutexTransferStack; +type TransferStack = MutexTransferStack; use super::{TaskHeader, TaskRef}; @@ -149,3 +149,32 @@ fn run_dequeue(taskref: &TaskRef) { taskref.header().state.run_dequeue(cs); }) } + +/// A wrapper type that acts like TransferStack by wrapping a normal Stack in a CS mutex +#[cfg(not(target_has_atomic="ptr"))] +struct MutexTransferStack>> { + inner: mutex::BlockingMutex>, +} + +#[cfg(not(target_has_atomic="ptr"))] +impl>> MutexTransferStack { + const fn new() -> Self { + Self { + inner: mutex::BlockingMutex::new(cordyceps::Stack::new()), + } + } + + fn push_was_empty(&self, item: T::Handle) -> bool { + self.inner.with_lock(|stack| { + let is_empty = stack.is_empty(); + stack.push(item); + is_empty + }) + } + + fn take_all(&self) -> cordyceps::Stack { + self.inner.with_lock(|stack| { + stack.take_all() + }) + } +} -- cgit From cf171ad6d9c0a7487400beb9e4a436e5c1b64e19 Mon Sep 17 00:00:00 2001 From: James Munns Date: Thu, 3 Jul 2025 09:11:32 +0200 Subject: fmt --- embassy-executor/src/raw/run_queue.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index 5fd703aad..b4b22819f 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs @@ -151,12 +151,12 @@ fn run_dequeue(taskref: &TaskRef) { } /// A wrapper type that acts like TransferStack by wrapping a normal Stack in a CS mutex -#[cfg(not(target_has_atomic="ptr"))] +#[cfg(not(target_has_atomic = "ptr"))] struct MutexTransferStack>> { inner: mutex::BlockingMutex>, } -#[cfg(not(target_has_atomic="ptr"))] +#[cfg(not(target_has_atomic = "ptr"))] impl>> MutexTransferStack { const fn new() -> Self { Self { @@ -173,8 +173,6 @@ impl>> MutexTransferStack { } fn take_all(&self) -> cordyceps::Stack { - self.inner.with_lock(|stack| { - stack.take_all() - }) + self.inner.with_lock(|stack| stack.take_all()) } } -- cgit From 20b56b0fe0570f0d1e8c61d23d067627a4dfc165 Mon Sep 17 00:00:00 2001 From: James Munns Date: Tue, 15 Jul 2025 13:33:51 +0200 Subject: Update to use critical-section::Mutex instead of mutex::BlockingMutex This allows the scheduler to better collaborate with existing critical sections --- embassy-executor/Cargo.toml | 4 ---- embassy-executor/src/raw/run_queue.rs | 28 +++++++++++++++++----------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 01c028704..290e67bce 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -81,10 +81,6 @@ avr-device = { version = "0.7.0", optional = true } version = "0.3.4" features = ["no-cache-pad"] -# Note: this is ONLY a dependency when the target does NOT have atomics -[target.'cfg(not(target_has_atomic="ptr"))'.dependencies.mutex] -version = "1.0" - [dev-dependencies] critical-section = { version = "1.1", features = ["std"] } trybuild = "1.0" diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index b4b22819f..9acb9dd28 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs @@ -70,8 +70,12 @@ impl RunQueue { /// /// `item` must NOT be already enqueued in any queue. #[inline(always)] - pub(crate) unsafe fn enqueue(&self, task: TaskRef, _: super::state::Token) -> bool { - self.stack.push_was_empty(task) + pub(crate) unsafe fn enqueue(&self, task: TaskRef, _tok: super::state::Token) -> bool { + self.stack.push_was_empty( + task, + #[cfg(not(target_has_atomic = "ptr"))] + _tok, + ) } /// # Standard atomic runqueue @@ -153,26 +157,28 @@ fn run_dequeue(taskref: &TaskRef) { /// A wrapper type that acts like TransferStack by wrapping a normal Stack in a CS mutex #[cfg(not(target_has_atomic = "ptr"))] struct MutexTransferStack>> { - inner: mutex::BlockingMutex>, + inner: critical_section::Mutex>>, } #[cfg(not(target_has_atomic = "ptr"))] impl>> MutexTransferStack { const fn new() -> Self { Self { - inner: mutex::BlockingMutex::new(cordyceps::Stack::new()), + inner: critical_section::Mutex::new(core::cell::RefCell::new(cordyceps::Stack::new())), } } - fn push_was_empty(&self, item: T::Handle) -> bool { - self.inner.with_lock(|stack| { - let is_empty = stack.is_empty(); - stack.push(item); - is_empty - }) + fn push_was_empty(&self, item: T::Handle, token: super::state::Token) -> bool { + let mut guard = self.inner.borrow_ref_mut(token); + let is_empty = guard.is_empty(); + guard.push(item); + is_empty } fn take_all(&self) -> cordyceps::Stack { - self.inner.with_lock(|stack| stack.take_all()) + critical_section::with(|cs| { + let mut guard = self.inner.borrow_ref_mut(cs); + guard.take_all() + }) } } -- cgit From 38e5e2e9ceb9a34badfdfc57477f0dba23c64ced Mon Sep 17 00:00:00 2001 From: James Munns Date: Tue, 15 Jul 2025 14:51:08 +0200 Subject: Replace use of RefCell with UnsafeCell --- embassy-executor/src/raw/run_queue.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index 9acb9dd28..97d26a18a 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs @@ -157,19 +157,26 @@ fn run_dequeue(taskref: &TaskRef) { /// A wrapper type that acts like TransferStack by wrapping a normal Stack in a CS mutex #[cfg(not(target_has_atomic = "ptr"))] struct MutexTransferStack>> { - inner: critical_section::Mutex>>, + inner: critical_section::Mutex>>, } #[cfg(not(target_has_atomic = "ptr"))] impl>> MutexTransferStack { const fn new() -> Self { Self { - inner: critical_section::Mutex::new(core::cell::RefCell::new(cordyceps::Stack::new())), + inner: critical_section::Mutex::new(core::cell::UnsafeCell::new(cordyceps::Stack::new())), } } + /// Push an item to the transfer stack, returning whether the stack was previously empty fn push_was_empty(&self, item: T::Handle, token: super::state::Token) -> bool { - let mut guard = self.inner.borrow_ref_mut(token); + /// SAFETY: The critical-section mutex guarantees that there is no *concurrent* access + /// for the lifetime of the token, but does NOT protect against re-entrant access. + /// However, we never *return* the reference, nor do we recurse (or call another method + /// like `take_all`) that could ever allow for re-entrant aliasing. Therefore, the + /// presence of the critical section is sufficient to guarantee exclusive access to + /// the `inner` field for the purposes of this function + let mut guard = unsafe { &mut *self.inner.borrow(token).get() }; let is_empty = guard.is_empty(); guard.push(item); is_empty @@ -177,7 +184,13 @@ impl>> MutexTransferStack { fn take_all(&self) -> cordyceps::Stack { critical_section::with(|cs| { - let mut guard = self.inner.borrow_ref_mut(cs); + /// SAFETY: The critical-section mutex guarantees that there is no *concurrent* access + /// for the lifetime of the token, but does NOT protect against re-entrant access. + /// However, we never *return* the reference, nor do we recurse (or call another method + /// like `push_was_empty`) that could ever allow for re-entrant aliasing. Therefore, the + /// presence of the critical section is sufficient to guarantee exclusive access to + /// the `inner` field for the purposes of this function + let mut guard = unsafe { &mut *self.inner.borrow(cs).get() }; guard.take_all() }) } -- cgit From 4479f5bbfce9002b965f9e3e189cdd5c61096eff Mon Sep 17 00:00:00 2001 From: James Munns Date: Tue, 15 Jul 2025 14:54:20 +0200 Subject: Regular comments not doc comments --- embassy-executor/src/raw/run_queue.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index 97d26a18a..1eb5775d8 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs @@ -170,12 +170,12 @@ impl>> MutexTransferStack { /// Push an item to the transfer stack, returning whether the stack was previously empty fn push_was_empty(&self, item: T::Handle, token: super::state::Token) -> bool { - /// SAFETY: The critical-section mutex guarantees that there is no *concurrent* access - /// for the lifetime of the token, but does NOT protect against re-entrant access. - /// However, we never *return* the reference, nor do we recurse (or call another method - /// like `take_all`) that could ever allow for re-entrant aliasing. Therefore, the - /// presence of the critical section is sufficient to guarantee exclusive access to - /// the `inner` field for the purposes of this function + // SAFETY: The critical-section mutex guarantees that there is no *concurrent* access + // for the lifetime of the token, but does NOT protect against re-entrant access. + // However, we never *return* the reference, nor do we recurse (or call another method + // like `take_all`) that could ever allow for re-entrant aliasing. Therefore, the + // presence of the critical section is sufficient to guarantee exclusive access to + // the `inner` field for the purposes of this function. let mut guard = unsafe { &mut *self.inner.borrow(token).get() }; let is_empty = guard.is_empty(); guard.push(item); @@ -184,12 +184,12 @@ impl>> MutexTransferStack { fn take_all(&self) -> cordyceps::Stack { critical_section::with(|cs| { - /// SAFETY: The critical-section mutex guarantees that there is no *concurrent* access - /// for the lifetime of the token, but does NOT protect against re-entrant access. - /// However, we never *return* the reference, nor do we recurse (or call another method - /// like `push_was_empty`) that could ever allow for re-entrant aliasing. Therefore, the - /// presence of the critical section is sufficient to guarantee exclusive access to - /// the `inner` field for the purposes of this function + // SAFETY: The critical-section mutex guarantees that there is no *concurrent* access + // for the lifetime of the token, but does NOT protect against re-entrant access. + // However, we never *return* the reference, nor do we recurse (or call another method + // like `push_was_empty`) that could ever allow for re-entrant aliasing. Therefore, the + // presence of the critical section is sufficient to guarantee exclusive access to + // the `inner` field for the purposes of this function. let mut guard = unsafe { &mut *self.inner.borrow(cs).get() }; guard.take_all() }) -- cgit From b5c9e721009fd4331cdc1ce58a07698eb54f2959 Mon Sep 17 00:00:00 2001 From: James Munns Date: Tue, 15 Jul 2025 14:58:41 +0200 Subject: Rename, remove excess mut --- embassy-executor/src/raw/run_queue.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index 1eb5775d8..97060f4b9 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs @@ -176,9 +176,9 @@ impl>> MutexTransferStack { // like `take_all`) that could ever allow for re-entrant aliasing. Therefore, the // presence of the critical section is sufficient to guarantee exclusive access to // the `inner` field for the purposes of this function. - let mut guard = unsafe { &mut *self.inner.borrow(token).get() }; - let is_empty = guard.is_empty(); - guard.push(item); + let inner = unsafe { &mut *self.inner.borrow(token).get() }; + let is_empty = inner.is_empty(); + inner.push(item); is_empty } @@ -190,8 +190,8 @@ impl>> MutexTransferStack { // like `push_was_empty`) that could ever allow for re-entrant aliasing. Therefore, the // presence of the critical section is sufficient to guarantee exclusive access to // the `inner` field for the purposes of this function. - let mut guard = unsafe { &mut *self.inner.borrow(cs).get() }; - guard.take_all() + let inner = unsafe { &mut *self.inner.borrow(cs).get() }; + inner.take_all() }) } } -- cgit From 3f606b28f3b32e9e3b9a9f136eeef52828a78512 Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Tue, 15 Jul 2025 13:40:30 +0200 Subject: Change deadline to use internal atomics --- embassy-executor/src/raw/deadline.rs | 101 +++++++++++++++++----------------- embassy-executor/src/raw/mod.rs | 4 +- embassy-executor/src/raw/run_queue.rs | 8 +-- 3 files changed, 55 insertions(+), 58 deletions(-) diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs index 0fb22a7ce..a61852612 100644 --- a/embassy-executor/src/raw/deadline.rs +++ b/embassy-executor/src/raw/deadline.rs @@ -1,15 +1,41 @@ use core::future::{poll_fn, Future}; +use core::sync::atomic::{AtomicU32, Ordering}; use core::task::Poll; /// A type for interacting with the deadline of the current task /// /// Requires the `edf-scheduler` feature pub struct Deadline { - /// Deadline value in ticks, same time base and ticks as `embassy-time` - pub instant_ticks: u64, + instant_ticks_hi: AtomicU32, + instant_ticks_lo: AtomicU32, } impl Deadline { + pub(crate) const fn new(instant_ticks: u64) -> Self { + Self { + instant_ticks_hi: AtomicU32::new((instant_ticks >> 32) as u32), + instant_ticks_lo: AtomicU32::new(instant_ticks as u32), + } + } + + pub(crate) const fn new_unset() -> Self { + Self::new(Self::UNSET_DEADLINE_TICKS) + } + + pub(crate) fn set(&self, instant_ticks: u64) { + self.instant_ticks_hi + .store((instant_ticks >> 32) as u32, Ordering::Relaxed); + self.instant_ticks_lo.store(instant_ticks as u32, Ordering::Relaxed); + } + + /// Deadline value in ticks, same time base and ticks as `embassy-time` + pub fn instant_ticks(&self) -> u64 { + let hi = self.instant_ticks_hi.load(Ordering::Relaxed) as u64; + let lo = self.instant_ticks_lo.load(Ordering::Relaxed) as u64; + + (hi << 32) | lo + } + /// Sentinel value representing an "unset" deadline, which has lower priority /// than any other set deadline value pub const UNSET_DEADLINE_TICKS: u64 = u64::MAX; @@ -17,7 +43,7 @@ impl Deadline { /// Does the given Deadline represent an "unset" deadline? #[inline] pub fn is_unset(&self) -> bool { - self.instant_ticks == Self::UNSET_DEADLINE_TICKS + self.instant_ticks() == Self::UNSET_DEADLINE_TICKS } /// Set the current task's deadline at exactly `instant_ticks` @@ -32,11 +58,7 @@ impl Deadline { pub fn set_current_task_deadline(instant_ticks: u64) -> impl Future { poll_fn(move |cx| { let task = super::task_from_waker(cx.waker()); - // SAFETY: A task can only modify its own deadline, while the task is being - // polled, meaning that there cannot be concurrent access to the deadline. - unsafe { - task.header().deadline.set(instant_ticks); - } + task.header().deadline.set(instant_ticks); Poll::Ready(()) }) } @@ -61,14 +83,9 @@ impl Deadline { // reasons later. let deadline = now.saturating_add(duration_ticks); - // SAFETY: A task can only modify its own deadline, while the task is being - // polled, meaning that there cannot be concurrent access to the deadline. - unsafe { - task.header().deadline.set(deadline); - } - Poll::Ready(Deadline { - instant_ticks: deadline, - }) + task.header().deadline.set(deadline); + + Poll::Ready(Deadline::new(deadline)) }) } @@ -90,24 +107,18 @@ impl Deadline { poll_fn(move |cx| { let task = super::task_from_waker(cx.waker()); - // SAFETY: A task can only modify its own deadline, while the task is being - // polled, meaning that there cannot be concurrent access to the deadline. - unsafe { - // Get the last value - let last = task.header().deadline.get(); + // Get the last value + let last = task.header().deadline.instant_ticks(); - // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave - // it for now, we can probably make this wrapping_add for performance - // reasons later. - let deadline = last.saturating_add(increment_ticks); + // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave + // it for now, we can probably make this wrapping_add for performance + // reasons later. + let deadline = last.saturating_add(increment_ticks); - // Store the new value - task.header().deadline.set(deadline); + // Store the new value + task.header().deadline.set(deadline); - Poll::Ready(Deadline { - instant_ticks: deadline, - }) - } + Poll::Ready(Deadline::new(deadline)) }) } @@ -119,12 +130,8 @@ impl Deadline { poll_fn(move |cx| { let task = super::task_from_waker(cx.waker()); - // SAFETY: A task can only modify its own deadline, while the task is being - // polled, meaning that there cannot be concurrent access to the deadline. - let deadline = unsafe { task.header().deadline.get() }; - Poll::Ready(Self { - instant_ticks: deadline, - }) + let deadline = task.header().deadline.instant_ticks(); + Poll::Ready(Self::new(deadline)) }) } @@ -137,20 +144,12 @@ impl Deadline { poll_fn(move |cx| { let task = super::task_from_waker(cx.waker()); - // SAFETY: A task can only modify its own deadline, while the task is being - // polled, meaning that there cannot be concurrent access to the deadline. - let deadline = unsafe { - // get the old value - let d = task.header().deadline.get(); - // Store the default value - task.header().deadline.set(Self::UNSET_DEADLINE_TICKS); - // return the old value - d - }; - - Poll::Ready(Self { - instant_ticks: deadline, - }) + // get the old value + let deadline = task.header().deadline.instant_ticks(); + // Store the default value + task.header().deadline.set(Self::UNSET_DEADLINE_TICKS); + + Poll::Ready(Self::new(deadline)) }) } } diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index cc43690cb..be2c5ee28 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -106,7 +106,7 @@ pub(crate) struct TaskHeader { /// Earliest Deadline First scheduler Deadline. This field should not be accessed /// outside the context of the task itself as it being polled by the executor. #[cfg(feature = "edf-scheduler")] - pub(crate) deadline: SyncUnsafeCell, + pub(crate) deadline: Deadline, pub(crate) executor: AtomicPtr, poll_fn: SyncUnsafeCell>, @@ -215,7 +215,7 @@ impl TaskStorage { // NOTE: The deadline is set to zero to allow the initializer to reside in `.bss`. This // will be lazily initalized in `initialize_impl` #[cfg(feature = "edf-scheduler")] - deadline: SyncUnsafeCell::new(0u64), + deadline: Deadline::new_unset(), executor: AtomicPtr::new(core::ptr::null_mut()), // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss` poll_fn: SyncUnsafeCell::new(None), diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index 97060f4b9..e8a046a48 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs @@ -108,11 +108,9 @@ impl RunQueue { /// runqueue are both empty, at which point this function will return. #[cfg(feature = "edf-scheduler")] pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { - // SAFETY: `deadline` can only be set through the `Deadline` interface, which - // only allows access to this value while the given task is being polled. - // This acts as mutual exclusion for access. - let mut sorted = - SortedList::::new_with_cmp(|lhs, rhs| unsafe { lhs.deadline.get().cmp(&rhs.deadline.get()) }); + let mut sorted = SortedList::::new_with_cmp(|lhs, rhs| { + lhs.deadline.instant_ticks().cmp(&rhs.deadline.instant_ticks()) + }); loop { // For each loop, grab any newly pended items -- cgit From d6d4df1c768f8ae43ad1339b74d351f4cbad0386 Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Tue, 15 Jul 2025 14:30:02 +0200 Subject: Add some docs --- embassy-executor/src/raw/deadline.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs index a61852612..cbb379b82 100644 --- a/embassy-executor/src/raw/deadline.rs +++ b/embassy-executor/src/raw/deadline.rs @@ -4,7 +4,11 @@ use core::task::Poll; /// A type for interacting with the deadline of the current task /// -/// Requires the `edf-scheduler` feature +/// Requires the `edf-scheduler` feature. +/// +/// Note: Interacting with the deadline should be done locally in a task. +/// In theory you could try to set or read the deadline from another task, +/// but that will result in weird (though not unsound) behavior. pub struct Deadline { instant_ticks_hi: AtomicU32, instant_ticks_lo: AtomicU32, -- cgit From 52d178560501a464dba67da89a1570ae9a2cf66c Mon Sep 17 00:00:00 2001 From: diondokter Date: Fri, 29 Aug 2025 14:36:17 +0200 Subject: Introduce metadata-deadline and let the EDF scheduler use it --- embassy-executor/Cargo.toml | 4 +++- embassy-executor/src/metadata.rs | 13 +++++++++++++ embassy-executor/src/raw/deadline.rs | 18 +++++++++--------- embassy-executor/src/raw/mod.rs | 19 +++++++------------ embassy-executor/src/raw/run_queue.rs | 5 ++++- 5 files changed, 36 insertions(+), 23 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 290e67bce..2de36d22d 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -118,6 +118,8 @@ arch-spin = ["_arch"] ## Enable the `name` field in task metadata. metadata-name = ["embassy-executor-macros/metadata-name"] +## Enable the `deadline` field in task metadata. +metadata-deadline = [] #! ### Executor @@ -133,4 +135,4 @@ _any_trace = [] ## Enable "Earliest Deadline First" Scheduler, using soft-realtime "deadlines" to prioritize ## tasks based on the remaining time before their deadline. Adds some overhead. -edf-scheduler = ["dep:embassy-time-driver"] +edf-scheduler = ["dep:embassy-time-driver", "metadata-deadline"] diff --git a/embassy-executor/src/metadata.rs b/embassy-executor/src/metadata.rs index f92c9b37c..fd8095629 100644 --- a/embassy-executor/src/metadata.rs +++ b/embassy-executor/src/metadata.rs @@ -12,6 +12,8 @@ use crate::raw; pub struct Metadata { #[cfg(feature = "metadata-name")] name: Mutex>>, + #[cfg(feature = "metadata-deadline")] + deadline: raw::Deadline, } impl Metadata { @@ -19,6 +21,10 @@ impl Metadata { Self { #[cfg(feature = "metadata-name")] name: Mutex::new(Cell::new(None)), + // NOTE: The deadline is set to zero to allow the initializer to reside in `.bss`. This + // will be lazily initalized in `initialize_impl` + #[cfg(feature = "metadata-deadline")] + deadline: raw::Deadline::new_unset(), } } @@ -52,4 +58,11 @@ impl Metadata { pub fn set_name(&self, name: &'static str) { critical_section::with(|cs| self.name.borrow(cs).set(Some(name))) } + + /// Earliest Deadline First scheduler Deadline. This field should not be accessed + /// outside the context of the task itself as it being polled by the executor. + #[cfg(feature = "metadata-deadline")] + pub fn deadline(&self) -> &raw::Deadline { + &self.deadline + } } diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs index cbb379b82..5b585195d 100644 --- a/embassy-executor/src/raw/deadline.rs +++ b/embassy-executor/src/raw/deadline.rs @@ -62,7 +62,7 @@ impl Deadline { pub fn set_current_task_deadline(instant_ticks: u64) -> impl Future { poll_fn(move |cx| { let task = super::task_from_waker(cx.waker()); - task.header().deadline.set(instant_ticks); + task.header().metadata.deadline().set(instant_ticks); Poll::Ready(()) }) } @@ -87,7 +87,7 @@ impl Deadline { // reasons later. let deadline = now.saturating_add(duration_ticks); - task.header().deadline.set(deadline); + task.header().metadata.deadline().set(deadline); Poll::Ready(Deadline::new(deadline)) }) @@ -109,10 +109,10 @@ impl Deadline { #[must_use = "Setting deadline must be polled to be effective"] pub fn increment_current_task_deadline(increment_ticks: u64) -> impl Future { poll_fn(move |cx| { - let task = super::task_from_waker(cx.waker()); + let task_header = super::task_from_waker(cx.waker()).header(); // Get the last value - let last = task.header().deadline.instant_ticks(); + let last = task_header.metadata.deadline().instant_ticks(); // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave // it for now, we can probably make this wrapping_add for performance @@ -120,7 +120,7 @@ impl Deadline { let deadline = last.saturating_add(increment_ticks); // Store the new value - task.header().deadline.set(deadline); + task_header.metadata.deadline().set(deadline); Poll::Ready(Deadline::new(deadline)) }) @@ -134,7 +134,7 @@ impl Deadline { poll_fn(move |cx| { let task = super::task_from_waker(cx.waker()); - let deadline = task.header().deadline.instant_ticks(); + let deadline = task.header().metadata.deadline().instant_ticks(); Poll::Ready(Self::new(deadline)) }) } @@ -146,12 +146,12 @@ impl Deadline { #[must_use = "Clearing deadline must be polled to be effective"] pub fn clear_current_task_deadline() -> impl Future { poll_fn(move |cx| { - let task = super::task_from_waker(cx.waker()); + let task_header = super::task_from_waker(cx.waker()).header(); // get the old value - let deadline = task.header().deadline.instant_ticks(); + let deadline = task_header.metadata.deadline().instant_ticks(); // Store the default value - task.header().deadline.set(Self::UNSET_DEADLINE_TICKS); + task_header.metadata.deadline().set(Self::UNSET_DEADLINE_TICKS); Poll::Ready(Self::new(deadline)) }) diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index be2c5ee28..f93bfdef9 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -26,7 +26,7 @@ pub(crate) mod util; #[cfg_attr(feature = "turbowakers", path = "waker_turbo.rs")] mod waker; -#[cfg(feature = "edf-scheduler")] +#[cfg(feature = "metadata-deadline")] mod deadline; use core::future::Future; @@ -43,7 +43,7 @@ use embassy_executor_timer_queue::TimerQueueItem; #[cfg(feature = "arch-avr")] use portable_atomic::AtomicPtr; -#[cfg(feature = "edf-scheduler")] +#[cfg(feature = "metadata-deadline")] pub use deadline::Deadline; #[cfg(feature = "arch-avr")] use portable_atomic::AtomicPtr; @@ -103,11 +103,6 @@ pub(crate) struct TaskHeader { pub(crate) state: State, pub(crate) run_queue_item: RunQueueItem, - /// Earliest Deadline First scheduler Deadline. This field should not be accessed - /// outside the context of the task itself as it being polled by the executor. - #[cfg(feature = "edf-scheduler")] - pub(crate) deadline: Deadline, - pub(crate) executor: AtomicPtr, poll_fn: SyncUnsafeCell>, @@ -212,10 +207,6 @@ impl TaskStorage { raw: TaskHeader { state: State::new(), run_queue_item: RunQueueItem::new(), - // NOTE: The deadline is set to zero to allow the initializer to reside in `.bss`. This - // will be lazily initalized in `initialize_impl` - #[cfg(feature = "edf-scheduler")] - deadline: Deadline::new_unset(), executor: AtomicPtr::new(core::ptr::null_mut()), // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss` poll_fn: SyncUnsafeCell::new(None), @@ -315,7 +306,11 @@ impl AvailableTask { // By default, deadlines are set to the maximum value, so that any task WITH // a set deadline will ALWAYS be scheduled BEFORE a task WITHOUT a set deadline #[cfg(feature = "edf-scheduler")] - self.task.raw.deadline.set(deadline::Deadline::UNSET_DEADLINE_TICKS); + self.task + .raw + .metadata + .deadline() + .set(deadline::Deadline::UNSET_DEADLINE_TICKS); let task = TaskRef::new(self.task); diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index e8a046a48..978ca082a 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs @@ -109,7 +109,10 @@ impl RunQueue { #[cfg(feature = "edf-scheduler")] pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { let mut sorted = SortedList::::new_with_cmp(|lhs, rhs| { - lhs.deadline.instant_ticks().cmp(&rhs.deadline.instant_ticks()) + lhs.metadata + .deadline() + .instant_ticks() + .cmp(&rhs.metadata.deadline().instant_ticks()) }); loop { -- cgit From 99209accb5b37f236691e060474bfc4823d2e123 Mon Sep 17 00:00:00 2001 From: diondokter Date: Fri, 29 Aug 2025 14:44:32 +0200 Subject: Add edf example to CI and fix the example --- ci.sh | 1 + examples/nrf52840-edf/Cargo.toml | 12 ++++++------ examples/nrf52840-edf/src/bin/basic.rs | 3 ++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ci.sh b/ci.sh index 50fb3e13d..a25097690 100755 --- a/ci.sh +++ b/ci.sh @@ -239,6 +239,7 @@ cargo batch \ --- build --release --manifest-path docs/examples/layer-by-layer/blinky-async/Cargo.toml --target thumbv7em-none-eabi \ --- build --release --manifest-path examples/nrf52810/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/nrf52810 \ --- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/nrf52840 \ + --- build --release --manifest-path examples/nrf52840-edf/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/nrf52840-edf \ --- build --release --manifest-path examples/nrf5340/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf5340 \ --- build --release --manifest-path examples/nrf54l15/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf54l15 \ --- build --release --manifest-path examples/nrf9160/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf9160 \ diff --git a/examples/nrf52840-edf/Cargo.toml b/examples/nrf52840-edf/Cargo.toml index c7147d1af..9efdff7c4 100644 --- a/examples/nrf52840-edf/Cargo.toml +++ b/examples/nrf52840-edf/Cargo.toml @@ -6,16 +6,16 @@ license = "MIT OR Apache-2.0" [dependencies] # NOTE: "edf-scheduler" feature is enabled -embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "edf-scheduler"] } -embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "edf-scheduler"] } +embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } -defmt = "0.3" -defmt-rtt = "0.4" +defmt = "1.0.1" +defmt-rtt = "1.0.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } +panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 diff --git a/examples/nrf52840-edf/src/bin/basic.rs b/examples/nrf52840-edf/src/bin/basic.rs index c270c67b9..8a8e46449 100644 --- a/examples/nrf52840-edf/src/bin/basic.rs +++ b/examples/nrf52840-edf/src/bin/basic.rs @@ -14,6 +14,7 @@ use core::sync::atomic::{compiler_fence, Ordering}; +use defmt::unwrap; use embassy_executor::raw::Deadline; use embassy_executor::Spawner; use embassy_time::{Duration, Instant, Timer}; @@ -57,7 +58,7 @@ async fn main(spawner: Spawner) { // Spawn all of our load workers! for i in 0..tasks { - spawner.must_spawn(load_task(i, work_time_ticks, time_window)); + spawner.spawn(unwrap!(load_task(i, work_time_ticks, time_window))); } // Let all the tasks spin up -- cgit From a853bbe2a4dbb64c2e691ddcb258b2530d2b5af5 Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Fri, 29 Aug 2025 15:16:31 +0200 Subject: Happy CI :) --- embassy-executor/CHANGELOG.md | 1 + embassy-executor/src/raw/mod.rs | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index dd462608b..03d60208e 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added new metadata API for tasks. - Main task automatically gets a name of `main` when the `metadata-name` feature is enabled. - Upgraded rtos-trace +- Added optional "earliest deadline first" EDF scheduling ## 0.9.1 - 2025-08-31 diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index f93bfdef9..86ee86842 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -39,12 +39,9 @@ use core::sync::atomic::AtomicPtr; use core::sync::atomic::Ordering; use core::task::{Context, Poll, Waker}; -use embassy_executor_timer_queue::TimerQueueItem; -#[cfg(feature = "arch-avr")] -use portable_atomic::AtomicPtr; - #[cfg(feature = "metadata-deadline")] pub use deadline::Deadline; +use embassy_executor_timer_queue::TimerQueueItem; #[cfg(feature = "arch-avr")] use portable_atomic::AtomicPtr; -- cgit From d04dc2bc35435602bb153d684dd547b2ffc57fbc Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Fri, 29 Aug 2025 15:37:00 +0200 Subject: Add cargo metadata --- examples/nrf52840-edf/Cargo.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/nrf52840-edf/Cargo.toml b/examples/nrf52840-edf/Cargo.toml index 9efdff7c4..4c0d910ea 100644 --- a/examples/nrf52840-edf/Cargo.toml +++ b/examples/nrf52840-edf/Cargo.toml @@ -3,6 +3,7 @@ edition = "2021" name = "embassy-nrf52840-edf-examples" version = "0.1.0" license = "MIT OR Apache-2.0" +publish = false [dependencies] # NOTE: "edf-scheduler" feature is enabled @@ -19,3 +20,8 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] } [profile.release] debug = 2 + +[package.metadata.embassy] +build = [ + { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf52840-edf" } +] -- cgit From adb0c3e947dc72027a121a74a700df10fc9e2337 Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Mon, 1 Sep 2025 11:17:14 +0200 Subject: Add more metadata --- embassy-executor/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 2de36d22d..e7136466d 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -24,6 +24,7 @@ build = [ {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-thread"]}, {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt"]}, {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread"]}, + {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "edf-scheduler"]}, {target = "armv7a-none-eabi", features = ["arch-cortex-ar", "executor-thread"]}, {target = "armv7r-none-eabi", features = ["arch-cortex-ar", "executor-thread"]}, {target = "armv7r-none-eabihf", features = ["arch-cortex-ar", "executor-thread"]}, -- cgit From 401fac6ea95b6dd16492d784f99f07fb9a1b318b Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Mon, 8 Sep 2025 11:40:34 +0200 Subject: Make requested API changes --- embassy-executor/Cargo.toml | 10 ++-- embassy-executor/src/metadata.rs | 64 ++++++++++++++++++-- embassy-executor/src/raw/deadline.rs | 109 ---------------------------------- embassy-executor/src/raw/mod.rs | 6 +- embassy-executor/src/raw/run_queue.rs | 6 +- 5 files changed, 71 insertions(+), 124 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index e7136466d..66352a00e 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -119,8 +119,6 @@ arch-spin = ["_arch"] ## Enable the `name` field in task metadata. metadata-name = ["embassy-executor-macros/metadata-name"] -## Enable the `deadline` field in task metadata. -metadata-deadline = [] #! ### Executor @@ -131,9 +129,13 @@ executor-interrupt = [] ## Enable tracing hooks trace = ["_any_trace"] ## Enable support for rtos-trace framework -rtos-trace = ["_any_trace", "metadata-name", "dep:rtos-trace", "dep:embassy-time-driver"] +rtos-trace = ["_any_trace", "metadata-name", "dep:rtos-trace", "embassy-time-driver"] _any_trace = [] ## Enable "Earliest Deadline First" Scheduler, using soft-realtime "deadlines" to prioritize ## tasks based on the remaining time before their deadline. Adds some overhead. -edf-scheduler = ["dep:embassy-time-driver", "metadata-deadline"] +scheduler-deadline = [] + +## Enable the embassy_time_driver dependency. +## This can unlock extra APIs, for example for the `sheduler-deadline` +embassy-time-driver = ["dep:embassy-time-driver"] diff --git a/embassy-executor/src/metadata.rs b/embassy-executor/src/metadata.rs index fd8095629..81c5afafb 100644 --- a/embassy-executor/src/metadata.rs +++ b/embassy-executor/src/metadata.rs @@ -7,12 +7,14 @@ use core::task::Poll; use critical_section::Mutex; use crate::raw; +#[cfg(feature = "scheduler-deadline")] +use crate::raw::Deadline; /// Metadata associated with a task. pub struct Metadata { #[cfg(feature = "metadata-name")] name: Mutex>>, - #[cfg(feature = "metadata-deadline")] + #[cfg(feature = "scheduler-deadline")] deadline: raw::Deadline, } @@ -23,7 +25,7 @@ impl Metadata { name: Mutex::new(Cell::new(None)), // NOTE: The deadline is set to zero to allow the initializer to reside in `.bss`. This // will be lazily initalized in `initialize_impl` - #[cfg(feature = "metadata-deadline")] + #[cfg(feature = "scheduler-deadline")] deadline: raw::Deadline::new_unset(), } } @@ -59,10 +61,62 @@ impl Metadata { critical_section::with(|cs| self.name.borrow(cs).set(Some(name))) } - /// Earliest Deadline First scheduler Deadline. This field should not be accessed - /// outside the context of the task itself as it being polled by the executor. - #[cfg(feature = "metadata-deadline")] + /// Get this task's deadline. + #[cfg(feature = "scheduler-deadline")] pub fn deadline(&self) -> &raw::Deadline { &self.deadline } + + /// Set this task's deadline. + /// + /// This method does NOT check whether the deadline has already passed. + #[cfg(feature = "scheduler-deadline")] + pub fn set_deadline(&self, instant_ticks: u64) { + self.deadline.set(instant_ticks); + } + + /// Remove this task's deadline. + /// This brings it back to the defaul where it's not scheduled ahead of other tasks. + #[cfg(feature = "scheduler-deadline")] + pub fn unset_deadline(&self) { + self.deadline.set(Deadline::UNSET_DEADLINE_TICKS); + } + + /// Set this task's deadline `duration_ticks` in the future from when + /// this future is polled. This deadline is saturated to the max tick value. + /// + /// Analogous to `Timer::after`. + #[cfg(all(feature = "scheduler-deadline", feature = "embassy-time-driver"))] + pub fn set_deadline_after(&self, duration_ticks: u64) { + let now = embassy_time_driver::now(); + + // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave + // it for now, we can probably make this wrapping_add for performance + // reasons later. + let deadline = now.saturating_add(duration_ticks); + + self.set_deadline(deadline); + } + + /// Set the this task's deadline `increment_ticks` from the previous deadline. + /// + /// This deadline is saturated to the max tick value. + /// + /// Note that by default (unless otherwise set), tasks start life with the deadline + /// not set, which means this method will have no effect. + /// + /// Analogous to one increment of `Ticker::every().next()`. + /// + /// Returns the deadline that was set. + #[cfg(feature = "scheduler-deadline")] + pub fn increment_deadline(&self, duration_ticks: u64) { + let last = self.deadline().instant_ticks(); + + // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave + // it for now, we can probably make this wrapping_add for performance + // reasons later. + let deadline = last.saturating_add(duration_ticks); + + self.set_deadline(deadline); + } } diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs index 5b585195d..d08dd06ed 100644 --- a/embassy-executor/src/raw/deadline.rs +++ b/embassy-executor/src/raw/deadline.rs @@ -1,6 +1,4 @@ -use core::future::{poll_fn, Future}; use core::sync::atomic::{AtomicU32, Ordering}; -use core::task::Poll; /// A type for interacting with the deadline of the current task /// @@ -49,111 +47,4 @@ impl Deadline { pub fn is_unset(&self) -> bool { self.instant_ticks() == Self::UNSET_DEADLINE_TICKS } - - /// Set the current task's deadline at exactly `instant_ticks` - /// - /// This method is a future in order to access the currently executing task's - /// header which contains the deadline. - /// - /// Analogous to `Timer::at`. - /// - /// This method does NOT check whether the deadline has already passed. - #[must_use = "Setting deadline must be polled to be effective"] - pub fn set_current_task_deadline(instant_ticks: u64) -> impl Future { - poll_fn(move |cx| { - let task = super::task_from_waker(cx.waker()); - task.header().metadata.deadline().set(instant_ticks); - Poll::Ready(()) - }) - } - - /// Set the current task's deadline `duration_ticks` in the future from when - /// this future is polled. This deadline is saturated to the max tick value. - /// - /// This method is a future in order to access the currently executing task's - /// header which contains the deadline. - /// - /// Analogous to `Timer::after`. - /// - /// Returns the deadline that was set. - #[must_use = "Setting deadline must be polled to be effective"] - pub fn set_current_task_deadline_after(duration_ticks: u64) -> impl Future { - poll_fn(move |cx| { - let task = super::task_from_waker(cx.waker()); - let now = embassy_time_driver::now(); - - // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave - // it for now, we can probably make this wrapping_add for performance - // reasons later. - let deadline = now.saturating_add(duration_ticks); - - task.header().metadata.deadline().set(deadline); - - Poll::Ready(Deadline::new(deadline)) - }) - } - - /// Set the current task's deadline `increment_ticks` from the previous deadline. - /// - /// This deadline is saturated to the max tick value. - /// - /// Note that by default (unless otherwise set), tasks start life with the deadline - /// u64::MAX, which means this method will have no effect. - /// - /// This method is a future in order to access the currently executing task's - /// header which contains the deadline - /// - /// Analogous to one increment of `Ticker::every().next()`. - /// - /// Returns the deadline that was set. - #[must_use = "Setting deadline must be polled to be effective"] - pub fn increment_current_task_deadline(increment_ticks: u64) -> impl Future { - poll_fn(move |cx| { - let task_header = super::task_from_waker(cx.waker()).header(); - - // Get the last value - let last = task_header.metadata.deadline().instant_ticks(); - - // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave - // it for now, we can probably make this wrapping_add for performance - // reasons later. - let deadline = last.saturating_add(increment_ticks); - - // Store the new value - task_header.metadata.deadline().set(deadline); - - Poll::Ready(Deadline::new(deadline)) - }) - } - - /// Get the current task's deadline as a tick value. - /// - /// This method is a future in order to access the currently executing task's - /// header which contains the deadline - pub fn get_current_task_deadline() -> impl Future { - poll_fn(move |cx| { - let task = super::task_from_waker(cx.waker()); - - let deadline = task.header().metadata.deadline().instant_ticks(); - Poll::Ready(Self::new(deadline)) - }) - } - - /// Clear the current task's deadline, returning the previous value. - /// - /// This sets the deadline to the default value of `u64::MAX`, meaning all - /// tasks with set deadlines will be scheduled BEFORE this task. - #[must_use = "Clearing deadline must be polled to be effective"] - pub fn clear_current_task_deadline() -> impl Future { - poll_fn(move |cx| { - let task_header = super::task_from_waker(cx.waker()).header(); - - // get the old value - let deadline = task_header.metadata.deadline().instant_ticks(); - // Store the default value - task_header.metadata.deadline().set(Self::UNSET_DEADLINE_TICKS); - - Poll::Ready(Self::new(deadline)) - }) - } } diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 86ee86842..6a9dd9749 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -26,7 +26,7 @@ pub(crate) mod util; #[cfg_attr(feature = "turbowakers", path = "waker_turbo.rs")] mod waker; -#[cfg(feature = "metadata-deadline")] +#[cfg(feature = "scheduler-deadline")] mod deadline; use core::future::Future; @@ -39,7 +39,7 @@ use core::sync::atomic::AtomicPtr; use core::sync::atomic::Ordering; use core::task::{Context, Poll, Waker}; -#[cfg(feature = "metadata-deadline")] +#[cfg(feature = "scheduler-deadline")] pub use deadline::Deadline; use embassy_executor_timer_queue::TimerQueueItem; #[cfg(feature = "arch-avr")] @@ -302,7 +302,7 @@ impl AvailableTask { // By default, deadlines are set to the maximum value, so that any task WITH // a set deadline will ALWAYS be scheduled BEFORE a task WITHOUT a set deadline - #[cfg(feature = "edf-scheduler")] + #[cfg(feature = "scheduler-deadline")] self.task .raw .metadata diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index 978ca082a..29c977226 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs @@ -2,7 +2,7 @@ use core::ptr::{addr_of_mut, NonNull}; use cordyceps::sorted_list::Links; use cordyceps::Linked; -#[cfg(feature = "edf-scheduler")] +#[cfg(feature = "scheduler-deadline")] use cordyceps::SortedList; #[cfg(target_has_atomic = "ptr")] @@ -83,7 +83,7 @@ impl RunQueue { /// Empty the queue, then call `on_task` for each task that was in the queue. /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. - #[cfg(not(feature = "edf-scheduler"))] + #[cfg(not(feature = "scheduler-deadline"))] pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { let taken = self.stack.take_all(); for taskref in taken { @@ -106,7 +106,7 @@ impl RunQueue { /// /// This process will repeat until the local `sorted` queue AND the global /// runqueue are both empty, at which point this function will return. - #[cfg(feature = "edf-scheduler")] + #[cfg(feature = "scheduler-deadline")] pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { let mut sorted = SortedList::::new_with_cmp(|lhs, rhs| { lhs.metadata -- cgit From 09701a339d9085d86a69bf271299d7b59eda9fdc Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Mon, 8 Sep 2025 12:33:04 +0200 Subject: Fix example --- embassy-executor/src/raw/deadline.rs | 2 +- examples/nrf52840-edf/Cargo.toml | 4 ++-- examples/nrf52840-edf/src/bin/basic.rs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs index d08dd06ed..f6d016ae7 100644 --- a/embassy-executor/src/raw/deadline.rs +++ b/embassy-executor/src/raw/deadline.rs @@ -2,7 +2,7 @@ use core::sync::atomic::{AtomicU32, Ordering}; /// A type for interacting with the deadline of the current task /// -/// Requires the `edf-scheduler` feature. +/// Requires the `scheduler-deadline` feature. /// /// Note: Interacting with the deadline should be done locally in a task. /// In theory you could try to set or read the deadline from another task, diff --git a/examples/nrf52840-edf/Cargo.toml b/examples/nrf52840-edf/Cargo.toml index 4c0d910ea..1e8803233 100644 --- a/examples/nrf52840-edf/Cargo.toml +++ b/examples/nrf52840-edf/Cargo.toml @@ -6,8 +6,8 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -# NOTE: "edf-scheduler" feature is enabled -embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "edf-scheduler"] } +# NOTE: "scheduler-deadline" and "embassy-time-driver" features are enabled +embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "scheduler-deadline", "embassy-time-driver"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } diff --git a/examples/nrf52840-edf/src/bin/basic.rs b/examples/nrf52840-edf/src/bin/basic.rs index 8a8e46449..d888e17d1 100644 --- a/examples/nrf52840-edf/src/bin/basic.rs +++ b/examples/nrf52840-edf/src/bin/basic.rs @@ -15,7 +15,6 @@ use core::sync::atomic::{compiler_fence, Ordering}; use defmt::unwrap; -use embassy_executor::raw::Deadline; use embassy_executor::Spawner; use embassy_time::{Duration, Instant, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -127,7 +126,8 @@ async fn main(spawner: Spawner) { let start = Instant::now(); // Set the deadline to ~2x the theoretical time. In practice, setting any deadline // here elevates the current task above all other worker tasks. - Deadline::set_current_task_deadline_after(theoretical * 2).await; + let meta = embassy_executor::Metadata::for_current_task().await; + meta.set_deadline_after(theoretical * 2); // Perform the trial for _ in 0..num_steps { @@ -147,7 +147,7 @@ async fn main(spawner: Spawner) { // Unset the deadline, deadlines are not automatically cleared, and if our // deadline is in the past, then we get very high priority! - Deadline::clear_current_task_deadline().await; + meta.unset_deadline(); Timer::after_millis(500).await; } -- cgit From 2e21dcf2e61440db8c56a421a87c7a6bd22424d0 Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Mon, 8 Sep 2025 13:20:47 +0200 Subject: Fix metadata --- embassy-executor/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 66352a00e..fb4c4d579 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -24,7 +24,7 @@ build = [ {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-thread"]}, {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt"]}, {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread"]}, - {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "edf-scheduler"]}, + {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "scheduler-deadline", "embassy-time-driver"]}, {target = "armv7a-none-eabi", features = ["arch-cortex-ar", "executor-thread"]}, {target = "armv7r-none-eabi", features = ["arch-cortex-ar", "executor-thread"]}, {target = "armv7r-none-eabihf", features = ["arch-cortex-ar", "executor-thread"]}, @@ -47,7 +47,7 @@ flavors = [ [package.metadata.docs.rs] default-target = "thumbv7em-none-eabi" targets = ["thumbv7em-none-eabi"] -features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt", "edf-scheduler"] +features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt", "scheduler-deadline", "embassy-time-driver"] [dependencies] defmt = { version = "1.0.1", optional = true } -- cgit From e1209c5563576d18c4d033b015c9a5dd6145d581 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 11 Sep 2025 15:40:33 +0200 Subject: executor: make Deadline actually private. --- embassy-executor/Cargo.toml | 2 +- embassy-executor/src/metadata.rs | 8 ++++---- embassy-executor/src/raw/deadline.rs | 14 ++++---------- embassy-executor/src/raw/mod.rs | 8 ++------ embassy-executor/src/raw/run_queue.rs | 8 ++------ 5 files changed, 13 insertions(+), 27 deletions(-) diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index fb4c4d579..0ac666f80 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -36,7 +36,7 @@ build = [ [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-v$VERSION/embassy-executor/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor/src/" -features = ["defmt"] +features = ["defmt", "scheduler-deadline"] flavors = [ { name = "std", target = "x86_64-unknown-linux-gnu", features = ["arch-std", "executor-thread"] }, { name = "wasm", target = "wasm32-unknown-unknown", features = ["arch-wasm", "executor-thread"] }, diff --git a/embassy-executor/src/metadata.rs b/embassy-executor/src/metadata.rs index 81c5afafb..4220048a6 100644 --- a/embassy-executor/src/metadata.rs +++ b/embassy-executor/src/metadata.rs @@ -63,8 +63,8 @@ impl Metadata { /// Get this task's deadline. #[cfg(feature = "scheduler-deadline")] - pub fn deadline(&self) -> &raw::Deadline { - &self.deadline + pub fn deadline(&self) -> u64 { + self.deadline.instant_ticks() } /// Set this task's deadline. @@ -79,7 +79,7 @@ impl Metadata { /// This brings it back to the defaul where it's not scheduled ahead of other tasks. #[cfg(feature = "scheduler-deadline")] pub fn unset_deadline(&self) { - self.deadline.set(Deadline::UNSET_DEADLINE_TICKS); + self.deadline.set(Deadline::UNSET_TICKS); } /// Set this task's deadline `duration_ticks` in the future from when @@ -110,7 +110,7 @@ impl Metadata { /// Returns the deadline that was set. #[cfg(feature = "scheduler-deadline")] pub fn increment_deadline(&self, duration_ticks: u64) { - let last = self.deadline().instant_ticks(); + let last = self.deadline(); // Since ticks is a u64, saturating add is PROBABLY overly cautious, leave // it for now, we can probably make this wrapping_add for performance diff --git a/embassy-executor/src/raw/deadline.rs b/embassy-executor/src/raw/deadline.rs index f6d016ae7..cc89fadb0 100644 --- a/embassy-executor/src/raw/deadline.rs +++ b/embassy-executor/src/raw/deadline.rs @@ -7,7 +7,7 @@ use core::sync::atomic::{AtomicU32, Ordering}; /// Note: Interacting with the deadline should be done locally in a task. /// In theory you could try to set or read the deadline from another task, /// but that will result in weird (though not unsound) behavior. -pub struct Deadline { +pub(crate) struct Deadline { instant_ticks_hi: AtomicU32, instant_ticks_lo: AtomicU32, } @@ -21,7 +21,7 @@ impl Deadline { } pub(crate) const fn new_unset() -> Self { - Self::new(Self::UNSET_DEADLINE_TICKS) + Self::new(Self::UNSET_TICKS) } pub(crate) fn set(&self, instant_ticks: u64) { @@ -31,7 +31,7 @@ impl Deadline { } /// Deadline value in ticks, same time base and ticks as `embassy-time` - pub fn instant_ticks(&self) -> u64 { + pub(crate) fn instant_ticks(&self) -> u64 { let hi = self.instant_ticks_hi.load(Ordering::Relaxed) as u64; let lo = self.instant_ticks_lo.load(Ordering::Relaxed) as u64; @@ -40,11 +40,5 @@ impl Deadline { /// Sentinel value representing an "unset" deadline, which has lower priority /// than any other set deadline value - pub const UNSET_DEADLINE_TICKS: u64 = u64::MAX; - - /// Does the given Deadline represent an "unset" deadline? - #[inline] - pub fn is_unset(&self) -> bool { - self.instant_ticks() == Self::UNSET_DEADLINE_TICKS - } + pub(crate) const UNSET_TICKS: u64 = u64::MAX; } diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 6a9dd9749..51a363385 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -40,7 +40,7 @@ use core::sync::atomic::Ordering; use core::task::{Context, Poll, Waker}; #[cfg(feature = "scheduler-deadline")] -pub use deadline::Deadline; +pub(crate) use deadline::Deadline; use embassy_executor_timer_queue::TimerQueueItem; #[cfg(feature = "arch-avr")] use portable_atomic::AtomicPtr; @@ -303,11 +303,7 @@ impl AvailableTask { // By default, deadlines are set to the maximum value, so that any task WITH // a set deadline will ALWAYS be scheduled BEFORE a task WITHOUT a set deadline #[cfg(feature = "scheduler-deadline")] - self.task - .raw - .metadata - .deadline() - .set(deadline::Deadline::UNSET_DEADLINE_TICKS); + self.task.raw.metadata.unset_deadline(); let task = TaskRef::new(self.task); diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index 29c977226..d98c26f73 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs @@ -108,12 +108,8 @@ impl RunQueue { /// runqueue are both empty, at which point this function will return. #[cfg(feature = "scheduler-deadline")] pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { - let mut sorted = SortedList::::new_with_cmp(|lhs, rhs| { - lhs.metadata - .deadline() - .instant_ticks() - .cmp(&rhs.metadata.deadline().instant_ticks()) - }); + let mut sorted = + SortedList::::new_with_cmp(|lhs, rhs| lhs.metadata.deadline().cmp(&rhs.metadata.deadline())); loop { // For each loop, grab any newly pended items -- cgit From 6ec9bcb1c4dfbe5fc5365d93e75c516bb03bf9fc Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 11 Sep 2025 16:15:27 +0200 Subject: executor: add priority scheduler. --- ci.sh | 6 ++++++ embassy-executor/CHANGELOG.md | 1 + embassy-executor/Cargo.toml | 14 +++++++++++--- embassy-executor/src/metadata.rs | 26 ++++++++++++++++++++++++++ embassy-executor/src/raw/mod.rs | 5 ----- embassy-executor/src/raw/run_queue.rs | 29 ++++++++++++++++++++++++----- 6 files changed, 68 insertions(+), 13 deletions(-) diff --git a/ci.sh b/ci.sh index a25097690..81e665edf 100755 --- a/ci.sh +++ b/ci.sh @@ -38,6 +38,12 @@ cargo batch \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt \ --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread,executor-interrupt \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt,executor-thread,embassy-time-driver \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt,executor-thread,embassy-time-driver,scheduler-priority \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt,executor-thread,embassy-time-driver,scheduler-priority,scheduler-deadline \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt,executor-thread,embassy-time-driver,scheduler-deadline \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt,executor-thread,scheduler-priority,scheduler-deadline \ + --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt,executor-thread,scheduler-deadline \ --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7a-none-eabi --features arch-cortex-ar,executor-thread \ --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7r-none-eabi --features arch-cortex-ar,executor-thread \ --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7r-none-eabihf --features arch-cortex-ar,executor-thread \ diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 03d60208e..6f079a11a 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added new metadata API for tasks. - Main task automatically gets a name of `main` when the `metadata-name` feature is enabled. - Upgraded rtos-trace +- Added optional "highest priority" scheduling - Added optional "earliest deadline first" EDF scheduling ## 0.9.1 - 2025-08-31 diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 0ac666f80..d4ea0e6ac 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -24,7 +24,12 @@ build = [ {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-thread"]}, {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt"]}, {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread"]}, - {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "scheduler-deadline", "embassy-time-driver"]}, + {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "embassy-time-driver"]}, + {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "embassy-time-driver", "scheduler-priority"]}, + {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "embassy-time-driver", "scheduler-priority", "scheduler-deadline"]}, + {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "embassy-time-driver", "scheduler-deadline"]}, + {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "scheduler-priority", "scheduler-deadline"]}, + {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "scheduler-deadline"]}, {target = "armv7a-none-eabi", features = ["arch-cortex-ar", "executor-thread"]}, {target = "armv7r-none-eabi", features = ["arch-cortex-ar", "executor-thread"]}, {target = "armv7r-none-eabihf", features = ["arch-cortex-ar", "executor-thread"]}, @@ -36,7 +41,7 @@ build = [ [package.metadata.embassy_docs] src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-v$VERSION/embassy-executor/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor/src/" -features = ["defmt", "scheduler-deadline"] +features = ["defmt", "scheduler-deadline", "scheduler-priority"] flavors = [ { name = "std", target = "x86_64-unknown-linux-gnu", features = ["arch-std", "executor-thread"] }, { name = "wasm", target = "wasm32-unknown-unknown", features = ["arch-wasm", "executor-thread"] }, @@ -47,7 +52,7 @@ flavors = [ [package.metadata.docs.rs] default-target = "thumbv7em-none-eabi" targets = ["thumbv7em-none-eabi"] -features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt", "scheduler-deadline", "embassy-time-driver"] +features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt", "scheduler-deadline", "scheduler-priority", "embassy-time-driver"] [dependencies] defmt = { version = "1.0.1", optional = true } @@ -136,6 +141,9 @@ _any_trace = [] ## tasks based on the remaining time before their deadline. Adds some overhead. scheduler-deadline = [] +## Enable "Highest Priority First" Scheduler. Adds some overhead. +scheduler-priority = [] + ## Enable the embassy_time_driver dependency. ## This can unlock extra APIs, for example for the `sheduler-deadline` embassy-time-driver = ["dep:embassy-time-driver"] diff --git a/embassy-executor/src/metadata.rs b/embassy-executor/src/metadata.rs index 4220048a6..bc0df0f83 100644 --- a/embassy-executor/src/metadata.rs +++ b/embassy-executor/src/metadata.rs @@ -1,6 +1,8 @@ #[cfg(feature = "metadata-name")] use core::cell::Cell; use core::future::{poll_fn, Future}; +#[cfg(feature = "scheduler-priority")] +use core::sync::atomic::{AtomicU8, Ordering}; use core::task::Poll; #[cfg(feature = "metadata-name")] @@ -14,6 +16,8 @@ use crate::raw::Deadline; pub struct Metadata { #[cfg(feature = "metadata-name")] name: Mutex>>, + #[cfg(feature = "scheduler-priority")] + priority: AtomicU8, #[cfg(feature = "scheduler-deadline")] deadline: raw::Deadline, } @@ -23,6 +27,8 @@ impl Metadata { Self { #[cfg(feature = "metadata-name")] name: Mutex::new(Cell::new(None)), + #[cfg(feature = "scheduler-priority")] + priority: AtomicU8::new(0), // NOTE: The deadline is set to zero to allow the initializer to reside in `.bss`. This // will be lazily initalized in `initialize_impl` #[cfg(feature = "scheduler-deadline")] @@ -33,6 +39,14 @@ impl Metadata { pub(crate) fn reset(&self) { #[cfg(feature = "metadata-name")] critical_section::with(|cs| self.name.borrow(cs).set(None)); + + #[cfg(feature = "scheduler-priority")] + self.set_priority(0); + + // By default, deadlines are set to the maximum value, so that any task WITH + // a set deadline will ALWAYS be scheduled BEFORE a task WITHOUT a set deadline + #[cfg(feature = "scheduler-deadline")] + self.unset_deadline(); } /// Get the metadata for the current task. @@ -61,6 +75,18 @@ impl Metadata { critical_section::with(|cs| self.name.borrow(cs).set(Some(name))) } + /// Get this task's priority. + #[cfg(feature = "scheduler-priority")] + pub fn priority(&self) -> u8 { + self.priority.load(Ordering::Relaxed) + } + + /// Set this task's priority. + #[cfg(feature = "scheduler-priority")] + pub fn set_priority(&self, priority: u8) { + self.priority.store(priority, Ordering::Relaxed) + } + /// Get this task's deadline. #[cfg(feature = "scheduler-deadline")] pub fn deadline(&self) -> u64 { diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 51a363385..9f36c60bc 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -300,11 +300,6 @@ impl AvailableTask { self.task.raw.poll_fn.set(Some(TaskStorage::::poll)); self.task.future.write_in_place(future); - // By default, deadlines are set to the maximum value, so that any task WITH - // a set deadline will ALWAYS be scheduled BEFORE a task WITHOUT a set deadline - #[cfg(feature = "scheduler-deadline")] - self.task.raw.metadata.unset_deadline(); - let task = TaskRef::new(self.task); SpawnToken::new(task) diff --git a/embassy-executor/src/raw/run_queue.rs b/embassy-executor/src/raw/run_queue.rs index d98c26f73..b8b052310 100644 --- a/embassy-executor/src/raw/run_queue.rs +++ b/embassy-executor/src/raw/run_queue.rs @@ -2,7 +2,7 @@ use core::ptr::{addr_of_mut, NonNull}; use cordyceps::sorted_list::Links; use cordyceps::Linked; -#[cfg(feature = "scheduler-deadline")] +#[cfg(any(feature = "scheduler-priority", feature = "scheduler-deadline"))] use cordyceps::SortedList; #[cfg(target_has_atomic = "ptr")] @@ -83,7 +83,7 @@ impl RunQueue { /// Empty the queue, then call `on_task` for each task that was in the queue. /// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue /// and will be processed by the *next* call to `dequeue_all`, *not* the current one. - #[cfg(not(feature = "scheduler-deadline"))] + #[cfg(not(any(feature = "scheduler-priority", feature = "scheduler-deadline")))] pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { let taken = self.stack.take_all(); for taskref in taken { @@ -106,10 +106,29 @@ impl RunQueue { /// /// This process will repeat until the local `sorted` queue AND the global /// runqueue are both empty, at which point this function will return. - #[cfg(feature = "scheduler-deadline")] + #[cfg(any(feature = "scheduler-priority", feature = "scheduler-deadline"))] pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) { - let mut sorted = - SortedList::::new_with_cmp(|lhs, rhs| lhs.metadata.deadline().cmp(&rhs.metadata.deadline())); + let mut sorted = SortedList::::new_with_cmp(|lhs, rhs| { + // compare by priority first + #[cfg(feature = "scheduler-priority")] + { + let lp = lhs.metadata.priority(); + let rp = rhs.metadata.priority(); + if lp != rp { + return lp.cmp(&rp).reverse(); + } + } + // compare deadlines in case of tie. + #[cfg(feature = "scheduler-deadline")] + { + let ld = lhs.metadata.deadline(); + let rd = rhs.metadata.deadline(); + if ld != rd { + return ld.cmp(&rd); + } + } + core::cmp::Ordering::Equal + }); loop { // For each loop, grab any newly pended items -- cgit From 55b3c5c6e8fb5e55a0e507c43db5d9ef32114f64 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 11 Sep 2025 21:27:02 +0200 Subject: ci: use devtool to build. --- .github/ci/build-nightly.sh | 3 + .github/ci/build-xtensa.sh | 11 +- .github/ci/build.sh | 3 + ci-nightly.sh | 17 +- ci-xtensa.sh | 28 +-- ci.sh | 359 +------------------------------ embassy-executor/Cargo.toml | 25 +++ embassy-net-wiznet/src/chip/mod.rs | 1 + embassy-net/Cargo.toml | 13 ++ embassy-sync/Cargo.toml | 2 + embassy-time-queue-utils/Cargo.toml | 3 + embassy-time/Cargo.toml | 2 + examples/mspm0c1104/Cargo.toml | 3 +- examples/nrf52840-rtic/src/bin/blinky.rs | 1 - 14 files changed, 68 insertions(+), 403 deletions(-) diff --git a/.github/ci/build-nightly.sh b/.github/ci/build-nightly.sh index 95cb4100c..2d7c4db3f 100755 --- a/.github/ci/build-nightly.sh +++ b/.github/ci/build-nightly.sh @@ -7,6 +7,7 @@ set -euo pipefail export RUSTUP_HOME=/ci/cache/rustup export CARGO_HOME=/ci/cache/cargo export CARGO_TARGET_DIR=/ci/cache/target +export PATH=$CARGO_HOME/bin:$PATH mv rust-toolchain-nightly.toml rust-toolchain.toml # needed for "dumb HTTP" transport support @@ -22,6 +23,8 @@ fi hashtime restore /ci/cache/filetime.json || true hashtime save /ci/cache/filetime.json +cargo install --git https://github.com/embassy-rs/cargo-embassy-devtool --locked --rev 280829ad163f1444999468a57d28fb7c412babbe + ./ci-nightly.sh # Save lockfiles diff --git a/.github/ci/build-xtensa.sh b/.github/ci/build-xtensa.sh index 103575bc9..b6626639d 100755 --- a/.github/ci/build-xtensa.sh +++ b/.github/ci/build-xtensa.sh @@ -7,13 +7,14 @@ set -euo pipefail export RUSTUP_HOME=/ci/cache/rustup export CARGO_HOME=/ci/cache/cargo export CARGO_TARGET_DIR=/ci/cache/target +export PATH=$CARGO_HOME/bin:$PATH # needed for "dumb HTTP" transport support # used when pointing stm32-metapac to a CI-built one. export CARGO_NET_GIT_FETCH_WITH_CLI=true -cargo install espup -/ci/cache/cargo/bin/espup install --toolchain-version 1.84.0.0 +cargo install espup --locked +espup install --toolchain-version 1.88.0.0 # Restore lockfiles if [ -f /ci/cache/lockfiles.tar ]; then @@ -24,11 +25,7 @@ fi hashtime restore /ci/cache/filetime.json || true hashtime save /ci/cache/filetime.json -mkdir .cargo -cat > .cargo/config.toml<< EOF -[unstable] -build-std = ["alloc", "core"] -EOF +cargo install --git https://github.com/embassy-rs/cargo-embassy-devtool --locked --rev 280829ad163f1444999468a57d28fb7c412babbe ./ci-xtensa.sh diff --git a/.github/ci/build.sh b/.github/ci/build.sh index 68a7c0c34..59bcefed6 100755 --- a/.github/ci/build.sh +++ b/.github/ci/build.sh @@ -7,6 +7,7 @@ set -euo pipefail export RUSTUP_HOME=/ci/cache/rustup export CARGO_HOME=/ci/cache/cargo export CARGO_TARGET_DIR=/ci/cache/target +export PATH=$CARGO_HOME/bin:$PATH if [ -f /ci/secrets/teleprobe-token.txt ]; then echo Got teleprobe token! export TELEPROBE_HOST=https://teleprobe.embassy.dev @@ -27,6 +28,8 @@ fi hashtime restore /ci/cache/filetime.json || true hashtime save /ci/cache/filetime.json +cargo install --git https://github.com/embassy-rs/cargo-embassy-devtool --locked --rev 280829ad163f1444999468a57d28fb7c412babbe + ./ci.sh # Save lockfiles diff --git a/ci-nightly.sh b/ci-nightly.sh index d486d442c..afe9f534c 100755 --- a/ci-nightly.sh +++ b/ci-nightly.sh @@ -8,19 +8,4 @@ if [[ -z "${CARGO_TARGET_DIR}" ]]; then export CARGO_TARGET_DIR=target_ci fi -cargo batch \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,log \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,defmt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt,arch-cortex-m,executor-thread,executor-interrupt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-interrupt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,executor-interrupt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32 \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread \ - --- build --release --manifest-path examples/nrf52840-rtic/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/nrf52840-rtic \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7a-none-eabi --features nightly,arch-cortex-ar,executor-thread \ - -RUSTFLAGS="$RUSTFLAGS -C target-cpu=atmega328p" cargo build --release --manifest-path embassy-executor/Cargo.toml --target avr-none -Z build-std=core,alloc --features nightly,arch-avr,avr-device/atmega328p +cargo embassy-devtool build --group nightly diff --git a/ci-xtensa.sh b/ci-xtensa.sh index 6c9807e98..0dd41a9ce 100755 --- a/ci-xtensa.sh +++ b/ci-xtensa.sh @@ -9,30 +9,4 @@ if [[ -z "${CARGO_TARGET_DIR}" ]]; then export CARGO_TARGET_DIR=target_ci fi -cargo batch \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target xtensa-esp32-none-elf \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target xtensa-esp32-none-elf --features log \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target xtensa-esp32-none-elf --features defmt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target xtensa-esp32s2-none-elf --features defmt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target xtensa-esp32-none-elf --features defmt,arch-spin,executor-thread \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target xtensa-esp32s2-none-elf --features defmt,arch-spin,executor-thread \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target xtensa-esp32s3-none-elf --features defmt,arch-spin,executor-thread \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target xtensa-esp32-none-elf --features arch-spin \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target xtensa-esp32-none-elf --features arch-spin,rtos-trace \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target xtensa-esp32-none-elf --features arch-spin,executor-thread \ - --- build --release --manifest-path embassy-sync/Cargo.toml --target xtensa-esp32s2-none-elf --features defmt \ - --- build --release --manifest-path embassy-time/Cargo.toml --target xtensa-esp32s2-none-elf --features defmt,defmt-timestamp-uptime,mock-driver \ - --- build --release --manifest-path embassy-time-queue-utils/Cargo.toml --target xtensa-esp32s2-none-elf \ - --- build --release --manifest-path embassy-time-queue-utils/Cargo.toml --target xtensa-esp32s2-none-elf --features generic-queue-8 \ - --- build --release --manifest-path embassy-net/Cargo.toml --target xtensa-esp32-none-elf --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet,packet-trace \ - --- build --release --manifest-path embassy-net/Cargo.toml --target xtensa-esp32-none-elf --features defmt,tcp,udp,dns,proto-ipv4,multicast,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target xtensa-esp32-none-elf --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target xtensa-esp32-none-elf --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,dhcpv4-hostname \ - --- build --release --manifest-path embassy-net/Cargo.toml --target xtensa-esp32-none-elf --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target xtensa-esp32-none-elf --features defmt,tcp,udp,dns,proto-ipv6,medium-ieee802154 \ - --- build --release --manifest-path embassy-net/Cargo.toml --target xtensa-esp32-none-elf --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,medium-ieee802154 \ - --- build --release --manifest-path embassy-net/Cargo.toml --target xtensa-esp32-none-elf --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target xtensa-esp32-none-elf --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target xtensa-esp32-none-elf --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip \ - --- build --release --manifest-path embassy-net/Cargo.toml --target xtensa-esp32-none-elf --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target xtensa-esp32-none-elf --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip,medium-ethernet,medium-ieee802154 \ +cargo embassy-devtool build --group xtensa diff --git a/ci.sh b/ci.sh index 81e665edf..6cc2a031d 100755 --- a/ci.sh +++ b/ci.sh @@ -10,362 +10,21 @@ if ! command -v cargo-batch &> /dev/null; then exit 1 fi +if ! command -v cargo-embassy-devtool &> /dev/null; then + echo "cargo-embassy-devtool could not be found. Install it with the following command:" + echo "" + echo " cargo install --git https://github.com/embassy-rs/cargo-embassy-devtool --locked" + echo "" + exit 1 +fi + export RUSTFLAGS=-Dwarnings export DEFMT_LOG=trace,embassy_hal_internal=debug,embassy_net_esp_hosted=debug,cyw43=info,cyw43_pio=info,smoltcp=info if [[ -z "${CARGO_TARGET_DIR}" ]]; then export CARGO_TARGET_DIR=target_ci fi -TARGET=$(rustc -vV | sed -n 's|host: ||p') - -BUILD_EXTRA="" -if [ $TARGET = "x86_64-unknown-linux-gnu" ] || [ $TARGET = "aarch64-unknown-linux-gnu" ]; then - BUILD_EXTRA="--- build --release --manifest-path examples/std/Cargo.toml --target $TARGET --artifact-dir out/examples/std" -fi - -# CI intentionally does not use -eabihf on thumbv7em to minimize dep compile time. -cargo batch \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features log \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features defmt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt,arch-cortex-m,executor-thread,executor-interrupt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,metadata-name \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,trace \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,rtos-trace \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,trace,rtos-trace \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread,executor-interrupt \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt,executor-thread,embassy-time-driver \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt,executor-thread,embassy-time-driver,scheduler-priority \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt,executor-thread,embassy-time-driver,scheduler-priority,scheduler-deadline \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt,executor-thread,embassy-time-driver,scheduler-deadline \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt,executor-thread,scheduler-priority,scheduler-deadline \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt,executor-thread,scheduler-deadline \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7a-none-eabi --features arch-cortex-ar,executor-thread \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7r-none-eabi --features arch-cortex-ar,executor-thread \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target armv7r-none-eabihf --features arch-cortex-ar,executor-thread \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32 \ - --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32,executor-thread \ - --- build --release --manifest-path embassy-embedded-hal/Cargo.toml --target thumbv7em-none-eabi \ - --- build --release --manifest-path embassy-embedded-hal/Cargo.toml --target thumbv7em-none-eabi --features time \ - --- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features defmt \ - --- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features defmt,defmt-timestamp-uptime,mock-driver \ - --- build --release --manifest-path embassy-time/Cargo.toml --features defmt,std \ - --- build --release --manifest-path embassy-time-queue-utils/Cargo.toml --target thumbv6m-none-eabi \ - --- build --release --manifest-path embassy-time-queue-utils/Cargo.toml --target thumbv6m-none-eabi --features generic-queue-8 \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet,packet-trace \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,multicast,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,dhcpv4-hostname \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ieee802154 \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,medium-ieee802154 \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip,medium-ethernet,medium-ieee802154 \ - --- build --release --manifest-path embassy-imxrt/Cargo.toml --target thumbv8m.main-none-eabihf --features mimxrt633s,defmt,unstable-pac,time,time-driver-rtc \ - --- build --release --manifest-path embassy-imxrt/Cargo.toml --target thumbv8m.main-none-eabihf --features mimxrt685s,defmt,unstable-pac,time,time-driver-rtc \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52805,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52810,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52811,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52820,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52832,gpiote,time,time-driver-rtc1,reset-pin-as-gpio \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52833,gpiote,time,time-driver-rtc1,nfc-pins-as-gpio \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf9160-s,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf9160-ns,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-app-s,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-app-ns,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-net,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf54l15-app-s,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf54l15-app-ns,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,log,time \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,log,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,log,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,defmt,time \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,defmt,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,defmt,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51,defmt,time,time-driver-rtc1 \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51,defmt,time \ - --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51,time \ - --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features time-driver,defmt,rp2040 \ - --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features time-driver,log,rp2040 \ - --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features time-driver,intrinsics,rp2040 \ - --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features time-driver,qspi-as-gpio,rp2040 \ - --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv8m.main-none-eabihf --features time-driver,defmt,rp235xa \ - --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv8m.main-none-eabihf --features time-driver,log,rp235xa \ - --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv8m.main-none-eabihf --features time-driver,rp235xa,binary-info \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,single-bank,defmt \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c071rb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c051f6,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c091gb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c092rc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f038f6,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f030c6,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f058t8,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f030r8,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f031k6,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f030rc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f070f6,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f078vb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f042g4,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f072c8,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f401ve,defmt,exti,time-driver-any \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f405zg,defmt,exti,time-driver-any \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f407zg,defmt,exti,time-driver-any \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f401ve,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f405zg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f407zg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f410tb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f411ce,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f412zg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f413vh,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f415zg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f417zg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f423zh,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f427zi,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f437zi,log,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f439zi,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446ze,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f469zi,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f479zi,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f730i8,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h753zi,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h735zg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,time,split-pc2,split-pc3 \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h725re,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-tim1,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7r3z8,defmt,exti,time-driver-tim1,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7r7a8,defmt,exti,time-driver-tim1,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s3a8,defmt,exti,time-driver-tim1,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s7z8,defmt,exti,time-driver-tim1,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l431cb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l422cb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb15cc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l041f6,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l051k8,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l073cz,defmt,exti,time-driver-any,low-power,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303c8,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f398ve,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f378cc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g0b0ce,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g0c1ve,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,dual-bank,defmt,exti,time-driver-any,low-power,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32wl54jc-cm0p,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wle5jb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g431kb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g474pe,dual-bank,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f107vc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f103re,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f100c4,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h503rb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h523cc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h562ag,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba50ke,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba55ug,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba62cg,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba65ri,defmt,exti,time-driver-any,low-power,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u5f9zj,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u5g9nj,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb35ce,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55rg,defmt,exti,time-driver-any,low-power,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u031r8,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u073mb,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u083rc,defmt,exti,time-driver-any,time \ - --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv8m.main-none-eabihf --features lpc55,defmt \ - --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv7em-none-eabihf --features mimxrt1011,rt,defmt,time-driver-pit \ - --- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv7em-none-eabihf --features mimxrt1062,rt,defmt,time-driver-pit \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0c1104dgs20,rt,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0c1106rgz,rt,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3507pm,rt,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3519pz,rt,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1306rhb,rt,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l2228pn,rt,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1345dgs28,rt,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1106dgs28,rt,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l1228pm,rt,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1107ycj,rt,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3105rhb,rt,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1505pt,rt,defmt,time-driver-any \ - --- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g1519rhb,rt,defmt,time-driver-any \ - --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features ''\ - --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log' \ - --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt' \ - --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log,firmware-logs' \ - --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt,firmware-logs' \ - --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log,firmware-logs,bluetooth' \ - --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt,firmware-logs,bluetooth' \ - --- build --release --manifest-path cyw43-pio/Cargo.toml --target thumbv6m-none-eabi --features 'embassy-rp/rp2040' \ - --- build --release --manifest-path cyw43-pio/Cargo.toml --target thumbv6m-none-eabi --features 'embassy-rp/rp2040' \ - --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \ - --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf5340-app-s \ - --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns \ - --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9120-ns \ - --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9151-ns \ - --- build --release --manifest-path embassy-boot-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9161-ns \ - --- build --release --manifest-path embassy-boot-rp/Cargo.toml --target thumbv6m-none-eabi --features embassy-rp/rp2040 \ - --- build --release --manifest-path embassy-boot-stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32l496zg \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --no-default-features \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features log \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features defmt \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features usbd-hid \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features max-interface-count-1 \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features max-interface-count-8 \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features max-handler-count-8 \ - --- build --release --manifest-path embassy-usb/Cargo.toml --target thumbv6m-none-eabi --features max-handler-count-8 \ - --- build --release --manifest-path docs/examples/basic/Cargo.toml --target thumbv7em-none-eabi \ - --- build --release --manifest-path docs/examples/layer-by-layer/blinky-pac/Cargo.toml --target thumbv7em-none-eabi \ - --- build --release --manifest-path docs/examples/layer-by-layer/blinky-hal/Cargo.toml --target thumbv7em-none-eabi \ - --- build --release --manifest-path docs/examples/layer-by-layer/blinky-irq/Cargo.toml --target thumbv7em-none-eabi \ - --- build --release --manifest-path docs/examples/layer-by-layer/blinky-async/Cargo.toml --target thumbv7em-none-eabi \ - --- build --release --manifest-path examples/nrf52810/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/nrf52810 \ - --- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/nrf52840 \ - --- build --release --manifest-path examples/nrf52840-edf/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/nrf52840-edf \ - --- build --release --manifest-path examples/nrf5340/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf5340 \ - --- build --release --manifest-path examples/nrf54l15/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf54l15 \ - --- build --release --manifest-path examples/nrf9160/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf9160 \ - --- build --release --manifest-path examples/nrf9151/s/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf9151/s \ - --- build --release --manifest-path examples/nrf9151/ns/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/nrf9151/ns \ - --- build --release --manifest-path examples/nrf51/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/nrf51 \ - --- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/rp \ - --- build --release --manifest-path examples/rp235x/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/rp235x \ - --- build --release --manifest-path examples/stm32f0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32f0 \ - --- build --release --manifest-path examples/stm32f1/Cargo.toml --target thumbv7m-none-eabi --artifact-dir out/examples/stm32f1 \ - --- build --release --manifest-path examples/stm32f2/Cargo.toml --target thumbv7m-none-eabi --artifact-dir out/examples/stm32f2 \ - --- build --release --manifest-path examples/stm32f3/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f3 \ - --- build --release --manifest-path examples/stm32f334/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f334 \ - --- build --release --manifest-path examples/stm32f4/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f4 \ - --- build --release --manifest-path examples/stm32f469/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f469 \ - --- build --release --manifest-path examples/stm32f7/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32f7 \ - --- build --release --manifest-path examples/stm32c0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32c0 \ - --- build --release --manifest-path examples/stm32g0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32g0 \ - --- build --release --manifest-path examples/stm32g4/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32g4 \ - --- build --release --manifest-path examples/stm32h5/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32h5 \ - --- build --release --manifest-path examples/stm32h7/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h7 \ - --- build --release --manifest-path examples/stm32h7b0/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h7b0 \ - --- build --release --manifest-path examples/stm32h723/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h723 \ - --- build --release --manifest-path examples/stm32h735/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h735 \ - --- build --release --manifest-path examples/stm32h755cm4/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h755cm4 \ - --- build --release --manifest-path examples/stm32h755cm7/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h755cm7 \ - --- build --release --manifest-path examples/stm32h7rs/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32h7rs \ - --- build --release --manifest-path examples/stm32l0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32l0 \ - --- build --release --manifest-path examples/stm32l1/Cargo.toml --target thumbv7m-none-eabi --artifact-dir out/examples/stm32l1 \ - --- build --release --manifest-path examples/stm32l4/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32l4 \ - --- build --release --manifest-path examples/stm32l432/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32l432 \ - --- build --release --manifest-path examples/stm32l5/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32l5 \ - --- build --release --manifest-path examples/stm32u0/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/stm32u0 \ - --- build --release --manifest-path examples/stm32u5/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32u5 \ - --- build --release --manifest-path examples/stm32wb/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32wb \ - --- build --release --manifest-path examples/stm32wba/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32wba \ - --- build --release --manifest-path examples/stm32wba6/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32wba6 \ - --- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32wl \ - --- build --release --manifest-path examples/lpc55s69/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/lpc55s69 \ - --- build --release --manifest-path examples/mimxrt1011/Cargo.toml --target thumbv7em-none-eabihf --artifact-dir out/examples/mimxrt1011 \ - --- build --release --manifest-path examples/mimxrt1062-evk/Cargo.toml --target thumbv7em-none-eabihf --artifact-dir out/examples/mimxrt1062-evk \ - --- build --release --manifest-path examples/mspm0g3507/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3507 \ - --- build --release --manifest-path examples/mspm0g3519/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3519 \ - --- build --release --manifest-path examples/mspm0l1306/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0l1306 \ - --- build --release --manifest-path examples/mspm0l2228/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0l2228 \ - --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840,skip-include --artifact-dir out/examples/boot/nrf52840 \ - --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns,skip-include --artifact-dir out/examples/boot/nrf9160 \ - --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9120-ns,skip-include --artifact-dir out/examples/boot/nrf9120 \ - --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9151-ns,skip-include --artifact-dir out/examples/boot/nrf9151 \ - --- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9161-ns,skip-include --artifact-dir out/examples/boot/nrf9161 \ - --- build --release --manifest-path examples/boot/application/rp/Cargo.toml --target thumbv6m-none-eabi --features skip-include --artifact-dir out/examples/boot/rp \ - --- build --release --manifest-path examples/boot/application/stm32f3/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32f3 \ - --- build --release --manifest-path examples/boot/application/stm32f7/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32f7 \ - --- build --release --manifest-path examples/boot/application/stm32h7/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32h7 \ - --- build --release --manifest-path examples/boot/application/stm32l0/Cargo.toml --target thumbv6m-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32l0 \ - --- build --release --manifest-path examples/boot/application/stm32l1/Cargo.toml --target thumbv7m-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32l1 \ - --- build --release --manifest-path examples/boot/application/stm32l4/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32l4 \ - --- build --release --manifest-path examples/boot/application/stm32wl/Cargo.toml --target thumbv7em-none-eabi --features skip-include --artifact-dir out/examples/boot/stm32wl \ - --- build --release --manifest-path examples/boot/application/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/boot/stm32wb-dfu \ - --- build --release --manifest-path examples/boot/application/stm32wba-dfu/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/boot/stm32wba-dfu \ - --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \ - --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns \ - --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9120-ns \ - --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9151-ns \ - --- build --release --manifest-path examples/boot/bootloader/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9161-ns \ - --- build --release --manifest-path examples/boot/bootloader/rp/Cargo.toml --target thumbv6m-none-eabi \ - --- build --release --manifest-path examples/boot/bootloader/stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32l496zg \ - --- build --release --manifest-path examples/boot/bootloader/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wb55rg \ - --- build --release --manifest-path examples/boot/bootloader/stm32wb-dfu/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wb55rg,verify \ - --- build --release --manifest-path examples/boot/bootloader/stm32wba-dfu/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-stm32/stm32wba65ri,verify \ - --- build --release --manifest-path examples/boot/bootloader/stm32-dual-bank/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32h743zi \ - --- build --release --manifest-path examples/wasm/Cargo.toml --target wasm32-unknown-unknown --artifact-dir out/examples/wasm \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f100rd --artifact-dir out/tests/stm32f100rd \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f103c8 --artifact-dir out/tests/stm32f103c8 \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f107vc --artifact-dir out/tests/stm32f107vc \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi --artifact-dir out/tests/stm32f429zi \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446re --artifact-dir out/tests/stm32f446re \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g491re --artifact-dir out/tests/stm32g491re \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g071rb --artifact-dir out/tests/stm32g071rb \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c031c6 --artifact-dir out/tests/stm32c031c6 \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c071rb --artifact-dir out/tests/stm32c071rb \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi --artifact-dir out/tests/stm32h755zi \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h753zi --artifact-dir out/tests/stm32h753zi \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7a3zi --artifact-dir out/tests/stm32h7a3zi \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55rg --artifact-dir out/tests/stm32wb55rg \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h563zi --artifact-dir out/tests/stm32h563zi \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u585ai --artifact-dir out/tests/stm32u585ai \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32u5a5zj --artifact-dir out/tests/stm32u5a5zj \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32wba52cg --artifact-dir out/tests/stm32wba52cg \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l073rz --artifact-dir out/tests/stm32l073rz \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l152re --artifact-dir out/tests/stm32l152re \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4a6zg --artifact-dir out/tests/stm32l4a6zg \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4r5zi --artifact-dir out/tests/stm32l4r5zi \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze --artifact-dir out/tests/stm32l552ze \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f767zi --artifact-dir out/tests/stm32f767zi \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f207zg --artifact-dir out/tests/stm32f207zg \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303ze --artifact-dir out/tests/stm32f303ze \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l496zg --artifact-dir out/tests/stm32l496zg \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55jc --artifact-dir out/tests/stm32wl55jc \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s3l8 --artifact-dir out/tests/stm32h7s3l8 \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f091rc --artifact-dir out/tests/stm32f091rc \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h503rb --artifact-dir out/tests/stm32h503rb \ - --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u083rc --artifact-dir out/tests/stm32u083rc \ - --- build --release --manifest-path tests/rp/Cargo.toml --target thumbv6m-none-eabi --features rp2040 --artifact-dir out/tests/rpi-pico \ - --- build --release --manifest-path tests/rp/Cargo.toml --target thumbv8m.main-none-eabihf --features rp235xb --artifact-dir out/tests/pimoroni-pico-plus-2 \ - --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv6m-none-eabi --features nrf51422 --artifact-dir out/tests/nrf51422-dk \ - --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52832 --artifact-dir out/tests/nrf52832-dk \ - --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52833 --artifact-dir out/tests/nrf52833-dk \ - --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840 --artifact-dir out/tests/nrf52840-dk \ - --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340 --artifact-dir out/tests/nrf5340-dk \ - --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf9160 --artifact-dir out/tests/nrf9160-dk \ - --- build --release --manifest-path tests/mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g3507 --artifact-dir out/tests/mspm0g3507 \ - --- build --release --manifest-path tests/riscv32/Cargo.toml --target riscv32imac-unknown-none-elf \ - $BUILD_EXTRA - - -# MSPM0C1104 must be built seperately since cargo batch does not consider env vars set in `.cargo/config.toml`. -# Since the target has 1KB of ram, we need to limit defmt's buffer size. -DEFMT_RTT_BUFFER_SIZE="72" cargo batch \ - --- build --release --manifest-path examples/mspm0c1104/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0c1104 \ +cargo embassy-devtool build # temporarily disabled, these boards are dead. rm -rf out/tests/stm32f103c8 diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index d4ea0e6ac..f6dce5c0e 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -35,6 +35,31 @@ build = [ {target = "armv7r-none-eabihf", features = ["arch-cortex-ar", "executor-thread"]}, {target = "riscv32imac-unknown-none-elf", features = ["arch-riscv32"]}, {target = "riscv32imac-unknown-none-elf", features = ["arch-riscv32", "executor-thread"]}, + # Nightly builds + {group = "nightly", target = "thumbv7em-none-eabi", features = ["nightly"]}, + {group = "nightly", target = "thumbv7em-none-eabi", features = ["nightly", "log"]}, + {group = "nightly", target = "thumbv7em-none-eabi", features = ["nightly", "defmt"]}, + {group = "nightly", target = "thumbv6m-none-eabi", features = ["nightly", "defmt"]}, + {group = "nightly", target = "thumbv6m-none-eabi", features = ["nightly", "defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"]}, + {group = "nightly", target = "thumbv7em-none-eabi", features = ["nightly", "arch-cortex-m"]}, + {group = "nightly", target = "thumbv7em-none-eabi", features = ["nightly", "arch-cortex-m", "executor-thread"]}, + {group = "nightly", target = "thumbv7em-none-eabi", features = ["nightly", "arch-cortex-m", "executor-interrupt"]}, + {group = "nightly", target = "thumbv7em-none-eabi", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt"]}, + {group = "nightly", target = "riscv32imac-unknown-none-elf", features = ["nightly", "arch-riscv32"]}, + {group = "nightly", target = "riscv32imac-unknown-none-elf", features = ["nightly", "arch-riscv32", "executor-thread"]}, + {group = "nightly", target = "armv7a-none-eabi", features = ["nightly", "arch-cortex-ar", "executor-thread"]}, + {group = "nightly", target = "avr-none", features = ["nightly", "arch-avr", "avr-device/atmega328p"], build-std = ["core", "alloc"], env = { RUSTFLAGS = "-Ctarget-cpu=atmega328p" }}, + # Xtensa builds + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = []}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["log"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["defmt"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32s2-none-elf", features = ["defmt"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["defmt", "arch-spin", "executor-thread"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32s2-none-elf", features = ["defmt", "arch-spin", "executor-thread"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32s3-none-elf", features = ["defmt", "arch-spin", "executor-thread"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["arch-spin"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["arch-spin", "rtos-trace"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["arch-spin", "executor-thread"]}, ] diff --git a/embassy-net-wiznet/src/chip/mod.rs b/embassy-net-wiznet/src/chip/mod.rs index 6e6e5cb78..47d7c5dc3 100644 --- a/embassy-net-wiznet/src/chip/mod.rs +++ b/embassy-net-wiznet/src/chip/mod.rs @@ -30,6 +30,7 @@ pub(crate) trait SealedChip { const SOCKET_RECVD_SIZE: Self::Address; const SOCKET_RX_DATA_READ_PTR: Self::Address; const SOCKET_INTR_MASK: Self::Address; + #[allow(dead_code)] const SOCKET_INTR: Self::Address; const SOCKET_INTR_CLR: Self::Address; diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index 245626c14..61a2c858a 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -26,6 +26,19 @@ build = [ {target = "thumbv7em-none-eabi", features = ["defmt", "dns", "medium-ip", "proto-ipv4", "proto-ipv6", "tcp", "udp"]}, {target = "thumbv7em-none-eabi", features = ["defmt", "dns", "medium-ethernet", "medium-ip", "proto-ipv4", "proto-ipv6", "tcp", "udp"]}, {target = "thumbv7em-none-eabi", features = ["defmt", "dns", "medium-ethernet", "medium-ieee802154", "medium-ip", "proto-ipv4", "proto-ipv6", "tcp", "udp"]}, + # Xtensa builds + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["defmt", "tcp", "udp", "dns", "proto-ipv4", "medium-ethernet", "packet-trace"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["defmt", "tcp", "udp", "dns", "proto-ipv4", "multicast", "medium-ethernet"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["defmt", "tcp", "udp", "dns", "dhcpv4", "medium-ethernet"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["defmt", "tcp", "udp", "dns", "dhcpv4", "medium-ethernet", "dhcpv4-hostname"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["defmt", "tcp", "udp", "dns", "proto-ipv6", "medium-ethernet"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["defmt", "tcp", "udp", "dns", "proto-ipv6", "medium-ieee802154"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["defmt", "tcp", "udp", "dns", "proto-ipv6", "medium-ethernet", "medium-ieee802154"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["defmt", "tcp", "udp", "dns", "proto-ipv6", "medium-ethernet"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["defmt", "tcp", "udp", "dns", "proto-ipv4", "proto-ipv6", "medium-ethernet"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["defmt", "tcp", "udp", "dns", "proto-ipv4", "proto-ipv6", "medium-ip"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["defmt", "tcp", "udp", "dns", "proto-ipv4", "proto-ipv6", "medium-ip", "medium-ethernet"]}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32-none-elf", features = ["defmt", "tcp", "udp", "dns", "proto-ipv4", "proto-ipv6", "medium-ip", "medium-ethernet", "medium-ieee802154"]}, ] [package.metadata.embassy_docs] diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml index 30a27c13f..6494da727 100644 --- a/embassy-sync/Cargo.toml +++ b/embassy-sync/Cargo.toml @@ -17,6 +17,8 @@ categories = [ [package.metadata.embassy] build = [ {target = "thumbv6m-none-eabi", features = ["defmt"]}, + # Xtensa builds + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32s2-none-elf", features = ["defmt"]}, ] [package.metadata.embassy_docs] diff --git a/embassy-time-queue-utils/Cargo.toml b/embassy-time-queue-utils/Cargo.toml index e1abf1cd8..13da62874 100644 --- a/embassy-time-queue-utils/Cargo.toml +++ b/embassy-time-queue-utils/Cargo.toml @@ -56,6 +56,9 @@ _generic-queue = [] build = [ {target = "thumbv6m-none-eabi", features = []}, {target = "thumbv6m-none-eabi", features = ["generic-queue-8"]}, + # Xtensa builds + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32s2-none-elf", features = []}, + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32s2-none-elf", features = ["generic-queue-8"]}, ] [package.metadata.embassy_docs] diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index 6ebf0a468..2d7c3c1fa 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml @@ -17,6 +17,8 @@ categories = [ [package.metadata.embassy] build = [ {target = "thumbv6m-none-eabi", features = ["defmt", "defmt-timestamp-uptime", "mock-driver"]}, + # Xtensa builds + {group = "xtensa", build-std = ["core", "alloc"], target = "xtensa-esp32s2-none-elf", features = ["defmt", "defmt-timestamp-uptime", "mock-driver"]}, ] [package.metadata.embassy_docs] diff --git a/examples/mspm0c1104/Cargo.toml b/examples/mspm0c1104/Cargo.toml index 4daddbbb4..21434106a 100644 --- a/examples/mspm0c1104/Cargo.toml +++ b/examples/mspm0c1104/Cargo.toml @@ -33,7 +33,6 @@ lto = true codegen-units = 1 [package.metadata.embassy] -skip = true # TODO: remove when we find a way to decrease the defmt buffer size in ci. build = [ - { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0c1104" } + { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0c1104", env = { DEFMT_RTT_BUFFER_SIZE = "72" }} ] diff --git a/examples/nrf52840-rtic/src/bin/blinky.rs b/examples/nrf52840-rtic/src/bin/blinky.rs index 719e22729..2adac7e0a 100644 --- a/examples/nrf52840-rtic/src/bin/blinky.rs +++ b/examples/nrf52840-rtic/src/bin/blinky.rs @@ -1,6 +1,5 @@ #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use {defmt_rtt as _, panic_probe as _}; -- cgit From 19bb3668669710dbd1d17dc5fb0dee6d915f012e Mon Sep 17 00:00:00 2001 From: Roi Bachynskyi Date: Sat, 30 Aug 2025 14:25:25 +0300 Subject: lpc55: gpio rewritten --- embassy-nxp/Cargo.toml | 6 +- embassy-nxp/src/chips/lpc55.rs | 2 +- embassy-nxp/src/gpio/lpc55.rs | 360 +++++------------------------------------ 3 files changed, 44 insertions(+), 324 deletions(-) diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index ab0bfbfd7..c66354ee2 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -37,13 +37,13 @@ embedded-io = "0.6.1" embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } ## Chip dependencies lpc55-pac = { version = "0.5.0", optional = true } -nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/i509VCB/nxp-pac", rev = "be4dd0936c20d5897364a381b1d95a99514c1e7e" } +nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/IrinaCh524/nxp-pac", rev = "d452e366105012ddd8ba332a9ab86e1931508235" } imxrt-rt = { version = "0.1.7", optional = true, features = ["device"] } [build-dependencies] cfg_aliases = "0.2.1" -nxp-pac = { version = "0.1.0", git = "https://github.com/i509VCB/nxp-pac", rev = "be4dd0936c20d5897364a381b1d95a99514c1e7e", features = ["metadata"], optional = true } +nxp-pac = { version = "0.1.0", git = "https://github.com/IrinaCh524/nxp-pac", rev = "d452e366105012ddd8ba332a9ab86e1931508235", features = ["metadata"], optional = true } proc-macro2 = "1.0.95" quote = "1.0.15" @@ -79,6 +79,6 @@ _rt1xxx = [] _time_driver = ["dep:embassy-time-driver", "dep:embassy-time-queue-utils"] #! ### Chip selection features -lpc55 = ["dep:lpc55-pac"] +lpc55 = ["nxp-pac/lpc55s69_core0"] mimxrt1011 = ["nxp-pac/mimxrt1011", "_rt1xxx", "dep:imxrt-rt"] mimxrt1062 = ["nxp-pac/mimxrt1062", "_rt1xxx", "dep:imxrt-rt"] diff --git a/embassy-nxp/src/chips/lpc55.rs b/embassy-nxp/src/chips/lpc55.rs index e168ced00..711bff3e7 100644 --- a/embassy-nxp/src/chips/lpc55.rs +++ b/embassy-nxp/src/chips/lpc55.rs @@ -1,4 +1,4 @@ -pub use lpc55_pac as pac; +pub use nxp_pac as pac; embassy_hal_internal::peripherals! { // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other diff --git a/embassy-nxp/src/gpio/lpc55.rs b/embassy-nxp/src/gpio/lpc55.rs index 8f407bb3a..36ea99d21 100644 --- a/embassy-nxp/src/gpio/lpc55.rs +++ b/embassy-nxp/src/gpio/lpc55.rs @@ -1,12 +1,17 @@ use embassy_hal_internal::{impl_peripheral, PeripheralType}; +use crate::pac::iocon::vals::{PioDigimode, PioMode}; +use crate::pac::{GPIO, IOCON, SYSCON}; use crate::{peripherals, Peri}; pub(crate) fn init() { // Enable clocks for GPIO, PINT, and IOCON - syscon_reg() - .ahbclkctrl0 - .modify(|_, w| w.gpio0().enable().gpio1().enable().mux().enable().iocon().enable()); + SYSCON.ahbclkctrl0().modify(|w| { + w.set_gpio0(true); + w.set_gpio1(true); + w.set_mux(true); + w.set_iocon(true); + }); info!("GPIO initialized"); } @@ -59,21 +64,24 @@ impl<'d> Output<'d> { } pub fn set_high(&mut self) { - gpio_reg().set[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) + GPIO.set(self.pin.pin_bank() as usize) + .write(|w| w.set_setp(self.pin.bit())); } pub fn set_low(&mut self) { - gpio_reg().clr[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) + GPIO.clr(self.pin.pin_bank() as usize) + .write(|w| w.set_clrp(self.pin.bit())); } pub fn toggle(&mut self) { - gpio_reg().not[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) + GPIO.not(self.pin.pin_bank() as usize) + .write(|w| w.set_notp(self.pin.bit())); } /// Get the current output level of the pin. Note that the value returned by this function is /// the voltage level reported by the pin, not the value set by the output driver. pub fn level(&self) -> Level { - let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits(); + let bits = GPIO.pin(self.pin.pin_bank() as usize).read().port(); if bits & self.pin.bit() != 0 { Level::High } else { @@ -101,18 +109,18 @@ impl<'d> Input<'d> { /// Set the pull configuration for the pin. To disable the pull, use [Pull::None]. pub fn set_pull(&mut self, pull: Pull) { - match_iocon!(register, iocon_reg(), self.pin.pin_bank(), self.pin.pin_number(), { - register.modify(|_, w| match pull { - Pull::None => w.mode().inactive(), - Pull::Up => w.mode().pull_up(), - Pull::Down => w.mode().pull_down(), + match_iocon!(register, self.pin.pin_bank(), self.pin.pin_number(), { + register.modify(|w| match pull { + Pull::None => w.set_mode(PioMode::INACTIVE), + Pull::Up => w.set_mode(PioMode::PULL_UP), + Pull::Down => w.set_mode(PioMode::PULL_DOWN), }); }); } /// Get the current input level of the pin. pub fn read(&self) -> Level { - let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits(); + let bits = GPIO.pin(self.pin.pin_bank() as usize).read().port(); if bits & self.pin.bit() != 0 { Level::High } else { @@ -188,8 +196,8 @@ impl<'d> Flex<'d> { /// Set the pin to digital mode. This is required for using a pin as a GPIO pin. The default /// setting for pins is (usually) non-digital. fn set_as_digital(&mut self) { - match_iocon!(register, iocon_reg(), self.pin_bank(), self.pin_number(), { - register.modify(|_, w| w.digimode().digital()); + match_iocon!(register, self.pin_bank(), self.pin_number(), { + register.modify(|w| w.set_digimode(PioDigimode::DIGITAL)); }); } @@ -197,12 +205,14 @@ impl<'d> Flex<'d> { /// function handles itself. pub fn set_as_output(&mut self) { self.set_as_digital(); - gpio_reg().dirset[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirsetp().bits(self.bit()) }) + GPIO.dirset(self.pin.pin_bank() as usize) + .write(|w| w.set_dirsetp(self.bit())) } pub fn set_as_input(&mut self) { self.set_as_digital(); - gpio_reg().dirclr[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirclrp().bits(self.bit()) }) + GPIO.dirclr(self.pin.pin_bank() as usize) + .write(|w| w.set_dirclrp(self.bit())) } } @@ -262,52 +272,6 @@ impl SealedPin for AnyPin { } } -/// Get the GPIO register block. This is used to configure all GPIO pins. -/// -/// # Safety -/// Due to the type system of peripherals, access to the settings of a single pin is possible only -/// by a single thread at a time. Read/Write operations on a single registers are NOT atomic. You -/// must ensure that the GPIO registers are not accessed concurrently by multiple threads. -pub(crate) fn gpio_reg() -> &'static lpc55_pac::gpio::RegisterBlock { - unsafe { &*lpc55_pac::GPIO::ptr() } -} - -/// Get the IOCON register block. -/// -/// # Safety -/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO -/// registers are not accessed concurrently by multiple threads. -pub(crate) fn iocon_reg() -> &'static lpc55_pac::iocon::RegisterBlock { - unsafe { &*lpc55_pac::IOCON::ptr() } -} - -/// Get the INPUTMUX register block. -/// -/// # Safety -/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO -/// registers are not accessed concurrently by multiple threads. -pub(crate) fn inputmux_reg() -> &'static lpc55_pac::inputmux::RegisterBlock { - unsafe { &*lpc55_pac::INPUTMUX::ptr() } -} - -/// Get the SYSCON register block. -/// -/// # Safety -/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO -/// registers are not accessed concurrently by multiple threads. -pub(crate) fn syscon_reg() -> &'static lpc55_pac::syscon::RegisterBlock { - unsafe { &*lpc55_pac::SYSCON::ptr() } -} - -/// Get the PINT register block. -/// -/// # Safety -/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO -/// registers are not accessed concurrently by multiple threads. -pub(crate) fn pint_reg() -> &'static lpc55_pac::pint::RegisterBlock { - unsafe { &*lpc55_pac::PINT::ptr() } -} - /// Match the pin bank and number of a pin to the corresponding IOCON register. /// /// # Example @@ -316,270 +280,26 @@ pub(crate) fn pint_reg() -> &'static lpc55_pac::pint::RegisterBlock { /// use embassy_nxp::pac_utils::{iocon_reg, match_iocon}; /// /// // Make pin PIO1_6 digital and set it to pull-down mode. -/// match_iocon!(register, iocon_reg(), Bank::Bank1, 6, { -/// register.modify(|_, w| w.mode().pull_down().digimode().digital()); +/// match_iocon!(register, Bank::Bank1, 6, { +/// register.modify(|w|{ +/// w.set_mode(PioMode::PULL_DOWN); +/// w.set_digimode(PioDigimode::DIGITAL); +/// +/// } /// }); /// ``` macro_rules! match_iocon { - ($register:ident, $iocon_register:expr, $pin_bank:expr, $pin_number:expr, $action:expr) => { - match ($pin_bank, $pin_number) { - (Bank::Bank0, 0) => { - let $register = &($iocon_register).pio0_0; - $action; - } - (Bank::Bank0, 1) => { - let $register = &($iocon_register).pio0_1; - $action; - } - (Bank::Bank0, 2) => { - let $register = &($iocon_register).pio0_2; - $action; - } - (Bank::Bank0, 3) => { - let $register = &($iocon_register).pio0_3; - $action; - } - (Bank::Bank0, 4) => { - let $register = &($iocon_register).pio0_4; - $action; - } - (Bank::Bank0, 5) => { - let $register = &($iocon_register).pio0_5; - $action; - } - (Bank::Bank0, 6) => { - let $register = &($iocon_register).pio0_6; - $action; - } - (Bank::Bank0, 7) => { - let $register = &($iocon_register).pio0_7; - $action; - } - (Bank::Bank0, 8) => { - let $register = &($iocon_register).pio0_8; - $action; - } - (Bank::Bank0, 9) => { - let $register = &($iocon_register).pio0_9; - $action; - } - (Bank::Bank0, 10) => { - let $register = &($iocon_register).pio0_10; + ($register:ident, $pin_bank:expr, $pin_number:expr, $action:expr) => { + match $pin_bank { + Bank::Bank0 => { + let $register = IOCON.pio0($pin_number as usize); $action; } - (Bank::Bank0, 11) => { - let $register = &($iocon_register).pio0_11; - $action; - } - (Bank::Bank0, 12) => { - let $register = &($iocon_register).pio0_12; - $action; - } - (Bank::Bank0, 13) => { - let $register = &($iocon_register).pio0_13; - $action; - } - (Bank::Bank0, 14) => { - let $register = &($iocon_register).pio0_14; - $action; - } - (Bank::Bank0, 15) => { - let $register = &($iocon_register).pio0_15; - $action; - } - (Bank::Bank0, 16) => { - let $register = &($iocon_register).pio0_16; - $action; - } - (Bank::Bank0, 17) => { - let $register = &($iocon_register).pio0_17; - $action; - } - (Bank::Bank0, 18) => { - let $register = &($iocon_register).pio0_18; - $action; - } - (Bank::Bank0, 19) => { - let $register = &($iocon_register).pio0_19; - $action; - } - (Bank::Bank0, 20) => { - let $register = &($iocon_register).pio0_20; - $action; - } - (Bank::Bank0, 21) => { - let $register = &($iocon_register).pio0_21; - $action; - } - (Bank::Bank0, 22) => { - let $register = &($iocon_register).pio0_22; - $action; - } - (Bank::Bank0, 23) => { - let $register = &($iocon_register).pio0_23; - $action; - } - (Bank::Bank0, 24) => { - let $register = &($iocon_register).pio0_24; - $action; - } - (Bank::Bank0, 25) => { - let $register = &($iocon_register).pio0_25; - $action; - } - (Bank::Bank0, 26) => { - let $register = &($iocon_register).pio0_26; - $action; - } - (Bank::Bank0, 27) => { - let $register = &($iocon_register).pio0_27; - $action; - } - (Bank::Bank0, 28) => { - let $register = &($iocon_register).pio0_28; - $action; - } - (Bank::Bank0, 29) => { - let $register = &($iocon_register).pio0_29; - $action; - } - (Bank::Bank0, 30) => { - let $register = &($iocon_register).pio0_30; - $action; - } - (Bank::Bank0, 31) => { - let $register = &($iocon_register).pio0_31; - $action; - } - (Bank::Bank1, 0) => { - let $register = &($iocon_register).pio1_0; - $action; - } - (Bank::Bank1, 1) => { - let $register = &($iocon_register).pio1_1; - $action; - } - (Bank::Bank1, 2) => { - let $register = &($iocon_register).pio1_2; - $action; - } - (Bank::Bank1, 3) => { - let $register = &($iocon_register).pio1_3; - $action; - } - (Bank::Bank1, 4) => { - let $register = &($iocon_register).pio1_4; - $action; - } - (Bank::Bank1, 5) => { - let $register = &($iocon_register).pio1_5; - $action; - } - (Bank::Bank1, 6) => { - let $register = &($iocon_register).pio1_6; - $action; - } - (Bank::Bank1, 7) => { - let $register = &($iocon_register).pio1_7; - $action; - } - (Bank::Bank1, 8) => { - let $register = &($iocon_register).pio1_8; - $action; - } - (Bank::Bank1, 9) => { - let $register = &($iocon_register).pio1_9; - $action; - } - (Bank::Bank1, 10) => { - let $register = &($iocon_register).pio1_10; - $action; - } - (Bank::Bank1, 11) => { - let $register = &($iocon_register).pio1_11; - $action; - } - (Bank::Bank1, 12) => { - let $register = &($iocon_register).pio1_12; - $action; - } - (Bank::Bank1, 13) => { - let $register = &($iocon_register).pio1_13; - $action; - } - (Bank::Bank1, 14) => { - let $register = &($iocon_register).pio1_14; - $action; - } - (Bank::Bank1, 15) => { - let $register = &($iocon_register).pio1_15; - $action; - } - (Bank::Bank1, 16) => { - let $register = &($iocon_register).pio1_16; - $action; - } - (Bank::Bank1, 17) => { - let $register = &($iocon_register).pio1_17; - $action; - } - (Bank::Bank1, 18) => { - let $register = &($iocon_register).pio1_18; - $action; - } - (Bank::Bank1, 19) => { - let $register = &($iocon_register).pio1_19; - $action; - } - (Bank::Bank1, 20) => { - let $register = &($iocon_register).pio1_20; - $action; - } - (Bank::Bank1, 21) => { - let $register = &($iocon_register).pio1_21; - $action; - } - (Bank::Bank1, 22) => { - let $register = &($iocon_register).pio1_22; - $action; - } - (Bank::Bank1, 23) => { - let $register = &($iocon_register).pio1_23; - $action; - } - (Bank::Bank1, 24) => { - let $register = &($iocon_register).pio1_24; - $action; - } - (Bank::Bank1, 25) => { - let $register = &($iocon_register).pio1_25; - $action; - } - (Bank::Bank1, 26) => { - let $register = &($iocon_register).pio1_26; - $action; - } - (Bank::Bank1, 27) => { - let $register = &($iocon_register).pio1_27; - $action; - } - (Bank::Bank1, 28) => { - let $register = &($iocon_register).pio1_28; - $action; - } - (Bank::Bank1, 29) => { - let $register = &($iocon_register).pio1_29; - $action; - } - (Bank::Bank1, 30) => { - let $register = &($iocon_register).pio1_30; - $action; - } - (Bank::Bank1, 31) => { - let $register = &($iocon_register).pio1_31; + + Bank::Bank1 => { + let $register = IOCON.pio1($pin_number as usize); $action; } - _ => unreachable!(), } }; } -- cgit From f58d2ceda1abcb44cd8e02c24316433ab4777b2c Mon Sep 17 00:00:00 2001 From: Roi Bachynskyi Date: Sun, 31 Aug 2025 20:08:35 +0300 Subject: lpc55: pint rewritten --- embassy-nxp/src/pint.rs | 97 +++++++++++++++++-------------------------------- 1 file changed, 33 insertions(+), 64 deletions(-) diff --git a/embassy-nxp/src/pint.rs b/embassy-nxp/src/pint.rs index ff414b4e6..e594aaa6a 100644 --- a/embassy-nxp/src/pint.rs +++ b/embassy-nxp/src/pint.rs @@ -5,10 +5,11 @@ use core::pin::Pin as FuturePin; use core::task::{Context, Poll}; use critical_section::Mutex; +use embassy_hal_internal::interrupt::InterruptExt; use embassy_sync::waitqueue::AtomicWaker; -use crate::gpio::{self, inputmux_reg, pint_reg, syscon_reg, AnyPin, Level, SealedPin}; -use crate::pac::interrupt; +use crate::gpio::{self, AnyPin, Level, SealedPin}; +use crate::pac::{interrupt, INPUTMUX, PINT, SYSCON}; use crate::Peri; struct PinInterrupt { @@ -88,18 +89,18 @@ enum InterruptOn { } pub(crate) fn init() { - syscon_reg().ahbclkctrl0.modify(|_, w| w.pint().enable()); + SYSCON.ahbclkctrl0().modify(|w| w.set_pint(true)); // Enable interrupts unsafe { - crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT0); - crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT1); - crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT2); - crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT3); - crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT4); - crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT5); - crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT6); - crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT7); + interrupt::PIN_INT0.enable(); + interrupt::PIN_INT1.enable(); + interrupt::PIN_INT2.enable(); + interrupt::PIN_INT3.enable(); + interrupt::PIN_INT4.enable(); + interrupt::PIN_INT5.enable(); + interrupt::PIN_INT6.enable(); + interrupt::PIN_INT7.enable(); }; info!("Pin interrupts initialized"); @@ -119,24 +120,19 @@ impl<'d> InputFuture<'d> { let interrupt_number = next_available_interrupt()?; // Clear interrupt, just in case - pint_reg() - .rise - .write(|w| unsafe { w.rdet().bits(1 << interrupt_number) }); - pint_reg() - .fall - .write(|w| unsafe { w.fdet().bits(1 << interrupt_number) }); + PINT.rise().write(|w| w.set_rdet(1 << interrupt_number)); + PINT.fall().write(|w| w.set_fdet(1 << interrupt_number)); // Enable input multiplexing on pin interrupt register 0 for pin (32*bank + pin_number) - inputmux_reg().pintsel[interrupt_number] - .write(|w| unsafe { w.intpin().bits(32 * pin.pin_bank() as u8 + pin.pin_number()) }); + INPUTMUX + .pintsel(interrupt_number as usize) + .write(|w| w.set_intpin(32 * pin.pin_bank() as u8 + pin.pin_number())); match interrupt_on { InterruptOn::Level(level) => { // Set pin interrupt register to edge sensitive or level sensitive // 0 = edge sensitive, 1 = level sensitive - pint_reg() - .isel - .modify(|r, w| unsafe { w.bits(r.bits() | (1 << interrupt_number)) }); + PINT.isel().modify(|w| w.set_pmode(w.pmode() | (1 << interrupt_number))); // Enable level interrupt. // @@ -144,63 +140,44 @@ impl<'d> InputFuture<'d> { // is activated. // 0 = no-op, 1 = enable - pint_reg() - .sienr - .write(|w| unsafe { w.setenrl().bits(1 << interrupt_number) }); + PINT.sienr().write(|w| w.set_setenrl(1 << interrupt_number)); // Set active level match level { Level::Low => { // 0 = no-op, 1 = select LOW - pint_reg() - .cienf - .write(|w| unsafe { w.cenaf().bits(1 << interrupt_number) }); + PINT.cienf().write(|w| w.set_cenaf(1 << interrupt_number)); } Level::High => { // 0 = no-op, 1 = select HIGH - pint_reg() - .sienf - .write(|w| unsafe { w.setenaf().bits(1 << interrupt_number) }); + PINT.sienf().write(|w| w.set_setenaf(1 << interrupt_number)); } } } InterruptOn::Edge(edge) => { // Set pin interrupt register to edge sensitive or level sensitive // 0 = edge sensitive, 1 = level sensitive - pint_reg() - .isel - .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << interrupt_number)) }); + PINT.isel() + .modify(|w| w.set_pmode(w.pmode() & !(1 << interrupt_number))); // Enable rising/falling edge detection match edge { Edge::Rising => { // 0 = no-op, 1 = enable rising edge - pint_reg() - .sienr - .write(|w| unsafe { w.setenrl().bits(1 << interrupt_number) }); + PINT.sienr().write(|w| w.set_setenrl(1 << interrupt_number)); // 0 = no-op, 1 = disable falling edge - pint_reg() - .cienf - .write(|w| unsafe { w.cenaf().bits(1 << interrupt_number) }); + PINT.cienf().write(|w| w.set_cenaf(1 << interrupt_number)); } Edge::Falling => { // 0 = no-op, 1 = enable falling edge - pint_reg() - .sienf - .write(|w| unsafe { w.setenaf().bits(1 << interrupt_number) }); + PINT.sienf().write(|w| w.set_setenaf(1 << interrupt_number)); // 0 = no-op, 1 = disable rising edge - pint_reg() - .cienr - .write(|w| unsafe { w.cenrl().bits(1 << interrupt_number) }); + PINT.cienr().write(|w| w.set_cenrl(1 << interrupt_number)); } Edge::Both => { // 0 = no-op, 1 = enable - pint_reg() - .sienr - .write(|w| unsafe { w.setenrl().bits(1 << interrupt_number) }); - pint_reg() - .sienf - .write(|w| unsafe { w.setenaf().bits(1 << interrupt_number) }); + PINT.sienr().write(|w| w.set_setenrl(1 << interrupt_number)); + PINT.sienf().write(|w| w.set_setenaf(1 << interrupt_number)); } } } @@ -239,12 +216,8 @@ impl<'d> Drop for InputFuture<'d> { // Disable pin interrupt // 0 = no-op, 1 = disable - pint_reg() - .cienr - .write(|w| unsafe { w.cenrl().bits(1 << interrupt_number) }); - pint_reg() - .cienf - .write(|w| unsafe { w.cenaf().bits(1 << interrupt_number) }); + PINT.cienr().write(|w| w.set_cenrl(1 << interrupt_number)); + PINT.cienf().write(|w| w.set_cenaf(1 << interrupt_number)); critical_section::with(|cs| { let mut pin_interrupts = PIN_INTERRUPTS.borrow(cs).borrow_mut(); @@ -277,12 +250,8 @@ impl<'d> Future for InputFuture<'d> { } fn handle_interrupt(interrupt_number: usize) { - pint_reg() - .rise - .write(|w| unsafe { w.rdet().bits(1 << interrupt_number) }); - pint_reg() - .fall - .write(|w| unsafe { w.fdet().bits(1 << interrupt_number) }); + PINT.rise().write(|w| w.set_rdet(1 << interrupt_number)); + PINT.fall().write(|w| w.set_fdet(1 << interrupt_number)); critical_section::with(|cs| { let mut pin_interrupts = PIN_INTERRUPTS.borrow(cs).borrow_mut(); -- cgit From e74dbe8c5d625f17c0bcee82aa8a2d45deb33a18 Mon Sep 17 00:00:00 2001 From: Roi Bachynskyi Date: Mon, 1 Sep 2025 23:19:24 +0300 Subject: lpc55: blocking usart rewritten --- embassy-nxp/src/usart.rs | 1 - embassy-nxp/src/usart/lpc55.rs | 884 ++++++++++++++++------------------------- 2 files changed, 332 insertions(+), 553 deletions(-) diff --git a/embassy-nxp/src/usart.rs b/embassy-nxp/src/usart.rs index 009c251e2..c426ab96d 100644 --- a/embassy-nxp/src/usart.rs +++ b/embassy-nxp/src/usart.rs @@ -1,5 +1,4 @@ //! Universal Synchronous/Asynchronous Receiver/Transmitter (USART) driver. -#![macro_use] #[cfg_attr(feature = "lpc55", path = "./usart/lpc55.rs")] mod inner; diff --git a/embassy-nxp/src/usart/lpc55.rs b/embassy-nxp/src/usart/lpc55.rs index 3f7456a2e..428b80c4b 100644 --- a/embassy-nxp/src/usart/lpc55.rs +++ b/embassy-nxp/src/usart/lpc55.rs @@ -2,9 +2,12 @@ use core::marker::PhantomData; use embassy_hal_internal::{Peri, PeripheralType}; use embedded_io::{self, ErrorKind}; -pub use sealed::SealedInstance; -use crate::gpio::AnyPin; +use crate::gpio::{match_iocon, AnyPin, Bank, SealedPin}; +use crate::pac::flexcomm::Flexcomm as FlexcommReg; +use crate::pac::iocon::vals::PioFunc; +use crate::pac::usart::Usart as UsartReg; +use crate::pac::*; use crate::{Blocking, Mode}; /// Serial error @@ -47,16 +50,6 @@ pub enum DataBits { DataBits9, } -impl DataBits { - fn bits(&self) -> u8 { - match self { - Self::DataBits7 => 0b00, - Self::DataBits8 => 0b01, - Self::DataBits9 => 0b10, - } - } -} - /// Parity bit. #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum Parity { @@ -68,16 +61,6 @@ pub enum Parity { ParityOdd, } -impl Parity { - fn bits(&self) -> u8 { - match self { - Self::ParityNone => 0b00, - Self::ParityEven => 0b10, - Self::ParityOdd => 0b11, - } - } -} - /// Stop bits. #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum StopBits { @@ -87,15 +70,6 @@ pub enum StopBits { Stop2, } -impl StopBits { - fn bits(&self) -> bool { - return match self { - Self::Stop1 => false, - Self::Stop2 => true, - }; - } -} - /// UART config. #[non_exhaustive] #[derive(Clone, Debug)] @@ -117,7 +91,7 @@ pub struct Config { impl Default for Config { fn default() -> Self { Self { - baudrate: 9600, + baudrate: 115200, data_bits: DataBits::DataBits8, stop_bits: StopBits::Stop1, parity: Parity::ParityNone, @@ -131,59 +105,72 @@ impl Default for Config { /// 'd: the lifetime marker ensuring correct borrow checking for peripherals used at compile time /// T: the peripheral instance type allowing usage of peripheral specific registers /// M: the operating mode of USART peripheral -pub struct Usart<'d, T: Instance, M: Mode> { - tx: UsartTx<'d, T, M>, - rx: UsartRx<'d, T, M>, +pub struct Usart<'d, M: Mode> { + tx: UsartTx<'d, M>, + rx: UsartRx<'d, M>, } -pub struct UsartTx<'d, T: Instance, M: Mode> { - phantom: PhantomData<(&'d (), T, M)>, +pub struct UsartTx<'d, M: Mode> { + info: &'static Info, + phantom: PhantomData<(&'d (), M)>, } -pub struct UsartRx<'d, T: Instance, M: Mode> { - phantom: PhantomData<(&'d (), T, M)>, +pub struct UsartRx<'d, M: Mode> { + info: &'static Info, + phantom: PhantomData<(&'d (), M)>, } -impl<'d, T: Instance, M: Mode> UsartTx<'d, T, M> { - pub fn new(_usart: Peri<'d, T>, tx: Peri<'d, impl TxPin>, config: Config) -> Self { - Usart::::init(Some(tx.into()), None, config); - Self::new_inner() +impl<'d, M: Mode> UsartTx<'d, M> { + pub fn new(_usart: Peri<'d, T>, tx: Peri<'d, impl TxPin>, config: Config) -> Self { + Usart::::init::(Some(tx.into()), None, config); + Self::new_inner(T::info()) } #[inline] - fn new_inner() -> Self { - Self { phantom: PhantomData } + fn new_inner(info: &'static Info) -> Self { + Self { + info, + phantom: PhantomData, + } } pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { - T::blocking_write(buffer) + for &b in buffer { + while !(self.info.usart_reg.fifostat().read().txnotfull()) {} + self.info.usart_reg.fifowr().write(|w| w.set_txdata(b as u16)); + } + Ok(()) } pub fn blocking_flush(&mut self) -> Result<(), Error> { - T::blocking_flush() + while !(self.info.usart_reg.fifostat().read().txempty()) {} + Ok(()) } pub fn tx_busy(&self) -> bool { - T::tx_busy() + !(self.info.usart_reg.fifostat().read().txempty()) } } -impl<'d, T: Instance> UsartTx<'d, T, Blocking> { - pub fn new_blocking(_usart: Peri<'d, T>, tx: Peri<'d, impl TxPin>, config: Config) -> Self { - Usart::::init(Some(tx.into()), None, config); - Self::new_inner() +impl<'d> UsartTx<'d, Blocking> { + pub fn new_blocking(_usart: Peri<'d, T>, tx: Peri<'d, impl TxPin>, config: Config) -> Self { + Usart::::init::(Some(tx.into()), None, config); + Self::new_inner(T::info()) } } -impl<'d, T: Instance, M: Mode> UsartRx<'d, T, M> { - pub fn new(_usart: Peri<'d, T>, rx: Peri<'d, impl RxPin>, config: Config) -> Self { - Usart::::init(None, Some(rx.into()), config); - Self::new_inner() +impl<'d, M: Mode> UsartRx<'d, M> { + pub fn new(_usart: Peri<'d, T>, rx: Peri<'d, impl RxPin>, config: Config) -> Self { + Usart::::init::(None, Some(rx.into()), config); + Self::new_inner(T::info()) } #[inline] - fn new_inner() -> Self { - Self { phantom: PhantomData } + fn new_inner(info: &'static Info) -> Self { + Self { + info, + phantom: PhantomData, + } } pub fn blocking_read(&mut self, mut buffer: &mut [u8]) -> Result<(), Error> { @@ -201,19 +188,35 @@ impl<'d, T: Instance, M: Mode> UsartRx<'d, T, M> { /// - Ok(n) -> read n bytes /// - Err(n, Error) -> read n-1 bytes, but encountered an error while reading nth byte fn drain_fifo(&mut self, buffer: &mut [u8]) -> Result { - T::drain_fifo(buffer) + for (i, b) in buffer.iter_mut().enumerate() { + while !(self.info.usart_reg.fifostat().read().rxnotempty()) {} + if self.info.usart_reg.fifostat().read().rxerr() { + return Err((i, Error::Overrun)); + } else if self.info.usart_reg.fifordnopop().read().parityerr() { + return Err((i, Error::Parity)); + } else if self.info.usart_reg.fifordnopop().read().framerr() { + return Err((i, Error::Framing)); + } else if self.info.usart_reg.fifordnopop().read().rxnoise() { + return Err((i, Error::Noise)); + } else if self.info.usart_reg.intstat().read().deltarxbrk() { + return Err((i, Error::Break)); + } + let dr = self.info.usart_reg.fiford().read().rxdata() as u8; + *b = dr; + } + Ok(buffer.len()) } } -impl<'d, T: Instance> UsartRx<'d, T, Blocking> { - pub fn new_blocking(_usart: Peri<'d, T>, rx: Peri<'d, impl RxPin>, config: Config) -> Self { - Usart::::init(None, Some(rx.into()), config); - Self::new_inner() +impl<'d> UsartRx<'d, Blocking> { + pub fn new_blocking(_usart: Peri<'d, T>, rx: Peri<'d, impl RxPin>, config: Config) -> Self { + Usart::::init::(None, Some(rx.into()), config); + Self::new_inner(T::info()) } } -impl<'d, T: Instance> Usart<'d, T, Blocking> { - pub fn new_blocking( +impl<'d> Usart<'d, Blocking> { + pub fn new_blocking( usart: Peri<'d, T>, tx: Peri<'d, impl TxPin>, rx: Peri<'d, impl RxPin>, @@ -223,29 +226,70 @@ impl<'d, T: Instance> Usart<'d, T, Blocking> { } } -impl<'d, T: Instance, M: Mode> Usart<'d, T, M> { - fn new_inner(_usart: Peri<'d, T>, mut tx: Peri<'d, AnyPin>, mut rx: Peri<'d, AnyPin>, config: Config) -> Self { - Self::init(Some(tx.reborrow()), Some(rx.reborrow()), config); +impl<'d, M: Mode> Usart<'d, M> { + fn new_inner( + _usart: Peri<'d, T>, + mut tx: Peri<'d, AnyPin>, + mut rx: Peri<'d, AnyPin>, + config: Config, + ) -> Self { + Self::init::(Some(tx.reborrow()), Some(rx.reborrow()), config); Self { - tx: UsartTx::new_inner(), - rx: UsartRx::new_inner(), + tx: UsartTx::new_inner(T::info()), + rx: UsartRx::new_inner(T::info()), } } - fn init(_tx: Option>, _rx: Option>, config: Config) { - T::enable_clock(); - T::reset_flexcomm(); - let source_clock: u32 = T::select_clock(config.baudrate); - T::configure_flexcomm(); - T::tx_pin_config(); - T::rx_pin_config(); - Self::set_baudrate(source_clock, config.baudrate); - T::configure_usart(config); - T::disable_dma(); - T::enable_usart(); + fn init(tx: Option>, rx: Option>, config: Config) { + Self::configure_flexcomm(T::info().fc_reg, T::instance_number()); + Self::configure_clock::(&config); + Self::pin_config::(tx, rx); + Self::configure_usart(T::info(), &config); } - fn set_baudrate(source_clock: u32, baudrate: u32) { + fn configure_clock(config: &Config) { + // Select source clock + + // Adaptive clock choice based on baud rate + // To get the desired baud rate, it is essential to choose the clock bigger than baud rate so that it can be 'chiseled' + // There are two types of dividers: integer divider (baud rate generator register and oversample selection value) + // and fractional divider (fractional rate divider). + + // By default, oversampling rate is 16 which is an industry standard. + // That means 16 clocks are used to deliver the byte to recipient. + // In this way the probability of getting correct bytes instead of noise directly increases as oversampling increases as well. + + // Minimum and maximum values were computed taking these formulas into account: + // For minimum value, MULT = 0, BRGVAL = 0 + // For maximum value, MULT = 255, BRGVAL = 255 + // Flexcomm Interface function clock = (clock selected via FCCLKSEL) / (1 + MULT / DIV) + // By default, OSRVAL = 15 (see above) + // Baud rate = [FCLK / (OSRVAL+1)] / (BRGVAL + 1) + let source_clock = match config.baudrate { + 750_001..=6_000_000 => { + SYSCON + .fcclksel(T::instance_number()) + .modify(|w| w.set_sel(syscon::vals::FcclkselSel::ENUM_0X3)); // 96 MHz + 96_000_000 + } + 1501..=750_000 => { + SYSCON + .fcclksel(T::instance_number()) + .modify(|w| w.set_sel(syscon::vals::FcclkselSel::ENUM_0X2)); // 12 MHz + 12_000_000 + } + 121..=1500 => { + SYSCON + .fcclksel(T::instance_number()) + .modify(|w| w.set_sel(syscon::vals::FcclkselSel::ENUM_0X4)); // 1 MHz + 1_000_000 + } + _ => { + panic!("{} baudrate is not permitted in this mode", config.baudrate); + } + }; + // Calculate MULT and BRG values based on baudrate + // There are two types of dividers: integer divider (baud rate generator register and oversample selection value) // and fractional divider (fractional rate divider). // For oversampling, the default is industry standard 16x oversampling, i.e. OSRVAL = 15 @@ -274,14 +318,167 @@ impl<'d, T: Instance, M: Mode> Usart<'d, T, M> { // Secondly, MULT is calculated to ultimately 'chisel' the clock to get the baud rate. // The deduced formulas are written below. - let brg_value = (source_clock / (16 * baudrate)).min(255); + let brg_value = (source_clock / (16 * config.baudrate)).min(255); let raw_clock = source_clock / (16 * brg_value); - let mult_value = ((raw_clock * 256 / baudrate) - 256).min(255); - T::set_baudrate(mult_value as u8, brg_value as u8); + let mult_value = ((raw_clock * 256 / config.baudrate) - 256).min(255); + + // Write values to the registers + + // FCLK = (clock selected via FCCLKSEL) / (1+ MULT / DIV) + // Remark: To use the fractional baud rate generator, 0xFF must be wirtten to the DIV value + // to yield a denominator vale of 256. All other values are not supported + SYSCON.flexfrgctrl(T::instance_number()).modify(|w| { + w.set_div(0xFF); + w.set_mult(mult_value as u8); + }); + + // Baud rate = [FCLK / (OSRVAL+1)] / (BRGVAL + 1) + // By default, oversampling is 16x, i.e. OSRVAL = 15 + + // Typical industry standard USARTs use a 16x oversample clock to transmit and receive + // asynchronous data. This is the number of BRG clocks used for one data bit. The + // Oversample Select Register (OSR) allows this USART to use a 16x down to a 5x + // oversample clock. There is no oversampling in synchronous modes. + T::info() + .usart_reg + .brg() + .modify(|w| w.set_brgval((brg_value - 1) as u16)); + } + + fn pin_config(tx: Option>, rx: Option>) { + if let Some(tx_pin) = tx { + match_iocon!(register, tx_pin.pin_bank(), tx_pin.pin_number(), { + register.modify(|w| { + w.set_func(T::tx_pin_func()); + w.set_mode(iocon::vals::PioMode::INACTIVE); + w.set_slew(iocon::vals::PioSlew::STANDARD); + w.set_invert(false); + w.set_digimode(iocon::vals::PioDigimode::DIGITAL); + w.set_od(iocon::vals::PioOd::NORMAL); + }); + }) + } + + if let Some(rx_pin) = rx { + match_iocon!(register, rx_pin.pin_bank(), rx_pin.pin_number(), { + register.modify(|w| { + w.set_func(T::rx_pin_func()); + w.set_mode(iocon::vals::PioMode::INACTIVE); + w.set_slew(iocon::vals::PioSlew::STANDARD); + w.set_invert(false); + w.set_digimode(iocon::vals::PioDigimode::DIGITAL); + w.set_od(iocon::vals::PioOd::NORMAL); + }); + }) + }; + } + + fn configure_flexcomm(flexcomm_register: crate::pac::flexcomm::Flexcomm, instance_number: usize) { + critical_section::with(|_cs| { + if !(SYSCON.ahbclkctrl0().read().iocon()) { + SYSCON.ahbclkctrl0().modify(|w| w.set_iocon(true)); + } + }); + critical_section::with(|_cs| { + if !(SYSCON.ahbclkctrl1().read().fc(instance_number)) { + SYSCON.ahbclkctrl1().modify(|w| w.set_fc(instance_number, true)); + } + }); + SYSCON + .presetctrl1() + .modify(|w| w.set_fc_rst(instance_number, syscon::vals::FcRst::ASSERTED)); + SYSCON + .presetctrl1() + .modify(|w| w.set_fc_rst(instance_number, syscon::vals::FcRst::RELEASED)); + flexcomm_register + .pselid() + .modify(|w| w.set_persel(flexcomm::vals::Persel::USART)); + } + + fn configure_usart(info: &'static Info, config: &Config) { + let registers = info.usart_reg; + // See section 34.6.1 + registers.cfg().modify(|w| { + // LIN break mode enable + // Disabled. Break detect and generate is configured for normal operation. + w.set_linmode(false); + //CTS Enable. Determines whether CTS is used for flow control. CTS can be from the + //input pin, or from the USART’s own RTS if loopback mode is enabled. + // No flow control. The transmitter does not receive any automatic flow control signal. + w.set_ctsen(false); + // Selects synchronous or asynchronous operation. + w.set_syncen(usart::vals::Syncen::ASYNCHRONOUS_MODE); + // Selects the clock polarity and sampling edge of received data in synchronous mode. + w.set_clkpol(usart::vals::Clkpol::RISING_EDGE); + // Synchronous mode Master select. + // When synchronous mode is enabled, the USART is a master. + w.set_syncmst(usart::vals::Syncmst::MASTER); + // Selects data loopback mode + w.set_loop_(usart::vals::Loop::NORMAL); + // Output Enable Turnaround time enable for RS-485 operation. + // Disabled. If selected by OESEL, the Output Enable signal deasserted at the end of + // the last stop bit of a transmission. + w.set_oeta(false); + // Output enable select. + // Standard. The RTS signal is used as the standard flow control function. + w.set_oesel(usart::vals::Oesel::STANDARD); + // Automatic address matching enable. + // Disabled. When addressing is enabled by ADDRDET, address matching is done by + // software. This provides the possibility of versatile addressing (e.g. respond to more + // than one address) + w.set_autoaddr(false); + // Output enable polarity. + // Low. If selected by OESEL, the output enable is active low. + w.set_oepol(usart::vals::Oepol::LOW); + }); + + // Configurations based on the config written by a user + registers.cfg().modify(|w| { + w.set_datalen(match config.data_bits { + DataBits::DataBits7 => usart::vals::Datalen::BIT_7, + DataBits::DataBits8 => usart::vals::Datalen::BIT_8, + DataBits::DataBits9 => usart::vals::Datalen::BIT_9, + }); + w.set_paritysel(match config.parity { + Parity::ParityNone => usart::vals::Paritysel::NO_PARITY, + Parity::ParityEven => usart::vals::Paritysel::EVEN_PARITY, + Parity::ParityOdd => usart::vals::Paritysel::ODD_PARITY, + }); + w.set_stoplen(match config.stop_bits { + StopBits::Stop1 => usart::vals::Stoplen::BIT_1, + StopBits::Stop2 => usart::vals::Stoplen::BITS_2, + }); + w.set_rxpol(match config.invert_rx { + false => usart::vals::Rxpol::STANDARD, + true => usart::vals::Rxpol::INVERTED, + }); + w.set_txpol(match config.invert_tx { + false => usart::vals::Txpol::STANDARD, + true => usart::vals::Txpol::INVERTED, + }); + }); + + // DMA-related settings + registers.fifocfg().modify(|w| { + w.set_dmatx(false); + w.set_dmatx(false); + }); + + // Enabling USART + registers.fifocfg().modify(|w| { + w.set_enabletx(true); + w.set_enablerx(true); + }); + registers.cfg().modify(|w| w.set_enable(true)); + + // Drain RX FIFO in case it still has some unrelevant data + while registers.fifostat().read().rxnotempty() { + let _ = registers.fiford().read().0; + } } } -impl<'d, T: Instance, M: Mode> Usart<'d, T, M> { +impl<'d, M: Mode> Usart<'d, M> { /// Transmit the provided buffer blocking execution until done. pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { self.tx.blocking_write(buffer) @@ -304,19 +501,19 @@ impl<'d, T: Instance, M: Mode> Usart<'d, T, M> { /// Split the Usart into a transmitter and receiver, which is particularly /// useful when having two tasks correlating to transmitting and receiving. - pub fn split(self) -> (UsartTx<'d, T, M>, UsartRx<'d, T, M>) { + pub fn split(self) -> (UsartTx<'d, M>, UsartRx<'d, M>) { (self.tx, self.rx) } /// Split the Usart into a transmitter and receiver by mutable reference, /// which is particularly useful when having two tasks correlating to /// transmitting and receiving. - pub fn split_ref(&mut self) -> (&mut UsartTx<'d, T, M>, &mut UsartRx<'d, T, M>) { + pub fn split_ref(&mut self) -> (&mut UsartTx<'d, M>, &mut UsartRx<'d, M>) { (&mut self.tx, &mut self.rx) } } -impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write for UsartTx<'d, T, M> { +impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write for UsartTx<'d, M> { type Error = Error; fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { @@ -328,7 +525,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write for } } -impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write for Usart<'d, T, M> { +impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write for Usart<'d, M> { type Error = Error; fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { @@ -340,11 +537,11 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write for } } -impl<'d, T: Instance> embedded_io::ErrorType for UsartTx<'d, T, Blocking> { +impl<'d> embedded_io::ErrorType for UsartTx<'d, Blocking> { type Error = Error; } -impl<'d, T: Instance> embedded_io::Write for UsartTx<'d, T, Blocking> { +impl<'d> embedded_io::Write for UsartTx<'d, Blocking> { fn write(&mut self, buf: &[u8]) -> Result { self.blocking_write(buf).map(|_| buf.len()) } @@ -354,21 +551,21 @@ impl<'d, T: Instance> embedded_io::Write for UsartTx<'d, T, Blocking> { } } -impl<'d, T: Instance> embedded_io::ErrorType for UsartRx<'d, T, Blocking> { +impl<'d> embedded_io::ErrorType for UsartRx<'d, Blocking> { type Error = Error; } -impl<'d, T: Instance> embedded_io::Read for UsartRx<'d, T, Blocking> { +impl<'d> embedded_io::Read for UsartRx<'d, Blocking> { fn read(&mut self, buf: &mut [u8]) -> Result { self.blocking_read(buf).map(|_| buf.len()) } } -impl<'d, T: Instance> embedded_io::ErrorType for Usart<'d, T, Blocking> { +impl<'d> embedded_io::ErrorType for Usart<'d, Blocking> { type Error = Error; } -impl<'d, T: Instance> embedded_io::Write for Usart<'d, T, Blocking> { +impl<'d> embedded_io::Write for Usart<'d, Blocking> { fn write(&mut self, buf: &[u8]) -> Result { self.blocking_write(buf).map(|_| buf.len()) } @@ -378,468 +575,69 @@ impl<'d, T: Instance> embedded_io::Write for Usart<'d, T, Blocking> { } } -impl<'d, T: Instance> embedded_io::Read for Usart<'d, T, Blocking> { +impl<'d> embedded_io::Read for Usart<'d, Blocking> { fn read(&mut self, buf: &mut [u8]) -> Result { self.blocking_read(buf).map(|_| buf.len()) } } -type UsartRegBlock = crate::pac::usart0::RegisterBlock; - -mod sealed { - use crate::usart::inner::UsartRegBlock; - use crate::usart::{Config, Error}; - pub trait SealedInstance { - fn usart_reg() -> &'static UsartRegBlock; - fn enable_clock(); - fn select_clock(baudrate: u32) -> u32; - fn configure_flexcomm(); - fn set_baudrate(mult_value: u8, brg_value: u8); - fn reset_flexcomm(); - fn tx_pin_config(); - fn rx_pin_config(); - - fn configure_usart(config: Config) { - // See section 34.6.1 - Self::usart_reg().cfg.modify(|_, w| { - // LIN break mode enable - w.linmode() - // Disabled. Break detect and generate is configured for normal operation. - .disabled() - //CTS Enable. Determines whether CTS is used for flow control. CTS can be from the - //input pin, or from the USART’s own RTS if loopback mode is enabled. - .ctsen() - // No flow control. The transmitter does not receive any automatic flow control signal. - .disabled() - // Selects synchronous or asynchronous operation. - .syncen() - .asynchronous_mode() - // Selects the clock polarity and sampling edge of received data in synchronous mode. - .clkpol() - .rising_edge() - // Synchronous mode Master select. - .syncmst() - // When synchronous mode is enabled, the USART is a master. - .master() - // Selects data loopback mode - .loop_() - // Normal operation - .normal() - // Output Enable Turnaround time enable for RS-485 operation. - .oeta() - // Disabled. If selected by OESEL, the Output Enable signal deasserted at the end of - // the last stop bit of a transmission. - .disabled() - // Output enable select. - .oesel() - // Standard. The RTS signal is used as the standard flow control function. - .standard() - // Automatic address matching enable. - .autoaddr() - // Disabled. When addressing is enabled by ADDRDET, address matching is done by - // software. This provides the possibility of versatile addressing (e.g. respond to more - // than one address) - .disabled() - // Output enable polarity. - .oepol() - // Low. If selected by OESEL, the output enable is active low. - .low() - }); +struct Info { + usart_reg: UsartReg, + fc_reg: FlexcommReg, +} - Self::usart_reg().cfg.modify(|_, w| unsafe { - w.datalen() - .bits(config.data_bits.bits()) - .paritysel() - .bits(config.parity.bits()) - .stoplen() - .bit(config.stop_bits.bits()) - .rxpol() - .bit(config.invert_rx) - .txpol() - .bit(config.invert_tx) - }); - } - fn disable_dma() { - Self::usart_reg() - .fifocfg - .modify(|_, w| w.dmatx().disabled().dmarx().disabled()); - } - fn enable_usart() { - Self::usart_reg() - .fifocfg - .modify(|_, w| w.enabletx().enabled().enablerx().enabled()); - Self::usart_reg().cfg.modify(|_, w| w.enable().enabled()); - while Self::usart_reg().fifostat.read().rxnotempty().bit_is_set() { - let _ = Self::usart_reg().fiford.read().bits(); - } - } - fn blocking_write(buffer: &[u8]) -> Result<(), Error> { - for &b in buffer { - while Self::usart_reg().fifostat.read().txnotfull().bit_is_clear() {} - Self::usart_reg() - .fifowr - .modify(|_, w| unsafe { w.txdata().bits(b as u16) }); - } - Ok(()) - } - fn blocking_flush() -> Result<(), Error> { - while Self::usart_reg().fifostat.read().txempty().bit_is_clear() {} - Ok(()) - } - fn tx_busy() -> bool { - Self::usart_reg().fifostat.read().txempty().bit_is_clear() - } - fn drain_fifo(buffer: &mut [u8]) -> Result { - for (i, b) in buffer.iter_mut().enumerate() { - while Self::usart_reg().fifostat.read().rxnotempty().bit_is_clear() {} - - if Self::usart_reg().fifostat.read().rxerr().bit_is_set() { - return Err((i, Error::Overrun)); - } else if Self::usart_reg().fifordnopop.read().parityerr().bit_is_set() { - return Err((i, Error::Parity)); - } else if Self::usart_reg().fifordnopop.read().framerr().bit_is_set() { - return Err((i, Error::Framing)); - } else if Self::usart_reg().fifordnopop.read().rxnoise().bit_is_set() { - return Err((i, Error::Noise)); - } else if Self::usart_reg().intstat.read().deltarxbrk().bit_is_set() { - return Err((i, Error::Break)); - } - let dr = Self::usart_reg().fiford.read().bits() as u8; - *b = dr; - } - Ok(buffer.len()) - } - } +trait SealedInstance { + fn info() -> &'static Info; + fn instance_number() -> usize; + fn tx_pin_func() -> PioFunc; + fn rx_pin_func() -> PioFunc; } /// UART instance. #[allow(private_bounds)] -pub trait Instance: sealed::SealedInstance + PeripheralType {} +pub trait Instance: SealedInstance + PeripheralType {} -#[macro_export] macro_rules! impl_instance { - ( - $inst:ident, - usart_peripheral: $USARTX:ident, - usart_crate: $usartX:ident, - - flexcomm: { - field: $FLEXCOMM_FIELD:ident, - clock_field: $FLEXCOMM_CLK_FIELD:ident - }, - - reset: { - bit: $RESET_BIT:ident - }, - - clock: { - sel_field: $CLKSEL_FIELD:ident, - frg_field: $FRG_FIELD:ident - }, - - pins: { - tx: $TX_IOCON:ident => $TX_FUNC:expr, - rx: $RX_IOCON:ident => $RX_FUNC:expr - } - - ) => { - impl $crate::usart::SealedInstance for $crate::peripherals::$inst { - fn usart_reg() -> &'static UsartRegBlock { - unsafe { &*$crate::pac::$USARTX::ptr() } - } - - fn enable_clock() { - critical_section::with(|_cs| { - if syscon_reg().ahbclkctrl0.read().iocon().is_disable() { - syscon_reg().ahbclkctrl0.modify(|_, w| w.iocon().enable()); - } - if syscon_reg().ahbclkctrl1.read().$FLEXCOMM_CLK_FIELD().is_disable() { - syscon_reg() - .ahbclkctrl1 - .modify(|_, w| w.$FLEXCOMM_CLK_FIELD().enable()); - } - }); - } - - fn configure_flexcomm() { - let flexcomm = unsafe { &*$crate::pac::$FLEXCOMM_FIELD::ptr() }; - flexcomm.pselid.modify(|_, w| w.persel().usart()); - } - - fn reset_flexcomm() { - syscon_reg().presetctrl1.modify(|_, w| w.$RESET_BIT().set_bit()); - syscon_reg().presetctrl1.modify(|_, w| w.$RESET_BIT().clear_bit()); - } - - fn select_clock(baudrate: u32) -> u32 { - // Adaptive clock choice based on baud rate - // To get the desired baud rate, it is essential to choose the clock bigger than baud rate so that it can be 'chiseled' - // There are two types of dividers: integer divider (baud rate generator register and oversample selection value) - // and fractional divider (fractional rate divider). - - // By default, oversampling rate is 16 which is an industry standard. - // That means 16 clocks are used to deliver the byte to recipient. - // In this way the probability of getting correct bytes instead of noise directly increases as oversampling increases as well. - - // Minimum and maximum values were computed taking these formulas into account: - // For minimum value, MULT = 0, BRGVAL = 0 - // For maximum value, MULT = 255, BRGVAL = 255 - // Flexcomm Interface function clock = (clock selected via FCCLKSEL) / (1 + MULT / DIV) - // By default, OSRVAL = 15 (see above) - // Baud rate = [FCLK / (OSRVAL+1)] / (BRGVAL + 1) - return match baudrate { - 750_001..=6000000 => { - syscon_reg().$CLKSEL_FIELD().write(|w| w.sel().enum_0x3()); // 96 MHz - 96_000_000 - } - 1501..=750_000 => { - syscon_reg().$CLKSEL_FIELD().write(|w| w.sel().enum_0x2()); // 12 MHz - 12_000_000 - } - 121..=1500 => { - syscon_reg().$CLKSEL_FIELD().write(|w| w.sel().enum_0x4()); // 1 MHz - 1_000_000 - } - _ => { - panic!("{} baudrate is not permitted in this mode", baudrate); - } + ($inst:ident, $fc:ident, $tx_pin:ident, $rx_pin:ident, $fc_num:expr) => { + impl $crate::usart::inner::SealedInstance for $crate::peripherals::$inst { + fn info() -> &'static Info { + static INFO: Info = Info { + usart_reg: crate::pac::$inst, + fc_reg: crate::pac::$fc, }; + &INFO } - - fn set_baudrate(mult_value: u8, brg_value: u8) { - // FCLK = (clock selected via FCCLKSEL) / (1+ MULT / DIV) - // Remark: To use the fractional baud rate generator, 0xFF must be wirtten to the DIV value - // to yield a denominator vale of 256. All other values are not supported - syscon_reg() - .$FRG_FIELD() - .modify(|_, w| unsafe { w.div().bits(0xFF).mult().bits(mult_value as u8) }); - - // Baud rate = [FCLK / (OSRVAL+1)] / (BRGVAL + 1) - // By default, oversampling is 16x, i.e. OSRVAL = 15 - - // Typical industry standard USARTs use a 16x oversample clock to transmit and receive - // asynchronous data. This is the number of BRG clocks used for one data bit. The - // Oversample Select Register (OSR) allows this USART to use a 16x down to a 5x - // oversample clock. There is no oversampling in synchronous modes. - Self::usart_reg() - .brg - .modify(|_, w| unsafe { w.brgval().bits((brg_value - 1) as u16) }); + #[inline] + fn instance_number() -> usize { + $fc_num } - - fn tx_pin_config() { - iocon_reg().$TX_IOCON.modify(|_, w| unsafe { - w.func() - .bits($TX_FUNC) - .digimode() - .digital() - .slew() - .standard() - .mode() - .inactive() - .invert() - .disabled() - .od() - .normal() - }); + #[inline] + fn tx_pin_func() -> PioFunc { + PioFunc::$tx_pin } - - fn rx_pin_config() { - iocon_reg().$RX_IOCON.modify(|_, w| unsafe { - w.func() - .bits($RX_FUNC) - .digimode() - .digital() - .slew() - .standard() - .mode() - .inactive() - .invert() - .disabled() - .od() - .normal() - }); + #[inline] + fn rx_pin_func() -> PioFunc { + PioFunc::$rx_pin } } - impl $crate::usart::Instance for $crate::peripherals::$inst {} }; } -impl_instance!(USART0, usart_peripheral: USART0, usart_crate: usart0, - flexcomm: { - field: FLEXCOMM0, - clock_field: fc0 - }, - - reset: { - bit: fc0_rst - }, - - clock: { - sel_field: fcclksel0, - frg_field: flexfrg0ctrl - }, - - pins: { - tx: pio1_6 => 1, - rx: pio1_5 => 1 - } -); - -impl_instance!(USART1, usart_peripheral: USART1, usart_crate: usart1, - flexcomm: { - field: FLEXCOMM1, - clock_field: fc1 - }, - - reset: { - bit: fc1_rst - }, - - clock: { - sel_field: fcclksel1, - frg_field: flexfrg1ctrl - }, - - pins: { - tx: pio1_11 => 2, - rx: pio1_10 => 2 - } -); - -impl_instance!(USART2, usart_peripheral: USART2, usart_crate: usart2, - flexcomm: { - field: FLEXCOMM2, - clock_field: fc2 - }, - - reset: { - bit: fc2_rst - }, - - clock: { - sel_field: fcclksel2, - frg_field: flexfrg2ctrl - }, - - pins: { - tx: pio0_27 => 1, - rx: pio1_24 => 1 - } -); - -impl_instance!(USART3, usart_peripheral: USART3, usart_crate: usart3, - flexcomm: { - field: FLEXCOMM3, - clock_field: fc3 - }, - - reset: { - bit: fc3_rst - }, - - clock: { - sel_field: fcclksel3, - frg_field: flexfrg3ctrl - }, - - pins: { - tx: pio0_2 => 1, - rx: pio0_3 => 1 - } -); - -impl_instance!(USART4, usart_peripheral: USART4, usart_crate: usart4, - flexcomm: { - field: FLEXCOMM4, - clock_field: fc4 - }, - - reset: { - bit: fc4_rst - }, - - clock: { - sel_field: fcclksel4, - frg_field: flexfrg4ctrl - }, - - pins: { - tx: pio0_16 => 1, - rx: pio0_5 => 2 - } -); - -impl_instance!(USART5, usart_peripheral: USART5, usart_crate: usart5, - flexcomm: { - field: FLEXCOMM5, - clock_field: fc5 - }, - - reset: { - bit: fc5_rst - }, - - clock: { - sel_field: fcclksel5, - frg_field: flexfrg5ctrl - }, - - pins: { - tx: pio0_9 => 3, - rx: pio0_8 => 3 - } -); - -impl_instance!(USART6, usart_peripheral: USART6, usart_crate: usart6, - flexcomm: { - field: FLEXCOMM6, - clock_field: fc6 - }, - - reset: { - bit: fc6_rst - }, - - clock: { - sel_field: fcclksel6, - frg_field: flexfrg6ctrl - }, - - pins: { - tx: pio1_16 => 2, - rx: pio1_13 => 2 - } -); - -impl_instance!(USART7, usart_peripheral: USART7, usart_crate: usart7, - flexcomm: { - field: FLEXCOMM7, - clock_field: fc7 - }, - - reset: { - bit: fc7_rst - }, - - clock: { - sel_field: fcclksel7, - frg_field: flexfrg7ctrl - }, - - pins: { - tx: pio0_19 => 7, - rx: pio0_20 => 7 - } -); +impl_instance!(USART0, FLEXCOMM0, ALT1, ALT1, 0); +impl_instance!(USART1, FLEXCOMM1, ALT2, ALT2, 1); +impl_instance!(USART2, FLEXCOMM2, ALT1, ALT1, 2); +impl_instance!(USART3, FLEXCOMM3, ALT1, ALT1, 3); +impl_instance!(USART4, FLEXCOMM4, ALT1, ALT2, 4); +impl_instance!(USART5, FLEXCOMM5, ALT3, ALT3, 5); +impl_instance!(USART6, FLEXCOMM6, ALT2, ALT2, 6); +impl_instance!(USART7, FLEXCOMM7, ALT7, ALT7, 7); /// Trait for TX pins. pub trait TxPin: crate::gpio::Pin {} /// Trait for RX pins. pub trait RxPin: crate::gpio::Pin {} -// TODO: Add RTS, CTS and CLK pin traits - macro_rules! impl_pin { ($pin:ident, $instance:ident, Tx) => { impl TxPin for crate::peripherals::$pin {} @@ -849,37 +647,19 @@ macro_rules! impl_pin { }; } -impl_pin!(PIO1_5, USART0, Rx); impl_pin!(PIO1_6, USART0, Tx); -impl_pin!(PIO1_10, USART1, Rx); +impl_pin!(PIO1_5, USART0, Rx); impl_pin!(PIO1_11, USART1, Tx); +impl_pin!(PIO1_10, USART1, Rx); impl_pin!(PIO0_27, USART2, Tx); impl_pin!(PIO1_24, USART2, Rx); impl_pin!(PIO0_2, USART3, Tx); impl_pin!(PIO0_3, USART3, Rx); impl_pin!(PIO0_16, USART4, Tx); impl_pin!(PIO0_5, USART4, Rx); -impl_pin!(PIO0_8, USART5, Rx); impl_pin!(PIO0_9, USART5, Tx); +impl_pin!(PIO0_8, USART5, Rx); impl_pin!(PIO1_16, USART6, Tx); impl_pin!(PIO1_13, USART6, Rx); -impl_pin!(PIO0_20, USART7, Rx); impl_pin!(PIO0_19, USART7, Tx); - -/// Get the SYSCON register block. -/// -/// # Safety -/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO -/// registers are not accessed concurrently by multiple threads. -pub(crate) fn syscon_reg() -> &'static crate::pac::syscon::RegisterBlock { - unsafe { &*crate::pac::SYSCON::ptr() } -} - -/// Get the IOCON register block. -/// -/// # Safety -/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO -/// registers are not accessed concurrently by multiple threads. -pub(crate) fn iocon_reg() -> &'static crate::pac::iocon::RegisterBlock { - unsafe { &*crate::pac::IOCON::ptr() } -} +impl_pin!(PIO0_20, USART7, Rx); -- cgit From d1dc7a3a88fbcc8a47fc8031a0338858c08090e9 Mon Sep 17 00:00:00 2001 From: Irina Chiorean Date: Mon, 1 Sep 2025 12:12:39 +0300 Subject: lpc55: rtc driver rewritten --- embassy-nxp/src/time_driver/rtc.rs | 76 ++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/embassy-nxp/src/time_driver/rtc.rs b/embassy-nxp/src/time_driver/rtc.rs index 94272e9c2..fb6de6a5e 100644 --- a/embassy-nxp/src/time_driver/rtc.rs +++ b/embassy-nxp/src/time_driver/rtc.rs @@ -6,7 +6,9 @@ use embassy_hal_internal::interrupt::{InterruptExt, Priority}; use embassy_sync::blocking_mutex::CriticalSectionMutex as Mutex; use embassy_time_driver::{time_driver_impl, Driver}; use embassy_time_queue_utils::Queue; -use lpc55_pac::{interrupt, PMC, RTC, SYSCON}; + +use crate::pac::{interrupt, pmc, rtc, PMC, RTC, SYSCON}; + struct AlarmState { timestamp: Cell, } @@ -32,33 +34,32 @@ time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { }); impl RtcDriver { fn init(&'static self) { - let syscon = unsafe { &*SYSCON::ptr() }; - let pmc = unsafe { &*PMC::ptr() }; - let rtc = unsafe { &*RTC::ptr() }; + let syscon = SYSCON; + let pmc = PMC; + let rtc = RTC; - syscon.ahbclkctrl0.modify(|_, w| w.rtc().enable()); + syscon.ahbclkctrl0().modify(|w| w.set_rtc(true)); // By default the RTC enters software reset. If for some reason it is // not in reset, we enter and them promptly leave.q - rtc.ctrl.modify(|_, w| w.swreset().set_bit()); - rtc.ctrl.modify(|_, w| w.swreset().clear_bit()); + rtc.ctrl().modify(|w| w.set_swreset(true)); + rtc.ctrl().modify(|w| w.set_swreset(false)); // Select clock source - either XTAL or FRO - // pmc.rtcosc32k.write(|w| w.sel().xtal32k()); - pmc.rtcosc32k.write(|w| w.sel().fro32k()); + // pmc.rtcosc32k().write(|w| w.set_sel(pmc::vals::Sel::XTAL32K)); + pmc.rtcosc32k().write(|w| w.set_sel(pmc::vals::Sel::FRO32K)); // Start the RTC peripheral - rtc.ctrl.modify(|_, w| w.rtc_osc_pd().power_up()); - - // rtc.ctrl.modify(|_, w| w.rtc_en().clear_bit()); // EXTRA + rtc.ctrl().modify(|w| w.set_rtc_osc_pd(rtc::vals::RtcOscPd::POWER_UP)); //reset/clear(?) counter - rtc.count.reset(); + rtc.count().modify(|w| w.set_val(0)); //en rtc main counter - rtc.ctrl.modify(|_, w| w.rtc_en().set_bit()); - rtc.ctrl.modify(|_, w| w.rtc1khz_en().set_bit()); + rtc.ctrl().modify(|w| w.set_rtc_en(true)); + rtc.ctrl().modify(|w| w.set_rtc1khz_en(true)); // subsec counter enable - rtc.ctrl.modify(|_, w| w.rtc_subsec_ena().set_bit()); + rtc.ctrl() + .modify(|w| w.set_rtc_subsec_ena(rtc::vals::RtcSubsecEna::POWER_UP)); // enable irq unsafe { @@ -68,7 +69,7 @@ impl RtcDriver { } fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool { - let rtc = unsafe { &*RTC::ptr() }; + let rtc = RTC; let alarm = &self.alarms.borrow(cs); alarm.timestamp.set(timestamp); let now = self.now(); @@ -83,33 +84,38 @@ impl RtcDriver { let sec = (diff / 32768) as u32; let subsec = (diff % 32768) as u32; - let current_sec = rtc.count.read().val().bits(); + let current_sec = rtc.count().read().val(); let target_sec = current_sec.wrapping_add(sec as u32); - rtc.match_.write(|w| unsafe { w.matval().bits(target_sec) }); - rtc.wake.write(|w| unsafe { + rtc.match_().write(|w| w.set_matval(target_sec)); + rtc.wake().write(|w| { let ms = (subsec * 1000) / 32768; - w.val().bits(ms as u16) + w.set_val(ms as u16) }); + if subsec > 0 { let ms = (subsec * 1000) / 32768; - rtc.wake.write(|w| unsafe { w.val().bits(ms as u16) }); + rtc.wake().write(|w| w.set_val(ms as u16)); } - rtc.ctrl.modify(|_, w| w.alarm1hz().clear_bit().wake1khz().clear_bit()); + + rtc.ctrl().modify(|w| { + w.set_alarm1hz(false); + w.set_wake1khz(rtc::vals::Wake1khz::RUN) + }); true } fn on_interrupt(&self) { critical_section::with(|cs| { - let rtc = unsafe { &*RTC::ptr() }; - let flags = rtc.ctrl.read(); - if flags.alarm1hz().bit_is_clear() { - rtc.ctrl.modify(|_, w| w.alarm1hz().set_bit()); + let rtc = RTC; + let flags = rtc.ctrl().read(); + if flags.alarm1hz() == false { + rtc.ctrl().modify(|w| w.set_alarm1hz(true)); self.trigger_alarm(cs); } - if flags.wake1khz().bit_is_clear() { - rtc.ctrl.modify(|_, w| w.wake1khz().set_bit()); + if flags.wake1khz() == rtc::vals::Wake1khz::RUN { + rtc.ctrl().modify(|w| w.set_wake1khz(rtc::vals::Wake1khz::TIMEOUT)); self.trigger_alarm(cs); } }); @@ -135,13 +141,13 @@ impl RtcDriver { impl Driver for RtcDriver { fn now(&self) -> u64 { - let rtc = unsafe { &*RTC::ptr() }; + let rtc = RTC; loop { - let sec1 = rtc.count.read().val().bits() as u64; - let sub1 = rtc.subsec.read().subsec().bits() as u64; - let sec2 = rtc.count.read().val().bits() as u64; - let sub2 = rtc.subsec.read().subsec().bits() as u64; + let sec1 = rtc.count().read().val() as u64; + let sub1 = rtc.subsec().read().subsec() as u64; + let sec2 = rtc.count().read().val() as u64; + let sub2 = rtc.subsec().read().subsec() as u64; if sec1 == sec2 && sub1 == sub2 { return sec1 * 32768 + sub1; @@ -162,7 +168,7 @@ impl Driver for RtcDriver { }) } } -#[cortex_m_rt::interrupt] +#[interrupt] fn RTC() { DRIVER.on_interrupt(); } -- cgit From 0816a6a4185eac63803bd7155941fa2d73a114a6 Mon Sep 17 00:00:00 2001 From: Roi Bachynskyi Date: Mon, 1 Sep 2025 21:22:14 +0300 Subject: lpc55: update Cargo.toml and CHANGELOG Co-authored-by: Irina Chiorean --- embassy-nxp/CHANGELOG.md | 2 +- embassy-nxp/Cargo.toml | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/embassy-nxp/CHANGELOG.md b/embassy-nxp/CHANGELOG.md index 7042ad14c..ab97c4185 100644 --- a/embassy-nxp/CHANGELOG.md +++ b/embassy-nxp/CHANGELOG.md @@ -7,5 +7,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate - +- Moved NXP LPC55S69 from `lpc55-pac` to `nxp-pac` - First release with changelog. diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index c66354ee2..dd132c7ba 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -36,21 +36,20 @@ embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-ut embedded-io = "0.6.1" embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } ## Chip dependencies -lpc55-pac = { version = "0.5.0", optional = true } -nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/IrinaCh524/nxp-pac", rev = "d452e366105012ddd8ba332a9ab86e1931508235" } +nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/i509VCB/nxp-pac", rev = "b736e3038254d593024aaa1a5a7b1f95a5728538"} imxrt-rt = { version = "0.1.7", optional = true, features = ["device"] } [build-dependencies] cfg_aliases = "0.2.1" -nxp-pac = { version = "0.1.0", git = "https://github.com/IrinaCh524/nxp-pac", rev = "d452e366105012ddd8ba332a9ab86e1931508235", features = ["metadata"], optional = true } +nxp-pac = { version = "0.1.0", git = "https://github.com/i509VCB/nxp-pac", rev = "b736e3038254d593024aaa1a5a7b1f95a5728538", features = ["metadata"], optional = true } proc-macro2 = "1.0.95" quote = "1.0.15" [features] default = ["rt"] # Enable PACs as optional dependencies, since some chip families will use different pac crates (temporarily). -rt = ["lpc55-pac?/rt", "nxp-pac?/rt"] +rt = ["nxp-pac?/rt"] ## Enable [defmt support](https://docs.rs/defmt) and enables `defmt` debug-log messages and formatting in embassy drivers. defmt = ["dep:defmt", "embassy-hal-internal/defmt", "embassy-sync/defmt"] @@ -79,6 +78,6 @@ _rt1xxx = [] _time_driver = ["dep:embassy-time-driver", "dep:embassy-time-queue-utils"] #! ### Chip selection features -lpc55 = ["nxp-pac/lpc55s69_core0"] +lpc55 = ["nxp-pac/lpc55s69_cm33_core0"] mimxrt1011 = ["nxp-pac/mimxrt1011", "_rt1xxx", "dep:imxrt-rt"] mimxrt1062 = ["nxp-pac/mimxrt1062", "_rt1xxx", "dep:imxrt-rt"] -- cgit From 547a52103b3c30506dc981fa89faa6c12765e97a Mon Sep 17 00:00:00 2001 From: Roi Bachynskyi Date: Wed, 10 Sep 2025 12:21:04 +0300 Subject: lpc55: added lpc55-core0 feature Co-authored-by: Irina Chiorean --- embassy-nxp/Cargo.toml | 6 +++--- embassy-nxp/src/gpio.rs | 2 +- embassy-nxp/src/lib.rs | 10 +++++----- embassy-nxp/src/usart.rs | 2 +- examples/lpc55s69/Cargo.toml | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index dd132c7ba..455915f29 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -7,7 +7,7 @@ publish = false [package.metadata.embassy] build = [ - {target = "thumbv8m.main-none-eabihf", features = ["defmt", "lpc55"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "lpc55-core0"]}, {target = "thumbv7em-none-eabihf", features = ["defmt", "mimxrt1011", "rt", "time-driver-pit"]}, {target = "thumbv7em-none-eabihf", features = ["defmt", "mimxrt1062", "rt", "time-driver-pit"]}, ] @@ -18,7 +18,7 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-nxp/s features = ["defmt", "unstable-pac" ] # TODO: Add time-driver-any, as both lpc55 and mimxrt1xxx use different drivers. flavors = [ - { regex_feature = "lpc55", target = "thumbv8m.main-none-eabihf" }, + { regex_feature = "lpc55-core0", target = "thumbv8m.main-none-eabihf" }, { regex_feature = "mimxrt.*", target = "thumbv7em-none-eabihf" }, ] @@ -78,6 +78,6 @@ _rt1xxx = [] _time_driver = ["dep:embassy-time-driver", "dep:embassy-time-queue-utils"] #! ### Chip selection features -lpc55 = ["nxp-pac/lpc55s69_cm33_core0"] +lpc55-core0 = ["nxp-pac/lpc55s69_cm33_core0"] mimxrt1011 = ["nxp-pac/mimxrt1011", "_rt1xxx", "dep:imxrt-rt"] mimxrt1062 = ["nxp-pac/mimxrt1062", "_rt1xxx", "dep:imxrt-rt"] diff --git a/embassy-nxp/src/gpio.rs b/embassy-nxp/src/gpio.rs index 3049cc12d..717b38d96 100644 --- a/embassy-nxp/src/gpio.rs +++ b/embassy-nxp/src/gpio.rs @@ -1,7 +1,7 @@ //! General purpose input/output (GPIO) driver. #![macro_use] -#[cfg_attr(feature = "lpc55", path = "./gpio/lpc55.rs")] +#[cfg_attr(feature = "lpc55-core0", path = "./gpio/lpc55.rs")] #[cfg_attr(rt1xxx, path = "./gpio/rt1xxx.rs")] mod inner; pub use inner::*; diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs index 3fcb14b7e..74142a10b 100644 --- a/embassy-nxp/src/lib.rs +++ b/embassy-nxp/src/lib.rs @@ -4,9 +4,9 @@ pub(crate) mod fmt; pub mod gpio; -#[cfg(feature = "lpc55")] +#[cfg(feature = "lpc55-core0")] pub mod pint; -#[cfg(feature = "lpc55")] +#[cfg(feature = "lpc55-core0")] pub mod usart; #[cfg(feature = "_time_driver")] @@ -15,7 +15,7 @@ pub mod usart; mod time_driver; // This mod MUST go last, so that it sees all the `impl_foo!` macros -#[cfg_attr(feature = "lpc55", path = "chips/lpc55.rs")] +#[cfg_attr(feature = "lpc55-core0", path = "chips/lpc55.rs")] #[cfg_attr(feature = "mimxrt1011", path = "chips/mimxrt1011.rs")] #[cfg_attr(feature = "mimxrt1062", path = "chips/mimxrt1062.rs")] mod chip; @@ -83,10 +83,10 @@ pub fn init(_config: config::Config) -> Peripherals { pac::CCM.ccgr6().modify(|v| v.set_cg0(1)); } - #[cfg(any(feature = "lpc55", rt1xxx))] + #[cfg(any(feature = "lpc55-core0", rt1xxx))] gpio::init(); - #[cfg(feature = "lpc55")] + #[cfg(feature = "lpc55-core0")] pint::init(); #[cfg(feature = "_time_driver")] diff --git a/embassy-nxp/src/usart.rs b/embassy-nxp/src/usart.rs index c426ab96d..1d8886f24 100644 --- a/embassy-nxp/src/usart.rs +++ b/embassy-nxp/src/usart.rs @@ -1,5 +1,5 @@ //! Universal Synchronous/Asynchronous Receiver/Transmitter (USART) driver. -#[cfg_attr(feature = "lpc55", path = "./usart/lpc55.rs")] +#[cfg_attr(feature = "lpc55-core0", path = "./usart/lpc55.rs")] mod inner; pub use inner::*; diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index 79b27f269..579748595 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" publish = false [dependencies] -embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55", "rt", "defmt", "time-driver-rtc"] } +embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55-core0", "rt", "defmt", "time-driver-rtc"] } embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768"] } -- cgit From a7e1bf2aff94ed0dd3d56848ccb9afe7a127054e Mon Sep 17 00:00:00 2001 From: Brian Schwind Date: Fri, 12 Sep 2025 20:02:08 +0900 Subject: Typo fixes --- embassy-stm32/src/ospi/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/ospi/mod.rs b/embassy-stm32/src/ospi/mod.rs index 8384f4fc4..4df3b0042 100644 --- a/embassy-stm32/src/ospi/mod.rs +++ b/embassy-stm32/src/ospi/mod.rs @@ -113,7 +113,7 @@ pub struct TransferConfig { /// Data width (DMODE) pub dwidth: OspiWidth, - /// Data buffer + /// Data Double Transfer rate enable pub ddtr: bool, /// Number of dummy cycles (DCYC) @@ -467,11 +467,11 @@ impl<'d, T: Instance, M: PeriMode> Ospi<'d, T, M> { if let Some(data_length) = data_len { T::REGS.dlr().write(|v| { v.set_dl((data_length - 1) as u32); - }) + }); } else { T::REGS.dlr().write(|v| { v.set_dl((0) as u32); - }) + }); } // Configure instruction/address/data/communication modes @@ -491,7 +491,7 @@ impl<'d, T: Instance, M: PeriMode> Ospi<'d, T, M> { w.set_sioo(command.sioo); }); - // Set informationrequired to initiate transaction + // Set information required to initiate transaction if let Some(instruction) = command.instruction { if let Some(address) = command.address { T::REGS.ir().write(|v| { -- cgit From 9c4df75940023456e92623700a9bb25fe6600196 Mon Sep 17 00:00:00 2001 From: Brian Schwind Date: Fri, 12 Sep 2025 20:02:33 +0900 Subject: Set the alternate bytes register to the correct value when configuring an Ospi command --- embassy-stm32/src/ospi/mod.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/embassy-stm32/src/ospi/mod.rs b/embassy-stm32/src/ospi/mod.rs index 4df3b0042..cbd6c8d35 100644 --- a/embassy-stm32/src/ospi/mod.rs +++ b/embassy-stm32/src/ospi/mod.rs @@ -451,11 +451,6 @@ impl<'d, T: Instance, M: PeriMode> Ospi<'d, T, M> { // Configure alternate bytes if let Some(ab) = command.alternate_bytes { T::REGS.abr().write(|v| v.set_alternate(ab)); - T::REGS.ccr().modify(|w| { - w.set_abmode(PhaseMode::from_bits(command.abwidth.into())); - w.set_abdtr(command.abdtr); - w.set_absize(SizeInBits::from_bits(command.absize.into())); - }) } // Configure dummy cycles @@ -474,7 +469,7 @@ impl<'d, T: Instance, M: PeriMode> Ospi<'d, T, M> { }); } - // Configure instruction/address/data/communication modes + // Configure instruction/address/alternate bytes/data/communication modes T::REGS.ccr().modify(|w| { w.set_imode(PhaseMode::from_bits(command.iwidth.into())); w.set_idtr(command.idtr); @@ -484,6 +479,10 @@ impl<'d, T: Instance, M: PeriMode> Ospi<'d, T, M> { w.set_addtr(command.addtr); w.set_adsize(SizeInBits::from_bits(command.adsize.into())); + w.set_abmode(PhaseMode::from_bits(command.abwidth.into())); + w.set_abdtr(command.abdtr); + w.set_absize(SizeInBits::from_bits(command.absize.into())); + w.set_dmode(PhaseMode::from_bits(command.dwidth.into())); w.set_ddtr(command.ddtr); -- cgit From 4a3e9e38e5fd0f5f2f576691154ecbbdc22eabab Mon Sep 17 00:00:00 2001 From: Brian Schwind Date: Sat, 13 Sep 2025 00:12:14 +0900 Subject: Apply fixes to HSPI as well --- embassy-stm32/src/hspi/mod.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/embassy-stm32/src/hspi/mod.rs b/embassy-stm32/src/hspi/mod.rs index 62bc0e979..3b73062a2 100644 --- a/embassy-stm32/src/hspi/mod.rs +++ b/embassy-stm32/src/hspi/mod.rs @@ -116,7 +116,7 @@ pub struct TransferConfig { /// Data width (DMODE) pub dwidth: HspiWidth, - /// Data buffer + /// Data Double Transfer rate enable pub ddtr: bool, /// Number of dummy cycles (DCYC) @@ -395,11 +395,6 @@ impl<'d, T: Instance, M: PeriMode> Hspi<'d, T, M> { // Configure alternate bytes if let Some(ab) = command.alternate_bytes { T::REGS.abr().write(|v| v.set_alternate(ab)); - T::REGS.ccr().modify(|w| { - w.set_abmode(command.abwidth.into()); - w.set_abdtr(command.abdtr); - w.set_absize(command.absize.into()); - }) } // Configure dummy cycles @@ -411,14 +406,14 @@ impl<'d, T: Instance, M: PeriMode> Hspi<'d, T, M> { if let Some(data_length) = data_len { T::REGS.dlr().write(|v| { v.set_dl((data_length - 1) as u32); - }) + }); } else { T::REGS.dlr().write(|v| { v.set_dl((0) as u32); - }) + }); } - // Configure instruction/address/data modes + // Configure instruction/address/alternate bytes/data modes T::REGS.ccr().modify(|w| { w.set_imode(command.iwidth.into()); w.set_idtr(command.idtr); @@ -428,6 +423,10 @@ impl<'d, T: Instance, M: PeriMode> Hspi<'d, T, M> { w.set_addtr(command.addtr); w.set_adsize(command.adsize.into()); + w.set_abmode(command.abwidth.into()); + w.set_abdtr(command.abdtr); + w.set_absize(command.absize.into()); + w.set_dmode(command.dwidth.into()); w.set_ddtr(command.ddtr); }); -- cgit From 881fee982005b36a73c3b09b69bda48f81603084 Mon Sep 17 00:00:00 2001 From: Brian Schwind Date: Sat, 13 Sep 2025 00:12:36 +0900 Subject: Apply fixes to XSPI as well --- embassy-stm32/src/xspi/mod.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/embassy-stm32/src/xspi/mod.rs b/embassy-stm32/src/xspi/mod.rs index 60ccf3c97..5ae074a90 100644 --- a/embassy-stm32/src/xspi/mod.rs +++ b/embassy-stm32/src/xspi/mod.rs @@ -110,7 +110,7 @@ pub struct TransferConfig { /// Data width (DMODE) pub dwidth: XspiWidth, - /// Data buffer + /// Data Double Transfer rate enable pub ddtr: bool, /// Number of dummy cycles (DCYC) @@ -424,11 +424,6 @@ impl<'d, T: Instance, M: PeriMode> Xspi<'d, T, M> { // Configure alternate bytes if let Some(ab) = command.alternate_bytes { T::REGS.abr().write(|v| v.set_alternate(ab)); - T::REGS.ccr().modify(|w| { - w.set_abmode(CcrAbmode::from_bits(command.abwidth.into())); - w.set_abdtr(command.abdtr); - w.set_absize(CcrAbsize::from_bits(command.absize.into())); - }) } else { T::REGS.ccr().modify(|w| { // disable alternate bytes @@ -445,14 +440,14 @@ impl<'d, T: Instance, M: PeriMode> Xspi<'d, T, M> { if let Some(data_length) = data_len { T::REGS.dlr().write(|v| { v.set_dl((data_length - 1) as u32); - }) + }); } else { T::REGS.dlr().write(|v| { v.set_dl((0) as u32); - }) + }); } - // Configure instruction/address/data modes + // Configure instruction/address/alternate bytes/data modes T::REGS.ccr().modify(|w| { w.set_imode(CcrImode::from_bits(command.iwidth.into())); w.set_idtr(command.idtr); @@ -462,6 +457,10 @@ impl<'d, T: Instance, M: PeriMode> Xspi<'d, T, M> { w.set_addtr(command.addtr); w.set_adsize(CcrAdsize::from_bits(command.adsize.into())); + w.set_abmode(CcrAbmode::from_bits(command.abwidth.into())); + w.set_abdtr(command.abdtr); + w.set_absize(CcrAbsize::from_bits(command.absize.into())); + w.set_dmode(CcrDmode::from_bits(command.dwidth.into())); w.set_ddtr(command.ddtr); }); -- cgit From ffe7f6b0a06bda06ab7bde395f6f74a56be8dbf4 Mon Sep 17 00:00:00 2001 From: Brian Schwind Date: Sat, 13 Sep 2025 00:27:30 +0900 Subject: Update embassy-stm32/CHANGELOG.md --- embassy-stm32/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 4ea11b664..93a1f4f64 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - fix: STM32: Prevent dropped DacChannel from disabling Dac peripheral if another DacChannel is still in scope ([#4577](https://github.com/embassy-rs/embassy/pull/4577)) - feat: Added support for more OctoSPI configurations (e.g. APS6408 RAM) ([#4581](https://github.com/embassy-rs/embassy/pull/4581)) - fix: stm32/usart: fix bug with blocking flush in buffered uart ([#4648](https://github.com/embassy-rs/embassy/pull/4648)) +- fix: stm32/(ospi/hspi/xspi): Fix the alternate bytes register config sticking around for subsequent writes ## 0.4.0 - 2025-08-26 -- cgit From 78d5d3f2dde14fcbf4879de19076eb89d9b9ef8b Mon Sep 17 00:00:00 2001 From: Robert Zieba Date: Thu, 11 Sep 2025 14:40:29 -0700 Subject: Remove `Sized` bound from `MutexGuard::map` Since `MutexGuard` has `T: ?Sized`, `U` does not need to be restricted to `Sized` types. This now allows using `map` to cast from `MutexGuard<'_, M, ImplsTrait>` to `MutexGuard<'_, M, dyn Trait>`. --- embassy-sync/CHANGELOG.md | 1 + embassy-sync/src/mutex.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-sync/CHANGELOG.md b/embassy-sync/CHANGELOG.md index a53d5f5b1..242b8b7ab 100644 --- a/embassy-sync/CHANGELOG.md +++ b/embassy-sync/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate - Fix wakers getting dropped by `Signal::reset` +- Remove `Sized` trait bound from `MutexGuard::map` ## 0.7.2 - 2025-08-26 diff --git a/embassy-sync/src/mutex.rs b/embassy-sync/src/mutex.rs index 4ce6dd987..aea682899 100644 --- a/embassy-sync/src/mutex.rs +++ b/embassy-sync/src/mutex.rs @@ -187,7 +187,7 @@ where T: ?Sized, { /// Returns a locked view over a portion of the locked data. - pub fn map(this: Self, fun: impl FnOnce(&mut T) -> &mut U) -> MappedMutexGuard<'a, M, U> { + pub fn map(this: Self, fun: impl FnOnce(&mut T) -> &mut U) -> MappedMutexGuard<'a, M, U> { let mutex = this.mutex; let value = fun(unsafe { &mut *this.mutex.inner.get() }); // Don't run the `drop` method for MutexGuard. The ownership of the underlying @@ -279,7 +279,7 @@ where T: ?Sized, { /// Returns a locked view over a portion of the locked data. - pub fn map(this: Self, fun: impl FnOnce(&mut T) -> &mut U) -> MappedMutexGuard<'a, M, U> { + pub fn map(this: Self, fun: impl FnOnce(&mut T) -> &mut U) -> MappedMutexGuard<'a, M, U> { let state = this.state; let value = fun(unsafe { &mut *this.value }); // Don't run the `drop` method for MutexGuard. The ownership of the underlying -- cgit From 0ea3478fb5e4fcdcd86e439186794d126ed2eca4 Mon Sep 17 00:00:00 2001 From: Riceman2000 Date: Fri, 12 Sep 2025 12:47:47 -0400 Subject: Fix typo in PIO SPI examples --- examples/rp/src/bin/pio_spi.rs | 6 +++--- examples/rp/src/bin/pio_spi_async.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/rp/src/bin/pio_spi.rs b/examples/rp/src/bin/pio_spi.rs index 4218327ec..c45aeac7d 100644 --- a/examples/rp/src/bin/pio_spi.rs +++ b/examples/rp/src/bin/pio_spi.rs @@ -27,9 +27,9 @@ async fn main(_spawner: Spawner) { // These pins are routed to different hardware SPI peripherals, but we can // use them together regardless - let mosi = p.PIN_6; // SPI0 SCLK - let miso = p.PIN_7; // SPI0 MOSI - let clk = p.PIN_8; // SPI1 MISO + let mosi = p.PIN_6; + let miso = p.PIN_7; + let clk = p.PIN_8; let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs); diff --git a/examples/rp/src/bin/pio_spi_async.rs b/examples/rp/src/bin/pio_spi_async.rs index 18b57d26e..e7d9b0ecc 100644 --- a/examples/rp/src/bin/pio_spi_async.rs +++ b/examples/rp/src/bin/pio_spi_async.rs @@ -27,9 +27,9 @@ async fn main(_spawner: Spawner) { // These pins are routed to different hardware SPI peripherals, but we can // use them together regardless - let mosi = p.PIN_6; // SPI0 SCLK - let miso = p.PIN_7; // SPI0 MOSI - let clk = p.PIN_8; // SPI1 MISO + let mosi = p.PIN_6; + let miso = p.PIN_7; + let clk = p.PIN_8; let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs); -- cgit From f829ddd3b236b146701951004b41525de4633c9a Mon Sep 17 00:00:00 2001 From: Riceman2000 Date: Fri, 12 Sep 2025 12:47:55 -0400 Subject: Example first draft --- examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs | 145 +++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs diff --git a/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs new file mode 100644 index 000000000..6f4ba4a70 --- /dev/null +++ b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs @@ -0,0 +1,145 @@ +//! This example implements a TCP client that attempts to connect to a host on port 1234 and send it some data once per second. +//! +//! Example written for the [`WIZnet W55RP20-EVB-Pico`](https://docs.wiznet.io/Product/ioNIC/W55RP20/w55rp20-evb-pico) board. +//! Note: the W55RP20 is a single package that contains both a RP2040 and the Wiznet W5500 ethernet +//! controller + +#![no_std] +#![no_main] + +use core::str::FromStr; + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::{Stack, StackResources}; +use embassy_net_wiznet::chip::W5500; +use embassy_net_wiznet::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::PIO0; +use embassy_rp::pio_programs::spi::Spi; +use embassy_rp::spi::{Async, Config as SpiConfig}; +use embassy_rp::{bind_interrupts, pio}; +use embassy_time::{Delay, Duration, Timer}; +use embedded_hal_bus::spi::ExclusiveDevice; +use embedded_io_async::Write; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => pio::InterruptHandler; +}); + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + W5500, + ExclusiveDevice, Output<'static>, Delay>, + Input<'static>, + Output<'static>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! { + runner.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + let mut led = Output::new(p.PIN_19, Level::Low); + + // The W55RP20 uses a PIO unit for SPI communication, once the SPI bus has been formed using a + // PIO statemachine everything else is generally unchanged from the other examples that use the W5500 + let mosi = p.PIN_23; + let miso = p.PIN_22; + let clk = p.PIN_21; + + let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs); + + // Construct an SPI driver backed by a PIO state machine + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let spi = Spi::new(&mut common, sm0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + + // Further control pins + let cs = Output::new(p.PIN_20, Level::High); + let w5500_int = Input::new(p.PIN_24, Pull::Up); + let w5500_reset = Output::new(p.PIN_25, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + static STATE: StaticCell> = StaticCell::new(); + let state = STATE.init(State::<8, 8>::new()); + let (device, runner) = embassy_net_wiznet::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await + .unwrap(); + spawner.spawn(unwrap!(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + static RESOURCES: StaticCell> = StaticCell::new(); + let (stack, runner) = embassy_net::new( + device, + embassy_net::Config::dhcpv4(Default::default()), + RESOURCES.init(StackResources::new()), + seed, + ); + + // Launch network task + spawner.spawn(unwrap!(net_task(runner))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + loop { + let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(Duration::from_secs(10))); + + led.set_low(); + info!("Connecting..."); + let host_addr = embassy_net::Ipv4Address::from_str("192.168.1.110").unwrap(); + if let Err(e) = socket.connect((host_addr, 1234)).await { + warn!("connect error: {:?}", e); + continue; + } + info!("Connected to {:?}", socket.remote_endpoint()); + led.set_high(); + + let msg = b"Hello world!\n"; + loop { + if let Err(e) = socket.write_all(msg).await { + warn!("write error: {:?}", e); + break; + } + info!("txd: {}", core::str::from_utf8(msg).unwrap()); + Timer::after_secs(1).await; + } + } +} + +async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 { + loop { + if let Some(config) = stack.config_v4() { + return config.clone(); + } + yield_now().await; + } +} -- cgit From 139ee907755bfa7817001c3ebc4a38eaf31cf243 Mon Sep 17 00:00:00 2001 From: riceman2000 Date: Fri, 12 Sep 2025 17:17:24 -0400 Subject: Updated example --- examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs | 34 +++++++++++++++------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs index 6f4ba4a70..17dc40aff 100644 --- a/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs @@ -1,4 +1,5 @@ -//! This example implements a TCP client that attempts to connect to a host on port 1234 and send it some data once per second. +//! This example implements a TCP echo server on port 1234 and using DHCP. +//! Send it some data, you should see it echoed back and printed in the console. //! //! Example written for the [`WIZnet W55RP20-EVB-Pico`](https://docs.wiznet.io/Product/ioNIC/W55RP20/w55rp20-evb-pico) board. //! Note: the W55RP20 is a single package that contains both a RP2040 and the Wiznet W5500 ethernet @@ -65,7 +66,8 @@ async fn main(spawner: Spawner) { // Construct an SPI driver backed by a PIO state machine let mut spi_cfg = SpiConfig::default(); - spi_cfg.frequency = 50_000_000; + spi_cfg.frequency = 10_000_000; // The PIO SPI program is much less stable than the actual SPI + // peripheral, use higher speeds at your peril let spi = Spi::new(&mut common, sm0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); // Further control pins @@ -109,28 +111,38 @@ async fn main(spawner: Spawner) { let mut rx_buffer = [0; 4096]; let mut tx_buffer = [0; 4096]; + let mut buf = [0; 4096]; loop { let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); socket.set_timeout(Some(Duration::from_secs(10))); led.set_low(); - info!("Connecting..."); - let host_addr = embassy_net::Ipv4Address::from_str("192.168.1.110").unwrap(); - if let Err(e) = socket.connect((host_addr, 1234)).await { - warn!("connect error: {:?}", e); + info!("Listening on TCP:1234..."); + if let Err(e) = socket.accept(1234).await { + warn!("accept error: {:?}", e); continue; } - info!("Connected to {:?}", socket.remote_endpoint()); + info!("Received connection from {:?}", socket.remote_endpoint()); led.set_high(); - let msg = b"Hello world!\n"; loop { - if let Err(e) = socket.write_all(msg).await { + let n = match socket.read(&mut buf).await { + Ok(0) => { + warn!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + warn!("{:?}", e); + break; + } + }; + info!("rxd {}", core::str::from_utf8(&buf[..n]).unwrap()); + + if let Err(e) = socket.write_all(&buf[..n]).await { warn!("write error: {:?}", e); break; } - info!("txd: {}", core::str::from_utf8(msg).unwrap()); - Timer::after_secs(1).await; } } } -- cgit From 6beb7e35a6bf2ae0e72a389b2dac6bde08e5dcd2 Mon Sep 17 00:00:00 2001 From: riceman2000 Date: Fri, 12 Sep 2025 22:52:53 -0400 Subject: Remove unused imports --- examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs index 17dc40aff..0d69b66c4 100644 --- a/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs @@ -8,8 +8,6 @@ #![no_std] #![no_main] -use core::str::FromStr; - use defmt::*; use embassy_executor::Spawner; use embassy_futures::yield_now; @@ -22,7 +20,7 @@ use embassy_rp::peripherals::PIO0; use embassy_rp::pio_programs::spi::Spi; use embassy_rp::spi::{Async, Config as SpiConfig}; use embassy_rp::{bind_interrupts, pio}; -use embassy_time::{Delay, Duration, Timer}; +use embassy_time::{Delay, Duration}; use embedded_hal_bus::spi::ExclusiveDevice; use embedded_io_async::Write; use static_cell::StaticCell; -- cgit From 8f10e3638d77cadf058b9083de09fc7189048b0b Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Sun, 14 Sep 2025 16:30:31 +0800 Subject: rp/pio: Add onewire strong pullups, parasite power DS18B20 sensors require a strong pullup to be applied for the duration of the temperature conversion, within 10us of the command. The rp2xxx pins have sufficient drive strength to use as the pullup (no external mosfet needed). Add a new write_bytes_pullup() that will apply the pullup after bytes are written. Existing read_bytes()/write_bytes() has no change to onewire timing. A pio_onewire_parasite example reads multiple sensors individually, applying the strong pullup. --- embassy-rp/CHANGELOG.md | 1 + embassy-rp/src/pio_programs/onewire.rs | 45 ++++++++++++++- examples/rp/src/bin/pio_onewire.rs | 1 + examples/rp/src/bin/pio_onewire_parasite.rs | 89 +++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 examples/rp/src/bin/pio_onewire_parasite.rs diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md index b50d41dd1..841c9f068 100644 --- a/embassy-rp/CHANGELOG.md +++ b/embassy-rp/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add PIO SPI - Add PIO I2S input +- Add PIO onewire parasite power strong pullup ## 0.8.0 - 2025-08-26 diff --git a/embassy-rp/src/pio_programs/onewire.rs b/embassy-rp/src/pio_programs/onewire.rs index 287ddab41..980d0fe5f 100644 --- a/embassy-rp/src/pio_programs/onewire.rs +++ b/embassy-rp/src/pio_programs/onewire.rs @@ -52,7 +52,8 @@ impl<'a, PIO: Instance> PioOneWireProgram<'a, PIO> { ; The low pulse was already done, we only need to delay and poll the bit in case we are reading write_1: - nop side 0 [( 6 / CLK) - 1] ; Delay before sampling the input pin + jmp y--, continue_1 side 0 [( 6 / CLK) - 1] ; Delay before sampling input. Always decrement y + continue_1: in pins, 1 side 0 [(48 / CLK) - 1] ; This writes the state of the pin into the ISR ; Fallthrough @@ -61,9 +62,24 @@ impl<'a, PIO: Instance> PioOneWireProgram<'a, PIO> { .wrap_target out x, 1 side 0 [(12 / CLK) - 1] ; Stalls if no data available in TX FIFO and OSR jmp x--, write_1 side 1 [( 6 / CLK) - 1] ; Do the always low part of a bit, jump to write_1 if we want to write a 1 bit - in null, 1 side 1 [(54 / CLK) - 1] ; Do the remainder of the low part of a 0 bit - ; This writes 0 into the ISR so that the shift count stays in sync + jmp y--, continue_0 side 1 [(48 / CLK) - 1] ; Do the remainder of the low part of a 0 bit + jmp pullup side 1 [( 6 / CLK) - 1] ; Remain low while jumping + continue_0: + in null, 1 side 1 [( 6 / CLK) - 1] ; This writes 0 into the ISR so that the shift count stays in sync .wrap + + ; Assume that strong pullup commands always have MSB (the last bit) = 0, + ; since the rising edge can be used to start the operation. + ; That's the case for DS18B20 (44h and 48h). + pullup: + set pins, 1 side 1[( 6 / CLK) - 1] ; Drive pin high output immediately. + ; Strong pullup must be within 10us of rise. + in null, 1 side 1[( 6 / CLK) - 1] ; Keep ISR in sync. Must occur after the y--. + out null, 8 side 1[( 6 / CLK) - 1] ; Wait for write_bytes_pullup() delay to complete. + ; The delay is hundreds of ms, so done externally. + set pins, 0 side 0[( 6 / CLK) - 1] ; Back to open drain, pin low when driven + in null, 8 side 1[( 6 / CLK) - 1] ; Inform write_bytes_pullup() it's ready + jmp next_bit side 0[( 6 / CLK) - 1] ; Continue "# ); @@ -98,6 +114,7 @@ impl<'d, PIO: Instance, const SM: usize> PioOneWire<'d, PIO, SM> { let mut cfg = Config::default(); cfg.use_program(&program.prg, &[&pin]); cfg.set_in_pins(&[&pin]); + cfg.set_set_pins(&[&pin]); let shift_cfg = ShiftConfig { auto_fill: true, @@ -146,6 +163,19 @@ impl<'d, PIO: Instance, const SM: usize> PioOneWire<'d, PIO, SM> { /// Write bytes to the onewire bus pub async fn write_bytes(&mut self, data: &[u8]) { + unsafe { self.sm.set_y(u32::MAX as u32) }; + let (rx, tx) = self.sm.rx_tx(); + for b in data { + tx.wait_push(*b as u32).await; + + // Empty the buffer that is being filled with every write + let _ = rx.wait_pull().await; + } + } + + /// Write bytes to the onewire bus, then apply a strong pullup + pub async fn write_bytes_pullup(&mut self, data: &[u8], pullup_time: embassy_time::Duration) { + unsafe { self.sm.set_y(data.len() as u32 * 8 - 1) }; let (rx, tx) = self.sm.rx_tx(); for b in data { tx.wait_push(*b as u32).await; @@ -153,10 +183,19 @@ impl<'d, PIO: Instance, const SM: usize> PioOneWire<'d, PIO, SM> { // Empty the buffer that is being filled with every write let _ = rx.wait_pull().await; } + + // Perform the delay, usually hundreds of ms. + embassy_time::Timer::after(pullup_time).await; + + // Signal that delay has completed + tx.wait_push(0 as u32).await; + // Wait until it's back at 0 low, open drain + let _ = rx.wait_pull().await; } /// Read bytes from the onewire bus pub async fn read_bytes(&mut self, data: &mut [u8]) { + unsafe { self.sm.set_y(u32::MAX as u32) }; let (rx, tx) = self.sm.rx_tx(); for b in data { // Write all 1's so that we can read what the device responds diff --git a/examples/rp/src/bin/pio_onewire.rs b/examples/rp/src/bin/pio_onewire.rs index 379e2b8f9..102f13c45 100644 --- a/examples/rp/src/bin/pio_onewire.rs +++ b/examples/rp/src/bin/pio_onewire.rs @@ -1,4 +1,5 @@ //! This example shows how you can use PIO to read one or more `DS18B20` one-wire temperature sensors. +//! This uses externally powered sensors. For parasite power, see the pio_onewire_parasite.rs example. #![no_std] #![no_main] diff --git a/examples/rp/src/bin/pio_onewire_parasite.rs b/examples/rp/src/bin/pio_onewire_parasite.rs new file mode 100644 index 000000000..fd076dee0 --- /dev/null +++ b/examples/rp/src/bin/pio_onewire_parasite.rs @@ -0,0 +1,89 @@ +//! This example shows how you can use PIO to read one or more `DS18B20` +//! one-wire temperature sensors using parasite power. +//! It applies a strong pullup during conversion, see "Powering the DS18B20" in the datasheet. +//! For externally powered sensors, use the pio_onewire.rs example. + +#![no_std] +#![no_main] +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::bind_interrupts; +use embassy_rp::peripherals::PIO0; +use embassy_rp::pio::{InterruptHandler, Pio}; +use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram, PioOneWireSearch}; +use embassy_time::Duration; +use heapless::Vec; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut pio = Pio::new(p.PIO0, Irqs); + + let prg = PioOneWireProgram::new(&mut pio.common); + let mut onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg); + + info!("Starting onewire search"); + + let mut devices = Vec::::new(); + let mut search = PioOneWireSearch::new(); + for _ in 0..10 { + if !search.is_finished() { + if let Some(address) = search.next(&mut onewire).await { + if crc8(&address.to_le_bytes()) == 0 { + info!("Found address: {:x}", address); + let _ = devices.push(address); + } else { + warn!("Found invalid address: {:x}", address); + } + } + } + } + + info!("Search done, found {} devices", devices.len()); + + loop { + // Read all devices one by one + for device in &devices { + onewire.reset().await; + onewire.write_bytes(&[0x55]).await; // Match rom + onewire.write_bytes(&device.to_le_bytes()).await; + // 750 ms delay required for default 12-bit resolution. + onewire.write_bytes_pullup(&[0x44], Duration::from_millis(750)).await; + + onewire.reset().await; + onewire.write_bytes(&[0x55]).await; // Match rom + onewire.write_bytes(&device.to_le_bytes()).await; + onewire.write_bytes(&[0xBE]).await; // Read scratchpad + + let mut data = [0; 9]; + onewire.read_bytes(&mut data).await; + if crc8(&data) == 0 { + let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; + info!("Read device {:x}: {} deg C", device, temp); + } else { + warn!("Reading device {:x} failed. {:02x}", device, data); + } + } + } +} + +fn crc8(data: &[u8]) -> u8 { + let mut crc = 0; + for b in data { + let mut data_byte = *b; + for _ in 0..8 { + let temp = (crc ^ data_byte) & 0x01; + crc >>= 1; + if temp != 0 { + crc ^= 0x8C; + } + data_byte >>= 1; + } + } + crc +} -- cgit From 7c551b4fdfd7fcf410423355a3a1b3f92d5f65a6 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Sun, 14 Sep 2025 16:38:20 +0800 Subject: rp/pio: Copy onewire examples from rp to rp235x The rp pio_onewire example was updated on cd27a8a06b0160d654ebed7b89ca473041710235 but not rp235x. Copy them to be the same. --- examples/rp235x/src/bin/pio_onewire.rs | 103 +++++++++++++----------- examples/rp235x/src/bin/pio_onewire_parasite.rs | 89 ++++++++++++++++++++ 2 files changed, 143 insertions(+), 49 deletions(-) create mode 100644 examples/rp235x/src/bin/pio_onewire_parasite.rs diff --git a/examples/rp235x/src/bin/pio_onewire.rs b/examples/rp235x/src/bin/pio_onewire.rs index 991510851..102f13c45 100644 --- a/examples/rp235x/src/bin/pio_onewire.rs +++ b/examples/rp235x/src/bin/pio_onewire.rs @@ -1,4 +1,5 @@ -//! This example shows how you can use PIO to read a `DS18B20` one-wire temperature sensor. +//! This example shows how you can use PIO to read one or more `DS18B20` one-wire temperature sensors. +//! This uses externally powered sensors. For parasite power, see the pio_onewire_parasite.rs example. #![no_std] #![no_main] @@ -6,9 +7,10 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::bind_interrupts; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{self, InterruptHandler, Pio}; -use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram}; +use embassy_rp::pio::{InterruptHandler, Pio}; +use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram, PioOneWireSearch}; use embassy_time::Timer; +use heapless::Vec; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { @@ -21,63 +23,66 @@ async fn main(_spawner: Spawner) { let mut pio = Pio::new(p.PIO0, Irqs); let prg = PioOneWireProgram::new(&mut pio.common); - let onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg); + let mut onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg); - let mut sensor = Ds18b20::new(onewire); + info!("Starting onewire search"); - loop { - sensor.start().await; // Start a new measurement - Timer::after_secs(1).await; // Allow 1s for the measurement to finish - match sensor.temperature().await { - Ok(temp) => info!("temp = {:?} deg C", temp), - _ => error!("sensor error"), + let mut devices = Vec::::new(); + let mut search = PioOneWireSearch::new(); + for _ in 0..10 { + if !search.is_finished() { + if let Some(address) = search.next(&mut onewire).await { + if crc8(&address.to_le_bytes()) == 0 { + info!("Found addres: {:x}", address); + let _ = devices.push(address); + } else { + warn!("Found invalid address: {:x}", address); + } + } } - Timer::after_secs(1).await; } -} -/// DS18B20 temperature sensor driver -pub struct Ds18b20<'d, PIO: pio::Instance, const SM: usize> { - wire: PioOneWire<'d, PIO, SM>, -} + info!("Search done, found {} devices", devices.len()); -impl<'d, PIO: pio::Instance, const SM: usize> Ds18b20<'d, PIO, SM> { - pub fn new(wire: PioOneWire<'d, PIO, SM>) -> Self { - Self { wire } - } + loop { + onewire.reset().await; + // Skip rom and trigger conversion, we can trigger all devices on the bus immediately + onewire.write_bytes(&[0xCC, 0x44]).await; - /// Calculate CRC8 of the data - fn crc8(data: &[u8]) -> u8 { - let mut temp; - let mut data_byte; - let mut crc = 0; - for b in data { - data_byte = *b; - for _ in 0..8 { - temp = (crc ^ data_byte) & 0x01; - crc >>= 1; - if temp != 0 { - crc ^= 0x8C; - } - data_byte >>= 1; + Timer::after_secs(1).await; // Allow 1s for the measurement to finish + + // Read all devices one by one + for device in &devices { + onewire.reset().await; + onewire.write_bytes(&[0x55]).await; // Match rom + onewire.write_bytes(&device.to_le_bytes()).await; + onewire.write_bytes(&[0xBE]).await; // Read scratchpad + + let mut data = [0; 9]; + onewire.read_bytes(&mut data).await; + if crc8(&data) == 0 { + let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; + info!("Read device {:x}: {} deg C", device, temp); + } else { + warn!("Reading device {:x} failed", device); } } - crc - } - - /// Start a new measurement. Allow at least 1000ms before getting `temperature`. - pub async fn start(&mut self) { - self.wire.write_bytes(&[0xCC, 0x44]).await; + Timer::after_secs(1).await; } +} - /// Read the temperature. Ensure >1000ms has passed since `start` before calling this. - pub async fn temperature(&mut self) -> Result { - self.wire.write_bytes(&[0xCC, 0xBE]).await; - let mut data = [0; 9]; - self.wire.read_bytes(&mut data).await; - match Self::crc8(&data) == 0 { - true => Ok(((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.), - false => Err(()), +fn crc8(data: &[u8]) -> u8 { + let mut crc = 0; + for b in data { + let mut data_byte = *b; + for _ in 0..8 { + let temp = (crc ^ data_byte) & 0x01; + crc >>= 1; + if temp != 0 { + crc ^= 0x8C; + } + data_byte >>= 1; } } + crc } diff --git a/examples/rp235x/src/bin/pio_onewire_parasite.rs b/examples/rp235x/src/bin/pio_onewire_parasite.rs new file mode 100644 index 000000000..fd076dee0 --- /dev/null +++ b/examples/rp235x/src/bin/pio_onewire_parasite.rs @@ -0,0 +1,89 @@ +//! This example shows how you can use PIO to read one or more `DS18B20` +//! one-wire temperature sensors using parasite power. +//! It applies a strong pullup during conversion, see "Powering the DS18B20" in the datasheet. +//! For externally powered sensors, use the pio_onewire.rs example. + +#![no_std] +#![no_main] +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::bind_interrupts; +use embassy_rp::peripherals::PIO0; +use embassy_rp::pio::{InterruptHandler, Pio}; +use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram, PioOneWireSearch}; +use embassy_time::Duration; +use heapless::Vec; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut pio = Pio::new(p.PIO0, Irqs); + + let prg = PioOneWireProgram::new(&mut pio.common); + let mut onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg); + + info!("Starting onewire search"); + + let mut devices = Vec::::new(); + let mut search = PioOneWireSearch::new(); + for _ in 0..10 { + if !search.is_finished() { + if let Some(address) = search.next(&mut onewire).await { + if crc8(&address.to_le_bytes()) == 0 { + info!("Found address: {:x}", address); + let _ = devices.push(address); + } else { + warn!("Found invalid address: {:x}", address); + } + } + } + } + + info!("Search done, found {} devices", devices.len()); + + loop { + // Read all devices one by one + for device in &devices { + onewire.reset().await; + onewire.write_bytes(&[0x55]).await; // Match rom + onewire.write_bytes(&device.to_le_bytes()).await; + // 750 ms delay required for default 12-bit resolution. + onewire.write_bytes_pullup(&[0x44], Duration::from_millis(750)).await; + + onewire.reset().await; + onewire.write_bytes(&[0x55]).await; // Match rom + onewire.write_bytes(&device.to_le_bytes()).await; + onewire.write_bytes(&[0xBE]).await; // Read scratchpad + + let mut data = [0; 9]; + onewire.read_bytes(&mut data).await; + if crc8(&data) == 0 { + let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; + info!("Read device {:x}: {} deg C", device, temp); + } else { + warn!("Reading device {:x} failed. {:02x}", device, data); + } + } + } +} + +fn crc8(data: &[u8]) -> u8 { + let mut crc = 0; + for b in data { + let mut data_byte = *b; + for _ in 0..8 { + let temp = (crc ^ data_byte) & 0x01; + crc >>= 1; + if temp != 0 { + crc ^= 0x8C; + } + data_byte >>= 1; + } + } + crc +} -- cgit From daae1fe5c9357ae97b897defae3d149eeafcc49f Mon Sep 17 00:00:00 2001 From: riceman2000 Date: Sun, 14 Sep 2025 11:30:22 -0400 Subject: Up SPI freq --- examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs index 0d69b66c4..f51df2df9 100644 --- a/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) { // Construct an SPI driver backed by a PIO state machine let mut spi_cfg = SpiConfig::default(); - spi_cfg.frequency = 10_000_000; // The PIO SPI program is much less stable than the actual SPI + spi_cfg.frequency = 12_500_000; // The PIO SPI program is much less stable than the actual SPI // peripheral, use higher speeds at your peril let spi = Spi::new(&mut common, sm0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); -- cgit From 1c080559fd20eb250e76278ff92d23432b5e0ce8 Mon Sep 17 00:00:00 2001 From: riceman2000 Date: Sun, 14 Sep 2025 14:14:59 -0400 Subject: Fix removed comments --- examples/rp/src/bin/pio_spi.rs | 6 +++--- examples/rp/src/bin/pio_spi_async.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/rp/src/bin/pio_spi.rs b/examples/rp/src/bin/pio_spi.rs index c45aeac7d..4218327ec 100644 --- a/examples/rp/src/bin/pio_spi.rs +++ b/examples/rp/src/bin/pio_spi.rs @@ -27,9 +27,9 @@ async fn main(_spawner: Spawner) { // These pins are routed to different hardware SPI peripherals, but we can // use them together regardless - let mosi = p.PIN_6; - let miso = p.PIN_7; - let clk = p.PIN_8; + let mosi = p.PIN_6; // SPI0 SCLK + let miso = p.PIN_7; // SPI0 MOSI + let clk = p.PIN_8; // SPI1 MISO let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs); diff --git a/examples/rp/src/bin/pio_spi_async.rs b/examples/rp/src/bin/pio_spi_async.rs index e7d9b0ecc..18b57d26e 100644 --- a/examples/rp/src/bin/pio_spi_async.rs +++ b/examples/rp/src/bin/pio_spi_async.rs @@ -27,9 +27,9 @@ async fn main(_spawner: Spawner) { // These pins are routed to different hardware SPI peripherals, but we can // use them together regardless - let mosi = p.PIN_6; - let miso = p.PIN_7; - let clk = p.PIN_8; + let mosi = p.PIN_6; // SPI0 SCLK + let miso = p.PIN_7; // SPI0 MOSI + let clk = p.PIN_8; // SPI1 MISO let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs); -- cgit From db1275358cfc33bb1ae3eeca47ddbfb73fe7cf48 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Mon, 15 Sep 2025 18:05:30 +0800 Subject: add gpio speed to qspi config --- embassy-stm32/src/qspi/mod.rs | 51 +++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index c0cd216f0..0ed661115 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -62,6 +62,8 @@ pub struct Config { pub cs_high_time: ChipSelectHighTime, /// Shift sampling point of input data (none, or half-cycle) pub sample_shifting: SampleShifting, + /// GPIO Speed + pub gpio_speed: Speed, } impl Default for Config { @@ -73,6 +75,7 @@ impl Default for Config { fifo_threshold: FIFOThresholdLevel::_17Bytes, cs_high_time: ChipSelectHighTime::_5Cycle, sample_shifting: SampleShifting::None, + gpio_speed: Speed::VeryHigh, } } } @@ -286,14 +289,14 @@ impl<'d, T: Instance> Qspi<'d, T, Blocking> { ) -> Self { Self::new_inner( peri, - new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d0, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(d1, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(d2, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(d3, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(sck, AfType::output(OutputType::PushPull, config.gpio_speed)), new_pin!( nss, - AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up) + AfType::output_pull(OutputType::PushPull, config.gpio_speed, Pull::Up) ), None, config, @@ -314,14 +317,14 @@ impl<'d, T: Instance> Qspi<'d, T, Blocking> { ) -> Self { Self::new_inner( peri, - new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d0, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(d1, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(d2, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(d3, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(sck, AfType::output(OutputType::PushPull, config.gpio_speed)), new_pin!( nss, - AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up) + AfType::output_pull(OutputType::PushPull, config.gpio_speed, Pull::Up) ), None, config, @@ -345,14 +348,14 @@ impl<'d, T: Instance> Qspi<'d, T, Async> { ) -> Self { Self::new_inner( peri, - new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d0, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(d1, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(d2, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(d3, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(sck, AfType::output(OutputType::PushPull, config.gpio_speed)), new_pin!( nss, - AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up) + AfType::output_pull(OutputType::PushPull, config.gpio_speed, Pull::Up) ), new_dma!(dma), config, @@ -374,14 +377,14 @@ impl<'d, T: Instance> Qspi<'d, T, Async> { ) -> Self { Self::new_inner( peri, - new_pin!(d0, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(d1, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(d2, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(d3, AfType::output(OutputType::PushPull, Speed::VeryHigh)), - new_pin!(sck, AfType::output(OutputType::PushPull, Speed::VeryHigh)), + new_pin!(d0, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(d1, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(d2, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(d3, AfType::output(OutputType::PushPull, config.gpio_speed)), + new_pin!(sck, AfType::output(OutputType::PushPull, config.gpio_speed)), new_pin!( nss, - AfType::output_pull(OutputType::PushPull, Speed::VeryHigh, Pull::Up) + AfType::output_pull(OutputType::PushPull, config.gpio_speed, Pull::Up) ), new_dma!(dma), config, -- cgit From 9a4bdec392af3e0e60c190c035875485d2a11433 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Mon, 15 Sep 2025 18:07:56 +0800 Subject: update changelog --- embassy-stm32/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 93a1f4f64..eb48fd6fe 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - feat: Added support for more OctoSPI configurations (e.g. APS6408 RAM) ([#4581](https://github.com/embassy-rs/embassy/pull/4581)) - fix: stm32/usart: fix bug with blocking flush in buffered uart ([#4648](https://github.com/embassy-rs/embassy/pull/4648)) - fix: stm32/(ospi/hspi/xspi): Fix the alternate bytes register config sticking around for subsequent writes +- feat: Configurable gpio speed for QSPI ## 0.4.0 - 2025-08-26 -- cgit From 219754ff6c82b79a0870faeeb6a79b88e4b6901c Mon Sep 17 00:00:00 2001 From: dimi Date: Tue, 22 Jul 2025 18:37:04 +0200 Subject: derive Debug and Format for Averaging --- embassy-stm32/src/adc/adc4.rs | 3 ++- embassy-stm32/src/adc/c0.rs | 3 ++- embassy-stm32/src/adc/v3.rs | 2 ++ embassy-stm32/src/adc/v4.rs | 3 ++- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/adc/adc4.rs b/embassy-stm32/src/adc/adc4.rs index 31cbdc0d7..255dc7956 100644 --- a/embassy-stm32/src/adc/adc4.rs +++ b/embassy-stm32/src/adc/adc4.rs @@ -83,7 +83,8 @@ pub enum DacChannel { } /// Number of samples used for averaging. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Averaging { Disabled, Samples2, diff --git a/embassy-stm32/src/adc/c0.rs b/embassy-stm32/src/adc/c0.rs index f5870801e..f2837a8f1 100644 --- a/embassy-stm32/src/adc/c0.rs +++ b/embassy-stm32/src/adc/c0.rs @@ -138,7 +138,8 @@ impl<'a> defmt::Format for Prescaler { /// Number of samples used for averaging. /// TODO: Implement hardware averaging setting. #[allow(unused)] -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Averaging { Disabled, Samples2, diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index 77f24c87f..fdf76fd30 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -96,6 +96,8 @@ cfg_if! { } /// Number of samples used for averaging. +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Averaging { Disabled, Samples2, diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index b0871019a..b66437e6e 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs @@ -142,7 +142,8 @@ impl Prescaler { } /// Number of samples used for averaging. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Averaging { Disabled, Samples2, -- cgit From 5ee77055a1d0073c3e5f312764acd566b1b92f84 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Mon, 15 Sep 2025 18:43:23 +0800 Subject: fix examples --- examples/stm32f7/src/bin/qspi.rs | 16 ++++++++-------- examples/stm32h742/src/bin/qspi.rs | 16 ++++++++-------- examples/stm32l432/src/bin/qspi_mmap.rs | 16 ++++++++-------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/examples/stm32f7/src/bin/qspi.rs b/examples/stm32f7/src/bin/qspi.rs index ab29ddeff..80652b865 100644 --- a/examples/stm32f7/src/bin/qspi.rs +++ b/examples/stm32f7/src/bin/qspi.rs @@ -273,14 +273,14 @@ async fn main(_spawner: Spawner) -> ! { let p = embassy_stm32::init(config); info!("Embassy initialized"); - let config = QspiCfg { - memory_size: MemorySize::_8MiB, - address_size: AddressSize::_24bit, - prescaler: 16, - cs_high_time: ChipSelectHighTime::_1Cycle, - fifo_threshold: FIFOThresholdLevel::_16Bytes, - sample_shifting: SampleShifting::None, - }; + let mut config = QspiCfg::default(); + config.memory_size = MemorySize::_8MiB; + config.address_size = AddressSize::_24bit; + config.prescaler = 16; + config.cs_high_time = ChipSelectHighTime::_1Cycle; + config.fifo_threshold = FIFOThresholdLevel::_16Bytes; + config.sample_shifting = SampleShifting::None; + let driver = Qspi::new_bank1( p.QUADSPI, p.PF8, p.PF9, p.PE2, p.PF6, p.PF10, p.PB10, p.DMA2_CH7, config, ); diff --git a/examples/stm32h742/src/bin/qspi.rs b/examples/stm32h742/src/bin/qspi.rs index 50e37ec52..9e79d7089 100644 --- a/examples/stm32h742/src/bin/qspi.rs +++ b/examples/stm32h742/src/bin/qspi.rs @@ -266,14 +266,14 @@ async fn main(_spawner: Spawner) -> ! { let p = embassy_stm32::init(config); info!("Embassy initialized"); - let config = QspiCfg { - memory_size: MemorySize::_8MiB, - address_size: AddressSize::_24bit, - prescaler: 16, - cs_high_time: ChipSelectHighTime::_1Cycle, - fifo_threshold: FIFOThresholdLevel::_16Bytes, - sample_shifting: SampleShifting::None, - }; + let mut config = QspiCfg::default(); + config.memory_size = MemorySize::_8MiB; + config.address_size = AddressSize::_24bit; + config.prescaler = 16; + config.cs_high_time = ChipSelectHighTime::_1Cycle; + config.fifo_threshold = FIFOThresholdLevel::_16Bytes; + config.sample_shifting = SampleShifting::None; + let driver = Qspi::new_blocking_bank1(p.QUADSPI, p.PD11, p.PD12, p.PE2, p.PD13, p.PB2, p.PB10, config); let mut flash = FlashMemory::new(driver); let flash_id = flash.read_id(); diff --git a/examples/stm32l432/src/bin/qspi_mmap.rs b/examples/stm32l432/src/bin/qspi_mmap.rs index 075458fe5..feabdd532 100644 --- a/examples/stm32l432/src/bin/qspi_mmap.rs +++ b/examples/stm32l432/src/bin/qspi_mmap.rs @@ -246,14 +246,14 @@ const MEMORY_ADDR: u32 = 0x00000000 as u32; async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let config = qspi::Config { - memory_size: MemorySize::_16MiB, - address_size: AddressSize::_24bit, - prescaler: 200, - cs_high_time: ChipSelectHighTime::_1Cycle, - fifo_threshold: FIFOThresholdLevel::_16Bytes, - sample_shifting: SampleShifting::None, - }; + let mut config = qspi::Config::default(); + config.memory_size = MemorySize::_16MiB; + config.address_size = AddressSize::_24bit; + config.prescaler = 200; + config.cs_high_time = ChipSelectHighTime::_1Cycle; + config.fifo_threshold = FIFOThresholdLevel::_16Bytes; + config.sample_shifting = SampleShifting::None; + let driver = qspi::Qspi::new_bank1(p.QUADSPI, p.PB1, p.PB0, p.PA7, p.PA6, p.PA3, p.PA2, p.DMA2_CH7, config); let mut flash = FlashMemory::new(driver); let mut wr_buf = [0u8; 256]; -- cgit From 77d82516131ca37a706e1965e44fca40854931c5 Mon Sep 17 00:00:00 2001 From: Süha Ünüvar <87157627+phycrax@users.noreply.github.com> Date: Mon, 15 Sep 2025 18:44:52 +0800 Subject: tag config as non exhaustive --- embassy-stm32/src/qspi/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index 0ed661115..0644069a6 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -48,6 +48,7 @@ impl Default for TransferConfig { /// QSPI driver configuration. #[derive(Clone, Copy)] +#[non_exhaustive] pub struct Config { /// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen. /// If you need other value the whose predefined use `Other` variant. -- cgit From 83209b812c5bc5b5db3ee1624b1eff27c6a45cf6 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 15 Sep 2025 14:03:12 +0200 Subject: Use new docserver bin to build docs. --- .github/ci/doc.sh | 68 +++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index ac96008d8..7d6544e73 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -19,42 +19,42 @@ mv rust-toolchain-nightly.toml rust-toolchain.toml # which makes rustup very sad rustc --version > /dev/null -docserver-builder -i ./embassy-boot -o webroot/crates/embassy-boot/git.zup -docserver-builder -i ./embassy-boot-nrf -o webroot/crates/embassy-boot-nrf/git.zup -docserver-builder -i ./embassy-boot-rp -o webroot/crates/embassy-boot-rp/git.zup -docserver-builder -i ./embassy-boot-stm32 -o webroot/crates/embassy-boot-stm32/git.zup -docserver-builder -i ./embassy-embedded-hal -o webroot/crates/embassy-embedded-hal/git.zup -docserver-builder -i ./embassy-executor -o webroot/crates/embassy-executor/git.zup -docserver-builder -i ./embassy-futures -o webroot/crates/embassy-futures/git.zup -docserver-builder -i ./embassy-nrf -o webroot/crates/embassy-nrf/git.zup -docserver-builder -i ./embassy-rp -o webroot/crates/embassy-rp/git.zup -docserver-builder -i ./embassy-mspm0 -o webroot/crates/embassy-mspm0/git.zup -docserver-builder -i ./embassy-nxp -o webroot/crates/embassy-nxp/git.zup -docserver-builder -i ./embassy-sync -o webroot/crates/embassy-sync/git.zup -docserver-builder -i ./cyw43 -o webroot/crates/cyw43/git.zup -docserver-builder -i ./cyw43-pio -o webroot/crates/cyw43-pio/git.zup -docserver-builder -i ./embassy-stm32-wpan -o webroot/crates/embassy-stm32-wpan/git.zup --output-static webroot/static +docserver build -c -i ./embassy-boot -o webroot/crates/embassy-boot/git.zup +docserver build -c -i ./embassy-boot-nrf -o webroot/crates/embassy-boot-nrf/git.zup +docserver build -c -i ./embassy-boot-rp -o webroot/crates/embassy-boot-rp/git.zup +docserver build -c -i ./embassy-boot-stm32 -o webroot/crates/embassy-boot-stm32/git.zup +docserver build -c -i ./embassy-embedded-hal -o webroot/crates/embassy-embedded-hal/git.zup +docserver build -c -i ./embassy-executor -o webroot/crates/embassy-executor/git.zup +docserver build -c -i ./embassy-futures -o webroot/crates/embassy-futures/git.zup +docserver build -c -i ./embassy-nrf -o webroot/crates/embassy-nrf/git.zup +docserver build -c -i ./embassy-rp -o webroot/crates/embassy-rp/git.zup +docserver build -c -i ./embassy-mspm0 -o webroot/crates/embassy-mspm0/git.zup +docserver build -c -i ./embassy-nxp -o webroot/crates/embassy-nxp/git.zup +docserver build -c -i ./embassy-sync -o webroot/crates/embassy-sync/git.zup +docserver build -c -i ./cyw43 -o webroot/crates/cyw43/git.zup +docserver build -c -i ./cyw43-pio -o webroot/crates/cyw43-pio/git.zup +docserver build -c -i ./embassy-stm32-wpan -o webroot/crates/embassy-stm32-wpan/git.zup --output-static webroot/static -docserver-builder -i ./embassy-time -o webroot/crates/embassy-time/git.zup -docserver-builder -i ./embassy-time-driver -o webroot/crates/embassy-time-driver/git.zup -docserver-builder -i ./embassy-time-queue-utils -o webroot/crates/embassy-time-queue-utils/git.zup +docserver build -c -i ./embassy-time -o webroot/crates/embassy-time/git.zup +docserver build -c -i ./embassy-time-driver -o webroot/crates/embassy-time-driver/git.zup +docserver build -c -i ./embassy-time-queue-utils -o webroot/crates/embassy-time-queue-utils/git.zup -docserver-builder -i ./embassy-usb -o webroot/crates/embassy-usb/git.zup -docserver-builder -i ./embassy-usb-dfu -o webroot/crates/embassy-usb-dfu/git.zup -docserver-builder -i ./embassy-usb-driver -o webroot/crates/embassy-usb-driver/git.zup -docserver-builder -i ./embassy-usb-logger -o webroot/crates/embassy-usb-logger/git.zup -docserver-builder -i ./embassy-usb-synopsys-otg -o webroot/crates/embassy-usb-synopsys-otg/git.zup +docserver build -c -i ./embassy-usb -o webroot/crates/embassy-usb/git.zup +docserver build -c -i ./embassy-usb-dfu -o webroot/crates/embassy-usb-dfu/git.zup +docserver build -c -i ./embassy-usb-driver -o webroot/crates/embassy-usb-driver/git.zup +docserver build -c -i ./embassy-usb-logger -o webroot/crates/embassy-usb-logger/git.zup +docserver build -c -i ./embassy-usb-synopsys-otg -o webroot/crates/embassy-usb-synopsys-otg/git.zup -docserver-builder -i ./embassy-net -o webroot/crates/embassy-net/git.zup -docserver-builder -i ./embassy-net-nrf91 -o webroot/crates/embassy-net-nrf91/git.zup -docserver-builder -i ./embassy-net-driver -o webroot/crates/embassy-net-driver/git.zup -docserver-builder -i ./embassy-net-driver-channel -o webroot/crates/embassy-net-driver-channel/git.zup -docserver-builder -i ./embassy-net-wiznet -o webroot/crates/embassy-net-wiznet/git.zup -docserver-builder -i ./embassy-net-ppp -o webroot/crates/embassy-net-ppp/git.zup -docserver-builder -i ./embassy-net-tuntap -o webroot/crates/embassy-net-tuntap/git.zup -docserver-builder -i ./embassy-net-enc28j60 -o webroot/crates/embassy-net-enc28j60/git.zup -docserver-builder -i ./embassy-net-esp-hosted -o webroot/crates/embassy-net-esp-hosted/git.zup -docserver-builder -i ./embassy-net-adin1110 -o webroot/crates/embassy-net-adin1110/git.zup +docserver build -c -i ./embassy-net -o webroot/crates/embassy-net/git.zup +docserver build -c -i ./embassy-net-nrf91 -o webroot/crates/embassy-net-nrf91/git.zup +docserver build -c -i ./embassy-net-driver -o webroot/crates/embassy-net-driver/git.zup +docserver build -c -i ./embassy-net-driver-channel -o webroot/crates/embassy-net-driver-channel/git.zup +docserver build -c -i ./embassy-net-wiznet -o webroot/crates/embassy-net-wiznet/git.zup +docserver build -c -i ./embassy-net-ppp -o webroot/crates/embassy-net-ppp/git.zup +docserver build -c -i ./embassy-net-tuntap -o webroot/crates/embassy-net-tuntap/git.zup +docserver build -c -i ./embassy-net-enc28j60 -o webroot/crates/embassy-net-enc28j60/git.zup +docserver build -c -i ./embassy-net-esp-hosted -o webroot/crates/embassy-net-esp-hosted/git.zup +docserver build -c -i ./embassy-net-adin1110 -o webroot/crates/embassy-net-adin1110/git.zup export KUBECONFIG=/ci/secrets/kubeconfig.yml POD=$(kubectl -n embassy get po -l app=docserver -o jsonpath={.items[0].metadata.name}) @@ -65,6 +65,6 @@ kubectl cp webroot/static $POD:/data # so that it doesn't prevent other crates from getting docs updates when it breaks. rm -rf webroot -docserver-builder -i ./embassy-stm32 -o webroot/crates/embassy-stm32/git.zup +docserver build -c -i ./embassy-stm32 -o webroot/crates/embassy-stm32/git.zup POD=$(kubectl -n embassy get po -l app=docserver -o jsonpath={.items[0].metadata.name}) kubectl cp webroot/crates $POD:/data -- cgit

You might want to browse the `embassy-mspm0` documentation on the Embassy website instead.

The documentation here on `docs.rs` is built for a single chip only, while on the Embassy website you can pick your exact chip from the top menu. Available peripherals and their APIs change depending on the chip.