v1.5.0
Go to the documentation of this file.
7 #ifndef _HARDWARE_DMA_H
8 #define _HARDWARE_DMA_H
11 #include "hardware/structs/dma.h"
12 #include "hardware/regs/dreq.h"
13 #include "pico/assert.h"
38 #define DREQ_DMA_TIMER0 DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_TIMER0
39 #define DREQ_DMA_TIMER1 DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_TIMER1
40 #define DREQ_DMA_TIMER2 DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_TIMER2
41 #define DREQ_DMA_TIMER3 DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_TIMER3
42 #define DREQ_FORCE DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_PERMANENT
45 #ifndef PARAM_ASSERTIONS_ENABLED_DMA
46 #define PARAM_ASSERTIONS_ENABLED_DMA 0
49 static inline void check_dma_channel_param(__unused uint channel) {
50 #if PARAM_ASSERTIONS_ENABLED(DMA)
52 extern void check_dma_channel_param_impl(uint channel);
53 check_dma_channel_param_impl(channel);
57 static inline void check_dma_timer_param(__unused uint timer_num) {
58 valid_params_if(DMA, timer_num < NUM_DMA_TIMERS);
62 check_dma_channel_param(channel);
63 return &dma_hw->ch[channel];
151 c->ctrl = incr ? (c->ctrl | DMA_CH0_CTRL_TRIG_INCR_READ_BITS) : (c->ctrl & ~DMA_CH0_CTRL_TRIG_INCR_READ_BITS);
162 c->ctrl = incr ? (c->ctrl | DMA_CH0_CTRL_TRIG_INCR_WRITE_BITS) : (c->ctrl & ~DMA_CH0_CTRL_TRIG_INCR_WRITE_BITS);
181 assert(dreq <= DREQ_FORCE);
182 c->ctrl = (c->ctrl & ~DMA_CH0_CTRL_TRIG_TREQ_SEL_BITS) | (dreq << DMA_CH0_CTRL_TRIG_TREQ_SEL_LSB);
195 assert(chain_to <= NUM_DMA_CHANNELS);
196 c->ctrl = (c->ctrl & ~DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS) | (chain_to << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB);
210 c->ctrl = (c->ctrl & ~DMA_CH0_CTRL_TRIG_DATA_SIZE_BITS) | (((uint)size) << DMA_CH0_CTRL_TRIG_DATA_SIZE_LSB);
229 assert(size_bits < 32);
230 c->ctrl = (c->ctrl & ~(DMA_CH0_CTRL_TRIG_RING_SIZE_BITS | DMA_CH0_CTRL_TRIG_RING_SEL_BITS)) |
231 (size_bits << DMA_CH0_CTRL_TRIG_RING_SIZE_LSB) |
232 (write ? DMA_CH0_CTRL_TRIG_RING_SEL_BITS : 0);
245 c->ctrl = bswap ? (c->ctrl | DMA_CH0_CTRL_TRIG_BSWAP_BITS) : (c->ctrl & ~DMA_CH0_CTRL_TRIG_BSWAP_BITS);
259 c->ctrl = irq_quiet ? (c->ctrl | DMA_CH0_CTRL_TRIG_IRQ_QUIET_BITS) : (c->ctrl & ~DMA_CH0_CTRL_TRIG_IRQ_QUIET_BITS);
277 c->ctrl = high_priority ? (c->ctrl | DMA_CH0_CTRL_TRIG_HIGH_PRIORITY_BITS) : (c->ctrl & ~DMA_CH0_CTRL_TRIG_HIGH_PRIORITY_BITS);
292 c->ctrl = enable ? (c->ctrl | DMA_CH0_CTRL_TRIG_EN_BITS) : (c->ctrl & ~DMA_CH0_CTRL_TRIG_EN_BITS);
304 c->ctrl = sniff_enable ? (c->ctrl | DMA_CH0_CTRL_TRIG_SNIFF_EN_BITS) : (c->ctrl &
305 ~DMA_CH0_CTRL_TRIG_SNIFF_EN_BITS);
352 c.ctrl = dma_channel_hw_addr(channel)->ctrl_trig;
391 dma_channel_hw_addr(channel)->read_addr = (uintptr_t) read_addr;
393 dma_channel_hw_addr(channel)->al3_read_addr_trig = (uintptr_t) read_addr;
406 dma_channel_hw_addr(channel)->write_addr = (uintptr_t) write_addr;
408 dma_channel_hw_addr(channel)->al2_write_addr_trig = (uintptr_t) write_addr;
421 dma_channel_hw_addr(channel)->transfer_count = trans_count;
423 dma_channel_hw_addr(channel)->al1_transfer_count_trig = trans_count;
438 const volatile void *read_addr,
439 uint transfer_count,
bool trigger) {
454 const volatile void *read_addr,
455 uint32_t transfer_count) {
458 hw->read_addr = (uintptr_t) read_addr;
459 hw->al1_transfer_count_trig = transfer_count;
471 hw->write_addr = (uintptr_t) write_addr;
472 hw->al1_transfer_count_trig = transfer_count;
481 valid_params_if(DMA, chan_mask && chan_mask < (1u << NUM_DMA_CHANNELS));
482 dma_hw->multi_channel_trigger = chan_mask;
528 check_dma_channel_param(channel);
529 dma_hw->abort = 1u << channel;
542 check_dma_channel_param(channel);
543 check_hw_layout(
dma_hw_t, inte0, DMA_INTE0_OFFSET);
571 check_dma_channel_param(channel);
572 check_hw_layout(
dma_hw_t, inte1, DMA_INTE1_OFFSET);
601 invalid_params_if(DMA, irq_index > 1);
617 invalid_params_if(DMA, irq_index > 1);
632 check_dma_channel_param(channel);
633 return dma_hw->ints0 & (1u << channel);
643 check_dma_channel_param(channel);
644 return dma_hw->ints1 & (1u << channel);
655 invalid_params_if(DMA, irq_index > 1);
656 check_dma_channel_param(channel);
657 return (irq_index ? dma_hw->ints1 : dma_hw->ints0) & (1u << channel);
666 check_dma_channel_param(channel);
667 dma_hw->ints0 = 1u << channel;
676 check_dma_channel_param(channel);
677 dma_hw->ints1 = 1u << channel;
687 invalid_params_if(DMA, irq_index > 1);
688 check_dma_channel_param(channel);
690 dma_hw->ints1 = 1u << channel;
692 dma_hw->ints0 = 1u << channel;
702 check_dma_channel_param(channel);
703 return !!(dma_hw->ch[channel].al1_ctrl & DMA_CH0_CTRL_TRIG_BUSY_BITS);
738 check_dma_channel_param(channel);
739 check_hw_layout(
dma_hw_t, sniff_ctrl, DMA_SNIFF_CTRL_OFFSET);
740 if (force_channel_enable) {
741 hw_set_bits(&dma_hw->ch[channel].al1_ctrl, DMA_CH0_CTRL_TRIG_SNIFF_EN_BITS);
744 (((channel << DMA_SNIFF_CTRL_DMACH_LSB) & DMA_SNIFF_CTRL_DMACH_BITS) |
745 ((mode << DMA_SNIFF_CTRL_CALC_LSB) & DMA_SNIFF_CTRL_CALC_BITS) |
746 DMA_SNIFF_CTRL_EN_BITS),
747 (DMA_SNIFF_CTRL_DMACH_BITS |
748 DMA_SNIFF_CTRL_CALC_BITS |
749 DMA_SNIFF_CTRL_EN_BITS));
765 hw_set_bits(&dma_hw->sniff_ctrl, DMA_SNIFF_CTRL_BSWAP_BITS);
767 hw_clear_bits(&dma_hw->sniff_ctrl, DMA_SNIFF_CTRL_BSWAP_BITS);
780 hw_set_bits(&dma_hw->sniff_ctrl, DMA_SNIFF_CTRL_OUT_INV_BITS);
782 hw_clear_bits(&dma_hw->sniff_ctrl, DMA_SNIFF_CTRL_OUT_INV_BITS);
795 hw_set_bits(&dma_hw->sniff_ctrl, DMA_SNIFF_CTRL_OUT_REV_BITS);
797 hw_clear_bits(&dma_hw->sniff_ctrl, DMA_SNIFF_CTRL_OUT_REV_BITS);
805 dma_hw->sniff_ctrl = 0;
817 dma_hw->sniff_data = seed_value;
826 return dma_hw->sniff_data;
877 check_dma_timer_param(timer);
878 dma_hw->timer[timer] = (((uint32_t)numerator) << DMA_TIMER0_X_LSB) | (((uint32_t)denominator) << DMA_TIMER0_Y_LSB);
887 static_assert(DREQ_DMA_TIMER1 == DREQ_DMA_TIMER0 + 1,
"");
888 static_assert(DREQ_DMA_TIMER2 == DREQ_DMA_TIMER0 + 2,
"");
889 static_assert(DREQ_DMA_TIMER3 == DREQ_DMA_TIMER0 + 3,
"");
890 check_dma_timer_param(timer_num);
891 return DREQ_DMA_TIMER0 + timer_num;
int dma_claim_unused_channel(bool required)
Claim a free dma channel.
Definition: dma.c:45
static void dma_sniffer_enable(uint channel, uint mode, bool force_channel_enable)
Enable the DMA sniffing targeting the specified channel.
Definition: dma.h:737
static __force_inline void hw_clear_bits(io_rw_32 *addr, uint32_t mask)
Atomically clear the specified bits to 0 in a HW register.
Definition: address_mapped.h:131
static void dma_channel_set_write_addr(uint channel, volatile void *write_addr, bool trigger)
Set the DMA initial write address.
Definition: dma.h:404
static void dma_set_irq1_channel_mask_enabled(uint32_t channel_mask, bool enabled)
Enable multiple DMA channels' interrupts via DMA_IRQ_1.
Definition: dma.h:585
static bool dma_channel_is_busy(uint channel)
Check if DMA channel is busy.
Definition: dma.h:701
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.
Definition: dma.h:600
dma_channel_transfer_size
Enumeration of available DMA channel transfer sizes.
Definition: dma.h:133
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.
Definition: dma.h:469
static void dma_channel_set_irq1_enabled(uint channel, bool enabled)
Enable single DMA channel's interrupt via DMA_IRQ_1.
Definition: dma.h:570
static void dma_start_channel_mask(uint32_t chan_mask)
Start one or more channels simultaneously.
Definition: dma.h:480
static void dma_channel_acknowledge_irq1(uint channel)
Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_1.
Definition: dma.h:675
static void dma_channel_set_read_addr(uint channel, const volatile void *read_addr, bool trigger)
Set the DMA initial read address.
Definition: dma.h:389
static uint32_t dma_sniffer_get_data_accumulator(void)
Get the sniffer's data accumulator value.
Definition: dma.h:825
static void channel_config_set_high_priority(dma_channel_config *c, bool high_priority)
Set the channel priority in a channel configuration object.
Definition: dma.h:276
static void dma_set_irq0_channel_mask_enabled(uint32_t channel_mask, bool enabled)
Enable multiple DMA channels' interrupts via DMA_IRQ_0.
Definition: dma.h:556
static void dma_sniffer_set_output_invert_enabled(bool invert)
Enable the Sniffer output invert function.
Definition: dma.h:778
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.
Definition: dma.h:437
static __force_inline void hw_write_masked(io_rw_32 *addr, uint32_t values, uint32_t write_mask)
Set new values for a sub-set of the bits in a HW register.
Definition: address_mapped.h:157
void dma_channel_claim(uint channel)
Mark a dma channel as used.
Definition: dma.c:23
static void dma_sniffer_set_byte_swap_enabled(bool swap)
Enable the Sniffer byte swap function.
Definition: dma.h:763
int dma_claim_unused_timer(bool required)
Claim a free dma timer.
Definition: dma.c:64
static void dma_sniffer_set_data_accumulator(uint32_t seed_value)
Set the sniffer's data accumulator with initial value.
Definition: dma.h:816
@ DMA_SIZE_8
Byte transfer (8 bits)
Definition: dma.h:134
static bool dma_irqn_get_channel_status(uint irq_index, uint channel)
Determine if a particular channel is a cause of DMA_IRQ_N.
Definition: dma.h:654
static void channel_config_set_irq_quiet(dma_channel_config *c, bool irq_quiet)
Set IRQ quiet mode in a channel configuration object.
Definition: dma.h:258
static void dma_channel_wait_for_finish_blocking(uint channel)
Wait for a DMA channel transfer to complete.
Definition: dma.h:711
static void channel_config_set_sniff_enable(dma_channel_config *c, bool sniff_enable)
Enable access to channel by sniff hardware in a channel configuration object.
Definition: dma.h:303
static void channel_config_set_bswap(dma_channel_config *c, bool bswap)
Set DMA byte swapping config in a channel configuration object.
Definition: dma.h:244
static __force_inline void hw_set_bits(io_rw_32 *addr, uint32_t mask)
Atomically set the specified bits to 1 in a HW register.
Definition: address_mapped.h:121
static void channel_config_set_dreq(dma_channel_config *c, uint dreq)
Select a transfer request signal in a channel configuration object.
Definition: dma.h:180
void dma_unclaim_mask(uint32_t channel_mask)
Mark multiple dma channels as no longer used.
Definition: dma.c:39
static void dma_sniffer_set_output_reverse_enabled(bool reverse)
Enable the Sniffer output bit reversal function.
Definition: dma.h:793
static void dma_channel_start(uint channel)
Start a single DMA channel.
Definition: dma.h:490
static void channel_config_set_write_increment(dma_channel_config *c, bool incr)
Set DMA channel write increment in a channel configuration object.
Definition: dma.h:161
bool dma_channel_is_claimed(uint channel)
Determine if a dma channel is claimed.
Definition: dma.c:49
void dma_channel_unclaim(uint channel)
Mark a dma channel as no longer used.
Definition: dma.c:34
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.
Definition: dma.h:419
static void channel_config_set_ring(dma_channel_config *c, bool write, uint size_bits)
Set address wrapping parameters in a channel configuration object.
Definition: dma.h:228
static void dma_irqn_acknowledge_channel(uint irq_index, uint channel)
Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_N.
Definition: dma.h:686
static void dma_channel_abort(uint channel)
Stop a DMA transfer.
Definition: dma.h:527
static void channel_config_set_read_increment(dma_channel_config *c, bool incr)
Set DMA channel read increment in a channel configuration object.
Definition: dma.h:150
static dma_channel_config dma_channel_get_default_config(uint channel)
Get the default channel configuration for a given channel.
Definition: dma.h:328
static dma_channel_config dma_get_channel_config(uint channel)
Get the current configuration for the specified channel.
Definition: dma.h:350
bool dma_timer_is_claimed(uint timer)
Determine if a dma timer is claimed.
Definition: dma.c:68
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 bool dma_channel_get_irq1_status(uint channel)
Determine if a particular channel is a cause of DMA_IRQ_1.
Definition: dma.h:642
@ DMA_SIZE_32
Word transfer (32 bits)
Definition: dma.h:136
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.
Definition: dma.h:453
static void dma_timer_set_fraction(uint timer, uint16_t numerator, uint16_t denominator)
Set the divider for the given DMA timer.
Definition: dma.h:876
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.
Definition: dma.h:616
static bool dma_channel_get_irq0_status(uint channel)
Determine if a particular channel is a cause of DMA_IRQ_0.
Definition: dma.h:631
static void dma_sniffer_disable(void)
Disable the DMA sniffer.
Definition: dma.h:804
@ DMA_SIZE_16
Half word transfer (16 bits)
Definition: dma.h:135
void dma_timer_claim(uint timer)
Mark a dma timer as used.
Definition: dma.c:54
static void dma_channel_set_config(uint channel, const dma_channel_config *config, bool trigger)
Set a channel configuration.
Definition: dma.h:373
static void channel_config_set_transfer_data_size(dma_channel_config *c, enum dma_channel_transfer_size size)
Set the size of each DMA bus transfer in a channel configuration object.
Definition: dma.h:208
static uint32_t channel_config_get_ctrl_value(const dma_channel_config *config)
Get the raw configuration register from a channel configuration.
Definition: dma.h:362
static void channel_config_set_chain_to(dma_channel_config *c, uint chain_to)
Set DMA channel chain_to channel in a channel configuration object.
Definition: dma.h:194
static void channel_config_set_enable(dma_channel_config *c, bool enable)
Enable/Disable the DMA channel in a channel configuration object.
Definition: dma.h:291
void dma_timer_unclaim(uint timer)
Mark a dma timer as no longer used.
Definition: dma.c:59
static uint dma_get_timer_dreq(uint timer_num)
Return the DREQ number for a given DMA timer.
Definition: dma.h:886
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
void dma_claim_mask(uint32_t channel_mask)
Mark multiple dma channels as used.
Definition: dma.c:28