【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内核移植过程的关键信息进行了一个介绍和总结,可作为复盘的记录;

相关推荐
奶糖趣多多2 分钟前
Redis知识点
数据库·redis·缓存
Lary_Rock1 小时前
RK3576 LINUX RKNN SDK 测试
linux·运维·服务器
CoderIsArt1 小时前
Redis的三种模式:主从模式,哨兵与集群模式
数据库·redis·缓存
云飞云共享云桌面3 小时前
8位机械工程师如何共享一台图形工作站算力?
linux·服务器·网络
师太,答应老衲吧3 小时前
SQL实战训练之,力扣:2020. 无流量的帐户数(递归)
数据库·sql·leetcode
Peter_chq4 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Channing Lewis4 小时前
salesforce case可以新建一个roll up 字段,统计出这个case下的email数量吗
数据库·salesforce
一坨阿亮4 小时前
Linux 使用中的问题
linux·运维
毕业设计制作和分享5 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
ketil275 小时前
Redis - String 字符串
数据库·redis·缓存