1、浅析redboot如何格式化serial输入和script脚本是怎么被读出来的浅析redboot如何格式化serial输入和script脚本是怎么被读出来的浅析redboot如何格式化serial输入和script脚本是怎么被读出来的 redboot的交互过程类似于linux中的shell,redboot中设计的交互快捷键,i完全参照了linux下terminal中的快捷键: ctrl+a 将光标移动到输入的所有数据的开头 ctrl+e 将光标移动到输入的所有数据的末尾 ctrl+b 将光标向后移动 ctrl+f 将光标向前移动 ctrl+d 删除光标所在字符 ctrl+k 将光标之后的所有内
2、容删除掉 还有一个快捷键redboot没有实现,即:ctrl+u,它是将光标之前的所有数据清除 ctrl+p 查询前一个历史命令 ctrl+n 查询下一个历史命令来看看源码实现:voidcyg_start(void) . static char lineCYGPKG_REDBOOT_MAX_CMD_LINE; . unsigned char *hold_script = script; script = (unsigned char *)0; / 下面的_rb_gets()函数将因为script为0,而跳过读取script操作luther.gliethttp res = _rb_gets(li
3、ne, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT); if (res = _GETS_CTRLC) / 如果用户从serial串口输入了ctrl+c组合 script = (unsigned char *)0; / Disable script else script = hold_script; / Re-enable script,这样再次执行_rb_gets()时,就会读取script脚本,然后执行它了 .int_rb_gets(char *buf, int buflen, int timeout) *buf = 0; / Empty b
4、uffer return _rb_gets_preloaded(buf, buflen, timeout);/ 如下对_rb_gets_preloaded返回值含义进行了描述/ Read a line of input from the user/ Return:/ _GETS_OK: n valid characters received/ _GETS_GDB: $ (GDB lead-in)/ _GETS_TIMEOUT: No input before timeout/ _GETS_CTRLC: C typed/int_rb_gets_preloaded(char *buf, int b
5、uflen, int timeout) char *ip = buf; / Insertion point char *eol = buf; / End of line char c; bool res = false; static char last_ch = 0; int _timeout;#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0 / 我们定义该值为16/ Command line history support/ P - Select previous line from history/ N - Select next line from hi
6、story/ A - Move insertion cursor to start of line/ E - Move cursor to end of line/ B - Move cursor back previous character/ F - Move cursor forward next character/ 我们定义CYGNUM_REDBOOT_CMD_LINE_EDITING该值为16#define _CL_NUM_LINES CYGNUM_REDBOOT_CMD_LINE_EDITING / Number of lines to keep / 保持16行数据,类似hist
7、ory / CYGPKG_REDBOOT_MAX_CMD_LINE我们定义为256字节 static char _cl_lines_CL_NUM_LINESCYGPKG_REDBOOT_MAX_CMD_LINE; / 循环缓冲区指针 static int _cl_index = -1; / Last known command line static int _cl_max_index = -1; / Last command in buffers int _index = _cl_index; / Last saved line char *xp;#endif / Display curre
8、nt buffer data while (*eol) / 先drain空buf中的内容,如果有的话 mon_write_char(*eol+); ip = eol; / insert point插入点指针 while (true) #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT / 我们定义了该宏 if (getc_script(&c) / 从script脚本中读取一个字节数据,同时script+,源码见后 do_idle(false); / 执行定义的idle函数,源码见后 else#endif if (timeout 0) & (eol = buf) / 所以如果我们
9、只是输入了几个字符串在minicom中,而并不按回车,那么程序将 / 永远停留在下面的mon_read_char(&c);上#define MIN_TIMEOUT 50 _timeout = timeout MIN_TIMEOUT ? MIN_TIMEOUT : timeout; mon_set_read_char_timeout(_timeout); while (timeout 0) / 最大超时_timeout,等待serial串口数据到来 res = mon_read_char_with_timeout(&c); if (res) / Got a character / 从serail
10、读到一个字符 do_idle(false); / 再次尝试执行idle函数 break; timeout -= _timeout; if (res = false) do_idle(true); return _GETS_TIMEOUT; / Input timed out else mon_read_char(&c); / 读一个字符 *eol = 0; switch (c) #define CTRL(c) (c)&0x1F)#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0 case CTRL(P): / Fetch the previous line int
11、o the buffer if (_index = 0) / Erase the previous line crude / 发送b让minicom向后退格一个字符,然后退格 while (ip != buf) / 删除上面mon_write_char(*eol+);发送出去的字符,如果发送了的话. mon_write_char(b); mon_write_char( ); / 发送 覆盖原有数据,所以这样看上去minicom就删除了一个字符 mon_write_char(b); ip-; / 现在ip等于buf了 strcpy(buf, _cl_lines_index); / 将前一个cmd
12、从_cl_lines取出来 while (*ip) mon_write_char(*ip+); / 将命令通过serial发送给minicom. eol = ip; / eol等于当前插入缓冲区指针ip / Move to previous line _index-; / 调整到前一个命令行历史记录 if (_index = 0) if (+_index _cl_max_index) _index = 0; / Erase the previous line crude while (ip != buf) mon_write_char(b); mon_write_char( ); mon_wr
13、ite_char(b); ip-; strcpy(buf, _cl_lines_index); while (*ip) mon_write_char(*ip+); eol = ip; else mon_write_char(0x07); / Audible bell on most devices break; case CTRL(B): / Move insertion point backwards / 向后移动光标,ip当前insert point减减,eof不变 if (ip != buf) mon_write_char(b); ip-; break; case CTRL(F): /
14、Move insertion point forwards / 如果当前ip还没有到eol,那么前移,即,再在此处输出一次同样的字符luther.gliethttp if (ip != eol) mon_write_char(*ip+); break; case CTRL(E): / Move insertion point to end of line / 原理同上 while (ip != eol) mon_write_char(*ip+); break; case CTRL(A): / Move insertion point to beginning of line / 原理同上 if
15、 (ip != buf) xp = eol; / 这里是个bug,应该改为xp = ip;才正常 while (xp- != buf) mon_write_char(b); ip = buf; break; case CTRL(K): / 从当前位置一直删除到结尾字符 / Kill to the end of line if (ip != eol) xp = ip; while (xp+ != eol) / 从当前插入指针所在出ip开始输出 空格,一直到eol / 这样原有的数据都因为 而看上去像是被删除了似的 mon_write_char( ); while (-xp != ip) mon_
16、write_char(b); / 退格在退到原来的ip处 eol = ip; / 因为当前ip后的数据已经全部清空,所以当前ip就是eol. break; case CTRL(D): / Erase the character under the cursor if (ip != eol) xp = ip; eol-; / 彻底删除当前ip所指字符,所以eol少1. while (xp != eol) *xp = *(xp+1); mon_write_char(*xp+); mon_write_char( ); / Erases last character mon_write_char(b)
17、; while (xp- != ip) mon_write_char(b); break;#endif / CYGNUM_REDBOOT_CMD_LINE_EDITING case CTRL(C): / C / Abort current input diag_printf(Cn); *buf = 0; / Nothing useful in buffer return _GETS_CTRLC; / ok,收到了ctrl+c组合. case n: case r: / If previous character was the other end-of-line, ignore this one
18、 if (c = n) & (last_ch = r) | (c = r) & (last_ch = n) / 如果前一个是与其配对的另外一个字符,那么退出 c = 0; / 追加0字符串结尾符号 break; / End of line if (console_echo) / 发送回车换行给console,这样console也才能出现回车换行luther.gliethttp mon_write_char(r); mon_write_char(n); last_ch = c; / 记录当前输入#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0 if (cmd_hi
19、story & (buf != eol) / Save current line - only when enabled / 允许作history时,才执行如下操作,将当前serial获得的命令行,存入_cl_lines历史记录缓冲区. if (+_cl_index = _CL_NUM_LINES) _cl_index = 0; if (_cl_index _cl_max_index) _cl_max_index = _cl_index; strcpy(_cl_lines_cl_index, buf); #endif return _GETS_OK; case b: case 0x7F: / DEL if (ip != buf) #if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0 if (ip != eol) ip-; mon_write_char(b); xp = ip; while (xp != (eol-1) *xp = *(xp+1); mon_write_char(*xp+); mon_write_char( ); / Erases last character mon_write_char(b); while (xp- != ip) mon_write_char(b);
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1