aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDiego Ismirlian <dismirlian (at) google's mail.com>2017-07-31 18:48:23 -0300
committerDiego Ismirlian <dismirlian (at) google's mail.com>2017-07-31 18:48:23 -0300
commit02585210d1f33b3d5dd52267faa15576d5f7f8b2 (patch)
tree910da63c73da9d1512ebc734c2bd6bece5cbfcec
parentca1882c01b7055a9dd16468e093e11ae87c65757 (diff)
downloadChibiOS-Contrib-02585210d1f33b3d5dd52267faa15576d5f7f8b2.tar.gz
ChibiOS-Contrib-02585210d1f33b3d5dd52267faa15576d5f7f8b2.tar.bz2
ChibiOS-Contrib-02585210d1f33b3d5dd52267faa15576d5f7f8b2.zip
USBH: STM32 LLD: various improvements
- general cleanup - implemented workaround to undocumented erratum (the OTG core may report successful enabling of port when connecting a low-speed device, but really it generates no traffic and remains in a "dumb" state) - improved handling of disconnection of devices (avoid submitting URBs if the port is disabled)
-rw-r--r--os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c244
-rw-r--r--os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h2
2 files changed, 134 insertions, 112 deletions
diff --git a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c
index 3a581f5..3944a79 100644
--- a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c
+++ b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.c
@@ -127,16 +127,6 @@ static inline void _save_dt_mask(usbh_ep_t *ep, uint32_t hctsiz) {
ep->dt_mask = hctsiz & HCTSIZ_DPID_MASK;
}
-#if 1
-#define _transfer_completed _transfer_completedI
-#else
-static inline void _transfer_completed(usbh_ep_t *ep, usbh_urb_t *urb, usbh_urbstatus_t status) {
- osalSysLockFromISR();
- _transfer_completedI(ep, urb, status);
- osalSysUnlockFromISR();
-}
-#endif
-
/*===========================================================================*/
/* Functions called from many places. */
/*===========================================================================*/
@@ -466,7 +456,7 @@ static void _purge_queue(USBHDriver *host, struct list_head *list) {
_release_channel(host, hcm);
_update_urb(ep, hcm->hc->HCTSIZ, urb, FALSE);
}
- _transfer_completed(ep, urb, USBH_URBSTATUS_DISCONNECTED);
+ _transfer_completedI(ep, urb, USBH_URBSTATUS_DISCONNECTED);
}
}
@@ -622,6 +612,13 @@ bool usbh_lld_ep_reset(usbh_ep_t *ep) {
void usbh_lld_urb_submit(usbh_urb_t *urb) {
usbh_ep_t *const ep = urb->ep;
+ USBHDriver *const host = ep->device->host;
+
+ if (!(host->otg->HPRT & HPRT_PENA)) {
+ uwarnf("\t%s: Can't submit URB, port disabled", ep->name);
+ _usbh_urb_completeI(urb, USBH_URBSTATUS_DISCONNECTED);
+ return;
+ }
/* add the URB to the EP's queue */
list_add_tail(&urb->node, &ep->urb_list);
@@ -633,7 +630,7 @@ void usbh_lld_urb_submit(usbh_urb_t *urb) {
_move_to_pending_queue(ep);
if (usbhEPIsPeriodic(ep)) {
- ep->device->host->otg->GINTMSK |= GINTMSK_SOFM;
+ host->otg->GINTMSK |= GINTMSK_SOFM;
} else {
/* try to queue non-periodic transfers */
_try_commit_np(ep->device->host);
@@ -666,7 +663,7 @@ bool usbh_lld_urb_abort(usbh_urb_t *urb, usbh_urbstatus_t status) {
return FALSE;
}
- /* This URB is active, we can cancel it now */
+ /* This URB is inactive, we can cancel it now */
uinfof("\t%s: usbh_lld_urb_abort: URB is not active", ep->name);
_transfer_completedI(ep, urb, status);
@@ -766,7 +763,7 @@ static void _complete_bulk_int(USBHDriver *host, stm32_hc_management_t *hcm, usb
_save_dt_mask(ep, hctsiz);
if (_update_urb(ep, hctsiz, urb, TRUE)) {
udbgf("\t%s: done", ep->name);
- _transfer_completed(ep, urb, USBH_URBSTATUS_OK);
+ _transfer_completedI(ep, urb, USBH_URBSTATUS_OK);
} else {
osalDbgCheck(urb->requestedLength > 0x7FFFF);
uwarnf("\t%s: incomplete", ep->name);
@@ -797,7 +794,7 @@ static void _complete_control(USBHDriver *host, stm32_hc_management_t *hcm, usbh
} else {
osalDbgCheck(ep->xfer.u.ctrl_phase == USBH_LLD_CTRLPHASE_STATUS);
udbgf("\t%s: STATUS done", ep->name);
- _transfer_completed(ep, urb, USBH_URBSTATUS_OK);
+ _transfer_completedI(ep, urb, USBH_URBSTATUS_OK);
}
_try_commit_np(host);
}
@@ -823,7 +820,7 @@ static void _complete_iso(USBHDriver *host, stm32_hc_management_t *hcm, usbh_ep_
udbgf("\t%s: done", hcm->ep->name);
_release_channel(host, hcm);
_update_urb(ep, hctsiz, urb, TRUE);
- _transfer_completed(ep, urb, USBH_URBSTATUS_OK);
+ _transfer_completedI(ep, urb, USBH_URBSTATUS_OK);
_try_commit_p(host, FALSE);
}
@@ -908,7 +905,7 @@ static inline void _chh_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_
switch (reason) {
case USBH_LLD_HALTREASON_NAK:
if ((ep->type == USBH_EPTYPE_INT) && ep->in) {
- _transfer_completed(ep, urb, USBH_URBSTATUS_TIMEOUT);
+ _transfer_completedI(ep, urb, USBH_URBSTATUS_TIMEOUT);
} else {
ep->xfer.error_count = 0;
_move_to_pending_queue(ep);
@@ -923,12 +920,12 @@ static inline void _chh_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_
} else {
ep->status = USBH_EPSTATUS_HALTED;
}
- _transfer_completed(ep, urb, USBH_URBSTATUS_STALL);
+ _transfer_completedI(ep, urb, USBH_URBSTATUS_STALL);
break;
case USBH_LLD_HALTREASON_ERROR:
if ((ep->type == USBH_EPTYPE_ISO) || done || (ep->xfer.error_count >= 3)) {
- _transfer_completed(ep, urb, USBH_URBSTATUS_ERROR);
+ _transfer_completedI(ep, urb, USBH_URBSTATUS_ERROR);
} else {
uerrf("\t%s: err=%d, done=%d, retry", ep->name, ep->xfer.error_count, done);
_move_to_pending_queue(ep);
@@ -937,7 +934,7 @@ static inline void _chh_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_
case USBH_LLD_HALTREASON_ABORT:
uwarnf("\t%s: Abort", ep->name);
- _transfer_completed(ep, urb, urb->status);
+ _transfer_completedI(ep, urb, urb->status);
break;
default:
@@ -1024,6 +1021,36 @@ static inline void _hcint_int(USBHDriver *host) {
/* Host interrupts. */
/*===========================================================================*/
static inline void _sof_int(USBHDriver *host) {
+
+ /* this is part of the workaround to the LS bug in the OTG core */
+#undef HPRT_PLSTS_MASK
+#define HPRT_PLSTS_MASK (3U<<10)
+ if (host->check_ls_activity) {
+ uint16_t remaining = host->otg->HFNUM >> 16;
+ if (remaining < 5975) {
+ uwarnf("LS: ISR called too late (time=%d)", 6000 - remaining);
+ return;
+ }
+ /* 15us loop */
+ for (;;) {
+ uint32_t line_status = host->otg->HPRT & HPRT_PLSTS_MASK;
+ remaining = host->otg->HFNUM >> 16;
+ if (line_status != HPRT_PLSTS_DM) {
+ uinfof("LS: activity detected, line=%d, time=%d", line_status >> 10, 6000 - remaining);
+ host->check_ls_activity = FALSE;
+ host->otg->GINTMSK = (host->otg->GINTMSK & ~GINTMSK_SOFM) | (GINTMSK_HCM | GINTMSK_RXFLVLM);
+ host->rootport.lld_status |= USBH_PORTSTATUS_ENABLE;
+ host->rootport.lld_c_status |= USBH_PORTSTATUS_C_ENABLE;
+ return;
+ }
+ if (remaining < 5910) {
+ uwarn("LS: No activity detected");
+ return;
+ }
+ }
+ }
+
+ /* real SOF interrupt */
udbg("SOF");
_try_commit_p(host, TRUE);
}
@@ -1143,17 +1170,19 @@ static inline void _ptxfe_int(USBHDriver *host) {
uinfo("PTXFE");
}
-static inline void _discint_int(USBHDriver *host) {
- uint32_t hprt = host->otg->HPRT;
-
- uwarn("\tDISCINT");
+static void _disable(USBHDriver *host) {
+ host->rootport.lld_status &= ~(USBH_PORTSTATUS_CONNECTION | USBH_PORTSTATUS_ENABLE);
+ host->rootport.lld_c_status |= USBH_PORTSTATUS_C_CONNECTION | USBH_PORTSTATUS_C_ENABLE;
- if (!(hprt & HPRT_PCSTS)) {
- host->rootport.lld_status &= ~(USBH_PORTSTATUS_CONNECTION | USBH_PORTSTATUS_ENABLE);
- host->rootport.lld_c_status |= USBH_PORTSTATUS_C_CONNECTION | USBH_PORTSTATUS_C_ENABLE;
- }
_purge_active(host);
_purge_pending(host);
+
+ host->otg->GINTMSK &= ~(GINTMSK_HCM | GINTMSK_RXFLVLM);
+}
+
+static inline void _discint_int(USBHDriver *host) {
+ uinfo("DISCINT: Port disconnection detected");
+ _disable(host);
}
static inline void _hprtint_int(USBHDriver *host) {
@@ -1169,8 +1198,6 @@ static inline void _hprtint_int(USBHDriver *host) {
uinfo("\tHPRT: Port connection detected");
host->rootport.lld_status |= USBH_PORTSTATUS_CONNECTION;
host->rootport.lld_c_status |= USBH_PORTSTATUS_C_CONNECTION;
- } else {
- uinfo("\tHPRT: Port disconnection detected");
}
}
@@ -1178,9 +1205,32 @@ static inline void _hprtint_int(USBHDriver *host) {
hprt_clr |= HPRT_PENCHNG;
if (hprt & HPRT_PENA) {
uinfo("\tHPRT: Port enabled");
- host->rootport.lld_status |= USBH_PORTSTATUS_ENABLE;
host->rootport.lld_status &= ~(USBH_PORTSTATUS_HIGH_SPEED | USBH_PORTSTATUS_LOW_SPEED);
+ /* configure FIFOs */
+#define HNPTXFSIZ DIEPTXF0
+#if STM32_USBH_USE_OTG1
+#if STM32_USBH_USE_OTG2
+ if (&USBHD1 == host)
+#endif
+ {
+ otg->GRXFSIZ = GRXFSIZ_RXFD(STM32_OTG1_RXFIFO_SIZE / 4);
+ otg->HNPTXFSIZ = HPTXFSIZ_PTXSA(STM32_OTG1_RXFIFO_SIZE / 4) | HPTXFSIZ_PTXFD(STM32_OTG1_NPTXFIFO_SIZE / 4);
+ otg->HPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG1_RXFIFO_SIZE / 4) + (STM32_OTG1_NPTXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG1_PTXFIFO_SIZE / 4);
+ }
+#endif
+#if STM32_USBH_USE_OTG2
+#if STM32_USBH_USE_OTG1
+ if (&USBHD2 == host)
+#endif
+ {
+ otg->GRXFSIZ = GRXFSIZ_RXFD(STM32_OTG2_RXFIFO_SIZE / 4);
+ otg->HNPTXFSIZ = HPTXFSIZ_PTXSA(STM32_OTG2_RXFIFO_SIZE / 4) | HPTXFSIZ_PTXFD(STM32_OTG2_NPTXFIFO_SIZE / 4);
+ otg->HPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG2_RXFIFO_SIZE / 4) + (STM32_OTG2_NPTXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG2_PTXFIFO_SIZE / 4);
+ }
+#endif
+#undef HNPTXFSIZ
+
/* Make sure the FIFOs are flushed. */
otg_txfifo_flush(host, 0x10);
otg_rxfifo_flush(host);
@@ -1197,9 +1247,23 @@ static inline void _hprtint_int(USBHDriver *host) {
host->rootport.lld_status |= USBH_PORTSTATUS_LOW_SPEED;
otg->HFIR = 6000;
otg->HCFG = (otg->HCFG & ~HCFG_FSLSPCS_MASK) | HCFG_FSLSPCS_6;
+
+ /* Low speed devices connected to the STM32's internal transceiver sometimes
+ * don't behave correctly. Although HPRT reports a port enable, really
+ * no traffic is generated, and the core is non-functional. To avoid
+ * this we won't report the port enable until we are sure that the
+ * port is working. */
+ host->check_ls_activity = TRUE;
+ otg->GINTMSK |= GINTMSK_SOFM;
} else {
otg->HFIR = 48000;
otg->HCFG = (otg->HCFG & ~HCFG_FSLSPCS_MASK) | HCFG_FSLSPCS_48;
+ host->check_ls_activity = FALSE;
+
+ /* enable channel and rx interrupts */
+ otg->GINTMSK |= GINTMSK_HCM | GINTMSK_RXFLVLM;
+ host->rootport.lld_status |= USBH_PORTSTATUS_ENABLE;
+ host->rootport.lld_c_status |= USBH_PORTSTATUS_C_ENABLE;
}
} else {
if (hprt & HPRT_PCSTS) {
@@ -1211,13 +1275,8 @@ static inline void _hprtint_int(USBHDriver *host) {
} else {
uerr("\tHPRT: Port disabled due to disconnect");
}
-
- _purge_active(host);
- _purge_pending(host);
-
- host->rootport.lld_status &= ~USBH_PORTSTATUS_ENABLE;
+ _disable(host);
}
- host->rootport.lld_c_status |= USBH_PORTSTATUS_C_ENABLE;
}
if (hprt & HPRT_POCCHNG) {
@@ -1249,24 +1308,19 @@ static void usb_lld_serve_interrupt(USBHDriver *host) {
}
/* check mismatch */
- if (gintsts & GINTSTS_MMIS) {
- uerr("Mode Mismatch");
- otg->GINTSTS = gintsts;
- return;
- }
+ osalDbgAssert((gintsts & GINTSTS_MMIS) == 0, "mode mismatch");
gintsts &= otg->GINTMSK;
-#if USBH_DEBUG_ENABLE_WARNINGS
if (!gintsts) {
+#if USBH_DEBUG_ENABLE_WARNINGS
uint32_t a, b;
a = otg->GINTSTS;
b = otg->GINTMSK;
- uwarnf("GINTSTS=%08x, GINTMSK=%08x", a, b);
+ uwarnf("Masked bits caused an ISR: GINTSTS=%08x, GINTMSK=%08x (unhandled bits=%08x)", a, b, a & ~b);
+#endif
return;
}
-#endif
- // otg->GINTMSK &= ~(GINTMSK_NPTXFEM | GINTMSK_PTXFEM);
otg->GINTSTS = gintsts;
if (gintsts & GINTSTS_SOF)
@@ -1365,25 +1419,23 @@ static void _init(USBHDriver *host) {
#if STM32_USBH_USE_OTG1
#if STM32_USBH_USE_OTG2
- if (&USBHD1 == host) {
+ if (&USBHD1 == host)
#endif
+ {
host->otg = OTG_FS;
host->channels_number = STM32_OTG1_CHANNELS_NUMBER;
-#if STM32_USBH_USE_OTG2
}
#endif
-#endif
#if STM32_USBH_USE_OTG2
#if STM32_USBH_USE_OTG1
- if (&USBHD2 == host) {
+ if (&USBHD2 == host)
#endif
+ {
host->otg = OTG_HS;
host->channels_number = STM32_OTG2_CHANNELS_NUMBER;
-#if STM32_USBH_USE_OTG1
}
#endif
-#endif
INIT_LIST_HEAD(&host->ch_free[0]);
INIT_LIST_HEAD(&host->ch_free[1]);
for (i = 0; i < host->channels_number; i++) {
@@ -1417,8 +1469,9 @@ static void _usbh_start(USBHDriver *usbh) {
/* Clock activation.*/
#if STM32_USBH_USE_OTG1
#if STM32_USBH_USE_OTG2
- if (&USBHD1 == usbh) {
+ if (&USBHD1 == usbh)
#endif
+ {
/* OTG FS clock enable and reset.*/
rccEnableOTG_FS(FALSE);
rccResetOTG_FS();
@@ -1427,15 +1480,14 @@ static void _usbh_start(USBHDriver *usbh) {
/* Enables IRQ vector.*/
nvicEnableVector(STM32_OTG1_NUMBER, STM32_USB_OTG1_IRQ_PRIORITY);
-#if STM32_USBH_USE_OTG2
}
#endif
-#endif
#if STM32_USBH_USE_OTG2
#if STM32_USBH_USE_OTG1
- if (&USBHD2 == usbh) {
+ if (&USBHD2 == usbh)
#endif
+ {
/* OTG HS clock enable and reset.*/
rccEnableOTG_HS(TRUE); // Enable HS clock when cpu is in sleep mode
rccDisableOTG_HSULPI(TRUE); // Disable HS ULPI clock when cpu is in sleep mode
@@ -1445,10 +1497,8 @@ static void _usbh_start(USBHDriver *usbh) {
/* Enables IRQ vector.*/
nvicEnableVector(STM32_OTG2_NUMBER, STM32_USB_OTG2_IRQ_PRIORITY);
-#if STM32_USBH_USE_OTG1
}
#endif
-#endif
otgp->GUSBCFG = GUSBCFG_PHYSEL | GUSBCFG_TRDT(5);
@@ -1487,41 +1537,11 @@ static void _usbh_start(USBHDriver *usbh) {
otgp->HPRT |= HPRT_PPWR;
- /* without this delay, the FIFO sizes are set INcorrectly */
- osalThreadSleepS(MS2ST(200));
-
-#define HNPTXFSIZ DIEPTXF0
-#if STM32_USBH_USE_OTG1
-#if STM32_USBH_USE_OTG2
- if (&USBHD1 == usbh) {
-#endif
- otgp->GRXFSIZ = GRXFSIZ_RXFD(STM32_OTG1_RXFIFO_SIZE / 4);
- otgp->HNPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG1_RXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG1_NPTXFIFO_SIZE / 4);
- otgp->HPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG1_RXFIFO_SIZE / 4) + (STM32_OTG1_NPTXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG1_PTXFIFO_SIZE / 4);
-#if STM32_USBH_USE_OTG2
- }
-#endif
-#endif
-#if STM32_USBH_USE_OTG2
-#if STM32_USBH_USE_OTG1
- if (&USBHD2 == usbh) {
-#endif
- otgp->GRXFSIZ = GRXFSIZ_RXFD(STM32_OTG2_RXFIFO_SIZE / 4);
- otgp->HNPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG2_RXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG2_NPTXFIFO_SIZE / 4);
- otgp->HPTXFSIZ = HPTXFSIZ_PTXSA((STM32_OTG2_RXFIFO_SIZE / 4) + (STM32_OTG2_NPTXFIFO_SIZE / 4)) | HPTXFSIZ_PTXFD(STM32_OTG2_PTXFIFO_SIZE / 4);
-#if STM32_USBH_USE_OTG1
- }
-#endif
-#endif
-#undef HNPTXFSIZ
-
otg_txfifo_flush(usbh, 0x10);
otg_rxfifo_flush(usbh);
otgp->GINTSTS = 0xffffffff;
- otgp->GINTMSK = GINTMSK_DISCM /*| GINTMSK_PTXFEM*/ | GINTMSK_HCM | GINTMSK_HPRTM
- /*| GINTMSK_IPXFRM | GINTMSK_NPTXFEM*/ | GINTMSK_RXFLVLM
- /*| GINTMSK_SOFM */ | GINTMSK_MMISM;
+ otgp->GINTMSK = GINTMSK_DISCM | GINTMSK_HPRTM | GINTMSK_MMISM;
usbh->rootport.lld_status = USBH_PORTSTATUS_POWER;
usbh->rootport.lld_c_status = 0;
@@ -1586,7 +1606,7 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy
break;
case USBH_PORT_FEAT_C_OVERCURRENT:
- usbh->rootport.lld_c_status &= USBH_PORTSTATUS_C_OVERCURRENT;
+ usbh->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_OVERCURRENT;
break;
default:
@@ -1597,18 +1617,7 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy
break;
case GetHubDescriptor:
- /*dev_dbg(hsotg->dev, "GetHubDescriptor\n");
- hub_desc = (struct usb_hub_descriptor *)buf;
- hub_desc->bDescLength = 9;
- hub_desc->bDescriptorType = USB_DT_HUB;
- hub_desc->bNbrPorts = 1;
- hub_desc->wHubCharacteristics =
- cpu_to_le16(HUB_CHAR_COMMON_LPSM |
- HUB_CHAR_INDV_PORT_OCPM);
- hub_desc->bPwrOn2PwrGood = 1;
- hub_desc->bHubContrCurrent = 0;
- hub_desc->u.hs.DeviceRemovable[0] = 0;
- hub_desc->u.hs.DeviceRemovable[1] = 0xff;*/
+ osalDbgAssert(0, "unsupported");
break;
case GetHubStatus:
@@ -1644,11 +1653,29 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy
uint32_t hprt;
otg->PCGCCTL = 0;
hprt = otg->HPRT;
+ if (hprt & HPRT_PENA) {
+ /* This can occur when the OTG core doesn't generate traffic
+ * despite reporting a successful por enable */
+ uerr("Detected enabled port; resetting OTG core");
+ otg->GAHBCFG = 0;
+ osalThreadSleepS(MS2ST(20));
+ _usbh_start(usbh); /* this effectively resets the core */
+ osalThreadSleepS(MS2ST(100)); /* during this delay, the core generates connect ISR */
+ uinfo("OTG reset ended");
+ if (otg->HPRT & HPRT_PCSTS) {
+ /* if the device is still connected, don't report a C_CONNECTION flag, which would cause
+ * the upper layer to abort enumeration */
+ uinfo("Clear connection change flag");
+ usbh->rootport.lld_c_status &= ~USBH_PORTSTATUS_C_CONNECTION;
+ }
+ }
/* note: writing PENA = 1 actually disables the port */
- hprt &= ~(HPRT_PSUSP | HPRT_PENA | HPRT_PCDET | HPRT_PENCHNG | HPRT_POCCHNG );
+ hprt &= ~(HPRT_PSUSP | HPRT_PENA | HPRT_PCDET | HPRT_PENCHNG | HPRT_POCCHNG);
+ while ((otg->GRSTCTL & GRSTCTL_AHBIDL) == 0);
otg->HPRT = hprt | HPRT_PRST;
- osalThreadSleepS(MS2ST(60));
+ osalThreadSleepS(MS2ST(15));
otg->HPRT = hprt;
+ osalThreadSleepS(MS2ST(10));
usbh->rootport.lld_c_status |= USBH_PORTSTATUS_C_RESET;
osalSysUnlock();
} break;
@@ -1672,14 +1699,7 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy
}
uint8_t usbh_lld_roothub_get_statuschange_bitmap(USBHDriver *usbh) {
- osalSysLock();
- if (usbh->rootport.lld_c_status) {
- osalSysUnlock();
- return 1 << 1;
- }
- osalSysUnlock();
- return 0;
+ return usbh->rootport.lld_c_status ? (1 << 1) : 0;
}
-
#endif
diff --git a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h
index a2b7628..fd7f4e0 100644
--- a/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h
+++ b/os/hal/ports/STM32/LLD/USBHv1/hal_usbh_lld.h
@@ -63,6 +63,8 @@ typedef struct stm32_hc_management {
#define _usbhdriver_ll_data \
stm32_otg_t *otg; \
+ /* low-speed port reset bug */ \
+ bool check_ls_activity; \
/* channels */ \
uint8_t channels_number; \
stm32_hc_management_t channels[STM32_OTG2_CHANNELS_NUMBER]; \