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