跳转到主要内容

华大MCU之七:DMA 导致 SPI 异常停止的原因分析、DMA 配置的那些坑

cathy 提交于

<strong><font color="#004a85">缘起</font> </strong>

在最近的项目测试中发现,SPI 通信总是莫名其妙的失败,查看寄存器发现 SPI 已经被停止了。根据手册,SPI 在异常情况下会被强制停止(SPI 的使能为被清零),而根据波形显示通信过程没有问题。下图是我实际中的 DMA 及 SPI 使用情况:

<center><img src="http://mcu.eetrend.com/files/2021-12/博客/100556636-238064-1.png&quot; alt=“华大MCU之七:DMA 导致 SPI 异常停止的原因分析、DMA 配置的那些坑"></center>

1、SPI1 仅使用发送功能,SPI2 仅使用接收功能,两者均使用 DMA。由于 SPI 没有仅发送模式,因此 SPI2 必须要配置一个 TX,否则导致 SPI 报错(实际并不配置 SPI 的发送引脚)。

2、在初始化时,先初始化了 SPI2(含 DMA),然后再初始化的 SPI1(含DMA),这里是关键。

3、在初始化之后,SPI 立刻开始工作(有数据通信)。其中,SPI2 大约以 8MHz 的速率不停的接收数据,SPI1 则以 1MHz 的速率在需要的时候才会发送数据。

4、问题是在以上流程中,在配置 SPI2 时,有概率导致 SPI2 异常停止!

<strong><font color="#004a85">问题分析</font> </strong>
  
最初怀疑是 SPI 的问题,因为在初始实现这部分功能时就遇到了很多坑,我也写过博文<a href="http://mcu.eetrend.com/blog/2021/100556346.html">华大MCU之五:SPI从机DMA模式配置(不能正常接收问题处理)</a>来专门记录遇到的问题。但是再一次整理了一下 SPI 的配置流程,并没有发现啥问题。在测试中发现,将 SPI2 使用的 DMA 停止,则不会出现问题,于是开始调查 DMA 的问题。

<strong><font color="#004a85">DMA 的坑</font> </strong>

最开始将问题重点放到了 DMA 的配置上,怀疑是不是 DMA 部分配置项不正确。但是,读数情况下 SPI 是工作正常的,如果是配置不对,应该是一个必出现的问题。转而又开始怀疑是不是配置时序(寄存器的配置的先后顺序)不对,反复查看代码也没有发现问题。正在一筹莫展之时,有同事提出了手册中 DMA 章节给出的一个注意事项:

<center><img src="http://mcu.eetrend.com/files/2021-12/博客/100556636-238065-2.png&quot; alt=“华大MCU之七:DMA 导致 SPI 异常停止的原因分析、DMA 配置的那些坑"></center>

其实,最开始实现 SPI 驱动时就关注过该注意事项,只是开始的理解是,这条注意事项是针对同一通道而言的,同一通道在工作时不能再次配置上面说的这些寄存器,不同 DMA 通道之间应该互不影响。然而实际情况是,只要 DMA 有任意一个通道在传输数据,其他所有通道都不可以配置!

这就导致了一个很大的问题,外设在工作中不可避免的要重新配置 DMA。例如,SPI 的 DMA 发送,由于发送数据长度是动态变化的,必须每次重新进行配置,则根据上面这一条,必须把该 DMA 下的其他通道(例如上面我的 SPI1 使用的通道)也都全部停止,这样就可能导致其他外设丢失数据。

最麻烦的是,这个问题没有找到任何其他的解决方法,只能是停止该 DMA 下的所有通道,进而来配置自己需要的那个通道参数。起初在寻找解决方法的时候,也考虑是不是可以用下图所示的寄存器位来进行一下判断,而是实际是下面的位根本没有任何用处。

<center><img src="http://mcu.eetrend.com/files/2021-12/博客/100556636-238066-3.png&quot; alt=“华大MCU之七:DMA 导致 SPI 异常停止的原因分析、DMA 配置的那些坑"></center>

还是以我上面的使用示例来说,SPI2 作为从机接收,由于使用了 DMA,MCU 并不能确定数据何时到来。即使 MCU 检测 DMAACT 未动作,可能在实际配置通道时,DMA 又变为了动作状态。

<strong><font color="#004a85">配置</font> </strong>

