dma.h

Direct Memory Access (DMA) support.

Types

struct dma_reg_map

DMA register map type.

Note that DMA controller 2 (register map base pointer DMA2_BASE) only supports channels 1–5.

Public Members
__io uint32 ISR

Interrupt status register.

__io uint32 IFCR

Interrupt flag clear register.

__io uint32 CCR1

Channel 1 configuration register.

__io uint32 CNDTR1

Channel 1 number of data register.

__io uint32 CPAR1

Channel 1 peripheral address register.

__io uint32 CMAR1

Channel 1 memory address register.

const uint32 RESERVED1

Reserved.

__io uint32 CCR2

Channel 2 configuration register.

__io uint32 CNDTR2

Channel 2 number of data register.

__io uint32 CPAR2

Channel 2 peripheral address register.

__io uint32 CMAR2

Channel 2 memory address register.

const uint32 RESERVED2

Reserved.

__io uint32 CCR3

Channel 3 configuration register.

__io uint32 CNDTR3

Channel 3 number of data register.

__io uint32 CPAR3

Channel 3 peripheral address register.

__io uint32 CMAR3

Channel 3 memory address register.

const uint32 RESERVED3

Reserved.

__io uint32 CCR4

Channel 4 configuration register.

__io uint32 CNDTR4

Channel 4 number of data register.

__io uint32 CPAR4

Channel 4 peripheral address register.

__io uint32 CMAR4

Channel 4 memory address register.

const uint32 RESERVED4

Reserved.

__io uint32 CCR5

Channel 5 configuration register.

__io uint32 CNDTR5

Channel 5 number of data register.

__io uint32 CPAR5

Channel 5 peripheral address register.

__io uint32 CMAR5

Channel 5 memory address register.

const uint32 RESERVED5

Reserved.

__io uint32 CCR6

Channel 6 configuration register.

__io uint32 CNDTR6

Channel 6 number of data register.

__io uint32 CPAR6

Channel 6 peripheral address register.

__io uint32 CMAR6

Channel 6 memory address register.

const uint32 RESERVED6

Reserved.

__io uint32 CCR7

Channel 7 configuration register.

__io uint32 CNDTR7

Channel 7 number of data register.

__io uint32 CPAR7

Channel 7 peripheral address register.

__io uint32 CMAR7

Channel 7 memory address register.

const uint32 RESERVED7

Reserved.

struct dma_dev

DMA device type.

Public Members
dma_reg_map * regs

Register map.

rcc_clk_id clk_id

Clock ID.

dma_handler_config handlers[]

IRQ handlers and NVIC numbers.

See:

dma_attach_interrupt()

dma_detach_interrupt()

struct dma_handler_config

Encapsulates state related to a DMA channel interrupt.

Public Members
void(* handler)(void)

User-specified channel interrupt handler.

nvic_irq_num irq_line

Channel’s NVIC interrupt number.

dma_mode_flags enum

Flags for DMA transfer configuration.

Values:

  • DMA_MEM_2_MEM = 1 << 14 -

    Memory to memory mode.

  • DMA_MINC_MODE = 1 << 7 -

    Auto-increment memory address.

  • DMA_PINC_MODE = 1 << 6 -

    Auto-increment peripheral address.

  • DMA_CIRC_MODE = 1 << 5 -

    Circular mode.

  • DMA_FROM_MEM = 1 << 4 -

    Read from memory to peripheral.

  • DMA_TRNS_ERR = 1 << 3 -

    Interrupt on transfer error.

  • DMA_HALF_TRNS = 1 << 2 -

    Interrupt on half-transfer.

  • DMA_TRNS_CMPLT = 1 << 1 -

    Interrupt on transfer completion.

dma_xfer_size enum

Source and destination transfer sizes.

Values:

  • DMA_SIZE_8BITS = 0 -

    8-bit transfers

  • DMA_SIZE_16BITS = 1 -

    16-bit transfers

  • DMA_SIZE_32BITS = 2 -

    32-bit transfers

dma_channel enum

DMA channel.

Values:

  • DMA_CH1 = 1 -

    Channel 1.

  • DMA_CH2 = 2 -

    Channel 2.

  • DMA_CH3 = 3 -

    Channel 3.

  • DMA_CH4 = 4 -

    Channel 4.

  • DMA_CH5 = 5 -

    Channel 5.

  • DMA_CH6 = 6 -

    Channel 6.

  • DMA_CH7 = 7 -

    Channel 7.

dma_priority enum

