omapl138移植uboot系列之添加点亮led命令(第六篇)

2.5  uboot命令体系

      刚刚你是否注意到,uboot启动后会先进入一个3s的倒计时,在倒计时变成0之前,敲打键盘的任意键,都会进入uboot的命令行状态,在此输入命令按回车结束,uboot会收取这个命令然后解析,然后执行。每一个uboot的命令背后都对应一个函数。这就是uboot实现命令体系的一种思路和方法。

进入uboot控制界面后,可以运行各种命令,比如下载文件到内存,擦除、读写Flash,运行内存、NorFlash、NandFlash中的程序,查看、修改、比较内存中的数据等。

2.5.1 uboot命令体系原理

      每一个uboot的命令背后都对应一个函数,这就是uboot实现命令体系的一种思路和方法,有些uboot的命令还支持传递参数。也就是说命令背后对应的函数接收的参数列表中有argc和argv,然后命令体系会把我们执行命令时的命令+参数(md 30000000 10)以argc(3)和argv(argv[0]=md, argv[1]=30000000 argv[2]=10)的方式传递给执行命令的函数,以help命令为例:

      help命令背后对应的函数名叫:do_help。在uboot/common/command.c的236行。int do_help (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])。

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

控制台命令获取

命令解析。parse_line函数把"md 30000000 10"解析成argv[0]=md, argv[1]=30000000 argv[2]=10;

命令集中查找命令。find_cmd(argv[0])函数去uboot的命令集合当中搜索有没有argv[0]这个命令。

执行命令。最后用函数指针的方式调用执行了对应函数。

关键点就在于find_cmd函数如何查找到这个命令是不是uboot的合法支持的命令?这取决于uboot的命令体系机制(uboot是如何完成命令的这一套设计的,命令如何去注册、存储、管理、索引。)。uboot没有使用数组或者链表,而是使用了一种新的方式来实现这个功能。

命令结构体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会去这些结构体实例中查找(查找方法和存储管理的方法有关)。如果找到则执行命令,如果未找到则提示命令未知。

uboot实现命令管理的思路

(1)填充1个结构体实例构成一个命令

(2)给命令结构体实例附加特定段属性(用户自定义段),链接时将带有该段属性的内容链接在一起排列(挨着的,不会夹杂其他东西,也不会丢掉一个带有这种段属性的,但是顺序是乱序的)。

(3)uboot重定位时将该段整体加载到DDR中。加载到DDR中的uboot镜像中带有特定段属性的这一段其实就是命令结构体的集合,有点像一个命令结构体数组。

(4)段起始地址和结束地址(链接地址、定义在u-boot.lds中)决定了这些命令集的开始和结束地址。

2.5.2 uboot命令定义具体实现分析

U_BOOT_CMD宏基本分析

这个宏定义在uboot/common/command.h中。

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"))) = {#name, maxargs, rep, cmd, usage, help}

总结:这个U_BOOT_CMD宏的理解,关键在于结构体变量的名字和段属性。名字使用##作为连字符,附加了用户自定义段属性,以保证链接时将这些数据结构链接在一起排布。

2.5.3 点亮LED

很多时候,我们新接触一块板卡都是从点亮led灯开始的,笔者注意到639A板卡上刚好有两个led灯,那就让我们趁热打铁,小试牛刀一下,使用uboot的命令体系来点亮这两个led灯吧!

首先在cmd目录下,创建一个名为“cmd_639aled.c”的文件,将所使用的GPIO控制函数和引脚配置声明进来。

/*

 *  Description: uboot  led command

 *

 *  Author:HanChao

 *

 *  CreatTime:  2018/7/30

 *

 */

 

#include <common.h>

#include <command.h>

#include <asm/arch/davinci_misc.h>

 

 

static const struct pinmux_config led_pins[] = {

         { pinmux(18), 8, 2 },

         { pinmux(18), 8, 6 }

};

 

const struct pinmux_resource led_pinmuxes[] = {

         PINMUX_ITEM(led_pins),

 

};

#define GPIO_CAL(io,pinn)       ((io)*16+(pinn))

const int led_pinmuxes_size = ARRAY_SIZE(led_pinmuxes);

 

int gpio_direction_output(unsigned gpio, int value);

int gpio_direction_output(unsigned gpio, int value);

控制GPIO需要的函数声明好了以后,接下来就要实现do_xxx格式的函数了,在这个函数里,我们需要解析命令行传递过来的参数并进行判断,来决定led的亮和灭!

我们暂且规定一下命令:

“led on”代表所有led均变为亮

“led off”代表所有led均灭

“led xx on”代表单独点亮第xx个led

“led xx off”代表单独灭掉第xx个led
 

int do_led(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

{

         char *cmd,*num;

         static char init = 0;

         int gpio=0;

         if(!init) //初始化IO

         {       

                   davinci_configure_pin_mux_items(led_pinmuxes, led_pinmuxes_size);

                   gpio_direction_output(GPIO_CAL(8,11),0);

                   gpio_direction_output(GPIO_CAL(8,15),0);

                   init = 1;

         }

         if(argc == 2)

         {

                   cmd = argv[1];

                   if(strcmp(cmd, "on") == 0)

                   {

                            gpio_set_value(GPIO_CAL(8,11),0);

                            gpio_set_value(GPIO_CAL(8,15),0);

                   }

                   else if(strcmp(cmd, "off") == 0)

                   {

                            gpio_set_value(GPIO_CAL(8,11),1);

                            gpio_set_value(GPIO_CAL(8,15),1);

                   }

                           

         }

         else if(argc == 3)

         {

                   num = argv[1];

                   cmd = argv[2];

                   if(strcmp(num, "1") == 0)

                            gpio = GPIO_CAL(8,11);

                   else if(strcmp(num, "2") == 0)

                            gpio = GPIO_CAL(8,15);

 

                   if(strcmp(cmd, "on") == 0)

                            gpio_set_value(gpio,0);

                   else if(strcmp(cmd, "off") == 0)

                            gpio_set_value(gpio,1);

                                                       

         }

}

U_BOOT_CMD(

    led,    CONFIG_SYS_MAXARGS, 1,  do_led,

    "control led on/off",

    "led on|off\n"

    "led 1/2 on|off "

);

     命令对应的led控制函数我们已经实现了,接下来我们需要使用uboot提供的U_BOOT_CMD宏,将我们的这条命令链接进命令段。

     c文件我们已经实现了,接下来我们将“cmd_639aled.c”文件添加到该目录Makefile文件中,如果不这么做,该文件是不会被编译链接的。

     打开Makefile文件,找个位置(尽量靠前),添加一句“obj-y += cmd_639bled.o”,保存退出,make编译完成后,你会发现cmd目录下多了一个cmd_639bled.o文件,这就说明cmd_639bled.c已经被链接至uboot镜像了。

     你现在可以立刻按照前面我们所讲的烧录方式将我们刚刚编译好的uboot镜像烧录到Flash验证一下,我还是要建议你看完下一节再烧录。

猜你喜欢

转载自blog.csdn.net/weixin_42314225/article/details/83241175