嵌入式开发学习之--DMA(上)
提示:本篇文章主要了解学习一下DMA
文章目录
前言
一、DMA是什么?
二、DMA使用步骤
1、外设通道选择
2.2、仲裁器
2.3、FIFO
2.4、存储器端口 外设端口
2.5、编程端口
三、DMA结构体初始化详解
总结
前言
上一篇文章学习了串口通信,这一篇我们来学习一下DMA的使用。
提示:以下是本篇文章正文内容,下面案例可供参考
一、DMA是什么?
DMA(Direct Memory Access,直接存储区访问)为实现数据高速在外设寄存器与存储器之间或者存储器与存储器之间传输提供了高效的方法。之所以称之为高效,是因为 DMA 传输实现高速数据移动过程无需任何 CPU 操作控制。从硬件层次上来说,DMA 控制器是独立于 Cortex-M4 内核的,有点类似 GPIO、USART 外设一般,只是 DMA 的功能是可以快速移动内存数据。
DMA 传输是不占用 CPU 的,可以节省很多 CPU 资源。
二、DMA使用步骤
1、外设通道选择
STM32F4xx 系列资源丰富,具有两个 DMA 控制器,同时外设繁多,为实现正常传输,DMA 需要通道选择控制。每个 DMA 控制器具有 8 个数据流,每个数据流对应 8 个外设请求。在实现 DMA 传输之前,DMA 控制器会通过 DMA 数据流 x 配置寄存器 DMA_SxCR(x为 0~7,对应 8 个 DMA 数据流)CHSEL[2:0]位选择对应的通道作为该数据流的目标外设。外设通道选择要解决的主要问题是决定哪一个外设作为该数据流的源地址或者目标地址。
每个外设请求都占用一个数据流通道,相同外设请求可以占用不同数据流通道。比如SPI3_RX 请求,即 SPI3 数据发送请求,占用 DMA1 的数据流 0 的通道 0,因此当我们使用该请求时,我们需要在把 DMA_S0CR 寄存器的 CHSEL[2:0]设置为“000”,此时相同数据流的其他通道不被选择,处于不可用状态,比如此时不能使用数据流 0 的通道 1 即I2C1_RX 请求等等。
2.2、仲裁器
一个DMA 控制器对应 8 个数据流,数据流包含要传输数据的源地址、目标地址、数据等等信息。如果我们需要同时使用同一个DMA 控制器(DMA1 或 DMA2)多个外设请求时,那必然需要同时使用多个数据流,这就需要仲裁器来管理判断了。
仲裁器管理数据流方法分为两个阶段。第一阶段属于软件阶段,我们在配置数据流时可以通过寄存器设定它的优先级别,具体配置 DMA_SxCR 寄存器 PL[1:0]位,可以设置为非常高、高、中和低四个级别。第二阶段属于硬件阶段,**如果两个或以上数据流软件设置优先级一样,则他们优先级取决于数据流编号,编号越低越具有优先权,**比如数据流 2 优先级高于数据流 3。
2.3、FIFO
每个数据流都独立拥有四级 32 位 FIFO(先进先出存储器缓冲区)。DMA 传输具有 FIFO模式和直接模式。
直接模式在每个外设请求都立即启动对存储器传输。在直接模式下,如果 DMA 配置为存储器到外设传输那 DMA 会见一个数据存放在 FIFO 内,如果外设启动 DMA 传输请求就可以马上将数据传输过去。
FIFO 用于在源数据传输到目标地址之前临时存放这些数据。可以通过 DMA 数据流xFIFO 控制寄存器 DMA_SxFCR 的 FTH[1:0]位来控制 FIFO 的阈值,分别为 1/4、1/2、3/4和满。如果数据存储量达到阈值级别时,FIFO 内容将传输到目标中。
FIFO 对于要求源地址和目标地址数据宽度不同时非常有用,比如源数据是源源不断的字节数据,而目标地址要求输出字宽度的数据,即在实现数据传输时同时把原来 4 个 8 位字节的数据拼凑成一个 32 位字数据。此时使用 FIFO 功能先把数据缓存起来,分别根据需要输出数据。FIFO 另外一个作用使用于突发(burst)传输。
2.4、存储器端口 外设端口
DMA 控制器实现双 AHB 主接口,更好利用总线矩阵和并行传输。DMA 控制器通过存储器端口和外设端口与存储器和外设进行数据传输,DMA 控制器的功能是快速转移内存数据,需要一个连接至源数据地址的端口和一个连接至目标地址的端口。DMA2(DMA 控制器 2)的存储器端口和外设端口都是连接到 AHB 总线矩阵,可以使用AHB 总线矩阵功能。DMA2 存储器和外设端口可以访问相关的内存地址,包括有内部Flash、内部 SRAM、AHB1 外设、AHB2 外设、APB2 外设和外部存储器空间。
DMA1 的存储区端口相比 DMA2 的要减少 AHB2 外设的访问权,同时 DMA1 外设端口是没有连接至总线矩阵的,只有连接到 APB1 外设,所以 DMA1 不能实现存储器到存储器传输。
2.5、编程端口
AHB 从器件编程端口是连接至 AHB2 外设的。AHB2 外设在使用 DMA 传输时需要相关控制信号。
三、DMA结构体初始化详解
代码如下(示例):
typedef struct { uint32_t DMA_Channel; /*!< Specifies the channel used for the specified stream. This parameter can be a value of @ref DMA_channel */ uint32_t DMA_PeripheralBaseAddr; /*!< Specifies the peripheral base address for DMAy Streamx. */ uint32_t DMA_Memory0BaseAddr; /*!< Specifies the memory 0 base address for DMAy Streamx. This memory is the default memory used when double buffer mode is not enabled. */ uint32_t DMA_DIR; /*!< Specifies if the data will be transferred from memory to peripheral, from memory to memory or from peripheral to memory. This parameter can be a value of @ref DMA_data_transfer_direction */ uint32_t DMA_BufferSize; /*!< Specifies the buffer size, in data unit, of the specified Stream. The data unit is equal to the configuration set in DMA_PeripheralDataSize or DMA_MemoryDataSize members depending in the transfer direction. */ uint32_t DMA_PeripheralInc; /*!< Specifies whether the Peripheral address register should be incremented or not. This parameter can be a value of @ref DMA_peripheral_incremented_mode */ uint32_t DMA_MemoryInc; /*!< Specifies whether the memory address register should be incremented or not. This parameter can be a value of @ref DMA_memory_incremented_mode */ uint32_t DMA_PeripheralDataSize; /*!< Specifies the Peripheral data width. This parameter can be a value of @ref DMA_peripheral_data_size */ uint32_t DMA_MemoryDataSize; /*!< Specifies the Memory data width. This parameter can be a value of @ref DMA_memory_data_size */ uint32_t DMA_Mode; /*!< Specifies the operation mode of the DMAy Streamx. This parameter can be a value of @ref DMA_circular_normal_mode @note The circular buffer mode cannot be used if the memory-to-memory data transfer is configured on the selected Stream */ uint32_t DMA_Priority; /*!< Specifies the software priority for the DMAy Streamx. This parameter can be a value of @ref DMA_priority_level */ uint32_t DMA_FIFOMode; /*!< Specifies if the FIFO mode or Direct mode will be used for the specified Stream. This parameter can be a value of @ref DMA_fifo_direct_mode @note The Direct mode (FIFO mode disabled) cannot be used if the memory-to-memory data transfer is configured on the selected Stream */ uint32_t DMA_FIFOThreshold; /*!< Specifies the FIFO threshold level. This parameter can be a value of @ref DMA_fifo_threshold_level */ uint32_t DMA_MemoryBurst; /*!< Specifies the Burst transfer configuration for the memory transfers. It specifies the amount of data to be transferred in a single non interruptable transaction. This parameter can be a value of @ref DMA_memory_burst @note The burst mode is possible only if the address Increment mode is enabled. */ uint32_t DMA_PeripheralBurst; /*!< Specifies the Burst transfer configuration for the peripheral transfers. It specifies the amount of data to be transferred in a single non interruptable transaction. This parameter can be a value of @ref DMA_peripheral_burst @note The burst mode is possible only if the address Increment mode is enabled. */ }DMA_InitTypeDef;
1、DMA_Channel:DMA 请求通道选择,可选通道 0 至通道 7,具体配置查表。
2、DMA_PeripheralBaseAddr:外设地址,设定 DMA_SxPAR 寄存器的值。
3、DMA_Memory0BaseAddr:存储器 0 地址,设定 DMA_SxM0AR 寄存器值。
4、DMA_DIR:传输方向选择,可选外设到存储器、存储器到外设以及存储器到存储器。
5、DMA_BufferSize:设定待传输数据数目,初始化设定 DMA_SxNDTR 寄存器的值。
6、DMA_PeripheralInc:使能外设地址自动递增功能。
7、DMA_MemoryInc:使能存储器地址自动递增功能。
8、DMA_PeripheralDataSize:外设数据宽度,可选字节(8 位)、半字(16 位)和字(32位)。
9、DMA_MemoryDataSize:存储器数据宽度,可选字节(8 位)、半字(16 位)和字(32位)。
10、DMA_Mode:DMA 传输模式选择,可选一次传输或者循环传输。
11、DMA_Priority:软件设置数据流的优先级,有 4 个可选优先级分别为非常高、高、中和低。
12、DMA_FIFOMode:FIFO 模式使能。
13、DMA_FIFOThreshold:FIFO 阈值选择,可选 4 种状态分别为 FIFO 容量的 1/4、1/2、3/4 和满。
14、DMA_MemoryBurst:存储器突发模式选择,可选单次模式、4 节拍的增量突发模式、8 节拍的增量突发模式或 16 节拍的增量突发模式。
15、DMA_PeripheralBurst:外设突发模式选择,可选单次模式、4 节拍的增量突发模式、8 节拍的增量突发模式或 16 节拍的增量突发模式
总结
本章了解一下DMA是个什么东西以及其作用,还有他的配置模式,下一章借实验实战一下。