Skip to content

Commit

Permalink
Replace use of Pin with StableDeref bounds
Browse files Browse the repository at this point in the history
Using Pin for DMA buffers does not provide the necessary safety.
See rust-embedded/embedonomicon#64
  • Loading branch information
teskje committed Apr 7, 2020
1 parent 542cc2a commit 2399507
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 25 deletions.
10 changes: 7 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,21 @@ version = "0.2"
features = ["const-fn"]

[dependencies.cast]
default-features = false
version = "0.2"

[dependencies.void]
default-features = false

[dependencies.stable_deref_trait]
version = "1"
default-features = false

[dependencies.stm32-usbd]
version = "0.5"
optional = true

[dependencies.void]
version = "1"
default-features = false

[dev-dependencies]
panic-semihosting = "0.5"
usb-device = "0.2"
Expand Down
7 changes: 3 additions & 4 deletions examples/serial_dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

use panic_semihosting as _;

use core::pin::Pin;
use cortex_m::singleton;
use cortex_m_rt::entry;
use stm32f3xx_hal::{prelude::*, serial::Serial, stm32};
Expand Down Expand Up @@ -43,11 +42,11 @@ fn main() -> ! {
let (tx_channel, rx_channel) = (dma1.ch4, dma1.ch5);

// start separate DMAs for sending and receiving the data
let sending = tx.write_all(Pin::new(tx_buf), tx_channel);
let receiving = rx.read_exact(Pin::new(rx_buf), rx_channel);
let sending = tx.write_all(tx_buf, tx_channel);
let receiving = rx.read_exact(rx_buf, rx_channel);

// block until all data was transmitted and received
let (mut tx_buf, tx_channel, tx) = sending.wait();
let (tx_buf, tx_channel, tx) = sending.wait();
let (rx_buf, rx_channel, rx) = receiving.wait();

assert_eq!(tx_buf, rx_buf);
Expand Down
16 changes: 7 additions & 9 deletions src/dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ use crate::{
stm32::{self, dma1::ch::cr},
};
use cast::u16;
use core::{
pin::Pin,
sync::atomic::{self, Ordering},
};
use core::sync::atomic::{self, Ordering};
use stable_deref_trait::StableDeref;

/// Extension trait to split a DMA peripheral into independent channels
pub trait DmaExt {
Expand All @@ -37,9 +35,9 @@ impl<B, C: Channel, T> Transfer<B, C, T> {
///
/// Callers must ensure that the DMA channel is configured correctly for
/// the given target and buffer.
pub unsafe fn start(buffer: Pin<B>, mut channel: C, target: T) -> Self
pub unsafe fn start(buffer: B, mut channel: C, target: T) -> Self
where
B: 'static,
B: StableDeref + 'static,
T: Target<C>,
{
assert!(!channel.is_enabled());
Expand All @@ -64,15 +62,15 @@ impl<B, C: Channel, T> Transfer<B, C, T> {
}

/// Stop this transfer and return ownership over its parts
pub fn stop(mut self) -> (Pin<B>, C, T) {
pub fn stop(mut self) -> (B, C, T) {
let mut inner = self.inner.take().unwrap();
inner.stop();

(inner.buffer, inner.channel, inner.target)
}

/// Block until this transfer is done and return ownership over its parts
pub fn wait(self) -> (Pin<B>, C, T) {
pub fn wait(self) -> (B, C, T) {
while !self.is_complete() {}

self.stop()
Expand All @@ -89,7 +87,7 @@ impl<B, C: Channel, T> Drop for Transfer<B, C, T> {

/// This only exists so we can implement `Drop` for `Transfer`.
struct TransferInner<B, C, T> {
buffer: Pin<B>,
buffer: B,
channel: C,
target: T,
}
Expand Down
16 changes: 7 additions & 9 deletions src/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,8 @@ use crate::gpio::gpioe;
mod dma_imports {
pub use crate::dma;
pub use as_slice::{AsMutSlice, AsSlice};
pub use core::{
ops::{Deref, DerefMut},
pin::Pin,
};
pub use core::ops::{Deref, DerefMut};
pub use stable_deref_trait::StableDeref;
}

#[cfg(feature = "stm32f303")]
Expand Down Expand Up @@ -376,13 +374,13 @@ macro_rules! hal {
/// Fill the buffer with received data using DMA.
pub fn read_exact<B, C>(
self,
mut buffer: Pin<B>,
mut buffer: B,
mut channel: C
) -> dma::Transfer<B, C, Self>
where
Self: dma::Target<C>,
B: DerefMut + 'static,
B::Target: AsMutSlice<Element = u8> + Unpin,
B: DerefMut + StableDeref + 'static,
B::Target: AsMutSlice<Element = u8>,
C: dma::Channel,
{
// NOTE(unsafe) taking the address of a register
Expand All @@ -406,12 +404,12 @@ macro_rules! hal {
/// Transmit all data in the buffer using DMA.
pub fn write_all<B, C>(
self,
buffer: Pin<B>,
buffer: B,
mut channel: C
) -> dma::Transfer<B, C, Self>
where
Self: dma::Target<C>,
B: Deref + 'static,
B: Deref + StableDeref + 'static,
B::Target: AsSlice<Element = u8>,
C: dma::Channel,
{
Expand Down

0 comments on commit 2399507

Please sign in to comment.