赞
踩
记录学习总结,能力有限,仅供参考
1. RTL8363支持:
每个端口都支持全双工
支持IEEE 802.1Q
VLAN支持4096个VLAN和32个额外VLAN
单芯片2+1端口10/100/1000M无阻塞交换机架构嵌入式2端口10/100/1000Base-T
PHY每个端口支持全双工10/100/1000M连接(仅在10/100M模式下支持半双工)
2. RTL8363结构图:
3. RTL8363框架图:
1. RTL8363使用的数据接口为rmii (限速100m)
RMII(Reduced Media Independent Interface)是一种常用的以太网物理层接口,用于将以太网 MAC(Media Access Control)层和 PHY(Physical Layer)层连接起来。它通常用于嵌入式系统中,使得系统可以通过以太网进行数据传输。
rtl8363不同模式接口下TXD0可能为RXD0,注意查看datasheet
)2. SMI管理接口
包括MDC和MDIO两条引脚线。MDIO是一个PHY的管理接口,用来读/写PHY的寄存器,以控制PHY的行为或获取PHY的状态,MDC为MDIO提供时钟。
3. phy和mac
mac媒体访问控制子层协议,处于链路层向下部分
phy即物理层设备,向上对接mac
4. cpu与RTL8363连接模式为:固定模式(mac_to_mac)
固定模式(mac_to_mac)
mac_to_mac简而言之,需要手动固定一个虚拟phy设备连接。
phy模式(mac_to_phy)
5. RTL8363寄存器
现在datasheet都没有相关寄存器说明,都被提供的api接口封装了。phy id根据mdi高低电位选择。
- 主控芯片arm:sigmastar ssd222d
- Linux内核版本:Linux ubuntu 4.4.0-142-generic
- 网络文件:mdrv_emac.c
- 连接模式:rmii,mac_to_mac
1.boot下支持
2. boot下初始化phy设备
3. 虚拟phy设备
- //phy扫描
- void MDrv_EMAC_PhyAddrScan(void)
- {
- u32 word_ETH_MAN = 0x00000000;
-
- MHal_EMAC_Write_JULIAN_0100(JULIAN_100_VAL);
- ThisUVE.flagISR_INT_DONE = 0x00;
- MHal_EMAC_read_phy(phy_id, PHY_REG_STATUS, &word_ETH_MAN);
- if((0xffff != word_ETH_MAN)&&(0x0000 != word_ETH_MAN))
- {
- //printf("phy [%d]=%x\n",phy_id, word_ETH_MAN);
- return;
- }
-
- for (phy_id = 0; phy_id < 32; phy_id++)
- {
- MHal_EMAC_read_phy(phy_id, PHY_REG_STATUS, &word_ETH_MAN);
- if((0xffff != word_ETH_MAN)&&(0x0000 != word_ETH_MAN))
- {
- printf("find phy [%d]=%x\n",phy_id, word_ETH_MAN);
- return;
- }
- }
- printf("Can't get correct PHY Addr and reset to 0\n");
- phy_id = 29;
- }
- ,,,,,,
- //初始化 phy
- #ifdef CONFIG_ETHERNET_RTL8363
- rtl8363_config_init();
- #endif
- ,,,,,,
-
- //phy读写 MDC_MDIO_PHY_ID =29;
- MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_CTRL0_REG, MDC_MDIO_ADDR_OP);
- MDC_MDIO_READ(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_DATA_READ_REG, rData);
4. rtl8363提供的mdio读写api,需要将替换成平台mdio读写接口(smi.c)
- /* MDC/MDIO, redefine/implement the following Macro */
- #define MDC_MDIO_WRITE(preamableLength, phyID, regID, data) MHal_EMAC_write_phy( MDC_MDIO_PHY_ID, regID, data)
-
- #define MDC_MDIO_READ(preamableLength, phyID, regID, pData) MHal_EMAC_read_phy( MDC_MDIO_PHY_ID, regID, pData)
1. 接口验证
如果上述正常,但是在boot下还是网络不通,先验证rmii和MII管理接口是否正常
- //if (ThisBCE.loopback == PHY_LOOPBACK)
- // {
- printf("Rx Data");
- MDrv_EMAC_DumpMem((u32)packet, 0x40);
- // }
- // else if (ThisBCE.loopback == MAC_LOOPBACK)
- // {
- // MDrv_EMAC_tx(nic, (void *)packet, pktlen);
- // }
- // else
- NetReceive((uchar *)packet, pktlen);
如果上述接口有问题就需要去排除硬件问题,没有就需要验证代码问题。
2. rtl8363初始化流程
硬件复位 -> rtk_switch_init(); -> 配置rtk_macability参数 ->end
3. uboot调试总结
建议接触先从uboot下理解phy怎么挂载在网卡上,实现网络互通。再在kernel下实现对rtl8363的开发。
由于是mac_to_mac,不用纠结MDrv_EMAC_PhyAddrScan扫描不到phy,只需理解phy是在mac的向下层,mactomac不经过phy,所以手动虚拟一个phy设备即可。
在uboot已经成功实现网络互通上,如果是傻瓜型,那在kernel只需配置引脚复用,在kernel下打开对rmii支持,设备树增加phy设备。即可在网络上互通。
由于需要实现软控制,选择dsa框架来实现。
1. dsa介绍
本质上是在链路层和网络层之间抽象出来的一层逻辑交换机。
2. dsa框架组成
DSA Switch:实现DSA框架的交换机设备。
DSA Master:DSA框架的主控节点,负责管理DSA Switch及其之间的通信,一般是网卡驱动。
DSA Slave:连接到DSA Switch的物理端口,负责转发数据包。
DSA Tag:标记数据包的源和目的信息,指示数据包应该从哪个端口发送和转发>到哪个端口。
3. phy驱动与switch驱动
4. 网络设备角度看
1703571336498)
1. 根据dsa_switch_ops结构体,根据实际需要实现相应接口
.get_tag_protocol:支持tagging协议
.probe:因为是虚拟phy,建议直接rutuen “驱动名”,表示支持该设备。
.setup: 当dsa驱动probe到设备,会调用该setup去配置和初始化设备。
.phy_read/.phy_write: switch的读写函数,根据平台不同去修改api底层接口。
例如:stmmac用的是stmmac_mdio_read,mdrv是MHal_EMAC_read_phy;
2. 增加attribute_group接口,方便应用层调试
增加一些接口来获取和设置rtl8363的配置。
例如: 获取rtl8363物理端口的连接状态
rtk_port_phyStatus_get
1.设备树配置主要注意的是mdio和dsa的reg
1.网卡驱动注册phy流程:
网卡驱动先注册mdio总线,注册总线时会将设备类型和mdio_bus_class关联,关联之后,创建phy绑定总线为mdio总线
- MDev_EMAC_init
- MDev_EMAC_mii_init
- of_mdiobus_register
- mdiobus_register
- bus->dev.class = &mdio_bus_class; //网络驱动的midobus归属于MDIO总线类设备,简而言之在mdio_bus_class下可以找到emac的mdiobus
- mdiobus_scan
- get_phy_device //手动返回phyid
- phy_device_create // 创建虚拟phy
- mdiodev = &dev->mdio;
- mdiodev->dev.bus = &mdio_bus_type; //设备总线类型为mdio总线
- phy_device_register
在sys文件系统下bus->dev.class = &mdio_bus_class的效果
在sys文件系统下mdiodev->dev.bus = &mdio_bus_type的效果
2.dsa probe phy流程:
- dsa_probe
- dsa_of_probe
- mdio_bus = of_mdio_find_bus(mdio);
- class_find_device(&mdio_bus_class, NULL, mdio_bus_np,
- of_mdio_bus_match); //寻找mdio类设备 本质上判断dsa的bus是否也归属于mdioclass,所以这里需要设备树设置正确
-
- dsa_setup_dst
- dsa_switch_setup
- dsa_switch_probe
- name = ops->probe(parent, host_dev, sw_addr, priv); //调用rtl8363 probe
- dsa_switch_setup_one
- tag_protocol = ops->get_tag_protocol(ds); //设置tag协议,根据实际情况设置
- dst->tag_ops = dsa_resolve_tag_protocol(tag_protocol);
- dst->rcv = dst->tag_ops->rcv; //协议回调处理函数
- ret = ops->setup(ds); // 调用rtl8363.setup初始化
- dsa_slave_create // 创建switch port
- dsa_cpu_dsa_setup //
- of_phy_find_device //
- bus_find_device(&mdio_bus_type, NULL, phy_np, of_phy_match);//在mdio总线下寻找固定连接phy
- ds->ops->adjust_link(ds, port, phydev); //cpu port和emac 固定phy建立连接
- genphy_update_link //更新链路
在sys文件系统下class_find_device的效果
在sys文件系统下bus_find_device的效果
在sys文件系统下mdio_bus_type下所有驱动
3.大体流程
网络数据流:
- MDev_EMAC_rx
- napi_gro_receive
- __netif_receive_skb
- __netif_receive_skb_core
- skb_vlan_untag
- type = skb->protocol;// 获取网络数据协议
- deliver_ptype_list_skb
- deliver_skb
- pt_prev->func(skb, skb->dev, pt_prev, orig_dev);//获取协议处理器的处理函数
- // 如果switch驱动.get_tag_protocol不为0,那么网络数据会dsa的协议处理器.func = dsa_switch_rcv 处理。
- //dsa处理完后又会调napi_gro_receive继续剥离数据heard
- napi_gro_receive
- ,,,,
- ---> 网络层
dsa协议处理器
- dsa_switch_setup_one
- tag_protocol = ops->get_tag_protocol(ds); // 获取驱动协议
- dst->tag_ops = dsa_resolve_tag_protocol(tag_protocol);
- ops = dsa_device_ops[tag_protocol]; /*
- const struct dsa_device_ops *dsa_device_ops[DSA_TAG_LAST] = {
- #ifdef CONFIG_NET_DSA_TAG_DSA
- [DSA_TAG_PROTO_DSA] = &dsa_netdev_ops,
- #endif
- #ifdef CONFIG_NET_DSA_TAG_EDSA
- [DSA_TAG_PROTO_EDSA] = &edsa_netdev_ops,
- #endif
- #ifdef CONFIG_NET_DSA_TAG_TRAILER
- [DSA_TAG_PROTO_TRAILER] = &trailer_netdev_ops,
- #endif
- #ifdef CONFIG_NET_DSA_TAG_BRCM
- [DSA_TAG_PROTO_BRCM] = &brcm_netdev_ops,
- #endif
- #ifdef CONFIG_NET_DSA_TAG_QCA
- [DSA_TAG_PROTO_QCA] = &qca_netdev_ops,
- #endif
- [DSA_TAG_PROTO_NONE] = &none_ops,
- };*/
- dst->rcv = dst->tag_ops->rcv;// 获取协议处理函数
DSA数据流和控制流图
略
略
相关资料链接:
【网络BSP开发经验】交换芯片驱动开发1(RTL8306MB交换芯片驱动开发)
https://blog.csdn.net/yy197696/article/details/129571370
//kernel dsa文档
https://www.kernel.org/doc/html/v5.15/networking/dsa/dsa.html
Linux 5.4内核Distributed Switch Architecture » Architecture翻译
https://blog.csdn.net/u010687717/article/details/124857859
网口扫盲二:Mac与Phy组成原理的简单分析
https://www.cnblogs.com/jason-lu/p/3196096.html
linux phy fixed-link
https://blog.csdn.net/u014044624/article/details/130670398?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0-130670398-blog-124857859.235v38pc_relevant_default_base3&spm=1001.2101.3001.4242.1&utm_relevant_index=3
一文搞懂 Linux 网络 Phy 驱动
https://cloud.tencent.com/developer/article/2355036?from=15425
ARM与交换芯片mac_to_mac固定模式总结
https://blog.csdn.net/newbee_sccc/article/details/126266772
设备树 phy节点 使用说明
https://blog.csdn.net/weixin_45647912/article/details/108975862
phy 驱动与 switch 驱动
https://blog.csdn.net/agave7/article/details/106519019
Linux DSA Net Switch驱动开发
https://blog.csdn.net/Zhu_Zhu_2009/article/details/108654578
Linux 内核:设备驱动模型(3)class与device
https://www.cnblogs.com/schips/p/linux_device_model_3.html
以太网驱动的流程浅析(五)-mii_bus初始化以及phy id的获取
https://www.cnblogs.com/sky-heaven/p/11942921.html
STMMAC驱动
https://blog.csdn.net/qq_41076734/article/details/129163748
第十六章PHY -基于Linux3.10
https://blog.csdn.net/shichaog/article/details/44682931
linux驱动_sigmastar_SSD202D网络驱动简析
https://blog.csdn.net/gavinpeng/article/details/127104218
linux内核网络协议栈–netif_receive_skb()函数(八)
https://blog.csdn.net/qq_20817327/article/details/106752029
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。