STM32家族中的有些系列,比如STM32G0/STM32G4/STM32L4+/STM32H7等系列都内置了DMAMUX模块,它是干什么用的?跟DMA有什么关联?
简单点说,它是DMA请求中转调度器,或说DMA请求路由器。基本功能就是将各路DMA请求经过它的再分配调度后连接到相应的DMA控制器传输通道以实现DMA传输。
用过不带DMAMUX的STM32芯片的DMA模块的人可能会问,之前没这个模块,不是照样用吗?外设申请DMA请求,DMA控制器做出应答响应后即可实现DMA传输。为什么后面推出的STM32系列往往要增加这个DMA请求复用路由器呢?
我们不妨先看看那些片内不带DMAMUX的DMA外设请求与DMA传输通道的关系。
下图是STM32F3系列的DMA1的DMA请求与传输通道的映射关系图[STM32F1系列的DMA架构跟F3系列类似]:
拿上图中的DMA传输通道Channel2为例,DMA请求可以来自多个外设,不过每路传输通道每次只能配置1个外设请求。从上图可以看出,各个外设请求所对应的DMA传输通道是唯一且固定的。比方说,若TIM1_CH1和TIM2_UP两个外设事件都想申请DMA传输,这时就有点麻烦,因为二者都只能申请DMA传输通道Channel2。那能不能有稍微灵活点的DMA请求与传输方案呢?像遇到多个DMA请求只能申请同一DMA传输通道时就麻烦了。ST后面推出的STM32F4/STM32F7等系列,在这个地方就做了调整。
下面是STM32F4系列的DMA2的DMA请求与传输通道的映射关系图:
不难看出,STM32F4系列的DMA架构跟STM32F1/F3有所不同,在DMA请求与DMA传输通道的映射安排方面有明显改良和优化,相比之下,DMA请求与DMA传输通道间的安排更为灵活了。
比如ADC2、SPI1_RX、USART1_RX原则上都可以申请Stream2的传输,由于每条传输通道每次只接受1个外设请求,根据上表,我们还可以将SPI1_RX请求安排在Stream0,将ADC2的请求安排在Stream3。显然,各个外设请求所对应的DMA传输通道的安排不像上面F3/F1系列那样固定僵化了。
不过,尽管说STM32F4系列的DMA请求与DMA传输通道的映射关系多了些选择性,更为灵活了,但各个外设请求与能申请到DMA传输通道的映射关系还是固定的。比方ADC2的请求只可能申请到Stream2或Strem3,而SPI_RX的请求就只能申请到Stream0或Stream2,别的DMA传输通道就别想了。这样的话,还是有可能遇到某些情况下安排不过来的局面,最糟糕的情形就是尽管DMA请求安排不过来,个别DMA传输通道可能又还闲着。那有没有可能DMA请求跟DMA传输通道的映射关系不事先固定下来,而在具体使用时通过一个中间机构来调度协调呢?这样既保证DMA请求安排的灵活性,又可提升DMA控制器的使用效率。另外,这里还有个问题,目前能申请到DMA传输的仅限于外设事件,能不能将DMA请求范围拓展下呢,让更多的其它非外设事件也可以产生DMA请求呢?
这时,应该说DMAMUX就基于这些需求应运而生了!【注:这是我理解加想象的推论,毕竟芯片不是我设计的。】
说到这里,打个生活中发快递的比方。早期发快递,我们往往是靠几张有限的快递小哥的名片或电话来找相应的小哥收发快递,如果他的名片你一下找不到或者说你联系他时,他正忙别的事情一会不会根本照顾不到你这里,别的小哥你又联系不上,这时你就只能干着急了。后来,快递公司搞了个客服部门,只需知道客户电话,随时申请快递,客服帮你搞定。客服帮你搞定不是亲自来给你收发快递,而是帮你灵活调度快递小哥来完成。小哥张不行,小哥李来。此处的客服部门就像这里描述的DMAMUX。当然,有了客服还可以拓展出其它跟快递有关的便利事务。
回到DMAMUX,它除了实现对DMA请求与DMA传输通道的灵活配置外,还可以基于某些本不能产生DMA请求的事件而生成DMA请求,该请求具有跟其它外设事件所产生DMA请求的同等效果,比方基于GPIO的外部中断事件产生DMA请求。
对于那些具有DMAMUX模块的STM32芯片,所有的DMA请求不再直接与DMA控制器相关联,而只是先与DMAMUX相连,DMAMUX的DMA请求路由通道再与DMA控制器相连。至于某个DMA请求到底跟DMA控制器的哪条传输通道相关联,通过软件配置,并不事先固定下来。对于那些用过不带DMAMUX的STM32用户来说,当它切换到带DMAMUX的STM32芯片,使用DMA时会发现之前的那张基于DMA请求与DMA传输通道映射表不复存在了,而换之以基于DMAMUX的各类输入、输出信号或事件的映射表。【注:DMA请求或称DMA请求线】
下面以STM32G4系列内置的DMAMUX为例,对其概念架构及工作原理再做些具体的介绍。下图是STM32G4系列内部的DMAMUX的功能框图。
从功能框架上看,它由两大块组成。
第一块,DMA请求路由器【Request Multiplexer】, 上面框图右上方的红色方框。
它的核心功能就是实现DMA请求的路由转发。其组成单元是DMA请求路由通道,请求路由器由多个请求路由通道组成。
每个路由通道可转发1路DMA请求【dmamux_req_outx】到DMA控制器并与相应的DMA传输通道相关联。
每个路由通道都与所有DMA输入请求线【dmamux_reqx】并行相连,并且都有同步单元【Sync】和DMA请求计数器。多个同步输入信号与各同步单元并行相连,可用来控制DMA请求的转发输出。
各同步单元还可以生成DMA路由事件【dmamux_evtx】,该事件既可以作为DMAMUX其它路由通道的同步输入信号,以实现不同路由通道之间的级联【不同路由通道最终对应到不同的DMA传输通道】,又可以作为DMA请求生成器的触发输入信号,可以实现基于不同DMA请求之间的级联关系。
第二块,DMA请求生成器【RequestGenerator】,上面框图中左下方的红色方框。
它的核心功能,就是生成DMA请求。其组成单元是请求生成通道,由多个请求生成通道构成请求生成器。每个生成通道与所有的触发输入信号并行相连,每个通道也具有DMA请求计数器。当生成器收到触发输入信号【dmamux_trgx】时,相应的请求生成通道则产生DMA请求信号【dmamux_req_genx】,并输出到DMA请求路由器。
通过DMA请求生成器基于触发信号生成DMA请求,一方面可以弥补只是部分外设事件【dmamux_req_inx】才可以申请DMA传输的局限,另一方面可以将不同DMA请求借助路由器模块输出的路由事件【dmamux_evtx】关联起来,让DMA应用更为灵活并富有创意。
下面继续以STM32G4系列的DMAMUX为例,将上面的功能框图具体化看看。
根据上图,STM32G4芯片因不同子序列,DMAMUX的路由输出通道数可能是12或16。
DMAMUX的请求生成器通道数为4,请求生成器可接受的触发输入信号有21个,路由通道的同步输入信号可达21个,可接受的外设请求输入信号或事件可达115个。
DMAMUX路由输出通道数最终与片内DMA控制器所拥有的传输通道相对应匹配。
这里DMAMUX的请求生成器通道数为4,即有4个通道可以基于触发输入信号产生DMA请求:
用来可以生成DMA请求的触发输入信号可以有21个:
从上图可以看出,绝大部分触发信号都源于外部中断事件,还有几个来自DMAMUX路由通道产生的DMA路由事件【红色方框内所示】。这么多触发输入信号,而可以产生DMA请求的生成通道才4个,每个通道根据什么来选择所需要的触发信号呢,当然是通过各个生成通道的配置寄存器DMAMUX_RGCnCR进行选择配置【n对应生成器通道号】。
可以用来作为DMAMUX路由通道的同步输入信号也可以有21个,具体内容跟上面的触发输入信号一样。同样,具体到各个路由通道选择哪路信号作为同步信号,通过路由通道配置寄存器MAMUX_CmCR进行配置即可【m对应路由通道号】。
可接受的外设请求输入信号或事件可达115个,这个数据应该包括了DMAMUX生成器的4个通道生成的DMA请求。手册一直将来自外设的DMA请求和基于生成器产生的DMA请求分开表述的,这里突然笼统地将二者称之为外设请求感觉有点突兀。
关于DMAMUX模块的大致原理及基本框架就介绍到这里,更多细节还得阅读STM32芯片相应的参考手册。当对它有了一个相对清晰的框架性了解后,再结合应用实例和手册就更容易理解和把握更深入的细节。