Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2603285
  • 博文数量: 877
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 5920
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-05 12:25
个人简介

技术的乐趣在于分享,欢迎多多交流,多多沟通。

文章分类

全部博文(877)

文章存档

2021年(2)

2016年(20)

2015年(471)

2014年(358)

2013年(26)

分类: 嵌入式

2014-03-07 14:09:16

14、u-boot中添加快捷菜单

    在u-boot启动的时候,在3秒之内按下空格键就可以进入快捷菜单,效果如下:
    
    通过串口输入数字,就可以执行相应的功能,例如:启动内核,重启u-boot,下载镜像到NandFlash。

   这个菜单其实就是u-boot中添加的一个命令,u-boot启动时,如果进入下载模式,就先运行这个命令。

    添加一个名为cmd_menu.c的文件到common目录下,该文件的内容如下:
  1. #include
  2. #include
  3. #include <../drivers/usb/slave/def.h>
  4. #include

  5. extern char console_buffer[];
  6. extern int readline (const char *const prompt);
  7. extern char awaitkey(unsigned long delay, int* error_p);

  8. /**
  9.  * Parses a string into a number. The number stored at ptr is
  10.  * potentially suffixed with K (for kilobytes, or 1024 bytes),
  11.  * M (for megabytes, or 1048576 bytes), or G (for gigabytes, or
  12.  * 1073741824). If the number is suffixed with K, M, or G, then
  13.  * the return value is the number multiplied by one kilobyte, one
  14.  * megabyte, or one gigabyte, respectively.
  15.  *
  16.  * @param ptr where parse begins
  17.  * @param retptr output pointer to next char after parse completes (output)
  18.  * @return resulting unsigned int
  19.  */
  20. static unsigned long memsize_parse2 (const char *const ptr, const char **retptr)
  21. {
  22.     unsigned long ret = simple_strtoul(ptr, (char **)retptr, 0);
  23.     int sixteen = 1;

  24.     switch (**retptr) {
  25.         case 'G':
  26.         case 'g':
  27.             ret <<= 10;
  28.         case 'M':
  29.         case 'm':
  30.             ret <<= 10;
  31.         case 'K':
  32.         case 'k':
  33.             ret <<= 10;
  34.             (*retptr)++;
  35.             sixteen = 0;
  36.         default:
  37.             break;
  38.     }

  39.     if (sixteen)
  40.         return simple_strtoul(ptr, NULL, 16);
  41.     
  42.     return ret;
  43. }


  44. void param_menu_usage(void)
  45. {
  46.     printf("\r\n##### Parameter Menu #####\r\n");
  47.     printf("[1] 查看参数\r\n");
  48.     printf("[2] 设置参数 \r\n");
  49.     printf("[3] 删除参数 \r\n");
  50.     printf("[4] 写入参数到flash \r\n");
  51.     printf("[5] 返回 \r\n");
  52.     printf("Enter your selection: ");
  53. }


  54. void param_menu_shell(void)
  55. {
  56.     char c;
  57.     char cmd_buf[256];

  58.     while (1)
  59.     {
  60.         param_menu_usage();
  61.         c = awaitkey(-1, NULL);
  62.         printf("%c\n", c);
  63.         switch (c)
  64.         {
  65.             case '1':
  66.             {
  67.                 strcpy(cmd_buf, "printenv ");
  68.                 printf("Name(enter to view all paramters): ");
  69.                 readline(NULL);
  70.                 strcat(cmd_buf, console_buffer);
  71.                 run_command(cmd_buf, 0);
  72.                 break;
  73.             }
  74.             
  75.             case '2':
  76.             {
  77.                 sprintf(cmd_buf, "setenv ");

  78.                 printf("Name: ");
  79.                 readline(NULL);
  80.                 strcat(cmd_buf, console_buffer);

  81.                 printf("Value: ");
  82.                 readline(NULL);
  83.                 strcat(cmd_buf, " ");
  84.                 strcat(cmd_buf, console_buffer);

  85.                 run_command(cmd_buf, 0);
  86.                 break;
  87.             }
  88.             
  89.             case '3':
  90.             {
  91.                 sprintf(cmd_buf, "setenv ");

  92.                 printf("Name: ");
  93.                 readline(NULL);
  94.                 strcat(cmd_buf, console_buffer);

  95.                 run_command(cmd_buf, 0);
  96.                 break;
  97.             }
  98.             
  99.             case '4':
  100.             {
  101.                 sprintf(cmd_buf, "saveenv");
  102.                 run_command(cmd_buf, 0);
  103.                 break;
  104.             }
  105.             
  106.             case '5':
  107.             {
  108.                 return;
  109.                 break;
  110.             }
  111.         }
  112.     }
  113. }


  114. void erase_menu_usage(void)
  115. {
  116.     printf("\r\n##### Erase Nand Menu #####\r\n");
  117.     printf("[1] Nand scrub - really clean NAND erasing bad blocks (UNSAFE) \r\n");
  118.     printf("[2] Nand earse - clean NAND eraseing \r\n");
  119.     printf("[q] Return main Menu \r\n");
  120.     printf("Enter your selection: ");
  121. }


  122. void erase_menu_shell(void)
  123. {
  124.     char c;
  125.     char cmd_buf[256];
  126.     char *p = NULL;
  127.     unsigned long size;

  128.     while (1)
  129.     {
  130.         erase_menu_usage();
  131.         c = awaitkey(-1, NULL);
  132.         printf("%c\n", c);
  133.         switch (c)
  134.         {
  135.             case '1':
  136.             {
  137.                 strcpy(cmd_buf, "nand scrub ");
  138.                 run_command(cmd_buf, 0);
  139.                 break;
  140.             }

  141.             case '2':
  142.             {
  143.                 strcpy(cmd_buf, "nand erase ");

  144.                 printf("Start address: ");
  145.                 readline(NULL);
  146.                 strcat(cmd_buf, console_buffer);

  147.                 printf("Size(eg. 4000000, 0x4000000, 64m and so on): ");
  148.                 readline(NULL);
  149.                 p = console_buffer;
  150.                 size = memsize_parse2(p, &p);
  151.                 sprintf(console_buffer, " %x", size);
  152.                 strcat(cmd_buf, console_buffer);

  153.                 run_command(cmd_buf, 0);
  154.                 break;
  155.             }

  156.             case 'q':
  157.             {
  158.                 return;
  159.                 break;
  160.             }
  161.         }
  162.     }
  163. }

  164. void main_menu_usage(void)
  165. {
  166.     printf("[1] 烧写bootloader到nandflash\r\n");
  167.     printf("[2] 烧写Linux Kernel到nandflash\r\n");
  168.     printf("[3] 烧写yaffs2文件系统到nandflash\r\n");
  169.     printf("[4] 下载程序在SDRAM中运行\r\n");
  170.     printf("[5] 设置uboot参数\r\n");
  171.     printf("[6] 格式化Nandflash\r\n");
  172.     printf("[7] 启动Linux系统\r\n");
  173.     printf("[8] 进入Shell模式\r\n");
  174.     printf("[9] 重启uboot\r\n");
  175.     if (bBootFrmNORFlash == 1)
  176.         printf("[0] 下载bootloader到NorFlash\r\n");
  177.     printf("Enter your selection: ");
  178. }


  179. void menu_shell(void)
  180. {
  181.     char c;
  182.     char cmd_buf[200];
  183.     
  184.     while (1)
  185.     {
  186.         main_menu_usage();
  187.         c = awaitkey(-1, NULL);
  188.         printf("%c\n", c);
  189.         switch (c)
  190.         {
  191.             case '1': //download bootloader
  192.             {
  193.                 strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase bios; nand write.jffs2 0x30000000 bios 0x100000");
  194.                 run_command(cmd_buf, 0);
  195.                 break;
  196.             }

  197.             case '2': //kernel
  198.             {
  199.                 strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase kernel; nand write.jffs2 0x30000000 kernel 0x400000");
  200.                 run_command(cmd_buf, 0);                
  201.                 break;
  202.             }

  203.             case '3': //yaffs
  204.             {
  205.                 strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase root; nand write.yaffs 0x30000000 root $(filesize)");
  206.                 run_command(cmd_buf, 0);
  207.                 break;
  208.             }

  209.             case '4': //sdram
  210.             {
  211.                 extern volatile U32 downloadAddress;
  212.                 extern int download_run;
  213.                 
  214.                 download_run = 1;
  215.                 strcpy(cmd_buf, "usbslave 1 0x30000000");
  216.                 run_command(cmd_buf, 0);
  217.                 download_run = 0;
  218.                 sprintf(cmd_buf, "go %x", downloadAddress);
  219.                 run_command(cmd_buf, 0);
  220.                 break;
  221.             }

  222.             case '5': //set param
  223.             {
  224.                 param_menu_shell();
  225.                 break;
  226.             }
  227.             
  228.             case '6': //format
  229.             {
  230.                 erase_menu_shell();
  231.                 break;
  232.             }

  233.             case '7': //boot
  234.             {
  235.                 printf("Start Linux ...\n");
  236.                 strcpy(cmd_buf, "nand read 0x30008000 0x120000 0x400000; go 0x30008000");
  237.                 run_command(cmd_buf, 0);
  238.                 break;
  239.             }

  240.             case '8': //quit
  241.             {
  242.                 return;    
  243.                 break;
  244.             }

  245.             case '9': //reset
  246.             {
  247.                 strcpy(cmd_buf, "reset");
  248.                 run_command(cmd_buf, 0);
  249.                 break;
  250.             }
  251.             
  252.             case '0': //download uboot to NOR
  253.             {
  254.                 if (bBootFrmNORFlash == 1)
  255.                 {
  256.                     strcpy(cmd_buf, "usbslave 1 0x30000000; protect off all; erase 0 +$(filesize); cp.b 0x30000000 0 $(filesize)");
  257.                     run_command(cmd_buf, 0);
  258.                 }
  259.                 break;
  260.             }

  261.         }
  262.                 
  263.     }
  264. }

  265. int do_menu (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  266. {
  267.     menu_shell();
  268.     return 0;
  269. }

  270. U_BOOT_CMD(
  271.     menu,    3,    0,    do_menu,
  272.     "menu - display a menu, to select the items to do something\n",
  273.     " - display a menu, to select the items to do something"
  274. );
     
    修改common目录下的Makefile文件,加入cmd_menu.c的编译选项,代码如下:
  1. COBJS-$(CONFIG_UPDATE_TFTP) += update.o
  2. COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
  3. COBJS-$(CONFIG_CMD_MENU) += cmd_menu.o
    然后修改smdk2440.h文件,添加CONFIG_CMD_MENU命令,这样就会编译cmd_menu.c文件,修改的代码如下:
  1. #define CONFIG_CMD_CACHE
  2. #define CONFIG_CMD_DATE
  3. #define CONFIG_CMD_ELF
  4. #define CONFIG_CMD_NAND
  5. #define CONFIG_CMD_MTDPARTS 
  6. #define CONFIG_CMD_PING 
  7. #define CONFIG_CMD_MENU 

    在main.c的main_loop函数中调用menu命令,在bootdelay时间没有按下空格键,如果是NorFlash启动的话则运行menu命令,如果是NandFlash启动则启动linux内核,修改代码如下:

  1. if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
  2. # ifdef CONFIG_AUTOBOOT_KEYED
  3.         int prev = disable_ctrlc(1);    /* disable Control C checking */
  4. # endif

  5. #ifdef CONFIG_CMD_MENU
  6.     if (bBootFrmNORFlash == 1)    
  7.     {
  8.         run_command("menu", 0);    
  9.     }
  10.     else
  11.     {
  12.         printf("Booting Linux ...\n");
  13.     }
  14. #else
  15.     printf("Booting Linux ...\n");
  16. #endif    
    
     u-boot源代码中,在bootdelay时间内按下空格键的话,则会进入shell命令行模式,我们修改代码使其运行menu命令,进入快捷菜单界面,修改的代码如下:

  1. #ifdef CONFIG_AMIGAONEG3SE
  2.     {
  3.      extern void video_banner(void);
  4.      video_banner();
  5.     }
  6. #endif

  7. #ifdef CONFIG_CMD_MENU
  8.     run_command("menu", 0);
  9. #endif

    另外,在start.S文件中定义变量bBootFrmNORFlash,如果是从NorFlash驱动的话,则把该变量置为1,修改的代码如下:
  1. .globl _bss_start
  2. _bss_start:
  3.     .word __bss_start

  4. .globl _bss_end
  5. _bss_end:
  6.     .word _end
  7.    
  8. .globl bBootFrmNORFlash      
  9. bBootFrmNORFlash:
  10.     .word 0

  在NorFlash启动的时候,把该变量置1
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0]    */
stmia r1!, {r3-r10} /* copy to   target address [r1]    */
cmp r0, r2 /* until source end addreee [r2]    */
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */

SetBootFlag:
ldr r0, =bBootFrmNORFlash
mov r1, #1
str r1, [r0]

/* Set up the stack     */
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot   */
sub r0, r0, #CONFIG_SYS_MALLOC_LEN
sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */


    修改include/asm-arm/目录下的u-boot-arm.h文件,这样在main.c里就可以使用bBootFrmNORFlash这个变量了,修改的代码如下:
  1. extern ulong IRQ_STACK_START;    /* top of IRQ stack */
  2. extern ulong FIQ_STACK_START;    /* top of FIQ stack */
  3. extern ulong bBootFrmNORFlash; 
    
    重新编译u-boot,下载到NandFlash中,就可以看到效果了。

    我们还可以继续修改代码,添加自己的打印消息,如下所示:

    在main.c中添加一个show_myinfo函数,修改的代码如下:
  1. static void show_myinfo(void)
  2. {
  3.     printf("****************************************\n");
  4.     printf("******* zjw 制作 2012.10.20 ********\n");
  5.     printf("*** u-boot-2010.03 for smdk2440 ***\n");
  6.     if (bBootFrmNORFlash == 1)
  7.         printf("*** NorFlash启动方式 ***\n");
  8.     else
  9.         printf("*** NandFlash启动方式 ***\n");
  10.     printf("****************************************\n");
  11. }

    在abortboot函数中调用show_myinfo函数,修改的代码如下:
  1. static __inline__ int abortboot(int bootdelay)
  2. {
  3.     int abort = 0;
  4.     show_myinfo(); 

    
    还可以在board.c中继续修改和添加自己的信息,修改version_string[]如下:
  1. const char version_string[] =
  2.     U_BOOT_VERSION"<-->"CONFIG_IDENT_STRING;
   
    在smdk2440.h中定义CONFIG_IDENT_STRING宏,代码如下:
  1. #define CONFIG_IDENT_STRING " zjw modify for SMDK2440 "
   
    修改board.c中的display_banner函数,修改的代码如下:
  1. static int display_banner (void)
  2. {
  3.     printf ("\n\n%s\n\n", version_string);
  4.     printf ("##########********** Board Info **********##########\n");
  5.     debug ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
  6.      _armboot_start, _bss_start, _bss_end);

    修改board.c中的start_armboot函数,修改的代码如下:
  1. printf ("##########******************************##########\n\n"); 
  2.     /* main_loop() can return to retry autoboot, if so just run it again. */
  3.     for (;;) {
  4.         main_loop ();
  5.     }

    最后重新编译u-boot,下载到NandFlas中运行,就会出现如本节最上面的图片一样的效果。

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