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

为何STM32H7的ADC数据不变?

[复制链接]
攻城狮Melo 发布时间:2022-11-13 13:27
有人使用STM32H7系列的ADC模块,定时器触发ADC,数据通过DMA传输到内存。对某通道连续转换几次后求个平均值。他却发现ADC结果虽没有什么问题,但一批数据出来后就纹丝不动了。DMA传输本来设计成的Circular模式,感觉好像工作在Normal模式,结果显然有点不合理。
鉴于这个现象和所用芯片,估计是因为Cache使用方面的原因,客户也的确使能了Cache。具体怎么回事呢?我们一起来看看。
我这边使用H743Nucleo板和ST免费的STM32CubeIDE。STM32H743片内有个Vrefint信号,电压一般在1.2v左右,用它做ADC的输入信号来测试。用LPTIM触发ADC转换,每读到5个数据就求个平均值。
我这里定义了一个6字大小的数组,uint32_t  AdcDataViaDMA [6];前5个位置放实时ADC数据,第6个位置即AdcDataViaDMA [5]存放换算后的最终Vrefint电压平均值,单位是mv。
我们使用STM32CubeMx进行配置。重点看下ADC的配置:[注:ADC是16位的]

/ a- K* k7 H* N) t
微信图片_20221113132735.png

: A/ v+ ^4 P5 j0 p7 N
微信图片_20221113132729.png
. @$ g# q: F* Q" U5 y/ n
生成初始化代码后,添加用户代码。我把数组AdcDataViaDMA【】指定在片内RAM2区域。
__attribute__((section(".AdcDataViaDMA")))   uint32_t AdcDataViaDMA [6];

0 h/ n  }3 U! P  S; `
微信图片_20221113132726.png
微信图片_20221113132657.png
% B- @( i3 u: c$ E6 X8 }6 h' v
HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED );
HAL_ADC_Start_DMA(&hadc3,(uint32_t *)&AdcDataViaDMA [0], 5);
HAL_LPTIM_PWM_Start(&hlptim2, Period, Pulse);

5 ^( s% p) E! Y
然后编译调试。同样出现数据纹丝不动的现象。我每次在传输完成中断回调函数里做数据处理。相关处理代码如下图所示:

7 V. t' q- _/ A. V. q0 f3 X6 p7 {
微信图片_20221113132648.png
, d  E4 P' J2 \
TIMER不停触发ADC,DMA传输也是循环的,按理数据应该动态改变。即使变化不大,也不至于纹丝不动。【除AdcDataViaDMA [5]外,其它均为AD转换值。】

% L9 W& l# k% i/ Q8 R' }* _
微信图片_20221113132639.png

0 F) r, A: q6 {8 i7 i/ x1 k2 U
那是什么原因呢?目前我们是开启了Cache的。
5 J+ h& D. {3 W' w* W$ [
微信图片_20221113132632.png
; O# ?# U% E) u4 I! P% _
现在数据的大致流程就是,ADC转换结果出来后,DMA将数据写入SRAM,然后CPU读取SRAM里的数据。因为开启了D-Cache,当CPU针对SRAM做读操作时发生读Allocate,相应内存地址的数据被拷贝一份到Cache里。下次CPU再去相应SRAM地址去读取时,因D-Cache里已经有了一份有效数据,即发生Cache命中事件,CPU就直接从Cache读数据,而不读取SRAM了。
+ ^- x; `4 R0 R# v
微信图片_20221113132627.png

3 Q2 _' n* S4 O3 Z. z, c3 f1 r
所以,尽管后面时间里ADC因TIMER不停触发而产生新数据并被DMA传输到SRAM,但CPU除了第一次外总是从D-Cache取数据,导致该数据永远就是第一次读到的数据而不变。
既然这样,我们可以在CPU每次针对SRAM做了读操作后,对D-Cache相应内容做无效处理,迫使CPU每次要取数据时因Cache Miss而发生读Allocate操作并更新Cache数据,进而保证CPU读到跟内存SRAM里一致的Cache数据。
我在DMA完成中断回调函数里加上一句针对D-Cache作无效操作的代码。如下图红线标注的代码。

( x; A7 J: Z% n0 Q
微信图片_20221113132623.png
) t$ k4 D! G) X7 N
然后进行测试,立即可以看到不断实时变化的数据了。【下图我随机截取的几个结果】
# t" i  V; d9 r" W1 ^
微信图片_20221113132619.png
6 D$ b4 P- R0 R# m! g! b
不过,请注意这里针对D-Cache相应地址做了无效化处理的代码要放在最前面。你可以将该句试着放在对AdcDataViaDMA [5]赋0语句的后面验证下,看看会有什么现象,要看细致点,不然发现不了问题。顺便提醒,目前所用SRAM区域在没有做MPU配置的情况下,默认为write back加write allocate Cache属性,我在前面贴图时已经圈出来了。有兴趣的话,可以基于上述代码自行进一步探究下,此处就不延伸了。
另外,除了上面的解决办法外,还有就是将上面内存数组所在区域做MPU设置,关闭那部分区域的Cacheable属性。

0 e& X. E' a) s: g/ @$ S
微信图片_20221113132604.png
+ n# k% r; T  O/ n& P: J3 v# Y
当这样配置后,之前那句针对Cache无效化的代码就不需要了。生成代码进行测试,结果跟预期一致,数据保持实时动态变化,结果也正常。
上面主要就开启D-Cache后,发生了主设备数据读取不一致的问题给出了些解决办法及思路,同时也算是给出些应用提醒,以后碰到类似问题时可以参考。当然,有人或许会说,完全不开启芯片的D-Cache功能也可以解决问题。诚然,但我们需要综合考虑开发便利性和芯片的性能发挥,尽量就问题做些针对性的处理以充分发挥芯片性能。

/ ]1 @. @6 @0 N0 {! x6 L/ ~
转载自:Miler
) a8 F6 `8 D4 d" B  s
赞 收藏 评论0 发布时间:2022-11-13 13:27

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版