STM32N6 ADC DMA 传输失败案例分享
有人使用STM32N6系列芯片的ADC模块时,发现通过 GPDMA 往内存搬运转换结果时,出现如下现象:当DMA 的 Source Data Width 和 Destination Data Width 配置为 HalfWord 时,DMA 无法正常搬运 ADC 数据。
当两者配置为 Word 时,DMA 可以正常工作。
从眼前ADC分辨率角度看,转换结果有效位数小于等于 16位,基于应用经验认为 DMA 使用 HalfWord 数据宽度是不该有啥问题的。何况,事实上很多其它STM32系列也支持这样的配置,即源端和目的端的数据访问宽度都配置为Halfword。
**为什么到这里就不行了呢?**
看来有必要从STM32N6芯片的ADC外设相关的总线访问宽度找找原因,即从硬件接口层面找原因。
来,我们高举那盏名为耐心的灯,睁大双眼,一起游走于寄存器、时序图与文字段落构建的迷宫里,逐行逐段地叩问真相,心无旁骛。
功夫不负有心人,我们从STM32N6的参考手册中看到两处描述,可以作为问题的解释。
第一处: ADC 总线接口说明
手册里有这样的描述:
Slave AHB interface
The ADCs implement an AHB slave port for control/status register and data access. The features of the AHB interface are listed below:
• Word accesses
该描述清晰地指出:
ADC 通过AHB slave 接口对外提供寄存器及数据的访问;
该接口访问特性明确为字访问;
因此我们可以得知:
ADC 作为AHB 从设备,各类主设备对ADC寄存器的访问粒度为 32 位字;
DMA 作为总线主设备访问ADC 时,自然要遵循32位字访问粒度。
第二处: ADC 数据存储结构说明
在STM32N6系列参考手册里还可以看到如下描述:
The converted data are stored into the eight 32-bit word FIFO accessible through the ADC_DR register.
该描述说明:
ADC 转换结果不是简单存放在一个 16位或32位数据寄存器中,
转换结果首先进入一个 深度为 8 的 FIFO;
FIFO 的每个条目的宽度为32位字;
ADC_DR 其实是访问该 FIFO 的寄存器接口;
这意味着从硬件结构上看,ADC数据对外暴露的可访问原子单位是32位字,而非其它。
**小结**
对于STM32N6的ADC模块而言,虽然 ADC 的有效转换结果可能仅为 12 位或 16 位,但 DMA 是否能实现正常搬运,还取决于 ADC 数据接口是否允许以对应位宽访问。在这里,ADC 数据接口允许主设备访问的位宽明确要求为 32 位字。另外,ADC_DR 也不是一个普通静态数据寄存器。准确地说,它是 ADC内部FIFO 的读出映射寄存器。FIFO的每个元素为 32位,通过 ADC_DR 实施读取时,本质是在读取一个 FIFO 条目。
顺便提醒下,在使用STM32CubeMx配置STM32N6 ADC时,关于那个overrun behaviour的选项,目前请选择data overwriten,不要选择data preserved,不然基于STM32 HAL库代码进行ADC校准时会失败。初步估计库代码在这个地方的处理有点小bug,要待**完善。
OK,今天的分享就到这里,下次再聊。
页:
[1]