zhangzhuoliang
驱动牛犊
驱动牛犊
  • 注册日期2003-06-23
  • 最后登录2016-01-07
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望42点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
阅读:3781回复:2

利用windriver 开发了个usb的驱动,写个开发心得

楼主#
更多 发布于:2009-03-31 19:20
项目组需要利用2440采集数字电视的采样数据,所以让我开发一个usb的数据采集系统,就两个要求
1 速度要达到500kbyte/s以上
2 稳定

由于之前没有做过windows驱动的经验,所以花了3,4天时间读了读ddk的文档,期间还上chinapub找个本书,读了免费的第1章,按照他配置了vc的 编译环境,呵呵。
然后就吧ddk下面的bulkusb源代码进行了修改,写好usb device的驱动,有些了个应用程序,测试一下,采集数据是ok了,但是发现有时候蓝屏,特别是采集100m左右,就会出现蓝品!这下没办法了,由于我本身就对windows内核编程不熟悉,有调试了大概3,4天确认问题可能处在电源管理方面,联系到自己对这方面不是很熟悉,而且时间紧迫,没办法转向windriver开发
!我安装的是9.21版本(请到迅雷下载)。

1. 驱动的开发:
      a   这步开发比较简单,首先确认你的device固件正确能枚举成功,然后将device连接到pc usb host 端。
      b  按照向导指引刷出你的设备进行配置,然后点击编译按钮生成代码。这部分内容请参考安装文档的快速开发向导!
2.应用程序开发:
     最主要的几个函数是,opendevice  和readwrite 函数:其实大家只要摘录向导生成代码的内容即可,这里贴一个我的


static WDU_DRIVER_HANDLE hDriver = 0;

static DRIVER_CONTEXT DrvCtx ;

static BOOL DLLCALLCONV DeviceAttach(WDU_DEVICE_HANDLE hDevice,
                                     WDU_DEVICE *pDeviceInfo, PVOID pUserData)
{
    DRIVER_CONTEXT *pDrvCtx = (DRIVER_CONTEXT *)pUserData;
    DEVICE_CONTEXT *pDevCtx, **ppDevCtx;
    DWORD dwInterfaceNum = pDeviceInfo->pActiveInterface[0]->pActiveAltSetting->Descriptor.bInterfaceNumber;
    DWORD dwAlternateSetting = pDeviceInfo->pActiveInterface[0]->pActiveAltSetting->Descriptor.bAlternateSetting;
    
    
    TRACE("\nDeviceAttach: received and accepted attach for vendor id 0x%x, "
        "product id 0x%x, interface %ld, device handle 0x%p\n",
        pDeviceInfo->Descriptor.idVendor, pDeviceInfo->Descriptor.idProduct,
        dwInterfaceNum, hDevice);
    
    /* Add our device to the device list */
    pDevCtx = (DEVICE_CONTEXT *)malloc(sizeof(DEVICE_CONTEXT));
    if (!pDevCtx)
    {
        ERR("DeviceAttach: failed allocating memory\n");
        return FALSE;
    }
    BZERO(*pDevCtx);
    pDevCtx->hDevice = hDevice;
    pDevCtx->dwInterfaceNum = dwInterfaceNum;
    pDevCtx->dwVendorId = pDeviceInfo->Descriptor.idVendor;
    pDevCtx->dwProductId = pDeviceInfo->Descriptor.idProduct;
    pDevCtx->dwAlternateSetting = dwAlternateSetting;
    
    OsMutexLock(pDrvCtx->hMutex);
    for (ppDevCtx = &pDrvCtx->deviceContextList; *ppDevCtx;
    ppDevCtx = &((*ppDevCtx)->pNext));
    *ppDevCtx = pDevCtx;
    pDrvCtx->dwDeviceCount++;
    OsMutexUnlock(pDrvCtx->hMutex);
    
    OsEventSignal(pDrvCtx->hEvent);
    /* Accept control over this device */
    return TRUE;
}

