一、write过程分析

  • App写:

    • 使用行规程来写
    • 数据最终存入uart_state->xmit的buffer里
  • 硬件发送:
    • 使用硬件驱动中uart_ops->start_tx开始发送
    • 具体的发送方式有两种:通过DMA、通过中断
  • 中断方式:
    • 方法1:直接使能tx empty中断,一开始tx buffer为空,在中断里填入数据
    • 方法2:写不封数据到tx fifo,使能中断,剩下的数据再次中断里继续发送

二、tty_write

文件在driver\tty\tty_io.c

static ssize_t tty_write(struct file *file, const char __user *buf,size_t count, loff_t *ppos)
{struct tty_struct *tty = file_tty(file);struct tty_ldisc *ld;//...if (!ld->ops->write)ret = -EIO;elseret = do_tty_write(ld->ops->write, tty, file, buf, count); //使用行规程里的惭怍函数,进行写入//tty_ldisc->tty_ldisc_ops->writetty_ldisc_deref(ld);return ret;
}

三、ldisk write

文件drivers\tty\n_tty.c

static struct tty_ldisc_ops n_tty_ops = {       //tty_ldisc_ops惭怍函数,实例结构体n_tty_ops.magic           = TTY_LDISC_MAGIC,.name            = "n_tty",.open            = n_tty_open,.close           = n_tty_close,.flush_buffer    = n_tty_flush_buffer,.read            = n_tty_read,.write           = n_tty_write,        //上面ld->ops->write,调用的是这个函数//...
};static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,const unsigned char *buf, size_t nr)
{//...while (1) {//...if (O_OPOST(tty)) {//...} else {struct n_tty_data *ldata = tty->disc_data;while (nr > 0) {mutex_lock(&ldata->output_lock);c = tty->ops->write(tty, b, nr);       //tty_struct->tty_operationsmutex_unlock(&ldata->output_lock);//...}}if (!nr)break;if (file->f_flags & O_NONBLOCK) {       //非阻塞方式的话,直接返回,不等数据发送完retval = -EAGAIN;break;}up_read(&tty->termios_rwsem);wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);       //阻塞方式,等待发送完毕down_read(&tty->termios_rwsem);}//...
}

四、uart_write

文件:drivers\tty\serial\serial_core.c

static const struct tty_operations uart_ops = {.open        = uart_open,.close     = uart_close,.write        = uart_write,//....
};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;//...port = uart_port_lock(state, flags);circ = &state->xmit;        //赋值寄存器地址//...while (port) {//...memcpy(circ->buf + circ->head, buf, c);     //把数据存入xmit buffercirc->head = (circ->head + c) & (UART_XMIT_SIZE - 1);buf += c;count -= c;ret += c;}__uart_start(tty);        //启动串口发送数据uart_port_unlock(port, flags);return ret;
}static void __uart_start(struct tty_struct *tty)
{struct uart_state *state = tty->driver_data;struct uart_port *port = state->uart_port;if (port && !uart_tx_stopped(port))port->ops->start_tx(port);      //uart_port->uart_ops->start_tx
}

五、硬件相关的发送

相关文件:drivers\tty\serial\imx.c

static const struct uart_ops imx_uart_pops = {.tx_empty = imx_uart_tx_empty,.set_mctrl = imx_uart_set_mctrl,.get_mctrl    = imx_uart_get_mctrl,.stop_tx  = imx_uart_stop_tx,.start_tx   = imx_uart_start_tx,.stop_rx   = imx_uart_stop_rx,//...
};static void imx_uart_start_tx(struct uart_port *port)
{//...if (!sport->dma_is_enabled) {      //不适用DMA时,比较容易理解,以它为例ucr1 = imx_uart_readl(sport, UCR1);//Transimiter Empty Interrupt Enable,发送buffer为空时,就产生中断//在中断函数里发送字符imx_uart_writel(sport, ucr1 | UCR1_TXMPTYEN, UCR1);}if (sport->dma_is_enabled) {//...}
}

一开始时,发送buffer肯定为空,就会立即产生中断:

static irqreturn_t imx_uart_txint(int irq, void *dev_id)
{struct imx_port *sport = dev_id;unsigned long flags;spin_lock_irqsave(&sport->port.lock, flags);imx_uart_transmit_buffer(sport);spin_unlock_irqrestore(&sport->port.lock, flags);return IRQ_HANDLED;
}static inline void imx_uart_transmit_buffer(struct imx_port *sport)
{struct circ_buf *xmit = &sport->port.state->xmit;//...while (!uart_circ_empty(xmit) &&!(imx_uart_readl(sport, imx_uart_uts_reg(sport)) & UTS_TXFULL)) {/* send xmit->buf[xmit->tail]* out the port here *///UART TX FIFO未满时,从xmit buffer取出数据写入FIFO,更新统计信息imx_uart_writel(sport, xmit->buf[xmit->tail], URTX0);xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);sport->port.icount.tx++;}if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)uart_write_wakeup(&sport->port);if (uart_circ_empty(xmit))imx_uart_stop_tx(&sport->port);
}

