Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2706758
  • 博文数量: 505
  • 博客积分: 1552
  • 博客等级: 上尉
  • 技术积分: 2514
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-23 18:24
文章分类

全部博文(505)

文章存档

2019年(12)

2018年(15)

2017年(1)

2016年(17)

2015年(14)

2014年(93)

2013年(233)

2012年(108)

2011年(1)

2009年(11)

分类: LINUX

2013-05-04 10:47:07

下面以添加menu命令为例分析U-Boot添加命令的方法。

 

  (1common目录下新建cmd_menu.c文件

习惯上把通用命令源代码放在common目录下,与开发板专有命令有关的源代码则放在board/目录下,命名方式只是习惯而已。为了方便阅读和查询习惯以cmd_<命 令名>.c为文件名。

2定义menu命令

cmd_menu.c中使用如下的代码定义menu命令:

U_BOOT_CMD(
 
 menu, 3, 0, do_menu,
 
 "menu - display a menu, to select the items to do something\n",
 
 " - display a menu, to select the items to do something"
 
 );

其中U_BOOT_CMD命令格式如下:

1 U_BOOT_CMD(name,maxargs,rep,cmd,usage,help)

  各个参数的意义如下:

name:命令名,非字符串,但在U_BOOT_CMD中用#符号转化为字符串

maxargs:命令的最大参数个数

rep:是否自动重复(按Enter键是否会重复执行)

cmd:该命令对应的响应函数

usage:简短的使用说明(字符串)

help:较详细的使用说明(字符串)

在内存中保存命令的help字段会占用一定的内存,通过配置U-Boot可以选择是否保存help字段。若在include/configs/mx51_bbg.h中定义了CONFIG_SYS_LONGHELP宏,则在U-Boot中使用help命令查看某个命令的帮助信息时将显示usagehelp字段的内容,否则就只显示usage字段的内容。

U_BOOT_CMD宏在include/command.h中定义:

1 #define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \  2   cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}

###都是预编译操作符,##有字符串连接的功能,#表示后面紧接着的是一个字符串。

点击(此处)折叠或打开

  1. struct cmd_tbl_s {
  2.  char *name; /* 命令名 */
  3.  int maxargs; /* 最大参数个数 */
  4.  int repeatable; /* 是否自动重复 */
  5.  int (*cmd)(struct cmd_tbl_s *, int, int, char *[]); /* 响应函数 */
  6.  char *usage; /* 简短的帮助信息 */
  7.  #ifdef CONFIG_SYS_LONGHELP
  8.  char *help; /* 较详细的帮助信息 */
  9.  #endif
  10.  #ifdef CONFIG_AUTO_COMPLETE
  11.  /* 自动补全参数 */
  12.  int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);
  13.  #endif
  14.  };
  15.  typedef struct cmd_tbl_s cmd_tbl_t;

一个cmd_tbl_t结构体变量包含了调用一条命令的所需要的信息。

其中Struct_Sectioninclude/command.h中定义如下:

1 #define Struct_Section  __attribute__ ((unused,section (".u_boot_cmd")))

