hardware_dma

Modules

 channel_config
 DMA channel configuration.
 

Enumerations

enum  dma_channel_transfer_size { DMA_SIZE_8 = 0 , DMA_SIZE_16 = 1 , DMA_SIZE_32 = 2 }
 Enumeration of available DMA channel transfer sizes. More...
 

Functions

void dma_channel_claim (uint channel)
 Mark a dma channel as used. More...
 
void dma_claim_mask (uint32_t channel_mask)
 Mark multiple dma channels as used. More...
 
void dma_channel_unclaim (uint channel)
 Mark a dma channel as no longer used. More...
 
void dma_unclaim_mask (uint32_t channel_mask)
 Mark multiple dma channels as no longer used. More...
 
int dma_claim_unused_channel (bool required)
 Claim a free dma channel. More...
 
bool dma_channel_is_claimed (uint channel)
 Determine if a dma channel is claimed. More...
 
static void dma_channel_set_config (uint channel, const dma_channel_config *config, bool trigger)
 Set a channel configuration. More...
 
static void dma_channel_set_read_addr (uint channel, const volatile void *read_addr, bool trigger)
 Set the DMA initial read address. More...
 
static void dma_channel_set_write_addr (uint channel, volatile void *write_addr, bool trigger)
 Set the DMA initial write address. More...
 
static void dma_channel_set_trans_count (uint channel, uint32_t trans_count, bool trigger)
 Set the number of bus transfers the channel will do. More...
 
static void dma_channel_configure (uint channel, const dma_channel_config *config, volatile void *write_addr, const volatile void *read_addr, uint transfer_count, bool trigger)
 Configure all DMA parameters and optionally start transfer. More...
 
static void dma_channel_transfer_from_buffer_now (uint channel, const volatile void *read_addr, uint32_t transfer_count)
 Start a DMA transfer from a buffer immediately. More...
 
static void dma_channel_transfer_to_buffer_now (uint channel, volatile void *write_addr, uint32_t transfer_count)
 Start a DMA transfer to a buffer immediately. More...
 
static void dma_start_channel_mask (uint32_t chan_mask)
 Start one or more channels simultaneously. More...
 
static void dma_channel_start (uint channel)
 Start a single DMA channel. More...
 
static void dma_channel_abort (uint channel)
 Stop a DMA transfer. More...
 
static void dma_channel_set_irq0_enabled (uint channel, bool enabled)
 Enable single DMA channel's interrupt via DMA_IRQ_0. More...
 
static void dma_set_irq0_channel_mask_enabled (uint32_t channel_mask, bool enabled)
 Enable multiple DMA channels' interrupts via DMA_IRQ_0. More...
 
static void dma_channel_set_irq1_enabled (uint channel, bool enabled)
 Enable single DMA channel's interrupt via DMA_IRQ_1. More...
 
static void dma_set_irq1_channel_mask_enabled (uint32_t channel_mask, bool enabled)
 Enable multiple DMA channels' interrupts via DMA_IRQ_1. More...
 
static void dma_irqn_set_channel_enabled (uint irq_index, uint channel, bool enabled)
 Enable single DMA channel interrupt on either DMA_IRQ_0 or DMA_IRQ_1. More...
 
static void dma_irqn_set_channel_mask_enabled (uint irq_index, uint32_t channel_mask, bool enabled)
 Enable multiple DMA channels' interrupt via either DMA_IRQ_0 or DMA_IRQ_1. More...
 
static bool dma_channel_get_irq0_status (uint channel)
 Determine if a particular channel is a cause of DMA_IRQ_0. More...
 
static bool dma_channel_get_irq1_status (uint channel)
 Determine if a particular channel is a cause of DMA_IRQ_1. More...
 
static bool dma_irqn_get_channel_status (uint irq_index, uint channel)
 Determine if a particular channel is a cause of DMA_IRQ_N. More...
 
static void dma_channel_acknowledge_irq0 (uint channel)
 Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_0. More...
 
static void dma_channel_acknowledge_irq1 (uint channel)
 Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_1. More...
 
static void dma_irqn_acknowledge_channel (uint irq_index, uint channel)
 Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_N. More...
 
static bool dma_channel_is_busy (uint channel)
 Check if DMA channel is busy. More...
 
static void dma_channel_wait_for_finish_blocking (uint channel)
 Wait for a DMA channel transfer to complete. More...
 
static void dma_sniffer_enable (uint channel, uint mode, bool force_channel_enable)
 Enable the DMA sniffing targeting the specified channel. More...
 
static void dma_sniffer_set_byte_swap_enabled (bool swap)
 Enable the Sniffer byte swap function. More...
 
