uboot命令体系

uboot命令体系
1.使用uboot命令:
uboot启动后进入命令行环境下,在此输入命令按回车结束,uboot会收取这个命令然后解析,然后执行。
2.uboot命令体系的实现代码在uboot/common/cmd_xxx.c中。有若干个.c文件和命令体系有关。(还有command.c main.c也是和命令有关的)
3.每个命令对应一个函数
(1)每一个uboot的命令背后都对应一个函数。这就是uboot实现命令体系的一种思路和方法
(2)我们要找到每一个命令背后所对应的那个函数,而且要分析这个函数和这个命令是怎样对应起来的
4.命令参数以argc&argv传给函数
有些uboot的命令还支持传递参数。也就是说命令背后对应的函数接收的参数列表中有argc和argv,然后命令体系会把我们执行命令时的命令+参数(md 30000000 10)以argc(3)和argv(argv[0]=md, argv[1]=30000000 argv[2]=10)的方式传递给执行命令的函数。
5.以help命令为例:
help命令背后对应的函数名叫:do_help。在uboot/common/command.c的236行。int do_help (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])


6.uboot命令解析和执行过程分析
(1)uboot启动的第二阶段,在初始化了所有该初始化的东西后,进入了一个死循环,死循环的循环体就是main_loop。
(2)main_loop函数执行一遍,就是一个获取命令、解析命令、执行命令的过程。
(3)run_command函数就是用来执行命令的函数。


7.if (bootdelay >= 0 && s && !abortboot (bootdelay))
abortboot:这个函数里面打印:Hit any key to stop autoboot: 0
并且判断有没有按键按下,如果函数abortboot正常结束返回0,if成立,有按键按下返回1,if不成立


8.run_command函数详解
(1)控制台命令获取
(2)命令解析。parse_line函数把"md 30000000 10"解析成argv[0]=md, argv[1]=30000000 argv[2]=10;
(3)命令集中查找命令。find_cmd(argv[0])函数去uboot的命令集合当中搜索有没有argv[0]这个命令,
(4)执行命令。最后用函数指针的方式调用执行了对应函数。
关键点就在于find_cmd函数如何查找到这个命令是不是uboot的合法支持的命令?这取决于uboot的命令体系机制(uboot是如何完成命令的这一套设计的,命令如何去注册、存储、管理、索引?


9.可能的管理方式
(1)数组。结构体数组,数组中每一个结构体成员就是一个命令的所有信息。
(2)链表。链表的每个节点data段就是一个命令结构体,所有的命令都放在一条链表上。这样就解决了数组方式的不灵活。坏处是需要额外的内存开销,然后各种算法(遍历、插入、删除等)需要一定复杂度的代码执行。
(3)有第三种吗?uboot没有使用数组或者链表,而是使用了一种新的方式来实现这个功能


10.命令结构体cmd_tbl_t
struct cmd_tbl_s {
char name; / Command Name /
int maxargs; /
maximum number of arguments /
int repeatable; /
autorepeat allowed? /
/
Implementation function */
int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
char usage; / Usage message (short) */
#ifdef CFG_LONGHELP
char help; / Help message (long) /
#endif
#ifdef CONFIG_AUTO_COMPLETE
/
do auto completion on the arguments */
int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);
#endif
};
typedef struct cmd_tbl_s cmd_tbl_t;
(1)name:命令名称,字符串格式。
(2)maxargs:命令最多可以接收多少个参数
(3)repeatable:指示这个命令是否可重复执行。重复执行是uboot命令行的一种工作机制,就是直接按回车则执行上一条执行的命令。
(4)cmd:函数指针,命令对应的函数的函数指针,将来执行这个命令的函数时使用这个函数指针来调用。
(5)usage:命令的短帮助信息。对命令的简单描述。
(6)help:命令的长帮助信息。细节的帮助信息。
(7)complete:函数指针,指向这个命令的自动补全的函数。
总结:uboot的命令体系在工作时,一个命令对应一个cmd_tbl_t结构体的一个实例,然后uboot支持多少个命令,就需要多少个结构体实例。uboot的命令体系把这些结构体实例管理起来,当用户输入了一个命令时,uboot会去这些结构体实例中查找(查找方法和存储管理的方法有关)。如果找到则执行命令,如果未找到则提示命令未知。


11.uboot实现命令管理的思路
(1)填充1个结构体实例构成一个命令
(2)给命令结构体实例附加特定段属性(用户自定义段),链接时将带有该段属性的内容链接在一起排列(挨着的,不会夹杂其他东西,也不会丢掉一个带有这种段属性的,但是顺序是乱序的)。
(3)uboot重定位时将该段整体加载到DDR中。加载到DDR中的uboot镜像中带有特定段属性的这一段其实就是命令结构体的集合,有点像一个命令结构体数组。
(4)段起始地址和结束地址(链接地址、定义在u-boot.lds中)决定了这些命令集的开始和结束地址


