你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

关于STM32 DMA重新使能的话题

[复制链接]
STMCU小助手 发布时间:2021-1-27 11:06
关于STM32DMA重新使能的话题
有人发现当DMA配置为normal模式,一轮传输完成后再使能同一DMA数据流时,即使有DMA请求产生,DMA根本不进行数据传输。这里不妨以STM32F4为例聊聊该话题。
其实,在非循环模式下配置的DMA数据流传输结束后(即要传输的数据数目达到零),除非软件重新对数据流编程并使能该数据流(通过将 DMA_SxCR 寄存器中的 EN 位置 1),否则DMA 会停止传输(硬件会将DMA_SxCR 寄存器中的EN 位清零)并不再响应任何DMA 请求。也就是说,当一轮DMA传输完成后,简单来一句__HAL_DMA_ENABLE(hdma)并不能再次重启DMA传输,必须先行对数据流重新进行初始化配置,然后使能该DMA数据流。
不过,要对STM32F4系列内部各DMA数据流进行配置,首先要保证 DMA_SxCR 寄存器中的 EN 位已被清零。一般来讲,在进行DMA数据流配置前,先对该EN位进行写0去禁用该DMA流,然后读取此位以确认没有正在进行的数据流传输操作。将此位写 0 可能不会立即生效,因为只有当前所有传输都已完成时才会将其写为 0。当读取到 EN 位为 0 时,才可以配置DMA数据流。配置完成后,如果是再次配置的话,记得将先前的DMA 传输中在状态寄存器(DMA_LISR 和 DMA_HISR)中置 1 的所有数据流专用位置0, 然后重新使能数据流,即将 DMA_SxCR 寄存器中的 EN位置 1 激活数据流。
OK,这里拿个实际案例看看以加深下印象。
有人用STM32F4芯片做产品,他是基于STM32CUBE库做应用开发。用DMA做USART通信的数据传输,DMA配置为循环模式。
他发现HAL_UART_Transmit_DMA()这个函数在做了一次DMA配置后,第二次使用它更新配置时无法生效。比如按下面步骤操作:
【1】HAL_UART_Transmit_DMA(&huart1,DataBuff,10);
【2】HAL_UART_DMAPause(&huart1);                           
【3】HAL_UART_Transmit_DMA(&huart1,&DataBuff[5],5);
【4】HAL_UART_DMAResume(&huart1);                          
            
开发者的目的是希望先将DataBuff[0]至DataBuff[9]10个数据传到串口上去。中途调整DMA配置[即第【3】句],然后发送DataBuff[5]至DataBuff[9]的5个数据到串口助手上去。
结果发现经过2次配置后的结果没变,发送的都是DataBuff[0]至DataBuff[9]的10个数据。为什么呢?不妨一起看看。
上面第【1】句做usart TX的DMA传输配置。循环从DataBuf处开始取10个数据送往串口;
接着第【2】句是在DMA完成中断里进行。暂停USART TX传输的DMA请求,并延时2S;
然后第【3】句再做USART TX的DMA配置,循环从&DataBuf【5】处开始取5个数据送往串口;
最后第【4】句重新开启USART TX的DMA传输;
按照上面几步也貌似条理清晰,有根有据。可结果为什么发现第【3】句的二次配置没法生效呢?
从前面的描述我们得知,如果需要对某STREAM进行DMA配置的话,首先须DISABLE该STREAM,即先对DMA_SxCR寄存器的EN位清零。而且这个清零并不一定立即生效,必须保证该STREAM当前没有在进行DMA传输。所以,做清零操作后,还要去读该EN位,直至读到该位为0后方能对该DMASTREAM 进行再次配置。
HAL_UART_Transmit_DMA()函数里有对DMA_SxCR的EN位清零的动作,不过没有读取确认的动作。复位后DMA_SxCR寄存器的EN位默认是0毫无疑问,所以复位后第【1】句用HAL_UART_Transmit_DMA()函数配置后生效自然没问题。
上面的第【2】句在DMA完成中断里进行,暂停UART TX的DMA请求,还延时了2S。本意是想让DMA停下来,为后面二次配置做准备。但他这里只是暂停了DMA请求,加上这里配置DMA为循环模式,也就是说在进入DMA完成中断时,DMA又做了下一轮传输的准备,其中包括传输数据项数目寄存器DMA_SxNDTR的重装。此时尽管暂停了DMA请求,但该DMA流是处于传输未完成状态。
那么紧跟着的第【3】句对USARTTX的DMA二次配置,HAL_UART_Transmit_DMA()函数里虽然有对DMA_SxCR的EN位清零,但由于此时该STREAM处于传输未完成状态,所以无法实现最终清零。
既然无法对EN位清零,相关配置就无法写入生效。加上该函数没有对EN位是否为0的未做进一步确认判断,自然而然地下行到第【4】句重新开启USART TX的DMA传输。最后的结果当然还是按照老配置运行了。【有心的话,可以去STM32F4参考手册看看数据流 x 配置寄存器 DMA_SxCR,里面多个参数只有在EN位为0时方可进行写操作】
好了,就此打住。MCU开发中不少问题往往可能就卡在技术手册看得不到位。在开发过程中遇到难解问题时,有时细心看看手册的相关部分,或许会有踏破铁鞋无觅处,得来全不费工夫的感觉。
文章出处: 茶话MCU
% E/ z9 P( Y! @. l! z
收藏 评论0 发布时间:2021-1-27 11:06

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版