此次购买了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
问题暂时解决,如有更好的方法,请不吝赐教!