Linux 系统要启动就必须需要一个 bootloader 程序,比如 U-Boot、 vivi、 RedBoot 等
等,其中以 U-Boot 使用最为广泛,为了方便书写,本文会将 U-Boot 写为 uboot。这段bootloader程序会先初始化DDR等外设,然后将Linux内核从flash(NAND,
NOR FLASH, SD, MMC 等)拷贝到 DDR 中,最后启动 Linux 内核。
ftp://ftp.denx.de/pub/u-boot/
主要被半导体产商使用,移植到自家芯片。
在半导体产商官网下载如NXP等,适配NXP官方开发板。
由开发板厂商提供,在半导体产商提供的uboot基础上修改,适配自家的开发板。
sudo apt-get install libncurses5-dev
#!/bin/bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean #清理
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- xxx_defconfig #配置
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j12 #编译
.imx文件是在.bin文件前添加一些头信息构成的。主要有:
IVT(Image Vector table): IVT里面包含了一系列的地址信息,比较重要的如链接地址。
Boot data: 启动数据,包含了镜像要拷贝到哪个地址,拷贝的大小是多少等等
DCD(Device configuration data): 设备配置信息,重点是 DDR3 的初始化配置
.bin: 用户代码可执行文件
具体见:正点原子手册V3 P324
可以通过SD卡启动或烧写金EMMC启动。主要测试SD卡驱动、EMMC驱动、LCD驱动、网络驱动。
copy板级文件目录
cd board/freescale/
cp mx6ullevk/ -r mx6ull_ht
修改目录下.c文件命名
cd mx6ull_ht
mv mx6ullevk.c mx6ull_ht.c
修改目录下的Makefile
obj-y :=mx6ull_ht.o #将修改命名的.c文件编译进去
修改目录下的imximag.cfg
PLUGIN board/freescale/mx6ullevk/plugin.bin 0x00907000 修改为 PLUGIN board/freescale/mx6ull_ht /plugin.bin 0x00907000
修改目录下的Kconfig
if TARGET_MX6ULL_HT
config SYS_BOARD
default "mx6ull_ht"
config SYS_VENDOR
default "freescale"
config SYS_SOC
default "mx6"
config SYS_CONFIG_NAME
default "mx6ull_ht"
endif
修改U-Boot图形界面配置文件
#在 arch/arm/cpu/armv7/mx6/Kconfig 中添加
config TARGET_MX6ULL_HT
bool "Support mx6ull_ht"
select MX6ULL
elect DM
select DM_THERMAL
#在endif前添加Kconfig源
source "board/freescale/mx6ull_ht/Kconfig"
cd configs
cp mx6ull_14x14_evk_emmc_defconfig mx6ull_ht_defconfig
#修改xmx6ull_ht_defconfig
CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6ull_ht/imximage.cfg,MX6ULL_EVK_EMMC_REWORK" #路径改成自己的板级文件夹
CONFIG_ARM=y
CONFIG_ARCH_MX6=y
CONFIG_TARGET_MX6ULL_HT=y #这一项主要控制Kconfig文件,要与Kconfig中的宏一致
CONFIG_CMD_GPIO=y
cp include/configs/mx6ullevk.h mx6ull_ht.h
#修改.h的重复检测宏
#ifndef __MX6ULL_HT_CONFIG_H
#define __MX6ULL_HT_CONFIG_H
#剩下的就是uboot功能的配置和裁剪
L14 添加头文件mx6_common.h也包含部分配置项
L29-L39 根据板子类型设置DRAM的大小
L50 定义宏CONFIG_DISPLAY_CPUINFO,uboot启动可以输出CPU信息。
L51 定义宏 CONFIG_DISPLAY_BOARDINFO,uboot启动可以输出板子信息.
L54 CONFIG_SYS_MALLOC_LEN,配置内存池大小。
L56 定义宏CONFIG_BOARD_EARLY_INIT_F,board_init_f可以调用board_early_init_f。
L57 定义宏CONFIG_BOARD_LATE_INIT,board_init_r可以调用board_early_init_r。
L59 定义宏CONFIG_MXC_UART,使能串口功能。
L60 CONFIG_MXC_UART_BASE,配置串口寄存器基地址。
L63 CONFIG_FSL_USDHC,EMMC使能,EMMC接在I.MX6ULL的USDHC2上。
L64 CONFIG_SYS_FSL_ESDHC_ADDR,配置EMMC使用接口寄存器的基地址。
L67-L2 NAND与USDHC2的引脚冲突,如果使用NAND则只能有一个USDHC设备(SD卡),否则两个。
L75-81 控制I2C使能与速度
L92-96 NAND分区设置
L98-111 CONFIG_MFG_ENV_SETTINGS定义了使用Mfgtool烧录时使用的一系列环境变量。
L113-202 COFIG_EXTRA_ENV_SETTING后面需要使用的设置一些环境变量。
L204-217 CONFIG_BOOTCOMMAND设置bootcmd的值。
L220-222 使能memtest并设置memtest的内存起始地址和内存大小。
L224 CONFIG_SYS_LOAD_ADDR,设置linux内核再DRAM中的加载地址。
L225 CONFIG_SYS_HZ,配置系统的时钟频率。单位HZ
L227 CONFIG_STACKSIZE,配置栈大小。
L230 CONFIG_NR_DRAM_BANKS,配置DRAM BANK的数量。
L231 PHYS_SDRAM,配置DRAM控制器MMDC0所管辖的DRAM起始地址。
L233 CONFIG_SYS_SDRAM_BASE,配置DRAM的起始地址。
L234 CONFIG_SYS_INIT_RAM_ADDR,配置IMX6ULL内部的IRAM的起始地址。
L235 CONFIG_SYS_INIT_RAM_SIZE,配置IRAM的大小。
L256 CONFIG_SYS_MMC_ENV_DEV,配置默认的MMC设备。
L257 CONFIG_SYS_MMC_ENV_PART,配置默认分区。
L258 CONFIG_MMCROOT,配置进入linux系统的根文件系统所在的分区,"/dev/mmcblk1p2"代表EMMC设备分区2,第0个分区保存uboot,第一个分区保存linux镜像和设备树,第二个分区为linux系统的根文件系统。
L325~342 与网络有关的宏。使能dhcp,ping等命令。CONFIG_FEC_ENET_DEV制度uboot使用的网口。IMX_FEC_BASE,配置网口基地址。CONFIG_FEC_MXC_PHYADDR,配置PHY芯片地址。CONFIG_FEC_XCV_TYPE,配置接口类型。
L344~END 配置宏。CONFIG_VIDEO开启LCD功能。CONFIG_VIDEO_LOGO使能LOGO显示。CONFIG_CMD_BMP 使能 BMP
图片显示指令。其中L345 CONFIG_PHY_MICREL表示使能Micrel公司的PHY驱动,对标的还有CONFIG_PHY_SMSC,SMSC公司的网络驱动如LAN8720A。
一般 uboot 中修改驱动基本都是在上文修改的 imx6ull_ht.h 和 imx6ull_ht.c 这两个文件中进行的。
bootcmd保存着uboot默认命令,主要是调用一些环境变量,环境变量默认值定义再include/env_default.h
bootcmd默认值:文件imx6ull_ht.h中
#define CONFIG_BOOTCOMMAND \
"run findfdt;" \ #findfdt是NXP自定义的环境变量,用来查找开发板对应的设备树文件,并设为环境变量fdt_file
"mmc dev ${mmcdev};" \ #切换mmc设备,这里mmcdev是1,就是EMMC.
"mmc dev ${mmcdev}; if mmc rescan; then " \ #判断能否检测到sd卡或者emmc
"if run loadbootscript; then " \ #如果检测到mmc,再判断能否运行loadbootscript(script文件是否存在)
"run bootscript; " \ #存在则运行boot脚本
"else " \ #否则
"if run loadimage; then " \ #判断能否运行loadimage(是否存在{zImage})
"run mmcboot; " \ #存在zImage运行mmcboot(从emmc启动)
"else run netboot; " \ #否则运行netboot
"fi; " \
"fi; " \
"else run netboot; fi" #检测不到mmcdev则从网络启动,运行netboot环境变量
#进一步解析:将环境变量都拆开,成功从emmc启动的命令如下:
mmc dev 1; fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-14x14-evk.dtb; bootz 0x80800000 - 0x83000000
mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}
#拆开后
mmcargs=setenv bootargs console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
setenv bootcmd 'mmc dev 1; fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull_ht.dtb; bootz 80800000 - 83000000;'
saveenv
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-ht.dtb; bootz 80800000 - 83000000'
saveenv
printenv
setenv
saveenv
md[.b, .w, .l] address [# of objects]
nm [.b, .w, .l] address
mm [.b, .w, .l] address
mw [.b, .w, .l] address value [count]
cp [.b, .w, .l] source target count
cmp [.b, .w, .l] addr1 addr2 count
setenv ipaddr 192.168.1.50 #开发板ip
setenv ethaddr 00:04:9f:04:d2:35
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
setenv serverip 192.168.1.250
saveenv
ping 192.168.1.250
dhcp
nfs [loadAddress] [[hostIPaddr:]bootfilename]
nfs 80800000 192.168.1.250:/home/ht/imx6ull/nfs/zImage
tftpboot [loadAddress] [[hostIPaddr:]bootfilename]
tftp 80800000 zImage
md[.b, .w, .l] address [# of objects]
nm [.b, .w, .l] address
mm [.b, .w, .l] address
mw [.b, .w, .l] address value [count]
cp [.b, .w, .l] source target count
cmp [.b, .w, .l] addr1 addr2 count
mmc info #当前选中的mmc信息
mmc rescan #扫描所有mmc
mmc list #查看当前开发板一共有几个 MMC 设备
mmc dev [dev] [part] #[dev]用来设置要切换的 MMC 设备号, [part]是分区号(默认0)。
mmc part #查看其分区
saveenv
ping 192.168.1.250
dhcp
nfs [loadAddress] [[hostIPaddr:]bootfilename]
nfs 80800000 192.168.1.250:/home/ht/imx6ull/nfs/zImage
tftpboot [loadAddress] [[hostIPaddr:]bootfilename]
tftp 80800000 zImage
mmc read addr blk# cnt
mmc write addr blk# cnt
mmc erase blk# cnt
sudo apt-get install build-essential
sudo apt-get install libncurses5-dev
.config文件保存着uboot的配置项;Kconfig文件是图形界面的描述文件,也就是描述图形界面应该有什么内容
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_ht_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
#谨慎使用make clean,因为会清理掉.config文件,而menuconfig文件是读取.config文件的。
mainmenu "U-Boot $UBOOTVERSION Configuration" #主菜单名字
source "xxx/Kconfig" #xxx为具体目录名,相对路径
menu General setup
....
endmenu
#顶层Kconfig
config LOCALVERSION
string "Local version - append to U-Boot release"
help
...
config LOCALVERSION_AUTO
bool "Automatically append version information to the version string"
default y
help
...
# 变量类型:bool、tristate、string、hex、int
bool:有y和n两个值,y表示配置该项。
tristate:有y、n、m三个值,m表示编译成模块。
string:表示字符串类型。此处显示标题
help:按h出来的提示
default y:默认为y
#arch/Kconfig
config SYS_GENERIC_BOARD
bool
depends on HAVE_GENERIC_BOARD
config ARC
bool "ARC architecture"
select HAVE_PRIVATE_LIBGCC
select HAVE_GENERIC_BOARD
select SYS_GENERIC_BOARD
select SUPPORT_OF_CONTROL
depends on:说明SYS_GENERIC_BOARD依赖于HAVE_GENERIC_BOARD,只有后者被选中才能被选中。
select:方向依赖,当ARC被选择,则下面4个也被选中。
#arch/Kconfig
choice
config
...
config
...
...
endchoice
#提供一组可选择项,供用户单选或多选,如架构。
menuconfig MODULES
bool "菜单"
if MODULES
...
endif # MODULES
#产生一个带选项的菜单,被选择后才会产生
在选项下产生注释