From 96cdf9c9e046300b76969c39ac950d512e0184ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kr=C3=B3lczyk?= Date: Thu, 27 Jun 2024 21:22:16 +0200 Subject: [PATCH 1/8] rp/i2c: add address flexibility and example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous i2c examples are using either blocking Embassy API or e-h traits, this example uses Embassy pub API directly. Signed-off-by: Krzysztof Królczyk --- embassy-rp/src/i2c.rs | 38 +++++------ examples/rp/src/bin/i2c_async_embassy.rs | 85 ++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 22 deletions(-) create mode 100644 examples/rp/src/bin/i2c_async_embassy.rs diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index 10ccca674..10d3c86b3 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -313,25 +313,29 @@ impl<'d, T: Instance> I2c<'d, T, Async> { } /// Read from address into buffer using DMA. - pub async fn read_async(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Error> { - Self::setup(addr)?; + pub async fn read_async(&mut self, addr: impl Into, buffer: &mut [u8]) -> Result<(), Error> { + Self::setup(addr.into())?; self.read_async_internal(buffer, true, true).await } /// Write to address from buffer using DMA. - pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator) -> Result<(), Error> { - Self::setup(addr)?; + pub async fn write_async( + &mut self, + addr: impl Into, + bytes: impl IntoIterator, + ) -> Result<(), Error> { + Self::setup(addr.into())?; self.write_async_internal(bytes, true).await } /// Write to address from bytes and read from address into buffer using DMA. pub async fn write_read_async( &mut self, - addr: u16, + addr: impl Into, bytes: impl IntoIterator, buffer: &mut [u8], ) -> Result<(), Error> { - Self::setup(addr)?; + Self::setup(addr.into())?; self.write_async_internal(bytes, false).await?; self.read_async_internal(buffer, true, true).await } @@ -595,20 +599,20 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { // ========================= /// Read from address into buffer blocking caller until done. - pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { + pub fn blocking_read(&mut self, address: impl Into, read: &mut [u8]) -> Result<(), Error> { Self::setup(address.into())?; self.read_blocking_internal(read, true, true) // Automatic Stop } /// Write to address from buffer blocking caller until done. - pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { + pub fn blocking_write(&mut self, address: impl Into, write: &[u8]) -> Result<(), Error> { Self::setup(address.into())?; self.write_blocking_internal(write, true) } /// Write to address from bytes and read from address into buffer blocking caller until done. - pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { + pub fn blocking_write_read(&mut self, address: impl Into, write: &[u8], read: &mut [u8]) -> Result<(), Error> { Self::setup(address.into())?; self.write_blocking_internal(write, false)?; self.read_blocking_internal(read, true, true) @@ -719,25 +723,15 @@ where T: Instance + 'd, { async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> { - let addr: u16 = address.into(); - - Self::setup(addr)?; - self.read_async_internal(read, false, true).await + self.read_async(address, read).await } async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> { - let addr: u16 = address.into(); - - Self::setup(addr)?; - self.write_async_internal(write.iter().copied(), true).await + self.write_async(address, write.iter().copied()).await } async fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { - let addr: u16 = address.into(); - - Self::setup(addr)?; - self.write_async_internal(write.iter().cloned(), false).await?; - self.read_async_internal(read, true, true).await + self.write_read_async(address, write.iter().copied(), read).await } async fn transaction( diff --git a/examples/rp/src/bin/i2c_async_embassy.rs b/examples/rp/src/bin/i2c_async_embassy.rs new file mode 100644 index 000000000..a65b71b9f --- /dev/null +++ b/examples/rp/src/bin/i2c_async_embassy.rs @@ -0,0 +1,85 @@ +//! This example shows how to communicate asynchronous using i2c with external chip. +//! +//! It's using embassy's functions directly instead of traits from embedded_hal_async::i2c::I2c. +//! While most of i2c devices are addressed using 7 bits, an extension allows 10 bits too. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_rp::i2c::InterruptHandler; +use {defmt_rtt as _, panic_probe as _}; + +// Our anonymous hypotetical temperature sensor could be: +// a 12-bit sensor, with 100ms startup time, range of -40*C - 125*C, and precision 0.25*C +// It requires no configuration or calibration, works with all i2c bus speeds, +// never stretches clock or does anything complicated. Replies with one u16. +// It requires only one write to take it out of suspend mode, and stays on. +// Often result would be just on 12 bits, but here we'll simplify it to 16. + +enum UncomplicatedSensorId { + A(UncomplicatedSensorU8), + B(UncomplicatedSensorU16), +} +enum UncomplicatedSensorU8 { + First = 0x48, +} +enum UncomplicatedSensorU16 { + Other = 0x0049, +} + +impl Into for UncomplicatedSensorU16 { + fn into(self) -> u16 { + self as u16 + } +} +impl Into for UncomplicatedSensorU8 { + fn into(self) -> u16 { + 0x48 + } +} +impl From for u16 { + fn from(t: UncomplicatedSensorId) -> Self { + match t { + UncomplicatedSensorId::A(x) => x.into(), + UncomplicatedSensorId::B(x) => x.into(), + } + } +} + +embassy_rp::bind_interrupts!(struct Irqs { + I2C1_IRQ => InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_task_spawner: embassy_executor::Spawner) { + let p = embassy_rp::init(Default::default()); + let sda = p.PIN_14; + let scl = p.PIN_15; + let config = embassy_rp::i2c::Config::default(); + let mut bus = embassy_rp::i2c::I2c::new_async(p.I2C1, scl, sda, Irqs, config); + + const WAKEYWAKEY: u16 = 0xBABE; + let mut result: [u8; 2] = [0, 0]; + // wait for sensors to initialize + embassy_time::Timer::after(embassy_time::Duration::from_millis(100)).await; + + let _res_1 = bus + .write_async(UncomplicatedSensorU8::First, WAKEYWAKEY.to_be_bytes()) + .await; + let _res_2 = bus + .write_async(UncomplicatedSensorU16::Other, WAKEYWAKEY.to_be_bytes()) + .await; + + loop { + let s1 = UncomplicatedSensorId::A(UncomplicatedSensorU8::First); + let s2 = UncomplicatedSensorId::B(UncomplicatedSensorU16::Other); + let sensors = [s1, s2]; + for sensor in sensors { + if bus.read_async(sensor, &mut result).await.is_ok() { + info!("Result {}", u16::from_be_bytes(result.into())); + } + } + embassy_time::Timer::after(embassy_time::Duration::from_millis(200)).await; + } +} From cbc67469d3faa65c4839657609b8e804bcfd75fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Flemstr=C3=B6m?= Date: Fri, 28 Jun 2024 19:10:59 +0200 Subject: [PATCH 2/8] Route sources of panics to the crate's fmt macros --- embassy-boot-nrf/src/lib.rs | 8 +++++++- embassy-boot-rp/src/lib.rs | 8 +++++++- embassy-boot-stm32/src/lib.rs | 8 +++++++- embassy-boot/src/test_flash/asynch.rs | 2 +- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/embassy-boot-nrf/src/lib.rs b/embassy-boot-nrf/src/lib.rs index d53e78895..e5bc870b5 100644 --- a/embassy-boot-nrf/src/lib.rs +++ b/embassy-boot-nrf/src/lib.rs @@ -20,7 +20,13 @@ impl BootLoader { pub fn prepare( config: BootLoaderConfig, ) -> Self { - Self::try_prepare::(config).expect("Boot prepare error") + if let Ok(loader) = Self::try_prepare::(config) { + loader + } else { + // Use explicit panic instead of .expect() to ensure this gets routed via defmt/etc. + // properly + panic!("Boot prepare error") + } } /// Inspect the bootloader state and perform actions required before booting, such as swapping firmware diff --git a/embassy-boot-rp/src/lib.rs b/embassy-boot-rp/src/lib.rs index d0a393bed..3e1731f5e 100644 --- a/embassy-boot-rp/src/lib.rs +++ b/embassy-boot-rp/src/lib.rs @@ -21,7 +21,13 @@ impl BootLoader { pub fn prepare( config: BootLoaderConfig, ) -> Self { - Self::try_prepare::(config).expect("Boot prepare error") + if let Ok(loader) = Self::try_prepare::(config) { + loader + } else { + // Use explicit panic instead of .expect() to ensure this gets routed via defmt/etc. + // properly + panic!("Boot prepare error") + } } /// Inspect the bootloader state and perform actions required before booting, such as swapping firmware diff --git a/embassy-boot-stm32/src/lib.rs b/embassy-boot-stm32/src/lib.rs index 708441835..387cc0ce5 100644 --- a/embassy-boot-stm32/src/lib.rs +++ b/embassy-boot-stm32/src/lib.rs @@ -20,7 +20,13 @@ impl BootLoader { pub fn prepare( config: BootLoaderConfig, ) -> Self { - Self::try_prepare::(config).expect("Boot prepare error") + if let Ok(loader) = Self::try_prepare::(config) { + loader + } else { + // Use explicit panic instead of .expect() to ensure this gets routed via defmt/etc. + // properly + panic!("Boot prepare error") + } } /// Inspect the bootloader state and perform actions required before booting, such as swapping firmware diff --git a/embassy-boot/src/test_flash/asynch.rs b/embassy-boot/src/test_flash/asynch.rs index 3ac9e71ab..c67f2495c 100644 --- a/embassy-boot/src/test_flash/asynch.rs +++ b/embassy-boot/src/test_flash/asynch.rs @@ -43,7 +43,7 @@ where } fn create_partition(mutex: &Mutex) -> Partition { - Partition::new(mutex, 0, mutex.try_lock().unwrap().capacity() as u32) + Partition::new(mutex, 0, unwrap!(mutex.try_lock()).capacity() as u32) } } From 73d937dc332d14c9e6e9bcf3871b99033399f924 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Flemstr=C3=B6m?= Date: Fri, 28 Jun 2024 21:10:41 +0200 Subject: [PATCH 3/8] Remove implicit bounds checking from rcc module --- embassy-stm32/src/rcc/mod.rs | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 0bf344c40..c29d31fd9 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -138,11 +138,17 @@ impl RccInfo { pub(crate) fn enable_and_reset_with_cs(&self, _cs: CriticalSection) { if self.refcount_idx_or_0xff != 0xff { let refcount_idx = self.refcount_idx_or_0xff as usize; - unsafe { - crate::_generated::REFCOUNTS[refcount_idx] += 1; - } - if unsafe { crate::_generated::REFCOUNTS[refcount_idx] } > 1 { - return; + + // Use .get_mut instead of []-operator so that we control how bounds checks happen. + // Otherwise, core::fmt will be pulled in here in order to format the integer in the + // out-of-bounds error. + if let Some(refcount) = unsafe { crate::_generated::REFCOUNTS }.get_mut(refcount_idx) { + *refcount += 1; + if *refcount > 1 { + return; + } + } else { + panic!("refcount_idx out of bounds: {}", refcount_idx) } } @@ -196,11 +202,15 @@ impl RccInfo { pub(crate) fn disable_with_cs(&self, _cs: CriticalSection) { if self.refcount_idx_or_0xff != 0xff { let refcount_idx = self.refcount_idx_or_0xff as usize; - unsafe { - crate::_generated::REFCOUNTS[refcount_idx] -= 1; - } - if unsafe { crate::_generated::REFCOUNTS[refcount_idx] } > 0 { - return; + + // Use .get_mut instead of []-operator so that we control how bounds checks happen. + // Otherwise, core::fmt will be pulled in here in order to format the integer in the + // out-of-bounds error. + if let Some(refcount) = unsafe { crate::_generated::REFCOUNTS }.get_mut(refcount_idx) { + *refcount -= 1; + if *refcount > 0 { + return; + } } } From 2f750a82bf15327958bd0a31f05714f3528edcc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Flemstr=C3=B6m?= Date: Fri, 28 Jun 2024 21:50:51 +0200 Subject: [PATCH 4/8] Swat some other occurrences of .unwrap() that pull in panicing infra --- embassy-stm32/src/can/bxcan/registers.rs | 20 ++++++++------------ embassy-stm32/src/flash/asynch.rs | 2 +- embassy-stm32/src/flash/common.rs | 2 +- embassy-stm32/src/flash/f0.rs | 2 +- embassy-stm32/src/flash/f1f3.rs | 2 +- embassy-stm32/src/flash/f4.rs | 8 ++++---- embassy-stm32/src/flash/f7.rs | 2 +- embassy-stm32/src/flash/g.rs | 2 +- embassy-stm32/src/flash/h50.rs | 2 +- embassy-stm32/src/flash/h7.rs | 6 +++--- embassy-stm32/src/flash/l.rs | 2 +- embassy-stm32/src/flash/u0.rs | 2 +- embassy-stm32/src/flash/u5.rs | 2 +- 13 files changed, 25 insertions(+), 29 deletions(-) diff --git a/embassy-stm32/src/can/bxcan/registers.rs b/embassy-stm32/src/can/bxcan/registers.rs index 5f3d70e25..c5de1c683 100644 --- a/embassy-stm32/src/can/bxcan/registers.rs +++ b/embassy-stm32/src/can/bxcan/registers.rs @@ -299,9 +299,9 @@ impl Registers { mb.tdtr().write(|w| w.set_dlc(frame.header().len() as u8)); mb.tdlr() - .write(|w| w.0 = u32::from_ne_bytes(frame.data()[0..4].try_into().unwrap())); + .write(|w| w.0 = u32::from_ne_bytes(unwrap!(frame.data()[0..4].try_into()))); mb.tdhr() - .write(|w| w.0 = u32::from_ne_bytes(frame.data()[4..8].try_into().unwrap())); + .write(|w| w.0 = u32::from_ne_bytes(unwrap!(frame.data()[4..8].try_into()))); let id: IdReg = frame.id().into(); mb.tir().write(|w| { w.0 = id.0; @@ -321,7 +321,7 @@ impl Registers { data[4..8].copy_from_slice(&mb.tdhr().read().0.to_ne_bytes()); let len = mb.tdtr().read().dlc(); - Some(Frame::new(Header::new(id.id(), len, id.rtr()), &data).unwrap()) + Some(unwrap!(Frame::new(Header::new(id.id(), len, id.rtr()), &data))) } else { // Abort request failed because the frame was already sent (or being sent) on // the bus. All mailboxes are now free. This can happen for small prescaler @@ -404,12 +404,12 @@ impl Registers { let rir = fifo.rir().read(); let id: embedded_can::Id = if rir.ide() == Ide::STANDARD { - embedded_can::StandardId::new(rir.stid()).unwrap().into() + unwrap!(embedded_can::StandardId::new(rir.stid())).into() } else { let stid = (rir.stid() & 0x7FF) as u32; let exid = rir.exid() & 0x3FFFF; let id = (stid << 18) | (exid); - embedded_can::ExtendedId::new(id).unwrap().into() + unwrap!(embedded_can::ExtendedId::new(id)).into() }; let rdtr = fifo.rdtr().read(); let data_len = rdtr.dlc(); @@ -422,7 +422,7 @@ impl Registers { data[0..4].copy_from_slice(&fifo.rdlr().read().0.to_ne_bytes()); data[4..8].copy_from_slice(&fifo.rdhr().read().0.to_ne_bytes()); - let frame = Frame::new(Header::new(id, data_len, rtr), &data).unwrap(); + let frame = unwrap!(Frame::new(Header::new(id, data_len, rtr), &data)); let envelope = Envelope { ts, frame }; rfr.modify(|v| v.set_rfom(true)); @@ -484,13 +484,9 @@ impl IdReg { /// Returns the identifier. fn id(self) -> embedded_can::Id { if self.is_extended() { - embedded_can::ExtendedId::new(self.0 >> Self::EXTENDED_SHIFT) - .unwrap() - .into() + unwrap!(embedded_can::ExtendedId::new(self.0 >> Self::EXTENDED_SHIFT)).into() } else { - embedded_can::StandardId::new((self.0 >> Self::STANDARD_SHIFT) as u16) - .unwrap() - .into() + unwrap!(embedded_can::StandardId::new((self.0 >> Self::STANDARD_SHIFT) as u16)).into() } } diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index 97eaece81..9468ac632 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs @@ -117,7 +117,7 @@ pub(super) async unsafe fn write_chunked(base: u32, size: u32, offset: u32, byte family::lock(); }); - family::write(address, chunk.try_into().unwrap()).await?; + family::write(address, unwrap!(chunk.try_into())).await?; address += WRITE_SIZE as u32; } Ok(()) diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index f8561edb3..8ec4bb2a1 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -125,7 +125,7 @@ pub(super) unsafe fn write_chunk_unlocked(address: u32, chunk: &[u8]) -> Result< family::lock(); }); - family::blocking_write(address, chunk.try_into().unwrap()) + family::blocking_write(address, unwrap!(chunk.try_into())) } pub(super) unsafe fn write_chunk_with_critical_section(address: u32, chunk: &[u8]) -> Result<(), Error> { diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index e2f135208..402312f68 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs @@ -37,7 +37,7 @@ pub(crate) unsafe fn disable_blocking_write() { pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for chunk in buf.chunks(2) { - write_volatile(address as *mut u16, u16::from_le_bytes(chunk.try_into().unwrap())); + write_volatile(address as *mut u16, u16::from_le_bytes(unwrap!(chunk.try_into()))); address += chunk.len() as u32; // prevents parallelism errors diff --git a/embassy-stm32/src/flash/f1f3.rs b/embassy-stm32/src/flash/f1f3.rs index b16354a74..e66842e31 100644 --- a/embassy-stm32/src/flash/f1f3.rs +++ b/embassy-stm32/src/flash/f1f3.rs @@ -37,7 +37,7 @@ pub(crate) unsafe fn disable_blocking_write() { pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for chunk in buf.chunks(2) { - write_volatile(address as *mut u16, u16::from_le_bytes(chunk.try_into().unwrap())); + write_volatile(address as *mut u16, u16::from_le_bytes(unwrap!(chunk.try_into()))); address += chunk.len() as u32; // prevents parallelism errors diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 2634fba37..d0bb957ee 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -277,7 +277,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) unsafe fn write_start(start_address: u32, buf: &[u8; WRITE_SIZE]) { let mut address = start_address; for val in buf.chunks(4) { - write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); + write_volatile(address as *mut u32, u32::from_le_bytes(unwrap!(val.try_into()))); address += val.len() as u32; // prevents parallelism errors @@ -379,7 +379,7 @@ fn get_result(sr: Sr) -> Result<(), Error> { } fn save_data_cache_state() { - let dual_bank = get_flash_regions().last().unwrap().bank == FlashBank::Bank2; + let dual_bank = unwrap!(get_flash_regions().last()).bank == FlashBank::Bank2; if dual_bank { // Disable data cache during write/erase if there are two banks, see errata 2.2.12 let dcen = pac::FLASH.acr().read().dcen(); @@ -391,7 +391,7 @@ fn save_data_cache_state() { } fn restore_data_cache_state() { - let dual_bank = get_flash_regions().last().unwrap().bank == FlashBank::Bank2; + let dual_bank = unwrap!(get_flash_regions().last()).bank == FlashBank::Bank2; if dual_bank { // Restore data cache if it was enabled let dcen = DATA_CACHE_WAS_ENABLED.load(Ordering::Relaxed); @@ -410,7 +410,7 @@ pub(crate) fn assert_not_corrupted_read(end_address: u32) { #[allow(unused)] let second_bank_read = - get_flash_regions().last().unwrap().bank == FlashBank::Bank2 && end_address > (FLASH_SIZE / 2) as u32; + unwrap!(get_flash_regions().last()).bank == FlashBank::Bank2 && end_address > (FLASH_SIZE / 2) as u32; #[cfg(any( feature = "stm32f427ai", diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs index 72de0b445..09ebe9db9 100644 --- a/embassy-stm32/src/flash/f7.rs +++ b/embassy-stm32/src/flash/f7.rs @@ -40,7 +40,7 @@ pub(crate) unsafe fn disable_blocking_write() { pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for val in buf.chunks(4) { - write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); + write_volatile(address as *mut u32, u32::from_le_bytes(unwrap!(val.try_into()))); address += val.len() as u32; // prevents parallelism errors diff --git a/embassy-stm32/src/flash/g.rs b/embassy-stm32/src/flash/g.rs index 6a5adc941..01a0c603f 100644 --- a/embassy-stm32/src/flash/g.rs +++ b/embassy-stm32/src/flash/g.rs @@ -41,7 +41,7 @@ pub(crate) unsafe fn disable_blocking_write() { pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for val in buf.chunks(4) { - write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); + write_volatile(address as *mut u32, u32::from_le_bytes(unwrap!(val.try_into()))); address += val.len() as u32; // prevents parallelism errors diff --git a/embassy-stm32/src/flash/h50.rs b/embassy-stm32/src/flash/h50.rs index 56ea7a421..82e77d130 100644 --- a/embassy-stm32/src/flash/h50.rs +++ b/embassy-stm32/src/flash/h50.rs @@ -44,7 +44,7 @@ pub(crate) unsafe fn disable_blocking_write() { pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for val in buf.chunks(4) { - write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); + write_volatile(address as *mut u32, u32::from_le_bytes(unwrap!(val.try_into()))); address += val.len() as u32; // prevents parallelism errors diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs index e32a82eef..254915381 100644 --- a/embassy-stm32/src/flash/h7.rs +++ b/embassy-stm32/src/flash/h7.rs @@ -62,7 +62,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) let mut res = None; let mut address = start_address; for val in buf.chunks(4) { - write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); + write_volatile(address as *mut u32, u32::from_le_bytes(unwrap!(val.try_into()))); address += val.len() as u32; res = Some(blocking_wait_ready(bank)); @@ -71,7 +71,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) w.set_eop(true); } }); - if res.unwrap().is_err() { + if unwrap!(res).is_err() { break; } } @@ -82,7 +82,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) bank.cr().write(|w| w.set_pg(false)); - res.unwrap() + unwrap!(res) } pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index b14224bff..a0bfeb395 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs @@ -63,7 +63,7 @@ pub(crate) unsafe fn disable_blocking_write() { pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for val in buf.chunks(4) { - write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); + write_volatile(address as *mut u32, u32::from_le_bytes(unwrap!(val.try_into()))); address += val.len() as u32; // prevents parallelism errors diff --git a/embassy-stm32/src/flash/u0.rs b/embassy-stm32/src/flash/u0.rs index dfc5a2f76..bfdbd15a5 100644 --- a/embassy-stm32/src/flash/u0.rs +++ b/embassy-stm32/src/flash/u0.rs @@ -41,7 +41,7 @@ pub(crate) unsafe fn disable_blocking_write() { pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for val in buf.chunks(4) { - write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); + write_volatile(address as *mut u32, u32::from_le_bytes(unwrap!(val.try_into()))); address += val.len() as u32; // prevents parallelism errors diff --git a/embassy-stm32/src/flash/u5.rs b/embassy-stm32/src/flash/u5.rs index ddd4d73ff..0601017ce 100644 --- a/embassy-stm32/src/flash/u5.rs +++ b/embassy-stm32/src/flash/u5.rs @@ -56,7 +56,7 @@ pub(crate) unsafe fn disable_blocking_write() { pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for val in buf.chunks(4) { - write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); + write_volatile(address as *mut u32, u32::from_le_bytes(unwrap!(val.try_into()))); address += val.len() as u32; // prevents parallelism errors From 114dda2fd1afb37d2b563b9ac5018830ad7b6d4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Flemstr=C3=B6m?= Date: Sat, 29 Jun 2024 01:34:07 +0200 Subject: [PATCH 5/8] Avoid accidental copy of static var before creating mut ref --- embassy-stm32/src/rcc/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index c29d31fd9..360df93ae 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -142,7 +142,7 @@ impl RccInfo { // Use .get_mut instead of []-operator so that we control how bounds checks happen. // Otherwise, core::fmt will be pulled in here in order to format the integer in the // out-of-bounds error. - if let Some(refcount) = unsafe { crate::_generated::REFCOUNTS }.get_mut(refcount_idx) { + if let Some(refcount) = unsafe { crate::_generated::REFCOUNTS.get_mut(refcount_idx) } { *refcount += 1; if *refcount > 1 { return; @@ -206,7 +206,7 @@ impl RccInfo { // Use .get_mut instead of []-operator so that we control how bounds checks happen. // Otherwise, core::fmt will be pulled in here in order to format the integer in the // out-of-bounds error. - if let Some(refcount) = unsafe { crate::_generated::REFCOUNTS }.get_mut(refcount_idx) { + if let Some(refcount) = unsafe { crate::_generated::REFCOUNTS.get_mut(refcount_idx) } { *refcount -= 1; if *refcount > 0 { return; From 662e97f7b5dafc652bf82ec8b57df1d99126407a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Flemstr=C3=B6m?= Date: Sat, 29 Jun 2024 01:37:35 +0200 Subject: [PATCH 6/8] Panic on index-out-of-bounds when releasing RCC node --- embassy-stm32/src/rcc/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 360df93ae..024c63cf5 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -211,6 +211,8 @@ impl RccInfo { if *refcount > 0 { return; } + } else { + panic!("refcount_idx out of bounds: {}", refcount_idx) } } From c3be54f96b2a7e9039f4d12bbd97217dd65969d7 Mon Sep 17 00:00:00 2001 From: trepidacious Date: Sun, 30 Jun 2024 17:47:04 +0100 Subject: [PATCH 7/8] Add check for closed connection to `read_ready()` --- embassy-net/src/tcp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs index 906102bbf..4d6dc92de 100644 --- a/embassy-net/src/tcp.rs +++ b/embassy-net/src/tcp.rs @@ -587,7 +587,7 @@ mod embedded_io_impls { impl<'d> embedded_io_async::ReadReady for TcpSocket<'d> { fn read_ready(&mut self) -> Result { - Ok(self.io.with(|s, _| s.can_recv())) + Ok(self.io.with(|s, _| s.can_recv() || !s.may_recv())) } } From 0b8a8e54dc4a00af2016a1dd14640773af10b3e6 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 1 Jul 2024 10:22:39 +0200 Subject: [PATCH 8/8] expose enabling and disabling irq for triggers --- embassy-nrf/src/egu.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/embassy-nrf/src/egu.rs b/embassy-nrf/src/egu.rs index c0cde8330..204446d29 100644 --- a/embassy-nrf/src/egu.rs +++ b/embassy-nrf/src/egu.rs @@ -77,6 +77,24 @@ impl<'d, T: Instance> Trigger<'d, T> { let regs = T::regs(); Event::from_reg(®s.events_triggered[nr]) } + + /// Enable interrupts for this trigger + pub fn enable_interrupt(&mut self) { + let regs = T::regs(); + unsafe { + regs.intenset + .modify(|r, w| w.bits(r.bits() | (1 << self.number as usize))) + }; + } + + /// Enable interrupts for this trigger + pub fn disable_interrupt(&mut self) { + let regs = T::regs(); + unsafe { + regs.intenclr + .modify(|r, w| w.bits(r.bits() | (1 << self.number as usize))) + }; + } } /// Represents a trigger within an EGU.