本帖最后由 MindMotion 于 2024-3-26 17:07 编辑
一、DMA简介
DMA全称为Direct Memory Access,即直接存储器访问。在进行DMA传输前,CPU将总线控制权交给DMA,通过共享系统总线,实现无需CPU参与的快速数据传输,能够直接将数据从一个地址空间复制到另一个地址空间,DMA在数据传输结束后将总线控制权交回CPU。
MM32F0140内置5路通用DMA,可以管理设备到存储器、存储器到设备与存储器到存储器的数据传输,每个通道都有专门的硬件DMA请求逻辑,也可以通过软件配置来触发每个通道。
MM32F0140的DMA模块所支持的外设类型包括UART、I2C、SPI、ADC与通用、高级和基础定时器,当DMA从外设产生的请求通过逻辑或输入DMA控制器时,为避免冲突,在一个通道中,同时只能有一个外设DMA请求有效,详细各通道DMA请求如图1所示。
图1. 各通道DMA外设请求
二、DMA配置
DMA的配置涉及到传输模式、数据宽度、外设地址、存储器地址、通道优先级、数据传输数量、中断使能、自动重装载及指针增量。
传输模式
1)存储器到外设模式
配置DMA_CCRx寄存器(x由1 ~ 7)的DIR位选择传输方向,该位置1,传输方向为从存储器读;DMA_CCRx寄存器的MEM2MEM位置0,关闭存储器到存储器模式。
2)外设到存储器模式
配置DMA_CCRx寄存器的DIR位选择传输方向,该位置0,传输方向为从外设读;DMA_CCRx寄存器的MEM2MEM位置0,关闭存储器到存储器模式。
3)存储器到存储器模式
数据传输方向为外设地址到存储器地址:DMA_CCRx寄存器的MEM2MEM位置1,使能存储器到存储器模式;DIR位置0,从外设读。
数据传输方向为存储器地址到外设地址:DMA_CCRx寄存器的MEM2MEM位置1,使能存储器到存储器模式;DIR位置1,从存储器读。
注意,存储器到存储器模式不能与循环模式同时使用。
4)循环模式
若需要循环读写缓冲区或进行连续的数据传输,则可以进入循环模式。配置DMA通道x配置寄存器(DMA_CCRx)中的CIRC位为1,使能循环模式。在循环模式下,若DMA传输数量递减为0,则重新加载先前配置的数值,继续进行DMA数据传输。
自动重新加载
DMA通道x配置寄存器(DMA_CCRx)的ARE位控制自动重装载,若ARE位置1,则使能自动重装载传输数量,当DMA通道x传输数量寄存器(DMA_CNDTRx)中数值为0时,会自动将DMA_CNDTRx寄存器中的值加载为之前配置的数值;若ARE位置0,则禁止自动重装载传输数量。
数据宽度
DMA的数据宽度配置包含:存储器数据宽度配置与外设数据宽度配置,可独立配置为字节、半字、全字。
存储器数据宽度由DMA通道x配置寄存器(DMA_CCRx)的MSIZE位控制,MSIZE[1:0]为00则数据宽度为8bit,MSIZE[1:0]为01则数据宽度为16bit,MSIZE[1:0]为10则数据宽度为32bit。
外设数据宽度配置由DMA通道x配置寄存器(DMA_CCRx)的PSIZE位控制,可配置为8bit, 16bit或32bit,MSIZE位与PSIZE位如图2所示。
图2. 数据宽度对应位
存储器/外设地址
DMA的地址配置包含:存储器地址的配置与外设地址的配置。
对DMA通道x存储器地址寄存器(DMA_CMARx)进行赋值,从而配置存储器地址,存储器地址可作为数据传输的源或目标。
对DMA通道x外设地址寄存器(DMA_CPARx)进行赋值,从而配置外设地址,外设地址是外设数据寄存器的基地址,作为数据传输的源或目标。
源和目标地址必须根据各自配置的数据传输宽度对齐。
指针增量
指针增量配置:每次传输后指针自动向后递增或保持不变。
操作DMA通道x配置寄存器(DMA_CCRx)的MINC位,若MINC位置1,则DMA配置为存储器地址递增模式,存储器的访问地址可以按照步长累加,不需要每次都去设置访问地址;若MINC位置0,则每次DMA传输固定访问同一个地址。
设置DMA通道x配置寄存器(DMA_CCRx)的PINC位,若PINC位置1,则DMA配置为外设地址递增模式,外设的访问地址可以按照步长累加;若PINC位置0,则每次DMA传输固定访问同一个地址。
外设或存储器配置为增量模式时,下一个要传输的地址将是前一个地址加上步长,步长取决于所选的数据宽度,首个传输的地址存放在DMA通道x外设地址寄存器(DMA_CPARx)/DMA通道x存储器地址寄存器(DMA_CMARx)中。
优先级
仲裁器根据通道请求的优先级来启动外设或存储器的访问,优先处理软件优先级高的请求,当软件优先级相同时,默认编号更低的通道优先处理。每个通道的优先级可在DMA通道x配置寄存器(DMA_CCRx)中的PL位配置,优先级分为四种:最高优先级(PL[1:0]=11)、高优先级(PL[1:0]=10)、中等优先级(PL[1:0]=01)与低优先级(PL[1:0]=00)。
数据传输数量
数据传输数量的最大值为65535,将数据传输数量值赋值到DMA通道x传输数量寄存器(DMA_CNDTRx),每次传输后,DMA_CNDTRx递减,表示剩余多少次DMA传输。
当数值递减为0时,数据全部传输完毕。若对应通道配置为自动重加载模式时,DMA_CNDTRx寄存器中的内容将被自动重新加载为之前配置时的数值。
中断
每个通道支持3种事件标志:DMA半传输(HTIF)、DMA传输完成(TCIF)和DMA传输出错(TEIF),各通道单独的中断请求由这3种事件标志逻辑或起来。可通过配置DMA通道x配置寄存器(DMA_CCRx)的TCIE位为1使能传输完成中断,配置HTIE位为1使能半传输中断,配置TEIE位为1使能传输错误中断。
三、实验
本实验演示DMA burst搬运模式的中断行为,配置DMA的传输模式为存储器到存储器模式且传输方向为从存储器读,开启自动重装载,宽度配置为全字,指针递增,优先级为低优先级,设置两数组为DMA数据传输地址,配置传输数量为16。DMA配置完成后,进行DMA数据传输,使能DMA通道,当产生半传输中断,设置半传输标志为true,当产生传输完成中断,设置传输完成标志为true,清除中断标志位。本实验可通过串口调试工具观察数据传输现象,当DMA传输已到一半时串口打印"half",当DMA传输完成时串口打印"done"。
启用外设时钟 enable_clock()
实验使用DMA1,并通过UART串口显示实验结果,因此需要启用DMA与UART的外设时钟。
- void enable_clock()
- {
- /* Enable UART1 clock. */
- RCC->APB2ENR |= RCC_APB2_PERIPH_UART1;
- /* Enable GPIOA clock. */
- RCC->AHB1ENR |= RCC_AHB1_PERIPH_GPIOA;
- /* Enable DMA1 clock. */
- RCC->AHB1ENR |= RCC_AHB1_PERIPH_DMA1;
- }
配置引脚 pin_init()
实验现象通过串口显示,因此配置UART的TX(PA9)与RX(PA10)引脚。
- void pin_init()
- {
- /* Setup PA9, PA10. */
- GPIOA->CRH &= ~GPIO_CRH_MODE9_MASK;
- GPIOA->CRH |= GPIO_PinMode_AF_PushPull; /* PA9 multiplexed push-pull output. */
- GPIOA->AFRH &= ~GPIO_AFRH_AFR_MASK;
- GPIOA->AFRH |= (GPIO_AF_1 << GPIO_CRH_MODE9_SHIFT); /* Use AF1. */
- GPIOA->CRH &= ~GPIO_CRH_MODE10_MASK;
- GPIOA->CRH |= GPIO_PinMode_In_Floating; /* PA10 floating input. */
- GPIOA->AFRH |= (GPIO_AF_1 << GPIO_CRH_MODE10_SHIFT); /* Use AF1. */
- }
UART初始化 uart_init()
初始化UART,配置时钟频率、波特率、数据长度、停止位、传输模式及是否使用校验。
|