mirror of
https://github.com/apache/nuttx.git
synced 2026-05-31 05:55:46 +08:00
Integration updates
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2201 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -100,7 +100,9 @@
|
|||||||
/* Endpoint identifiers. The STM32 supports up to 16 mono-directional or 8
|
/* Endpoint identifiers. The STM32 supports up to 16 mono-directional or 8
|
||||||
* bidirectional endpoints. However, when you take into account PMA buffer
|
* bidirectional endpoints. However, when you take into account PMA buffer
|
||||||
* usage (see below) and the fact that EP0 is bidirectional, then there is
|
* usage (see below) and the fact that EP0 is bidirectional, then there is
|
||||||
* a functional limitation of EP0 + 5 mono-directional endpoints = 6.
|
* a functional limitation of EP0 + 5 mono-directional endpoints = 6. We'll
|
||||||
|
* define STM32_NENDPOINTS to be 8, however, because that is how many
|
||||||
|
* endpoint register sets there are.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define STM32_NENDPOINTS (8)
|
#define STM32_NENDPOINTS (8)
|
||||||
@@ -143,6 +145,8 @@
|
|||||||
#define STM32_EP0_RXADDR STM32_BUFFER_START
|
#define STM32_EP0_RXADDR STM32_BUFFER_START
|
||||||
#define STM32_EP0_TXADDR (STM32_EP0_RXADDR+STM32_EP0MAXPACKET)
|
#define STM32_EP0_TXADDR (STM32_EP0_RXADDR+STM32_EP0MAXPACKET)
|
||||||
|
|
||||||
|
#warning "Doesn't the buffer size need to include 2 bytes for the CRC?"
|
||||||
|
|
||||||
#define STM32_BUFFER_EP0 0x03
|
#define STM32_BUFFER_EP0 0x03
|
||||||
#define STM32_NBUFFERS 7
|
#define STM32_NBUFFERS 7
|
||||||
#define STM32_BUFFER_BIT(bn) (1 << (bn))
|
#define STM32_BUFFER_BIT(bn) (1 << (bn))
|
||||||
@@ -348,10 +352,12 @@ static void stm32_dumpep(int epno);
|
|||||||
/* Low-Level Helpers ********************************************************/
|
/* Low-Level Helpers ********************************************************/
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
stm32_epsettxcount(ubyte epno, uint16 count);
|
stm32_seteptxcount(ubyte epno, uint16 count);
|
||||||
static inline void
|
static inline void
|
||||||
stm32_seteptxaddr(ubyte epno, ubyte addr);
|
stm32_seteptxaddr(ubyte epno, ubyte addr);
|
||||||
static void stm32_epsetrxcount(ubyte epno, uint16 count);
|
static void stm32_seteprxcount(ubyte epno, uint16 count);
|
||||||
|
static inline uint16
|
||||||
|
stm32_geteprxcount(ubyte epno);
|
||||||
static inline void
|
static inline void
|
||||||
stm32_seteprxaddr(ubyte epno, ubyte addr);
|
stm32_seteprxaddr(ubyte epno, ubyte addr);
|
||||||
static inline void
|
static inline void
|
||||||
@@ -378,6 +384,9 @@ static uint16 stm32_eptxstalled(ubyte epno);
|
|||||||
static uint16 stm32_eprxstalled(ubyte epno);
|
static uint16 stm32_eprxstalled(ubyte epno);
|
||||||
static void stm32_setimask(struct stm32_usbdev_s *priv, uint16 setbits,
|
static void stm32_setimask(struct stm32_usbdev_s *priv, uint16 setbits,
|
||||||
uint16 clrbits);
|
uint16 clrbits);
|
||||||
|
|
||||||
|
/* Suspend/Resume Helpers ***************************************************/
|
||||||
|
|
||||||
static void stm32_suspend(struct stm32_usbdev_s *priv);
|
static void stm32_suspend(struct stm32_usbdev_s *priv);
|
||||||
static void stm32_initresume(struct stm32_usbdev_s *priv);
|
static void stm32_initresume(struct stm32_usbdev_s *priv);
|
||||||
static void stm32_esofpoll(struct stm32_usbdev_s *priv) ;
|
static void stm32_esofpoll(struct stm32_usbdev_s *priv) ;
|
||||||
@@ -415,15 +424,15 @@ static int stm32_lpinterrupt(int irq, void *context);
|
|||||||
/* Endpoint helpers *********************************************************/
|
/* Endpoint helpers *********************************************************/
|
||||||
|
|
||||||
static inline struct stm32_ep_s *
|
static inline struct stm32_ep_s *
|
||||||
stm32_reserveep(struct stm32_usbdev_s *priv, ubyte epset);
|
stm32_epreserve(struct stm32_usbdev_s *priv, ubyte epset);
|
||||||
static inline void
|
static inline void
|
||||||
stm32_unreserveep(struct stm32_usbdev_s *priv,
|
stm32_epunreserve(struct stm32_usbdev_s *priv,
|
||||||
struct stm32_ep_s *privep);
|
struct stm32_ep_s *privep);
|
||||||
static inline boolean
|
static inline boolean
|
||||||
stm32_epreserved(struct stm32_usbdev_s *priv, int epno);
|
stm32_epreserved(struct stm32_usbdev_s *priv, int epno);
|
||||||
static int stm32_allocpma(struct stm32_usbdev_s *priv);
|
static int stm32_epallocpma(struct stm32_usbdev_s *priv);
|
||||||
static inline void
|
static inline void
|
||||||
stm32_freepma(struct stm32_usbdev_s *priv,
|
stm32_epfreepma(struct stm32_usbdev_s *priv,
|
||||||
struct stm32_ep_s *privep);
|
struct stm32_ep_s *privep);
|
||||||
|
|
||||||
/* Endpoint operations ******************************************************/
|
/* Endpoint operations ******************************************************/
|
||||||
@@ -451,7 +460,7 @@ static int stm32_getframe(struct usbdev_s *dev);
|
|||||||
static int stm32_wakeup(struct usbdev_s *dev);
|
static int stm32_wakeup(struct usbdev_s *dev);
|
||||||
static int stm32_selfpowered(struct usbdev_s *dev, boolean selfpowered);
|
static int stm32_selfpowered(struct usbdev_s *dev, boolean selfpowered);
|
||||||
|
|
||||||
/* Initialization ***********************************************************/
|
/* Initialization/Reset *****************************************************/
|
||||||
|
|
||||||
static void stm32_reset(struct stm32_usbdev_s *priv);
|
static void stm32_reset(struct stm32_usbdev_s *priv);
|
||||||
static void stm32_hwreset(struct stm32_usbdev_s *priv);
|
static void stm32_hwreset(struct stm32_usbdev_s *priv);
|
||||||
@@ -592,7 +601,7 @@ static void stm32_dumpep(int epno)
|
|||||||
/* Endpoint register */
|
/* Endpoint register */
|
||||||
|
|
||||||
addr = STM32_USB_EPR(epno);
|
addr = STM32_USB_EPR(epno);
|
||||||
lldbg("EPR%02d: [%08x] %04x\n", epno, addr, getreg16(addr));
|
lldbg("EPR%d: [%08x] %04x\n", epno, addr, getreg16(addr));
|
||||||
|
|
||||||
/* Endpoint descriptor */
|
/* Endpoint descriptor */
|
||||||
|
|
||||||
@@ -639,12 +648,12 @@ static void stm32_checksetup(void)
|
|||||||
* Low-Level Helpers
|
* Low-Level Helpers
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32_epsettxcount
|
* Name: stm32_seteptxcount
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void stm32_epsettxcount(ubyte epno, uint16 count)
|
static inline void stm32_seteptxcount(ubyte epno, uint16 count)
|
||||||
{
|
{
|
||||||
uint32 *epaddr = (uint32*)STM32_USB_COUNT_TX(epno);
|
volatile uint32 *epaddr = (uint32*)STM32_USB_COUNT_TX(epno);
|
||||||
*epaddr = count;
|
*epaddr = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -654,17 +663,17 @@ static inline void stm32_epsettxcount(ubyte epno, uint16 count)
|
|||||||
|
|
||||||
static inline void stm32_seteptxaddr(ubyte epno, ubyte addr)
|
static inline void stm32_seteptxaddr(ubyte epno, ubyte addr)
|
||||||
{
|
{
|
||||||
uint32 *txaddr = (uint32*)STM32_USB_ADDR_TX(epno);
|
volatile uint32 *txaddr = (uint32*)STM32_USB_ADDR_TX(epno);
|
||||||
*txaddr = addr;
|
*txaddr = addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32_epsetrxcount
|
* Name: stm32_seteprxcount
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void stm32_epsetrxcount(ubyte epno, uint16 count)
|
static void stm32_seteprxcount(ubyte epno, uint16 count)
|
||||||
{
|
{
|
||||||
uint32 *epaddr = (uint32*)STM32_USB_COUNT_RX(epno);
|
volatile uint32 *epaddr = (uint32*)STM32_USB_COUNT_RX(epno);
|
||||||
uint16 nblocks;
|
uint16 nblocks;
|
||||||
|
|
||||||
/* The upper bits of the RX COUNT value contain the size of allocated
|
/* The upper bits of the RX COUNT value contain the size of allocated
|
||||||
@@ -703,13 +712,23 @@ static void stm32_epsetrxcount(ubyte epno, uint16 count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stm32_geteprxcount
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static inline uint16 stm32_geteprxcount(ubyte epno)
|
||||||
|
{
|
||||||
|
volatile uint32 *epaddr = (uint32*)STM32_USB_COUNT_RX(epno);
|
||||||
|
return (*epaddr) & USB_COUNT_RX_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32_seteprxaddr
|
* Name: stm32_seteprxaddr
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void stm32_seteprxaddr(ubyte epno, ubyte addr)
|
static inline void stm32_seteprxaddr(ubyte epno, ubyte addr)
|
||||||
{
|
{
|
||||||
uint32 *rxaddr = (uint32*)STM32_USB_ADDR_RX(epno);
|
volatile uint32 *rxaddr = (uint32*)STM32_USB_ADDR_RX(epno);
|
||||||
*rxaddr = addr;
|
*rxaddr = addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1130,7 +1149,7 @@ static void stm32_epwrite(struct stm32_usbdev_s *priv,
|
|||||||
|
|
||||||
/* Send the packet (might be a null packet nbytes == 0) */
|
/* Send the packet (might be a null packet nbytes == 0) */
|
||||||
|
|
||||||
stm32_epsettxcount(epno, nbytes);
|
stm32_seteptxcount(epno, nbytes);
|
||||||
priv->txstatus = USB_EPR_STATTX_VALID;
|
priv->txstatus = USB_EPR_STATTX_VALID;
|
||||||
|
|
||||||
/* Indicate that there is data in the TX packet memory. This will be cleared
|
/* Indicate that there is data in the TX packet memory. This will be cleared
|
||||||
@@ -1243,10 +1262,13 @@ static int stm32_rdrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *prive
|
|||||||
{
|
{
|
||||||
struct stm32_req_s *privreq;
|
struct stm32_req_s *privreq;
|
||||||
ubyte *buf;
|
ubyte *buf;
|
||||||
|
ubyte epno;
|
||||||
|
int pmalen;
|
||||||
int readlen;
|
int readlen;
|
||||||
|
|
||||||
/* Check the request from the head of the endpoint request queue */
|
/* Check the request from the head of the endpoint request queue */
|
||||||
|
|
||||||
|
epno = USB_EPNO(privep->ep.eplog);
|
||||||
privreq = stm32_rqpeek(privep);
|
privreq = stm32_rqpeek(privep);
|
||||||
if (!privreq)
|
if (!privreq)
|
||||||
{
|
{
|
||||||
@@ -1255,13 +1277,12 @@ static int stm32_rdrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *prive
|
|||||||
* soon.
|
* soon.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUTQEMPTY), 0);
|
usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUTQEMPTY), epno);
|
||||||
priv->rxpending = TRUE;
|
priv->rxpending = TRUE;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ullvdbg("len=%d xfrd=%d nullpkt=%d\n",
|
ullvdbg("EP%d: len=%d xfrd=%d\n", epno, privreq->req.len, privreq->req.xfrd);
|
||||||
privreq->req.len, privreq->req.xfrd, privep->txnullpkt);
|
|
||||||
|
|
||||||
/* Ignore any attempt to receive a zero length packet */
|
/* Ignore any attempt to receive a zero length packet */
|
||||||
|
|
||||||
@@ -1274,10 +1295,15 @@ static int stm32_rdrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *prive
|
|||||||
|
|
||||||
usbtrace(TRACE_READ(USB_EPNO(privep->ep.eplog)), privreq->req.xfrd);
|
usbtrace(TRACE_READ(USB_EPNO(privep->ep.eplog)), privreq->req.xfrd);
|
||||||
|
|
||||||
|
/* Get the number of bytes to read from packet memory */
|
||||||
|
#warning "Doesn't this length include 2 bytes for the CRC?"
|
||||||
|
|
||||||
|
pmalen = stm32_geteprxcount(epno);
|
||||||
|
|
||||||
/* Receive the next packet */
|
/* Receive the next packet */
|
||||||
|
|
||||||
buf = privreq->req.buf + privreq->req.xfrd;
|
buf = privreq->req.buf + privreq->req.xfrd;
|
||||||
readlen = MIN(privreq->req.len, privep->ep.maxpacket);
|
readlen = MIN(privreq->req.len, pmalen);
|
||||||
stm32_copyfrompma(buf, (uint16)STM32_USB_ADDR_TX(EP0), readlen);
|
stm32_copyfrompma(buf, (uint16)STM32_USB_ADDR_TX(EP0), readlen);
|
||||||
|
|
||||||
/* If the receive buffer is full then we are finished with the transfer */
|
/* If the receive buffer is full then we are finished with the transfer */
|
||||||
@@ -1285,7 +1311,7 @@ static int stm32_rdrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *prive
|
|||||||
privreq->req.xfrd += readlen;
|
privreq->req.xfrd += readlen;
|
||||||
if (privreq->req.xfrd >= privreq->req.len)
|
if (privreq->req.xfrd >= privreq->req.len)
|
||||||
{
|
{
|
||||||
usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)), privreq->req.xfrd);
|
usbtrace(TRACE_COMPLETE(epno), privreq->req.xfrd);
|
||||||
priv->devstate = DEVSTATE_IDLE;
|
priv->devstate = DEVSTATE_IDLE;
|
||||||
priv->rxstatus = USB_EPR_STATRX_VALID; /* Re-enable for next data reception */
|
priv->rxstatus = USB_EPR_STATRX_VALID; /* Re-enable for next data reception */
|
||||||
stm32_reqcomplete(privep, OK);
|
stm32_reqcomplete(privep, OK);
|
||||||
@@ -1342,7 +1368,7 @@ static int stm32_dispatchrequest(struct stm32_usbdev_s *priv)
|
|||||||
|
|
||||||
static void stm32_ep0post(struct stm32_usbdev_s *priv)
|
static void stm32_ep0post(struct stm32_usbdev_s *priv)
|
||||||
{
|
{
|
||||||
stm32_epsetrxcount(EP0, STM32_EP0MAXPACKET);
|
stm32_seteprxcount(EP0, STM32_EP0MAXPACKET);
|
||||||
if (priv->devstate == DEVSTATE_STALLED)
|
if (priv->devstate == DEVSTATE_STALLED)
|
||||||
{
|
{
|
||||||
priv->rxstatus = USB_EPR_STATRX_STALL;
|
priv->rxstatus = USB_EPR_STATRX_STALL;
|
||||||
@@ -2178,10 +2204,12 @@ static int stm32_lpinterrupt(int irq, void *context)
|
|||||||
|
|
||||||
if ((istr & USB_ISTR_RESET) != 0)
|
if ((istr & USB_ISTR_RESET) != 0)
|
||||||
{
|
{
|
||||||
/* Wakeup interrupt received. Clear the WKUP interrupt status. */
|
/* Wakeup interrupt received. Clear the WKUP interrupt status. The cause of
|
||||||
|
* the wakeup is indicated in the FNR register
|
||||||
|
*/
|
||||||
|
|
||||||
stm32_putreg(~USB_ISTR_RESET, STM32_USB_ISTR);
|
stm32_putreg(~USB_ISTR_RESET, STM32_USB_ISTR);
|
||||||
usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_RESET), 0);
|
usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_RESET), stm32_getreg(STM32_USB_FNR));
|
||||||
|
|
||||||
/* Restore our power-up state and exit now because istr is no longer
|
/* Restore our power-up state and exit now because istr is no longer
|
||||||
* valid.
|
* valid.
|
||||||
@@ -2208,15 +2236,11 @@ static int stm32_lpinterrupt(int irq, void *context)
|
|||||||
priv->rsmstate = RSMSTATE_IDLE;
|
priv->rsmstate = RSMSTATE_IDLE;
|
||||||
|
|
||||||
/* Disable ESOF polling, disable the wakeup interrupt, and
|
/* Disable ESOF polling, disable the wakeup interrupt, and
|
||||||
* re-enable the suspend interrupt.
|
* re-enable the suspend interrupt. Clear any pending SUSP
|
||||||
|
* interrupts.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
priv->imask &= ~(USB_CNTR_ESOFM|USB_CNTR_WKUPM);
|
stm32_setimask(priv, USB_CNTR_SUSPM, USB_CNTR_ESOFM|USB_CNTR_WKUPM);
|
||||||
priv->imask |= USB_CNTR_SUSPM;
|
|
||||||
stm32_putreg(priv->imask, STM32_USB_CNTR);
|
|
||||||
|
|
||||||
/* Clear any pending interrupts that we just enabled */
|
|
||||||
|
|
||||||
stm32_putreg(~USB_CNTR_SUSPM, STM32_USB_ISTR);
|
stm32_putreg(~USB_CNTR_SUSPM, STM32_USB_ISTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2277,6 +2301,9 @@ stm32_setimask(struct stm32_usbdev_s *priv, uint16 setbits, uint16 clrbits)
|
|||||||
stm32_putreg(regval, STM32_USB_CNTR);
|
stm32_putreg(regval, STM32_USB_CNTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Suspend/Resume Helpers
|
||||||
|
****************************************************************************/
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32_suspend
|
* Name: stm32_suspend
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -2292,20 +2319,31 @@ static void stm32_suspend(struct stm32_usbdev_s *priv)
|
|||||||
stm32_setimask(priv, USB_CNTR_WKUPM, USB_CNTR_ESOFM|USB_CNTR_SUSPM);
|
stm32_setimask(priv, USB_CNTR_WKUPM, USB_CNTR_ESOFM|USB_CNTR_SUSPM);
|
||||||
stm32_putreg(~USB_ISTR_WKUP, STM32_USB_ISTR);
|
stm32_putreg(~USB_ISTR_WKUP, STM32_USB_ISTR);
|
||||||
|
|
||||||
/* Enter suspend mode */
|
/* Set the FSUSP bit in the CNTR register. This activates suspend mode
|
||||||
|
* within the USB peripheral and disables further SUSP interrupts.
|
||||||
|
*/
|
||||||
|
|
||||||
regval = stm32_getreg(STM32_USB_CNTR);
|
regval = stm32_getreg(STM32_USB_CNTR);
|
||||||
regval |= USB_CNTR_FSUSP;
|
regval |= USB_CNTR_FSUSP;
|
||||||
stm32_putreg(regval, STM32_USB_CNTR);
|
stm32_putreg(regval, STM32_USB_CNTR);
|
||||||
|
|
||||||
/* Only works with bus-powered devices */
|
/* If we are not a self-powered device, the got to low-power mode */
|
||||||
/* Force low-power mode in the macrocell */
|
|
||||||
|
if (!priv->selfpowered)
|
||||||
|
{
|
||||||
|
/* Setting LPMODE in the CNTR register removes static power
|
||||||
|
* consumption in the USB analog transceivers but keeps them
|
||||||
|
* able to detect resume activity
|
||||||
|
*/
|
||||||
|
|
||||||
regval = stm32_getreg(STM32_USB_CNTR);
|
regval = stm32_getreg(STM32_USB_CNTR);
|
||||||
regval |= USB_CNTR_LPMODE;
|
regval |= USB_CNTR_LPMODE;
|
||||||
stm32_putreg(regval, STM32_USB_CNTR);
|
stm32_putreg(regval, STM32_USB_CNTR);
|
||||||
|
}
|
||||||
|
|
||||||
/* Enter reduce-power consumption mode */
|
/* Let the board-specific logic know that we have entered the suspend
|
||||||
|
* state
|
||||||
|
*/
|
||||||
|
|
||||||
stm32_usbsuspend((struct usbdev_s *)priv, FALSE);
|
stm32_usbsuspend((struct usbdev_s *)priv, FALSE);
|
||||||
}
|
}
|
||||||
@@ -2318,18 +2356,25 @@ static void stm32_initresume(struct stm32_usbdev_s *priv)
|
|||||||
{
|
{
|
||||||
uint16 regval;
|
uint16 regval;
|
||||||
|
|
||||||
/* Only works on bus-powered devices */
|
/* This function is called when either (1) a WKUP interrupt is received from
|
||||||
/* USB_CNTR_LPMODE = 0 */
|
* the host PC, or (2) the class device implementation calls the wakeup()
|
||||||
|
* method.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Clear the USB low power mode (lower power mode was not set if this is
|
||||||
|
* a self-powered device. Also, low power mode is automatically cleared by
|
||||||
|
* hardware when a WKUP interrupt event occurs).
|
||||||
|
*/
|
||||||
|
|
||||||
regval = stm32_getreg(STM32_USB_CNTR);
|
regval = stm32_getreg(STM32_USB_CNTR);
|
||||||
regval &= (~USB_CNTR_LPMODE);
|
regval &= (~USB_CNTR_LPMODE);
|
||||||
stm32_putreg(regval, STM32_USB_CNTR);
|
stm32_putreg(regval, STM32_USB_CNTR);
|
||||||
|
|
||||||
/* Restore full power */
|
/* Restore full power -- whatever that means for this particular board */
|
||||||
|
|
||||||
stm32_usbsuspend((struct usbdev_s *)priv, TRUE);
|
stm32_usbsuspend((struct usbdev_s *)priv, TRUE);
|
||||||
|
|
||||||
/* Reset FSUSP bit */
|
/* Reset FSUSP bit and enable normal interrupt handling */
|
||||||
|
|
||||||
stm32_putreg(STM32_CNTR_SETUP, STM32_USB_CNTR);
|
stm32_putreg(STM32_CNTR_SETUP, STM32_USB_CNTR);
|
||||||
}
|
}
|
||||||
@@ -2389,11 +2434,11 @@ static void stm32_esofpoll(struct stm32_usbdev_s *priv)
|
|||||||
* Endpoint Helpers
|
* Endpoint Helpers
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32_reserveep
|
* Name: stm32_epreserve
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline struct stm32_ep_s *
|
static inline struct stm32_ep_s *
|
||||||
stm32_reserveep(struct stm32_usbdev_s *priv, ubyte epset)
|
stm32_epreserve(struct stm32_usbdev_s *priv, ubyte epset)
|
||||||
{
|
{
|
||||||
struct stm32_ep_s *privep = NULL;
|
struct stm32_ep_s *privep = NULL;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
@@ -2429,11 +2474,11 @@ stm32_reserveep(struct stm32_usbdev_s *priv, ubyte epset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32_unreserveep
|
* Name: stm32_epunreserve
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
stm32_unreserveep(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep)
|
stm32_epunreserve(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep)
|
||||||
{
|
{
|
||||||
irqstate_t flags = irqsave();
|
irqstate_t flags = irqsave();
|
||||||
priv->epavail |= STM32_ENDP_BIT(USB_EPNO(privep->ep.eplog));
|
priv->epavail |= STM32_ENDP_BIT(USB_EPNO(privep->ep.eplog));
|
||||||
@@ -2451,10 +2496,10 @@ stm32_epreserved(struct stm32_usbdev_s *priv, int epno)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32_allocpma
|
* Name: stm32_epallocpma
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int stm32_allocpma(struct stm32_usbdev_s *priv)
|
static int stm32_epallocpma(struct stm32_usbdev_s *priv)
|
||||||
{
|
{
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
int bufno = ERROR;
|
int bufno = ERROR;
|
||||||
@@ -2484,11 +2529,11 @@ static int stm32_allocpma(struct stm32_usbdev_s *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32_freepma
|
* Name: stm32_epfreepma
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
stm32_freepma(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep)
|
stm32_epfreepma(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep)
|
||||||
{
|
{
|
||||||
irqstate_t flags = irqsave();
|
irqstate_t flags = irqsave();
|
||||||
priv->epavail |= STM32_ENDP_BIT(privep->bufno);
|
priv->epavail |= STM32_ENDP_BIT(privep->bufno);
|
||||||
@@ -2590,7 +2635,7 @@ static int stm32_epconfigure(struct usbdev_ep_s *ep,
|
|||||||
/* Set up RX; disable TX */
|
/* Set up RX; disable TX */
|
||||||
|
|
||||||
stm32_seteprxaddr(epno, pma);
|
stm32_seteprxaddr(epno, pma);
|
||||||
stm32_epsetrxcount(epno, maxpacket);
|
stm32_seteprxcount(epno, maxpacket);
|
||||||
stm32_seteprxstatus(epno, USB_EPR_STATRX_VALID);
|
stm32_seteprxstatus(epno, USB_EPR_STATRX_VALID);
|
||||||
stm32_seteptxstatus(epno, USB_EPR_STATTX_DIS);
|
stm32_seteptxstatus(epno, USB_EPR_STATTX_DIS);
|
||||||
}
|
}
|
||||||
@@ -2627,7 +2672,7 @@ static int stm32_epdisable(struct usbdev_ep_s *ep)
|
|||||||
|
|
||||||
/* Disable TX; disable RX */
|
/* Disable TX; disable RX */
|
||||||
|
|
||||||
stm32_epsetrxcount(epno, 0);
|
stm32_seteprxcount(epno, 0);
|
||||||
stm32_seteprxstatus(epno, USB_EPR_STATRX_DIS);
|
stm32_seteprxstatus(epno, USB_EPR_STATRX_DIS);
|
||||||
stm32_seteptxstatus(epno, USB_EPR_STATTX_DIS);
|
stm32_seteptxstatus(epno, USB_EPR_STATTX_DIS);
|
||||||
|
|
||||||
@@ -2870,7 +2915,7 @@ static int stm32_epstall(struct usbdev_ep_s *ep, boolean resume)
|
|||||||
{
|
{
|
||||||
/* After clear the STALL, enable the default endpoint receiver */
|
/* After clear the STALL, enable the default endpoint receiver */
|
||||||
|
|
||||||
stm32_epsetrxcount(epno, ep->maxpacket);
|
stm32_seteprxcount(epno, ep->maxpacket);
|
||||||
stm32_seteprxstatus(epno, USB_EPR_STATRX_VALID);
|
stm32_seteprxstatus(epno, USB_EPR_STATRX_VALID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2969,7 +3014,7 @@ static struct usbdev_ep_s *stm32_allocep(struct usbdev_s *dev, ubyte epno,
|
|||||||
|
|
||||||
/* Check if the selected endpoint number is available */
|
/* Check if the selected endpoint number is available */
|
||||||
|
|
||||||
privep = stm32_reserveep(priv, epset);
|
privep = stm32_epreserve(priv, epset);
|
||||||
if (!privep)
|
if (!privep)
|
||||||
{
|
{
|
||||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPRESERVE), (uint16)epset);
|
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPRESERVE), (uint16)epset);
|
||||||
@@ -2980,7 +3025,7 @@ static struct usbdev_ep_s *stm32_allocep(struct usbdev_s *dev, ubyte epno,
|
|||||||
/* Allocate a PMA buffer for this endpoint */
|
/* Allocate a PMA buffer for this endpoint */
|
||||||
|
|
||||||
#warning "REVISIT: Should configure BULK EPs using double buffer feature"
|
#warning "REVISIT: Should configure BULK EPs using double buffer feature"
|
||||||
bufno = stm32_allocpma(priv);
|
bufno = stm32_epallocpma(priv);
|
||||||
if (bufno < 0)
|
if (bufno < 0)
|
||||||
{
|
{
|
||||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPBUFFER), 0);
|
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPBUFFER), 0);
|
||||||
@@ -2990,7 +3035,7 @@ static struct usbdev_ep_s *stm32_allocep(struct usbdev_s *dev, ubyte epno,
|
|||||||
return &privep->ep;
|
return &privep->ep;
|
||||||
|
|
||||||
errout_with_ep:
|
errout_with_ep:
|
||||||
stm32_unreserveep(priv, privep);
|
stm32_epunreserve(priv, privep);
|
||||||
errout:
|
errout:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -3019,11 +3064,11 @@ static void stm32_freeep(struct usbdev_s *dev, struct usbdev_ep_s *ep)
|
|||||||
{
|
{
|
||||||
/* Free the PMA buffer assigned to this endpoint */
|
/* Free the PMA buffer assigned to this endpoint */
|
||||||
|
|
||||||
stm32_freepma(priv, privep);
|
stm32_epfreepma(priv, privep);
|
||||||
|
|
||||||
/* Mark the endpoint as available */
|
/* Mark the endpoint as available */
|
||||||
|
|
||||||
stm32_unreserveep(priv, privep);
|
stm32_epunreserve(priv, privep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3111,7 +3156,7 @@ static int stm32_selfpowered(struct usbdev_s *dev, boolean selfpowered)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Initialization
|
* Initialization/Reset
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -3170,10 +3215,6 @@ static void stm32_hwreset(struct stm32_usbdev_s *priv)
|
|||||||
priv->imask = 0;
|
priv->imask = 0;
|
||||||
stm32_putreg(priv->imask, STM32_USB_CNTR);
|
stm32_putreg(priv->imask, STM32_USB_CNTR);
|
||||||
|
|
||||||
/* Clear any pending interrupts */
|
|
||||||
|
|
||||||
stm32_putreg(0, STM32_USB_ISTR);
|
|
||||||
|
|
||||||
/* Set the STM32 BTABLE address */
|
/* Set the STM32 BTABLE address */
|
||||||
|
|
||||||
stm32_putreg(STM32_BTABLE_ADDRESS & 0xfff8, STM32_USB_BTABLE);
|
stm32_putreg(STM32_BTABLE_ADDRESS & 0xfff8, STM32_USB_BTABLE);
|
||||||
@@ -3183,7 +3224,7 @@ static void stm32_hwreset(struct stm32_usbdev_s *priv)
|
|||||||
stm32_seteptype(EP0, USB_EPR_EPTYPE_CONTROL);
|
stm32_seteptype(EP0, USB_EPR_EPTYPE_CONTROL);
|
||||||
stm32_seteptxstatus(EP0, USB_EPR_STATTX_NAK);
|
stm32_seteptxstatus(EP0, USB_EPR_STATTX_NAK);
|
||||||
stm32_seteprxaddr(EP0, STM32_EP0_RXADDR);
|
stm32_seteprxaddr(EP0, STM32_EP0_RXADDR);
|
||||||
stm32_epsetrxcount(EP0, STM32_EP0MAXPACKET);
|
stm32_seteprxcount(EP0, STM32_EP0MAXPACKET);
|
||||||
stm32_seteptxaddr(EP0, STM32_EP0_TXADDR);
|
stm32_seteptxaddr(EP0, STM32_EP0_TXADDR);
|
||||||
stm32_clrstatusout(EP0);
|
stm32_clrstatusout(EP0);
|
||||||
stm32_seteprxstatus(EP0, USB_EPR_STATRX_VALID);
|
stm32_seteprxstatus(EP0, USB_EPR_STATRX_VALID);
|
||||||
@@ -3192,6 +3233,10 @@ static void stm32_hwreset(struct stm32_usbdev_s *priv)
|
|||||||
|
|
||||||
stm32_setdevaddr(priv, 0);
|
stm32_setdevaddr(priv, 0);
|
||||||
|
|
||||||
|
/* Clear any pending interrupts */
|
||||||
|
|
||||||
|
stm32_putreg(0, STM32_USB_ISTR);
|
||||||
|
|
||||||
/* Enable interrupts at the USB controller */
|
/* Enable interrupts at the USB controller */
|
||||||
|
|
||||||
stm32_setimask(priv, STM32_CNTR_SETUP, (USB_CNTR_ALLINTS & ~STM32_CNTR_SETUP));
|
stm32_setimask(priv, STM32_CNTR_SETUP, (USB_CNTR_ALLINTS & ~STM32_CNTR_SETUP));
|
||||||
@@ -3279,18 +3324,18 @@ void up_usbinitialize(void)
|
|||||||
|
|
||||||
/* Power up the USB controller, holding it in reset. There is a delay of
|
/* Power up the USB controller, holding it in reset. There is a delay of
|
||||||
* about 1uS after applying power before the USB will behave predictably.
|
* about 1uS after applying power before the USB will behave predictably.
|
||||||
* One millisecond is more than enough.
|
* A 5MS delay is more than enough. NOTE that we leave the USB controller
|
||||||
|
* in the reset state; the hardware will not be initialized until the
|
||||||
|
* class driver has been bound.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
stm32_putreg(USB_CNTR_FRES, STM32_USB_CNTR);
|
stm32_putreg(USB_CNTR_FRES, STM32_USB_CNTR);
|
||||||
up_mdelay(1);
|
up_mdelay(5);
|
||||||
|
|
||||||
/* Setup the USB controller */
|
/* Attach USB controller interrupt handlers. The hardware will not be
|
||||||
|
* initialized and interrupts will not be enabled until the class device
|
||||||
stm32_hwreset(priv);
|
* driver is bound. Getting the IRQs here only makes sure that we have
|
||||||
|
* them when we need them later.
|
||||||
/* Attach USB controller interrupt handlers. Interrupts will not be
|
|
||||||
* enabled until the class device is registered
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (irq_attach(STM32_IRQ_USBHPCANTX, stm32_hpinterrupt) != 0)
|
if (irq_attach(STM32_IRQ_USBHPCANTX, stm32_hpinterrupt) != 0)
|
||||||
@@ -3421,7 +3466,11 @@ int usbdev_register(struct usbdevclass_driver_s *driver)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Enable USB controller interrupts */
|
/* Setup the USB controller -- enabling interrupts at the USB controller */
|
||||||
|
|
||||||
|
stm32_hwreset(priv);
|
||||||
|
|
||||||
|
/* Enable USB controller interrupts at the NVIC */
|
||||||
|
|
||||||
up_enable_irq(STM32_IRQ_USBHPCANTX);
|
up_enable_irq(STM32_IRQ_USBHPCANTX);
|
||||||
up_enable_irq(STM32_IRQ_USBLPCANRX0);
|
up_enable_irq(STM32_IRQ_USBLPCANRX0);
|
||||||
|
|||||||
Reference in New Issue
Block a user