aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-06-13 20:41:08 +0200
committerDario Nieuwenhuis <[email protected]>2024-06-13 20:41:08 +0200
commit7ad76f5f603078e7be300ae6fb08c6f6bf23f6c5 (patch)
treeb47109f801a901c01f079a573d06a1c89dd9d0e9
parent4d9115b3fb17f441a3280dd7913e682157ca1dac (diff)
Use raw slices .len() method instead of unsafe hacks.
Stabilized in 1.79.
-rw-r--r--embassy-nrf/src/i2s.rs7
-rw-r--r--embassy-nrf/src/spim.rs12
-rw-r--r--embassy-nrf/src/spis.rs16
-rw-r--r--embassy-nrf/src/util.rs35
-rw-r--r--embassy-rp/src/dma.rs29
-rw-r--r--embassy-rp/src/spi.rs15
-rw-r--r--embassy-stm32/src/dma/dma_bdma.rs16
-rw-r--r--embassy-stm32/src/dma/gpdma.rs16
-rw-r--r--embassy-stm32/src/dma/mod.rs13
-rw-r--r--embassy-stm32/src/spi/mod.rs8
10 files changed, 51 insertions, 116 deletions
diff --git a/embassy-nrf/src/i2s.rs b/embassy-nrf/src/i2s.rs
index 966271ed9..5f565a9b7 100644
--- a/embassy-nrf/src/i2s.rs
+++ b/embassy-nrf/src/i2s.rs
@@ -16,7 +16,7 @@ use embassy_sync::waitqueue::AtomicWaker;
16use crate::gpio::{AnyPin, Pin as GpioPin}; 16use crate::gpio::{AnyPin, Pin as GpioPin};
17use crate::interrupt::typelevel::Interrupt; 17use crate::interrupt::typelevel::Interrupt;
18use crate::pac::i2s::RegisterBlock; 18use crate::pac::i2s::RegisterBlock;
19use crate::util::{slice_in_ram_or, slice_ptr_parts}; 19use crate::util::slice_in_ram_or;
20use crate::{interrupt, Peripheral, EASY_DMA_SIZE}; 20use crate::{interrupt, Peripheral, EASY_DMA_SIZE};
21 21
22/// Type alias for `MultiBuffering` with 2 buffers. 22/// Type alias for `MultiBuffering` with 2 buffers.
@@ -1028,9 +1028,8 @@ impl<T: Instance> Device<T> {
1028 } 1028 }
1029 1029
1030 fn validated_dma_parts<S>(buffer_ptr: *const [S]) -> Result<(u32, u32), Error> { 1030 fn validated_dma_parts<S>(buffer_ptr: *const [S]) -> Result<(u32, u32), Error> {
1031 let (ptr, len) = slice_ptr_parts(buffer_ptr); 1031 let ptr = buffer_ptr as *const S as u32;
1032 let ptr = ptr as u32; 1032 let bytes_len = buffer_ptr.len() * size_of::<S>();
1033 let bytes_len = len * size_of::<S>();
1034 let maxcnt = (bytes_len / size_of::<u32>()) as u32; 1033 let maxcnt = (bytes_len / size_of::<u32>()) as u32;
1035 1034
1036 trace!("PTR={}, MAXCNT={}", ptr, maxcnt); 1035 trace!("PTR={}, MAXCNT={}", ptr, maxcnt);
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index 373f22642..52660711a 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -19,7 +19,7 @@ pub use pac::spim0::frequency::FREQUENCY_A as Frequency;
19use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 19use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
20use crate::gpio::{self, convert_drive, AnyPin, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _}; 20use crate::gpio::{self, convert_drive, AnyPin, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _};
21use crate::interrupt::typelevel::Interrupt; 21use crate::interrupt::typelevel::Interrupt;
22use crate::util::{slice_in_ram_or, slice_ptr_len, slice_ptr_parts, slice_ptr_parts_mut}; 22use crate::util::slice_in_ram_or;
23use crate::{interrupt, pac, Peripheral}; 23use crate::{interrupt, pac, Peripheral};
24 24
25/// SPIM error 25/// SPIM error
@@ -240,14 +240,12 @@ impl<'d, T: Instance> Spim<'d, T> {
240 } 240 }
241 241
242 // Set up the DMA read. 242 // Set up the DMA read.
243 let (ptr, len) = slice_ptr_parts_mut(rx); 243 let (rx_ptr, rx_len) = xfer_params(rx as *mut u8 as _, rx.len() as _, offset, length);
244 let (rx_ptr, rx_len) = xfer_params(ptr as _, len as _, offset, length);
245 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(rx_ptr) }); 244 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(rx_ptr) });
246 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(rx_len as _) }); 245 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(rx_len as _) });
247 246
248 // Set up the DMA write. 247 // Set up the DMA write.
249 let (ptr, len) = slice_ptr_parts(tx); 248 let (tx_ptr, tx_len) = xfer_params(tx as *const u8 as _, tx.len() as _, offset, length);
250 let (tx_ptr, tx_len) = xfer_params(ptr as _, len as _, offset, length);
251 r.txd.ptr.write(|w| unsafe { w.ptr().bits(tx_ptr) }); 249 r.txd.ptr.write(|w| unsafe { w.ptr().bits(tx_ptr) });
252 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(tx_len as _) }); 250 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(tx_len as _) });
253 251
@@ -302,7 +300,7 @@ impl<'d, T: Instance> Spim<'d, T> {
302 // NOTE: RAM slice check for rx is not necessary, as a mutable 300 // NOTE: RAM slice check for rx is not necessary, as a mutable
303 // slice can only be built from data located in RAM. 301 // slice can only be built from data located in RAM.
304 302
305 let xfer_len = core::cmp::max(slice_ptr_len(rx), slice_ptr_len(tx)); 303 let xfer_len = core::cmp::max(rx.len(), tx.len());
306 for offset in (0..xfer_len).step_by(EASY_DMA_SIZE) { 304 for offset in (0..xfer_len).step_by(EASY_DMA_SIZE) {
307 let length = core::cmp::min(xfer_len - offset, EASY_DMA_SIZE); 305 let length = core::cmp::min(xfer_len - offset, EASY_DMA_SIZE);
308 self.blocking_inner_from_ram_chunk(rx, tx, offset, length); 306 self.blocking_inner_from_ram_chunk(rx, tx, offset, length);
@@ -356,7 +354,7 @@ impl<'d, T: Instance> Spim<'d, T> {
356 // NOTE: RAM slice check for rx is not necessary, as a mutable 354 // NOTE: RAM slice check for rx is not necessary, as a mutable
357 // slice can only be built from data located in RAM. 355 // slice can only be built from data located in RAM.
358 356
359 let xfer_len = core::cmp::max(slice_ptr_len(rx), slice_ptr_len(tx)); 357 let xfer_len = core::cmp::max(rx.len(), tx.len());
360 for offset in (0..xfer_len).step_by(EASY_DMA_SIZE) { 358 for offset in (0..xfer_len).step_by(EASY_DMA_SIZE) {
361 let length = core::cmp::min(xfer_len - offset, EASY_DMA_SIZE); 359 let length = core::cmp::min(xfer_len - offset, EASY_DMA_SIZE);
362 self.async_inner_from_ram_chunk(rx, tx, offset, length).await; 360 self.async_inner_from_ram_chunk(rx, tx, offset, length).await;
diff --git a/embassy-nrf/src/spis.rs b/embassy-nrf/src/spis.rs
index 47bbeaf77..e98b34369 100644
--- a/embassy-nrf/src/spis.rs
+++ b/embassy-nrf/src/spis.rs
@@ -15,7 +15,7 @@ pub use pac::spis0::config::ORDER_A as BitOrder;
15use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 15use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
16use crate::gpio::{self, AnyPin, Pin as GpioPin, SealedPin as _}; 16use crate::gpio::{self, AnyPin, Pin as GpioPin, SealedPin as _};
17use crate::interrupt::typelevel::Interrupt; 17use crate::interrupt::typelevel::Interrupt;
18use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut}; 18use crate::util::slice_in_ram_or;
19use crate::{interrupt, pac, Peripheral}; 19use crate::{interrupt, pac, Peripheral};
20 20
21/// SPIS error 21/// SPIS error
@@ -226,20 +226,18 @@ impl<'d, T: Instance> Spis<'d, T> {
226 let r = T::regs(); 226 let r = T::regs();
227 227
228 // Set up the DMA write. 228 // Set up the DMA write.
229 let (ptr, len) = slice_ptr_parts(tx); 229 if tx.len() > EASY_DMA_SIZE {
230 if len > EASY_DMA_SIZE {
231 return Err(Error::TxBufferTooLong); 230 return Err(Error::TxBufferTooLong);
232 } 231 }
233 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) }); 232 r.txd.ptr.write(|w| unsafe { w.ptr().bits(tx as *const u8 as _) });
234 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); 233 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(tx.len() as _) });
235 234
236 // Set up the DMA read. 235 // Set up the DMA read.
237 let (ptr, len) = slice_ptr_parts_mut(rx); 236 if rx.len() > EASY_DMA_SIZE {
238 if len > EASY_DMA_SIZE {
239 return Err(Error::RxBufferTooLong); 237 return Err(Error::RxBufferTooLong);
240 } 238 }
241 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) }); 239 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(rx as *mut u8 as _) });
242 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); 240 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(rx.len() as _) });
243 241
244 // Reset end event. 242 // Reset end event.
245 r.events_end.reset(); 243 r.events_end.reset();
diff --git a/embassy-nrf/src/util.rs b/embassy-nrf/src/util.rs
index 13aba7dec..78f71719f 100644
--- a/embassy-nrf/src/util.rs
+++ b/embassy-nrf/src/util.rs
@@ -1,42 +1,21 @@
1#![allow(dead_code)] 1#![allow(dead_code)]
2use core::mem;
3 2
4const SRAM_LOWER: usize = 0x2000_0000; 3const SRAM_LOWER: usize = 0x2000_0000;
5const SRAM_UPPER: usize = 0x3000_0000; 4const SRAM_UPPER: usize = 0x3000_0000;
6 5
7// #![feature(const_slice_ptr_len)]
8// https://github.com/rust-lang/rust/issues/71146
9pub(crate) fn slice_ptr_len<T>(ptr: *const [T]) -> usize {
10 use core::ptr::NonNull;
11 let ptr = ptr.cast_mut();
12 if let Some(ptr) = NonNull::new(ptr) {
13 ptr.len()
14 } else {
15 // We know ptr is null, so we know ptr.wrapping_byte_add(1) is not null.
16 NonNull::new(ptr.wrapping_byte_add(1)).unwrap().len()
17 }
18}
19
20// TODO: replace transmutes with core::ptr::metadata once it's stable
21pub(crate) fn slice_ptr_parts<T>(slice: *const [T]) -> (*const T, usize) {
22 unsafe { mem::transmute(slice) }
23}
24
25pub(crate) fn slice_ptr_parts_mut<T>(slice: *mut [T]) -> (*mut T, usize) {
26 unsafe { mem::transmute(slice) }
27}
28
29/// Does this slice reside entirely within RAM? 6/// Does this slice reside entirely within RAM?
30pub(crate) fn slice_in_ram<T>(slice: *const [T]) -> bool { 7pub(crate) fn slice_in_ram<T>(slice: *const [T]) -> bool {
31 let (ptr, len) = slice_ptr_parts(slice); 8 if slice.is_empty() {
32 let ptr = ptr as usize; 9 return true;
33 ptr >= SRAM_LOWER && (ptr + len * core::mem::size_of::<T>()) < SRAM_UPPER 10 }
11
12 let ptr = slice as *const T as usize;
13 ptr >= SRAM_LOWER && (ptr + slice.len() * core::mem::size_of::<T>()) < SRAM_UPPER
34} 14}
35 15
36/// Return an error if slice is not in RAM. Skips check if slice is zero-length. 16/// Return an error if slice is not in RAM. Skips check if slice is zero-length.
37pub(crate) fn slice_in_ram_or<T, E>(slice: *const [T], err: E) -> Result<(), E> { 17pub(crate) fn slice_in_ram_or<T, E>(slice: *const [T], err: E) -> Result<(), E> {
38 let (_, len) = slice_ptr_parts(slice); 18 if slice_in_ram(slice) {
39 if len == 0 || slice_in_ram(slice) {
40 Ok(()) 19 Ok(())
41 } else { 20 } else {
42 Err(err) 21 Err(err)
diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs
index e6374a86c..8c04b43a1 100644
--- a/embassy-rp/src/dma.rs
+++ b/embassy-rp/src/dma.rs
@@ -47,12 +47,11 @@ pub unsafe fn read<'a, C: Channel, W: Word>(
47 to: *mut [W], 47 to: *mut [W],
48 dreq: u8, 48 dreq: u8,
49) -> Transfer<'a, C> { 49) -> Transfer<'a, C> {
50 let (to_ptr, len) = crate::dma::slice_ptr_parts(to);
51 copy_inner( 50 copy_inner(
52 ch, 51 ch,
53 from as *const u32, 52 from as *const u32,
54 to_ptr as *mut u32, 53 to as *mut W as *mut u32,
55 len, 54 to.len(),
56 W::size(), 55 W::size(),
57 false, 56 false,
58 true, 57 true,
@@ -69,12 +68,11 @@ pub unsafe fn write<'a, C: Channel, W: Word>(
69 to: *mut W, 68 to: *mut W,
70 dreq: u8, 69 dreq: u8,
71) -> Transfer<'a, C> { 70) -> Transfer<'a, C> {
72 let (from_ptr, len) = crate::dma::slice_ptr_parts(from);
73 copy_inner( 71 copy_inner(
74 ch, 72 ch,
75 from_ptr as *const u32, 73 from as *const W as *const u32,
76 to as *mut u32, 74 to as *mut u32,
77 len, 75 from.len(),
78 W::size(), 76 W::size(),
79 true, 77 true,
80 false, 78 false,
@@ -114,13 +112,13 @@ pub unsafe fn copy<'a, C: Channel, W: Word>(
114 from: &[W], 112 from: &[W],
115 to: &mut [W], 113 to: &mut [W],
116) -> Transfer<'a, C> { 114) -> Transfer<'a, C> {
117 let (from_ptr, from_len) = crate::dma::slice_ptr_parts(from); 115 let from_len = from.len();
118 let (to_ptr, to_len) = crate::dma::slice_ptr_parts_mut(to); 116 let to_len = to.len();
119 assert_eq!(from_len, to_len); 117 assert_eq!(from_len, to_len);
120 copy_inner( 118 copy_inner(
121 ch, 119 ch,
122 from_ptr as *const u32, 120 from.as_ptr() as *const u32,
123 to_ptr as *mut u32, 121 to.as_mut_ptr() as *mut u32,
124 from_len, 122 from_len,
125 W::size(), 123 W::size(),
126 true, 124 true,
@@ -287,17 +285,6 @@ macro_rules! channel {
287 }; 285 };
288} 286}
289 287
290// TODO: replace transmutes with core::ptr::metadata once it's stable
291#[allow(unused)]
292pub(crate) fn slice_ptr_parts<T>(slice: *const [T]) -> (usize, usize) {
293 unsafe { core::mem::transmute(slice) }
294}
295
296#[allow(unused)]
297pub(crate) fn slice_ptr_parts_mut<T>(slice: *mut [T]) -> (usize, usize) {
298 unsafe { core::mem::transmute(slice) }
299}
300
301channel!(DMA_CH0, 0); 288channel!(DMA_CH0, 0);
302channel!(DMA_CH1, 1); 289channel!(DMA_CH1, 1);
303channel!(DMA_CH2, 2); 290channel!(DMA_CH2, 2);
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs
index ef4c644ae..1617c144c 100644
--- a/embassy-rp/src/spi.rs
+++ b/embassy-rp/src/spi.rs
@@ -394,17 +394,14 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
394 self.transfer_inner(words, words).await 394 self.transfer_inner(words, words).await
395 } 395 }
396 396
397 async fn transfer_inner(&mut self, rx_ptr: *mut [u8], tx_ptr: *const [u8]) -> Result<(), Error> { 397 async fn transfer_inner(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
398 let (_, tx_len) = crate::dma::slice_ptr_parts(tx_ptr);
399 let (_, rx_len) = crate::dma::slice_ptr_parts_mut(rx_ptr);
400
401 // Start RX first. Transfer starts when TX starts, if RX 398 // Start RX first. Transfer starts when TX starts, if RX
402 // is not started yet we might lose bytes. 399 // is not started yet we might lose bytes.
403 let rx_ch = self.rx_dma.as_mut().unwrap(); 400 let rx_ch = self.rx_dma.as_mut().unwrap();
404 let rx_transfer = unsafe { 401 let rx_transfer = unsafe {
405 // If we don't assign future to a variable, the data register pointer 402 // If we don't assign future to a variable, the data register pointer
406 // is held across an await and makes the future non-Send. 403 // is held across an await and makes the future non-Send.
407 crate::dma::read(rx_ch, self.inner.regs().dr().as_ptr() as *const _, rx_ptr, T::RX_DREQ) 404 crate::dma::read(rx_ch, self.inner.regs().dr().as_ptr() as *const _, rx, T::RX_DREQ)
408 }; 405 };
409 406
410 let mut tx_ch = self.tx_dma.as_mut().unwrap(); 407 let mut tx_ch = self.tx_dma.as_mut().unwrap();
@@ -413,10 +410,10 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
413 let tx_transfer = async { 410 let tx_transfer = async {
414 let p = self.inner.regs(); 411 let p = self.inner.regs();
415 unsafe { 412 unsafe {
416 crate::dma::write(&mut tx_ch, tx_ptr, p.dr().as_ptr() as *mut _, T::TX_DREQ).await; 413 crate::dma::write(&mut tx_ch, tx, p.dr().as_ptr() as *mut _, T::TX_DREQ).await;
417 414
418 if rx_len > tx_len { 415 if rx.len() > tx.len() {
419 let write_bytes_len = rx_len - tx_len; 416 let write_bytes_len = rx.len() - tx.len();
420 // write dummy data 417 // write dummy data
421 // this will disable incrementation of the buffers 418 // this will disable incrementation of the buffers
422 crate::dma::write_repeated(tx_ch, p.dr().as_ptr() as *mut u8, write_bytes_len, T::TX_DREQ).await 419 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> {
426 join(tx_transfer, rx_transfer).await; 423 join(tx_transfer, rx_transfer).await;
427 424
428 // if tx > rx we should clear any overflow of the FIFO SPI buffer 425 // if tx > rx we should clear any overflow of the FIFO SPI buffer
429 if tx_len > rx_len { 426 if tx.len() > rx.len() {
430 let p = self.inner.regs(); 427 let p = self.inner.regs();
431 while p.sr().read().bsy() {} 428 while p.sr().read().bsy() {}
432 429
diff --git a/embassy-stm32/src/dma/dma_bdma.rs b/embassy-stm32/src/dma/dma_bdma.rs
index a6344cf06..a462e317f 100644
--- a/embassy-stm32/src/dma/dma_bdma.rs
+++ b/embassy-stm32/src/dma/dma_bdma.rs
@@ -565,16 +565,13 @@ impl<'a> Transfer<'a> {
565 ) -> Self { 565 ) -> Self {
566 into_ref!(channel); 566 into_ref!(channel);
567 567
568 let (ptr, len) = super::slice_ptr_parts_mut(buf);
569 assert!(len > 0 && len <= 0xFFFF);
570
571 Self::new_inner( 568 Self::new_inner(
572 channel.map_into(), 569 channel.map_into(),
573 request, 570 request,
574 Dir::PeripheralToMemory, 571 Dir::PeripheralToMemory,
575 peri_addr as *const u32, 572 peri_addr as *const u32,
576 ptr as *mut u32, 573 buf as *mut W as *mut u32,
577 len, 574 buf.len(),
578 true, 575 true,
579 W::size(), 576 W::size(),
580 options, 577 options,
@@ -602,16 +599,13 @@ impl<'a> Transfer<'a> {
602 ) -> Self { 599 ) -> Self {
603 into_ref!(channel); 600 into_ref!(channel);
604 601
605 let (ptr, len) = super::slice_ptr_parts(buf);
606 assert!(len > 0 && len <= 0xFFFF);
607
608 Self::new_inner( 602 Self::new_inner(
609 channel.map_into(), 603 channel.map_into(),
610 request, 604 request,
611 Dir::MemoryToPeripheral, 605 Dir::MemoryToPeripheral,
612 peri_addr as *const u32, 606 peri_addr as *const u32,
613 ptr as *mut u32, 607 buf as *const W as *mut u32,
614 len, 608 buf.len(),
615 true, 609 true,
616 W::size(), 610 W::size(),
617 options, 611 options,
@@ -653,6 +647,8 @@ impl<'a> Transfer<'a> {
653 data_size: WordSize, 647 data_size: WordSize,
654 options: TransferOptions, 648 options: TransferOptions,
655 ) -> Self { 649 ) -> Self {
650 assert!(mem_len > 0 && mem_len <= 0xFFFF);
651
656 channel.configure( 652 channel.configure(
657 _request, dir, peri_addr, mem_addr, mem_len, incr_mem, data_size, options, 653 _request, dir, peri_addr, mem_addr, mem_len, incr_mem, data_size, options,
658 ); 654 );
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs
index a3717e67b..13d5d15be 100644
--- a/embassy-stm32/src/dma/gpdma.rs
+++ b/embassy-stm32/src/dma/gpdma.rs
@@ -125,16 +125,13 @@ impl<'a> Transfer<'a> {
125 ) -> Self { 125 ) -> Self {
126 into_ref!(channel); 126 into_ref!(channel);
127 127
128 let (ptr, len) = super::slice_ptr_parts_mut(buf);
129 assert!(len > 0 && len <= 0xFFFF);
130
131 Self::new_inner( 128 Self::new_inner(
132 channel.map_into(), 129 channel.map_into(),
133 request, 130 request,
134 Dir::PeripheralToMemory, 131 Dir::PeripheralToMemory,
135 peri_addr as *const u32, 132 peri_addr as *const u32,
136 ptr as *mut u32, 133 buf as *mut W as *mut u32,
137 len, 134 buf.len(),
138 true, 135 true,
139 W::size(), 136 W::size(),
140 options, 137 options,
@@ -162,16 +159,13 @@ impl<'a> Transfer<'a> {
162 ) -> Self { 159 ) -> Self {
163 into_ref!(channel); 160 into_ref!(channel);
164 161
165 let (ptr, len) = super::slice_ptr_parts(buf);
166 assert!(len > 0 && len <= 0xFFFF);
167
168 Self::new_inner( 162 Self::new_inner(
169 channel.map_into(), 163 channel.map_into(),
170 request, 164 request,
171 Dir::MemoryToPeripheral, 165 Dir::MemoryToPeripheral,
172 peri_addr as *const u32, 166 peri_addr as *const u32,
173 ptr as *mut u32, 167 buf as *const W as *mut u32,
174 len, 168 buf.len(),
175 true, 169 true,
176 W::size(), 170 W::size(),
177 options, 171 options,
@@ -213,6 +207,8 @@ impl<'a> Transfer<'a> {
213 data_size: WordSize, 207 data_size: WordSize,
214 _options: TransferOptions, 208 _options: TransferOptions,
215 ) -> Self { 209 ) -> Self {
210 assert!(mem_len > 0 && mem_len <= 0xFFFF);
211
216 let info = channel.info(); 212 let info = channel.info();
217 let ch = info.dma.ch(info.num); 213 let ch = info.dma.ch(info.num);
218 214
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index 3f5687a62..66c4aa53c 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -22,8 +22,6 @@ pub(crate) use util::*;
22pub(crate) mod ringbuffer; 22pub(crate) mod ringbuffer;
23pub mod word; 23pub mod word;
24 24
25use core::mem;
26
27use embassy_hal_internal::{impl_peripheral, Peripheral}; 25use embassy_hal_internal::{impl_peripheral, Peripheral};
28 26
29use crate::interrupt; 27use crate::interrupt;
@@ -121,17 +119,6 @@ pub struct NoDma;
121 119
122impl_peripheral!(NoDma); 120impl_peripheral!(NoDma);
123 121
124// TODO: replace transmutes with core::ptr::metadata once it's stable
125#[allow(unused)]
126pub(crate) fn slice_ptr_parts<T>(slice: *const [T]) -> (usize, usize) {
127 unsafe { mem::transmute(slice) }
128}
129
130#[allow(unused)]
131pub(crate) fn slice_ptr_parts_mut<T>(slice: *mut [T]) -> (usize, usize) {
132 unsafe { mem::transmute(slice) }
133}
134
135// safety: must be called only once at startup 122// safety: must be called only once at startup
136pub(crate) unsafe fn init( 123pub(crate) unsafe fn init(
137 cs: critical_section::CriticalSection, 124 cs: critical_section::CriticalSection,
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index 03c908db8..2e5f82dcb 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -9,7 +9,7 @@ use embassy_futures::join::join;
9use embassy_hal_internal::PeripheralRef; 9use embassy_hal_internal::PeripheralRef;
10pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 10pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
11 11
12use crate::dma::{slice_ptr_parts, word, ChannelAndRequest}; 12use crate::dma::{word, ChannelAndRequest};
13use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed}; 13use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
14use crate::mode::{Async, Blocking, Mode as PeriMode}; 14use crate::mode::{Async, Blocking, Mode as PeriMode};
15use crate::pac::spi::{regs, vals, Spi as Regs}; 15use crate::pac::spi::{regs, vals, Spi as Regs};
@@ -798,10 +798,8 @@ impl<'d> Spi<'d, Async> {
798 } 798 }
799 799
800 async fn transfer_inner<W: Word>(&mut self, read: *mut [W], write: *const [W]) -> Result<(), Error> { 800 async fn transfer_inner<W: Word>(&mut self, read: *mut [W], write: *const [W]) -> Result<(), Error> {
801 let (_, rx_len) = slice_ptr_parts(read); 801 assert_eq!(read.len(), write.len());
802 let (_, tx_len) = slice_ptr_parts(write); 802 if read.len() == 0 {
803 assert_eq!(rx_len, tx_len);
804 if rx_len == 0 {
805 return Ok(()); 803 return Ok(());
806 } 804 }
807 805