DMA transfer priority.

Values:

  • DMA_PRIORITY_LOW = DMA_CCR_PL_LOW -

    Low priority.

  • DMA_PRIORITY_MEDIUM = DMA_CCR_PL_MEDIUM -

    Medium priority.

  • DMA_PRIORITY_HIGH = DMA_CCR_PL_HIGH -

    High priority.

  • DMA_PRIORITY_VERY_HIGH = DMA_CCR_PL_VERY_HIGH -

    Very high priority.

dma_irq_cause enum

Encodes the reason why a DMA interrupt was called.

See:dma_get_irq_cause()

Values:

  • DMA_TRANSFER_COMPLETE -

    Transfer is complete.

  • DMA_TRANSFER_HALF_COMPLETE -

    Transfer is half complete.

  • DMA_TRANSFER_ERROR -

    Error occurred during transfer.

struct dma_channel_reg_map

DMA channel register map type.

Provides access to an individual channel’s registers.

Public Members
__io uint32 CCR

Channel configuration register.

__io uint32 CNDTR

Channel number of data register.

__io uint32 CPAR

Channel peripheral address register.

__io uint32 CMAR

Channel memory address register.

Devices

dma_dev * DMA1

DMA1 device.

dma_dev * DMA2

DMA2 device.

Functions

void dma_init(dma_dev * dev)

Initialize a DMA device.

Parameters:
  • dev -

    Device to initialize.

void dma_setup_transfer(dma_dev * dev, dma_channel channel, __io void * peripheral_address, dma_xfer_size peripheral_size, __io void * memory_address, dma_xfer_size memory_size, uint32 mode)

Set up a DMA transfer.

The channel will be disabled before being reconfigured. The transfer will have low priority by default. You may choose another priority before the transfer begins using dma_set_priority(), as well as performing any other configuration you desire. When the channel is configured to your liking, enable it using dma_enable().

Parameters:
  • dev -

    DMA device.

  • channel -

    DMA channel.

  • peripheral_address -

    Base address of peripheral data register involved in the transfer.

  • peripheral_size -

    Peripheral data transfer size.

  • memory_address -

    Base memory address involved in the transfer.

  • memory_size -

    Memory data transfer size.

  • mode -

    Logical OR of dma_mode_flags

Side Effects::

Disables the given DMA channel.

See:

dma_xfer_size

dma_mode_flags

dma_set_num_transfers()

dma_set_priority()

dma_attach_interrupt()

dma_enable()

void dma_set_num_transfers(dma_dev * dev, dma_channel channel, uint16 num_transfers)

Set the number of data to be transferred on a DMA channel.

You may not call this function while the channel is enabled.

Parameters:
  • dev -

    DMA device

  • channel -

    Channel through which the transfer occurs.

  • num_transfers -

void dma_set_priority(dma_dev * dev, dma_channel channel, dma_priority priority)

Set the priority of a DMA transfer.

You may not call this function while the channel is enabled.

Parameters:
  • dev -

    DMA device

  • channel -

    DMA channel

  • priority -

    priority to set.

void dma_attach_interrupt(dma_dev * dev, dma_channel channel, void(*)(void) handler)

Attach an interrupt to a DMA transfer.

Interrupts are enabled using appropriate mode flags in dma_setup_transfer().

Parameters:
  • dev -

    DMA device

  • channel -

    Channel to attach handler to

  • handler -

    Interrupt handler to call when channel interrupt fires.

See:

dma_setup_transfer()

dma_get_irq_cause()

dma_detach_interrupt()

void dma_detach_interrupt(dma_dev * dev, dma_channel channel)

Detach a DMA transfer interrupt handler.

After calling this function, the given channel’s interrupts will be disabled.

Parameters:
  • dev -

    DMA device

  • channel -

    Channel whose handler to detach

Side Effects::

Clears interrupt enable bits in the channel’s CCR register.

See:

dma_attach_interrupt()

dma_irq_cause dma_get_irq_cause(dma_dev * dev, dma_channel channel)

Discover the reason why a DMA interrupt was called.

You may only call this function within an attached interrupt handler for the given channel.

This function resets the internal DMA register state which encodes the cause of the interrupt; consequently, it can only be called once per interrupt handler invocation.

Parameters:
  • dev -

    DMA device

  • channel -

    Channel whose interrupt is being handled.

Return:

Reason why the interrupt fired.

Side Effects::

Clears channel status flags in dev->regs->ISR.

See:

dma_attach_interrupt()

dma_irq_cause

