您的位置:首页 > 其它

转载的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提供的工具,先看一下映射的空间地址和中断号!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: