DMA引擎的编程指南通常涉及一系列步骤和API调用,以确保数据在内存之间的高效传输,而无需CPU的直接干预。
DMA引擎的编程指南包括以下部分:
一、编写微代码为AXI事务编写CCRx程序
通道微码用于设置dmac.CCRx寄存器以定义AXI事务的属性。这是通过使用DMAMOV CCR指令完成的。
在启动DMA传输之前,用户应该通过写入dmac.CCR{7:0}寄存器对微码进行编程。以下是微码中写入的AXI属性:
- 基于突发的类型(递增或固定地址)对src_inc和dst_inc比特字段进行编程。这会影响ARBURST[0]和AWBURST[0]AXI信号。
- 对src_burst_size和dst_burst_size比特字段(AXI上每个数据节拍的字节数)进行编程。这会影响ARSIZE[2:0]和AWSIZE[2:0]AXI信号。
- 对src_burst_len和dst_burst_len比特字段(每个AXI突发事务的数据节拍数)进行编程。这会影响ARLEN[3:0]和AWLEN[3.0]AXI信号。
- 对src_cache_ctrl和dst_cache_ctrl位字段进行编程(缓存策略)。这会影响ARCACHE[2:0]和AWCACHE[2:0]AXI信号。
- 对src_prot_ctrl和dst_prot_ctrl位字段(管理器线程的安全状态)进行编程。如果管理器线程是安全的,则ARPROT[1]应设置为0,如果不安全,则应设置为1。ARPROT[0]和ARPROT[2]值应设置为=0。例如:
--如果DMA管理器是安全的,则设置src_prot_ctrl=0'b0000;
--如果DMA管理器是不安全的,则设置scr_prot_ctrl=0'b010。
6. 程序endian_swap_size=0(不交换)
二、内存到内存的传输
显示DMAC操作以执行对齐、未对齐和固定数据传输的微码示例。对齐传输请参见表1,未对齐传输请参阅表2,固定传输请参阅图3。
注意:如果DMA传输使用缓存,程序员应确保使用适当的缓存操作来保持缓存一致性。在对DMA通道进行编程之前,应清除与存储器地址范围相对应的高速缓存条目并使其无效。
描述 | 代码 | MFIFO使用 |
简单对齐程序 |
DMAMOV CCR, SB4 SS64
DB4 DS64
DMAMOV SAR, 0x1000
DMAMOV DAR, 0x4000
DMALP 16
DMALD
DMAST
DMALPEND
DMAEND
| 每个DMALD需要四个条目,而每个DMAST删除四个条目。 |
具有多个负载的对齐不对称程序 |
DMAMOV CCR, SB1 SS64
DB4 DS64
DMAMOV SAR, 0x1000
DMAMOV DAR, 0x4000
DMALP 16
DMALD
DMALD
DMALD
DMALD
DMAST
DMALPEND
| 每个DMALD需要一个条目,而每个DMAST删除四个条目。 |
具有多个存储的对齐不对称程序 |
DMAMOV CCR, SB4 SS64
DB1 DS64
DMAMOV SAR, 0x1000
DMAMOV DAR, 0x4000
DMALP 16
DMALD
DMAST
DMAST
DMAST
DMAST
DMALPEND
DMAEND
| 每个DMALD需要四个条目,而每个DMAST删除一个条目。 |
描述 | 代码 | MFIFO使用 |
已对齐的源地址与未对齐的目标地址 |
DMAMOV CCR, SB4 SS64
DB4 DS64
DMAMOV SAR, 0x1000
DMAMOV DAR, 0x4004
DMALP 16
DMALD
DMAST
DMALPEND
DMAMOV CCR, SB4 SS64
DB1 DS32
DMAST
DMAEND
| 第一条DMALD指令加载四个双字,但由于目标地址未对齐,DMAC将它们移位四个字节,因此它只删除第一个循环中的三个条目,留下一个静态MFIFO条目。每个DMAST只需要四个数据条目,因此额外的条目在程序的持续时间内一直使用,直到最后一个DMAST清空为止。 |
未对齐的源地址与对齐的目标地址 |
DMAMOV CCR, SB4 SS64
DB4 DS64
DMAMOV SAR, 0x1004
DMAMOV DAR, 0x4000
DMALD
DMALP 15
DMALD
DMAST
DMALPEND
DMAMOV CCR, SB1 SS32
DB4 DS64
DMALD
DMAST
DMAEND
| 第一DMALD指令没有加载足够的数据以使DMAC能够执行DMAST,因此在循环开始之前,程序包括额外的DMALD。在第一个DMALD之后,随后的DMALD与源突发大小对齐。这优化了性能,但需要更多的MFIFO条目。 |
未对齐的源地址到对齐的目标地址,初始负载过多 |
DMAMOV CCR, SB5 SS64
DB4 DS64
DMAMOV SAR, 0x1004
DMAMOV DAR, 0x4000
DMALD
DMAST
DMAMOV CCR, SB4 SS64
DB4 DS64
DMALP 14
DMALD
DMAST
DMALPEND
DMAMOV CCR, SB3 SS64
DB4 DS64
DMALD
DMAMOV CCR, SB1 SS32
DB4 DS64
DMALD
DMAST
DMAEND
| 第一DMALD指令加载五拍数据以使DMAC能够执行第一DMAST。 |
对齐的突发大小,未对齐的MFIFO |
DMAMOV CCR, SB4 SS32
DB4 DS32
DMAMOV SAR, 0x1000
DMAMOV DAR, 0x4004
DMALP 16
DMALD
DMAST
DMALPEND
DMAEND
| 如果DMAC配置具有32位AXI数据总线宽度,则该程序需要四个MFIFO条目。然而,在这个例子中,DMAC具有64位AXI数据总线宽度,并且由于目的地地址不是64位对齐的,所以它需要三个而不是预期的两个MFIFO条目。 此示例具有零个MFIFO条目的静态要求和三个MFIF奥条目的动态要求。 |
描述 | 代码 | MFIFO使用 |
地址对齐的固定目的地 |
DMAMOV CCR, SB2 SS64
DB4 DS32 DAF
DMAMOV SAR, 0x1000
DMAMOV DAR, 0x4000
DMALP 16
DMALD
DMAST
DMALPEND
DMAEND
| 程序中的每个DMALD将两个64位数据传输加载到MFIFO中。因为目的地地址是32位固定地址,所以DMAC将每个64位数据项拆分为MFIFO中的两个条目。 |
三、PL外设DMA传输长度管理
示例:由外围设备管理的长度
以下示例显示了一个DMAC程序,当外围设备发送突发请求(DMA{3:0}_DRTYPE[1:0]=01)时,该程序将64个字从存储器传输到外围设备0。当外围设备发送单个请求(DMA{3:0}_DRTYPE[1:0]=00)时,DMAC程序将一个字从存储器传输到外围设备0。
为了传输64个字,程序指示DMAC执行16个AXI总线事务。每个事务由4比特突发(SB=4,DB=4)组成,其每个节拍移动一个数据字(SS=32,DS=32)。
在本例中,程序显示了以下说明的使用:
- DMAWFP指令——DMAC等待来自外围设备的突发或单个请求。
- DMASTPB和DMASTPS指令——DMAC在传输完成时通知外围设备。
# Set up for burst transfers (4-beat burst, so SB4 and DB4),
# (word data width, so SS32 and DS32)
DMAMOV CCR SB4 SS32 DB4 DS32
DMAMOV SAR ...
DMAMOV DAR ...
# Initialize peripheral '0'
DMAFLUSHP P0
# Perform peripheral transfers
# Outer loop - DMAC responds to peripheral requests until peripheral
# sets drlast_0 = 1
DMALPFE
# Wait for request, DMAC sets request_type0 flag depending on the
# request type it receives
DMAWFP 0, periph
# Set up loop for burst request: first 15 of 16 sets of transactions
# Note: B suffix - conditionally executed only if request_type0
# flag = Burst
DMALP 15
DMALDB
DMASTB
# Only loopback if servicing a burst, otherwise treat as a NOP
DMALPENDB
# Perform final transaction (16 of 16). Send the peripheral
# acknowledgement of burst request completion
DMALDB
DMASTPB P0
# Perform transaction if the peripheral signals a single request
# Note: S suffix - conditionally executed only if request_type0
# flag = Single
DMALDS
DMASTPS P0
# Exit loop if DMAC receives the last request, that is, drlast_0 = 1
DMALPEND
DMAEND
示例:DMAC管理的长度
这个例子显示了一个DMAC程序,当外围设备发出16个连续的突发请求和3个连续的单个请求信号时,该程序可以传输1027个字。
# Set up for AXI burst transfer
# (4-beat burst, so SB4 and DB4), (word data width, so SS32 and DS32)
DMAMOV CCR SB4 SS32 DB4 DS32
DMAMOV SAR ...
DMAMOV DAR ...
# Initialize peripheral '0'
DMAFLUSHP P0
# Perform peripheral transfers
# Burst request loop to transfer 1024 words
DMALP 16
# Wait for the peripheral to signal a burst request.
# DMAC transfers 64 words for each burst request
DMAWFP 0, burst
# Set up loop for burst request: first 15 of 16 sets of transactions
DMALP 15
DMALD
DMAST
DMALPEND
# Perform final transaction (16 of 16).
# Send the peripheral acknowledgment of burst request completion
DMALD
DMASTPB 0
# Finish burst loop
DMALPEND
# Set up for AXI single transfer (word data width, so SS32 and DS32)
DMAMOV CCR SB1 SS32 DB1 DS32
# Single request loop to transfer 3 words
DMALP 3
# Wait for the peripheral to signal a single request. DMAC to transfer
# one word
DMAWFP 0, single
# Perform transaction for single request and send completion
# acknowledgement to the peripheral
DMALDS
DMASTPS P0
# Finish single loop
DMALPEND
# Flush the peripheral, in case the single transfers were in response
# to a burst request
DMAFLUSHP 0
DMAEND
四、使用事件重新启动频道
当INTEN寄存器被编程为生成事件时,DMASEV和DMAWFE指令可用于重新启动一个或多个DMA通道。
以下部分描述了DMAC在以下情况下的行为:
- DMAC在DMASEV之前执行DMAWFE
- DMAC在DMAWFE之前执行DMASEV
DMAC在DMASEV之前执行DMAWFE
要重新启动单个DMA通道:
- 第一个DMA通道执行DMAWFE,然后在等待事件发生时暂停。
- 另一个DMA通道使用相同的事件编号执行DMASEV。这将生成一个事件,并且第一个DMA通道将重新启动。DMAC在执行DMASEV一个DMA{3:0}_ACLK周期后清除该事件。
可以对多个通道进行编程,以等待同一事件。例如,如果四个DMA通道都执行了事件12的DMAWFE,那么当另一个DMA通道执行事件12的DMASEV时,四个DMA信道都同时重新启动。DMAC在执行DMASEV一个时钟周期后清除事件。
DMAC在DMAWFE之前执行DMASEV
如果DMAC在另一个通道执行DMAWFE之前执行DMASEV,则该事件将一直挂起,直到DMAC执行DMAWFE。当DMAC执行DMAWFE时,它会在一个DMA{3:0}_ACLK周期内停止执行,清除事件,然后继续执行通道线程。
例如,如果DMAC执行DMASEV 6,而其他线程都没有执行DMAWFE 6,则该事件保持挂起状态。如果DMAC对通道4执行DMAWFE 6指令,然后对通道3执行DMAWFE6指令,则:
- DMAC在一个DMA{3:0}_ACLK周期内停止信道4线程的执行。
- DMAC清除事件6。
- DMAC恢复信道4线程的执行。
- DMAC暂停通道3线程的执行,并且线程在等待事件6的下一次发生时暂停。
五、中断处理器
控制器通过中断控制器(GIC)向CPU提供七个活动的高敏感中断(IRQ ID#75:72和49:46)。当INTEN寄存器被编程为生成中断时,在DMAC执行DMASEV之后,控制器将相应的中断设置为活动高状态。
外部微处理器可以通过写入中断清除寄存器(ICR)来清除中断。
执行DMAWFE不会清除中断。
如果DMASEV指令用于在DMAC完成DMALD或DMAST指令时通知微处理器,Arm建议在DMASEV之前插入内存屏障指令。否则,DMAC可能会在AXI事务完成之前发出中断信号。
以下示例对此进行了演示:
DMALD
DMAST
# Issue a write memory barrier
# Wait for the AXI write transfer to complete before the DMAC can
# send an interrupt
DMAWMB
# The DMAC sends the interrupt
DMASEV
六、 指令集引用
表4和表5总结了DMAC指令和命令。
表4 DMA引擎指令摘要
表5 汇编程序提供的DMA引擎附加命令