uboot源代码中是只要串口中输入任意的字符uboot就进入命令模式。在嵌入式设备中,这是个不太稳定的方式。嵌入式设备一般使用的环境比较复杂,所受的干扰了比较大,系统启动的时候串口易受到干扰而导致误触发输入字符,这样设备就进入了uboot的命令行模式,最终导致系统不能自动启动。为了降低这种干扰,软件端可以设置uboot组合按键进入uboot,这样误触发的概率就降低了。
如果要设置组合按键,需要修改的是/common/main.c 文件。函数原型如下:
abortboot 源函数
static __inline__ int abortboot(int bootdelay)
{
int abort = 0;
#ifdef CONFIG_MENUPROMPT
printf(CONFIG_MENUPROMPT);
#else
printf("Hit any key to stop autoboot: %2d ", bootdelay);
#endif
#if defined CONFIG_ZERO_BOOTDELAY_CHECK
/*
* Check if key already pressed
* Don't check if bootdelay < 0
*/
if (bootdelay >= 0) {
if (tstc()) { /* we got a key press */
(void) getc(); /* consume input */
puts ("\b\b\b 0");
abort = 1; /* don't auto boot */
}
}
#endif
while ((bootdelay > 0) && (!abort)) {
int i;
--bootdelay;
/* delay 100 * 10ms */
for (i=0; !abort && i<100; ++i) {
if (tstc()) { /* we got a key press */
abort = 1; /* don't auto boot */
bootdelay = 0; /* no more delay */
# ifdef CONFIG_MENUKEY
menukey = getc();
# else
(void) getc(); /* consume input */
# endif
break;
}
udelay(10000);
}
printf("\b\b\b%2d ", bootdelay);
}
putc('\n');
#ifdef CONFIG_SILENT_CONSOLE
if (abort)
gd->flags &= ~GD_FLG_SILENT;
#endif
return abort;
}
函数解析
这里涉及到两个函数tstc()和getc()函数,他们的功能如下:
详细函数内容可以参看uboot文档:https://casper.berkeley.edu/svn/trunk/roach/sw/uboot/doc/README.console
如果要修改成CTRL+C/c uboot 才进入命令模式,可以按下面这种方式修改:
修改后的abortboot函数
static __inline__ int abortboot(int bootdelay)
{
int abort = 0;
unsigned long ts;
#ifdef CONFIG_MENUPROMPT
printf(CONFIG_MENUPROMPT);
#else
//printf("Hit any key to stop autoboot: %2d ", bootdelay);
printf("Press 'ctrl+C/c' to stop autoboot: %2d ", bootdelay);
#endif
#if 0
#if defined CONFIG_ZERO_BOOTDELAY_CHECK
/*
* Check if key already pressed
* Don't check if bootdelay < 0
*/
if (bootdelay >= 0) {
if (tstc()) { /* we got a key press */
(void) getc(); /* consume input */
puts ("\b\b\b 0");
abort = 1; /* don't auto boot */
}
}
#endif
#endif
while ((bootdelay > 0) && (!abort)) {
int i;
--bootdelay;
#if 0
/* delay 100 * 10ms */
for (i=0; !abort && i<100; ++i) {
if (tstc()) { /* we got a key press */
abort = 1; /* don't auto boot */
bootdelay = 0; /* no more delay */
# ifdef CONFIG_MENUKEY
menukey = getc();
# else
(void) getc(); /* consume input */
# endif
break;
}
udelay(10000);
}
#else
/* delay 1000 ms */
ts = get_timer(0);
do {
if (tstc()) { /* we got a key press */
if(0x03 == getc()){
abort = 1; /* don't auto boot */
bootdelay = 0; /* no more delay */
# ifdef CONFIG_MENUKEY
menukey = getc();
# else
(void) getc(); /* consume input */
# endif
break;
}
}
udelay(10000);
} while (!abort && get_timer(ts) < 1000);
#endif
printf("\b\b\b%2d ", bootdelay);
}
putc('\n');
#ifdef CONFIG_SILENT_CONSOLE
if (abort)
gd->flags &= ~GD_FLG_SILENT;
#endif
return abort;
}
我使用#if 0 来区分源码和修改后的代码。这里需要注意下面这几行代码:
if(0x03 == getc()){
abort = 1; /* don't auto boot */
bootdelay = 0; /* no more delay */
# ifdef CONFIG_MENUKEY
menukey = getc();
# else
(void) getc(); /* consume input */
# endif
break;
}
}
CTRL+C的ASCII控制符是03,所以直接用了if(0x03 == getc())来判断是否有输入CTRL+C 组合按键。下面是部分ASCII控制码对照表,可以根据自己的需求设置不同的组合按键。
ASCII控制对照表
十进制 | 十六进制 | 控制字符 | 转义字符 | 说明 | Ctrl + 下列字母 |
---|---|---|---|---|---|
0 | 00 | NUL | \0 | Null character(空字符) | @ |
1 | 01 | SOH | Start of Header(标题开始) | A | |
2 | 02 | STX | Start of Text(正文开始) | B | |
3 | 03 | ETX | End of Text(正文结束) | C | |
4 | 04 | EOT | End of Transmission(传输结束) | D | |
5 | 05 | ENQ | Enquiry(请求) | E | |
6 | 06 | ACK | Acknowledgment(收到通知/响应) | F | |
7 | 07 | BEL | \a | Bell(响铃) | G |
8 | 08 | BS | \b | Backspace(退格) | H |
9 | 09 | HT | \t | Horizontal Tab(水平制表符) | I |
10 | 0A | LF | \n | Line feed(换行键) | J |
11 | 0B | VT | \v | Vertical Tab(垂直制表符) | K |
12 | 0C | FF | \f | Form feed(换页键) | L |
13 | 0D | CR | \r | Carriage return(回车键) | M |
14 | 0E | SO | Shift Out(不用切换) | N | |
15 | 0F | SI | Shift In(启用切换) | O | |
16 | 10 | DLE | Data Link Escape(数据链路转义) | P | |
17 | 11 | DC1 | Device Control 1(设备控制1) /XON(Transmit On) | Q | |
18 | 12 | DC2 | Device Control 2(设备控制2) | R | |
19 | 13 | DC3 | Device Control 3(设备控制3) /XOFF(Transmit Off) | S | |
20 | 14 | DC4 | Device Control 4(设备控制4) | T | |
21 | 15 | NAK | Negative Acknowledgement(拒绝接收/无响应) | U | |
22 | 16 | SYN | Synchronous Idle(同步空闲) | V | |
23 | 17 | ETB | End of Trans the Block(传输块结束) | W | |
24 | 18 | CAN | Cancel(取消) | X | |
25 | 19 | EM | End of Medium(已到介质末端/介质存储已满) | Y | |
26 | 1A | SUB | Substitute(替补/替换) | Z | |
27 | 1B | ESC | \e | Escape(溢出/逃离/取消) | [ |
28 | 1C | FS | File Separator(文件分割符) | \ | |
29 | 1D | GS | Group Separator(分组符) | ] | |
30 | 1E | RS | Record Separator(记录分隔符) | ^ | |
31 | 1F | US | Unit Separator(单元分隔符) | _ | |
32 | 20 | SP | White space | [Space] | |
127 | 7F | DEL | Delete(删除) | ? |