RT1060 eDMA 详解 (3)

RT1060 eDMA 详解 (3)

RT1060 eDMA Part3 初始化 & 应用

第 6 章 增强型直接内存访问(eDMA) 初始化 & 应用

要点:

???

6.4 初始化 / 应用信息

以下部分讨论 eDMA 的初始化和编程注意事项。

6.4.1 eDMA 初始化

初始化 eDMA 的步骤如下:

  1. 如果需要默认配置以外的设置,请写入控制寄存器(CR)。
  2. 如果需要默认优先级以外的配置,请将通道优先级级别写入 DCHPRIn 寄存器。
  3. 如果需要,在 EEI 寄存器中启用错误中断。
  4. 为每个可能请求服务的通道写入 32 字节的传输控制描述符(TCD)。
  5. 通过 ERQ 寄存器启用任何硬件服务请求。
  6. 通过以下方式请求通道服务: ・软件方式:设置 TCDn_CSR [START] 位 ・硬件方式:从设备断言其 eDMA 外设请求信号

任何通道请求服务后,将根据编程模型中的仲裁和优先级级别选择一个通道执行。eDMA 引擎会将所选通道的整个 TCD(包括 TCD 控制和状态字段,如表 6-6 所示)读取到其内部地址路径模块中。 表 6-6 TCD 控制和状态字段

TCD n_CSR 字段名称 描述
START 使用软件启动的 DMA 服务时,显式启动通道的控制位(硬件自动清除)
ACTIVE 状态位,指示通道当前正在执行
DONE 状态位,指示主循环完成(使用软件启动的 DMA 服务时由软件清除)
DREQ 使用硬件启动的 DMA 服务时,在主循环完成结束时禁用 DMA 请求的控制位
BWC 用于限制通道带宽控制的控制位
ESG 启用分散 / 聚集功能的控制位
INTHALF 主循环完成一半时启用中断的控制位
INTMAJOR 主循环完成时启用中断的控制位

读取 TCD 时,除非检测到配置错误,否则会在系统总线上启动第一次传输。从 TCDn_SADDR 定义的源地址到 TCDn_DADDR 定义的目标地址的传输将持续进行,直到传输完 TCDn_NBYTES 指定的字节数。

传输完成后,eDMA 引擎会将本地的 TCDn_SADDR、TCDn_DADDR 和 TCDn_CITER 写回主 TCD 内存,并执行任何已启用的微循环通道链接(如果已启用)。如果主循环耗尽,将执行进一步的后处理,例如中断、主循环通道链接和分散 / 聚集操作(如果已启用)。

下图显示了每个 DMA 请求如何在无需 CPU 干预的情况下启动一次微循环传输或迭代。每次微循环后可能发生 DMA 仲裁,并且允许一级微循环 DMA 抢占。主循环中的微循环次数由起始迭代计数(BITER)指定。 图 6-5 多重循环迭代示例

源或目标内存 当前主循环迭代计数(CITER)
DMA 请求
微循环 3
• •
DMA 请求
微循环 主循环 2
DMA 请求
微循环 1

下图列出了内存数组术语以及 TCD 设置的相互关系。 图 6-6 内存数组术语

xADDR:(起始地址) xSIZE:(一次数据传输的大小) 微循环(微循环中的 NBYTES,通常与 xSIZE 值相同)
• • • 偏移量(xOFF):每次传输后添加到当前地址的字节数(通常与 xSIZE 相同)
• • • • • • • • • • • • 每个 DMA 源(S)和目标(D)都有自己的:地址(xADDR)、大小(xSIZE)、偏移量(xOFF)、模(xMOD)、最后地址调整(xLAST),其中 x = S 或 D
• • • 最后一次微循环 外设队列的大小和偏移量通常等于 NBYTES
xLAST: 主循环后添加到当前地址的字节数(通常用于循环回退)

6.4.2 编程错误

eDMA 会对传输控制描述符执行各种测试,以验证描述符数据的一致性。除通道优先级错误(ES [CPE])外,大多数编程错误都会按通道报告。

