ImageVerifierCode 换一换
格式:DOCX , 页数:22 ,大小:126.49KB ,
资源ID:3546616      下载积分:12 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/3546616.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Linux终端控制台体系及串口驱动分析.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Linux终端控制台体系及串口驱动分析.docx

1、Linux终端控制台体系及串口驱动分析Linux终端控制台体系及串口驱动分析数据通信的基本方式可分为并行通信与串行通信两种:并行通信:利用多条数据线路将数据的各位同时传送。它的特点是传输速度快,适用于短距离通信。串行通信:利用一条数据线将数据一位位顺序传送。特点是通信线路简单,利用简单的线缆就可实现通信,低成本,适用于远距离通信。异步通信以一个字符为传输单位,通信中的两个字符间的时间间隔是不固定的,然而同一个字符中的两个相邻位之间的时间间隔是固定的。通信协议:是指双方约定的一些规则。在使用异步串口传送一个字符信息时,对数据格式有如下规定:规定有空闲位、起始位、资料位、奇偶校验位、停止位。起始位

2、:先发一个逻辑“0”信号,表示传输字符的开始数据位:紧接在起始位之后。数据位的个数可以是4、5、6、7、8,从最低位开始传送,靠时钟定位。奇偶校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此校验数据传送的正确性。停止位:它是一个字符数据的结束标志。空闲位:处于逻辑“1”状态,表示当前线路上没有数据传送。波特率:是衡量数据传送速率的指针。表述每秒钟传送的二进制位数。注:异步通信是按字符传输的,接收设备在收到起始信号之后在一个字符的传输时间内能和发送设备保持同步就能正确接收。传送方式:单工方式、半双工方式、全双工方式终端概述:在Linux中,TTY(终端)是一类

3、字符设备的统称,它包括了3种类型:控制台、串口和伪终端。控制台:供内核使用的终端为控制台。控制台在Linux启动时,通过命令console=指定,如果没有指定控制台,系统把第一个注册的终端(tty)作为控制台。1、 控制台是一个虚拟的终端,它必须映射到真正的终端上。2、 控制台可以简单的理解为printk输出的地方3、 控制台是个只输出的设备,功能很简单,只能在内核中访问。伪终端:伪终端设备是一种特殊的终端设备,由主-从两个成对的设备构成,当打开主设备时,对应的从设备随之打开,形成连接状态。输入到主设备的数据成为从设备的输出,输入到从设备的数据成为主设备的输出,形成双向管道。伪终端设备通常用于

4、远程登录服务器来建立网络和终端的关联。当通过telnet远程登录到另一台主机时,telnet进程与远程主机的telnet服务器相连接。telnet服务器使用某个主设备并通过对应的从设备与telnet进程相互通信。终端体系:从上往下:TTY coreTTY line discipline(可以没有)tty driver 在Linux中,TTY体系分为:TTY核心、TTY线路规程、TTY驱动3部分。TTY核心从用户获取要发送给TTY设备的数据,然后把数据传送给TTY线路规程(协议),它对数据进行处理后,负责把数据传递到TTY驱动程序,TTY驱动程序负责格式化数据,并通过硬件发送出去。从硬件收到的数

5、据向上通过TTY驱动,进入TTY线路规程,再进入TTY核心,最后被用户获取。TTY驱动可以直接和TTY核心通讯,但通常TTY线路规程会修改在两者之间的传送的数据。TTY驱动不能直接和线路规程通信,甚至不知道它的存在,线路规程的工作是格式化从用户或者硬件收到的数据。这种格式常常实现为一个协议,如PPP或Bluetooth终端体系串口()往串口发送数据时的数据流向:/dev/ttys0(串口的设备文件)tty_io.c(TTY core)n_tty.c(tty线路规程,必须向core注册)处理完返回tty core再由tty core交给驱动程序serial.c驱动程序控制硬件数据流 读操作:TT

