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