基于IMX6Q的u-boot-2017.11的移植(3)->Ethernet MAC (ENET)移植
观察上次移植的uboot的串口输出:
U-Boot 2017.11 (Jan 07 2018 - 11:50:48 +0800)
CPU: Freescale i.MX6Q rev1.5 at 792 MHz
Reset cause: POR
Board: MX6Q-Armadillo2
DRAM: 2 GiB
MMC: FSL_SDHC: 0, FSL_SDHC: 1
In: serial
Out: serial
Err: serial
Net: FEC
Error: FEC address not set.
Hit any key to stop autoboot: 0
=>
有一个错误提示:Error: FEC address not set.
这个错误是情理之中的因为我们的网络驱动还没有移植。
下面进行相关修改移植:
根据错误提示搜索:grep "address not set" ./* -rn
./net/eth_legacy.c:163: printf("\nError: %s address not set.\n",
找到在我们编译进uboot中的这个文件有这个输出,然后我们打开这个文件:vim ./net/eth_legacy.c +163
发现是在下面这个函数里面输出的这个错误信息。
int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
int eth_number)
{
unsigned char env_enetaddr[ARP_HLEN];
int ret = 0;
eth_env_get_enetaddr_by_index(base_name, eth_number, env_enetaddr);
if (!is_zero_ethaddr(env_enetaddr)) {
if (!is_zero_ethaddr(dev->enetaddr) &&
memcmp(dev->enetaddr, env_enetaddr, ARP_HLEN)) {
printf("\nWarning: %s MAC addresses don't match:\n",
dev->name);
printf("Address in SROM is %pM\n",
dev->enetaddr);
printf("Address in environment is %pM\n",
env_enetaddr);
}
memcpy(dev->enetaddr, env_enetaddr, ARP_HLEN);
} else if (is_valid_ethaddr(dev->enetaddr)) {
eth_env_set_enetaddr_by_index(base_name, eth_number,
dev->enetaddr);
} else if (is_zero_ethaddr(dev->enetaddr)) {
#ifdef CONFIG_NET_RANDOM_ETHADDR
net_random_ethaddr(dev->enetaddr);
printf("\nWarning: %s (eth%d) using random MAC address - %pM\n",
dev->name, eth_number, dev->enetaddr);
#else
printf("\nError: %s address not set.\n",
dev->name);
return -EINVAL;
#endif
}
if (dev->write_hwaddr && !eth_mac_skip(eth_number)) {
if (!is_valid_ethaddr(dev->enetaddr)) {
printf("\nError: %s address %pM illegal value\n",
dev->name, dev->enetaddr);
return -EINVAL;
}
ret = dev->write_hwaddr(dev);
if (ret)
printf("\nWarning: %s failed to set MAC address\n",
dev->name);
}
return ret;
}
在输出错误提示信息的函数里面有个宏CONFIG_NET_RANDOM_ETHADDR,这个宏如果被定义就执行net_random_ethaddr(dev->enetaddr);
net_random_ethaddr这个函数会生成一个随机的地址保存在dev->enetaddr中。所以就在配置的头文件中找一个合适位置
添加这个宏。
vim vim include/configs/mx6qarm2.h
#define CONFIG_NET_RANDOM_ETHADDR /*add by xcl*/
编译:make
提示出错:
net/built-in.o: In function `net_random_ethaddr':
/home/xcl/imx6q/uboot/u-boot-2017.11/include/net.h:818: undefined reference to `rand_r'
发现提示rand_r这个函数没有实现。
查找改函数:grep "rand_r" -rn
发现:lib/rand.c:15:unsigned int rand_r(unsigned int *seedp)
查看:ls lib/rand.*
发现只有lib/rand.c,rand.c没有被编译,
查看Makefile:vim lib/Makefile
发现:obj-$(CONFIG_LIB_RAND) += rand.o
说明需要定义CONFIG_LIB_RAND这个宏rand.c才能被编译,所以就在配置的头文件中找一个合适位置
添加这个宏。
vim vim include/configs/mx6qarm2.h
#define CONFIG_LIB_RAND /*add by xcl*/
编译下载重启串口输出:
U-Boot 2017.11 (Jan 08 2018 - 21:22:25 +0800)
CPU: Freescale i.MX6Q rev1.5 at 792 MHz
Reset cause: POR
Board: MX6Q-Armadillo2
DRAM: 2 GiB
MMC: FSL_SDHC: 0, FSL_SDHC: 1
In: serial
Out: serial
Err: serial
Net: FEC
Warning: FEC (eth0) using random MAC address - 5a:b7:8b:df:73:11
Hit any key to stop autoboot: 0
这个时候发现生成了随机的mac地址,为了试一试网卡驱动能用不,输入命令:
=> setenv ipaddr 192.168.0.200
=> setenv serverip 192.168.0.106
=> saveenv
Saving Environment to MMC...
Writing to MMC(0)... done
=> ping 192.168.0.106
Using FEC device
host 192.168.0.106 is alive
=> ping 192.168.0.107
Using FEC device
ARP Retry count exceeded; starting again
ping failed; host 192.168.0.107 is not alive
=> tftp 12000000 a.bin
Using FEC device
TFTP from server 192.168.0.106; our IP address is 192.168.0.200
Filename 'a.bin'.
Load address: 0x12000000
Loading: ######################
455.1 KiB/s
done
Bytes transferred = 319135 (4de9f hex)
=>
哇卡!!!!!!貌似能用
虽然这儿感觉能ping通,能够下载,但是还是去检查和修改一下初始化网卡的流程。
vim common/board_f.c
static const init_fnc_t init_sequence_f[]数组里面的board_early_init_f函数。
该函数位置:board/freescale/mx6qarm2/mx6qarm2.c
源代码为:
int board_early_init_f(void)
{
setup_iomux_uart();
setup_iomux_enet();
return 0;
}
setup_iomux_enet函数代码:
static void setup_iomux_enet(void)
{
imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads));
}
追踪enet_pads到:
iomux_v3_cfg_t const enet_pads[] = {
MX6_PAD_KEY_COL1__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_KEY_COL2__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
};
发现我们参考的这个板和我们的板引脚链接方式一大部分都是相同的,虽然
上面测试貌似能用但是还是参照原理图(下图)去把有差异的引脚修改一下。
修改后:
/* modefied by xcl */
iomux_v3_cfg_t const enet_pads[] = {
MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_RXD1__GPIO1_IO26 | MUX_PAD_CTRL(NO_PAD_CTRL),
MX6_PAD_ENET_CRS_DV__GPIO1_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL),
MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
};
配置了复用引脚,然后将ar8035收发器复位方便后期的使用,所以添加函数:
/* add by xcl */
static void reset_ar8035(void)
{
volatile unsigned int i = 0x88888;
unsigned int reg = *((unsigned int*)(GPIO1_BASE_ADDR + 0x04));
reg |= ~0x2000000;
*((unsigned int*)(GPIO1_BASE_ADDR + 0x04)) = reg;
reg = *((unsigned int*)(GPIO1_BASE_ADDR + 0x00));
reg &= ~0x2000000;
*((unsigned int*)(GPIO1_BASE_ADDR + 0x00)) = reg;
while(i--)
;
reg = *((unsigned int*)(GPIO1_BASE_ADDR + 0x00));
reg |= ~0x2000000;
*((unsigned int*)(GPIO1_BASE_ADDR + 0x00)) = reg;
}
在board_early_init_f函数中调用。
/* modefied by xcl */
int board_early_init_f(void)
{
setup_iomux_uart();
setup_iomux_enet();
reset_ar8035();
return 0;
}
最后编译下载重启测试......
测试通过就算移植完成。
---------------------
作者:honorxcl
来源:CSDN
原文:https://blog.csdn.net/qq_15015097/article/details/79007735
版权声明:本文为博主原创文章,转载请附上博文链接!