对于组错误或通道优先级错误以外的所有错误类型,导致错误的通道号会记录在错误状态寄存器(DMAx_ES)中。如果在问题通道下次激活之前未清除错误源,该错误将被再次检测和记录。

通道优先级错误在某个组被选为活动组后在该组内识别。例如:

  1. eDMA 配置为固定组和固定通道仲裁模式。
  2. 组 1 是最高优先级,且该组中的所有通道优先级唯一。
  3. 组 0 是次高优先级,包含两个具有相同优先级的通道。
  4. 如果组 1 有任何服务请求,这些请求将被执行。
  5. 组 1 的请求全部完成后,组 0 将成为下一个活动组。
  6. 如果组 0 有服务请求,则会选择组 0 中的一个未定义通道,并发生通道优先级错误。
  7. 这种情况会持续,直到组 0 的所有请求被移除或更高优先级的组 1 请求进入。

在这个序列中,对于第 2 项,仅当选定的通道通过 eDMA 外设请求信号请求服务时,eDMA 确认线才会断言。如果为所有通道启用了中断,用户将收到错误中断,但 ERR 寄存器的通道号和错误中断请求线可能错误,因为它们反映的是所选通道。组优先级错误是全局的,任何组中的请求都会导致组优先级错误。

如果优先级级别不唯一,当任何通道请求服务时,将报告通道优先级错误。具有活动请求的最高通道 / 组优先级被选中,但仲裁会选择该优先级中编号最小的通道,并由 eDMA 引擎执行。硬件服务请求握手信号、错误中断和错误报告与所选通道相关联。

6.4.3 仲裁模式注意事项

本节讨论 eDMA 的仲裁注意事项。

6.4.3.1 固定组仲裁,固定通道仲裁

在这种模式下,选择最高优先级组中最高优先级通道的服务请求进行执行。如果 eDMA 编程为某组内的通道使用 “固定” 优先级,并且该组被分配为所有组中的最高 “固定” 优先级,则该组可以占用 eDMA 控制器的所有带宽。也就是说,如果控制器仲裁下一个 DMA 请求时,最高优先级组中至少有一个 DMA 请求挂起,其他组将不会被服务。这种情况的优点是需要快速服务的通道的延迟可以很小。抢占仅在这种情况下可用。

6.4.3.2 固定组仲裁,循环通道仲裁

有请求的最高优先级组将被服务。如果更高优先级组中没有挂起的请求,则服务低优先级组。

在每个组内,通道服务从最高通道号开始,循环到最低通道号,而不考虑组内分配的通道优先级级别。

这种情况可能导致与 “固定组仲裁,固定通道仲裁” 中提到的相同带宽消耗问题,但最高优先级组中的所有通道都将被服务。最高优先级组的服务延迟较短,但随着组优先级降低,延迟可能会显著增加。

6.4.4 DMA 传输示例

本节介绍如何使用 eDMA 执行 DMA 传输的示例。

6.4.4.1 单次请求

要通过一次激活执行 n 字节数据的简单传输,将主循环设置为 1(TCDn_CITER = TCDn_BITER = 1)。通道服务请求被确认并选择通道执行后,数据传输开始。传输完成后,TCDn_CSR [DONE] 位被设置,如果启用了中断,则会生成中断。

例如,以下 TCD 条目配置为传输 16 字节数据。eDMA 被编程为主循环一次迭代,每次迭代传输 16 字节。源内存有一个位于 0x1000 的 8 位内存端口,目标内存有一个位于 0x2000 的 32 位端口。地址偏移量按增量编程以匹配传输大小:源为 1 字节,目标为 4 字节。最终的源和目标地址被调整为返回其初始值。

1
2
3
4
5
6
7
8
9
10
11
12
13
TCDn_CITER = TCDn_BITER = 1  
TCDn_NBYTES = 16
TCDn_SADDR = 0x1000
TCDn_SOFF = 1
TCDn_ATTR[SSIZE] = 0
TCDn_SLAST = -16
TCDn_DADDR = 0x2000
TCDn_DOFF = 4
TCDn_ATTR[DSIZE] = 2
TCDn_DLAST_SGA = –16
TCDn_CSR[INTMAJOR] = 1
TCDn_CSR[START] = 1(应在初始化所有其他字段后最后写入)
所有其他TCDn字段 = 0

