linux中serial driver理解【转】

转自:http://blog.csdn.net/laoliu_lcl/article/details/39967225

英文文档地址:myandroid/kernel_imx/Documentation/serialg/driver。译文如下:

底层串口API

本文件介绍新串口驱动某些方面的简要概述。介绍并不全,有任何问题可以访问<rmk@arm.linux.org.uk>。

 

参考实现包含在amba_pl011.c内。

底层串口硬件驱动

--------------------------------

底层串口硬件驱动向核心串口驱动程序提供端口信息(定义在uart_port)和一系列控制方法(定义在uart_ops)。底层驱动也可以处理中断的端口,并提供任何控制台支持。

控制台支持

--------------------------------

串口核心提供一些帮助函数,包括确定的正确端口结构(通过uart_get_console)和解码命令行参数(uart_parse_options)。

还有一个帮助函数(uart_write_console),执行每个字符写功能,换行符译成CRLF序列。驱动程序开发者建议使用此函数,而不是实现它们自己的版本。

--------------------------------

底层硬件驱动程序使用port->lock来执行所需的锁定功能。有些情况例外(在下面列出的uart_ops中描述)。

 

有3个锁,每个端口自旋锁、每个端口tmpbuf信号和整体信号。

 

从核心驱动程序,port->lock锁定以下数据:

port->mctrl

       port->icount

       info->xmit.head(circ->head)

       info->xmit.tail(circ->tail)

底层驱动程序可以随时使用该锁来提供任意额外的锁定。

 

核心驱动程序使用info->tmpbuf_sem锁,以防止多线程访问端口写入的使用info->tmpbuf回弹缓冲区。

 

port_sem信号用来防止在不恰当的时间添加/删除或重新配置端口。

uart_ops

--------------------------------

uart_ops结构是serial_core和硬件特定驱动程序之间重要接口。包含控制硬件的所有方法。

 tx_empty(port)

此函数检查发送fifo和移位通过“端口”中描述的端口是否为空。如果为空,函数应返回TIOCSER_TEMT,否则返回0。如果端口不支持此操作,返回TIOCSER_TEMT。

锁:none

中断:取决于调用者;

此调用不休眠。

 

set_mctrl(port, mctrl)

此函数设置串口modem控制模式。mctrl相关的位是:

              - TIOCM_RTS       RTS signal.

              - TIOCM_DTR      DTR signal.

              - TIOCM_OUT1    OUT1 signal.

              - TIOCM_OUT2    OUT2 signal.

              - TIOCM_LOOP    设置端口为回环模式

如果相应的位被置位,该信号应被驱动为有效;如果该位清空,该信号应被驱动为无效。

锁定:采用port->lock

中断:本地禁用

此调用不休眠。

 

 get_mctrl(port)

返回modem控制输入的当前状态。不应返回输出状态,因为核心驱动追踪它们的状态。状态信息应包含:

              -TIOCM_DCD      state of DCD signal

              -TIOCM_CTS       state of CTS signal

              -TIOCM_DSR      state of DSR signal

              -TIOCM_RI   state of RI signal

如果信号当前是有效地,位被设置。如果端口不支持CTS、DCD 或DSR,驱动程序应指明该信号是持续有效的。如果RI不可用,该信号不应表示为有效。

锁定:采用port->lock

中断:本地禁用

此调用必须不休眠。

 

 stop_tx(port)

停止发送字符。这可能由于CTS线路变为非活动状态,或tty层表明由于XOFF字符我们要停止传输。

驱动程序应尽快停止传输字符。

锁定:采用port->lock

中断:本地禁用

此调用不休眠。

 

 start_tx(port)

开始传输字符。

锁定:采用port->lock

中断:本地禁用

此调用不休眠。

 

 stop_rx(port)

停止接收字符。端口处于即将关闭进程中。

锁定:采用port->lock

中断:本地禁用

此调用不休眠。

 

 enable_ms(port)

