IMX6ULL-Kernel 5.4.70移植记录

开发环境简介
开发板正点原子MINI
操作系统Linux-Mint 20.2
交叉编译链gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf
Kernel版本imx_5.4.70_2.3.0
NXP官方Kernel准备

​ NXP Kernel官方下载地址:https://source.codeaurora.org/external/imx/linux-imx

​ 笔者在这里遇到了很大的困难,主要是一下三点:

  1. 访问速度,电信的网站访问外网真的很慢(其他的直接起飞),最后挂VPN解决;
  2. RPC Failed,完整的NXP的Kernel仓库分支太多导致的(.git文件大小有3G+);
  3. 软链接文件在Windows下下载会变成普通文件失去链接功能,要在Linux环境下clone。

解决方案:使用浅层克隆,然后恢复为完整仓库

浅层克隆:

git clone -depth=1 https://source.codeaurora.org/external/imx/linux-imx

修改 .git/config 文件:

[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
[remote "origin"]
	url = https://source.codeaurora.org/external/imx/linux-imx
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
	remote = origin
	merge = refs/heads/master

获取仓库:

git fetch --all

等到下载完成,就可以查看所有分支(按q退出):

git branch -a

切换到我们想要的分支(本文选用imx_5.4.70_2.3.0):

git checkout imx_5.4.70_2.3.0
依赖环境安装
编译官方Kernel
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v7_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j8
  1. 找不到 openssl/bio.h
scripts/extract-cert.c:21:10: fatal error: openssl/bio.h: No such file or directory
   21 | #include <openssl/bio.h>
      |          ^~~~~~~~~~~~~~~
compilation terminated.

​ 解决办法:

sudo apt install libssl-dev
  1. 找不到lzop
/bin/sh: 1: lzop: not found

​ 解决办法:

sudo apt install lzop
  1. 找不到ncurses包
*
* Unable to find the ncurses package.
* Install ncurses (ncurses-devel or libncurses-dev
* depending on your distribution).
*

​ 解决办法:

sudo apt install libncurses5-dev 
  1. 留坑待定

添加自定义开发板
  • 复制默认配置文件

    cp arch/arm/configs/imx_v7_defconfig arch/arm/configs/imx_custom_defconfig 
    
  • 复制设备树

    cp arch/arm/boot/dts/imx6ull-14x14-evk.dts arch/arm/boot/dts/imx6ull-custom.dts
    cp arch/arm/boot/dts/imx6ull-14x14-evk-emmc.dts arch/arm/boot/dts/imx6ull-custom-emmc.dts
    
  • 更改imx6ull-custom-emmc.dts里的头文件改成imx6ull-custom.dts

    xxx-emmc.dts实质就是在xxx.dts的基础上加入了emmc节点信息。

  • 添加设备树到Makefile

    vim arch/arm/boot/dts/Makefile
    

    添加修改如下:

    dtb-$(CONFIG_SOC_IMX6UL) += \
    	imx6ul-14x14-evk.dtb \
    	... \
    	imx6ull-14x14-evk.dtb \
    	imx6ull-14x14-evk-emmc.dtb \
    	imx6ull-custom.dtb \
    	imx6ull-custom-emmc.dtb \
    	imx6ull-14x14-evk-btwifi.dtb \
    	imx6ull-14x14-evk-btwifi-oob.dtb \
    	...
    
  • 创建编译脚本

    在Kernel根目录创建build_custom_kernel.sh

    #! /bin/sh
    
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean // 清理
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_custom_defconfig // 默认配置
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig // 图形化配置
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j8 // 编译
    

    添加运行权限

    chmod a+x build_custom_kernel.sh
    
  • 编译

    出现如下即说明内核编译成功

    Kernel: arch/arm/boot/zImage is ready
    
网络启动Linux
TFTP服务搭建
  1. 安装软件包

    sudo apt install tftp-hpa tftpd-hpa // TFTP
    sudo apt install xinetd // 必须
    
  2. 配置环境

    新建文件夹作为传输目标地址

    mkdir /home/<usr>/Workdir/tftp // 新建文件夹
    chmod 777 /home/<usr>/Workdir/tftp  // 以防万一,权限给满
    

    新建 /etc/xinetd.d/tftp 文件(修改需要权限),内容如下

    server tftp
    {
        socket_type = dgram
        protocol    = udp
        wait        = yes
        user        = root
        server      = /usr/sbin/in.tftpd
        server_args = -s /home/<usr>/Workdir/tftp/  // 上面新建的
        disable     = no
        per_source  = 11
        cps         = 100 2
        flags       = IPv4
    }
    

    修改 /etc/default/tftpd-hpa 文件,内容如下:

    # /etc/default/tftpd-hpa
    
    TFTP_USERNAME="tftp"
    TFTP_DIRECTORY="/home/hugh/Network/tftp"
    TFTP_ADDRESS=":69"
    TFTP_OPTIONS="-c -l -s"
    
  3. 重启服务

    sudo service tftpd-hpa restart
    
  4. 传输测试

    将上面生成的 zImage 放入tftp文件夹,启动UBoot设置服务器地址并下载zImage

    setenv serverip 192.168.0.101
    setenv
    tftp 80800000 zImage // 将zIamge刷写在80800000处
    

    成功打印如下(不成功可以先确认tftp服务是否成功启动):

    => tftp 80800000 zImage
    Using ethernet@20b4000 device
    TFTP from server 192.168.0.101; our IP address is 192.168.0.107
    Filename 'zImage'.
    Load address: 0x80800000
    Loading: #################################################################
             #################################################################
             #################################################################
             #################################################################
             #################################################################
             #################################################################
             #################################################################
             #################################################################
             #################################################################
             ##################################
             635.7 KiB/s
    done
    Bytes transferred = 9076752 (8a8010 hex)
    
网络挂载Kernel和设备树

​ 将生成的zImage(arch/arm/boot)和dtb文件(arch/arm/boot/dts)都放入tftp文件夹。

​ 从网络直接启动

setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs ip=dhcp nfsroot=192.168.0.101:,v3,tcp'
setenv fdt_file=imx6ull-custom-emmc.dtb
saveenv

​ 将zImage和设备树下载到开发板再启动

setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-custom-emmc.dtb; bootz 80800000 - 83000000'
saveenv

​ 显示如下就表明内核启动成功

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 5.4.70 (hugh@E540) (gcc version 7.5.0 (Linaro GCC 7.5-2019.12)) #1 SMP PREEMPT Sat Oct 16 20:34:03 CST 2021
[    0.000000] CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=10c5387d
[    0.000000] CPU: div instructions available: patching division code
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache

​ 出现这个现象是因为没有挂载根文件系统

[   98.560735] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)
[   98.569017] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0) ]---
问题及解决
LCD显示修改

​ 本文中使用的是800x480 TFT4.3的屏幕,NXP提供的设备树默认是480x272 TFT4.3的屏幕

​ 根据对 im6ull-custom-emmc.dts 的层层查找可知,屏幕相关的参数在 imx6ul-14x14-evk.dtsi 设置。

	display0: display@0 {
		bits-per-pixel = <16>;
		bus-width = <24>;

		display-timings {
			native-mode = <&timing0>;

			timing0: timing0 {
				clock-frequency = <9200000>;
				hactive = <480>;
				vactive = <272>;
				hfront-porch = <8>;
				hback-porch = <4>;
				hsync-len = <41>;
				vback-porch = <2>;
				vfront-porch = <4>;
				vsync-len = <10>;
				hsync-active = <0>;
				vsync-active = <0>;
				de-active = <1>;
				pixelclk-active = <0>;
			};
		};
	};

填入对应的屏幕参数即可。

网卡驱动修改

​ PHY报错如下,原因是LAN8720的问题,需要复位:

[    2.454825] fec 20b4000.ethernet eth0: Unable to connect to phy
[    2.462375] IP-Config: Failed to open eth0
[    2.468597] fec 2188000.ethernet eth1: Unable to connect to phy
[    2.476182] IP-Config: Failed to open eth1
[    2.480310] IP-Config: No network devices available

​ 根据对 im6ull-custom-emmc.dts 的层层查找可知,屏幕相关的参数在 imx6ul-14x14-evk.dtsi 设置。

​ 正点原子开发板的ENET1 复位引脚 ENET1_RST 连接在 I.M6ULL 的 SNVS_TAMPER7 ,ENET2的复位引脚 ENET2_RST 连接在 I.MX6ULL 的 SNVS_TAMPER8 。MINI只有一个网口,ENET2。

  • 失能spi里的冲突引脚

    	pinctrl_spi4: spi4grp {
    		fsl,pins = <
    			MX6UL_PAD_BOOT_MODE0__GPIO5_IO10	0x70a1
    			MX6UL_PAD_BOOT_MODE1__GPIO5_IO11	0x70a1
    			/* 
    			MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07	0x70a1
    			MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08	0x80000000
    			*/
    		>;
    	};
    
    spi4 {
    		compatible = "spi-gpio";
    		pinctrl-names = "default";
    		pinctrl-0 = <&pinctrl_spi4>;
    		status = "disable";  // 失能
    		/* pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>; */
    		gpio-sck = <&gpio5 11 0>;
    		gpio-mosi = <&gpio5 10 0>;
    		/* cs-gpios = <&gpio5 7 0>; */
    		num-chipselects = <1>;
    		#address-cells = <1>;
    		#size-cells = <0>;
    
  • 给网口添加复位引脚,并修改时钟

    pinctrl_enet1: enet1grp {
    		fsl,pins = <
    			MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN	0x1b0b0
    			MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER	0x1b0b0
    			MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00	0x1b0b0
    			MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01	0x1b0b0
    			MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN	0x1b0b0
    			MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00	0x1b0b0
    			MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01	0x1b0b0
    			MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x4001b009 // 时钟
    			MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07	0x10B0 // 复位引脚
    		>;
    	};
    
    	pinctrl_enet2: enet2grp {
    		fsl,pins = <
    			MX6UL_PAD_GPIO1_IO07__ENET2_MDC		0x1b0b0
    			MX6UL_PAD_GPIO1_IO06__ENET2_MDIO	0x1b0b0
    			MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN	0x1b0b0
    			MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER	0x1b0b0
    			MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00	0x1b0b0
    			MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01	0x1b0b0
    			MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN	0x1b0b0
    			MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00	0x1b0b0
    			MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01	0x1b0b0
    			MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2	0x4001b009
    			MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08	0x10B0
    		>;
    	};
    
  • 修改FEC节点

    &fec1 {
    	pinctrl-names = "default";
    	pinctrl-0 = <&pinctrl_enet1>;
    	phy-mode = "rmii";
    	phy-handle = <&ethphy0>;
    	phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>; // 复位引脚
    	phy-reset-duration = <200>; //复位时间
    	status = "disable";
    };
    
    &fec2 {
    	pinctrl-names = "default";
    	pinctrl-0 = <&pinctrl_enet2>;
    	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 {
    			reg = <0>;
    			smsc,led-mode = <1>;  // LAN8720属于SMSC公司
    			clocks = <&clks IMX6UL_CLK_ENET_REF>;
    			clock-names = "rmii-ref";
    		};
    
    		ethphy1: ethernet-phy@1 {
    			reg = <1>;
    			smsc,led-mode = <1>;
    			clocks = <&clks IMX6UL_CLK_ENET2_REF>;
    			clock-names = "rmii-ref";
    		};
    	};
    };
    
  • 修改重置函数(与UBoot不同,不过好像不修改也是正常的,记录一下)(!!!未完成!!!)

    修改 smsc_phy_reset(…) 函数, 在本文的所用内核中,没做成功,卡在通过路径查找节点,主要思路就是通过phy_device找到是哪个网口,然后通过路径查找节点,在利用节点的参数复位,留待正式学习了再回头看:

    // 添加头文件,查找和引脚操作
    #include <linux/of_gpio.h>
    #include <linux/io.h>
    
    // 
    // if( phy_dev->addr == 0/1 ) // 旧版
    if( phy_dev->mdio.addr == 0/1 )    // 判断是哪个网口
    node = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000") // 通过路径查找节点
    of_property_read_u32(node, "phy-reset-duration", &msec); // 读取复位时间
    gpio = of_get_named_gpio(np, "phy-reset-gpios", 0); // 获取引脚
    if(!gpio_is_valid(gpio)) // 判断引脚是否有效
    gpio_direction_output(gpio, 0); // 设置引脚模式
    gpio_set_value(gpio, 0); // 设置引脚输出
    msleep(msec); // 延时
    
  • 启动

    SMSC LAN8710/LAN8720 20b4000.ethernet-1:01: attached PHY driver [SMSC LAN8710/LAN8720] (mii_bus:phy_addr=20b4000.ethernet-1:01, irq=POLL)
    [    4.805177] fec 20b4000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
    [    4.834878] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
    [    4.864452] Sending DHCP requests ., OK
    [    5.008421] IP-Config: Got DHCP answer from 192.168.0.1, my address is 192.168.0.109
    [    5.016915] IP-Config: Complete:
    [    5.020539]      device=eth0, hwaddr=f6:b4:f4:d5:0a:f0, ipaddr=192.168.0.109, mask=255.255.255.0, gw=192.168.0.1
    [    5.030781]      host=192.168.0.109, domain=, nis-domain=(none)
    [    5.036924]      bootserver=0.0.0.0, rootserver=192.168.0.101, rootpath=
    [    5.036942]      nameserver0=192.168.1.1, nameserver1=192.168.0.1
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值