Skip to content

Commit

Permalink
Merge pull request #621 from jannic/unsafe-dma-targets
Browse files Browse the repository at this point in the history
Mark ReadTarget and WriteTarget as unsafe
  • Loading branch information
jannic authored Aug 30, 2023
2 parents a12bcda + 172b1fa commit d46bb60
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 10 deletions.
34 changes: 30 additions & 4 deletions rp2040-hal/src/dma/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,19 @@ impl<CH: ChannelIndex> ChannelRegs for Channel<CH> {
}

/// Trait which is implemented by anything that can be read via DMA.
pub trait ReadTarget {
///
/// # Safety
///
/// The implementing type must be safe to use for DMA reads. This means:
///
/// - The range returned by rx_address_count must point to a valid address,
/// and if rx_increment is true, count must fit into the allocated buffer.
/// - As long as no `&mut self` method is called on the implementing object:
/// - `rx_address_count` must always return the same value, if called multiple
/// times.
/// - The memory specified by the pointer and size returned by `rx_address_count`
/// must not be freed during the transfer it is used in as long as `self` is not dropped.
pub unsafe trait ReadTarget {
/// Type which is transferred in a single DMA transfer.
type ReceivedWord;

Expand Down Expand Up @@ -182,7 +194,8 @@ pub trait ReadTarget {
/// two DMA channels. In the case of peripherals, the function can always return the same values.
pub trait EndlessReadTarget: ReadTarget {}

impl<B: ReadBuffer> ReadTarget for B {
/// Safety: ReadBuffer and ReadTarget have the same safety requirements.
unsafe impl<B: ReadBuffer> ReadTarget for B {
type ReceivedWord = <B as ReadBuffer>::Word;

fn rx_treq() -> Option<u8> {
Expand All @@ -200,7 +213,19 @@ impl<B: ReadBuffer> ReadTarget for B {
}

/// Trait which is implemented by anything that can be written via DMA.
pub trait WriteTarget {
///
/// # Safety
///
/// The implementing type must be safe to use for DMA writes. This means:
///
/// - The range returned by tx_address_count must point to a valid address,
/// and if tx_increment is true, count must fit into the allocated buffer.
/// - As long as no other `&mut self` method is called on the implementing object:
/// - `tx_address_count` must always return the same value, if called multiple
/// times.
/// - The memory specified by the pointer and size returned by `tx_address_count`
/// must not be freed during the transfer it is used in as long as `self` is not dropped.
pub unsafe trait WriteTarget {
/// Type which is transferred in a single DMA transfer.
type TransmittedWord;

Expand All @@ -224,7 +249,8 @@ pub trait WriteTarget {
/// two DMA channels. In the case of peripherals, the function can always return the same values.
pub trait EndlessWriteTarget: WriteTarget {}

impl<B: WriteBuffer> WriteTarget for B {
/// Safety: WriteBuffer and WriteTarget have the same safety requirements.
unsafe impl<B: WriteBuffer> WriteTarget for B {
type TransmittedWord = <B as WriteBuffer>::Word;

fn tx_treq() -> Option<u8> {
Expand Down
8 changes: 6 additions & 2 deletions rp2040-hal/src/pio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1394,7 +1394,9 @@ impl<SM: ValidStateMachine> Rx<SM> {
}
}

impl<SM: ValidStateMachine> ReadTarget for Rx<SM> {
// Safety: This only reads from the state machine fifo, so it doesn't
// interact with rust-managed memory.
unsafe impl<SM: ValidStateMachine> ReadTarget for Rx<SM> {
type ReceivedWord = u32;

fn rx_treq() -> Option<u8> {
Expand Down Expand Up @@ -1586,7 +1588,9 @@ impl<SM: ValidStateMachine> Tx<SM> {
}
}

impl<SM: ValidStateMachine> WriteTarget for Tx<SM> {
// Safety: This only writes to the state machine fifo, so it doesn't
// interact with rust-managed memory.
unsafe impl<SM: ValidStateMachine> WriteTarget for Tx<SM> {
type TransmittedWord = u32;

fn tx_treq() -> Option<u8> {
Expand Down
8 changes: 6 additions & 2 deletions rp2040-hal/src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,9 @@ macro_rules! impl_write {
}
}

impl<D: SpiDevice, P: ValidSpiPinout<D>> ReadTarget for Spi<Enabled, D, P, $nr> {
// Safety: This only reads from the RX fifo, so it doesn't
// interact with rust-managed memory.
unsafe impl<D: SpiDevice, P: ValidSpiPinout<D>> ReadTarget for Spi<Enabled, D, P, $nr> {
type ReceivedWord = $type;

fn rx_treq() -> Option<u8> {
Expand All @@ -493,7 +495,9 @@ macro_rules! impl_write {

impl<D: SpiDevice, P: ValidSpiPinout<D>> EndlessReadTarget for Spi<Enabled, D, P, $nr> {}

impl<D: SpiDevice, P: ValidSpiPinout<D>> WriteTarget for Spi<Enabled, D, P, $nr> {
// Safety: This only writes to the TX fifo, so it doesn't
// interact with rust-managed memory.
unsafe impl<D: SpiDevice, P: ValidSpiPinout<D>> WriteTarget for Spi<Enabled, D, P, $nr> {
type TransmittedWord = $type;

fn tx_treq() -> Option<u8> {
Expand Down
4 changes: 3 additions & 1 deletion rp2040-hal/src/uart/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,9 @@ impl<D: UartDevice, P: ValidUartPinout<D>> Read<u8> for Reader<D, P> {
}
}

impl<D: UartDevice, P: ValidUartPinout<D>> ReadTarget for Reader<D, P> {
// Safety: This only reads from the RX fifo, so it doesn't
// interact with rust-managed memory.
unsafe impl<D: UartDevice, P: ValidUartPinout<D>> ReadTarget for Reader<D, P> {
type ReceivedWord = u8;

fn rx_treq() -> Option<u8> {
Expand Down
4 changes: 3 additions & 1 deletion rp2040-hal/src/uart/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,9 @@ impl<D: UartDevice, P: ValidUartPinout<D>> Write<u8> for Writer<D, P> {
}
}

impl<D: UartDevice, P: ValidUartPinout<D>> WriteTarget for Writer<D, P> {
// Safety: This only writes to the TX fifo, so it doesn't
// interact with rust-managed memory.
unsafe impl<D: UartDevice, P: ValidUartPinout<D>> WriteTarget for Writer<D, P> {
type TransmittedWord = u8;

fn tx_treq() -> Option<u8> {
Expand Down

0 comments on commit d46bb60

Please sign in to comment.