vxWorks6.6下基于VxBus架构的Can控制器(sja1000t)驱动编写

vxWorks6.6下基于VxBus架构的Can控制器驱动编写

 

 

目录

1       VxBus下驱动的架构...1

1.1        WorkBench3.0的认识...1

1.2        VxBus下驱动的结构以及编译...1

1.3        VxBus下驱动的编译...4

2       Can控制器的驱动编写...5

2.1        Can总线的认识...5

2.2        SJA1000T的认识...5

2.3        驱动的编写...6

2.3.1         驱动模板的选择...6

2.3.2         添加驱动所需的资源...6

2.3.3         驱动功能的完善...7

3       驱动调试...9

3.1        调试环境的搭建...9

3.2        调试中用到的方法...9

3.3        调试过程中遇到问题...9

 


1       VxBus下驱动的架构

1.1    WorkBench3.0的认识

Workbench3.0是VxWorks 6.x 的集成开发环境,而VxWorks 5.5是采用Tornado2.2 来进行开发的。Workbench3.0相比Tornado2.2来说提供了更为强大的功能,在Workbench3.0可以根据需要创建各种工程,常用的有以下几种VxWorks Image Projects,Boot Loader/BSP Projects,VxWorks Real-time Process Projects,VxWorks Downloadable Kernel ModuleProjects.

在进行驱动开发时需要创建VxWorks Image Projects。基于VxBus架构模型驱动在开发环境Workbench3.0中是以组件的形式体现的,这样的话就方便开发人员根据需要进行驱动的添加,重新编译VxWorks image后就可将驱动编进内核。开发人员只需将精力集中在驱动源码的编写上了。VxWorks5.5中没有VxBus架构,它的驱动的调用直接在BSP中的sysLIib.c中调用即可,这样开发的驱动可移植性不够好,当更换BSP时,又得重新移植。

关于Workbench3.0 的使用详见wr_workbench_vxworks_users_guide_3.0.pdf。

1.2    VxBus下驱动的结构以及编译

驱动源码结构

VxBus下驱源码主要由以下几个文件组成:

 README

 Makefile

 driverName.cdf

 driverName.dr

 driverName.dc

driverName.c

 

1 README

         关于驱动的说明文件

2 Makefile

         驱动的编译规则

3 driverName.cdf

         驱动的描述文件,里边包括的该驱动依赖的组件,驱动的位置,父目录以及子目录,在Workbench3.0下的说明信息等,很重要,若不正确,在Workbench3.0无法添加。

4 driverName.dr

         向VxBus进行注册的函数。

5 driverName.dc

         向VxBus进行注册的函数的声明。

6 driverName.c

         驱动的核心文件,驱动源码基本结构如下(用CAN1000t.c来举例)

A)芯片自身的数据结构,在驱动开发的过程中逐步完善,必需有这个结构VXB_DEVICE_ID,以便同VxBu进行通信。

typedef struct can1000tHwmonCtrl

{

VXB_DEVICE_ID _pDev;

*;

} CAN1000T_HWMON_CTRL;

 

B)三个基本的必需的函数,这几个函数在系统初始化的不同阶段进行调用

LOCAL voidcan1000tHwmonInstInit(VXB_DEVICE_ID);

LOCAL void can1000tHwmonInstInit2(VXB_DEVICE_ID);

LOCAL voidcan1000tHwmonInstConnect(VXB_DEVICE_ID);

 

C)驱动所提供的方法结构声明

LOCAL device_method_tcan1000tHwmon_methods[] =

{

DEVMETHOD(HwmonSendData,can1000tHwmonSendData),

DEVMETHOD(HwmonRecvData,can1000tHwmonRecvData),

DEVMETHOD_END

};

 

D)三个基本的必需的函数的声明

LOCAL struct drvBusFuncs can1000tHwmonFuncs=

{

can1000tHwmonInstInit,    /* devInstanceInit */

can1000tHwmonInstInit2,   /* devInstanceInit2 */

can1000tHwmonInstConnect  /* devInstanceConnect */

};

 

E)向VxBus注册的结构,包含了以上C,D。

LOCAL DRIVER_REGISTRATIONcan1000tHwmonDevRegistration =

