/*和read的分析过程一样, 我们首先分析tty_write*//*最重要的就是do_tty_write函数。 前面都是一些合法性判断*/
static ssize_t tty_write(struct file *file, const char __user *buf,size_t count, loff_t *ppos)
{struct inode *inode = file->f_path.dentry->d_inode;struct tty_struct *tty = file_tty(file);struct tty_ldisc *ld;ssize_t ret;if (tty_paranoia_check(tty, inode, "tty_write"))return -EIO;if (!tty || !tty->ops->write ||(test_bit(TTY_IO_ERROR, &tty->flags)))return -EIO;/* Short term debug to catch buggy drivers */if (tty->ops->write_room == NULL)printk(KERN_ERR "tty driver %s lacks a write_room method.\n",tty->driver->name);ld = tty_ldisc_ref_wait(tty);if (!ld->ops->write)ret = -EIO;else/*调用tty_ldisc_N_TTY中的write函数*/ret = do_tty_write(ld->ops->write, tty, file, buf, count);tty_ldisc_deref(ld);return ret;
}/*调用uart_ops中的write函数*/
static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,const unsigned char *buf, size_t nr)
{c = tty->ops->write(tty, b, nr);
}static int uart_write(struct tty_struct *tty,const unsigned char *buf, int count)
{struct uart_state *state = tty->driver_data;struct uart_port *port;struct circ_buf *circ;unsigned long flags;int c, ret = 0;/** This means you called this function _after_ the port was* closed.  No cookie for you.*/if (!state) {WARN_ON(1);return -EL3HLT;}/*取出所对应的port和循环缓冲buf*/port = state->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);/*调正循环缓冲head的位置*/circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);/*挪动buf当前的指针位置*/buf += c;count -= c;ret += c;}spin_unlock_irqrestore(&port->lock, flags);uart_start(tty);return ret;
}/*判断循环缓冲是否为空等。 然后调用注册驱动时的ops。 也就是s3c24xx_serial_ops*/
static void __uart_start(struct tty_struct *tty)
{struct uart_state *state = tty->driver_data;struct uart_port *port = state->uart_port;if (!uart_circ_empty(&state->xmit) && state->xmit.buf &&!tty->stopped && !tty->hw_stopped)port->ops->start_tx(port);
}/*判断端口是否使能,如果没使能则使能端口。 然后使能tx中断
* 使能tx中断,则当有数据来时,则会触发tx中断,调用中断函数
*/
static void s3c24xx_serial_start_tx(struct uart_port *port)
{struct s3c24xx_uart_port *ourport = to_ourport(port);static int a =1;//tempif (port->line == 3) {
//      printk("485_start_tx\n");if(a){s3c_gpio_cfgpin(S3C64XX_GPK(5), S3C_GPIO_SFN(1));a=0;}gpio_set_value(S3C64XX_GPK(5), 1);}if (!tx_enabled(port)) {if (port->flags & UPF_CONS_FLOW)s3c24xx_serial_rx_disable(port);enable_irq(ourport->tx_irq);tx_enabled(port) = 1;}
}/*tx中断触发函数*/
static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
{struct s3c24xx_uart_port *ourport = id;struct uart_port *port = &ourport->port;struct circ_buf *xmit = &port->state->xmit;int count = 256;/*判断x_char是否存在,如果存在则写进UTXH寄存器。清空x_char*/if (port->x_char) {wr_regb(port, S3C2410_UTXH, port->x_char);port->icount.tx++;port->x_char = 0;goto out;}/* if there isn't anything more to transmit, or the uart is now* stopped, disable the uart and exit*//*判断循环缓冲是否为空,或者tx是否为停止状态。 如果是则停止发送*/if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {s3c24xx_serial_stop_tx(port);goto out;}/* try and drain the buffer... *//*当循环缓冲buff不为空,而且count是大于0的。则进入while循环*/while (!uart_circ_empty(xmit) && count-- > 0) {/*首先读取UFSTAT寄存器,然后判断tx_fifo是否为0.是则退出*/if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)break;/*然后将循环buff中的数据读出到UTXH寄存器。然后设置tail的指针位置*/wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);port->icount.tx++;}/*判断循环缓冲中的数据是否小于WAKEUP_CHARS, 小于则启动接受*/if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)uart_write_wakeup(port);/*如果循环buff为空,则停止发送,退出*/if (uart_circ_empty(xmit))s3c24xx_serial_stop_tx(port);
}