void dma_enable(dma_dev * dev, dma_channel channel)

Enable a DMA channel.

Parameters:
  • dev -

    DMA device

  • channel -

    Channel to enable

void dma_disable(dma_dev * dev, dma_channel channel)

Disable a DMA channel.

Parameters:
  • dev -

    DMA device

  • channel -

    Channel to disable

void dma_set_mem_addr(dma_dev * dev, dma_channel channel, __io void * addr)

Set the base memory address where data will be read from or written to.

You must not call this function while the channel is enabled.

If the DMA memory size is 16 bits, the address is automatically aligned to a half-word. If the DMA memory size is 32 bits, the address is aligned to a word.

Parameters:
  • dev -

    DMA Device

  • channel -

    Channel whose base memory address to set.

  • addr -

    Memory base address to use.

void dma_set_per_addr(dma_dev * dev, dma_channel channel, __io void * addr)

Set the base peripheral address where data will be read from or written to.

You must not call this function while the channel is enabled.

If the DMA peripheral size is 16 bits, the address is automatically aligned to a half-word. If the DMA peripheral size is 32 bits, the address is aligned to a word.

Parameters:
  • dev -

    DMA Device

  • channel -

    Channel whose peripheral data register base address to set.

  • addr -

    Peripheral memory base address to use.

dma_channel_reg_map * dma_channel_regs(dma_dev * dev, dma_channel channel)

Obtain a pointer to an individual DMA channel’s registers.

For example, dma_channel_regs(DMA1, DMA_CH1)->CCR is DMA1_BASE->CCR1.

Parameters:
  • dev -

    DMA device

  • channel -

    DMA channel whose channel register map to obtain.

uint8 dma_is_channel_enabled(dma_dev * dev, dma_channel channel)

Check if a DMA channel is enabled.

Parameters:
  • dev -

    DMA device

  • channel -

    Channel whose enabled bit to check.

uint8 dma_get_isr_bits(dma_dev * dev, dma_channel channel)

Get the ISR status bits for a DMA channel.

The bits are returned right-aligned, in the following order: transfer error flag, half-transfer flag, transfer complete flag, global interrupt flag.

If you’re attempting to figure out why a DMA interrupt fired; you may find dma_get_irq_cause() more convenient.

Parameters:
  • dev -

    DMA device

  • channel -

    Channel whose ISR bits to return.

See:

dma_get_irq_cause().

void dma_clear_isr_bits(dma_dev * dev, dma_channel channel)

Clear the ISR status bits for a given DMA channel.

If you’re attempting to clean up after yourself in a DMA interrupt, you may find dma_get_irq_cause() more convenient.

Parameters:
  • dev -

    DMA device

  • channel -

    Channel whose ISR bits to clear.

See:

dma_get_irq_cause()

Register Map Base Pointers

DMA1_BASE

DMA controller 1 register map base pointer.

DMA2_BASE

DMA controller 2 register map base pointer.

Register Bit Definitions

Interrupt status register

DMA_ISR_TEIF7_BIT

DMA_ISR_HTIF7_BIT

DMA_ISR_TCIF7_BIT

DMA_ISR_GIF7_BIT

DMA_ISR_TEIF6_BIT

DMA_ISR_HTIF6_BIT

DMA_ISR_TCIF6_BIT

DMA_ISR_GIF6_BIT

DMA_ISR_TEIF5_BIT

DMA_ISR_HTIF5_BIT

DMA_ISR_TCIF5_BIT

DMA_ISR_GIF5_BIT

DMA_ISR_TEIF4_BIT

DMA_ISR_HTIF4_BIT

DMA_ISR_TCIF4_BIT

DMA_ISR_GIF4_BIT

DMA_ISR_TEIF3_BIT

DMA_ISR_HTIF3_BIT

DMA_ISR_TCIF3_BIT

DMA_ISR_GIF3_BIT

DMA_ISR_TEIF2_BIT

DMA_ISR_HTIF2_BIT

DMA_ISR_TCIF2_BIT

DMA_ISR_GIF2_BIT

DMA_ISR_TEIF1_BIT

DMA_ISR_HTIF1_BIT

DMA_ISR_TCIF1_BIT

DMA_ISR_GIF1_BIT

DMA_ISR_TEIF7

DMA_ISR_HTIF7

DMA_ISR_TCIF7

DMA_ISR_GIF7

DMA_ISR_TEIF6

DMA_ISR_HTIF6

DMA_ISR_TCIF6

DMA_ISR_GIF6

