1 DMA模块图
DMA模块图如下图所示
DMA控制器通过与其他系统主设备共享AHB总线来执行直接内存传输。总线矩阵实现轮询调度。当CPU和DMA瞄准同一目标(内存或外设)时,DMA请求也许会在多个总线周期内停止CPU对系统总线的访问。
根据AHB从机接口的配置,DMA控制器在DMA通道和其相关的接收请求之间进行仲裁。DMA控制器还可以通过单个AHB主机接口调度DMA数据传输。
DMA控制器为中断控制器的每个通道产生一个中断。
2 DMA传输
软件可以配置DMA控制器的各个通道,以执行有AHB总线传输序列组成的块传输。
DMA块传输可以从外设发出请求,或者在内存到内存传输时由软件触发。
事件发生后,单个DMA传输将执行以下步骤:
- 外设向DMA控制器发送单个DMA请求信号
- DMA控制器根据与该外设相关通道的的优先级来处理请求
- 一旦DMA控制器授权外设,DMA控制器会向外设发送一个确认信号
- 外设收到DMA控制器的确认信号后悔立即释放请求
- 一旦外设取消请求,DMA控制器就会释放确认信号
外设可以发送另一个请求并初始化另一个单个DMA传输。
当外设是传输的院或者目标时,使用请求/确认协议。例如,内存到外设的情况下,外设驱动其单个请求至DMA控制器来启动传输。DMA读取内存中单个数据,将该数据写入外设。
对于给定的通道x,DMA块传输包含以下重复序列:
-
单个DMA传输,通过DMA AHB总线主机凤凰组昂单个数据的两次AHB传输
-
从外设数据寄存器或内存中某个位置读取单个数据(字节、半字或字),通过内部外设/内存地址寄存器进行寻址。
第一次单个传输的起始地址是外设或者内存的基地址,并在DMA_CPARx或者DMA_CMARx寄存机中配置。
-
将单个数据(字节、半字或字)写入外设数据寄存器或内存中某一位置,通过内部外设/内存地址寄存器进行寻址。
第一次传输的起始地址是外设或者内存的基地址,并在DMA_CPARx或者DMA_CMARx寄存机中配置。
-
-
已编程的DMA_CBDTRx寄存器递减。改寄存器包含要传输的数据项的剩余数量(AHB先读后写传输的数量)。
这个序列重复,直到DMA_CNDTRx寄存器为空。
注意:AHB主机总线源/目标地址必须和传输到源/目标的单个数据的编程大小对齐。
3 DMA仲裁
DMA仲裁器管理不同通道之间的优先级。
当仲裁器允许一个激活通道x(硬件请求或软件触发)时,将发出单个DMA传输(例如单个数据的AHB先读后写传输)。随后,仲裁器再次考虑激活通道组,并选择其中一个优先级最高的通道。
优先级被分为2个阶段管理:
- 软件:各个通道的优先级通过DMA_CCRx寄存器配置,分为4个等级:
- 非常高
- 高
- 中等
- 低
- 硬件:如果两个请求具有相同的软件优先级,具有最小索引值的通道获胜。例如,通道2的优先级高于通道4。
当通道x被编程用作内存到内存的块传输时,该通道的每个单个DMA传输之间都会考虑重新仲裁。没当存在另一个并发激活请求通道时,DMA仲裁器会自动交替并允许另一个最高优先级请求的通道,该通道的优先级可能低于内存到内存通道的优先级。
4 DMA通道
每个通道也许处理位于固定地址的外设寄存器和内存地址之间的DMA传输。要传输的数据项的数量也是可编程的。每次传输后,改寄存器数值会递减。
DMA通道在块传输级别编程。
可编程数据尺寸
外设到内存的单个数据(字节、半字或字)的传输尺寸,分别由DMA_CCRx寄存器中的PSIZE[1:0]和MSIZE[1:0]进行编程。
指针增加
每次传输后,外设和内存的指针也许会自动增加,取决于DMA_CCRx中的PINC和MINC位。
如果递增模式被使能(PINC和MINC设置为1),下次传输的地址是上次传输地址加1/2或4,具体取决于PSIZE和MSIZE中配置的数据尺寸。第一个传输的地址是DMA_CPARx或DMA_CMARx寄存器中配置的地址。在传输过程中,这些寄存器保持最初的配置值。当前传输的地址(在当前内部外设/内存地址寄存器中)不能通过软件访问到。
如果通道x被配置为非循环模式,在最后一次数据传输之后(一旦要传输的单个数据的数量达到零)将不在处理DMA请求。为了将新的数据项数量重新加载进DMA_CNSTRx寄存器中,DMA通道需要被禁用。
注意:如果通道x被禁用,DMA寄存器不会被复位。
在循环模式中,最后一次数据传传输之后,DMA_CNDTRx寄存器自动重新加载为初始编程值。当前内部地址寄存器重新加载为DMA_CPARx和DMA_CMARx寄存器中的基地址。
通道配置流程
配置通道x需要以下过程:
-
在DMA_CPARx寄存器中设置外设寄存器地址
在外设事件之后,或者在内存到内存模式使能之后,数据从改地址转移至内存或者从内存转移至内存。
-
在DMA_CMARx寄存器中设置内存地址
在外设事件之后,或者在内存到内存模式使能之后,数据写到内存或从内存读取。
-
在DMA_CNDTRx寄存器中配置所有数据传输的数量
每次传输之后,该值递减。
-
在DMA_CCRx中配置相关参数
- 通道优先级
- 数据传输方向
- 循环模式
- 外设和内存递增模式
- 外设和内存数据尺寸
- 半传输、传输完成、传输错误中断使能
-
通过设置DMA_CCRx中的EN位来激活通道。
通道一旦激活启用,就可以开始处理连接到该通道的外设的任何DMA请求,或者可以启动内存到内存的块传输。
注意:通道配置过程的最后两个步骤可以合并为对DMA_CCRx寄存器的单次访问,去配置和使能通道。
通道状态和通道禁用
处于激活状态的通道x是启用的通道(读取DMA_CCRx.EN位为1)。激活通道必须由软件激活,并且随后没有发生传输错误(DMA_ISR.TEIFx=0)。假设出现传输错误,通道由硬件自动禁用(DMA_CCRx.EN=0)。
可能会发生以下三种情况:
-
挂起和恢复通道
对应以下两个操作:
- 激活通道由软件禁用(DMA_CCRx.EN写0)
- 软件再次启用通道,并且未配置其他通道寄存器(DMA_CNDTRx,DMA_CPARx,DMA_CMARx)。
DMA硬件不支持这种情况,因此不能保证剩余的数据传输正常执行。
-
停止并中断通道
如果应用程序不再需要该通道,可以通过软件来禁用该通道。该通道被停止并中断,但是DMA_CNDTRx寄存器的内容也许不能正常反应剩余数据传输和终止的源或者目标缓存/寄存器的情况。
-
终止并重启通道
对应的软件顺序:禁用一个通道,然后配置并重新使能该通道。
如果满足以下情况,硬件支持该功能:
- 应用程序保证当软件仅用该通道时,与此同时在其主端口上没有DMA数据传输。例如,应用程序可以再DMA模式下禁用外设,以确保没有来自该外设挂起的DMA请求。
- 软件必须对同一DMA_CCRx寄存器进行单独写访问:首先禁用通道。其次,如果需要变更配置,重新配置下一个块传输的配置,包括DMA_CCRx。最终再次使能通道。
当通道发生传输错误时,DMA_CCRx.EN由硬件清零。在DMA_ISR.TEIFx位没有置位之前,软件无法置位EN并重新激活通道。
循环模式(内存到外设/外设到内存传输)
循环模式可以用于处理循环缓存区和连续数据流(例如ADC扫描模式)。该功能可以通过DMA_CCRx.CIRC位来配置。
注意:循环模式不能应用于内存到内存模式。在使能通道为循环模式之前,软件必须要清除DMA_CCRx.MEM2MEM位。当循环模式被激活,要传输的数据数量会重新加载到配置通道阶段的初始值,DMA请求会被继续执行。
为了停止循环传输,软件需要禁用DMA通道之前停止外设产生请求(例如停止ADC扫描模式)。
软件必须在开始/使能传输之前,或者停止循环传输之后,显示编程的DMA_CNDTRx的值。
内存到内存模式
DMA通道可以再没有外设请求触发的情况下运行。这种模式称为内存到内存模式,由软件启动。
如果DMA_CCRx中MEM2MEM位设置为1,通道将启动传输。当DMA_CNDTRx值为0时,传输停止。
注意:的内存到内存模式不能应用于循环模式。在内存到内存模式启动之前,软件必须清楚DMA_CCRx.CIRC位。
外设到外设模式
任何DMA通道可以执行外设到外设模式:
-
当来自外设的硬件请求被选中去触发DMA通道
该外设是DMA启动器,并调节从该外设到另一个内存映射外设,或者从另一个内存映射外设到该外设的数据传输,另一个从内存映射外设是DMA模式下未配置的。
-
当没有外设请求被选中并连接到DMA通道
软件配置一个寄存器到寄存器的传输,通过设置MEM2MEM为1。
配置传输方向,确定源和目标
DMA_CCRx中DIR位来设置传输方向,无论源和目标的类型,它定义了源和目标
-
DIR=1定义了典型的内存到外设传输。如果DIR=1:
-
源属性由DMA_MARx寄存器和DMA_CCRx中的MSIZE、MINC来定义。
无论怎么命名,这些内存寄存器、字段和位都用来定义源外设,在外设到外设模式中。
-
目标属性由DMA_PARx寄存器和DMA_CCRx中的PSIZE、PINC来定义。
无论怎么命名,这些内存寄存器、字段和位都用来定义目标外设,在内存到内存模式中。
-
-
DIR=0定义了典型的外设到内存传输。如果DIR=0:
-
源属性由DMA_PARx寄存器和DMA_CCRx中的PSIZE、PINC来定义。
无论怎么命名,这些内存寄存器、字段和位都用来定义目标外设,在内存到内存模式中。
-
目标属性由DMA_MARx寄存器和DMA_CCRx中的MSIZE、MINC来定义。
无论怎么命名,这些内存寄存器、字段和位都用来定义目标外设,在外设到外设模式中。
-
5 DMA数据位宽、对齐方式和大小端
DMA控制器根据OSIZE和MSIZE取值不同执行不同的对齐方式。
寻址不支持字节/半字写传输的AHB外设
当DMA控制器启动了一个AHB字节/半字传输,数据将在AHB主32位总线的未使用通道上复制。
当AHB总计外设不支持字节/半字写传输并且不产任何错误时,DMA控制器将写入32位HWDATA,如下面两个示例所示:
- 要写入半字0xABCD,DMA控制器设置HWDATA总线为半字数据大小(AHB总线中HSIZE设置为半字)数据为0xABCDABCD。
- 要写入字节0xAB,DMA控制字设置HWDATA为0xABABABAB,HSIZE设置为字节。
假设AHB/APB桥是一个不考虑HSIZE的AHB32位从外设,则任何AHB字节/半字传输都会改为32位APB传输:
- AHB字节写传输0xB0到0x0/0x1/0x2/0x3之间的一个地址,会被转换为APB的一个字传输0xB0B0B0B0写到0x0地址。
- AHB半字写传输0xB1B0到0x0/0x2之间的一个地址,会被转换为APB的一个字传输0xB1B0B1B0写到0x0地址。
6 DMA错误管理
当从保留地址读取或写入数据时,将会产生DMA传输错误。在DMA读或写访问过程中发生DMA传输错误时,错误通道x自动禁用,通过硬件清除DMA_CCRx中的EN位。
DMA_ISR中的TEIFx位设置为1。如果DMA_CCRx中TEIE位为1时,会产生一个中断。
DMA_CCRx中EN位不能被软件再次置一,在DMA_ISR中TEIF清除之前。
当软件收到涉及外设的通道上传输错误通知时,软件必须首先在DMA模式下停止该外设,一遍禁用任何挂起的或者未来的DMA请求。然后软件可以在DMA模式下重新配置新的传输的配置。
7 中断
每个DMA通道可以产生半传输、传输完成和传输错误的中断。为了灵活性,中断有单独的使能位。