阅读:3781回复:2
利用windriver 开发了个usb的驱动,写个开发心得
项目组需要利用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,处理不当速度很难上去! |
|
沙发#
发布于:2009-04-28 12:43
要是再详细点就更好了,本人菜鸟飞飞,刚开始做USB驱动
|
|
板凳#
发布于:2009-04-28 13:13
收藏慢慢学习先
谢谢分享! |
|