本文描述移植NXP官方 linux 5.4 内核到i.MX6ULL开发板。
一、NXP官方linux内核
1. 下载
NXP官方linux仓库地址为:https://github.com/Freescale/linux-fslc/tree/5.4-2.1.x-imx。
选择该分支下载zip包即可,不要整个仓库下载,太大了:
2. 编译
安装库:
?
sudo?apt-get?install?lzop sudo?apt-get?install?libncurses5-dev
?
设置临时环境变量(编译器版本为7.5.0):
?
export?ARCH=arm export?CROSS_COMPILE=arm-linux-gnueabihf-
?
清理构建:
?
make?distclean
?
查看arch/arm/configs目录下imx6ull相关的单板:配置:
?
make?imx_v7_defconfig
?
配置好之后编译:
?
make?-j32
?
编译成功后,进入arch/arm/boot目录可以看到编译出的linux镜像,在dts目录下是编译出的设备树文件,找找evk的设备树:
3. 下载到开发板
将内核镜像和设备树文件拷贝到tftp根目录中:
?
cp?zImage?~/tftp_root/ cp?dts/imx6ull-14x14-evk-emmc.dtb?~/tftp_root/
?
接下来在开发板上进入uboot,确保bootargs环境变量的值如下:
?
setenv?bootargs?'console=ttymxc0,115200?root=/dev/mmcblk1p2?rootwait?rw' saveenv
?
加载这两个文件:
?
tftp?80800000?zImage tftp?83000000?imx6ull-14x14-evk-emmc.dtb
?
启动内核:
?
bootz?80800000?-?83000000
?
4. 启动结果分析
因为EMMC中有出厂烧写的文件系统,所以Linux内核成功挂载了根文件系统,启动成功,但是也有一些问题:
LCD屏幕无显示;
网卡eth0报错,但是可以获取到ip,可以ping通主机;
接下来,我们就基于NXP官方提供的linux,针对正点原子imx6ull开发板进行一些配置参数的修改,修复LCD和网络问题。
二、移植linux内核
1. 新建单板
(1)新建单板配置文件进入 arch/arm/configs 目录,复制一份新的单板文件:
?
cp?arch/arm/configs/imx_v7_defconfig?arch/arm/configs/imx_v7_atk_emmc_defconfig
?
(2)新建设备树文件进入 arch/arm/boot/dts 目录,复制一份新的设备树文件:
?
cp?arch/arm/boot/dts/imx6ull-14x14-evk-emmc.dts?arch/arm/boot/dts/imx6ull-14x14-atk-emmc.dts
?
查看该文件,依赖于evk板子的设备树,需要将该文件也复制一份出来:
?
cp?arch/arm/boot/dts/imx6ull-14x14-evk.dts?arch/arm/boot/dts/imx6ull-14x14-atk.dts
?
再查看有没有依赖,竟然还有一级:
修改依赖:
将该文件也复制一份出来:
?
cp?arch/arm/boot/dts/imx6ul-14x14-evk.dtsi?arch/arm/boot/dts/imx6ul-14x14-atk.dtsi
?
接着修改同级目录下的Makefile,添加新建的文件:
(3)编译测试
?
make?distclean make?imx_v7_atk_emmc_defconfig make
?
使用新的内核和设备树启动,方便起见,设个环境变量,下次直接用命令启动:
?
setenv?boot_tftp?'tftp?80800000?zImage;tftp?83000000?imx6ull-14x14-atk-emmc.dtb;bootz?80800000?-?83000000' saveenv
?
启动:
?
run?boot_tftp
?
内核启动没啥问题。
2. 修改网络驱动
(1)修改LAN8720A的复位引脚驱动
修改设备树文件arch/arm/boot/dts/imx6ul-14x14-atk.dtsi,搜索 GPIO5_IO07、GPIO5_IO08,发现已被spi4使用,删除这两行后,代码如下:
?
pinctrl_spi4:?spi4grp?{ ?????????????????????fsl,pins?=?< ?????????????????????????????MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10????????0x70a1 ?????????????????????????????MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11????????0x70a1 ?????????????????????>; ?????????????};
?
接着再找到spi4,删除与这两个GPIO相关的代码,删除后如下:
?
?spi4?{ ??compatible?=?"spi-gpio"; ??pinctrl-names?=?"default"; ??pinctrl-0?=?<&pinctrl_spi4>; ??status?=?"okay"; ??gpio-sck?=?<&gpio5?11?0>; ??gpio-mosi?=?<&gpio5?10?0>; ??num-chipselects?=?<1>; ??#address-cells?=?<1>; ??#size-cells?=?<0>; ??gpio_spi:?gpio_spi@0?{ ???compatible?=?"fairchild,74hc595"; ???gpio-controller; ???#gpio-cells?=?<2>; ???reg?=?<0>; ???registers-number?=?<1>; ???registers-default?=?/bits/?8?<0x57>; ???spi-max-frequency?=?<100000>; ??}; ?};
?
接着将复位引脚加入到 pinctrl_enet1 节点的描述中:
?
MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07?0x10b0

?
接着将复位引脚加入到 pinctrl_enet2 的代码中:
?
MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08?0x10b0
?
接着搜索fec1和fec2节点,添加网络驱动复位引脚使用,添加的代码如下:
?
phy-reset-gpios?=?<&gpio5?7?GPIO_ACTIVE_LOW>; phy-reset-duration?=?<200>;

phy-reset-gpios?=?<&gpio5?8?GPIO_ACTIVE_LOW>; phy-reset-duration?=?<200>;
?
(2)修改LAN8720的PHY地址
修改mdio节点中的地址:
至此,设备树修改完成。
(3)修改fec_main.c文件
修改drivers/net/ethernet/freescale/fec_main.c文件,找到函数fec_probe,在函数开头添加如下代码:
?
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); fec_enet_get_queue_num(pdev,?&num_tx_qs,?&num_rx_qs);
?
(4)修改PHY驱动源码
修改drivers/net/phy/smsc.c文件,添加两个头文件:
?
#include?#include?
?
然后找到smsc_phy_reset函数,修改之后如下:
?
tatic?int?smsc_phy_reset(struct?phy_device?*phydev) { ?int?err,?phy_reset; ?int?msec?=?1; ?struct?device_node?*np; ?int?timeout?=?50000; ?int?rc; ?if?(phydev->mdio.addr?==?0)?{ ??np?=?of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000"); ?}?else?if?(phydev->mdio.addr?==?1)?{ ??np?=?of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000"); ?} ?if?(!np)?{ ??return?-1; ?} ?/*?A?sane?reset?duration?should?not?be?longer?than?1s?*/ ?err?=?of_property_read_u32(np,?"phy-reset-duration",?&msec); ?if?(!err?&&?msec?>?1000) ??msec?=?1; ?phy_reset?=?of_get_named_gpio(np,?"phy-reset-gpios",?0); ?if?(!gpio_is_valid(phy_reset)) ??return?-1; ?gpio_direction_output(phy_reset,?0); ?gpio_set_value(phy_reset,?0); ?msleep(msec); ?gpio_set_value(phy_reset,?1); ?rc?=?phy_read(phydev,?MII_LAN83C185_SPECIAL_MODES); ?if?(rc?0) ??return?rc; ?/*?If?the?SMSC?PHY?is?in?power?down?mode,?then?set?it ??*?in?all?capable?mode?before?using?it. ??*/ ?if?((rc?&?MII_LAN83C185_MODE_MASK)?==?MII_LAN83C185_MODE_POWERDOWN)?{ ??/*?set?"all?capable"?mode?*/ ??rc?|=?MII_LAN83C185_MODE_ALL; ??phy_write(phydev,?MII_LAN83C185_SPECIAL_MODES,?rc); ?} ?phy_write(phydev,?MII_BMCR,?BMCR_RESET); ?/*?wait?end?of?reset?(max?500?ms)?*/ ?do?{ ??udelay(10); ??if?(timeout--?==?0) ???return?-1; ??rc?=?phy_read(phydev,?MII_BMCR); ?}?while?(rc?&?BMCR_RESET); ?/*?reset?the?phy?*/ ?return?genphy_soft_reset(phydev); }
?
此时编译内核可以通过。
(5)配置Linux内核,使能LAN8720驱动
?
make?menuconfig
?
使能Device DriversNetwork device support PHY Device support and infrastructureDrivers for SMSC PHYs:
保存到.config,然后退出。
(6)编译测试
重新编译内核,使用新的内核和设备树启动,测试网络是否正常。
ping主机测试:
至此,网络驱动修改成功。
3. 修改LCD驱动
本文用的是正点原子 7' RGB屏幕,分辨率1024*600,设备树中找到lcdif节点的补充描述,改一下屏幕参数和时序即可:
重新编译设备树,启动,可以看到LCD左上角显示企鹅logo:
在uboot的bootargs参数中加入console=tty1,即可新注册一个终端到LCD:
本文移植的内核仓库地址(点击阅读原文即可访问):
https://git.code.tencent.com/mculover666/linux-imx6ull。
审核编辑:汤梓红
评论