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.
 
 
 

1405 lines
37 KiB

  1. /**
  2. ******************************************************************************
  3. * @file stm32f0xx_hal_pcd.c
  4. * @author MCD Application Team
  5. * @brief PCD HAL module driver.
  6. * This file provides firmware functions to manage the following
  7. * functionalities of the USB Peripheral Controller:
  8. * + Initialization and de-initialization functions
  9. * + IO operation functions
  10. * + Peripheral Control functions
  11. * + Peripheral State functions
  12. *
  13. @verbatim
  14. ==============================================================================
  15. ##### How to use this driver #####
  16. ==============================================================================
  17. [..]
  18. The PCD HAL driver can be used as follows:
  19. (#) Declare a PCD_HandleTypeDef handle structure, for example:
  20. PCD_HandleTypeDef hpcd;
  21. (#) Fill parameters of Init structure in HCD handle
  22. (#) Call HAL_PCD_Init() API to initialize the HCD peripheral (Core, Device core, ...)
  23. (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
  24. (##) Enable the PCD/USB Low Level interface clock using
  25. (+++) __HAL_RCC_USB_CLK_ENABLE);
  26. (##) Initialize the related GPIO clocks
  27. (##) Configure PCD pin-out
  28. (##) Configure PCD NVIC interrupt
  29. (#)Associate the Upper USB device stack to the HAL PCD Driver:
  30. (##) hpcd.pData = pdev;
  31. (#)Enable HCD transmission and reception:
  32. (##) HAL_PCD_Start();
  33. @endverbatim
  34. ******************************************************************************
  35. * @attention
  36. *
  37. * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
  38. *
  39. * Redistribution and use in source and binary forms, with or without modification,
  40. * are permitted provided that the following conditions are met:
  41. * 1. Redistributions of source code must retain the above copyright notice,
  42. * this list of conditions and the following disclaimer.
  43. * 2. Redistributions in binary form must reproduce the above copyright notice,
  44. * this list of conditions and the following disclaimer in the documentation
  45. * and/or other materials provided with the distribution.
  46. * 3. Neither the name of STMicroelectronics nor the names of its contributors
  47. * may be used to endorse or promote products derived from this software
  48. * without specific prior written permission.
  49. *
  50. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  51. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  52. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  53. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  54. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  55. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  56. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  57. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  58. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  59. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  60. *
  61. ******************************************************************************
  62. */
  63. /* Includes ------------------------------------------------------------------*/
  64. #include "stm32f0xx_hal.h"
  65. /** @addtogroup STM32F0xx_HAL_Driver
  66. * @{
  67. */
  68. #ifdef HAL_PCD_MODULE_ENABLED
  69. #if defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F072xB) || defined(STM32F078xx) || defined(STM32F070xB)|| defined(STM32F070x6)
  70. /** @defgroup PCD PCD
  71. * @brief PCD HAL module driver
  72. * @{
  73. */
  74. /* Private typedef -----------------------------------------------------------*/
  75. /* Private define ------------------------------------------------------------*/
  76. /** @defgroup PCD_Private_Define PCD Private Define
  77. * @{
  78. */
  79. #define BTABLE_ADDRESS (0x000)
  80. /**
  81. * @}
  82. */
  83. /* Private macro -------------------------------------------------------------*/
  84. /* Private variables ---------------------------------------------------------*/
  85. /* Private function prototypes -----------------------------------------------*/
  86. /** @defgroup PCD_Private_Functions PCD Private Functions
  87. * @{
  88. */
  89. static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd);
  90. void PCD_WritePMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes);
  91. void PCD_ReadPMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes);
  92. /**
  93. * @}
  94. */
  95. /* Exported functions --------------------------------------------------------*/
  96. /** @defgroup PCD_Exported_Functions PCD Exported Functions
  97. * @{
  98. */
  99. /** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
  100. * @brief Initialization and Configuration functions
  101. *
  102. @verbatim
  103. ===============================================================================
  104. ##### Initialization and de-initialization functions #####
  105. ===============================================================================
  106. [..] This section provides functions allowing to:
  107. @endverbatim
  108. * @{
  109. */
  110. /**
  111. * @brief Initializes the PCD according to the specified
  112. * parameters in the PCD_InitTypeDef and create the associated handle.
  113. * @param hpcd PCD handle
  114. * @retval HAL status
  115. */
  116. HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
  117. {
  118. uint32_t i = 0U;
  119. uint32_t wInterrupt_Mask = 0U;
  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. /* Init endpoints structures */
  136. for (i = 0U; i < hpcd->Init.dev_endpoints ; i++)
  137. {
  138. /* Init ep structure */
  139. hpcd->IN_ep[i].is_in = 1U;
  140. hpcd->IN_ep[i].num = i;
  141. /* Control until ep is actvated */
  142. hpcd->IN_ep[i].type = PCD_EP_TYPE_CTRL;
  143. hpcd->IN_ep[i].maxpacket = 0U;
  144. hpcd->IN_ep[i].xfer_buff = 0U;
  145. hpcd->IN_ep[i].xfer_len = 0U;
  146. }
  147. for (i = 0U; i < hpcd->Init.dev_endpoints ; i++)
  148. {
  149. hpcd->OUT_ep[i].is_in = 0U;
  150. hpcd->OUT_ep[i].num = i;
  151. /* Control until ep is activated */
  152. hpcd->OUT_ep[i].type = PCD_EP_TYPE_CTRL;
  153. hpcd->OUT_ep[i].maxpacket = 0U;
  154. hpcd->OUT_ep[i].xfer_buff = 0U;
  155. hpcd->OUT_ep[i].xfer_len = 0U;
  156. }
  157. /* Init Device */
  158. /*CNTR_FRES = 1*/
  159. hpcd->Instance->CNTR = USB_CNTR_FRES;
  160. /*CNTR_FRES = 0*/
  161. hpcd->Instance->CNTR = 0;
  162. /*Clear pending interrupts*/
  163. hpcd->Instance->ISTR = 0;
  164. /*Set Btable Adress*/
  165. hpcd->Instance->BTABLE = BTABLE_ADDRESS;
  166. /*set wInterrupt_Mask global variable*/
  167. wInterrupt_Mask = USB_CNTR_CTRM | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_ERRM \
  168. | USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_RESETM;
  169. /*Set interrupt mask*/
  170. hpcd->Instance->CNTR = wInterrupt_Mask;
  171. hpcd->USB_Address = 0U;
  172. hpcd->State= HAL_PCD_STATE_READY;
  173. return HAL_OK;
  174. }
  175. /**
  176. * @brief DeInitializes the PCD peripheral
  177. * @param hpcd PCD handle
  178. * @retval HAL status
  179. */
  180. HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
  181. {
  182. /* Check the PCD handle allocation */
  183. if(hpcd == NULL)
  184. {
  185. return HAL_ERROR;
  186. }
  187. hpcd->State = HAL_PCD_STATE_BUSY;
  188. /* Stop Device */
  189. HAL_PCD_Stop(hpcd);
  190. /* DeInit the low level hardware */
  191. HAL_PCD_MspDeInit(hpcd);
  192. hpcd->State = HAL_PCD_STATE_RESET;
  193. return HAL_OK;
  194. }
  195. /**
  196. * @brief Initializes the PCD MSP.
  197. * @param hpcd PCD handle
  198. * @retval None
  199. */
  200. __weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
  201. {
  202. /* Prevent unused argument(s) compilation warning */
  203. UNUSED(hpcd);
  204. /* NOTE : This function Should not be modified, when the callback is needed,
  205. the HAL_PCD_MspInit could be implemented in the user file
  206. */
  207. }
  208. /**
  209. * @brief DeInitializes PCD MSP.
  210. * @param hpcd PCD handle
  211. * @retval None
  212. */
  213. __weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
  214. {
  215. /* Prevent unused argument(s) compilation warning */
  216. UNUSED(hpcd);
  217. /* NOTE : This function Should not be modified, when the callback is needed,
  218. the HAL_PCD_MspDeInit could be implemented in the user file
  219. */
  220. }
  221. /**
  222. * @}
  223. */
  224. /** @defgroup PCD_Exported_Functions_Group2 IO operation functions
  225. * @brief Data transfers functions
  226. *
  227. @verbatim
  228. ===============================================================================
  229. ##### IO operation functions #####
  230. ===============================================================================
  231. [..]
  232. This subsection provides a set of functions allowing to manage the PCD data
  233. transfers.
  234. @endverbatim
  235. * @{
  236. */
  237. /**
  238. * @brief Start the USB device.
  239. * @param hpcd PCD handle
  240. * @retval HAL status
  241. */
  242. HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
  243. {
  244. /* Enabling DP Pull-Down bit to Connect internal pull-up on USB DP line */
  245. hpcd->Instance->BCDR |= USB_BCDR_DPPU;
  246. return HAL_OK;
  247. }
  248. /**
  249. * @brief Stop the USB device.
  250. * @param hpcd PCD handle
  251. * @retval HAL status
  252. */
  253. HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
  254. {
  255. __HAL_LOCK(hpcd);
  256. /* disable all interrupts and force USB reset */
  257. hpcd->Instance->CNTR = USB_CNTR_FRES;
  258. /* clear interrupt status register */
  259. hpcd->Instance->ISTR = 0;
  260. /* switch-off device */
  261. hpcd->Instance->CNTR = (USB_CNTR_FRES | USB_CNTR_PDWN);
  262. __HAL_UNLOCK(hpcd);
  263. return HAL_OK;
  264. }
  265. /**
  266. * @brief This function handles PCD interrupt request.
  267. * @param hpcd PCD handle
  268. * @retval HAL status
  269. */
  270. void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
  271. {
  272. uint32_t wInterrupt_Mask = 0U;
  273. if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_CTR))
  274. {
  275. /* servicing of the endpoint correct transfer interrupt */
  276. /* clear of the CTR flag into the sub */
  277. PCD_EP_ISR_Handler(hpcd);
  278. }
  279. if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_RESET))
  280. {
  281. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
  282. HAL_PCD_ResetCallback(hpcd);
  283. HAL_PCD_SetAddress(hpcd, 0U);
  284. }
  285. if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_PMAOVR))
  286. {
  287. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);
  288. }
  289. if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ERR))
  290. {
  291. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR);
  292. }
  293. if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP))
  294. {
  295. hpcd->Instance->CNTR &= (uint16_t)(~(USB_CNTR_LPMODE));
  296. /*set wInterrupt_Mask global variable*/
  297. wInterrupt_Mask = USB_CNTR_CTRM | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_ERRM \
  298. | USB_CNTR_ESOFM | USB_CNTR_RESETM;
  299. /*Set interrupt mask*/
  300. hpcd->Instance->CNTR = wInterrupt_Mask;
  301. HAL_PCD_ResumeCallback(hpcd);
  302. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);
  303. }
  304. if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SUSP))
  305. {
  306. /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
  307. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);
  308. /* Force low-power mode in the macrocell */
  309. hpcd->Instance->CNTR |= USB_CNTR_FSUSP;
  310. hpcd->Instance->CNTR |= USB_CNTR_LPMODE;
  311. if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP) == 0)
  312. {
  313. HAL_PCD_SuspendCallback(hpcd);
  314. }
  315. }
  316. if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SOF))
  317. {
  318. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);
  319. HAL_PCD_SOFCallback(hpcd);
  320. }
  321. if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ESOF))
  322. {
  323. /* clear ESOF flag in ISTR */
  324. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);
  325. }
  326. }
  327. /**
  328. * @brief Data out stage callbacks
  329. * @param hpcd PCD handle
  330. * @param epnum endpoint number
  331. * @retval None
  332. */
  333. __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  334. {
  335. /* Prevent unused argument(s) compilation warning */
  336. UNUSED(hpcd);
  337. UNUSED(epnum);
  338. /* NOTE : This function Should not be modified, when the callback is needed,
  339. the HAL_PCD_DataOutStageCallback could be implemented in the user file
  340. */
  341. }
  342. /**
  343. * @brief Data IN stage callbacks
  344. * @param hpcd PCD handle
  345. * @param epnum endpoint number
  346. * @retval None
  347. */
  348. __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  349. {
  350. /* Prevent unused argument(s) compilation warning */
  351. UNUSED(hpcd);
  352. UNUSED(epnum);
  353. /* NOTE : This function Should not be modified, when the callback is needed,
  354. the HAL_PCD_DataInStageCallback could be implemented in the user file
  355. */
  356. }
  357. /**
  358. * @brief Setup stage callback
  359. * @param hpcd PCD handle
  360. * @retval None
  361. */
  362. __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
  363. {
  364. /* Prevent unused argument(s) compilation warning */
  365. UNUSED(hpcd);
  366. /* NOTE : This function Should not be modified, when the callback is needed,
  367. the HAL_PCD_SetupStageCallback could be implemented in the user file
  368. */
  369. }
  370. /**
  371. * @brief USB Start Of Frame callbacks
  372. * @param hpcd PCD handle
  373. * @retval None
  374. */
  375. __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
  376. {
  377. /* Prevent unused argument(s) compilation warning */
  378. UNUSED(hpcd);
  379. /* NOTE : This function Should not be modified, when the callback is needed,
  380. the HAL_PCD_SOFCallback could be implemented in the user file
  381. */
  382. }
  383. /**
  384. * @brief USB Reset callbacks
  385. * @param hpcd PCD handle
  386. * @retval None
  387. */
  388. __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
  389. {
  390. /* Prevent unused argument(s) compilation warning */
  391. UNUSED(hpcd);
  392. /* NOTE : This function Should not be modified, when the callback is needed,
  393. the HAL_PCD_ResetCallback could be implemented in the user file
  394. */
  395. }
  396. /**
  397. * @brief Suspend event callbacks
  398. * @param hpcd PCD handle
  399. * @retval None
  400. */
  401. __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
  402. {
  403. /* Prevent unused argument(s) compilation warning */
  404. UNUSED(hpcd);
  405. /* NOTE : This function Should not be modified, when the callback is needed,
  406. the HAL_PCD_SuspendCallback could be implemented in the user file
  407. */
  408. }
  409. /**
  410. * @brief Resume event callbacks
  411. * @param hpcd PCD handle
  412. * @retval None
  413. */
  414. __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
  415. {
  416. /* Prevent unused argument(s) compilation warning */
  417. UNUSED(hpcd);
  418. /* NOTE : This function Should not be modified, when the callback is needed,
  419. the HAL_PCD_ResumeCallback could be implemented in the user file
  420. */
  421. }
  422. /**
  423. * @brief Incomplete ISO OUT callbacks
  424. * @param hpcd PCD handle
  425. * @param epnum endpoint number
  426. * @retval None
  427. */
  428. __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  429. {
  430. /* Prevent unused argument(s) compilation warning */
  431. UNUSED(hpcd);
  432. UNUSED(epnum);
  433. /* NOTE : This function Should not be modified, when the callback is needed,
  434. the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
  435. */
  436. }
  437. /**
  438. * @brief Incomplete ISO IN callbacks
  439. * @param hpcd PCD handle
  440. * @param epnum endpoint number
  441. * @retval None
  442. */
  443. __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  444. {
  445. /* Prevent unused argument(s) compilation warning */
  446. UNUSED(hpcd);
  447. UNUSED(epnum);
  448. /* NOTE : This function Should not be modified, when the callback is needed,
  449. the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
  450. */
  451. }
  452. /**
  453. * @brief Connection event callbacks
  454. * @param hpcd PCD handle
  455. * @retval None
  456. */
  457. __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
  458. {
  459. /* Prevent unused argument(s) compilation warning */
  460. UNUSED(hpcd);
  461. /* NOTE : This function Should not be modified, when the callback is needed,
  462. the HAL_PCD_ConnectCallback could be implemented in the user file
  463. */
  464. }
  465. /**
  466. * @brief Disconnection event callbacks
  467. * @param hpcd PCD handle
  468. * @retval None
  469. */
  470. __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
  471. {
  472. /* Prevent unused argument(s) compilation warning */
  473. UNUSED(hpcd);
  474. /* NOTE : This function Should not be modified, when the callback is needed,
  475. the HAL_PCD_DisconnectCallback could be implemented in the user file
  476. */
  477. }
  478. /**
  479. * @}
  480. */
  481. /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
  482. * @brief management functions
  483. *
  484. @verbatim
  485. ===============================================================================
  486. ##### Peripheral Control functions #####
  487. ===============================================================================
  488. [..]
  489. This subsection provides a set of functions allowing to control the PCD data
  490. transfers.
  491. @endverbatim
  492. * @{
  493. */
  494. /**
  495. * @brief Connect the USB device
  496. * @param hpcd PCD handle
  497. * @retval HAL status
  498. */
  499. HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
  500. {
  501. __HAL_LOCK(hpcd);
  502. /* Enabling DP Pull-Down bit to Connect internal pull-up on USB DP line */
  503. hpcd->Instance->BCDR |= USB_BCDR_DPPU;
  504. __HAL_UNLOCK(hpcd);
  505. return HAL_OK;
  506. }
  507. /**
  508. * @brief Disconnect the USB device
  509. * @param hpcd PCD handle
  510. * @retval HAL status
  511. */
  512. HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
  513. {
  514. __HAL_LOCK(hpcd);
  515. /* Disable DP Pull-Down bit*/
  516. hpcd->Instance->BCDR &= (uint16_t)(~(USB_BCDR_DPPU));
  517. __HAL_UNLOCK(hpcd);
  518. return HAL_OK;
  519. }
  520. /**
  521. * @brief Set the USB Device address
  522. * @param hpcd PCD handle
  523. * @param address new device address
  524. * @retval HAL status
  525. */
  526. HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
  527. {
  528. __HAL_LOCK(hpcd);
  529. if(address == 0U)
  530. {
  531. /* set device address and enable function */
  532. hpcd->Instance->DADDR = USB_DADDR_EF;
  533. }
  534. else /* USB Address will be applied later */
  535. {
  536. hpcd->USB_Address = address;
  537. }
  538. __HAL_UNLOCK(hpcd);
  539. return HAL_OK;
  540. }
  541. /**
  542. * @brief Open and configure an endpoint
  543. * @param hpcd PCD handle
  544. * @param ep_addr endpoint address
  545. * @param ep_mps endpoint max packert size
  546. * @param ep_type endpoint type
  547. * @retval HAL status
  548. */
  549. HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type)
  550. {
  551. HAL_StatusTypeDef ret = HAL_OK;
  552. PCD_EPTypeDef *ep;
  553. if ((ep_addr & 0x80U) == 0x80U)
  554. {
  555. ep = &hpcd->IN_ep[ep_addr & 0x7FU];
  556. }
  557. else
  558. {
  559. ep = &hpcd->OUT_ep[ep_addr & 0x7FU];
  560. }
  561. ep->num = ep_addr & 0x7FU;
  562. ep->is_in = (0x80U & ep_addr) != 0U;
  563. ep->maxpacket = ep_mps;
  564. ep->type = ep_type;
  565. __HAL_LOCK(hpcd);
  566. /* initialize Endpoint */
  567. switch (ep->type)
  568. {
  569. case PCD_EP_TYPE_CTRL:
  570. PCD_SET_EPTYPE(hpcd->Instance, ep->num, USB_EP_CONTROL);
  571. break;
  572. case PCD_EP_TYPE_BULK:
  573. PCD_SET_EPTYPE(hpcd->Instance, ep->num, USB_EP_BULK);
  574. break;
  575. case PCD_EP_TYPE_INTR:
  576. PCD_SET_EPTYPE(hpcd->Instance, ep->num, USB_EP_INTERRUPT);
  577. break;
  578. case PCD_EP_TYPE_ISOC:
  579. PCD_SET_EPTYPE(hpcd->Instance, ep->num, USB_EP_ISOCHRONOUS);
  580. break;
  581. default:
  582. break;
  583. }
  584. PCD_SET_EP_ADDRESS(hpcd->Instance, ep->num, ep->num);
  585. if (ep->doublebuffer == 0U)
  586. {
  587. if (ep->is_in)
  588. {
  589. /*Set the endpoint Transmit buffer address */
  590. PCD_SET_EP_TX_ADDRESS(hpcd->Instance, ep->num, ep->pmaadress);
  591. PCD_CLEAR_TX_DTOG(hpcd->Instance, ep->num)
  592. /* Configure NAK status for the Endpoint*/
  593. PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_NAK)
  594. }
  595. else
  596. {
  597. /*Set the endpoint Receive buffer address */
  598. PCD_SET_EP_RX_ADDRESS(hpcd->Instance, ep->num, ep->pmaadress);
  599. /*Set the endpoint Receive buffer counter*/
  600. PCD_SET_EP_RX_CNT(hpcd->Instance, ep->num, ep->maxpacket)
  601. PCD_CLEAR_RX_DTOG(hpcd->Instance, ep->num)
  602. /* Configure VALID status for the Endpoint*/
  603. PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_VALID)
  604. }
  605. }
  606. /*Double Buffer*/
  607. else
  608. {
  609. /*Set the endpoint as double buffered*/
  610. PCD_SET_EP_DBUF(hpcd->Instance, ep->num);
  611. /*Set buffer address for double buffered mode*/
  612. PCD_SET_EP_DBUF_ADDR(hpcd->Instance, ep->num,ep->pmaaddr0, ep->pmaaddr1)
  613. if (ep->is_in==0U)
  614. {
  615. /* Clear the data toggle bits for the endpoint IN/OUT*/
  616. PCD_CLEAR_RX_DTOG(hpcd->Instance, ep->num)
  617. PCD_CLEAR_TX_DTOG(hpcd->Instance, ep->num)
  618. /* Reset value of the data toggle bits for the endpoint out*/
  619. PCD_TX_DTOG(hpcd->Instance, ep->num);
  620. PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_VALID)
  621. PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_DIS)
  622. }
  623. else
  624. {
  625. /* Clear the data toggle bits for the endpoint IN/OUT*/
  626. PCD_CLEAR_RX_DTOG(hpcd->Instance, ep->num)
  627. PCD_CLEAR_TX_DTOG(hpcd->Instance, ep->num)
  628. PCD_RX_DTOG(hpcd->Instance, ep->num);
  629. /* Configure DISABLE status for the Endpoint*/
  630. PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_DIS)
  631. PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_DIS)
  632. }
  633. }
  634. __HAL_UNLOCK(hpcd);
  635. return ret;
  636. }
  637. /**
  638. * @brief Deactivate an endpoint
  639. * @param hpcd PCD handle
  640. * @param ep_addr endpoint address
  641. * @retval HAL status
  642. */
  643. HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  644. {
  645. PCD_EPTypeDef *ep;
  646. if ((ep_addr & 0x80U) == 0x80U)
  647. {
  648. ep = &hpcd->IN_ep[ep_addr & 0x7FU];
  649. }
  650. else
  651. {
  652. ep = &hpcd->OUT_ep[ep_addr & 0x7FU];
  653. }
  654. ep->num = ep_addr & 0x7FU;
  655. ep->is_in = (0x80U & ep_addr) != 0U;
  656. __HAL_LOCK(hpcd);
  657. if (ep->doublebuffer == 0U)
  658. {
  659. if (ep->is_in)
  660. {
  661. PCD_CLEAR_TX_DTOG(hpcd->Instance, ep->num)
  662. /* Configure DISABLE status for the Endpoint*/
  663. PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_DIS)
  664. }
  665. else
  666. {
  667. PCD_CLEAR_RX_DTOG(hpcd->Instance, ep->num)
  668. /* Configure DISABLE status for the Endpoint*/
  669. PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_DIS)
  670. }
  671. }
  672. /*Double Buffer*/
  673. else
  674. {
  675. if (ep->is_in==0U)
  676. {
  677. /* Clear the data toggle bits for the endpoint IN/OUT*/
  678. PCD_CLEAR_RX_DTOG(hpcd->Instance, ep->num)
  679. PCD_CLEAR_TX_DTOG(hpcd->Instance, ep->num)
  680. /* Reset value of the data toggle bits for the endpoint out*/
  681. PCD_TX_DTOG(hpcd->Instance, ep->num);
  682. PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_DIS)
  683. PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_DIS)
  684. }
  685. else
  686. {
  687. /* Clear the data toggle bits for the endpoint IN/OUT*/
  688. PCD_CLEAR_RX_DTOG(hpcd->Instance, ep->num)
  689. PCD_CLEAR_TX_DTOG(hpcd->Instance, ep->num)
  690. PCD_RX_DTOG(hpcd->Instance, ep->num);
  691. /* Configure DISABLE status for the Endpoint*/
  692. PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_DIS)
  693. PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_DIS)
  694. }
  695. }
  696. __HAL_UNLOCK(hpcd);
  697. return HAL_OK;
  698. }
  699. /**
  700. * @brief Receive an amount of data
  701. * @param hpcd PCD handle
  702. * @param ep_addr endpoint address
  703. * @param pBuf pointer to the reception buffer
  704. * @param len amount of data to be received
  705. * @retval HAL status
  706. */
  707. HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
  708. {
  709. PCD_EPTypeDef *ep;
  710. ep = &hpcd->OUT_ep[ep_addr & 0x7FU];
  711. /*setup and start the Xfer */
  712. ep->xfer_buff = pBuf;
  713. ep->xfer_len = len;
  714. ep->xfer_count = 0U;
  715. ep->is_in = 0U;
  716. ep->num = ep_addr & 0x7FU;
  717. /* Multi packet transfer*/
  718. if (ep->xfer_len > ep->maxpacket)
  719. {
  720. len=ep->maxpacket;
  721. ep->xfer_len-=len;
  722. }
  723. else
  724. {
  725. len=ep->xfer_len;
  726. ep->xfer_len =0U;
  727. }
  728. /* configure and validate Rx endpoint */
  729. if (ep->doublebuffer == 0)
  730. {
  731. /*Set RX buffer count*/
  732. PCD_SET_EP_RX_CNT(hpcd->Instance, ep->num, len)
  733. }
  734. else
  735. {
  736. /*Set the Double buffer counter*/
  737. PCD_SET_EP_DBUF_CNT(hpcd->Instance, ep->num, ep->is_in, len)
  738. }
  739. PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_VALID)
  740. return HAL_OK;
  741. }
  742. /**
  743. * @brief Get Received Data Size
  744. * @param hpcd PCD handle
  745. * @param ep_addr endpoint address
  746. * @retval Data Size
  747. */
  748. uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  749. {
  750. return hpcd->OUT_ep[ep_addr & 0x7FU].xfer_count;
  751. }
  752. /**
  753. * @brief Send an amount of data
  754. * @param hpcd PCD handle
  755. * @param ep_addr endpoint address
  756. * @param pBuf pointer to the transmission buffer
  757. * @param len amount of data to be sent
  758. * @retval HAL status
  759. */
  760. HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
  761. {
  762. PCD_EPTypeDef *ep;
  763. uint16_t pmabuffer = 0U;
  764. ep = &hpcd->IN_ep[ep_addr & 0x7FU];
  765. /*setup and start the Xfer */
  766. ep->xfer_buff = pBuf;
  767. ep->xfer_len = len;
  768. ep->xfer_count = 0U;
  769. ep->is_in = 1U;
  770. ep->num = ep_addr & 0x7FU;
  771. /*Multi packet transfer*/
  772. if (ep->xfer_len > ep->maxpacket)
  773. {
  774. len=ep->maxpacket;
  775. ep->xfer_len-=len;
  776. }
  777. else
  778. {
  779. len=ep->xfer_len;
  780. ep->xfer_len =0U;
  781. }
  782. /* configure and validate Tx endpoint */
  783. if (ep->doublebuffer == 0U)
  784. {
  785. PCD_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, len);
  786. PCD_SET_EP_TX_CNT(hpcd->Instance, ep->num, len);
  787. }
  788. else
  789. {
  790. /*Write the data to the USB endpoint*/
  791. if ((PCD_GET_ENDPOINT(hpcd->Instance, ep->num)& USB_EP_DTOG_TX) == USB_EP_DTOG_TX)
  792. {
  793. /*Set the Double buffer counter for pmabuffer1*/
  794. PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, len)
  795. pmabuffer = ep->pmaaddr1;
  796. }
  797. else
  798. {
  799. /*Set the Double buffer counter for pmabuffer0*/
  800. PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, len)
  801. pmabuffer = ep->pmaaddr0;
  802. }
  803. PCD_WritePMA(hpcd->Instance, ep->xfer_buff, pmabuffer, len);
  804. PCD_FreeUserBuffer(hpcd->Instance, ep->num, ep->is_in)
  805. }
  806. PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_VALID)
  807. return HAL_OK;
  808. }
  809. /**
  810. * @brief Set a STALL condition over an endpoint
  811. * @param hpcd PCD handle
  812. * @param ep_addr endpoint address
  813. * @retval HAL status
  814. */
  815. HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  816. {
  817. PCD_EPTypeDef *ep;
  818. __HAL_LOCK(hpcd);
  819. if ((0x80U & ep_addr) == 0x80U)
  820. {
  821. ep = &hpcd->IN_ep[ep_addr & 0x7FU];
  822. }
  823. else
  824. {
  825. ep = &hpcd->OUT_ep[ep_addr];
  826. }
  827. ep->is_stall = 1;
  828. ep->num = ep_addr & 0x7FU;
  829. ep->is_in = ((ep_addr & 0x80U) == 0x80U);
  830. if (ep->num == 0U)
  831. {
  832. /* This macro sets STALL status for RX & TX*/
  833. PCD_SET_EP_TXRX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_STALL, USB_EP_TX_STALL)
  834. }
  835. else
  836. {
  837. if (ep->is_in)
  838. {
  839. PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num , USB_EP_TX_STALL)
  840. }
  841. else
  842. {
  843. PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num , USB_EP_RX_STALL)
  844. }
  845. }
  846. __HAL_UNLOCK(hpcd);
  847. return HAL_OK;
  848. }
  849. /**
  850. * @brief Clear a STALL condition over in an endpoint
  851. * @param hpcd PCD handle
  852. * @param ep_addr endpoint address
  853. * @retval HAL status
  854. */
  855. HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  856. {
  857. PCD_EPTypeDef *ep;
  858. if ((0x80U & ep_addr) == 0x80U)
  859. {
  860. ep = &hpcd->IN_ep[ep_addr & 0x7FU];
  861. }
  862. else
  863. {
  864. ep = &hpcd->OUT_ep[ep_addr];
  865. }
  866. ep->is_stall = 0U;
  867. ep->num = ep_addr & 0x7FU;
  868. ep->is_in = ((ep_addr & 0x80U) == 0x80U);
  869. __HAL_LOCK(hpcd);
  870. if (ep->is_in)
  871. {
  872. PCD_CLEAR_TX_DTOG(hpcd->Instance, ep->num)
  873. PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_VALID)
  874. }
  875. else
  876. {
  877. PCD_CLEAR_RX_DTOG(hpcd->Instance, ep->num)
  878. PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_VALID)
  879. }
  880. __HAL_UNLOCK(hpcd);
  881. return HAL_OK;
  882. }
  883. /**
  884. * @brief Flush an endpoint
  885. * @param hpcd PCD handle
  886. * @param ep_addr endpoint address
  887. * @retval HAL status
  888. */
  889. HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  890. {
  891. return HAL_OK;
  892. }
  893. /**
  894. * @brief HAL_PCD_ActivateRemoteWakeup : active remote wakeup signalling
  895. * @param hpcd PCD handle
  896. * @retval HAL status
  897. */
  898. HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
  899. {
  900. if (hpcd->Init.lpm_enable ==1)
  901. {
  902. /* Apply L1 Resume */
  903. hpcd->Instance->CNTR |= USB_CNTR_L1RESUME;
  904. }
  905. else
  906. {
  907. /* Apply L2 Resume */
  908. hpcd->Instance->CNTR |= USB_CNTR_RESUME;
  909. }
  910. return (HAL_OK);
  911. }
  912. /**
  913. * @brief HAL_PCD_DeActivateRemoteWakeup : de-active remote wakeup signalling
  914. * @param hpcd PCD handle
  915. * @retval HAL status
  916. */
  917. HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
  918. {
  919. if (hpcd->Init.lpm_enable ==1)
  920. {
  921. /* Release L1 Resume */
  922. hpcd->Instance->CNTR &= ((uint16_t)(~ USB_CNTR_L1RESUME));
  923. }
  924. else
  925. {
  926. /* Release L2 Resume */
  927. hpcd->Instance->CNTR &= ((uint16_t)(~ USB_CNTR_RESUME)) ;
  928. }
  929. return (HAL_OK);
  930. }
  931. /**
  932. * @}
  933. */
  934. /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
  935. * @brief Peripheral State functions
  936. *
  937. @verbatim
  938. ===============================================================================
  939. ##### Peripheral State functions #####
  940. ===============================================================================
  941. [..]
  942. This subsection permits to get in run-time the status of the peripheral
  943. and the data flow.
  944. @endverbatim
  945. * @{
  946. */
  947. /**
  948. * @brief Return the PCD state
  949. * @param hpcd PCD handle
  950. * @retval HAL state
  951. */
  952. PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
  953. {
  954. return hpcd->State;
  955. }
  956. /**
  957. * @}
  958. */
  959. /**
  960. * @}
  961. */
  962. /** @addtogroup PCD_Private_Functions
  963. * @{
  964. */
  965. /**
  966. * @brief Copy a buffer from user memory area to packet memory area (PMA)
  967. * @param USBx USB peripheral instance register address.
  968. * @param pbUsrBuf pointer to user memory area.
  969. * @param wPMABufAddr address into PMA.
  970. * @param wNBytes no. of bytes to be copied.
  971. * @retval None
  972. */
  973. void PCD_WritePMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
  974. {
  975. uint32_t n = ((uint32_t)((uint32_t)wNBytes + 1U)) >> 1U;
  976. uint32_t i;
  977. uint16_t temp1, temp2;
  978. uint16_t *pdwVal;
  979. pdwVal = (uint16_t *)((uint32_t)(wPMABufAddr + (uint32_t)USBx + 0x400U));
  980. for (i = n; i != 0; i--)
  981. {
  982. temp1 = (uint16_t) * pbUsrBuf;
  983. pbUsrBuf++;
  984. temp2 = temp1 | ((uint16_t)((uint16_t) * pbUsrBuf << 8U)) ;
  985. *pdwVal++ = temp2;
  986. pbUsrBuf++;
  987. }
  988. }
  989. /**
  990. * @brief Copy a buffer from user memory area to packet memory area (PMA)
  991. * @param USBx USB peripheral instance register address.
  992. * @param pbUsrBuf = pointer to user memory area.
  993. * @param wPMABufAddr address into PMA.
  994. * @param wNBytes no. of bytes to be copied.
  995. * @retval None
  996. */
  997. void PCD_ReadPMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
  998. {
  999. uint32_t n = (uint32_t)wNBytes >> 1U;
  1000. uint32_t i;
  1001. uint16_t *pdwVal;
  1002. uint32_t temp;
  1003. pdwVal = (uint16_t *)((uint32_t)(wPMABufAddr + (uint32_t)USBx + 0x400U));
  1004. for (i = n; i != 0U; i--)
  1005. {
  1006. temp = *pdwVal++;
  1007. *pbUsrBuf++ = ((temp >> 0) & 0xFF);
  1008. *pbUsrBuf++ = ((temp >> 8) & 0xFF);
  1009. }
  1010. if (wNBytes % 2)
  1011. {
  1012. temp = *pdwVal++;
  1013. *pbUsrBuf++ = ((temp >> 0) & 0xFF);
  1014. }
  1015. }
  1016. /**
  1017. * @brief This function handles PCD Endpoint interrupt request.
  1018. * @param hpcd PCD handle
  1019. * @retval HAL status
  1020. */
  1021. static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
  1022. {
  1023. PCD_EPTypeDef *ep;
  1024. uint16_t count=0U;
  1025. uint8_t EPindex;
  1026. __IO uint16_t wIstr;
  1027. __IO uint16_t wEPVal = 0U;
  1028. /* stay in loop while pending interrupts */
  1029. while (((wIstr = hpcd->Instance->ISTR) & USB_ISTR_CTR) != 0U)
  1030. {
  1031. /* extract highest priority endpoint number */
  1032. EPindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
  1033. if (EPindex == 0U)
  1034. {
  1035. /* Decode and service control endpoint interrupt */
  1036. /* DIR bit = origin of the interrupt */
  1037. if ((wIstr & USB_ISTR_DIR) == 0U)
  1038. {
  1039. /* DIR = 0 */
  1040. /* DIR = 0 => IN int */
  1041. /* DIR = 0 implies that (EP_CTR_TX = 1) always */
  1042. PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
  1043. ep = &hpcd->IN_ep[0];
  1044. ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
  1045. ep->xfer_buff += ep->xfer_count;
  1046. /* TX COMPLETE */
  1047. HAL_PCD_DataInStageCallback(hpcd, 0U);
  1048. if((hpcd->USB_Address > 0U)&& ( ep->xfer_len == 0U))
  1049. {
  1050. hpcd->Instance->DADDR = (hpcd->USB_Address | USB_DADDR_EF);
  1051. hpcd->USB_Address = 0U;
  1052. }
  1053. }
  1054. else
  1055. {
  1056. /* DIR = 1 */
  1057. /* DIR = 1 & CTR_RX => SETUP or OUT int */
  1058. /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
  1059. ep = &hpcd->OUT_ep[0];
  1060. wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
  1061. if ((wEPVal & USB_EP_SETUP) != 0U)
  1062. {
  1063. /* Get SETUP Packet*/
  1064. ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
  1065. PCD_ReadPMA(hpcd->Instance, (uint8_t*)(void*)hpcd->Setup ,ep->pmaadress , ep->xfer_count);
  1066. /* SETUP bit kept frozen while CTR_RX = 1*/
  1067. PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
  1068. /* Process SETUP Packet*/
  1069. HAL_PCD_SetupStageCallback(hpcd);
  1070. }
  1071. else if ((wEPVal & USB_EP_CTR_RX) != 0U)
  1072. {
  1073. PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
  1074. /* Get Control Data OUT Packet*/
  1075. ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
  1076. if (ep->xfer_count != 0U)
  1077. {
  1078. PCD_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count);
  1079. ep->xfer_buff+=ep->xfer_count;
  1080. }
  1081. /* Process Control Data OUT Packet*/
  1082. HAL_PCD_DataOutStageCallback(hpcd, 0U);
  1083. PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket)
  1084. PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID)
  1085. }
  1086. }
  1087. }
  1088. else
  1089. {
  1090. /* Decode and service non control endpoints interrupt */
  1091. /* process related endpoint register */
  1092. wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, EPindex);
  1093. if ((wEPVal & USB_EP_CTR_RX) != 0U)
  1094. {
  1095. /* clear int flag */
  1096. PCD_CLEAR_RX_EP_CTR(hpcd->Instance, EPindex);
  1097. ep = &hpcd->OUT_ep[EPindex];
  1098. /* OUT double Buffering*/
  1099. if (ep->doublebuffer == 0U)
  1100. {
  1101. count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
  1102. if (count != 0U)
  1103. {
  1104. PCD_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
  1105. }
  1106. }
  1107. else
  1108. {
  1109. if ((PCD_GET_ENDPOINT(hpcd->Instance, ep->num)& USB_EP_DTOG_RX) == USB_EP_DTOG_RX)
  1110. {
  1111. /*read from endpoint BUF0Addr buffer*/
  1112. count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
  1113. if (count != 0U)
  1114. {
  1115. PCD_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
  1116. }
  1117. }
  1118. else
  1119. {
  1120. /*read from endpoint BUF1Addr buffer*/
  1121. count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
  1122. if (count != 0U)
  1123. {
  1124. PCD_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
  1125. }
  1126. }
  1127. PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_OUT)
  1128. }
  1129. /*multi-packet on the NON control OUT endpoint*/
  1130. ep->xfer_count+=count;
  1131. ep->xfer_buff+=count;
  1132. if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
  1133. {
  1134. /* RX COMPLETE */
  1135. HAL_PCD_DataOutStageCallback(hpcd, ep->num);
  1136. }
  1137. else
  1138. {
  1139. HAL_PCD_EP_Receive(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
  1140. }
  1141. } /* if((wEPVal & EP_CTR_RX) */
  1142. if ((wEPVal & USB_EP_CTR_TX) != 0U)
  1143. {
  1144. ep = &hpcd->IN_ep[EPindex];
  1145. /* clear int flag */
  1146. PCD_CLEAR_TX_EP_CTR(hpcd->Instance, EPindex);
  1147. /* IN double Buffering*/
  1148. if (ep->doublebuffer == 0U)
  1149. {
  1150. ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
  1151. if (ep->xfer_count != 0)
  1152. {
  1153. PCD_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count);
  1154. }
  1155. }
  1156. else
  1157. {
  1158. if ((PCD_GET_ENDPOINT(hpcd->Instance, ep->num)& USB_EP_DTOG_TX) == USB_EP_DTOG_TX)
  1159. {
  1160. /*read from endpoint BUF0Addr buffer*/
  1161. ep->xfer_count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
  1162. if (ep->xfer_count != 0U)
  1163. {
  1164. PCD_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, ep->xfer_count);
  1165. }
  1166. }
  1167. else
  1168. {
  1169. /*read from endpoint BUF1Addr buffer*/
  1170. ep->xfer_count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
  1171. if (ep->xfer_count != 0U)
  1172. {
  1173. PCD_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, ep->xfer_count);
  1174. }
  1175. }
  1176. PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_IN)
  1177. }
  1178. /*multi-packet on the NON control IN endpoint*/
  1179. ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
  1180. ep->xfer_buff+=ep->xfer_count;
  1181. /* Zero Length Packet? */
  1182. if (ep->xfer_len == 0U)
  1183. {
  1184. /* TX COMPLETE */
  1185. HAL_PCD_DataInStageCallback(hpcd, ep->num);
  1186. }
  1187. else
  1188. {
  1189. HAL_PCD_EP_Transmit(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
  1190. }
  1191. }
  1192. }
  1193. }
  1194. return HAL_OK;
  1195. }
  1196. /**
  1197. * @}
  1198. */
  1199. /**
  1200. * @}
  1201. */
  1202. #endif /* STM32F042x6 || STM32F072xB || STM32F078xx || STM32F070xB || STM32F070x6 */
  1203. #endif /* HAL_PCD_MODULE_ENABLED */
  1204. /**
  1205. * @}
  1206. */
  1207. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/