S32K3XX单片机DMA原理深度解析(下)

简介: S32K3XX单片机DMA原理深度解析(下)

4 相关操作

4.1 执行DMA转换

4.1.1 单次请求

比方说,我们需要传输16个字节的数据。eDMA可编程为一个大循环,每次传输16字节。在源内存有个1字节宽度的内存接口,地址为0x1000。数据终点地址为0x2000,有32位的接口。地址偏移量以增量方式编程以匹配传输大小,读取四次数据,才会写一次数据。相关配置程序如下:

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[INTMAJ] = 1
TCDn_CSR[START] = 1 (should be written last after all other fields have been initialized)
All other TCDn fields = 0

以上的配置,会按照如下顺序执行:

  1. 用户将TCDn_CSR[START]写入数据进行通道服务请求
  2. 通过通道仲裁后,该通道被选择
  3. eDMA引擎写入:
CHn_CSR[DONE] = 0 
 TCDn_CSR[START] = 0  
 CHn_CSR[ACTIVE] = 1
  1. eDMA引擎读取:从局部内存中读取通道的TCD数据到内部寄存器文件
  2. 从源头到终点的传输流程如下:
    0x10000x10010x10020x1003各读取一个字节的数据。
    写32位的数据到0x2000,进行小循环第一次迭代
    0x10040x10050x10060x1007各读取一个字节的数据。
    写32位的数据到0x2004,进行小循环第二次迭代
    0x10080x10090x100A0x100B各读取一个字节的数据。
    写32位的数据到0x2008,进行小循环第三次迭代
    0x100C0x100D0x100E0x100F各读取一个字节的数据。
    写32位的数据到0x200C,进行小循环第四次迭代,大循环迭代完成
  3. eDMA引擎写入:TCDn_SADDR = 0x1000, TCDn_DADDR = 0x2000, TCDn_CITER = 1 (TCDn_BITER)
  4. eDMA引擎写入:CHn_CSR[ACTIVE] = 0, CHn_CSR[DONE] = 1, CHn_INT[INT] = 1
  5. 通道退出,eDMA进入空闲状态,或者服务下一个通道。

具体流程大致如下图所示:

4.1.2 多次请求

如果说我们需要搬运32字节的数据,这个时候就需要两次硬件请求,其他都和上述的单次请求一致。这个时候我们只需要修改主循环的次数和最后的地址偏移。变成两次主循环,每次搬运16字节数据,最后我们通过CHn_CSR[ERQ]寄存器字段使能硬件请求,可初始化从机的通道服务请求。配置如下:

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

执行的基本流程如下:

  1. 第一个硬件通道请求
  2. 通过通道仲裁后,该通道被选择
  3. eDMA引擎写入:
CHn_CSR[DONE] = 0 
 TCDn_CSR[START] = 0  
 CHn_CSR[ACTIVE] = 1
  1. eDMA引擎读取:从局部内存中读取通道的TCD数据到内部寄存器文件
  2. 从源头到终点的传输流程如下:
    0x10000x10010x10020x1003各读取一个字节的数据。
    写32位的数据到0x2000,进行小循环第一次迭代
    0x10040x10050x10060x1007各读取一个字节的数据。
    写32位的数据到0x2004,进行小循环第二次迭代
    0x10080x10090x100A0x100B各读取一个字节的数据。
    写32位的数据到0x2008,进行小循环第三次迭代
    0x100C0x100D0x100E0x100F各读取一个字节的数据。
    写32位的数据到0x200C,小循环迭代完成
  3. eDMA引擎写入:TCDn_SADDR = 0x1010, TCDn_DADDR = 0x2010, TCDn_CITER = 1
  4. eDMA引擎写入:CHn_CSR[ACTIVE] = 0
  5. 通道退出,主循环的一次迭代结束,eDMA进入空闲状态,或者服务下一个通道。
  6. 第二个硬件通道请求
  7. 通过通道仲裁后,该通道被选择
  8. eDMA引擎写入:
CHn_CSR[DONE] = 0 
 TCDn_CSR[START] = 0  
 CHn_CSR[ACTIVE] = 1
  1. eDMA引擎读取:从局部内存中读取通道的TCD数据到内部寄存器文件
  2. 从源头到终点的传输流程如下:
    0x10100x10110x10120x1013各读取一个字节的数据。
    写32位的数据到0x2010,进行小循环第一次迭代
    0x10140x10150x10160x1017各读取一个字节的数据。
    写32位的数据到0x2014,进行小循环第二次迭代
    0x10180x10190x101A0x101B各读取一个字节的数据。
    写32位的数据到0x2018,进行小循环第三次迭代
    0x101C0x101D0x101E0x101F各读取一个字节的数据。
    写32位的数据到0x201C,进行小循环第四次迭代,大循环完成
  3. eDMA引擎写入:TCDn_SADDR = 0x1000, TCDn_DADDR = 0x2000, TCDn_CITER = 2 (TCDn_BITER)
  4. eDMA引擎写入:CHn_CSR[ACTIVE] = 0, CHn_CSR[DONE] = 1, CHn_INT[INT] = 1
  5. 通道退出,主循环结束,eDMA进入空闲状态,或者服务下一个通道。

具体流程大致如下图所示:

4.2 监视描述符状态

4.2.1 测试小循环是否完成

两种方法可以测试小循环(次循环)的状态

  1. 读取TCDn_CITER字段,并测试其是否有更改
  2. 读取下表相应字段,根据数值判断状态

    当使用硬件发起的(即外设发起的)服务请求时,测试小循环完成的最佳方法是读取TCDn_CITER字段并测试更改。硬件请求和确认握手信号在程序员的模型中是不可见的。
    TCD状态字段为硬件激活的通道执行以下序列:

4.2.2 读取激活通道的传输描述符状态

如果在通道执行时读取TCDn_SADDRTCDn_DADDRTCDn_NBYTES的值,eDMA将回读它们的真实值。SADDRDADDRNBYTES的真实值是eDMA引擎当前在其内部寄存器文件中使用的值,而不是该通道的TCD本地内存中的值。

4.2.3 检查通道抢占状态

抢占的情况是启用了抢占的通道正在执行,而高优先级的请求变为活动的情况。

启用轮循仲裁模式时,通道优先级为0的优先级被视为相等,即不断轮换。

被抢占通道的CHn_CSR[ACTIVE]字段在整个抢占过程中保持断言。当抢占通道执行一次主循环迭代时,被抢占的通道被暂时挂起。如果在全局TCD映射中同时设置了两个CHn_CSR[ACTIVE]字段,则高优先级通道正在主动抢占低优先级通道。

4.3 通道连接(通道链接)

通道连接(或链接)是一种机制,其中一个通道设置另一个通道(或其自身)的TCDn_CSR[START]字段,从而为该通道发起服务请求。在配置得当时,eDMA引擎会在大循环或小循环完成时自动执行此操作。

注:相关寄存器/字段解释

START:如果此标志为1,则通道正在请求服务。eDMA硬件在通道开始执行后自动将此标志清除为0

小循环通道连接发生在小循环(或大循环的一次迭代)完成时。TCDn_CITER[ELINK]字段决定是否请求小环路连接。启用后,除了最后一次迭代之外,每次大循环迭代之后都会建立通道链接。当主环路耗尽时,仅使用大环路通道link字段来确定是否应该建立通道链路。例如,若采用如下配置:

TCDn_CITER[ELINK] = 1
TCDn_CITER[LINKCH] = 0xC
TCDn_CITER[CITER] value = 0x4
TCDn_CSR[MAJORELINK] = 1
TCDn_CSR[MAJORLINKCH] = 0x7

则执行过程如下:

小循环完成——>设置TCD12_CSR[START]字段

小循环完成——>设置TCD12_CSR[START]字段

小循环完成——>设置TCD12_CSR[START]字段

小循环完成,大循环完成——>设置TCD7_CSR[START]字段

注:相关寄存器/字段解释

TCDn_CITER[CITER]:Current Major Iteration Count

表示通道的当前主循环计数。每次通道完成一个服务请求并将其写回TCD内存时,它都会减少。

从以上配置来看,一个大循环包含了四个小循环。

下面的表格总结了一个DMA通道如何连接到其他DMA通道,也就是在一次循环结束后,使用其他通道的TCD

4.4 动态程序设计

在通道的执行过程中,也可以改变eDMA的一些配置。

4.4.1 动态改变通道优先级

若想改变或者通道的优先级可以这样做:

  • 通过将CSR[HALT]字段写1来终止DMA写入
  • 改变想改变的组或者通道的优先级
  • 通过将CSR[HALT]字段写0来重新启动DMA操作

