• NK-RTU980 USB bulk传输


            NUC980_Non-OS_BSP_v1.03.000 SDK中没有提供USB bulk传输的例程,基于USBD_HID_Mouse例程进行修改。大体思路参考这个文章,先修改设备、配置、接口、端点等描述符,再安装驱动,最后编写下位机和上位机程序进行验证。

    USB Device Controller的框图如下:

    特性: 

    • USB Specification reversion 2.0 compliant
    • Supports 12 configurable endpoints in addition to Control Endpoint
    • Each of the endpoints can be Isochronous, Bulk or Interrupt and either IN or OUT direction
    • Three different operation modes of an in-endpoint - Auto Validation mode, Manual Validation mode, Fly mode
    • Supports DMA operation
    • 4096 Bytes Configurable RAM used as endpoint buffer
    • Supports Endpoint Maximum Packet Size up to 1024 bytes

    1.修改描述符

    关于描述符的详细说明参考博客

    各种描述符之间的关系:

    修改descriptors.c中DeviceDescriptor:

    1. uint8_t gu8DeviceDescriptor[] __attribute__((aligned(4))) =
    2. {
    3. #endif
    4. LEN_DEVICE, /* bLength */
    5. DESC_DEVICE, /* bDescriptorType */
    6. 0x00, 0x02, /* bcdUSB */ //0x10,0x01->0x00,0x20
    7. 0xFF, /* bDeviceClass */ //0x00->0xFF
    8. 0x00, /* bDeviceSubClass */
    9. 0x00, /* bDeviceProtocol */
    10. CEP_MAX_PKT_SIZE, /* bMaxPacketSize0 */
    11. /* idVendor */
    12. USBD_VID & 0x00FF,
    13. ((USBD_VID & 0xFF00) >> 8),
    14. /* idProduct */
    15. USBD_PID & 0x00FF,
    16. ((USBD_PID & 0xFF00) >> 8),
    17. 0x00, 0x00, /* bcdDevice */
    18. 0x01, /* iManufacture */
    19. 0x02, /* iProduct */
    20. 0x00, /* iSerialNumber - no serial */
    21. 0x01 /* bNumConfigurations */
    22. };

    修改hid_mouse.h中VID和PID的值(不是必须要修改的):

    1. #define USBD_VID 0x303A //0x0416->0x303A
    2. #define USBD_PID 0x3002 //0x8249->0x3001

    在hid_mouse.h中增加OUT节点的定义:

    1. /* Define EP maximum packet size */
    2. #define CEP_MAX_PKT_SIZE 64
    3. #define CEP_OTHER_MAX_PKT_SIZE 64
    4. #define EPA_MAX_PKT_SIZE 512 //修改,由64改为512
    5. #define EPA_OTHER_MAX_PKT_SIZE 64
    6. #define EPB_MAX_PKT_SIZE 512 //新增
    7. #define EPB_OTHER_MAX_PKT_SIZE 64
    8. #define CEP_BUF_BASE 0
    9. #define CEP_BUF_LEN CEP_MAX_PKT_SIZE
    10. #define EPA_BUF_BASE 0x200 //新增
    11. #define EPA_BUF_LEN EPA_MAX_PKT_SIZE
    12. #define EPB_BUF_BASE 0x400 //新增
    13. #define EPB_BUF_LEN EPB_MAX_PKT_SIZE //新增
    14. /* Define the interrupt In EP number */
    15. #define INT_IN_EP_NUM 0x01
    16. #define INT_OUT_EP_NUM 0x01 //新增

    修改descriptors.c中ConfigDescriptor :

    1. uint8_t gu8ConfigDescriptor[] __attribute__((aligned(4))) =
    2. {
    3. #endif
    4. LEN_CONFIG, /* bLength */
    5. DESC_CONFIG, /* bDescriptorType */
    6. /* wTotalLength */
    7. LEN_CONFIG_AND_SUBORDINATE & 0x00FF,
    8. ((LEN_CONFIG_AND_SUBORDINATE & 0xFF00) >> 8),
    9. 0x01, /* bNumInterfaces */
    10. 0x01, /* bConfigurationValue */
    11. 0x00, /* iConfiguration */
    12. 0x80 | (USBD_SELF_POWERED << 6) | (USBD_REMOTE_WAKEUP << 5),/* bmAttributes */
    13. USBD_MAX_POWER, /* MaxPower */
    14. /* I/F descr: HID */
    15. LEN_INTERFACE, /* bLength */
    16. DESC_INTERFACE, /* bDescriptorType */
    17. 0x00, /* bInterfaceNumber */
    18. 0x00, /* bAlternateSetting */
    19. 0x02, /* bNumEndpoints */ //0x01->0x02
    20. 0xFF, /* bInterfaceClass */ //0x03->0xFF
    21. 0x01, /* bInterfaceSubClass */
    22. 0x00, /* bInterfaceProtocol */ //HID_MOUSE->0x00
    23. 0x00, /* iInterface */
    24. /* HID Descriptor */ //不使用报告描述符,将此段配置注释。
    25. // LEN_HID, /* Size of this descriptor in UINT8s. */
    26. // DESC_HID, /* HID descriptor type. */
    27. // 0x10, 0x01, /* HID Class Spec. release number. */
    28. // 0x00, /* H/W target country. */
    29. // 0x01, /* Number of HID class descriptors to follow. */
    30. // DESC_HID_RPT, /* Descriptor type. */
    31. /* Total length of report descriptor. */
    32. // sizeof(HID_MouseReportDescriptor) & 0x00FF,
    33. // ((sizeof(HID_MouseReportDescriptor) & 0xFF00) >> 8),
    34. /* EP Descriptor: bulk in. */
    35. LEN_ENDPOINT, /* bLength */
    36. DESC_ENDPOINT, /* bDescriptorType */
    37. (INT_IN_EP_NUM | EP_INPUT), /* bEndpointAddress */
    38. EP_BULK, /* bmAttributes */ //EP_INT->EP_BULK
    39. /* wMaxPacketSize */
    40. EPA_MAX_PKT_SIZE & 0x00FF,
    41. ((EPA_MAX_PKT_SIZE & 0xFF00) >> 8),
    42. 0x00, /* bInterval */ //HID_DEFAULT_INT_IN_INTERVAL->0x00
    43. /* EP Descriptor: bulk out. */ //新增一个输出端点。
    44. LEN_ENDPOINT, /* bLength */
    45. DESC_ENDPOINT, /* bDescriptorType */
    46. (INT_OUT_EP_NUM | EP_OUTPUT), /* bEndpointAddress */
    47. EP_BULK, /* bmAttributes */
    48. /* wMaxPacketSize */
    49. EPB_MAX_PKT_SIZE & 0x00FF,
    50. ((EPB_MAX_PKT_SIZE & 0xFF00) >> 8),
    51. 0x00 /* bInterval */
    52. };

    修改LEN_CONFIG_AND_SUBORDINATE的值(减去了一个REPORT,增加了一个END):

    #define LEN_CONFIG_AND_SUBORDINATE      (LEN_CONFIG+LEN_INTERFACE+LEN_ENDPOINT+LEN_ENDPOINT)

    修改hid_mouse.c中的HID_InitForHighSpeed()、HID_InitForFullSpeed(),增加OUT端点配置:

    1. /**
    2. * @brief USBD Endpoint Config.
    3. * @param None.
    4. * @retval None.
    5. */
    6. void HID_InitForHighSpeed(void)
    7. {
    8. /* EPA ==> Interrupt IN endpoint, address 1 */
    9. USBD_SetEpBufAddr(EPA, EPA_BUF_BASE, EPA_BUF_LEN);
    10. USBD_SET_MAX_PAYLOAD(EPA, EPA_MAX_PKT_SIZE);
    11. USBD_ConfigEp(EPA, INT_IN_EP_NUM, USB_EP_CFG_TYPE_BULK, USB_EP_CFG_DIR_IN);
    12. /* EPB ==> Interrupt OUT endpoint, address 1 */
    13. USBD_SetEpBufAddr(EPB, EPB_BUF_BASE, EPB_BUF_LEN);
    14. USBD_SET_MAX_PAYLOAD(EPB, EPA_MAX_PKT_SIZE);
    15. USBD_ConfigEp(EPB, INT_OUT_EP_NUM, USB_EP_CFG_TYPE_BULK, USB_EP_CFG_DIR_OUT);
    16. USBD_ENABLE_EP_INT(EPB, USBD_EPINTEN_RXPKIEN_Msk);
    17. }
    18. void HID_InitForFullSpeed(void)
    19. {
    20. /* EPA ==> Interrupt IN endpoint, address 1 */
    21. USBD_SetEpBufAddr(EPA, EPA_BUF_BASE, EPA_BUF_LEN);
    22. USBD_SET_MAX_PAYLOAD(EPA, EPA_OTHER_MAX_PKT_SIZE);
    23. USBD_ConfigEp(EPA, INT_IN_EP_NUM, USB_EP_CFG_TYPE_BULK, USB_EP_CFG_DIR_IN);
    24. /* EPB ==> Interrupt OUT endpoint, address 1 */
    25. USBD_SetEpBufAddr(EPB, EPB_BUF_BASE, EPB_BUF_LEN);
    26. USBD_SET_MAX_PAYLOAD(EPB, EPB_OTHER_MAX_PKT_SIZE);
    27. USBD_ConfigEp(EPB, INT_OUT_EP_NUM, USB_EP_CFG_TYPE_BULK, USB_EP_CFG_DIR_IN);
    28. USBD_ENABLE_EP_INT(EPB, USBD_EPINTEN_RXPKIEN_Msk);
    29. }

    修改UsbString:

    1. uint8_t gu8ProductStringDesc[] __attribute__((aligned(4))) =
    2. {
    3. #endif
    4. 34,
    5. DESC_STRING,
    6. 'B', 0, 'U', 0, 'L', 0, 'K', 0,' ', 0, 'T', 0, 'r', 0, 'a', 0, 'n', 0, 's', 0, 'a', 0, 'c', 0, 't', 0, 'i', 0, 'o', 0, 'n', 0
    7. };

    编译程序,重新烧录。电脑->设备管理器>其它设备 下多了一个名称为BULK Transaction的设备:

     2.生成USB 驱动

    运行inf-wizard.exe应用,点击 Next:

     选择Vendor ID为0x303A、Product ID为0x3002的设备,点击Next:

     Manufacturer Name、Device Name可修改为其它类容,点击Next:

     选择一个路径存放驱动文件。

     点击Done完成并退出。

    3.安装驱动

    右键 ->更新驱动程序->浏览我的电脑以查找驱动程序(R),选择刚才存放驱动的文件夹:

     点击 下一页。

     一般会遇到以上问题,这是因为驱动没有包含数字签名,解决办法

    驱动安装成功之后,设备管理器展示如下:

     4.使用工具查看设备描述符

    运行testlibusb-win.exe,设备描述符如下:

    5.编写NUC980 bulk读写函数及测试程序

    在hid_mouse.c中增加bulk读写函数:

    1. /**
    2. * @brief USBD Endpoint Write.
    3. * @param None.
    4. * @retval None.
    5. */
    6. void BulkWriteData( uint8_t *Datas, uint16_t Len )
    7. {
    8. uint16_t i;
    9. for ( i=0; i<Len; i++)
    10. {
    11. USBD->EP[EPA].ep.EPDAT_BYTE = Datas[i];
    12. }
    13. USBD->EP[EPA].EPRSPCTL = USB_EP_RSPCTL_SHORTTXEN;
    14. USBD_ENABLE_EP_INT(EPA, USBD_EPINTEN_INTKIEN_Msk);
    15. }
    16. /**
    17. * @brief USBD Endpoint Read.
    18. * @param None.
    19. * @retval None.
    20. */
    21. uint16_t BulkReadData( uint8_t *Datas, uint16_t Len )
    22. {
    23. uint16_t i;
    24. uint16_t DataCnt = USBD->EP[EPB].EPDATCNT;
    25. if( DataCnt > 0 )
    26. {
    27. for( i = 0; i < DataCnt; i++ )
    28. {
    29. Datas[i] = USBD->EP[EPB].ep.EPDAT_BYTE;
    30. }
    31. }
    32. return DataCnt;
    33. }

    main.c中增加接收和发送数据的逻辑,main()函数如下:

    1. int32_t main (void)
    2. {
    3. uint8_t i, Cnt = 0;
    4. uint8_t DataBuf[EPB_MAX_PKT_SIZE];
    5. uint16_t RxLen;
    6. sysDisableCache();
    7. sysFlushCache(I_D_CACHE);
    8. sysEnableCache(CACHE_WRITE_BACK);
    9. UART_Init();
    10. printf("\n");
    11. printf("=======================\n");
    12. printf(" USB HID Mouse \n");
    13. printf("=======================\n");
    14. sysInstallISR(IRQ_LEVEL_1, IRQ_UDC, (PVOID)USBD_IRQHandler);
    15. /* enable CPSR I bit */
    16. sysSetLocalInterrupt(ENABLE_IRQ);
    17. sysEnableInterrupt(IRQ_UDC);
    18. USBD_Open(&gsInfo, HID_ClassRequest, NULL);
    19. /* Endpoint configuration */
    20. HID_Init();
    21. /* Start transaction */
    22. while(1)
    23. {
    24. if (USBD_IS_ATTACHED())
    25. {
    26. USBD_Start();
    27. break;
    28. }
    29. }
    30. while(1)
    31. {
    32. RxLen = BulkReadData(DataBuf, EPB_MAX_PKT_SIZE );
    33. if( RxLen > 0 )
    34. {
    35. BulkWriteData( DataBuf, EPA_MAX_PKT_SIZE );
    36. }
    37. }
    38. }

     编译之后烧写到NUC980。

    6.编写windows应用程序测试数据通信

    基于libusb.lib编写一个测试应用,进行简单的数据的发送和接收。代码如下:

    1. #include "lusb0_usb.h"
    2. #include <stdio.h>
    3. #include "stdint.h"
    4. #include <iostream>
    5. #include <sys/timeb.h>
    6. #include "windows.h"
    7. using namespace std;
    8. // Enables this example to work with a device running the
    9. // libusb-win32 PIC Benchmark Firmware.
    10. //#define BENCHMARK_DEVICE
    11. //
    12. // TEST SETUP (User configurable)
    13. // Issues a Set configuration request
    14. #define TEST_SET_CONFIGURATION
    15. // Issues a claim interface request
    16. #define TEST_CLAIM_INTERFACE
    17. // Use the libusb-win32 async transfer functions. see
    18. // transfer_bulk_async() below.
    19. #define TEST_ASYNC
    20. // Attempts one bulk read.
    21. #define TEST_BULK_READ
    22. // Attempts one bulk write.
    23. #define TEST_BULK_WRITE
    24. // Device vendor and product id.
    25. //#define MY_VID 0x05AC
    26. //#define MY_PID 0x12A0
    27. #define MY_VID 0x303A
    28. #define MY_PID 0x3002
    29. // Device configuration and interface id.
    30. #define MY_CONFIG 1 //bConfigurationValue --lwz
    31. #define MY_INTF 0 //bInterfaceNumber --lwz
    32. // Device endpoint(s)
    33. #define EP_IN 0x81 //0x81
    34. #define EP_OUT 0x01
    35. // Device of bytes to transfer.
    36. #define RX_BUF_SIZE 512
    37. #define TX_BUF_SIZE 512
    38. #define TEST_BULK_SPEED
    39. usb_dev_handle *dev = NULL; /* the device handle */
    40. //
    41. usb_dev_handle *open_dev(void);
    42. uint16_t usb_dev_read_sync( uint8_t *Buf, uint16_t bufsz );
    43. bool usb_dev_write_async( uint8_t *Datas, uint16_t DataLen, int timeout );
    44. int usb_dev_read_async( uint8_t *Buf, uint16_t bufsz, int timeout );
    45. static int transfer_bulk_async(usb_dev_handle *dev,
    46. int ep,
    47. char *bytes,
    48. int size,
    49. int timeout);
    50. usb_dev_handle *open_dev(void)
    51. {
    52. struct usb_bus *bus;
    53. struct usb_device *dev;
    54. for (bus = usb_get_busses(); bus; bus = bus->next)
    55. {
    56. for (dev = bus->devices; dev; dev = dev->next)
    57. {
    58. if (dev->descriptor.idVendor == MY_VID
    59. && dev->descriptor.idProduct == MY_PID)
    60. {
    61. return usb_open(dev);
    62. }
    63. }
    64. }
    65. return NULL;
    66. }
    67. //
    68. // usb_dev_init.
    69. //
    70. void usb_dev_init( void )
    71. {
    72. usb_init(); /* initialize the library */
    73. }
    74. //
    75. // usb_dev_open.
    76. //
    77. bool usb_dev_open( void )
    78. {
    79. usb_find_busses(); /* find all busses */
    80. usb_find_devices(); /* find all connected devices */
    81. if (!(dev = open_dev()))
    82. {
    83. printf("error opening device: \n%s\n", usb_strerror());
    84. return false;
    85. }
    86. if (usb_set_configuration(dev, MY_CONFIG) < 0) //MY_CONFIG是配置描述符中的bConfigurationValue
    87. {
    88. printf("error setting config #%d: %s\n", MY_CONFIG, usb_strerror());
    89. usb_close(dev);
    90. return false;
    91. }
    92. if (usb_claim_interface(dev, MY_INTF) < 0) //注册与操作系统通信的接口 --lwz
    93. {
    94. printf("error claiming interface #%d:\n%s\n", MY_INTF, usb_strerror());
    95. usb_close(dev);
    96. return false;
    97. }
    98. return true;
    99. }
    100. //
    101. // usb_dev_close.
    102. //
    103. void usb_dev_close( void )
    104. {
    105. if (dev)
    106. {
    107. usb_release_interface(dev, MY_INTF); //注销被usb_claim_interface函数调用后的接口,释放资源 --lwz
    108. usb_close(dev);
    109. }
    110. }
    111. bool usb_dev_isopen( void )
    112. {
    113. if( dev != NULL )
    114. {
    115. return true;
    116. }
    117. return false;
    118. }
    119. void usb_dev_reset_epin( void )
    120. {
    121. usb_clear_halt( dev, EP_IN );
    122. }
    123. void usb_dev_reset_epout( void )
    124. {
    125. usb_clear_halt( dev, EP_OUT );
    126. }
    127. int main(char argc,char **argv)
    128. {
    129. usb_dev_handle *dev = NULL; /* the device handle */
    130. char tmp[RX_BUF_SIZE];
    131. int ret;
    132. void* async_read_context = NULL;
    133. void* async_write_context = NULL;
    134. usb_init(); /* initialize the library */
    135. usb_find_busses(); /* find all busses */
    136. usb_find_devices(); /* find all connected devices */
    137. if (!(dev = open_dev()))
    138. {
    139. printf("error opening device: \n%s\n", usb_strerror());
    140. return 0;
    141. }
    142. else
    143. {
    144. printf("success: device %04X:%04X opened\n", MY_VID, MY_PID);
    145. }
    146. #ifdef TEST_SET_CONFIGURATION
    147. if (usb_set_configuration(dev, MY_CONFIG) < 0) //MY_CONFIG是配置描述符中的bConfigurationValue
    148. {
    149. printf("error setting config #%d: %s\n", MY_CONFIG, usb_strerror());
    150. usb_close(dev);
    151. return 0;
    152. }
    153. else
    154. {
    155. printf("success: set configuration #%d\n", MY_CONFIG);
    156. }
    157. #endif
    158. #ifdef TEST_CLAIM_INTERFACE
    159. if (usb_claim_interface(dev, 0) < 0) //注册与操作系统通信的接口 --lwz
    160. {
    161. printf("error claiming interface #%d:\n%s\n", MY_INTF, usb_strerror());
    162. usb_close(dev);
    163. return 0;
    164. }
    165. else
    166. {
    167. printf("success: claim_interface #%d\n", MY_INTF);
    168. }
    169. #endif
    170. #ifdef TEST_BULK_SPEED
    171. char tmpOut[TX_BUF_SIZE];
    172. char tmpIn[RX_BUF_SIZE];
    173. uint8_t Count = 0;
    174. uint64_t ComCnt = 0;
    175. uint64_t errCnt = 0;
    176. struct timeb rawtime;
    177. ftime(&rawtime);
    178. uint64_t StartTime = rawtime.time;
    179. for( ;; )
    180. {
    181. for( uint16_t i = 0; i < sizeof(tmpOut); i++ )
    182. {
    183. tmpOut[i] = Count++;
    184. }
    185. ComCnt ++;
    186. ret = transfer_bulk_async(dev, EP_OUT, tmpOut, sizeof(tmpOut), 5000);
    187. if (ret < 0)
    188. {
    189. // printf("error writing:\n%s\n", usb_strerror());
    190. }
    191. else
    192. {
    193. // printf("success: bulk write %d bytes\n", ret);
    194. }
    195. // Running an async read test
    196. ret = transfer_bulk_async(dev, EP_IN, tmpIn, sizeof(tmpIn), 5000);
    197. if (ret < 0)
    198. {
    199. printf("error reading:\n%s\n", usb_strerror());
    200. }
    201. else
    202. {
    203. printf("success: bulk read %d bytes\n", ret);
    204. }
    205. //if( memcmp( tmpOut, tmpIn, BUF_SIZE ) != 0 )
    206. //{
    207. // errCnt ++;
    208. //}
    209. for( int j = 0; j < TX_BUF_SIZE; j++ )
    210. {
    211. if( tmpOut[j] != tmpIn[j] )
    212. {
    213. errCnt ++;
    214. break;
    215. }
    216. }
    217. if( (ComCnt % 2000) == 0 )
    218. {
    219. printf("ComCnt:%d ",ComCnt );
    220. printf("errCnt:%d \n",errCnt );
    221. struct timeb rawtime1;
    222. ftime(&rawtime1);
    223. uint64_t endTime = rawtime1.time;
    224. printf("transfer speed:%0.2f bps\n", ((float)(ComCnt * TX_BUF_SIZE * 2 * 8) / (endTime - StartTime)) );
    225. }
    226. // Sleep(3);
    227. }
    228. #endif
    229. #ifdef TEST_BULK_WRITE
    230. #ifdef BENCHMARK_DEVICE
    231. ret = usb_control_msg(dev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
    232. 14, /* set/get test */
    233. 2, /* test type */
    234. MY_INTF, /* interface id */
    235. tmp, 1, 1000); //从默认的管道发送和接受控制数据--lwz
    236. #endif
    237. #ifdef TEST_ASYNC
    238. // Running an async write test
    239. for( int i = 0; i < sizeof(tmp); i++ )
    240. {
    241. tmp[i] = i;
    242. }
    243. ret = transfer_bulk_async(dev, EP_OUT, tmp, sizeof(tmp), 5000);
    244. #else
    245. // Running a sync write test
    246. ret = usb_bulk_write(dev, EP_OUT, tmp, sizeof(tmp), 5000);
    247. #endif
    248. if (ret < 0)
    249. {
    250. printf("error writing:\n%s\n", usb_strerror());
    251. }
    252. else
    253. {
    254. printf("success: bulk write %d bytes\n", ret);
    255. }
    256. #endif
    257. memset(tmp, 0 , TX_BUF_SIZE );
    258. #ifdef TEST_BULK_READ
    259. #ifdef BENCHMARK_DEVICE
    260. ret = usb_control_msg(dev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
    261. 14, /* set/get test */
    262. 1, /* test type */
    263. MY_INTF, /* interface id */
    264. tmp, 1, 1000);
    265. #endif
    266. #ifdef TEST_ASYNC //有声明--lwz
    267. // Running an async read test
    268. ret = transfer_bulk_async(dev, EP_IN, tmp, sizeof(tmp), 5000);
    269. #else
    270. // Running a sync read test
    271. ret = usb_bulk_read(dev, EP_IN, tmp, sizeof(tmp), 5000);
    272. #endif
    273. if (ret < 0)
    274. {
    275. printf("error reading:\n%s\n", usb_strerror());
    276. }
    277. else
    278. {
    279. printf("success: bulk read %d bytes\n", ret);
    280. for(int i = 0; i < ret; i++ )
    281. {
    282. printf( "%02X ", tmp[i]);
    283. }
    284. printf("\n");
    285. }
    286. #endif
    287. #ifdef TEST_BULK_READ
    288. #ifdef BENCHMARK_DEVICE
    289. ret = usb_control_msg(dev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
    290. 14, /* set/get test */
    291. 1, /* test type */
    292. MY_INTF, /* interface id */
    293. tmp, 1, 1000);
    294. #endif
    295. #ifdef TEST_ASYNC
    296. // Running an async read test
    297. ret = transfer_bulk_async(dev, EP_IN, tmp, sizeof(tmp), 5000);
    298. #else
    299. // Running a sync read test
    300. ret = usb_bulk_read(dev, EP_IN, tmp, sizeof(tmp), 5000);
    301. #endif
    302. if (ret < 0)
    303. {
    304. printf("error reading:\n%s\n", usb_strerror());
    305. }
    306. else
    307. {
    308. printf("success: bulk read %d bytes\n", ret);
    309. }
    310. #endif
    311. #ifdef TEST_CLAIM_INTERFACE
    312. usb_release_interface(dev, 0); //注销被usb_claim_interface函数调用后的接口,释放资源 --lwz
    313. #endif
    314. if (dev)
    315. {
    316. usb_close(dev);
    317. }
    318. printf("Done.\n");
    319. return 0;
    320. }
    321. /*
    322. * Read/Write using async transfer functions.
    323. *
    324. * NOTE: This function waits for the transfer to complete essentially making
    325. * it a sync transfer function so it only serves as an example of how one might
    326. * implement async transfers into thier own code.
    327. */
    328. static int transfer_bulk_async(usb_dev_handle *dev,
    329. int ep,
    330. char *bytes,
    331. int size,
    332. int timeout)
    333. {
    334. // Each async transfer requires it's own context. A transfer
    335. // context can be re-used. When no longer needed they must be
    336. // freed with usb_free_async().
    337. //
    338. void* async_context = NULL;
    339. int ret;
    340. // Setup the async transfer. This only needs to be done once
    341. // for multiple submit/reaps. (more below)
    342. //
    343. ret = usb_bulk_setup_async(dev, &async_context, ep);
    344. if (ret < 0)
    345. {
    346. printf("error usb_bulk_setup_async:\n%s\n", usb_strerror());
    347. goto Done;
    348. }
    349. // Submit this transfer. This function returns immediately and the
    350. // transfer is on it's way to the device.
    351. //
    352. ret = usb_submit_async(async_context, bytes, size);
    353. if (ret < 0)
    354. {
    355. printf("error usb_submit_async:\n%s\n", usb_strerror());
    356. usb_free_async(&async_context);
    357. goto Done;
    358. }
    359. // Wait for the transfer to complete. If it doesn't complete in the
    360. // specified time it is cancelled. see also usb_reap_async_nocancel().
    361. //
    362. ret = usb_reap_async(async_context, timeout);
    363. // Free the context.
    364. usb_free_async(&async_context);
    365. Done:
    366. return ret;
    367. }
    368. //
    369. // usb_dev_read_async.
    370. //
    371. int usb_dev_read_async( uint8_t *Buf, uint16_t bufsz, int timeout )
    372. {
    373. if( dev == NULL )
    374. {
    375. return 0;
    376. }
    377. int ret;
    378. char tmp[RX_BUF_SIZE];
    379. ret = transfer_bulk_async(dev, EP_IN, tmp, RX_BUF_SIZE, timeout );
    380. if( ret > 0 )
    381. {
    382. if( bufsz >= ret )
    383. {
    384. memcpy(Buf, tmp, ret );
    385. }
    386. }
    387. return ret;
    388. }
    389. //
    390. // usb_dev_write_async.
    391. //
    392. bool usb_dev_write_async( uint8_t *Datas, uint16_t DataLen, int timeout )
    393. {
    394. if( dev == NULL )
    395. {
    396. return false;
    397. }
    398. int ret;
    399. ret = transfer_bulk_async(dev, EP_OUT, (char *)Datas, DataLen , timeout);
    400. if( ret < 0 )
    401. {
    402. return false;
    403. }
    404. return true;
    405. }
    406. //
    407. // usb_dev_read_sync.
    408. //
    409. uint16_t usb_dev_read_sync( uint8_t *Buf, uint16_t bufsz )
    410. {
    411. if( dev == NULL )
    412. {
    413. return 0;
    414. }
    415. int ret;
    416. char tmp[RX_BUF_SIZE];
    417. ret = usb_bulk_read(dev, EP_IN, tmp, RX_BUF_SIZE,5000);
    418. if( ret > 0 )
    419. {
    420. if( bufsz >= ret )
    421. {
    422. memcpy(Buf, tmp, ret );
    423. }
    424. }
    425. return ret;
    426. }

    上位机运行日志如下:

     计算出的速率大约2.7MB/s,比全速高一点,这个速度还有待提升。

    NUC980技术交流QQ群:912184327

  • 相关阅读:
    生产力工具如何选择?印象笔记 Verse、Notion、FlowUs
    Windows CSC提权漏洞复现(CVE-2024-26229)
    Node历史版本下载及配置npm镜像
    剑指 Offer 12. 矩阵中的路径
    Matlab图像处理-三基色
    流量主如何在广告收益和用户体验中找到平衡
    微信小程序:炫酷恶趣制作神器小程序源码
    JavaWeb之MySql高级(保姆级教程)
    俯瞰·明攻山西之战(太原之战)
    计算机毕业设计之java+ssm基于android的家庭理财系统app
  • 原文地址:https://blog.csdn.net/professionalmcu/article/details/126338573