From 28462d476ab058d5fe9666f6f7e872246c1ad9bf Mon Sep 17 00:00:00 2001 From: bcostm Date: Thu, 8 Nov 2018 10:10:39 +0100 Subject: [PATCH] STM32F7 USB: add patch in CubeF7 hal driver --- .../TARGET_STM32F7/device/stm32f7xx_hal_pcd.c | 195 ++++++++++++++---- .../TARGET_STM32F7/device/stm32f7xx_hal_pcd.h | 1 + .../TARGET_STM32F7/device/stm32f7xx_ll_usb.c | 184 ++++++++++++++++- .../TARGET_STM32F7/device/stm32f7xx_ll_usb.h | 3 + 4 files changed, 335 insertions(+), 48 deletions(-) diff --git a/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_pcd.c b/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_pcd.c index 2785ae76bd..5e9e291208 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_pcd.c +++ b/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_pcd.c @@ -102,6 +102,7 @@ * @{ */ static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum); +static HAL_StatusTypeDef PCD_ReadRxFifo(PCD_HandleTypeDef *hpcd); // MBED PATCH /** * @} */ @@ -148,8 +149,9 @@ HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd) { /* Allocate lock resource and initialize it */ hpcd->Lock = HAL_UNLOCKED; - for (i = 0; i < hpcd->Init.dev_endpoints ; i++) - hpcd->EPLock[i].Lock = HAL_UNLOCKED; + for (i = 0; i < hpcd->Init.dev_endpoints ; i++) { // MBED PATCH + hpcd->EPLock[i].Lock = HAL_UNLOCKED; + } /* Init the low level hardware : GPIO, CLOCK, NVIC... */ HAL_PCD_MspInit(hpcd); } @@ -300,10 +302,10 @@ __weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) */ HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd) { - __HAL_LOCK(hpcd); + // MBED PATCH __HAL_LOCK(hpcd); USB_DevConnect (hpcd->Instance); __HAL_PCD_ENABLE(hpcd); - __HAL_UNLOCK(hpcd); + // MBED PATCH __HAL_UNLOCK(hpcd); return HAL_OK; } @@ -314,11 +316,11 @@ HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd) */ HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd) { - __HAL_LOCK(hpcd); + // MBED PATCH __HAL_LOCK(hpcd); __HAL_PCD_DISABLE(hpcd); USB_StopDevice(hpcd->Instance); USB_DevDisconnect (hpcd->Instance); - __HAL_UNLOCK(hpcd); + // MBED PATCH __HAL_UNLOCK(hpcd); return HAL_OK; } @@ -393,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) { /* setup/out transaction management for Core ID >= 310A */ @@ -440,7 +449,8 @@ void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd) if(( epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC) { fifoemptymsk = 0x1 << epnum; - atomic_clr_u32(&USBx_DEVICE->DIEPEMPMSK, fifoemptymsk); // MBED: changed + + atomic_clr_u32(&USBx_DEVICE->DIEPEMPMSK, fifoemptymsk); // MBED PATCH CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC); @@ -662,25 +672,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) >> 17) == STS_DATA_UPDT) - { - if((temp & USB_OTG_GRXSTSP_BCNT) != 0) - { - USB_ReadPacket(USBx, ep->xfer_buff, (temp & USB_OTG_GRXSTSP_BCNT) >> 4); - ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4; - ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4; - } - } - else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT) - { - USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8); - ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4; - } - USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL); + PCD_ReadRxFifo(hpcd); // MBED PATCH } /* Handle SOF Interrupt */ @@ -988,9 +980,9 @@ HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint ep->data_pid_start = 0; } - __HAL_LOCK(hpcd); + __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7FU]); // MBED PATCH USB_ActivateEndpoint(hpcd->Instance , ep); - __HAL_UNLOCK(hpcd); + __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7FU]); // MBED PATCH return ret; } @@ -1017,9 +1009,9 @@ HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) ep->is_in = (0x80 & ep_addr) != 0; - __HAL_LOCK(hpcd); + __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7FU]); // MBED PATCH USB_DeactivateEndpoint(hpcd->Instance , ep); - __HAL_UNLOCK(hpcd); + __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7FU]); // MBED PATCH return HAL_OK; } @@ -1050,7 +1042,7 @@ HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, u ep->dma_addr = (uint32_t)pBuf; } - __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED:added + __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED PATCH if ((ep_addr & 0x7F) == 0) { @@ -1061,7 +1053,7 @@ HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, u USB_EPStartXfer(hpcd->Instance, ep, hpcd->Init.dma_enable); } - __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED: added + __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED PATCH return HAL_OK; } @@ -1102,7 +1094,7 @@ HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, ep->dma_addr = (uint32_t)pBuf; } - __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED: added + __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED PATCH if ((ep_addr & 0x7F) == 0) { @@ -1113,11 +1105,91 @@ HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, USB_EPStartXfer(hpcd->Instance, ep, hpcd->Init.dma_enable); } - __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED: added + __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED PATCH 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 @@ -1146,8 +1218,7 @@ HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) ep->num = ep_addr & 0x7F; ep->is_in = ((ep_addr & 0x80) == 0x80); - - __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED: changed + __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED PATCH USB_EPSetStall(hpcd->Instance , ep); if((ep_addr & 0x7F) == 0) @@ -1155,7 +1226,7 @@ HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) USB_EP0_OutStart(hpcd->Instance, hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup); } - __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED: changed + __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED PATCH return HAL_OK; } @@ -1188,9 +1259,11 @@ HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) ep->num = ep_addr & 0x7F; ep->is_in = ((ep_addr & 0x80) == 0x80); - __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED: changed + __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED PATCH + USB_EPClearStall(hpcd->Instance , ep); - __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED: changed + + __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED PATCH return HAL_OK; } @@ -1203,7 +1276,7 @@ HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) */ HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) { - __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED: changed + __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED PATCH if ((ep_addr & 0x80) == 0x80) { @@ -1214,7 +1287,7 @@ HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) USB_FlushRxFifo(hpcd->Instance); } - __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED: change + __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]); // MBED PATCH return HAL_OK; } @@ -1337,13 +1410,51 @@ static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t if (ep->xfer_count >= ep->xfer_len) { fifoemptymsk = 0x1 << epnum; - atomic_clr_u32(&USBx_DEVICE->DIEPEMPMSK, fifoemptymsk); // MBED: changed + atomic_clr_u32(&USBx_DEVICE->DIEPEMPMSK, fifoemptymsk); // MBED PATCH } 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 + /** * @} */ diff --git a/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_pcd.h b/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_pcd.h index 41504f5db5..f895df94d3 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_pcd.h +++ b/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_pcd.h @@ -286,6 +286,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); diff --git a/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_ll_usb.c b/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_ll_usb.c index 16c21ac3e3..645eb10af3 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_ll_usb.c +++ b/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_ll_usb.c @@ -479,7 +479,8 @@ HAL_StatusTypeDef USB_ActivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTy if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0) { - USBx_INEP(ep->num)->DIEPCTL |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + // MBED PATCH + USBx_INEP(ep->num)->DIEPCTL = ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\ ((ep->num) << 22 ) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP)); } @@ -490,7 +491,8 @@ HAL_StatusTypeDef USB_ActivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTy if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0) { - USBx_OUTEP(ep->num)->DOEPCTL |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + // MBED PATCH + USBx_OUTEP(ep->num)->DOEPCTL = ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\ (USB_OTG_DIEPCTL_SD0PID_SEVNFRM)| (USB_OTG_DOEPCTL_USBAEP)); } } @@ -511,7 +513,8 @@ HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB { if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0) { - USBx_INEP(ep->num)->DIEPCTL |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + // MBED PATCH + USBx_INEP(ep->num)->DIEPCTL = ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\ ((ep->num) << 22 ) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP)); } @@ -525,7 +528,8 @@ HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB { if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0) { - USBx_OUTEP(ep->num)->DOEPCTL |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + // MBED PATCH + USBx_OUTEP(ep->num)->DOEPCTL = ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\ ((ep->num) << 22 ) | (USB_OTG_DOEPCTL_USBAEP)); debug = (uint32_t)(((uint32_t )USBx) + USB_OTG_OUT_ENDPOINT_BASE + (0)*USB_OTG_EP_REG_SIZE); @@ -639,7 +643,7 @@ HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDe /* Enable the Tx FIFO Empty Interrupt for this EP */ if (ep->xfer_len > 0) { - atomic_set_u32(&USBx_DEVICE->DIEPEMPMSK, 1 << ep->num); // MBED: changed + atomic_set_u32(&USBx_DEVICE->DIEPEMPMSK, 1 << ep->num); // MBED PATCH } } } @@ -793,6 +797,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 @@ -1635,7 +1807,7 @@ HAL_StatusTypeDef USB_HC_StartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_HCTypeDe /* Write packet into the Tx FIFO. */ USB_WritePacket(USBx, hc->xfer_buff, hc->ch_num, hc->xfer_len, 0); - hc->xfer_count = hc->xfer_len; // MBED: added + hc->xfer_count = hc->xfer_len; // MBED PATCH } } diff --git a/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_ll_usb.h b/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_ll_usb.h index b3a0cf3ea0..2d0fc74098 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_ll_usb.h +++ b/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_ll_usb.h @@ -415,6 +415,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);