summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorClifroy Henry <[email protected]>2023-07-08 17:21:19 -0400
committerhathach <[email protected]>2024-04-11 20:57:40 +0700
commita3286932add7c8142b94160522f19e5544e27c0a (patch)
tree62e06cbefb7b98ad0a7888e5e64500c0eb8689bb /src
parentb8b22b929e1bbbbae7c7337972129ae6f7192bc6 (diff)
Correctly implementing recommended workarounds for erratas USB4 and USB10.
Diffstat (limited to 'src')
-rw-r--r--src/portable/ti/msp430x5xx/dcd_msp430x5xx.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c
index a0d9b3ea5..25c2fb301 100644
--- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c
+++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c
@@ -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;