这将生成以下事件序列:

  1. 用户写入 TCDn_CSR [START] 位请求通道服务。
  2. 通过仲裁选择通道进行服务。
  3. eDMA 引擎写入:TCDn_CSR [DONE] = 0,TCDn_CSR [START] = 0,TCDn_CSR [ACTIVE] = 1。
  4. eDMA 引擎从本地内存读取通道 TCD 数据到内部寄存器文件。
  5. 源到目标的传输执行如下: a. 从地址 0x1000 读取字节,从 0x1001 读取字节,从 0x1002 读取字节,从 0x1003 读取字节。 b. 向地址 0x2000 写入 32 位 → 微循环第一次迭代。 c. 从地址 0x1004 读取字节,从 0x1005 读取字节,从 0x1006 读取字节,从 0x1007 读取字节。 d. 向地址 0x2004 写入 32 位 → 微循环第二次迭代。 e. 从地址 0x1008 读取字节,从 0x1009 读取字节,从 0x100A 读取字节,从 0x100B 读取字节。 f. 向地址 0x2008 写入 32 位 → 微循环第三次迭代。 g. 从地址 0x100C 读取字节,从 0x100D 读取字节,从 0x100E 读取字节,从 0x100F 读取字节。 h. 向地址 0x200C 写入 32 位 → 微循环最后一次迭代 → 主循环完成。
  6. eDMA 引擎写入:TCDn_SADDR = 0x1000,TCDn_DADDR = 0x2000,TCDn_CITER = 1(TCDn_BITER)。
  7. eDMA 引擎写入:TCDn_CSR [ACTIVE] = 0,TCDn_CSR [DONE] = 1,INT [n] = 1。
  8. 通道退出,eDMA 进入空闲状态或服务下一个通道。

6.4.4.2 多次请求

以下示例通过两次硬件请求传输 32 字节数据,其他方面与前一个示例相同。唯一变化的字段是主循环迭代计数和最终地址偏移量。eDMA 被编程为主循环两次迭代,每次迭代传输 16 字节。在 ERQ 寄存器中启用通道的硬件请求后,从设备发起通道服务请求。

1
2
3
TCDn_CITER = TCDn_BITER = 2  
TCDn_SLAST = –32
TCDn_DLAST_SGA = –32

这将生成以下事件序列:

  1. 第一次硬件(即 eDMA 外设)请求通道服务。
  2. 通过仲裁选择通道进行服务。
  3. eDMA 引擎写入:TCD_CSR [DONE] = 0,TCDn_CSR [START] = 0,TCDn_CSR [ACTIVE] = 1。
  4. eDMA 引擎从本地内存读取通道 TCDn 数据到内部寄存器文件。
  5. 源到目标的传输执行如下: a. 从地址 0x1000 读取字节,从 0x1001 读取字节,从 0x1002 读取字节,从 0x1003 读取字节。 b. 向地址 0x2000 写入 32 位 → 微循环第一次迭代。 c. 从地址 0x1004 读取字节,从 0x1005 读取字节,从 0x1006 读取字节,从 0x1007 读取字节。 d. 向地址 0x2004 写入 32 位 → 微循环第二次迭代。 e. 从地址 0x1008 读取字节,从 0x1009 读取字节,从 0x100A 读取字节,从 0x100B 读取字节。 f. 向地址 0x2008 写入 32 位 → 微循环第三次迭代。 g. 从地址 0x100C 读取字节,从 0x100D 读取字节,从 0x100E 读取字节,从 0x100F 读取字节。 h. 向地址 0x200C 写入 32 位 → 微循环最后一次迭代。
  6. eDMA 引擎写入:TCDn_SADDR = 0x1010,TCDn_DADDR = 0x2010,TCDn_CITER = 1。
  7. eDMA 引擎写入:TCDn_CSR [ACTIVE] = 0。
  8. 通道退出 → 主循环一次迭代。eDMA 进入空闲状态或服务下一个通道。
  9. 第二次硬件(即 eDMA 外设)请求通道服务。
  10. 通过仲裁选择通道进行服务。
  11. eDMA 引擎写入:TCDn_CSR [DONE] = 0,TCDn_CSR [START] = 0,TCDn_CSR [ACTIVE] = 1。
  12. eDMA 引擎从本地内存读取通道 TCD 数据到内部寄存器文件。
  13. 源到目标的传输执行如下: a. 从地址 0x1010 读取字节,从 0x1011 读取字节,从 0x1012 读取字节,从 0x1013 读取字节。 b. 向地址 0x2010 写入 32 位 → 微循环第一次迭代。 c. 从地址 0x1014 读取字节,从 0x1015 读取字节,从 0x1016 读取字节,从 0x1017 读取字节。 d. 向地址 0x2014 写入 32 位 → 微循环第二次迭代。 e. 从地址 0x1018 读取字节,从 0x1019 读取字节,从 0x101A 读取字节,从 0x101B 读取字节。 f. 向地址 0x2018 写入 32 位 → 微循环第三次迭代。 g. 从地址 0x101C 读取字节,从 0x101D 读取字节,从 0x101E 读取字节,从 0x101F 读取字节。 h. 向地址 0x201C 写入 32 位 → 微循环最后一次迭代 → 主循环完成。
  14. eDMA 引擎写入:TCDn_SADDR = 0x1000,TCDn_DADDR = 0x2000,TCDn_CITER = 2(TCDn_BITER)。
  15. eDMA 引擎写入:TCDn_CSR [ACTIVE] = 0,TCDn_CSR [DONE] = 1,INT [n] = 1。
  16. 通道退出 → 主循环完成。eDMA 进入空闲状态或服务下一个通道。

