uboot初次编译:
首先在 Ubuntu 中安装 ncurses 库, 否则编译会报错
sudo apt-get install libncurses5-dev
初次编译先清理工程、配置uboot、编译uboot,可以写一个shell脚本
#!/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 (12核编译)
上述脚本解释:
1. make clean 清除之前编译的可执行文件及配置文件。make distclean要清除所有生成的文件。
2. uboot 是 bootloader 的一种,可以用来引导 Linux,但是 uboot 除了引导 Linux 以外还可以引导其它的系统,而且 uboot 还支持其它的架构和外设,比如 USB、 网络、 SD 卡等。这些都是可以配置的,需要什么功能就使能什么功能。所以在编译uboot前,需要先进行配置,配置编译哪些外设、功能、架构、配置需要引导什么系统、什么芯片等等。xxx_defconfig文件在uboot/configs目录中
3. V=1 用于设置编译过程的信息输出级别,-j用来配置几核编译
uboot命令使用
进入 uboot 的命令行模式以后输入“help”或者“?”,即可查看当前 uboot 所支持的命令有哪些;想查看命令的具体用法,输入 ? boot 或者(help boot)就可以查看boot命令的用法
1.信息查询命令
常用的信息查询命令有三个:bdinfo print version
bdinfo查看板子信息 print查看环境变量 version查看uboot的版本号
2.环境变量操作命令
环境变量操作命令常用setenv和saveenv
比如要将环境变量 bootdelay 改为 5
setenv bootdelay 5
saveenv
当我们使用命令 saveenv 保存修改后的环境变量的话会有保存过程提示信息,根据提示可以看出环境变量保存到了 MMC(1)中,也就是 EMMC 中。
有时候我们修改的环境变量值可能会有空格, 比如 bootcmd、 bootargs 等, 这个时候环境变量值就得用单引号括起来
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
saveenv
新建环境变量:
setenv author glj saveenv
删除环境变量:要删除一个环境变量只要给这个环境变量赋空值即可 (把glj三个字母去掉就是删除环境变量了)
3.内存操作命令
常用的内存操作命令有:md、nm、mm、mw、cp
md:
md 命令用于显示内存值,格式如下:
md[.b, .w, .l] address [# of objects]
命令中的[.b .w .l]对应 byte、 word 和 long,也就是分别以 1 个字节、 2 个字节、 4 个字节来显示内存值。 address 就是要查看的内存起始地址, [# of objects]表示要查看的数据长度,这个数据长度单位不是字节,而是跟你所选择的显示格式有关。
特别注意:uboot 命令中的数字都是十六进制的!不是十进制的!
比如你想查看以 0X80000000 开始的 20 个字节的内存值
md.b 80000000 14
另外关于.b .w .l 参数读取的区别
nm:
nm 命令用于修改指定地址的内存值
nm [.b, .w, .l] address
80000000 表示现在要修改的内存地址, ffffff00 表示地址 0x80000000 现在的数据,?后面就可以输入要修改后的数据0x12345678,输入完成以后按下回车,然后再输入‘q’即可退出
mm:
mm和nm一样,也是修改指定地址内存值的,但 mm 修改内存值的时候地址会自增
比如以.l 格式修改从地址 0x80000000 开始的连续 3 个内存块 (3*4=12个字节) 的数据为 0X05050505
mw:
mw 用于使用一个指定的数据填充一段内存
mw [.b, .w, .l] address value [count]
比如使用.l 格式将以 0X80000000 为起始地址的 0x10 个内存块(0x10 * 4=64 字节)填充为 0X0A0A0A0A
mw.l 80000000 0A0A0A0A 10
cp 命令
数据拷贝命令,将 DRAM 中的数据从一段内存拷贝到另一段内存
cp [.b, .w, .l] source target count
将 0x80000000 处的地址拷贝到 0X80000100 处,长度为 0x10 个内存块(0x10 * 4=64 个字节)
cp.l 80000000 80000100 10
4.网络操作命令
主要有三个,ping nfs tftp
uboot 是支持网络的,我们在移植 uboot 的时候一般都要调通网络功能,因为在移植 linux kernel 的时候需要使用到 uboot 的网络功能做调试
首先需要设置ip地址
setenv ipaddr 192.168.1.50
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命令:注意!只能在 uboot 中 ping 其他的机器,其他机器不能 ping uboot,因为 uboot 没有对 ping命令做处理,如果用其他的机器 ping uboot 的话会失败!
nfs:为何使用nfs?像stm32是烧写代码到内部的flash中,有ide很方便,但嵌入式linux一般烧写到nand、mmc中,没有专门的IDE可以烧写到外部存储器,虽然半导体厂商会提供一个烧写软件,但是使用复杂,烧写速度很慢。
关于nfs和tftp的具体使用,查看NFS、TFTP使用方法
5.EMMC和SD卡命令
uboot 支持 EMMC 和 SD 卡,因此也要提供 EMMC 和 SD 卡的操作命令。
主要有 mmc info mmc read mmc write mmc dev mmc list mmc rescan mmc part
mmc info用于查看当前mmc设备的信息
mmc rescan 用于扫描当前开发板上所有的MMC设备(在命令行里输入没有输出,猜测可以返回是否存在mmc设备)
mmc list 查看总共有几个mmc设备
mmc dev 切换mmc设备和分区 例如 mmc dev 0 0 切换到mmc0的分区0 ; mmc dev 1 2 切换到mmc1的分区2
mmc part 可以查看分区情况
如果 EMMC 里面烧写了 Linux 系统的话, EMMC 是有3 个分区的,第 0 个分区存放 uboot,第 1 个分区存放 Linux 镜像文件和设备树,第 2 个分区存放根文件系统。但是在图 30.4.5.6 中只有两个分区,那是因为第 0 个分区没有格式化,所以识别不出来,实际上第 0 个分区是存在的。一个新的 SD 卡默认只有一个分区,那就是分区 0,所以前面讲解的 uboot 烧写到 SD 卡,其实就是将 u-boot.bin 烧写到了 SD 卡的分区 0 里面。
mmc read 命令
mmc read addr blk# cnt
比如从 EMMC 的第 1536(0x600)个块开始,读取 16(0x10)个块的数据到 DRAM 的0X80800000 地址处
mmc dev 1 0 //切换到 MMC 分区 0
mmc read 80800000 600 10 //读取数据
然后通过 md.b 命令查看 0x80800000 处的数据就行了 md.b 80800000 2000
mmc write 命令
mmc write addr blk# cnt
addr 是要写入 MMC 中的数据在 DRAM 中的起始地址;blk 是要写入MMC 的块起始地址(十六进制), cnt 是要写入的块大小,一个块为 512 字节
我们可以使用命令“mmc write”来升级 uboot,也就是在 uboot 中更新 uboot。这里要用到 nfs 或者 tftp 命令,通过 nfs 或者 tftp 命令将新的 u-boot.bin 下载到开发板的 DRAM 中,然后再使用命令“mmc write”将其写入到 MMC设备中
具体代码如下:使用命令“mmc write”从 SD 卡分区 0 第 2 个块(扇区)开始烧写,一共烧写 814(0x32E)个块
tftp 80800000 u-boot.imx
mmc dev 0 0
mmc write 80800000 2 32E
mmc partconf 1 1 0 0 //分区配置, EMMC 需要这一步!
千万不要写 SD 卡或者 EMMC 的前两个块(0 号 1号扇区),前两个块里面保存着分区表!如果破坏的话,将会损坏sd卡(分区表破坏可以重建分区来修复mmc,不过这样的话,mmc里面的数据就全没了)
6.FAT 格式文件系统操作命令
fatls、 fatload (注意:只支持fat文件系统)
fatls 命令
用于查询 FAT 格式设备的目录和文件信息
fatls mmc 1:1 fatls可以不写分区号,这样查询全部分区的文件
fatload 命令
将指定的文件读取到 DRAM 中
将 EMMC 分区 1 中的 zImage 文件读取到 DRAM 中的0X80800000 地址处,命令如下:
fatload mmc 1:1 80800000 zImage
7.boot相关操作
主要有两个,bootz和boot
bootz:启动linux内核和设备树
从网络:
tftp 80800000 zImage
tftp 83000000 imx6ull-alientek-emmc.dtb
bootz 80800000 – 83000000
从EMMC:
fatload mmc 1:1 80800000 zImage
fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb
bootz 80800000 - 83000000
boot 命令也是用来启动 Linux 系统的,只是 boot 会读取环境变量 bootcmd 来启动 Linux 系统
比如我们要想使用 tftp 命令从网络启动 Linux 那么就可以设置 bootcmd 为“tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000”,然后使用 saveenv 将 bootcmd 保存起来。然后直接输入 boot 命令即可从网络启动Linux 系统
如果想从 EMMC 启动那就设置 bootcmd 为“fatload mmc 1:1 80800000 zImage; fatload mmc1:1 83000000 imx6ull-alientek_emmc.dtb; bootz 80800000 - 83000000”,然后使用 boot 命令启动即可
8.其他命令:
reset:复位命令,重启uboot
go命令:跳转到指定地址执行应用 例如 tftp 87800000 printf.bin go 87800000
思考:能否将linux内核通过tftp命令拷贝到80800000处,然后go 80800000
答案是不可以的。因为linux镜像需要通过uboot引导才能启动,目前相当于uboot执行了bootdelay后卡在命令行了,只有使用boot、bootz命令才能与uboot建立联系,才能继续执行uboot的初始化函数,你使用go命令直接跳到了linux内核中,这时候linux运行的环境都还没搭建起来,uboot只执行了一部分而已,是不可能引导linux启动的
run 命令:run运行环境变量定义的命令。主要是运行自己定义的变量。像bootcmd变量可以通过boot缩写来运行,但是其他变量不可以直接运行,所以运行需要加上run命令。
在后面调试 Linux 系统的时候常常要在网络启动和 EMMC/NAND 启动之间来回切换,而 bootcmd 只能保存一种启动方式,如果要换另外一种启动方式的话就得重写 bootcmd,会很麻烦。这里我们就可以通过
自定义环境变量来实现不同的启动方式,比如定义环境变量 mybootemmc 表示从 emmc 启动,定义 mybootnet 表示从网络启动,定义 mybootnand 表示从 NAND 启动。如果要切换启动方式的话只需要运行“run mybootxxx(xxx 为 emmc、 net 或 nand)”即可。
uboot图形化界面、xxx_defconfig
uboot 或 Linux 内核可以通过输入“make menuconfig”来打开图形化配置界面, menuconfig是一套图形化的配置工具,需要 ncurses 库支持,需要先在 Ubuntu 中安装 ncurses 库
sudo apt-get install build-essential
sudo apt-get install libncurses5-dev
使用图形化配置完成后,需要保存配置项,否则clean后就白配置了
可以直接将.config文件另存为XXX_defconfig;
既然图形化界面配置后的配置项保存在.config 中,那么就简单粗暴,直接将.config 文件另存为 imx_alientek_emmc_defconfig,然后其复制到 arch/arm/configs 目录下,替换以前的imx_alientek_emmc_defconfig。
但是这里要注意的是:
一,defconfig与.config是什么关系?
.config不是defconfig的拷贝,defconfig仅仅保存与默认配置不同的选项。也就是说,uboot或者kernel里面有默认的配置项,来生成.config,哪怕没用defconfig文件,也有许多默认配置项可以生成.config;但是defconfig里面是自己定义的一些系统未配置的项。当然,如果你defconfig里面包含了系统的一些已经配置的项,也是完全可以用的啊
那么,图形化界面配置完了后,如何文雅的保存defconfig文件呢?(粗暴的方法是直接将.config文件保存为defconfig)
采用:make savedefconfig
会在uboot根目录下生成一个defconfig文件,将defconfig文件里的内容复制到自己原先的defconfig文件里即可。
二,defconfig中的语法
CONFIG_<optionName>=y
# CONFIG_<optionName> is not set --- 表示 CONFIG_<optionName>为no