一.串口结构体
1.串口驱动结构体
- struct uart_driver {
- struct module *owner; //模块所有者
- const char *driver_name; //驱动名
- const char *dev_name; //设备名
- int major; //主设备号
- int minor; //次设备号
- int nr; //支持串口个数
- struct console *cons; //控制台设备
- struct uart_state *state; //串口状态
- struct tty_driver *tty_driver; //tty设备
- };
2.串口端口结构体
- struct uart_port {
- spinlock_t lock;
- unsigned long iobase; //io端口基地址
- unsigned char __iomem *membase; //内存端口基地址
- unsigned int (*serial_in)(struct uart_port *, int);
- void (*serial_out)(struct uart_port *, int, int);
- void (*set_termios)(struct uart_port *,struct ktermios *new,struct ktermios *old);
- void (*pm)(struct uart_port *, unsigned int state,unsigned int old);
- unsigned int irq; //中断号
- unsigned long irqflags; //中断标志
- unsigned int uartclk;
- unsigned int fifosize; //fifo大小
- unsigned char x_char;
- unsigned char regshift; //寄存器偏移值
- unsigned char iotype; //io访问类型
- unsigned char unused1;
- unsigned int read_status_mask;
- unsigned int ignore_status_mask;
- struct uart_state *state; //uart_state结构体
- struct uart_icount icount; //串口使用计数
- struct console *cons; //console控制台
- #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ)
- unsigned long sysrq;
- #endif
- upf_t flags;
- unsigned int mctrl;
- unsigned int timeout;
- unsigned int type;
- const struct uart_ops *ops; //串口操作函数集
- unsigned int custom_divisor;
- unsigned int line; //端口号
- resource_size_t mapbase;
- struct device *dev; //设备文件
- unsigned char hub6;
- unsigned char suspended;
- unsigned char irq_wake;
- unsigned char unused[2];
- void *private_data;
- };
3.操作函数集
- struct uart_ops {
- unsigned int (*tx_empty)(struct uart_port *); //发送缓冲区为空
- void (*set_mctrl)(struct uart_port *, unsigned int mctrl); //设置串口modem控制模式
- unsigned int (*get_mctrl)(struct uart_port *); //获取串口modem控制模式
- void (*stop_tx)(struct uart_port *); //停止发送
- void (*start_tx)(struct uart_port *); //开始发送
- void (*send_xchar)(struct uart_port *, char ch);
- void (*stop_rx)(struct uart_port *); //停止接收
- void (*enable_ms)(struct uart_port *); //使能modem状态信息
- void (*break_ctl)(struct uart_port *, int ctl);
- int (*startup)(struct uart_port *); //打开串口
- void (*shutdown)(struct uart_port *); //关闭串口
- void (*flush_buffer)(struct uart_port *);
- void (*set_termios)(struct uart_port *, struct ktermios *new,struct ktermios *old); //设置串口参数
- void (*set_ldisc)(struct uart_port *, int new);
- void (*pm)(struct uart_port *, unsigned int state,unsigned int oldstate);
- int (*set_wake)(struct uart_port *, unsigned int state);
- const char *(*type)(struct uart_port *);
- void (*release_port)(struct uart_port *); //释放端口
- int (*request_port)(struct uart_port *); //请求端口
- void (*config_port)(struct uart_port *, int); //配置端口
- int (*verify_port)(struct uart_port *, struct serial_struct *); //校验端口
- int (*ioctl)(struct uart_port *, unsigned int, unsigned long); //控制
- #ifdef CONFIG_CONSOLE_POLL
- void (*poll_put_char)(struct uart_port *, unsigned char);
- int (*poll_get_char)(struct uart_port *);
- #endif
- };
4.uart_state
- struct uart_state {
- struct tty_port port;
- int pm_state;
- struct circ_buf xmit;
- struct tasklet_struct tlet;
- struct uart_port *uart_port;
- };
二.串口驱动的注册与注销
注册
- int uart_register_driver(struct uart_driver *drv)
- {
- struct tty_driver *normal;
- int i, retval;
- BUG_ON(drv->state);
- drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); //分配uart_state内存
- if (!drv->state)
- goto out;
- normal = alloc_tty_driver(drv->nr); //分配tty_driver
- if (!normal)
- goto out_kfree;
- drv->tty_driver = normal; //tty_driver和uart_driver捆绑
- normal->owner = drv->owner; //模块所有者
- normal->driver_name = drv->driver_name; //驱动名
- normal->name = drv->dev_name; //设备名
- normal->major = drv->major; //主设备号
- normal->minor_start = drv->minor; //次设备号
- normal->type = TTY_DRIVER_TYPE_SERIAL; //tty类型
- normal->subtype = SERIAL_TYPE_NORMAL; //tty子类型
- normal->init_termios = tty_std_termios; //termios结构体
- normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; //设置默认串口信息
- normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600; //波特率
- normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
- normal->driver_state = drv;
- tty_set_operations(normal, &uart_ops); //设置tty操作函数集
- for (i = 0; i < drv->nr; i++) { //初始化uart_state
- struct uart_state *state = drv->state + i;
- struct tty_port *port = &state->port;
- tty_port_init(port); //初始化tty端口
- port->ops = &uart_port_ops; //tty端口操作函数集
- port->close_delay = 500; /* .5 seconds */
- port->closing_wait = 30000; /* 30 seconds */
- tasklet_init(&state->tlet, uart_tasklet_action,(unsigned long)state);
- }
- retval = tty_register_driver(normal); //注册tty驱动
- if (retval >= 0)
- return retval;
- put_tty_driver(normal); //引用计数
- out_kfree:
- kfree(drv->state);
- out:
- return -ENOMEM;
- }
注销
- void uart_unregister_driver(struct uart_driver *drv)
- {
- struct tty_driver *p = drv->tty_driver;
- tty_unregister_driver(p); //注销tty驱动
- put_tty_driver(p); //减少引用计数
- kfree(drv->state);
- drv->tty_driver = NULL;
- }
三.端口注册与注销
注册
- int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
- {
- struct uart_state *state;
- struct tty_port *port;
- int ret = 0;
- struct device *tty_dev;
- BUG_ON(in_interrupt());
- if (uport->line >= drv->nr)
- return -EINVAL;
- state = drv->state + uport->line; //获取uart_state
- port = &state->port; //获取tty_port
- mutex_lock(&port_mutex);
- mutex_lock(&port->mutex);
- if (state->uart_port) {
- ret = -EINVAL;
- goto out;
- }
- state->uart_port = uport; //设置uart_state->uart_port
- state->pm_state = -1;
- uport->cons = drv->cons; //设置uart_port->cons控制台
- uport->state = state; //设置uart_port->state
- if (!(uart_console(uport) && (uport->cons->flags & CON_ENABLED))) {
- spin_lock_init(&uport->lock);
- lockdep_set_class(&uport->lock, &port_lock_key);
- }
- uart_configure_port(drv, state, uport); //配置端口
- tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev); //生成tty设备文件/dev/ttyXXX
- if (likely(!IS_ERR(tty_dev))) {
- device_init_wakeup(tty_dev, 1);
- device_set_wakeup_enable(tty_dev, 0);
- } else
- printk(KERN_ERR "Cannot register tty device on line %d\n",uport->line);
- uport->flags &= ~UPF_DEAD;
- out:
- mutex_unlock(&port->mutex);
- mutex_unlock(&port_mutex);
- return ret;
- }
uart_configure_port
- static void uart_configure_port(struct uart_driver *drv, struct uart_state *state,struct uart_port *port)
- {
- unsigned int flags;
- if (!port->iobase && !port->mapbase && !port->membase)
- return;
- flags = 0;
- if (port->flags & UPF_AUTO_IRQ) //设置可中断标志
- flags |= UART_CONFIG_IRQ;
- if (port->flags & UPF_BOOT_AUTOCONF) { //设置自动配置标志
- if (!(port->flags & UPF_FIXED_TYPE)) {
- port->type = PORT_UNKNOWN;
- flags |= UART_CONFIG_TYPE;
- }
- port->ops->config_port(port, flags); //调用uart_port的config_port方法
- }
- if (port->type != PORT_UNKNOWN) {
- unsigned long flags;
- uart_report_port(drv, port);
- uart_change_pm(state, 0);
- spin_lock_irqsave(&port->lock, flags);
- port->ops->set_mctrl(port, port->mctrl & TIOCM_DTR); //调用uart_port的set_mctrl方法
- spin_unlock_irqrestore(&port->lock, flags);
- if (port->cons && !(port->cons->flags & CON_ENABLED)) //若console存在且设置了CON_ENABLED标志
- register_console(port->cons); //注册控制台设备
- if (!uart_console(port))
- uart_change_pm(state, 3);
- }
- }
注销
- int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
- {
- struct uart_state *state = drv->state + uport->line;
- struct tty_port *port = &state->port;
- BUG_ON(in_interrupt());
- if (state->uart_port != uport)
- printk(KERN_ALERT "Removing wrong port: %p != %p\n",state->uart_port, uport);
- mutex_lock(&port_mutex);
- mutex_lock(&port->mutex);
- uport->flags |= UPF_DEAD;
- mutex_unlock(&port->mutex);
- tty_unregister_device(drv->tty_driver, uport->line);
- if (port->tty)
- tty_vhangup(port->tty);
- if (uport->type != PORT_UNKNOWN)
- uport->ops->release_port(uport);
- uport->type = PORT_UNKNOWN;
- tasklet_kill(&state->tlet);
- state->uart_port = NULL;
- mutex_unlock(&port_mutex);
- return 0;
- }
四.串口对应的tty_driver的操作函数集
1.tty的操作函数集uart_ops
- static const struct tty_operations uart_ops = {
- .open = uart_open,
- .close = uart_close,
- .write = uart_write,
- .put_char = uart_put_char,
- .flush_chars = uart_flush_chars,
- .write_room = uart_write_room,
- .chars_in_buffer= uart_chars_in_buffer,
- .flush_buffer = uart_flush_buffer,
- .ioctl = uart_ioctl,
- .throttle = uart_throttle,
- .unthrottle = uart_unthrottle,
- .send_xchar = uart_send_xchar,
- .set_termios = uart_set_termios,
- .set_ldisc = uart_set_ldisc,
- .stop = uart_stop,
- .start = uart_start,
- .hangup = uart_hangup,
- .break_ctl = uart_break_ctl,
- .wait_until_sent= uart_wait_until_sent,
- #ifdef CONFIG_PROC_FS
- .proc_fops = &uart_proc_fops,
- #endif
- .tiocmget = uart_tiocmget,
- .tiocmset = uart_tiocmset,
- .get_icount = uart_get_icount,
- #ifdef CONFIG_CONSOLE_POLL
- .poll_init = uart_poll_init,
- .poll_get_char = uart_poll_get_char,
- .poll_put_char = uart_poll_put_char,
- #endif
- };
2.open方法
- static int uart_open(struct tty_struct *tty, struct file *filp)
- {
- struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state;
- struct uart_state *state;
- struct tty_port *port;
- int retval, line = tty->index;
- BUG_ON(!tty_locked());
- pr_debug("uart_open(%d) called\n", line);
- retval = -ENODEV;
- if (line >= tty->driver->num)
- goto fail;
- state = uart_get(drv, line); //获取uart_state
- if (IS_ERR(state)) {
- retval = PTR_ERR(state);
- goto fail;
- }
- port = &state->port; //获取tty_port
- tty->driver_data = state;
- state->uart_port->state = state;
- tty->low_latency = (state->uart_port->flags & UPF_LOW_LATENCY) ? 1 : 0;
- tty->alt_speed = 0;
- tty_port_tty_set(port, tty);
- if (tty_hung_up_p(filp)) {
- retval = -EAGAIN;
- port->count--;
- mutex_unlock(&port->mutex);
- goto fail;
- }
- if (port->count == 1)
- uart_change_pm(state, 0);
- retval = uart_startup(tty, state, 0); //启动串口
- mutex_unlock(&port->mutex);
- if (retval == 0)
- retval = tty_port_block_til_ready(port, tty, filp);
- fail:
- return retval;
- }
uart_startup
- static int uart_startup(struct tty_struct *tty, struct uart_state *state, int init_hw)
- {
- struct uart_port *uport = state->uart_port; //获取uart_port
- struct tty_port *port = &state->port; //获取tty_port
- unsigned long page;
- int retval = 0;
- if (port->flags & ASYNC_INITIALIZED)
- return 0;
- set_bit(TTY_IO_ERROR, &tty->flags);
- if (uport->type == PORT_UNKNOWN)
- return 0;
- if (!state->xmit.buf) {
- /* This is protected by the per port mutex */
- page = get_zeroed_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
- state->xmit.buf = (unsigned char *) page;
- uart_circ_clear(&state->xmit);
- }
- retval = uport->ops->startup(uport); //调用uart_port的startup方法
- if (retval == 0) {
- if (init_hw) {
- uart_change_speed(tty, state, NULL);
- if (tty->termios->c_cflag & CBAUD)
- uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR);
- }
- if (port->flags & ASYNC_CTS_FLOW) {
- spin_lock_irq(&uport->lock);
- if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS))
- tty->hw_stopped = 1;
- spin_unlock_irq(&uport->lock);
- }
- set_bit(ASYNCB_INITIALIZED, &port->flags);
- clear_bit(TTY_IO_ERROR, &tty->flags);
- }
- if (retval && capable(CAP_SYS_ADMIN))
- retval = 0;
- return retval;
- }
3.写方法
- static int uart_write(struct tty_struct *tty,const unsigned char *buf, int count)
- {
- struct uart_state *state = tty->driver_data; //获取uart_state
- struct uart_port *port;
- struct circ_buf *circ;
- unsigned long flags;
- int c, ret = 0;
- if (!state) {
- WARN_ON(1);
- return -EL3HLT;
- }
- port = state->uart_port; //获取uart_port
- circ = &state->xmit;
- if (!circ->buf)
- return 0;
- spin_lock_irqsave(&port->lock, flags);
- 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;
- }
- spin_unlock_irqrestore(&port->lock, flags);
- uart_start(tty); //调用uart_start方法
- return ret;
- }
uart_start
- static void uart_start(struct tty_struct *tty)
- {
- struct uart_state *state = tty->driver_data; //获取tty_state
- struct uart_port *port = state->uart_port; //获取uart_port
- unsigned long flags;
- spin_lock_irqsave(&port->lock, flags);
- __uart_start(tty); //调用__uart_start函数
- spin_unlock_irqrestore(&port->lock, flags);
- }
uart_start>>>__uart_start
- static void __uart_start(struct tty_struct *tty)
- {
- struct uart_state *state = tty->driver_data; //获取uart_state
- struct uart_port *port = state->uart_port; //获取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方法
- }