使能modem状态中断。

此方法可被多次调用,当调用shutdown方法时,modem状态中断禁用。

锁定:采用port->lock

中断:本地禁用

此调用不休眠。

 

 break_ctl(port,ctl)

控制中断信号的传输。如果ctl非零,中断信号应被传输。当另一个调用作为零ctl时,此信号应终止。

锁定:none

中断:取决于调用者

此调用不休眠。

 

 startup(port)

抓取任意中断资源,并初始化任一底层驱动状态。使能接收端口。不应该启用RTS和DTR;可通过一个单独的调用set_mctrl来完成。

此方法只有在端口最初打开时被调用。

锁定:采用port_sem

中断:全球禁用。

 

 shutdown(port)

禁用端口,禁用任何可能有效地中断条件,以及释放任何中断资源。不应该禁用RTS和DTR;可通过一个单独的调用set_mctrl来完成。

一旦调用完成,驱动程序不能访问port->info。

此方法只有当没有更多的用户端口时才被调用。

锁定:采用port_sem

中断:取决于调用者

 

  flush_buffer(port)

刷新任何写缓冲区,重置所有的DMA状态,并停止正在进行的DMA传输。

每当port->info->xmit循环缓冲区清零时都被调用。

锁定:采用port->lock

中断:本地禁用

此调用不能休眠。

 

 set_termios(port,termios,oldtermios)

改变端口参数,包括:字长、奇偶校验、停止位。更新read_status_mask而忽略状态掩码,表示我们有兴趣接收的事件类型。相应的termios->c_cflag位是:

