[tty与uart]2.tty和uart的函数调用流程
以下是在include/uapi/linux/tty.h中定义了现有的线规号,如果需要定义新的,则需要在后面添加新的
/* line disciplines */
#define N_TTY 0
#define N_SLIP 1
... ...
#define N_TRACESINK 23 /* Trace data routing for MIPI P1149.7 */
#define N_TRACEROUTER 24 /* Trace data routing for MIPI P1149.7 */
1.应用层发送数据
-->write()
-->file_operation.tty_write /* file_operation函数集在何时被赋值? */
-->do_tty_write(ld->ops->write, tty, file, buf, count) /* tty_ldisc->tty_ldisc_ops->write */
-->tty_ldisc_ops.ldisc_write /* tty_ldisc_ops函数集在何时被赋值? */ ///该write函数是在线路规程模块中定义
-->tty->driver->ops->write (tty, tbuf->buf, tbuf->count) /* tty_struct->tty_driver->tty_operations->write */
-->tty_operations.uart_write /* tty_operation函数集在何时被赋值? */
-->uart_start(tty);
-->__uart_start(tty);
-->port->ops->start_tx(port); /* uart_port->uart_ops->start_tx */
-->uart_ops.imx_start_tx /* uart_ops函数集在何时被赋值? */
至此消息也发送出去了,从消息流程可以看出来消息是经过ldisc线路规程层,然后tty层,然后到硬件驱动层。
上面的调用关系有个问题,为什么顺序是调到ldisc层,又调回tty层,再直接到hardware层?
- file_operation.do_tty_write(ld->ops->write, tty, file, buf, count)::: tty_ldisc->ops->(*write)(struct tty_struct *tty, struct file *file, const unsigned char *buf, size_t nr);
- tty_ldisc_ops.n_tty_write(struct tty_struct *tty, struct file *file,const unsigned char *buf, size_t nr):::tty->ops->write(tty, b, nr); tty_operations->ops->(*write)(struct tty_struct * tty,const unsigned char *buf, int count)
- tty_operations.uart_write(struct tty_struct * tty, const unsigned char *buf, int count )::: memcpy(circ->buf + circ->head, buf, c);
- uart_ops.imx_start_tx(struct uart_port *port)::: writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
2.uart和tty逐层调用关系
2.1.关于file_operation函数集的赋值
- uart_register_driver函数中完成了file_operations和tty_operations函数集的初始化
-->uart_register_driver(uart_driver*) //uart driver驱动文件中
-->tty_set_operations(normal, &uart_ops);//完成tty_operation赋值,serail_core.c中初始化结构体
-->tty_register_driver(normal)
-->tty_cdev_add(driver, dev, 0, driver->num);
-->cdev_init(&driver->cdevs[index], &tty_fops);//而tty_fops为file_operations 类型,tty_io.c中初始化结构体
/* drivers/tty/tty_io.c */
static const struct file_operations tty_fops = {
.llseek = no_llseek,
.read = tty_read,
.write = tty_write,
.poll = tty_poll,
.unlocked_ioctl = tty_ioctl,
.compat_ioctl = tty_compat_ioctl,
.open = tty_open,
.release = tty_release,
.fasync = tty_fasync,
};
2.2.关于tty_operation函数集的赋值(同上)
-->uart_register_driver(uart_driver*) //uart driver驱动文件中
-->tty_set_operations(normal, &uart_ops); //完成tty_operation赋值,serial_core.c
-->tty_register_driver(normal)
/* drivers/tty/serial/serial_core.c */
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.3.关于tty_ldisc_ops函数集的赋值
-->tty_register_ldisc(ldisc, tty_ldisc_ops); /* 此函数可以是在线路规程模块初始化时调用 */
-->tty_ldiscs[disc] = tty_ldisc_ops; /* 可见是tty_ldiscs中包含每个线路规程号对应的ops函数集, 假如是默认tty, 则在n_tty.c中,全局变量tty_ldisc_N_TTY */
下面只是默认N_tty.c中默认线路规程号N_tty的例子,用户可以编写自己的线路规程模块,进行数据封装,有自己的方法集。
/* drivers/tty/N_tty.c */
struct tty_ldisc_ops tty_ldisc_N_TTY = {
.magic = TTY_LDISC_MAGIC,
.name = "n_tty",
.open = n_tty_open,
.close = n_tty_close,
.flush_buffer = n_tty_flush_buffer,
.chars_in_buffer = n_tty_chars_in_buffer,
.read = n_tty_read,
.write = n_tty_write,
.ioctl = n_tty_ioctl,
.set_termios = n_tty_set_termios,
.poll = n_tty_poll,
.receive_buf = n_tty_receive_buf,
.write_wakeup = n_tty_write_wakeup,
.fasync = n_tty_fasync,
.receive_buf2 = n_tty_receive_buf2,
};
2.4.关于uart_ops函数集赋值
-->platform_driver_register(platform_driver*)
-->serial_imx_probe() //设备驱动匹配
-->sport->port.ops = &imx_pops; //调用也是通过port口来调ops
这里举的例子是freescale的串口方法集
/* drivers/tty/serial/imx.c */
static struct uart_ops imx_pops = {
.tx_empty = imx_tx_empty,
.set_mctrl = imx_set_mctrl,
.get_mctrl = imx_get_mctrl,
.stop_tx = imx_stop_tx,
.start_tx = imx_start_tx,
.stop_rx = imx_stop_rx,
.enable_ms = imx_enable_ms,
.break_ctl = imx_break_ctl,
.startup = imx_startup,
.shutdown = imx_shutdown,
.flush_buffer = imx_flush_buffer,
.set_termios = imx_set_termios,
.type = imx_type,
.release_port = imx_release_port,
.request_port = imx_request_port,
.config_port = imx_config_port,
.verify_port = imx_verify_port,
#if defined(CONFIG_CONSOLE_POLL)
.poll_get_char = imx_poll_get_char,
.poll_put_char = imx_poll_put_char,
#endif
#ifdef CONFIG_IB2_SUPPORT
.ioctl = imx_ioctl,
#endif
};
3.线路规程号配置
3.1.Console的线路规程是怎么回事?
-->__init console_init(void)
-->tty_ldisc_begin(); /* Setup the default TTY line discipline. */
-->(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY); /* tty_ldisc_N_TTY中对应都是n_tty_**函数集 */
3.2.那么其他串口的的线路规程默认是怎样的?也是N_TTY吗?
答案:是的,这要从应用层open设备文件开始说起
亦可参考该链接:http://blog.csdn.net/rockrockwu/article/details/7897283
-->open("/dev/ttys0",O_RDWR|O_NOCTTY); /* app layer */
-->tty_operations.tty_open
-->tty_init_dev
-->initialize_tty_struct
-->tty_ldisc_init
-->struct tty_ldisc *ld = tty_ldisc_get(N_TTY)
-->struct tty_struct *tty->ldisc = ld; /* 至此tty_struct和N_TTY绑定,该串口默认线路规程 */
3.3.应用程序修改线路规程
如果不适用默认的线路规程,需要在串口实现一些协议,那该如何做呢?--新建线路规程号,实现线路规程代码
ioctl(fd, TIOCSETD, &ldisc); //application:ldisc=25
-->tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) /* tty_io.c*/
-->tiocsetd(tty, p)
-->tty_set_ldisc(tty, ldisc)
-->tty->ldisc = new_ldisc; /* Now set up the new line discipline. */
至此完成了新的ldisc设置。
4.推荐几个Linux uart的博客
http://www.uml.org.cn/embeded/201209071.asp
http://www.wowotech.net/linux_kenrel/183.html
http://blog.csdn.net/goodluckwhh/article/details/13368279
[tty与uart]2.tty和uart的函数调用流程的更多相关文章
- [tty与uart]3.tty驱动分析
转自:http://www.wowotech.net/linux_kenrel/183.html 目录: 1 首先分析设备驱动的注册 1.1 uart_register_driver分析 1.2 tt ...
- [uart]3.tty驱动分析
转自:http://www.wowotech.net/linux_kenrel/183.html 目录: 1 首先分析设备驱动的注册 1.1 uart_register_driver分析 1.2 tt ...
- [uart]2.tty和uart的函数调用流程
以下是在include/uapi/linux/tty.h中定义了现有的线规号,如果需要定义新的,则需要在后面添加新的 /* line disciplines */ #define N_TTY 0 #d ...
- s3c2440裸机-UART编程(二、UART编程实现)
UART编程 1.初始化 我们的2440支持3个UART串口,以uart0为例讲解. 那么我们需要实现以下这几个函数完成串口的最基本功能: (1)uart0_init()用于初始化串口 (2)putc ...
- s3c2440裸机-UART编程(一、UART硬件介绍及传输原理)
1.uart硬件介绍 UART的全称是Universal Asynchronous Receiver and Transmitter(异步收发器). uart主要用于: 1.打印调试 2.数据传输 串 ...
- tty初探 — uart驱动框架分析
写在前面: 我们没有讲UART驱动,不过我们认为,只要系统学习了第2期,应该具备分析UART驱动的能力,小编做答疑几年以来,陆陆续续有不少人问到UART驱动怎么写,所以今天就分享一篇深度长文(1700 ...
- 一、uart&tty驱动
一.I.MX6 UART驱动 文件路径:\linux_IMX6_CoreC_3..35_for_Linux\drivers\tty\serial\imx.c .驱动入口函数:imx_serial_in ...
- 十一、UART&TTY驱动
Linux系统中UART驱动和TTY驱动两者有着紧密的关系,它们不像I2C和SPI驱动是单独一个模块,分析时应当将它们看成一个整体来分析.UART驱动部分依赖于硬件平台,而TTY驱动和具体的平台无关. ...
- 基于Linux的tty架构及UART驱动详解
更多嵌入式Linux原创,请关注公众号:一口Linux 一.模块硬件学习 1.1. Uart介绍 通用异步收发传输器(Universal Asynchronous Receiver/Transmitt ...
随机推荐
- DEDECMS调用特定ID文章内容的实现方法
DEDECMS调用特定ID文章内容的实现方法 {dede:loop table='dede_addonarticle' sort='aid' row='8' if='aid=524'} [field: ...
- ZSDR101-跑成品MRP
*&---------------------------------------------------------------------**& Report ZSDR101*&a ...
- 343. Integer Break
Given a positive integer n, break it into the sum of at least two positive integers and maximize the ...
- Java 23种设计模式全解析
转自:http://blog.csdn.net/longyulu/article/details/9159589
- 第九章 C语言在嵌入式中的应用
上章回顾 编码的规范和程序版式 版权管理和申明 头文件结构和作用 程序命名 程序注释和代码布局规范 assert断言函数的应用 与0或NULL值的比较 内存的分配和释放细节,避免内存泄露 常量特性 g ...
- 通过laravel理解IoC(控制反转)容器和DI(依赖注入)
原文地址: http://www.insp.top/learn-laravel-container ,转载务必保留来源,谢谢了! 容器,字面上理解就是装东西的东西.常见的变量.对象属性等都可以算是容器 ...
- 【BZOJ1010】【HNOI2008】玩具装箱
继续看黄学长代码 原题: P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1.. ...
- Vimdiff---VIM的比较和合并工具
本文来自IBMDW http://www.ibm.com/developerworks/cn/linux/l-vimdiff/ 源程序文件(通常是纯文本文件)比较和合并工具一直是软件开发过程中比较 ...
- Python 基本语法1
Python 基础语法(一) Python的特点 1. 简单 Python是一种代表简单思想的语言. 2. 易学 Python有极其简单的语法. 3. 免费.开源 Python是FLOSS(自由/开放 ...
- 论文笔记之:From Facial Parts Responses to Face Detection: A Deep Learning Approach
From Facial Parts Responses to Face Detection: A Deep Learning Approach ICCV 2015 从以上两张图就可以感受到本文所提方法 ...