五 linux 串口驱动

一.串口结构体

1.串口驱动结构体

  1. struct uart_driver {  
  2.     struct module   *owner; //模块所有者  
  3.     const char  *driver_name;   //驱动名  
  4.     const char  *dev_name;  //设备名  
  5.     int  major; //主设备号  
  6.     int  minor; //次设备号  
  7.     int  nr;    //支持串口个数  
  8.     struct console  *cons;  //控制台设备  
  9.     struct uart_state   *state; //串口状态  
  10.     struct tty_driver   *tty_driver;    //tty设备  
  11. };  

2.串口端口结构体

  1. struct uart_port {  
  2.     spinlock_t  lock;  
  3.     unsigned long   iobase; //io端口基地址  
  4.     unsigned char __iomem   *membase;       //内存端口基地址  
  5.     unsigned int    (*serial_in)(struct uart_port *, int);  
  6.     void    (*serial_out)(struct uart_port *, intint);  
  7.     void    (*set_termios)(struct uart_port *,struct ktermios *new,struct ktermios *old);  
  8.     void    (*pm)(struct uart_port *, unsigned int state,unsigned int old);  
  9.     unsigned int    irq;    //中断号  
  10.     unsigned long   irqflags;   //中断标志  
  11.     unsigned int    uartclk;  
  12.     unsigned int    fifosize;   //fifo大小      
  13.     unsigned char   x_char;  
  14.     unsigned char   regshift;   //寄存器偏移值      
  15.     unsigned char   iotype; //io访问类型  
  16.     unsigned char   unused1;  
  17.     unsigned int    read_status_mask;  
  18.     unsigned int    ignore_status_mask;  
  19.     struct uart_state   *state; //uart_state结构体   
  20.     struct uart_icount  icount; //串口使用计数  
  21.     struct console  *cons;  //console控制台  
  22. #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ)  
  23.     unsigned long   sysrq;  
  24. #endif  
  25.     upf_t   flags;  
  26.     unsigned int    mctrl;  
  27.     unsigned int    timeout;  
  28.     unsigned int    type;  
  29.     const struct uart_ops   *ops;   //串口操作函数集  
  30.     unsigned int    custom_divisor;  
  31.     unsigned int    line;   //端口号  
  32.     resource_size_t mapbase;  
  33.     struct device   *dev;   //设备文件  
  34.     unsigned char   hub6;  
  35.     unsigned char   suspended;  
  36.     unsigned char   irq_wake;  
  37.     unsigned char   unused[2];  
  38.     void    *private_data;  
  39. };  

3.操作函数集

  1. struct uart_ops {  
  2.     unsigned int    (*tx_empty)(struct uart_port *);    //发送缓冲区为空  
  3.     void    (*set_mctrl)(struct uart_port *, unsigned int mctrl);   //设置串口modem控制模式  
  4.     unsigned int    (*get_mctrl)(struct uart_port *);   //获取串口modem控制模式  
  5.     void    (*stop_tx)(struct uart_port *); //停止发送  
  6.     void    (*start_tx)(struct uart_port *);    //开始发送  
  7.     void    (*send_xchar)(struct uart_port *, char ch);  
  8.     void    (*stop_rx)(struct uart_port *); //停止接收  
  9.     void    (*enable_ms)(struct uart_port *);   //使能modem状态信息  
  10.     void    (*break_ctl)(struct uart_port *, int ctl);  
  11.     int (*startup)(struct uart_port *); //打开串口  
  12.     void    (*shutdown)(struct uart_port *);    //关闭串口  
  13.     void    (*flush_buffer)(struct uart_port *);  
  14.     void    (*set_termios)(struct uart_port *, struct ktermios *new,struct ktermios *old);  //设置串口参数  
  15.     void    (*set_ldisc)(struct uart_port *, int new);  
  16.     void    (*pm)(struct uart_port *, unsigned int state,unsigned int oldstate);  
  17.     int (*set_wake)(struct uart_port *, unsigned int state);  
  18.     const char *(*type)(struct uart_port *);  
  19.     void    (*release_port)(struct uart_port *);    //释放端口  
  20.     int (*request_port)(struct uart_port *);    //请求端口  
  21.     void    (*config_port)(struct uart_port *, int);    //配置端口  
  22.     int (*verify_port)(struct uart_port *, struct serial_struct *); //校验端口  
  23.     int (*ioctl)(struct uart_port *, unsigned int, unsigned long);  //控制  
  24. #ifdef CONFIG_CONSOLE_POLL  
  25.     void    (*poll_put_char)(struct uart_port *, unsigned char);  
  26.     int (*poll_get_char)(struct uart_port *);  
  27. #endif  
  28. };  

