转载的PCI驱动帖子整理
2012-09-01 08:35
441 查看
我有一块FPGA+PLX9030的继电器板,板的作用就是要通过上位机控制继电器的动作,在Windows平台下的驱动已经完成,并验证好用。现在想在运行有VxWorks5.5的Pentium3目标机上使用,则需要开发VxWorks的PCI驱动,目标机安装的是Tornado2.2版本。看了不少论文,里面提到了一些有用的思路,然后我就编写了下面的PCI设备初始化函数:
int pciDevConfig()
{
if(pciFindDevice(VENDOR_ID, DEVECE_ID, 0, (int *)&pciBus, (int *)&pciDev, (int *)&pciFunc) != OK)
{
logMsg("Device not found!\n", 0, 0, 0, 0, 0, 0);
return(ERROR);
}
logMsg("pciBus = %d!\n", pciBus, 0, 0, 0, 0, 0);
logMsg("pciDev = %d!\n", pciDev, 0, 0, 0, 0, 0);
logMsg("pciFunc = %d!\n", pciFunc, 0, 0, 0, 0, 0);
pciConfigInLong (pciBus, pciDev, pciFunc, PCI_CFG_BASE_ADDRESS_2, (int *)&memBase); //9030使用的local address space 0
logMsg("PCI_CFG_BASE_ADDRESS_2 = 0x%x!\n", memBase, 0, 0, 0, 0, 0);
memBase &= PCI_MEMBASE_MASK;
pciConfigInLong (pciBus, pciDev, pciFunc, PCI_CFG_COMMAND, (int *)&nCommand);
pciConfigOutLong(pciBus, pciDev, pciFunc, PCI_CFG_COMMAND,
nCommand | PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE | PCI_CMD_MEM_ENABLE );
pciConfigInLong (pciBus, pciDev, pciFunc, PCI_CFG_MODE, (int *)&sleepMode);
pciConfigOutLong(pciBus, pciDev, pciFunc, PCI_CFG_MODE, sleepMode | SLEEP_MODE_DIS);
if (sysMmuMapAdd(memBase, 0x2000,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE |
VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE |
VM_STATE_CACHEABLE_NOT
) == ERROR)
{
printf("\nMmuMap Error\n");
return ERROR;
};
return(OK);
}
在调试的时候,我是先将VxWorks镜像文件加载,然后启动Tornado,在新建的downloadable的项目中调用的这个函数,然后下载到目标机上执行。
我困惑的是:pciDevConfig必须是在硬件初始化的时候调用,即sysLib.c文件的sysHwInit()函数中调用吗?还有,即使我得到内存映射的地址,我怎么使用这个地址呢?
因为我使用的是内存空间,那么
var = *((long *)memBase);
*((long *)memBase) = 0xXXXX;
这样就可以访问这片内存空间了吗?还是使用sysInWord、sysOutWord这类函数?
另外我可以在sysLib.c的PHYS_MEM_DESC sysPhysMemDesc结构体中手动指定PCI的内存映射地址吗,应该怎样实现?
这个问题困扰我好久了,希望有高手能够指点一二!
1. 修改目标BSP目录下的sysLib.c文件中的sysHwInit()函数,如下所示:
#include "PlxPCI9056.h"
void sysHwInit (void)
{
PHYS_MEM_DESC *pMmu;
int ix = 0;
............................................
#ifdef INCLUDE_PCI
pciConfigLibInit (PCI_MECHANISM_1, PCI_CONFIG_ADDR, PCI_CONFIG_DATA, NONE);
sysPciIntInit (); /* it does pciIntLibInit() */
PCI_CAN_Init();
#endif /* INCLUDE_PCI */
.................................
}
注:
1) 在目标BSP目录下的Config.h文件中要将PCI相关的宏定义打开
在工程的设置中"VxWorks"选项卡中 hardware -> buses -> PCI configuration 包含此配置。
3) 函数PCI_CAN_Init()调用位置,必须在 PCI 初始化完成之后和在 MMU 初始化(usrMmuInit())完成之前插入此函数的调用,否则驱动程序不能工作。
2. sysInWord、sysOutWord: 这样的函数是读写IO端口用的!
内存映射方式读取,参考下面的函数:
/************************************************************************/
/*Function : 从ulPortAddr+ucRegister内存地址读取数据
/*Input : ulPortAddr, 端口号(即CAN-X通道基地址);
/* ucRegister, 读取的数据(即CAN的寄存器);
/*Output : 从ulPortAddr+ucRegister内存地址读取数据
/*RetValue : 从ulPortAddr+ucRegister内存地址读取数据
/*Author : qcj_21 at [2010-8-10 10:54:32]
/************************************************************************/
UCHAR CANR(ULONG ulPortAddr, UCHAR ucRegister)
{
return *(volatile unsigned char*)(ulPortAddr+ucRegister) ;
}
/************************************************************************/
/*Function : 向ulPortAddr+ucRegister内存地址写数据
/*Input : ulPortAddr, 端口号(即CAN-X通道基地址);
/* ucRegister, 写入的数据(即CAN的寄存器);
/* ucValue, 写入的数据(即CAN寄存器的设置值);
/*Output : 无
/*RetValue : 无
/*Author : qcj_21 at [2010-8-10 11:09:15]
/************************************************************************/
void CANW(ULONG ulPortAddr, UCHAR ucRegister, UCHAR ucValue)
{
*(volatile unsigned char*)(ulPortAddr+ucRegister) = ucValue;
}
3. 另外我可以在sysLib.c的PHYS_MEM_DESC sysPhysMemDesc结构体中手动指定PCI的内存映射地址吗,应该怎样实现?
这个问题取决于你的PCI板卡,是静态映射还是动态映射,如果是静态映射需要在PHYS_MEM_DESC sysPhysMemDesc中手动添加映射地址,如果是动态映射,你需要读取PCI的配置空间获取。
首先感谢这位大哥的帮助,
除了“在工程的设置中"VxWorks"选项卡中 hardware -> buses -> PCI configuration 包含此配置。”这个设置没有进行,其他的我都做了。
另外我还有个问题,如果PCI设备初始化函数是在sysLib.c中调用的,那么他就应该是在BSP文件夹中,那么我在这里得到的内存映射地址memBase在应用程序层面上怎么用啊,这个变量memBase应用程序根本看不到啊?
我开始是将mypciDevInit()函数写在mypciDevInit.c中,然后将mypciDevInit.c放在BSP路径下(pvPentium文件夹),编译没有问题,我就将基于这个BSP的bootable的项目新生成的VxWorks镜像重新引导启动(BootRom也重新制作了);接着开始编写应用程序,我又新建一个downloadable的项目,对pci内存进行读写,此时我想使用memBase这个变量,不知道怎么用啊?
也可能是我理解有问题,希望能够再指点一下。
这个问题如下:
/************************************************************************/
/*Function : 得到PlxPCI9056信息,即内存映射基地址和映射空间大小,IO空间基地址,中断号
/*Input : pnMemBaseAddress,内存映射基地址
/* pnIOBaseAddress, IO空间基地址
/* pnCAN_IRQNum, PCI9056总占用中断号
/* pnMemSpaceLen, 映射空间大小
/*Output : 无
/*RetValue : 无
/*Author : qcj_21 at [2010-9-28 15:17:29]
/************************************************************************/
void GetPlxPCI9056Info(UINT32 *pnMemBaseAddress,
UINT32 *pnIOBaseAddress,
UINT32 *pnCAN_IRQNum,
UINT32 *pnMemSpaceLen)
{
*pnMemBaseAddress = g_nMemBaseAddress;
*pnIOBaseAddress = g_nIOBaseAddress;
*pnCAN_IRQNum = g_nCAN_IRQNum;
*pnMemSpaceLen = g_nMemSpaceLen;
}
建议你先在windows平台下,用windriver提供的工具,先看一下映射的空间地址和中断号!
int pciDevConfig()
{
if(pciFindDevice(VENDOR_ID, DEVECE_ID, 0, (int *)&pciBus, (int *)&pciDev, (int *)&pciFunc) != OK)
{
logMsg("Device not found!\n", 0, 0, 0, 0, 0, 0);
return(ERROR);
}
logMsg("pciBus = %d!\n", pciBus, 0, 0, 0, 0, 0);
logMsg("pciDev = %d!\n", pciDev, 0, 0, 0, 0, 0);
logMsg("pciFunc = %d!\n", pciFunc, 0, 0, 0, 0, 0);
pciConfigInLong (pciBus, pciDev, pciFunc, PCI_CFG_BASE_ADDRESS_2, (int *)&memBase); //9030使用的local address space 0
logMsg("PCI_CFG_BASE_ADDRESS_2 = 0x%x!\n", memBase, 0, 0, 0, 0, 0);
memBase &= PCI_MEMBASE_MASK;
pciConfigInLong (pciBus, pciDev, pciFunc, PCI_CFG_COMMAND, (int *)&nCommand);
pciConfigOutLong(pciBus, pciDev, pciFunc, PCI_CFG_COMMAND,
nCommand | PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE | PCI_CMD_MEM_ENABLE );
pciConfigInLong (pciBus, pciDev, pciFunc, PCI_CFG_MODE, (int *)&sleepMode);
pciConfigOutLong(pciBus, pciDev, pciFunc, PCI_CFG_MODE, sleepMode | SLEEP_MODE_DIS);
if (sysMmuMapAdd(memBase, 0x2000,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE |
VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE |
VM_STATE_CACHEABLE_NOT
) == ERROR)
{
printf("\nMmuMap Error\n");
return ERROR;
};
return(OK);
}
在调试的时候,我是先将VxWorks镜像文件加载,然后启动Tornado,在新建的downloadable的项目中调用的这个函数,然后下载到目标机上执行。
我困惑的是:pciDevConfig必须是在硬件初始化的时候调用,即sysLib.c文件的sysHwInit()函数中调用吗?还有,即使我得到内存映射的地址,我怎么使用这个地址呢?
因为我使用的是内存空间,那么
var = *((long *)memBase);
*((long *)memBase) = 0xXXXX;
这样就可以访问这片内存空间了吗?还是使用sysInWord、sysOutWord这类函数?
另外我可以在sysLib.c的PHYS_MEM_DESC sysPhysMemDesc结构体中手动指定PCI的内存映射地址吗,应该怎样实现?
这个问题困扰我好久了,希望有高手能够指点一二!
1. 修改目标BSP目录下的sysLib.c文件中的sysHwInit()函数,如下所示:
#include "PlxPCI9056.h"
void sysHwInit (void)
{
PHYS_MEM_DESC *pMmu;
int ix = 0;
............................................
#ifdef INCLUDE_PCI
pciConfigLibInit (PCI_MECHANISM_1, PCI_CONFIG_ADDR, PCI_CONFIG_DATA, NONE);
sysPciIntInit (); /* it does pciIntLibInit() */
PCI_CAN_Init();
#endif /* INCLUDE_PCI */
.................................
}
注:
1) 在目标BSP目录下的Config.h文件中要将PCI相关的宏定义打开
在工程的设置中"VxWorks"选项卡中 hardware -> buses -> PCI configuration 包含此配置。
3) 函数PCI_CAN_Init()调用位置,必须在 PCI 初始化完成之后和在 MMU 初始化(usrMmuInit())完成之前插入此函数的调用,否则驱动程序不能工作。
2. sysInWord、sysOutWord: 这样的函数是读写IO端口用的!
内存映射方式读取,参考下面的函数:
/************************************************************************/
/*Function : 从ulPortAddr+ucRegister内存地址读取数据
/*Input : ulPortAddr, 端口号(即CAN-X通道基地址);
/* ucRegister, 读取的数据(即CAN的寄存器);
/*Output : 从ulPortAddr+ucRegister内存地址读取数据
/*RetValue : 从ulPortAddr+ucRegister内存地址读取数据
/*Author : qcj_21 at [2010-8-10 10:54:32]
/************************************************************************/
UCHAR CANR(ULONG ulPortAddr, UCHAR ucRegister)
{
return *(volatile unsigned char*)(ulPortAddr+ucRegister) ;
}
/************************************************************************/
/*Function : 向ulPortAddr+ucRegister内存地址写数据
/*Input : ulPortAddr, 端口号(即CAN-X通道基地址);
/* ucRegister, 写入的数据(即CAN的寄存器);
/* ucValue, 写入的数据(即CAN寄存器的设置值);
/*Output : 无
/*RetValue : 无
/*Author : qcj_21 at [2010-8-10 11:09:15]
/************************************************************************/
void CANW(ULONG ulPortAddr, UCHAR ucRegister, UCHAR ucValue)
{
*(volatile unsigned char*)(ulPortAddr+ucRegister) = ucValue;
}
3. 另外我可以在sysLib.c的PHYS_MEM_DESC sysPhysMemDesc结构体中手动指定PCI的内存映射地址吗,应该怎样实现?
这个问题取决于你的PCI板卡,是静态映射还是动态映射,如果是静态映射需要在PHYS_MEM_DESC sysPhysMemDesc中手动添加映射地址,如果是动态映射,你需要读取PCI的配置空间获取。
首先感谢这位大哥的帮助,
除了“在工程的设置中"VxWorks"选项卡中 hardware -> buses -> PCI configuration 包含此配置。”这个设置没有进行,其他的我都做了。
另外我还有个问题,如果PCI设备初始化函数是在sysLib.c中调用的,那么他就应该是在BSP文件夹中,那么我在这里得到的内存映射地址memBase在应用程序层面上怎么用啊,这个变量memBase应用程序根本看不到啊?
我开始是将mypciDevInit()函数写在mypciDevInit.c中,然后将mypciDevInit.c放在BSP路径下(pvPentium文件夹),编译没有问题,我就将基于这个BSP的bootable的项目新生成的VxWorks镜像重新引导启动(BootRom也重新制作了);接着开始编写应用程序,我又新建一个downloadable的项目,对pci内存进行读写,此时我想使用memBase这个变量,不知道怎么用啊?
也可能是我理解有问题,希望能够再指点一下。
这个问题如下:
/************************************************************************/
/*Function : 得到PlxPCI9056信息,即内存映射基地址和映射空间大小,IO空间基地址,中断号
/*Input : pnMemBaseAddress,内存映射基地址
/* pnIOBaseAddress, IO空间基地址
/* pnCAN_IRQNum, PCI9056总占用中断号
/* pnMemSpaceLen, 映射空间大小
/*Output : 无
/*RetValue : 无
/*Author : qcj_21 at [2010-9-28 15:17:29]
/************************************************************************/
void GetPlxPCI9056Info(UINT32 *pnMemBaseAddress,
UINT32 *pnIOBaseAddress,
UINT32 *pnCAN_IRQNum,
UINT32 *pnMemSpaceLen)
{
*pnMemBaseAddress = g_nMemBaseAddress;
*pnIOBaseAddress = g_nIOBaseAddress;
*pnCAN_IRQNum = g_nCAN_IRQNum;
*pnMemSpaceLen = g_nMemSpaceLen;
}
建议你先在windows平台下,用windriver提供的工具,先看一下映射的空间地址和中断号!
相关文章推荐
- vs2013+WDK8.1+WinDbg调试驱动开发环境配置(多帖子整理,水原创)
- Oracle的rownum原理和使用(整理几个达人的帖子)(转载)
- vs2013+WDK8.1+WinDbg调试驱动开发环境配置(多帖子整理,水原创)
- [转载]linux查看硬件信息及驱动设备相关整理
- 如何学习wince驱动开发--转载(作者:gooogle man)
- 推荐!国外程序员整理的 C++ 资源大全(转载)
- 【整理转载】四月股票市场分析与复盘
- Linux 视频设备驱动V4L2最常用的控制命令使用说明--实际中应用的整理
- JVM(Java虚拟机)内存模型(转载/整理)
- 帖子整理汇总
- Android ListVeiw控件(转载整理)
- xHci-PCI驱动设计
- WINDOW CE驱动文档的整理开始
- 没想到在CSDN论坛发的一篇帖子被很多人转载了,意外啊~
- CString用法整理(转载)
- (转载整理)SAP ERP常用表
- VxWorks PCI驱动编程步骤
- VC:CString用法整理(转载)
- Linux PCI驱动模型
- 【整理】常见笔试题,对应解释转载