【linux-kernel内核移植记录-踩坑以及注意事项】

目录

  • [1. 环境介绍](#1. 环境介绍)
  • 2.编译原厂的kernel
    • [2.1 通过tftp挂载原厂linux内核](#2.1 通过tftp挂载原厂linux内核)
  • [3. 修改对应的驱动](#3. 修改对应的驱动)
    • [3.1 修改CPU频率](#3.1 修改CPU频率)
    • [3.2 修改MMC](#3.2 修改MMC)
    • [3.3 修改网络驱动](#3.3 修改网络驱动)
  • [4. 总结](#4. 总结)

1. 环境介绍

  • ubuntu版本16.04
  • I.MX6ULL开发板,阿尔法
  • uboot正常启动,能ping通ubuntu,可通过tftpboot进行网络下载,校准了DDR
  • 使用NXP原厂的内核进行修改:linux-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2

2.编译原厂的kernel

上节已经移植完毕uboot,链接,接下来就是对linux内核的移植,对于内核的移植有大神就会对linux内核进行裁剪,但是由于刚开始学习,对于内核的移植先保证能正常启动和运行,对于后续的剪裁和优化就先暂时丢弃;

  • tar -vxjf linux-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2:对压缩包进行解压;
  • 和uboot编译类似,创建一个shell脚本文件my.sh,内容如下:

#!/bin/bash

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

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

make ARCH=arm CROSS_COMPILE=arm-iinux-gnueabihf- menuconfig

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j8

  • ./my.sh:运行脚本进行第一次的编译
  • 给顶层Makefile文件夹加上这两句内容,以后的编译只用使用make -j8就行了

ARCH ?= arm

CROSS_COMPILE ?= arm-linux-gnueabihf-

  • 编译结果如下:

2.1 通过tftp挂载原厂linux内核

  • setenv bootcmd 'tftpboot 0x80800000 zImage;tftpboot 0x83000000 imx6ull-14x14-evk.dtb;bootz 0x80800000 - 0x83000000'
  • saveenv
  • run bootcmd

结果如下图所示:成功进入进入内核。但是缺少,根文件系统;


假设我们把根文件系统已经放在了mmc中的mmcblk1p2中我们进行设置下面的命令:

  • setenv bootargs console=ttymxc0,115200 root=/dev/mmcblk1p2 rw:出现下面的错误:uboot传递给内核的参数bootargs需添加rootwait,避免sd卡驱动加载完成前就从sd卡加载文件系统
  • setenv bootargs console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw

  • 添加完毕的结果如下:

3. 修改对应的驱动

在进行uboot移植时我们并没有过多的进行驱动的修复,例如屏幕驱动我们就没有修改,我们只修改了网络驱动,现在我们看看进入Linux内核完毕后网络是否正常,结果如下图:

3.1 修改CPU频率

刚进入系统时,我们的cpu的工作频率是792MHZ满频率运行,我们要进行设置,使cpu工作为自动负载的模式


修改如下,两种修改方式,一种是通过defconfig文件,一种是图形化界面进行修改,这里使用图形化界面进行修改;

  1. make menuconfig:运行这个命令,打开配置界面:

  1. 进入下图对应的目录,并选择默认的cpu频率的配置,退出后运行make -j8,然后编译 Linux内核,一定不要清理工程!否则的话我们刚刚的设置就会被清理掉。编译完成以后使用新的zImage 重启 Linux,查看当前 CPU 的工作频率和调频策略,把生成的zImage文件下载的板子中

  1. 配置完毕,把新的zImage加载到板子中可以发现,cpu已经工作在了onmend模式下;重要的事情说三遍,可以把保存好的配置文件给备份一份;
  2. 一定不要清理工程!否则的话我们刚刚的设置就会被清理掉!
  3. 一定不要清理工程!否则的话我们刚刚的设置就会被清理掉!
  4. 一定不要清理工程!否则的话我们刚刚的设置就会被清理掉!

3.2 修改MMC

我使用的开发板核心板上的 EMMC 采用的 8 位数据线,原理图如图所示:


Linux 内核驱动里面 EMMC 默认是 4 线模式的,4 线模式肯定没有 8 线模式的速度快,所以本节我们将 EMMC 的驱动修改为 8 线模式。修改方法很简单,直接修改设备树即可,打开文

件 imx6ull-14x14-evk.dts,找到如下所示内容修改如下:

c 复制代码
&usdhc2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_usdhc2_8bit>;
	pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
	pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
	bus-width=<8>;
	non-removable;
	no-1-8-v;/*关闭1.8V  供电*/
	status = "okay";
	// pinctrl-names = "default", "state_100mhz", "state_200mhz";
	// pinctrl-0 = <&pinctrl_usdhc2_8bit>;
	// pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
	// pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
	// bus-width = <8>;
	// non-removable;
	// status = "okay";
};

3.3 修改网络驱动

每个人的设备引脚不一样,修改的地方也不一样,不具备参考性,我使用的是正点原子的IMX6ULL开发板,因此详细修改过程可以参考正点原子的嵌入式linux驱动开发指南,对于正点原子的驱动的修改如下:ENET1 复位引脚 ENET1_RST 连接在 I.M6ULL 的 SNVS_TAMPER7 这个引脚上。ENET2的复位引脚 ENET2_RST 连接在 I.MX6ULL 的 SNVS_TAMPER8 上;我这里移植uboot和移植linux内核时均未添加自己的板卡信息,均是在原板级文件上进行修改;

  1. 第一处修改的地方在imx6ull-14x14-evk.dts文件中:修改如下:
c 复制代码
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 */
                 >;
 };
  1. 第二处修改也是在这个文件中,也就是把和IO07和IO08引脚有关的全部改掉;
c 复制代码
	spi4 {
		compatible = "spi-gpio";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_spi4>;
	/*	pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>; */
		status = "okay";
		gpio-sck = <&gpio5 11 0>;
		gpio-mosi = <&gpio5 10 0>;
	/*	cs-gpios = <&gpio5 7 0>; */
		num-chipselects = <1>;
		#address-cells = <1>;
		#size-cells = <0>;
  1. 第三处修改也是在这个文件中,添加PHY的复位引脚;也就是下面的内容:
c 复制代码
		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	0x4001b031
				/*加上下面这句*/
				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	0x4001b031
				/*加上下面这句*/
				MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08		0x10B0
			>;
		};
  1. 第四处修改也是在这个文件中,添加PHY复位节点,修改内容如下:
c 复制代码
&iomuxc_snvs {
	pinctrl-names = "default_snvs";
        pinctrl-0 = <&pinctrl_hog_2>;
        imx6ul-evk {
        
		/*添加下面两个复位节点*/
		pinctrl_enet1_reset: enet1resetgrp {

 			fsl,pins = <MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x10B0>;
 		};
		pinctrl_enet2_reset: enet2resetgrp {
 			fsl,pins = <MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x10B0>;
 		};
...........................
  1. 第五处修改也是在这个文件中,修改如下:
c 复制代码
&fec1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet1
				 &pinctrl_enet1_reset>;/* 添加内容 */
	phy-mode = "rmii";
	phy-handle = <&ethphy0>;
	status = "okay";
};

&fec2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet2
				 &pinctrl_enet2_reset>; /*添加内容*/
  1. 第六处修改也是在这个文件中,修改的PHY的地址,修改如下:
c 复制代码
mdio {
		#address-cells = <1>;
		#size-cells = <0>;
		/*修改phy的地址*/
		ethphy0: ethernet-phy@0 {
			compatible = "ethernet-phy-ieee802.3-c22";
			reg = <0>;
		};

		ethphy1: ethernet-phy@1 {
			compatible = "ethernet-phy-ieee802.3-c22";
			reg = <1>;
		};
	};
  1. 第七处修改如下,要 在 I.MX6ULL 上 使 用 LAN8720A ,需要修改一下Linux内核源码 ,打开drivers/net/ethernet/freescale/fec_main.c,找到函数 fec_probe,在fec_probe 中加入如下代码:
c 复制代码
fec_probe(struct platform_device *pdev)
{
	struct fec_enet_private *fep;
	struct fec_platform_data *pdata;
	struct net_device *ndev;
	int i, irq, ret = 0;
	struct resource *r;
	const struct of_device_id *of_id;
	static int dev_id;
	struct device_node *np = pdev->dev.of_node, *phy_node;
	int num_tx_qs;
	int num_rx_qs;
	fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
	/*下面是新加入的代码*/
	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);
...................
}
  1. 使能使能 LAN8720 驱动,通过图型化界面进行配置:如下:

  1. 运行make -j8命令进行重新编译,把生成的zImage挂载到系统中进行测试:

4. 总结

通过上述步骤,成功完成了I.MX6ULL开发板的内核移植与驱动修改,实现了系统的正常启动和基本功能的运行。主要修改内容包括CPU频率设置、EMMC驱动模式以及网络驱动配置。在实践中需要特别注意保持编译配置的持久性,避免清理工程导致配置丢失,这里主要是对自己进行linux内核移植过程的关键信息进行了一个介绍和总结,可作为复盘的记录;

相关推荐
馨谙4 分钟前
网络故障排查三板斧:路由追踪、端口检查,快速定位网络问题
linux·网络
我的offer在哪里23 分钟前
Redis
数据库·redis·缓存
点灯小铭31 分钟前
基于单片机的多模式自动洗衣机设计与实现
数据库·单片机·嵌入式硬件·毕业设计·课程设计
潜心编码33 分钟前
基于python的仓库管理系统
数据库
herinspace35 分钟前
如何设置电脑分辨率和显示缩放
服务器·数据库·智能手机·电脑
报错小能手35 分钟前
linux学习笔记(49)Redis详解(1)
linux·笔记·学习
biubiubiu070636 分钟前
Ubuntu中定时任务测试
数据库·postgresql
QT 小鲜肉37 分钟前
【个人成长笔记】在本地Windows系统中如何正确使用adb pull命令,把Linux系统中的文件或文件夹复制到本地中(亲测有效)
linux·windows·笔记·学习·adb
panplan.top1 小时前
Tornado + Motor 微服务架构(Docker + 测试 + Kubernetes)
linux·python·docker·微服务·k8s·tornado