static VOID DLLCALLCONV DeviceDetach(WDU_DEVICE_HANDLE hDevice, PVOID pUserData)
{
    DRIVER_CONTEXT *pDrvCtx = (DRIVER_CONTEXT *)pUserData;
    DEVICE_CONTEXT **pCur;
    DEVICE_CONTEXT *pTmpDev;
    BOOL bDetachActiveDev = FALSE;
    
    TRACE("\nDeviceDetach: received detach for device handle 0x%p\n", hDevice);
    
    OsMutexLock(pDrvCtx->hMutex);
    for (pCur = &pDrvCtx->deviceContextList;
    *pCur && (*pCur)->hDevice != hDevice;
    pCur = &((*pCur)->pNext));
    
    if (*pCur == pDrvCtx->pActiveDev)
    {
        bDetachActiveDev = TRUE;
        pDrvCtx->pActiveDev = NULL;
    }
    
    pTmpDev = *pCur;
    *pCur = pTmpDev->pNext;
    free(pTmpDev);
    
    pDrvCtx->dwDeviceCount--;
    OsMutexUnlock(pDrvCtx->hMutex);
    
    if (bDetachActiveDev)
    {
    /* When hDeviceUnusedEvent is not signaled, hDevice is possibly in use,
    * and therefore the detach callback needs to wait on it until it is
    * certain that it cannot be used.
        * When it is signaled - hDevice is no longer used. */
        OsEventWait(pDrvCtx->hDeviceUnusedEvent, INFINITE);
    }
}

DWORD DriverInit(WDU_MATCH_TABLE *pMatchTables, DWORD dwNumMatchTables,
                 const PCHAR sDriverName, const PCHAR sLicense, DRIVER_CONTEXT *pDrvCtx)
{
    DWORD dwError;
    WDU_EVENT_TABLE eventTable;
    
    /* Set Driver Name */
    if (!WD_DriverName(sDriverName))
    {
        ERR("Error: Could not set driver name to %s, exiting\n",
            sDriverName);
        return WD_SYSTEM_INTERNAL_ERROR;
    }
    
    dwError = OsEventCreate(&pDrvCtx->hEvent);
    if (dwError)
    {
        ERR("DriverInit: OsEventCreate() failed on event 0x%p: error 0x%lx "
            "(\"%s\")\n", pDrvCtx->hEvent, dwError, Stat2Str(dwError));
        return dwError;
    }
    
    dwError = OsMutexCreate(&pDrvCtx->hMutex);
    if (dwError)
    {
        ERR("DriverInit: OsMutexCreate() failed on mutex 0x%p: error 0x%lx "
            "(\"%s\")\n", pDrvCtx->hMutex, dwError, Stat2Str(dwError));
        return dwError;
    }
    
    dwError = OsEventCreate(&pDrvCtx->hDeviceUnusedEvent);
    if (dwError)
    {
        ERR("DriverInit: OsEventCreate() failed on event 0x%p: error 0x%lx "
            "(\"%s\")\n", pDrvCtx->hDeviceUnusedEvent, dwError,
            Stat2Str(dwError));
        return dwError;
    }
    
    OsEventSignal(pDrvCtx->hDeviceUnusedEvent);
    BZERO(eventTable);
    eventTable.pfDeviceAttach = DeviceAttach;
    eventTable.pfDeviceDetach = DeviceDetach;
    eventTable.pUserData = pDrvCtx;
    
    dwError = WDU_Init(&hDriver, pMatchTables, dwNumMatchTables, &eventTable,
        sLicense, WD_ACKNOWLEDGE);
    if (dwError)
    {
        ERR("DriverInit: failed to initialize USB driver: error 0x%lx "
            "(\"%s\")\n", dwError, Stat2Str(dwError));
        return dwError;
    }
    
    return WD_STATUS_SUCCESS;
}

VOID DriverUninit(DRIVER_CONTEXT *pDrvCtx)
{
    DEVICE_CONTEXT *pCur, *pTmpDev;
    
    if (pDrvCtx->hEvent)
        OsEventClose(pDrvCtx->hEvent);
    if (pDrvCtx->hMutex)
        OsMutexClose(pDrvCtx->hMutex);
    if (pDrvCtx->hDeviceUnusedEvent)
        OsEventClose(pDrvCtx->hDeviceUnusedEvent);
    if (hDriver)
        WDU_Uninit(hDriver);
    
    /* Release any remaining devices */
    pCur = pDrvCtx->deviceContextList;
    while (pCur)
    {
        pTmpDev = pCur;
        pCur = pCur->pNext;
        free(pTmpDev);
    }
}

