Correctly implementing recommended workarounds for erratas USB4 and USB10.

This commit is contained in:
Clifroy Henry 2023-07-08 17:21:19 -04:00 committed by hathach
parent b8b22b929e
commit a3286932ad
No known key found for this signature in database
GPG Key ID: 26FAB84F615C3C52

View File

@ -94,10 +94,6 @@ static void bus_reset(void)
USBOEPCNT_0 &= ~NAK;
USBIEPCNT_0 &= ~NAK;
// Disable (subsequent) bus reset events from causing a functional
// reset of the USB module.
USBCTL &= ~FRSTE;
// Enable responding to packets.
USBCTL |= FEN;
@ -108,6 +104,28 @@ static void bus_reset(void)
USBKEYPID = 0;
}
// Controls reset behavior of the USB module on receipt of a bus reset event.
// - enable: When true, bus reset events will cause a reset the USB module.
static void enable_functional_reset(const bool enable)
{
// Check whether or not the USB configuration registers were
// locked prior to this function being called so that, if
// necessary, the lock state can be restored on exit.
bool unlocked = (USBKEYPID == 0xA528) ? true : false;
if(!unlocked) USBKEYPID = USBKEY;
if(enable)
{
USBCTL |= FRSTE;
}
else
{
USBCTL &= ~FRSTE;
}
if(!unlocked) USBKEYPID = 0;
}
/*------------------------------------------------------------------*/
/* Controller API
@ -339,10 +357,6 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
if(epnum == 0)
{
// Enables a bus reset to cause a functional reset of the USB
// module.
USBCTL |= FRSTE;
if(dir == TUSB_DIR_OUT)
{
// Interrupt will notify us when data was received.
@ -638,7 +652,11 @@ static void handle_setup_packet(void)
//
// "...the SETUPIFG is cleared upon reading USBIV. In addition, the NAK on
// input endpoint 0 and output endpoint 0 is also cleared."
USBIEPCNF_0 &= ~UBME; // Errata USB10 workaround.
USBOEPCNF_0 &= ~UBME; // Errata USB10 workaround.
USBIFG &= ~SETUPIFG;
USBIEPCNF_0 |= UBME; // Errata USB10 workaround.
USBOEPCNF_0 |= UBME; // Errata USB10 workaround.
dcd_event_setup_received(0, (uint8_t*) &_setup_packet[0], true);
}
@ -661,7 +679,7 @@ static void handle_bus_power_event(void *param)
uint16_t attempts = 0;
do // Poll the PLL to check for a successful lock.
do // Poll the PLL, checking for a successful lock.
{
USBPLLIR = 0;
osal_task_delay(1);
@ -694,6 +712,7 @@ void dcd_int_handler(uint8_t rhport)
if(setup_status)
{
enable_functional_reset(true);
handle_setup_packet();
}
@ -716,6 +735,7 @@ void dcd_int_handler(uint8_t rhport)
break;
case USBVECINT_RSTR:
enable_functional_reset(false); // Errata USB4 workaround.
bus_reset();
dcd_event_bus_reset(0, TUSB_SPEED_FULL, true);
break;
@ -762,10 +782,12 @@ void dcd_int_handler(uint8_t rhport)
break;
case USBVECINT_INPUT_ENDPOINT0:
enable_functional_reset(true);
transmit_packet(0);
break;
case USBVECINT_OUTPUT_ENDPOINT0:
enable_functional_reset(true);
receive_packet(0);
break;