vxworks字符设备驱动傻瓜教程

* 标准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 */

  }
}

你可能感兴趣的:(struct,cmd,null,search,任务,Signal)