1:3280芯片手册详解过程:
MAC 控制器支持 DMA 接收和发送,内部在接收和发送方向各有一个 2048 字节的 FIFO作为缓存。由于 FIFO 深度所限,MAC 控制器不支持硬件自动流控机制。
模式和带宽的切换
1:在做 MII 和 RMII 之间的切换前,应该先掉电
2:上电后软件重新配置芯片系统控制模块中MAC 的工作接口模式寄存器,之后再启动 MAC 控制器
3:需要注意的是,在收发功能开启的状态下不能对双工模式或速率进行改变(先关掉Mac收发,这样可以避免出现大量的错包的情况)
1:所有的发送中断和接收中断触发的条件都是dma操作完成(dma完成数据搬运的操作);
2:较早发送和接收中断说明数据帧较大不是一个buffer发送;
芯片的寄存器空间:
MAC 模块支持以太网 PHY 的 MII 接口和 RMII 接口。
CSR(Control & Status 寄存器)共占有 8KB 地址空间,分为两段:DMA CSR 和 MAC CSR。
AHB Master 接口为 DMA 模块与系统主机的接口。
APB 接口即 CSR 接口,用于读写访问 DMA CSR 和 MAC CSR。
DMA 模块有独立的发送和接收引擎,进行系统内存与 MAC 间的数据搬运,将 CPU 的 干预最小化,只在帧发送或接收结束以及其他一些条件(如发生错误)下中断 CPU。 DMA 数据传输基于具有链表结构的 Descriptor 和数据缓冲区
一个 Descriptor 单元由 4 个双字组成。在发送方向和接收方向各有指向发送和接收数据缓存的 Descriptor。发送 Descriptor、接收 Descriptor 与总线一样,均为 Little-endian。
发送中断:表示一帧发送完成。当一帧发送完成后,发送 Descriptor TDES1 的最高位清
- 软件可以读取发送信息,desc在初始化的时候最高位置0,表示主机可用,在发包时候我们需要赋值buff和数据信息,own置1表示dma可用,启动发送,发送完毕dma自动清除该位,所以我们可以不对dma的发送过程做回收操作;
不能访问发送数据缓存中断:表示 DMA 模块不能获取下一个 Descriptor,此 Descriptor
正在被主机占用,没有可用的有效发送数据,就是刚初始化完成的阶段;
接收中断:表示一帧接收完成。当一帧接收完成后,接收 Descriptor RDES1 的最高位清
- 软件可以对该 Descriptor 进行访问,表示现在主机占有该描述符,对数据操作完成,需要置1dma占有的回收;
寄存器描述的关键配置和筛查重点:
可以按照uboot的下的mac和dma的寄存器进行配置;
发送轮询请求。该寄存器启动 Tx DMA 检查
DMA 是否占有当前发送 Descriptor。在我们发包的时候手动写入该寄存器;
接收轮询请求。该寄存器启动 Rx DMA 检测
DMA 是否占有当前 Descriptor,在初始化结束后直接赋值,开始遍历接收dma描述符
接收 Descriptor 列表的起始地址:申请的描述符的地址,转化成物理地址;
发送 Descriptor 列表的起始地址 :申请发送的描述符的地址,转化成物理地址写入寄存器
MAC_FILTER:调试阶段只能收到广播报文,该寄存器过滤数据帧
Mac控制器初始化阶段:
/* set the adapte the ethaddr设置基地址 */
/* P1:disable mii io && enable rmii io 配置系统控制寄存器*/
/*P1: DMA reset,等待复位结束,AHB状态*/
/*P2: config only bus mode,配置dma的传输模式*/
/*P3: tx rx ring desc init,收发包描述符的初始化*/
收包的初始化: desc->des01.rx.own = 1;记得接收完毕回收资源;
/*if set the RI interrupte not set,收包触发不了中断的问题*/
desc->des01.rx.disable_ic = 0;
/* the data for rx the packet,收包缓存相关的赋值的操作*/
pTempRxDesc->des2 = (void *)K0_TO_PHYS(pTempBuf);
/*the virtaddr */
*(pDrvCtrl->pRxBufVirtAddr + ix) = pTempBuf;
发包的初始化
own等于0表示主机占有,发包初始化1;dma占有,dma负责清0;
/*P12: request input,将收包的轮训位置一的操作,一直在遍历收包描述符*/
/*P13: GmacFrameFilter register config,数据帧不过滤,因为这样我们收到的全是广播报文*/
/*P14:中断 /* interrupt config register 必须配置中断的系统寄存器,然后配置mac的中 断寄存器*/
/* P15 connect interrupt handler,收包的中断函数的挂载的实现 */
中断的处理过程完成的是:1:关闭中断2:处理中断;3:清除中断4:开中断
中断处理报文上送协议栈注意细节:主要操作之后要update的操作
关键点:1:描述符的复位;2:cur ,tail数值的环形操作的实现的过程
数据发送操作:
数据发送大致包括如下步骤:
1) 读取描述符占用状态,等待直到描述符空闲,或者等待超时。(own等于0表示可用)
2) 刷一下 cache,保证内存数据实时。
3) 根据发送数据,初始化描述符。(buffer和数据的配置)
4) 写 DMA 状态寄存器的 TI 位,清除发送结束标志;
5) 写 MAC_TX_POLL 寄存器 1,触发发送。(dma拷贝结束,自动清除own位)
6) 读取 DMA 状态寄存器的 TI 位,检查是否发送结束,或者等待超时(发送阶段暂时不要回收资源)
数据的接收:
类似地,接收数据前,软件需要分配一段内存空间作为接收数据缓存,并将接收缓存的
首地址写入内存中分配的接收 Descriptor 空间,最后启动 MAC 的接收引擎。MAC 会通过 AHB总线访问到接收 Descriptor 的内容从而得知接收数据缓存的地址,这样就会把接收到的报文写入数据缓存,在上送协议栈的时候,是拷贝一份上送,而不是将指针赋值
Uboot下gamc代码的分析
blx_enet_init(bis);------>gmac初始化的入口函数,在这个函数当中完成函数指针的挂载
* must enable rmii io first */ 首先配置系统寄存器的值和io的多路复用
/*rmii的设置和iomux的使能*/
/* wait DMA Reset Complete */
/* wait DMA AHB master FSM in idle */
dprintf("P4: Configure Bus Mode Register.\n");
dprintf("P6: Rx/Tx ring descriptor list initialization\n");
dprintf("P9: Configure DMA Operation Mode Register\n");
dprintf("P10: Clear interrupt request\n");
dprintf("P11: disable DMA interrupt, use polling\n");
dprintf("P13: DMA Tx & Rx Enable\n");
if (gsc3280_mac_phy_init() < 0) 设置mac的流控和能力集等信息,以及phy寄存器配置
dprintf("MAC P-5: Configure MAC Address Register.\n");
dprintf("MAC P-11: Enable MAC Tx & Rx\n");
GSC3280_MAC_WRITE(1, DMA_RCV_POLL_DEMAND); /* request input */
Uboot下收发包描述符的初始化:
flush_cache:使用非缓存的数据,刷新cache; /* use uncache address */
缓冲区的地址和描述符的基地址一定要注意地址对齐的操作
gsc3280_mac_phy_init:phy芯片的初始化和mac能力集寄存器的设置
gsc3280_mac_eth_tx:uboot发包函数
/* Make sure data is in real memory*/ 将buf指针转化成物理地址,开始发包
/*处理完数据帧的update操作,cur_rx的更新,当前描述符置为有效,update的操作
//tcp的客户端和服务器socket连接和收发数据异常的问题分析
1:定位解决vxworks作为tcp客户端收发数据,在打开wireshark的时候对端才会收到发送的数据,关闭抓包,数据发送到socket缓冲区,没有发送到对端的问题,定位原因是在抓包的时候会将pc网卡设置成混杂模式(所有报文上送处理,mac不过滤),这样pmblk在发送的时候都会上送pc协议栈,关闭抓包pmblk数据报文会被网卡过滤掉,因为没有包含报文有效信息,修改vxworks驱动代码,改循环发送为拷贝到buffer当中,一次上送协议栈处理,这样vxworks作为tcp客户端收发数据正常
2:定位vxworks作为tcp服务器无法恢复syn连接报文,排除报文异常导致的连接失败,dump出上送协议栈的报文,没有发现错误;报文时间戳丢包,写了个linux下的客户端,关闭linux下rfc1323的时间戳配置,还是握手失败连接超时,所以怀疑和时间戳问题不大,正在分析协议栈的初始化,怀疑是协议栈的组件的参数和配置问题;
wiki调试日志信息如下:
在收包中断当中打印信息导致设备异常,因为涉及到中断的重入导致的问题;
1:设备启动到命令行下,ping主机ip,ping不同,无法进入中断处理函数,现在怀疑是dma初始化配置的时候存在问题,重点分析了rtg的start函数和send函数关于dma配置的部分,暂未发现问题;
2:准备结合linux内核下dma初始化的代码综合比较下,dump出寄存器的值比较寄存器的差异和配置;
2019/11/14
1:dump出mac控制寄存器,分析未发现差异和区别,初步怀疑是dma的配置或者dma desc初始化的问题;
2:设备在ping的时候抓包分析,发现对端设备没有收到ping包报文,报文没有正常发送;
3:dump出mac的dma相关的控制器数值分析差异和配置以及Desc初始化的流程和内存申请的分析;
4:分析uboot写个rt_thread的相关dma的配置和初始化;
2019/11/18
1:打印分析vxworks和uboot下ping数据包的内容,数据内容基本无差异;
2:在开始dma传输之后,打印dma状态寄存器,一直提示dma正在传输,等待dma传输完成,所以怀疑是dma传输这部分可能存在问题;
3:分析dma传输的初始化过程和报文desc的构造过程;
2019/11/20
1:dma描desc初始化部分重现定义描述结构体整改,开始发包,发包完成的相应bit位可以正常置位;
2:抓包分析发现arp的数据包可以正常发送,但是源mac为0,正在分析vxworks5.5如何初始化mac地址;
2019/11/21
1:mac地址可以正常设置和show出来,抓包分析mac地址设置正常;
2:调试发包中断,在配置了mac相关的中断寄存器后,和中断源相关的中断号之后还是无法触发,定位是中断控制器没有配置,配置完中断控制器后,中断可以触发(中断控制器相关寄存器没有使能);
3:中断触发之后,进入中断处理函数return之后,系统无法正常接着执行,感觉像是中断没有正常退出,正在定位;
2019/11/22
1:定位中断触发之后,进入中断处理函数return之后,系统无法正常接着执行,感觉像是中断没有正常退出,分析发现是在中断函数当中使用printf打印函数导致的中断的重入的问题;
2:收包中断可以正常触发,调试中断处理和报文解析上送协议栈,但是上送协议栈死机;
2019/11/26
1:定位报文上送协议栈死机,发现是收包缓存的地址转化有问题,修改和整理包缓存部分的代码,可以将报文正常上送协议栈;
2019/11/27
1:收包中断正常,但是arp的回包无法收到,打印报文信息发现只能收到广播报文,单播报文收不到;
2:初步怀疑是mac控制器的配置和phy的寄存器的配置问题,dump出uboot下和vxworks寄存器发现无差异;
3:仔细分析芯片手册,发现MAC_FILTER寄存器的最高位是包mac地址过滤位,将过滤功能关闭之后可以正常收到报文,(发送给自己的单播报文为什么会过滤掉待查);
4:将报文上送协议栈解析,解析完毕没有回应,正在分析上送协议栈的方式和部分代码;
2019/12/3
1:设备socket测试发现udp可以正常收发数据,tcp连接和发送数据存在问题;
2:抓包数据分析,发送数据之后,回包较慢,需要多次request,导致网络拥堵;
3:初步定为是mac包过滤关闭,大量报文上送导致网络拥堵,协议回包较慢,正在定位中;
4:dump出linux内核下寄存器和vxworks下寄存器分析,没有发现异常,正在分析代码中;
2019/12/4
1:抓包分析vxworks分别作为tcp服务器和客户端的情况,分析报文内容;
2:报文内容发包分析,发现发送的数据包丢失端口号和协议相关的信息,所以初步还是怀疑协议栈的问题;
2019/12/5
1:抓包分析vxworks分别作为tcp服务器和客户端的情况,分析报文内容;
2:作为tcp服务器端的时候,可以收到syn连接报文,正常上送协议栈,但是没有报文回复,怀疑是协议栈的问题;
3:作为tcp客户端的时候可以正常发包,但是发包内容数据部分为空,怀疑是收发包代码的问题,正在分析;
2019/12/10
1:发送的数据内容为空,这部分怀疑是驱动代码发送mBlk链式数据的时候存在问题;
2:参考别的mac控制器,使用netMblkToBufCopy函数接口,拷贝发送报文,但是报文大概率发送失败;
3:dump出发送报文的长度和发送报文的内容,发现和正常发送的报文没有差异,正在定位;
2019/12/11
1:参考别的mac控制器,使用netMblkToBufCopy函数接口,拷贝发送报文,但是报文大概率发送失败,TLB报错,定位发现在拷贝报文的时候,buff是虚拟地址在转化成dma操作的时候需要转化成物理地址;
2:地址转化之后可以dma发包,但是对端抓包分析报文乱码,但是我buf当中的格式是正确的,定位是在操作的时候cache缓存没有刷新,刷新之后正常;
2019/12/12
1:收发包正常,跑一段时间之后,设备异常,定位发现是pmblk存在内存泄漏,释放内存之后跑一晚上,设备正常,没有出现死机问题;
2:vxworks作为tcp的客户端收发数据在打开wireshark的时候收发数据是正常的,关闭之后对端收不到数据,但是我的发送函数正常调用;
2019/12/13
1:分析wireshark和socket的底层实现原理,socket在发送数据的时候,内核会为每一个socket创建一个接受和发送的buffer,send函数只是将数据从用户空间拷贝到内核buffer,真正的发送是tcp实现发送,不由我们控制;
2:所以怀疑是socket的buffer设置和tcp协议的配置问题导致的数据发送到buffer但是没从buffer发送到对端设备;
2019/12/23
1:定位解决vxworks作为tcp客户端收发数据,在打开wireshark的时候对端才会收到发送的数据,关闭抓包,数据发送到socket缓冲区,没有发送到对端的问题,定位原因是在抓包的时候会将pc网卡设置成混杂模式,
2:这样pmblk在发送的时候都会上送pc协议栈,关闭抓包pmblk数据报文会被网卡过滤掉,因为没有包含报文有效信息,修改vxworks驱动代码,改循环发送为拷贝到buffer当中,一次上送协议栈处理,这样vxworks作为tcp客户端收发数据正常;
3:定位vxworks作为tcp服务器无法恢复syn连接报文,排除报文异常导致的连接失败,dump出上送协议栈的报文,没有发现错误;
4:报文时间戳丢包,写了个linux下的客户端,关闭linux下rfc1323的时间戳配置,还是握手失败连接超时,所以怀疑和时间戳问题不大,正在分析协议栈的初始化