6、Y驱动从硬件接收到数据后,负责把数据传送到TTY核心,TTY核心将从TTY驱动收到的数据缓存到一个tty_flip_buffer类型的结构中。该结构包含两个数据数组(一个用于读、一个用于写)。从TTY设备接收到的数据被存储到第一个数组,当这个数组满,等待数据的用户将被通知。当用户从这个数组读数据时,任何从 TTY驱动新来的数据被存储在第2个数组。当第二个数组存满后,数据再次提交给用户,并且驱动又开始填充第1个数组,以此交替。驱动描述:Linux内核使用uart_driver描述串口驱动,它包含串口设备的驱动名、设备名、设备号等信息。 struct uart_driver struct modu

7、le *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;注册驱动:Linux为串口驱动注册了如下接口:int uart_register_driver(struct uart_driver *drv)端口描述:uart_port用于描述一个UART端口(一个串口)的地址

8、、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; .操作串口: uart_ops定义了针对串口的一系列操作,包括发送、接收及线路设置等。struct uart_ops unsigned int(*tx_

9、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_poart*); /停止发送 void (*start_tx)(struct uart_poart*); /开始发送 void(*send_xchar)(struct uart_poart*, char ch); /发送xchar void(*stop_rx)(struct uart_p

10、ort*); /停止接收 .添加串口:串口核心层提供如下函数添加1个端口:int uart_add_one_port(struct uart_driver*drv, struct uart_port* port)串口驱动设计流程:1、 定义一个uart_driver的变量,并初始化2、 使用uart_regisetr_driver来注册这个驱动3、 初始化uart_port和ops函数表4、 调用uart_add_one_poart()添加初始化好的uart_port 实例分析mini2440串口驱动程序分析 1发送和接收发送:循环buffer 发送fifo发送移位寄存器 /循环buffer(

11、驱动实现) 发送fifo(串口芯片)过程由驱动程序完成;发送fifo发送移位寄存器过程由硬件完成接收:接收移位寄存器接收fifo Flip_buf 发送的过程是:把数据写到发送fifo中,fifo把收到的数据传给发送移位寄存器(自动的,非driver控制),然后每个时钟脉冲往串口线上写一bit数据。接收的过程是:接收移位寄存器收到数据,发送给接收fifo,接收fifo事先设置好了触发门限,当里面的数据量超过门限时就会触发一个中断,调用驱动中的中断处理函数,把数据写到flip_buf中。 2寄存器UART Line Control Register:Word Length :数据位长度Numbe

12、r of Stop Bit :停止位数Parity Mode :奇偶校验位类型Infra-Red Mode :UART/红外模式选择(当以UART模式工作时,需设为“0”)UART Control RegisterReceive Mode:选择接收模式。如果是采用DMA模式的话,还需要指定说使用的DMA信道。Transmit Mode :同上。Send Break Signal :选择是否在传1帧资料中途发送Break信号。Loopback Mode :选择是否将UART置于Loopback测试模式。Rx Error Status Interrupt Enable :选择是否使能当发生接收异常

13、时,是否产生接收错误中断。Rx Time Out Enable :是否使能接收超时中断。Rx Interrupt Type :选择接收中断类型。选择0:Pulse(脉冲式/边沿式中断。非FIFO模式时,一旦接收缓冲区中有数据,即产生一个中断;为FIFO模式时,一旦当FIFO中的资料达到一定的触发水平后,即产生一个中断)选择1:Level(电平模式中断。非FIFO模式时,只要接收缓冲区中有数据,即产生中断;为FIFO模式时,只有FIFO中的资料达到触发水平后,即产生中断)Tx Interrupt Type :类同于Rx Interrupt TypeUART FIFO Conrtol Regist

14、erFIFO Enable :FIFO使能选择。Rx FIFO Reset :选择当复位接收FIFO时是否自动清除FIFO中的内容。Tx FIFO Reset :选择当复位发送FIFO时是否自动清除FIFO中的内容。Rx FIFO Trigger Level :选择接收FIFO的触发水平。Tx FIFO Trigger Level :选择发送FIFO的触发水平。UART TX/RX Status RegisterReceive buffer data ready :当接收缓冲寄存器从UART接收端口接收到有效资料时将自动置“1”。反之为“0则表示缓冲器中没有资料。Transmit buffer

