NUC972 + rtl8306sd vlan 调试记录。

RTL8306SD 芯片支持VLAN功能,这颗芯片比较老了,据说已经停产,最新的RTL8306E,但坑的是,realtek的技术支持,没用过这个芯片,无法提供技术支持和资料,网上资料太少,最终是在某论坛里找到了一些api驱动资料和说明,datasheet 规格书看了一遍又一遍,慢慢清晰起来。由于先前对这个芯片不了解,直接参考了原理图,导致设计有些错误。调试过程也走了不少弯路,在此记录。

涉及的代码部分已经上传在我的资源里,需要的同学可以自行下载。

先来看一下框图:

该芯片有5路 phy接口,其中第5口 phy 具有复用功能。 另外有两路 mii/rmii 接口,可以通过不同的配置工作在不同模式下。 这里的配置有点复杂。经过这几天调试,基本摸清楚了。

接下来说一下可以配置为哪些模式。

1.先说一下 phy4(第五个phy), phy4可以与 mac4 一起工作在 UTP模式,什么是UTP模式??就是正常的工作模式 和上面几路phy 一致。除此外 phy4还可以配置为独立的phy,通过mii/rmii 接外部 mac 如图。此时 phy4 与其他phy是独立的,不互通。

2. 再来说一下 MAC4 和 MAC5. 他们都可以配置为:

              1. PHY MODE MII

              2. MAC MODE MII

              3. RMII 模式

  上面两种模式我还不太确定具体接什么,但可以确定的是,一种模式是接外置phy的,另一种接 cpu的。我需要用的是RMII模式。

我的需求是 MAC4 PHY4 工作在 UTP模式,MAC5工作在RMII模式。 对应配置表。 是01000,付上配置表。

调试过程如下。

1.硬件部分调试

板子回来后,上电,cpu能正常启动,但是没识别出网卡。

 1. 按以往经验判断,应该是MDIO总线没通讯成功。示波器查了波形,芯片果然没响应。

 2. 先查 晶振,复位,3.3V电源,1.8V电源。挨个查了一遍。都正常。插上网线,灯不闪。

 3. 这样判断 内部逻辑电路可能没启动,通常phy部分,只要插上网线灯就会亮。再次仔细检查电源,发现有个AVDD18接错了,接到了GND上。飞线大法后,插上网线指示灯已经可以闪了,说明内部电路已经开始工作。 奇怪的是这路AVDD接错,芯片没烧,没任何反应,说明这个AVDD18 在芯片内部是独立供电的。 找到第1个坑

4. 重启板子后,发现网卡已经识别出来,说明MDIO已经通讯成功。 测试了4个网口,相互联通的。

5. 但是网络一直不通,没有数据包。把模式配置为 01000后,查了波形。发现RMII没有任何波形。refclock也没有。印象中refclock方向可以配置,翻了datasheet, 81脚需要拉低,82脚才会对外输出refclock。第2个坑

6. 再次飞线,refclock已经有了,示波器量了,标准的50M,说明已经工作在rmii模式了,如果是MII模式,refclock是25M.

7.但数据还是不通,量RMII TX是低电平, RX是高电平。有点疑问。正常情况没有数据通讯的时候应该都是低电平。可能数据线接错了。 这里引入一个新的知识点,也是在这次调试中了解的。 有种接法叫 mac to mac without phy,也叫 fixed-link。顾名思义,是一个固定连接,用于两个有mac控制器的cpu 直连,不通过phy。 这样可以省去2个phy 和 网络变压器等外部器件。由于直连,没有MDIO通讯,所以如果要直连,底层网卡驱动需要调整。MAC直连的时候,需要交叉连接 如下图。

TXD0RXD0
TXD1RXD1
TX_ENRX_DV

我们的板子接错了。由于芯片的rmii可配置的模式太多,同一个引脚可以配置为tx或rx. 导致误导了我们硬件工程师。实际上同一个引脚的rx或tx。是站在不通角度而言的。在phy 模式的tx,就是 mac模式的rx,数据方向都是一致的第3个坑

