|
|
| | -文章搜索 - 最新文章 - | |
串口驱动概述 |
| 发布时间:2006年5月18日 点击次数:4226 |
| 来源: 作者: |
串口驱动概述 1. 启动顺序 在usrConfig.c 中,usrInit()调用sysHwInit(), 对系统硬件进行基本的初始化,使其处于 安静状态。sysHwInit()[在sysLib.c 中]调用sysSerial.c 中的sysSerialHwInit()对BSP 串行器件 进行初始化,使其处于静态;sysSerialHwInit()再通过xxDevInit()复位串行通道。 在usrInit()函数的最后,产生根任务usrRoot()。usrRoot()调用sysClkConnect()。sysHwInit2() 主要安装系统中断, 它调用sysSerialHwInit2() 连接串行中断。如果定义了 INCLUDE_TTY_DEV,而没有定义INCLUDE_TYCODRV_5_2,在usrRoot()任务中调用 ttyDrv()来初始化串行设备驱动,并通过ttyDevCreate()函数创建串行设备。 串行驱动是在VxWorks系统开始过程中被初始化的。 2. 编码步骤 (1)初始化 ①定义系统可支持的串行通道数。 ②初始化驱动的设备描述 ③写设备初始化代码 (2)写入口程序 (3)写中断服务程序管理中断 (4)使用模板wind/target/src/drv/ssio/templateSio.c 3.详细步骤介绍 (1)定义系统可支持的串行通道数。 在config.h 中定义串口通道数NUM_TTY。 (2)初始化驱动的设备描述 TEMPLATE_CHAN 例子如下所示: typedef struct { /* SIO_CHAN *MUST* be first */ SIO_CHAN sio; /* standard SIO_CHAN element */ UINT32 ioBase; UINT32 vecBase; UINT32 intLevel; /* callbacks */ STATUS (*getTxChar) (void *, char *); void (*putRcvChar) (void *, char); void (*errorRtn) (void *, int, void *, int); void * getTxArg; void * putRcvArg; 2 void * errorArg; /* misc */ int intConnect; /* intConnect done flag */ int baudFreq; /* current baud rate */ int mode; /* current mode (interrupt or poll) */ int clkFreq; /* input clock frequency */ uint_t options; /* Hardware options */ int scanMode; /* keyboard mapping mode */ } TEMPLATE_CHAN; 在XX_DRV 结构中每一个通道有一个XX_CHAN 结构。 在上面的例子中,TEMPLATE_CHAN 中的SIO_CHAN 必须被第一个定义! SIO_CHAN 指向SIO_DRV_FUNCS, SIO_DRV_FUNCS 结构提供驱动的入口函数。 SIO_DRV_FUNCS 定义在wind/target/h/sioLib.h 中。如下: struct sio_drv_funcs /* driver functions */ { int (*ioctl) ( SIO_CHAN * pSioChan, int cmd, void * arg ); int (*txStartup) ( SIO_CHAN * pSioChan ); int (*callbackInstall) ( SIO_CHAN * pSioChan, int callbackType, STATUS (*callback)(void *, ...), void * callbackArg ); int (*pollInput) ( SIO_CHAN * pSioChan, char * inChar ); int (*pollOutput) 3 ( SIO_CHAN * pSioChan, char outChar ); }; xxIoctl(): 支持设备特定的ioctl 命令 xxTxStartup(): 初始化一个传输循环(transmit cycle) xxCallBackInstall(): 安装到高层协议的入口(I/O system,target agent(目标代理),等等) xxPollInput() : 轮巡模式输入 xxPollOutPut() : 轮巡模式输出 a.启动发送循环 因为串口发送数据时需要启动,xxTxStartup()就是用来启动串口数据发送,当发送成功 后会触发串口中断,中断根据缓存中是否还有数据来决定是否继续发送,当缓存清空后串口 将恢复初始状态,并等待下一次传送的启动。 b.驱动回调安装程序 回调用于层间协作,上层将本层函数安装在下层,这个函数就是回调,而下层在一定 条件下触发回调,例如作为一个驱动,是一个底层,他在收到一个数据时,除了完成本层的 处理工作外,还将进行回调,将这个数据交给上层应用层来做进一步处理,这在分层的数据 通信中很普遍。 int xxCallbackInstall (pSioChan,callbackType, callback, callbackArg) pSioChan: 指向SIO_CHAN结构的指针 callbackTyp:SIO_CALLBACK_GET_TX_CHAR or SIO_CALLBACK_PUT_RCV_CHAR callback: 指向回调函数的指针 callbackArg:传给回调函数的参数 /****************************************************************************** * * templateCallbackInstall - install ISR callbacks to get/put chars * * This driver allows interrupt callbacks for transmitting characters * and receiving characters. In general, drivers may support other * types of callbacks too. * * RETURNS: OK on success, or ENOSYS for an unsupported callback type. */ LOCAL int templateCallbackInstall ( SIO_CHAN * pSioChan, /* channel */ int callbackType, /* type of callback */ STATUS (*callback)(void *,...), /* callback */ 4 void * callbackArg /* parameter to callback */ ) { TEMPLATE_CHAN * pChan = (TEMPLATE_CHAN *)pSioChan; switch (callbackType) { case SIO_CALLBACK_GET_TX_CHAR: pChan->getTxChar = (STATUS (*)(void *, char *))callback; pChan->getTxArg = callbackArg; return (OK); case SIO_CALLBACK_PUT_RCV_CHAR: pChan->putRcvChar = (void (*)(void *, char))callback; pChan->putRcvArg = callbackArg; return (OK); case SIO_CALLBACK_ERROR: pChan->errorRtn = (void (*)(void *, int, void *, int))callback; pChan->errorArg = callbackArg; return (OK); default: return (ENOSYS); } } (3)驱动初始化:void xxDevInit (pxxDrv) 这个函数是用来复位芯片,使芯片处于安静的状态。 (4)写函数 用户通过I/O系统的write()操作是调用tyWrite()——在驱动列表中的ttyDrv的写入口函 数。tyWrite()把数据拷贝到环形缓冲中,并且调用xxTxStartup( )来初始化一个发送周期。 当设备输出完毕后,设备就给CPU一个中断表示可以接受下一个字符,然后进入中断 xxInTxt( )。函数xxIntTx ( )通过调用回调函数getTxChar从高层协议去字节,把字节写入到设 备。如果需要的话清除中断。如果需要的话在没有数据等待发送的时候,复位发送中断。 (5)读函数 串口的读操作相对于写操作来说复杂一些。数据的读写有两种方式:查询式和中断式。 查询方式根据事先设定的时间间隔定时读端口,不论端口是否有数据,操作都要进行。所以 查询方式并不能完全适应实时操作系统的及时相应要求,因此在嵌入式实时操作系统中应用 的比较少。而中断方式(或者类似中断的机制)则使用比较多。VxWorks提供的Select函数, 可以使任务阻塞在一个或者多个I/O设备上,并能制定最多所等待的时间。利用Select函数可 5 以将读串口设备的操作阻塞在设备的读操作上,当有数据可读时,被阻塞的任务就继续向下 执行,这是就可以对串口继续读操作,将数据从端口读入。因此可以将读端口的操作单独放 在一个任务中,利用Select将任务阻塞在端口读操作,而当端口有数据时继续该任务。Select 函数是一种类似于事件触发的机制,利用Select函数可以实现类似于中断的方式的数据读操 作。 下面简单说明一下利用Select实现串口的读操作。 FOREVER { /*清除等待设备集合中的读屏蔽位*/ FD_ZERO(&readFds); /*初始化屏蔽位为等待串口状态*/ (SerialDevFd,& readFds); Width = SerialDevFd + 1; /*阻塞,等待串口设备变为就绪状态*/ if(select(width,& readFds,NULL,NULL,NULL) == ERROR) return (ERROR); if(FD_ISSET(SerialDevFd,&readFds)) { FOREVER { /*当端口仍有未读数据*/ If((DataLen = read(SerialDevFd,ComReadBuffer,MAX_IN_DATA)) == ERROR) { printf(“\nError in read comport”); return(ERROR); } if(DataLen == 0) breake; /*处理所读出的数据,如将其写到缓存或直接处理*/ } } } 当采用中断方式读数据时,接收中断服务程序void xxIntRcv(pSioChan)实现从设 备中读字节,并通过调用回调函数putRcvChar来将字节传给高层协议。 /****************************************************************************** * * templateSioIntRcv - handle a channel's receive-character interrupt * * RETURNS: N/A */ LOCAL void templateSioIntRcv ( 6 TEMPLATE_CHAN * pChan /* channel generating the interrupt */ ) { char inChar; /* rcvr data */ char crData = 0; /* rcvr status */ STATUS status = OK; /* * TODO - * * Get status and data from the device. Determine if valid data is ready * or not. * * For PCI devices, do an immediate return if device is not asserting * an interrupt. */ TEMPLATE_SIO_READ8(pChan, TEMPLATE_CSR_ID, &crData); /* Check for error conditions */ if (crData & TEMPLATE_CR_OKAY) { TEMPLATE_SIO_READ8(pChan, TEMPLATE_DATA_ID, &inChar); #if 0 /* Keyboard emulation code */ /* * TODO - For a keyboard type device we would map the raw scan code * to ASCII, or other mapping. Do that here. */ if (pChan->scanMode == SIO_KYBD_MODE_ASCII) inChar = templateAsciiTbl[(UINT8)inChar]; #endif } else { /* * TODO - Determine precise error condition and perform * recovery actions. */ status = ERROR; 7 } /* * TODO - Typically, acknowledge the interrupt as soon as possible. * Usually before passing data or error conditions upstream. */ TEMPLATE_SIO_WRITE8(pChan, TEMPLATE_CSR_ID, TEMPLATE_RESET_INT); /* ack interrupt*/ if (status == ERROR) { /* send error notification upstream */ (*pChan->errorRtn) (pChan->errorArg, SIO_ERROR_UNKNWN, NULL, 0); } else { /* send data character upstream */ (*pChan->putRcvChar) (pChan->putRcvArg, inChar); } } (6) I/O控制函数ioctl() 指向驱动的标准I/O控制接口函数。此函数为任何驱动提供主要的控制接口。为了 实现标准的SIO设备的I/O控制,用以下的定义: SIO_BAUD_SET 设定一个新的波特率 SIO_BAUD_GET 得到当前的波特率 SIO_HW_OPTS_SET 设定一个新的硬件属性 SIO_HW_OPTS_GET 得到当前的硬件属性 SIO_MODE_SET 设定一个新的操作模式 SIO_MODE_GET 得到当前的操作模式 SIO_AVAIL_MODES_GET 得到可能的模式 SIO_OPEN 打开一个通道 SIO_HUP 关闭一个通道 (7)修改sysSerial.c 在sysSerial.c中,主要需要修改三个函数,sysSerialHwInit( ),sysSerialHwInit2( ), sysSerialChanGet( )。 sysSerialHwInit( )主要完成以下功能:初始化和硬件相关的的驱动的XX_CHAN结构(例 如寄存器地址);调用xxDevInit()来执行实际的设备初始化;设定标志位来标志ISR仍然没有 被安装。此函数是被sysHwInit( )调用的。 sysSerialHwInit2( )主要是连接中断服务程序。在intConnect()中的第三个参数应该是指向 8 xx_CHAN结构的一个指针。此函数是由usrRoot任务在系统启动过程中由sysClkConnect() 调用的。它设定标志位标志ISR已经被安装。 sysSerialChanGet( )主要是把通道号转换成一个SIO_CHAN结构的指针。 |
|
|
|
|
[通信网络] 相关文章: 未来十年CDMA2000发展明朗化,CDG力推1xEV-DO版本A年底商用简介:
CDMA发展组织(CDG)日前公布了CDMA2000在未来十年的详细演进路线图(roadmap)。重点包括:CDMA2000 1xEV-DO版本A网络将于2006年晚些时候实现商用部署,版本C标准将于2007年第二季度发布。这些发展使CDMA2000运营商可以率先引入全IP和下一代多媒体技术。 “随着版本A的商用产品在今年上市,以及针对版本C的工作也在顺利进行,CDMA2000已经拥有了未来10年内的一条清晰的演进路线。”CDG执行董事Perry LaForge说,“这一路线图为CDMA2000运营商和设备制造商带来了快速上市的巨大优势,因为他们现在就可以制定长期的计划并开始执行...... 研华工业级智能型以太网络交换器具网管功能
近距离无线通信技术首次投入商用 信息技术简化消费者旅行体验
Enea与MontaVista共推融合了Linux与RTOS“电信盒”
中国版3G将赴韩测试 专家力荐四大扶持政策
浅谈WIMAX与3G竞争力比较分析
ZEBRA为SAP客户提供更加丰富的RFID打印/编码选择
解读DOCSIS2.0技术
ppp协议中文-2
大唐称明年第一季度将推出TD双模高速手机 |
|
|
|