备注:本文以正点原子imx6ull芯片Alpha开发板为例。参考《正点原子嵌入式linux驱动开发指南V1.4.pdf》整理的笔记。
该步骤的作用是:测试源码是否可以正常编译,如果可以确定自己的源码能够正常编译通过无误,则可以跳过此步骤
ARM芯片官网下载对应的U-BOOT,并解压
tar -vxjf uboot-imx-2016.03-2.1.0-g8b546e4.tar.bz2
下表格为常用目录,以及后续修改配置需要打交道的文件夹及含义
目录 | 含义 |
---|---|
configs | 各种芯片型号的配置文件均在此文件夹下,根据自己使用的芯片有对应的配置文件 比如: imx6ull对应的配置文件名称为:mx6ull_xxxx_defconfig 其中: 当板卡为emmc启动方式时使用配置文件mx6ull_14x14_evk_emmc_defconfig 当板卡为nand启动方式时使用配置文件mx6ull_14x14_evk_nand_defconfig |
include/configs | 头文件 |
board/freescale | 板级文件 |
安装依赖库
sudo apt-get install libncurses5-dev
u-boot根目录下编写shell编译脚本
vim mx6ull_14x14_emmc.sh
文件中写入如下内容:
因为我是用的开发板是emmc启动板卡,所以第二条命令使用配置文件mx6ull_14x14_evk_emmc_defconfig
#!/bin/bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16
赋予脚本可执行权限
chomd 777 mx6ull_14x14_emmc.sh
执行脚本,编译u-boot
./mx6ull_14x14_emmc.sh
编译完成后终端显示如下镜像信息
......
fg.cfgtmp board/freescale/mx6ullevk/imximage.cfg
./tools/mkimage -n board/freescale/mx6ullevk/imximage.cfg.cfgtmp -T imximage -e 0x87800000 -d u-boot.bin u-boot.imx
Image Type: Freescale IMX Boot Image
Image Ver: 2 (i.MX53/6/7 compatible)
Mode: DCD
Data Size: 425984 Bytes = 416.00 kB = 0.41 MB
Load Address: 877ff420
Entry Point: 87800000
修改源码,作用其实是将源码中跟自己板卡最接近的平台的【配置文件】和【头文件】和【板级文件】拷贝一份重命名为自己板卡的对应文件,然后修改里面的源码,在进行编译生成zImage/rootfs等文件。
这里阿尔法开发板芯片为imx6ull,emmc启动方式,所以在后续拷贝文件时,NXP官方evk开发板与阿尔法开发板最为类似,故,拷贝文件名形如【mx6ull_14x14_evk_emmc_xxx】,命名为自己板卡【mx6ull_alientek_emmc_xxx】
拷贝类似平台配置文件,重名民为自己的平台配置文件
cd configs
cp mx6ull_14x14_evk_emmc_defconfig mx6ull_alientek_emmc_defconfig
修改配置文件
将第1行和第4行的mx6ullevk修改为mx6ull_alientek_emmc
vim mx6ull_alientek_emmc_defconfig
修改为如下内容:
CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6ull_alientek_emmc/imximage.cfg,MX6ULL_EVK_EMMC_REWORK"
CONFIG_ARM=y
CONFIG_ARCH_MX6=y
CONFIG_TARGET_MX6ULL_ALIENTEK_EMMC=y
CONFIG_CMD_GPIO=y
拷贝类似平台头文件,重命名为自己平台头文件
cd {
uboot顶层目录}
cd include/configs/ #注意:二级子目录是:【configs】,不是【config】!!!
cp mx6ullevk.h mx6ull_alientek_emmc.h
打开头文件
vim mx6ull_alientek_emmc.h
修改ifndef头文件声明中的名字
#ifndef __MX6ULLEVK_CONFIG_H
#define __MX6ULLEVK_CONFIG_H
修改为:
#ifndef __MX6ULL_ALIENTEK_EMMC_CONFIG_H
#define __MX6ULL_ALIENTEK_EMMC_CONFIG_H
在文件前面的include引用模块增加头文件引用
该头文件中相对于mx6ull_alientek_emmc.h 中有更多的配置功能或命令
#include "mx6_common.h"
头文件其他内容解析
备注:mx6ull_alientek_emmc.h 里面有很多宏定义,这些宏定义基本用于配置 uboot,也有一些I.MX6ULL 的配置项目。如果我们自己要想使能或者禁止 uboot 的某些功能,那就在mx6ull_alientek_emmc.h 里面做修改即可。
以下为mx6ull_alientek_emmc.h文件内容大致功能解析。(参考:《正点原子嵌入式linux驱动开发指南V1.4.pdf》)
第 29~39 行,设置 DRAM 的大小
第 50 行,定义宏 CONFIG_DISPLAY_CPUINFO, uboot 启动的时候可以输出 CPU 信息。
第 51 行,定义宏 CONFIG_DISPLAY_BOARDINFO, uboot 启动的时候可以输出板子信息。
第 54 行, CONFIG_SYS_MALLOC_LEN 为 malloc 内存池大小,这里设置为 16MB。
第 59、60 行,使能 I.MX6ULL 的串口功能,宏 CONFIG_MXC_UART_BASE 表示串口寄存器基地址,
这里使用的串口1,基地址为UART1_BASE,
UART1_BASE定义在文件arch/arm/include/asm/arch-mx6/imx-regs.h中,
imx-regs.h是I.MX6ULL寄存器描述文件,
根据imx-regs.h可得到UART1_BASE的值如下:(备注:该值可以在imx6ull手册中查询到)
UART1_BASE= (ATZ1_BASE_ADDR + 0x20000)
=AIPS1_ARB_BASE_ADDR + 0x20000
=0x02000000 + 0x20000
=0X02020000
第 63、64 行, EMMC接在I.MX6ULL的USDHC2上,
宏 CONFIG_SYS_FSL_ESDHC_ADDR 为EMMC所使用接口的寄存器基地址,也就是 USDHC2 的基地址。
第 224 行,宏 CONFIG_SYS_LOAD_ADDR 表示 linux kernel 在 DRAM 中的加载地址,
也就是 linux kernel 在 DRAM 中的存储首地址, CONFIG_LOADADDR=0X80800000。
第 225 行,宏 CONFIG_SYS_HZ 为系统时钟频率,这里为 1000Hz。
第 227 行,宏 CONFIG_STACKSIZE 为栈大小,这里为 128KB
第 230 行,宏 CONFIG_NR_DRAM_BANKS 为 DRAM BANK 的数量,
I.MX6ULL 只有一个 DRAM BANK,我们也只用到了一个 BANK,所以为 1。
第 256 行,宏CONFIG_SYS_MMC_ENV_DEV为默认的MMC设备, 这里默认为USDHC2,也就是 EMMC。
第 258 行,宏CONFIG_MMCROOT设置进入linux系统的根文件系统所在的分区,
这里设置为 "/dev/mmcblk1p2",也就是 EMMC 设备的第 2 个分区。
第 0 个分区保存 uboot,
第 1 个分区保存 linux 镜像和设备树,
第 2 个分区为 Linux 系统的根文件系统。
第 331 行的宏 CONFIG_FEC_ENET_DEV 指定 uboot 所使用的网口。
I.MX6ULL 有两个网口,为 0 的时候使用 ENET1,为 1 的时候使用 ENET2。
宏 IMX_FEC_BASE 为 ENET 接口的寄存器首地址,
宏 CONFIG_FEC_MXC_PHYADDR 为网口 PHY 芯片的地址。
宏 CONFIG_FEC_XCV_TYPE 为PHY芯片所使用的接口类型,
I.MX6U-ALPHA 开发板的两个PHY都使用的 RMII 接口。
该文件中,其中以 CONFIG_CMD 开头的宏都是用于使能相应命令的,其他的以 CONFIG 开头的宏都是完成一些配置功能的。以后会频繁的和mx6ull_alientek_emmc.h 这个文件打交道。
拷贝板级文件夹,重命名为自己的开发板对应文件夹
cd {
u-boot顶层目录}
cd board/freescale/
cp mx6ullevk mx6ull_alientek_emmc -rf
cd mx6ull_alientek_emmc
修改文件名
mv mx6ullevk.c mx6ull_alientek_emmc.c
修改同目录下Makefile文件内容
vim Makefile
修改第六行文件名为自己板卡文件名
obj-y := mx6ull_alientek_emmc.o
修改同目录下imximage.cfg 文件
vim imximage.cfg
将imximage.cfg 文件中的
PLUGIN board/freescale/mx6ullevk/plugin.bin 0x00907000
修改为
PLUGIN board/freescale/mx6ull_alientek_emmc/plugin.bin 0x00907000
修改同目录下Kconfig 文件
删除Kcofig原有内容,复制如下内容:
if TARGET_MX6ULL_ALIENTEK_EMMC
config SYS_BOARD
default "mx6ull_alientek_emmc"
config SYS_VENDOR
default "freescale"
config SYS_SOC
default "mx6"
config SYS_CONFIG_NAME
default "mx6ull_alientek_emmc"
endif
修改同目录下MAINTAINERS 文件
删除MAINTAINERS原有内容,复制如下内容(其实就是修改了板卡名字)
MX6ULLEVK BOARD
M: Peng Fan <peng.fan@nxp.com>
S: Maintained
F: board/freescale/mx6ull_alientek_emmc/
F: include/configs/mx6ull_alientek_emmc.h
F: configs/mx6ull_14x14_evk_defconfig
F: configs/mx6ull_9x9_evk_defconfig
修改u-boot图形界面配置文件
cd [U-BOOT根目录]
cd arch/arm/cpu/armv7/mx6/
vim Kconfig
在207行加入:
config TARGET_MX6ULL_ALIENTEK_EMMC
>---bool "Support mx6ull_alientek_emmc"
>---select MX6ULL
>---select DM
>---select DM_THERMAL
再在最后一样endif之前加上:
source "board/freescale/mx6ull_alientek_emmc/Kconfig"
Uboot启动时开发板名称可以在这里修改,也可以在这里加入一些自己需要的LOG(可选)
vim board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c
第798行,int checkboard(void)函数中有开发板的名字。
puts("Board: MX6ULL 14x14 EVK\n");
U-Boot移植一般必须要解决的驱动有串口、网口、EMMC/NAND、SD卡等,网络驱动修改后续再进行补充,可查阅正点原子《嵌入式驱动开发指南》—>《U-Boot》章节 —>《在U-Boot中添加自己的开发板》小节 —> 《网络驱动修改》小节查阅具体步骤。
新建编译脚本文件
cd [U-BOOT根目录]
vim mx6ull_alientek_emmc.sh
加入如下内容:
#!/bin/bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_alientek_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16
执行脚本,进行U-BOOT编译
chmod 777 mx6ull_alientek_emmc.sh
./mx6ull_alientek_emmc.sh
成功编译完成后,终端显示如下
注意:编译完成后会在U-Boot根目录下生成u-boot.bin文件,该bin文件就是我们需要烧写到SD卡中的引导文件
...
./tools/mkimage -n board/freescale/mx6ull_alientek_emmc/imximage.cfg.cfgtmp -T imximage -e 0x87800000 -d u-boot.bin u-boot.imx
Image Type: Freescale IMX Boot Image
Image Ver: 2 (i.MX53/6/7 compatible)
Mode: DCD
Data Size: 425984 Bytes = 416.00 kB = 0.41 MB
Load Address: 877ff420
Entry Point: 87800000
检查添加的mx6ull_alientek_emmc.h头文件是否被引用
编译完成之后,在终端输入:
grep -nR "mx6ull_alientek_emmc.h"
若出现很多文件都引用了mx6ull_alientek_emmc.h 这个头文件,则表示新板卡添加成功。
终端执行命令
ls /dev/sd*
插上SD卡后,再执行上述命令看多出来的SD卡序号是多少,我这里是/dev/sdb 和 /dev/sdb1,1表示分区一,后面使用/dev/sdb即可。
使用工具imxdownload 将 u-boot.bin 烧写到SD卡
cd [u-boot根目录]
cp [工具imxdownload路径]/imxdownload [u-boot根目录]
imxdownload u-boot.bin /dev/sdb
将SD卡插入开发板,开发上电直接敲击任意按键进入U-Boot
U-boot启动后,命令行左侧会出现一个“=>”标志。
U-boot启动过程中,屏幕上(串口)会打印一些U-boot信息,包含时间、版本、网络等。
常用命令
printenv
setenv setenv ipaddr xxx
setenv serveraddr xxx
setenv bootdelay 5
...
saveenv
ping
tftp
nfs
其他命令
help
echo
run
mmc相关命令
mmc list #sd卡和emmc驱动检查
mmc dev 0 #选择mmc设备0
mmc info #打印mmc0设备的设备信息
mmc dev 1 #选择mmc设备1
mmc info #打印mmc1设备的设备信息
怎么确定u-boot编译命令该用什么命令?命令所带参数都从哪来?
#!/bin/bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_alientek_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16
解答:
参数 | 含义 |
---|---|
mx6ull_14x14_ddr512_emmc_defconfig | 来自u-boot源码中configs目录中的配置文件名。 半导体厂商出场的时候为了简化开发人员的开发难度,会配置很多开发板的一套默认配置,在configs目录下,对应的芯片使用对应的配置文件即可。 |
-j12 | 表示12个线程都进行编译,一般系统支持几核几线程线程可以根据需要设置,满线程时,编译速度最快。 |
V=1 | 在终端中输出短命令虽然看起来很清爽,但是不利于分析uboot的编译过程。可以通过设置变量“V=1“来实现完整的命令输出 |
当U-Boot移植完成以后,下一步就要进行内核移植了。内核移植过程中,如果采用tftp服务器和nfs服务器挂载文件系统的话,则需要在U-Boot中配置环境变量【bootcmd】和【bootargs】的值,这样U-Boot才能识别去哪里下载zImage文件、dtb文件、以及在哪里查找文件系统等。具体两个参数的值设置方法分别在前面的博客【搭建TFTP服务器】和【搭建NFS服务器】文章末尾有介绍。此处仍旧做个记录。
配置环境变量【bootcmd】和【bootargs】步骤如下:
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000'
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs rw nfsroot=192.168.0.250:/home/lsy/tools/nfs/rootfs ip=192.168.0.100:192.168.0.250:192.168.0.1:255.255.255.0::eth0:off'
save
然后重启板卡,U-Boot就会根据配置好的参数,到指定服务器IP地址中寻找zImage文件、dtb文件以及文件系统了。