8. 依然是飞线大法,之后再查,发现已经有波形了8306的tx0,tx1,tx_en都有波形输出,但是还是收不到数据。接收数据包是0

难道是时序不对,请出逻辑分析仪来一探,结果逻辑分析仪太楼,最高只能测100M,而RMII是50M的数据。100M就100M吧勉强能用,按照采样定理,回顾一下:采样定理,又称香农采样定理,奈奎斯特采样定理,只要采样频率大于或等于有效信号最高频率的两倍,采样值就可以包含原始信号的所有信息,被采样的信号就可以不失真地还原成原始信号。

在100M采样的时候只支持3个通道,好吧,3个就3个,大不了分组采,因为数据包相同的,我网线接了一个只ping 一个固定地址板子。1组 refclock,txd0, tx_en. 2组 refclock txd1 tx_en.

看波形应该没问题,怀疑tx和rx时序格式可能不对。但是MAC能与MAC直连,肯定说明格式是一致的。

换了一个方法调试的这块板子,ping 外面,ping肯定是不通的,但能知道对方是否收到数据。简单的来说,就看对方数据包是否增加了,高级点就用抓包工具,我用了tcpdump,发现能收到板子发出的数据包。  更加确信了 tx与rx的格式是一致的。 tx_en就是对方rx_dv。那为什么 MAC过来的数据收不到呢? 又查了一遍RMII接口,发现漏了一个rx_err 信号,非常重要的引脚,RX还有一个 RX_ERR 信号。这个怎么接?RX_ERR 这个信号是可选的,但调试被它卡了2天的时间。 这个信号的作用是 phy芯片通知cpu 检测到载波错误,高电平有效。这时cpu就会丢弃掉接收的数据。 第4个坑

9.飞线 直接拉rx_err 引脚到gnd,再次测试,已经能ping通了。测试了与其他网口都能互通,到此芯片调的差不多了。

到目前为止 rtl8306的几路网口都已经联通了,但还没有工作在vlan模式。根据芯片资料描述,要工作在vlan模式,需要把93脚拉低。

但是这个引脚拉低后,网络就不通了。根据判断,硬件连接这时肯定没问题了,应该是需要软件控制。

 

2.软件部分调试

这个芯片支持vlan功能,vlan功能是通过寄存器控制的,规格书上写的清清楚楚。但是坑的是datasheet上,故意隐去了关于vlan部分的寄存器描述,只保留了基本的phy寄存器描述。 还好在某论坛找到了api驱动资料。这样其实不必关心内部寄存器了,只要会用api接口,就可以控制vlan功能。vlan功能只是这个芯片多种功能中的其中一种,我们这里只要用到vlan就行了。

寄存器通过MDIO总线控制,我的系统运行环境是linux。官方驱动更像是运行在单片机上的驱动类型。所以我决定把驱动做成一个应用层的工具,通过网卡驱动的ioctl接口读写mdio。通过这个工具来控制vlan配置。

主要代码如下: 可以通过这个工具调用2个设置vlan的主要函数

void vlan_config()
{
	rtk_vlan_init();
}

void printhelp()
{
	printf("vlanmgr V0.1 \n\n");
	printf("Usage: vlanmgr [-i|-v|-p|-s] ... \n");
	printf("    -i      Init the vlan chip\n");
	printf("    -v      Set vlan\n");
	printf("            Format: vlanmgr -v vid mbmsk(hex) untagmsk(hex) \n");
	printf("                eg: vlanmgr -v 1 3f 00  \n");
	printf("    -p      Set portPvid\n");
	printf("            Format: vlanmgr -p port pvid prio \n");
	printf("    -s      show the vlan setting\n");
}

