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);
}