{

NULL,                             /* pNext */

VXB_DEVID_DEVICE,       /* devID */

VXB_BUSID_PLB,          /* busID = Processor Local Bus */

VXBUS_VERSION_3,        /* busVer 1 */

"can1000t",         /* drvName */

&can1000tHwmonFuncs,     /* pDrvBusFuncs */

can1000tHwmon_methods,   /* pMethods */

NULL                    /* devProbe */

};

 

F)向VxBus注册的函数

void can1000tHwmonRegister(void)

{

vxbDevRegister((struct vxbDevRegInfo*)&can1000tHwmonDevRegistration);

}

1.3    VxBus下驱动的编译

install: 指vxWorks的安装目录

1)      在cmd下运行  

wrenv.exe -p vxworks-6.6

2) 进入如下目录

cd installDir\vxworks-6.x\target\config\comps\src\hwif

3)运行下列命令  make vxbUsrCmdLine.c

注意:若已经存在vxbUsrCmdLine.c的话则手工删除掉

4)进入下列目录

cd installDir\vxworks-6.x\target\config\comps\vxWorks

5)运行下列命令

Del  CxrCat.txt

6)运行下列命   

make

7)进入如下目录

cd installDir\vxworks-6.x\target\3rdparty\vendor\driver

8)运行下列命令

make CPU=cpuName TOOL=tool

注意:cpuName是所选BSP对应处理器的型号,如PPC32;

tool是对应的编译工具,如sfdiab 和 gnu         

 

至此就可以在对应的库目录下看见刚编译生成的库件

installDir\vxworks-6.x\target\lib\ppc\PPC32\common\下

此时在workbench中创建image工程,在kernel configuration下就可以看到刚才编译的

当然也可以把这些命令写成一个脚本直接点运行即可。也可以进入所写的驱动目录下单独编译该驱动命令如:

 makeCPU=PPC32           TOOL=sfidab

 

2        Can控制器的驱动编写

2.1    Can总线的认识

CAN是控制器局域网络(Controller Area Network, CAN)的简称,是由研发和生产汽车电子产品著称的德国BOSCH公司开发了的,并最终成为国际标准(ISO118?8)。是国际上应用最广泛的现场总线之一。在我看来,CAN其实就是一种通信的模式。使用如下


 

 

2.2  SJA1000T的认识

SJA1000T是一款CAN控制器的芯片,要编写它的驱动,首先必须熟悉它的工作模式。有两种工作模式:BasicCAN(兼容PCA82C20)和PeliCAN。通过阅读SJA1000T的DataSheet,来熟悉它的寄存器的布局,以及它的工作模式。

2.3  驱动的编写

2.3.1  驱动模板的选择

VxBus下的驱动按类进行区分,选择一个合适的驱动模板很重要,我选择的是adt7461(温度传感器)的驱动,然后进行修改,删除一些无用的代码,最终只有一个空的架子,然后按前面讲的方法进行编译,编译通过后,在WorkBench3.0中选择合适的BSP创建VxWorks Image Projects,在第三方驱动组件下添加所编写的驱动组件,若不能添加检查驱动中的driverName.cdf文件是否正确。若正确后则可以添加该组件如下图所示


2.3.2  添加驱动所需的资源

打开相应的BSP中的文件hwconf.c添加驱动所需的资源,寄存器基地址和中断号,以便在驱动初始化时使用添加如下:

 

1中断资源

#ifdefDRV_HWMON_ZKHXET_CAN1000T

          { EPIC_VEC_EXT_IRQ0,         "can1000t",      0,     0 },

          { EPIC_VEC_EXT_IRQ0,         "can1000t",      1,     0 },

#endif/*DRV_HWMON_ZKHXET_CAN1000T*/

 

2寄存器等资源

#ifdefDRV_HWMON_ZKHXET_CAN1000T

const structhcfResource can1000t1Resources[] = {

{VXB_REG_BASE,   HCF_RES_INT,    { (void *)(0xEE000000) } },

{"irq",            HCF_RES_INT,   {(void *)EPIC_VEC_EXT_IRQ0}  },

{ "busno",         HCF_RES_INT,    { (void *)(0) } },

};

#definecan1000t1Num NELEMENTS(can1000t1Resources)