4.uart_state

  1. struct uart_state {  
  2.     struct tty_port port;  
  3.     int     pm_state;  
  4.     struct circ_buf xmit;  
  5.     struct tasklet_struct   tlet;  
  6.     struct uart_port    *uart_port;  
  7. };  

 

二.串口驱动的注册与注销

注册

  1. int uart_register_driver(struct uart_driver *drv)  
  2. {  
  3.     struct tty_driver *normal;  
  4.     int i, retval;  
  5.     BUG_ON(drv->state);  
  6.     drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);    //分配uart_state内存  
  7.     if (!drv->state)  
  8.         goto out;  
  9.     normal = alloc_tty_driver(drv->nr);  //分配tty_driver  
  10.     if (!normal)  
  11.         goto out_kfree;  
  12.     drv->tty_driver = normal;    //tty_driver和uart_driver捆绑  
  13.   
  14.     normal->owner        = drv->owner;    //模块所有者  
  15.     normal->driver_name  = drv->driver_name;  //驱动名  
  16.     normal->name     = drv->dev_name; //设备名  
  17.     normal->major        = drv->major;    //主设备号  
  18.     normal->minor_start  = drv->minor;    //次设备号  
  19.     normal->type     = TTY_DRIVER_TYPE_SERIAL;   //tty类型  
  20.     normal->subtype      = SERIAL_TYPE_NORMAL;   //tty子类型  
  21.     normal->init_termios = tty_std_termios;      //termios结构体  
  22.     normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; //设置默认串口信息  
  23.     normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600; //波特率  
  24.     normal->flags        = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;  
  25.     normal->driver_state    = drv;     
  26.     tty_set_operations(normal, &uart_ops);  //设置tty操作函数集  
  27.   
  28.     for (i = 0; i < drv->nr; i++) {   //初始化uart_state  
  29.         struct uart_state *state = drv->state + i;  
  30.         struct tty_port *port = &state->port;  
  31.         tty_port_init(port);    //初始化tty端口  
  32.         port->ops = &uart_port_ops;  //tty端口操作函数集  
  33.         port->close_delay     = 500; /* .5 seconds */  
  34.         port->closing_wait    = 30000;   /* 30 seconds */  
  35.         tasklet_init(&state->tlet, uart_tasklet_action,(unsigned long)state);  
  36.     }  
  37.     retval = tty_register_driver(normal);   //注册tty驱动  
  38.     if (retval >= 0)  
  39.         return retval;  
  40.   
  41.     put_tty_driver(normal); //引用计数  
  42. out_kfree:  
  43.     kfree(drv->state);  
  44. out:  
  45.     return -ENOMEM;  
  46. }  

 注销

  1. void uart_unregister_driver(struct uart_driver *drv)  
  2. {  
  3.     struct tty_driver *p = drv->tty_driver;  
  4.     tty_unregister_driver(p);   //注销tty驱动  
  5.     put_tty_driver(p);  //减少引用计数  
  6.     kfree(drv->state);  
  7.     drv->tty_driver = NULL;  
  8. }  

三.端口注册与注销

