Skip to content

Commit 13315d1

Browse files
ccli8nashif
authored andcommitted
drivers: usb: udc: numaker: refactor large isr function
For clear, this splits large isr function into smaller ones which are dedicated for handling plug/unplug, wakeup, reset/suspend/resume, SOF, Setup, and endpoint events. Signed-off-by: Chun-Chieh Li <[email protected]>
1 parent 866080d commit 13315d1

File tree

1 file changed

+176
-115
lines changed

1 file changed

+176
-115
lines changed

drivers/usb/udc/udc_numaker.c

Lines changed: 176 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -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 */
400436
static 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)
12091372
static 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

Comments
 (0)