#endif /*DRV_HWMON_ZKHXET_CAN1000T */

 

3验证驱动是否加载成功

修改hwconf.c文件后,在WorkBench3.0创建Boot Loader/BSP Projects,选择相应BSP进行编译,编译完成后,更新要添加驱动板子的boot。加载编译了驱动的内核映像,加载后,输入VxBusShow命令就可以看到加载后的驱动。若没有看到,检查驱动中设备名字是否正确。

2.3.3  驱动功能的完善

经过以上步骤,驱动的基本架构已经基本搭建完成,下来就是根据具体的CAN控制器芯片来按部就班的实现相应的功能。

2.3.3.1        SJA1000T的初始化

总体来说SJA1000T的初始话比较简单,主要是如下步骤

1)      通过配置模式寄存器(MOD)进入复位模式,因为进入复位模式后,一些寄存器才允许配置。

2)      配置时钟分频寄存器,选择PeliCAN模式,根据具体的电路,是否使能时钟等。

3)      配置模式寄存器,选择合适工作模式,是单滤波还是双滤波等。

4)      配置验收代码/屏蔽寄存器,配置一些初始值,一般配置全部接收,这个允许用户配置。

5)      配置总线定时器,选择合适的波特率,这些允许用户重新配置。

6)      通过配置模式寄存器(MOD)进入正常模式,此时SJA1000T就可以工作了。

详见驱动中的函数:

CanControllerInit(VXB_DEVICE_IDpDev);

 

2.3.3.2        SJA1000T发送数据

发送数据采用查询模式。每次发送之前查询状态寄存器的发送缓冲器状态是否释放。注意发送前允许用户配置一下帧格式的信息,如扩展帧还是标准帧,是否是远程帧,帧ID等信息。

详见驱动中的函数:

CanControllerTransmit(VXB_DEVICE_IDpDev, unsigned char *TXdata, int len);

 

2.3.3.3        SJA1000T接收数据

驱动的结构中分配存储数据的buffer,buffer包括帧的全部信息。

1)      中断处理

当有接收中断时,中断处理函数负责将数据存到分配的buffer中,相应的标志进行记录。

详见驱动中的函数:

Can1000tHwmonRecvInt(VXB_DEVICE_IDpDev);

2)      接收数据

当应用程序读取数据时,驱动只需将buffer中的数据传给应用层,相应的标志进行记录。

详见驱动中的函数:

can1000tHwmonRecvData(VXB_DEVICE_IDpDev, int* id, int* ext_flag, int * rtr_flag, int * time_stamp, int* data, intbuf_len);

 

2.3.3.4        SJA1000T的配置

CAN和串口不一样,并不是单纯的发送接收数据,它有自己的帧格式,如ID等,这些都需要用户设置,用户根据所需的数据设置相应的屏蔽码,确定哪些想接收,哪些想屏蔽,所以驱动必须提供用户可配置函数接口。如ioctl函数

详见驱动中的函数:

hwmonIoctl(HWMON_DEV_HDR*pDevHdr, int func, int arg);

至此为止CAN控制器SJA1000T的驱动完成,下来进入关键的一步调式。

3      驱动调试

3.1  调试环境的搭建

调试要用到USBCAN-2I调试工具,CAN发送和接收的应用程序。连接好硬件电路,就可以调试了。

3.2  调试中用到的方法

以下是我用到的方法:

7)      在驱动中创建全局变量,然后在应用程序调用时打印。系统加载驱动时,一些信息没办法看见,可以先将保存到全局变量中,最后在打印,这样就可知道了。

8)      利用logMsg进行打印。

9)      示波器的使用,在没有任何输出时,可以使用示波器在电路级联的地方进行波形的检测。

3.3  调试过程中遇到问题

遇到的问题有以下几个

1)      WorkBench3.0中无法添加驱动的组件,最后检查是driverName.cdf中的文件目录不正确。

正确的:_CHILDREN   FOLDER_3RD_DRIVERS

2)      驱动加载后,在命令行用VxBusShow查看驱动的信息时,最后检查是驱动文件中的名字不匹配。

 

 

 

 

 

 

 

 

 

 

 

 

 


你可能感兴趣的:(vxWorks)