文章目录
[0x100] 特性概述
- DMAC是高级微控总线结构(AMBA),通过两个主AHB总线传输数据,一个备AHB总线编程控制;
- 共有 两个通道DMAC,每次可以缓存4字(8字节);
- 支持 16个 DMA单向的请求信道,且每个信道可以为终端计数和传输错误生成独立的中断掩码;
- 支持可编程的 单独DMA请求 或者 爆发DMA请求;
- 支持内存->内存、内存->外设、外设->内存、外设->外设的传输;
- 链表的聚集与发散的DMA支持;
- DMA 信道优先级 信道0 优先级最高,信道7 优先级最低,高优先级信道先服务;
- 源和目标的递增或非递增寻址;
- FIFO方式的可编程的突发DMA传输容量;
- 支持 大端或者小端 的 8位/16位/32位的传输事项,默认为小端模式;
- 独立与联合的DMA错误与DMA请求计数,形成三种中断DMACINTTC、DMACINTERR、DMACINTR;
- RAW 中断状态 优先于 中断掩码;
- 拥有集成的测试寄存器和操作系统自动配置的标识寄存器;
[0x200] 操作条件
- 已经激活的DMA channel 且 channel enable 为 高电平时,不能执行写操作,不能重新编程;
- 如果 源位宽 小于目标位宽,传输数据容量必须是源位宽的倍数,且为目标位宽的整数倍;
- 需指定 DMACLSREQ or DMACLBREQ 为源/目的位宽的整数倍,否则将放弃数据并会引发 ”UNPREDICTABLE “;
- 寄存器(DMACCxCONFIG)中的这两个数值(SRCPERIPHERAL and DESTPERIPHERAL)配置不能超过15;
- 寄存器(DMACCxCONFIG)中的这两个数值(SWIDTH and DWIDTH) 不能超过32位的外设宽度;
- 寄存器(DMACCxCONFIG)清空 Channel Enable 位 来软关闭一个信道,需要一个延迟 AHB burst;
- 寄存器(DMACENBLDCHNS) 重启需要写0 到这个寄存器;
- 寄存器(DMACCxLLIREG) 声明的地址不能超过 0xFFFFFFF0,否则 LLI data structure 将不会连续放置到内存中;
- 如果设置的传输深度大于源/目的外设FIFO,DMAC不能设置生成递增地址;
- 在接收到DMACCLR信号时,将取消置位任何DMACSREQ,DMACBREQ,DMACLSREQ或DMACLBREQ信号 ;
- DMACCLR 不是单独请求的信号,DMACSREQ, 或者突发信号,DMACSBEQ,是DMA上逻辑或;
- DMACCLR 为高电平,生成新的DMACSREQ or DMACBREQ,是不合法的;
- DMAC 是流模式时,寄存器(DMACCxCONFIG)中的Transfer Size field =0 时,将不会初始化或者传输任何数据;
- 寄存器(DMACCxCONFIG)不是一个 典型写与读回寄存器,
- 写入时,类似一个控制寄存器,决定需要DMAC执行传输次数;
- 读回时,类似一个状态寄存器,读取多少周期源位宽的数据,返回存储在(TRFSIZEDST)中的目的完成数乘以因子。;
- 在目标流控制模式且外设到外设的传输:
- 如果FIFO中存在足够的数据来服务目标外设引发的DMACLSREQ或DMACLBREQ请求,而不需要从源外设获取数据
- 目的为流控模式状态下且 DWIDTH < SWIDTH 时,传输数据必须是源位宽的整数倍,否则将丢失数据;
当访问低优先级信道结束时, 一个IDLE周期插入AHB总线来开启其它主信道访问总线. 这样可以确保低优先级信道不会一直占用总线. 最差的情况下,意味着低优先级信道会占用总线至多16个周期. 这个应用包括内存到内存传输;
[0x300] 流程描述
DMAC 支持以下类型事务:
- 内存 ->内存 (Memory-to-memory)
- 内存 ->外设 (Memory-to-peripheral)
- 外设 ->内存(Peripheral-to-memory)
- 外设 ->外设(Peripheral-to-peripheral)
每个DMA 流是被配置为一对一的单向的DMA传输,但是对于一个双向的传输是一个流传输与一个流接收;源与目的的区域可以内存区域、外设,你可以访问使用相同AHB主线,或者每个区域一个AHB主线;DMAC的基地址不是固定的,对于任何系统部署不同的地址,但是基于基地址的任何偏移都是固定的;
[0x310] DMA控制器和DMA信道
[0x311]DMAC的寄存器
- 保留和未使用的地址位置是不可访问的,因为返回的结果可能是不可预知的;
- 保留和未使用的地址位必须被写为0, 除非另有文本说明;
- 系统或者电源重置状态的寄存器将会被逻辑0 填充;
- 所有的寄存器都支持读写,写是用来更新寄存器中数值的,读是用来返回寄存器中数值的;
- 访问寄存器都是一个字的读取或者写入,除非另有文本说明;
[0x312]启动DMA控制器
通过置位 DMAenable 和 E位,可以看看寄存器 Configuration Register 章节
[0x313]关闭DMA控制器
关闭DMAC信道与DMAC控制器:
DMACENBLDCHNS_ADDR = 0xC000_101C ;
- 读取寄存器(DMACENBLDCHNS)确保你关闭了所有的DMA信道,如果有任何信道是激活状态。
一个只读寄存器的偏移地址是 0x01C, 声明了在寄存器(DMACCxCONFIGURATION) 位标识为高的信道, 启用的信道的在这里标识为1. DMA传输结束时,处于寄存器(DMACENBLDCHNS)的位将会被清除; - 通过清除 DMAenable 和 E位,可以看看寄存器 Configuration Register 章节。
[0x314]启动DMA信道
NOTE: 启用信道前,必须启用DMAC控制器和初始化信道
初始化信道与启用信道 可以查看 Channel Control Registers (0 to 7) 章节.
[0x315]关闭DMA信道
-
直接写入 0到对应信道的 Channel Control Registers E 位,来关闭DMA信道;
NOTE: 使用这种方法,你会失去所有不在FIFO中的数据; -
使用 Active位 和 Halt 位 联合关闭或者启用 信道,等待DMA传输完成. 信道会自动的关闭.
H [18] RW Halt: 此位用于标识是否接受 DMA请求,可以配合Active位使用,1即为挂起,0= 启用DMA信道; 0 = Enable DMA requests 1 = Ignore extra source DMA requests. A [17] R Active: 用于检测是否存在待传输数据,可以配合Halt 位使用; 0 = There is no data in the FIFO of the channel 1 = The FIFO of the channel has data.
[0x316]不丢弃FIFO数据关闭 DMA信道
- 设置处于Channel Control Registers 章节中的H 位,此位为引发DMA请求忽略的子集,即挂起信道;
- 轮询处于Channel Control Registers 章节中的A 位,直到此位为0,该位用于标识是否存在待传输数据;
- 清空处于Channel Control Registers 章节中的E 位,关闭信道启用;
[0x317]配置新的DMA传输事项
- 如果信道没有设置为传输选项:
读取寄存器(Enabled Channel Register)中DMACENBLDCHNS 位 ,确定信道是否启用
为非激活的信道选择一个必要的优先级; - 编程DMA控制器.
[0x317]配置DMA信道
- 选择空闲优先级到DMA信道,通常信道号码越小,优先级越高,所以信道0 最高 信道7最低;
- 通常需要清空中断的抑制,之前的信道操作有可能会留下激活的中断,(INTTCCLEAR and INTERRCLR) ;
- 寄存器(DMACCxSRCADDR )写入源地址;
- 寄存器(DMACCxDESTADDR )写入目的地址;
- 寄存器(CHANNEL LINKED LISTITEM REGISTERS)写入下一个信道链表项目(Channel Linked List Item); 单包传输需要写入0;
- 寄存器(DMACCxCONTROL )写入控制信息;
- 寄存器(DMACCxCONFIGURATION) 写入信道配置信息,Enable位如果被设置,DMA信道将自动可用;
[0x320] 发散DMA/聚集DMA(Scatter/gather)
- 发散DMA/聚集DMA是通过链表实现的. 这意味着目标区域与源区域不能占用连续的内存.。
- 如果不需要发散DMA/聚集DMA,将寄存器 (DMACCxLLI)设置为0;
链表项目所需的结构共有4种字大小的数据,组织顺序如下:
- 寄存器(DMACCxSCRADDR) 数据指向源地址;
- 寄存器(DMACCxDESTADDR)数据指向目的地址;
- 寄存器(DMACCxLLI)数据指向下一个链表项目;
- 寄存器(DMACCxCONTROL)数据指向信道控制信息;
NOTE: 寄存器(DMACCxCONFIGURATION) 信道配置信息寄存器不是 链表项目(LLI)的一部分.
[0x321]编程DMAC 使用 Scatter/Gather DMA功能
链表项目写入内存完善DMA传输数据, 每个链表项目包括以下4个字的数据:
- 源地址
- 目的地址
- 指向下一个LLI的指针
- 信道控制信息
- LLI 的最后一个项目需要使用空项目来结尾;
- 空闲的DMA信道请求优先级. 0~7 越小越优先;
- 写入第一个LLI 项目到内存;
- 向寄存器(channel configuration register)中写入信道配置信息,然后设置启用信道(Channel Enable);
- DMAC 将载入所有 LLI 项目,然后一个接着一个的传输数据;
- 每个LLI 传输结束将生成一个中断,中断依赖寄存器(DMACCxCONTROL):[Terminal Count]位;
- 处理中断请求并先清除中断于寄存器(DMACINTTCCLEAR):[INTTCCLEAR] 位;
[0x322] 操作 LLI 使用 Scatter/Gather DMA 功能
- 链表定义了源和目的的数据区域,每个LLI控制传输一块数据,并且可以选择是否需要继续DMA操作
- LLI 描述了一个需要传输的数据,源与目的通常会请求一个或者多个突发的DMA请求;
LLI 例子:图中长方形区域为一个 LLI 描述了需要传输的数据,LLI存储于起始0x20000地址的连续地址空间中;
第一个LLI存储于 0x20000, 定义了需要传输的数据存储于 0x0A200 and 0x0AE00之间:
- 源起始地址: 0x0A200;
- 目的地址被设置为外设地址;
- 传输位宽: 字,32位;
- 传输大小: 3072 字节, 0xC00;
- 源目的突发容量 16 个;
- 下一个LLI地址, 0x20010;
第二个LLI存储于 0x20010, 定义了下一块需要传输的数据:
- 源起始地址: 0x0B200;
- 目的地址被设置为外设地址;
- 传输位宽: 字,32位;
- 传输大小: 3072 字节, 0xC00;
- 源目的突发容量 16 个;
- 下一个LLI地址, 0x20020;
构建了一个链状的描述方式,每个LLI指向下一个需要传输的数据,初始化的DMA流,第一个LLI地址是 0x20000指定到DMAC中。当第一个数据包传输完成后,将自动加载下一个LLI;
最后的LLI存储于 0x20070, 包含:
- 源起始地址: 0x11200;
- 目的地址被设置为外设地址;
- 传输位宽: 字,32位;
- 传输容量: 3072 字节, 0xC00;
- 源目的突发容量 16 个;
- 下一个LLI地址, 0x0;
因为最后一个项目数据是0,最后一个描述符,当最后一个数据被传输完毕后将关闭DMA信道,信道也有可能生成一个中断发送给ARM处理器.来通知信道需要重新编程处理;
[0x330] 中断请求
AHB错误、传输结束、当前所有的LLI相关的数据都传输到目标的终端计数、将产生中断,以下寄存器可以屏蔽中断:
DMACCxCONTROL and DMACCxCONFIGURATION
在中断屏蔽之前对来自所有DMA通道的中断请求进行分组:
DMACRAWINTTCSTATUS,DMACRAWINTERRORSTATUS
在中断屏蔽之后对来自所有DMA通道的中断请求进行分组:
DMACINTTCSTATUS, DMACINTERRORSTATUS
DMACINTTCSTATUS and DMACINTERRORSTATUS 请求 联合到寄存器( DMACINTSTATUS),来迅速的发现源中断:
写一个高位到以下寄存器可选择的清除中断:
( DMACINTTCCLEAR 或者 DMACINTERRCLR)
DMAC 提供了两种中断主题. 联合错误 和 数据传输完成请求. 发现一个源中断读取这两个寄存器 :
(DMACINTSTATUS and DMACINTTCSTATUS).
对于快速的中断响应, 这个项目用于独立的源中断请求 错误 和 传输完成,有如下两种选择:
DMACINTTCSTATUS orDMACINTERRORSTATUS
[0x331] 联合 终端计数与错误终端 的次序流
当你使用 中断请求 “DMACINTR ”:
- 你必须等待DMAC 激活联合中断请求. 假设中断被启用在 中断控制器中 跳转处理器分支的中断向量表 并进入处理流程;
- 你必须读取中断控制器的状态寄存器,来确定中断源是否来源于DMAC;
- 检查寄存器(DMACINTSTATUS)来确定是由哪个信道产生的中断,如果有多个请求,先检查高优先级那个信道;
- 检查寄存器 (DMACINTTCSTATUS)来确定哪种中断被生成,传输结束(高位标识)、终端计数、错误;
- 检查寄存器 (DMACINTERRORSTATUS)来确定哪种中断被生成,传输结束(高位标识)、终端计数、错误;
- 写1到寄存器(DMACINTTCCLEAR, or DMACINTERRCLR)相关位, 清除中断请求;
[0x332]终端计数中断次序流
当使用单独的DMACINTTC和DMACINTERR中断请求时:
- 你必须等待DMAC 激活计数中断请求. 假设中断被启用在 中断控制器中 跳转处理器分支的中断向量表 并进入处理流程;
- 你必须读取中断控制器的状态寄存器,来确定中断源是否来源于DMAC捕获的信号 DMACINTTC.
- 检查寄存器(DMACINTTCSTATUS)来确定是由哪个信道产生的中断,如果有多个请求,先检查高优先级那个信道
- 处理中断请求;
- 写1到寄存器(DMACINTTCCLEAR)相关位, 清除中断请求;
[0x332]错误中断次序流
当使用单独的DMACINTTC and DMACINTERR中断请求时:
- 等待DMAC 激活信道错误中断请求. 假设中断被启用在 中断控制器中 跳转处理器分支的中断向量表 并进入处理流程;
- 你必须读取中断控制器的状态寄存器,来确定中断源是否来源于DMAC捕获的信号 DMACINTERR.
- 检查寄存器(DMACINTERRORSTATUS)来确定是由哪个信道产生的中断,如果有多个请求,先检查高优先级那个信道;
- 处理中断请求;
- 写1到寄存器(DMACINTERRCLR)相关位, 清除中断请求;
[0x333]中断轮询次序流
屏蔽了DMAC 中断请求,在中断控制器中阻止拦截或者在CPU中拦截;
当你轮询DMAC的时:
- 检查寄存器(DMACINTSTATUS )如果没有高位将循环, 否则执行步骤2,如果有多个请求,先检查高优先级那个信道;
- 检查寄存器 (DMACINTTCSTATUS)来确定哪种中断被生成,传输结束(高位标识)、终端计数、错误;
- 处理中断请求;
- 如果是错误中断,写1到寄存器(DMACINTERRCLR)相关位, 如果是计数中断,写1到寄存器(DMACINTTCCLEAR)相关位清除中断请求;
[0x340] DMA控制器数据流
[0x341]内存到内存的DMA流
-
配置并启用DMA通道;
-
传输数据时DMA信道总是有最高的代决优先权,DMAC获取AHB总线的总控权;
-
传输过程中,如果错误发生,将生成一个错误中断并关闭数据传输;
-
减少已经传输的计数;
-
如果终端计数到达0;
- 生成一个终端计数中断,并屏蔽该种类中断; - 如果寄存器(DMACCxLLI)不是0,载入下一条LLI并返回步骤2执行,如果寄存器(DMACCxLLI)是0,关闭流;
[0x342]内存与外设之间的DMA流
-
配置并启用DMA通道;
-
等待DMA请求;
-
DMAC开始传输数据条件:
- 存在激活的DMA请求. - DMA流拥有最高的代决优先权; - DMAC获取AHB总线的总控权;
-
传输过程中,如果错误发生,将生成一个错误中断并关闭数据传输;
-
如果是DMAC 发送的情况下,减少已经传输的计数;
-
如果DMAC 为控制流传输,终端计数为0,或者外设设置信号 (DMACLBREQ or DMACLSREQ ),将结束流传输;
- DMAC 捕获信号 DMACTC; - 生成一个终端计数中断,并屏蔽该种类中断; - 如果寄存器(DMACCxLLI)不是0,载入下一条LLI并返回步骤2执行,如果寄存器(DMACCxLLI)是0,关闭流;
[0x342]外设与外设之间的DMA流
-
配置并启用DMA通道;
-
等待源DMA请求.
-
DMAC开始传输数据条件:
- 存在激活的DMA请求. - DMA流拥有最高的代决优先权; - DMAC获取AHB总线的总控权;
-
传输过程中,如果错误发生,将生成一个错误中断并关闭数据传输;
-
如果是DMAC 发送的情况下,减少已经传输的计数;
-
如果DMAC 为控制流传输,终端计数为0,或者外设设置信号 (DMACLBREQ or DMACLSREQ ),将结束流传输;
- The DMAC 捕获信号DMACTC来自于源外设; - 之后DMA请求将会忽略;
-
当存在目标DMA请求且需要传输的数据处于DMACFIFO,将传输数据到目标外设;
-
如果传输过程发生错误,将生成错误中断,并停止传输操作,终结流;
-
如果是DMAC 发送的情况下,减少已经传输的计数;
-
如果DMAC 为控制流传输,终端计数为0,或者外设设置信号 (DMACLBREQ or DMACLSREQ ),将结束流传输;
- DMAC 捕获信号 DMACTC; - 生成一个终端计数中断,并屏蔽该种类中断; - 如果寄存器(DMACCxLLI)不是0,载入下一条LLI并返回步骤2执行,如果寄存器(DMACCxLLI)是0,关闭流;
[0x400]寄存器的描述
DMA1_Base_addr = 0xC000_0000
DMA1_Base_addr = 0xC000_1000
[0x410]中断相关寄存器
寄存器名称 | 访问权限 | 基地址偏移 | 寄存器描述 |
---|---|---|---|
DMACINTSTATUS | RO | 0x00 | 后于中断屏蔽的中断状态寄存器,高位表示错误或者终端计数激活的DMA信道中断; |
DMACINTTCSTATUS | RO | 0x04 | 后于中断屏蔽的计数状态寄存器,可与寄存器(DMACINTSTATUS)生成联合中断请求; |
DMACINTTCCLEAR | WO | 0x08 | 清除计数中断请求寄存器,向对应位写入HIGH 清除对应的中断状态寄存器; |
DMACINTERRORSTATUS | RO | 0x0C | 后于中断屏蔽的错误状态寄存器,可与寄存器(DMACINTSTATUS)生成联合中断请求; |
DMACINTERRCLR | WO | 0x10 | 清除错误中断请求寄存器,写入HIGH位 清除对应的中断状态寄存器; |
DMACRAWINTTCSTATUS | RO | 0x14 | 优先于屏蔽的DMA信道请求传输完成、终端计数的状态寄存器,HIGH=激活的终端计数中断请求; |
DMACRAWINTERRORSTATUS | RO | 0x18 | 优先于屏蔽的DMA信道请求错误的状态寄存器,HIGH=激活的错误中断请求; |
DMACENBLDCHNS | RO | 0x1C | HIGH = 寄存器(DMACCxCONFIGURATION)对应DMA信道启用,完成传输时,该位将被清除; |
DMACSOFTBREQ | RW | 0x20 | 软生成或者被动检测DMA突发请求源,写1到寄存器对应位生成软请求,事务处理完成将被清除 |
DMACSOFTSREQ | RW | 0x24 | 软生成或者被动检测DMA独立请求源,写1到寄存器对应位生成软请求,事务处理完成将被清除 |
DMACSOFTLBREQ | RW | 0x28 | 软生成或者被动检测DMA最终突发请求源,写1到寄存器对应位生成软请求,事务处理完成将清位 |
DMACSOFTLSREQ | RW | 0x2C | 软生成或者被动检测DMA最终独立请求源,写1到寄存器对应位生成软请求,事务处理完成将清位 |
[0x420]通讯相关寄存器
寄存器名称 | 访问权限 | 基地址偏移 | 寄存器描述 |
---|---|---|---|
DMACCONFIGURATION | RW | 0x30 | DMAC配置寄存器,设置M1和M2 来选择 AHB主端口1和 AHB主端口2 的选择主机字节序,默认为小端 |
DMACSYNC | RW | 0x34 | 特定DMA组请求信道同步逻辑寄存器,0=启用同步 1=关闭同步,默认是0 |
DMA请求信号组成:
- DMACBREQ[15:0]
- DMACSREQ[15:0]
- DMACLBREQ[15:0]
- DMACLSREQ[15:0]
NOTE:
- 当 DMACCLR = HIGH 时,外设会发送信号(DMACSREQ or DMACBREQ);
- 当外设的时钟与DMAC的时钟不一致时,需要启用同步逻辑;
- 当外设的时钟与DMAC的时钟一致时,关闭同步逻辑将会提升DMAC的响应速度;
- 如果必要的话,同步DMA的响应信号( DMACCLR and DMACTC)到外设中。
[0x430]信道参数寄存器
寄存器名称 | 访问权限 | 基地址起始偏移 | 寄存器描述 |
---|---|---|---|
DMACCxSRCADDR | RW | 0x100 | 字节对齐的当前源地址,递增源地址,基于LLI跟踪数据包的传输情况,通道工作时不提供有效数据 |
DMACCxDESTADDR | RW | 0x104 | 字节对齐的当前目的地址,递增目的地址,基于LLI跟踪数据包的传输情况,通道工作时不提供有效数据 |
DMACCxLLI | RW | 0x108 | 字对齐的下一条LLI地址,如果该寄存器=0 则等待所有绑定的DMA传输结束时,关闭DMA信道 |
编程DMA信道需要配置以下寄存器,中括号地址为每个信道的偏移:
- 8* DMACCxSRCADDR [0x100, 0x120, 0x140, 0x160, 0x180,0x1A0, 0x1C0, and 0x1E0 ]
- 8* DMACCxDESTADDR [0x104, 0x124, 0x144, 0x164, 0x184,0x1A4, 0x1C4, and 0x1E4 ]
- 8* DMACCxLLI [0x108, 0x128, 0x148, 0x168, 0x188, 0x1A8,0x1C8, and 0x1E8 ]
- 8* DMACCxCONTROL [0x010c, 0x12c, 0x14c, 0x16c, 0x18c, 0x1ac,0x1cc, and 0x1ec]
- 8* DMACCxCONFIGURATION [0x110, 0x130, 0x150, 0x170, 0x190, 0x1B0,0x1D0, and 0x1F0]
NOTE:
- 当执行scatter/gather DMA时,前四个寄存器会被自动更新;
- 如果在信道工作过程中更新以上寄存器可能会产生不可预料的结果,建议先关闭信道后更改以上寄存器配置;
- 保证LLI 的数据结构 是 4字对齐的;
[0x440]信道控制寄存器(Channel Control Registers)
寄存器用途
- DMA信道控制信息:传输容量、突发容量、传输位宽;
- 需要信道启动之前,写入配置信息;
- 信道工作时,不能提供有效数据信息,信道停止时,该寄存器是只读的;
下表源目的请求突发容量的对应的DBSIZE 和 SBSIZE数值:
下表源目的传输位宽位数(DBSIZE 和 SBSIZE)数值:
保护与访问信息:
- 当DMA传输发生时,AHB访问信息是由源外设和目的外设提供的,传输数据是由DMA信道提供的;
- 寄存器(DMACCxCONTROL):[Prot] = 保护状态寄存器
- 寄存器(DMACCxCONFIGURATION):[lock] = 设置这个位是带锁的DMA传输;
- 位0 为 特权模式=0 用户模式=1;
- 位1 为 突发访问是否使用缓冲,0=不缓冲 1= 缓冲;
- 位2 为 突发访问是否使用缓存,0=不缓存 1= 缓存;
[0x450]信道配置寄存器(Channel Configuration Registers)
- 该寄存器新的LLI被请求时,不会更新;
下表为不同传输类型的流控制器: