1 环境
- 正点原子imx6ull开发板
- 内核4.14.13
2 移植目标
开发板能够正常启动,并且网络功能正常,能使用nfs、tftp等方式,便于调试。
3 移植过程
3.1 创建自己的板级配置文件-defconfig文件
复制一份imx_v6_v7_defconfig,这里我命名为dfos_mini_defconfig。
3.2 创建配套的dts文件
复制一份imx6ull-14x14-evk.dts,重命名为dfos.dts。同时还要修改Makefile,让内核编译出dfos.dtb。
3.3 修改内核顶层Makefile
3.4 编译
执行编译出.config,然后再执行make编译出镜像。uboot通过tftp的方式下载镜像并且启动内核。这里插入我开发板里uboot的环境变量,关于网络功能相关配置:make dfos_mini_defconfig
setenv gatewayip "192.168.1.1"
setenv ipaddr "192.168.1.110"
setenv netmask "255.255.255.0"
setenv serverip "192.168.1.104"
setenv bootcmd "tftp 80800000 zImage; tftp 83000000 dfos.dtb; bootz 80800000 - 83000000"
setenv bootargs "console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.104:/home/zrc/nfs/rootfs,proto=tcp rw ip=192.168.1.100:192.168.1.104:192.168.1.1:255.255.255.0::eth0:off"
setenv ethaddr "00:04:9f:04:d2:35"
3.5 启动
如下图,内核启动到挂载nfs文件系统前提示打开eth0失败,随后挂载nfs失败。因此需要对网络驱动进行适配,参考正点原子提供的教程移植到4.14.13。
3.6 网络驱动修改
3.6.1 修改imx6ul-14x14-evk.dts
注意,这个修改的是,不是,也不要看成,我们创建的dfos.dts会调imx6ul-14x14-evk.dts。imx6ul-14x14-evk.dts
dfos.dts
imx6ull-14x14-evk.dts
dfos.dts
|-- imx6ul-14x14-evk.dts
|-- imx6ul.dtsi
3.6.1.1 修改fec1和fec2节点
3.6.1.2 修改iomuxc节点
3.6.1.3 修改MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1和2
原值是0x4001b031,修改成0x4001b009.
3.6.2 在arch/arm/boot/dts/imx6ul-pinfunc.h增加2个宏定义
这两个宏就是在3.6.1.2 修改iomuxc节点里用到了。
#define MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x0024 0x0068 0x0000 0x5 0x0
#define MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x0028 0x006C 0x0000 0x5 0x0
3.6.3 修改drivers/net/ethernet/freescale/fec_main.c
增加set_enet_tx_clk函数,并在fec_probe函数最开始调用它,设置寄存器的 SION 位为 1。
static void set_enet_tx_clk(void){
/*
* 设置 MX6UL_PAD_ENET1_TX_CLK 和 MX6UL_PAD_ENET2_TX_CLK
* 这两个 IO 的复用寄存器的 SION 位为 1。 */
void __iomem *IMX6U_ENET1_TX_CLK;
void __iomem *IMX6U_ENET2_TX_CLK;
IMX6U_ENET1_TX_CLK = ioremap(0X020E00DC, 4);
writel(0X14, IMX6U_ENET1_TX_CLK);
IMX6U_ENET2_TX_CLK = ioremap(0X020E00FC, 4);
writel(0X14, IMX6U_ENET2_TX_CLK);
}
static int
fec_probe(struct platform_device *pdev){
···省略···
set_enet_tx_clk();
}
3.6.4 修改drivers/net/phy/smsc.c
增加2个头文件,df_phy_reset函数,并在smsc_phy_reset调用df_phy_reset复位phy。
#include
#include
static void df_phy_reset(struct phy_device *phydev){
int err;
struct device_node *np;
int msec = 1;
int phy_reset;
if(phydev->mdio.addr == 0) { /* FEC1 */
np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000");
if(np == NULL) {
pr_err("%s %d: get np fail\n", __func__, __LINE__);
return;
}
}
if(phydev->mdio.addr == 1) { /* FEC2 */
np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000");
if(np == NULL) {
pr_err("%s %d: get np fail\n", __func__, __LINE__);
return;
}
}
err = of_property_read_u32(np, "phy-reset-duration", &msec);
/* A sane reset duration should not be longer than 1s */
if (!err && msec > 1000)
msec = 1;
phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
if (!gpio_is_valid(phy_reset))
return;
gpio_direction_output(phy_reset, 0);
gpio_set_value(phy_reset, 0);
msleep(msec);
gpio_set_value(phy_reset, 1);
}
static int smsc_phy_reset(struct phy_device *phydev){
···省略···
df_phy_reset(phydev);
···省略···
}
至此,网络驱动修改完成,重新编译并启动。
测试
启动可以看到相关网络信息的打印,并且已经进入到根文件系统nfsroot,至此,kernel4.14.13算是成功移植到imx6ull上了,最重要的网络功能已经能正常使用。
本文使用 文章同步助手 同步