CSIZE    - word size

              CSTOPB - 2 stop bits

              PARENB - parity enable

              PARODD- oddparity (when PARENB is in force)

              CREAD  - enable reception of characters (if not set,

                                 still receive characters from the port, but

                                  throwthem away.

              CRTSCTS       - if set, enable CTS status changereporting

              CLOCAL - if not set, enable modem status change

                                  reporting.

相应的termios->c_iflag位是:

               INPCK    - enable frame and parity error events to be

                                  passed to the TTY layer.

              BRKINT

              PARMRK       - both of these enable break events to be

                                passedto the TTY layer.

 

              IGNPAR - ignore parity and framing errors

              IGNBRK - ignore break errors,  If IGNPAR is also

                                 set,ignore overrun errors as well.

iflag位的相互作用如下(奇偶校验错误为例):

Parity error     INPCK    IGNPAR

       n/a          0          n/a         character received, marked as

                                               TTY_NORMAL

       None       1          n/a         character received, marked as

                                               TTY_NORMAL

       Yes         1             0          character received,marked as

                                               TTY_PARITY

       Yes         1           1           character discarded

如果你的硬件支持硬件“软”流量控制,其他标志可以使用(例如,XON / XOFF字符)。

锁定:none

中断:取决于调用者

此调用不能休眠。

 

 pm(port,state,oldstate)

在指定的端口上执行任何电源管理有关的活动。状态表示新状态(定义为ACPI D0-D3),旧状态表示以前状态。从本质上讲,D0表示完全供电,D3指断电。

此函数不应用于抓取任何资源。

当端口最初打开,最终关闭,除非该端口也是系统控制台时,这才被调用。即使CONFIG_PM没被设置,也会发生。

锁定:none

中断:取决于调用者。

 

 type(port)

返回一个指向字符串常量、描述指定端口的指针,或返回NULL,在这种情况下,字符串“unknow”被替换。

锁定:none

中断:取决于调用者。

 

 release_port(port)

释放目前在该端口使用的任何内存和IO区域资源。

锁定:none

中断:取决于调用者。

 

 request_port(port)

请求端口所需任意内存和IO区域资源。如果有任何失败,当该函数返回时,没有注册资源,它应该返回-EBUSY失败。

锁定:none

中断:取决于调用者。

 

 config_port(port,type)

执行所需端口的自动配置步骤。`type`包括所需配置的位掩码。UART_CONFIG_TYPE表示端口需要探测和识别。如果未检测到端口的类型,port->type应设置为已建立的类型或PORT_UNKNOWN。

UART_CONFIG_IRQ表示应采用标准内核自动探测技术探测的中断信号的自动配置。端口有中断的内部硬连接平台是内有必要的(例如,片上系统的实现)。

锁定:none

中断:取决于调用者。

 

 verify_port(port,serinfo)

验证包含在serinfo新的串口信息适于此端口类型。

锁定:none

中断:取决于调用者。

 

 ioctl(port,cmd,arg)

执行任何特定端口的IOCTLs。Ioctl命令使用标准编号系统定义,参见<asm/ioctl.h>。

锁定:none

中断:取决于调用者。

 

 

其他函数

---------------

uart_update_timeout(port,cflag,baud)

更新的FIFO消耗超时,port->timeout,根据位数、奇偶校验位数、停止位和波特率。

锁定:调用者预计需要port->lock

中断:n/a。

 

uart_get_baud_rate(port,termios,old,min,max)

返回指定termios的波特率数值,考虑到特定38400波特率,B0波特率被映射为9600波特率。

如果波特率不在min..max,旧的波特率不为null,那么原来的波特率将受到影响。如果超出min..max约束,9600波特将被退回。Termios更新到正在使用的波特率。

注意:min..max必须始终允许9600波特被选中。

锁定:取决于调用者

中断:n/a。

 

uart_get_divisor(port,baud)

返回除数(baud_base/波特)为指定的波特率,适当地舍入。

如果38400和自定义的除数被选中,返回自定义的除数来代替。

锁定:取决于调用者

中断:n/a。

 

uart_match_port(port1,port2)

该实用程序可用于确定两个uart_port结构是否拥有相同的端口。

锁定:n/a

中断:n/a。

 

uart_write_wakeup(port)

当发送缓冲区中的字符数已降低到低于阀值时,驱动程序将调用此函数。

锁定:使用port->lock。

中断:n/a。

 

uart_register_driver(drv)

向核心驱动程序注册串口驱动。我们依次注册tty层,初始化核心驱动程序每个端口的状态。

drv->port应该是NULL,调用成功后,使用uart_add_one_port函数注册每个端口结构。

锁定:none

中断:禁用。

 

uart_unregister_driver()

从核心驱动中删除驱动所有的声明。如果注册时使用uart_add_one_port()函数,底层驱动程序必须使用uart_remove_one_port()函数删除所有的端口。

锁定:none

中断:禁用。

 

uart_suspend_port()

uart_resume_port()

uart_add_one_port()

uart_remove_one_port()

 

其他注意事项

----------------------

它的目的是有一天从uart_port删除“未使用”的条目,底层驱动程序向核心驱动注册自己的单独uart_port。这将允许驱动程序把uart_port作为一个指向包含uart_port条目与自己的扩展结构指针来使用:

 

       structmy_port {

              structuart_port      port;

              int                 my_stuff;

       };

时间: 2024-09-13 04:09:23

linux中serial driver理解【转】的相关文章

对Linux中inode的理解

文件名 -> inode -> device block 转自:http://www.cnblogs.com/itech/archive/2012/05/15/2502284.html 一.inode是什么? 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个"块&

linux中关于路径的理解

 1.Linux文件系统是从/开始的:      在Linux操作系统的文件管理中,命令行模式(在控制台或终端下)的文件或目录管理,要涉及路径这一概念,这是Linux命令行操作的最基础的基础.如果我们了解了路径的概念,就可以随心所欲的进入任何目录,进行我们想的工作.      Linux 文件系统,是一个呈树形结构,是从/做为入口,/(也被称为根目录)下有子目录,比如etc.usr.lib等,在每个子目录下又有文件或子目录,这样就形成了一个树形结构,这种树形结构比较单一.而Windows文件系统

深入理解计算机系统-之-内存寻址(六)--linux中的分页机制

linux的分页机制 四级分页机制 前面我们提到Linux内核仅使用了较少的分段机制,但是却对分页机制的依赖性很强,其使用一种适合32位和64位结构的通用分页模型,该模型使用四级分页机制,即 页全局目录(Page Global Directory) 页上级目录(Page Upper Directory) 页中间目录(Page Middle Directory) 页表(Page Table) 页全局目录包含若干页上级目录的地址: 页上级目录又依次包含若干页中间目录的地址: 而页中间目录又包含若干页

深入理解计算机系统-之-内存寻址(四)--linux中分段机制的实现方式

linux中的分段机制 前面说了那么多关于分段机制的实现,其实,Linux以非常有限的方式使用分段.因为,Linux基本不使用分段的机制(注:并不是不使用,使用分段方式还是必须的,会简化程序的编写和运行方式),或者说,Linux中的分段机制只是为了兼容IA32的硬件而设计的.实际上,分段和分页在某种程度上显得有些多余,因为它们都可以划分进程的物理地址空间,分段可以给每一个进程分配不同的线性地址,而分页可以把同一线性地址,映射到不同的物理地址空间.与分段相比,linux更喜欢分页方式,因为: 当所

linux中文件描述符fd和文件指针flip的理解

整理自:http://www.cnblogs.com/Jezze/archive/2011/12/23/2299861.html 简单归纳:fd(file descriptor)只是一个整数,在open时产生.起到一个索引的作用.每个进程在PCB(Process Control Block)即进程控制块中都保存着一份文件描述符表,文件描述符就是这个表的索引,文件描述表中每个表项都有一个指向已打开文件的指针,进程通过PCB中的文件描述符表找到该fd所指向的文件指针filp. 文件描述符的操作(如:

深入理解Linux中的grep命令_linux shell

介绍 Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户. grep [-acinv] [--color=auto] '查找字符串' filename 参数:     -a :将binary文件以text文件的方式查找数据     -c :计算找到'查找字符串'的次数     -i :忽略大小写的区别,即把大小写视为相

Linux中如何克隆KVM虚拟机

Linux中如何克隆KVM虚拟机 作者 digoal 日期 2016-11-11 标签 Linux , KVM , 虚拟化 , 克隆 背景 当需要批量部署虚拟机时,通常有几种做法,使用模板重新安装. 或者使用已有的虚拟机克隆. 使用模板安装可以参考kickstart脚本的编写方法. <install kvm hosts use kickstart in CentOS 6 in text mode> 本文介绍一下在已经安装好的虚拟机上,克隆虚拟机的方法. 从0开始安装一个虚拟机 在服务器安装必要

I.MX6 Linux I2C device&amp; driver hacking

/******************************************************************************************* * I.MX6 Linux I2C device& driver hacking * 声明: * 1. 本文主要是对Linux I2C驱动进行代码跟踪,主要是为了能够对I2C驱动框架有个全面的了解: * 2. 本文源代码来自myzr_android4_2_2_1_1_0.tar.bz2: * 3. 如果你有兴趣,

浅析Linux中的时间编程和实现原理(一) Linux应用层的时间编程

引子 我们都生活在时间中,但却无法去思考它.什么是时间呢?似乎这是一个永远也不能被回答的问题.然而作为一个程序员,在工作中,总有那么几次我必须思考什么是时间.比如,需要知道一段代码运行了多久:要在 log 文件中记录事件发生时的时间戳:再比如需要一个定时器以便能够定期做某些计算机操作.我发现,在计算机世界中,时间在不同场合也往往有不同的含义,让试图思考它的人感到迷茫.但值得庆幸的是,Linux 中的时间终究是可以理解的.因此我打算讨论一下有关时间的话题,尝试着深入理解 Linux 系统中 C 语