test_usbd.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. * Copyright (c) 2022-2024, Xiaohua Semiconductor Co., Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024-12-30 CDT first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #ifdef RT_USB_DEVICE_CDC
  13. /* menuconfig:
  14. 1.Hardware Drivers Config--->On-Chip Peripheral Driver--->Enable USB--->
  15. [*]Use USBFS Core
  16. Select USB Mode(USB Device Mode)
  17. [*]Enable VBUS Sensing for Device
  18. 2.RT-Thread Components--->
  19. Using USB legacy version--->
  20. Using USB device--->Device type--->
  21. [*]Enable to use device as CDC device
  22. */
  23. /*
  24. * 程序清单:这是一个 usb device 设备使用例程
  25. * 例程导出了 cdc_sample 命令到控制终端
  26. * PC上需要使用串口助手以DTR[√]方式打开USB的虚拟串口(比如 SSCOM 有这个功能)
  27. * 命令调用格式:cdc_sample
  28. * 程序功能:首先会打印三次str_write字符串内容,同时虚拟串口可输入发送任意小于255个字符的字符串,
  29. * 发送内容可在Finsh串口显示。
  30. */
  31. #define USBD_DEV_NAME "vcom" /* 名称 */
  32. rt_uint8_t str_read[255];
  33. static rt_err_t cdc_rx_handle(rt_device_t dev, rt_size_t size)
  34. {
  35. /* 读取虚拟串口接收内容 */
  36. rt_device_read(dev, 0, str_read, size);
  37. rt_kprintf("Read message: %s\n", str_read);
  38. return RT_EOK;
  39. }
  40. static int cdc_sample(void)
  41. {
  42. rt_uint8_t i;
  43. rt_err_t ret = RT_EOK;
  44. rt_device_t cdc_dev = RT_NULL; /* usb device设备句柄 */
  45. rt_uint8_t str_write[] = "This is a usb cdc device test!\r\n";
  46. rt_size_t str_len = rt_strlen((const char *)str_write);
  47. /* 查找USB虚拟串口设备 */
  48. cdc_dev = rt_device_find(USBD_DEV_NAME);
  49. if (cdc_dev == RT_NULL)
  50. {
  51. rt_kprintf("cdc sample run failed! can't find %s device!\n", USBD_DEV_NAME);
  52. return -RT_ERROR;
  53. }
  54. /* 以读写方式打开设备 */
  55. ret = rt_device_open(cdc_dev, RT_DEVICE_FLAG_INT_RX);
  56. if (ret != RT_EOK)
  57. {
  58. rt_kprintf("open %s device failed!\n", USBD_DEV_NAME);
  59. return ret;
  60. }
  61. rt_device_set_rx_indicate(cdc_dev, cdc_rx_handle);
  62. for (i = 1; i < 4; i++)
  63. {
  64. rt_kprintf("Start to send test message 3 timers :%d.\n", i);
  65. if (rt_device_write(cdc_dev, 0, str_write, str_len) != str_len)
  66. {
  67. rt_kprintf("send test message failed\n");
  68. return -RT_ERROR;
  69. }
  70. /* 延时1000ms */
  71. rt_thread_mdelay(1000);
  72. }
  73. // for (;;);
  74. return ret;
  75. }
  76. /* 导出到 msh 命令列表中 */
  77. MSH_CMD_EXPORT(cdc_sample, usbd cdc sample);
  78. #endif
  79. #if defined(RT_USB_DEVICE_MSTORAGE)
  80. /* F4A0 only FS can used with spi flash */
  81. #if ((defined(HC32F4A0) || defined(HC32F4A8)) && defined(BSP_USING_USBFS)) || \
  82. defined(HC32F460) || defined(HC32F472)
  83. /* Enable spibus1, SFUD, usb msc */
  84. /* menuconfig:
  85. 1. Hardware Drivers Config--->On-Chip Peripheral Driver--->Enable SPI BUS--->Enable SPI1 BUS
  86. 2. Hardware Drivers Config--->On-Chip Peripheral Driver--->Enable USB--->
  87. [*]Use USBFS Core
  88. Select USB Mode(USB Device Mode)
  89. [*]Enable VBUS Sensing for Device
  90. 3. RT-Thread Components--->Device Drivers--->Using SPI Bus/Device device drivers
  91. [*]Using Serial Flash Universal Driver
  92. [*]Using auto probe flash JEDEC SFDP parameters
  93. [*]Using defined supported flash chip information table
  94. (50000000)Default spi maximum speed(HZ)
  95. 4. RT-Thread Components--->Using USB legacy version
  96. [*]Using USB device--->
  97. Device type--->...Mass Storage device
  98. (spiflash)msc class disk name
  99. */
  100. #include "drv_gpio.h"
  101. #include "drv_spi.h"
  102. #include "dev_spi_flash_sfud.h"
  103. #define SPI_FLASH_CHIP RT_USB_MSTORAGE_DISK_NAME /* msc class disk name */
  104. #if defined(HC32F4A0) || defined(HC32F4A8)
  105. #define SPI_FLASH_SS_PORT GPIO_PORT_C
  106. #define SPI_FLASH_SS_PIN GPIO_PIN_07
  107. #define SPI_BUS_NAME "spi1"
  108. #define SPI_FLASH_DEVICE_NAME "spi10"
  109. #elif defined(HC32F460)
  110. #define SPI_FLASH_SS_PORT GPIO_PORT_C
  111. #define SPI_FLASH_SS_PIN GPIO_PIN_07
  112. #define SPI_BUS_NAME "spi3"
  113. #define SPI_FLASH_DEVICE_NAME "spi30"
  114. #elif defined(HC32F472)
  115. #define SPI_FLASH_SS_PORT GPIO_PORT_B
  116. #define SPI_FLASH_SS_PIN GPIO_PIN_12
  117. #define SPI_BUS_NAME "spi1"
  118. #define SPI_FLASH_DEVICE_NAME "spi10"
  119. #endif
  120. static void rt_hw_spi_flash_reset(char *spi_dev_name)
  121. {
  122. struct rt_spi_device *spi_dev_w25;
  123. rt_uint8_t w25_en_reset = 0x66;
  124. rt_uint8_t w25_reset_dev = 0x99;
  125. spi_dev_w25 = (struct rt_spi_device *)rt_device_find(spi_dev_name);
  126. if (!spi_dev_w25)
  127. {
  128. rt_kprintf("Can't find %s device!\n", spi_dev_name);
  129. }
  130. else
  131. {
  132. rt_spi_send(spi_dev_w25, &w25_en_reset, 1U);
  133. rt_spi_send(spi_dev_w25, &w25_reset_dev, 1U);
  134. DDL_DelayMS(1U);
  135. rt_kprintf("Reset ext flash!\n");
  136. }
  137. }
  138. static int rt_hw_spi_flash_with_sfud_init(void)
  139. {
  140. #if defined(HC32F4A0) || defined(HC32F460) || defined(HC32F4A8)
  141. rt_hw_spi_device_attach(SPI_BUS_NAME, SPI_FLASH_DEVICE_NAME, GET_PIN(C, 7));
  142. #elif defined(HC32F472)
  143. rt_hw_spi_device_attach(SPI_BUS_NAME, SPI_FLASH_DEVICE_NAME, GET_PIN(B, 12));
  144. #endif
  145. if (RT_NULL == rt_sfud_flash_probe(SPI_FLASH_CHIP, SPI_FLASH_DEVICE_NAME))
  146. {
  147. rt_hw_spi_flash_reset(SPI_FLASH_DEVICE_NAME);
  148. if (RT_NULL == rt_sfud_flash_probe(SPI_FLASH_CHIP, SPI_FLASH_DEVICE_NAME))
  149. {
  150. return -RT_ERROR;
  151. }
  152. }
  153. return RT_EOK;
  154. }
  155. INIT_COMPONENT_EXPORT(rt_hw_spi_flash_with_sfud_init);
  156. #endif
  157. #endif
  158. #ifdef RT_USB_DEVICE_HID
  159. #include "drv_gpio.h"
  160. /* menuconfig:
  161. 1. Hardware Drivers Config--->On-Chip Peripheral Driver--->Enable USB--->
  162. [*]Use USBFS Core
  163. Select USB Mode(USB Device Mode)
  164. [*]Enable VBUS Sensing for Device
  165. 2. RT-Thread Components--->
  166. Using USB legacy version--->
  167. Using USB device--->Device type--->
  168. [*]Enable to use device as HID device
  169. */
  170. /*
  171. * 程序清单:这是一个 usb hid device 设备使用例程
  172. * 例程导出了 hid_sample 命令到控制终端
  173. * 命令调用格式:hid_sample
  174. * 程序功能:首先会打印str_write[0]字符串内容,然后按下按键WKUP,hid设备将发送按键keyn,n是按下次数,可
  175. * 通过bus hound查看数据。
  176. * 发送内容可在Finsh串口显示。
  177. */
  178. #define USBD_DEV_NAME "hidd" /* 名称 */
  179. #if defined(HC32F4A0) || defined(HC32F4A8)
  180. #define KEY_PIN_NUM GET_PIN(A,0) /* PA0 */
  181. #elif defined(HC32F460)
  182. #define KEY_PIN_NUM GET_PIN(B,1) /* PB1 */
  183. #elif defined(HC32F472)
  184. #define KEY_PIN_NUM GET_PIN(B,5) /* PB5 */
  185. #endif
  186. static int hid_sample(void)
  187. {
  188. rt_err_t ret = RT_EOK;
  189. rt_device_t hid_dev = RT_NULL; /* usb device设备句柄 */
  190. char str_write[2][5] = {"test", "Key0"};
  191. /* 查找设备 */
  192. hid_dev = rt_device_find(USBD_DEV_NAME);
  193. if (hid_dev == RT_NULL)
  194. {
  195. rt_kprintf("hid sample run failed! can't find %s device!\n", USBD_DEV_NAME);
  196. return -RT_ERROR;
  197. }
  198. /* 以收中断方式打开设备 */
  199. ret = rt_device_open(hid_dev, RT_DEVICE_OFLAG_RDWR);
  200. if (ret != RT_EOK)
  201. {
  202. rt_kprintf("open %s device failed!\n", USBD_DEV_NAME);
  203. return ret;
  204. }
  205. rt_kprintf("This is a usb hid device test!\r\n");
  206. rt_device_write(hid_dev, 0, str_write[0], sizeof(str_write[0]));
  207. rt_pin_mode(KEY_PIN_NUM, PIN_MODE_INPUT);
  208. for (;;)
  209. {
  210. rt_thread_mdelay(200);
  211. if (PIN_LOW == rt_pin_read(KEY_PIN_NUM))
  212. {
  213. rt_device_write(hid_dev, 0, str_write[1], sizeof(str_write[1]));
  214. str_write[1][3] += 0x01;
  215. }
  216. }
  217. //return ret;
  218. }
  219. /* 导出到 msh 命令列表中 */
  220. MSH_CMD_EXPORT(hid_sample, usbd hid sample);
  221. #endif
  222. #ifdef RT_USB_DEVICE_WINUSB
  223. /* menuconfig:
  224. 1. Hardware Drivers Config--->On-Chip Peripheral Driver--->Enable USB--->
  225. [*]Use USBFS Core
  226. Select USB Mode(USB Device Mode)
  227. [*]Enable VBUS Sensing for Device
  228. 2. RT-Thread Components--->
  229. Using USB legacy version--->
  230. Using USB device--->Device type--->
  231. [*]Enable to use device as winusb device
  232. */
  233. /*
  234. * 程序清单:这是一个 usb WINUSB device 设备使用例程
  235. * RTT 的WINUSB Windows无法免驱,需要使用zadig安装winusb驱动程序(如设备管理器-通用串行总线设备-RTT Win USB已识别则不需要安装)。
  236. * 例程导出了 winusb_sample 命令到控制终端
  237. * 命令调用格式:winusb_sample
  238. * 软件:llcom.exe
  239. * 程序功能:MSH命令发送winusb_sample,运行测试程序。
  240. * 打开llcom.exe软件,选择小工具-WinUSB设备-选择对应RTT Win USB设备-打开-勾选Hex发送-发送数据(注意:每次发送数据长度为4的整数倍)。
  241. * 通过llcom.exe可发送bulk数据(100字符以内)到设备,设备收到后会回发给主机(llcom.exe),同时通过MSH终端显示收到的HEX数据。
  242. * 注意:1、llcom.exe中的GUID与驱动程序中设定保持一致(通过设备管理器选择RTT Win USB设备的属性来查看);
  243. * 2、win_usb_read()函数中的UIO_REQUEST_READ_FULL改为UIO_REQUEST_READ_BEST,实现数据即读即取;
  244. * 否则需要接满传入的size数量,才会回调接收函数。
  245. *
  246. */
  247. #define WINUSB_DEV_NAME "winusb" /* 名称 */
  248. uint8_t str_read[100];
  249. static rt_err_t winusb_rx_handle(rt_device_t dev, rt_size_t size)
  250. {
  251. uint8_t i;
  252. /* 读取定时器当前值 */
  253. rt_kprintf("Rx:");
  254. for (i = 0; i < size; i++)
  255. {
  256. rt_kprintf("%x", str_read[i]);
  257. }
  258. rt_kprintf("\r\n");
  259. rt_device_write(dev, 0, str_read, size);
  260. /* prepare read config */
  261. rt_device_read(dev, 0, str_read, sizeof(str_read));
  262. return RT_EOK;
  263. }
  264. static int winusb_sample(void)
  265. {
  266. rt_err_t ret = RT_EOK;
  267. rt_device_t winusb_dev = RT_NULL; /* usb device设备句柄 */
  268. /* 查找设备 */
  269. winusb_dev = rt_device_find(WINUSB_DEV_NAME);
  270. if (winusb_dev == RT_NULL)
  271. {
  272. rt_kprintf("winusb sample run failed! can't find %s device!\n", WINUSB_DEV_NAME);
  273. return -RT_ERROR;
  274. }
  275. /* 以读写方式打开设备 */
  276. ret = rt_device_open(winusb_dev, RT_DEVICE_OFLAG_RDWR);
  277. if (ret != RT_EOK)
  278. {
  279. rt_kprintf("open %s device failed!\n", WINUSB_DEV_NAME);
  280. return ret;
  281. }
  282. rt_kprintf("Found and open success %s device!\n", WINUSB_DEV_NAME);
  283. ret = rt_device_set_rx_indicate(winusb_dev, winusb_rx_handle);
  284. if (ret == RT_EOK)
  285. {
  286. /* prepare read config,set once,read once, */
  287. rt_device_read(winusb_dev, 0, str_read, sizeof(str_read));
  288. }
  289. return ret;
  290. }
  291. /* 导出到 msh 命令列表中 */
  292. MSH_CMD_EXPORT(winusb_sample, usbd winusb sample);
  293. #endif