这一节我们进行uboot的移植。
移植的版本是u-boot-2013.01,在上课的时候老师主要带着分析了一下uboot的启动流程,而没有重点说uboot移植中进行修改的内容,修改也仅仅是按照实验手册进行,绝大多数的修改完全不知道为什么,而且实验手册上还有一些错误,如果不知道修改的原因一旦出现错误完全不知道从何下手。
这里我把移植时需要的文件和我更改过的文档上传共同学们使用,我修改的文档主要是在我自己按照原版的手册进行时出现的问题改正过来。
移植实验所用的文档下载:FS4412系统移植uboot移植实验代码
uboot移植实验手册:uboot移植实验手册修正版
以上的实验就按照实验手册自己进行吧,我觉得相比照着文档粘贴还不如自己在uboot添加一条命令来的实际,在以后的工作中如果需要修改uboot基本上也是在已有的uboot上添加和修改命令。
下面就让我们来添加自己的第一条命令hello
也就是在uboot的命令界面上添加可以输入hello来完成一些功能,我们的目标是在输入hello之后可以输入一些参数,然后当hello将我们输入的参数打印到终端上,这样做可以上我们学习到uboot命令是如何接受命令行参数的,为以后我们自己写一些自己的有参命令做准备。
首先我们需要有一个原始参考,也就是我们不能自己凭空想象怎么添加命令就怎么写,我们要找一个已经存在的命令来参考,照着那个去写。
这里我们参考源码文件中的cmd_test.c来改写,这个文件在/u-boot-2013.01/common文件夹下
首先我们包含两个头文件
#include <common.h>
#include <command.h>
然后写一个自己的函数,函数原型为int do_xxxx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
其中xxxx为你的cmd后面的文件名,比如我们写一个cmd_hello文件,那么这个函数就应该是int do_hello(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
必须要这种形式的函数,这个是uboot的规定,在后面需要加入到宏中去。
下面我们来实现函数,我们想让我们在输入hello之后添加的参数都在终端返回来,我们就需要如下面编写
int do_hello(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { int i; printf("argc = %d\n", argc); for(i = 0; i<argc; i++) { printf("i = %d, %s\n", i, argv[i]); } return 0; }
argv中保存着我们每个参数的指针。
有了函数之后我们还需要将这个函数加入到uboot的命令列表,需要使用一个宏定义--U_BOOT_CMD
使用这个宏去把你写的函数加入到命令列表中,这样在uboot中敲入你写的命令就可以正确执行了。
简单解释一下这个宏的各个参数。
U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help)
_name是在uboot中的命令名字,这个名字不必是你定义的函数名字,比如你定义的是do_hello函数,这个名字和一输入world,但是这样你在uboot命令行中就需要输入world才能执行这个do_hello 命令。
_maxargs这个是可以接收的参数个数。
_rep这个函数是否可重复执行,也就是在执行一次之后,在按回车键是否自动执行,如果是1表示可以自动执行,0表示不能自动执行。
_cmd函数名,就是咱们自己实现的那个do_xxx
_usage短帮助,就是在uboot命令中输入?时候返回是帮助信息。
_help完整帮助,就是 在使用help 命令 的时候进行查询的帮助信息。
好了知道这些之后我们就可以写出自己的U_BOOT_CMD宏命令了。
U_BOOT_CMD( hello, 5, 0, do_hello, "hello world!\n", "this is a hello world test!\n" );命令名为hello,最多5个参数,不可重复,执行的函数为de_hello,短帮助为hello world!,完整帮助为this is a hello world test!
完整的文件为
#include <common.h> #include <command.h> int do_hello(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { int i; printf("argc = %d\n", argc); for(i = 0; i<argc; i++) { printf("i = %d, %s\n", i, argv[i]); } return 0; } U_BOOT_CMD( hello, 5, 0, do_hello, "hello world!\n", "this is a hello world test!\n" );
现在编译还不能在我们的uboot中使用我们的命令,需要我们修改一下Makefile,好让我们新建的cmd_hello.c文件被编译进uboot。
vim common/Makefile
在后面添加一行COBJS-$(CONFIG_CMD_HELLO) += cmd_hello.o
这句话是将cmd_hello.o添加到all的依赖文件中去,这样在make的时候就会对md_hello.c文件进行编译,但是all的依赖是一个叫做COBJS-y的变量,也就是我们需要让CONFIG_CMD_HELLO宏被定义,我们在fs4412.h中加入#define CONFIG_CMD_HELLO这句话,好了大功告成。现在可以去进行我们的脚本./build.sh了,编译完成后下载到开发板就可以使用hello命令去体验下一了。
U-Boot 2013.01 (May 20 2016 - 10:56:15) for FS4412 by RZ CPU: Exynos4412@1000MHz Board: FS4412 DRAM: 1 GiB WARNING: Caches not enabled MMC: MMC0: 3728 MB In: serial Out: serial Err: serial MMC read: dev # 0, block # 48, count 16 ...16 blocks read: OK eMMC CLOSE Success.!! Checking Boot Mode ... EMMC4.41 Net: dm9000 Hit any key to stop autoboot: 0 FS4412 # FS4412 # hello 1 2 a 3 argc = 5 i = 0, hello i = 1, 1 i = 2, 2 i = 3, a i = 4, 3 FS4412 #