Merge branch 'main' into nrf9151
This commit is contained in:
commit
98263ac220
@ -20,7 +20,13 @@ impl<const BUFFER_SIZE: usize> BootLoader<BUFFER_SIZE> {
|
|||||||
pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash>(
|
pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash>(
|
||||||
config: BootLoaderConfig<ACTIVE, DFU, STATE>,
|
config: BootLoaderConfig<ACTIVE, DFU, STATE>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::try_prepare::<ACTIVE, DFU, STATE>(config).expect("Boot prepare error")
|
if let Ok(loader) = Self::try_prepare::<ACTIVE, DFU, STATE>(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
|
/// Inspect the bootloader state and perform actions required before booting, such as swapping firmware
|
||||||
|
|||||||
@ -21,7 +21,13 @@ impl<const BUFFER_SIZE: usize> BootLoader<BUFFER_SIZE> {
|
|||||||
pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash>(
|
pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash>(
|
||||||
config: BootLoaderConfig<ACTIVE, DFU, STATE>,
|
config: BootLoaderConfig<ACTIVE, DFU, STATE>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::try_prepare::<ACTIVE, DFU, STATE>(config).expect("Boot prepare error")
|
if let Ok(loader) = Self::try_prepare::<ACTIVE, DFU, STATE>(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
|
/// Inspect the bootloader state and perform actions required before booting, such as swapping firmware
|
||||||
|
|||||||
@ -20,7 +20,13 @@ impl BootLoader {
|
|||||||
pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>(
|
pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>(
|
||||||
config: BootLoaderConfig<ACTIVE, DFU, STATE>,
|
config: BootLoaderConfig<ACTIVE, DFU, STATE>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::try_prepare::<ACTIVE, DFU, STATE, BUFFER_SIZE>(config).expect("Boot prepare error")
|
if let Ok(loader) = Self::try_prepare::<ACTIVE, DFU, STATE, BUFFER_SIZE>(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
|
/// Inspect the bootloader state and perform actions required before booting, such as swapping firmware
|
||||||
|
|||||||
@ -43,7 +43,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create_partition<T: NorFlash>(mutex: &Mutex<NoopRawMutex, T>) -> Partition<NoopRawMutex, T> {
|
fn create_partition<T: NorFlash>(mutex: &Mutex<NoopRawMutex, T>) -> Partition<NoopRawMutex, T> {
|
||||||
Partition::new(mutex, 0, mutex.try_lock().unwrap().capacity() as u32)
|
Partition::new(mutex, 0, unwrap!(mutex.try_lock()).capacity() as u32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -587,7 +587,7 @@ mod embedded_io_impls {
|
|||||||
|
|
||||||
impl<'d> embedded_io_async::ReadReady for TcpSocket<'d> {
|
impl<'d> embedded_io_async::ReadReady for TcpSocket<'d> {
|
||||||
fn read_ready(&mut self) -> Result<bool, Self::Error> {
|
fn read_ready(&mut self) -> Result<bool, Self::Error> {
|
||||||
Ok(self.io.with(|s, _| s.can_recv()))
|
Ok(self.io.with(|s, _| s.can_recv() || !s.may_recv()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -77,6 +77,24 @@ impl<'d, T: Instance> Trigger<'d, T> {
|
|||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
Event::from_reg(®s.events_triggered[nr])
|
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.
|
/// Represents a trigger within an EGU.
|
||||||
|
|||||||
@ -313,25 +313,29 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Read from address into buffer using DMA.
|
/// Read from address into buffer using DMA.
|
||||||
pub async fn read_async(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Error> {
|
pub async fn read_async(&mut self, addr: impl Into<u16>, buffer: &mut [u8]) -> Result<(), Error> {
|
||||||
Self::setup(addr)?;
|
Self::setup(addr.into())?;
|
||||||
self.read_async_internal(buffer, true, true).await
|
self.read_async_internal(buffer, true, true).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write to address from buffer using DMA.
|
/// Write to address from buffer using DMA.
|
||||||
pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator<Item = u8>) -> Result<(), Error> {
|
pub async fn write_async(
|
||||||
Self::setup(addr)?;
|
&mut self,
|
||||||
|
addr: impl Into<u16>,
|
||||||
|
bytes: impl IntoIterator<Item = u8>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
Self::setup(addr.into())?;
|
||||||
self.write_async_internal(bytes, true).await
|
self.write_async_internal(bytes, true).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write to address from bytes and read from address into buffer using DMA.
|
/// Write to address from bytes and read from address into buffer using DMA.
|
||||||
pub async fn write_read_async(
|
pub async fn write_read_async(
|
||||||
&mut self,
|
&mut self,
|
||||||
addr: u16,
|
addr: impl Into<u16>,
|
||||||
bytes: impl IntoIterator<Item = u8>,
|
bytes: impl IntoIterator<Item = u8>,
|
||||||
buffer: &mut [u8],
|
buffer: &mut [u8],
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
Self::setup(addr)?;
|
Self::setup(addr.into())?;
|
||||||
self.write_async_internal(bytes, false).await?;
|
self.write_async_internal(bytes, false).await?;
|
||||||
self.read_async_internal(buffer, true, true).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.
|
/// 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<u16>, read: &mut [u8]) -> Result<(), Error> {
|
||||||
Self::setup(address.into())?;
|
Self::setup(address.into())?;
|
||||||
self.read_blocking_internal(read, true, true)
|
self.read_blocking_internal(read, true, true)
|
||||||
// Automatic Stop
|
// Automatic Stop
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write to address from buffer blocking caller until done.
|
/// 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<u16>, write: &[u8]) -> Result<(), Error> {
|
||||||
Self::setup(address.into())?;
|
Self::setup(address.into())?;
|
||||||
self.write_blocking_internal(write, true)
|
self.write_blocking_internal(write, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write to address from bytes and read from address into buffer blocking caller until done.
|
/// 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<u16>, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
|
||||||
Self::setup(address.into())?;
|
Self::setup(address.into())?;
|
||||||
self.write_blocking_internal(write, false)?;
|
self.write_blocking_internal(write, false)?;
|
||||||
self.read_blocking_internal(read, true, true)
|
self.read_blocking_internal(read, true, true)
|
||||||
@ -719,25 +723,15 @@ where
|
|||||||
T: Instance + 'd,
|
T: Instance + 'd,
|
||||||
{
|
{
|
||||||
async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> {
|
async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> {
|
||||||
let addr: u16 = address.into();
|
self.read_async(address, read).await
|
||||||
|
|
||||||
Self::setup(addr)?;
|
|
||||||
self.read_async_internal(read, false, true).await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> {
|
async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> {
|
||||||
let addr: u16 = address.into();
|
self.write_async(address, write.iter().copied()).await
|
||||||
|
|
||||||
Self::setup(addr)?;
|
|
||||||
self.write_async_internal(write.iter().copied(), true).await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
|
async fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
|
||||||
let addr: u16 = address.into();
|
self.write_read_async(address, write.iter().copied(), read).await
|
||||||
|
|
||||||
Self::setup(addr)?;
|
|
||||||
self.write_async_internal(write.iter().cloned(), false).await?;
|
|
||||||
self.read_async_internal(read, true, true).await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn transaction(
|
async fn transaction(
|
||||||
|
|||||||
@ -299,9 +299,9 @@ impl Registers {
|
|||||||
mb.tdtr().write(|w| w.set_dlc(frame.header().len() as u8));
|
mb.tdtr().write(|w| w.set_dlc(frame.header().len() as u8));
|
||||||
|
|
||||||
mb.tdlr()
|
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()
|
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();
|
let id: IdReg = frame.id().into();
|
||||||
mb.tir().write(|w| {
|
mb.tir().write(|w| {
|
||||||
w.0 = id.0;
|
w.0 = id.0;
|
||||||
@ -321,7 +321,7 @@ impl Registers {
|
|||||||
data[4..8].copy_from_slice(&mb.tdhr().read().0.to_ne_bytes());
|
data[4..8].copy_from_slice(&mb.tdhr().read().0.to_ne_bytes());
|
||||||
let len = mb.tdtr().read().dlc();
|
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 {
|
} else {
|
||||||
// Abort request failed because the frame was already sent (or being sent) on
|
// 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
|
// 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 rir = fifo.rir().read();
|
||||||
let id: embedded_can::Id = if rir.ide() == Ide::STANDARD {
|
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 {
|
} else {
|
||||||
let stid = (rir.stid() & 0x7FF) as u32;
|
let stid = (rir.stid() & 0x7FF) as u32;
|
||||||
let exid = rir.exid() & 0x3FFFF;
|
let exid = rir.exid() & 0x3FFFF;
|
||||||
let id = (stid << 18) | (exid);
|
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 rdtr = fifo.rdtr().read();
|
||||||
let data_len = rdtr.dlc();
|
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[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());
|
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 };
|
let envelope = Envelope { ts, frame };
|
||||||
|
|
||||||
rfr.modify(|v| v.set_rfom(true));
|
rfr.modify(|v| v.set_rfom(true));
|
||||||
@ -484,13 +484,9 @@ impl IdReg {
|
|||||||
/// Returns the identifier.
|
/// Returns the identifier.
|
||||||
fn id(self) -> embedded_can::Id {
|
fn id(self) -> embedded_can::Id {
|
||||||
if self.is_extended() {
|
if self.is_extended() {
|
||||||
embedded_can::ExtendedId::new(self.0 >> Self::EXTENDED_SHIFT)
|
unwrap!(embedded_can::ExtendedId::new(self.0 >> Self::EXTENDED_SHIFT)).into()
|
||||||
.unwrap()
|
|
||||||
.into()
|
|
||||||
} else {
|
} else {
|
||||||
embedded_can::StandardId::new((self.0 >> Self::STANDARD_SHIFT) as u16)
|
unwrap!(embedded_can::StandardId::new((self.0 >> Self::STANDARD_SHIFT) as u16)).into()
|
||||||
.unwrap()
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -117,7 +117,7 @@ pub(super) async unsafe fn write_chunked(base: u32, size: u32, offset: u32, byte
|
|||||||
family::lock();
|
family::lock();
|
||||||
});
|
});
|
||||||
|
|
||||||
family::write(address, chunk.try_into().unwrap()).await?;
|
family::write(address, unwrap!(chunk.try_into())).await?;
|
||||||
address += WRITE_SIZE as u32;
|
address += WRITE_SIZE as u32;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -125,7 +125,7 @@ pub(super) unsafe fn write_chunk_unlocked(address: u32, chunk: &[u8]) -> Result<
|
|||||||
family::lock();
|
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> {
|
pub(super) unsafe fn write_chunk_with_critical_section(address: u32, chunk: &[u8]) -> Result<(), Error> {
|
||||||
|
|||||||
@ -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> {
|
pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> {
|
||||||
let mut address = start_address;
|
let mut address = start_address;
|
||||||
for chunk in buf.chunks(2) {
|
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;
|
address += chunk.len() as u32;
|
||||||
|
|
||||||
// prevents parallelism errors
|
// prevents parallelism errors
|
||||||
|
|||||||
@ -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> {
|
pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> {
|
||||||
let mut address = start_address;
|
let mut address = start_address;
|
||||||
for chunk in buf.chunks(2) {
|
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;
|
address += chunk.len() as u32;
|
||||||
|
|
||||||
// prevents parallelism errors
|
// prevents parallelism errors
|
||||||
|
|||||||
@ -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]) {
|
unsafe fn write_start(start_address: u32, buf: &[u8; WRITE_SIZE]) {
|
||||||
let mut address = start_address;
|
let mut address = start_address;
|
||||||
for val in buf.chunks(4) {
|
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;
|
address += val.len() as u32;
|
||||||
|
|
||||||
// prevents parallelism errors
|
// prevents parallelism errors
|
||||||
@ -379,7 +379,7 @@ fn get_result(sr: Sr) -> Result<(), Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn save_data_cache_state() {
|
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 {
|
if dual_bank {
|
||||||
// Disable data cache during write/erase if there are two banks, see errata 2.2.12
|
// Disable data cache during write/erase if there are two banks, see errata 2.2.12
|
||||||
let dcen = pac::FLASH.acr().read().dcen();
|
let dcen = pac::FLASH.acr().read().dcen();
|
||||||
@ -391,7 +391,7 @@ fn save_data_cache_state() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn restore_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 {
|
if dual_bank {
|
||||||
// Restore data cache if it was enabled
|
// Restore data cache if it was enabled
|
||||||
let dcen = DATA_CACHE_WAS_ENABLED.load(Ordering::Relaxed);
|
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)]
|
#[allow(unused)]
|
||||||
let second_bank_read =
|
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(
|
#[cfg(any(
|
||||||
feature = "stm32f427ai",
|
feature = "stm32f427ai",
|
||||||
|
|||||||
@ -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> {
|
pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> {
|
||||||
let mut address = start_address;
|
let mut address = start_address;
|
||||||
for val in buf.chunks(4) {
|
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;
|
address += val.len() as u32;
|
||||||
|
|
||||||
// prevents parallelism errors
|
// prevents parallelism errors
|
||||||
|
|||||||
@ -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> {
|
pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> {
|
||||||
let mut address = start_address;
|
let mut address = start_address;
|
||||||
for val in buf.chunks(4) {
|
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;
|
address += val.len() as u32;
|
||||||
|
|
||||||
// prevents parallelism errors
|
// prevents parallelism errors
|
||||||
|
|||||||
@ -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> {
|
pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> {
|
||||||
let mut address = start_address;
|
let mut address = start_address;
|
||||||
for val in buf.chunks(4) {
|
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;
|
address += val.len() as u32;
|
||||||
|
|
||||||
// prevents parallelism errors
|
// prevents parallelism errors
|
||||||
|
|||||||
@ -62,7 +62,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE])
|
|||||||
let mut res = None;
|
let mut res = None;
|
||||||
let mut address = start_address;
|
let mut address = start_address;
|
||||||
for val in buf.chunks(4) {
|
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;
|
address += val.len() as u32;
|
||||||
|
|
||||||
res = Some(blocking_wait_ready(bank));
|
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);
|
w.set_eop(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if res.unwrap().is_err() {
|
if unwrap!(res).is_err() {
|
||||||
break;
|
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));
|
bank.cr().write(|w| w.set_pg(false));
|
||||||
|
|
||||||
res.unwrap()
|
unwrap!(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> {
|
pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> {
|
||||||
|
|||||||
@ -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> {
|
pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> {
|
||||||
let mut address = start_address;
|
let mut address = start_address;
|
||||||
for val in buf.chunks(4) {
|
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;
|
address += val.len() as u32;
|
||||||
|
|
||||||
// prevents parallelism errors
|
// prevents parallelism errors
|
||||||
|
|||||||
@ -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> {
|
pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> {
|
||||||
let mut address = start_address;
|
let mut address = start_address;
|
||||||
for val in buf.chunks(4) {
|
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;
|
address += val.len() as u32;
|
||||||
|
|
||||||
// prevents parallelism errors
|
// prevents parallelism errors
|
||||||
|
|||||||
@ -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> {
|
pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> {
|
||||||
let mut address = start_address;
|
let mut address = start_address;
|
||||||
for val in buf.chunks(4) {
|
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;
|
address += val.len() as u32;
|
||||||
|
|
||||||
// prevents parallelism errors
|
// prevents parallelism errors
|
||||||
|
|||||||
@ -138,12 +138,18 @@ impl RccInfo {
|
|||||||
pub(crate) fn enable_and_reset_with_cs(&self, _cs: CriticalSection) {
|
pub(crate) fn enable_and_reset_with_cs(&self, _cs: CriticalSection) {
|
||||||
if self.refcount_idx_or_0xff != 0xff {
|
if self.refcount_idx_or_0xff != 0xff {
|
||||||
let refcount_idx = self.refcount_idx_or_0xff as usize;
|
let refcount_idx = self.refcount_idx_or_0xff as usize;
|
||||||
unsafe {
|
|
||||||
crate::_generated::REFCOUNTS[refcount_idx] += 1;
|
// 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
|
||||||
if unsafe { crate::_generated::REFCOUNTS[refcount_idx] } > 1 {
|
// out-of-bounds error.
|
||||||
|
if let Some(refcount) = unsafe { crate::_generated::REFCOUNTS.get_mut(refcount_idx) } {
|
||||||
|
*refcount += 1;
|
||||||
|
if *refcount > 1 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
panic!("refcount_idx out of bounds: {}", refcount_idx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "low-power")]
|
#[cfg(feature = "low-power")]
|
||||||
@ -196,12 +202,18 @@ impl RccInfo {
|
|||||||
pub(crate) fn disable_with_cs(&self, _cs: CriticalSection) {
|
pub(crate) fn disable_with_cs(&self, _cs: CriticalSection) {
|
||||||
if self.refcount_idx_or_0xff != 0xff {
|
if self.refcount_idx_or_0xff != 0xff {
|
||||||
let refcount_idx = self.refcount_idx_or_0xff as usize;
|
let refcount_idx = self.refcount_idx_or_0xff as usize;
|
||||||
unsafe {
|
|
||||||
crate::_generated::REFCOUNTS[refcount_idx] -= 1;
|
// 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
|
||||||
if unsafe { crate::_generated::REFCOUNTS[refcount_idx] } > 0 {
|
// out-of-bounds error.
|
||||||
|
if let Some(refcount) = unsafe { crate::_generated::REFCOUNTS.get_mut(refcount_idx) } {
|
||||||
|
*refcount -= 1;
|
||||||
|
if *refcount > 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
panic!("refcount_idx out of bounds: {}", refcount_idx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "low-power")]
|
#[cfg(feature = "low-power")]
|
||||||
|
|||||||
85
examples/rp/src/bin/i2c_async_embassy.rs
Normal file
85
examples/rp/src/bin/i2c_async_embassy.rs
Normal file
@ -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<u16> for UncomplicatedSensorU16 {
|
||||||
|
fn into(self) -> u16 {
|
||||||
|
self as u16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Into<u16> for UncomplicatedSensorU8 {
|
||||||
|
fn into(self) -> u16 {
|
||||||
|
0x48
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<UncomplicatedSensorId> 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_rp::peripherals::I2C1>;
|
||||||
|
});
|
||||||
|
|
||||||
|
#[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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user