DMA知识

DMA(Direct Memory Access,直接内存存取)

DMA的英文拼写是“Direct Memory Access”,汉语的意思就是直接内存访问,是一种不经过CPU而直接从内存存取数据的数据交换模式。在DMA模式下,CPU只须向DMA控制器下达指令,让DMA控制器来处理数据的传送,数据传送完毕再把信息反馈给CPU,这样就很大程度上减轻了CPU资源占有率,可以大大节省系统资源。

DMA方式是一种完全由硬件进行组信息传送的控制方式。具有程序中断方式的优点,即在数据准备阶段,CPU与外设并行工作。DMA方式在外设与内存之间开辟一条“直接数据通路”,信息传送不再经过CPU,降低了CPU在传送数据时的开销,因此称为直接存储器存取方式,由于数据传送不再经过CPU,也就不需要保护、恢复CPU现场等繁琐操作。
这种方式适用于磁盘机、磁带机等高速设备大批量数据的传送,它的硬件开销比较大,在DMA方式中,中断的作用仅限于故障和正常传送结束时的处理。
1.DMA方式的特点
主存和DMA接口之间有一条直接数据通路。由于DMA方式传送数据不需要经过CPU,因此不必中断现行程序,I/O与主机并行工作,程序和传送并行工作。
DMA方式具有下列特点:
①它使主存与CPU的固定联系脱钩,主存既可被CPU访问,又可被外存访问。
②在数据块传送时,主存地址的确定、传送数据的计数等由硬件电路直接实现。
③主存中要开辟专用缓冲区,及时供给和接受外设的数据。
④DMA传送数据块,CPU和外设并行工作,提高了系统效率。
⑤DMA在传送开始前要通过程序进行预处理,结束后要通过中断方式进行后处理。
2.DMA控制器的组成
对数据传送过程中进行控制的硬件称为DMA控制器(DMA接口)。当I/O设备需要进行数据传送时,通过DMA控制器向CPU提出DMA传送请求,CPU响应之后让出系统总线,由DMA控制器接管总线进行数据传送。
1)接受外设发出的DMA请求,并向CPU发出总线请求。
2)CPU响应总线请求,发出总线响应信号,接管总线控制权,进入DMA操作周期。
3)确定传送数据的主存单元地址及长度,并能自动修改主存地址计数和传送长度计数。
4)规定数据在主存和外设间的传送方向,发出读写等控制信号,执行数据传送操作。
5)向CPU发送DMA操作的结束。
主存地址计数器:存放要交换数据的主存地址。
传送长度计数器:用来记录传送数据的长度。计数溢出时,数据即传送完毕,自动发出中断请求信号。
数据缓冲寄存器:用于暂存每次传送的数据。
DMA请求触发器:每当I/O设备准备好数据后给出一个控制信号,使DMA请求触发器置位。
“控制/状态”逻辑:由控制和时序电路及状态标志组成,用于指定传动方向,修改传送参数,并对DMA请求信号和CPU响应信号进行协调和同步。
中断机构:当一个数据块传送完毕后触发中断机构,向CPU提出中断请求。
在DMA传送过程中,DMA控制器将接管CPU的地址总线、数据总线和控制总线,CPU的主存控制信号被禁止使用。而当DMA传送结束后,将恢复CPU的一切权利并开始执行其操作。由此可见,DMA控制器必须具有控制系统总线的能力。
3.DMA的传送方式
主存和DMA控制器之间有一条数据通路,因此主存和I/O设备之间交换信息时。不通过CPU。但当I/O设备和CPU同时访问主存时,可能发生冲突,为了有效地使用主存,DMA控制器与CPU通常外用以下三种方式使用主存:
(1)停止CPU访问主存
这种方式是当外设需要传送组数据时,由DMA接口向CPU发送一个信号,要求CPU放弃地址线、数据线和有关控制线的使用权,DMA接口获得总线控制权后,开始进行数据传送,在数据传送结束后,DMA接口通知CPU可以使用主存,并把总线控制权交还给CPU。这种传送过程中,CPU基本处于不工作状态和保持原状态。
(2)DMA与CPU交替访存
这种方式适用于CPU的工作周期比主存存取周期长的情况。例如,CPU的工作周期是1.2us,主存的存取周期小于0.6us,那么可将一个CPU周期分为C1和C2两个周期。其中C1专供DMA访存,C2专供CPU访存。这种方式不需要总线使用权的申请、建立和归还过程,总线使用权是通过C1和C2分时控制的。
(3)周期挪用
这种方式是前两种方式的折中,当I/O设备没有DMA请求时,CPU按程序的要求访问主存,一旦I/O设备有了DMA请求,会遇到3种情况。第一种是此时CPU不在访存(如CPU正在执行乘法指令),故I/O的访存请求与CPU未发生冲突;第2种是CPU正在访存,则必须等待存取周期结束后,CPU再将总线占有权让出。第3种是I/O和CPU同时请求访存,出现了访存冲突,此时CPU要暂时放弃总线占用权,由I/O设备挪用一个或几个存取周期。
4.DMA的传送过程
DMA的数据传送分为预处理、数据传送和后处理3个阶段。
(1)预处理
由CPU完成一些必要的准备工作。首先,CPU执行几条I/O指令,用以测试I/O设备状态,向DMA控制器的有关寄存器置初值,设置传送方向、启动该设备等。然后,CPU继续执行原来的程序,直到I/O设备准备好发送的数据(输入情况)或接受的数据(输出情况)时,I/O设备向DMA控制器发送DMA请求,再由DMA控制器向CPU发送总线请求(有时将这两个过程统称为DMA请求),用以传输数据。
(2)数据传送
DMA的数据传输可以以单字节(或字)为基本单位,对于以数据块为单位的传送(如硬盘),DMA占用总线后的数据输入和输出操作都是通过循环来实现的。需要指出的是,这一循环也是由DMA控制器(而不是通过CPU执行程序)实现的,也就是说,数据传送阶段是完全由DMA(硬件)来控制的。
(3)后处理
DMA控制器向CPU发送中断请求,CPU执行中断服务程序做DMA结束处理,包括检验送入主存的数据是否正确,测试传送过程中是否出错(错误则转入诊断程序)和决定是否继续使用DMA传送其他数据块等。
5.DMA方式和中断方式的区别
DMA方式和中断方式的重要区别:
①中断方式是程序的切换,需要保护和恢复现场,而DMA方式除了预处理和后处理,其他时候不占用CPU的任何资源。
②对中断请求的响应只能发生在每条指令执行完毕时(即指令的执行周期之后),而对DMA请求的响应可以发生在每个机器周期的结束时(在取值周期,间址周期,执行周期之后均可),只要CPU不占用总线就可以被响应。
③中断传输过程需要CPU的干预;而DMA传输过程不需要CPU的干预,故数据传输速率非常高,适合高速外设的成组数据传送。
④DMA请求的优先级高于中断请求。
⑤中断方式具有对异常事件的处理能力,而DMA方式仅局限于传输数据块的I/O操作。
⑥从数据传送来看,中断方式靠程序传送,DMA方式靠硬件传送。

