目录
- [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文件,一种是图形化界面进行修改,这里使用图形化界面进行修改;
make menuconfig
:运行这个命令,打开配置界面:
- 进入下图对应的目录,并选择默认的cpu频率的配置,退出后运行
make -j8
,然后编译 Linux内核,一定不要清理工程!否则的话我们刚刚的设置就会被清理掉。编译完成以后使用新的zImage 重启 Linux,查看当前 CPU 的工作频率和调频策略,把生成的zImage文件下载的板子中
- 配置完毕,把新的zImage加载到板子中可以发现,cpu已经工作在了onmend模式下;重要的事情说三遍,可以把保存好的配置文件给备份一份;
- 一定不要清理工程!否则的话我们刚刚的设置就会被清理掉!
- 一定不要清理工程!否则的话我们刚刚的设置就会被清理掉!
- 一定不要清理工程!否则的话我们刚刚的设置就会被清理掉!
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内核时均未添加自己的板卡信息,均是在原板级文件上进行修改;
- 第一处修改的地方在
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 */
>;
};
- 第二处修改也是在这个文件中,也就是把和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>;
- 第三处修改也是在这个文件中,添加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
>;
};
- 第四处修改也是在这个文件中,添加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>;
};
...........................
- 第五处修改也是在这个文件中,修改如下:
c
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1
&pinctrl_enet1_reset>;/* 添加内容 */
phy-mode = "rmii";
phy-handle = <ðphy0>;
status = "okay";
};
&fec2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet2
&pinctrl_enet2_reset>; /*添加内容*/
- 第六处修改也是在这个文件中,修改的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>;
};
};
- 第七处修改如下,要 在 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);
...................
}
- 使能使能 LAN8720 驱动,通过图型化界面进行配置:如下:
- 运行
make -j8
命令进行重新编译,把生成的zImage挂载到系统中进行测试:
4. 总结
通过上述步骤,成功完成了I.MX6ULL开发板的内核移植与驱动修改,实现了系统的正常启动和基本功能的运行。主要修改内容包括CPU频率设置、EMMC驱动模式以及网络驱动配置。在实践中需要特别注意保持编译配置的持久性,避免清理工程导致配置丢失,这里主要是对自己进行linux内核移植过程的关键信息进行了一个介绍和总结,可作为复盘的记录;