12.uboot命令定义具体实现分析
(1)U_BOOT_CMD宏基本分析,这个宏定义在uboot/common/command.h中。
(2)宏原型的定义:
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help)
cmd_tbl_t _u_boot_cmd##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}
(3)例子分析:
U_BOOT_CMD(
version, 1, 1, do_version,
“version - print monitor version\n”,
NULL
);
展开:
cmd_tbl_t __u_boot_cmd_version attribute ((unused,section (".u_boot_cmd"))) =
{“version”, 1, 1, do_version, “version - print monitor version\n”, NULL};
(4)这个宏其实就是定义了一个命令对应的结构体变量,这个变量名和宏的第一个参数有关,因此只要宏调用时传参的第一个参数不同则定义的结构体变量不会重名。
总结:这个U_BOOT_CMD宏的理解,关键在于结构体变量的名字和段属性。名字使用##作为连字符,附加了用户自定义段属性,以保证链接时将这些数据结构链接在一起排布。
(2)链接脚本。


13.find_cmd函数详解
(1)find_cmd函数的任务是从当前uboot的命令集中查找是否有某个命令。如果找到则返回这个命令结构体的指针,如果未找到返回NULL。
(2)函数的实现思路很简单,如果不考虑命令带点的情况(md.b md.w这种)就更简单了。查找命令的思路其实就是for循环遍历数组的思路,不同的是数组的起始地址和结束地址是用地址值来给定的,数组中的元素是结构体变量类型。


14.uboot中增加自定义命令
在已有的c文件中直接添加命令
(1)在uboot/common/command.c中添加一个命令,叫:mycmd
(2)在已有的.c文件中添加命令比较简单,直接使用U_BOOT_CMD宏即可添加命令,给命令提供一个do_xxx的对应的函数这个命令就齐活了。
(3)添加完成后要重新编译工程(make distclean; make x210_sd_config; make),然后烧录新的uboot去运行即可体验新命令。
(4)还可以在函数中使用argc和argv来验证传参。
自建一个c文件并添加命令
(1)在uboot/common目录下新建一个命令文件,叫wyz_cmd.c(对应的命令名就叫wan,对应的函数就叫do_wan函数),然后在c文件中添加命令对应的U_BOOT_CMD宏和函数。注意头文件包含不要漏掉。
(2)在uboot/common/Makefile中添加上wyz_cmd.o,目的是让Make在编译时能否把wyz_cmd.c编译链接进去。
COBJS-y += wyz_cmd.o 这里的y就是yes的意思
(3)重新编译烧录。重新编译步骤是:make distclean; make x210_sd_config; make


总结:uboot的命令体系本身稍微复杂,但是他写好之后就不用动了。我们后面在移植uboot时也不会去动uboot的命令体系。我们最多就是向uboot中去添加命令。

### U-Boot简介 U-Boot (Universal Boot Loader) 是一种广泛应用于嵌入式系统的引导加载程序。其主要功能是在操作系统启动之前初始化硬件并提供必要的环境支持,以便能够顺利加载和执行操作系统内核。 在特定版本中,`libs-y` 原先是u-boot的所有子目录的集合,但是通过使用 `patsubst` 函数处理后,它转变为了所有子目录下 `built-in.o` 文件的集合[^1]。这表明了构建过程中如何收集不同模块的目标文件来准备最终链接阶段的工作。 对于指定版本如2022.10版[U-Boot](https://ftp.denx.de/pub/u-boot/),该版本提供了最新的特性和改进以适应现代处理器架构的需求[^2]。 ### 使用方法及教程 #### 下载源码 可以从官方FTP服务器下载所需版本的U-Boot压缩包: ```bash wget https://ftp.denx.de/pub/u-boot/u-boot-2022.10.tar.bz2 tar jxf u-boot-2022.10.tar.bz2 cd u-boot-2022.10/ ``` #### 编译配置 进入解压后的目录后,可以为具体平台设置相应的配置选项。通常情况下会有一个预定义好的`.config`文件用于简化此过程: ```bash make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- <board>_defconfig ``` 这里假设目标体系结构是ARM,并指定了交叉编译工具链前缀(`CROSS_COMPILE`)。 #### 构建项目 完成上述准备工作之后就可以开始实际编译工作了: ```bash make all ``` 这条命令将会依据Makefile中的规则依次调用gcc等工具来进行汇编、编译以及链接操作,从而得到可执行映像文件u-boot.bin。 #### 安装部署 最后一步则是将生成出来的二进制镜像烧录到开发板对应的存储介质上(比如NAND Flash),这样当设备重启时就会自动运行新编译成功的固件。 ### 示例:查看帮助信息 如果想要了解更详细的指令列表及其参数说明,则可以在成功安装好U-Boot以后,在串口终端输入help命令获得更多信息: ```bash => help ? ... ``` 以上展示了基本的操作流程;然而具体的细节可能会因所选平台的不同而有所变化,请参照官方文档获取最权威指导。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值