凡是带有__attribute__ ((unused,section (".u_boot_cmd"))属性声明的变量都将被存放在".u_boot_cmd"段中,并且即使该变量没有在代码中显式的使用编译器也不产生警告信息。

U-Boot连接脚本u-boot.lds中定义了".u_boot_cmd"段:

1 . = .; 2 __u_boot_cmd_start = .; /*将 __u_boot_cmd_start指定为当前地址 */ 3 .u_boot_cmd : { *(.u_boot_cmd) } 4 __u_boot_cmd_end = .; /* 将__u_boot_cmd_end指定为当前地址 */

这表明带有.u_boot_cmd声明的函数或变量将存储在u_boot_cmd段。这样只要将U-Boot所有命令对应的cmd_tbl_t变量加上.u_boot_cmd声明,编译器就会自动将其放在u_boot_cmd段,查找cmd_tbl_t变量时只要在__u_boot_cmd_start__u_boot_cmd_end之间查找就可以了。

因此menu命令的定义经过宏展开后如下:

 
cmd_tbl_t __u_boot_cmd_menu __attribute__ 
((unused,section (".u_boot_cmd"))) = 
{menu, 3, 0, do_menu, 
"menu - display a menu, to select the items to do something\n", 
" - display a menu, to select the items to do something"}

实质上就是用U_BOOT_CMD宏定义的信息构造了一个cmd_tbl_t类型的结构体。编译器将该结构体放在u_boot_cmd段,执行命令时就可以在u_boot_cmd段查找到对应的cmd_tbl_t类型结构体。

3实现命令的函数

U_BOOT_CMD(name,maxargs,rep,cmd,usage,help)中的cmd参数

cmd_menu.c中添加menu命令的响应函数的实现。具体的实现代码略:

1 int do_menu (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) 2 { 3 /* 实现代码略 */ 4 }

4 common/cmd_menu.c编译进u-boot.bin

common/Makefile中把目标代码cmd_menu.o也加入一起编译:

include/configs/mx51_bbg.h加入如代码:

#define CONFIG_BOOT_MENU 1

重新编译下载U-Boot就可以使用menu命令了

5menu命令执行的过程

U-Boot中输入menu命令执行时,U-Boot接收输入的字符串menu,传递给run_command函数。run_command函数调用common/command.c中实现的find_cmd函数在__u_boot_cmd_start__u_boot_cmd_end间查找命令,并返回menu命令的cmd_tbl_t结构。然后run_command函数使用返回的cmd_tbl_t结构中的函数指针调用menu命令的响应函数do_menu,从而完成了命令的执行。

6)例子:USB下载,命令很简单。

