平台:ise14.7,Win driver10.21,Visual Studio 2015
操作系统:Windows7
硬件设备:PCI板卡
最近在开发过程中,作为一个逻辑开发人员,在有的的情况下需要自己快速验证逻辑正确性。我使用WinDriver来作为驱动开发软件进行简单调试硬件设备。适合我们这种初学者使用,我们不需要设计复杂的驱动程序,就可以验真硬件的正确性。今天我们使用WinDriver来进行PCI的简单访问,在使用WinDriver生成简单的驱动代码,来对硬件进行连续读写访问。
这里省略FPGA关于PCI开发的部分。
我们在xilinx的PCI的IP核中定义PCI板卡信息。Vender ID,Device ID以及板卡的BAR空间。我们这里定义使用BAR0和BAR1空间。下载逻辑到PCI板卡后。打开WinDriver设备。
打开New host driver project。
找到该设备。双击进入该设备。
找到两个BAR空间。
读写BAR空间。
这里完成了简单的硬件读写测试。
下面我们使用WinDriver生成驱动。
保存后,进行进入WinDriver,点击project。生成代码。
下一步生成代码,选择如下。
继续选择。
生成的文件夹如下。x86里面就是生成的代码。
下面我们为硬件设备安装驱动文件,生成的驱动就是你保存的文件下面的.inf文件。点击更新驱动文件。
接下来,我们打开工程。pci_driver_diag.c就是我们需要看的。在此里面添加简单的测试代码,来测试我们的硬件设备。
打开工程后如下。
下面是我添加部分的代码。
这里主要说明两个函数。
WDC_ReadAddr32(hDev, dwAddrSpace, dwOffset, &u32Data) :
WDC_WriteAddr32(hDev, dwAddrSpace, dwOffset, u32Data);
WDC_WriteAddr32:向目标设备写入值。
WDC_ReadAddr32:从目标设备读出值。
hDev | dwAddrSpace | dwOffset | u32Data |
外部设备的句柄 | 外部设备上的BAR空间。 | 偏移地址 | Write:写入值。 Read:读出值。 |
这里我在源代码基础上添加了一个for循环来循环向一个地址写入和读出。判断两者是否相等。不相等就报错。说明pci写入或者读取失败。
/* Read/write memory or I/O space address menu */
static void MenuReadWriteAddr(WDC_DEVICE_HANDLE hDev)
{
DWORD option;
static DWORD dwAddrSpace = ACTIVE_ADDR_SPACE_NEEDS_INIT;
static WDC_ADDR_MODE mode = WDC_MODE_32;
static BOOL fBlock = FALSE;
UINT32 u32Data = 0;
/* Initialize active address space */
if (ACTIVE_ADDR_SPACE_NEEDS_INIT == dwAddrSpace)
{
DWORD dwNumAddrSpaces = PXI_DRIVER_GetNumAddrSpaces(hDev);
/* Find the first active address space */
for (dwAddrSpace = 0; dwAddrSpace < dwNumAddrSpaces; dwAddrSpace++)
{
if (WDC_AddrSpaceIsActive(hDev, dwAddrSpace))
break;
}
/* Sanity check */
if (dwAddrSpace == dwNumAddrSpaces)
{
PXI_DRIVER_ERR("MenuReadWriteAddr: Error - no active address spaces found\n");
dwAddrSpace = ACTIVE_ADDR_SPACE_NEEDS_INIT;
return;
}
}
do
{
printf("\n");
printf("Read/write the device's memory and IO ranges\n");
printf("---------------------------------------------\n");
printf("%d. Change active address space for read/write "
"(currently: BAR %ld)\n", MENU_RW_ADDR_SET_ADDR_SPACE, dwAddrSpace);
printf("%d. Change active read/write mode (currently: %s)\n",
MENU_RW_ADDR_SET_MODE,
(WDC_MODE_8 == mode) ? "8 bit" : (WDC_MODE_16 == mode) ? "16 bit" :
(WDC_MODE_32 == mode) ? "32 bit" : "64 bit");
printf("%d. Toggle active transfer type (currently: %s)\n",
MENU_RW_ADDR_SET_TRANS_TYPE,
(fBlock ? "block transfers" : "non-block transfers"));
printf("%d. Read from active address space\n", MENU_RW_ADDR_READ);
printf("%d. Write to active address space\n", MENU_RW_ADDR_WRITE);
printf("%d. Exit menu\n", MENU_RW_ADDR_EXIT);
printf("\n");
if (DIAG_INPUT_FAIL == DIAG_GetMenuOption(&option,
MENU_RW_ADDR_WRITE))
{
continue;
}
switch (option)
{
case MENU_RW_ADDR_EXIT: /* Exit menu */
break;
case MENU_RW_ADDR_SET_ADDR_SPACE: /* Set active address space for read/write address requests */
{
SetAddrSpace(hDev, &dwAddrSpace);
break;
}
case MENU_RW_ADDR_SET_MODE: /* Set active mode for read/write address requests */
WDC_DIAG_SetMode(&mode);
break;
case MENU_RW_ADDR_SET_TRANS_TYPE: /* Toggle active transfer type */
fBlock = !fBlock;
break;
case MENU_RW_ADDR_READ: /* Read from a memory or I/O address */
case MENU_RW_ADDR_WRITE: /* Write to a memory or I/O address */
{
WDC_DIRECTION direction =
(MENU_RW_ADDR_READ == option) ? WDC_READ : WDC_WRITE;
if (fBlock)
WDC_DIAG_ReadWriteBlock(hDev, direction, dwAddrSpace);
else
WDC_DIAG_ReadWriteAddr(hDev, direction, dwAddrSpace, mode);
for (int i = 0; i <= 10; i++)
{
WDC_WriteAddr32(hDev, dwAddrSpace, 0x00000000, 0x00005555);
WDC_ReadAddr32(hDev, dwAddrSpace, 0x00000000, &u32Data);
printf(" from = %i read bar0 0x00 =%x write data is =%x\n", i, u32Data, 0x00005555);
if (u32Data != 0x00005555)
printf("diffenent from = %i read bar0 0x00 =%x write data is =%x\n", i, u32Data, 0x00005555);
WDC_WriteAddr32(hDev, dwAddrSpace, 0x00000000, 0x0000aaaa);
WDC_ReadAddr32(hDev, dwAddrSpace, 0x00000000, &u32Data);
if (u32Data != 0x0000aaaa)
printf("diffenent from = %i read bar0 0x00 =%x write data is =%x\n", i, u32Data, 0x0000aaaa);
}
break;
}
}
} while (MENU_RW_ADDR_EXIT != option);
}
运行代码。
这里我们输入3:Read/write memory and IO addresses on the device
我们可以看到这里bar空间选择的为BAR0,读写方式选择的为32位读写。
我们选择:Read from active address space。
继续输入偏移地址:00。
我们看到没有报错,说明读写正常。