static void dma_sniffer_set_output_invert_enabled (bool invert)
 Enable the Sniffer output invert function. More...
 
static void dma_sniffer_set_output_reverse_enabled (bool reverse)
 Enable the Sniffer output bit reversal function. More...
 
static void dma_sniffer_disable (void)
 Disable the DMA sniffer.
 
static void dma_sniffer_set_data_accumulator (uint32_t seed_value)
 Set the sniffer's data accumulator with initial value. More...
 
static uint32_t dma_sniffer_get_data_accumulator (void)
 Get the sniffer's data accumulator value. More...
 
void dma_timer_claim (uint timer)
 Mark a dma timer as used. More...
 
void dma_timer_unclaim (uint timer)
 Mark a dma timer as no longer used. More...
 
int dma_claim_unused_timer (bool required)
 Claim a free dma timer. More...
 
bool dma_timer_is_claimed (uint timer)
 Determine if a dma timer is claimed. More...
 
static void dma_timer_set_fraction (uint timer, uint16_t numerator, uint16_t denominator)
 Set the divider for the given DMA timer. More...
 
static uint dma_get_timer_dreq (uint timer_num)
 Return the DREQ number for a given DMA timer. More...
 
void dma_channel_cleanup (uint channel)
 Performs DMA channel cleanup after use. More...
 

Detailed Description

DMA Controller API

The RP2040 Direct Memory Access (DMA) master performs bulk data transfers on a processor’s behalf. This leaves processors free to attend to other tasks, or enter low-power sleep states. The data throughput of the DMA is also significantly higher than one of RP2040’s processors.

The DMA can perform one read access and one write access, up to 32 bits in size, every clock cycle. There are 12 independent channels, which each supervise a sequence of bus transfers, usually in one of the following scenarios:

Enumeration Type Documentation

◆ dma_channel_transfer_size

Enumeration of available DMA channel transfer sizes.

Names indicate the number of bits.

Enumerator
DMA_SIZE_8 

Byte transfer (8 bits)

DMA_SIZE_16 

Half word transfer (16 bits)

DMA_SIZE_32 

Word transfer (32 bits)

Function Documentation

◆ dma_channel_abort()

static void dma_channel_abort ( uint  channel)
inlinestatic

Stop a DMA transfer.

Function will only return once the DMA has stopped.

Note that due to errata RP2040-E13, aborting a channel which has transfers in-flight (i.e. an individual read has taken place but the corresponding write has not), the ABORT status bit will clear prematurely, and subsequently the in-flight transfers will trigger a completion interrupt once they complete.

The effect of this is that you may see a spurious completion interrupt on the channel as a result of calling this method.

The calling code should be sure to ignore a completion IRQ as a result of this method. This may not require any additional work, as aborting a channel which may be about to complete, when you have a completion IRQ handler registered, is inherently race-prone, and so code is likely needed to disambiguate the two occurrences.

If that is not the case, but you do have a channel completion IRQ handler registered, you can simply disable/re-enable the IRQ around the call to this method as shown by this code fragment (using DMA IRQ0).

// disable the channel on IRQ0
// abort the channel
// clear the spurious IRQ (if there was one)
// re-enable the channel on IRQ0
static void dma_channel_abort(uint channel)
Stop a DMA transfer.
Definition: dma.h:527
static void dma_channel_set_irq0_enabled(uint channel, bool enabled)
Enable single DMA channel's interrupt via DMA_IRQ_0.
Definition: dma.h:541
static void dma_channel_acknowledge_irq0(uint channel)
Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_0.
Definition: dma.h:665
Parameters
channelDMA channel

◆ dma_channel_acknowledge_irq0()

static void dma_channel_acknowledge_irq0 ( uint  channel)
inlinestatic

Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_0.

Parameters
channelDMA channel

◆ dma_channel_acknowledge_irq1()

static void dma_channel_acknowledge_irq1 ( uint  channel)
inlinestatic

Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_1.

Parameters
channelDMA channel

◆ dma_channel_claim()

void dma_channel_claim ( uint  channel)

Mark a dma channel as used.

Method for cooperative claiming of hardware. Will cause a panic if the channel is already claimed. Use of this method by libraries detects accidental configurations that would fail in unpredictable ways.

Parameters
channelthe dma channel

◆ dma_channel_cleanup()

void dma_channel_cleanup ( uint  channel)

Performs DMA channel cleanup after use.

This can be used to cleanup dma channels when they're no longer needed, such that they are in a clean state for reuse. IRQ's for the channel are disabled, any in flight-transfer is aborted and any outstanding interrupts are cleared. The channel is then clear to be reused for other purposes.