DWORD OpenUsbDevice( void)
{
    
    DWORD dwError;
    WORD wVendorId = 0;
    WORD wProductId = 0;
    WDU_MATCH_TABLE matchTable;
    
   BZERO(DrvCtx);

    wVendorId = USE_DEFAULT;
    wProductId = USE_DEFAULT;
        
    /* use defaults */
    if (wVendorId == USE_DEFAULT)
        wVendorId = DEFAULT_VENDOR_ID;
    if (wProductId == USE_DEFAULT)
        wProductId = DEFAULT_PRODUCT_ID;
    BZERO(matchTable);
    matchTable.wVendorId = wVendorId;
    matchTable.wProductId = wProductId;
    
    dwError = DriverInit(&matchTable, 1, DEFAULT_DRIVER_NAME,
        DEFAULT_LICENSE_STRING, &DrvCtx);
    if (dwError)
    {
      goto Exit;
    }
    
    /* Wait for the device to be attached */
    dwError = OsEventWait(DrvCtx.hEvent, ATTACH_EVENT_TIMEOUT);
    if (dwError)
    {
        if (dwError==WD_TIME_OUT_EXPIRED)
        {
            ERR("Timeout expired for connection with the device.\n"
                "Check that the device is connected and try again.\n");
        }
        else
        {
            ERR("main: OsEventWait() failed on event 0x%p: error 0x%lx "
                "(\"%s\")\n", DrvCtx.hEvent, dwError, Stat2Str(dwError));
        }
        goto Exit;
    }

    OsMutexLock(DrvCtx.hMutex);
    if (!DrvCtx.dwDeviceCount)
    {
        OsMutexUnlock(DrvCtx.hMutex);
        return 1;
    }

    OsMutexUnlock(DrvCtx.hMutex);

    if (!DrvCtx.pActiveDev)
            DrvCtx.pActiveDev = DrvCtx.deviceContextList;

    OsEventReset(DrvCtx.hDeviceUnusedEvent);

    return 0 ;

Exit:    
    DriverUninit(&DrvCtx);
    return dwError;
}


void CloseUsbDevice( void)
{
  DriverUninit(&DrvCtx);
}


DWORD UsbRead(char *pBuffer , DWORD dwBufferSize , PDWORD pdwBytesTransferred)
{
    DWORD dwError ;
    WDU_DEVICE_HANDLE hDevice;


    OsMutexLock(DrvCtx.hMutex);
    hDevice = DrvCtx.pActiveDev->hDevice;
    OsMutexUnlock(DrvCtx.hMutex);
    

    

    dwError = WDU_TransferBulk(hDevice, 0x81,TRUE, 0, pBuffer, dwBufferSize,
                           pdwBytesTransferred,  TRANSFER_TIMEOUT);

  return dwError ;
}


3.驱动程序的发布:

这个也比较简单,请参考自带文档usb manual 的11章节,其实就是用到了他的一个wdreg工具,我写了个批处理文件,想安装的直接点批处理即可!

windriver开发驱动是比较方便,至于稳定性,现在正在测试,看来比较稳定!速度方面500kB是没问题!

不过速度方面pc驱动固然有影响,device的firmware影响也是很大的,特别是双缓冲的ep,处理不当速度很难上去!

最新喜欢:

haseahasea ilyb11ilyb11
jianboxu
驱动牛犊
驱动牛犊
  • 注册日期2009-02-23
  • 最后登录2009-04-29
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望111点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2009-04-28 12:43
要是再详细点就更好了,本人菜鸟飞飞,刚开始做USB驱动
bogkamp
驱动牛犊
驱动牛犊
  • 注册日期2009-04-28
  • 最后登录2009-04-28
  • 粉丝0
  • 关注0
  • 积分2分
  • 威望21点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2009-04-28 13:13
收藏慢慢学习先
谢谢分享!
游客

返回顶部