UART驱动情景分析-write相关推荐

  1. UART驱动情景分析-read

    一.源码框架回顾 shell读数据,一开始的时候没有就休眠.数据从串口发送到驱动,驱动接收到中断,驱动读取串口数据,这个数据会传给行规程. 行规程获取到数据后,会回显.按下删除就删除一个字符,按下回车 ...

  2. usb serial port 驱动_tty初探 — uart驱动框架分析

    写在前面: 我们没有讲UART驱动,不过我们认为,只要系统学习了第2期,应该具备分析UART驱动的能力,小编做答疑几年以来,陆陆续续有不少人问到UART驱动怎么写,所以今天就分享一篇深度长文(1700 ...

  3. tty初探 — uart驱动框架分析

    写在前面: 我们没有讲UART驱动,不过我们认为,只要系统学习了第2期,应该具备分析UART驱动的能力,小编做答疑几年以来,陆陆续续有不少人问到UART驱动怎么写,所以今天就分享一篇深度长文(1700 ...

  4. linux下I2C驱动发送IO时序,I2C驱动情景分析——怎样控制I2C时序

    内核版本:linux-3.4.2 源程序:    linux-3.4.2\drivers\i2c\busses\I2c-s3c2410.c 这次要解决的问题是:如何配置soc的I2C模块,输出想要的时 ...

  5. linux设备模型之tty驱动架构分析,linux设备模型之uart驱动架构分析

    五: uart_add_one_port()操作本文引用地址:http://www.eepw.com.cn/article/201610/305916.htm 在前面提到.在对uart设备文件过程中. ...

  6. 慢慢欣赏linux之串口驱动代码分析 - 基于powerpc 2.6.x版本

    串口驱动分两阶段初始化 第一阶段  串口驱动没有初始化前的准备工作,包括设备树的解析,platform设备注册 asmlinkage void __init start_kernel(void)    ...

  7. 基于Linux的UART驱动框架源码分析笔记

    文章目录 前言 一.I.MX6ULL串口接收和发送方式 1.非DMA方式 1.1.接收方式 1.2 发送方式 2.DMA方式 2.1.接收方式 2.2 发送方式 二.UART驱动注册 1.uart_r ...

  8. Linux UART驱动分析及测试

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

  9. i.MX6ULL终结者Linux RS232/485驱动实验i.MX6UL UART驱动分析

    文章目录 1 uart的platform驱动框架 2 uart_driver初始化 3 uart_port初始化和注册 4 imx_pops结构体 1 uart的platform驱动框架 首先看一下在 ...

最新文章

  1. debian php mysql 包_Linux+Varnish+Apache+MySQL+PHP一键包For Ubuntu/Debian
  2. 我的android绘图学习笔记(二)
  3. python打印小数
  4. 住手!!你不需要微服务!
  5. 一些基本的ABAP技巧
  6. b500k电位器引脚接法_可调电位器实物接线图及接线方法详解
  7. Pinyin4j中文字符和拼音之间的转换
  8. 让不带www的域名跳转到带www的域名
  9. hiho图的联通性(自留)
  10. oracle中只存储两年数据,Oracle中作为永久存储机制的嵌套表的数据追加
  11. 使用tail和head读取字节流
  12. MySQL 入门(一)—— 常用数据库介绍
  13. matlab 多变量最小值,【求助】用fmincon求含有多组变量的目标函数的最小值问题...
  14. 26字母的自然拼读发音规则和组合发音,字母本身音、元音、辅音、爆破音、摩擦音、连读、辅音浊化规则、、、、、
  15. python函数返回值可以有多个吗_Python函数中如何返回多个值?(代码示例)
  16. Web前端:HTML+CSS+JS实现美女照片3D立方体旋转
  17. 地表最强的 9 则程序员笑话
  18. 关于我和计算机的故事
  19. 软件项目管理的平衡原则和高效原则
  20. Presto的学习笔记

热门文章

  1. 新玺配资:投资决策时的股票收益率计算公式
  2. 字节换算(byte-to-bit)
  3. H3C DDNS配置简介
  4. Klayout如何导入图片进行画图--适合EBL套刻
  5. WAMP 下 awstats 配置
  6. 定位技术之室内定位浅析--新导智能
  7. 小试牛刀 --- Tinker集成教程
  8. idea环境下 servlet配置导致jsp页面显示源码问题
  9. 软件测试笔记2——什么是软件测试及软件测试分类
  10. kickstart 报错