注册

  1. int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)  
  2. {  
  3.     struct uart_state *state;  
  4.     struct tty_port *port;  
  5.     int ret = 0;  
  6.     struct device *tty_dev;  
  7.     BUG_ON(in_interrupt());  
  8.     if (uport->line >= drv->nr)  
  9.         return -EINVAL;  
  10.     state = drv->state + uport->line; //获取uart_state  
  11.     port = &state->port; //获取tty_port  
  12.     mutex_lock(&port_mutex);  
  13.     mutex_lock(&port->mutex);  
  14.     if (state->uart_port) {  
  15.         ret = -EINVAL;  
  16.         goto out;  
  17.     }  
  18.     state->uart_port = uport;    //设置uart_state->uart_port  
  19.     state->pm_state = -1;  
  20.     uport->cons = drv->cons;  //设置uart_port->cons控制台  
  21.     uport->state = state;    //设置uart_port->state  
  22.     if (!(uart_console(uport) && (uport->cons->flags & CON_ENABLED))) {  
  23.         spin_lock_init(&uport->lock);  
  24.         lockdep_set_class(&uport->lock, &port_lock_key);  
  25.     }  
  26.     uart_configure_port(drv, state, uport); //配置端口  
  27.     tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);   //生成tty设备文件/dev/ttyXXX  
  28.     if (likely(!IS_ERR(tty_dev))) {  
  29.         device_init_wakeup(tty_dev, 1);  
  30.         device_set_wakeup_enable(tty_dev, 0);  
  31.     } else  
  32.         printk(KERN_ERR "Cannot register tty device on line %d\n",uport->line);  
  33.     uport->flags &= ~UPF_DEAD;  
  34.  out:  
  35.     mutex_unlock(&port->mutex);  
  36.     mutex_unlock(&port_mutex);  
  37.   
  38.     return ret;  
  39. }  

uart_configure_port

  1. static void uart_configure_port(struct uart_driver *drv, struct uart_state *state,struct uart_port *port)  
  2. {  
  3.     unsigned int flags;  
  4.     if (!port->iobase && !port->mapbase && !port->membase)  
  5.         return;  
  6.     flags = 0;  
  7.     if (port->flags & UPF_AUTO_IRQ)  //设置可中断标志  
  8.         flags |= UART_CONFIG_IRQ;  
  9.     if (port->flags & UPF_BOOT_AUTOCONF) {   //设置自动配置标志  
  10.         if (!(port->flags & UPF_FIXED_TYPE)) {  
  11.             port->type = PORT_UNKNOWN;  
  12.             flags |= UART_CONFIG_TYPE;  
  13.         }  
  14.         port->ops->config_port(port, flags);  //调用uart_port的config_port方法  
  15.     }  
  16.   
  17.     if (port->type != PORT_UNKNOWN) {  
  18.         unsigned long flags;  
  19.         uart_report_port(drv, port);  
  20.         uart_change_pm(state, 0);  
  21.         spin_lock_irqsave(&port->lock, flags);  
  22.         port->ops->set_mctrl(port, port->mctrl & TIOCM_DTR);   //调用uart_port的set_mctrl方法  
  23.         spin_unlock_irqrestore(&port->lock, flags);  
  24.         if (port->cons && !(port->cons->flags & CON_ENABLED))  //若console存在且设置了CON_ENABLED标志  
  25.             register_console(port->cons);    //注册控制台设备  
  26.         if (!uart_console(port))  
  27.             uart_change_pm(state, 3);  
  28.     }  
  29. }  

 注销

  1. int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)  
  2. {  
  3.     struct uart_state *state = drv->state + uport->line;  
  4.     struct tty_port *port = &state->port;  
  5.     BUG_ON(in_interrupt());  
  6.     if (state->uart_port != uport)  
  7.         printk(KERN_ALERT "Removing wrong port: %p != %p\n",state->uart_port, uport);  
  8.     mutex_lock(&port_mutex);  
  9.     mutex_lock(&port->mutex);  
  10.     uport->flags |= UPF_DEAD;  
  11.     mutex_unlock(&port->mutex);  
  12.     tty_unregister_device(drv->tty_driver, uport->line);  
  13.     if (port->tty)  
  14.         tty_vhangup(port->tty);  
  15.     if (uport->type != PORT_UNKNOWN)  
  16.         uport->ops->release_port(uport);  
  17.     uport->type = PORT_UNKNOWN;  
  18.     tasklet_kill(&state->tlet);  
  19.     state->uart_port = NULL;  
  20.     mutex_unlock(&port_mutex);  
  21.     return 0;  
  22. }  

