开发环境简介
开发板 | 正点原子MINI |
---|---|
操作系统 | Linux-Mint 20.2 |
交叉编译链 | gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf |
UBoot版本 | imx_v2020.04_5.4.70_2.3.0 |
环境搭建
交叉编译链配置
-
下载交叉编译链
linaro官方下载地址:https://releases.linaro.org/components/toolchain/binaries/
文中选用工具链为 gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
-
解压并移动到要安装的目录
# 解压 xz -d gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz tar -vxf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar # 移动到想要安装的目录(这里我选择放到/opt) sudo mv gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf /opt/
-
配置环境
打开环境配置文件:
sudo vim ~/.bashrc
在末尾添加交叉编译器路径:
export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin
更新文件
source ~/.bashrc
-
验证
运行命令:
arm-linux-gnueabihf-gcc -v
出现如图所示即为成功配置编译链
Thread model: posix gcc version 7.5.0 (Linaro GCC 7.5-2019.12)
NXP官方UBoot下载(区别于UBoot官方)
NXP UBoot官方下载地址:https://source.codeaurora.org/external/imx/uboot-imx
# 克隆仓库
git clone https://source.codeaurora.org/external/imx/uboot-imx
# 查看分支
cd uboot-imx
git branch -a
#切换分支 (这里选用imx_v2020.04_5.4.70_2.3.0)
git checkout imx_v2020.04_5.4.70_2.3.0
编译依赖安装
原版UBoot编译测试
# 进入UBootgen目录
cd uboot-imx
# 清理
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
# 加载配置
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig
# 编译
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j8
中间可能会因为缺乏依赖而编译报错,以下是常见错误及解决方案。
-
缺少build-essential编译库
现象:
HOSTCC scripts/basic/fixdep scripts/basic/fixdep.c:106:23: fatal error: sys/types.h: No such file or directory
解决方法:
sudo apt install build-essential
-
在Ubuntu需要过,在Linux-Mint没出现,先贴出来
sudo apt install lsb-core lib32stdc++6 device-tree-compiler
-
占坑留待
…
移植UBoot
文件准备
-
复制生成自己的配置文件(这里取名mx6ull_custom_defconfig,可自定义)
cp configs/mx6ull_14x14_evk_emmc_defconfig configs/mx6ull_custom_defconfig
修改:
vim configs/mx6ull_custom_defconfig
CONFIG_TARGET_MX6ULL_14X14_EVK=y --> CONFIG_TARGET_MX6ULL_CUSTOM=y
CONFIG_SYS_EXTRA_OPTIONS=“IMX_CONFIG=board/freescale/mx6ullevk/imximage.cfg” --> CONFIG_SYS_EXTRA_OPTIONS=“IMX_CONFIG=board/freescale/mx6ull_custom/imximage.cfg”
CONFIG_DEFAULT_DEVICE_TREE=“imx6ull-14x14-evk-emmc” --> CONFIG_DEFAULT_DEVICE_TREE=“imx6ull-custom-emmc”
-
复制头文件
cp include/configs/mx6ullevk.h include/configs/mx6ull_custom.h
修改头文件条件编译宏:
vim include/configs/mx6ull_custom.h
#ifndef __MX6ULL_CUSTOM_CONFIG_H #define __MX6ULL_CUSTOM_CONFIG_H
-
复制设备树
cp arch/arm/dts/imx6ull-14x14-evk.dts arch/arm/dts/imx6ull-custom.dts cp arch/arm/dts/imx6ull-14x14-evk-emmc.dts arch/arm/dts/imx6ull-custom-emmc.dts
修改imx6ull-custom-emmc.dts头文件包含为
#include "imx6ull-custom.dts"
添加到Makefile:
vim arch/arm/dts/Makefile
,修改位置:dtb-$(CONFIG_MX6ULL) += \ imx6ull-14x14-ddr3-val.dtb \ imx6ull-14x14-ddr3-val-epdc.dtb \ imx6ull-14x14-ddr3-val-emmc.dtb \ imx6ull-14x14-ddr3-val-gpmi-weim.dtb \ imx6ull-14x14-ddr3-val-tsc.dtb \ imx6ull-14x14-evk.dtb \ imx6ull-14x14-evk-emmc.dtb \ imx6ull-custom.dtb \ imx6ull-custom-emmc.dtb \ ...
-
复制资源文件夹
cp -rf board/freescale/mx6ullevk/ board/freescale/mx6ull_custom/
进入文件夹并修改 :
cd board/freescale/mx6ull_custom/
-
Makefile
obj-y := mx6ullevk.o--> obj-y := mx6ull_custom.o -
imximage.cfg
PLUGIN board/freescale/mx6ullevk/plugin.bin 0x00907000-> PLUGIN board/freescale/mx6ull_custom/plugin.bin 0x00907000 -
Kconfig
if TARGET_MX6ULL_CUSTOM config SYS_BOARD default "mx6ull_custom" config SYS_VENDOR default "freescale" config SYS_CONFIG_NAME default "mx6ull_custom" config SYS_TEXT_BASE default 0x87800000 endif
-
MAINTAINERS
MX6ULL_CUSTOM BOARD M: Peng Fan <peng.fan@nxp.com> S: Maintained F: board/freescale/mx6ull_custom/ F: include/configs/mx6ull_custom.h F: configs/mx6ull_custom_defconfig
-
mx6ullevk.c
mv mx6ullevk.c mx6ull_custom.c
-
-
添加Makefile编译选项
新版UBoot与旧版不同,大概以17年为界吧。
旧版地址为 arch/arm/cpu/armv7/mx6/Kconfig
新版地址为 arch/arm/mach-imx/mx6/Kconfig
在 config TARGET_MX6ULL_14X14_EVK 语句段下面添加如下:
config TARGET_MX6ULL_CUSTOM bool "Support mx6ull_custom" select BOARD_LATE_INIT select DM select DM_THERMAL select MX6ULL imply CMD_DM
并在文件后面添加:
source "board/freescale/mx6ull_custom/Kconfig"
-
编写编译脚本
回到UBoot根目录,新建build_custom_uboot.sh
#!/bin/bash make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_custom_defconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j8
sh脚本第一行主要是为了防止linux有多个bash解释器,指明要使用哪一个。
编译UBoot
给sh文件添加执行权限并执行
chmod a+x build_custom_uboot.sh
./build_custom_uboot.sh
编译成功后会显示
CAT u-boot-dtb.bin
COPY u-boot.dtb
COPY u-boot.bin
CFGS u-boot-dtb.cfgout
MKIMAGE u-boot-dtb.imx
CFGCHK u-boot.cfg
烧录到SD卡
在UBoot的 board/freescale/mx6ullevk/ 文件里 README 文件里有介绍UBoot的用法
How to use U-Boot on Freescale MX6ULL 14x14 EVK
----------------------------------------------
- First make sure you have installed the dtc package (device tree compiler):
$ sudo apt-get install device-tree-compiler
- Build U-Boot for MX6ULL 14x14 EVK:
$ make mrproper
$ make mx6ull_14x14_evk_defconfig
$ make
This generates the u-boot-dtb.imx image in the current directory.
- Flash the u-boot-dtb.imx image into the micro SD card:
$ sudo dd if=u-boot-dtb.imx of=/dev/sdb bs=1K seek=1 && sync
- Jumper settings:
SW601: 0 0 1 0
Sw602: 1 0
Where 0 means bottom position and 1 means top position (from the switch label
numbers reference).
Connect the USB cable between the EVK and the PC for the console.
(The USB console connector is the one close the push buttons)
Insert the micro SD card in the board, power it up and U-Boot messages should
come up.
The link for the board: http://www.nxp.com/products/microcontrollers-and- \
processors/arm-processors/i.mx-applications-processors/i.mx-6-processors/ \
i.mx6qp/evaluation-kit-for-the-i.mx-6ull-applications-processor:MCIMX6ULL-EVK
-
将SD卡插入到电脑
-
查看电脑是否成功识别SD卡
ls /dev/ | grep sd
sda
sda1
sda2
sdb
sdb1
sdb2
sdc
sdc1
sdd
可以发现当插入SD卡,会多出一个sdd设备(不同的设备会不同)
- 烧录到SD卡
sudo dd if=u-boot-dtb.imx of=/dev/sdd bs=1K seek=1 && sync
上电启动及Bug修改
上电启动
将SD卡插入开发板,打开串口助手,上电。屏幕使用的是800x480 TFT4.3,串口助手打印如下:
U-Boot 2020.04 (Oct 16 2021 - 13:09:27 +0800)
CPU: i.MX6ULL rev1.1 792 MHz (running at 396 MHz)
CPU: Industrial temperature grade (-40C to 105C) at 49C
Reset cause: POR
Model: i.MX6 ULL 14x14 EVK Board
Board: MX6ULL 14x14 EVK
DRAM: 512 MiB
MMC: FSL_SDHC: 0, FSL_SDHC: 1
Loading Environment from MMC... OK
[*]-Video Link 0 (480 x 272)
[0] lcdif@21c8000, video
In: serial
Out: serial
Err: serial
switch to partitions #0, OK
mmc0 is current device
flash target is MMC:0
Net: eth1: ethernet@20b4000 [PRIME]Get shared mii bus on ethernet@2188000
Could not get PHY for FEC1: addr 2
Fastboot: Normal
Normal Boot
Hit any key to stop autoboot: 0
switch to partitions #0, OK
mmc0 is current device
switch to partitions #0, OK
mmc0 is current device
** No partition table - mmc 0 **
** No partition table - mmc 0 **
可以得知:
-
CPU、DRAM、MMC、串口、FLASH正常启动
-
网络启动失败
Net: eth1: ethernet@20b4000 [PRIME]Get shared mii bus on ethernet@2188000
Could not get PHY for FEC1: addr 2
- 屏幕显示出两个NXP logo,分辨率不对
[*]-Video Link 0 (480 x 272)
[0] lcdif@21c8000, video
这些问题是由于参数设置不当导致的,对于旧版只需要在/board/freescale/mx6ull_custom/mx6ull_custom.c
中修改,在新版中参数设置都在设备树中设置。
LCD修改
根据对imx6ull-custom-emmc.dts文件的头文件包含查找,会在imx6ul-14x14-evk.dtsi找到描述
&lcdif {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lcdif_dat
&pinctrl_lcdif_ctrl>;
display = <&display0>;
status = "okay";
display0: display@0 {
bits-per-pixel = <24>;
bus-width = <24>;
display-timings {
native-mode = <&timing0>;
timing0: timing0 {
clock-frequency = <9200000>;
hactive = <480>;
vactive = <272>;
hfront-porch = <8>;
hback-porch = <4>;
hsync-len = <41>;
vback-porch = <2>;
vfront-porch = <4>;
vsync-len = <10>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <1>;
pixelclk-active = <0>;
};
};
};
};
根据具体使用的LCD参数进行修改,本人懒狗,就只修改clock-frequency、hactive、vactive了(不正常就老老实实查手册吧)。
clock-frequency = <25000000>;
hactive = <800>;
vactive = <480>;
网卡设置
正点原子使用PHY的是LAN8720,在某些平台初始化需要复位,所有修改会有点多。
-
设置复位引脚
正点原子开发板的ENET1 复位引脚 ENET1_RST 连接在 I.M6ULL 的 SNVS_TAMPER7 ,ENET2的复位引脚 ENET2_RST 连接在 I.MX6ULL 的 SNVS_TAMPER8 。MINI只有一个网口,ENET2。
在设备树描述中可以发现这两个脚与SPI4冲突,修改方法如下:
pinctrl_spi4: spi4grp { fsl,pins = < MX6UL_PAD_BOOT_MODE0__GPIO5_IO10 0x70a1 MX6UL_PAD_BOOT_MODE1__GPIO5_IO11 0x70a1 /* MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x70a1 MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x80000000 */ >; };
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>;
-
添加复位引脚(也可以直接添加在pinctrl_enetx: enetxgrp):
&iomuxc { pinctrl-names = "default"; ... pinctrl_enet1_reset: enet1rstgrp{ fsl,pins = < MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x10B0 >; }; pinctrl_enet2_reset: enet2rstgrp{ fsl,pins = < MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x10B0 >; }; ... };
-
修改时钟频率:
pinctrl_enet1: enet1grp { fsl,pins = < ... MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b009 >; }; pinctrl_enet2: enet2grp { fsl,pins = < ... MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b009 >; };
-
修改FEC节点属性:
&fec1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_enet1 &pinctrl_enet1_reset >; // phy-mode = "rmii"; phy-handle = <ðphy0>; phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>; // 复位引脚 phy-reset-duration = <200>; //复位时间 status = "disable"; // 禁用 }; &fec2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_enet2 &pinctrl_enet2_reset >; // phy-mode = "rmii"; phy-handle = <ðphy1>; phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>; // 复位引脚 phy-reset-duration = <200>; //复位时间 status = "okay"; mdio { #address-cells = <1>; #size-cells = <0>; ethphy0: ethernet-phy@0 { // 修改PHY地址 reg = <0>; // smsc,led-mode = <1>; // LAN8720属于SMSC公司 clocks = <&clks IMX6UL_CLK_ENET_REF>; clock-names = "rmii-ref"; }; ethphy1: ethernet-phy@1 { reg = <1>; smsc,led-mode = <1>; clocks = <&clks IMX6UL_CLK_ENET2_REF>; clock-names = "rmii-ref"; }; }; };
-
编译启动测试
此时编译启动可以发现网口还是不能正常使用
Net: Error: ethernet@20b4000 address not set. Error: ethernet@20b4000 address not set. No ethernet found.
到 configs/mx6ull_custom_defconfig 文件,使能随机生成MAC地址(最好在UBoot里手动设置固定MAC):
CONFIG_NET_RANDOM_ETHADDR=y
再次编译启动
Net: Warning: ethernet@20b4000 (eth1) using random MAC address - 7e:61:8b:1f:97:b9 eth1: ethernet@20b4000 [PRIME]
-
Ping测试
UBoot启动过程打断进入命令行模式,设置网络参数
setenv ipaddr 192.168.0.123 // 设置开发板IP地址 // setenv ethaddr xx:xx:xx:xx:xx:xx // 设置开发板MAC地址 setenv gatewayip 192.168.0.1 // 设置开发板默认网关 setenv netmask 255.255.255.0 // 设置开发板子网掩码 setenv serverip 192.168.0.1 // 设置服务器地址 saveenv // 保存设置 print // 打印设置信息
重启开发板,打印信息如下:
=> ping 192.168.0.1 Using ethernet@20b4000 device ARP Retry count exceeded; starting again ping failed; host 192.168.0.1 is not alive
测试失败,原因可能是LAN8720初始化需要重启,修改SMSC驱动。
在 drivers/net/phy/phy.c 文件中修改:
int genphy_config_aneg(struct phy_device *phydev) { int result; /* SOFT RESET */ phy_reset(phydev); ... }
再次编译启动,Ping成功。
=> ping 192.168.0.1 Using ethernet@20b4000 device host 192.168.0.1 is alive
到此,UBoot的移植工作完成。
附加
- 对于UBoot的环境设置是设置在MMC中的,不会随着UBoot重新编译而清除,如果修改乱了可以使用如下命令恢复默认:
env default -a // 恢复默认设置
saveenv // 将改变覆盖到MMC
- 使能随机MAC地址生成,会使UBoot每次启动都会随机生成MAC地址,UBoot环境参数会被使能,也就导致在UBoot里每次IP都不固定,实际使用请使能这个参数并在UBoot里手动设置。