void enablePortlink()
{
	rtk_port_mac_ability_t pPortability;
	pPortability.forcemode = 1;
	pPortability.nway = 0;
	pPortability.speed = PORT_SPEED_100M;
	pPortability.link = 1;
	pPortability.duplex = PORT_HALF_DUPLEX;
	pPortability.rxpause = 0;
	pPortability.txpause = 0;

	rtk_port_macForceLinkExt0_set(MODE_EXT_RMII,&pPortability);
}

int main(int argc,char *argv[])
{
	
	if(mdio_open("eth0") == 0)
	{
		printf(" mdio_open fail \n");
		return 0;
	}

	if(argc > 1)
	{
		if(strcmp(argv[1],"help")==0 || strcmp(argv[1],"-h")==0)
		{
			printhelp();
		}
		else if(strcmp(argv[1],"-i")==0)
		{
			printf(" vlan chip init\n");
			rtk_switch_init();
			vlan_config();
			
			enablePortlink();
		}
		else if(strcmp(argv[1],"-s")==0)
		{			
			rtk_portmask_t mbrmsk, untagmsk;
			rtk_fid_t fid;
			rtk_vlan_t pvid;
			rtk_pri_t prio;
			int i;
			for(i=1;i<6;i++)
			{
				rtk_vlan_get(i,&mbrmsk,&untagmsk,&fid);
				printf(" vlan %d mbrmsk[%02X] untagmsk[%02X]\n",i,mbrmsk.bits[0],untagmsk.bits[0]);
			}

			for(i=0;i<6;i++)
			{		
				rtk_vlan_portPvid_get(i,&pvid,&prio);
				printf(" port %d pvid[%d] prio[%d]\n",i,pvid,prio);
			}
		}
		else if(strcmp(argv[1],"-v")==0)
		{
			int vid;
			char cmmsk,cumsk;
			rtk_portmask_t mbrmsk;
			rtk_portmask_t untagmsk;
			rtk_api_ret_t ret;
			if(argc < 5)
			{
				printf(" vlan set param error!\n");
				return 0;
			}
			vid = atoi(argv[2]);
			common_string_to_hex(argv[3],&cmmsk,1);
			common_string_to_hex(argv[4],&cumsk,1);

			mbrmsk.bits[0] = cmmsk;
			untagmsk.bits[0] = cumsk;
			
			ret = rtk_vlan_set(vid,mbrmsk,untagmsk,0);
			if(ret != RT_ERR_OK)
				printf(" vlan set error[%d]! vid[%d] mbrmsk[%02X] untagmsk[%02X]\n",ret,vid,mbrmsk.bits[0],untagmsk.bits[0]);
			else
				printf(" vlan set OK, vid[%d] mbrmsk[%02X] untagmsk[%02X]\n",vid,mbrmsk.bits[0],untagmsk.bits[0]);
		}
		else if(strcmp(argv[1],"-p")==0)
		{
			int port;
			int pvid;
			int prio;
			rtk_api_ret_t ret;
			if(argc < 5)
			{
				printf(" set port Pvid param error!\n");
				return 0;
			}
			port = atoi(argv[2]);
			pvid = atoi(argv[3]);
			prio = atoi(argv[4]);
			ret = rtk_vlan_portPvid_set(port,pvid,prio);
			if(ret != RT_ERR_OK)
				printf(" port Pvid set error[%d]! port[%d] pvid[%02X] prio[%02X]\n",ret,port,pvid,prio);
			else
				printf(" vlan set OK, port[%d] pvid[%02X] prio[%02X]\n",port,pvid,prio);
		}

	}
	else
	{
		printhelp();
	}
	

	return 1;
	
}

 

这个芯片有6个phy,地址分别是 0,1,2,3,4,5,6。 默认网卡驱动初始化的时候,扫描mdio总线,把所有找到的phy都加入phymap中,但是只会取第一个phy作为网卡的phy。这样的话,不是我们要的效果,网线的状态是跟随第一个网口的。所以驱动要调整一下。

