From 3d27a0e7cbf226d2a9df3e2efa058589ebfca858 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 19 Jan 2022 15:59:25 +0100 Subject: [PATCH] stm32/dma: make lowlevel api take ptrs instead of slices. --- embassy-stm32/src/dma/bdma.rs | 14 +++++----- embassy-stm32/src/dma/dma.rs | 14 +++++----- embassy-stm32/src/dma/mod.rs | 49 +++++++++++++++++++++++------------ 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index b4c77757..e06ce8c3 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs @@ -89,7 +89,8 @@ pac::dma_channels! { ($channel_peri:ident, $dma_peri:ident, bdma, $channel_num:expr, $dmamux:tt) => { impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { - unsafe fn start_write(&mut self, request: Request, buf: &[W], reg_addr: *mut W) { + unsafe fn start_write(&mut self, request: Request, buf: *const[W], reg_addr: *mut W) { + let (ptr, len) = super::slice_ptr_parts(buf); low_level_api::start_transfer( pac::$dma_peri, $channel_num, @@ -97,8 +98,8 @@ pac::dma_channels! { request, vals::Dir::FROMMEMORY, reg_addr as *const u32, - buf.as_ptr() as *mut u32, - buf.len(), + ptr as *mut u32, + len, true, vals::Size::from(W::bits()), #[cfg(dmamux)] @@ -129,7 +130,8 @@ pac::dma_channels! { ) } - unsafe fn start_read(&mut self, request: Request, reg_addr: *mut W, buf: &mut [W]) { + unsafe fn start_read(&mut self, request: Request, reg_addr: *const W, buf: *mut [W]) { + let (ptr, len) = super::slice_ptr_parts_mut(buf); low_level_api::start_transfer( pac::$dma_peri, $channel_num, @@ -137,8 +139,8 @@ pac::dma_channels! { request, vals::Dir::FROMPERIPHERAL, reg_addr as *const u32, - buf.as_ptr() as *mut u32, - buf.len(), + ptr as *mut u32, + len, true, vals::Size::from(W::bits()), #[cfg(dmamux)] diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index efe4d1d9..8e48bb26 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs @@ -84,15 +84,16 @@ pub(crate) unsafe fn init() { pac::dma_channels! { ($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $dmamux:tt) => { impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { - unsafe fn start_write(&mut self, request: Request, buf: &[W], reg_addr: *mut W) { + unsafe fn start_write(&mut self, request: Request, buf: *const [W], reg_addr: *mut W) { + let (ptr, len) = super::slice_ptr_parts(buf); low_level_api::start_transfer( pac::$dma_peri, $channel_num, request, vals::Dir::MEMORYTOPERIPHERAL, reg_addr as *const u32, - buf.as_ptr() as *mut u32, - buf.len(), + ptr as *mut u32, + len, true, vals::Size::from(W::bits()), #[cfg(dmamux)] @@ -121,15 +122,16 @@ pac::dma_channels! { ) } - unsafe fn start_read(&mut self, request: Request, reg_addr: *mut W, buf: &mut [W]) { + unsafe fn start_read(&mut self, request: Request, reg_addr: *const W, buf: *mut [W]) { + let (ptr, len) = super::slice_ptr_parts_mut(buf); low_level_api::start_transfer( pac::$dma_peri, $channel_num, request, vals::Dir::PERIPHERALTOMEMORY, reg_addr as *const u32, - buf.as_ptr() as *mut u32, - buf.len(), + ptr as *mut u32, + len, true, vals::Size::from(W::bits()), #[cfg(dmamux)] diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index accc5565..b7067a9c 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs @@ -10,6 +10,7 @@ pub use dmamux::*; use core::future::Future; use core::marker::PhantomData; +use core::mem; use core::pin::Pin; use core::task::Waker; use core::task::{Context, Poll}; @@ -36,12 +37,13 @@ pub(crate) mod sealed { /// Starts this channel for writing a stream of words. /// /// Safety: + /// - `buf` must point to a valid buffer for DMA reading. /// - `buf` must be alive for the entire duration of the DMA transfer. /// - `reg_addr` must be a valid peripheral register address to write to. unsafe fn start_write( &mut self, request: Request, - buf: &[W], + buf: *const [W], reg_addr: *mut W, ); @@ -60,13 +62,14 @@ pub(crate) mod sealed { /// Starts this channel for reading a stream of words. /// /// Safety: + /// - `buf` must point to a valid buffer for DMA writing. /// - `buf` must be alive for the entire duration of the DMA transfer. - /// - `reg_addr` must be a valid peripheral register address to write to. + /// - `reg_addr` must be a valid peripheral register address to read from. unsafe fn start_read( &mut self, request: Request, - reg_addr: *mut W, - buf: &mut [W], + reg_addr: *const W, + buf: *mut [W], ); /// Requests the channel to stop. @@ -132,10 +135,7 @@ mod transfers { unsafe { channel.start_read::(request, reg_addr, buf) }; - Transfer { - channel, - _phantom: PhantomData, - } + Transfer::new(channel) } #[allow(unused)] @@ -150,10 +150,7 @@ mod transfers { unsafe { channel.start_write::(request, buf, reg_addr) }; - Transfer { - channel, - _phantom: PhantomData, - } + Transfer::new(channel) } #[allow(unused)] @@ -168,17 +165,24 @@ mod transfers { unsafe { channel.start_write_repeated::(request, repeated, count, reg_addr) }; - Transfer { - channel, - _phantom: PhantomData, - } + Transfer::new(channel) } - struct Transfer<'a, C: Channel> { + pub(crate) struct Transfer<'a, C: Channel> { channel: C, _phantom: PhantomData<&'a mut C>, } + impl<'a, C: Channel> Transfer<'a, C> { + pub(crate) fn new(channel: impl Unborrow + 'a) -> Self { + unborrow!(channel); + Self { + channel, + _phantom: PhantomData, + } + } + } + impl<'a, C: Channel> Drop for Transfer<'a, C> { fn drop(&mut self) { self.channel.request_stop(); @@ -221,3 +225,14 @@ pub(crate) unsafe fn init() { #[cfg(dmamux)] dmamux::init(); } + +// TODO: replace transmutes with core::ptr::metadata once it's stable +#[allow(unused)] +pub(crate) fn slice_ptr_parts(slice: *const [T]) -> (usize, usize) { + unsafe { mem::transmute(slice) } +} + +#[allow(unused)] +pub(crate) fn slice_ptr_parts_mut(slice: *mut [T]) -> (usize, usize) { + unsafe { mem::transmute(slice) } +}