Expand description
Mechanism for sharing buffers with DMA peripherals.
When implementing a chip peripheral driver using DMA, the driver must be
careful to not introduce any undefined behavior. This module provides
DmaSlice types, which drivers can use when passing a buffer to the DMA
hardware. When used correctly, these types ensure that Rust’s memory requirements
are preserved when hardware is accessing memory in a way the Rust compiler
cannot reason about.
Tock provides multiple implementations of DmaSlice depending on the
needs of the user. These include:
DmaSlice: For immutable buffers and read-only DMA operations.DmaSliceMut: For mutable buffers and writable DMA operations.DmaSubSlice: For immutableSubSlices and read-only DMA operations.DmaSubSliceMut: For mutableSubSliceMuts and writable DMA operations.
Internally, all implementations of DmaSlice use an architecture or
chip-provided implementation of DmaFence to ensure that the
Rust compiler cannot assume the memory passed to the DMA hardware is not
modified.
Conceptually, a DmaSlice consumes a memory buffer. Once consumed, a
pointer to that memory can then be safely provided to DMA hardware. When the
buffer is consumed, the DmaSlice prevents the Rust compiler from making
assumptions about the state of the memory accessed by DMA hardware that
would be incorrect and introduce undefined behavior. Once the DMA operation
finishes, the buffer must be extracted from the DmaSlice. Before
extracting the buffer, the user must guarantee that the DMA hardware can no
longer access the memory.
§Usage
This example shows how a developer might use the DmaSlice infrastructure
in a driver. The DmaSliceMut::new operation can be replaced by the safe
DmaSliceMut::new_static alternative if the provided slice reference has
a 'static lifetime.
// Buffer that will be used by the DMA hardware.
let mut buffer: [u8; 16] = [0_u8; 16];
// Create the `DmaSlice` that can be provided to the DMA hardware.
//
// For a static slice, users can instead use the safe `new_static`
// constructor.
let dma_slice = unsafe { DmaSliceMut::new(&mut buffer, SomeDmaFence) };
// Provide the pointer to the buffer to the DMA hardware registers.
regs.dma_ptr.set(dma_slice.as_mut_ptr());
// Wait for the DMA operation to finish...
// Disable the DMA engine to ensure it cannot access the buffer.
regs.dma_ctrl.set(DmaOp::Stop);
// Extract the buffer to retrieve the Rust slice.
let buffer = unsafe { dma_slice.take(SomeDmaFence) };Modules§
Structs§
- DmaSlice
- An immutable buffer that can be safely used for read-only DMA operations.
- DmaSlice
Mut - A mutable buffer that can be safely used for DMA operations that read or write the buffer’s contents.
- DmaSub
Slice - An immutable buffer that can be safely used for read-only DMA operations,
created from a
SubSlicedescribing an active range in a larger buffer. - DmaSub
Slice Mut - A mutable buffer that can be safely used for DMA operations that read or write the buffer’s contents.
Enums§
- DmaSlice
MutImmut - A buffer that can be safely used for read-only DMA operations, backed by either a shared (immutable) or unique (mutable) Rust slice.
- DmaSub
Slice MutImmut - A buffer that can be safely used for read-only DMA operations, backed by
either a
SubSliceMutImmut.