四.串口对应的tty_driver的操作函数集

1.tty的操作函数集uart_ops

  1. static const struct tty_operations uart_ops = {  
  2.     .open       = uart_open,  
  3.     .close      = uart_close,  
  4.     .write      = uart_write,  
  5.     .put_char   = uart_put_char,  
  6.     .flush_chars    = uart_flush_chars,  
  7.     .write_room = uart_write_room,  
  8.     .chars_in_buffer= uart_chars_in_buffer,  
  9.     .flush_buffer   = uart_flush_buffer,  
  10.     .ioctl      = uart_ioctl,  
  11.     .throttle   = uart_throttle,  
  12.     .unthrottle = uart_unthrottle,  
  13.     .send_xchar = uart_send_xchar,  
  14.     .set_termios    = uart_set_termios,  
  15.     .set_ldisc  = uart_set_ldisc,  
  16.     .stop       = uart_stop,  
  17.     .start      = uart_start,  
  18.     .hangup     = uart_hangup,  
  19.     .break_ctl  = uart_break_ctl,  
  20.     .wait_until_sent= uart_wait_until_sent,  
  21. #ifdef CONFIG_PROC_FS  
  22.     .proc_fops  = &uart_proc_fops,  
  23. #endif  
  24.     .tiocmget   = uart_tiocmget,  
  25.     .tiocmset   = uart_tiocmset,  
  26.     .get_icount = uart_get_icount,  
  27. #ifdef CONFIG_CONSOLE_POLL  
  28.     .poll_init  = uart_poll_init,  
  29.     .poll_get_char  = uart_poll_get_char,  
  30.     .poll_put_char  = uart_poll_put_char,  
  31. #endif  
  32. };  

2.open方法

  1. static int uart_open(struct tty_struct *tty, struct file *filp)  
  2. {  
  3.     struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state;  
  4.     struct uart_state *state;  
  5.     struct tty_port *port;  
  6.     int retval, line = tty->index;  
  7.   
  8.     BUG_ON(!tty_locked());  
  9.     pr_debug("uart_open(%d) called\n", line);  
  10.     retval = -ENODEV;  
  11.     if (line >= tty->driver->num)  
  12.         goto fail;  
  13.     state = uart_get(drv, line);    //获取uart_state  
  14.     if (IS_ERR(state)) {  
  15.         retval = PTR_ERR(state);  
  16.         goto fail;  
  17.     }  
  18.     port = &state->port; //获取tty_port  
  19.     tty->driver_data = state;  
  20.     state->uart_port->state = state;  
  21.     tty->low_latency = (state->uart_port->flags & UPF_LOW_LATENCY) ? 1 : 0;  
  22.     tty->alt_speed = 0;  
  23.     tty_port_tty_set(port, tty);  
  24.     if (tty_hung_up_p(filp)) {  
  25.         retval = -EAGAIN;  
  26.         port->count--;  
  27.         mutex_unlock(&port->mutex);  
  28.         goto fail;  
  29.     }  
  30.     if (port->count == 1)  
  31.         uart_change_pm(state, 0);  
  32.     retval = uart_startup(tty, state, 0);   //启动串口  
  33.     mutex_unlock(&port->mutex);  
  34.     if (retval == 0)  
  35.         retval = tty_port_block_til_ready(port, tty, filp);  
  36. fail:  
  37.     return retval;  
  38. }  

uart_startup

  1. static int uart_startup(struct tty_struct *tty, struct uart_state *state, int init_hw)  
  2. {  
  3.     struct uart_port *uport = state->uart_port;  //获取uart_port  
  4.     struct tty_port *port = &state->port;    //获取tty_port  
  5.     unsigned long page;  
  6.     int retval = 0;  
  7.   
  8.     if (port->flags & ASYNC_INITIALIZED)  
  9.         return 0;  
  10.     set_bit(TTY_IO_ERROR, &tty->flags);  
  11.     if (uport->type == PORT_UNKNOWN)  
  12.         return 0;  
  13.     if (!state->xmit.buf) {  
  14.         /* This is protected by the per port mutex */  
  15.         page = get_zeroed_page(GFP_KERNEL);  
  16.         if (!page)  
  17.             return -ENOMEM;  
  18.         state->xmit.buf = (unsigned char *) page;  
  19.         uart_circ_clear(&state->xmit);  
  20.     }  
  21.     retval = uport->ops->startup(uport);  //调用uart_port的startup方法  
  22.     if (retval == 0) {  
  23.         if (init_hw) {  
  24.             uart_change_speed(tty, state, NULL);  
  25.             if (tty->termios->c_cflag & CBAUD)  
  26.                 uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR);  
  27.         }  
  28.         if (port->flags & ASYNC_CTS_FLOW) {  
  29.             spin_lock_irq(&uport->lock);  
  30.             if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS))  
  31.                 tty->hw_stopped = 1;  
  32.             spin_unlock_irq(&uport->lock);  
  33.         }  
  34.         set_bit(ASYNCB_INITIALIZED, &port->flags);  
  35.         clear_bit(TTY_IO_ERROR, &tty->flags);  
  36.     }  
  37.     if (retval && capable(CAP_SYS_ADMIN))  
  38.         retval = 0;  
  39.     return retval;  
  40. }  

3.写方法

  1. static int uart_write(struct tty_struct *tty,const unsigned char *buf, int count)  
  2. {  
  3.     struct uart_state *state = tty->driver_data; //获取uart_state  
  4.     struct uart_port *port;  
  5.     struct circ_buf *circ;  
  6.     unsigned long flags;  
  7.     int c, ret = 0;  
  8.     if (!state) {  
  9.         WARN_ON(1);  
  10.         return -EL3HLT;  
  11.     }  
  12.     port = state->uart_port; //获取uart_port  
  13.     circ = &state->xmit;  
  14.     if (!circ->buf)  
  15.         return 0;  
  16.   
  17.     spin_lock_irqsave(&port->lock, flags);  
  18.     while (1) {  
  19.         c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);  
  20.         if (count < c)  
  21.             c = count;  
  22.         if (c <= 0)  
  23.             break;  
  24.         memcpy(circ->buf + circ->head, buf, c);  
  25.         circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);  
  26.         buf += c;  
  27.         count -= c;  
  28.         ret += c;  
  29.     }  
  30.     spin_unlock_irqrestore(&port->lock, flags);  
  31.     uart_start(tty);    //调用uart_start方法  
  32.     return ret;  
  33. }  

uart_start

  1. static void uart_start(struct tty_struct *tty)  
  2. {  
  3.     struct uart_state *state = tty->driver_data; //获取tty_state  
  4.     struct uart_port *port = state->uart_port;   //获取uart_port  
  5.     unsigned long flags;  
  6.   
  7.     spin_lock_irqsave(&port->lock, flags);  
  8.     __uart_start(tty);      //调用__uart_start函数  
  9.     spin_unlock_irqrestore(&port->lock, flags);  
  10. }  

uart_start>>>__uart_start

  1. static void __uart_start(struct tty_struct *tty)  
  2. {  
  3.     struct uart_state *state = tty->driver_data; //获取uart_state  
  4.     struct uart_port *port = state->uart_port;   //获取uart_port  
  5.     if (!uart_circ_empty(&state->xmit) && state->xmit.buf &&!tty->stopped && !tty->hw_stopped)  
  6.         port->ops->start_tx(port);    //调用uart_port的start_tx方法  


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值