现在的位置: 首页 > 综合 > 正文

终端控制台体系

2017年08月24日 ⁄ 综合 ⁄ 共 3597字 ⁄ 字号 评论关闭

数据通信--

并行通信

串行通信

异步通信--以一个字符为单位,通信中两个字符间的时间间隔不固定的,然而同一个字符中的两个相邻位之间的时间间隔是固定 的。

通信协议----是指通信双方约定的一些规则。在使用异步串口传送一个字符的信息时,对数据格式有如下约定:规定有空闲位,起始位,资料位,奇偶校验位,停止位

波特率---表示每秒传送的二进制位数。

注:异步通信是按字符传输的,接收设备在收到起始信号之后只要在一个字符的传输时间内能和发送设备保持同步就能正确接收。

传送方式----

单工方式

半双工方式

全双工方式

终端概述----

在linux中,TTY(终端)是一类字符设备的统称,包括了3种类型:控制台串口和伪终端

控制台----

供内核使用的终端为控制台。控制台在linux启动时,通过命令console=。。。指定,如果没有指定控制台,系统把第一个注册的终端(tty)作为控制台。

控制台---

1--控制台是一个虚拟的终端,它必须映射到真正的终端上。

2--控制台可以简单的理解为printk输出的地方。

3--控制台是个只能输出的设备,功能很简单,只能在内核中访问。

伪终端----

是一种特殊的终端设备,由主-从两个成对的设备构成,当打开主设备时,对应的从设备随之打开,形成连接状态。输入到主设备的数据成为从设备的输出,输入到从设备的数据成为主设备的输出,形成双向管道。伪终端设备常用于远程登录服务器来建立网络和终端的关联。当通过telnet远程登录到另一台主机时,telnet进程与远程主机的telnet服务器相连接,telnet服务器使用某个主设备并通过对应的从设备与telnet进程相互通信。

终端体系---


在linux中,TTY体系分为:TTY核心,TTY线路规程,TTY驱动3部分。TTY核心从用户获取要发送给TTY设备的数据,然后把数据传递给TTY线路规程,它对数据进行处理后,负责把数据传递到TTY驱动程序,TTY驱动程序负责格式化数据,并通过硬件发送出去。

从硬件收到的数据向上通过TTY驱动,进入TTY线路规程,再进入TTY核心,最后被用户获取。TTY驱动可以直接和TTY核心通讯,但是通常TTY线路规程会修改在两者之间传送的数据。TTY驱动不能直接和线路规程通信,甚至不知道它的存在,线路规程的工作是格式化从用户或者硬件收到的数据,这种格式化常常实现为一个协议,如PPP或Bluetooth。

读操作---

TTY驱动从硬件收到数据后,负责把数据传递到TTY核心,TTY核心将从TTY驱动收到的数据缓存到一个tty_flip_buffer类型的结构中。该结构包含两个数据数组。从tty设备接收到的数据被存储于第一个数组,当这个数组满时,等待数据的用户将被通知。当用户从这个数组读数据时,任何从TTY驱动新来的数据将被存储在第二个数组。当第二个数组存满后,数据再次提交给用户,并且驱动又开始填充第一个数组,以此交替。

注---若只有一个buffer,要加信号量,效率低,否则容易造成数据混乱。故弄两个。

驱动描述---

struct
uart_driver

{

struct module           *owner;

const char                *driver_name;驱动名

const char                *dev_name;设备名

int                             major;主设备号

int                             minor;起始次设备号

int                             nr; 设备数

struct console          *cons;

struct uart_state       *state;

struct tty_driver        *tty_driver;

}

注册驱动----

int uart_register_driver(struct uart_driver *drv)

端口描述---

uart_port用于描述一个UART端口(一个串口)的地址,FIFO大小,端口类型等信息。

struct
uart_port

{

spinlock_t lock;端口锁

unsigned int iobase;IO端口基地址

unsigned char __iomem *membase;IO内存基地址

unsigned int irq;中断号

unsigned char fifosize;传输fifo大小

const struct uart_ops *ops;operation set

..........................................................

}

操作串口----

uart_ops定义了针对串口的一系列操作,包括发送,接收及线路设置等。

struct uart_ops

{

unsigned int (*tx_empty) (struct uart_port *);

void (*set_mctrl) (struct uart_port *,unsigned int mctrl);

unsigned int (*get_mctrl) (struct uart_port * );

void (*stop_tx) (struct uart_port *);停止发送

void (*start_tx) (struct uart_port *);开始发送

void (*send_xchar) (struct uart_port *,char ch);发送xchar

void (*stop_tx) (struct uart_port *);停止接收

}

添加端口---串口核心层提供如下函数来添加一个端口

int uart_add_one_port(struct uart_driver *drv,struct uart_port *port)

操作流程----

1-定义一个uart_driver的变量,并初始化。

2-使用uart_register_driver来注册这个驱动;

3-初始化uart_port和ops函数表

4-调用uart_add_one_port()添加初始化好的uart_port.


串口驱动程序分析

1 发送和接收

发送:循环buffer->发送fifo->发送移位寄存器

接收:接收移位寄存器->接收fifo->flip_buf

发送的过程:把数据写到发送fifo中,fifo把收到的数据传给发送移位寄存器(自动的,非driver控制),然后每个时钟脉冲往串口线上写一bit数据。

接收过程:接收移位寄存器收到数据,发送给接收fifo,接收fifo事件设置好了触发门限,当里面的数据量超过门限时就会触发一个中断,调用驱动中的中断处理函数,把数据写到flip_buf

用printk,内核会根据日志级别,可能把消息打印到当前控制台上,这个控制台通常是一个字符模式的终端、一个串口打印机或是一个并口打印机。这些消息正常输出的前提是──日志输出级别小于console_loglevel(在内核中数字越小优先级越高)。  没有指定日志级别的printk语句默认采用的级别是
DEFAULT_ MESSAGE_LOGLEVEL(这个默认级别一般为<4>,即与KERN_WARNING在一个级别上),其定义在linux26/kernel/printk.c中可以找到。  

日志级别一共有8个级别,printk的日志级别定义如下(在include/linux/kernel.h中):

#define KERN_EMERG 0 紧急事件消息,系统崩溃之前提示,表示系统不可用  #define KERN_ALERT 1/*报告消息,表示必须立即采取措施*/  

#define KERN_CRIT 2/*临界条件,通常涉及严重的硬件或软件操作失败*/  

#define KERN_ERR 3/*错误条件,驱动程序常用KERN_ERR来报告硬件的错误*/  #define KERN_WARNING 4/*警告条件,对可能出现问题的情况进行警告*/  

#define KERN_NOTICE 5/*正常但又重要的条件,用于提醒*/  

#define KERN_INFO 6/*提示信息,如驱动程序启动时,打印硬件信息*/  

#define KERN_DEBUG 7/*调试级别的消息*/

 通过读写/proc/sys/kernel/printk文件可读取和修改控制台的日志级别。查看这个文件的方法如下:  #cat /proc/sys/kernel/printk 6 4 1 7  上面显示的4个数据分别对应控制台日志级别、默认的消息日志级别、最低的控制台日志级别和默认的控制台日志级别。  可用下面的命令设置当前日志级别:  #
echo 8 > /proc/sys/kernel/printk  这样所有级别<8,(0-7)的消息都可以显示在控制台上.






抱歉!评论已关闭.