drv_usbd.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2021-02-24 klcheng First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #ifdef BSP_USING_USBD
  14. #include <rtthread.h>
  15. #include <rtdevice.h>
  16. #include <string.h>
  17. #include "NuMicro.h"
  18. #define LOG_TAG "drv.usbd"
  19. #define DBG_ENABLE
  20. #define DBG_SECTION_NAME "drv.usbd"
  21. #define DBG_LEVEL DBG_ERROR
  22. #define DBG_COLOR
  23. #include <rtdbg.h>
  24. /* Private define ---------------------------------------------------------------*/
  25. /* Define EP maximum packet size */
  26. #define EP0_MAX_PKT_SIZE 64
  27. #define EP1_MAX_PKT_SIZE EP0_MAX_PKT_SIZE /* EP0 and EP1 are assigned the same size for control endpoint */
  28. #define EP2_MAX_PKT_SIZE 64
  29. #define EP3_MAX_PKT_SIZE 64
  30. #define EP4_MAX_PKT_SIZE 64
  31. #define EP5_MAX_PKT_SIZE 64
  32. #define EP6_MAX_PKT_SIZE 64
  33. #define EP7_MAX_PKT_SIZE 64
  34. #define SETUP_BUF_BASE 0
  35. #define SETUP_BUF_LEN 8
  36. #define EP0_BUF_BASE (SETUP_BUF_BASE + SETUP_BUF_LEN)
  37. #define EP0_BUF_LEN EP0_MAX_PKT_SIZE
  38. #define EP1_BUF_BASE (SETUP_BUF_BASE + SETUP_BUF_LEN)
  39. #define EP1_BUF_LEN EP1_MAX_PKT_SIZE
  40. #define EP2_BUF_BASE (EP1_BUF_BASE + EP1_BUF_LEN)
  41. #define EP2_BUF_LEN EP2_MAX_PKT_SIZE
  42. #define EP3_BUF_BASE (EP2_BUF_BASE + EP2_BUF_LEN)
  43. #define EP3_BUF_LEN EP3_MAX_PKT_SIZE
  44. #define EP4_BUF_BASE (EP3_BUF_BASE + EP3_BUF_LEN)
  45. #define EP4_BUF_LEN EP4_MAX_PKT_SIZE
  46. #define EP5_BUF_BASE (EP4_BUF_BASE + EP4_BUF_LEN)
  47. #define EP5_BUF_LEN EP5_MAX_PKT_SIZE
  48. #define EP6_BUF_BASE (EP5_BUF_BASE + EP5_BUF_LEN)
  49. #define EP6_BUF_LEN EP6_MAX_PKT_SIZE
  50. #define EP7_BUF_BASE (EP6_BUF_BASE + EP6_BUF_LEN)
  51. #define EP7_BUF_LEN EP7_MAX_PKT_SIZE
  52. #define EPADR_SW2HW(address) ((((address & USB_EPNO_MASK) * 2) + (!(address & USB_DIR_IN))))
  53. #define EPADR_HW2SW(address) ((address & USB_EPNO_MASK) / 2)
  54. /* Private typedef --------------------------------------------------------------*/
  55. typedef struct _nu_usbd_t
  56. {
  57. USBD_T *Instance; /* REG base */
  58. uint8_t address_tmp; /* Keep assigned address for flow control */
  59. } nu_usbd_t;
  60. /* Private variables ------------------------------------------------------------*/
  61. static nu_usbd_t nu_usbd =
  62. {
  63. .Instance = USBD,
  64. .address_tmp = 0,
  65. };
  66. static struct udcd _rt_obj_udc;
  67. static struct ep_id _ep_pool[] =
  68. {
  69. {EPADR_HW2SW(EP0), USB_EP_ATTR_CONTROL, USB_DIR_INOUT, EP0_MAX_PKT_SIZE, ID_ASSIGNED },
  70. {EPADR_HW2SW(EP2), USB_EP_ATTR_BULK, USB_DIR_IN, EP2_MAX_PKT_SIZE, ID_UNASSIGNED},
  71. {EPADR_HW2SW(EP3), USB_EP_ATTR_BULK, USB_DIR_OUT, EP3_MAX_PKT_SIZE, ID_UNASSIGNED},
  72. {EPADR_HW2SW(EP4), USB_EP_ATTR_INT, USB_DIR_IN, EP4_MAX_PKT_SIZE, ID_UNASSIGNED},
  73. {EPADR_HW2SW(EP5), USB_EP_ATTR_INT, USB_DIR_OUT, EP5_MAX_PKT_SIZE, ID_UNASSIGNED},
  74. {EPADR_HW2SW(EP6), USB_EP_ATTR_BULK, USB_DIR_IN, EP6_MAX_PKT_SIZE, ID_UNASSIGNED},
  75. {EPADR_HW2SW(EP7), USB_EP_ATTR_BULK, USB_DIR_OUT, EP7_MAX_PKT_SIZE, ID_UNASSIGNED},
  76. {0xFF, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 0, ID_ASSIGNED },
  77. };
  78. static void _nu_ep_partition(void)
  79. {
  80. /* Init setup packet buffer */
  81. /* Buffer range for setup packet -> [0 ~ 0x7] */
  82. USBD->STBUFSEG = SETUP_BUF_BASE;
  83. /*****************************************************/
  84. /* EP0 ==> control IN endpoint, address 0 */
  85. USBD_CONFIG_EP(EP0, USBD_CFG_CSTALL | USBD_CFG_EPMODE_IN | EPADR_HW2SW(EP0));
  86. /* Buffer range for EP0 */
  87. USBD_SET_EP_BUF_ADDR(EP0, EP0_BUF_BASE);
  88. /* EP1 ==> control OUT endpoint, address 0 */
  89. USBD_CONFIG_EP(EP1, USBD_CFG_CSTALL | USBD_CFG_EPMODE_OUT | EPADR_HW2SW(EP1));
  90. /* Buffer range for EP1 */
  91. USBD_SET_EP_BUF_ADDR(EP1, EP1_BUF_BASE);
  92. /*****************************************************/
  93. /* EP2 ==> Bulk IN endpoint, address 1 */
  94. USBD_CONFIG_EP(EP2, USBD_CFG_EPMODE_IN | EPADR_HW2SW(EP2));
  95. /* Buffer range for EP2 */
  96. USBD_SET_EP_BUF_ADDR(EP2, EP2_BUF_BASE);
  97. /* EP3 ==> Bulk OUT endpoint, address 1 */
  98. USBD_CONFIG_EP(EP3, USBD_CFG_EPMODE_OUT | EPADR_HW2SW(EP3));
  99. /* Buffer range for EP3 */
  100. USBD_SET_EP_BUF_ADDR(EP3, EP3_BUF_BASE);
  101. /*****************************************************/
  102. /* EP4 ==> Interrupt IN endpoint, address 2 */
  103. USBD_CONFIG_EP(EP4, USBD_CFG_EPMODE_IN | EPADR_HW2SW(EP4));
  104. /* Buffer range for EP4 */
  105. USBD_SET_EP_BUF_ADDR(EP4, EP4_BUF_BASE);
  106. /* EP5 ==> Interrupt Out endpoint, address 2 */
  107. USBD_CONFIG_EP(EP5, USBD_CFG_EPMODE_OUT | EPADR_HW2SW(EP5));
  108. /* Buffer range for EP5 */
  109. USBD_SET_EP_BUF_ADDR(EP5, EP5_BUF_BASE);
  110. /*****************************************************/
  111. /* EP6 ==> Bulk IN endpoint, address 3 */
  112. USBD_CONFIG_EP(EP6, USBD_CFG_EPMODE_IN | EPADR_HW2SW(EP6));
  113. /* Buffer range for EP4 */
  114. USBD_SET_EP_BUF_ADDR(EP6, EP6_BUF_BASE);
  115. /* EP7 ==> Bulk Out endpoint, address 3 */
  116. USBD_CONFIG_EP(EP7, USBD_CFG_EPMODE_OUT | EPADR_HW2SW(EP7));
  117. /* Buffer range for EP5 */
  118. USBD_SET_EP_BUF_ADDR(EP7, EP7_BUF_BASE);
  119. }
  120. static rt_err_t _ep_set_stall(rt_uint8_t address)
  121. {
  122. USBD_SET_EP_STALL(EPADR_SW2HW(address));
  123. return RT_EOK;
  124. }
  125. static rt_err_t _ep_clear_stall(rt_uint8_t address)
  126. {
  127. USBD_ClearStall(EPADR_SW2HW(address));
  128. return RT_EOK;
  129. }
  130. static rt_err_t _set_address(rt_uint8_t address)
  131. {
  132. if (0 != address)
  133. {
  134. nu_usbd.address_tmp = address;
  135. }
  136. return RT_EOK;
  137. }
  138. static rt_err_t _set_config(rt_uint8_t address)
  139. {
  140. return RT_EOK;
  141. }
  142. static rt_err_t _ep_enable(uep_t ep)
  143. {
  144. RT_ASSERT(ep != RT_NULL);
  145. RT_ASSERT(ep->ep_desc != RT_NULL);
  146. USBD_CONFIG_EP(EPADR_SW2HW(EP_ADDRESS(ep)),
  147. USBD_CFG_CSTALL
  148. | ((EP_ADDRESS(ep) & USB_DIR_IN) ? USBD_CFG_EPMODE_IN : USBD_CFG_EPMODE_OUT)
  149. | (EP_ADDRESS(ep) & USB_EPNO_MASK));
  150. return RT_EOK;
  151. }
  152. static rt_err_t _ep_disable(uep_t ep)
  153. {
  154. RT_ASSERT(ep != RT_NULL);
  155. RT_ASSERT(ep->ep_desc != RT_NULL);
  156. USBD_CONFIG_EP(EPADR_SW2HW(EP_ADDRESS(ep)), USBD_CFG_EPMODE_DISABLE);
  157. return RT_EOK;
  158. }
  159. static rt_size_t _ep_read(rt_uint8_t address, void *buffer)
  160. {
  161. rt_size_t size = 0;
  162. rt_uint8_t *buf;
  163. rt_uint32_t hw_ep_num = EPADR_SW2HW(address);
  164. RT_ASSERT(!(address & USB_DIR_IN));
  165. RT_ASSERT(buffer != RT_NULL);
  166. size = USBD_GET_PAYLOAD_LEN(hw_ep_num);
  167. buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(hw_ep_num));
  168. USBD_MemCopy(buffer, (uint8_t *)buf, size);
  169. return size;
  170. }
  171. static rt_size_t _ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size)
  172. {
  173. RT_ASSERT(!(address & USB_DIR_IN));
  174. USBD_SET_PAYLOAD_LEN(EPADR_SW2HW(address), size);
  175. return size;
  176. }
  177. static rt_size_t _ep_write(rt_uint8_t address, void *buffer, rt_size_t size)
  178. {
  179. RT_ASSERT((address & USB_DIR_IN));
  180. /* even number is for IN endpoint */
  181. rt_uint32_t hw_ep_num = EPADR_SW2HW(address);
  182. uint8_t *buf;
  183. buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(hw_ep_num));
  184. USBD_MemCopy(buf, (uint8_t *)buffer, size);
  185. USBD_SET_PAYLOAD_LEN(hw_ep_num, size);
  186. return size;
  187. }
  188. static rt_err_t _ep0_send_status(void)
  189. {
  190. /* Status stage */
  191. USBD_SET_DATA1(EP0);
  192. USBD_SET_PAYLOAD_LEN(EP0, 0);
  193. return RT_EOK;
  194. }
  195. static rt_err_t _suspend(void)
  196. {
  197. return RT_EOK;
  198. }
  199. static rt_err_t _wakeup(void)
  200. {
  201. return RT_EOK;
  202. }
  203. __STATIC_INLINE void _USBD_IRQHandler(void)
  204. {
  205. rt_uint32_t u32IntSts = USBD_GET_INT_FLAG();
  206. rt_uint32_t u32State = USBD_GET_BUS_STATE();
  207. //------------------------------------------------------------------
  208. if (u32IntSts & USBD_INTSTS_VBDETIF_Msk)
  209. {
  210. // Floating detect
  211. USBD_CLR_INT_FLAG(USBD_INTSTS_VBDETIF_Msk);
  212. if (USBD_IS_ATTACHED())
  213. {
  214. /* USB Plug In */
  215. USBD_ENABLE_USB();
  216. rt_usbd_connect_handler(&_rt_obj_udc);
  217. }
  218. else
  219. {
  220. /* USB Unplug */
  221. USBD_DISABLE_USB();
  222. rt_usbd_disconnect_handler(&_rt_obj_udc);
  223. }
  224. }
  225. if (u32IntSts & USBD_INTSTS_SOFIF_Msk)
  226. {
  227. USBD_CLR_INT_FLAG(USBD_INTSTS_SOFIF_Msk);
  228. rt_usbd_sof_handler(&_rt_obj_udc);
  229. }
  230. //------------------------------------------------------------------
  231. if (u32IntSts & USBD_INTSTS_BUSIF_Msk)
  232. {
  233. /* Clear event flag */
  234. USBD_CLR_INT_FLAG(USBD_INTSTS_BUSIF_Msk);
  235. if (u32State & USBD_ATTR_USBRST_Msk)
  236. {
  237. USBD_ENABLE_USB();
  238. /* Reset PID DATA0 */
  239. for (rt_uint32_t i = 0ul; i < USBD_MAX_EP; i++)
  240. {
  241. nu_usbd.Instance->EP[i].CFG &= ~USBD_CFG_DSQSYNC_Msk;
  242. }
  243. /* Reset USB device address */
  244. USBD_SET_ADDR(0ul);
  245. /* Bus reset */
  246. rt_usbd_reset_handler(&_rt_obj_udc);
  247. }
  248. if (u32State & USBD_ATTR_SUSPEND_Msk)
  249. {
  250. /* Enable USB but disable PHY */
  251. USBD_DISABLE_PHY();
  252. }
  253. if (u32State & USBD_ATTR_RESUME_Msk)
  254. {
  255. /* Enable USB and enable PHY */
  256. USBD_ENABLE_USB();
  257. }
  258. }
  259. //------------------------------------------------------------------
  260. if (u32IntSts & USBD_INTSTS_WAKEUP)
  261. {
  262. /* Clear event flag */
  263. USBD_CLR_INT_FLAG(USBD_INTSTS_WAKEUP);
  264. USBD_ENABLE_USB();
  265. }
  266. if (u32IntSts & USBD_INTSTS_USBIF_Msk)
  267. {
  268. // USB event
  269. if (u32IntSts & USBD_INTSTS_SETUP_Msk)
  270. {
  271. // Setup packet
  272. /* Clear event flag */
  273. USBD_CLR_INT_FLAG(USBD_INTSTS_SETUP_Msk);
  274. /* Clear the data IN/OUT ready flag of control end-points */
  275. USBD_STOP_TRANSACTION(EP0);
  276. USBD_STOP_TRANSACTION(EP1);
  277. USBD_SET_DATA1(EP0);
  278. rt_usbd_ep0_setup_handler(&_rt_obj_udc, (struct urequest *)USBD_BUF_BASE);
  279. }
  280. // EP events
  281. if (u32IntSts & USBD_INTSTS_EP0)
  282. {
  283. /* Clear event flag */
  284. USBD_CLR_INT_FLAG(USBD_INTSTS_EP0);
  285. if ((USBD_GET_ADDR() == 0)
  286. && (nu_usbd.address_tmp)
  287. )
  288. {
  289. USBD_SET_ADDR(nu_usbd.address_tmp);
  290. LOG_I("SET ADDR: 0x%02x", nu_usbd.address_tmp);
  291. nu_usbd.address_tmp = 0;
  292. }
  293. rt_usbd_ep0_in_handler(&_rt_obj_udc);
  294. }
  295. if (u32IntSts & USBD_INTSTS_EP1)
  296. {
  297. /* Clear event flag */
  298. USBD_CLR_INT_FLAG(USBD_INTSTS_EP1);
  299. rt_usbd_ep0_out_handler(&_rt_obj_udc, 0);
  300. }
  301. if (u32IntSts & USBD_INTSTS_EP2)
  302. {
  303. /* Clear event flag */
  304. USBD_CLR_INT_FLAG(USBD_INTSTS_EP2);
  305. rt_usbd_ep_in_handler(&_rt_obj_udc, USB_DIR_IN | EPADR_HW2SW(EP2), 0);
  306. }
  307. if (u32IntSts & USBD_INTSTS_EP3)
  308. {
  309. /* Clear event flag */
  310. USBD_CLR_INT_FLAG(USBD_INTSTS_EP3);
  311. rt_usbd_ep_out_handler(&_rt_obj_udc, USB_DIR_OUT | EPADR_HW2SW(EP3), 0);
  312. }
  313. if (u32IntSts & USBD_INTSTS_EP4)
  314. {
  315. /* Clear event flag */
  316. USBD_CLR_INT_FLAG(USBD_INTSTS_EP4);
  317. rt_usbd_ep_in_handler(&_rt_obj_udc, USB_DIR_IN | EPADR_HW2SW(EP4), 0);
  318. }
  319. if (u32IntSts & USBD_INTSTS_EP5)
  320. {
  321. /* Clear event flag */
  322. USBD_CLR_INT_FLAG(USBD_INTSTS_EP5);
  323. rt_usbd_ep_out_handler(&_rt_obj_udc, USB_DIR_OUT | EPADR_HW2SW(EP5), 0);
  324. }
  325. if (u32IntSts & USBD_INTSTS_EP6)
  326. {
  327. /* Clear event flag */
  328. USBD_CLR_INT_FLAG(USBD_INTSTS_EP6);
  329. rt_usbd_ep_in_handler(&_rt_obj_udc, USB_DIR_IN | EPADR_HW2SW(EP6), 0);
  330. }
  331. if (u32IntSts & USBD_INTSTS_EP7)
  332. {
  333. /* Clear event flag */
  334. USBD_CLR_INT_FLAG(USBD_INTSTS_EP7);
  335. rt_usbd_ep_out_handler(&_rt_obj_udc, USB_DIR_OUT | EPADR_HW2SW(EP7), 0);
  336. }
  337. }
  338. }
  339. void USBD_IRQHandler(void)
  340. {
  341. rt_interrupt_enter();
  342. _USBD_IRQHandler();
  343. rt_interrupt_leave();
  344. }
  345. static rt_err_t _init(rt_device_t device)
  346. {
  347. nu_usbd_t *nu_usbd = (nu_usbd_t *)device->user_data;
  348. /* Initialize USB PHY */
  349. SYS_UnlockReg();
  350. /* Select USBD */
  351. SYS_ResetModule(USBD_RST);
  352. SYS_LockReg();
  353. _nu_ep_partition();
  354. /* Initial USB engine */
  355. nu_usbd->Instance->ATTR = 0x6D0ul;
  356. /* Force SE0 */
  357. USBD_SET_SE0();
  358. NVIC_EnableIRQ(USBD_IRQn);
  359. USBD_Start();
  360. return RT_EOK;
  361. }
  362. const static struct udcd_ops _udc_ops =
  363. {
  364. _set_address,
  365. _set_config,
  366. _ep_set_stall,
  367. _ep_clear_stall,
  368. _ep_enable,
  369. _ep_disable,
  370. _ep_read_prepare,
  371. _ep_read,
  372. _ep_write,
  373. _ep0_send_status,
  374. _suspend,
  375. _wakeup,
  376. };
  377. #ifdef RT_USING_DEVICE_OPS
  378. const static struct rt_device_ops _ops =
  379. {
  380. _init,
  381. RT_NULL,
  382. RT_NULL,
  383. RT_NULL,
  384. RT_NULL,
  385. RT_NULL,
  386. };
  387. #endif
  388. int nu_usbd_register(void)
  389. {
  390. if (RT_NULL != rt_device_find("usbd"))
  391. {
  392. LOG_E("\nUSBD Register failed. Another USBD device registered\n");
  393. return -RT_ERROR;
  394. }
  395. rt_memset((void *)&_rt_obj_udc, 0, sizeof(struct udcd));
  396. _rt_obj_udc.parent.type = RT_Device_Class_USBDevice;
  397. #ifdef RT_USING_DEVICE_OPS
  398. _rt_obj_udc.parent.ops = &_ops;
  399. #else
  400. _rt_obj_udc.parent.init = _init;
  401. #endif
  402. _rt_obj_udc.parent.user_data = &nu_usbd;
  403. _rt_obj_udc.ops = &_udc_ops;
  404. /* Register endpoint information */
  405. _rt_obj_udc.ep_pool = _ep_pool;
  406. _rt_obj_udc.ep0.id = &_ep_pool[0];
  407. _rt_obj_udc.device_is_hs = RT_FALSE; /* Support Full-Speed only */
  408. rt_device_register((rt_device_t)&_rt_obj_udc, "usbd", 0);
  409. rt_usb_device_init();
  410. return RT_EOK;
  411. }
  412. INIT_DEVICE_EXPORT(nu_usbd_register);
  413. #endif