You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1203 lines
31 KiB

  1. /**
  2. ******************************************************************************
  3. * @file stm32f7xx_hal_pcd.c
  4. * @author MCD Application Team
  5. * @version V1.0.1
  6. * @date 25-June-2015
  7. * @brief PCD HAL module driver.
  8. * This file provides firmware functions to manage the following
  9. * functionalities of the USB Peripheral Controller:
  10. * + Initialization and de-initialization functions
  11. * + IO operation functions
  12. * + Peripheral Control functions
  13. * + Peripheral State functions
  14. *
  15. @verbatim
  16. ==============================================================================
  17. ##### How to use this driver #####
  18. ==============================================================================
  19. [..]
  20. The PCD HAL driver can be used as follows:
  21. (#) Declare a PCD_HandleTypeDef handle structure, for example:
  22. PCD_HandleTypeDef hpcd;
  23. (#) Fill parameters of Init structure in HCD handle
  24. (#) Call HAL_PCD_Init() API to initialize the HCD peripheral (Core, Device core, ...)
  25. (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
  26. (##) Enable the PCD/USB Low Level interface clock using
  27. (+++) __OTGFS-OTG_CLK_ENABLE()/__OTGHS-OTG_CLK_ENABLE();
  28. (+++) __OTGHSULPI_CLK_ENABLE(); (For High Speed Mode)
  29. (##) Initialize the related GPIO clocks
  30. (##) Configure PCD pin-out
  31. (##) Configure PCD NVIC interrupt
  32. (#)Associate the Upper USB device stack to the HAL PCD Driver:
  33. (##) hpcd.pData = pdev;
  34. (#)Enable HCD transmission and reception:
  35. (##) HAL_PCD_Start();
  36. @endverbatim
  37. ******************************************************************************
  38. * @attention
  39. *
  40. * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
  41. *
  42. * Redistribution and use in source and binary forms, with or without modification,
  43. * are permitted provided that the following conditions are met:
  44. * 1. Redistributions of source code must retain the above copyright notice,
  45. * this list of conditions and the following disclaimer.
  46. * 2. Redistributions in binary form must reproduce the above copyright notice,
  47. * this list of conditions and the following disclaimer in the documentation
  48. * and/or other materials provided with the distribution.
  49. * 3. Neither the name of STMicroelectronics nor the names of its contributors
  50. * may be used to endorse or promote products derived from this software
  51. * without specific prior written permission.
  52. *
  53. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  54. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  55. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  56. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  57. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  58. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  59. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  60. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  61. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  62. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  63. *
  64. ******************************************************************************
  65. */
  66. /* Includes ------------------------------------------------------------------*/
  67. #include "stm32f7xx_hal.h"
  68. /** @addtogroup STM32F7xx_HAL_Driver
  69. * @{
  70. */
  71. /** @defgroup PCD PCD
  72. * @brief PCD HAL module driver
  73. * @{
  74. */
  75. #ifdef HAL_PCD_MODULE_ENABLED
  76. /* Private types -------------------------------------------------------------*/
  77. /* Private variables ---------------------------------------------------------*/
  78. /* Private constants ---------------------------------------------------------*/
  79. /* Private macros ------------------------------------------------------------*/
  80. /** @defgroup PCD_Private_Macros PCD Private Macros
  81. * @{
  82. */
  83. #define PCD_MIN(a, b) (((a) < (b)) ? (a) : (b))
  84. #define PCD_MAX(a, b) (((a) > (b)) ? (a) : (b))
  85. /**
  86. * @}
  87. */
  88. /* Private functions prototypes ----------------------------------------------*/
  89. /** @defgroup PCD_Private_Functions PCD Private Functions
  90. * @{
  91. */
  92. static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
  93. /**
  94. * @}
  95. */
  96. /* Exported functions --------------------------------------------------------*/
  97. /** @defgroup PCD_Exported_Functions PCD Exported Functions
  98. * @{
  99. */
  100. /** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
  101. * @brief Initialization and Configuration functions
  102. *
  103. @verbatim
  104. ===============================================================================
  105. ##### Initialization and de-initialization functions #####
  106. ===============================================================================
  107. [..] This section provides functions allowing to:
  108. @endverbatim
  109. * @{
  110. */
  111. /**
  112. * @brief Initializes the PCD according to the specified
  113. * parameters in the PCD_InitTypeDef and create the associated handle.
  114. * @param hpcd: PCD handle
  115. * @retval HAL status
  116. */
  117. HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
  118. {
  119. uint32_t i = 0;
  120. /* Check the PCD handle allocation */
  121. if(hpcd == NULL)
  122. {
  123. return HAL_ERROR;
  124. }
  125. /* Check the parameters */
  126. assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
  127. hpcd->State = HAL_PCD_STATE_BUSY;
  128. /* Init the low level hardware : GPIO, CLOCK, NVIC... */
  129. HAL_PCD_MspInit(hpcd);
  130. /* Disable the Interrupts */
  131. __HAL_PCD_DISABLE(hpcd);
  132. /*Init the Core (common init.) */
  133. USB_CoreInit(hpcd->Instance, hpcd->Init);
  134. /* Force Device Mode*/
  135. USB_SetCurrentMode(hpcd->Instance , USB_OTG_DEVICE_MODE);
  136. /* Init endpoints structures */
  137. for (i = 0; i < 15 ; i++)
  138. {
  139. /* Init ep structure */
  140. hpcd->IN_ep[i].is_in = 1;
  141. hpcd->IN_ep[i].num = i;
  142. hpcd->IN_ep[i].tx_fifo_num = i;
  143. /* Control until ep is activated */
  144. hpcd->IN_ep[i].type = EP_TYPE_CTRL;
  145. hpcd->IN_ep[i].maxpacket = 0;
  146. hpcd->IN_ep[i].xfer_buff = 0;
  147. hpcd->IN_ep[i].xfer_len = 0;
  148. }
  149. for (i = 0; i < 15 ; i++)
  150. {
  151. hpcd->OUT_ep[i].is_in = 0;
  152. hpcd->OUT_ep[i].num = i;
  153. hpcd->IN_ep[i].tx_fifo_num = i;
  154. /* Control until ep is activated */
  155. hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
  156. hpcd->OUT_ep[i].maxpacket = 0;
  157. hpcd->OUT_ep[i].xfer_buff = 0;
  158. hpcd->OUT_ep[i].xfer_len = 0;
  159. hpcd->Instance->DIEPTXF[i] = 0;
  160. }
  161. /* Init Device */
  162. USB_DevInit(hpcd->Instance, hpcd->Init);
  163. hpcd->State= HAL_PCD_STATE_READY;
  164. /* Activate LPM */
  165. if (hpcd->Init.lpm_enable == 1)
  166. {
  167. HAL_PCDEx_ActivateLPM(hpcd);
  168. }
  169. USB_DevDisconnect (hpcd->Instance);
  170. return HAL_OK;
  171. }
  172. /**
  173. * @brief DeInitializes the PCD peripheral
  174. * @param hpcd: PCD handle
  175. * @retval HAL status
  176. */
  177. HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
  178. {
  179. /* Check the PCD handle allocation */
  180. if(hpcd == NULL)
  181. {
  182. return HAL_ERROR;
  183. }
  184. hpcd->State = HAL_PCD_STATE_BUSY;
  185. /* Stop Device */
  186. HAL_PCD_Stop(hpcd);
  187. /* DeInit the low level hardware */
  188. HAL_PCD_MspDeInit(hpcd);
  189. hpcd->State = HAL_PCD_STATE_RESET;
  190. return HAL_OK;
  191. }
  192. /**
  193. * @brief Initializes the PCD MSP.
  194. * @param hpcd: PCD handle
  195. * @retval None
  196. */
  197. __weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
  198. {
  199. /* NOTE : This function Should not be modified, when the callback is needed,
  200. the HAL_PCD_MspInit could be implemented in the user file
  201. */
  202. }
  203. /**
  204. * @brief DeInitializes PCD MSP.
  205. * @param hpcd: PCD handle
  206. * @retval None
  207. */
  208. __weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
  209. {
  210. /* NOTE : This function Should not be modified, when the callback is needed,
  211. the HAL_PCD_MspDeInit could be implemented in the user file
  212. */
  213. }
  214. /**
  215. * @}
  216. */
  217. /** @defgroup PCD_Exported_Functions_Group2 IO operation functions
  218. * @brief Data transfers functions
  219. *
  220. @verbatim
  221. ===============================================================================
  222. ##### IO operation functions #####
  223. ===============================================================================
  224. [..]
  225. This subsection provides a set of functions allowing to manage the PCD data
  226. transfers.
  227. @endverbatim
  228. * @{
  229. */
  230. /**
  231. * @brief Start The USB OTG Device.
  232. * @param hpcd: PCD handle
  233. * @retval HAL status
  234. */
  235. HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
  236. {
  237. __HAL_LOCK(hpcd);
  238. USB_DevConnect (hpcd->Instance);
  239. __HAL_PCD_ENABLE(hpcd);
  240. __HAL_UNLOCK(hpcd);
  241. return HAL_OK;
  242. }
  243. /**
  244. * @brief Stop The USB OTG Device.
  245. * @param hpcd: PCD handle
  246. * @retval HAL status
  247. */
  248. HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
  249. {
  250. __HAL_LOCK(hpcd);
  251. __HAL_PCD_DISABLE(hpcd);
  252. USB_StopDevice(hpcd->Instance);
  253. USB_DevDisconnect (hpcd->Instance);
  254. __HAL_UNLOCK(hpcd);
  255. return HAL_OK;
  256. }
  257. /**
  258. * @brief This function handles PCD interrupt request.
  259. * @param hpcd: PCD handle
  260. * @retval HAL status
  261. */
  262. void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
  263. {
  264. USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
  265. uint32_t i = 0, ep_intr = 0, epint = 0, epnum = 0;
  266. uint32_t fifoemptymsk = 0, temp = 0;
  267. USB_OTG_EPTypeDef *ep;
  268. /* ensure that we are in device mode */
  269. if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
  270. {
  271. /* avoid spurious interrupt */
  272. if(__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
  273. {
  274. return;
  275. }
  276. if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
  277. {
  278. /* incorrect mode, acknowledge the interrupt */
  279. __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
  280. }
  281. if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
  282. {
  283. epnum = 0;
  284. /* Read in the device interrupt bits */
  285. ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
  286. while ( ep_intr )
  287. {
  288. if (ep_intr & 0x1)
  289. {
  290. epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, epnum);
  291. if(( epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
  292. {
  293. CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
  294. if(hpcd->Init.dma_enable == 1)
  295. {
  296. hpcd->OUT_ep[epnum].xfer_count = hpcd->OUT_ep[epnum].maxpacket- (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ);
  297. hpcd->OUT_ep[epnum].xfer_buff += hpcd->OUT_ep[epnum].maxpacket;
  298. }
  299. HAL_PCD_DataOutStageCallback(hpcd, epnum);
  300. if(hpcd->Init.dma_enable == 1)
  301. {
  302. if((epnum == 0) && (hpcd->OUT_ep[epnum].xfer_len == 0))
  303. {
  304. /* this is ZLP, so prepare EP0 for next setup */
  305. USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup);
  306. }
  307. }
  308. }
  309. if(( epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
  310. {
  311. /* Inform the upper layer that a setup packet is available */
  312. HAL_PCD_SetupStageCallback(hpcd);
  313. CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
  314. }
  315. if(( epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
  316. {
  317. CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
  318. }
  319. }
  320. epnum++;
  321. ep_intr >>= 1;
  322. }
  323. }
  324. if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
  325. {
  326. /* Read in the device interrupt bits */
  327. ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
  328. epnum = 0;
  329. while ( ep_intr )
  330. {
  331. if (ep_intr & 0x1) /* In ITR */
  332. {
  333. epint = USB_ReadDevInEPInterrupt(hpcd->Instance, epnum);
  334. if(( epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
  335. {
  336. fifoemptymsk = 0x1 << epnum;
  337. USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
  338. CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
  339. if (hpcd->Init.dma_enable == 1)
  340. {
  341. hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket;
  342. }
  343. HAL_PCD_DataInStageCallback(hpcd, epnum);
  344. if (hpcd->Init.dma_enable == 1)
  345. {
  346. /* this is ZLP, so prepare EP0 for next setup */
  347. if((epnum == 0) && (hpcd->IN_ep[epnum].xfer_len == 0))
  348. {
  349. /* prepare to rx more setup packets */
  350. USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup);
  351. }
  352. }
  353. }
  354. if(( epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
  355. {
  356. CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
  357. }
  358. if(( epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
  359. {
  360. CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
  361. }
  362. if(( epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
  363. {
  364. CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
  365. }
  366. if(( epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
  367. {
  368. CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
  369. }
  370. if(( epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
  371. {
  372. PCD_WriteEmptyTxFifo(hpcd , epnum);
  373. }
  374. }
  375. epnum++;
  376. ep_intr >>= 1;
  377. }
  378. }
  379. /* Handle Resume Interrupt */
  380. if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
  381. {
  382. /* Clear the Remote Wake-up Signaling */
  383. USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
  384. if(hpcd->LPM_State == LPM_L1)
  385. {
  386. hpcd->LPM_State = LPM_L0;
  387. HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
  388. }
  389. else
  390. {
  391. HAL_PCD_ResumeCallback(hpcd);
  392. }
  393. __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
  394. }
  395. /* Handle Suspend Interrupt */
  396. if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
  397. {
  398. if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
  399. {
  400. HAL_PCD_SuspendCallback(hpcd);
  401. }
  402. __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
  403. }
  404. /* Handle LPM Interrupt */
  405. if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT))
  406. {
  407. __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT);
  408. if( hpcd->LPM_State == LPM_L0)
  409. {
  410. hpcd->LPM_State = LPM_L1;
  411. hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >>2 ;
  412. HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
  413. }
  414. else
  415. {
  416. HAL_PCD_SuspendCallback(hpcd);
  417. }
  418. }
  419. /* Handle Reset Interrupt */
  420. if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
  421. {
  422. USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
  423. USB_FlushTxFifo(hpcd->Instance , 0 );
  424. for (i = 0; i < hpcd->Init.dev_endpoints ; i++)
  425. {
  426. USBx_INEP(i)->DIEPINT = 0xFF;
  427. USBx_OUTEP(i)->DOEPINT = 0xFF;
  428. }
  429. USBx_DEVICE->DAINT = 0xFFFFFFFF;
  430. USBx_DEVICE->DAINTMSK |= 0x10001;
  431. if(hpcd->Init.use_dedicated_ep1)
  432. {
  433. USBx_DEVICE->DOUTEP1MSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM);
  434. USBx_DEVICE->DINEP1MSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);
  435. }
  436. else
  437. {
  438. USBx_DEVICE->DOEPMSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM);
  439. USBx_DEVICE->DIEPMSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);
  440. }
  441. /* Set Default Address to 0 */
  442. USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
  443. /* setup EP0 to receive SETUP packets */
  444. USB_EP0_OutStart(hpcd->Instance, hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup);
  445. __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
  446. }
  447. /* Handle Enumeration done Interrupt */
  448. if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
  449. {
  450. USB_ActivateSetup(hpcd->Instance);
  451. hpcd->Instance->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
  452. if ( USB_GetDevSpeed(hpcd->Instance) == USB_OTG_SPEED_HIGH)
  453. {
  454. hpcd->Init.speed = USB_OTG_SPEED_HIGH;
  455. hpcd->Init.ep0_mps = USB_OTG_HS_MAX_PACKET_SIZE ;
  456. hpcd->Instance->GUSBCFG |= (uint32_t)((USBD_HS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT);
  457. }
  458. else
  459. {
  460. hpcd->Init.speed = USB_OTG_SPEED_FULL;
  461. hpcd->Init.ep0_mps = USB_OTG_FS_MAX_PACKET_SIZE ;
  462. hpcd->Instance->GUSBCFG |= (uint32_t)((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT);
  463. }
  464. HAL_PCD_ResetCallback(hpcd);
  465. __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
  466. }
  467. /* Handle RxQLevel Interrupt */
  468. if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
  469. {
  470. USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
  471. temp = USBx->GRXSTSP;
  472. ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
  473. if(((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT)
  474. {
  475. if((temp & USB_OTG_GRXSTSP_BCNT) != 0)
  476. {
  477. USB_ReadPacket(USBx, ep->xfer_buff, (temp & USB_OTG_GRXSTSP_BCNT) >> 4);
  478. ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
  479. ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
  480. }
  481. }
  482. else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT)
  483. {
  484. USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8);
  485. ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
  486. }
  487. USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
  488. }
  489. /* Handle SOF Interrupt */
  490. if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
  491. {
  492. HAL_PCD_SOFCallback(hpcd);
  493. __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
  494. }
  495. /* Handle Incomplete ISO IN Interrupt */
  496. if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
  497. {
  498. HAL_PCD_ISOINIncompleteCallback(hpcd, epnum);
  499. __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
  500. }
  501. /* Handle Incomplete ISO OUT Interrupt */
  502. if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
  503. {
  504. HAL_PCD_ISOOUTIncompleteCallback(hpcd, epnum);
  505. __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
  506. }
  507. /* Handle Connection event Interrupt */
  508. if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
  509. {
  510. HAL_PCD_ConnectCallback(hpcd);
  511. __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
  512. }
  513. /* Handle Disconnection event Interrupt */
  514. if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
  515. {
  516. temp = hpcd->Instance->GOTGINT;
  517. if((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
  518. {
  519. HAL_PCD_DisconnectCallback(hpcd);
  520. }
  521. hpcd->Instance->GOTGINT |= temp;
  522. }
  523. }
  524. }
  525. /**
  526. * @brief Data out stage callbacks
  527. * @param hpcd: PCD handle
  528. * @param epnum: endpoint number
  529. * @retval None
  530. */
  531. __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  532. {
  533. /* NOTE : This function Should not be modified, when the callback is needed,
  534. the HAL_PCD_DataOutStageCallback could be implemented in the user file
  535. */
  536. }
  537. /**
  538. * @brief Data IN stage callbacks
  539. * @param hpcd: PCD handle
  540. * @param epnum: endpoint number
  541. * @retval None
  542. */
  543. __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  544. {
  545. /* NOTE : This function Should not be modified, when the callback is needed,
  546. the HAL_PCD_DataInStageCallback could be implemented in the user file
  547. */
  548. }
  549. /**
  550. * @brief Setup stage callback
  551. * @param hpcd: PCD handle
  552. * @retval None
  553. */
  554. __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
  555. {
  556. /* NOTE : This function Should not be modified, when the callback is needed,
  557. the HAL_PCD_SetupStageCallback could be implemented in the user file
  558. */
  559. }
  560. /**
  561. * @brief USB Start Of Frame callbacks
  562. * @param hpcd: PCD handle
  563. * @retval None
  564. */
  565. __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
  566. {
  567. /* NOTE : This function Should not be modified, when the callback is needed,
  568. the HAL_PCD_SOFCallback could be implemented in the user file
  569. */
  570. }
  571. /**
  572. * @brief USB Reset callbacks
  573. * @param hpcd: PCD handle
  574. * @retval None
  575. */
  576. __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
  577. {
  578. /* NOTE : This function Should not be modified, when the callback is needed,
  579. the HAL_PCD_ResetCallback could be implemented in the user file
  580. */
  581. }
  582. /**
  583. * @brief Suspend event callbacks
  584. * @param hpcd: PCD handle
  585. * @retval None
  586. */
  587. __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
  588. {
  589. /* NOTE : This function Should not be modified, when the callback is needed,
  590. the HAL_PCD_SuspendCallback could be implemented in the user file
  591. */
  592. }
  593. /**
  594. * @brief Resume event callbacks
  595. * @param hpcd: PCD handle
  596. * @retval None
  597. */
  598. __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
  599. {
  600. /* NOTE : This function Should not be modified, when the callback is needed,
  601. the HAL_PCD_ResumeCallback could be implemented in the user file
  602. */
  603. }
  604. /**
  605. * @brief Incomplete ISO OUT callbacks
  606. * @param hpcd: PCD handle
  607. * @param epnum: endpoint number
  608. * @retval None
  609. */
  610. __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  611. {
  612. /* NOTE : This function Should not be modified, when the callback is needed,
  613. the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
  614. */
  615. }
  616. /**
  617. * @brief Incomplete ISO IN callbacks
  618. * @param hpcd: PCD handle
  619. * @param epnum: endpoint number
  620. * @retval None
  621. */
  622. __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  623. {
  624. /* NOTE : This function Should not be modified, when the callback is needed,
  625. the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
  626. */
  627. }
  628. /**
  629. * @brief Connection event callbacks
  630. * @param hpcd: PCD handle
  631. * @retval None
  632. */
  633. __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
  634. {
  635. /* NOTE : This function Should not be modified, when the callback is needed,
  636. the HAL_PCD_ConnectCallback could be implemented in the user file
  637. */
  638. }
  639. /**
  640. * @brief Disconnection event callbacks
  641. * @param hpcd: PCD handle
  642. * @retval None
  643. */
  644. __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
  645. {
  646. /* NOTE : This function Should not be modified, when the callback is needed,
  647. the HAL_PCD_DisconnectCallback could be implemented in the user file
  648. */
  649. }
  650. /**
  651. * @}
  652. */
  653. /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
  654. * @brief management functions
  655. *
  656. @verbatim
  657. ===============================================================================
  658. ##### Peripheral Control functions #####
  659. ===============================================================================
  660. [..]
  661. This subsection provides a set of functions allowing to control the PCD data
  662. transfers.
  663. @endverbatim
  664. * @{
  665. */
  666. /**
  667. * @brief Connect the USB device
  668. * @param hpcd: PCD handle
  669. * @retval HAL status
  670. */
  671. HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
  672. {
  673. __HAL_LOCK(hpcd);
  674. USB_DevConnect(hpcd->Instance);
  675. __HAL_UNLOCK(hpcd);
  676. return HAL_OK;
  677. }
  678. /**
  679. * @brief Disconnect the USB device
  680. * @param hpcd: PCD handle
  681. * @retval HAL status
  682. */
  683. HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
  684. {
  685. __HAL_LOCK(hpcd);
  686. USB_DevDisconnect(hpcd->Instance);
  687. __HAL_UNLOCK(hpcd);
  688. return HAL_OK;
  689. }
  690. /**
  691. * @brief Set the USB Device address
  692. * @param hpcd: PCD handle
  693. * @param address: new device address
  694. * @retval HAL status
  695. */
  696. HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
  697. {
  698. __HAL_LOCK(hpcd);
  699. USB_SetDevAddress(hpcd->Instance, address);
  700. __HAL_UNLOCK(hpcd);
  701. return HAL_OK;
  702. }
  703. /**
  704. * @brief Open and configure an endpoint
  705. * @param hpcd: PCD handle
  706. * @param ep_addr: endpoint address
  707. * @param ep_mps: endpoint max packet size
  708. * @param ep_type: endpoint type
  709. * @retval HAL status
  710. */
  711. HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type)
  712. {
  713. HAL_StatusTypeDef ret = HAL_OK;
  714. USB_OTG_EPTypeDef *ep;
  715. if ((ep_addr & 0x80) == 0x80)
  716. {
  717. ep = &hpcd->IN_ep[ep_addr & 0x7F];
  718. }
  719. else
  720. {
  721. ep = &hpcd->OUT_ep[ep_addr & 0x7F];
  722. }
  723. ep->num = ep_addr & 0x7F;
  724. ep->is_in = (0x80 & ep_addr) != 0;
  725. ep->maxpacket = ep_mps;
  726. ep->type = ep_type;
  727. if (ep->is_in)
  728. {
  729. /* Assign a Tx FIFO */
  730. ep->tx_fifo_num = ep->num;
  731. }
  732. /* Set initial data PID. */
  733. if (ep_type == EP_TYPE_BULK )
  734. {
  735. ep->data_pid_start = 0;
  736. }
  737. __HAL_LOCK(hpcd);
  738. USB_ActivateEndpoint(hpcd->Instance , ep);
  739. __HAL_UNLOCK(hpcd);
  740. return ret;
  741. }
  742. /**
  743. * @brief Deactivate an endpoint
  744. * @param hpcd: PCD handle
  745. * @param ep_addr: endpoint address
  746. * @retval HAL status
  747. */
  748. HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  749. {
  750. USB_OTG_EPTypeDef *ep;
  751. if ((ep_addr & 0x80) == 0x80)
  752. {
  753. ep = &hpcd->IN_ep[ep_addr & 0x7F];
  754. }
  755. else
  756. {
  757. ep = &hpcd->OUT_ep[ep_addr & 0x7F];
  758. }
  759. ep->num = ep_addr & 0x7F;
  760. ep->is_in = (0x80 & ep_addr) != 0;
  761. __HAL_LOCK(hpcd);
  762. USB_DeactivateEndpoint(hpcd->Instance , ep);
  763. __HAL_UNLOCK(hpcd);
  764. return HAL_OK;
  765. }
  766. /**
  767. * @brief Receive an amount of data
  768. * @param hpcd: PCD handle
  769. * @param ep_addr: endpoint address
  770. * @param pBuf: pointer to the reception buffer
  771. * @param len: amount of data to be received
  772. * @retval HAL status
  773. */
  774. HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
  775. {
  776. USB_OTG_EPTypeDef *ep;
  777. ep = &hpcd->OUT_ep[ep_addr & 0x7F];
  778. /*setup and start the Xfer */
  779. ep->xfer_buff = pBuf;
  780. ep->xfer_len = len;
  781. ep->xfer_count = 0;
  782. ep->is_in = 0;
  783. ep->num = ep_addr & 0x7F;
  784. if (hpcd->Init.dma_enable == 1)
  785. {
  786. ep->dma_addr = (uint32_t)pBuf;
  787. }
  788. __HAL_LOCK(hpcd);
  789. if ((ep_addr & 0x7F) == 0 )
  790. {
  791. USB_EP0StartXfer(hpcd->Instance , ep, hpcd->Init.dma_enable);
  792. }
  793. else
  794. {
  795. USB_EPStartXfer(hpcd->Instance , ep, hpcd->Init.dma_enable);
  796. }
  797. __HAL_UNLOCK(hpcd);
  798. return HAL_OK;
  799. }
  800. /**
  801. * @brief Get Received Data Size
  802. * @param hpcd: PCD handle
  803. * @param ep_addr: endpoint address
  804. * @retval Data Size
  805. */
  806. uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  807. {
  808. return hpcd->OUT_ep[ep_addr & 0x7F].xfer_count;
  809. }
  810. /**
  811. * @brief Send an amount of data
  812. * @param hpcd: PCD handle
  813. * @param ep_addr: endpoint address
  814. * @param pBuf: pointer to the transmission buffer
  815. * @param len: amount of data to be sent
  816. * @retval HAL status
  817. */
  818. HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
  819. {
  820. USB_OTG_EPTypeDef *ep;
  821. ep = &hpcd->IN_ep[ep_addr & 0x7F];
  822. /*setup and start the Xfer */
  823. ep->xfer_buff = pBuf;
  824. ep->xfer_len = len;
  825. ep->xfer_count = 0;
  826. ep->is_in = 1;
  827. ep->num = ep_addr & 0x7F;
  828. if (hpcd->Init.dma_enable == 1)
  829. {
  830. ep->dma_addr = (uint32_t)pBuf;
  831. }
  832. __HAL_LOCK(hpcd);
  833. if ((ep_addr & 0x7F) == 0 )
  834. {
  835. USB_EP0StartXfer(hpcd->Instance , ep, hpcd->Init.dma_enable);
  836. }
  837. else
  838. {
  839. USB_EPStartXfer(hpcd->Instance , ep, hpcd->Init.dma_enable);
  840. }
  841. __HAL_UNLOCK(hpcd);
  842. return HAL_OK;
  843. }
  844. /**
  845. * @brief Set a STALL condition over an endpoint
  846. * @param hpcd: PCD handle
  847. * @param ep_addr: endpoint address
  848. * @retval HAL status
  849. */
  850. HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  851. {
  852. USB_OTG_EPTypeDef *ep;
  853. if ((0x80 & ep_addr) == 0x80)
  854. {
  855. ep = &hpcd->IN_ep[ep_addr & 0x7F];
  856. }
  857. else
  858. {
  859. ep = &hpcd->OUT_ep[ep_addr];
  860. }
  861. ep->is_stall = 1;
  862. ep->num = ep_addr & 0x7F;
  863. ep->is_in = ((ep_addr & 0x80) == 0x80);
  864. __HAL_LOCK(hpcd);
  865. USB_EPSetStall(hpcd->Instance , ep);
  866. if((ep_addr & 0x7F) == 0)
  867. {
  868. USB_EP0_OutStart(hpcd->Instance, hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup);
  869. }
  870. __HAL_UNLOCK(hpcd);
  871. return HAL_OK;
  872. }
  873. /**
  874. * @brief Clear a STALL condition over in an endpoint
  875. * @param hpcd: PCD handle
  876. * @param ep_addr: endpoint address
  877. * @retval HAL status
  878. */
  879. HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  880. {
  881. USB_OTG_EPTypeDef *ep;
  882. if ((0x80 & ep_addr) == 0x80)
  883. {
  884. ep = &hpcd->IN_ep[ep_addr & 0x7F];
  885. }
  886. else
  887. {
  888. ep = &hpcd->OUT_ep[ep_addr];
  889. }
  890. ep->is_stall = 0;
  891. ep->num = ep_addr & 0x7F;
  892. ep->is_in = ((ep_addr & 0x80) == 0x80);
  893. __HAL_LOCK(hpcd);
  894. USB_EPClearStall(hpcd->Instance , ep);
  895. __HAL_UNLOCK(hpcd);
  896. return HAL_OK;
  897. }
  898. /**
  899. * @brief Flush an endpoint
  900. * @param hpcd: PCD handle
  901. * @param ep_addr: endpoint address
  902. * @retval HAL status
  903. */
  904. HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  905. {
  906. __HAL_LOCK(hpcd);
  907. if ((ep_addr & 0x80) == 0x80)
  908. {
  909. USB_FlushTxFifo(hpcd->Instance, ep_addr & 0x7F);
  910. }
  911. else
  912. {
  913. USB_FlushRxFifo(hpcd->Instance);
  914. }
  915. __HAL_UNLOCK(hpcd);
  916. return HAL_OK;
  917. }
  918. /**
  919. * @brief HAL_PCD_ActivateRemoteWakeup : Active remote wake-up signalling
  920. * @param hpcd: PCD handle
  921. * @retval HAL status
  922. */
  923. HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
  924. {
  925. USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
  926. if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
  927. {
  928. /* Activate Remote wake-up signaling */
  929. USBx_DEVICE->DCTL |= USB_OTG_DCTL_RWUSIG;
  930. }
  931. return HAL_OK;
  932. }
  933. /**
  934. * @brief HAL_PCD_DeActivateRemoteWakeup : de-active remote wake-up signalling
  935. * @param hpcd: PCD handle
  936. * @retval HAL status
  937. */
  938. HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
  939. {
  940. USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
  941. /* De-activate Remote wake-up signaling */
  942. USBx_DEVICE->DCTL &= ~(USB_OTG_DCTL_RWUSIG);
  943. return HAL_OK;
  944. }
  945. /**
  946. * @}
  947. */
  948. /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
  949. * @brief Peripheral State functions
  950. *
  951. @verbatim
  952. ===============================================================================
  953. ##### Peripheral State functions #####
  954. ===============================================================================
  955. [..]
  956. This subsection permits to get in run-time the status of the peripheral
  957. and the data flow.
  958. @endverbatim
  959. * @{
  960. */
  961. /**
  962. * @brief Return the PCD state
  963. * @param hpcd: PCD handle
  964. * @retval HAL state
  965. */
  966. PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
  967. {
  968. return hpcd->State;
  969. }
  970. /**
  971. * @}
  972. */
  973. /**
  974. * @}
  975. */
  976. /* Private functions ---------------------------------------------------------*/
  977. /** @addtogroup PCD_Private_Functions
  978. * @{
  979. */
  980. /**
  981. * @brief DCD_WriteEmptyTxFifo
  982. * check FIFO for the next packet to be loaded
  983. * @param hpcd: PCD handle
  984. * @param epnum : endpoint number
  985. * @retval HAL status
  986. */
  987. static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
  988. {
  989. USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
  990. USB_OTG_EPTypeDef *ep;
  991. int32_t len = 0;
  992. uint32_t len32b;
  993. uint32_t fifoemptymsk = 0;
  994. ep = &hpcd->IN_ep[epnum];
  995. len = ep->xfer_len - ep->xfer_count;
  996. if (len > ep->maxpacket)
  997. {
  998. len = ep->maxpacket;
  999. }
  1000. len32b = (len + 3) / 4;
  1001. while ( (USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) > len32b &&
  1002. ep->xfer_count < ep->xfer_len &&
  1003. ep->xfer_len != 0)
  1004. {
  1005. /* Write the FIFO */
  1006. len = ep->xfer_len - ep->xfer_count;
  1007. if (len > ep->maxpacket)
  1008. {
  1009. len = ep->maxpacket;
  1010. }
  1011. len32b = (len + 3) / 4;
  1012. USB_WritePacket(USBx, ep->xfer_buff, epnum, len, hpcd->Init.dma_enable);
  1013. ep->xfer_buff += len;
  1014. ep->xfer_count += len;
  1015. }
  1016. if(len <= 0)
  1017. {
  1018. fifoemptymsk = 0x1 << epnum;
  1019. USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
  1020. }
  1021. return HAL_OK;
  1022. }
  1023. /**
  1024. * @}
  1025. */
  1026. #endif /* HAL_PCD_MODULE_ENABLED */
  1027. /**
  1028. * @}
  1029. */
  1030. /**
  1031. * @}
  1032. */
  1033. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/