6.4.4.3 使用模运算功能

eDMA 的模运算功能支持实现循环数据队列,其中队列大小为 2 的幂。TCD 中源和目标的 MOD 是一个 5 位字段,用于指定地址 + 偏移量计算后,哪些低位地址位会递增,而所有高位地址位保持原值。该字段设置为 0 时将禁用模运算功能。

下表展示了如何根据 MOD 字段的设置指定传输地址。在此示例中,创建了一个循环缓冲区,地址会回绕到初始值,同时 28 个高位地址位(0x1234567x)保持原值。假设源地址设置为 0x12345670,偏移量设置为 4 字节,MOD 字段设置为 4,从而支持一个 2⁴字节(16 字节)大小的队列。 表 6-7 模运算示例(续表见下页)

传输次数 地址
1 0x12345670
2 0x12345674
3 0x12345678
4 0x1234567C
5 0x12345670
6 0x12345674

6.4.5 监控传输描述符状态

本节讨论如何监控 eDMA 状态。

6.4.5.1 测试微循环完成情况

使用软件启动的服务请求时,有两种方法可测试微循环是否完成。第一种方法是读取 TCDn_CITER 字段并检测其变化。另一种方法可从以下序列中推导:通过测试 TCDn_CSR [START] 和 TCDn_CSR [ACTIVE] 位的状态。当 TCDn_CSR [START] 位被设置后,若这两个位均读为 0,则表示微循环完成。轮询 TCDn_CSR [ACTIVE] 位可能不可靠,因为如果通道执行时间较短,可能会错过活动状态。

对于软件激活的通道,TCD 状态位按以下序列变化:

阶段 TCDn_CSR 位状态 状态
START ACTIVE DONE
1 1 0 0 通过软件请求通道服务
2 0 1 0 通道正在执行
3a 0 0 0 通道已完成微循环并进入空闲状态
3b 0 0 1 通道已完成主循环并进入空闲状态

使用硬件(外设)启动的服务请求时,测试微循环完成的最佳方法是读取 TCDn_CITER 字段并检测其变化。硬件请求和确认握手信号在编程模型中不可见。

对于硬件激活的通道,TCD 状态位按以下序列变化:

阶段 TCDn_CSR 位状态 状态
START ACTIVE DONE
1 0 0 0 通过硬件请求通道服务(外设请求有效)
2 0 1 0 通道正在执行
3a 0 0 0 通道已完成微循环并进入空闲状态
3b 0 0 1 通道已完成主循环并进入空闲状态

