基于arm和uclinux多串口通讯的设计与实现3图文Word格式文档下载.docx
- 文档编号:6824491
- 上传时间:2023-05-07
- 格式:DOCX
- 页数:14
- 大小:479.18KB
基于arm和uclinux多串口通讯的设计与实现3图文Word格式文档下载.docx
《基于arm和uclinux多串口通讯的设计与实现3图文Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《基于arm和uclinux多串口通讯的设计与实现3图文Word格式文档下载.docx(14页珍藏版)》请在冰点文库上搜索。
工作原理
图1 TL16C752B功能模块图[1]
TL16C752B芯片与UART芯片ST16C2550引脚兼容,使用外部晶振时有高达3Mbps的波特率,内置两套UART系统,每套都能独立工作,具有可选的流控功能等。
TL16C752B具有64字节发送/接收FIFO,收、发FIFO的触发等级可通过软件编程实现,能减少对CPU中断次数,提高芯片收发效率。
TL16C752B芯片功能模块如图1所示。
2.2 接口电路设计
处理器S3C44B0X[2]与TL16C752B之间的硬件连接如图2所示,D0~D7通过总线收发芯片SN74LVC16245A连接CPU数据总线的低8位,是
441 计算机与数字工程 第35卷3收到本文时间:
2006年9月20日
作者简介:
王欣,男,硕士研究生,研究方向:
嵌入式系统、数字图像处理。
罗志祥,男,副教授,硕士生导师,研究方向:
宽带光通信,
传感器网络。
沈光,男,硕士研究生,研究方向:
嵌入式系统。
UART的数据输入与输出通道,其中SN74LVC16245A是用来延时和增强数据总线驱动
能力;
片选CSA、CSB连接Bank4和Bank5的引脚nCGS4、nGCS5,这两个片选可以确定2个UART端口的起始地址,分别是0x08000000、0x0a000000。
即高位地址部分已固定,而片内寄存器的地址主要由地址低3位A0~A2确定。
只有在片选信号和地址信号都有效时,才能对片内相应的寄存器进行正常读写。
要注意的是,Bank4和Bank5的控制寄存器的设置要参考TL16C752B
图2 S3C44B0X与TL16C752B硬件连接图
采用中断方式通知CPU接收到新的字符或字符已发送,这样可以提高系统的实时性。
这里中断引脚INTA、INTB直接连接S3C44B0X的外部中断引脚EXINT2~EXINT3。
接入TL16C752B的外接时钟频率最好是使用的波特率的倍数。
本文使用的是11.0592M的外部时钟,输出的的串口波特率是115200。
TL16C752B内部寄存器的映射表及访问方法在参考文献[1]中可查到。
3 串行设备驱动程序设计
3.1 uClinux
系统内核架构
图3 uClinux内核架构(字符型设备
设备驱动程序是操作系统内核与机器硬件之
间的接口。
它为应用程序屏蔽了硬件的细节。
在应用程序看来,硬件设备只是一个设备文件,应用程序可以像操作普通文件一样对硬件设备进行操作。
而事实上,对硬件的所有实际操作都是由用户空间的应用程序调用内核空间的驱动程序来完成操作的。
在uClinux(本文使用2.4.20中:
、网络接口型。
其中字,(比如文件一样被访问。
open、close、read和write等系统调用,如图3所示。
3.2 串行设备驱动的分析
在uClinux内核中提供了访问串行硬件的设备,通常叫tty设备(tty是Teletype的简写,也可称为终端设备,现在用来表示任何基于字符的数据终端。
uClinux提供了三类tty设备:
串行设备(有的书中干脆称为串口,控制台,伪终端(pty。
其中,后两者的命名只是因为从程序员的角度来看,它们和典型的tty设备(即串行设备以相似的方
式工作,且它们的驱动程序已经被编写好了,而且可能也不必为这两类tty驱动程序编写其他的驱动程序。
这使得任何使用tty核心与用户和系统交互的新驱动程序都可以被看成是串行设备驱动程序。
本文所设计的硬件就是典型的串行设备。
下面将详细介绍tty类设备驱动的层次结构和串行设备驱动的实现。
3.2.1 TTY驱动的层次结构
在uClinux系统中,tty驱动根据它们与设备的关系,以及在执行流程中的位置,可以分为tty驱动程序和与上层直接联系的tty驱动接口程序。
可以用图4示意图来表示这种控制关系。
各种串行设备都有自己的tty驱动程序来控制硬件。
在tty驱动程序上层接口中,tty驱动程序的核心紧挨在标准字符设备驱动层之下,并提供了一系列的功能,作为接口被终端类型设备使用。
内核负责控制通过tty设备的数据流,并且格式化这些数据。
这使得tty驱动程序把重点放在处理流向或者流出硬件的数据上,而不必重点考虑使用常规方法与用户空间的交互。
为了控制数据流,有许多不同的线路设置(linediscipline可虚拟地“插入”任何的tty设备上,这由不同的tty线路设置驱动程序实现。
tty线路设置对于tty驱动程序来说是不透明
的。
驱动程序不能直接与线路设置通信,甚至不知
5
41第35卷(2007第8期 计算机与数字工程
道它的存在。
在某种意义上讲,驱动程序的作用是将发送给它的数据格式化成硬件能理解的格式,并从硬件那里接收数据。
tty线路设置的作用就是使用特殊的方法,把从用户或者硬件那里接收的数据格式化。
这种格式化通常使用一些协议来完成转
换,比如PPP或者是蓝牙(Bluetooth[3]
。
图4 tty驱动层次结构图
在tty驱动中使用到了一些数据结构,这些数据结构关联了整个tty驱动的各个层次。
如图4和图5所示,这些数据结构有如下几种。
在终端驱动程序上层接口tty_io.c文件中定义了终端驱动程序的文件操作结构file_operations实例-用于和用户空间通讯,这是典型的字符设备的结构,它的每一个成员函数都将与系统调用的read、write、ioctl等关联起来。
在文件中还定义了tty_struct结构实例(如图4虚线框所示,它内部包含了下面的三种结构-它描述了通用(或高层tty的属性,主要是在当tty设备打开的时候,tty核心将当前特定的tty端口的状态保存在此结构中。
在默认线路设置模块n_tty.c文件和其它文件如ppp协议的线路设置文件ppp_async.c中,定义了tty_ldisc结构实例
[5]
-它列出了所有的当前线路设置的入口。
在各种
串行设备的tty驱动程序中定义了tty_driver结构实例(如图4虚线框所示,它内部包含了下面的termios结构-用来向tty核心注册一个tty驱动
程序。
tty_driver结构中还包含所有的回调函数,它们被tty驱动程序设置,并被tty核心调用。
这些回调函数的实现需要调用到底层硬件控制,对具体寄存器进行读写,完成串行设备的收发操作。
termios结构(如下所示-每个tty驱动程序
都包含有这样一个结构实例,结构中的标志集合控制终端接口的各种特征。
用户进程就是通过ter2mios结构来设置和修改终端属性的。
structtermios{
tcflag_tc_iflag;
/3输入模式标志3/tcflag_tc_oflag;
/3输出模式标志3/tcflag_tc_cflag;
/3控制模式标志3/tcflag_tc_lflag;
/3局部模式标志3/cc_tc_line;
/3线路设置3/cc_tc_cc[NCCS];
/33/};
3.2.2tty驱动中最重要的一中,tty核心从用户那里得到将被tty设备的数据,然后把数据发送给tty线路设置驱动程序,该驱动程序负责把数据传递给tty驱动程序。
tty驱动程序对数据进行格式化,然后才能发送给硬件。
从tty硬件那里接受的数据将回溯至tty驱动程序,然后流入tty线路设置驱动程序,接着是tty核心,最后用户从tty核心那里得到数
据。
有时tty驱动程序直接与tty核心通信,tty核心将数据直接发送给tty驱动程序,但通常是tty线路设置驱动程序修改在二者之间流动的数据
[3]
在不同的线路设置中,数据的流向和处理方式是不同的。
例如如图5所示,串行设备在默认状态下和ppp拨号连接建立时的数据处理方式是不同的,而且数据传入的用户空间(或是传出的用户空间也是不同的。
图5中描述了串行设备驱动所涉及的重要模块是如何注册的(注册是为了允许每个程序块能像内核模块一样被调用,以及串行数据是如何在不同的线路设置情况下传输的。
其中实线箭头表示串行设备驱动在默认的线路设置下的情况下数据在不同的驱动程序文件间的流向,而点划线箭头描述了串行设备驱动在ppp拨号连接的线路设置下的情况。
3.3 串行设备驱动的实现
如前面所述,实现串行设备驱动(即tty驱动程序,就是要定义tty_driver结构实例和实现结构中的回调函数。
而在uClinux内核中(如图5所示,为了简化并标准化串行设备驱动的编写,又在tty驱动程序中抽象出了一个串行核心驱动层serial_core,其中申明了uart_driver结构(用来向串
行核心驱动注册一个串行设备硬件控制驱动,并将对串行设备硬件的一组标准控制方法接口(供tty_driver结构中的回调函数使用封装在uart_ops[6]
结构中,另外在uart_port结构中封装了串行
设备端口的相关参数,还对外提供了注册串行设备硬件控制驱动的辅助函数。
6
41 王 欣等:
基于ARM和uClinux多串口通讯的设计与实现 第35卷
图5 串行设备驱动模块关联图
由于串行核心驱动serial_core封装的大部分的通用串行设备的操作,且为串行设备硬件控制驱动提供了一组实现串行硬件控制的标准接口,这就大大简化了编写此类串行设备驱动的难度。
只需针对特定的硬件实现这一组方法和对应的中断服务程序,就基本上实现了串行设备驱动。
(如果在某些情况下不适合使用这套标准接口,也可以不借助串行核心驱动,而单独编写串行设备驱动。
具体情况请参考Linux/uClinux的串行设备驱动源码。
因此,实现串行设备硬件控制驱动是本文编写串行设备驱动的主要目标。
本文中所需做的就只是在串行设备硬件控制驱动程序中对端口进行注册和实现uart_ops结构中提供的对端口的一组控制方法及所需的中断服务程序(ISR。
uart_ops结构是串行核心驱动serial_core和串行设备硬件控制驱动之间的主要接口。
它包含控制硬件的所有方法。
其中重要函数的伪码及说明如下所示:
int(3startup(structuart_port3port,structuart_info3info{
重置串行设备对应端口的FIFO队列;
清除对应端口中断相关的寄存器的值;
检查对应端口线路状态寄存器的值判断UART是否存在,如果不存在,则立即返回;
抢占对应端口的中断资源,如果中断申请出错,则立即返回;
初始化对应端口的状态;
使能对应的端口中断并再次重置FIFO队列;
}
该函数在接收字符时调用并使能端口。
此外,还有void(3shutdown(structuart_port3port,structuart_info3info函数,它与startup(函数操作相反,该函数在关闭端口时调用,并释放所有的中断资源。
在串行设备硬件控制驱动中还使用了串行核心驱动提供的一些辅助函数。
如在模块初始化函数中使用了intuart_register_driver(structuart_driv2er3drv函数来注册一个串行设备端口;
在模块卸载函数中使用了voiduart_unregister_driver(structuart_driver3drv函数移除串行设备端口。
中断处理是串行设备硬件控制驱动中的重要部分,当接收FIFO中的字符和发送FIFO中的字符数到达触发等级的时候都会触发系统中断进行处理。
为了减少中断次数,提高收发效率,在设置端口参数时,设置接收FIFO至少有8个字符时就触发中断,设置发送FIFO至少有8个空位时就触发中断。
当注册中断服务程序时,如“request_irq(port->
irq,handler,SA_INTERRUPT,“tl16c751buart_int_proc”,info;
”,驱动将通知内核该串行设备将使用port->
irq对应的中断号(本文驱动中使用的中断号是22、23。
handler指向的是中断服务函数的地址,SA_INTERRUPT说明注册的是一个快速中断。
由于每个UART都分配了一个中断,且UART收发字符都会产生中断,因此在中断服务函数中应对两种中断分别进行处理,这可由中断标示寄存器IIR的值来区分。
其中发送中断的操作如图7所示。
为了解决字符型设备的外设处理速度和CPU的处理速度不匹配问题,往往需要缓冲。
一般的7
UART控制器都带有不多于几十个比特的FIFO,
但这远远不够,还需要从主存中开辟缓冲区,具体
大小视情况而定。
在tty驱动程序中缓冲区采用的是一种环形缓冲区,如图6所示。
当接收中断到来后中断服务程序从UART的FIFO中读入接收的字节,放入接收环形缓冲区的头,然后唤醒处于睡眠状态的用户读操作。
用户读操作将接收缓冲区尾部的数据传给用户空间。
当用户进程想读操作,而接收缓冲区无数据时,用户读进程睡眠在读等待队列上,直到UART有新的数据到来,断时才被唤醒。
当发送中断到来后,,当用户进程想写操作,用户写进程睡眠在写等待队列上,直到UART产生新的发送中断,读走发送缓从区的数据时才被唤醒。
当中断服务函数退出前,应该清除中断。
清除中断有两步:
一是清除UART端口的中断请求信号,只需设置UART的中断使能寄存器关闭中断即可。
二是清除CPU的相应中断请求位,只需对S3C44B0X的中断挂起寄存器相应位置1即可
图6 接收/发送缓冲示意图
中断服务程序的伪码如下所示:
voidtl16c752buart_int_proc(intirq,void3dev_id,structpt_regs3regs
{
清除中断请求位;
判断该中断来自哪个UART端口;
读取该端口的中断标示寄存器;
if(端口的tty_struct结构不存在或中断未发生
退出本程序;
switch(中断标示寄存器{case发送中断:
调用中断发送函数;
break;
case接收中断:
case接收超时中断:
调用中断接收函数;
default:
}}
中断发送函数的流程图如图7所示
:
图7 中断发送函数
中断接收函数与中断发送函数类似,只不过函
数中还要检查并记录接收字符是否有错,若果有错,字符应被忽略掉。
4 结束语
在嵌入式领域中,随着嵌入式操作系统的逐渐完善,可靠性和稳定性的提高,加上嵌入式操作系统的源代码公开性,使我们可以根据实际需求来定制内核,开发驱动支持新产品,设计应用程序也更有效率。
可以预见随着微处理器及各种接口价格的进一步降低和嵌入式操作系统的发展、成熟,将会出现大量有着低廉价格和高速接口的新产品及系统。
参考文献
[1]TIcompany.TL16C752BDataSheet[EB/OL].www.ti.
com.cn,2000,8
[2]李岩,荣盘祥.基于S3C44B0X嵌入式uClinux系统原
理及应用[M],清华大学出版社,2005,1
[3]JONATHANCorbet,ALESSANDRORubini,
GREG
Kroah-Hartman.LinuxDeviceDrivers(ThirdEdition
[M].O’Reilly&
Associates,2005,2
[4]毛德操,胡希明.Linux内核源代码情景分析(下册
[M].浙江大学出版社,2001,9
[5]ALESSANDRORubini.SerialDrivers[EB/OL].http:
//
www.linux.it/~rubini/docs/serial/serial.html,2001[6]GREGKroah-Hartman.TheSerialDriverLayer[EB/
OL].http:
//www.linuxjournal.com/article/6331,2002
8
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 arm uclinux 串口 通讯 设计 实现 图文