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.
 
 
 

1256 lines
33 KiB

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