对于两种激活类型,主循环完成状态均通过 TCDn_CSR [DONE] 位明确指示。无论通道如何激活,TCDn_CSR [START] 位在通道开始执行时自动清除。

6.4.5.2 读取活动通道的传输描述符

当通道执行时,读取 TCDn_SADDR、TCDn_DADDR 和 TCDn_NBYTES 字段将返回真实值。这些真实值是 eDMA 引擎当前在内部寄存器文件中使用的值,而非该通道 TCD 本地内存中的值。随着传输进行而递减至 0 的地址(SADDR、DADDR)和字节数(NBYTES)可指示传输进度。所有其他值从 TCD 本地内存读取。

6.4.5.3 检查通道抢占状态

仅当同时为组仲裁和通道仲裁选择固定仲裁模式时,才支持抢占功能。抢占场景发生在以下情况:已启用抢占的通道正在运行时,更高优先级请求变为有效。当 eDMA 引擎未运行在固定组 + 固定通道仲裁模式下时,当前运行通道与待处理请求的相对优先级无法确定。选择循环仲裁模式时,通道和 / 或组优先级被视为相等(即持续轮换)。

被抢占通道的 TCDn_CSR [ACTIVE] 位在整个抢占期间保持有效。被抢占通道会暂时挂起,直至抢占通道完成一次主循环迭代。如果全局 TCD 映射中同时设置了两个 TCDn_CSR [ACTIVE] 位,则表示高优先级通道正在主动抢占低优先级通道。

6.4.6 通道链接

通道链接(或链式传输)是一种机制,其中一个通道设置另一个通道(或自身)的 TCDn_CSR [START] 位,从而为该通道发起服务请求。启用后,eDMA 引擎会在主循环或微循环完成时自动执行此操作。

微循环通道链接在微循环完成(或主循环的一次迭代)时触发。TCDn_CITER [ELINK] 字段决定是否请求微循环链接。启用后,除最后一次迭代外,每次主循环迭代完成后都会进行通道链接。当主循环耗尽时,仅使用主循环通道链接字段来决定是否进行通道链接。例如,初始字段设置为:

1
2
3
4
5
TCDn_CITER[ELINK] = 1  
TCDn_CITER[LINKCH] = 0xC
TCDn_CITER[CITER] = 0x4
TCDn_CSR[MAJOR_ELINK] = 1
TCDn_CSR[MAJOR_LINKCH] = 0x3

执行流程如下:

  1. 微循环完成 → 设置 TCD2_CSR [START] 位。
  2. 微循环完成 → 设置 TCD2_CSR [START] 位。
  3. 微循环完成 → 设置 TCD2_CSR [START] 位。
  4. 微循环完成且主循环完成 → 设置 TCD3_CSR [START] 位。

启用微循环链接(TCDn_CITER [ELINK] = 1)时,TCDn_CITER [CITER] 字段使用 9 位向量构成当前迭代计数。禁用微循环链接(TCDn_CITER [ELINK] = 0)时,TCDn_CITER [CITER] 字段使用 15 位向量构成当前迭代计数。与 TCDn_CITER [LINKCH] 字段相关的位会连接到 CITER 值,以扩展 CITER 的范围。

注意:TCDn_CITER [ELINK] 位和 TCDn_BITER [ELINK] 位必须相等,否则会报告配置错误。CITER 和 BITER 的向量宽度必须相等,以计算主循环中途完成的中断点。

下表总结了 DMA 通道如何在循环结束时链接到另一个 DMA 通道(即使用另一个通道的 TCD)。 表 6-8 通道链接参数

期望的链接行为 TCD 控制字段名称 描述
微循环结束时链接 CITER[ELINK] 启用微循环完成时的通道间链接(当前迭代)
CITER[LINKCH] 微循环结束时链接的目标通道号(当前迭代)
主循环结束时链接 CSR[MAJOR_ELINK] 启用主循环完成时的通道间链接
CSR[MAJOR_LINKCH] 主循环结束时链接的目标通道号

6.4.7 动态编程

本节提供在通道执行期间更改编程模型的推荐方法。

6.4.7.1 动态更改通道优先级

