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

查看所有分支:

git branch --all

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

git checkout imx_5.4.70_2.3.0


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

ARCH = arm
CROSS_COMPILE = arm-linux-gnueabihf-

初次编译:

make imx_v7_defconfig
make -j 2

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


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

拷贝配置文件:

cp arch/arm/configs/imx_v7_defconfig arch/arm/configs/imx_v7_hello_emmc_defconfig

拷贝设备树文件:

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

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

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

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

改为:

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

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

#include "imx6ull.dtsi"
#include "imx6ul-14x14-evk.dtsi"

改为:

#include "imx6ull.dtsi"
#include "imx6ul-14x14-hello.dtsi"

在将:

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

改为:

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

尝试编译:

make imx_v7_hello_emmc_defconfig
make -j 2

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

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

设置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
  • ipaddr:板子的IP地址
  • gatewayip:网关
  • netmask:掩码
  • serverip:ubuntu的ip地址

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

tftp 80800000 zImage
tftp 83000000 imx6ull-14x14-hello-emmc.dtb
bootz 80800000 - 83000000

内核启动最终如下:

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

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

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

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

如果你的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";
		};
	};

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

	/* +++lakun: led */
	pinctrl_led: ledgrp {
		fsl,pins = <
			MX6UL_PAD_JTAG_MOD__GPIO1_IO10    0xb0a0
		>;
	};

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

&iomuxc_snvs {
	/* +++lakun: led heartbeat */
	pinctrl_heartbeat: heartbeatgrp {
		fsl,pins = <
			MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03    0x17059  /* !!这里注意这个宏的是MX6ULL_而不是MX6UL_!! */
		>;
	};
};

如下图所示:

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

单独编译一下设备树:

make dtbs

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

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

在测试一下led1开关灯:

开灯:

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

关灯:

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


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>;
			};
		};
	};



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
		>;
	};

如下图:

修改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";
		};
	};
};

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

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

ifconfig eth0 up
ifconfig eth1 down
ifconfig eth0 192.168.28.234
ping 192.168.28.1

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

ifconfig eth0 down
ifconfig eth1 up
ifconfig eth1 192.168.28.235
ping 192.168.28.1

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


未完待续。。。

Logo

更多推荐