<think>好的,我现在需要处理用户关于GD32F303单片机DMA功能的详细讲解和使用方法的请求。首先,用户之前提到了GD32F407的DMA和DAC相关内容,但现在转向GD32F303,我需要确保回答针对正确的型号。用户可能希望了解GD32F303的DMA配置步骤、与GD32F407的区别以及实际应用示例。我需要查阅GD32F303的参考手册,确认其DMA控制器结构、通道分配、寄存器配置等关键点。接下来,用户可能需要具体的代码示例,比如ADC使用DMA传输。需要确认GD32F303的ADC和DMA的寄存器配置,以及如何初始化DMA通道,设置传输模式等。同时,用户可能对中断处理感兴趣,因此需要说明如何配置DMA中断。 还需要注意用户提到的数学公式格式,确保符合要求,比如使用$...$和$$...$$。此外,生成相关问题时要围绕DMA配置、性能优化、多外设使用等可能的问题。需要检查是否有遗漏点,比如DMA的优先级设置、不同模式的区别,以及常见错误配置导致的后果。最后,确保引用正确,比如引用之前的GD32F407内容作为对比,但明确指出GD32F303的特性。</think>### GD32F303单片机DMA功能详解与配置指南 #### 一.DMA核心特性 GD32F303的DMA控制器支持外设与存储器间高速数据传输,具备以下特性: - 7个独立通道,支持优先级仲裁[^1] - 支持循环传输、外设流控制模式 - 地址递增模式可选(存储器/外设) - 传输数据宽度可配置:$8/16/32$位 - 支持中断触发(传输完成、半传输、错误) #### 二.DMA内部结构 其内部结构包含以下关键模块: $$ \begin{cases} \text{仲裁器} & \text{通道优先级控制} \\ \text{通道寄存器组} & \text{含CCR/CNDTR/CMAR/CPAR} \\ \text{状态寄存器} & \text{ISR/IFCR} \\ \end{cases} $$ #### 三.配置流程(以ADC-DMA为例) ```c // 1. 使能DMA时钟 rcu_periph_clock_enable(RCU_DMA0); // 2. 配置DMA通道参数 dma_parameter_struct dma_init; dma_init.periph_addr = (uint32_t)&ADC_RDATA(ADC0); // 外设地址 dma_init.memory_addr = (uint32_t)adc_value; // 存储器地址 dma_init.direction = DMA_PERIPH_TO_MEMORY; // 传输方向 dma_init.number = 1024; // 传输数据量 dma_init.periph_inc = DMA_PERIPH_INCREASE_DISABLE; // 外设地址不递增 dma_init.memory_inc = DMA_MEMORY_INCREASE_ENABLE; // 存储器地址递增 dma_init.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;// 外设数据宽度 dma_init.memory_width = DMA_MEMORY_WIDTH_16BIT; // 存储器数据宽度 dma_init.priority = DMA_PRIORITY_HIGH; // 通道优先级 dma_init.channel = DMA_CH0; dma_deinit(DMA0, DMA_CH0); dma_init(DMA0, DMA_CH0, &dma_init); // 3. 配置DMA中断 dma_interrupt_enable(DMA0, DMA_CH0, DMA_INT_FTF); // 传输完成中断 nvic_irq_enable(DMA0_Channel0_IRQn, 0, 0); // 4. 使能DMA通道 dma_channel_enable(DMA0, DMA_CH0); ``` #### 四.关键寄存器说明 1. **DMA_CCRx** 通道配置寄存器: - MEM2MEM: 存储器到存储器模式 - PL[1:0]: 优先级设置 - CIRC: 循环模式 - DIR: 传输方向 2. **DMA_CNDTRx** 计数器: $$ \text{剩余传输量} = \text{初始值} - \text{已完成传输数} $$ 3. **DMA_ISR** 状态寄存器: - TCIFx: 传输完成标志 - HTIFx: 半传输标志 - TEIFx: 传输错误标志 #### 五.性能优化技巧 1. 使用双缓冲技术提升传输效率: ```c #define BUF_SIZE 512 uint16_t buffer1[BUF_SIZE], buffer2[BUF_SIZE]; void DMA_IRQHandler() { if(dma_interrupt_flag_get(DMA0, DMA_CH0, DMA_INT_FLAG_FTF)) { // 切换缓冲区 static uint8_t buf_sel = 0; dma_memory_address_config(DMA0, DMA_CH0, buf_sel ? (uint32_t)buffer1 : (uint32_t)buffer2); buf_sel = !buf_sel; } } ``` 2. 对齐优化原则: - 32位传输时地址应对齐到4字节边界 - 使用`__align(4)`修饰缓冲区变量 #### 六.常见问题处理 1. **传输停滞**: - 检查外设是否持续产生请求(如ADC的连续模式) - 验证DMA_CNDTRx是否递减到0 2. **数据错位**: - 确认外设与存储器的数据宽度匹配 - 检查地址递增模式设置 --- ### 相关问题 1. 如何实现DMA与定时器触发的外设配合使用? 2. DMA传输过程中如何保证数据一致性? 3. GD32F303的DMA与GD32F407在通道分配上有何差异? 4. 如何通过DMA实现多外设并行数据采集? 5. DMA传输超时检测应如何实现?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值