理解STM32中DMA的FIFO和突发模式

STM32的DMA中FIFO和突发模式理解
学习stm32DMA时遇到了FIFO和突发配置的疑惑,看手册完全云里雾里,节拍是什么等等都不清楚。
首先理解什么是突发,突发传输就是两个设备进行数据传输,一个设备发数据,一个设备接收数据,或者像是CPU到内存进行读取数据,肯定是每读取一个字节,读取指针就会自增一次,如果每次读一个字节,还要到程序里面执行一个指针自增指令的话,那CPU岂不是时时刻刻都在读取内存然后指针自增指令执行,那也太蠢了,CPU利用率太低了,所以出现了突发模式,我设定为CPU进行读内存,我指定一个宽度,每次读取都读这一个宽度的数据,比如为128B,每次读取,指针会自己增加,读取满了这128B再告诉CPU读了一次,那么这个128B就是一次突发的大小,只是进行简单的封装,突发不管每次传输多少,突发规定的是指针每次增加的单位宽度是多少,就像上面的我读取内存,规定每次读取1280B,那么一次读取就是10次突发,相当于读写指针按每次自增128进行了10次。突发就是这么个意思,是为了方便传输时指针自增进行的优化操作,将每次指针自增由指令控制,封装为硬件突发模式进行。

上图就是stm32里面突发和FIFO配置的表。
突发模式一定是与FIFO一起使用的,突发的意思就是打包,而且只针对接收端的配置,与发送端没有关系,这么理解,突发的节拍即按接收端数据宽度作为单位,突发可以选择4、8、16节拍进行打包,跟架子鼓一样,每4秒敲一次,这里就是接收端按接收宽度,每收到4次该宽度作为一次突发,那么就是4节拍一次突发。
如果接收端数据宽度为byte,选择4节拍一次突发,如果将每次突发封装为一个突发包的话,那么就是一个突发包大小为4字节,每次突发发送一个突发包,意思就是每发送4字节即4次接收端的数据宽度,进行一次打包突发,对应到FIFO上面就是,FIFO选择的阈值是满了就发送给接收端,但是一次传输必须是以突发包大小作为单位来进行,所以选择1/4阈值,则满1/4就进行传输,正好满一次突发;按1/2阈值,满1/2传输一次,正好是2个突发包,那么就是传输一次突发两次,以此类推;
所以选择突发计算的是突发包的位宽,即突发包大小=节拍*接收端数据宽度,每次FIFO传输的大小由FIFO自己的阈值决定,但是每次传输的大小一定要大于突发包才行,因为突发包是最小的单位,一次传输内进行几次突发不重要,系统会自己配置,但是需要注意的是,一次FIFO传输必须是整数个突发包的大小宽度,不能切分突发;
突发和数据宽度紧密联系的根本原因,就像是C指针一样,char指针自增是+1,而int* 增长是+4每次,所以突发就跟指针增长一样,是指针增长的封装,
实际例子:
配置突发为4节拍,这是确定一次突发的大小宽度是多少,假如接收端端口数据宽度配置为半字(2B)那么一次突发就是8B,切记一次突发不是一次传输,一次传输包含多次突发,突发本质上是指针增长,即接收端地址自增,每次传输由FIFO决定,FIFO如果选择的阈值为1/4,那么就是说FIFO每装满1个字,就触发传输,传输1个字,但是这里突发的最小单位为8B,而一次传输却是4B,肯定不行。打个比方,我设定指针每自增一次最小增量为8字节,但是现在你却要让指针自增一次只移位4B,肯定不行,因为我已经规定了指针最小的自增长度为8。突发就是这个意思,突发就是为了地址接收数据的同时进行指针偏移,突发包的大小就是指针每次偏移的最小位移,所以FIFO阈值最小只能是1/2,所以一次FIFO传输为1/2*4字=2字=8B的数据,正好一次突发,而3/4又不行,因为3/4阈值FIFO一次传输为12B,而我每次指针自增宽度就是突发包的大小为8B,你说这次传输为12B,我不能是指针自增1.5吧,有见过int * +1.5的么,肯定没有。
最后,还有一点,那就是记住,突发次数是不需要你管的,一次传输有几次突发系统会自动算出来,一次传输的大小一定是有FIFO阈值决定的,你只需要确保,每次传输的大小一定是整数个突发大小就行,每次传输就行几次突发不需要你管。

物联沃分享整理
物联沃-IOTWORD物联网 » 理解STM32中DMA的FIFO和突发模式

发表评论