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:
parent
98bb7fb5df
commit
f6d6d2068a
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue