• IMX6ULL | 从零开始移植linux内核5.4.70_2.3.0


    i.MX6ULL - 从零开始移植linux内核5.4.70_2.3.0



    前言

    uboot移植看这里:https://blog.csdn.net/qq153471503/article/details/126587387


    1、环境搭建

    见此篇博客:https://blog.csdn.net/qq153471503/article/details/126587387


    2、官方EVK开发板内核编译

    注意:建议内核的版本最好是跟你uboot的版本是一致或者相似的,否则可能uboot无法启动起内核,我的uboot也是5.4.70.2.3.0,所以内核也选用该版本。

    下载内核(文件很大且非常慢,建议晚上睡前开始下载,下一晚上):

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

    查看所有分支:

    git branch --all
    
    • 1

    切换到imx_5.4.70_2.3.0分支:

    git checkout imx_5.4.70_2.3.0
    
    • 1


    修改顶层Makefile文件,找到ARCH ?= $(SUBARCH),修改为:

    ARCH = arm
    CROSS_COMPILE = arm-linux-gnueabihf-
    
    • 1
    • 2

    初次编译:

    make imx_v7_defconfig
    make -j 2
    
    • 1
    • 2

    这一步可以直接编译通过。


    3、建立自己的板子配置进行编译

    拷贝配置文件:

    cp arch/arm/configs/imx_v7_defconfig arch/arm/configs/imx_v7_hello_emmc_defconfig
    
    • 1

    拷贝设备树文件:

    cp arch/arm/boot/dts/imx6ull-14x14-evk-emmc.dts arch/arm/boot/dts/imx6ull-14x14-hello-emmc.dts
    cp arch/arm/boot/dts/imx6ull-14x14-evk.dts arch/arm/boot/dts/imx6ull-14x14-hello.dts
    cp arch/arm/boot/dts/imx6ul-14x14-evk.dtsi arch/arm/boot/dts/imx6ul-14x14-hello.dtsi
    
    • 1
    • 2
    • 3

    修改arch/arm/boot/dts/Makefile文件,将新增的设备树文件添加进编译,如下图所示:

    修改设备树文件arch/arm/boot/dts/imx6ull-14x14-hello-emmc.dts,将:

    #include "imx6ull-14x14-evk.dts"
    
    • 1

    改为:

    #include "imx6ull-14x14-hello.dts"
    
    • 1

    修改arch/arm/boot/dts/imx6ull-14x14-hello.dts文件,将:

    #include "imx6ull.dtsi"
    #include "imx6ul-14x14-evk.dtsi"
    
    • 1
    • 2

    改为:

    #include "imx6ull.dtsi"
    #include "imx6ul-14x14-hello.dtsi"
    
    • 1
    • 2

    在将:

    model = "Freescale i.MX6 ULL 14x14 EVK Board";
    compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
    
    • 1
    • 2

    改为:

    model = "Freescale i.MX6 ULL 14x14 HELLO Board";
    compatible = "fsl,imx6ull-14x14-hello", "fsl,imx6ull";
    
    • 1
    • 2

    尝试编译:

    make imx_v7_hello_emmc_defconfig
    make -j 2
    
    • 1
    • 2

    将编译出的设备树文件和内核文件拷贝到tftp的目录:

    cp arch/arm/boot/zImage /tftpboot/
    cp arch/arm/boot/dts/imx6ull-14x14-hello-emmc.dtb /tftpboot/
    
    • 1
    • 2

    设置uboot中关于网络的环境变量:

    setenv ipaddr 192.168.28.234
    setenv gatewayip 192.28.28.1
    setenv netmask 255.255.255.0
    setenv serverip 192.168.28.254
    saveenv
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • ipaddr:板子的IP地址
    • gatewayip:网关
    • netmask:掩码
    • serverip:ubuntu的ip地址

    在uboot中使用tftp下载内核验证测试:

    tftp 80800000 zImage
    tftp 83000000 imx6ull-14x14-hello-emmc.dtb
    bootz 80800000 - 83000000
    
    • 1
    • 2
    • 3

    内核启动最终如下:

    看这个提示可以知道挂载文件系统失败了,原因是unknown-block(0,0),未知的块,这个问题是由于uboot中bootargs的参数有误导致的。

    复位开发板,查看一下uboot中bootargs这个环境变量:

    没有定义,那么我们给他定义一下:

    setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
    saveenv
    
    • 1
    • 2

    如果你的emmc中存在文件系统,再次使用tftp下载内核和设备树并启动就能进入文件系统了。

    到目前为止,基础内核已经移植完毕,下面的工作主要就是修改设备树arch/arm/boot/dts/imx6ul-14x14-hello.dtsi文件来适配我们自己板子上的硬件了!


    4、LED灯设备树驱动添加

    !!!!必看注意事项!!!!!
       ~~   

    IMX6ULL的设备树引用了IMX6UL的设备树文件,由于这两款SOC是差不多的,普通IO部分大部分都一样,所以共用imx6ul-pinfunc.h里的这些宏定义,在设备树文件中也可以看到大部分是使用的MX6UL_开头的宏。
       ~~   
    但是对于IMX6ULL来说,它的IO支持更多的功能映射以及复用,所以这个时候的宏定义是在imx6ul-pinfunc.h找不到的,要在imx6ull-pinfunc.h中找;
       ~~   
    其次,如果使用到了GPIO5组下的IO,
       ~~   
    例如使用GPIO5_IO03这个IO,
       ~~   
    那么不能使用imx6ul-pinfunc.h文件中的宏MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03
       ~~   
    而是应该使用imx6ull-pinfunc-snvs.h文件中的宏MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03
       ~~   
    !!!!!!!!!这里一定要格外注意!!!!!!!!!!

    我的板子上有两个LED灯:

    GPIO1_IO10:低电平点亮
    GPIO5_IO03:心跳灯指示灯,用于指示板子在正常工作

    编辑设备树文件arch/arm/boot/dts/imx6ul-14x14-hello.dtsi,在memory节点下方新增led灯的设备树配置:

    	/* +++lakun */
    	leds {
    		compatible = "gpio-leds";
    		pinctrl-names = "default";
    		pinctrl-0 = <&pinctrl_led &pinctrl_heartbeat>;
    		status = "okay";
    		led1 {
    			label = "led1";
    			gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
    			default-state = "off";
    		};
    		led2 {
    			label = "heartbeat";
    			gpios = <&gpio5 3 GPIO_ACTIVE_LOW>;
    			linux,default-trigger = "heartbeat";
    		};
    	};
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    由于LED2是GPIO5下的,所以要使用iomuxc_snvs节点;找到iomuxc节点并新增LED1的配置:

    	/* +++lakun: led */
    	pinctrl_led: ledgrp {
    		fsl,pins = <
    			MX6UL_PAD_JTAG_MOD__GPIO1_IO10    0xb0a0
    		>;
    	};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    并在iomuxc节点上方添加iomuxc_snvs节点:

    &iomuxc_snvs {
    	/* +++lakun: led heartbeat */
    	pinctrl_heartbeat: heartbeatgrp {
    		fsl,pins = <
    			MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03    0x17059  /* !!这里注意这个宏的是MX6ULL_而不是MX6UL_!! */
    		>;
    	};
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    如下图所示:

    配置完之后全局搜索MX6UL_PAD_JTAG_MOD__GPIO1_IO10、MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03、MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03,看看这两几个宏有没有被其他外设使用,如果有的话就屏蔽掉。

    单独编译一下设备树:

    make dtbs
    
    • 1

    再次使用tftp下载内核和设备树,进入到文件系统,此时/sys/class/leds/目录下会多出来一个heartbeatled1文件夹:

    板子上的心跳灯也会有规律的闪烁:

    在测试一下led1开关灯:

    开灯:

    echo > /sys/class/leds/led1/brightness 1
    
    • 1

    关灯:

    echo > /sys/class/leds/led1/brightness 0
    
    • 1


    5、删除设备树中的无用配置

    官网EVK开发板中使用了一片74LV595来扩展IO,我们自己的板子没有使用,所以屏蔽掉相关的设备树配置:

    	reg_can_3v3: regulator-can-3v3 {
    		compatible = "regulator-fixed";
    		regulator-name = "can-3v3";
    		regulator-min-microvolt = <3300000>;
    		regulator-max-microvolt = <3300000>;
    		/* gpios = <&gpio_spi 3 GPIO_ACTIVE_LOW>; */
    	};
    
    /*
    	spi4 {
    		compatible = "spi-gpio";
    		pinctrl-names = "default";
    		pinctrl-0 = <&pinctrl_spi4>;
    		status = "okay";
    		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>;
    
    		gpio_spi: gpio@0 {
    			compatible = "fairchild,74hc595";
    			gpio-controller;
    			#gpio-cells = <2>;
    			reg = <0>;
    			registers-number = <1>;
    			registers-default = /bits/ 8 <0x57>;
    			spi-max-frequency = <100000>;
    		};
    	};
    */
    
    	ov5640: ov5640@3c {
    		compatible = "ovti,ov5640";
    		reg = <0x3c>;
    		pinctrl-names = "default";
    		pinctrl-0 = <&pinctrl_csi1>;
    		clocks = <&clks IMX6UL_CLK_CSI>;
    		clock-names = "csi_mclk";
    		/* pwn-gpios = <&gpio_spi 6 1>; */
    		/* rst-gpios = <&gpio_spi 5 0>; */
    		csi_id = <0>;
    		mclk = <24000000>;
    		mclk_source = <0>;
    		status = "disabled";
    		port {
    			ov5640_ep: endpoint {
    				remote-endpoint = <&csi1_ep>;
    			};
    		};
    	};
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    6、网络PHY驱动修改适配

    我的板子有两路网口,接口使用到的io引脚与官方EVK开发板一致,但是硬件复位引脚使用的不一样,所以需要修改设备树fec1和fec2节点。

    我的板子enet1复位引脚是GPIO5_IO08,enet1复位引脚是GPIO5_IO04,可以看到这两个IO也都是在GPIO5下,所以设备树的配置同样要在ipmuxc_snvs下,添加以下内容:

    	/* +++lakun: enet1_nrst */
    	pinctrl_eth1rst: eth1rstgrp {
    		fsl,pins = <
    			MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08    0x17059
    		>;
    	};
    
    	/* +++lakun: enet2_nrst */
    	pinctrl_eth2rst: eth2rstgrp {
    		fsl,pins = <
    			MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04    0x17059
    		>;
    	};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    如下图:

    修改fec1和fec2节点为:

    &fec1 {
    	pinctrl-names = "default";
    	pinctrl-0 = <&pinctrl_enet1 &pinctrl_eth1rst>;
    	phy-mode = "rmii";
    	phy-handle = <&ethphy0>;
    	phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
    	phy-reset-duration = <200>;
    	status = "okay";
    };
    
    &fec2 {
    	pinctrl-names = "default";
    	pinctrl-0 = <&pinctrl_enet2 &pinctrl_eth2rst>;
    	phy-mode = "rmii";
    	phy-handle = <&ethphy1>;
    	phy-reset-gpios = <&gpio5 4 GPIO_ACTIVE_LOW>;
    	phy-reset-duration = <200>;
    	status = "okay";
    
    	mdio {
    		#address-cells = <1>;
    		#size-cells = <0>;
    
    		ethphy0: ethernet-phy@2 {
    			reg = <2>;
    			micrel,led-mode = <1>;
    			clocks = <&clks IMX6UL_CLK_ENET_REF>;
    			clock-names = "rmii-ref";
    		};
    
    		ethphy1: ethernet-phy@1 {
    			reg = <1>;
    			micrel,led-mode = <1>;
    			clocks = <&clks IMX6UL_CLK_ENET2_REF>;
    			clock-names = "rmii-ref";
    		};
    	};
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    ethphy0: ethernet-phy@2:这里的2表示的是phy1的地址为2
    ethphy1: ethernet-phy@1:这里的1表示的是phy2的地址为1

    这需要和你的原理图去对应。

    全局搜索MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04、MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08、MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04、MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08,查看有无其他外设占用这两个IO,如果有就屏蔽掉。

    重新编译设备树并下载,板子启动后进入文件系统。

    查看所有网络设备:

    ifconfig -a
    
    • 1

    先测试eth0,网线插到eth0的RJ45接口上,启动eth0,禁用eth1:

    ifconfig eth0 up
    ifconfig eth1 down
    ifconfig eth0 192.168.28.234
    ping 192.168.28.1
    
    • 1
    • 2
    • 3
    • 4

    在测试eth1,网线插到eth1的RJ45接口上,启动eth1,禁用eth0:

    ifconfig eth0 down
    ifconfig eth1 up
    ifconfig eth1 192.168.28.235
    ping 192.168.28.1
    
    • 1
    • 2
    • 3
    • 4

    都能够ping通,完成网络的移植适配!


    未完待续。。。

  • 相关阅读:
    一文了解Go语言的函数
    Z-Libary最新地址检测,再也不用担心找不到ZLibary了
    zabbix部署与监控
    Mysql加锁流程详解
    JS——垃圾回收的原理
    Leetcode(81)——搜索旋转排序数组 II
    Docker基本操作
    IDEA如何拉取gitee项目?
    DSP28335学习记录(三)——ePWM
    java从入门到精通二十八(Spring注解开发)
  • 原文地址:https://blog.csdn.net/qq153471503/article/details/126869581