您的位置:首页 > 其它

vxworks字符设备驱动傻瓜教程

2005-12-08 15:06 471 查看
* 标准I/O函数
open(), create(), read(), write(), ioctl(), close() , remove()
各个函数的详细说明可参考Tornado的相关帮助文件。
* 字符设备驱动实例(头文件和源文件代码)
* 安装驱动/创建设备代码
* SELECT机制使用举例
/*****************************************************/
+++++++++++头文件:
/* 定义MYXXX_DEV结构体 */
typedef struct
{
DEV_HDR devHdr; /* 必须 */
SEL_WAKEUP_LIST selWakeupList; /* 支持SELECT机制 */
/* 自己定义的其他成员 */
BOOL readyRead;
BOOL readyWrite;
...
}
MYXXX_DEV;
/* 其他定义 */

+++++++++++源文件:
#include "vxWorks.h"
#include "iv.h"
#include "ioLib.h"
#include "iosLib.h"
#include "intLib.h"
#include "errnoLib.h"
#include "sysLib.h"
#include "drv/XXX/XXX.h"
LOCAL int myxxxDrvNum = 0;
LOCAL MYXXX_DEV mymyxxxDev;
/* myxxxDrv() 安装驱动例程
入口参数: 无
返回值:
------OK: 驱动安装成功
------ERROR: 驱动安装失败
*/
STATUS myxxxDrv(void)
{
if(myxxxDrvNum > 0)
{
return(OK); /* 驱动程序已经安装,直接返回 */
}
/* 驱动初始化代码 */

/* 中断向量初始化 */
if(intConnect(INUM_TO_IVEC(myxxx_INT_NUM), myxxxIntHandler, (int)(&mymyxxxDev)) == ERROR)
return (ERROR);
if(intEnable(myxxx_INT_NUM)==ERROR)
return (ERROR);

/* 调用iosDrvInstall()安装驱动 */
if((myxxxDrvNum = iosDrvInstall(myxxxOpen, myxxxDelete, myxxxOpen, myxxxClose, /
myxxxRead, myxxxWrite, myxxxIoctl)) == ERROR)
return (ERROR);
return (OK);
}
/* myxxxDevCreate()创建设备例程
入口参数:
----devname: 所要创建的设备名称;
返回值:
----OK: 创建设备成功;
----ERROR: 创建设备失败;

*/
STATUS myxxxDevCreate(char * devName)
{
MYXXX_DEV *pmyxxxDev = &mymyxxxDev;

if(myxxxDrvNum < 1)
{
errnoSet(S_ioLib_NO_DRIVER);
return (ERROR);
}

/* init pmyxxxDev */
if( iosDevAdd(&pmyxxxDev->devHdr, devName, myxxxDrvNum) == ERROR)
{
return (ERROR);
}
selWakeupListInit(&pmyxxxDev->selWakeupList);
/* init other */
return (OK);
}
/*
myxxxOpen() 打开设备
入口参数: 参考open();
返回值:
-------ERROR:失败
-------指向设备的句柄
*/
int myxxxOpen(DEV_HDR *pDevHdr, int option, int flags)
{
MYXXX_DEV *pmyxxxDev = (MYXXX_DEV *)pDevHdr;
if(pmyxxxDev == NULL)
{
return (ERROR);
}

return ((int)pDevHdr);
}
/*
读设备
*/
int myxxxRead(int myxxxDevId, char *pBuf, int nBytes)
{
MYXXX_DEV *pmyxxxDev = (MYXXX_DEV *)myxxxDevId;
int ReadLength;

ReadLength=0;
if(pmyxxxDev == (MYXXX_DEV *)NULL)
{
return ERROR;
}
/*read code here*/

return (ReadLength);
}
/* 写设备 */
int myxxxWrite(int myxxxDevId, char *pBuf, int nBytes)
{
MYXXX_DEV *pmyxxxDev = (MYXXX_DEV *)myxxxDevId;
int WriteLength = 0;

if(pmyxxxDev == (MYXXX_DEV *)NULL)
{
return (ERROR);
}

return (WriteLength);
}
/* 设备控制 */
int myxxxIoctl(int myxxxDevId, int cmd, int arg)
{
MYXXX_DEV *pmyxxxDev = (MYXXX_DEV *)myxxxDevId;
int status;
UCHAR temp;

status = OK;
switch(cmd)
{
case FIOSELECT:
selNodeAdd(&pmyxxxDev->selWakeupList, (SEL_WAKEUP_NODE *)arg);
if((selWakeupType((SEL_WAKEUP_NODE *)arg) == SELREAD) && (pmyxxxDev->readyRead))
selWakeup((SEL_WAKEUP_NODE *)arg);
if((selWakeupType((SEL_WAKEUP_NODE *)arg) == SELWRITE) && (pmyxxxDev->readyWrite))
selWakeup((SEL_WAKEUP_NODE *)arg);
break;
case FIOUNSELECT:
selNodeDelete(&pmyxxxDev->selWakeupList, (SEL_WAKEUP_NODE *)arg);
break;

/* other cmd */
default:
errnoSet(S_ioLib_UNKNOWN_REQUEST);
status = ERROR;
}
return (status);
}
/* 关闭设备 */
int myxxxClose(int myxxxDevId)
{
MYXXX_DEV *pmyxxxDev = (MYXXX_DEV *)myxxxDevId;

if(pmyxxxDev == (MYXXX_DEV *)NULL)
{
return (ERROR);
}
/* */
pmyxxxDev->opened = FALSE;
return (OK);
}
/* 删除设备 */
STATUS myxxxDelete(char *devName)
{
DEV_HDR *pDevHdr;
char *pNameTail;
/* search dev */
pDevHdr = iosDevFind(devName, &pNameTail);
if(pDevHdr == NULL || *pNameTail != '/0')
return (ERROR);
/* release resourse sample sam wakeup signal */
/* uninstall */
iosDevDelete(pDevHdr);
return (OK);
}
/* 设备中断处理 *
void myxxxIntHandler(int myxxxDevId)
{

/* interrupt process */
selWakeupAll(&myxxxDev->selWakeupList,SELREAD); /* 若支持SELECT机制 */
selWakeupAll(&myxxxDev->selWakeupList,SELWRITE); /* 若支持SELECT机制 */
}
/*************************************************************/
应用程序中安装驱动和创建设备代码:
/* 包含的头文件 */
myxxxDrv(); /* 安装驱动 */
myxxxDevCreate(“/myxxxDev"); /* 创建设备 */
/*************************************************************/
SELECT机制的使用
使用SELECT可以在设备没有准备好读写之前将此任务挂起,只到设备准备好或者超时,
从而提高系统运行效率。用户可以通过调用select()函数来达到这一目的。具体用法如下:
在驱动程序中SELECT的初始化以及在ioctl()如何支持SELECT请参考上面的示例代码;
需要注意的是,SELECT机制只能用于字符型的设备驱动,并且是可选的(非必需)。
SELECT机制使用举例=>
SELECT使用一个名为fd_set的结构体来实现,一个fd_set结构体可以看作一个位数组,每个位代表
所要读写的文件描述符。可以用下列宏来对fd_set进行操作:
FD_SET(fd,&fdset) 在fdset中设置fd标志位;
FD_CLR(fd,&fdset) 清除fdset中的fd标志位;
FD_ZERO(fd,&fdset) 清楚fdset中的所有标志位;
FD_ISSET(fd,&fdset) 测试fdset中的fd位是否被置位;
select()函数原型:
int select (width, pReadFds, pWriteFds,pExceptFds, pTimeOut)
其中 width: 要检查的fdset中的标志位的最大宽度;
pReadFds:指向结构体fdset的指针,其中包含了要读文件的描述符;
pWriteFds:指向结构体fdset的指针,其中包含了要写文件的描述符;
pExceptFds:指向结构体fdset的指针,其中包含了异常文件的描述符;(未实现)
pTimeOut:指向结构体timeval的指针,NULL代表无限等待;
返回值:准备好的文件描述符的个数,0表示超时或者出错(如不支持SELECT);
返回时,结构体fdset中的各个位被修改,只有那些已经准备好的相应位被置位。
应用举例:
struct fd_set readFds;
int fds[NUM_FDS], width = 0;
FD_ZERO (&readFds);
for (i=0; i<NUM_FDS; i++)
{
FD_SET (fds[i], &readFds);
width = (fds[i] > width) ? fds[i] : width;
}
width++;
if (select(width, &readFds,NULL,NULL,NULL) == ERROR)
return (ERROR);
for (i=0; i<NUM_FDS; i++)
{
if (FD_ISSET (fds[i], &readFds))
{
/* do something now that fds[i] is ready */
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: