Linux下串口读写过程小析

open串口过程 


static const struct file_operations tty_fops = {
	.open		= tty_open,
	.read		= tty_read,
	.write		= tty_write,
};

static struct tty_ldisc_ops n_tty_ops = {
        .open            = n_tty_open,
        .read            = n_tty_read,
        .write           = n_tty_write,
};

static const struct tty_operations uart_ops = {
	.open		= uart_open,
	.write		= uart_write,
};

static const struct uart_ops serial_sprd_ops = {
	.stop_tx = sprd_stop_tx,
	.start_tx = sprd_start_tx,
	.stop_rx = sprd_stop_rx,
	.set_termios = sprd_set_termios,

};

//open
static int tty_open(struct inode *inode, struct file *filp)
{
	struct tty_struct *tty;
	tty = tty_open_by_driver(device, inode, filp);
	retval = tty->ops->open(tty, filp);----->
}

//寻找driver,比如有usb转串口driver,cpu的uart driver
static struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode,struct file *filp)
{
	driver = tty_lookup_driver(device, filp, &index);
			-->tty = tty_init_dev(driver, index);
				tty = alloc_tty_struct(driver, idx);---->tty_ldisc_init(tty);
									tty->ops = driver->ops;
				retval = tty_driver_install_tty(driver, tty);
				retval = tty_ldisc_setup(tty, tty->link);

}

static struct uart_driver sprd_uart_driver = {
	.owner = THIS_MODULE,
	.driver_name = "sprd_serial",
	.dev_name = SPRD_TTY_NAME,
	.major = 0,
	.minor = 0,
	.nr = UART_NR_MAX,
	.cons = SPRD_CONSOLE,
};

static int uart_open(struct tty_struct *tty, struct file *filp)
{

	retval = uart_startup(tty, state, 0);--->retval = uport->ops->startup(uport);
		uart_change_speed(tty, state, NULL);--->uport->ops->set_termios(uport, termios, old_termios);

}

static const struct tty_operations uart_ops = {
	.open		= uart_open,
	.write		= uart_write,

};
int uart_register_driver(struct uart_driver *drv)
{
	tty_set_operations(normal, &uart_ops);--->driver->ops = op;
}

串口发送过程

static ssize_t tty_write(struct file *file, const char __user *buf,size_t count, loff_t *ppos)
{
		ret = do_tty_write(ld->ops->write, tty, file, buf, count);
}

static inline ssize_t do_tty_write(ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char *, size_t),struct tty_struct *tty,struct file *file,const char __user *buf,size_t count)
{
	ret = write(tty, file, tty->write_buf, size);--->n_tty_write
}

static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,const unsigned char *buf, size_t nr)
{
		while (nr > 0) {
			c = tty->ops->write(tty, b, nr);

		}
}

static int uart_write(struct tty_struct *tty,const unsigned char *buf, int count)
{
	while (1) {
		c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
		if (count < c)
			c = count;
		if (c <= 0)
			break;
		memcpy(circ->buf + circ->head, buf, c);
		circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
		buf += c;
		count -= c;
		ret += c;
	}

	__uart_start(tty);

}

static void __uart_start(struct tty_struct *tty)
{
		port->ops->start_tx(port);
}

static void sprd_start_tx(struct uart_port *port)
{
	unsigned int ien;

	ien = serial_in(port, SPRD_IEN);
	if (!(ien & SPRD_IEN_TX_EMPTY)) {
		ien |= SPRD_IEN_TX_EMPTY;
		serial_out(port, SPRD_IEN, ien);
	}
}
//准备好了,把数据发过去
static irqreturn_t sprd_handle_irq(int irq, void *dev_id)
{
	if (ims & SPRD_IMSR_TX_FIFO_EMPTY)
		sprd_tx(port);
}

static inline void sprd_tx(struct uart_port *port)
{
	do {
		serial_out(port, SPRD_TXD, xmit->buf[xmit->tail]);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		port->icount.tx++;
		if (uart_circ_empty(xmit))
			break;
	} while (--count > 0);
}

串口接收过程
//中断来了,开始读数据,并存储 

static irqreturn_t sprd_handle_irq(int irq, void *dev_id){
	ims = serial_in(port, SPRD_IMSR);
	if (ims & (SPRD_IMSR_RX_FIFO_FULL |
		SPRD_IMSR_BREAK_DETECT | SPRD_IMSR_TIMEOUT))
		sprd_rx(port);	
}

static inline void sprd_rx(struct uart_port *port)
{
	struct tty_port *tty = &port->state->port;
	unsigned int ch, flag, lsr, max_count = SPRD_TIMEOUT;

	while ((serial_in(port, SPRD_STS1) & 0x00ff) && max_count--) {
		lsr = serial_in(port, SPRD_LSR);
		ch = serial_in(port, SPRD_RXD);//把数据一个接一个读处理,然后放缓冲区里
		uart_insert_char(port, lsr, SPRD_LSR_OE, ch, flag);--->uart_insert_char--->
	}

	tty_flip_buffer_push(tty);
}

static ssize_t tty_read(struct file *file, char __user *buf, size_t count,loff_t *ppos)
{
		i = ld->ops->read(tty, file, buf, count);--->n_tty_read

}

static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,unsigned char __user *buf, size_t nr)
{
	uncopied = copy_from_read_buf(tty, &b, &nr);
}

你可能感兴趣的:(TTY)