Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1e2802d

Browse files
author
rechrtb
committedApr 29, 2024
Fully reset USB hardware when changing mode
Resetting the USB DMA registers fixes a crash when changing between host and device mode.
1 parent c7dd0ec commit 1e2802d

File tree

1 file changed

+55
-23
lines changed

1 file changed

+55
-23
lines changed
 

‎src/TinyUsbInterface.cpp

+55-23
Original file line numberDiff line numberDiff line change
@@ -375,60 +375,92 @@ extern "C" void CoreUsbDeviceTask(void* param) noexcept
375375

376376
while (true)
377377
{
378-
auto tusb_init = isHostMode ? tuh_init : tud_init;
379-
auto tusb_int_enable = isHostMode ? hcd_int_enable : dcd_int_enable;
380-
auto tusb_task = isHostMode ? tuh_task_ext : tud_task_ext;
381-
382378
digitalWrite(UsbVbusOn, isHostMode);
383-
tusb_init(0);
379+
380+
auto tusb_init = isHostMode ? tuh_init : tud_init;
384381
if (changingMode)
385382
{
386-
if (isHostMode)
383+
auto tusb_inited = isHostMode ? tuh_inited : tud_inited;
384+
if (tusb_inited())
387385
{
388-
if (tuh_inited())
386+
// TinyUSB class drivers already inited previously, just call
387+
// the functions to initialize the USB peripheral.
388+
if (isHostMode)
389389
{
390390
hcd_init(0);
391+
hcd_int_enable(0);
392+
}
393+
else
394+
{
395+
dcd_init(0);
396+
dcd_int_enable(0);
391397
}
392398
}
393399
else
394400
{
395-
tud_connect();
401+
tusb_init(0);
396402
}
397403
}
398-
tusb_int_enable(0);
404+
else
405+
{
406+
tusb_init(0);
407+
}
408+
409+
auto tusb_task = isHostMode ? tuh_task_ext : tud_task_ext;
399410

400411
changingMode = false;
401412
while (!changingMode)
402413
{
403414
tusb_task(100, false);
404415
}
405416

406-
// Deinit current tinyUSB context.
407-
if (isHostMode)
408-
{
409-
hcd_event_device_remove(0, false);
410-
}
411-
else
412-
{
413-
tud_disconnect();
414-
}
415-
tusb_task(100, false);
416-
417-
// Reset USB hardware.
418-
USBHS->USBHS_CTRL &= ~USBHS_CTRL_USBE;
417+
// Disable pipes, deallocate DPRAM
419418
for (int i = 9; i >= 0; i--)
420419
{
421420
if (isHostMode)
422421
{
422+
USBHS->USBHS_HSTPIP &= ~(USBHS_HSTPIP_PEN0 << i);
423423
USBHS->USBHS_HSTPIPCFG[i] &= ~(USBHS_HSTPIPCFG_ALLOC);
424424
}
425425
else
426426
{
427+
USBHS->USBHS_DEVEPT &= ~(USBHS_DEVEPT_EPEN0 << i);
427428
USBHS->USBHS_DEVEPTCFG[i] &= ~(USBHS_DEVEPTCFG_ALLOC);
428429
}
429430
}
430431

431-
// Complete the mode change.
432+
// Reset DMA registers
433+
for (int i = 0; i < 7; i++)
434+
{
435+
if (isHostMode)
436+
{
437+
USBHS->USBHS_HSTDMA[i].USBHS_HSTDMAADDRESS = 0;
438+
USBHS->USBHS_HSTDMA[i].USBHS_HSTDMACONTROL = 0;
439+
USBHS->USBHS_HSTDMA[i].USBHS_HSTDMASTATUS = 0;
440+
}
441+
else
442+
{
443+
USBHS->USBHS_DEVDMA[i].USBHS_DEVDMAADDRESS = 0;
444+
USBHS->USBHS_DEVDMA[i].USBHS_DEVDMACONTROL = 0;
445+
USBHS->USBHS_DEVDMA[i].USBHS_DEVDMASTATUS = 0;
446+
}
447+
}
448+
449+
// Deinit current tinyUSB host context. Not needed for device
450+
// since changing mode requires the board to not be connected
451+
// to a host, so if we are changing mode then the DCD_EVENT_UNPLUGGED
452+
// must have been handled in the past already.
453+
if (isHostMode)
454+
{
455+
hcd_event_device_remove(0, false);
456+
tusb_task(100, false);
457+
}
458+
459+
// Reset USB hardware
460+
USBHS->USBHS_CTRL &= ~(USBHS_CTRL_USBE | USBHS_CTRL_UIMOD);
461+
USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK;
462+
463+
// Toggle mode for next loop
432464
isHostMode = !isHostMode;
433465
}
434466
}

0 commit comments

Comments
 (0)
Please sign in to comment.