@@ -396,12 +396,53 @@ static void numaker_usbd_hw_shutdown(const struct device *dev)
396396 SYS_LockReg ();
397397}
398398
399+ /* Interrupt top half processing for vbus plug */
400+ static void numaker_usbd_vbus_plug_th (const struct device * dev )
401+ {
402+ const struct udc_numaker_config * config = dev -> config ;
403+ USBD_T * base = config -> base ;
404+
405+ /* Enable back USB/PHY */
406+ base -> ATTR |= USBD_ATTR_USBEN_Msk | USBD_ATTR_PHYEN_Msk ;
407+
408+ /* UDC stack would handle bottom-half processing */
409+ udc_submit_event (dev , UDC_EVT_VBUS_READY , 0 );
410+
411+ LOG_DBG ("USB plug-in" );
412+ }
413+
414+ /* Interrupt top half processing for vbus unplug */
415+ static void numaker_usbd_vbus_unplug_th (const struct device * dev )
416+ {
417+ const struct udc_numaker_config * config = dev -> config ;
418+ USBD_T * base = config -> base ;
419+
420+ /* Disable USB */
421+ base -> ATTR &= ~USBD_USB_EN ;
422+
423+ /* UDC stack would handle bottom-half processing */
424+ udc_submit_event (dev , UDC_EVT_VBUS_REMOVED , 0 );
425+
426+ LOG_DBG ("USB unplug" );
427+ }
428+
429+ /* Interrupt top half processing for bus wakeup */
430+ static void numaker_usbd_bus_wakeup_th (const struct device * dev )
431+ {
432+ LOG_DBG ("USB wake-up" );
433+ }
434+
399435/* Interrupt top half processing for bus reset */
400436static void numaker_usbd_bus_reset_th (const struct device * dev )
401437{
438+ const struct udc_numaker_config * config = dev -> config ;
439+ USBD_T * base = config -> base ;
402440 struct udc_numaker_data * priv = udc_get_private (dev );
403441 USBD_EP_T * ep_base ;
404442
443+ /* Enable back USB/PHY */
444+ base -> ATTR |= USBD_ATTR_USBEN_Msk | USBD_ATTR_PHYEN_Msk ;
445+
405446 for (uint32_t i = 0ul ; i < priv -> ep_pool_size ; i ++ ) {
406447 ep_base = numaker_usbd_ep_base (dev , EP0 + i );
407448
@@ -421,6 +462,128 @@ static void numaker_usbd_bus_reset_th(const struct device *dev)
421462 }
422463
423464 numaker_usbd_reset_addr (dev );
465+
466+ /* UDC stack would handle bottom-half processing,
467+ * including reset device address (udc_set_address),
468+ * un-configure device (udc_ep_disable), etc.
469+ */
470+ udc_submit_event (dev , UDC_EVT_RESET , 0 );
471+
472+ LOG_DBG ("USB reset" );
473+ }
474+
475+ /* Interrupt top half processing for bus suspend */
476+ static void numaker_usbd_bus_suspend_th (const struct device * dev )
477+ {
478+ const struct udc_numaker_config * config = dev -> config ;
479+ USBD_T * base = config -> base ;
480+
481+ /* Enable USB but disable PHY */
482+ base -> ATTR &= ~USBD_PHY_EN ;
483+
484+ /* UDC stack would handle bottom-half processing */
485+ udc_submit_event (dev , UDC_EVT_SUSPEND , 0 );
486+
487+ LOG_DBG ("USB suspend" );
488+ }
489+
490+ /* Interrupt top half processing for bus resume */
491+ static void numaker_usbd_bus_resume_th (const struct device * dev )
492+ {
493+ const struct udc_numaker_config * config = dev -> config ;
494+ USBD_T * base = config -> base ;
495+
496+ /* Enable back USB/PHY */
497+ base -> ATTR |= USBD_ATTR_USBEN_Msk | USBD_ATTR_PHYEN_Msk ;
498+
499+ /* UDC stack would handle bottom-half processing */
500+ udc_submit_event (dev , UDC_EVT_RESUME , 0 );
501+
502+ LOG_DBG ("USB resume" );
503+ }
504+
505+ /* Interrupt top half processing for SOF */
506+ static void numaker_usbd_sof_th (const struct device * dev )
507+ {
508+ /* UDC stack would handle bottom-half processing */
509+ udc_submit_sof_event (dev );
510+ }
511+
512+ static void numaker_usbd_setup_copy_to_user (const struct device * dev , uint8_t * usrbuf );
513+
514+ /* Interrupt top half processing for Setup packet */
515+ static void numaker_usbd_setup_th (const struct device * dev )
516+ {
517+ USBD_EP_T * ep0_base = numaker_usbd_ep_base (dev , EP0 );
518+ USBD_EP_T * ep1_base = numaker_usbd_ep_base (dev , EP1 );
519+ struct numaker_usbd_msg msg = {0 };
520+
521+ /* Clear the data IN/OUT ready flag of control endpoints */
522+ ep0_base -> CFGP |= USBD_CFGP_CLRRDY_Msk ;
523+ ep1_base -> CFGP |= USBD_CFGP_CLRRDY_Msk ;
524+
525+ /* By USB spec, following transactions, regardless of Data/Status stage,
526+ * will always be DATA1
527+ */
528+ ep0_base -> CFG |= USBD_CFG_DSQSYNC_Msk ;
529+ ep1_base -> CFG |= USBD_CFG_DSQSYNC_Msk ;
530+
531+ /* Message for bottom-half processing */
532+ /* NOTE: In Zephyr USB device stack, Setup packet is passed via
533+ * CTRL OUT EP
534+ */
535+ msg .type = NUMAKER_USBD_MSG_TYPE_SETUP ;
536+ numaker_usbd_setup_copy_to_user (dev , msg .setup .packet );
537+ numaker_usbd_send_msg (dev , & msg );
538+ }
539+
540+ /* Interrupt top half processing for EP (excluding Setup) */
541+ static void numaker_usbd_ep_th (const struct device * dev , uint32_t ep_hw_idx )
542+ {
543+ struct udc_numaker_data * priv = udc_get_private (dev );
544+ USBD_EP_T * ep_base = numaker_usbd_ep_base (dev , ep_hw_idx );
545+ uint8_t ep_dir ;
546+ uint8_t ep_idx ;
547+ uint8_t ep ;
548+ struct numaker_usbd_msg msg = {0 };
549+
550+ /* We don't enable INNAKEN interrupt, so as long as EP event occurs,
551+ * we can just regard one data transaction has completed (ACK for
552+ * CTRL/BULK/INT or no-ACK for Iso), that is, no need to check EPSTS0,
553+ * EPSTS1, etc.
554+ */
555+
556+ /* EP direction, number, and address */
557+ ep_dir = ((ep_base -> CFG & USBD_CFG_STATE_Msk ) == USBD_CFG_EPMODE_IN ) ? USB_EP_DIR_IN
558+ : USB_EP_DIR_OUT ;
559+ ep_idx = (ep_base -> CFG & USBD_CFG_EPNUM_Msk ) >> USBD_CFG_EPNUM_Pos ;
560+ ep = USB_EP_GET_ADDR (ep_idx , ep_dir );
561+
562+ /* NOTE: See comment in udc_numaker_set_address()'s implementation
563+ * for safe place to change USB device address
564+ */
565+ if (ep == USB_EP_GET_ADDR (0 , USB_EP_DIR_IN )) {
566+ numaker_usbd_set_addr (dev );
567+ }
568+
569+ /* NOTE: See comment on mxpld_ctrlout for why make one copy of
570+ * CTRL OUT's MXPLD
571+ */
572+ if (ep == USB_EP_GET_ADDR (0 , USB_EP_DIR_OUT )) {
573+ struct numaker_usbd_ep * ep_ctrlout = priv -> ep_pool + 0 ;
574+
575+ ep_ctrlout -> mxpld_ctrlout = ep_base -> MXPLD ;
576+ }
577+
578+ /* Message for bottom-half processing */
579+ if (USB_EP_DIR_IS_OUT (ep )) {
580+ msg .type = NUMAKER_USBD_MSG_TYPE_OUT ;
581+ msg .out .ep = ep ;
582+ } else {
583+ msg .type = NUMAKER_USBD_MSG_TYPE_IN ;
584+ msg .in .ep = ep ;
585+ }
586+ numaker_usbd_send_msg (dev , & msg );
424587}
425588
426589/* USBD SRAM base for DMA */
@@ -1209,11 +1372,7 @@ static void numaker_usbd_msg_handler(const struct device *dev)
12091372static void numaker_usbd_isr (const struct device * dev )
12101373{
12111374 const struct udc_numaker_config * config = dev -> config ;
1212- struct udc_numaker_data * priv = udc_get_private (dev );
12131375 USBD_T * const base = config -> base ;
1214-
1215- struct numaker_usbd_msg msg = {0 };
1216-
12171376 uint32_t usbd_intsts = base -> INTSTS ;
12181377 uint32_t usbd_bus_state = base -> ATTR ;
12191378
@@ -1232,75 +1391,39 @@ static void numaker_usbd_isr(const struct device *dev)
12321391 if (usbd_intsts & USBD_INTSTS_FLDET ) {
12331392 if (base -> VBUSDET & USBD_VBUSDET_VBUSDET_Msk ) {
12341393 /* USB plug-in */
1235-
1236- /* Enable back USB/PHY */
1237- base -> ATTR |= USBD_ATTR_USBEN_Msk | USBD_ATTR_PHYEN_Msk ;
1238-
1239- /* UDC stack would handle bottom-half processing */
1240- udc_submit_event (dev , UDC_EVT_VBUS_READY , 0 );
1241-
1242- LOG_DBG ("USB plug-in" );
1394+ numaker_usbd_vbus_plug_th (dev );
12431395 } else {
12441396 /* USB unplug */
1245-
1246- /* Disable USB */
1247- base -> ATTR &= ~USBD_USB_EN ;
1248-
1249- /* UDC stack would handle bottom-half processing */
1250- udc_submit_event (dev , UDC_EVT_VBUS_REMOVED , 0 );
1251-
1252- LOG_DBG ("USB unplug" );
1397+ numaker_usbd_vbus_unplug_th (dev );
12531398 }
12541399 }
12551400
12561401 /* USB wake-up */
12571402 if (usbd_intsts & USBD_INTSTS_WAKEUP ) {
1258- LOG_DBG ( "USB wake-up" );
1403+ numaker_usbd_bus_wakeup_th ( dev );
12591404 }
12601405
12611406 /* USB reset/suspend/resume */
12621407 if (usbd_intsts & USBD_INTSTS_BUS ) {
1408+ /* Bus reset */
12631409 if (usbd_bus_state & USBD_STATE_USBRST ) {
1264- /* Bus reset */
1265-
1266- /* Enable back USB/PHY */
1267- base -> ATTR |= USBD_ATTR_USBEN_Msk | USBD_ATTR_PHYEN_Msk ;
1268-
1269- /* Bus reset top half */
12701410 numaker_usbd_bus_reset_th (dev );
1271-
1272- /* UDC stack would handle bottom-half processing,
1273- * including reset device address (udc_set_address),
1274- * un-configure device (udc_ep_disable), etc.
1275- */
1276- udc_submit_event (dev , UDC_EVT_RESET , 0 );
1277-
1278- LOG_DBG ("USB reset" );
12791411 }
1280- if (usbd_bus_state & USBD_STATE_SUSPEND ) {
1281- /* Enable USB but disable PHY */
1282- base -> ATTR &= ~USBD_PHY_EN ;
1283-
1284- /* UDC stack would handle bottom-half processing */
1285- udc_submit_event (dev , UDC_EVT_SUSPEND , 0 );
12861412
1287- LOG_DBG ("USB suspend" );
1413+ /* Bus suspend */
1414+ if (usbd_bus_state & USBD_STATE_SUSPEND ) {
1415+ numaker_usbd_bus_suspend_th (dev );
12881416 }
1289- if (usbd_bus_state & USBD_STATE_RESUME ) {
1290- /* Enable back USB/PHY */
1291- base -> ATTR |= USBD_ATTR_USBEN_Msk | USBD_ATTR_PHYEN_Msk ;
12921417
1293- /* UDC stack would handle bottom-half processing */
1294- udc_submit_event (dev , UDC_EVT_RESUME , 0 );
1295-
1296- LOG_DBG ("USB resume" );
1418+ /* Bus resume */
1419+ if (usbd_bus_state & USBD_STATE_RESUME ) {
1420+ numaker_usbd_bus_resume_th (dev );
12971421 }
12981422 }
12991423
13001424 /* USB SOF */
13011425 if (usbd_intsts & USBD_INTSTS_SOFIF_Msk ) {
1302- /* UDC stack would handle bottom-half processing */
1303- udc_submit_sof_event (dev );
1426+ numaker_usbd_sof_th (dev );
13041427 }
13051428
13061429 /* USB Setup/EP */
@@ -1309,26 +1432,7 @@ static void numaker_usbd_isr(const struct device *dev)
13091432
13101433 /* Setup event */
13111434 if (usbd_intsts & USBD_INTSTS_SETUP ) {
1312- USBD_EP_T * ep0_base = numaker_usbd_ep_base (dev , EP0 );
1313- USBD_EP_T * ep1_base = numaker_usbd_ep_base (dev , EP1 );
1314-
1315- /* Clear the data IN/OUT ready flag of control endpoints */
1316- ep0_base -> CFGP |= USBD_CFGP_CLRRDY_Msk ;
1317- ep1_base -> CFGP |= USBD_CFGP_CLRRDY_Msk ;
1318-
1319- /* By USB spec, following transactions, regardless of Data/Status stage,
1320- * will always be DATA1
1321- */
1322- ep0_base -> CFG |= USBD_CFG_DSQSYNC_Msk ;
1323- ep1_base -> CFG |= USBD_CFG_DSQSYNC_Msk ;
1324-
1325- /* Message for bottom-half processing */
1326- /* NOTE: In Zephyr USB device stack, Setup packet is passed via
1327- * CTRL OUT EP
1328- */
1329- msg .type = NUMAKER_USBD_MSG_TYPE_SETUP ;
1330- numaker_usbd_setup_copy_to_user (dev , msg .setup .packet );
1331- numaker_usbd_send_msg (dev , & msg );
1435+ numaker_usbd_setup_th (dev );
13321436 }
13331437
13341438 /* EP events */
@@ -1339,51 +1443,8 @@ static void numaker_usbd_isr(const struct device *dev)
13391443
13401444 while (epintsts ) {
13411445 uint32_t ep_hw_idx = u32_count_trailing_zeros (epintsts );
1342- USBD_EP_T * ep_base = numaker_usbd_ep_base (dev , ep_hw_idx );
1343- uint8_t ep_dir ;
1344- uint8_t ep_idx ;
1345- uint8_t ep ;
13461446
1347- /* We don't enable INNAKEN interrupt, so as long as EP event occurs,
1348- * we can just regard one data transaction has completed (ACK for
1349- * CTRL/BULK/INT or no-ACK for Iso), that is, no need to check EPSTS0,
1350- * EPSTS1, etc.
1351- */
1352-
1353- /* EP direction, number, and address */
1354- ep_dir = ((ep_base -> CFG & USBD_CFG_STATE_Msk ) == USBD_CFG_EPMODE_IN )
1355- ? USB_EP_DIR_IN
1356- : USB_EP_DIR_OUT ;
1357- ep_idx = (ep_base -> CFG & USBD_CFG_EPNUM_Msk ) >> USBD_CFG_EPNUM_Pos ;
1358- ep = USB_EP_GET_ADDR (ep_idx , ep_dir );
1359-
1360- /* NOTE: See comment in udc_numaker_set_address()'s implementation
1361- * for safe place to change USB device address
1362- */
1363- if (ep == USB_EP_GET_ADDR (0 , USB_EP_DIR_IN )) {
1364- numaker_usbd_set_addr (dev );
1365- }
1366-
1367- /* NOTE: See comment on mxpld_ctrlout for why make one copy of
1368- * CTRL OUT's MXPLD
1369- */
1370- if (ep == USB_EP_GET_ADDR (0 , USB_EP_DIR_OUT )) {
1371- struct numaker_usbd_ep * ep_ctrlout = priv -> ep_pool + 0 ;
1372- USBD_EP_T * ep_ctrlout_base = numaker_usbd_ep_base (
1373- dev , ep_ctrlout -> ep_hw_idx );
1374-
1375- ep_ctrlout -> mxpld_ctrlout = ep_ctrlout_base -> MXPLD ;
1376- }
1377-
1378- /* Message for bottom-half processing */
1379- if (USB_EP_DIR_IS_OUT (ep )) {
1380- msg .type = NUMAKER_USBD_MSG_TYPE_OUT ;
1381- msg .out .ep = ep ;
1382- } else {
1383- msg .type = NUMAKER_USBD_MSG_TYPE_IN ;
1384- msg .in .ep = ep ;
1385- }
1386- numaker_usbd_send_msg (dev , & msg );
1447+ numaker_usbd_ep_th (dev , ep_hw_idx );
13871448
13881449 /* Have handled this EP and go next */
13891450 epintsts &= ~BIT (ep_hw_idx );
0 commit comments