From e83071c9fef2d1b347fec4aa41650fe0950c60f8 Mon Sep 17 00:00:00 2001 From: Matt Baker Date: Sat, 6 Apr 2019 15:12:51 -0700 Subject: [PATCH] lpc176x: force minimum usb disconnect time Fixes GitHub Issue #1499. Resolves USB hang by forcing a minimum USB disconnection time at boot. Signed-off-by: Matt Baker --- src/lpc176x/internal.h | 2 ++ src/lpc176x/main.c | 15 +++++++++++++++ src/lpc176x/usbserial.c | 2 ++ 3 files changed, 19 insertions(+) diff --git a/src/lpc176x/internal.h b/src/lpc176x/internal.h index 5dcf99a46..985c30df9 100644 --- a/src/lpc176x/internal.h +++ b/src/lpc176x/internal.h @@ -18,4 +18,6 @@ int is_enabled_pclock(uint32_t pclk); void enable_pclock(uint32_t pclk); void gpio_peripheral(uint32_t gpio, int func, int pullup); +void udelay(uint32_t usecs); + #endif // internal.h diff --git a/src/lpc176x/main.c b/src/lpc176x/main.c index 1147faecf..c417a2c72 100644 --- a/src/lpc176x/main.c +++ b/src/lpc176x/main.c @@ -7,6 +7,7 @@ #include "LPC17xx.h" // NVIC_SystemReset #include "command.h" // DECL_CONSTANT #include "sched.h" // sched_main +#include "board/misc.h" // timer_read_time DECL_CONSTANT_STR("MCU", "lpc176x"); @@ -66,6 +67,20 @@ command_reset(uint32_t *args) } DECL_COMMAND_FLAGS(command_reset, HF_IN_SHUTDOWN, "reset"); +// Implement simple early-boot delay mechanism +void +udelay(uint32_t usecs) +{ + if (!(CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk)) { + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + } + + uint32_t end = timer_read_time() + timer_from_us(usecs); + while (timer_is_before(timer_read_time(), end)) + ; +} + // Main entry point int main(void) diff --git a/src/lpc176x/usbserial.c b/src/lpc176x/usbserial.c index 18466da7f..b2e67467a 100644 --- a/src/lpc176x/usbserial.c +++ b/src/lpc176x/usbserial.c @@ -277,6 +277,8 @@ usbserial_init(void) gpio_peripheral(GPIO(0, 30), 1, 0); gpio_peripheral(GPIO(0, 29), 1, 0); gpio_peripheral(GPIO(2, 9), 1, 0); + // enforce a minimum time bus is disconnected before connecting + udelay(5000); // setup endpoints realize_endpoint(EP0OUT, USB_CDC_EP0_SIZE); realize_endpoint(EP0IN, USB_CDC_EP0_SIZE);