STM32F4 USB: add patch in CubeF4 hal driver

pull/9768/head
bcostm 2018-10-30 09:43:15 +01:00 committed by Russ Butler
parent 7db3a8a34a
commit 1e807a305e
4 changed files with 307 additions and 25 deletions

View File

@ -106,6 +106,7 @@
* @{
*/
static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
static HAL_StatusTypeDef PCD_ReadRxFifo(PCD_HandleTypeDef *hpcd); // MBED PATCH
/**
* @}
*/
@ -394,6 +395,13 @@ void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
}
}
// MBED PATCH
if (( epint & USB_OTG_DOEPINT_EPDISD) == USB_OTG_DOEPINT_EPDISD)
{
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_EPDISD);
}
// MBED PATCH
if(( epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
{
/* Inform the upper layer that a setup packet is available */
@ -667,27 +675,7 @@ void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
/* Handle RxQLevel Interrupt */
if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
{
USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
temp = USBx->GRXSTSP;
ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
if(((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17U) == STS_DATA_UPDT)
{
if((temp & USB_OTG_GRXSTSP_BCNT) != 0U)
{
USB_ReadPacket(USBx, ep->xfer_buff, (temp & USB_OTG_GRXSTSP_BCNT) >> 4U);
ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4U;
ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4U;
}
}
else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17U) == STS_SETUP_UPDT)
{
USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4U;
}
USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
PCD_ReadRxFifo(hpcd); // MBED PATCH
}
/* Handle SOF Interrupt */
@ -1131,6 +1119,86 @@ HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
return HAL_OK;
}
// MBED PATCH
/**
* @brief Abort a transaction.
* @param hpcd: PCD handle
* @param ep_addr: endpoint address
* @retval HAL status
*/
HAL_StatusTypeDef HAL_PCD_EP_Abort(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
{
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
HAL_StatusTypeDef ret = HAL_OK;
USB_OTG_EPTypeDef *ep;
if ((0x80 & ep_addr) == 0x80)
{
ep = &hpcd->IN_ep[ep_addr & 0x7F];
}
else
{
ep = &hpcd->OUT_ep[ep_addr];
}
__HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]);
ep->num = ep_addr & 0x7F;
ep->is_in = ((ep_addr & 0x80) == 0x80);
USB_EPSetNak(hpcd->Instance, ep);
if ((0x80 & ep_addr) == 0x80)
{
ret = USB_EPStopXfer(hpcd->Instance , ep);
if (ret == HAL_OK)
{
ret = USB_FlushTxFifo(hpcd->Instance, ep_addr & 0x7F);
}
}
else
{
/* Set global NAK */
USBx_DEVICE->DCTL |= USB_OTG_DCTL_SGONAK;
/* Read all entries from the fifo so global NAK takes effect */
while (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
{
PCD_ReadRxFifo(hpcd);
}
/* Stop the transfer */
ret = USB_EPStopXfer(hpcd->Instance , ep);
if (ret == HAL_BUSY)
{
/* If USB_EPStopXfer returns HAL_BUSY then a setup packet
* arrived after the rx fifo was processed but before USB_EPStopXfer
* was called. Process the rx fifo one more time to read the
* setup packet.
*
* Note - after the setup packet has been received no further
* packets will be received over USB. This is because the next
* phase (data or status) of the control transfer started by
* the setup packet will be naked until global nak is cleared.
*/
while (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
{
PCD_ReadRxFifo(hpcd);
}
ret = USB_EPStopXfer(hpcd->Instance , ep);
}
/* Clear global nak */
USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK;
}
__HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]);
return ret;
}
// MBED PATCH
/**
* @brief Set a STALL condition over an endpoint.
* @param hpcd PCD handle
@ -1356,6 +1424,44 @@ static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t
return HAL_OK;
}
// MBED PATCH
/**
* @brief Process the next RX fifo entry
* @param hpcd: PCD handle
* @retval HAL status
*/
static HAL_StatusTypeDef PCD_ReadRxFifo(PCD_HandleTypeDef *hpcd)
{
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
USB_OTG_EPTypeDef *ep;
uint32_t temp = 0;
USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
temp = USBx->GRXSTSP;
ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
if(((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17U) == STS_DATA_UPDT)
{
if((temp & USB_OTG_GRXSTSP_BCNT) != 0U)
{
USB_ReadPacket(USBx, ep->xfer_buff, (temp & USB_OTG_GRXSTSP_BCNT) >> 4U);
ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4U;
ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4U;
}
}
else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17U) == STS_SETUP_UPDT)
{
USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4U;
}
USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
return HAL_OK;
}
// MBED PATCH
/**
* @}
*/

