浅析redboot如何格式化serial输入和script脚本是怎么被读出来的.docx
《浅析redboot如何格式化serial输入和script脚本是怎么被读出来的.docx》由会员分享,可在线阅读,更多相关《浅析redboot如何格式化serial输入和script脚本是怎么被读出来的.docx(18页珍藏版)》请在冰豆网上搜索。
![浅析redboot如何格式化serial输入和script脚本是怎么被读出来的.docx](https://file1.bdocx.com/fileroot1/2023-2/21/2b7e9188-35a7-4dc8-98fa-8ee438665b4c/2b7e9188-35a7-4dc8-98fa-8ee438665b4c1.gif)
浅析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将光标之后的所有内容删除掉
还有一个快捷键redboot没有实现,即:
ctrl+u,它是将光标之前的所有数据清除
ctrl+p查询前一个历史命令
ctrl+n查询下一个历史命令
来看看源码实现:
void
cyg_start(void)
{
......
staticcharline[CYGPKG_REDBOOT_MAX_CMD_LINE];
......
unsignedchar*hold_script=script;
script=(unsignedchar*)0;//下面的_rb_gets()函数将因为script为0,而跳过读取script操作[luther.gliethttp]
res=_rb_gets(line,sizeof(line),CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
if(res==_GETS_CTRLC){//如果用户从serial串口输入了ctrl+c组合
script=(unsignedchar*)0; //Disablescript
}else{
script=hold_script; //Re-enablescript,这样再次执行_rb_gets()时,就会读取script脚本,然后执行它了
}
......
}
int
_rb_gets(char*buf,intbuflen,inttimeout)
{
*buf='\0'; //Emptybuffer
return_rb_gets_preloaded(buf,buflen,timeout);
}
//如下对_rb_gets_preloaded返回值含义进行了描述
//Readalineofinputfromtheuser
//Return:
// _GETS_OK:
'n'validcharactersreceived
// _GETS_GDB:
'$'(GDBlead-in)
// _GETS_TIMEOUT:
Noinputbeforetimeout
// _GETS_CTRLC:
^Ctyped
//
int
_rb_gets_preloaded(char*buf,intbuflen,inttimeout)
{
char*ip=buf; //Insertionpoint
char*eol=buf; //Endofline
charc;
boolres=false;
staticcharlast_ch='\0';
int_timeout;
#ifCYGNUM_REDBOOT_CMD_LINE_EDITING!
=0//我们定义该值为16
//
//Commandlinehistorysupport
// ^P-Selectpreviouslinefromhistory
// ^N-Selectnextlinefromhistory
// ^A-Moveinsertion[cursor]tostartofline
// ^E-Movecursortoendofline
// ^B-Movecursorback[previouscharacter]
// ^F-Movecursorforward[nextcharacter]
//
//我们定义CYGNUM_REDBOOT_CMD_LINE_EDITING该值为16
#define_CL_NUM_LINESCYGNUM_REDBOOT_CMD_LINE_EDITING //Numberoflinestokeep
//保持16行数据,类似history
//CYGPKG_REDBOOT_MAX_CMD_LINE我们定义为256字节
staticchar_cl_lines[_CL_NUM_LINES][CYGPKG_REDBOOT_MAX_CMD_LINE];
//循环缓冲区指针
staticint _cl_index=-1; //Lastknowncommandline
staticint _cl_max_index=-1; //Lastcommandinbuffers
int_index=_cl_index; //Lastsavedline
char*xp;
#endif
//Displaycurrentbufferdata
while(*eol){
//先drain空buf中的内容,如果有的话
mon_write_char(*eol++);
}
ip=eol;//insertpoint插入点指针
while(true){
#ifdefCYGFUN_REDBOOT_BOOT_SCRIPT
//我们定义了该宏
if(getc_script(&c))//从script脚本中读取一个字节数据,同时script++,源码见后
do_idle(false);//执行定义的idle函数,源码见后
else
#endif
if((timeout>0)&&(eol==buf)){//所以如果我们只是输入了几个字符串在minicom中,而并不按回车,那么程序将
//永远停留在下面的mon_read_char(&c);上
#defineMIN_TIMEOUT50
_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){
//Gotacharacter
//从serail读到一个字符
do_idle(false);//再次尝试执行idle函数
break;
}
timeout-=_timeout;
}
if(res==false){
do_idle(true);
return_GETS_TIMEOUT; //Inputtimedout
}
}else{
mon_read_char(&c);//读一个字符
}
*eol='\0';
switch(c){
#defineCTRL(c)((c)&0x1F)
#ifCYGNUM_REDBOOT_CMD_LINE_EDITING!
=0
caseCTRL('P'):
//Fetchthepreviouslineintothebuffer
if(_index>=0){
//Erasethepreviousline[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从_cl_lines[]取出来
while(*ip){
mon_write_char(*ip++);//将命令通过serial发送给minicom.
}
eol=ip;//eol等于当前插入缓冲区指针ip
//Movetopreviousline
_index--;//调整到前一个命令行历史记录
if(_index<0){
_index=_cl_max_index;//循环到最大处,不保证此处有有效命令
}
}else{
//发送bell铃声数据,minicom会让pc的bios发声
mon_write_char(0x07); //Audiblebellonmostdevices
}
break;
caseCTRL('N'):
//Fetchthenextlineintothebuffer
//操作和上面的'P'操作一致
if(_index>=0){
if(++_index>_cl_max_index)_index=0;
//Erasethepreviousline[crude]
while(ip!
=buf){
mon_write_char('\b');
mon_write_char('');
mon_write_char('\b');
ip--;
}
strcpy(buf,_cl_lines[_index]);
while(*ip){
mon_write_char(*ip++);
}
eol=ip;
}else{
mon_write_char(0x07); //Audiblebellonmostdevices
}
break;
caseCTRL('B'):
//Moveinsertionpointbackwards
//向后移动光标,ip当前insertpoint减减,eof不变
if(ip!
=buf){
mon_write_char('\b');
ip--;
}
break;
caseCTRL('F'):
//Moveinsertionpointforwards
//如果当前ip还没有到eol,那么前移,即,再在此处输出一次同样的字符[luther.gliethttp]
if(ip!
=eol){
mon_write_char(*ip++);
}
break;
caseCTRL('E'):
//Moveinsertionpointtoendofline
//原理同上
while(ip!
=eol){
mon_write_char(*ip++);
}
break;
caseCTRL('A'):
//Moveinsertionpointtobeginningofline
//原理同上
if(ip!
=buf){
xp=eol;//这里是个bug,应该改为xp=ip;才正常
while(xp--!
=buf){
mon_write_char('\b');
}
}
ip=buf;
break;
caseCTRL('K'):
//从当前位置一直删除到结尾字符
//Killtotheendofline
if(ip!
=eol){
xp=ip;
while(xp++!
=eol){
//从当前插入指针所在出ip开始输出''空格,一直到eol
//这样原有的数据都因为''而看上去像是被删除了似的
mon_write_char('');
}
while(--xp!
=ip){
mon_write_char('\b');//退格在退到原来的ip处
}
eol=ip;//因为当前ip后的数据已经全部清空,所以当前ip就是eol.
}
break;
caseCTRL('D'):
//Erasethecharacterunderthecursor
if(ip!
=eol){
xp=ip;
eol--;//彻底删除当前ip所指字符,所以eol少1.
while(xp!
=eol){
*xp=*(xp+1);
mon_write_char(*xp++);
}
mon_write_char(''); //Eraseslastcharacter
mon_write_char('\b');
while(xp--!
=ip){
mon_write_char('\b');
}
}
break;
#endif//CYGNUM_REDBOOT_CMD_LINE_EDITING
caseCTRL('C'):
//^C
//Abortcurrentinput
diag_printf("^C\n");
*buf='\0'; //Nothingusefulinbuffer
return_GETS_CTRLC;//ok,收到了ctrl+c组合.
case'\n':
case'\r':
//Ifpreviouscharacterwasthe"other"end-of-line,ignorethisone
if(((c=='\n')&&(last_ch=='\r'))||
((c=='\r')&&(last_ch=='\n'))){
//如果前一个是与其配对的另外一个字符,那么退出
c='\0';//追加'\0'字符串结尾符号
break;
}
//Endofline
if(console_echo){
//发送回车换行给console,这样console也才能出现回车换行[luther.gliethttp]
mon_write_char('\r');
mon_write_char('\n');
}
last_ch=c;//记录当前输入
#ifCYGNUM_REDBOOT_CMD_LINE_EDITING!
=0
if(cmd_history&&(buf!
=eol)){
//Savecurrentline-onlywhenenabled
//允许作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':
case0x7F:
//DEL
if(ip!
=buf){
#ifCYGNUM_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(''); //Eraseslastcharacter
mon_write_char('\b');
while(xp--!
=ip){
mon_write_char('\b');