if (dma_channel >= 0) {
dma_channel_cleanup(dma_channel);
dma_channel_unclaim(dma_channel);
dma_channel = -1;
}
void dma_channel_cleanup(uint channel)
Performs DMA channel cleanup after use.
Definition: dma.c:73
void dma_channel_unclaim(uint channel)
Mark a dma channel as no longer used.
Definition: dma.c:34
Parameters
channelDMA channel

◆ dma_channel_configure()

static void dma_channel_configure ( uint  channel,
const dma_channel_config config,
volatile void *  write_addr,
const volatile void *  read_addr,
uint  transfer_count,
bool  trigger 
)
inlinestatic

Configure all DMA parameters and optionally start transfer.

Parameters
channelDMA channel
configPointer to DMA config structure
write_addrInitial write address
read_addrInitial read address
transfer_countNumber of transfers to perform
triggerTrue to start the transfer immediately

◆ dma_channel_get_irq0_status()

static bool dma_channel_get_irq0_status ( uint  channel)
inlinestatic

Determine if a particular channel is a cause of DMA_IRQ_0.

Parameters
channelDMA channel
Returns
true if the channel is a cause of DMA_IRQ_0, false otherwise

◆ dma_channel_get_irq1_status()

static bool dma_channel_get_irq1_status ( uint  channel)
inlinestatic

Determine if a particular channel is a cause of DMA_IRQ_1.

Parameters
channelDMA channel
Returns
true if the channel is a cause of DMA_IRQ_1, false otherwise

◆ dma_channel_is_busy()

static bool dma_channel_is_busy ( uint  channel)
inlinestatic

Check if DMA channel is busy.

Parameters
channelDMA channel
Returns
true if the channel is currently busy

◆ dma_channel_is_claimed()

bool dma_channel_is_claimed ( uint  channel)

Determine if a dma channel is claimed.

Parameters
channelthe dma channel
Returns
true if the channel is claimed, false otherwise
See also
dma_channel_claim
dma_channel_claim_mask

◆ dma_channel_set_config()

static void dma_channel_set_config ( uint  channel,
const dma_channel_config config,
bool  trigger 
)
inlinestatic

Set a channel configuration.

Parameters
channelDMA channel
configPointer to a config structure with required configuration
triggerTrue to trigger the transfer immediately

◆ dma_channel_set_irq0_enabled()

static void dma_channel_set_irq0_enabled ( uint  channel,
bool  enabled 
)
inlinestatic

Enable single DMA channel's interrupt via DMA_IRQ_0.

Parameters
channelDMA channel
enabledtrue to enable interrupt 0 on specified channel, false to disable.

◆ dma_channel_set_irq1_enabled()

static void dma_channel_set_irq1_enabled ( uint  channel,
bool  enabled 
)
inlinestatic

Enable single DMA channel's interrupt via DMA_IRQ_1.

Parameters
channelDMA channel
enabledtrue to enable interrupt 1 on specified channel, false to disable.

◆ dma_channel_set_read_addr()

static void dma_channel_set_read_addr ( uint  channel,
const volatile void *  read_addr,
bool  trigger 
)
inlinestatic

Set the DMA initial read address.

Parameters
channelDMA channel
read_addrInitial read address of transfer.
triggerTrue to start the transfer immediately

◆ dma_channel_set_trans_count()

static void dma_channel_set_trans_count ( uint  channel,
uint32_t  trans_count,
bool  trigger 
)
inlinestatic

Set the number of bus transfers the channel will do.

Parameters
channelDMA channel
trans_countThe number of transfers (not NOT bytes, see channel_config_set_transfer_data_size)
triggerTrue to start the transfer immediately

◆ dma_channel_set_write_addr()

static void dma_channel_set_write_addr ( uint  channel,
volatile void *  write_addr,
bool  trigger 
)
inlinestatic

Set the DMA initial write address.

Parameters
channelDMA channel
write_addrInitial write address of transfer.
triggerTrue to start the transfer immediately

◆ dma_channel_start()

static void dma_channel_start ( uint  channel)
inlinestatic

Start a single DMA channel.

Parameters
channelDMA channel

◆ dma_channel_transfer_from_buffer_now()

static void dma_channel_transfer_from_buffer_now ( uint  channel,
const volatile void *  read_addr,
uint32_t  transfer_count 
)
inlinestatic

Start a DMA transfer from a buffer immediately.

Parameters
channelDMA channel
read_addrSets the initial read address
transfer_countNumber of transfers to make. Not bytes, but the number of transfers of channel_config_set_transfer_data_size() to be sent.