View File

@ -300,6 +300,7 @@ HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint
HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len);
HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len);
HAL_StatusTypeDef HAL_PCD_EP_Abort(PCD_HandleTypeDef *hpcd, uint8_t ep_addr); // MBED PATCH
uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);
HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr);

View File

@ -450,7 +450,8 @@ HAL_StatusTypeDef USB_ActivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTy
if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0U)
{
USBx_INEP(ep->num)->DIEPCTL |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18U) |\
// MBED PATCH
USBx_INEP(ep->num)->DIEPCTL = ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18U) |\
((ep->num) << 22U) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP));
}
}
@ -460,7 +461,8 @@ HAL_StatusTypeDef USB_ActivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTy
if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0U)
{
USBx_OUTEP(ep->num)->DOEPCTL |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18U) |\
// MBED PATCH
USBx_OUTEP(ep->num)->DOEPCTL = ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18U) |\
(USB_OTG_DIEPCTL_SD0PID_SEVNFRM)| (USB_OTG_DOEPCTL_USBAEP));
}
}
@ -481,7 +483,8 @@ HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB
{
if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0U)
{
USBx_INEP(ep->num)->DIEPCTL |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18U) |\
// MBED PATCH
USBx_INEP(ep->num)->DIEPCTL = ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18U) |\
((ep->num) << 22U) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP));
}
@ -495,7 +498,8 @@ HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB
{
if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0U)
{
USBx_OUTEP(ep->num)->DOEPCTL |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18U) |\
// MBED PATCH
USBx_OUTEP(ep->num)->DOEPCTL = ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18U) |\
((ep->num) << 22U) | (USB_OTG_DOEPCTL_USBAEP));
debug = (uint32_t)(((uint32_t )USBx) + USB_OTG_OUT_ENDPOINT_BASE + (0U)*USB_OTG_EP_REG_SIZE);
@ -865,6 +869,174 @@ HAL_StatusTypeDef USB_EP0StartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeD
return HAL_OK;
}
// MBED PATCH
/**
* @brief USB_EPStoptXfer : stop transfer on this endpoint
* @param USBx : Selected device
* @param ep: pointer to endpoint structure
* @retval HAL status
* @note IN endpoints must have NAK enabled before calling this function
* @note OUT endpoints must have global out NAK enabled before calling this
* function. Furthermore, the RX fifo must be empty or the status
* HAL_BUSY will be returned.
*/
HAL_StatusTypeDef USB_EPStopXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep)
{
HAL_StatusTypeDef ret = HAL_OK;
uint32_t count = 0U;
uint32_t epint, fifoemptymsk;
/* IN endpoint */
if (ep->is_in == 1U)
{
/* EP enable, IN data in FIFO */
if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
{
/* Disable this endpoint */
USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_EPDIS;
count = 0;
do
{
if (++count > 200000U)
{
return HAL_TIMEOUT;
}
}
while ((USBx_INEP(ep->num)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA);
}
/* Clear transfer complete interrupt */
epint = USB_ReadDevInEPInterrupt(USBx, ep->num);
if((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
{
CLEAR_IN_EP_INTR(ep->num, USB_OTG_DIEPINT_XFRC);
}
/* Mask fifo empty interrupt */
fifoemptymsk = 0x1U << ep->num;
atomic_clr_u32(&USBx_DEVICE->DIEPEMPMSK, fifoemptymsk);
}
else /* OUT endpoint */
{
if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
{
/* Disable this endpoint */
USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_EPDIS;
count = 0;
do
{
if (++count > 200000U)
{
return HAL_TIMEOUT;
}
if ((USBx->GINTSTS & USB_OTG_GINTSTS_RXFLVL) == USB_OTG_GINTSTS_RXFLVL)
{
/* Although not mentioned in the Reference Manual, it appears that the
* rx fifo must be empty for an OUT endpoint to be disabled. Typically
* this will happen when setting the global OUT nak (required by Reference
* Manual) as this requires processing the rx fifo. This is not guaranteed
* though, as a setup packet can arrive even while global OUT nak is set.
*
* During testing this event was observed and prevented endpoint disabling
* from completing until the rx fifo was empty. To address this problem
* return HAL_BUSY if the rx fifo is not empty to give higher level code
* a chance to clear the fifo and retry the operation.
*
*/
return HAL_BUSY;
}
}
while ((USBx_OUTEP(ep->num)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA);
}
/* Clear interrupt */
epint = USB_ReadDevOutEPInterrupt(USBx, ep->num);
if(( epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
{
CLEAR_OUT_EP_INTR(ep->num, USB_OTG_DOEPINT_XFRC);
}
}
return ret;
}
/**
* @brief USB_EPSetNak : stop transfer and nak all tokens on this endpoint
* @param USBx : Selected device
* @param ep: pointer to endpoint structure
* @retval HAL status
*/
HAL_StatusTypeDef USB_EPSetNak(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep)
{
uint32_t count = 0;
if (ep->is_in == 1U)
{
USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
count = 0;
do
{
if (++count > 200000U)
{
return HAL_TIMEOUT;
}
}
while ((USBx_INEP(ep->num)->DIEPCTL & USB_OTG_DIEPCTL_NAKSTS) != USB_OTG_DIEPCTL_NAKSTS);
}
else
{
USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
count = 0;
do
{
if (++count > 200000U)
{
return HAL_TIMEOUT;
}
}
while ((USBx_OUTEP(ep->num)->DOEPCTL & USB_OTG_DOEPCTL_NAKSTS) != USB_OTG_DOEPCTL_NAKSTS);
}
return HAL_OK;
}
/**
* @brief USB_EPSetNak : resume transfer and stop naking on this endpoint
* @param USBx : Selected device
* @param ep: pointer to endpoint structure
* @retval HAL status
*/
HAL_StatusTypeDef USB_EPClearNak(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep)
{
uint32_t count = 0;
if (ep->is_in == 1U)
{
USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_CNAK;
count = 0;
do
{
if (++count > 200000U)
{
return HAL_TIMEOUT;
}
}
while ((USBx_INEP(ep->num)->DIEPCTL & USB_OTG_DIEPCTL_NAKSTS) == USB_OTG_DIEPCTL_NAKSTS);
}
else
{
USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
count = 0;
do
{
if (++count > 200000U)
{
return HAL_TIMEOUT;
}
}
while ((USBx_OUTEP(ep->num)->DOEPCTL & USB_OTG_DOEPCTL_NAKSTS) == USB_OTG_DOEPCTL_NAKSTS);
}
return HAL_OK;
}
// MBED PATCH
/**
* @brief USB_WritePacket : Writes a packet into the Tx FIFO associated
* with the EP/channel

View File

@ -416,6 +416,9 @@ HAL_StatusTypeDef USB_DeactivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EP
HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep);
HAL_StatusTypeDef USB_DeactivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep);
HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma);
HAL_StatusTypeDef USB_EPStopXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep); // MBED PATCH
HAL_StatusTypeDef USB_EPSetNak(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep); // MBED PATCH
HAL_StatusTypeDef USB_EPClearNak(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep); // MBED PATCH
HAL_StatusTypeDef USB_EP0StartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma);
HAL_StatusTypeDef USB_WritePacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *src, uint8_t ch_ep_num, uint16_t len, uint8_t dma);
void * USB_ReadPacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *dest, uint16_t len);