Skip to content

Instantly share code, notes, and snippets.

@ObKo
Created August 8, 2015 11:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ObKo/a08174a1a2446ea6a208 to your computer and use it in GitHub Desktop.
Save ObKo/a08174a1a2446ea6a208 to your computer and use it in GitHub Desktop.
diff -Naur ChibiOS-svn/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h ChibiOS-iso/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h
--- ChibiOS-svn/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h 2015-07-15 20:18:40.000000000 +0600
+++ ChibiOS-iso/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h 2015-07-31 16:08:43.768582531 +0600
@@ -671,6 +671,8 @@
SOF mask. */
#define DSTS_FNSOF(n) ((n)<<8) /**< Frame number of the received
SOF value. */
+#define DSTS_FNSOF_ODD (1U<<8) /**< Frame parity of the received
+ SOF value. */
#define DSTS_EERR (1U<<3) /**< Erratic error. */
#define DSTS_ENUMSPD_MASK (3U<<1) /**< Enumerated speed mask. */
#define DSTS_ENUMSPD_FS_48 (3U<<1) /**< Full speed (PHY clock is
diff -Naur ChibiOS-svn/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c ChibiOS-iso/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
--- ChibiOS-svn/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c 2015-07-15 20:18:40.000000000 +0600
+++ ChibiOS-iso/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c 2015-08-07 14:40:19.698220001 +0600
@@ -614,6 +614,69 @@
}
/**
+ * @brief Isochronous IN transfer failed handler.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+static void otg_isoc_in_failed_handler(USBDriver *usbp) {
+ usbep_t ep;
+ stm32_otg_t *otgp = usbp->otg;
+
+ for (ep = 0; ep <= usbp->otgparams->num_endpoints; ep++) {
+ if (((otgp->ie[ep].DIEPCTL & DIEPCTL_EPTYP_MASK) == DIEPCTL_EPTYP_ISO) &&
+ ((otgp->ie[ep].DIEPCTL & DIEPCTL_EPENA) != 0)) {
+ /* Endpoint enabled -> ISOC IN transfer failed */
+ /* Disable endpoint */
+ otgp->ie[ep].DIEPCTL |= (DIEPCTL_EPDIS | DIEPCTL_SNAK);
+ while (otgp->ie[ep].DIEPCTL & DIEPCTL_EPENA)
+ ;
+
+ /* Flush FIFO */
+ otg_txfifo_flush(usbp, ep);
+
+ /* Prepare data for next frame */
+ _usb_isr_invoke_in_cb(usbp, ep);
+
+ /* Pump out data for next frame */
+ osalSysLockFromISR();
+ otgp->DIEPEMPMSK &= ~(1 << ep);
+ usbp->txpending |= (1 << ep);
+ osalThreadResumeI(&usbp->wait, MSG_OK);
+ osalSysUnlockFromISR();
+ }
+ }
+}
+
+/**
+ * @brief Isochronous OUT transfer failed handler.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+
+static void otg_isoc_out_failed_handler(USBDriver *usbp) {
+ usbep_t ep;
+ stm32_otg_t *otgp = usbp->otg;
+
+ for (ep = 0; ep <= usbp->otgparams->num_endpoints; ep++) {
+ if (((otgp->oe[ep].DOEPCTL & DOEPCTL_EPTYP_MASK) == DOEPCTL_EPTYP_ISO) &&
+ ((otgp->oe[ep].DOEPCTL & DOEPCTL_EPENA) != 0)) {
+ /* Endpoint enabled -> ISOC OUT transfer failed */
+ /* Disable endpoint */
+ /* FIXME: Core stucks here */
+ /*otgp->oe[ep].DOEPCTL |= (DOEPCTL_EPDIS | DOEPCTL_SNAK);
+ while (otgp->oe[ep].DOEPCTL & DOEPCTL_EPENA)
+ ;*/
+ /* Prepare transfer for next frame */
+ _usb_isr_invoke_out_cb(usbp, ep);
+ }
+ }
+}
+
+/**
* @brief OTG shared ISR.
*
* @param[in] usbp pointer to the @p USBDriver object
@@ -644,6 +707,16 @@
_usb_isr_invoke_sof_cb(usbp);
}
+ /* Isochronous IN failed handling */
+ if (sts & GINTSTS_IISOIXFR) {
+ otg_isoc_in_failed_handler(usbp);
+ }
+
+ /* Isochronous OUT failed handling */
+ if (sts & GINTSTS_IISOOXFR) {
+ otg_isoc_out_failed_handler(usbp);
+ }
+
/* RX FIFO not empty handling.*/
if (sts & GINTSTS_RXFLVL) {
/* The interrupt is masked while the thread has control or it would
@@ -868,12 +941,16 @@
otgp->DIEPMSK = 0;
otgp->DOEPMSK = 0;
otgp->DAINTMSK = 0;
+
if (usbp->config->sof_cb == NULL)
otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM /*| GINTMSK_USBSUSPM |
- GINTMSK_ESUSPM |*/;
+ GINTMSK_ESUSPM */ | GINTMSK_IISOIXFRM |
+ GINTMSK_IISOOXFRM;
else
otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM /*| GINTMSK_USBSUSPM |
- GINTMSK_ESUSPM */ | GINTMSK_SOFM;
+ GINTMSK_ESUSPM */ | GINTMSK_IISOIXFRM |
+ GINTMSK_IISOOXFRM | GINTMSK_SOFM;
+
otgp->GINTSTS = 0xFFFFFFFF; /* Clears all pending IRQs, if any. */
#if defined(_CHIBIOS_RT_)
@@ -1196,7 +1273,9 @@
/* Normal case.*/
uint32_t pcnt = (isp->txsize + usbp->epc[ep]->in_maxsize - 1) /
usbp->epc[ep]->in_maxsize;
- usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(pcnt) |
+ /* DIEPTSIZ_MCNT is for isochronous IN transfers */
+ /* TODO: Support more than one packet per frame for isochronous transfers */
+ usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_MCNT(1) | DIEPTSIZ_PKTCNT(pcnt) |
DIEPTSIZ_XFRSIZ(isp->txsize);
}
}
@@ -1210,8 +1289,15 @@
* @notapi
*/
void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
-
- usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_CNAK;
+ if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) {
+ /* Odd/even bit toggling for isochronous endpoint */
+ if (usbp->otg->DSTS & DSTS_FNSOF_ODD)
+ usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SEVNFRM;
+ else
+ usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SODDFRM;
+ }
+
+ usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_EPENA | DOEPCTL_CNAK;
}
/**
@@ -1223,7 +1309,14 @@
* @notapi
*/
void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
-
+ if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) {
+ /* Odd/even bit toggling */
+ if (usbp->otg->DSTS & DSTS_FNSOF_ODD)
+ usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_SEVNFRM;
+ else
+ usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_SODDFRM;
+ }
+
usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_EPENA | DIEPCTL_CNAK;
usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEM(ep);
}
@niklasnisbeth
Copy link

Hi. Is this working well? And maybe somehow related to your KDAC project?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment