08531fb561
This information is all STM32F1 only. Signed-off-by: Marti Bolivar <mbolivar@leaflabs.com>
100 lines
3.6 KiB
Plaintext
100 lines
3.6 KiB
Plaintext
DMA Notes
|
|
=========
|
|
|
|
Medium-density devices have one DMA controller, DMA1. High-density
|
|
devices and up also have DMA2. DMA1 has 7 channels; DMA2 has 5. Each
|
|
channel multiplexes DMA requests from various peripherals, like so:
|
|
|
|
Channel Capabilities
|
|
--------------------
|
|
|
|
DMA1:
|
|
|
|
* Channel 1: ADC1, TIM2_CH3, TIM4_CH1
|
|
* Channel 2: USART3_TX, TIM1_CH1, TIM2_UP, TIM3_CH3, SPI1_RX
|
|
* Channel 3: USART3_RX, TIM1_CH2, TIM3_CH4, TIM3_UP, SPI1_TX
|
|
* Channel 4: USART1_TX, TIM1_CH4, TIM1_TRIG, TIM1_COM, TIM4_CH2,
|
|
SPI2/I2S2_RX, I2C2_TX
|
|
* Channel 5: USART1_RX, TIM1_UP, TIM2_CH1, TIM4_CH3,
|
|
SPI2/I2S2_TX, I2C2_RX
|
|
* Channel 6: USART2_RX, TIM1_CH3, TIM3_CH1, TIM3_TRIG, I2C1_TX
|
|
* Channel 7: USART2_TX, TIM2_CH2, TIM2_CH4, TIM4_UP, I2C1_RX
|
|
|
|
DMA2:
|
|
|
|
* Channel 1: TIM5_CH4, TIM5_TRIG, TIM8_CH3, TIM8_UP, SPI/I2S3_RX
|
|
* Channel 2: TIM8_CH4, TIM8_TRIG, TIM8_COM, TIM5_CH3, TIM5_UP, SPI/I2S3_TX
|
|
* Channel 3: TIM8_CH1, UART4_RX, TIM6_UP/DAC_CH1
|
|
* Channel 4: TIM5_CH2, SDIO, TIM7_UP/DAC_CH2
|
|
* Channel 5: ADC3, TIM8_CH2, TIM5_CH1, UART4_TX
|
|
|
|
An example usage: via DMA1, channel 1, you can have ADC1 periodically
|
|
dump converted data into an array in memory. The DMA controller can
|
|
then interrupt you when the array is half-full and full, and if any
|
|
error occurred.
|
|
|
|
Since channels are multiplexed in hardware, you can't simultaneously
|
|
use the same DMA channel to serve requests from two of its peripherals
|
|
at the same time. For example, if you are using DMA 1 channel 1 to
|
|
serve DMA requests from ADC1, you can't also serve requests from Timer
|
|
2 channel 3.
|
|
|
|
Channel Priority
|
|
----------------
|
|
|
|
An arbiter prioritizes simultaneous channel DMA requests. Channel
|
|
priority levels are configurable (4 levels of priority). Ties within
|
|
a DMA controller are broken by choosing the lower channel number;
|
|
between the controllers, DMA1 has higher priority than DMA2.
|
|
|
|
Interrupts
|
|
----------
|
|
|
|
You can cause an interrupt to fire once half the transfers are
|
|
complete, when all the transfers are complete, if an error occurs
|
|
during transfer, or any combination of the three.
|
|
|
|
If an error occurs, the transfer is automatically disabled.
|
|
|
|
Configuration
|
|
-------------
|
|
|
|
In order to configure a DMA transfer for DMA controller n, channel x,
|
|
ST RM0008 says you should do the following:
|
|
|
|
A. Set the peripheral register address in DMAn_BASE->CPARx.
|
|
B. Set the memory address in DMAn_BASE->CMARx.
|
|
C. Set the number of data to be transferred in DMAn_BASE->CNDTRx.
|
|
D. Set the channel priority via the PL bits in DMAn_BASE->CCRx.
|
|
E. Configure various other things (e.g. data transfer sizes, what
|
|
events cause channel interrupts) in DMAn_BASE->CCRx as desired.
|
|
F. Activate the channel by setting ENABLE bit in DMAn_BASE->CCRx.
|
|
|
|
The channel will start serving DMA requests as soon as it's activated.
|
|
|
|
The DMA library lets you accomplish these tasks as follows:
|
|
|
|
**Setup transfer**
|
|
|
|
Do (A), (B), and (E) using dma_setup_transfer().
|
|
|
|
This also does (D), but chooses the lowest priority by default.
|
|
|
|
**Perform any other desired configuration**
|
|
|
|
You can do (C) using dma_set_num_transfers().
|
|
|
|
You can do (D) using dma_set_priority().
|
|
|
|
You can attach interrupt handlers with dma_attach_interrupt().
|
|
|
|
**Activate the channel**
|
|
|
|
Do (F) with dma_enable().
|
|
|
|
Once you're all done, you can dma_disable() the channel. If you
|
|
dma_detach_interrupt() an interrupt handler, the channel interrupts
|
|
will stop firing, but the transfer itself won't stop until it's done
|
|
(which never happens if you set the DMA_CIRC_MODE flag when you called
|
|
dma_setup_transfer()).
|