15、 empty :当发送缓冲寄存器中为空,自动置“1”;反之表明缓冲器中正有资料等待发送。Transmitter empty :当发送缓冲器中已经没有有效资料时,自动置“1”;反之表明尚有资料未发送。UART FIFO Status RegisterRx FIFO Count :接收FIFO中当前存放的字节数。Tx FIFO Count :发送FIFO中当前存放的字节数。Rx FIFO Full :为“1“表明接收FIFO已满。Tx FIFO Full :为“1“表明发送FIFO已满。3函数介绍模块初始化函数:static int _init s3c2410uart_init(void)retu

16、rn uart_register_driver(&s3c2410_reg);使用uart_register_driver注册串口驱动。static struct uart_driver s3c2410_reg = owner: THIS_MODULE, normal_major: SERIAL_S3C2410_MAJOR, normal_name: ttyS%d, callout_name: cua%d, normal_driver: &normal, callout_major: CALLOUT_S3C2410_MAJOR, callout_driver: &callout, table:

17、s3c2410_table, termios: s3c2410_termios, termios_locked: s3c2410_termios_locked, minor: MINOR_START, nr: UART_NR, port: s3c2410_ports, cons: S3C2410_CONSOLE,;static struct uart_port s3c2410_portsUART_NR = iobase: (unsigned long)(UART0_CTL_BASE), iotype: SERIAL_IO_PORT, irq: IRQ_RXD0, uartclk: 130252

18、800, fifosize: 16, ops: &s3c2410_pops, type: PORT_S3C2410, flags: ASYNC_BOOT_AUTOCONF, , 。 。 。;static struct uart_ops s3c2410_pops = tx_empty: s3c2410uart_tx_empty,set_mctrl: s3c2410uart_set_mctrl, get_mctrl: s3c2410uart_get_mctrl, stop_tx: s3c2410uart_stop_tx, start_tx: s3c2410uart_start_tx, stop_r

19、x: s3c2410uart_stop_rx, enable_ms: s3c2410uart_enable_ms, break_ctl: s3c2410uart_break_ctl, startup: s3c2410uart_startup, shutdown: s3c2410uart_shutdown, change_speed: s3c2410uart_change_speed, type: s3c2410uart_type, config_port: s3c2410uart_config_port, release_port: s3c2410uart_release_port, requ

