Experimental isochronous capability added to STM32 OTGv1 driver.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8289 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
Giovanni Di Sirio 2015-09-09 09:06:50 +00:00
parent 98bb7fb5df
commit f6d6d2068a
4 changed files with 101 additions and 6 deletions

View File

@ -678,6 +678,8 @@ typedef struct {
SOF mask. */ SOF mask. */
#define DSTS_FNSOF(n) ((n)<<8) /**< Frame number of the received #define DSTS_FNSOF(n) ((n)<<8) /**< Frame number of the received
SOF value. */ SOF value. */
#define DSTS_FNSOF_ODD (1U<<8) /**< Frame parity of the received
SOF value. */
#define DSTS_EERR (1U<<3) /**< Erratic error. */ #define DSTS_EERR (1U<<3) /**< Erratic error. */
#define DSTS_ENUMSPD_MASK (3U<<1) /**< Enumerated speed mask. */ #define DSTS_ENUMSPD_MASK (3U<<1) /**< Enumerated speed mask. */
#define DSTS_ENUMSPD_FS_48 (3U<<1) /**< Full speed (PHY clock is #define DSTS_ENUMSPD_FS_48 (3U<<1) /**< Full speed (PHY clock is

View File

@ -562,6 +562,69 @@ static void otg_epout_handler(USBDriver *usbp, usbep_t ep) {
} }
} }
/**
* @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. * @brief OTG shared ISR.
* *
@ -622,6 +685,16 @@ static void usb_lld_serve_interrupt(USBDriver *usbp) {
_usb_isr_invoke_sof_cb(usbp); _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.*/ /* RX FIFO not empty handling.*/
if (sts & GINTSTS_RXFLVL) { if (sts & GINTSTS_RXFLVL) {
/* The interrupt is masked while the thread has control or it would /* The interrupt is masked while the thread has control or it would
@ -830,7 +903,7 @@ void usb_lld_start(USBDriver *usbp) {
- USB turn-around time = TRDT_VALUE_HS or TRDT_VALUE_FS.*/ - USB turn-around time = TRDT_VALUE_HS or TRDT_VALUE_FS.*/
#if defined(BOARD_OTG2_USES_ULPI) #if defined(BOARD_OTG2_USES_ULPI)
/* High speed ULPI PHY.*/ /* High speed ULPI PHY.*/
otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_HS) | /*XXXXXXXXXXX*/ otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_HS) |
GUSBCFG_SRPCAP | GUSBCFG_HNPCAP; GUSBCFG_SRPCAP | GUSBCFG_HNPCAP;
#else #else
otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_FS) | otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_FS) |
@ -893,10 +966,12 @@ void usb_lld_start(USBDriver *usbp) {
otgp->DAINTMSK = 0; otgp->DAINTMSK = 0;
if (usbp->config->sof_cb == NULL) if (usbp->config->sof_cb == NULL)
otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM | GINTMSK_USBSUSPM | otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM | GINTMSK_USBSUSPM |
GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM; GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM |
GINTMSK_IISOIXFRM | GINTMSK_IISOOXFRM;
else else
otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM | GINTMSK_USBSUSPM | otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM | GINTMSK_USBSUSPM |
GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM | GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM |
GINTMSK_IISOIXFRM | GINTMSK_IISOOXFRM |
GINTMSK_SOFM; GINTMSK_SOFM;
/* Clears all pending IRQs, if any. */ /* Clears all pending IRQs, if any. */
@ -1225,7 +1300,8 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) {
/* Normal case.*/ /* Normal case.*/
uint32_t pcnt = (isp->txsize + usbp->epc[ep]->in_maxsize - 1) / uint32_t pcnt = (isp->txsize + usbp->epc[ep]->in_maxsize - 1) /
usbp->epc[ep]->in_maxsize; usbp->epc[ep]->in_maxsize;
usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(pcnt) | /* 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); DIEPTSIZ_XFRSIZ(isp->txsize);
} }
} }
@ -1240,7 +1316,15 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) {
*/ */
void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { 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;
} }
/** /**
@ -1253,6 +1337,14 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
*/ */
void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { 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->ie[ep].DIEPCTL |= DIEPCTL_EPENA | DIEPCTL_CNAK;
usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEM(ep); usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEM(ep);
} }

View File

@ -73,6 +73,7 @@
***************************************************************************** *****************************************************************************
*** 3.1.0 *** *** 3.1.0 ***
- HAL: Experimental isochronous capability added to STM32 OTGv1 driver.
- HAL: Modified the serial-USB driver to reject write/read attempts if the - HAL: Modified the serial-USB driver to reject write/read attempts if the
underlying USB is not in active state. In case of disconnection the underlying USB is not in active state. In case of disconnection the
SDU driver broadcasts a CHN_DISCONNECTED event. SDU driver broadcasts a CHN_DISCONNECTED event.

View File

@ -92,8 +92,8 @@ include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
# HAL-OSAL files (optional). # HAL-OSAL files (optional).
include $(CHIBIOS)/os/hal/hal.mk include $(CHIBIOS)/os/hal/hal.mk
include $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx/platform.mk include $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx/platform.mk
include $(CHIBIOS)/os/hal/boards/OLIMEX_STM32_E407/board.mk #include $(CHIBIOS)/os/hal/boards/OLIMEX_STM32_E407/board.mk
#include $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY/board.mk include $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY/board.mk
include $(CHIBIOS)/os/hal/osal/rt/osal.mk include $(CHIBIOS)/os/hal/osal/rt/osal.mk
# RTOS files (optional). # RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk include $(CHIBIOS)/os/rt/rt.mk