DMA Controller API. More...
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... | |
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:
|
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).
channel | DMA channel |
|
inlinestatic |
Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_0.
channel | DMA channel |
|
inlinestatic |
Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_1.
channel | DMA channel |
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.
channel | the dma channel |
|
inlinestatic |
Configure all DMA parameters and optionally start transfer.
channel | DMA channel |
config | Pointer to DMA config structure |
write_addr | Initial write address |
read_addr | Initial read address |
transfer_count | Number of transfers to perform |
trigger | True to start the transfer immediately |
|
inlinestatic |
Determine if a particular channel is a cause of DMA_IRQ_0.
channel | DMA channel |
|
inlinestatic |
Determine if a particular channel is a cause of DMA_IRQ_1.
channel | DMA channel |
|
inlinestatic |
Check if DMA channel is busy.
channel | DMA channel |
bool dma_channel_is_claimed | ( | uint | channel | ) |
Determine if a dma channel is claimed.
channel | the dma channel |
|
inlinestatic |
Set a channel configuration.
channel | DMA channel |
config | Pointer to a config structure with required configuration |
trigger | True to trigger the transfer immediately |
|
inlinestatic |
Enable single DMA channel's interrupt via DMA_IRQ_0.
channel | DMA channel |
enabled | true to enable interrupt 0 on specified channel, false to disable. |
|
inlinestatic |
Enable single DMA channel's interrupt via DMA_IRQ_1.
channel | DMA channel |
enabled | true to enable interrupt 1 on specified channel, false to disable. |
|
inlinestatic |
Set the DMA initial read address.
channel | DMA channel |
read_addr | Initial read address of transfer. |
trigger | True to start the transfer immediately |
|
inlinestatic |
Set the number of bus transfers the channel will do.
channel | DMA channel |
trans_count | The number of transfers (not NOT bytes, see channel_config_set_transfer_data_size) |
trigger | True to start the transfer immediately |
|
inlinestatic |
Set the DMA initial write address.
channel | DMA channel |
write_addr | Initial write address of transfer. |
trigger | True to start the transfer immediately |
|
inlinestatic |
Start a single DMA channel.
channel | DMA channel |
|
inlinestatic |
Start a DMA transfer from a buffer immediately.
channel | DMA channel |
read_addr | Sets the initial read address |
transfer_count | Number of transfers to make. Not bytes, but the number of transfers of channel_config_set_transfer_data_size() to be sent. |
|
inlinestatic |
Start a DMA transfer to a buffer immediately.
channel | DMA channel |
write_addr | Sets the initial write address |
transfer_count | Number of transfers to make. Not bytes, but the number of transfers of channel_config_set_transfer_data_size() to be sent. |
void dma_channel_unclaim | ( | uint | channel | ) |
Mark a dma channel as no longer used.
channel | the dma channel to release |
|
inlinestatic |
Wait for a DMA channel transfer to complete.
channel | DMA channel |
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.
channel_mask | Bitfield of all required channels to claim (bit 0 == channel 0, bit 1 == channel 1 etc) |
int dma_claim_unused_channel | ( | bool | required | ) |
Claim a free dma channel.
required | if true the function will panic if none are available |
int dma_claim_unused_timer | ( | bool | required | ) |
Claim a free dma timer.
required | if true the function will panic if none are available |
|
inlinestatic |
Return the DREQ number for a given DMA timer.
timer_num | DMA timer number 0-3 |
|
inlinestatic |
Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_N.
irq_index | the IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1 |
channel | DMA channel |
|
inlinestatic |
Determine if a particular channel is a cause of DMA_IRQ_N.
irq_index | the IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1 |
channel | DMA channel |
|
inlinestatic |
Enable single DMA channel interrupt on either DMA_IRQ_0 or DMA_IRQ_1.
irq_index | the IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1 |
channel | DMA channel |
enabled | true to enable interrupt via irq_index for specified channel, false to disable. |
|
inlinestatic |
Enable multiple DMA channels' interrupt via either DMA_IRQ_0 or DMA_IRQ_1.
irq_index | the IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1 |
channel_mask | Bitmask of all the channels to enable/disable. Channel 0 = bit 0, channel 1 = bit 1 etc. |
enabled | true to enable all the interrupts specified in the mask, false to disable all the interrupts specified in the mask. |
|
inlinestatic |
Enable multiple DMA channels' interrupts via DMA_IRQ_0.
channel_mask | Bitmask of all the channels to enable/disable. Channel 0 = bit 0, channel 1 = bit 1 etc. |
enabled | true to enable all the interrupts specified in the mask, false to disable all the interrupts specified in the mask. |
|
inlinestatic |
Enable multiple DMA channels' interrupts via DMA_IRQ_1.
channel_mask | Bitmask of all the channels to enable/disable. Channel 0 = bit 0, channel 1 = bit 1 etc. |
enabled | true to enable all the interrupts specified in the mask, false to disable all the interrupts specified in the mask. |
|
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) |
channel | DMA channel |
mode | See description |
force_channel_enable | Set 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). |
|
inlinestatic |
Get the sniffer's data accumulator value.
Read value calculated by the hardware from sniffing the DMA stream
|
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.
swap | Set true to enable byte swapping |
|
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)
seed_value | value to set data accumulator |
|
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.
invert | Set true to enable output bit inversion |
|
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.
reverse | Set true to enable output bit reversal |
|
inlinestatic |
Start one or more channels simultaneously.
chan_mask | Bitmask of all the channels requiring starting. Channel 0 = bit 0, channel 1 = bit 1 etc. |
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.
timer | the dma timer |
bool dma_timer_is_claimed | ( | uint | timer | ) |
Determine if a dma timer is claimed.
timer | the dma timer |
|
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
timer | the dma timer |
numerator | the fraction's numerator |
denominator | the fraction's denominator |
void dma_timer_unclaim | ( | uint | timer | ) |
Mark a dma timer as no longer used.
Method for cooperative claiming of hardware.
timer | the dma timer to release |
void dma_unclaim_mask | ( | uint32_t | channel_mask | ) |
Mark multiple dma channels as no longer used.
channel_mask | Bitfield of all channels to unclaim (bit 0 == channel 0, bit 1 == channel 1 etc) |