微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 打通linux的tty驱动的数据链路

打通linux的tty驱动的数据链路

时间:10-08 来源:互联网 点击:

c);

}

在函数的最后,初始化了一个工作队列。

而这个队列在什么时候调度呢,在驱动层里receive_chars的最后调用了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->commit = tty->buf.tail->used;spin_unlock_irqrestore(tty->buf.lock, flags);

if (tty->low_latency)

flush_to_ldisc(tty->buf.work.work);else schedule_delayed_work(tty->buf.work, 1);

}

那么,在push数据到tty_buffer的时候有两种方式,一种是flush_to_ldisc,另一种就是调度tty缓冲区的工作队列。

flush_to_ldisc是队列调用的函数:

static void flush_to_ldisc(struct work_struct *work)

{

……

while((head = tty->buf.head) != NULL) {

………

count= head->commit – head->read;

………

char_buf= head->char_buf_ptr + head->read;

flag_buf= head->flag_buf_ptr + head->read;

head->read+= count;

disc->ops->receive_buf(tty,char_buf,

flag_buf,count);

………

}

……

}

这个函数主要的功能是,从tty_buffer中找到数据缓冲区char_buf_ptr,并将这个缓冲区指针传递给线路规程的操作函数receive_buf.再来看receive_buf:

static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char*cp,

char *fp, int count)

{

……

if(tty->real_raw) {

………

memcpy(tty->read_buf+ tty->read_head, cp, i);

………

}else{

………

switch(flags) {

caseTTY_NORMAL:

n_tty_receive_char(tty,*p);

break;

……

}

if(tty->ops->flush_chars)

tty->ops->flush_chars(tty);

………

}

………

}

从上面这段代码可以看到,if条件成立,明显地是拷贝数据进tty的read_buf;进入else,在正常的状态下会调用n_tty_receive_char,然后会调用put_tty_queue,在这个函数里最终还是把数据拷贝到tty的read_buf中。

到此,tty驱动的读操作数据链路基本上连通了。

uart_write:

static int uart_write(struct tty_struct *tty,

const unsigned char *buf, int count)

{

……

port= state->uart_port;

circ= state->xmit;

……

while(1){

c= CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);

………

memcpy(circ->buf+ circ->head, buf, c);

………

}

……

uart_start(tty);

return ret;

}

上面代码的意思是把要写的数据拷贝到state的缓冲区里。然后调用uart_start.

static void __uart_start(struct tty_struct *tty)

{

struct uart_state *state = tty->driver_data;

struct uart_port *port = state->uart_port;

if(!uart_circ_empty(state->xmit) state->xmit.buf

!tty->stopped !tty->hw_stopped)

port->ops->start_tx(port);

}

调用了uart_port的操作函数集的start_tx.

static void serial8250_start_tx(struct uart_port *port)

{

struct uart_8250_port *up = container_of(port, struct uart_8250_port, port);

……

transmit_chars(up);

………

}

在transmit_chars中会把state->xmit缓冲区的数据写进串口发送数据寄存器,也就是数据到达硬件层。到此,写操作的数据链路也连通。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top