点击(此处)折叠或打开

  1. #include <common.h>
  2.  #include <command.h>
  3.  extern char console_buffer[];
  4.  extern int readline (const char *const prompt);
  5.  extern char awaitkey(unsigned long delay, int* error_p);
  6.  extern void download_nkbin_to_flash(void);
  7.  /**
  8.   * Parses a string into a number. The number stored at ptr is
  9.   * potentially suffixed with K (for kilobytes, or 1024 bytes),
  10.   * M (for megabytes, or 1048576 bytes), or G (for gigabytes, or
  11.   * 1073741824). If the number is suffixed with K, M, or G, then
  12.   * the return value is the number multiplied by one kilobyte, one
  13.   * megabyte, or one gigabyte, respectively.
  14.   *
  15.   * @param ptr where parse begins
  16.   * @param retptr output pointer to next char after parse completes (output)
  17.   * @return resulting unsigned int
  18.   */
  19.  static unsigned long memsize_parse2 (const char *const ptr, const char **retptr)
  20.  {
  21.   unsigned long ret = simple_strtoul(ptr, (char **)retptr, 0);
  22.      int sixteen = 1;
  23.   switch (**retptr) {
  24.    case 'G':
  25.    case 'g':
  26.     ret <<= 10;
  27.    case 'M':
  28.    case 'm':
  29.     ret <<= 10;
  30.    case 'K':
  31.    case 'k':
  32.     ret <<= 10;
  33.     (*retptr)++;
  34.              sixteen = 0;
  35.    default:
  36.     break;
  37.   }
  38.      if (sixteen)
  39.          return simple_strtoul(ptr, NULL, 16);
  40.     
  41.    return ret;
  42.  }
  43.  
  44.  void param_menu_usage()
  45.  {
  46.      printf("\r\n##### Parameter Menu #####\r\n");
  47.      printf("[v] View the parameters\r\n");
  48.      printf("[s] Set parameter \r\n");
  49.      printf("[d] Delete parameter \r\n");
  50.      printf("[w] Write the parameters to flash memeory \r\n");
  51.      printf("[q] Quit \r\n");
  52.      printf("Enter your selection: ");
  53.  }
  54.  
  55.  void param_menu_shell(void)
  56.  {
  57.      char c;
  58.      char cmd_buf[256];
  59.      char name_buf[20];
  60.      char val_buf[256];
  61.     
  62.       while (1)
  63.      {
  64.          param_menu_usage();
  65.          c = awaitkey(-1, NULL);
  66.          printf("%c\n", c);
  67.          switch (c)
  68.          {
  69.              case 'v':
  70.              {
  71.                  strcpy(cmd_buf, "printenv ");
  72.                  printf("Name(enter to view all paramters): ");
  73.                  readline(NULL);
  74.                  strcat(cmd_buf, console_buffer);
  75.                  run_command(cmd_buf, 0);
  76.                  break;
  77.              }
  78.             
  79.               case 's':
  80.              {
  81.                  sprintf(cmd_buf, "setenv ");
  82.                  printf("Name: ");
  83.                  readline(NULL);
  84.                  strcat(cmd_buf, console_buffer);
  85.                  printf("Value: ");
  86.                  readline(NULL);
  87.                  strcat(cmd_buf, " ");
  88.                  strcat(cmd_buf, console_buffer);
  89.                  run_command(cmd_buf, 0);
  90.                  break;
  91.              }
  92.             
  93.               case 'd':
  94.              {
  95.                  sprintf(cmd_buf, "setenv ");
  96.                  printf("Name: ");
  97.                  readline(NULL);
  98.                  strcat(cmd_buf, console_buffer);
  99.                  run_command(cmd_buf, 0);
  100.                  break;
  101.              }
  102.             
  103.               case 'w':
  104.              {
  105.                  sprintf(cmd_buf, "saveenv");
  106.                  run_command(cmd_buf, 0);
  107.                  break;
  108.              }
  109.             
  110.               case 'q':
  111.              {
  112.                  return;
  113.                  break;
  114.              }
  115.          }
  116.      }
  117.  }
  118.  
  119.  void main_menu_usage(void)
  120.  {
  121.      printf("\r\n##### 100ask Bootloader for OpenJTAG #####\r\n");
  122.      printf("[n] Download u-boot to Nand Flash\r\n");
  123.   if (bBootFrmNORFlash())
  124.       printf("[o] Download u-boot to Nor Flash\r\n");
  125.      printf("[k] Download Linux kernel uImage\r\n");
  126.      printf("[j] Download root_jffs2 image\r\n");
  127.  // printf("[c] Download root_cramfs image\r\n");
  128.      printf("[y] Download root_yaffs image\r\n");
  129.      printf("[d] Download to SDRAM & Run\r\n");
  130.      printf("[z] Download zImage into RAM\r\n");
  131.      printf("[g] Boot linux from RAM\r\n");
  132.      printf("[f] Format the Nand Flash\r\n");
  133.      printf("[s] Set the boot parameters\r\n");
  134.      printf("[b] Boot the system\r\n");
  135.      printf("[r] Reboot u-boot\r\n");
  136.      printf("[q] Quit from menu\r\n");
  137.      printf("Enter your selection: ");
  138.  }
  139.  
  140.  void menu_shell(void)
  141.  {
  142.      char c;
  143.      char cmd_buf[200];
  144.      char *p = NULL;
  145.      unsigned long size;
  146.      unsigned long offset;
  147.      struct mtd_info *mtd = &nand_info[nand_curr_device];
  148.      while (1)
  149.      {
  150.          main_menu_usage();
  151.          c = awaitkey(-1, NULL);
  152.          printf("%c\n", c);
  153.          switch (c)
  154.          {
  155.     case 'n':
  156.     {
  157.                  strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase bootloader; nand write.jffs2 0x30000000 bootloader $(filesize)");
  158.                  run_command(cmd_buf, 0);
  159.                  break;
  160.     }
  161.              case 'o':
  162.              {
  163.                  if (bBootFrmNORFlash())
  164.                  {
  165.                      strcpy(cmd_buf, "usbslave 1 0x30000000; protect off all; erase 0 +$(filesize); cp.b 0x30000000 0 $(filesize)");
  166.                      run_command(cmd_buf, 0);
  167.                  }
  168.      break;
  169.              }
  170.             
  171.               case 'k':
  172.              {
  173.                  strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase kernel; nand write.jffs2 0x30000000 kernel $(filesize)");
  174.                  run_command(cmd_buf, 0);
  175.                  break;
  176.              }
  177.              case 'j':
  178.              {
  179.                  strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase root; nand write.jffs2 0x30000000 root $(filesize)");
  180.                  run_command(cmd_buf, 0);
  181.                  break;
  182.              }
  183.  #if 0
  184.              case 'c':
  185.              {
  186.                  strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase root; nand write.jffs2 0x30000000 root $(filesize)");
  187.                  run_command(cmd_buf, 0);
  188.                  break;
  189.              }
  190.  #endif
  191.              case 'y':
  192.              {
  193.                  strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase root; nand write.yaffs 0x30000000 root $(filesize)");
  194.                  run_command(cmd_buf, 0);
  195.                  break;
  196.              }
  197.              case 'd':
  198.              {
  199.                  extern volatile U32 downloadAddress;
  200.                  extern int download_run;
  201.                 
  202.                   download_run = 1;
  203.                  strcpy(cmd_buf, "usbslave 1");
  204.                  run_command(cmd_buf, 0);
  205.                  download_run = 0;
  206.                  sprintf(cmd_buf, "go %x", downloadAddress);
  207.                  run_command(cmd_buf, 0);
  208.                  break;
  209.              }
  210.     case 'z':
  211.     {
  212.      strcpy(cmd_buf, "usbslave 1 0x30008000");
  213.      run_command(cmd_buf, 0);
  214.      break;
  215.     }
  216.     case 'g':
  217.     {
  218.      extern void do_bootm_rawLinux (ulong addr);
  219.      do_bootm_rawLinux(0x30008000);
  220.     }
  221.              case 'b':
  222.              {
  223.                  printf("Booting Linux ...\n");
  224.                  strcpy(cmd_buf, "nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0");
  225.                  run_command(cmd_buf, 0);
  226.                  break;
  227.              }
  228.              case 'f':
  229.              {
  230.                  strcpy(cmd_buf, "nand erase ");
  231.                  printf("Start address: ");
  232.                  readline(NULL);
  233.                  strcat(cmd_buf, console_buffer);
  234.                  printf("Size(eg. 4000000, 0x4000000, 64m and so on): ");
  235.                  readline(NULL);
  236.                  p = console_buffer;
  237.                  size = memsize_parse2(p, &p);
  238.                  sprintf(console_buffer, " %x", size);
  239.                  strcat(cmd_buf, console_buffer);
  240.                  run_command(cmd_buf, 0);
  241.                  break;
  242.              }
  243.              case 's':
  244.              {
  245.                  param_menu_shell();
  246.                  break;
  247.              }
  248.              case 'r':
  249.              {
  250.      strcpy(cmd_buf, "reset");
  251.      run_command(cmd_buf, 0);
  252.                  break;
  253.              }
  254.             
  255.               case 'q':
  256.              {
  257.                  return;
  258.                   break;
  259.              }
  260.          }
  261.                 
  262.       }
  263.  }
  264.  int do_menu (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  265.  {
  266.      menu_shell();
  267.      return 0;
  268.  }
  269.  U_BOOT_CMD(
  270.   menu, 3, 0, do_menu,
  271.   "menu - display a menu, to select the items to do something\n",
  272.   " - display a menu, to select the items to do something"
  273.  );



TFTP下载:

点击(此处)折叠或打开

  1. #include <common.h>
  2.  #include <command.h>
  3.  /**功能:等待键盘输入***/
  4.  static char awaitkey(unsigned long delay, int* error_p)
  5.  {
  6.      int i;
  7.      char c;
  8.      if (delay == -1) {
  9.          while (1) {
  10.              if (tstc()) /* we got a key press */
  11.                  return getc();
  12.          }
  13.      }
  14.      else {
  15.           for (i = 0; i < delay; i++) {
  16.        if (tstc()) /* we got a key press */
  17.         return getc();
  18.              udelay (10*1000);
  19.          }
  20.      }
  21.      if (error_p)
  22.          *error_p = -1;
  23.      return 0;
  24.  }
  25.  /*****提示符,功能说明****/
  26.  void main_menu_usage(void)
  27.  {
  28.   printf("\r\n######## Hotips TFTP DownLoad for SMDK2440 ########\r\n");
  29.   printf("\r\n");
  30.   printf("[1] 下载 u-boot.bin 写入 Nand Flash\r\n");
  31.   printf("[2] 下载 Linux(uImage) 内核镜像写入 Nand Flash\r\n");
  32.   printf("[3] 下载 yaffs2(fs.yaffs) 文件系统镜像写入 Nand Flash\r\n");
  33.   printf("[4] 下载 Linux(uImage) 内核镜像到内存并运行\r\n");
  34.   printf("[5] 重启设备\r\n");
  35.   printf("[q] 退出菜单\r\n");
  36.   printf("\r\n");
  37.   printf("输入选择: ");
  38.  }
  39.  /***do_menu()的调用函数,命令的具体实现***/
  40.   
  41.  void menu_shell(void)
  42.  {
  43.      char c;
  44.      char cmd_buf[200];
  45.      while (1)
  46.      {
  47.        main_menu_usage();
  48.        c = awaitkey(-1, NULL);
  49.        printf("%c\n", c);
  50.        switch (c)
  51.        {
  52.    case '1':
  53.    {
  54.            strcpy(cmd_buf, "tftp 0x32000000 u-boot.bin; nand erase 0x0 0x60000; nand write 0x32000000 0x0 0x60000");
  55.            run_command(cmd_buf, 0);
  56.            break;
  57.    }
  58.          case '2':
  59.          {
  60.            strcpy(cmd_buf, "tftp 0x32000000 uImage; nand erase 0x80000 0x200000; nand write 0x32000000 0x80000 0x200000");
  61.            run_command(cmd_buf, 0);
  62.       break;
  63.          }
  64.          case '3':
  65.          {
  66.            strcpy(cmd_buf, "tftp 0x32000000 fs.yaffs; nand erase 0x280000; nand write.yaffs2 0x32000000 0x280000 $(filesize)");
  67.            run_command(cmd_buf, 0);
  68.            break;
  69.          }
  70.    case '4':
  71.          {
  72.            strcpy(cmd_buf, "tftp 0x32000000 uImage; bootm 0x32000000");
  73.            run_command(cmd_buf, 0);
  74.            break;
  75.          }
  76.    case '5':
  77.          {
  78.            strcpy(cmd_buf, "reset");
  79.            run_command(cmd_buf, 0);
  80.            break;
  81.          }
  82.          case 'q':
  83.          {
  84.            return;
  85.             break;
  86.          }
  87.        }
  88.      }
  89.  }
  90.  int do_menu (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  91.  {
  92.      menu_shell();
  93.      return 0;
  94.  }
  95.  U_BOOT_CMD(
  96.   menu, 1, 0, do_menu,
  97.   "Download Menu",
  98.   "U-boot Download Menu by Hotips\n"
  99.  );


对比两种下载方式我们清楚命令的添加和执行方式了。
转自:http://www.cnblogs.com/sdphome/archive/2011/08/19/2146327.html


阅读(1874) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~