串口通信picocom源码解析
一.Main入口分析
picocom.c文件是main入口文件,与其他程序一样,先进行初始化:
int
main (int argc, char *argv[])
{
....
parse_args(argc, argv);//参数设置
establish_signal_handlers();//信号中断处理
r = term_lib_init();//terminal 初始化
...
//日志初始化
log_fd = open(opts.log_filename,
O_CREAT | O_RDWR | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
...
//串口初始化
tty_fd = open(opts.port, O_RDWR | O_NONBLOCK | O_NOCTTY);
//这个函数进行串口参数设置
term_set(...)
/****** 下面代码进行2次set_dtr_rt();----------- *****/
/* Set DTR and RTS status, as quickly as possible after opening
the serial port (i.e. before configuring it) */
set_dtr_rts();
r = term_apply(tty_fd, 0);
if ( r < 0 )
fatal("failed to config port: %s",
term_strerror(term_errno, errno));
/* Set DTR and RTS status *again* after configuring the port. On
some systems term_apply() resets the status of DTR and / or
RTS */
set_dtr_rts();
/*** ------判断串口读取是否成功,由以下三个参数共同决定-------- ***/
if ( !opts.quiet && !opts.noinit && show_status(1) != 0 )
...
/******* ---------主处理函数------------ ******/
ler = loop();
主处理函数 loop()
通过select遍历文件符集(rdset,wrset),参数opts.exit_after是否设置阻塞时间.
注意memmove与memcpy用法区别.
while ( ! sig_exit ) {
....
r = select(tty_fd + 1, &rdset, &wrset, NULL, ptv);
...
n = read(STI, buff_rd, sizeof(buff_rd));//读一遍STI,即terminal,是否有输入指令
...
n = read(tty_fd, &buff_rd, sizeof(buff_rd));//读一边串口,看是否有输出
...
n = write(tty_fd, tty_q.buff, sz);//写入tty_q.buff,即由STI中读取到的命令,写到串口中
...
}
读取STI分析
以下代码中,tty_q_push函数分析用户在STI中的每一个字符,对enter\删除键等等做处理.
tty_q_push 把每一个字符存入tty_q.buff中,
for ( i = 0; i < n; i++ ) {
c = buff_rd[i];
switch (state) {
case ST_COMMAND:
if ( c == opts.escape ) {
/* pass the escape character down */
if ( tty_q_push((char *)&c, 1) != 1 )
fd_printf(STO, "\x07");
} else {
/* process command key */
if ( do_command(c) )
/* picocom exit */
return LE_CMD;
}
state = ST_TRANSPARENT;
break;
case ST_TRANSPARENT:
if ( ! opts.noescape && c == opts.escape )
state = ST_COMMAND;
else
if ( tty_q_push((char *)&c, 1) != 1 )
fd_printf(STO, "\x07");
break;
default:
assert(0);
break;
}
}