串口驱动概述
4
以将读串口设备的操作阻塞在设备的读操作上,当有数据可读时,被阻塞的任务就继续向下 执行,这是就可以对串口继续读操作,将数据从端口读入。因此可以将读端口的操作单独放 在一个任务中,利用Select将任务阻塞在端口读操作,而当端口有数据时继续该任务。Select 函数是一种类似于事件触发的机制,利用Select函数可以实现类似于中断的方式的数据读操 作。
void
(*errorRtn) (void *, int, void *, int);
void * getTxArg;
void * putRcvArg;
1
void * errorArg;
/* misc */
int
intConnect; /* intConnect done flag */
int
baudFreq; /* current baud rate */
串行驱动是在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 */
2
(
SIO_CHAN * pSioChan,
char
outChar
);
};
xxIoctl():
支持设备特定的 ioctl 命令
xxTxStartup(): 初始化一个传输循环(transmit cycle)
xxCallBackInstall(): 安装到高层协议的入口(I/O system,target agent(目标代理),等等)
LOCAL int templateCallbackInstall
(
SIO_CHAN * pSioChan,
int
callbackType,
STATUS (*callback)(void *,...),
/* channel */ /* type of callback */ /* callback */
SIO_CHAN sio; /* standard SIO_CHAN element */
UINT32 ioBase; UINT32 vecBase; UINT32 intLevel;
/* callbacks */
STATUS
(*getTxChar) (void *, char *);
void
(*putRcvChar) (void *, 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);
xxPollInput() : 轮巡模式输入
xxPollOutPut() : 轮巡模式输出
a.启动发送循环 因为串口发送数据时需要启动,xxTxStartup()就是用来启动串口数据发送,当发送成功 后会触发串口中断,中断根据缓存中是否还有数据来决定是否继续发送,当缓存清空后串口 将恢复初始状态,并等待下一次传送的启动。 b.驱动回调安装程序 回调用于层间协作,上层将本层函数安装在下层,这个函数就是回调,而下层在一定 条件下触发回调,例如作为一个驱动,是一个底层,他在收到一个数据时,除了完成本层的 处理工作外,还将进行回调,将这个数据交给上层应用层来做进一步处理,这在分层的数据 通信中很普遍。
} 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 中。如下:
} }
当采用中断方式读数据时,接收中断服务程序 void xxIntRcv(pSioChan)实现从设 备中读字节,并通过调用回调函数putRcvChar来将字节传给高层协议。
/****************************************************************************** * * templateSioIntRcv - handle a channel's receive-character interrupt * * RETURNS: N/A */ LOCAL void templateSioIntRcv
下面简单说明一下利用Select实现串口的读操作。 FOREVER {
/*清除等待设备集合中的读屏蔽位*/ FD_ZERO(&readFds); /*初始化屏蔽位为等待串口状态*/ (SerialDevFd,& readFds); Width = SerialDevFd + 1; /*阻塞,等待串口设备变为就绪状态*/ if(select(width,& readFds,NULL,NULL,NULL) == ERROR)
串口驱动概述
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()函数创建串行设备。
int
mode;
/* current mode (interrupt or poll) */
int
clkFreq;
/* input clock frequency */
uint_t options; /* Hardware options */
int
scanMode; /* keyboard mapping mode */
} }
(3)驱动初始化:void xxDevInit (pxxDrv) 这个函数是用来复位芯片,使芯片处于安静的状态。
(4)写函数 用户通过I/O系统的write()操作是调用tyWrite()——在驱动列表中的ttyDrv的写入口函
数。tyWrite()把数据拷贝到环形缓冲中,并且调用xxTxStartup( )来初始化一个发送周期。 当 设 备 输 出 完 毕 后 , 设 备 就 给 CPU 一 个 中 断 表 示 可 以 接 受 下 一 个 字 符 , 然 后 进 入 中 断 xxInTxt( )。函数xxIntTx ( )通过调用回调函数getTxChar从高层协议去字节,把字节写入到设 备。如果需要的话清除中断。如果需要的话在没有数据等待发送的时候,复位发送中断。
/****************************************************************************** * * 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. */
3
void *
callbackArg
/* parameter to callback */
)
{
TEMPLATE_CHAN * pChan = (TEMPLATE_CHAN *)pSioChan;
switch (callbackType) { case SIO_CALLBACK_GET_TX_CISSET(SerialDevFd,&readFds))
{ FOREVER { /*当端口仍有未读数据*/ If((DataLen = read(SerialDevFd,ComReadBuffer,MAX_IN_DATA)) == ERROR) { printf(“\nError in read comport”); return(ERROR); } if(DataLen == 0) breake; /*处理所读出的数据,如将其写到缓存或直接处理*/ }