◆ dma_channel_transfer_to_buffer_now()

static void dma_channel_transfer_to_buffer_now ( uint  channel,
volatile void *  write_addr,
uint32_t  transfer_count 
)
inlinestatic

Start a DMA transfer to a buffer immediately.

Parameters
channelDMA channel
write_addrSets the initial write address
transfer_countNumber of transfers to make. Not bytes, but the number of transfers of channel_config_set_transfer_data_size() to be sent.

◆ dma_channel_unclaim()

void dma_channel_unclaim ( uint  channel)

Mark a dma channel as no longer used.

Parameters
channelthe dma channel to release

◆ dma_channel_wait_for_finish_blocking()

static void dma_channel_wait_for_finish_blocking ( uint  channel)
inlinestatic

Wait for a DMA channel transfer to complete.

Parameters
channelDMA channel

◆ dma_claim_mask()

void dma_claim_mask ( uint32_t  channel_mask)

Mark multiple dma channels as used.

Method for cooperative claiming of hardware. Will cause a panic if any of the channels are already claimed. Use of this method by libraries detects accidental configurations that would fail in unpredictable ways.

Parameters
channel_maskBitfield of all required channels to claim (bit 0 == channel 0, bit 1 == channel 1 etc)

◆ dma_claim_unused_channel()

int dma_claim_unused_channel ( bool  required)

Claim a free dma channel.

Parameters
requiredif true the function will panic if none are available
Returns
the dma channel number or -1 if required was false, and none were free

◆ dma_claim_unused_timer()

int dma_claim_unused_timer ( bool  required)

Claim a free dma timer.

Parameters
requiredif true the function will panic if none are available
Returns
the dma timer number or -1 if required was false, and none were free

◆ dma_get_timer_dreq()

static uint dma_get_timer_dreq ( uint  timer_num)
inlinestatic

Return the DREQ number for a given DMA timer.

Parameters
timer_numDMA timer number 0-3

◆ dma_irqn_acknowledge_channel()

static void dma_irqn_acknowledge_channel ( uint  irq_index,
uint  channel 
)
inlinestatic

Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_N.

Parameters
irq_indexthe IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1
channelDMA channel

◆ dma_irqn_get_channel_status()

static bool dma_irqn_get_channel_status ( uint  irq_index,
uint  channel 
)
inlinestatic

Determine if a particular channel is a cause of DMA_IRQ_N.

Parameters
irq_indexthe IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1
channelDMA channel
Returns
true if the channel is a cause of the DMA_IRQ_N, false otherwise

◆ dma_irqn_set_channel_enabled()

static void dma_irqn_set_channel_enabled ( uint  irq_index,
uint  channel,
bool  enabled 
)
inlinestatic

Enable single DMA channel interrupt on either DMA_IRQ_0 or DMA_IRQ_1.

Parameters
irq_indexthe IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1
channelDMA channel
enabledtrue to enable interrupt via irq_index for specified channel, false to disable.

◆ dma_irqn_set_channel_mask_enabled()

static void dma_irqn_set_channel_mask_enabled ( uint  irq_index,
uint32_t  channel_mask,
bool  enabled 
)
inlinestatic

Enable multiple DMA channels' interrupt via either DMA_IRQ_0 or DMA_IRQ_1.

Parameters
irq_indexthe IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1
channel_maskBitmask of all the channels to enable/disable. Channel 0 = bit 0, channel 1 = bit 1 etc.
enabledtrue to enable all the interrupts specified in the mask, false to disable all the interrupts specified in the mask.

◆ dma_set_irq0_channel_mask_enabled()

static void dma_set_irq0_channel_mask_enabled ( uint32_t  channel_mask,
bool  enabled 
)
inlinestatic

Enable multiple DMA channels' interrupts via DMA_IRQ_0.

Parameters
channel_maskBitmask of all the channels to enable/disable. Channel 0 = bit 0, channel 1 = bit 1 etc.
enabledtrue to enable all the interrupts specified in the mask, false to disable all the interrupts specified in the mask.

◆ dma_set_irq1_channel_mask_enabled()

static void dma_set_irq1_channel_mask_enabled ( uint32_t  channel_mask,
bool  enabled 
)
inlinestatic

Enable multiple DMA channels' interrupts via DMA_IRQ_1.

Parameters
channel_maskBitmask of all the channels to enable/disable. Channel 0 = bit 0, channel 1 = bit 1 etc.
enabledtrue to enable all the interrupts specified in the mask, false to disable all the interrupts specified in the mask.