20、est_port: s3c2410uart_request_port,;3.1 阻止发送函数uart_stop_tx static void s3c2410uart_stop_tx(struct uart_port *port, u_int from_tty) disable_irq(TX_IRQ(port); 停止发送的功能,其内部的函数disable_irq是停止中断的功能 ,发送数据是通过中断来完成的,关闭中断也就关闭了发送。3.2 发送使能函数uart_start_txstatic void s3c2410uart_start_tx(struct uart_port *port, u_

21、int nonempty, u_int from_tty) enable_irq(TX_IRQ(port); 与上面的过程类似,就是一个相反的过程 3.3 阻止接收函数uart_stop_rx static void s3c2410uart_stop_rx(struct uart_port *port) disable_irq(RX_IRQ(port); 3.4 发送缓冲空判断函数uart_tx_emptystatic u_int s3c2410uart_tx_empty(struct uart_port *port) return (UART_UTRSTAT(port) & UTRSTAT_

22、TR_EMP ? 0 : TIOCSER_TEMT); 如果发送缓冲为空则返回0,否则返回1。 3.5 获取控制信息函数uart_get_mctrl static u_int s3c2410uart_get_mctrl(struct uart_port *port) return (TIOCM_CTS | TIOCM_DSR | TIOCM_CAR); 获得控制信息, TIOCM_CTS ,TIOCM_DSR 和TIOCM_CAR,这几个宏代表串口的控制信息, 分别是clear to send,data set ready和data carrier detect(详见Serial Progra

23、mming Guide for POSIX Operating Systems) 3.6 接收中断函数uart_rx_interrupt static void s3c2410uart_rx_interrupt(int irq, void *dev_id, struct pt_regs *regs) struct uart_info *info = dev_id; struct tty_struct *tty = info-tty; unsigned int status, ch, max_count = 256; struct uart_port *port = info-port; sta

24、tus = UART_UTRSTAT(port); while (status & UTRSTAT_RX_RDY) & max_count-) / status & UTRSTAT_RX_RDY判断有数据if (tty-flip.count = TTY_FLIPBUF_SIZE) /flipbuf已满tty-flip.tqueue.routine(void *) tty); /交换到另一个缓冲数组if (tty-flip.count = TTY_FLIPBUF_SIZE) /再进行判断printk(KERN_WARNING TTY_DONT_FLIP setn); return; ch = U

25、ART_URXH(port); /从寄存器中取数据*tty-flip.char_buf_ptr = ch; *tty-flip.flag_buf_ptr = TTY_NORMAL; port-icount.rx+; tty-flip.flag_buf_ptr+; tty-flip.char_buf_ptr+; tty-flip.count+; /处理一个字节 status = UART_UTRSTAT(port); tty_flip_buffer_push(tty); return; 功能:主要是是while大循环,首先看循环判断条件status & UTRSTAT_RX_RDY,前面有sta

26、tus = UART_UTRSTAT(port),查2410的datasheet, status & UTRSTAT_RX_RDY这个位是判断接收buffer内是否还有有效数据?按道理一次中断只是把接收的fifobuffer中的数据放到flipbuffer中去,接收的fifo的中断门限是4-12字节,进行一次接收往往要中断好多次,这样中断开销比较大,所以在while的循环条件中判断一下是否还有接收的有效数据,如果有,就继续在中断程序中继续接收,当然,永远都在接收中断中(如果一直有数据要接收)也不合适,所以while循环还有计数,最多循环256次。 在循环中,首先是要判断一下接收数据用的flip

27、-buffer是不是已经满了, if (tty-flip.count = TTY_FLIPBUF_SIZE)如果满了,就要跳到另一个buffer上去, tty-flip.tqueue.routine(void *) tty)是用来实现跳到另一个buffer上的功能,然后把收到的数据写到flip-buffer中,相应的状态,统计数据都要改,接着再来while 循环,循环结束后就要调用tty_flip_buffer_push(tty)来让用户把存在缓冲里的数据取走,接收一次都要把缓存清空。3.7 发送中断函数uart_tx_interrupt static void s3c2410uart_tx_

28、interrupt(int irq, void *dev_id, struct pt_regs *reg) struct uart_info *info = dev_id; struct uart_port *port = info-port; int count; if (port-x_char) /x_char为停止位UART_UTXH(port) = port-x_char; port-icount.tx+; port-x_char = 0; return; if (info-xmit.head = info-xmit.tail /无数据发送| info-tty-stopped | in

29、fo-tty-hw_stopped) s3c2410uart_stop_tx(info-port, 0); /关闭发送中断return; count = port-fifosize 1; do /有数据发送UART_UTXH(port) = info-xmit.bufinfo-xmit.tail; info-xmit.tail = (info-xmit.tail + 1) & (UART_XMIT_SIZE - 1); port-icount.tx+; if (info-xmit.head = info-xmit.tail) break; while (-count 0); /count=fi

30、fpsize(16字节)1即8字节if (CIRC_CNT(info-xmit.head, info-xmit.tail, UART_XMIT_SIZE) xmit.head = info-xmit.tail) s3c2410uart_stop_tx(info-port, 0); (1) 首先查看port中的x_char是不是为0,不为0则把x_char发送出去。x_char是xon/xoff的意思,每发一个字节时在开始前先发xon信号,在结束时发xoff。 (2) 如果x_char没有被设置,再看环形缓冲区是否为空,或者info-tty-stopped 和 info-tty-hw_stopped 两个位是不是为1,如果这些条件成立的话,就停止发送。Tty-stop指示

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1