此次购买了10块RK3566的核心板,收到后发现以太网的MAC地址全是一样的,然后尝试使用工具自行设置MAC地址。
使用RKDevInfoWriteTool工具(使用方法参照:RKDevInfoWriteTool使用指南 - V1.2.5.pdf)给主板设置LAN MAC地址,但是主板启动后读取的MAC地址不是设置的MAC地址:
让主板进入Loader模式,启动RKDevInfoWriteTool工具,勾选LAN后面的复选框,勾选单次读取,点击读取,读取出的MAC地址是12个字节,猜想可能系统默认有两个gmac(RK3568有2个GMAC,RK3566只有1个GMAC,GMAC1。),前面6字节是gmac0的地址,后面6字节是gmac1的地址,所以加起来12字节。通过ifconfig指令获取eth0的mac地址为026E784A75A6,为后面6字节。
点击左上角的设置,进入设置页面:
将8CAE49610002作为MAC地址写入设备,如果选择“自增”的形式这里不能写入12字节,会提示MAC地址不符合规范。
写入之后再读取,LAN:的内容变为8CAE49610003,重启设备再次进入LOADER模式之后再读取,LAN:的内容变为了8CAE49610002A66AE16D2872。
重启正常进入系统之后通过ifconfig指令获取eth0 的mac地址为A66AE16D2872,如下所示:
系统启动时会在uboot过程中获取存储在vendor storage中的ETH MAC地址传给内核。
uboot启动过程中执行..\x3566_linux_v1.2.0\u-boot\arch\arm\mach-rockchip\board.c中board_late_init()函数进行平台late初始化,函数实现如下:
int board_late_init(void)
{
rockchip_set_ethaddr();
rockchip_set_serialno();
setup_download_mode();
#if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0)
setup_boot_mode();
#endif
#ifdef CONFIG_ROCKCHIP_USB_BOOT
boot_from_udisk();
#endif
#ifdef CONFIG_DM_CHARGE_DISPLAY
charge_display();
#endif
#ifdef CONFIG_DRM_ROCKCHIP
rockchip_show_logo();
#endif
#ifdef CONFIG_ROCKCHIP_EINK_DISPLAY
rockchip_eink_show_uboot_logo();
#endif
env_fixup();
soc_clk_dump();
cmdline_handle();
#ifdef CONFIG_AMP
amp_cpus_on();
#endif
return rk_board_late_init();
}
board_late_init()函数调用rockchip_set_ethaddr()进行eth mac地址的设置,函数实现如下:
#define MAX_ETHERNET 0x2
static int rockchip_set_ethaddr(void)
{
#ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
char buf[ARP_HLEN_ASCII + 1], mac[16];
u8 ethaddr[ARP_HLEN * MAX_ETHERNET] = {0};
int ret, i;
bool need_write = false, randomed = false;
ret = vendor_storage_read(LAN_MAC_ID, ethaddr, sizeof(ethaddr));
for (i = 0; i < MAX_ETHERNET; i++) {
if (ret <= 0 || !is_valid_ethaddr(ðaddr[i * ARP_HLEN])) {
if (!randomed) {
net_random_ethaddr(ðaddr[i * ARP_HLEN]);
randomed = true;
} else {
if (i > 0) {
memcpy(ðaddr[i * ARP_HLEN],
ðaddr[(i - 1) * ARP_HLEN],
ARP_HLEN);
ethaddr[i * ARP_HLEN] |= 0x02;
ethaddr[i * ARP_HLEN] += (i << 2);
}
}
need_write = true;
}
if (is_valid_ethaddr(ðaddr[i * ARP_HLEN])) {
sprintf(buf, "%pM", ðaddr[i * ARP_HLEN]);
if (i == 0)
memcpy(mac, "ethaddr", sizeof("ethaddr"));
else
sprintf(mac, "eth%daddr", i);
env_set(mac, buf);
}
}
if (need_write) {
ret = vendor_storage_write(LAN_MAC_ID,
ethaddr, sizeof(ethaddr));
if (ret < 0)
printf("%s: vendor_storage_write failed %d\n",
__func__, ret);
}
#endif
return 0;
}
RK3566虽然只有一个gmac,但是是gmac1,只写入6字节的MAC地址会被默认为gmac0,所以需要写入12字节的MAC,然后系统取后6字节作为gmac1的MAC地址,系统启动后通过ifconfig才能获取到正确的MAC地址。但是通过LAN无法写入12字节,会提示"获取LAN MAC失败!!!",如下所示:
目前想到的解决方案是给Vendor storage区新增一个ID用来存储两个以太网的MAC地址,编号为18,因为从vendor.h文件中看到0~17已有定义:
#define RSV_ID 0
#define SN_ID 1
#define WIFI_MAC_ID 2
#define LAN_MAC_ID 3
#define BT_MAC_ID 4
#define HDCP_14_HDMI_ID 5
#define HDCP_14_DP_ID 6
#define HDCP_2X_ID 7
#define DRM_KEY_ID 8
#define PLAYREADY_CERT_ID 9
#define ATTENTION_KEY_ID 10
#define PLAYREADY_ROOT_KEY_0_ID 11
#define PLAYREADY_ROOT_KEY_1_ID 12
#define SENSOR_CALIBRATION_ID 13
#define IMEI_ID 15
#define LAN_RGMII_DL_ID 16
#define EINK_VCOM_ID 17
再修改下static int rockchip_set_ethaddr(void)函数,如下所示:
static int rockchip_set_ethaddr(void)
{
#ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
char buf[ARP_HLEN_ASCII + 1], mac[16];
u8 ethaddr[ARP_HLEN * MAX_ETHERNET] = {0};
int ret, i;
bool need_write = false, randomed = false;
// ret = vendor_storage_read(LAN_MAC_ID, ethaddr, sizeof(ethaddr));
ret = vendor_storage_read(18, ethaddr, sizeof(ethaddr));
for (i = 0; i < MAX_ETHERNET; i++) {
if (ret <= 0 || !is_valid_ethaddr(ðaddr[i * ARP_HLEN])) {
if (!randomed) {
net_random_ethaddr(ðaddr[i * ARP_HLEN]);
randomed = true;
} else {
if (i > 0) {
memcpy(ðaddr[i * ARP_HLEN],
ðaddr[(i - 1) * ARP_HLEN],
ARP_HLEN);
ethaddr[i * ARP_HLEN] |= 0x02;
ethaddr[i * ARP_HLEN] += (i << 2);
}
}
need_write = true;
}
if (is_valid_ethaddr(ðaddr[i * ARP_HLEN])) {
sprintf(buf, "%pM", ðaddr[i * ARP_HLEN]);
if (i == 0)
memcpy(mac, "ethaddr", sizeof("ethaddr"));
else
sprintf(mac, "eth%daddr", i);
env_set(mac, buf);
}
}
if (need_write) {
// ret = vendor_storage_write(LAN_MAC_ID,
// ethaddr, sizeof(ethaddr));
ret = vendor_storage_write(18,
ethaddr, sizeof(ethaddr));
if (ret < 0)
printf("%s: vendor_storage_write failed %d\n",
__func__, ret);
}
#endif
return 0;
}
修改完成之后,重新编译uboot,然后烧写到主板。
重启主板进入loader模式,使用RKDevInfoWriteTool工具向vendor storage ID为18的区域写入两个MAC地址,操作如下所示:
手动输入,ID为18,二进制,然后点保存回到主界面:
填写内容后再写入,前6字节可以填写任意内容,后6字节内容为MAC地址。
写入之后重启主板,正常启动之后,通过ifconfig命令查询到eth0的mac地址为:8C:AE:49:61:00:03
eth0 Link encap:Ethernet HWaddr 8C:AE:49:61:00:03
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interrupt:35
问题暂时解决,如有更好的方法,请不吝赐教!
之前使用的工具为RKDevInfoWriteTool_1.2.6,没有多MAC的选项,换为RKDevInfoWriteTool_Setup_V1.1.4工具后,LAN MAC设置界面可选择多LAN MAC,如下所示:
虽然RK3566只有一个gmac,但是使用的gmac1,所以需要将MAC地址写入MAC1。
介绍手动写入的方法:
单击读取可以获取两个MAC地址,第二个地址为gmac1的地址,也就是RK3566实际的eth0地址,将第二个地址改为需要写入的地址后单击写入。