基于VxWorks的VxBus字符设备驱动
来源:互联网 发布:nginx 内网端口转发 编辑:程序博客网 时间:2024/05/22 17:10
基于VxWorks的VxBus字符设备驱动
VxBus是指在 VxWorks 中用于支持设备驱动的特有的架构,这种架构包含对minimal BSP的支持。它包括以下功能:
- 允许设备驱动匹配对应设备;
- 提供驱动程序访问硬件的机制;
- 软件其他部分访问设备功能;
- 在VxWorks系统中,实现设备驱动的模块化。
VxBus是Vxworks的模块化机制,类似于linux中的module。通过VxBus可以对模块方便的裁剪或者添加。VxBus 在总线控制器驱动程序服务的支持下,能在总线上发现设备,并执行一些初始化工作,使驱动与硬件设备之间正常的通讯。
vxBus下对设备管理做了更为详细的划分,简单说来,硬件称为device,软件叫做driver。如果一个device出现在硬件列表中,启动时需要到driver的队列中去找相应的driver,如果找到,二者结合成一个instance,否则在vxBusShow里可以看到一个orphan。使用vxBusShow可以比较清晰的看到driver列表和device列表以及orphan列表。
相关参数
设备注册:vxbDevRegister(structure vxbDevRegInfo *pDevInfo)
显然,我们唯一要做的就是填充vxbDevRegIndo *pDevInfo结构体,其定义如下
struct vxbDevRegInfo{ struct vxbDevRegInfo * pNext; UINT32 devID; UINT32 busID; UINT32 vxbVersion; char drvName[MAX_DRV_NAME_LEN+1]; struct drvBusFuncs * pDrvBusFuncs; struct vxbDeviceMethod * pMethods; BOOL (*devProbe) ( struct vxbDev * pDevInfo); struct vxbParams * pParamDefaults;};
参数解释:
- pNext
pNext用于总线级联。如一个挂在网卡上的网卡,其phy通过mii与mac相间接。我们要访问phy,则需要先通过pci总线访问mac,再通过mii总线访问phy。有点类似先做汽车到县城,再转驴车到村子。这里的pNext就是告诉你下面该转驴车了。如果没有级联,则设为NULL。 - pMethods
pMethods用于提供了总线的各种方法,但实际上通常只提供该总线特有方法。因为通用方法,如open、read等,一般都是通过io层的system call调用的,他们需要单独注册。 - pDrvBusFuncs
pDrvBusFuncs 提供了设备初始化需要的几个接口,一共有三个:
struct drvBusFuncs
struct drvBusFuncs{ void (*devInstanceInit) (struct vxbDev *); void (*devInstanceInit2) (struct vxbDev *); void (*devInstanceConnect) (struct vxbDev *);};
devInstanceInit在kernel初始化前被调用,如果这个设备或它的一部分是kernel要用到的,就要放在这里。devInstanceInit2在kernel初始化后被调用,没有什么特别要求的话,初始化最好都放在这里。当然如果该设备特别重要,其他设备需要调用它,一般也会放到devInstanceInit中,因为各个设备之间的调用devInstanceInit时不保证前后顺序。devInstanceConnect用于设备的连接,通常可以不使用,但如果它依赖于其他设备,则可以把启动代码放在这里。如果实在不需要,可以都置为NULL。
系统接口函数
对于字符设备驱动来说,需要实现的仅为I/O系统所需要的接口,即 create, open, read, write, close, ioctl, delete 7个接口函数, I/O系统在与这些接口通信的时候都有规定的参数,其中最重要的就是设备的数据结构。这个数据结构会在设备打开时返回给系统,用于I/O系统与驱动之间的数据交换。
一个典型的设备的数据结构定义为:
typedef struct { DEV_HDR devHdr; int ix; /*设备驱动号*/ SEL_WAKEUP_LIST selWakeupList; BOOL Opened; Bool ReadyToRead; Bool ReadyToWrite;}xxx_DEV/*DEV_HDR 是用于创建设备链表的系统定义结构,如下所示*/typedef struvcr /*设备头数据结构*/{ DL_NODE node; /*设备链表节点*/ short drvNum; /*设备所对应的驱动索引号*/ cha *name; /*设备名称*/}
用链表将设备管理起来,I/O系统只需要完成对链表的增删改查即可以完成对设备的添加和修改
heloWorld驱动实例
驱动程序的配置
采用VxBus驱动的一个主要优点是:设备的驱动程序可以被看成VxWorks 系统的一个组件,通过集成的Workbench开发环境来配置设备驱动。PCI1304数据采集卡需要有以下文件:
- 一个驱动源文件vxb335xHello.c,执行驱动运行逻辑,包括Hello驱动的实现代码。
- 一个组件描述文件vxb335xHello.cdf,允许集成驱动到VxWorks开发工具Workbench当中。
- 一个vxb335xHello.dc文件,提供驱动注册函数原型。
- 一个vxb335xHello.dr文件,提供一个调用注册函数的C语言代码段。
- 一个readme文件 ,提供版本信息。
- 一个makefile 文件,提供建立驱动的编译规则。
helloWorld驱动实例
vxb335xHello.c
/** * @file vxb335xHello.c * * @brief GPIO控制按键驱动 * * @version 1.00 * * @author liwanneng * * @date 2017.7.24 * * @copyright liwanneng * * @details * * @history 2017.7.24 liwanneng 创建 * @todo * * @attention * * @see *//******************************************************************************** includes******************************************************************************/#include <vxWorks.h>#include <stdio.h> /* for printf() */#include <logLib.h> /* for logMsg() */#include <string.h> /* for strcmp() */#include <vxBusLib.h> /* for VXB_DEVICE_ID */#include <hwif/vxbus/vxBus.h>#include <hwif/util/hwMemLib.h> /* for hwMemAlloc() */#include <hwif/vxbus/hwConf.h> /* for devResourceGet() and * hcfDeviceGet() */#include <driverControl.h> /* for struct vxbDriverControl */#include "../pmcConfig.h"#include "vxb335xHello.h"//extern void getUnixTime(UNIX_CLOCK_STRUCT *time);/*********************************************************************************** GLOBAL VARIABLE DEFINITIONS*********************************************************************************/LOCAL int g_helDrvNum = 0; /* 驱动程序索引号 *///LOCAL SEM_ID g_semLedM; /* gpioLed互斥信号量 *//*********************************************************************************** MACRO DEFINITIONS*********************************************************************************/#define HELLO_DEVICE_NAME "/hello" /*********************************************************************************** FUNCTION DECLARATIONS*********************************************************************************/LOCAL void helInstInit(VXB_DEVICE_ID pInst);LOCAL void helInstInit2(VXB_DEVICE_ID pInst);LOCAL void helInstConnect(VXB_DEVICE_ID pInst);//void helAm335xShow( VXB_DEVICE_ID pDev);LOCAL int helDrvOpen(DEV_HDR *pHelDevHdr, int option, int flags);LOCAL int helDrvClose(int helDevId);LOCAL STATUS helDrvIoctl(int helDevId, int cmd, int arg);LOCAL STATUS helWrite(int helDevId, int *pBuf, int len);LOCAL STATUS helRead(int helDevId, int *pBuf, int len);/*********************************************************************************** VxBus 驱动框架 *********************************************************************************//* VXB初始化设备调用程序 */LOCAL struct drvBusFuncs helFuncs ={ helInstInit, /* devInstanceInit */ helInstInit2, /* devInstanceInit2 */ helInstConnect /* devConnect */};LOCAL struct vxbDeviceMethod helMethods[ ] ={ { 0, 0}};/*diver rigister info*/LOCAL struct vxbDevRegInfo helDevRegistration ={ NULL, /* pNext */ VXB_DEVID_DEVICE, /* devID */ VXB_BUSID_PLB, /* busID = PLB */ VXB_VER_5_0_0, /* vxbVersion */ "hello", /* drvName */ &helFuncs, /* pDrvBusFuncs */ helMethods, /* pMethods */ NULL, /* devProbe */ NULL /* pParamDefaults */};/*********************************************************************************** DRIVER FUNCTIONS *********************************************************************************//********************************************************************************* gpioLedRegister - register GpioLed driver** This routine registers the GpioLed driver and device recognition* data with the vxBus subsystem.** RETURNS: N/A** ERRNO*/void am335xHelRegister(void) { vxbDevRegister((struct vxbDevRegInfo *)&helDevRegistration); }/********************************************************************************* GpioLedInstInit - initialize GpioLed device** This is the wrsample initialization routine.** RETURNS: N/A** ERRNO*/LOCAL void helInstInit ( VXB_DEVICE_ID pInst){ return;}/********************************************************************************* GpioLedInstInit2 - initialize GpioLed device** This is seconde phase initialize routine for VxBus driver. ** RETURNS: N/A** ERRNO*/LOCAL void helInstInit2 ( VXB_DEVICE_ID pInst ) { HEL_DEV * pDrvCtrl; /* to store the HCF device */ HCF_DEVICE * pHcf = NULL; /* check for vaild parameter */ if (pInst == NULL) return; /* allocate the memory for the structure */ pDrvCtrl = (HEL_DEV *)malloc(sizeof(HEL_DEV)); /* check if memory allocation is successful */ if (pDrvCtrl == NULL) return; /* get the HCF device from vxBus device structure */ pHcf = hcfDeviceGet (pInst); /* if pHcf is NULL, no device is present */ if (pHcf == NULL) return; /* per-device init */ pInst->pDrvCtrl = pDrvCtrl; }/********************************************************************************* gpioInstConnect - VxBus connect phase routine for Gpio driver** This is connect phase routine.** RETURNS: N/A** ERRNO: not set*/LOCAL void helInstConnect( VXB_DEVICE_ID pInst){ HEL_DEV * pDrvCtrl; pDrvCtrl = pInst->pDrvCtrl; logMsg("debug:helInstConnect entered.\n",0,0,0,0,0,0); if(pDrvCtrl == NULL) { // GPIO_DBG_MSG(2,"HelInstConnect: pDrvCtrl is NULL, pDev is 0x%x\n", pInst,1,2,3,4,5); return; } /*注册驱动*/ if((g_helDrvNum = iosDrvInstall( helDrvOpen, (FUNCPTR) NULL, helDrvOpen, (FUNCPTR) helDrvClose, helRead, helWrite, helDrvIoctl )) < 0) { logMsg("debug:iosDrvInstall failed.\n",0,0,0,0,0,0); return; } /* 添加设备 */ if(iosDevAdd(&pDrvCtrl->devHdr, HELLO_DEVICE_NAME, g_helDrvNum)) { free((char *)pDrvCtrl); return ; } return; }/********************************************************************************* gpioDrvOpen - open Gpio**/ LOCAL int helDrvOpen( DEV_HDR *pHelDevHdr, int option, int flags){ HEL_DEV *pHelDev = (HEL_DEV *)pHelDevHdr; if(pHelDev == NULL) { return ERROR; } return ((int)pHelDevHdr);}/********************************************************************************* gpioDrvClose - close Gpio**/ LOCAL int helDrvClose( int helDevId){ HEL_DEV *pHelDev = (HEL_DEV *)helDevId; if(pHelDev == NULL) { return ERROR; } return((int)helDevId);}/********************************************************************************* gpioRead - **/LOCAL STATUS helRead( int helDevId, int *pBuf, int len){ return OK;}/********************************************************************************* gpioWrite - **/LOCAL STATUS helWrite( int helDevId, int *pBuf, int len){ return OK;}/********************************************************************************* gpioDrvIoctl - special device control** RETURNS: OK or ERROR.*/LOCAL STATUS helDrvIoctl( int helDevId, int cmd, int arg){ switch((HEL_CTL)cmd) { case HEL_WRITE: logMsg("ioctl write in kernel.\n",0,0,0,0,0,0); break; case HEL_READ: logMsg("ioctl read in kernel.\n",0,0,0,0,0,0); break; default: return ERROR; } return OK;}
vxb335xHello.cdf文件
/************************************************************************ sample 3rd-party VxBus driver provided by Wind River**/Component DRV_AM335X_HEL { NAME AM335X HELLO VxBus driver SYNOPSIS AM335X HELLO VxBus driver provided by ceiec REQUIRES INCLUDE_VXBUS \ INCLUDE_PLB_BUS MODULES vxb335xHello.o PROTOTYPE void am335xHelRegister(void); INIT_RTN am335xHelRegister(); INIT_AFTER INCLUDE_PLB_BUS _INIT_ORDER hardWareInterFaceBusInit _CHILDREN FOLDER_DRIVERS}
vxb335xHello.dc文件
IMPORT void am335xHelRegister(void);
vxb335xHello.dr文件
#ifdef DRV_AM335X_HEL am335xHelRegister();#endif /* DRV_AM335X_HEL */
hwconfig.c中添加设备列表
完成上述驱动之后,在hwconfig.c中添加设备列表以及硬件信息
如果需要增加一个设备,需要在hwconfig.c中的设备列表即hcfDeviceList数组添加设备信息,这个数组中列有本系统中所有需要初始化的硬件设备。例如:
HCF_DEVICE hcfDeviceList[] = { #ifdef DRV_AM335X_HEL { "hello", 0, VXB_BUSID_PLB, 0, vxbHelNum, vxbHelResources},#endif
在参数中指明了它的名字“hello”,初始化的时候根据这个名字去搜索驱动。它的unit是0,初始化结束以后,会在设备列表中看到这个unit number。vxbHelResources是前面定义的一组资源。 对于单核CPU,配置到这里就结束了。如果是多核,还需要修改一下sysDeviceFilter,这个函数决定一个设备在哪个核上初始化。如果还有hypervisor,还需要修改wrhvConfig.xml和vxworksX.xml,将特定的终端放开到指定的核。
我们这里只需要添加设备列表和硬件信息就可以了。如下:
/* Hello驱动硬件信息*/#ifdef DRV_AM335X_HELconst struct hcfResource vxbHelResources[] = { { "regBase", HCF_RES_INT, { (void *)0} },};#define vxbHelNum NELEMENTS(vxbHelResources)#endif/*添加设备对设备链表*/#ifdef DRV_AM335X_HEL { "hello", 0, VXB_BUSID_PLB, 0, vxbHelNum, vxbHelResources},#endif
VxBus的驱动相比 Linux 不需要虚拟内存物理内存的映射,所以实现起来简单多了。
- 基于VxWorks的VxBus字符设备驱动
- 基于VxBus的设备驱动开发
- VxWorks设备驱动开发指南--VxBus And VxBus Device Driver
- 基于VxBus设备驱动程序架构的设备驱动开发
- 转载_基于VxBus的设备驱动开发
- VxWorks设备驱动开发指南(二)--VxBus And VxBus Device Driver
- VxBus设备驱动模型
- 基于vxworks的PCI设备驱动编写
- vxWorks字符设备驱动模板
- vxworks字符设备驱动傻瓜教程
- 基于字符设备的IIC驱动源代码
- 基于宋宝华老师的字符设备驱动
- 基于TQ2440的led字符设备驱动
- vxworks驱动开发----2-vxbus与组件以及arp表
- fsl_e500 pci设备驱动vxworks的实现
- vxWorks6.6下基于VxBus架构的Can控制器(sja1000t)驱动编写
- 基于VxWorks系统的NVMe驱动
- 基于ARM9开发板的按键字符设备驱动实现
- 1-12tar归档 文件并在系统间复制文件
- 超实用git技巧之提交代码冲突或报error
- (LeetCode)算法题目——Add Two Numbers
- Lock的await/singal 和 Object的wait/notify 的区别
- Javaweb出错处理,myeclipse,Tomcat服务器选择错误
- 基于VxWorks的VxBus字符设备驱动
- Dubbo源码分析 Handler & Filter
- 使用if语句编写程序
- pythonweb练习(一)
- JavaScript之BOM操作
- A
- 【codeforces
- Matlab蚁群算法解决TSP问题代码超详细注释
- 你想要的岁月都会给你.