再内核中找到 网卡驱动 nuc970_ether0.c,  源码稍后补上。只改一处即可,把第一个phy改 phy_map[6]。

 

static int nuc970_mii_setup(struct net_device *dev)
{
    ...

    for (i = 0; i < PHY_MAX_ADDR; i++)
		ether->mii_bus->irq[i] = PHY_POLL;
	//ether->mii_bus->irq[1] = ??   write me after the irq number is known

	if (mdiobus_register(ether->mii_bus)) {
		dev_err(&pdev->dev, "mdiobus_register() failed\n");
		goto out2;
	}
    
   #if 0

    phydev = phy_find_first(ether->mii_bus);
   #else
	phydev = ether->mii_bus->phy_map[6]; //强制设置为第六个phy
   #endif
	if(phydev == NULL) {
		err = -ENODEV;
		dev_err(&pdev->dev, "phy_find_first() failed\n");
		goto out3;
	}
	printk("###################################\n");
	printk("########   phy_find_first id = %d\n",phydev->addr);
	dev_info(&pdev->dev, "########   phy_find_first id = %d\n",phydev->addr);
	//phydev = &phydev[5];
	//dev_info(&pdev->dev, "########   chg phydev to id = %d\n",phydev->addr);
	
	//printk("########  chg phydev to id = %d\n",phydev->addr);
	printk("###################################\n");
	
    ...
}

 

最后是工具的用法:

  1. 查看帮助 vlanmgr -h

 

参数说明:

-i 初始化RTL8306SD芯片,初始化之后网络才通。初始化之后所有网口在一个vlan分组,所有网口互通。

-v 设置vlan 分组。 需要3个参数,1vid,2 mbrmask,3.untagmsk。

        vid:表示vlan的编号 从1开始。

       mbrmask:分组掩码: 用于配置vlan分组中有哪些端口。

       例如:port0,port1。在一组。对应的mask 就是 0x03(二进制0000 0011)

                 port3,port5在一组,对应mbr mask是 0x14 (二进制 0001 0100)

       untagmsk:设为00即可。

-p 设置端口的Pvid,作用是确定这个端口属于第几个vlan分组。

    3个参数分别是 端口号(0开始),pvid编号(1开始对应vlan),优先级。

    例如:port0 属于第1个vlan分组: vlanmgr -p 0 1 0

-s 查看当前vlan配置。

初始化之后查看vlan分组如下图, 所有端口在一个分组vlan1中。

 

配置举例:

当前板子port5是连cpu的端口,port4是内置网口,port0-3是对外网口。cpu端口需要同时能连通2个vlan分组。

假设划分:port4,port5互通。 port0-3,port5也互通。port4,port0-3 相互之间不通。

需要划分3个vlan分组:如下

vlan配置

vlan id

成员

mbrmask

1

port 4,port5

0x30(0011 0000)

2

port0-3,port5

0x27(0010 0111)

3

port 0-5

0x3F (0011 1111)

 

配置每个port0,属于哪个vlan分组。

pvid配置

端口号

pvid

说明

0

2

port0-3 处于第2个vlan分组,成员是 port0-3 还有 port5.

1

2

2

2

3

2

4

1

port4,属于第一个vlan分组,成员是port4,port5

5

3

port5,属于第3个vlan分组,成员是全部端口。

 

 

命令如下:

  1. vlanmgr -i //初始化芯片
  2. vlanmgr -v 1 30 00
  3. vlanmgr -v 2 27 00
  4. vlanmgr -v 3 3F 00
  5. vlanmgr -p 0 2 0
  6. vlanmgr -p 1 2 0
  7. vlanmgr -p 2 2 0
  8. vlanmgr -p 3 2 0
  9. vlanmgr -p 4 1 0
  10. vlanmgr -p 5 3 0
  11. vlanmgr -s // 查看分组

 

 

 

 

 

  • 7
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值