根据手册,使用 DMA 时需要先写寄存器将 DMA 控制器使能,使能方法是写 DMA 使能寄存器 DMA_EN.EN 位。 如下图所示:

<center><img src="http://mcu.eetrend.com/files/2021-12/博客/100556636-238067-4.png&quot; alt=“华大MCU之七:DMA 导致 SPI 异常停止的原因分析、DMA 配置的那些坑"></center>

我试了一下,不先使能貌似也没法发现啥问题啊!不知道为啥!?

<strong><font color="#004a85">无法获取当前传出数据长度</font> </strong>

先来说一下需求:在串口驱动中,串口的接收使用 DMA 来实现,DMA 配置为循环模式,在指定缓冲区中循环存放收到的数据,通过读写指针来标记数据的读和写位置。

然而,驱动库中 DMA 接口并没有能获取当前 DMA 传输了多少字节的接口!!!无奈只能选择修改驱动库,添加一些指定的接口,如下图所示:

<center><img src="http://mcu.eetrend.com/files/2021-12/博客/100556636-238068-5.png&quot; alt=“华大MCU之七:DMA 导致 SPI 异常停止的原因分析、DMA 配置的那些坑"></center>

后来,为了不修改驱动库,我直接把接口放到了自己的驱动里面,然后使用寄存器直接读取:M4DMA1->MONRPT0_f.DRPT,这样的话,需要注意与通道号的对应关系,如 MONRPT0 即通道 0。

<strong><font color="#004a85">中断的使用</font> </strong>

在华大的 DMA 中,中断默认都是开启的,这点在配置 DMA 的时候需要特殊注意。我们需要使用 DMA 的屏蔽中断寄存器来屏蔽不使用的中断。如下图示:

<center><img src="http://mcu.eetrend.com/files/2021-12/博客/100556636-238069-6.png&quot; alt=“华大MCU之七:DMA 导致 SPI 异常停止的原因分析、DMA 配置的那些坑"></center>

在实际写代码时,需要调用 en_result_t DMA_DisableIrq(M4_DMA_TypeDef* pstcDmaReg, uint8_t u8Ch, en_dma_irq_sel_t enIrqSel); 来关闭不需要的中中断。例如,DMA 的块传输完成中断 和 传输完成中断 通常不会一起使用!这点对于用惯了 ST MCU 的人来说需要特殊注意!

<strong><font color="#004a85">结论</font> </strong>

1、在使用中,发现华大 MCU 的外设配置中,有不少的坑,尤其是对于我这种用惯了 STM32 的人来说。例如之前说的 SPI、中断、这里说的 DMA 等等。

2、千万不要完全相信华大 MCU 驱动库中给出的示例,里面是丢三落四各种错误!

3、在用户手册中一些比较重要的点,手册往往是一笔带过,在我们实际使用中容易被忽略,而往往忽略的就是问题的关键。而且对于异常情况,手册中没有很详细的描述,导致真正出现问题时,从手册中不能很快分析出原因。

4、对于某些外设,有很多用来观察外设工作的寄存器(ST 没有这部分寄存器),我们在实际使用中,往往需要等待这些寄存器中的某些位被置位之后才可以继续操作,否则会出现各种错误

<strong><font color="#004a85">参考</font> </strong>

HC32F460系列用户手册Rev1.21.pdf

<strong><font color="#FF0000"> 相关阅读:</font></strong>
<a href="http://mcu.eetrend.com/blog/2021/100555546.html">华大MCU之一:HC32F460 替换 STM32F411 移植记录</a>
<a href="http://mcu.eetrend.com/blog/2021/100555692.html">华大MCU之二:USB 驱动 + FatFs 的移植使用详解</a>
<a href="http://mcu.eetrend.com/blog/2021/100555710.html">华大MCU之三:时钟控制器(CMU)配置记录</a>
<a href="http://mcu.eetrend.com/blog/2021/100555934.html">华大MCU之四:使用问题记录</a>
<a href="http://mcu.eetrend.com/blog/2021/100556346.html">华大MCU之五:SPI从机DMA模式配置(不能正常接收问题处理)</a>
<a href="http://mcu.eetrend.com/blog/2021/100556529.html">华大MCU之六:SEGGER Embedded Studio及Ozone使用Jlink调试</a>

版权声明:本文为CSDN博主「ZC·Shou」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ZCShouCSDN/article/details/121414394
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。