Linux串口驱动分析write相关推荐

  1. linux串口驱动分析

    linux串口驱动分析 硬件资源及描写叙述 s3c2440A 通用异步接收器和发送器(UART)提供了三个独立的异步串行 I/O(SIO)port,每一个port都能够在中断模式或 DMA 模式下操作 ...

  2. linux串口驱动分析【转】

    转自:http://blog.csdn.net/hanmengaidudu/article/details/11946591 硬件资源及描述 s3c2440A 通用异步接收器和发送器(UART)提供了 ...

  3. linux串口发送数据程序,linux串口驱动分析——发送数据

    一.应用程序中write函数到底层驱动历程 和前文提到的一样,首先先注册串口,使用uart_register_driver函数,依次分别为tty_register_driver,cdev_init函数 ...

  4. LINUX串口驱动分析——发送数据

    https://www.cnblogs.com/51qianrushi/p/4324845.html

  5. GPS NMEA 0183 4.10协议/GPS Linux串口驱动

      NMEA 0183是美国国家海洋电子协会(National Marine Electronics Association)为海用电子设备制定的标准格式.现在已经成为GPS导航设备统一的RTCM(R ...

  6. Linux UART驱动分析及测试

    1.Linux TTY驱动程序框架 Linux TTY驱动程序代码位于/drivers/tty下面.TTY的层次接口包括TTY应用层.TTY文件层.TTY线路规程层.TTY驱动层.TTY设备驱动层.T ...

  7. Linux串口驱动(2) - 线路规程

    1. 注册tty的ldisc ldisc全称 line discipline(线路规程),因为历史原因,tty属于一类设备,而串口设备只是其中一种,所以该模块负责将用户操作桥接到不同的tty驱动.从代 ...

  8. Linux串口驱动(3) - open详解

    1. 用户空间open的操作实现 串口设备是被注册为字符设备的,在注册过程中填充了struct file_operations tty_fops结构体,该结构体中的成员open.read.write等 ...

  9. wince串口驱动分析(转)

    wince串口驱动分析 串行通讯接口主要是指UART(通用串行)和IRDA两种.通常的串行连接电气连接上有3wire和9wire两种.3wire的接线方式下定义了发送.接收和地三根连接.其用途就如名称 ...

  10. Linux spi驱动分析(四)----SPI设备驱动(W25Q32BV)

    一.W25Q32BV芯片简介 W25X是一系列SPI接口Flash芯片的简称,它采用SPI接口和CPU通信,本文使用的W25Q32BV容量为32M,具体特性如下: 1.1.基本特性 该芯片最大支持10 ...

最新文章

  1. 基于YOLOv3和PyTorch 的视频-图像模型
  2. 传海思砍台积电第三季度一半手机订单
  3. jQuery如果选中复选框
  4. MES系统实施4大关键点,您都知道吗?
  5. JZOJ 1980. 【2011集训队出题】Construct
  6. springMVC——SSM整合(IDEA 搭建简单 ssm 框架最详细最简单教程)
  7. C# WPF抽屉效果实现
  8. Oracle 学习笔记二 Create table
  9. 详解Python中函数和模块的特殊属性__annotations__
  10. 滴滴缺席的这 11 个月,顺风车迷局如何破?
  11. tomcat部署安装
  12. python爬淘宝评论源代码_python3爬取淘宝信息代码分析
  13. 希尔伯特空间/再生核希尔伯特空间
  14. 【原创】【2021 android逆向系列】番外:oppo A57手机刷官方纯净版ROM且ROOT
  15. K-近邻算法学习总结
  16. 一文带你看懂自然语言处理——word表示技术的变迁(从bool模型到BERT)
  17. Common IO 使用小结
  18. 433MHz资讯一点通
  19. nexus9刷机全记录
  20. win7系统安装信息服务器不可用怎么办,Win7电脑RPC服务器不可用怎么办 RPC服务器不可用解决方法...

热门文章

  1. Dynamics 365 Online-Unified User Interface
  2. Python网络编程、爬虫之requests模块使用
  3. oracle、mysql、sql server等;流行数据库的链接驱动配置
  4. 《Entity Framework 6 Recipes》中文翻译系列 (24) ------ 第五章 加载实体和导航属性之查询内存对象...
  5. 成员函数指针有多态的效果吗?
  6. simple resource manager
  7. Ambari——大数据平台的搭建利器之进阶篇[配置spark]
  8. c#文件流读取编码问题(转)新增加一个方法解决不带BOM的问题
  9. c++14 0 名字空间和条件编译
  10. sqlite3 命令行操作