Add STM32 OTG FS device endpoint stall logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4556 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
7f31ea84b7
commit
1f6d3d6c26
@ -511,7 +511,7 @@ fi
|
||||
<table width ="100%">
|
||||
<tr bgcolor="#e4e4e4">
|
||||
<td>
|
||||
<a name="startupscript"><h2>1.7 NSH Start-Up Scrip</h2></a>
|
||||
<a name="startupscript"><h2>1.7 NSH Start-Up Script</h2></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -508,7 +508,17 @@ static int stm32_epsubmit(FAR struct usbdev_ep_s *ep,
|
||||
struct usbdev_req_s *req);
|
||||
static int stm32_epcancel(FAR struct usbdev_ep_s *ep,
|
||||
struct usbdev_req_s *req);
|
||||
|
||||
/* Stall handling */
|
||||
|
||||
static int stm32_epsetstall(FAR struct stm32_usbdev_s *priv,
|
||||
FAR struct stm32_ep_s *privep);
|
||||
static int stm32_epclrstall(FAR struct stm32_usbdev_s *priv,
|
||||
FAR struct stm32_ep_s *privep)
|
||||
static int stm32_epstall(FAR struct usbdev_ep_s *ep, bool resume);
|
||||
static void stm32_ep0stall(FAR struct stm32_usbdev_s *priv);
|
||||
|
||||
/* Endpoint allocation */
|
||||
|
||||
static FAR struct usbdev_ep_s *stm32_allocep(FAR struct usbdev_s *dev,
|
||||
uint8_t epno, bool in, uint8_t eptype);
|
||||
@ -1415,7 +1425,7 @@ static inline void stm32_stdrequest(struct stm32_usbdev_s *priv,
|
||||
else if (priv->paddrset != 0 && ctrlreq->value == USB_FEATURE_ENDPOINTHALT && ctrlreq->len == 0 &&
|
||||
(privep = stm32_epfindbyaddr(priv, ctrlreq->index)) != NULL)
|
||||
{
|
||||
stm32_epstall(&privep->ep, true);
|
||||
stm32_epclrstall(priv, &privep->ep);
|
||||
stm32_ep0state(priv, EP0STATE_NAK_IN);
|
||||
}
|
||||
else
|
||||
@ -1447,7 +1457,7 @@ static inline void stm32_stdrequest(struct stm32_usbdev_s *priv,
|
||||
else if (priv->paddrset != 0 && ctrlreq->value == USB_FEATURE_ENDPOINTHALT && ctrlreq->len == 0 &&
|
||||
(privep = stm32_epfindbyaddr(priv, ctrlreq->index)) != NULL)
|
||||
{
|
||||
stm32_epstall(&privep->ep, false);
|
||||
stm32_epsetstall(priv, privep);
|
||||
stm32_ep0state(priv, EP0STATE_NAK_IN);
|
||||
}
|
||||
else
|
||||
@ -1663,8 +1673,7 @@ static inline void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
if (priv->stalled)
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EP0SETUPSTALLED), priv->ep0state);
|
||||
stm32_epstall(&priv->epin[STM32_EP0_IN].ep, false);
|
||||
stm32_epstall(&priv->epin[STM32_EP0_OUT].ep, false);
|
||||
stm32_ep0stall(priv);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1745,8 +1754,7 @@ static void stm32_ep0complete(struct stm32_usbdev_s *priv, uint8_t epphy)
|
||||
if (priv->stalled)
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EP0SETUPSTALLED), priv->ep0state);
|
||||
stm32_epstall(&priv->epin[STM32_EP0_IN].ep, false);
|
||||
stm32_epstall(&priv->epin[STM32_EP0_OUT].ep, false);
|
||||
stm32_ep0stall(priv);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2626,11 +2634,133 @@ static int stm32_epcancel(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *r
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: stm32_epsetstall
|
||||
*
|
||||
* Description:
|
||||
* Stall an endpoint
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static int stm32_epsetstall(FAR struct stm32_usbdev_s *priv,
|
||||
FAR struct stm32_ep_s *privep)
|
||||
{
|
||||
uint32_t regaddr;
|
||||
uint32_t regval;
|
||||
|
||||
usbtrace(TRACE_EPSTALL, privep->epphy);
|
||||
|
||||
/* Is this an IN endpoint? */
|
||||
|
||||
if (privep->isin == 1)
|
||||
{
|
||||
/* Get the IN endpoint device control register */
|
||||
|
||||
regaddr = STM32_OTGFS_DIEPCTL(privep->epphy);
|
||||
regval = stm32_getreg(regaddr);
|
||||
|
||||
/* Is the endpoint enabled? */
|
||||
|
||||
if ((regval & OTGFS_DIEPCTL_EPENA) != 0)
|
||||
{
|
||||
/* Yes.. the endpoint is enabled, disable it */
|
||||
|
||||
regval = OTGFS_DIEPCTL_EPDIS;
|
||||
}
|
||||
else
|
||||
{
|
||||
regval = 0;
|
||||
}
|
||||
|
||||
/* Then stall the endpoint */
|
||||
|
||||
regval |= OTGFS_DIEPCTL_STALL;
|
||||
stm32_putreg(regval, regaddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the OUT endpoint device control register */
|
||||
|
||||
regaddr = STM32_OTGFS_DOEPCTL(privep->epphy);
|
||||
regval = stm32_getreg(regaddr);
|
||||
|
||||
/* Then stall the endpoint */
|
||||
|
||||
regval |= OTGFS_DOEPCTL_STALL;
|
||||
stm32_putreg(regval, regaddr);
|
||||
}
|
||||
|
||||
/* The endpoint is now stalled */
|
||||
|
||||
privep->stalled = true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: stm32_epclrstall
|
||||
*
|
||||
* Description:
|
||||
* Resume a stalled endpoint
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static int stm32_epclrstall(FAR struct stm32_usbdev_s *priv,
|
||||
FAR struct stm32_ep_s *privep)
|
||||
{
|
||||
uint32_t regaddr;
|
||||
uint32_t regval;
|
||||
uint32_t stallbit;
|
||||
uint32_t data0bit;
|
||||
|
||||
usbtrace(TRACE_EPRESUME, privep->epphy);
|
||||
|
||||
/* Is this an IN endpoint? */
|
||||
|
||||
if (privep->isin == 1)
|
||||
{
|
||||
/* Clear the stall bit in the IN endpoint device control register */
|
||||
|
||||
regaddr = STM32_OTGFS_DIEPCTL(privep->epphy);
|
||||
stallbit = OTGFS_DIEPCTL_STALL;
|
||||
data0bit = OTGFS_DIEPCTL_SD0PID;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear the stall bit in the IN endpoint device control register */
|
||||
|
||||
regaddr = STM32_OTGFS_DOEPCTL(privep->epphy);
|
||||
stallbit = OTGFS_DOEPCTL_STALL;
|
||||
data0bit = OTGFS_DOEPCTL_SD0PID;
|
||||
}
|
||||
|
||||
/* Clear the stall bit */
|
||||
|
||||
regval = stm32_getreg(regaddr);
|
||||
regval &= ~stallbit;
|
||||
|
||||
/* Set the DATA0 pid for interrupt and bulk endpoints */
|
||||
|
||||
if (privep->eptype == USB_EP_ATTR_XFER_INT ||
|
||||
privep->eptype == USB_EP_ATTR_XFER_BULK)
|
||||
{
|
||||
/* Writing this bit sets the DATA0 PID */
|
||||
|
||||
regval |= data0bit;
|
||||
}
|
||||
|
||||
stm32_putreg(regval, regaddr);
|
||||
|
||||
/* The endpoint is no longer stalled */
|
||||
|
||||
privep->stalled = false;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: stm32_epstall
|
||||
*
|
||||
* Description:
|
||||
* Stall or resume and endpoint
|
||||
* Stall or resume an endpoint
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
@ -2638,33 +2768,37 @@ static int stm32_epstall(FAR struct usbdev_ep_s *ep, bool resume)
|
||||
{
|
||||
FAR struct stm32_ep_s *privep = (FAR struct stm32_ep_s *)ep;
|
||||
irqstate_t flags;
|
||||
int ret;
|
||||
|
||||
/* STALL or RESUME the endpoint */
|
||||
/* Set or clear the stall condition as requested */
|
||||
|
||||
flags = irqsave();
|
||||
usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, privep->epphy);
|
||||
|
||||
uint32_t addr = STM32_USBDEV_ENDPTCTRL(privep->epphy);
|
||||
uint32_t ctrl_xs = STM32_EPPHYIN(privep->epphy) ? USBDEV_ENDPTCTRL_TXS : USBDEV_ENDPTCTRL_RXS;
|
||||
uint32_t ctrl_xr = STM32_EPPHYIN(privep->epphy) ? USBDEV_ENDPTCTRL_TXR : USBDEV_ENDPTCTRL_RXR;
|
||||
|
||||
if (resume)
|
||||
{
|
||||
privep->stalled = false;
|
||||
|
||||
/* Clear stall and reset the data toggle */
|
||||
|
||||
stm32_chgbits (ctrl_xs | ctrl_xr, ctrl_xr, addr);
|
||||
ret = stm32_epclrstall(priv, privep);
|
||||
}
|
||||
else
|
||||
{
|
||||
privep->stalled = true;
|
||||
|
||||
stm32_setbits (ctrl_xs, addr);
|
||||
ret = stm32_epsetstall(priv, privep);
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
return OK;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: stm32_ep0stall
|
||||
*
|
||||
* Description:
|
||||
* Stall endpoint 0
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static void stm32_ep0stall(FAR struct stm32_usbdev_s *priv)
|
||||
{
|
||||
stm32_epsetstall(priv, &priv->epin[EP0]);
|
||||
stm32_epsetstall(priv, &priv->epout[EP0]);
|
||||
stm32_ep0outstart(priv);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
Loading…
Reference in New Issue
Block a user