动态更改通道优先级级别的推荐方法有以下两种:

  1. 切换到循环通道仲裁模式,更改通道优先级,然后切换回固定仲裁模式。
  2. 禁用所有通道,更改通道优先级,然后启用相应的通道。

6.4.7.2 动态通道链接

动态通道链接是指在通道执行期间设置 TCDn_CSR [MAJORELINK] 位(参见 TCD 结构示意图)。该字段在通道执行结束时从 TCD 本地内存读取,因此允许在通道执行期间启用该功能。

由于可以在执行期间更改配置,因此需要一致性模型。例如,当尝试通过启用 TCDn_CSR [MAJORELINK] 位执行动态通道链接时,若同时 eDMA 引擎正在退出该通道,则编程模型中 TCDn_CSR [MAJORELINK] 位会被设置,但无法确定在通道退出前是否实际完成了链接。

执行动态通道链接请求时,推荐以下一致性模型:

  1. 向 TCDn_CSR [MAJORELINK] 写入 1。
  2. 读回 TCDn_CSR [MAJORELINK]。
  3. 测试 TCDn_CSR [MAJORELINK] 请求状态: ・若 TCDn_CSR [MAJORELINK] = 1,表示动态链接尝试成功。 ・若 TCDn_CSR [MAJORELINK] = 0,表示动态链接尝试失败(通道已在退出中)。

对于此请求,一旦通道的 TCD.done 位设置(表示主循环完成),TCD 本地内存控制器会强制将任何写入通道 TCD.word7 的 TCDn_CSR [MAJORELINK] 位清零。

注意:必须在写入 TCDn_CSR [MAJORELINK] 之前清除 TCDn_CSR [DONE] 位。eDMA 引擎在通道开始执行后会自动清除 TCDn_CSR [DONE] 位。

6.4.7.3 动态分散 / 聚集

分散 / 聚集是指自动将新 TCD 加载到通道中的过程。它使 DMA 通道能够使用多个 TCD,从而支持将 DMA 数据分散到多个目标或从多个源聚集数据。启用分散 / 聚集功能且通道完成主循环后,会从系统内存中获取新 TCD 并加载到 eDMA 编程模型中的该通道描述符位置,替换当前描述符。

由于可以在执行期间更改配置,因此需要一致性模型。例如,当尝试通过启用 TCDn_CSR [ESG] 位执行动态分散 / 聚集操作时,若同时 eDMA 引擎正在退出该通道,则编程模型中 ESG 位会被设置,但无法确定在通道退出前是否实际处理了分散 / 聚集请求。

以下子节介绍两种一致性模型方法。方法 1 的优点是可以通过一次读取同时获取 MAJORLINKCH 字段和 ESG 位。对于动态通道链接和分散 / 聚集请求,一旦通道的 TCD [DONE] 位设置(表示主循环完成),TCD 本地内存控制器会强制将任何写入通道 TCD word7 的 TCD MAJOR [ELINK] 和 ESG 位清零。

注意:用户必须在写入 MAJORELINK 或 ESG 位之前清除 TCDn_CSR [DONE] 位。eDMA 引擎在通道开始执行后会自动清除 TCDn_CSR [DONE] 位。

6.4.7.3.1 方法 1(不使用主循环通道链接的通道)

对于不使用主循环通道链接的通道,此一致性模型可用于动态分散 / 聚集请求。

当 TCDn_CSR [MAJORELINK] = 0 时,eDMA 不使用 TCDn_CSR [MAJORLINKCH] 字段。此时,MAJORLINKCH 可用于其他用途。此方法将 MAJORLINKCH 字段用作 TCD 标识(ID)。

  1. 构建描述符时,为每个使用动态分散 / 聚集的通道对应的 TCD,在 TCDn_CSR [MAJORLINKCH] 中写入唯一的 TCD ID。
  2. 向 TCDn_CSR [DREQ] 写入 1。 若动态分散 / 聚集尝试失败,设置 DREQ 位可防止通道未来通过硬件激活。这将避免通道使用基于分散 / 聚集地址(在下一步写入)计算的目标地址(DADDR)执行,而非使用 DLAST_SGA 最终偏移量值。
  3. 向 TCDn_DLASTSGA 寄存器写入分散 / 聚集地址。
  4. 向 TCDn_CSR [ESG] 写入 1。
  5. 读回 16 位 TCD 控制 / 状态字段。
  6. 测试 TCDn_CSR 寄存器中的 ESG 请求状态和 MAJORLINKCH 值:
    • 若 ESG = 1,表示动态链接尝试成功。
    • 若 ESG = 0 且 MAJORLINKCH(ID)未改变,表示动态链接尝试失败(通道已在退出中)。
    • 若 ESG = 0 且 MAJORLINKCH(ID)改变,表示动态链接尝试成功(新 TCD 的 ESG 值清除了 ESG 位)。
