AXI-DMA有几种模式,其中最难使用的莫过于Scatter/Gather模式,以下简称sg模式,axi_dma的框架如下:
在AX7021上,有4路PL端的网口,该网口的驱动和PS端的驱动有所差别,移植到我们自己的RTOS下,需要重新做驱动,除了phy的配置,mac的配置,最关键的部分在于网络协议栈的描述符的处理,这里也就要涉及到sg模式的使用,要对网络协议栈也有比较强的理解。
该部分的结构如下:
这里axi_dma使能了sg模式,关于sg模式的使用,以下做一个介绍:
一、简介
axi_dma的使用需要在内存中实现一个常驻的结构链表,这个常驻的概念,可以是ddr里面,也可以在ocm中,这段内存在分配后,不能被破坏,关于这段结构,xilinx官方给出了结构的组成,如下:
这个结构体的基地址是由使用者构造的时候指定的,可以使用memalign结构,也可以直接将结构的首地址指定到ocm,0xffff0000地址上,这里需要注意的是对齐问题。
这个结构要被组织成为一个所谓的描述符链,也就是buffer description,简称BD,每一个BD都有一个指针指向下一个成员的地址,加入你需要128个描述符,在最后一个描述符的时候,需要重新指向第一个描述符,这样就形成了一个环形缓冲区,也就是bdring。
sg模式允许数据包被超过一个描述符描述,我理解的是load和unload的关系,描述符是可以复用的,一个典型的应用就是从一个位置存储或取header从另一个位置存储或者取实际的负载数据,这样可以有效的提高吞吐量。
为了说明描述符链中的各个包,使用起始帧位TXSOF和结束帧位TXEOF。当DMA获取了设置TXSOF的米饿哦舒服时,将触发起始传输,按照描述符继续获取后续数据包,直到碰到TXEOF,停止
这里也就是TXSOF开始,TXEOF是结束。
在S2MM通道,数据包开始被接收的时候,AXI DMA会把开始的这一包用RXSOF进行标记,告诉软件,这个包关联的描述符这里是起始包,如果接收的数据包的长度比较长,下一个描述符的数据部分则继续存储前序数据,一直持续到整个数据都被搬移走了,结束的时候,在最后一包标记一个RXEOF。
每个描述符的status字段,包含了这个描述符实际传输的字节数长度,我们可以通过从有RXSOF标志的的描述符遍历到RXEOF标志的描述符,这样来计算一共传输了多少长度的数据。
要使用SG操作,必须要先设置control寄存器和描述符的指针。
二、MM2S的使用
1.填充current descriptor寄存器,将要传输的描述符的起始地址写进去,如果地址大于32位,还需要填充高32位;
2.设置MM2S_DMACR.RS =1,来启动传输,同时,应该讲DMASR.Halted的位设置为无效,表明MM2S正在运行;
3.使能enable interrupts by writing a 1 to MM2S_DMACR.IOC_IrqEn and MM2S_DMACR.Err_IrqEn,使能完成中断和错误中断
4.将一个有效地址,写到tai descriptor寄存器,也就是尾部寄存器,如果地址超过32位,则要把高位也填充进去;
5.当写入tai 寄存器之后,会触发DMA从内存开始加载处理描述符,在多通道的情况下,数据包到达通道以后,才开始启动传输;
6.当被取出来的描述符处理之后,数据从mem被送到mm2s streaming通道。
三、S2MM的使用
1.填充current descriptor寄存器,将要传输的描述符的起始地址写进去,如果地址大于32位,还需要填充高32位;
2.设置S2MM_DMACR.RS =1,来启动传输,同时,应该讲DMASR.Halted的位设置为无效,表明S2MM正在运行;
3.使能enable interrupts by writing a 1 to S2MM_DMACR.IOC_IrqEn and S2MM_DMACR.Err_IrqEn,使能完成中断和错误中断
4.将一个有效地址,写到tai descriptor寄存器,也就是尾部寄存器,如果地址超过32位,则要把高位也填充进去;
5.当写入tai 寄存器之后,会触发DMA从内存开始加载处理描述符,在多通道的情况下,数据包到达通道以后,才开始启动传输;
6.当被取出来的描述符处理之后,数据从mem被送到mm2s streaming通道。