◆ dma_sniffer_enable()

static void dma_sniffer_enable ( uint  channel,
uint  mode,
bool  force_channel_enable 
)
inlinestatic

Enable the DMA sniffing targeting the specified channel.

The mode can be one of the following:

Mode Function
0x0 Calculate a CRC-32 (IEEE802.3 polynomial)
0x1 Calculate a CRC-32 (IEEE802.3 polynomial) with bit reversed data
0x2 Calculate a CRC-16-CCITT
0x3 Calculate a CRC-16-CCITT with bit reversed data
0xe XOR reduction over all data. == 1 if the total 1 population count is odd.
0xf Calculate a simple 32-bit checksum (addition with a 32 bit accumulator)
Parameters
channelDMA channel
modeSee description
force_channel_enableSet true to also turn on sniffing in the channel configuration (this is usually what you want, but sometimes you might have a chain DMA with only certain segments of the chain sniffed, in which case you might pass false).

◆ dma_sniffer_get_data_accumulator()

static uint32_t dma_sniffer_get_data_accumulator ( void  )
inlinestatic

Get the sniffer's data accumulator value.

Read value calculated by the hardware from sniffing the DMA stream

◆ dma_sniffer_set_byte_swap_enabled()

static void dma_sniffer_set_byte_swap_enabled ( bool  swap)
inlinestatic

Enable the Sniffer byte swap function.

Locally perform a byte reverse on the sniffed data, before feeding into checksum.

Note that the sniff hardware is downstream of the DMA channel byteswap performed in the read master: if channel_config_set_bswap() and dma_sniffer_set_byte_swap_enabled() are both enabled, their effects cancel from the sniffer’s point of view.

Parameters
swapSet true to enable byte swapping

◆ dma_sniffer_set_data_accumulator()

static void dma_sniffer_set_data_accumulator ( uint32_t  seed_value)
inlinestatic

Set the sniffer's data accumulator with initial value.

Generally, CRC algorithms are used with the data accumulator initially seeded with 0xFFFF or 0xFFFFFFFF (for crc16 and crc32 algorithms)

Parameters
seed_valuevalue to set data accumulator

◆ dma_sniffer_set_output_invert_enabled()

static void dma_sniffer_set_output_invert_enabled ( bool  invert)
inlinestatic

Enable the Sniffer output invert function.

If enabled, the sniff data result appears bit-inverted when read. This does not affect the way the checksum is calculated.

Parameters
invertSet true to enable output bit inversion

◆ dma_sniffer_set_output_reverse_enabled()

static void dma_sniffer_set_output_reverse_enabled ( bool  reverse)
inlinestatic

Enable the Sniffer output bit reversal function.

If enabled, the sniff data result appears bit-reversed when read. This does not affect the way the checksum is calculated.

Parameters
reverseSet true to enable output bit reversal

◆ dma_start_channel_mask()

static void dma_start_channel_mask ( uint32_t  chan_mask)
inlinestatic

Start one or more channels simultaneously.

Parameters
chan_maskBitmask of all the channels requiring starting. Channel 0 = bit 0, channel 1 = bit 1 etc.

◆ dma_timer_claim()

void dma_timer_claim ( uint  timer)

Mark a dma timer as used.

Method for cooperative claiming of hardware. Will cause a panic if the timer is already claimed. Use of this method by libraries detects accidental configurations that would fail in unpredictable ways.

Parameters
timerthe dma timer

◆ dma_timer_is_claimed()

bool dma_timer_is_claimed ( uint  timer)

Determine if a dma timer is claimed.

Parameters
timerthe dma timer
Returns
true if the timer is claimed, false otherwise
See also
dma_timer_claim

◆ dma_timer_set_fraction()

static void dma_timer_set_fraction ( uint  timer,
uint16_t  numerator,
uint16_t  denominator 
)
inlinestatic

Set the divider for the given DMA timer.

The timer will run at the system_clock_freq * numerator / denominator, so this is the speed that data elements will be transferred at via a DMA channel using this timer as a DREQ

Parameters
timerthe dma timer
numeratorthe fraction's numerator
denominatorthe fraction's denominator

◆ dma_timer_unclaim()

void dma_timer_unclaim ( uint  timer)

Mark a dma timer as no longer used.

Method for cooperative claiming of hardware.

Parameters
timerthe dma timer to release

◆ dma_unclaim_mask()

void dma_unclaim_mask ( uint32_t  channel_mask)

Mark multiple dma channels as no longer used.

Parameters
channel_maskBitfield of all channels to unclaim (bit 0 == channel 0, bit 1 == channel 1 etc)