怎样在uboot上创建菜单(menu)?
一、原理
uboot菜单其实就是一个uboot中的命令,和其他的命令没有什么差别。
uboot启动时,如果进入uboot命令模式,先运行这个命令,就会打印出一个菜单界面。在uboot的命令模式,通过键入“menu”命令,同样可以调出这个界面。
二、操作步骤
1、在uboot的common目录下创建cmd_menu.c, 定义一个uboot cmd:
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"
);
cmd的名为 menu ,执行的动作是do_menu函数。
实现do_menu:
int do_menu (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
tftp_menu_shell();
return 0;
}
然后继续完善cmd_menu.c,内容如下:
#include <common.h>
#include <command.h>
#ifdef CONFIG_CMD_MENU
#define USE_TFTP_DOWN 1
#define USE_USB_DOWN 2
extern char console_buffer[];
/*
* Reads and returns a character from the serial port
* - Times out after delay iterations checking for presence of character
* - Sets *error_p to UART error bits or - on timeout
* - On timeout, sets *error_p to -1 and returns 0
*/
static char awaitkey(unsigned long delay, int* error_p)
{
int i;
char c;
if (delay == -1) {
while (1) {
if (tstc()) /* we got a key press */
return getc();
}
}
else {
for (i = 0; i < delay; i++) {
if (tstc()) /* we got a key press */
return getc();
udelay (10*1000);
}
}
if (error_p)
*error_p = -1;
return 0;
}
static int bBootFrmNORFlash(void)
{
volatile unsigned int *pdw = (volatile unsigned int *)0;
unsigned int dwVal;
dwVal = *pdw;
*pdw = 0x12345678;
if (*pdw != 0x12345678)
{
return 1;
}
else
{
*pdw = dwVal;
return 0;
}
}
void main_menu_usage(char menu_type)
{
if (bBootFrmNORFlash())
printf("\r\n##### Boot for Nor Flash Main Menu #####\r\n");
else
printf("\r\n##### Boot for Nand Flash Main Menu #####\r\n");
if( menu_type == USE_USB_DOWN)
{
printf("##### EmbedSky USB download mode #####\r\n\n");
}
else if( menu_type == USE_TFTP_DOWN)
{
printf("##### EmbedSky TFTP download mode #####\r\n\n");
}
if( menu_type == USE_USB_DOWN)
{
printf("[1] Download u-boot or STEPLDR.nb1 or other bootloader to Nand Flash\r\n");
}
else if( menu_type == USE_TFTP_DOWN)
{
printf("[1] Download u-boot.bin to Nand Flash\r\n");
}
printf("[2] Download Eboot (eboot.nb0) to Nand Flash\r\n");
printf("[3] Download Linux Kernel (zImage.bin) to Nand Flash\r\n");
if( menu_type == USE_USB_DOWN)
{
#ifdef CONFIG_SURPORT_WINCE
printf("[4] Download WinCE NK.bin to Nand Flash\r\n");
#endif
printf("[5] Download CRAMFS image to Nand Flash\r\n");
}
else if( menu_type == USE_TFTP_DOWN)
{
printf("[4] Download stepldr.nb1 to Nand Flash\r\n");
printf("[5] Set TFTP parameters(PC IP,TQ2440 IP,Mask IP...)\r\n");
}
printf("[6] Download YAFFS image (root.bin) to Nand Flash\r\n");
printf("[7] Download Program (uCOS-II or TQ2440_Test) to SDRAM and Run it\r\n");
printf("[8] Boot the system\r\n");
printf("[9] Format the Nand Flash\r\n");
printf("[0] Set the boot parameters\r\n");
printf("[a] Download User Program (eg: uCOS-II or TQ2440_Test)\r\n");
printf("[b] Download LOGO Picture (.bin) to Nand Flash \r\n");
printf("[l] Set LCD Parameters \r\n");
if( menu_type == USE_USB_DOWN)
{
printf("[n] Enter TFTP download mode menu \r\n");
}
if (bBootFrmNORFlash())
printf("[o] Download u-boot to Nor Flash\r\n");
if( menu_type == USE_TFTP_DOWN)
printf("[p] Test network (TQ2440 Ping PC's IP) \r\n");
printf("[r] Reboot u-boot\r\n");
printf("[t] Test Linux Image (zImage)\r\n");
if( menu_type == USE_USB_DOWN)
{
printf("[q] quit from menu\r\n");
}
else if( menu_type == USE_TFTP_DOWN)
{
printf("[q] Return main Menu \r\n");
}
printf("Enter your selection: ");
}
void tftp_menu_shell(void)
{
char c;
char cmd_buf[200];
while (1)
{
main_menu_usage(USE_TFTP_DOWN);
c = awaitkey(-1, NULL);
printf("%c\n", c);
switch (c)
{
case '1':
{
strcpy(cmd_buf, "tftp 0x30000000 u-boot.bin; nand erase bios; nand write.jffs2 0x30000000 bios $(filesize)");
run_command(cmd_buf, 0);
break;
}
case '2':
{
sprintf(cmd_buf, "tftp 0x30000000 eboot.nb0; nand erase eboot; nand write.jffs2 0x30000000 eboot $(filesize)");
run_command(cmd_buf, 0);
break;
}
case '3':
{
strcpy(cmd_buf, "tftp 0x30000000 zImage.bin; nand erase kernel; nand write.jffs2 0x30000000 kernel $(filesize)");
run_command(cmd_buf, 0);
break;
}
case '4':
{
strcpy(cmd_buf, "tftp 0x30000000 stepldr.nb1; nand erase kernel; nand write.jffs2 0x30000000 kernel $(filesize)");
run_command(cmd_buf, 0);
break;
}
case '5':
{
char param_buf1[25];
char param_buf2[25];
char param_buf3[25];
printf("Enter the TFTP Server(PC) IP address:(xxx.xxx.xxx.xxx)\n");
readline(NULL);
strcpy(param_buf1,console_buffer);
sprintf(cmd_buf, "setenv serverip %s",param_buf1);
run_command(cmd_buf, 0);
printf("Enter the SKY2440/TQ2440 IP address:(xxx.xxx.xxx.xxx)\n");
readline(NULL);
strcpy(param_buf2,console_buffer);
sprintf(cmd_buf, "setenv ipaddr %s",param_buf2);
run_command(cmd_buf, 0);
printf("Enter the Mask IP address:(xxx.xxx.xxx.xxx)\n");
readline(NULL);
strcpy(param_buf3,console_buffer);
sprintf(cmd_buf, "setenv netmask %s",param_buf3);
run_command(cmd_buf, 0);
printf("Save TFTP IP parameters?(y/n)\n");
if (getc() == 'y' )
{
printf("y");
getc() == '\r';
printf("\n");
sprintf(cmd_buf, "saveenv");
run_command(cmd_buf, 0);
}
else
{
printf("Not Save it!!!\n");
}
break;
}
case '6':
{
strcpy(cmd_buf, "tftp 0x30000000 root.bin; nand erase root; nand write.yaffs 0x30000000 root $(filesize)");
run_command(cmd_buf, 0);
break;
}
case '7':
{
char tftpaddress[12];
char filename[32];
printf("Enter downloads to SDRAM address:\n");
readline(NULL);
strcpy(tftpaddress, console_buffer);
printf("Enter program name:\n");
readline(NULL);
strcpy(filename, console_buffer);
sprintf(cmd_buf, "tftp %s %s", tftpaddress, filename);
printf("tftp %s %s\n", tftpaddress, filename);
run_command(cmd_buf, 0);
sprintf(cmd_buf, "go %s", tftpaddress);
run_command(cmd_buf, 0);
break;
}
case '8':
{
printf("Start Linux ...\n");
strcpy(cmd_buf, "boot_zImage");
run_command(cmd_buf, 0);
break;
}
case '9':
{
strcpy(cmd_buf, "nand scrub ");
run_command(cmd_buf, 0);
// erase_menu_shell();
break;
}
case 'A':
case 'a':
{
char filename[32];
printf("Enter program name:\n");
readline(NULL);
strcpy(filename, console_buffer);
sprintf(cmd_buf, "tftp 0x30000000 %s; nand erase 0x0 $(filesize+1); nand write.jffs2 0x30000000 0x0 $(filesize+1)", filename);
run_command(cmd_buf, 0);
break;
}
case 'B':
case 'b':
{
strcpy(cmd_buf, "tftp 0x30000000 logo.bin; nand erase logo; nand write.jffs2 0x30000000 logo $(filesize)");
run_command(cmd_buf, 0);
break;
}
case 'O':
case 'o':
{
if (bBootFrmNORFlash())
{
strcpy(cmd_buf, "tftp 0x30000000 uboot.bin; protect off all; erase 0 +$(filesize); cp.b 0x30000000 0 $(filesize)");
run_command(cmd_buf, 0);
}
break;
}
case 'P':
case 'p':
{
char *serverip;
serverip=getenv("serverip");
printf("TQ2440 ping PC IP:ping %s\n",serverip);
sprintf(cmd_buf, "ping %s",serverip);
run_command(cmd_buf, 0);
break;
}
case 'R':
case 'r':
{
strcpy(cmd_buf, "reset");
run_command(cmd_buf, 0);
break;
}
case 'T':
case 't':
{
strcpy(cmd_buf, "tftp 0x30008000 zImage.bin; test_zImage");
run_command(cmd_buf, 0);
break;
}
case 'Q':
case 'q':
{
return;
break;
}
default: ;
}
}
}
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"
);
int do_menu (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
tftp_menu_shell();
return 0;
}
#endif /* #ifdef CONFIG_CMD_MENU */
2、新建一个名为:cmd_menu.c的文件,放到common目录下,修改同目录下的Makefile文件,加入编译选项:
COBJS-$(CONFIG_CMD_MENU) += cmd_menu.o
3、修改common/main.c,调用菜单命令(menu), 加上一行:
ifdef CONFIG_CMD_MENU
run_command("menu", 0);
endif
if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
# ifdef CONFIG_AUTOBOOT_KEYED
int prev = disable_ctrlc(1); /* disable Control C checking */
# endif
# ifndef CFG_HUSH_PARSER
run_command (s, 0);
# else
parse_string_outer(s, FLAG_PARSE_SEMICOLON |
FLAG_EXIT_FROM_LOOP);
# endif
# ifdef CONFIG_AUTOBOOT_KEYED
disable_ctrlc(prev); /* restore Control C checking */
# endif
}
#ifdef CONFIG_CMD_MENU
run_command("menu", 0);
#endif
4、修改开发板相关的头文件,这里修改:include/configs/TQ2440.h
增加一行:
#define CONFIG_CMD_MENU 1
然后重新编译uboot,烧写到开发板即可看到uboot 菜单。
-THE END-
关注公众号baiwenkeji第一时间获得嵌入式干货。
技术交流加个人威信13266630429,验证:****博客