6.4.7.3.2 方法 2(使用主循环通道链接的通道)

对于使用主循环通道链接的通道,此一致性模型可用于动态分散 / 聚集请求。此方法将 TCD [DLAST_SGA] 字段用作 TCD 标识(ID)。

  1. 向 TCDn_CSR [DREQ] 写入 1。 若动态分散 / 聚集尝试失败,设置 TCDn_CSR [DREQ] 位可防止通道未来通过硬件激活。这将避免通道使用基于分散 / 聚集地址(在下一步写入)计算的目标地址(DADDR)执行,而非使用 DLAST_SGA 最终偏移量值。
  2. 向 TCDn_DLAST_SGA 寄存器写入分散 / 聚集地址。
  3. 向 TCDn_CSR [ESG] 写入 1。
  4. 读回 TCDn_CSR [ESG]。
  5. 测试 ESG 请求状态:
    • 若 ESG = 1,表示动态链接尝试成功。
    • 若 ESG = 0,读取 32 位 TCDn_DLAST_SGA 字段:
      • 若 ESG = 0 且 TCDn_DLAST_SGA 未改变,表示动态链接尝试失败(通道已在退出中)。
      • 若 ESG = 0 且 TCDn_DLAST_SGA 改变,表示动态链接尝试成功(新 TCD 的 ESG 值清除了 ESG 位)。

6.4.8 挂起 / 恢复具有活动硬件服务请求的 DMA 通道

DMA 允许在无需 CPU 干预的情况下将数据从内存或外设寄存器传输到内存或外设寄存器的另一位置。配置并激活 DMA 和外设后,动态挂起外设服务请求的情况较为罕见。在此类场景中,禁用 DMA 硬件服务请求有特定限制。为确保一致性,必须遵循特定流程。本节提供当 DMA 由从模块(如串行外设接口(SPI)、ADC 或其他模块)触发时,如何一致地挂起和恢复 DMA 通道的指导。

6.4.8.1 挂起活动 DMA 通道

挂起活动 DMA 通道的步骤如下:

  1. 首先在外设端停止 DMA 服务请求。通过读取外设的相应寄存器,确认请求已禁用。
  2. 检查 DMA 的硬件请求状态寄存器(DMA_HRSn),确保待挂起的 DMA 通道无服务请求。然后通过清除相应 DMA 通道的 ERQ 位,禁用硬件服务请求。

6.4.8.2 恢复 DMA 通道

恢复 DMA 通道的步骤如下:

  1. 通过设置相应的 ERQ 位,启用目标通道的 DMA 服务请求。
  2. 在外设端启用 DMA 服务请求。

例如,假设 SPI 被配置为主设备,当 SPI_TXFIFO 出现空槽时通过 DMA 服务请求传输数据。DMA 会在请求时将下一条命令和数据传输到 TXFIFO。若需挂起 DMA/SPI 传输循环并执行恢复操作,步骤如下:

  1. 向 SPI_RSER [TFFF_RE] 写入 0,禁用源端的 DMA 服务请求。确认 SPI_RSER [TFFF_RE] 为 0。
  2. 验证对应通道的 DMA_HRS [HRSn] 为 0,确保 SPI 未发起 DMA 服务请求。若不存在服务请求,通过清除通道的 ERQ 位禁用 DMA 通道;若存在服务请求,等待请求处理完成且 HRS 位读为 0。
作者

Gavin

发布于

2025-05-24

更新于

2025-05-24

许可协议

CC BY-NC-SA 4.0

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×