STM32 OTF FS device patches from Petteri Aimonen (patches 0001-0003)

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5687 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2013-02-28 16:53:16 +00:00
parent be1b67a1a2
commit d0f21192e0

View file

@ -1,7 +1,7 @@
/*******************************************************************************
* arch/arm/src/stm32/stm32_usbdev.c
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -168,16 +168,18 @@
#define STM32_TRACEERR_EP0NOSETUP 0x11
#define STM32_TRACEERR_EP0SETUPSTALLED 0x12
#define STM32_TRACEERR_EPINNULLPACKET 0x13
#define STM32_TRACEERR_EPOUTNULLPACKET 0x14
#define STM32_TRACEERR_INVALIDCTRLREQ 0x15
#define STM32_TRACEERR_INVALIDPARMS 0x16
#define STM32_TRACEERR_IRQREGISTRATION 0x17
#define STM32_TRACEERR_NOEP 0x18
#define STM32_TRACEERR_NOTCONFIGURED 0x19
#define STM32_TRACEERR_EPOUTQEMPTY 0x1a
#define STM32_TRACEERR_EPINREQEMPTY 0x1b
#define STM32_TRACEERR_NOOUTSETUP 0x1c
#define STM32_TRACEERR_POLLTIMEOUT 0x1d
#define STM32_TRACEERR_EPINUNEXPECTED 0x14
#define STM32_TRACEERR_EPOUTNULLPACKET 0x15
#define STM32_TRACEERR_EPOUTUNEXPECTED 0x16
#define STM32_TRACEERR_INVALIDCTRLREQ 0x17
#define STM32_TRACEERR_INVALIDPARMS 0x18
#define STM32_TRACEERR_IRQREGISTRATION 0x19
#define STM32_TRACEERR_NOEP 0x1a
#define STM32_TRACEERR_NOTCONFIGURED 0x1b
#define STM32_TRACEERR_EPOUTQEMPTY 0x1c
#define STM32_TRACEERR_EPINREQEMPTY 0x1d
#define STM32_TRACEERR_NOOUTSETUP 0x1e
#define STM32_TRACEERR_POLLTIMEOUT 0x1f
/* Trace interrupt codes */
@ -704,7 +706,9 @@ const struct trace_msg_t g_usb_trace_strings_deverror[] =
TRACE_STR(STM32_TRACEERR_EP0NOSETUP ),
TRACE_STR(STM32_TRACEERR_EP0SETUPSTALLED ),
TRACE_STR(STM32_TRACEERR_EPINNULLPACKET ),
TRACE_STR(STM32_TRACEERR_EPINUNEXPECTED ),
TRACE_STR(STM32_TRACEERR_EPOUTNULLPACKET ),
TRACE_STR(STM32_TRACEERR_EPOUTUNEXPECTED ),
TRACE_STR(STM32_TRACEERR_INVALIDCTRLREQ ),
TRACE_STR(STM32_TRACEERR_INVALIDPARMS ),
TRACE_STR(STM32_TRACEERR_IRQREGISTRATION ),
@ -2595,6 +2599,41 @@ static inline void stm32_epout_interrupt(FAR struct stm32_usbdev_s *priv)
regval &= stm32_getreg(STM32_OTGFS_DAINTMSK);
daint = (regval & OTGFS_DAINT_OEP_MASK) >> OTGFS_DAINT_OEP_SHIFT;
if (daint == 0)
{
/* We got an interrupt, but there is no unmasked endpoint that caused
* it ?! When this happens, the interrupt flag never gets cleared and
* we are stuck in infinite interrupt loop.
*
* This shouldn't happen if we are diligent about handling timing
* issues when masking endpoint interrupts. However, this workaround
* avoids infinite loop and allows operation to continue normally. It
* works by clearing each endpoint flags, masked or not.
*/
regval = stm32_getreg(STM32_OTGFS_DAINT);
daint = (regval & OTGFS_DAINT_OEP_MASK) >> OTGFS_DAINT_OEP_SHIFT;
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPOUTUNEXPECTED),
(uint16_t)regval);
epno = 0;
while (daint)
{
if ((daint & 1) != 0)
{
regval = stm32_getreg(STM32_OTGFS_DOEPINT(epno));
ulldbg("DOEPINT(%d) = %08x\n", epno, regval);
stm32_putreg(0xFF, STM32_OTGFS_DOEPINT(epno));
}
epno++;
daint >>= 1;
}
return;
}
/* Process each pending IN endpoint interrupt */
epno = 0;
@ -2791,6 +2830,41 @@ static inline void stm32_epin_interrupt(FAR struct stm32_usbdev_s *priv)
daint &= stm32_getreg(STM32_OTGFS_DAINTMSK);
daint &= OTGFS_DAINT_IEP_MASK;
if (daint == 0)
{
/* We got an interrupt, but there is no unmasked endpoint that caused
* it ?! When this happens, the interrupt flag never gets cleared and
* we are stuck in infinite interrupt loop.
*
* This shouldn't happen if we are diligent about handling timing
* issues when masking endpoint interrupts. However, this workaround
* avoids infinite loop and allows operation to continue normally. It
* works by clearing each endpoint flags, masked or not.
*/
daint = stm32_getreg(STM32_OTGFS_DAINT);
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPINUNEXPECTED),
(uint16_t)daint);
daint &= OTGFS_DAINT_IEP_MASK;
epno = 0;
while (daint)
{
if ((daint & 1) != 0)
{
ulldbg("DIEPINT(%d) = %08x\n",
epno, stm32_getreg(STM32_OTGFS_DIEPINT(epno)));
stm32_putreg(0xFF, STM32_OTGFS_DIEPINT(epno));
}
epno++;
daint >>= 1;
}
return;
}
/* Process each pending IN endpoint interrupt */
epno = 0;
@ -3976,6 +4050,10 @@ static void stm32_epout_disable(FAR struct stm32_ep_s *privep)
up_mdelay(50);
#endif
/* Clear the EPDISD interrupt */
stm32_putreg(OTGFS_DOEPINT_EPDISD, STM32_OTGFS_DOEPINT(privep->epphy));
/* Then disble the Global OUT NAK mode to continue receiving data
* from other non-disabled OUT endpoints.
*/
@ -4022,6 +4100,12 @@ static void stm32_epin_disable(FAR struct stm32_ep_s *privep)
return;
}
/* This INEPNE wait logic is suggested by reference manual, but seems
* to get stuck to infinite loop.
*/
#if 0
/* Make sure that there is no pending IPEPNE interrupt (because we are
* to poll this bit below).
*/
@ -4042,7 +4126,9 @@ static void stm32_epin_disable(FAR struct stm32_ep_s *privep)
while ((stm32_getreg(regaddr) & OTGFS_DIEPINT_INEPNE) == 0);
stm32_putreg(OTGFS_DIEPINT_INEPNE, regaddr);
/* Deactivate and disable the endpoint by setting the EPIS and SNAK bits
#endif
/* Deactivate and disable the endpoint by setting the EPDIS and SNAK bits
* the DIEPCTLx register.
*/
@ -4060,6 +4146,10 @@ static void stm32_epin_disable(FAR struct stm32_ep_s *privep)
regaddr = STM32_OTGFS_DIEPINT(privep->epphy);
while ((stm32_getreg(regaddr) & OTGFS_DIEPINT_EPDISD) == 0);
/* Clear the EPDISD interrupt */
stm32_putreg(OTGFS_DIEPINT_EPDISD, stm32_getreg(regaddr));
/* Flush any data remaining in the TxFIFO */
stm32_txfifo_flush(OTGFS_GRSTCTL_TXFNUM_D(privep->epphy));