BetaFlight统一硬件配置文件研读之dma命令
统一硬件配置文件的设计是一种非常好的设计模式,可以将硬件和软件的工作进行解耦。
1. 源由
cli命令中dma是对硬件DMA资源进行分配的一个操作。
DMA是SOC架构提供的功能,它能使数据:1)从设备直接发送到SOC内存;2)从内存直接发送到设备;3)从一个内存位置直接发送到另一个内存位置。
其最重要的一个特色就是当数据进行移动的时候,不需要CPU介入。而通常我们理解的CPU介入数据传输,不仅需要消耗CPU资源,还需要消耗总线和内存资源(任务切换),这样对于系统整体的性能就大大降低了。严重的时候会导致CPU频繁的在搬数据,而真正需要运算的业务就得不到及时处理,从而影响应用。
飞控对于系统实时性的要求是非常高。目前BetaFlight飞控设计中也大量配置和使用了DMA来提升性能。
注1:除了这个以外,STM32H7的DMA配置非常的灵活,对于习惯查表(以前很多DMA大部分都是和硬件端口绑定,因此可以找到Datasheet查表)的嵌入式朋友来说,确实也折腾了一段时间。为此整理下,希望后续能更进一步深入了解相关设计。
注2:本次看的配置是一块STM32H743芯片,具体datasheet,可以网上下载。
2. 代码分析
DMA这部分配置的代码看似很多,其实逻辑简单,其复杂的部分在于理解硬件和DMA配置之间的关系。早期MCU的DMA是可以通过查表配置的,目前H7的DMA多路复用的灵活性更高了。也就是说可以更好的灵活配置。此时这张DMA配置表就没有了。
主要可以配置的外设为pin和dmaoptEntryTable:
dmaoptEntry_t dmaoptEntryTable[] = {
DEFW("SPI_SDO", DMA_PERIPH_SPI_SDO, PG_SPI_PIN_CONFIG, spiPinConfig_t, txDmaopt, SPIDEV_COUNT, MASK_IGNORED),
DEFW("SPI_SDI", DMA_PERIPH_SPI_SDI, PG_SPI_PIN_CONFIG, spiPinConfig_t, rxDmaopt, SPIDEV_COUNT, MASK_IGNORED),
// SPI_TX/SPI_RX for backwards compatibility with unified configs defined for 4.2.x
DEFW("SPI_TX", DMA_PERIPH_SPI_SDO, PG_SPI_PIN_CONFIG, spiPinConfig_t, txDmaopt, SPIDEV_COUNT, MASK_IGNORED),
DEFW("SPI_RX", DMA_PERIPH_SPI_SDI, PG_SPI_PIN_CONFIG, spiPinConfig_t, rxDmaopt, SPIDEV_COUNT, MASK_IGNORED),
DEFA("ADC", DMA_PERIPH_ADC, PG_ADC_CONFIG, adcConfig_t, dmaopt, ADCDEV_COUNT, MASK_IGNORED),
DEFS("SDIO", DMA_PERIPH_SDIO, PG_SDIO_CONFIG, sdioConfig_t, dmaopt),
DEFW("UART_TX", DMA_PERIPH_UART_TX, PG_SERIAL_UART_CONFIG, serialUartConfig_t, txDmaopt, UARTDEV_CONFIG_MAX, MASK_IGNORED),
DEFW("UART_RX", DMA_PERIPH_UART_RX, PG_SERIAL_UART_CONFIG, serialUartConfig_t, rxDmaopt, UARTDEV_CONFIG_MAX, MASK_IGNORED),
#if defined(STM32H7) || defined(STM32G4)
DEFW("TIMUP", DMA_PERIPH_TIMUP, PG_TIMER_UP_CONFIG, timerUpConfig_t, dmaopt, HARDWARE_TIMER_DEFINITION_COUNT, TIMUP_TIMERS),
#endif
};
2.1 cliDma
直接将dma资源分配命令切分为两部分:
- showDma //外设DMA配置情况
- cliDmaopt //配置DMA
cliDma
├──> "show"
│ └──> showDma()
└──> cliDmaopt(cmdName, cmdline)
注:常见情况USE_DMA_SPEC已定义。
2.2 showDma
这里以外设owner的角度给出DMA资源配置情况。
showDma
├──> cliPrintLinefeed()
├──> cliPrintLine("Currently active DMA:")
└──> loop DMA_LAST_HANDLER
├──> const resourceOwner_t *owner = dmaGetOwner(i)
├──> cliPrintf(DMA_OUTPUT_STRING, DMA_DEVICE_NO(i), DMA_DEVICE_INDEX(i))
├──> <owner->resourceIndex > 0>
│ └──> cliPrintLinef(" %s %d", ownerNames[owner->owner], owner->resourceIndex)
└──> <owner->resourceIndex <= 0>cliPrintLinef(" %s", ownerNames[owner->owner])
└──> cliPrintLinef(" %s", ownerNames[owner->owner])
注:常见情况MINIMAL_CLI无定义。
2.3 cliDmaopt
cliDmaopt
├──> [Peripheral name or command option]
│ ├──> pch = strtok_r(cmdline, " ", &saveptr);
│ ├──> <!pch> //无命令
│ │ └──> printDmaopt(DUMP_MASTER | HIDE_UNUSED, NULL); return
│ └──> <"list"> //有命令
│ └──> "dma: NOT IMPLEMENTED YET"
├──> [Get peripheral name or pin]
│ ├──> <search dmaoptEntryTable for peripheral: SPI_SDO/SPI_SDI/SPI_TX/SPI_RX/ADC/SDIO/UART_TX/UART_RX/TIMUP>
│ │ └──> [assign dmaoptEntry_t *entry]
│ └──> "pin" //如果是pin引脚
│ └──> [dmaoptEntry_t *entry = NULL]
├──> [default settings]
│ └──> dmaoptValue_t orgval = DMA_OPT_UNUSED; dmaoptValue_t *optaddr = NULL; timerIOConfig_t *timerIoConfig = NULL; timerHardware_t *timer = NULL;
├──> <entry> //Peripheral
│ ├──> index = pch ? (atoi(pch) - 1) : -1; //index赋值及边界检查
│ └──> orgval = *optaddr; //获取设备index的原始optval
├──> <pin> //pin
│ ├──> orgval = dmaoptByTag(ioTag); //通过dmaoptByTag获取pin引脚原始optval
│ └──> timerIoConfig = timerIoConfigByTag(ioTag); timer = timerGetConfiguredByTag(ioTag); //引脚对应的timer配置
└──> [opt or list]
├──> <!pch> //无optval参数
│ ├──> <entry> printPeripheralDmaoptDetails(entry, index, *optaddr, true, DUMP_MASTER, cliDumpPrintLinef) // peripheral dma配置打印输出
│ └──> <!entry> printTimerDmaoptDetails(ioTag, timer, orgval, true, DUMP_MASTER, cliDumpPrintLinef) //pin dma配置打印输出
├──> "list"
│ ├──> <entry> printPeripheralDmaoptDetails(entry, index, *optaddr, true, DUMP_MASTER, cliDumpPrintLinef) // peripheral dma可配置 打印输出
│ └──> <!entry> printTimerDmaoptDetails(ioTag, timer, orgval, true, DUMP_MASTER, cliDumpPrintLinef) //pin dma可配置 打印输出
└──> <pch> //资源分配
├──> <"none"> optval = DMA_OPT_UNUSED;
└──> <not "none"> optval = atoi(pch);
├──> <entry> dmaGetChannelSpecByPeripheral(entry->peripheral, index, optval) // 检查设备optval有效性
├──> <!entry> dmaGetChannelSpecByTimerValue(timer->tim, timer->channel, optval) // 检查引脚optval有效性
├──> <optval == orgval>
│ ├──> <entry> *optaddr = optval; // 设备optval赋值
│ └──> <!entry> timerIoConfig->dmaopt = optval; // 引脚optval赋值
└──> <optval != orgval> "no change" 打印命令执行结果
注:常见情况USE_TIMER_MGMT已定义。
3. 实例分析
# dma
dma ADC 1 8
# ADC 1: DMA2 Stream 0 Request 9
dma ADC 3 9
# ADC 3: DMA2 Stream 1 Request 115
dma TIMUP 1 0
# TIMUP 1: DMA1 Stream 0 Request 15
dma TIMUP 3 2
# TIMUP 3: DMA1 Stream 2 Request 27
dma TIMUP 4 1
# TIMUP 4: DMA1 Stream 1 Request 32
dma TIMUP 5 0
# TIMUP 5: DMA1 Stream 0 Request 59
dma pin A10 0
# pin A10: DMA1 Stream 0 Request 13
dma pin B00 0
# pin B00: DMA1 Stream 0 Request 25
dma pin B01 1
# pin B01: DMA1 Stream 1 Request 26
dma pin A00 2
# pin A00: DMA1 Stream 2 Request 55
dma pin A01 3
# pin A01: DMA1 Stream 3 Request 56
dma pin A02 4
# pin A02: DMA1 Stream 4 Request 57
dma pin A03 5
# pin A03: DMA1 Stream 5 Request 58
dma pin D12 6
# pin D12: DMA1 Stream 6 Request 29
dma pin D13 7
# pin D13: DMA1 Stream 7 Request 30
dma pin D14 12
# pin D14: DMA2 Stream 4 Request 31
dma pin E05 0
# pin E05: DMA1 Stream 0 Request 105
dma pin A08 14
# pin A08: DMA2 Stream 6 Request 11
4. 配置情况
# help dma
dma - show/set DMA assignments
<> | <device> <index> list | <device> <index> [<option>|none] | list | show
4.1 dma
当前配置情况列表。
# dma
dma ADC 1 8
# ADC 1: DMA2 Stream 0 Request 9
dma ADC 3 9
# ADC 3: DMA2 Stream 1 Request 115
dma TIMUP 1 0
# TIMUP 1: DMA1 Stream 0 Request 15
dma TIMUP 3 2
# TIMUP 3: DMA1 Stream 2 Request 27
dma TIMUP 4 1
# TIMUP 4: DMA1 Stream 1 Request 32
dma TIMUP 5 0
# TIMUP 5: DMA1 Stream 0 Request 59
dma pin A10 0
# pin A10: DMA1 Stream 0 Request 13
dma pin B00 0
# pin B00: DMA1 Stream 0 Request 25
dma pin B01 1
# pin B01: DMA1 Stream 1 Request 26
dma pin A00 2
# pin A00: DMA1 Stream 2 Request 55
dma pin A01 3
# pin A01: DMA1 Stream 3 Request 56
dma pin A02 4
# pin A02: DMA1 Stream 4 Request 57
dma pin A03 5
# pin A03: DMA1 Stream 5 Request 58
dma pin D12 6
# pin D12: DMA1 Stream 6 Request 29
dma pin D13 7
# pin D13: DMA1 Stream 7 Request 30
dma pin D14 12
# pin D14: DMA2 Stream 4 Request 31
dma pin E05 0
# pin E05: DMA1 Stream 0 Request 105
dma pin A08 14
# pin A08: DMA2 Stream 6 Request 11
4.2 dma show
按照DMA stream上的各外设分配情况。
\# dma show
Currently active DMA:
--------------------
DMA1 Stream 0: DSHOT_BITBANG 2
DMA1 Stream 1: DSHOT_BITBANG 1
DMA1 Stream 2: SPI_MOSI 1
DMA1 Stream 3: SPI_MISO 1
DMA1 Stream 4: SPI_MOSI 2
DMA1 Stream 5: SPI_MISO 2
DMA1 Stream 6: SPI_MOSI 3
DMA1 Stream 7: SPI_MISO 3
DMA2 Stream 0: ADC 1
DMA2 Stream 1: ADC 3
DMA2 Stream 2: SPI_MOSI 4
DMA2 Stream 3: SPI_MISO 4
DMA2 Stream 4: FREE
DMA2 Stream 5: FREE
DMA2 Stream 6: LED_STRIP
DMA2 Stream 7: FREE
4.3 dma device list
设备可分配DMA资源列表。
# dma adc 1 list
# 0: DMA1 Stream 0 Request 9
# 1: DMA1 Stream 1 Request 9
# 2: DMA1 Stream 2 Request 9
# 3: DMA1 Stream 3 Request 9
# 4: DMA1 Stream 4 Request 9
# 5: DMA1 Stream 5 Request 9
# 6: DMA1 Stream 6 Request 9
# 7: DMA1 Stream 7 Request 9
# 8: DMA2 Stream 0 Request 9
# 9: DMA2 Stream 1 Request 9
# 10: DMA2 Stream 2 Request 9
# 11: DMA2 Stream 3 Request 9
# 12: DMA2 Stream 4 Request 9
# 13: DMA2 Stream 5 Request 9
# 14: DMA2 Stream 6 Request 9
# 15: DMA2 Stream 7 Request 9
# dma adc 2 list
# 0: DMA1 Stream 0 Request 10
# 1: DMA1 Stream 1 Request 10
# 2: DMA1 Stream 2 Request 10
# 3: DMA1 Stream 3 Request 10
# 4: DMA1 Stream 4 Request 10
# 5: DMA1 Stream 5 Request 10
# 6: DMA1 Stream 6 Request 10
# 7: DMA1 Stream 7 Request 10
# 8: DMA2 Stream 0 Request 10
# 9: DMA2 Stream 1 Request 10
# 10: DMA2 Stream 2 Request 10
# 11: DMA2 Stream 3 Request 10
# 12: DMA2 Stream 4 Request 10
# 13: DMA2 Stream 5 Request 10
# 14: DMA2 Stream 6 Request 10
# 15: DMA2 Stream 7 Request 10
# dma adc 3 list
# 0: DMA1 Stream 0 Request 115
# 1: DMA1 Stream 1 Request 115
# 2: DMA1 Stream 2 Request 115
# 3: DMA1 Stream 3 Request 115
# 4: DMA1 Stream 4 Request 115
# 5: DMA1 Stream 5 Request 115
# 6: DMA1 Stream 6 Request 115
# 7: DMA1 Stream 7 Request 115
# 8: DMA2 Stream 0 Request 115
# 9: DMA2 Stream 1 Request 115
# 10: DMA2 Stream 2 Request 115
# 11: DMA2 Stream 3 Request 115
# 12: DMA2 Stream 4 Request 115
# 13: DMA2 Stream 5 Request 115
# 14: DMA2 Stream 6 Request 115
# 15: DMA2 Stream 7 Request 115
4.4 dma pin list
pin脚可分配DMA资源列表。
# dma pin A10 list
# 0: DMA1 Stream 0 Request 13
# 1: DMA1 Stream 1 Request 13
# 2: DMA1 Stream 2 Request 13
# 3: DMA1 Stream 3 Request 13
# 4: DMA1 Stream 4 Request 13
# 5: DMA1 Stream 5 Request 13
# 6: DMA1 Stream 6 Request 13
# 7: DMA1 Stream 7 Request 13
# 8: DMA2 Stream 0 Request 13
# 9: DMA2 Stream 1 Request 13
# 10: DMA2 Stream 2 Request 13
# 11: DMA2 Stream 3 Request 13
# 12: DMA2 Stream 4 Request 13
# 13: DMA2 Stream 5 Request 13
# 14: DMA2 Stream 6 Request 13
# 15: DMA2 Stream 7 Request 13
4.5 dma device id
设备DMA资源配置情况。
4.5.1 dma adc id
# dma adc 1
dma ADC 1 8
# ADC 1: DMA2 Stream 0 Request 9
4.5.2 dma TIMUP id
# dma timup 5
dma TIMUP 5 0
# TIMUP 5: DMA1 Stream 0 Request 59
4.5.3 dma pin id
# dma pin A10
dma pin A10 0
# pin A10: DMA1 Stream 0 Request 13
4.6 dma device id stream
设备DMA资源配置,因为多路复用可以随意配置(不考虑优先级/冲突)。
4.6.1 dma adc id stream
# dma adc 1
dma ADC 1 8
# ADC 1: DMA2 Stream 0 Request 9
# dma adc 1 10
# dma ADC 1: changed from 8 to 10
# dma adc 1
dma ADC 1 10
# ADC 1: DMA2 Stream 2 Request 9
4.6.2 dma TIMUP id stream
# dma timup 5
dma TIMUP 5 0
# TIMUP 5: DMA1 Stream 0 Request 59
# dma TIMUP 5 1
# dma TIMUP 5: changed from 0 to 1
# dma TIMUP 5
dma TIMUP 5 1
# TIMUP 5: DMA1 Stream 1 Request 59
4.6.3 dma pin id stream
# dma pin A10
dma pin A10 0
# pin A10: DMA1 Stream 0 Request 13
# dma pin A10 1
# dma pin A10: changed from 0 to 1
# dma pin A10
dma pin A10 1
# pin A10: DMA1 Stream 1 Request 13
5. STM32 H743
5.1 DMA简介
大体上,通过RM0433资料:
- H743 DMA控制器 x 2
- 每个DMA控制器 有 stream x 8
- DMA stream由 DMAMUX信号来驱动(Request)
- Request信号可以是115种可用信号的其中一种
DMA主要功能不在这里展开,希望更多了解请下载RM0433资料,更深入的了解DMA技术细节,可以对工作原理,优先级、带宽、工作模式优化提供帮助,但这不是本章节重点。有兴趣的朋友可以自行研究先,有时间我们会在后续驱动方面的文章中进行探讨。
从这里我们就可以理解request信号源来自17.3.2章节,这里给出BF里面用到的DMA表格。
5.2 DMAMUX1 关联
这些定义已被HAL打包定义,详见:\lib\main\STM32H7\Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_dma.h。
/** @defgroup DMA_Request_selection DMA Request selection
* @brief DMA Request selection
* @{
*/
/* DMAMUX1 requests */
#define DMA_REQUEST_MEM2MEM 0U /*!< memory to memory transfer */
#define DMA_REQUEST_GENERATOR0 1U /*!< DMAMUX1 request generator 0 */
#define DMA_REQUEST_GENERATOR1 2U /*!< DMAMUX1 request generator 1 */
#define DMA_REQUEST_GENERATOR2 3U /*!< DMAMUX1 request generator 2 */
#define DMA_REQUEST_GENERATOR3 4U /*!< DMAMUX1 request generator 3 */
#define DMA_REQUEST_GENERATOR4 5U /*!< DMAMUX1 request generator 4 */
#define DMA_REQUEST_GENERATOR5 6U /*!< DMAMUX1 request generator 5 */
#define DMA_REQUEST_GENERATOR6 7U /*!< DMAMUX1 request generator 6 */
#define DMA_REQUEST_GENERATOR7 8U /*!< DMAMUX1 request generator 7 */
#define DMA_REQUEST_ADC1 9U /*!< DMAMUX1 ADC1 request */
#define DMA_REQUEST_ADC2 10U /*!< DMAMUX1 ADC2 request */
#define DMA_REQUEST_TIM1_CH1 11U /*!< DMAMUX1 TIM1 CH1 request */
#define DMA_REQUEST_TIM1_CH2 12U /*!< DMAMUX1 TIM1 CH2 request */
#define DMA_REQUEST_TIM1_CH3 13U /*!< DMAMUX1 TIM1 CH3 request */
#define DMA_REQUEST_TIM1_CH4 14U /*!< DMAMUX1 TIM1 CH4 request */
#define DMA_REQUEST_TIM1_UP 15U /*!< DMAMUX1 TIM1 UP request */
#define DMA_REQUEST_TIM1_TRIG 16U /*!< DMAMUX1 TIM1 TRIG request */
#define DMA_REQUEST_TIM1_COM 17U /*!< DMAMUX1 TIM1 COM request */
#define DMA_REQUEST_TIM2_CH1 18U /*!< DMAMUX1 TIM2 CH1 request */
#define DMA_REQUEST_TIM2_CH2 19U /*!< DMAMUX1 TIM2 CH2 request */
#define DMA_REQUEST_TIM2_CH3 20U /*!< DMAMUX1 TIM2 CH3 request */
#define DMA_REQUEST_TIM2_CH4 21U /*!< DMAMUX1 TIM2 CH4 request */
#define DMA_REQUEST_TIM2_UP 22U /*!< DMAMUX1 TIM2 UP request */
#define DMA_REQUEST_TIM3_CH1 23U /*!< DMAMUX1 TIM3 CH1 request */
#define DMA_REQUEST_TIM3_CH2 24U /*!< DMAMUX1 TIM3 CH2 request */
#define DMA_REQUEST_TIM3_CH3 25U /*!< DMAMUX1 TIM3 CH3 request */
#define DMA_REQUEST_TIM3_CH4 26U /*!< DMAMUX1 TIM3 CH4 request */
#define DMA_REQUEST_TIM3_UP 27U /*!< DMAMUX1 TIM3 UP request */
#define DMA_REQUEST_TIM3_TRIG 28U /*!< DMAMUX1 TIM3 TRIG request */
#define DMA_REQUEST_TIM4_CH1 29U /*!< DMAMUX1 TIM4 CH1 request */
#define DMA_REQUEST_TIM4_CH2 30U /*!< DMAMUX1 TIM4 CH2 request */
#define DMA_REQUEST_TIM4_CH3 31U /*!< DMAMUX1 TIM4 CH3 request */
#define DMA_REQUEST_TIM4_UP 32U /*!< DMAMUX1 TIM4 UP request */
#define DMA_REQUEST_I2C1_RX 33U /*!< DMAMUX1 I2C1 RX request */
#define DMA_REQUEST_I2C1_TX 34U /*!< DMAMUX1 I2C1 TX request */
#define DMA_REQUEST_I2C2_RX 35U /*!< DMAMUX1 I2C2 RX request */
#define DMA_REQUEST_I2C2_TX 36U /*!< DMAMUX1 I2C2 TX request */
#define DMA_REQUEST_SPI1_RX 37U /*!< DMAMUX1 SPI1 RX request */
#define DMA_REQUEST_SPI1_TX 38U /*!< DMAMUX1 SPI1 TX request */
#define DMA_REQUEST_SPI2_RX 39U /*!< DMAMUX1 SPI2 RX request */
#define DMA_REQUEST_SPI2_TX 40U /*!< DMAMUX1 SPI2 TX request */
#define DMA_REQUEST_USART1_RX 41U /*!< DMAMUX1 USART1 RX request */
#define DMA_REQUEST_USART1_TX 42U /*!< DMAMUX1 USART1 TX request */
#define DMA_REQUEST_USART2_RX 43U /*!< DMAMUX1 USART2 RX request */
#define DMA_REQUEST_USART2_TX 44U /*!< DMAMUX1 USART2 TX request */
#define DMA_REQUEST_USART3_RX 45U /*!< DMAMUX1 USART3 RX request */
#define DMA_REQUEST_USART3_TX 46U /*!< DMAMUX1 USART3 TX request */
#define DMA_REQUEST_TIM8_CH1 47U /*!< DMAMUX1 TIM8 CH1 request */
#define DMA_REQUEST_TIM8_CH2 48U /*!< DMAMUX1 TIM8 CH2 request */
#define DMA_REQUEST_TIM8_CH3 49U /*!< DMAMUX1 TIM8 CH3 request */
#define DMA_REQUEST_TIM8_CH4 50U /*!< DMAMUX1 TIM8 CH4 request */
#define DMA_REQUEST_TIM8_UP 51U /*!< DMAMUX1 TIM8 UP request */
#define DMA_REQUEST_TIM8_TRIG 52U /*!< DMAMUX1 TIM8 TRIG request */
#define DMA_REQUEST_TIM8_COM 53U /*!< DMAMUX1 TIM8 COM request */
#define DMA_REQUEST_TIM5_CH1 55U /*!< DMAMUX1 TIM5 CH1 request */
#define DMA_REQUEST_TIM5_CH2 56U /*!< DMAMUX1 TIM5 CH2 request */
#define DMA_REQUEST_TIM5_CH3 57U /*!< DMAMUX1 TIM5 CH3 request */
#define DMA_REQUEST_TIM5_CH4 58U /*!< DMAMUX1 TIM5 CH4 request */
#define DMA_REQUEST_TIM5_UP 59U /*!< DMAMUX1 TIM5 UP request */
#define DMA_REQUEST_TIM5_TRIG 60U /*!< DMAMUX1 TIM5 TRIG request */
#define DMA_REQUEST_SPI3_RX 61U /*!< DMAMUX1 SPI3 RX request */
#define DMA_REQUEST_SPI3_TX 62U /*!< DMAMUX1 SPI3 TX request */
#define DMA_REQUEST_UART4_RX 63U /*!< DMAMUX1 UART4 RX request */
#define DMA_REQUEST_UART4_TX 64U /*!< DMAMUX1 UART4 TX request */
#define DMA_REQUEST_UART5_RX 65U /*!< DMAMUX1 UART5 RX request */
#define DMA_REQUEST_UART5_TX 66U /*!< DMAMUX1 UART5 TX request */
#define DMA_REQUEST_DAC1_CH1 67U /*!< DMAMUX1 DAC1 Channel 1 request */
#define DMA_REQUEST_DAC1_CH2 68U /*!< DMAMUX1 DAC1 Channel 2 request */
#define DMA_REQUEST_TIM6_UP 69U /*!< DMAMUX1 TIM6 UP request */
#define DMA_REQUEST_TIM7_UP 70U /*!< DMAMUX1 TIM7 UP request */
#define DMA_REQUEST_USART6_RX 71U /*!< DMAMUX1 USART6 RX request */
#define DMA_REQUEST_USART6_TX 72U /*!< DMAMUX1 USART6 TX request */
#define DMA_REQUEST_I2C3_RX 73U /*!< DMAMUX1 I2C3 RX request */
#define DMA_REQUEST_I2C3_TX 74U /*!< DMAMUX1 I2C3 TX request */
#if defined (PSSI)
#define DMA_REQUEST_DCMI_PSSI 75U /*!< DMAMUX1 DCMI/PSSI request */
#define DMA_REQUEST_DCMI DMA_REQUEST_DCMI_PSSI /* Legacy define */
#else
#define DMA_REQUEST_DCMI 75U /*!< DMAMUX1 DCMI request */
#endif /* PSSI */
#define DMA_REQUEST_CRYP_IN 76U /*!< DMAMUX1 CRYP IN request */
#define DMA_REQUEST_CRYP_OUT 77U /*!< DMAMUX1 CRYP OUT request */
#define DMA_REQUEST_HASH_IN 78U /*!< DMAMUX1 HASH IN request */
#define DMA_REQUEST_UART7_RX 79U /*!< DMAMUX1 UART7 RX request */
#define DMA_REQUEST_UART7_TX 80U /*!< DMAMUX1 UART7 TX request */
#define DMA_REQUEST_UART8_RX 81U /*!< DMAMUX1 UART8 RX request */
#define DMA_REQUEST_UART8_TX 82U /*!< DMAMUX1 UART8 TX request */
#define DMA_REQUEST_SPI4_RX 83U /*!< DMAMUX1 SPI4 RX request */
#define DMA_REQUEST_SPI4_TX 84U /*!< DMAMUX1 SPI4 TX request */
#define DMA_REQUEST_SPI5_RX 85U /*!< DMAMUX1 SPI5 RX request */
#define DMA_REQUEST_SPI5_TX 86U /*!< DMAMUX1 SPI5 TX request */
#define DMA_REQUEST_SAI1_A 87U /*!< DMAMUX1 SAI1 A request */
#define DMA_REQUEST_SAI1_B 88U /*!< DMAMUX1 SAI1 B request */
#if defined(SAI2)
#define DMA_REQUEST_SAI2_A 89U /*!< DMAMUX1 SAI2 A request */
#define DMA_REQUEST_SAI2_B 90U /*!< DMAMUX1 SAI2 B request */
#endif /* SAI2 */
#define DMA_REQUEST_SWPMI_RX 91U /*!< DMAMUX1 SWPMI RX request */
#define DMA_REQUEST_SWPMI_TX 92U /*!< DMAMUX1 SWPMI TX request */
#define DMA_REQUEST_SPDIF_RX_DT 93U /*!< DMAMUX1 SPDIF RXDT request*/
#define DMA_REQUEST_SPDIF_RX_CS 94U /*!< DMAMUX1 SPDIF RXCS request*/
#if defined(HRTIM1)
#define DMA_REQUEST_HRTIM_MASTER 95U /*!< DMAMUX1 HRTIM1 Master request 1 */
#define DMA_REQUEST_HRTIM_TIMER_A 96U /*!< DMAMUX1 HRTIM1 TimerA request 2 */
#define DMA_REQUEST_HRTIM_TIMER_B 97U /*!< DMAMUX1 HRTIM1 TimerB request 3 */
#define DMA_REQUEST_HRTIM_TIMER_C 98U /*!< DMAMUX1 HRTIM1 TimerC request 4 */
#define DMA_REQUEST_HRTIM_TIMER_D 99U /*!< DMAMUX1 HRTIM1 TimerD request 5 */
#define DMA_REQUEST_HRTIM_TIMER_E 100U /*!< DMAMUX1 HRTIM1 TimerE request 6 */
#endif /* HRTIM1 */
#define DMA_REQUEST_DFSDM1_FLT0 101U /*!< DMAMUX1 DFSDM Filter0 request */
#define DMA_REQUEST_DFSDM1_FLT1 102U /*!< DMAMUX1 DFSDM Filter1 request */
#define DMA_REQUEST_DFSDM1_FLT2 103U /*!< DMAMUX1 DFSDM Filter2 request */
#define DMA_REQUEST_DFSDM1_FLT3 104U /*!< DMAMUX1 DFSDM Filter3 request */
#define DMA_REQUEST_TIM15_CH1 105U /*!< DMAMUX1 TIM15 CH1 request */
#define DMA_REQUEST_TIM15_UP 106U /*!< DMAMUX1 TIM15 UP request */
#define DMA_REQUEST_TIM15_TRIG 107U /*!< DMAMUX1 TIM15 TRIG request */
#define DMA_REQUEST_TIM15_COM 108U /*!< DMAMUX1 TIM15 COM request */
#define DMA_REQUEST_TIM16_CH1 109U /*!< DMAMUX1 TIM16 CH1 request */
#define DMA_REQUEST_TIM16_UP 110U /*!< DMAMUX1 TIM16 UP request */
#define DMA_REQUEST_TIM17_CH1 111U /*!< DMAMUX1 TIM17 CH1 request */
#define DMA_REQUEST_TIM17_UP 112U /*!< DMAMUX1 TIM17 UP request */
#if defined(SAI3)
#define DMA_REQUEST_SAI3_A 113U /*!< DMAMUX1 SAI3 A request */
#define DMA_REQUEST_SAI3_B 114U /*!< DMAMUX1 SAI3 B request */
#endif /* SAI3 */
#if defined(ADC3)
#define DMA_REQUEST_ADC3 115U /*!< DMAMUX1 ADC3 request */
#endif /* ADC3 */
#if defined(UART9)
#define DMA_REQUEST_UART9_RX 116U /*!< DMAMUX1 UART9 request */
#define DMA_REQUEST_UART9_TX 117U /*!< DMAMUX1 UART9 request */
#endif /* UART9 */
#if defined(USART10)
#define DMA_REQUEST_USART10_RX 118U /*!< DMAMUX1 USART10 request */
#define DMA_REQUEST_USART10_TX 119U /*!< DMAMUX1 USART10 request */
#endif /* USART10 */
#if defined(FMAC)
#define DMA_REQUEST_FMAC_READ 120U /*!< DMAMUX1 FMAC Read request */
#define DMA_REQUEST_FMAC_WRITE 121U /*!< DMAMUX1 FMAC Write request */
#endif /* FMAC */
#if defined(CORDIC)
#define DMA_REQUEST_CORDIC_READ 122U /*!< DMAMUX1 CORDIC Read request */
#define DMA_REQUEST_CORDIC_WRITE 123U /*!< DMAMUX1 CORDIC Write request */
#endif /* CORDIC */
#if defined(I2C5)
#define DMA_REQUEST_I2C5_RX 124U /*!< DMAMUX1 I2C5 RX request */
#define DMA_REQUEST_I2C5_TX 125U /*!< DMAMUX1 I2C5 TX request */
#endif /* I2C5 */
#if defined(TIM23)
#define DMA_REQUEST_TIM23_CH1 126U /*!< DMAMUX1 TIM23 CH1 request */
#define DMA_REQUEST_TIM23_CH2 127U /*!< DMAMUX1 TIM23 CH2 request */
#define DMA_REQUEST_TIM23_CH3 128U /*!< DMAMUX1 TIM23 CH3 request */
#define DMA_REQUEST_TIM23_CH4 129U /*!< DMAMUX1 TIM23 CH4 request */
#define DMA_REQUEST_TIM23_UP 130U /*!< DMAMUX1 TIM23 UP request */
#define DMA_REQUEST_TIM23_TRIG 131U /*!< DMAMUX1 TIM23 TRIG request */
#endif /* TIM23 */
#if defined(TIM24)
#define DMA_REQUEST_TIM24_CH1 132U /*!< DMAMUX1 TIM24 CH1 request */
#define DMA_REQUEST_TIM24_CH2 133U /*!< DMAMUX1 TIM24 CH2 request */
#define DMA_REQUEST_TIM24_CH3 134U /*!< DMAMUX1 TIM24 CH3 request */
#define DMA_REQUEST_TIM24_CH4 135U /*!< DMAMUX1 TIM24 CH4 request */
#define DMA_REQUEST_TIM24_UP 136U /*!< DMAMUX1 TIM24 UP request */
#define DMA_REQUEST_TIM24_TRIG 137U /*!< DMAMUX1 TIM24 TRIG request */
#endif /* TIM24 */
5.3 dmaPeripheralMapping 关联
static const dmaPeripheralMapping_t dmaPeripheralMapping[] = {
#ifdef USE_SPI
REQMAP_DIR(SPI, 1, SDO),
REQMAP_DIR(SPI, 1, SDI),
REQMAP_DIR(SPI, 2, SDO),
REQMAP_DIR(SPI, 2, SDI),
REQMAP_DIR(SPI, 3, SDO),
REQMAP_DIR(SPI, 3, SDI),
REQMAP_DIR(SPI, 4, SDO),
REQMAP_DIR(SPI, 4, SDI),
REQMAP_DIR(SPI, 5, SDO), // Not available in smaller packages
REQMAP_DIR(SPI, 5, SDI), // ditto
// REQMAP_DIR(SPI, 6, SDO), // SPI6 is on BDMA (todo)
// REQMAP_DIR(SPI, 6, SDO), // ditto
#endif // USE_SPI
#ifdef USE_ADC
REQMAP(ADC, 1),
REQMAP(ADC, 2),
#if defined(STM32H743xx) || defined(STM32H750xx) || defined(STM32H723xx) || defined(STM32H725xx) || defined(STM32H730xx)
REQMAP(ADC, 3),
#endif
#endif
#ifdef USE_UART
REQMAP_DIR(UART, 1, TX),
REQMAP_DIR(UART, 1, RX),
REQMAP_DIR(UART, 2, TX),
REQMAP_DIR(UART, 2, RX),
REQMAP_DIR(UART, 3, TX),
REQMAP_DIR(UART, 3, RX),
REQMAP_DIR(UART, 4, TX),
REQMAP_DIR(UART, 4, RX),
REQMAP_DIR(UART, 5, TX),
REQMAP_DIR(UART, 5, RX),
REQMAP_DIR(UART, 6, TX),
REQMAP_DIR(UART, 6, RX),
REQMAP_DIR(UART, 7, TX),
REQMAP_DIR(UART, 7, RX),
REQMAP_DIR(UART, 8, TX),
REQMAP_DIR(UART, 8, RX),
#if defined(STM32H7A3xxQ)
REQMAP_DIR(UART, 9, TX),
REQMAP_DIR(UART, 9, RX),
REQMAP_DIR(UART, 10, TX),
REQMAP_DIR(UART, 10, RX),
#endif
#ifdef USE_LPUART1
{ DMA_PERIPH_UART_TX, LPUARTDEV_1, BDMA_REQUEST_LPUART1_TX },
{ DMA_PERIPH_UART_RX, LPUARTDEV_1, BDMA_REQUEST_LPUART1_RX },
#endif
#endif
#ifdef USE_TIMER
// Pseudo peripheral for TIMx_UP channel
REQMAP_TIMUP(TIMUP, 1),
REQMAP_TIMUP(TIMUP, 2),
REQMAP_TIMUP(TIMUP, 3),
REQMAP_TIMUP(TIMUP, 4),
REQMAP_TIMUP(TIMUP, 5),
REQMAP_TIMUP(TIMUP, 6),
REQMAP_TIMUP(TIMUP, 7),
REQMAP_TIMUP(TIMUP, 8),
REQMAP_TIMUP(TIMUP, 15),
REQMAP_TIMUP(TIMUP, 16),
REQMAP_TIMUP(TIMUP, 17),
#endif
};
5.4 dmaTimerMapping关联
static const dmaTimerMapping_t dmaTimerMapping[] = {
REQMAP_TIM(TIM1, CH1),
REQMAP_TIM(TIM1, CH2),
REQMAP_TIM(TIM1, CH3),
REQMAP_TIM(TIM1, CH4),
REQMAP_TIM(TIM2, CH1),
REQMAP_TIM(TIM2, CH2),
REQMAP_TIM(TIM2, CH3),
REQMAP_TIM(TIM2, CH4),
REQMAP_TIM(TIM3, CH1),
REQMAP_TIM(TIM3, CH2),
REQMAP_TIM(TIM3, CH3),
REQMAP_TIM(TIM3, CH4),
REQMAP_TIM(TIM4, CH1),
REQMAP_TIM(TIM4, CH2),
REQMAP_TIM(TIM4, CH3),
REQMAP_TIM(TIM5, CH1),
REQMAP_TIM(TIM5, CH2),
REQMAP_TIM(TIM5, CH3),
REQMAP_TIM(TIM5, CH4),
REQMAP_TIM(TIM8, CH1),
REQMAP_TIM(TIM8, CH2),
REQMAP_TIM(TIM8, CH3),
REQMAP_TIM(TIM8, CH4),
REQMAP_TIM(TIM15, CH1),
REQMAP_TIM(TIM16, CH1),
REQMAP_TIM(TIM17, CH1),
};
5.5 dmaIdentifier_e关联
typedef enum {
DMA_NONE = 0,
DMA1_ST0_HANDLER = 1,
DMA1_ST1_HANDLER,
DMA1_ST2_HANDLER,
DMA1_ST3_HANDLER,
DMA1_ST4_HANDLER,
DMA1_ST5_HANDLER,
DMA1_ST6_HANDLER,
DMA1_ST7_HANDLER,
DMA2_ST0_HANDLER,
DMA2_ST1_HANDLER,
DMA2_ST2_HANDLER,
DMA2_ST3_HANDLER,
DMA2_ST4_HANDLER,
DMA2_ST5_HANDLER,
DMA2_ST6_HANDLER,
DMA2_ST7_HANDLER,
DMA_LAST_HANDLER = DMA2_ST7_HANDLER
} dmaIdentifier_e;
6. 参考资料
【1】BetaFlight开源代码框架简介
【2】BetaFlight统一硬件资源简单配置修改
【3】BetaFlight统一硬件配置文件研读
7. 附录-DMA on STM32介绍视频
DMA on STM32 HAL with 2 example projects