pub struct DmaChannel<C: Channel> { /* private fields */ }Expand description
Strongly-typed handle to a DMA0 channel.
The lifetime of this value is tied to the unique peripheral token
supplied by embassy_hal_internal::peripherals!, so safe code cannot
create two DmaChannel instances for the same hardware channel.
Implementations§
Source§impl<C: Channel> DmaChannel<C>
impl<C: Channel> DmaChannel<C>
Sourcepub fn new(_ch: Peri<'_, C>) -> Self
pub fn new(_ch: Peri<'_, C>) -> Self
Wrap a DMA channel token (takes ownership of the Peri wrapper).
Note: DMA is initialized during hal::init() via dma::init().
Sourcepub fn into_any(self) -> AnyChannel
pub fn into_any(self) -> AnyChannel
Convert this typed channel into a type-erased AnyChannel.
Sourcepub fn as_any(&self) -> AnyChannel
pub fn as_any(&self) -> AnyChannel
Get a reference to the type-erased channel info.
Sourcepub fn tcd(&self) -> &'static Tcd
pub fn tcd(&self) -> &'static Tcd
Return a reference to the underlying TCD register block.
This steals the eDMA pointer internally since MCXA276 has only one eDMA instance.
§Note
This is exposed for advanced use cases that need direct TCD access. For most use cases, prefer the higher-level transfer methods.
Sourcepub unsafe fn start_transfer(&self) -> Transfer<'_> ⓘ
pub unsafe fn start_transfer(&self) -> Transfer<'_> ⓘ
Start an async transfer.
The channel must already be configured. This enables the channel
request and returns a Transfer future that resolves when the
DMA transfer completes.
§Safety
The caller must ensure the DMA channel has been properly configured and that source/destination buffers remain valid for the duration of the transfer.
Sourcepub fn mem_to_mem<W: Word>(
&self,
src: &[W],
dst: &mut [W],
options: TransferOptions,
) -> Result<Transfer<'_>, Error>
pub fn mem_to_mem<W: Word>( &self, src: &[W], dst: &mut [W], options: TransferOptions, ) -> Result<Transfer<'_>, Error>
Perform a memory-to-memory DMA transfer (simplified API).
This is a type-safe wrapper that uses the Word trait to determine
the correct transfer width automatically. Uses the global eDMA TCD
register accessor internally.
§Arguments
src- Source bufferdst- Destination buffer (must be at least as large as src)options- Transfer configuration options
§Safety
The source and destination buffers must remain valid for the duration of the transfer.
Sourcepub fn memset<W: Word>(
&self,
pattern: &W,
dst: &mut [W],
options: TransferOptions,
) -> Transfer<'_> ⓘ
pub fn memset<W: Word>( &self, pattern: &W, dst: &mut [W], options: TransferOptions, ) -> Transfer<'_> ⓘ
Fill a memory buffer with a pattern value (memset).
This performs a DMA transfer where the source address remains fixed (pattern value) while the destination address increments through the buffer. It’s useful for quickly filling large memory regions with a constant value.
§Arguments
pattern- Reference to the pattern value (will be read repeatedly)dst- Destination buffer to filloptions- Transfer configuration options
§Example
use embassy_mcxa::dma::{DmaChannel, TransferOptions};
let dma_ch = DmaChannel::new(p.DMA_CH0);
let pattern: u32 = 0xDEADBEEF;
let mut buffer = [0u32; 256];
unsafe {
dma_ch.memset(&pattern, &mut buffer, TransferOptions::default()).await;
}
// buffer is now filled with 0xDEADBEEFSourcepub unsafe fn write<W: Word>(
&self,
buf: &[W],
peri_addr: *mut W,
options: TransferOptions,
) -> Transfer<'_> ⓘ
pub unsafe fn write<W: Word>( &self, buf: &[W], peri_addr: *mut W, options: TransferOptions, ) -> Transfer<'_> ⓘ
Write data from memory to a peripheral register.
The destination address remains fixed (peripheral register) while the source address increments through the buffer.
§Arguments
buf- Source buffer to write fromperi_addr- Peripheral register addressoptions- Transfer configuration options
§Safety
- The buffer must remain valid for the duration of the transfer.
- The peripheral address must be valid for writes.
Sourcepub unsafe fn setup_write<W: Word>(
&self,
buf: &[W],
peri_addr: *mut W,
enable_interrupt: EnableInterrupt,
)
pub unsafe fn setup_write<W: Word>( &self, buf: &[W], peri_addr: *mut W, enable_interrupt: EnableInterrupt, )
Configure a memory-to-peripheral DMA transfer without starting it.
This is a convenience wrapper around setup_write_to_peripheral()
that uses the default eDMA TCD register block.
This method configures the TCD but does NOT return a Transfer. The caller
is responsible for the complete DMA lifecycle:
- Call
enable_request()to start the transfer - Poll
is_done()or use interrupts to detect completion - Call
disable_request(),clear_done(),clear_interrupt()for cleanup
§Example
let data = [0x48, 0x65, 0x6c, 0x6c, 0x6f]; // "Hello"
unsafe {
// Configure the transfer
dma_ch.setup_write(&data, uart_tx_addr, EnableInterrupt::Yes);
// Start when peripheral is ready
dma_ch.enable_request();
// Wait for completion (or use interrupt)
while !dma_ch.is_done() {}
// Clean up
dma_ch.clear_done();
dma_ch.clear_interrupt();
}§Arguments
buf- Source buffer to write fromperi_addr- Peripheral register addressenable_interrupt- Whether to enable interrupt on completion
§Safety
- The buffer must remain valid for the duration of the transfer.
- The peripheral address must be valid for writes.
Sourcepub unsafe fn write_to_peripheral<W: Word>(
&self,
buf: &[W],
peri_addr: *mut W,
options: TransferOptions,
) -> Transfer<'_> ⓘ
pub unsafe fn write_to_peripheral<W: Word>( &self, buf: &[W], peri_addr: *mut W, options: TransferOptions, ) -> Transfer<'_> ⓘ
Write data from memory to a peripheral register.
The destination address remains fixed (peripheral register) while the source address increments through the buffer.
§Arguments
buf- Source buffer to write fromperi_addr- Peripheral register addressoptions- Transfer configuration options
§Safety
- The buffer must remain valid for the duration of the transfer.
- The peripheral address must be valid for writes.
Sourcepub unsafe fn read<W: Word>(
&self,
peri_addr: *const W,
buf: &mut [W],
options: TransferOptions,
) -> Transfer<'_> ⓘ
pub unsafe fn read<W: Word>( &self, peri_addr: *const W, buf: &mut [W], options: TransferOptions, ) -> Transfer<'_> ⓘ
Read data from a peripheral register to memory.
The source address remains fixed (peripheral register) while the destination address increments through the buffer.
§Arguments
peri_addr- Peripheral register addressbuf- Destination buffer to read intooptions- Transfer configuration options
§Safety
- The buffer must remain valid for the duration of the transfer.
- The peripheral address must be valid for reads.
Sourcepub unsafe fn setup_read<W: Word>(
&self,
peri_addr: *const W,
buf: &mut [W],
enable_interrupt: EnableInterrupt,
)
pub unsafe fn setup_read<W: Word>( &self, peri_addr: *const W, buf: &mut [W], enable_interrupt: EnableInterrupt, )
Configure a peripheral-to-memory DMA transfer without starting it.
This is a convenience wrapper around setup_read_from_peripheral()
that uses the default eDMA TCD register block.
This method configures the TCD but does NOT return a Transfer. The caller
is responsible for the complete DMA lifecycle:
- Call
enable_request()to start the transfer - Poll
is_done()or use interrupts to detect completion - Call
disable_request(),clear_done(),clear_interrupt()for cleanup
§Example
let mut buf = [0u8; 32];
unsafe {
// Configure the transfer
dma_ch.setup_read(uart_rx_addr, &mut buf, EnableInterrupt::Yes);
// Start when peripheral is ready
dma_ch.enable_request();
// Wait for completion (or use interrupt)
while !dma_ch.is_done() {}
// Clean up
dma_ch.clear_done();
dma_ch.clear_interrupt();
}
// buf now contains received data§Arguments
peri_addr- Peripheral register addressbuf- Destination buffer to read intoenable_interrupt- Whether to enable interrupt on completion
§Safety
- The buffer must remain valid for the duration of the transfer.
- The peripheral address must be valid for reads.
Sourcepub unsafe fn read_from_peripheral<W: Word>(
&self,
peri_addr: *const W,
buf: &mut [W],
options: TransferOptions,
) -> Transfer<'_> ⓘ
pub unsafe fn read_from_peripheral<W: Word>( &self, peri_addr: *const W, buf: &mut [W], options: TransferOptions, ) -> Transfer<'_> ⓘ
Read data from a peripheral register to memory.
The source address remains fixed (peripheral register) while the destination address increments through the buffer.
§Arguments
peri_addr- Peripheral register addressbuf- Destination buffer to read intooptions- Transfer configuration options
§Safety
- The buffer must remain valid for the duration of the transfer.
- The peripheral address must be valid for reads.
Sourcepub unsafe fn setup_write_to_peripheral<W: Word>(
&self,
buf: &[W],
peri_addr: *mut W,
enable_interrupt: EnableInterrupt,
)
pub unsafe fn setup_write_to_peripheral<W: Word>( &self, buf: &[W], peri_addr: *mut W, enable_interrupt: EnableInterrupt, )
Configure a memory-to-peripheral DMA transfer without starting it.
This configures the TCD for a memory-to-peripheral transfer but does NOT return a Transfer object. The caller is responsible for:
- Enabling the peripheral’s DMA request
- Calling
enable_request()to start the transfer - Polling
is_done()or using interrupts to detect completion - Calling
disable_request(),clear_done(),clear_interrupt()for cleanup
Use this when you need manual control over the DMA lifecycle (e.g., in peripheral drivers that have their own completion polling).
§Arguments
buf- Source buffer to write fromperi_addr- Peripheral register addressenable_interrupt- Whether to enable interrupt on completion
§Safety
- The buffer must remain valid for the duration of the transfer.
- The peripheral address must be valid for writes.
Sourcepub unsafe fn setup_read_from_peripheral<W: Word>(
&self,
peri_addr: *const W,
buf: &mut [W],
enable_interrupt: EnableInterrupt,
)
pub unsafe fn setup_read_from_peripheral<W: Word>( &self, peri_addr: *const W, buf: &mut [W], enable_interrupt: EnableInterrupt, )
Configure a peripheral-to-memory DMA transfer without starting it.
This configures the TCD for a peripheral-to-memory transfer but does NOT return a Transfer object. The caller is responsible for:
- Enabling the peripheral’s DMA request
- Calling
enable_request()to start the transfer - Polling
is_done()or using interrupts to detect completion - Calling
disable_request(),clear_done(),clear_interrupt()for cleanup
Use this when you need manual control over the DMA lifecycle (e.g., in peripheral drivers that have their own completion polling).
§Arguments
peri_addr- Peripheral register addressbuf- Destination buffer to read intoenable_interrupt- Whether to enable interrupt on completion
§Safety
- The buffer must remain valid for the duration of the transfer.
- The peripheral address must be valid for reads.
Sourcepub unsafe fn set_request_source<R: DmaRequest>(&self)
pub unsafe fn set_request_source<R: DmaRequest>(&self)
Configure the integrated channel MUX to use the given typed
DMA request source (e.g., Lpuart2TxRequest or Lpuart2RxRequest).
This is the type-safe version that uses marker types to ensure compile-time verification of request source validity.
§Safety
The channel must be properly configured before enabling requests. The caller must ensure the DMA request source matches the peripheral that will drive this channel.
§Note
The NXP SDK requires a two-step write sequence: first clear the mux to 0, then set the actual source. This is a hardware requirement on eDMA4 for the mux to properly latch.
§Example
use embassy_mcxa::dma::{DmaChannel, Lpuart2RxRequest};
// Type-safe: compiler verifies this is a valid DMA request type
unsafe {
channel.set_request_source::<Lpuart2RxRequest>();
}Sourcepub unsafe fn enable_request(&self)
pub unsafe fn enable_request(&self)
Enable hardware requests for this channel (ERQ=1).
§Safety
The channel must be properly configured before enabling requests.
Sourcepub unsafe fn disable_request(&self)
pub unsafe fn disable_request(&self)
Disable hardware requests for this channel (ERQ=0).
§Safety
Disabling requests on an active transfer may leave the transfer incomplete.
Sourcepub unsafe fn clear_done(&self)
pub unsafe fn clear_done(&self)
Clear the DONE flag for this channel.
Uses modify to preserve other bits (especially ERQ) unlike write which would clear ERQ and halt an active transfer.
§Safety
Clearing DONE while a transfer is in progress may cause undefined behavior.
Sourcepub unsafe fn clear_interrupt(&self)
pub unsafe fn clear_interrupt(&self)
Clear the channel interrupt flag (CH_INT.INT).
§Safety
Must be called from the correct interrupt context or with interrupts disabled.
Sourcepub unsafe fn trigger_start(&self)
pub unsafe fn trigger_start(&self)
Trigger a software start for this channel.
§Safety
The channel must be properly configured with a valid TCD before triggering.
Sourcepub fn waker(&self) -> &'static AtomicWaker
pub fn waker(&self) -> &'static AtomicWaker
Get the waker for this channel
Sourcepub fn enable_interrupt(&self)
pub fn enable_interrupt(&self)
Enable the interrupt for this channel in the NVIC.
Sourcepub unsafe fn set_major_link(&self, link_ch: usize)
pub unsafe fn set_major_link(&self, link_ch: usize)
Sourcepub unsafe fn clear_major_link(&self)
pub unsafe fn clear_major_link(&self)
Disable Major Loop Linking.
Removes any major loop channel linking previously configured.
§Safety
The caller must ensure this doesn’t disrupt an active transfer that depends on the linking.
Sourcepub unsafe fn set_minor_link(&self, link_ch: usize)
pub unsafe fn set_minor_link(&self, link_ch: usize)
Enable Minor Loop Linking.
After each minor loop, the hardware will trigger a service request
on link_ch.
§Arguments
link_ch- Target channel index (0-7) to link to
§Note
This rewrites CITER and BITER registers to the ELINKYES format. It preserves the current loop count.
§Safety
The channel must be properly configured before setting up linking.
Sourcepub unsafe fn clear_minor_link(&self)
pub unsafe fn clear_minor_link(&self)
Disable Minor Loop Linking.
Removes any minor loop channel linking previously configured. This rewrites CITER and BITER registers to the ELINKNO format, preserving the current loop count.
§Safety
The caller must ensure this doesn’t disrupt an active transfer that depends on the linking.
Sourcepub unsafe fn load_tcd(&self, tcd: &Tcd)
pub unsafe fn load_tcd(&self, tcd: &Tcd)
Load a TCD from memory into the hardware channel registers.
This is useful for scatter/gather and ping-pong transfers where TCDs are prepared in RAM and then loaded into the hardware.
§Safety
- The TCD must be properly initialized.
- The caller must ensure no concurrent access to the same channel.
Source§impl<C: Channel> DmaChannel<C>
impl<C: Channel> DmaChannel<C>
Sourcepub unsafe fn setup_circular_read<'a, W: Word>(
&self,
peri_addr: *const W,
buf: &'a mut [W],
) -> RingBuffer<'a, W>
pub unsafe fn setup_circular_read<'a, W: Word>( &self, peri_addr: *const W, buf: &'a mut [W], ) -> RingBuffer<'a, W>
Set up a circular DMA transfer for continuous peripheral-to-memory reception.
This configures the DMA channel for circular operation with both half-transfer
and complete-transfer interrupts enabled. The transfer runs continuously until
stopped via RingBuffer::stop().
§Arguments
peri_addr- Peripheral register address to read frombuf- Destination buffer (should be power-of-2 size for best efficiency)
§Returns
A RingBuffer that can be used to read received data.
§Safety
- The buffer must remain valid for the lifetime of the returned RingBuffer.
- The peripheral address must be valid for reads.
- The peripheral’s DMA request must be configured to trigger this channel.