4.4.2 动态通道连接(动态通道链接)

动态通道连接是通设置TCDn_CSR[MAJORELINK]字段来实现的,这个字段从TCD的局部内存中读取的,因此可以在DMA通道运行的时使用该特性。为了保险起见,建议采用下面的步骤。

  1. TCDn_CSR[MAJORELINK]字段写1
  2. 读取TCDn_CSR[MAJORELINK]字段的值
  3. 测试TCDn_CSR[MAJORELINK]请求状态
    如果为1,则动态连接尝试成功
    如果为0,则动态连接尝试失败

4.4.3 动态分散/聚集

自动加载一个新的TCD到一个通道,允许同时使用多个TCD,然后进行多个DMA数据的搬运。

有两种方法可以实现动态分散/聚集

Method 1 (不使用大循环连接

如果通道没有使用大循环连接,则可以使用动态分散/收集请求。

Method 2 (使用大循环连接

如果通道使用了大循环连接,则仍然可以使用动态分散/收集请求。此方法使用TCDn_DLAST_SGA字段作为TCD的标识。

注:字段/寄存器解释

TCDn_DLAST_SGA :TCD Last Destination Address Adjustment / Scatter Gather Address

调整要加载到此通道的下一个传输控制描述符的最后一个目标地址或内存地址。

4.5 挂起/重启一个已经激活的通道

挂起一个被激活的通道:

  1. 停止其DMA请求服务;
  2. 通过读取DMAHardware Request Status (HRS)确保没有服务请求的通道被挂起。

如果需要挂起一个DMA/DSPI传输环路。需要执行以下步骤:

  1. 通过将DSPI_RSER[TFFF_RE]字段置0来禁用中断服务请求。
  2. 验证DSPI_RSER[TFFF_RE]0,确保没有来自DSPIDMA服务请求被执行。如果没有被执行,则通过将ERQ字段置零来禁用硬件服务请求。

注:相关术语解释

DSPI :Dual Serial Peripheral Interface(不能100%确实是这个意思)

双线串行外设接口

我们发现标准SPI通信时发送和接收时主机和从机都只能使用自己的那根数据线进行数据传输,Dual SPI无论是接收还是发送都是使用两根数据线进行的,所以单向数据传输速度上是标准SPI的双倍。

关于什么是标准的SPI通信,可以看这篇帖子:SPI通信协议详解

5 后记

通道仲裁的基本逻辑与《操作系统》中的调度算法非常类似,相关内容可以看这篇帖子:《操作系统》第二章 2.2处理机调度

没有比人更高的山,没有比脚更长的路。在学习eDMA的过程中,遇到了比较多的困难,关于这种特殊的DMA网上的资料并不多,只能硬着头皮去看官网的文档,一点一点地分析,比较,推理。但这也是一条充满乐趣的道路!

------------------------------------------------------------------------END------------------------------------------------------------------------

相关文章
|
7月前
|
安全 算法 网络协议
解析:HTTPS通过SSL/TLS证书加密的原理与逻辑
HTTPS通过SSL/TLS证书加密,结合对称与非对称加密及数字证书验证实现安全通信。首先,服务器发送含公钥的数字证书,客户端验证其合法性后生成随机数并用公钥加密发送给服务器,双方据此生成相同的对称密钥。后续通信使用对称加密确保高效性和安全性。同时,数字证书验证服务器身份,防止中间人攻击;哈希算法和数字签名确保数据完整性,防止篡改。整个流程保障了身份认证、数据加密和完整性保护。
|
6月前
|
机器学习/深度学习 数据可视化 PyTorch
深入解析图神经网络注意力机制:数学原理与可视化实现
本文深入解析了图神经网络(GNNs)中自注意力机制的内部运作原理,通过可视化和数学推导揭示其工作机制。文章采用“位置-转移图”概念框架,并使用NumPy实现代码示例,逐步拆解自注意力层的计算过程。文中详细展示了从节点特征矩阵、邻接矩阵到生成注意力权重的具体步骤,并通过四个类(GAL1至GAL4)模拟了整个计算流程。最终,结合实际PyTorch Geometric库中的代码,对比分析了核心逻辑,为理解GNN自注意力机制提供了清晰的学习路径。
482 7
深入解析图神经网络注意力机制:数学原理与可视化实现
|
6月前
|
机器学习/深度学习 缓存 自然语言处理
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
Tiktokenizer 是一款现代分词工具,旨在高效、智能地将文本转换为机器可处理的离散单元(token)。它不仅超越了传统的空格分割和正则表达式匹配方法,还结合了上下文感知能力,适应复杂语言结构。Tiktokenizer 的核心特性包括自适应 token 分割、高效编码能力和出色的可扩展性,使其适用于从聊天机器人到大规模文本分析等多种应用场景。通过模块化设计,Tiktokenizer 确保了代码的可重用性和维护性,并在分词精度、处理效率和灵活性方面表现出色。此外,它支持多语言处理、表情符号识别和领域特定文本处理,能够应对各种复杂的文本输入需求。
806 6
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
|
7月前
|
机器学习/深度学习 算法 数据挖掘
解析静态代理IP改善游戏体验的原理
静态代理IP通过提高网络稳定性和降低延迟,优化游戏体验。具体表现在加快游戏网络速度、实时玩家数据分析、优化游戏设计、简化更新流程、维护网络稳定性、提高连接可靠性、支持地区特性及提升访问速度等方面,确保更流畅、高效的游戏体验。
189 22
解析静态代理IP改善游戏体验的原理
|
7月前
|
编解码 缓存 Prometheus
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
本期内容为「ximagine」频道《显示器测试流程》的规范及标准,我们主要使用Calman、DisplayCAL、i1Profiler等软件及CA410、Spyder X、i1Pro 2等设备,是我们目前制作内容数据的重要来源,我们深知所做的仍是比较表面的活儿,和工程师、科研人员相比有着不小的差距,测试并不复杂,但是相当繁琐,收集整理测试无不花费大量时间精力,内容不完善或者有错误的地方,希望大佬指出我们好改进!
474 16
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
|
6月前
|
传感器 人工智能 监控
反向寻车系统怎么做?基本原理与系统组成解析
本文通过反向寻车系统的核心组成部分与技术分析,阐述反向寻车系统的工作原理,适用于适用于商场停车场、医院停车场及火车站停车场等。如需获取智慧停车场反向寻车技术方案前往文章最下方获取,如有项目合作及技术交流欢迎私信作者。
445 2
|
8月前
|
机器学习/深度学习 自然语言处理 搜索推荐
自注意力机制全解析:从原理到计算细节,一文尽览!
自注意力机制(Self-Attention)最早可追溯至20世纪70年代的神经网络研究,但直到2017年Google Brain团队提出Transformer架构后才广泛应用于深度学习。它通过计算序列内部元素间的相关性,捕捉复杂依赖关系,并支持并行化训练,显著提升了处理长文本和序列数据的能力。相比传统的RNN、LSTM和GRU,自注意力机制在自然语言处理(NLP)、计算机视觉、语音识别及推荐系统等领域展现出卓越性能。其核心步骤包括生成查询(Q)、键(K)和值(V)向量,计算缩放点积注意力得分,应用Softmax归一化,以及加权求和生成输出。自注意力机制提高了模型的表达能力,带来了更精准的服务。
10258 46
|
7月前
|
Java 数据库 开发者
详细介绍SpringBoot启动流程及配置类解析原理
通过对 Spring Boot 启动流程及配置类解析原理的深入分析,我们可以看到 Spring Boot 在启动时的灵活性和可扩展性。理解这些机制不仅有助于开发者更好地使用 Spring Boot 进行应用开发,还能够在面对问题时,迅速定位和解决问题。希望本文能为您在 Spring Boot 开发过程中提供有效的指导和帮助。
785 12
|
7月前
|
开发框架 监控 JavaScript
解锁鸿蒙装饰器:应用、原理与优势全解析
ArkTS提供了多维度的状态管理机制。在UI开发框架中,与UI相关联的数据可以在组件内使用,也可以在不同组件层级间传递,比如父子组件之间、爷孙组件之间,还可以在应用全局范围内传递或跨设备传递。
162 2
|
6月前
|
负载均衡 JavaScript 前端开发
分片上传技术全解析:原理、优势与应用(含简单实现源码)
分片上传通过将大文件分割成多个小的片段或块,然后并行或顺序地上传这些片段,从而提高上传效率和可靠性,特别适用于大文件的上传场景,尤其是在网络环境不佳时,分片上传能有效提高上传体验。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

推荐镜像

更多
  • DNS