编程 DW_axi_dmac
DW_axi_dmac 可以通过软件寄存器或 DW_axi_dmac 低级软件驱动程序进行编程。
基于影子寄存器的多块传输的编程流程
1. 软件读取 DMAC 通道使能寄存器 (DMAC_ChEnReg) 以选择可用(未使用)的通道。
2. 软件将 CHx_CFG 寄存器编程为适合 DMA 传输的值。 SRC_MLTBLK_TYPE 和/或 DST_MLTBLK_TYPE 位必须设置为 2'b10。
3. 软件对 CHx_SAR 和/或 CHx_DAR、Hx_BLOCK_TS 和 CHx_CTL 寄存器进行编程,为第一个块设置适当的值。
DW_axi_dmac 使用这些值加载相应的影子寄存器。 CHx_CTL 寄存器必须是最后一个要编程的寄存器,ShadowReg_Or_LLI_Valid 位设置为 1 以指示影子寄存器内容有效。 如果从接口数据总线宽度或传输大小小于 64 位,则必须最后更新 CHx_CTL[63:56]。
4. 软件通过将 1 写入 DMAC_ChEnReg 寄存器中的适当位位置来启用通道。
- 必须在编程CHx_SAR、CHx_DAR、CHx_BLOCK_TS 或CHx_CTL 寄存器之前编程CHx_CFG 寄存器,因为SRC_MLTBLK_TYPE 和/或DST_MLTBLK_TYPE 字段的值用于访问影子寄存器。
- 如果从接口数据总线宽度或传输大小小于 64 位,CHx_CFG[7:0]应在第一次写入 CHx_CFG 寄存器时更新。
- 可以交换第 3 步和第 4 步的顺序。但是,如果在第 3 步之前执行第 4 步,并且在影子寄存器提取阶段 ShadowReg_Or_LLI_Valid 位的值为 0,则 DW_axi_dmac 可能会生成shadowReg_Or_LLI_Invalid_ERR 中断。
5. DW_axi_dmac 根据块传输的设置启动 DMA 块传输操作。
- a.块传输可能立即开始,也可能在硬件或软件握手请求之后开始,具体取决于 CHx_CFG 寄存器中 TT_FC 字段的值。
- b. DW_axi_dmac 检查 CHx_CTL_ShadowReg.ShadowReg_Or_LLI_Valid 位,如果它被视为'0',DW_axi_dmac 等待软件写入(任何值)到 CHx_BLK_TFR_ResumeReqReg 以指示有效的 LLI 可用性,然后再尝试另一个影子寄存器fetch操作。
- 在这种情况下,DW_axi_dmac 可能会生成“ShadowReg_Or_LLI_Invalid_ERR”中断。
- c. DW_axi_dmac 检查 CHx_CTL_ShadowReg.ShadowReg_Or_LLI_Valid 位,如果它被视为'1,' DW_axi_dmac 将影子寄存器内容复制到用于执行 DMA 块传输的寄存器(CHx_SAR 和/或 CHx_DAR、CHx_BLOCK_TS 和 CHx_CTL 寄存器),并将 CHx_CTL 和 CHx_CTL_ShadowReg 寄存器中的 ShadowReg_Or_LLI_Valid 位清除为 0。
- i. 如果 DW_axi_dmac 看到复制的影子寄存器的 CHx_CTL.ShadowReg_Or_LLI_Last 位为1,它理解当前块是传输中的最后一个块,并在当前块传输结束时完成DMA传输操作。
- ii. 如果 DW_axi_dmac 看到复制的影子寄存器的 CHx_CTL.ShadowReg_Or_LLI_Last 位为 0,它就知道有一个或多个块要传输,并在当前块传输结束时再次检查 CHx_CTL_ShadowReg.ShadowReg_Or_LLI_Valid 位。
6. 软件轮询 CHx_CTL 寄存器中的 ShadowReg_Or_LLI_Valid 位直到为 0。
- a. 只有在将影子寄存器内容复制到用于执行 DMA 块传输的寄存器(即 CHx_SAR 和/或 CHx_DAR、CHx_BLOCK_TS 和 CHx_CTL 寄存器)后,DW_axi_dmac 才会将该位清零。
- b. 只有在 ShadowReg_Or_LLI_Valid 位设置为 0 后,软件才必须使用一组新值对影子寄存器进行编程。
- c. 如果软件尝试在 ShadowReg_Or_LLI_Valid 位设置为 1 时对影子寄存器进行编程,则 DW_axi_dmac 忽略此写操作,设置CHx_IntStatusReg 寄存器的 SLVIF_ShadowReg_WrOnValid_ERR位为 1,并产生一个中断(如果相应的中断产生没有被屏蔽掉)。
7. 软件对 CHx_SAR 和/或 CHx_DAR、CHx_BLOCK_TS 和 CHx_CTL 寄存器进行编程,为下一个块设置适当的值。
- a.CHx_CTL 寄存器必须是最后一个要编程的寄存器,ShadowReg_Or_LLI_Valid 位设置为 1 以指示影子寄存器内容有效。
- b. 如果当前块是传输中的最后一个块,S/W 必须设置CHx_CTL.ShadowReg_Or_LLI_Last 位为 1。
- c.与先前影子寄存器内容相对应的 DMA 块传输可能在此期间正在进行。
- d. DW_axi_dmac 使用这些新值加载相应的影子寄存器。
8. DW_axi_dmac 根据块传输的设置启动 DMA 块传输操作。
- a.根据 CHx_CFG 寄存器中 TT_FC 字段的设置,块传输可能会立即开始或在硬件/软件握手请求之后开始。
- b. DW_axi_dmac 检查 CHx_CTL_ShadowReg.ShadowReg_Or_LLI_Valid 位,如果它被视为 0,DW_axi_dmac 会等待直到软件写入(任何值)到 CHx_BLK_TFR_ResumeReqReg 以指示有效的 LLI 可用性,然后再尝试另一个影子寄存器提取操作。
- 在这种情况下,DW_axi_dmac 可能会生成 ShadowReg_Or_LLI_Invalid_ERR 中断。
- c. DW_axi_dmac 检查 CHx_CTL_ShadowReg.ShadowReg_Or_LLI_Valid 位,如果它被视为 1,DW_axi_dmac 将影子寄存器内容复制到用于执行 DMA 块传输的寄存器(CHx_SAR 和/或 CHx_DAR、CHx_BLOCK_TS 和 CHx_CTL 寄存器)并清除 CHx_CTL 中的 ShadowReg_Or_LLI_Valid 位和 CHx_CTL_ShadowReg 寄存器为 0。
- d. 如果DW_axi_dmac看到复制的Shadow Register的CHx_CTL.ShadowReg_Or_LLI_Last位为1,它就知道当前块是传输中的最后一个块,并在当前块传输结束时完成DMA传输操作。
- e. 如果 DW_axi_dmac 看到复制的影子寄存器的 CHx_CTL.ShadowReg_Or_LLI_Last 位为 0,它就知道有一个或多个块要传输并检查
- CHx_CTL_ShadowReg.ShadowReg_Or_LLI_Valid 位在当前块传输结束时再次出现。
9. 软件等待块传输完成中断或轮询CHx_IntStatusReg寄存器的块传输完成指示位(BLOCK_TFR_DONE)直到设置为1。
10. 区块传输完成:
- a. DW_axi_dmac 检查 CHx_CTL_ShadowReg.ShadowReg_Or_LLI_Valid 位,如果它被视为 0,DW_axi_dmac 会等待直到软件写入(任何值)到 CHx_BLK_TFR_ResumeReqReg 以指示有效的 LLI 可用性,然后再尝试另一个影子寄存器提取操作。
- 在这种情况下,DW_axi_dmac 可能会生成 ShadowReg_Or_LLI_Invalid_ERR 中断。
- b. DW_axi_dmac 检查 CHx_CTL_ShadowReg.ShadowReg_Or_LLI_Valid 位,如果它被视为 1,DW_axi_dmac 将影子寄存器内容复制到用于执行 DMA 块传输的寄存器(CHx_SAR 和/或 CHx_DAR、CHx_BLOCK_TS 和 CHx_CTL 寄存器)和将 CHx_CTL 和 CHx_CTL_ShadowReg 寄存器中的 ShadowReg_Or_LLI_Valid 位清零。
- 如果复制的Shadow Register 的CHx_CTL.ShadowReg_Or_LLI_Last 位为1,则它知道当前块是传输中的最后一个块并完成DMA 传输操作。
- 如果复制的影子寄存器的CHx_CTL.ShadowReg_Or_LLI_Last 位为0,它知道有一个或多个块要传输并在当前块传输结束时再次检查CHx_CTL_ShadowReg.ShadowReg_Or_LLI_Valid 位。
- c.如果有一个或多个块要传输,软件轮询CHx_CTL.ShadowReg_Or_LLI_Valid 位,直到它被视为 0 并转到步骤 7。
一次读取操作就足够了,因为 DW_axi_dmac 应该已经复制了影子寄存器内容并将该位清除为 0。
如果生成 ShadowReg_Or_LLI_Invalid_ERR,建议的恢复传输流程为:
- 软件程序CHx_SAR 和/或CHx_DAR、CHx_BLOCK_TS 和CHx_CTL 寄存器具有下一个块的适当值。
- 使用中断寄存器CHx_IntClearReg 清除中断。
- 程序块恢复请求CHx_BLK_TFR_ResumeReqReg。
基于链表的多块传输的编程流程
1. 软件读取 DMAC 通道使能寄存器 (DMAC_ChEnReg) 以选择可用(未使用)的通道。
2. 软件将 CHx_CFG 寄存器编程为适合 DMA 传输的值。 SRC_MLTBLK_TYPE 和/或 DST_MLTBLK_TYPE 位必须设置为 2’b11。
3. 软件在CHx_LLP 寄存器中编程第一个链表项的基地址和链表项可用的主接口。
llp = `BASE_ADDR_AUDIO_SRAM_HIFI_SLV;
next_lli_addr = llp;
foreach(block_size[i]) begin
if(i == block_num - 1) begin
curr_lli_addr = next_lli_addr;
next_lli_addr = curr_lli_addr + 'h40;
// SINC DINC SRC_STAT_EN DST_STAT_EN SHADOW_OR_LLI_LAST SHADOW_OR_LLI_VALID DST_TR_WIDTH SRC_TR_WIDTH SRC_MSIZE DST_MSIZE
ch_ctl = ((1'b0<<4) + (1'b0<<6) + (1'b0<<56) + (1'b0<<57) + (1'b1 << 62) + (1'b1 << 63) + (dst_tr_width << 11) +(src_tr_width << 8)) + (3'b000 <<14)+ (3'b000 <<18);
end
else begin
curr_lli_addr = next_lli_addr;
next_lli_addr = curr_lli_addr + 'h40;
// SINC DINC SRC_STAT_EN DST_STAT_EN SHADOW_OR_LLI_LAST SHADOW_OR_LLI_VALID DST_TR_WIDTH SRC_TR_WIDTH SRC_MSIZE DST_MSIZE
ch_ctl = ((1'b0<<4) + (1'b0<<6) + (1'b0<<56) + (1'b0<<57) + (1'b0 << 62) + (1'b1 << 63) + (dst_tr_width << 11) +(src_tr_width << 8)) + (3'b000 <<14)+ (3'b000 <<18);
end
set_LLI(curr_lli_addr, src_addr[i], dst_addr[i], block_size[i], next_lli_addr, ch_ctl);
end
4. 软件在系统内存中创建一个或多个链表项。 软件可以预先创建整个链表项,也可以使用 LLI 的 CHx_CTL.ShadowReg_Or_LLI_Valid 和 CHx_CTL.LLI_Last 字段动态扩展链表。
task set_LLI(bit[63:0] current_lli_addr, bit[31:0] ch_sar, bit[31:0] ch_dar, bit[31:0] block_ts, bit[63:0] next_lli_addr, bit[63:0] ch_ctl);
`uvm_info(get_type_name(), "Set LLI Configuration Entering...", UVM_LOW)
// 0. Set CHx_SAR
cfg_write32(current_lli_addr, ch_sar);
cfg_write32(current_lli_addr + 32'h4, 32'h0);
// 1. Set CHx_DAR
cfg_write32(current_lli_addr + 32'h8, ch_dar);
cfg_write32(current_lli_addr + 32'hc, 32'h0);
// 2. Set CHx_BLOCK_TS
cfg_write32(current_lli_addr + 32'h10, block_ts);
cfg_write32(current_lli_addr + 32'h14, 32'h0);
// 3. Set CHx_LLP
cfg_write32(current_lli_addr + 32'h18, next_lli_addr[31:0]);
cfg_write32(current_lli_addr + 32'h1c, next_lli_addr[63:32]);
// 4. Set CHx_CTL
cfg_write32(current_lli_addr + 32'h20, ch_ctl[31:0]);
cfg_write32(current_lli_addr + 32'h24, ch_ctl[63:32]);
// 5. Set Write-back
cfg_write32(current_lli_addr + 32'h28, 32'h0);
cfg_write32(current_lli_addr + 32'h2c, 32'h0);
`uvm_info(get_type_name(), $sformatf("current_lli_add = %0h",current_lli_addr), UVM_LOW)
endtask: set_LLI
5. 软件通过将 1 写入 DMAC_ChEnReg 寄存器中的适当位位置来启用通道。
6. DW_axi_dmac 根据块传输的设置启动 DMA 块传输操作。
// 1. Set DMAC_CFGREG to enable DW_axi_dmac
set_enable(1'b1, 1'b1);
// 2. Set CH_CFG register of ch_id
// SRC_MLTBLK_TYPE DST_MLTBLK_TYPE tt_fc hs_if
set_chx_cfg(channel_num, 2'b11, 2'b11, 3'b000, 0); //mem2mem
//set_chx_cfg(channel_num, 2'b11, 2'b11, 3'b001, hs_if); //mem2peri
//set_chx_cfg(channel_num, 2'b11, 2'b11, 3'b010, hs_if); //peri2mem
// 3. Set CHx_LLP pointed to the base address of the first LLI
cfg_write32(`BASE_ADDR_AUDIO_DMA_DSP + `DMA_CHX_LLP + (channel_num -1) * 'h100, llp[31:0]);
cfg_write32(`BASE_ADDR_AUDIO_DMA_DSP + `DMA_CHX_LLP + (channel_num -1) * 'h100 + 4, llp[63:32]);
// 4. Set CHENREG to enable channel
set_chx_enable(channel_num);
块传输可能立即开始,也可能在硬件或软件握手请求之后开始,具体取决于 CHx_CFG 寄存器中 TT_FC 字段的设置。
DW_axi_dmac 将链表内容复制到用于执行 DMA 块传输的寄存器(即 CHx_SAR 和/或 CHx_DAR、CHx_BLOCK_TS 和 CHx_CTL 寄存器)和启动 DMA 块传输。
7、链表fetch阶段:
- a. 如果 DW_axi_dmac 看到获取的 LLI 的 CHx_CTL.ShadowReg_Or_LLI_Last 位为 1,则它知道当前块是传输中的最后一个块,并在当前块传输结束时完成 DMA 传输操作。
- b. 如果 DW_axi_dmac 看到获取的 LLI 的 CHx_CTL.ShadowReg_Or_LLI_Last 位为 0,它知道有一个或多个块要传输并转到步骤 6。
- c.如果 DW_axi_dmac 看到获取的 LLI 的 CHx_CTL.ShadowReg_Or_LLI_Valid 位为 0,DW_axi_dmac 可能会生成 ShadowReg_Or_LLI_Invalid_ERR 中断。 在尝试另一个 LLI 读取操作之前,DW_axi_dmac 等待软件写入(任何值)到 CHx_BLK_TFR_ResumeReqReg 以指示有效的 LLI 可用性。
- 可以交换第 4 步和第 5 步的顺序。但是,如果第 5 步在第 4 步之前执行,或者如果在多块期间的任何时候系统内存中都没有用于下一个块传输的链表项 传输,如获取的 LLI 的 CHx_CTL.ShadowReg_Or_LLI_Valid 位设置为 0 所示,DW_axi_dmac 可能会生成 ShadowReg_Or_LLI_Invalid_ERR 中断。
单块传输的编程流程
1. 软件读取 DMAC 通道启用寄存器 (DMAC_ChEnReg) 以选择一个空闲(未使用)的通道。
2. 软件将 CHx_CFG 寄存器的源和目标外设的多块类型值设置为 2'b00。
3. 软件对 CHx_SAR 和/或 CHx_DAR、CHx_BLOCK_TS 和 CHx_CTL 寄存器进行编程,使其具有适合块的值。
4. 软件通过将 1 写入 DMAC_ChEnReg 寄存器中的适当位位置来启用通道。
5. 源和目标请求单个或突发 DMA 事务来传输数据块(假设非内存外设)。 DW_axi_dmac 在块中的每个事务(突发和单个)完成时确认并执行块传输。
6. 软件等待块传输完成中断/轮询 CHx_IntStatusReg 寄存器中的块传输完成指示位(BLOCK_TFR_DONE)直到该位为 1。

浙公网安备 33010602011771号