原文:https://blog.csdn.net/weixin_41252596/article/details/128317180
有些用户玩uboot比较花,除了引导系统还要做一堆驱动,有些驱动除了按流程执行还要留出命令行接口用于调试。比如我现在的设备外接了个fpga,fpga和cpu的接口已经做好了,但是为了调试要新增个命令,在命令行下手动与fpga通信。
分析
先看以下这段代码:
我们来分析以下这段代码,首先是一个函数do_fpga,然后下面U_BOOT_CMD是个啥呢?其实U_BOOT_CMD是一个宏,在uboot源码目录include/command.h中有如下定义:
其中:
name:添加的命令的名字
maxargs:添加的命令最多有几个参数(可以默认使用CONFIG_SYS_MAXARGS=16)
rep:是否重复(1重复,0不重复)(在uboot命令行按下Enter键的时候,重复执行上次的命令)
cmd:执行函数,即执行命令会运行哪个函数
usage:短帮助信息
help:长帮助信息
对应代码:
name = fpga //命令行中使用的命令名字
maxargs=CONFIG_SYS_MAXARGS //该宏默认定义在uboot中,大小为16,一般是足足够的
rep=1 //可以重复执行,提高效率
cmd=do_fpga // do_fpga是我们在宏前实现的具体执行函数
usage=fpga utility commands //短帮助信息(注意短信息和长信息之间有个逗号)
help=....... //长帮助信息,具体看图(长信息的开头并不是fpga read是因为命令会自动在此加一个fpga)
U_BOOT_CMD宏又使用了U_BOOT_CMD_COMPLETE宏,其实如果一直研究下去,最终会得到一个关于此命令的数据结构,该数据结构会被存储到uboot的命令段里面,在命令使用的时候会从该列表查找,在此我们不做过多分析,先学会用再说。
让我们再分析下函数实现,我们可以看到函数的声明为:
int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
其中:
cmd_tbl_t是一个结构体,在include/command.h中有如下定义:
结构体定义的内容其实就是U_BOOT_CMD实现包含的几个参数。
flag这个参数没有深究是干嘛用的,好多命令在最底层实现的时候都没用到这个参数
argc:命令行传入总的参数数量,与linux应用、命令下传参是一样的,都是命令本身+参数个数,所以argc至少等于1,即命令本身
argv[ ] :参数。argv[0]是命令,argv[1]是命令后跟的第一个参数
我们来看一下具体代码内容
代码首先判断了argc的数量,如果小于1,那是不可能的,肯定有问题,如果等于1,说明没有输入参数,此时调用cmd_usage函数告诉用户怎么用,其实就是打印帮助信息
如果参数个数没问题,那我们要判断用户输入的是什么参数,在此例程中,使用字符串对比函数判断参数是read还是write,然后分别执行printf打印执行信息,在具体的实现中,把自己真正的要实现的功能替换掉printf打印即可。
如果传入的参数未定义,那同样进行用法打印。
所以我们最开始放出的这一段代码中,函数则是具体的命令执行过程,U_BOOT_CMD宏则是对命令的一种声明。
自定义U_BOOT_CMD实现
第一步:我们就按照前面给出的这段代码去具体实现,在board目录下(自定义命令可以不把源文件存放至uboot存放命令源文件的地方),新建.c文件,名字随便起,输入开头给出的代码内容。具体的内容随需求更改!
第二步:在所在目录Makefile中添加该文件(注意:有的uboot版本使用了SPL/TPL,但是这些命令不应该出现在这两个阶段,如果对编译情况不做限制会出现编译报错,因此在这类uboot中的Makefile还要加入如下编译条件:
红框是要判断的条件,箭头所指是新增的命令源文件。
第三步:编译、下载、测试
在uboot命令行中使用 “ ?”可以显示命令列表,找一下我们实现的命令是否存在:
使用命令 fpga 查看帮助信息:
测试fpga read 和fpga write 是否运行:
至此,自定义命令完成,具体的命令实现函数内容根据需求设计!
————————————————
版权声明:本文为CSDN博主「Absorbed_w」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41252596/article/details/128317180