Windriver驱动开发工具使用快速入门

平台: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。

我们看到没有报错,说明读写正常。 

 

  • 12
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Wind River是一个嵌入式系统开发工具公司,提供了一系列的软件和工具来帮助开发者创建、测试和部署嵌入式系统。其中,Wind River的VxWorks操作系统是一个广泛应用于嵌入式系统中的实时操作系统。 下面是Wind River驱动开发的大致流程: 1. 确定驱动的需求和规格:在开始驱动程序的开发之前,需要明确驱动程序的需求和规格。这包括确定驱动程序需要支持的硬件设备、操作系统和应用程序等。 2. 编写驱动程序:根据需求和规格,编写驱动程序的源代码。这需要使用C或C++等编程语言,并且需要掌握硬件和操作系统的相关知识。 3. 进行单元测试:在编写完驱动程序之后,进行单元测试以确保驱动程序的正确性和稳定性。这包括对驱动程序各个模块的功能进行测试,以及对驱动程序的异常情况进行测试。 4. 进行集成测试:在完成单元测试之后,需要进行集成测试。这包括将驱动程序与应用程序和操作系统进行集成测试,以确保驱动程序能够正常工作并与其他部分协同工作。 5. 进行系统测试:在完成集成测试之后,需要进行系统测试。这包括对整个嵌入式系统进行测试,以确保驱动程序与其他组件的协同工作符合预期。 6. 进行调试和修复:在测试过程中,可能会出现一些问题。需要对这些问题进行调试和修复,确保驱动程序的正确性和稳定性。 7. 发布和维护:在驱动程序开发完毕之后,需要将其发布到生产环境中,并对其进行维护和更新,以确保其能够长期稳定地运行。 总之,Wind River驱动开发流程需要掌握硬件和操作系统的相关知识,以及熟练掌握编程语言和开发工具。同时,需要进行充分的测试和调试,以确保驱动程序的正确性和稳定性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值