Linux串口驱动分析write

  1. 文章来自:http://blog.csdn.net/longwang155069/article/details/42780331

  2. /*和read的分析过程一样, 我们首先分析tty_write*/  
  3.   
  4. /*最重要的就是do_tty_write函数。 前面都是一些合法性判断*/  
  5. static ssize_t tty_write(struct file *file, const char __user *buf,size_t count, loff_t *ppos)  
  6. {  
  7.     struct inode *inode = file->f_path.dentry->d_inode;  
  8.     struct tty_struct *tty = file_tty(file);  
  9.     struct tty_ldisc *ld;  
  10.     ssize_t ret;  
  11.   
  12.     if (tty_paranoia_check(tty, inode, "tty_write"))  
  13.         return -EIO;  
  14.     if (!tty || !tty->ops->write ||  
  15.         (test_bit(TTY_IO_ERROR, &tty->flags)))  
  16.             return -EIO;  
  17.     /* Short term debug to catch buggy drivers */  
  18.     if (tty->ops->write_room == NULL)  
  19.         printk(KERN_ERR "tty driver %s lacks a write_room method.\n",  
  20.             tty->driver->name);  
  21.     ld = tty_ldisc_ref_wait(tty);  
  22.     if (!ld->ops->write)  
  23.         ret = -EIO;  
  24.     else  
  25.         /*调用tty_ldisc_N_TTY中的write函数*/  
  26.         ret = do_tty_write(ld->ops->write, tty, file, buf, count);  
  27.     tty_ldisc_deref(ld);  
  28.     return ret;  
  29. }  
  30.   
  31. /*调用uart_ops中的write函数*/  
  32. static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,const unsigned char *buf, size_t nr)  
  33. {  
  34.     c = tty->ops->write(tty, b, nr);  
  35. }  
  36.   
  37. static int uart_write(struct tty_struct *tty,const unsigned char *buf, int count)  
  38. {  
  39.     struct uart_state *state = tty->driver_data;  
  40.     struct uart_port *port;  
  41.     struct circ_buf *circ;  
  42.     unsigned long flags;  
  43.     int c, ret = 0;  
  44.   
  45.     /* 
  46.      * This means you called this function _after_ the port was 
  47.      * closed.  No cookie for you. 
  48.      */  
  49.     if (!state) {  
  50.         WARN_ON(1);  
  51.         return -EL3HLT;  
  52.     }  
  53.   
  54.   /*取出所对应的port和循环缓冲buf*/  
  55.     port = state->uart_port;  
  56.     circ = &state->xmit;  
  57.   
  58.     if (!circ->buf)  
  59.         return 0;  
  60.   
  61.     spin_lock_irqsave(&port->lock, flags);  
  62.     while (1) {  
  63.         /*计算循环缓冲的剩余空间 */  
  64.         c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);  
  65.         if (count < c)  
  66.             c = count;  
  67.         if (c <= 0)  
  68.             break;  
  69.         /*拷贝数据到循环缓冲区*/  
  70.         memcpy(circ->buf + circ->head, buf, c);  
  71.         /*调正循环缓冲head的位置*/  
  72.         circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);  
  73.         /*挪动buf当前的指针位置*/  
  74.         buf += c;  
  75.         count -= c;  
  76.         ret += c;  
  77.     }  
  78.     spin_unlock_irqrestore(&port->lock, flags);  
  79.   
  80.     uart_start(tty);  
  81.     return ret;  
  82. }  
  83.   
  84. /*判断循环缓冲是否为空等。 然后调用注册驱动时的ops。 也就是s3c24xx_serial_ops*/  
  85. static void __uart_start(struct tty_struct *tty)  
  86. {  
  87.     struct uart_state *state = tty->driver_data;  
  88.     struct uart_port *port = state->uart_port;  
  89.   
  90.     if (!uart_circ_empty(&state->xmit) && state->xmit.buf &&  
  91.         !tty->stopped && !tty->hw_stopped)  
  92.         port->ops->start_tx(port);  
  93. }  
  94.   
  95. /*判断端口是否使能,如果没使能则使能端口。 然后使能tx中断 
  96. * 使能tx中断,则当有数据来时,则会触发tx中断,调用中断函数 
  97. */  
  98. static void s3c24xx_serial_start_tx(struct uart_port *port)  
  99. {  
  100.     struct s3c24xx_uart_port *ourport = to_ourport(port);  
  101.     static int a =1;//temp  
  102.     if (port->line == 3) {  
  103. //      printk("485_start_tx\n");  
  104.   
  105.         if(a){  
  106.             s3c_gpio_cfgpin(S3C64XX_GPK(5), S3C_GPIO_SFN(1));  
  107.             a=0;  
  108.         }  
  109.         gpio_set_value(S3C64XX_GPK(5), 1);  
  110.     }  
  111.     if (!tx_enabled(port)) {  
  112.         if (port->flags & UPF_CONS_FLOW)  
  113.             s3c24xx_serial_rx_disable(port);  
  114.   
  115.         enable_irq(ourport->tx_irq);  
  116.         tx_enabled(port) = 1;  
  117.     }  
  118. }  
  119.   
  120. /*tx中断触发函数*/  
  121. static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)  
  122. {  
  123.     struct s3c24xx_uart_port *ourport = id;  
  124.     struct uart_port *port = &ourport->port;  
  125.     struct circ_buf *xmit = &port->state->xmit;  
  126.     int count = 256;  
  127.   
  128.     /*判断x_char是否存在,如果存在则写进UTXH寄存器。清空x_char*/  
  129.     if (port->x_char) {  
  130.         wr_regb(port, S3C2410_UTXH, port->x_char);  
  131.         port->icount.tx++;  
  132.         port->x_char = 0;  
  133.         goto out;  
  134.     }  
  135.   
  136.     /* if there isn't anything more to transmit, or the uart is now 
  137.      * stopped, disable the uart and exit 
  138.     */  
  139.   
  140.     /*判断循环缓冲是否为空,或者tx是否为停止状态。 如果是则停止发送*/  
  141.     if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {  
  142.         s3c24xx_serial_stop_tx(port);  
  143.         goto out;  
  144.     }  
  145.   
  146.     /* try and drain the buffer... */  
  147.   
  148.     /*当循环缓冲buff不为空,而且count是大于0的。则进入while循环*/  
  149.     while (!uart_circ_empty(xmit) && count-- > 0) {  
  150.           
  151.         /*首先读取UFSTAT寄存器,然后判断tx_fifo是否为0.是则退出*/  
  152.         if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)  
  153.             break;  
  154.   
  155.         /*然后将循环buff中的数据读出到UTXH寄存器。然后设置tail的指针位置*/  
  156.         wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);  
  157.         xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);  
  158.         port->icount.tx++;  
  159.     }  
  160.   
  161.     /*判断循环缓冲中的数据是否小于WAKEUP_CHARS, 小于则启动接受*/  
  162.     if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)  
  163.         uart_write_wakeup(port);  
  164.           
  165.     /*如果循环buff为空,则停止发送,退出*/  
  166.     if (uart_circ_empty(xmit))  
  167.         s3c24xx_serial_stop_tx(port);  
  168. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值