STM32 OTF FS device. USB console now works for me. Some of these changes are hacks that need to be revisited.
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4777 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
17f219dcb1
commit
a1edf7977d
@ -2819,4 +2819,8 @@
|
|||||||
is an important USB serial fix.
|
is an important USB serial fix.
|
||||||
* arch/arc/src/stm32_otgfsdev.c: Bug fix: Don't process TXFE if we have
|
* arch/arc/src/stm32_otgfsdev.c: Bug fix: Don't process TXFE if we have
|
||||||
already processed an XFRC interrupt. We have already done what needs
|
already processed an XFRC interrupt. We have already done what needs
|
||||||
to done in that case.
|
to done in that case.
|
||||||
|
* arch/arc/src/stm32_otgfsdev.c: Fixed some status settings in queuing of write
|
||||||
|
messages. Added a "hack" to work around missing TxFIFO empty interrupts. The
|
||||||
|
hack is basically to poll for space in the TxFIFO instead of of setting up
|
||||||
|
the interrupt.
|
||||||
|
@ -146,6 +146,15 @@
|
|||||||
# error "CONFIG_USBDEV_EP3_TXFIFO_SIZE is out of range"
|
# error "CONFIG_USBDEV_EP3_TXFIFO_SIZE is out of range"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* REVISIT! This forces a hack that polls DTXFSTS for space in the Tx FIFO.
|
||||||
|
* Enabling this option is a BAD thing. It will cause inline waits inside
|
||||||
|
* of the USB interrupt handler. The correct way to handle this is to
|
||||||
|
* enable the correct TxFIFO interrupt and wait until the Tx FIFO is empty.
|
||||||
|
* Unfortunately, the interrupt driven logic is not working... Please fix!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ENABLE_DTXFSTS_POLLHACK 1
|
||||||
|
|
||||||
/* Debug ***********************************************************************/
|
/* Debug ***********************************************************************/
|
||||||
/* Trace error codes */
|
/* Trace error codes */
|
||||||
|
|
||||||
@ -221,11 +230,13 @@
|
|||||||
#define STM32_TRACEINTID_EPIN_EPDISD (70 + 3)
|
#define STM32_TRACEINTID_EPIN_EPDISD (70 + 3)
|
||||||
#define STM32_TRACEINTID_EPIN_TXFE (70 + 4)
|
#define STM32_TRACEINTID_EPIN_TXFE (70 + 4)
|
||||||
|
|
||||||
#define STM32_TRACEINTID_OUTNAK (80 + 0) /* RXFLVL second level decode */
|
#define STM32_TRACEINTID_EPIN_EMPWAIT (80 + 0) /* EPIN second level decode */
|
||||||
#define STM32_TRACEINTID_OUTRECVD (80 + 1)
|
|
||||||
#define STM32_TRACEINTID_OUTDONE (80 + 2)
|
#define STM32_TRACEINTID_OUTNAK (90 + 0) /* RXFLVL second level decode */
|
||||||
#define STM32_TRACEINTID_SETUPDONE (80 + 3)
|
#define STM32_TRACEINTID_OUTRECVD (90 + 1)
|
||||||
#define STM32_TRACEINTID_SETUPRECVD (80 + 4)
|
#define STM32_TRACEINTID_OUTDONE (90 + 2)
|
||||||
|
#define STM32_TRACEINTID_SETUPDONE (90 + 3)
|
||||||
|
#define STM32_TRACEINTID_SETUPRECVD (90 + 4)
|
||||||
|
|
||||||
/* Endpoints ******************************************************************/
|
/* Endpoints ******************************************************************/
|
||||||
|
|
||||||
@ -1071,17 +1082,32 @@ static void stm32_epin_request(FAR struct stm32_usbdev_s *priv,
|
|||||||
struct stm32_req_s *privreq;
|
struct stm32_req_s *privreq;
|
||||||
uint32_t regaddr;
|
uint32_t regaddr;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
|
#ifdef ENABLE_DTXFSTS_POLLHACK
|
||||||
|
int32_t timeout;
|
||||||
|
#endif
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
int nbytes;
|
int nbytes;
|
||||||
int nwords;
|
int nwords;
|
||||||
int bytesleft;
|
int bytesleft;
|
||||||
|
|
||||||
/* We get here when an IN endpoint or Tx FIFO empty interrupt occurs. So
|
/* We get here in one of four possible ways. From three interrupting
|
||||||
* now we know that there is no TX transfer in progress.
|
* events:
|
||||||
|
*
|
||||||
|
* 1. From stm32_epin as part of the transfer complete interrupt processing
|
||||||
|
* This interrupt indicates that the last transfer has completed.
|
||||||
|
* 2. As part of the ITTXFE interrupt processing. That interrupt indicates
|
||||||
|
* that an IN token was received when the associated TxFIFO was empty.
|
||||||
|
* 3. From stm32_epin_txfifoempty as part of the TXFE interrupt processing.
|
||||||
|
* The TXFE interrupt is only enabled when the TxFIFO is full and the
|
||||||
|
* software must wait for space to become available in the TxFIFO.
|
||||||
|
*
|
||||||
|
* And this function may be called immediately when the write request is
|
||||||
|
* queue to start up the next transaction.
|
||||||
|
*
|
||||||
|
* 4. From stm32_ep_submit when a new write request is received WHILE the
|
||||||
|
* endpoint is not active (privep->active == false).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
privep->active = false;
|
|
||||||
|
|
||||||
/* Check the request from the head of the endpoint request queue */
|
/* Check the request from the head of the endpoint request queue */
|
||||||
|
|
||||||
privreq = stm32_rqpeek(privep);
|
privreq = stm32_rqpeek(privep);
|
||||||
@ -1192,14 +1218,33 @@ static void stm32_epin_request(FAR struct stm32_usbdev_s *priv,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
regaddr = STM32_OTGFS_DTXFSTS(privep->epphy);
|
regaddr = STM32_OTGFS_DTXFSTS(privep->epphy);
|
||||||
regval = stm32_getreg(regaddr);
|
|
||||||
|
|
||||||
/* And terminate the loop if there is insufficient space in the TxFIFO
|
#ifdef ENABLE_DTXFSTS_POLLHACK
|
||||||
* hold the entire packet.
|
/* If ENABLE_DTXFSTS_POLLHACK is enabled , then poll DTXFSTS until
|
||||||
|
* space in the TxFIFO is available. If it doesn't become available,
|
||||||
|
* in a reasonable amount of time, then just pretend that it is.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (timeout = 250000; timeout > 0; timeout--)
|
||||||
|
{
|
||||||
|
regval = stm32_getreg(regaddr);
|
||||||
|
if ((regval & OTGFS_DTXFSTS_MASK) >= nwords)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* If ENABLE_DTXFSTS_POLLHACK is not enabled, then check once for
|
||||||
|
* space in the TxFIFO. If space in the TxFIFO is not available,
|
||||||
|
* then set up an interrupt to resume the transfer when the TxFIFO
|
||||||
|
* is empty.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
regval = stm32_getreg(regaddr);
|
||||||
if ((regval & OTGFS_DTXFSTS_MASK) < nwords)
|
if ((regval & OTGFS_DTXFSTS_MASK) < nwords)
|
||||||
{
|
{
|
||||||
|
usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_EMPWAIT), (uint16_t)regval);
|
||||||
|
|
||||||
/* There is insufficent space in the TxFIFO. Wait for a TxFIFO
|
/* There is insufficent space in the TxFIFO. Wait for a TxFIFO
|
||||||
* empty interrupt and try again.
|
* empty interrupt and try again.
|
||||||
*/
|
*/
|
||||||
@ -1207,8 +1252,12 @@ static void stm32_epin_request(FAR struct stm32_usbdev_s *priv,
|
|||||||
uint32_t empmsk = stm32_getreg(STM32_OTGFS_DIEPEMPMSK);
|
uint32_t empmsk = stm32_getreg(STM32_OTGFS_DIEPEMPMSK);
|
||||||
empmsk |= OTGFS_DIEPEMPMSK(privep->epphy);
|
empmsk |= OTGFS_DIEPEMPMSK(privep->epphy);
|
||||||
stm32_putreg(empmsk, STM32_OTGFS_DIEPEMPMSK);
|
stm32_putreg(empmsk, STM32_OTGFS_DIEPEMPMSK);
|
||||||
|
|
||||||
|
/* Terminate the transfer loop */
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Transfer data to the TxFIFO */
|
/* Transfer data to the TxFIFO */
|
||||||
|
|
||||||
@ -4099,19 +4148,26 @@ static int stm32_ep_submit(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Add the new request to the request queue for the endpoint */
|
/* Add the new request to the request queue for the endpoint. */
|
||||||
|
|
||||||
if (stm32_req_addlast(privep, privreq))
|
if (stm32_req_addlast(privep, privreq) && !privep->active)
|
||||||
{
|
{
|
||||||
/* If a request was added to an IN endpoint, then attempt to send
|
/* If a request was added to an IN endpoint, then attempt to send
|
||||||
* the request data buffer now (this will, of course, fail if there
|
* the request data buffer now.
|
||||||
* is already a transmission in progress).
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (privep->isin)
|
if (privep->isin)
|
||||||
{
|
{
|
||||||
usbtrace(TRACE_INREQQUEUED(privep->epphy), privreq->req.len);
|
usbtrace(TRACE_INREQQUEUED(privep->epphy), privreq->req.len);
|
||||||
stm32_epin_request(priv, privep);
|
|
||||||
|
/* If the endpoint is not busy with another write request,
|
||||||
|
* then process the newly received write request now.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!privep->active)
|
||||||
|
{
|
||||||
|
stm32_epin_request(priv, privep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the request was added to an OUT endoutput, then attempt to
|
/* If the request was added to an OUT endoutput, then attempt to
|
||||||
@ -4875,7 +4931,7 @@ static void stm32_hwinitialize(FAR struct stm32_usbdev_s *priv)
|
|||||||
* FS AHB configuration register.
|
* FS AHB configuration register.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
stm32_putreg(0, STM32_OTGFS_GAHBCFG);
|
stm32_putreg(OTGFS_GAHBCFG_TXFELVL, STM32_OTGFS_GAHBCFG);
|
||||||
|
|
||||||
/* Common USB OTG core initialization */
|
/* Common USB OTG core initialization */
|
||||||
/* Reset after a PHY select and set Host mode. First, wait for AHB master
|
/* Reset after a PHY select and set Host mode. First, wait for AHB master
|
||||||
@ -5068,11 +5124,11 @@ static void stm32_hwinitialize(FAR struct stm32_usbdev_s *priv)
|
|||||||
|
|
||||||
stm32_putreg(regval, STM32_OTGFS_GINTMSK);
|
stm32_putreg(regval, STM32_OTGFS_GINTMSK);
|
||||||
|
|
||||||
/* Ensable the USB global interrupt by setting GINTMSK in the global OTG
|
/* Enable the USB global interrupt by setting GINTMSK in the global OTG
|
||||||
* FS AHB configuration register.
|
* FS AHB configuration register.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
stm32_putreg(OTGFS_GAHBCFG_GINTMSK, STM32_OTGFS_GAHBCFG);
|
stm32_putreg(OTGFS_GAHBCFG_GINTMSK | OTGFS_GAHBCFG_TXFELVL, STM32_OTGFS_GAHBCFG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
Loading…
x
Reference in New Issue
Block a user