mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-21 22:32:29 +00:00
Use raw slices .len() method instead of unsafe hacks.
Stabilized in 1.79.
This commit is contained in:
parent
4d9115b3fb
commit
7ad76f5f60
@ -16,7 +16,7 @@ use embassy_sync::waitqueue::AtomicWaker;
|
|||||||
use crate::gpio::{AnyPin, Pin as GpioPin};
|
use crate::gpio::{AnyPin, Pin as GpioPin};
|
||||||
use crate::interrupt::typelevel::Interrupt;
|
use crate::interrupt::typelevel::Interrupt;
|
||||||
use crate::pac::i2s::RegisterBlock;
|
use crate::pac::i2s::RegisterBlock;
|
||||||
use crate::util::{slice_in_ram_or, slice_ptr_parts};
|
use crate::util::slice_in_ram_or;
|
||||||
use crate::{interrupt, Peripheral, EASY_DMA_SIZE};
|
use crate::{interrupt, Peripheral, EASY_DMA_SIZE};
|
||||||
|
|
||||||
/// Type alias for `MultiBuffering` with 2 buffers.
|
/// Type alias for `MultiBuffering` with 2 buffers.
|
||||||
@ -1028,9 +1028,8 @@ impl<T: Instance> Device<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn validated_dma_parts<S>(buffer_ptr: *const [S]) -> Result<(u32, u32), Error> {
|
fn validated_dma_parts<S>(buffer_ptr: *const [S]) -> Result<(u32, u32), Error> {
|
||||||
let (ptr, len) = slice_ptr_parts(buffer_ptr);
|
let ptr = buffer_ptr as *const S as u32;
|
||||||
let ptr = ptr as u32;
|
let bytes_len = buffer_ptr.len() * size_of::<S>();
|
||||||
let bytes_len = len * size_of::<S>();
|
|
||||||
let maxcnt = (bytes_len / size_of::<u32>()) as u32;
|
let maxcnt = (bytes_len / size_of::<u32>()) as u32;
|
||||||
|
|
||||||
trace!("PTR={}, MAXCNT={}", ptr, maxcnt);
|
trace!("PTR={}, MAXCNT={}", ptr, maxcnt);
|
||||||
|
@ -19,7 +19,7 @@ pub use pac::spim0::frequency::FREQUENCY_A as Frequency;
|
|||||||
use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
|
use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
|
||||||
use crate::gpio::{self, convert_drive, AnyPin, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _};
|
use crate::gpio::{self, convert_drive, AnyPin, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _};
|
||||||
use crate::interrupt::typelevel::Interrupt;
|
use crate::interrupt::typelevel::Interrupt;
|
||||||
use crate::util::{slice_in_ram_or, slice_ptr_len, slice_ptr_parts, slice_ptr_parts_mut};
|
use crate::util::slice_in_ram_or;
|
||||||
use crate::{interrupt, pac, Peripheral};
|
use crate::{interrupt, pac, Peripheral};
|
||||||
|
|
||||||
/// SPIM error
|
/// SPIM error
|
||||||
@ -240,14 +240,12 @@ impl<'d, T: Instance> Spim<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set up the DMA read.
|
// Set up the DMA read.
|
||||||
let (ptr, len) = slice_ptr_parts_mut(rx);
|
let (rx_ptr, rx_len) = xfer_params(rx as *mut u8 as _, rx.len() as _, offset, length);
|
||||||
let (rx_ptr, rx_len) = xfer_params(ptr as _, len as _, offset, length);
|
|
||||||
r.rxd.ptr.write(|w| unsafe { w.ptr().bits(rx_ptr) });
|
r.rxd.ptr.write(|w| unsafe { w.ptr().bits(rx_ptr) });
|
||||||
r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(rx_len as _) });
|
r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(rx_len as _) });
|
||||||
|
|
||||||
// Set up the DMA write.
|
// Set up the DMA write.
|
||||||
let (ptr, len) = slice_ptr_parts(tx);
|
let (tx_ptr, tx_len) = xfer_params(tx as *const u8 as _, tx.len() as _, offset, length);
|
||||||
let (tx_ptr, tx_len) = xfer_params(ptr as _, len as _, offset, length);
|
|
||||||
r.txd.ptr.write(|w| unsafe { w.ptr().bits(tx_ptr) });
|
r.txd.ptr.write(|w| unsafe { w.ptr().bits(tx_ptr) });
|
||||||
r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(tx_len as _) });
|
r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(tx_len as _) });
|
||||||
|
|
||||||
@ -302,7 +300,7 @@ impl<'d, T: Instance> Spim<'d, T> {
|
|||||||
// NOTE: RAM slice check for rx is not necessary, as a mutable
|
// NOTE: RAM slice check for rx is not necessary, as a mutable
|
||||||
// slice can only be built from data located in RAM.
|
// slice can only be built from data located in RAM.
|
||||||
|
|
||||||
let xfer_len = core::cmp::max(slice_ptr_len(rx), slice_ptr_len(tx));
|
let xfer_len = core::cmp::max(rx.len(), tx.len());
|
||||||
for offset in (0..xfer_len).step_by(EASY_DMA_SIZE) {
|
for offset in (0..xfer_len).step_by(EASY_DMA_SIZE) {
|
||||||
let length = core::cmp::min(xfer_len - offset, EASY_DMA_SIZE);
|
let length = core::cmp::min(xfer_len - offset, EASY_DMA_SIZE);
|
||||||
self.blocking_inner_from_ram_chunk(rx, tx, offset, length);
|
self.blocking_inner_from_ram_chunk(rx, tx, offset, length);
|
||||||
@ -356,7 +354,7 @@ impl<'d, T: Instance> Spim<'d, T> {
|
|||||||
// NOTE: RAM slice check for rx is not necessary, as a mutable
|
// NOTE: RAM slice check for rx is not necessary, as a mutable
|
||||||
// slice can only be built from data located in RAM.
|
// slice can only be built from data located in RAM.
|
||||||
|
|
||||||
let xfer_len = core::cmp::max(slice_ptr_len(rx), slice_ptr_len(tx));
|
let xfer_len = core::cmp::max(rx.len(), tx.len());
|
||||||
for offset in (0..xfer_len).step_by(EASY_DMA_SIZE) {
|
for offset in (0..xfer_len).step_by(EASY_DMA_SIZE) {
|
||||||
let length = core::cmp::min(xfer_len - offset, EASY_DMA_SIZE);
|
let length = core::cmp::min(xfer_len - offset, EASY_DMA_SIZE);
|
||||||
self.async_inner_from_ram_chunk(rx, tx, offset, length).await;
|
self.async_inner_from_ram_chunk(rx, tx, offset, length).await;
|
||||||
|
@ -15,7 +15,7 @@ pub use pac::spis0::config::ORDER_A as BitOrder;
|
|||||||
use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
|
use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
|
||||||
use crate::gpio::{self, AnyPin, Pin as GpioPin, SealedPin as _};
|
use crate::gpio::{self, AnyPin, Pin as GpioPin, SealedPin as _};
|
||||||
use crate::interrupt::typelevel::Interrupt;
|
use crate::interrupt::typelevel::Interrupt;
|
||||||
use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut};
|
use crate::util::slice_in_ram_or;
|
||||||
use crate::{interrupt, pac, Peripheral};
|
use crate::{interrupt, pac, Peripheral};
|
||||||
|
|
||||||
/// SPIS error
|
/// SPIS error
|
||||||
@ -226,20 +226,18 @@ impl<'d, T: Instance> Spis<'d, T> {
|
|||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
// Set up the DMA write.
|
// Set up the DMA write.
|
||||||
let (ptr, len) = slice_ptr_parts(tx);
|
if tx.len() > EASY_DMA_SIZE {
|
||||||
if len > EASY_DMA_SIZE {
|
|
||||||
return Err(Error::TxBufferTooLong);
|
return Err(Error::TxBufferTooLong);
|
||||||
}
|
}
|
||||||
r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
|
r.txd.ptr.write(|w| unsafe { w.ptr().bits(tx as *const u8 as _) });
|
||||||
r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
|
r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(tx.len() as _) });
|
||||||
|
|
||||||
// Set up the DMA read.
|
// Set up the DMA read.
|
||||||
let (ptr, len) = slice_ptr_parts_mut(rx);
|
if rx.len() > EASY_DMA_SIZE {
|
||||||
if len > EASY_DMA_SIZE {
|
|
||||||
return Err(Error::RxBufferTooLong);
|
return Err(Error::RxBufferTooLong);
|
||||||
}
|
}
|
||||||
r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
|
r.rxd.ptr.write(|w| unsafe { w.ptr().bits(rx as *mut u8 as _) });
|
||||||
r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
|
r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(rx.len() as _) });
|
||||||
|
|
||||||
// Reset end event.
|
// Reset end event.
|
||||||
r.events_end.reset();
|
r.events_end.reset();
|
||||||
|
@ -1,42 +1,21 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use core::mem;
|
|
||||||
|
|
||||||
const SRAM_LOWER: usize = 0x2000_0000;
|
const SRAM_LOWER: usize = 0x2000_0000;
|
||||||
const SRAM_UPPER: usize = 0x3000_0000;
|
const SRAM_UPPER: usize = 0x3000_0000;
|
||||||
|
|
||||||
// #![feature(const_slice_ptr_len)]
|
|
||||||
// https://github.com/rust-lang/rust/issues/71146
|
|
||||||
pub(crate) fn slice_ptr_len<T>(ptr: *const [T]) -> usize {
|
|
||||||
use core::ptr::NonNull;
|
|
||||||
let ptr = ptr.cast_mut();
|
|
||||||
if let Some(ptr) = NonNull::new(ptr) {
|
|
||||||
ptr.len()
|
|
||||||
} else {
|
|
||||||
// We know ptr is null, so we know ptr.wrapping_byte_add(1) is not null.
|
|
||||||
NonNull::new(ptr.wrapping_byte_add(1)).unwrap().len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: replace transmutes with core::ptr::metadata once it's stable
|
|
||||||
pub(crate) fn slice_ptr_parts<T>(slice: *const [T]) -> (*const T, usize) {
|
|
||||||
unsafe { mem::transmute(slice) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn slice_ptr_parts_mut<T>(slice: *mut [T]) -> (*mut T, usize) {
|
|
||||||
unsafe { mem::transmute(slice) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Does this slice reside entirely within RAM?
|
/// Does this slice reside entirely within RAM?
|
||||||
pub(crate) fn slice_in_ram<T>(slice: *const [T]) -> bool {
|
pub(crate) fn slice_in_ram<T>(slice: *const [T]) -> bool {
|
||||||
let (ptr, len) = slice_ptr_parts(slice);
|
if slice.is_empty() {
|
||||||
let ptr = ptr as usize;
|
return true;
|
||||||
ptr >= SRAM_LOWER && (ptr + len * core::mem::size_of::<T>()) < SRAM_UPPER
|
}
|
||||||
|
|
||||||
|
let ptr = slice as *const T as usize;
|
||||||
|
ptr >= SRAM_LOWER && (ptr + slice.len() * core::mem::size_of::<T>()) < SRAM_UPPER
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return an error if slice is not in RAM. Skips check if slice is zero-length.
|
/// Return an error if slice is not in RAM. Skips check if slice is zero-length.
|
||||||
pub(crate) fn slice_in_ram_or<T, E>(slice: *const [T], err: E) -> Result<(), E> {
|
pub(crate) fn slice_in_ram_or<T, E>(slice: *const [T], err: E) -> Result<(), E> {
|
||||||
let (_, len) = slice_ptr_parts(slice);
|
if slice_in_ram(slice) {
|
||||||
if len == 0 || slice_in_ram(slice) {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(err)
|
Err(err)
|
||||||
|
@ -47,12 +47,11 @@ pub unsafe fn read<'a, C: Channel, W: Word>(
|
|||||||
to: *mut [W],
|
to: *mut [W],
|
||||||
dreq: u8,
|
dreq: u8,
|
||||||
) -> Transfer<'a, C> {
|
) -> Transfer<'a, C> {
|
||||||
let (to_ptr, len) = crate::dma::slice_ptr_parts(to);
|
|
||||||
copy_inner(
|
copy_inner(
|
||||||
ch,
|
ch,
|
||||||
from as *const u32,
|
from as *const u32,
|
||||||
to_ptr as *mut u32,
|
to as *mut W as *mut u32,
|
||||||
len,
|
to.len(),
|
||||||
W::size(),
|
W::size(),
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
@ -69,12 +68,11 @@ pub unsafe fn write<'a, C: Channel, W: Word>(
|
|||||||
to: *mut W,
|
to: *mut W,
|
||||||
dreq: u8,
|
dreq: u8,
|
||||||
) -> Transfer<'a, C> {
|
) -> Transfer<'a, C> {
|
||||||
let (from_ptr, len) = crate::dma::slice_ptr_parts(from);
|
|
||||||
copy_inner(
|
copy_inner(
|
||||||
ch,
|
ch,
|
||||||
from_ptr as *const u32,
|
from as *const W as *const u32,
|
||||||
to as *mut u32,
|
to as *mut u32,
|
||||||
len,
|
from.len(),
|
||||||
W::size(),
|
W::size(),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
@ -114,13 +112,13 @@ pub unsafe fn copy<'a, C: Channel, W: Word>(
|
|||||||
from: &[W],
|
from: &[W],
|
||||||
to: &mut [W],
|
to: &mut [W],
|
||||||
) -> Transfer<'a, C> {
|
) -> Transfer<'a, C> {
|
||||||
let (from_ptr, from_len) = crate::dma::slice_ptr_parts(from);
|
let from_len = from.len();
|
||||||
let (to_ptr, to_len) = crate::dma::slice_ptr_parts_mut(to);
|
let to_len = to.len();
|
||||||
assert_eq!(from_len, to_len);
|
assert_eq!(from_len, to_len);
|
||||||
copy_inner(
|
copy_inner(
|
||||||
ch,
|
ch,
|
||||||
from_ptr as *const u32,
|
from.as_ptr() as *const u32,
|
||||||
to_ptr as *mut u32,
|
to.as_mut_ptr() as *mut u32,
|
||||||
from_len,
|
from_len,
|
||||||
W::size(),
|
W::size(),
|
||||||
true,
|
true,
|
||||||
@ -287,17 +285,6 @@ macro_rules! channel {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: replace transmutes with core::ptr::metadata once it's stable
|
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn slice_ptr_parts<T>(slice: *const [T]) -> (usize, usize) {
|
|
||||||
unsafe { core::mem::transmute(slice) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn slice_ptr_parts_mut<T>(slice: *mut [T]) -> (usize, usize) {
|
|
||||||
unsafe { core::mem::transmute(slice) }
|
|
||||||
}
|
|
||||||
|
|
||||||
channel!(DMA_CH0, 0);
|
channel!(DMA_CH0, 0);
|
||||||
channel!(DMA_CH1, 1);
|
channel!(DMA_CH1, 1);
|
||||||
channel!(DMA_CH2, 2);
|
channel!(DMA_CH2, 2);
|
||||||
|
@ -394,17 +394,14 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
|||||||
self.transfer_inner(words, words).await
|
self.transfer_inner(words, words).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn transfer_inner(&mut self, rx_ptr: *mut [u8], tx_ptr: *const [u8]) -> Result<(), Error> {
|
async fn transfer_inner(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
|
||||||
let (_, tx_len) = crate::dma::slice_ptr_parts(tx_ptr);
|
|
||||||
let (_, rx_len) = crate::dma::slice_ptr_parts_mut(rx_ptr);
|
|
||||||
|
|
||||||
// Start RX first. Transfer starts when TX starts, if RX
|
// Start RX first. Transfer starts when TX starts, if RX
|
||||||
// is not started yet we might lose bytes.
|
// is not started yet we might lose bytes.
|
||||||
let rx_ch = self.rx_dma.as_mut().unwrap();
|
let rx_ch = self.rx_dma.as_mut().unwrap();
|
||||||
let rx_transfer = unsafe {
|
let rx_transfer = unsafe {
|
||||||
// If we don't assign future to a variable, the data register pointer
|
// If we don't assign future to a variable, the data register pointer
|
||||||
// is held across an await and makes the future non-Send.
|
// is held across an await and makes the future non-Send.
|
||||||
crate::dma::read(rx_ch, self.inner.regs().dr().as_ptr() as *const _, rx_ptr, T::RX_DREQ)
|
crate::dma::read(rx_ch, self.inner.regs().dr().as_ptr() as *const _, rx, T::RX_DREQ)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut tx_ch = self.tx_dma.as_mut().unwrap();
|
let mut tx_ch = self.tx_dma.as_mut().unwrap();
|
||||||
@ -413,10 +410,10 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
|||||||
let tx_transfer = async {
|
let tx_transfer = async {
|
||||||
let p = self.inner.regs();
|
let p = self.inner.regs();
|
||||||
unsafe {
|
unsafe {
|
||||||
crate::dma::write(&mut tx_ch, tx_ptr, p.dr().as_ptr() as *mut _, T::TX_DREQ).await;
|
crate::dma::write(&mut tx_ch, tx, p.dr().as_ptr() as *mut _, T::TX_DREQ).await;
|
||||||
|
|
||||||
if rx_len > tx_len {
|
if rx.len() > tx.len() {
|
||||||
let write_bytes_len = rx_len - tx_len;
|
let write_bytes_len = rx.len() - tx.len();
|
||||||
// write dummy data
|
// write dummy data
|
||||||
// this will disable incrementation of the buffers
|
// this will disable incrementation of the buffers
|
||||||
crate::dma::write_repeated(tx_ch, p.dr().as_ptr() as *mut u8, write_bytes_len, T::TX_DREQ).await
|
crate::dma::write_repeated(tx_ch, p.dr().as_ptr() as *mut u8, write_bytes_len, T::TX_DREQ).await
|
||||||
@ -426,7 +423,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
|||||||
join(tx_transfer, rx_transfer).await;
|
join(tx_transfer, rx_transfer).await;
|
||||||
|
|
||||||
// if tx > rx we should clear any overflow of the FIFO SPI buffer
|
// if tx > rx we should clear any overflow of the FIFO SPI buffer
|
||||||
if tx_len > rx_len {
|
if tx.len() > rx.len() {
|
||||||
let p = self.inner.regs();
|
let p = self.inner.regs();
|
||||||
while p.sr().read().bsy() {}
|
while p.sr().read().bsy() {}
|
||||||
|
|
||||||
|
@ -565,16 +565,13 @@ impl<'a> Transfer<'a> {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(channel);
|
into_ref!(channel);
|
||||||
|
|
||||||
let (ptr, len) = super::slice_ptr_parts_mut(buf);
|
|
||||||
assert!(len > 0 && len <= 0xFFFF);
|
|
||||||
|
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
channel.map_into(),
|
channel.map_into(),
|
||||||
request,
|
request,
|
||||||
Dir::PeripheralToMemory,
|
Dir::PeripheralToMemory,
|
||||||
peri_addr as *const u32,
|
peri_addr as *const u32,
|
||||||
ptr as *mut u32,
|
buf as *mut W as *mut u32,
|
||||||
len,
|
buf.len(),
|
||||||
true,
|
true,
|
||||||
W::size(),
|
W::size(),
|
||||||
options,
|
options,
|
||||||
@ -602,16 +599,13 @@ impl<'a> Transfer<'a> {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(channel);
|
into_ref!(channel);
|
||||||
|
|
||||||
let (ptr, len) = super::slice_ptr_parts(buf);
|
|
||||||
assert!(len > 0 && len <= 0xFFFF);
|
|
||||||
|
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
channel.map_into(),
|
channel.map_into(),
|
||||||
request,
|
request,
|
||||||
Dir::MemoryToPeripheral,
|
Dir::MemoryToPeripheral,
|
||||||
peri_addr as *const u32,
|
peri_addr as *const u32,
|
||||||
ptr as *mut u32,
|
buf as *const W as *mut u32,
|
||||||
len,
|
buf.len(),
|
||||||
true,
|
true,
|
||||||
W::size(),
|
W::size(),
|
||||||
options,
|
options,
|
||||||
@ -653,6 +647,8 @@ impl<'a> Transfer<'a> {
|
|||||||
data_size: WordSize,
|
data_size: WordSize,
|
||||||
options: TransferOptions,
|
options: TransferOptions,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
assert!(mem_len > 0 && mem_len <= 0xFFFF);
|
||||||
|
|
||||||
channel.configure(
|
channel.configure(
|
||||||
_request, dir, peri_addr, mem_addr, mem_len, incr_mem, data_size, options,
|
_request, dir, peri_addr, mem_addr, mem_len, incr_mem, data_size, options,
|
||||||
);
|
);
|
||||||
|
@ -125,16 +125,13 @@ impl<'a> Transfer<'a> {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(channel);
|
into_ref!(channel);
|
||||||
|
|
||||||
let (ptr, len) = super::slice_ptr_parts_mut(buf);
|
|
||||||
assert!(len > 0 && len <= 0xFFFF);
|
|
||||||
|
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
channel.map_into(),
|
channel.map_into(),
|
||||||
request,
|
request,
|
||||||
Dir::PeripheralToMemory,
|
Dir::PeripheralToMemory,
|
||||||
peri_addr as *const u32,
|
peri_addr as *const u32,
|
||||||
ptr as *mut u32,
|
buf as *mut W as *mut u32,
|
||||||
len,
|
buf.len(),
|
||||||
true,
|
true,
|
||||||
W::size(),
|
W::size(),
|
||||||
options,
|
options,
|
||||||
@ -162,16 +159,13 @@ impl<'a> Transfer<'a> {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(channel);
|
into_ref!(channel);
|
||||||
|
|
||||||
let (ptr, len) = super::slice_ptr_parts(buf);
|
|
||||||
assert!(len > 0 && len <= 0xFFFF);
|
|
||||||
|
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
channel.map_into(),
|
channel.map_into(),
|
||||||
request,
|
request,
|
||||||
Dir::MemoryToPeripheral,
|
Dir::MemoryToPeripheral,
|
||||||
peri_addr as *const u32,
|
peri_addr as *const u32,
|
||||||
ptr as *mut u32,
|
buf as *const W as *mut u32,
|
||||||
len,
|
buf.len(),
|
||||||
true,
|
true,
|
||||||
W::size(),
|
W::size(),
|
||||||
options,
|
options,
|
||||||
@ -213,6 +207,8 @@ impl<'a> Transfer<'a> {
|
|||||||
data_size: WordSize,
|
data_size: WordSize,
|
||||||
_options: TransferOptions,
|
_options: TransferOptions,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
assert!(mem_len > 0 && mem_len <= 0xFFFF);
|
||||||
|
|
||||||
let info = channel.info();
|
let info = channel.info();
|
||||||
let ch = info.dma.ch(info.num);
|
let ch = info.dma.ch(info.num);
|
||||||
|
|
||||||
|
@ -22,8 +22,6 @@ pub(crate) use util::*;
|
|||||||
pub(crate) mod ringbuffer;
|
pub(crate) mod ringbuffer;
|
||||||
pub mod word;
|
pub mod word;
|
||||||
|
|
||||||
use core::mem;
|
|
||||||
|
|
||||||
use embassy_hal_internal::{impl_peripheral, Peripheral};
|
use embassy_hal_internal::{impl_peripheral, Peripheral};
|
||||||
|
|
||||||
use crate::interrupt;
|
use crate::interrupt;
|
||||||
@ -121,17 +119,6 @@ pub struct NoDma;
|
|||||||
|
|
||||||
impl_peripheral!(NoDma);
|
impl_peripheral!(NoDma);
|
||||||
|
|
||||||
// TODO: replace transmutes with core::ptr::metadata once it's stable
|
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn slice_ptr_parts<T>(slice: *const [T]) -> (usize, usize) {
|
|
||||||
unsafe { mem::transmute(slice) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) fn slice_ptr_parts_mut<T>(slice: *mut [T]) -> (usize, usize) {
|
|
||||||
unsafe { mem::transmute(slice) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// safety: must be called only once at startup
|
// safety: must be called only once at startup
|
||||||
pub(crate) unsafe fn init(
|
pub(crate) unsafe fn init(
|
||||||
cs: critical_section::CriticalSection,
|
cs: critical_section::CriticalSection,
|
||||||
|
@ -9,7 +9,7 @@ use embassy_futures::join::join;
|
|||||||
use embassy_hal_internal::PeripheralRef;
|
use embassy_hal_internal::PeripheralRef;
|
||||||
pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
|
pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
|
||||||
|
|
||||||
use crate::dma::{slice_ptr_parts, word, ChannelAndRequest};
|
use crate::dma::{word, ChannelAndRequest};
|
||||||
use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
|
use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
|
||||||
use crate::mode::{Async, Blocking, Mode as PeriMode};
|
use crate::mode::{Async, Blocking, Mode as PeriMode};
|
||||||
use crate::pac::spi::{regs, vals, Spi as Regs};
|
use crate::pac::spi::{regs, vals, Spi as Regs};
|
||||||
@ -798,10 +798,8 @@ impl<'d> Spi<'d, Async> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn transfer_inner<W: Word>(&mut self, read: *mut [W], write: *const [W]) -> Result<(), Error> {
|
async fn transfer_inner<W: Word>(&mut self, read: *mut [W], write: *const [W]) -> Result<(), Error> {
|
||||||
let (_, rx_len) = slice_ptr_parts(read);
|
assert_eq!(read.len(), write.len());
|
||||||
let (_, tx_len) = slice_ptr_parts(write);
|
if read.len() == 0 {
|
||||||
assert_eq!(rx_len, tx_len);
|
|
||||||
if rx_len == 0 {
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user