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。
- 程序endian_swap_size=0(不交换)
二、内存到内存的传输
显示DMAC操作以执行对齐、未对齐和固定数据传输的微码示例。对齐传输请参见表1,未对齐传输请参阅表2,固定传输请参阅图3。
注意:如果DMA传输使用缓存,程序员应确保使用适当的缓存操作来保持缓存一致性。在对DMA通道进行编程之前,应清除与存储器地址范围相对应的高速缓存条目并使其无效。
|-------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------|
| 描述 | 代码 | MFIFO使用 |
| 简单对齐程序 在这个程序中,源地址和目的地址与AXI数据总线宽度对齐。 | DMAMOV CCR, SB4 SS64 DB4 DS64 DMAMOV SAR, 0x1000 DMAMOV DAR, 0x4000 DMALP 16 DMALD DMAST DMALPEND DMAEND | 每个DMALD需要四个条目,而每个DMAST删除四个条目。 此示例具有零个MFIFO条目的静态要求和四个MFIF奥条目的动态要求。 |
| 具有多个负载的对齐不对称程序 以下程序为每个存储执行四次加载,并且源地址和目标地址与AXI数据总线宽度对齐。 | DMAMOV CCR, SB1 SS64 DB4 DS64 DMAMOV SAR, 0x1000 DMAMOV DAR, 0x4000 DMALP 16 DMALD DMALD DMALD DMALD DMAST DMALPEND | 每个DMALD需要一个条目,而每个DMAST删除四个条目。 此示例具有零个MFIFO条目的静态要求和四个MFIF奥条目的动态要求。 |
| 具有多个存储的对齐不对称程序 以下程序为每个加载执行四个存储,并且源地址和目的地地址与AXI数据总线宽度对齐。 | DMAMOV CCR, SB4 SS64 DB1 DS64 DMAMOV SAR, 0x1000 DMAMOV DAR, 0x4000 DMALP 16 DMALD DMAST DMAST DMAST DMAST DMALPEND DMAEND | 每个DMALD需要四个条目,而每个DMAST删除一个条目。 此示例具有零个MFIFO条目的静态要求和四个MFIF奥条目的动态要求。 |
[表1 DMAC对齐内存到内存的传输]
|-------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 描述 | 代码 | MFIFO使用 |
| 已对齐的源地址与未对齐的目标地址 在这个程序中,源地址与AXI数据总线宽度对齐,但目标地址不对齐。目的地址未与目的突发大小对齐,因此第一DMAST指令删除的数据少于第一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清空为止。 此示例具有一个MFIFO条目的静态需求和四个MFIF奥条目的动态需求。 |
| 未对齐的源地址与对齐的目标地址 在这个程序中,源地址与AXI数据总线宽度不对齐,但目的地址对齐。源地址未与源突发大小对齐,因此第一个DMALD指令读取的数据少于DMAST所需的数据。 因此,需要额外的DMALD来满足第一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条目。 此示例具有四个MFIFO条目的静态需求和四个MFINFO条目的动态需求。 |
| 未对齐的源地址到对齐的目标地址,初始负载过多 此程序是未对齐的源地址到对齐的目标地址中描述的程序的替代方案。该程序使用不同的源突发序列,这可能效率较低,但需要较少的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。 在第一个DMALD之后,后续的DMALD不与源突发大小对齐,例如第二个DMALD从地址0x1028读取。在循环之后,最后两个DMALD读取满足最终DMAST所需的数据。 此示例具有一个MFIFO条目的静态需求和四个MFIF奥条目的动态需求。 |
| 对齐的突发大小,未对齐的MFIFO 在该程序中,比MFIFO宽度窄的目标地址与突发大小对齐,但不与 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奥条目的动态要求。 |
[表2 DMAC未对齐传输]
|--------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|
| 描述 | 代码 | MFIFO使用 |
| 地址对齐的固定目的地 在这个程序中,源地址和目的地地址与AXI数据总线宽度对齐,目的地地址是固定的。 | 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中的两个条目。 此示例具有零个MFIFO条目的静态要求和四个MFIF奥条目的动态要求。 |
[表3 DMAC固定传输]
三、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
DMASTBOnly 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 P0Perform transaction if the peripheral signals a single request
Note: S suffix - conditionally executed only if request_type0
flag = Single
DMALDS
DMASTPS P0Exit 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引擎附加命令