DMA_ISR_TEIF5

DMA_ISR_HTIF5

DMA_ISR_TCIF5

DMA_ISR_GIF5

DMA_ISR_TEIF4

DMA_ISR_HTIF4

DMA_ISR_TCIF4

DMA_ISR_GIF4

DMA_ISR_TEIF3

DMA_ISR_HTIF3

DMA_ISR_TCIF3

DMA_ISR_GIF3

DMA_ISR_TEIF2

DMA_ISR_HTIF2

DMA_ISR_TCIF2

DMA_ISR_GIF2

DMA_ISR_TEIF1

DMA_ISR_HTIF1

DMA_ISR_TCIF1

DMA_ISR_GIF1

Interrupt flag clear register

DMA_IFCR_CTEIF7_BIT

DMA_IFCR_CHTIF7_BIT

DMA_IFCR_CTCIF7_BIT

DMA_IFCR_CGIF7_BIT

DMA_IFCR_CTEIF6_BIT

DMA_IFCR_CHTIF6_BIT

DMA_IFCR_CTCIF6_BIT

DMA_IFCR_CGIF6_BIT

DMA_IFCR_CTEIF5_BIT

DMA_IFCR_CHTIF5_BIT

DMA_IFCR_CTCIF5_BIT

DMA_IFCR_CGIF5_BIT

DMA_IFCR_CTEIF4_BIT

DMA_IFCR_CHTIF4_BIT

DMA_IFCR_CTCIF4_BIT

DMA_IFCR_CGIF4_BIT

DMA_IFCR_CTEIF3_BIT

DMA_IFCR_CHTIF3_BIT

DMA_IFCR_CTCIF3_BIT

DMA_IFCR_CGIF3_BIT

DMA_IFCR_CTEIF2_BIT

DMA_IFCR_CHTIF2_BIT

DMA_IFCR_CTCIF2_BIT

DMA_IFCR_CGIF2_BIT

DMA_IFCR_CTEIF1_BIT

DMA_IFCR_CHTIF1_BIT

DMA_IFCR_CTCIF1_BIT

DMA_IFCR_CGIF1_BIT

DMA_IFCR_CTEIF7

DMA_IFCR_CHTIF7

DMA_IFCR_CTCIF7

DMA_IFCR_CGIF7

DMA_IFCR_CTEIF6

DMA_IFCR_CHTIF6

DMA_IFCR_CTCIF6

DMA_IFCR_CGIF6

DMA_IFCR_CTEIF5

DMA_IFCR_CHTIF5

DMA_IFCR_CTCIF5

DMA_IFCR_CGIF5

DMA_IFCR_CTEIF4

DMA_IFCR_CHTIF4

DMA_IFCR_CTCIF4

DMA_IFCR_CGIF4

DMA_IFCR_CTEIF3

DMA_IFCR_CHTIF3

DMA_IFCR_CTCIF3

DMA_IFCR_CGIF3

DMA_IFCR_CTEIF2

DMA_IFCR_CHTIF2

DMA_IFCR_CTCIF2

DMA_IFCR_CGIF2

DMA_IFCR_CTEIF1

DMA_IFCR_CHTIF1

DMA_IFCR_CTCIF1

DMA_IFCR_CGIF1

Channel configuration register

DMA_CCR_MEM2MEM_BIT

DMA_CCR_MINC_BIT

DMA_CCR_PINC_BIT

DMA_CCR_CIRC_BIT

DMA_CCR_DIR_BIT

DMA_CCR_TEIE_BIT

DMA_CCR_HTIE_BIT

DMA_CCR_TCIE_BIT

DMA_CCR_EN_BIT

DMA_CCR_MEM2MEM

DMA_CCR_PL

DMA_CCR_PL_LOW

DMA_CCR_PL_MEDIUM

DMA_CCR_PL_HIGH

DMA_CCR_PL_VERY_HIGH

DMA_CCR_MSIZE

DMA_CCR_MSIZE_8BITS

DMA_CCR_MSIZE_16BITS

DMA_CCR_MSIZE_32BITS

DMA_CCR_PSIZE

DMA_CCR_PSIZE_8BITS

DMA_CCR_PSIZE_16BITS

DMA_CCR_PSIZE_32BITS

DMA_CCR_MINC

DMA_CCR_PINC

DMA_CCR_CIRC

DMA_CCR_DIR

DMA_CCR_TEIE

DMA_CCR_HTIE

DMA_CCR_TCIE

DMA_CCR_EN