我们使用NXP官方提供的Linux源码,移植到i.MX6UL终结者开发板上。官方Linux源码可以从网盘资料中获取,路径:i.MX6UL终结者光盘资料/05_uboot linux源码/NXP官方原版Uboot和Linux.zip。通过ssh将Linux内核源码发送到Ubuntu虚拟机中并解压,得到内核源码文件目录linux-imx-rel_imx_4.1.15_2.1.0_ga。图 1.1所示:
NXP官方提供的Linux源码编译后只能在自己的开发板上运行,所以以NXP的开发板作为参考,将Linux内核移植到i.MX6UL终结者开发板上。
进入内核目录linux-imx-rel_imx_4.1.15_2.1.0_ga下,修改Makefile文件,在Makefile文件中有ARCH 和CROSS_COMPILE 这两个的变量,通过这两个变量指定交叉编译工具。修改如图 1.1.1.1所示:
修改这两个变量的值后在编译时,就不用在指定编译工具了。
每个板子都有对应的默认的配置文件,在编译Linux内核之前,需要根据目标开发板选择不同的配置文件,这些配置文件保存在arch/arm/configs目录下。NXP官方的开发板默认对应的配置文件是imx_v7_mfg_defconfig。
进入到Ubuntu虚拟机的Linux源码目录下,执行以下命令来配置内核:
make clean //编译之前先清理一下
make imx_v7_mfg_defconfig //配置Linux内核
配置完成后,会生成 .config文件,如图 1.1.2.1和图 1.1.2.2所示:
配置完成后就可以进行编译了,使用下面的命令:
make -j8 //编译Linux内核
编译完成如图 1.1.2.3所示:
编译完成后,我们会得到两个文件。
① Linux内核镜像文件:arch/arm/boot/zImage。
② 设备树文件:arch/arm/boot/dts/imx6ull-14x14-evk.dtb。
通过编译官方Linux源码得到了Linux内核和设备树文件。Linux内核源码的编译流程是一样的,不同开发板对应的配置文件和设备树文件不一样。因此在移植Linux源码到自己的开发板时需要添加对应的内核配置文件和设备树文件。
在上一节中我们介绍了如何编译Linux内核源码用于NXP的官方测试板,所以我们参考测试板的配置,在Linux内核源码中添加i.MX6UL终结者开发板的相关配置文件。
进入到arch/arm/configs目录下,复制一份imx_v7_mfg_defconfig文件,重命名为imx_topeet_defconfig,将其作为i.MX6UL终结者开发板的内核默认配置文件。命令如下:
cd arch/arm/configs
cp imx_v7_mfg_defconfig imx_topeet_defconfig
以后再次编译内核时执行下列命令来配置i.MX6UL终结者开发板的Linux内核:
make imx_topeet_defconfig
进入到arch/arm/boot/dts目录下,复制一份 imx6ull-14x14-evk.dts,将其重命名为 topeet_emmc_4_3.dts,命令如下:
cd arch/arm/boot/dts
cp imx6ull-14x14-evk.dts topeet_emmc_4_3.dts
注意:i.MX6UL终结者开发板分为emmc和nand flash版本,在本节中以emmc版本为例进行介绍,如果是nand flash版本的开发板,使用cp imx6ull-14x14-evk-gpmi-weim.dts imx6ul_topeet_nand.dts 然后设置屏幕显示为4.3寸,内核移植步骤和emmc版本相同。
创建设备树文件后,还需要修改文件arch/arm/boot/dts/Makefile,添加新创建的设备树文件,这样再次编译时,才会编译设备树文件生成.dtb文件。修改内容如下:
emmc版本如下:
400 dtb-$(CONFIG_SOC_IMX6ULL) += \
401 imx6ull-14x14-ddr3-arm2.dtb \
…
438 imx6ull-9x9-evk-ldo.dtb
439 topeet_emmc_4_3.dtb
nand flash版本如下:
400 dtb-$(CONFIG_SOC_IMX6ULL) += \
401 imx6ull-14x14-ddr3-arm2.dtb \
…
438 imx6ull-9x9-evk-ldo.dtb
439 imx6ul_topeet_nand.dts
在前面两个小节添加了自己开发板对应的内核配置文件和设备树文件后,可以编译Linux内核源码生成镜像文件。命令如下:
make clean
make imx_topeet_defconfig
make -j8
编译完成后,我们会得到两个文件。
① Linux内核镜像文件:arch/arm/boot/zImage。
② 设备树文件:arch/arm/boot/dts/topeet_emmc_4_3.dtb。
注意:当使用新编译生成的zImage和dtb设备树文件下载时,参考镜像烧写章节,需要注意的是下载器中需要烧写不同屏幕尺寸对应的dtb文件,在内核移植测试阶段或者驱动测试阶段,只需要修改topeet_emmc_4_3.dts设备树文件即可,但是下载时其他的文件也要存在,否则不能下载。使用新的topeet_emmc_4_3.dtb文件替换即可。下载需要的dtb文件如图 1.2.3.1所示:
图 1.2.3.1
修改编译好内核后,首先添加一下网卡驱动,方便后面使用。
1、添加pinctrl信息
打开topeet_emmc_4_3.dts设备树文件,首先添加GPIO引脚信息,在开发板上有两个网卡芯片,所以会有两组网卡GPIO引脚信息,内容如下:
309 pinctrl_enet1: enet1grp {
310 fsl,pins = <
311 MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0
312 MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0
313 MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
314 MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
315 MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0
316 MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
317 MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
318 MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031
319 >;
320 };
321
322 pinctrl_enet2: enet2grp {
323 fsl,pins = <
324 MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0
325 MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0
326 MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0
327 MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0
328 MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
329 MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
330 MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0
331 MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
332 MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
333 MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031
334 >;
335 };
上述代码中的pinctrl_enet1和pinctrl_enet2分别是两个网卡信息的pinctrl信息,其实在topeet_emmc_4_3.dts设备树文件中已经存在了,在iomuxc节点下,然后我们需要添加的是两个网卡芯片的复位引脚信息。在iomuxc节点下,内容如下:
337 pinctrl_fec1_reset: fec1_resetgrp {
338 fsl,pins = <
339 MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x79
340 >;
341 };
342
343 pinctrl_fec2_reset: fec2_resetgrp {
344 fsl,pins = <
345 MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x79
346 >;
347 };
两个网卡芯片分别使用了GPIO5_IO07和GPIO5_IO08作为复位引脚。需要我们手动添加。
需要注意的是,引脚功能只能被申请注册一次,所以需要把设备树文件中关于这两个引脚的其他申请信息删除或者注释掉。在设备树文件中搜索这两个引脚,结果图 1.3.1.1:
图 1.3.1.1
发现在pinct_spi4节点中使用到了GPIO5_IO07和GPIO5_IO08,所以需要把这两条语句删除或者注释掉。图 1.3.1.2所示:
图 1.3.1.2
然后还需要注释spi4节点中的内容,因为使用了GPIO5_IO08,如图 1.3.1.3所示:
图 1.3.1.3
2、添加网卡节点信息
修改完pinctrl信息后,需要添加网卡设备信息,在topeet_emmc_4_3.dts设备树文件下,已经存在了网卡的设备节点信息,如下所示;
171 &fec1 {
172 pinctrl-names = "default";
173 pinctrl-0 = <&pinctrl_enet1>;
174 phy-mode = "rmii";
175 phy-handle = <ðphy0>;
176 status = "okay";
177 };
178 &fec2 {
179 pinctrl-names = "default";
180 pinctrl-0 = <&pinctrl_enet2>;
181 phy-mode = "rmii";
182 phy-handle = <ðphy1>;
183 status = "okay";
184
185 mdio {
186 #address-cells = <1>;
187 #size-cells = <0>;
188
189 ethphy0: ethernet-phy@2 {
190 compatible = "ethernet-phy-ieee802.3-c22";
191 reg = <2>;
192 };
193
194 ethphy1: ethernet-phy@1 {
195 compatible = "ethernet-phy-ieee802.3-c22";
196 reg = <1>;
197 };
198 };
199 };
但是上述两个网卡信息不完善,需要添加一些内容,修改后如下所示:
170 &fec1 {
171 pinctrl-names = "default";
172 pinctrl-0 = <&pinctrl_enet1
173 &pinctrl_fec1_reset>;
174 phy-mode = "rmii";
175 phy-handle = <ðphy0>;
176 phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;
177 phy-reset-duration = <200>;
178 status = "okay";
179 };
180
181 &fec2 {
182 pinctrl-names = "default";
183 pinctrl-0 = <&pinctrl_enet2
184 &pinctrl_fec2_reset>;
185 phy-mode = "rmii";
186 phy-handle = <ðphy1>;
187 phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
188 phy-reset-duration = <200>;
189 status = "okay";
190
191 mdio {
192 #address-cells = <1>;
193 #size-cells = <0>;
194
195 ethphy0: ethernet-phy@2 {
196 compatible = "ethernet-phy-ieee802.3-c22";
197 reg = <2>;
198 };
199
200 ethphy1: ethernet-phy@1 {
201 compatible = "ethernet-phy-ieee802.3-c22";
202 reg = <1>;
203 };
204 };
205 };
添加了复位引脚信息。
这样设备树文件就修改完成了,在内核中已经默认配置网卡芯片的驱动了,就不用修改了。然后重新编译设备树文件,使用新的dtb文件启动开发板。
当开发板启动完成后,可以使用ifconfig命令查看当前的网卡信息。如图 1.3.1.4所示:
图 1.3.1.4
发现只有一个eth0设备,说明eth0网卡是默认打开的,使用“ifconfig -a”命令就可以查看所有的网卡设备信息了,结果如图 1.3.1.5所示:
图 1.3.1.5
可以使用下面的命令打开eth1网卡:
ifconfig eth1 up
然后可以使用网线进行测试,看一下是否能够连接网络。如果网卡设备正常,插入网线会有如下信息打印:
图 1.3.1.6
“eth1: link becomes ready”说明eth1网卡正常,同理eth0设备也会有同样的信息。
在开发板上有一个LED灯。我们可以添加驱动来驱动这个LED灯。
1、修改设备树文件
和网卡驱动一样,修改设备树文件分为两步,添加pinctrl信息和led设备节点。
首先添加pinctrl信息,在iomuxc节点下添加如下内容:
pinctrl_gpio_leds: gpio-leds {
fsl,pins = <
MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x17059
>;
};
LED灯设备使用了GPIO1_IO03引脚。
然后添加LED灯的设备节点信息。在根节点“/”下添加如下内容:
1 leds {
2 compatible = "gpio-leds";
3 pinctrl-names = "default";
4 pinctrl-0 = <&pinctrl_gpio_leds>;
5
6 led1{
7 label = "sys-led";
8 gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
9 linux,default-trigger = "heartbeat";
10 default-state = "on";
11 };
12 };
第4行,指定LED设备使用的pinctrl信息。
第9行,指定LED灯的功能是心跳功能。
2、配置内核
在Linux内核中集成了LED灯的驱动文件,根据下面路径配置选项:
Device Drivers —>
-- LED Support —>
<> LED Support for GPIO connected LEDs
选中LED灯的配置,编译内核的时候会自动编译,按空格键选择选中的状态,使此选项前面变为“<*>”,如图 1.3.2.1所示:
图 1.3.2.1
然后重新编译内核和设备树文件,使用新的zImage和dtb文件启动开发板,可以看到LED灯设备以1S的频率闪烁。