IMX6ULL Linux内核移植

本次移植实验使用的是正点原子开发板ALPHA V2.2
交叉编译工具:gcc-linaro-5.5.0-2017.10-x86_64_arm-linux-gnueabihf
使用的是NXP官方开发板的Linux内核源码移植
在这里插入图片描述
然后解压把目录改为自己工程的名字,我这里改成
linux-imx-rel_imx_4.1.15_2.1.0_ga_myimx
首先就是配置文件,我们复制一份配置文件,更改为我们自己的名字

cd arch/arm/configs/
cp imx_v7_mfg_defconfig imx_myimx_emmc_defconfig

接下来就是设备树文件复制,在目录 arch/arm/boot/dts中,复制一份imx6ull-14x14-evk.dts,然后将其重命名为 imx6ull-myimx-emmc.dts

cd arch/arm/boot/dts
cp imx6ull-14x14-evk.dts imx6ull-myimx-emmc.dts

复制完后我们需要更改arch/arm/boot/dts/Makefile的Makefile文件。
找到dtb-$(CONFIG_SOC_IMX6ULL)的配置项,加入
imx6ull-myimx-emmc.dtbIMX6ULL Linux内核移植_第1张图片
下面我们就可以开始编译了
输入命令

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_myimx_emmc_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j4

IMX6ULL Linux内核移植_第2张图片
编译成功
编译成功后会在目录 arch/arm/boot 下生成 zImage 镜像文件。在 arch/arm/boot/dts 目录
下生成 imx6ull-myimx-emmc.dtb 文件

然后我们拷贝到tftp服务器下 让uboot启动时拷贝zImage文件和dtb文件并且启动

cp arch/arm/boot/dts/imx6ull-myimx-emmc.dtb /home/dwh/linux/tftpboot/
cp arch/arm/boot/zImage /home/dwh/linux/tftpboot/

在这里插入图片描述然后重启开发板,在
uboot 命令模式中使用 tftp 命令下载这两个文件并启动

tftp 80800000 zImage
tftp 83000000 imx6ull-myimx-emmc.dtb
bootz 8080000083000000

IMX6ULL Linux内核移植_第3张图片
重启后,我们可以看到linux内核已经成功启动!
在这里Linux内核已经启动了,但是我们还需要修改网络驱动,因为正点原子的开发板与NXP官方的板子是不一样的,因此我们要修改网络驱动
首先把imx6ull_myix_emmc.dts里面 588和599行
初始化 SNVS_TAMPER7 和 SNVS_TAMPER8 这两个
引脚的,是作为了 SPI4 的 IO,这不是我们想要的,所以将 588 和 589 这两行
删除掉!
IMX6ULL Linux内核移植_第4张图片
第 129 行,设置 GPIO5_IO08 为 SPI4 的一个功能引脚(我也不清楚具体作为什么功能用), 而 GPIO5_IO08 就是 SNVS_TAMPER8 的 GPIO 功能引脚。
第 133 行,设置 GPIO5_IO07 作为 SPI4 的片选引脚,而 GPIO5_IO07 就是 SNVS_TAMPER7
的 GPIO 功能引脚。
IMX6ULL Linux内核移植_第5张图片
现在我们需要 GPIO5_IO07 和 GPIO5_IO08 分别作为 ENET1 和 ENET2 的复位引脚,而不
是 SPI4 的什么功能引脚,因此将第 129 行和第 133 行处的代码删除掉!!
否则会干扰到网络复位引脚!
面找到名为“iomuxc_snvs”的节点,然后在
此节点下添加网络复位引脚信息
更改后如下

&iomuxc_snvs {
	pinctrl-names = "default_snvs";
        pinctrl-0 = <&pinctrl_hog_2>;
        imx6ul-evk {
		pinctrl_hog_2: hoggrp-2 {
                        fsl,pins = <
                                MX6ULL_PAD_SNVS_TAMPER0__GPIO5_IO00      0x80000000
                        >;
                };

		pinctrl_dvfs: dvfsgrp {
                        fsl,pins = <
                                MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03      0x79
                        >;
                };
		
		pinctrl_lcdif_reset: lcdifresetgrp {
                        fsl,pins = <
                                /* used for lcd reset */
                                MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09  0x79
                        >;
                };

		pinctrl_spi4: spi4grp {
                        fsl,pins = <
                                MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10        0x70a1
                                MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11        0x70a1
                                /*
								MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07      0x70a1
                                MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08      0x80000000
								*/
                        >;
                };

		pinctrl_sai2_hp_det_b: sai2_hp_det_grp {
				fsl,pins = <
						MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04   0x17059
				>;
		};

		pinctrl_enet1_reset: enet1resetgrp {
					 fsl,pins = <
								/* used for enet1 reset */
								MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x10B0 
					 >;
					 };
		/*enet2 reset zuozhongkai*/
		pinctrl_enet2_reset: enet2resetgrp {
					fsl,pins = <
							/* used for enet2 reset */
							MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x10B0 
					>;
				};
        };
};

IMX6ULL Linux内核移植_第6张图片
最后更改一下网络的时钟引脚电气属性

MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b009
MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b009

将这两个引脚的电气属性值改为 0x4001b009,原来默认值为 0x4001b031

IMX6ULL Linux内核移植_第7张图片

然后找到 fec1、fec2 这两个节点修改修改为如下

&fec1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet1
				&pinctrl_enet1_reset>;
	phy-mode = "rmii";
	phy-handle = <&ethphy0>;
	phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;
	phy-reset-duration = <200>;
	status = "okay";
};

&fec2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet2
				&pinctrl_enet2_reset>;
	phy-mode = "rmii";
	phy-handle = <&ethphy1>;
	phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
	phy-reset-duration = <200>;
	status = "okay";

	mdio {
		#address-cells = <1>;
		#size-cells = <0>;

		ethphy0: ethernet-phy@0 {
			compatible = "ethernet-phy-ieee802.3-c22";
			smsc,disable-energy-detect;
			reg = <0>;
		};

		ethphy1: ethernet-phy@1 {
			compatible = "ethernet-phy-ieee802.3-c22";
			smsc,disable-energy-detect;
			reg = <1>;
		};
	};
};

然后编译

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtb

然后生成了设备树dtb文件

然后修 改 一 下 Linux 内 核 源 码 , 打 开
drivers/net/ethernet/freescale/fec_main.c,找到函数 fec_probe,在 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);

IMX6ULL Linux内核移植_第8张图片
输入命令
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig,打开图形化配置界面,选择使能 LAN8720A 的驱动,路径
如下:
-> Device Drivers
-> Network device support
-> PHY Device support and infrastructure
-> Drivers for SMSC PHYs
IMX6ULL Linux内核移植_第9张图片
修改 smsc.c 文件
首先需要找到 LAN8720A 的驱动文件,LAN8720A 的驱动文件是 drivers/net/phy/smsc.c,
在此文件中有个叫做 smsc_phy_reset 的函数,看名字都知道这是 SMSC PHY 的复位函数,因
此,LAN8720A 肯定也会使用到这个复位函数,修改此函数的内容,修改以后的 smsc_phy_reset
函数内容如下所示

static int smsc_phy_reset(struct phy_device *phydev)
{
	int err, phy_reset;
	int msec = 1;
	struct device_node *np;
	int timeout = 50000;
	if(phydev->addr == 0)
	{
		np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000");
		if (np == NULL)
		{
			return -EINVAL;
		}
		
	}

	if(phydev->addr == 1)
	{
		np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000");
		if (np == NULL)
		{
			return -EINVAL;
		}
		
	}

	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;

	gpio_direction_output(phy_reset, 0);

    gpio_set_value(phy_reset, 0);

    msleep(msec);

    gpio_set_value(phy_reset, 1);

	int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);

    if (rc < 0)
    	return rc;

	if ((rc & MII_LAN83C185_MODE_MASK) ==MII_LAN83C185_MODE_POWERDOWN) {

	 	/* set "all capable" mode and reset the phy */
		rc |= MII_LAN83C185_MODE_ALL;
		phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc);
	}

	phy_write(phydev, MII_BMCR, BMCR_RESET);

	do {
		udelay(10);
		if (timeout-- == 0)
			return -1;
		rc = phy_read(phydev, MII_BMCR);
    } while (rc & BMCR_RESET);
     
	return 0;
}

完工,保存,编译!!

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_myimx_emmc_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j4

IMX6ULL Linux内核移植_第10张图片
编译完成。
复制zImage 和 设备树文件到 tftpboot

cp arch/arm/boot/dts/imx6ull-myimx-emmc.dtb /home/dwh/linux/tftpboot/
cp arch/arm/boot/zImage /home/dwh/linux/tftpboot/

启动Uboot时设置一下参数,更改根文件系统nfs的地址 和tftp下载的地址

setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000'
setenv bootargs 'console=ttymxc0,115200 rw root=/dev/nfs nfsroot=192.168.0.9:/home/dwh/linux/nfs/rootfs ip=192.168.0.20:192.168.0.9:192.168.0.1:255.255.255.0::eth0:off'

启动网卡

ifconfig eth0 up
ifconfig eth0 192.168.0.20

启动!
IMX6ULL Linux内核移植_第11张图片
最后成功使用网络!!
![在这里插入图片描述](https://img-blog.csdnimg.cn/61ff6e2a340b46928150123f11212c65.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2R3aDEzMTQ=,size_16,color_FFFFFF,t_70

你可能感兴趣的:(Linux嵌入式)