问题:输入字符,没有回显,输入命令没有输出
4020使用的串口完全兼容8250,8250调用串口顺序如下:
serial8250_interrupt(串口芯片层)->
seirial8250_handle_port(串口芯片层)->
receive_chars(串口芯片层)->
uart_insert_char(串口抽象层)->
tty_insert_flip_char(终端设备层)//保存受到的数据及其他标记是否有错误
tty_flip_buffer_push(终端设备层)->
flush_to_idisc(终端设备层)->
disc->receive_buf,即n_tty_receive_buf(行规层)->
n_tty_receive_char(行规层)->
n_tty_receive_char(终端设备层)->
echo_char(回显)
可以看出要经过这么多层调用才会出现echo_char(),回显你输入的字符,经过排查,我们发现问题出在tty_io.c的函数:
tty_flip_buffer_push()
void tty_flip_buffer_push(struct tty_struct *tty)
{
unsigned long flags;
spin_lock_irqsave(&tty->buf.lock, flags);
if (tty->buf.tail != NULL) {
tty->buf.tail->active = 0;
tty->buf.tail->commit = tty->buf.tail->used;
}
spin_unlock_irqrestore(&tty->buf.lock, flags);
if (tty->low_latency)
flush_to_ldisc((void *) tty);
else
schedule_delayed_work(&tty->buf.work, 1);
其中
if (tty->low_latency)
flush_to_ldisc((void *) tty);
low_latency的值一直为0,所以进不了flush_to_ldisc()。
在《linux内核驱动第三版》中提到:
“如果 tty 驱动可高速接收数据, tty->low_latency 标志应当设置, 它是对 tty_flip_buffer_pus 的调用被立刻执行当调用时. 否则, tty_flip_buffer_push 调用会调度它自己来将数据推出缓冲, 在之后近期的一个时间点.”
可惜还是不懂是什么意思,跟踪这个函数的赋值情况,发现在serial_core.c以下函数中有调用:
uart_open()
* Once we set tty->driver_data here, we are guaranteed that
* uart_close() will decrement the driver module use count.
* Any failures from here onwards should not touch the count.
*/
tty->driver_data = state;
tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0;
tty->alt_speed = 0;
state->info->tty = tty;
其中这句话tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0;,对low_latency变量进行了赋值,还有个open函数也进行了同样的赋值。
UPF_LOW_LATENCY是一个宏定义,在serial_core.h中有定义:
#define UPF_LOW_LATENCY ((__force upf_t) (1 << 13))
因此赋值语句的含义:是state->port->flags中需要对UPF_LOW_LATENCY位进行赋值。解决方法如下:
在/arch/arm/Machsep-4020/4020.c文件中对uart初始话的flag结构中添加UPF_LOW_LATENCY位
static struct plat_serial8250_port serial_platform_data[] = {
{
.membase = (void*)UART0_BASE_V,
.mapbase = UART0_BASE,
.irq = INTSRC_UART0,
.uartclk = 88000000,
.regshift = 2,
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_LOW_LATENCY,
},
重新编译,可以正确操作控制台输入输出。