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.
 
 
 

1879 lines
47 KiB

  1. /**
  2. ******************************************************************************
  3. * @file stm32l0xx_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 PCD 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(); For USB Device only FS peripheral
  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 PCD transmission and reception:
  32. (##) HAL_PCD_Start();
  33. @endverbatim
  34. ******************************************************************************
  35. * @attention
  36. *
  37. * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
  38. * All rights reserved.</center></h2>
  39. *
  40. * This software component is licensed by ST under BSD 3-Clause license,
  41. * the "License"; You may not use this file except in compliance with the
  42. * License. You may obtain a copy of the License at:
  43. * opensource.org/licenses/BSD-3-Clause
  44. *
  45. ******************************************************************************
  46. */
  47. /* Includes ------------------------------------------------------------------*/
  48. #include "stm32l0xx_hal.h"
  49. /** @addtogroup STM32L0xx_HAL_Driver
  50. * @{
  51. */
  52. /** @defgroup PCD PCD
  53. * @brief PCD HAL module driver
  54. * @{
  55. */
  56. #ifdef HAL_PCD_MODULE_ENABLED
  57. #if defined (USB)
  58. /* Private types -------------------------------------------------------------*/
  59. /* Private variables ---------------------------------------------------------*/
  60. /* Private constants ---------------------------------------------------------*/
  61. /* Private macros ------------------------------------------------------------*/
  62. /** @defgroup PCD_Private_Macros PCD Private Macros
  63. * @{
  64. */
  65. #define PCD_MIN(a, b) (((a) < (b)) ? (a) : (b))
  66. #define PCD_MAX(a, b) (((a) > (b)) ? (a) : (b))
  67. /**
  68. * @}
  69. */
  70. /* Private functions prototypes ----------------------------------------------*/
  71. /** @defgroup PCD_Private_Functions PCD Private Functions
  72. * @{
  73. */
  74. static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd);
  75. /**
  76. * @}
  77. */
  78. /* Exported functions --------------------------------------------------------*/
  79. /** @defgroup PCD_Exported_Functions PCD Exported Functions
  80. * @{
  81. */
  82. /** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
  83. * @brief Initialization and Configuration functions
  84. *
  85. @verbatim
  86. ===============================================================================
  87. ##### Initialization and de-initialization functions #####
  88. ===============================================================================
  89. [..] This section provides functions allowing to:
  90. @endverbatim
  91. * @{
  92. */
  93. /**
  94. * @brief Initializes the PCD according to the specified
  95. * parameters in the PCD_InitTypeDef and initialize the associated handle.
  96. * @param hpcd PCD handle
  97. * @retval HAL status
  98. */
  99. HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
  100. {
  101. uint8_t i;
  102. /* Check the PCD handle allocation */
  103. if (hpcd == NULL)
  104. {
  105. return HAL_ERROR;
  106. }
  107. /* Check the parameters */
  108. assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
  109. if (hpcd->State == HAL_PCD_STATE_RESET)
  110. {
  111. /* Allocate lock resource and initialize it */
  112. hpcd->Lock = HAL_UNLOCKED;
  113. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  114. hpcd->SOFCallback = HAL_PCD_SOFCallback;
  115. hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
  116. hpcd->ResetCallback = HAL_PCD_ResetCallback;
  117. hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
  118. hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
  119. hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
  120. hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
  121. hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback;
  122. hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback;
  123. hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback;
  124. hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback;
  125. hpcd->LPMCallback = HAL_PCDEx_LPM_Callback;
  126. hpcd->BCDCallback = HAL_PCDEx_BCD_Callback;
  127. if (hpcd->MspInitCallback == NULL)
  128. {
  129. hpcd->MspInitCallback = HAL_PCD_MspInit;
  130. }
  131. /* Init the low level hardware */
  132. hpcd->MspInitCallback(hpcd);
  133. #else
  134. /* Init the low level hardware : GPIO, CLOCK, NVIC... */
  135. HAL_PCD_MspInit(hpcd);
  136. #endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */
  137. }
  138. hpcd->State = HAL_PCD_STATE_BUSY;
  139. /* Disable the Interrupts */
  140. __HAL_PCD_DISABLE(hpcd);
  141. /* Init endpoints structures */
  142. for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
  143. {
  144. /* Init ep structure */
  145. hpcd->IN_ep[i].is_in = 1U;
  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 = 0U;
  151. hpcd->IN_ep[i].xfer_buff = 0U;
  152. hpcd->IN_ep[i].xfer_len = 0U;
  153. }
  154. for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
  155. {
  156. hpcd->OUT_ep[i].is_in = 0U;
  157. hpcd->OUT_ep[i].num = i;
  158. /* Control until ep is activated */
  159. hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
  160. hpcd->OUT_ep[i].maxpacket = 0U;
  161. hpcd->OUT_ep[i].xfer_buff = 0U;
  162. hpcd->OUT_ep[i].xfer_len = 0U;
  163. }
  164. /* Init Device */
  165. if (USB_DevInit(hpcd->Instance, hpcd->Init) != HAL_OK)
  166. {
  167. hpcd->State = HAL_PCD_STATE_ERROR;
  168. return HAL_ERROR;
  169. }
  170. hpcd->USB_Address = 0U;
  171. hpcd->State = HAL_PCD_STATE_READY;
  172. /* Activate LPM */
  173. if (hpcd->Init.lpm_enable == 1U)
  174. {
  175. (void)HAL_PCDEx_ActivateLPM(hpcd);
  176. }
  177. /* Activate Battery charging */
  178. if (hpcd->Init.battery_charging_enable == 1U)
  179. {
  180. (void)HAL_PCDEx_ActivateBCD(hpcd);
  181. }
  182. return HAL_OK;
  183. }
  184. /**
  185. * @brief DeInitializes the PCD peripheral.
  186. * @param hpcd PCD handle
  187. * @retval HAL status
  188. */
  189. HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
  190. {
  191. /* Check the PCD handle allocation */
  192. if (hpcd == NULL)
  193. {
  194. return HAL_ERROR;
  195. }
  196. hpcd->State = HAL_PCD_STATE_BUSY;
  197. /* Stop Device */
  198. (void)HAL_PCD_Stop(hpcd);
  199. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  200. if (hpcd->MspDeInitCallback == NULL)
  201. {
  202. hpcd->MspDeInitCallback = HAL_PCD_MspDeInit; /* Legacy weak MspDeInit */
  203. }
  204. /* DeInit the low level hardware */
  205. hpcd->MspDeInitCallback(hpcd);
  206. #else
  207. /* DeInit the low level hardware: CLOCK, NVIC.*/
  208. HAL_PCD_MspDeInit(hpcd);
  209. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  210. hpcd->State = HAL_PCD_STATE_RESET;
  211. return HAL_OK;
  212. }
  213. /**
  214. * @brief Initializes the PCD MSP.
  215. * @param hpcd PCD handle
  216. * @retval None
  217. */
  218. __weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
  219. {
  220. /* Prevent unused argument(s) compilation warning */
  221. UNUSED(hpcd);
  222. /* NOTE : This function should not be modified, when the callback is needed,
  223. the HAL_PCD_MspInit could be implemented in the user file
  224. */
  225. }
  226. /**
  227. * @brief DeInitializes PCD MSP.
  228. * @param hpcd PCD handle
  229. * @retval None
  230. */
  231. __weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
  232. {
  233. /* Prevent unused argument(s) compilation warning */
  234. UNUSED(hpcd);
  235. /* NOTE : This function should not be modified, when the callback is needed,
  236. the HAL_PCD_MspDeInit could be implemented in the user file
  237. */
  238. }
  239. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  240. /**
  241. * @brief Register a User USB PCD Callback
  242. * To be used instead of the weak predefined callback
  243. * @param hpcd USB PCD handle
  244. * @param CallbackID ID of the callback to be registered
  245. * This parameter can be one of the following values:
  246. * @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
  247. * @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
  248. * @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
  249. * @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
  250. * @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
  251. * @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
  252. * @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
  253. * @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
  254. * @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
  255. * @param pCallback pointer to the Callback function
  256. * @retval HAL status
  257. */
  258. HAL_StatusTypeDef HAL_PCD_RegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID, pPCD_CallbackTypeDef pCallback)
  259. {
  260. HAL_StatusTypeDef status = HAL_OK;
  261. if (pCallback == NULL)
  262. {
  263. /* Update the error code */
  264. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  265. return HAL_ERROR;
  266. }
  267. /* Process locked */
  268. __HAL_LOCK(hpcd);
  269. if (hpcd->State == HAL_PCD_STATE_READY)
  270. {
  271. switch (CallbackID)
  272. {
  273. case HAL_PCD_SOF_CB_ID :
  274. hpcd->SOFCallback = pCallback;
  275. break;
  276. case HAL_PCD_SETUPSTAGE_CB_ID :
  277. hpcd->SetupStageCallback = pCallback;
  278. break;
  279. case HAL_PCD_RESET_CB_ID :
  280. hpcd->ResetCallback = pCallback;
  281. break;
  282. case HAL_PCD_SUSPEND_CB_ID :
  283. hpcd->SuspendCallback = pCallback;
  284. break;
  285. case HAL_PCD_RESUME_CB_ID :
  286. hpcd->ResumeCallback = pCallback;
  287. break;
  288. case HAL_PCD_CONNECT_CB_ID :
  289. hpcd->ConnectCallback = pCallback;
  290. break;
  291. case HAL_PCD_DISCONNECT_CB_ID :
  292. hpcd->DisconnectCallback = pCallback;
  293. break;
  294. case HAL_PCD_MSPINIT_CB_ID :
  295. hpcd->MspInitCallback = pCallback;
  296. break;
  297. case HAL_PCD_MSPDEINIT_CB_ID :
  298. hpcd->MspDeInitCallback = pCallback;
  299. break;
  300. default :
  301. /* Update the error code */
  302. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  303. /* Return error status */
  304. status = HAL_ERROR;
  305. break;
  306. }
  307. }
  308. else if (hpcd->State == HAL_PCD_STATE_RESET)
  309. {
  310. switch (CallbackID)
  311. {
  312. case HAL_PCD_MSPINIT_CB_ID :
  313. hpcd->MspInitCallback = pCallback;
  314. break;
  315. case HAL_PCD_MSPDEINIT_CB_ID :
  316. hpcd->MspDeInitCallback = pCallback;
  317. break;
  318. default :
  319. /* Update the error code */
  320. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  321. /* Return error status */
  322. status = HAL_ERROR;
  323. break;
  324. }
  325. }
  326. else
  327. {
  328. /* Update the error code */
  329. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  330. /* Return error status */
  331. status = HAL_ERROR;
  332. }
  333. /* Release Lock */
  334. __HAL_UNLOCK(hpcd);
  335. return status;
  336. }
  337. /**
  338. * @brief Unregister an USB PCD Callback
  339. * USB PCD callabck is redirected to the weak predefined callback
  340. * @param hpcd USB PCD handle
  341. * @param CallbackID ID of the callback to be unregistered
  342. * This parameter can be one of the following values:
  343. * @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
  344. * @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
  345. * @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
  346. * @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
  347. * @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
  348. * @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
  349. * @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
  350. * @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
  351. * @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
  352. * @retval HAL status
  353. */
  354. HAL_StatusTypeDef HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID)
  355. {
  356. HAL_StatusTypeDef status = HAL_OK;
  357. /* Process locked */
  358. __HAL_LOCK(hpcd);
  359. /* Setup Legacy weak Callbacks */
  360. if (hpcd->State == HAL_PCD_STATE_READY)
  361. {
  362. switch (CallbackID)
  363. {
  364. case HAL_PCD_SOF_CB_ID :
  365. hpcd->SOFCallback = HAL_PCD_SOFCallback;
  366. break;
  367. case HAL_PCD_SETUPSTAGE_CB_ID :
  368. hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
  369. break;
  370. case HAL_PCD_RESET_CB_ID :
  371. hpcd->ResetCallback = HAL_PCD_ResetCallback;
  372. break;
  373. case HAL_PCD_SUSPEND_CB_ID :
  374. hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
  375. break;
  376. case HAL_PCD_RESUME_CB_ID :
  377. hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
  378. break;
  379. case HAL_PCD_CONNECT_CB_ID :
  380. hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
  381. break;
  382. case HAL_PCD_DISCONNECT_CB_ID :
  383. hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
  384. break;
  385. case HAL_PCD_MSPINIT_CB_ID :
  386. hpcd->MspInitCallback = HAL_PCD_MspInit;
  387. break;
  388. case HAL_PCD_MSPDEINIT_CB_ID :
  389. hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
  390. break;
  391. default :
  392. /* Update the error code */
  393. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  394. /* Return error status */
  395. status = HAL_ERROR;
  396. break;
  397. }
  398. }
  399. else if (hpcd->State == HAL_PCD_STATE_RESET)
  400. {
  401. switch (CallbackID)
  402. {
  403. case HAL_PCD_MSPINIT_CB_ID :
  404. hpcd->MspInitCallback = HAL_PCD_MspInit;
  405. break;
  406. case HAL_PCD_MSPDEINIT_CB_ID :
  407. hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
  408. break;
  409. default :
  410. /* Update the error code */
  411. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  412. /* Return error status */
  413. status = HAL_ERROR;
  414. break;
  415. }
  416. }
  417. else
  418. {
  419. /* Update the error code */
  420. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  421. /* Return error status */
  422. status = HAL_ERROR;
  423. }
  424. /* Release Lock */
  425. __HAL_UNLOCK(hpcd);
  426. return status;
  427. }
  428. /**
  429. * @brief Register USB PCD Data OUT Stage Callback
  430. * To be used instead of the weak HAL_PCD_DataOutStageCallback() predefined callback
  431. * @param hpcd PCD handle
  432. * @param pCallback pointer to the USB PCD Data OUT Stage Callback function
  433. * @retval HAL status
  434. */
  435. HAL_StatusTypeDef HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd, pPCD_DataOutStageCallbackTypeDef pCallback)
  436. {
  437. HAL_StatusTypeDef status = HAL_OK;
  438. if (pCallback == NULL)
  439. {
  440. /* Update the error code */
  441. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  442. return HAL_ERROR;
  443. }
  444. /* Process locked */
  445. __HAL_LOCK(hpcd);
  446. if (hpcd->State == HAL_PCD_STATE_READY)
  447. {
  448. hpcd->DataOutStageCallback = pCallback;
  449. }
  450. else
  451. {
  452. /* Update the error code */
  453. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  454. /* Return error status */
  455. status = HAL_ERROR;
  456. }
  457. /* Release Lock */
  458. __HAL_UNLOCK(hpcd);
  459. return status;
  460. }
  461. /**
  462. * @brief UnRegister the USB PCD Data OUT Stage Callback
  463. * USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataOutStageCallback() predefined callback
  464. * @param hpcd PCD handle
  465. * @retval HAL status
  466. */
  467. HAL_StatusTypeDef HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd)
  468. {
  469. HAL_StatusTypeDef status = HAL_OK;
  470. /* Process locked */
  471. __HAL_LOCK(hpcd);
  472. if (hpcd->State == HAL_PCD_STATE_READY)
  473. {
  474. hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback; /* Legacy weak DataOutStageCallback */
  475. }
  476. else
  477. {
  478. /* Update the error code */
  479. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  480. /* Return error status */
  481. status = HAL_ERROR;
  482. }
  483. /* Release Lock */
  484. __HAL_UNLOCK(hpcd);
  485. return status;
  486. }
  487. /**
  488. * @brief Register USB PCD Data IN Stage Callback
  489. * To be used instead of the weak HAL_PCD_DataInStageCallback() predefined callback
  490. * @param hpcd PCD handle
  491. * @param pCallback pointer to the USB PCD Data IN Stage Callback function
  492. * @retval HAL status
  493. */
  494. HAL_StatusTypeDef HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef *hpcd, pPCD_DataInStageCallbackTypeDef pCallback)
  495. {
  496. HAL_StatusTypeDef status = HAL_OK;
  497. if (pCallback == NULL)
  498. {
  499. /* Update the error code */
  500. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  501. return HAL_ERROR;
  502. }
  503. /* Process locked */
  504. __HAL_LOCK(hpcd);
  505. if (hpcd->State == HAL_PCD_STATE_READY)
  506. {
  507. hpcd->DataInStageCallback = pCallback;
  508. }
  509. else
  510. {
  511. /* Update the error code */
  512. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  513. /* Return error status */
  514. status = HAL_ERROR;
  515. }
  516. /* Release Lock */
  517. __HAL_UNLOCK(hpcd);
  518. return status;
  519. }
  520. /**
  521. * @brief UnRegister the USB PCD Data IN Stage Callback
  522. * USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataInStageCallback() predefined callback
  523. * @param hpcd PCD handle
  524. * @retval HAL status
  525. */
  526. HAL_StatusTypeDef HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef *hpcd)
  527. {
  528. HAL_StatusTypeDef status = HAL_OK;
  529. /* Process locked */
  530. __HAL_LOCK(hpcd);
  531. if (hpcd->State == HAL_PCD_STATE_READY)
  532. {
  533. hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback; /* Legacy weak DataInStageCallback */
  534. }
  535. else
  536. {
  537. /* Update the error code */
  538. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  539. /* Return error status */
  540. status = HAL_ERROR;
  541. }
  542. /* Release Lock */
  543. __HAL_UNLOCK(hpcd);
  544. return status;
  545. }
  546. /**
  547. * @brief Register USB PCD Iso OUT incomplete Callback
  548. * To be used instead of the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
  549. * @param hpcd PCD handle
  550. * @param pCallback pointer to the USB PCD Iso OUT incomplete Callback function
  551. * @retval HAL status
  552. */
  553. HAL_StatusTypeDef HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd, pPCD_IsoOutIncpltCallbackTypeDef pCallback)
  554. {
  555. HAL_StatusTypeDef status = HAL_OK;
  556. if (pCallback == NULL)
  557. {
  558. /* Update the error code */
  559. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  560. return HAL_ERROR;
  561. }
  562. /* Process locked */
  563. __HAL_LOCK(hpcd);
  564. if (hpcd->State == HAL_PCD_STATE_READY)
  565. {
  566. hpcd->ISOOUTIncompleteCallback = pCallback;
  567. }
  568. else
  569. {
  570. /* Update the error code */
  571. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  572. /* Return error status */
  573. status = HAL_ERROR;
  574. }
  575. /* Release Lock */
  576. __HAL_UNLOCK(hpcd);
  577. return status;
  578. }
  579. /**
  580. * @brief UnRegister the USB PCD Iso OUT incomplete Callback
  581. * USB PCD Iso OUT incomplete Callback is redirected to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
  582. * @param hpcd PCD handle
  583. * @retval HAL status
  584. */
  585. HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd)
  586. {
  587. HAL_StatusTypeDef status = HAL_OK;
  588. /* Process locked */
  589. __HAL_LOCK(hpcd);
  590. if (hpcd->State == HAL_PCD_STATE_READY)
  591. {
  592. hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback; /* Legacy weak ISOOUTIncompleteCallback */
  593. }
  594. else
  595. {
  596. /* Update the error code */
  597. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  598. /* Return error status */
  599. status = HAL_ERROR;
  600. }
  601. /* Release Lock */
  602. __HAL_UNLOCK(hpcd);
  603. return status;
  604. }
  605. /**
  606. * @brief Register USB PCD Iso IN incomplete Callback
  607. * To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
  608. * @param hpcd PCD handle
  609. * @param pCallback pointer to the USB PCD Iso IN incomplete Callback function
  610. * @retval HAL status
  611. */
  612. HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd, pPCD_IsoInIncpltCallbackTypeDef pCallback)
  613. {
  614. HAL_StatusTypeDef status = HAL_OK;
  615. if (pCallback == NULL)
  616. {
  617. /* Update the error code */
  618. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  619. return HAL_ERROR;
  620. }
  621. /* Process locked */
  622. __HAL_LOCK(hpcd);
  623. if (hpcd->State == HAL_PCD_STATE_READY)
  624. {
  625. hpcd->ISOINIncompleteCallback = pCallback;
  626. }
  627. else
  628. {
  629. /* Update the error code */
  630. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  631. /* Return error status */
  632. status = HAL_ERROR;
  633. }
  634. /* Release Lock */
  635. __HAL_UNLOCK(hpcd);
  636. return status;
  637. }
  638. /**
  639. * @brief UnRegister the USB PCD Iso IN incomplete Callback
  640. * USB PCD Iso IN incomplete Callback is redirected to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
  641. * @param hpcd PCD handle
  642. * @retval HAL status
  643. */
  644. HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd)
  645. {
  646. HAL_StatusTypeDef status = HAL_OK;
  647. /* Process locked */
  648. __HAL_LOCK(hpcd);
  649. if (hpcd->State == HAL_PCD_STATE_READY)
  650. {
  651. hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback; /* Legacy weak ISOINIncompleteCallback */
  652. }
  653. else
  654. {
  655. /* Update the error code */
  656. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  657. /* Return error status */
  658. status = HAL_ERROR;
  659. }
  660. /* Release Lock */
  661. __HAL_UNLOCK(hpcd);
  662. return status;
  663. }
  664. /**
  665. * @brief Register USB PCD BCD Callback
  666. * To be used instead of the weak HAL_PCDEx_BCD_Callback() predefined callback
  667. * @param hpcd PCD handle
  668. * @param pCallback pointer to the USB PCD BCD Callback function
  669. * @retval HAL status
  670. */
  671. HAL_StatusTypeDef HAL_PCD_RegisterBcdCallback(PCD_HandleTypeDef *hpcd, pPCD_BcdCallbackTypeDef pCallback)
  672. {
  673. HAL_StatusTypeDef status = HAL_OK;
  674. if (pCallback == NULL)
  675. {
  676. /* Update the error code */
  677. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  678. return HAL_ERROR;
  679. }
  680. /* Process locked */
  681. __HAL_LOCK(hpcd);
  682. if (hpcd->State == HAL_PCD_STATE_READY)
  683. {
  684. hpcd->BCDCallback = pCallback;
  685. }
  686. else
  687. {
  688. /* Update the error code */
  689. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  690. /* Return error status */
  691. status = HAL_ERROR;
  692. }
  693. /* Release Lock */
  694. __HAL_UNLOCK(hpcd);
  695. return status;
  696. }
  697. /**
  698. * @brief UnRegister the USB PCD BCD Callback
  699. * USB BCD Callback is redirected to the weak HAL_PCDEx_BCD_Callback() predefined callback
  700. * @param hpcd PCD handle
  701. * @retval HAL status
  702. */
  703. HAL_StatusTypeDef HAL_PCD_UnRegisterBcdCallback(PCD_HandleTypeDef *hpcd)
  704. {
  705. HAL_StatusTypeDef status = HAL_OK;
  706. /* Process locked */
  707. __HAL_LOCK(hpcd);
  708. if (hpcd->State == HAL_PCD_STATE_READY)
  709. {
  710. hpcd->BCDCallback = HAL_PCDEx_BCD_Callback; /* Legacy weak HAL_PCDEx_BCD_Callback */
  711. }
  712. else
  713. {
  714. /* Update the error code */
  715. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  716. /* Return error status */
  717. status = HAL_ERROR;
  718. }
  719. /* Release Lock */
  720. __HAL_UNLOCK(hpcd);
  721. return status;
  722. }
  723. /**
  724. * @brief Register USB PCD LPM Callback
  725. * To be used instead of the weak HAL_PCDEx_LPM_Callback() predefined callback
  726. * @param hpcd PCD handle
  727. * @param pCallback pointer to the USB PCD LPM Callback function
  728. * @retval HAL status
  729. */
  730. HAL_StatusTypeDef HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef *hpcd, pPCD_LpmCallbackTypeDef pCallback)
  731. {
  732. HAL_StatusTypeDef status = HAL_OK;
  733. if (pCallback == NULL)
  734. {
  735. /* Update the error code */
  736. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  737. return HAL_ERROR;
  738. }
  739. /* Process locked */
  740. __HAL_LOCK(hpcd);
  741. if (hpcd->State == HAL_PCD_STATE_READY)
  742. {
  743. hpcd->LPMCallback = pCallback;
  744. }
  745. else
  746. {
  747. /* Update the error code */
  748. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  749. /* Return error status */
  750. status = HAL_ERROR;
  751. }
  752. /* Release Lock */
  753. __HAL_UNLOCK(hpcd);
  754. return status;
  755. }
  756. /**
  757. * @brief UnRegister the USB PCD LPM Callback
  758. * USB LPM Callback is redirected to the weak HAL_PCDEx_LPM_Callback() predefined callback
  759. * @param hpcd PCD handle
  760. * @retval HAL status
  761. */
  762. HAL_StatusTypeDef HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef *hpcd)
  763. {
  764. HAL_StatusTypeDef status = HAL_OK;
  765. /* Process locked */
  766. __HAL_LOCK(hpcd);
  767. if (hpcd->State == HAL_PCD_STATE_READY)
  768. {
  769. hpcd->LPMCallback = HAL_PCDEx_LPM_Callback; /* Legacy weak HAL_PCDEx_LPM_Callback */
  770. }
  771. else
  772. {
  773. /* Update the error code */
  774. hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  775. /* Return error status */
  776. status = HAL_ERROR;
  777. }
  778. /* Release Lock */
  779. __HAL_UNLOCK(hpcd);
  780. return status;
  781. }
  782. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  783. /**
  784. * @}
  785. */
  786. /** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
  787. * @brief Data transfers functions
  788. *
  789. @verbatim
  790. ===============================================================================
  791. ##### IO operation functions #####
  792. ===============================================================================
  793. [..]
  794. This subsection provides a set of functions allowing to manage the PCD data
  795. transfers.
  796. @endverbatim
  797. * @{
  798. */
  799. /**
  800. * @brief Start the USB device
  801. * @param hpcd PCD handle
  802. * @retval HAL status
  803. */
  804. HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
  805. {
  806. __HAL_LOCK(hpcd);
  807. (void)USB_DevConnect(hpcd->Instance);
  808. __HAL_PCD_ENABLE(hpcd);
  809. __HAL_UNLOCK(hpcd);
  810. return HAL_OK;
  811. }
  812. /**
  813. * @brief Stop the USB device.
  814. * @param hpcd PCD handle
  815. * @retval HAL status
  816. */
  817. HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
  818. {
  819. __HAL_LOCK(hpcd);
  820. __HAL_PCD_DISABLE(hpcd);
  821. if (USB_StopDevice(hpcd->Instance) != HAL_OK)
  822. {
  823. __HAL_UNLOCK(hpcd);
  824. return HAL_ERROR;
  825. }
  826. __HAL_UNLOCK(hpcd);
  827. return HAL_OK;
  828. }
  829. /**
  830. * @brief This function handles PCD interrupt request.
  831. * @param hpcd PCD handle
  832. * @retval HAL status
  833. */
  834. void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
  835. {
  836. if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_CTR))
  837. {
  838. /* servicing of the endpoint correct transfer interrupt */
  839. /* clear of the CTR flag into the sub */
  840. (void)PCD_EP_ISR_Handler(hpcd);
  841. }
  842. if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_RESET))
  843. {
  844. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
  845. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  846. hpcd->ResetCallback(hpcd);
  847. #else
  848. HAL_PCD_ResetCallback(hpcd);
  849. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  850. (void)HAL_PCD_SetAddress(hpcd, 0U);
  851. }
  852. if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_PMAOVR))
  853. {
  854. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);
  855. }
  856. if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_ERR))
  857. {
  858. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR);
  859. }
  860. if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_WKUP))
  861. {
  862. hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_LPMODE);
  863. hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_FSUSP);
  864. if (hpcd->LPM_State == LPM_L1)
  865. {
  866. hpcd->LPM_State = LPM_L0;
  867. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  868. hpcd->LPMCallback(hpcd, PCD_LPM_L0_ACTIVE);
  869. #else
  870. HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
  871. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  872. }
  873. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  874. hpcd->ResumeCallback(hpcd);
  875. #else
  876. HAL_PCD_ResumeCallback(hpcd);
  877. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  878. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);
  879. }
  880. if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_SUSP))
  881. {
  882. /* Force low-power mode in the macrocell */
  883. hpcd->Instance->CNTR |= USB_CNTR_FSUSP;
  884. /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
  885. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);
  886. hpcd->Instance->CNTR |= USB_CNTR_LPMODE;
  887. if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_WKUP) == 0U)
  888. {
  889. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  890. hpcd->SuspendCallback(hpcd);
  891. #else
  892. HAL_PCD_SuspendCallback(hpcd);
  893. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  894. }
  895. }
  896. /* Handle LPM Interrupt */
  897. if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_L1REQ))
  898. {
  899. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_L1REQ);
  900. if (hpcd->LPM_State == LPM_L0)
  901. {
  902. /* Force suspend and low-power mode before going to L1 state*/
  903. hpcd->Instance->CNTR |= USB_CNTR_LPMODE;
  904. hpcd->Instance->CNTR |= USB_CNTR_FSUSP;
  905. hpcd->LPM_State = LPM_L1;
  906. hpcd->BESL = ((uint32_t)hpcd->Instance->LPMCSR & USB_LPMCSR_BESL) >> 2;
  907. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  908. hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
  909. #else
  910. HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
  911. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  912. }
  913. else
  914. {
  915. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  916. hpcd->SuspendCallback(hpcd);
  917. #else
  918. HAL_PCD_SuspendCallback(hpcd);
  919. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  920. }
  921. }
  922. if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_SOF))
  923. {
  924. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);
  925. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  926. hpcd->SOFCallback(hpcd);
  927. #else
  928. HAL_PCD_SOFCallback(hpcd);
  929. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  930. }
  931. if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_ESOF))
  932. {
  933. /* clear ESOF flag in ISTR */
  934. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);
  935. }
  936. }
  937. /**
  938. * @brief Data OUT stage callback.
  939. * @param hpcd PCD handle
  940. * @param epnum endpoint number
  941. * @retval None
  942. */
  943. __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  944. {
  945. /* Prevent unused argument(s) compilation warning */
  946. UNUSED(hpcd);
  947. UNUSED(epnum);
  948. /* NOTE : This function should not be modified, when the callback is needed,
  949. the HAL_PCD_DataOutStageCallback could be implemented in the user file
  950. */
  951. }
  952. /**
  953. * @brief Data IN stage callback
  954. * @param hpcd PCD handle
  955. * @param epnum endpoint number
  956. * @retval None
  957. */
  958. __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  959. {
  960. /* Prevent unused argument(s) compilation warning */
  961. UNUSED(hpcd);
  962. UNUSED(epnum);
  963. /* NOTE : This function should not be modified, when the callback is needed,
  964. the HAL_PCD_DataInStageCallback could be implemented in the user file
  965. */
  966. }
  967. /**
  968. * @brief Setup stage callback
  969. * @param hpcd PCD handle
  970. * @retval None
  971. */
  972. __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
  973. {
  974. /* Prevent unused argument(s) compilation warning */
  975. UNUSED(hpcd);
  976. /* NOTE : This function should not be modified, when the callback is needed,
  977. the HAL_PCD_SetupStageCallback could be implemented in the user file
  978. */
  979. }
  980. /**
  981. * @brief USB Start Of Frame callback.
  982. * @param hpcd PCD handle
  983. * @retval None
  984. */
  985. __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
  986. {
  987. /* Prevent unused argument(s) compilation warning */
  988. UNUSED(hpcd);
  989. /* NOTE : This function should not be modified, when the callback is needed,
  990. the HAL_PCD_SOFCallback could be implemented in the user file
  991. */
  992. }
  993. /**
  994. * @brief USB Reset callback.
  995. * @param hpcd PCD handle
  996. * @retval None
  997. */
  998. __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
  999. {
  1000. /* Prevent unused argument(s) compilation warning */
  1001. UNUSED(hpcd);
  1002. /* NOTE : This function should not be modified, when the callback is needed,
  1003. the HAL_PCD_ResetCallback could be implemented in the user file
  1004. */
  1005. }
  1006. /**
  1007. * @brief Suspend event callback.
  1008. * @param hpcd PCD handle
  1009. * @retval None
  1010. */
  1011. __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
  1012. {
  1013. /* Prevent unused argument(s) compilation warning */
  1014. UNUSED(hpcd);
  1015. /* NOTE : This function should not be modified, when the callback is needed,
  1016. the HAL_PCD_SuspendCallback could be implemented in the user file
  1017. */
  1018. }
  1019. /**
  1020. * @brief Resume event callback.
  1021. * @param hpcd PCD handle
  1022. * @retval None
  1023. */
  1024. __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
  1025. {
  1026. /* Prevent unused argument(s) compilation warning */
  1027. UNUSED(hpcd);
  1028. /* NOTE : This function should not be modified, when the callback is needed,
  1029. the HAL_PCD_ResumeCallback could be implemented in the user file
  1030. */
  1031. }
  1032. /**
  1033. * @brief Incomplete ISO OUT callback.
  1034. * @param hpcd PCD handle
  1035. * @param epnum endpoint number
  1036. * @retval None
  1037. */
  1038. __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  1039. {
  1040. /* Prevent unused argument(s) compilation warning */
  1041. UNUSED(hpcd);
  1042. UNUSED(epnum);
  1043. /* NOTE : This function should not be modified, when the callback is needed,
  1044. the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
  1045. */
  1046. }
  1047. /**
  1048. * @brief Incomplete ISO IN callback.
  1049. * @param hpcd PCD handle
  1050. * @param epnum endpoint number
  1051. * @retval None
  1052. */
  1053. __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  1054. {
  1055. /* Prevent unused argument(s) compilation warning */
  1056. UNUSED(hpcd);
  1057. UNUSED(epnum);
  1058. /* NOTE : This function should not be modified, when the callback is needed,
  1059. the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
  1060. */
  1061. }
  1062. /**
  1063. * @brief Connection event callback.
  1064. * @param hpcd PCD handle
  1065. * @retval None
  1066. */
  1067. __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
  1068. {
  1069. /* Prevent unused argument(s) compilation warning */
  1070. UNUSED(hpcd);
  1071. /* NOTE : This function should not be modified, when the callback is needed,
  1072. the HAL_PCD_ConnectCallback could be implemented in the user file
  1073. */
  1074. }
  1075. /**
  1076. * @brief Disconnection event callback.
  1077. * @param hpcd PCD handle
  1078. * @retval None
  1079. */
  1080. __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
  1081. {
  1082. /* Prevent unused argument(s) compilation warning */
  1083. UNUSED(hpcd);
  1084. /* NOTE : This function should not be modified, when the callback is needed,
  1085. the HAL_PCD_DisconnectCallback could be implemented in the user file
  1086. */
  1087. }
  1088. /**
  1089. * @}
  1090. */
  1091. /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
  1092. * @brief management functions
  1093. *
  1094. @verbatim
  1095. ===============================================================================
  1096. ##### Peripheral Control functions #####
  1097. ===============================================================================
  1098. [..]
  1099. This subsection provides a set of functions allowing to control the PCD data
  1100. transfers.
  1101. @endverbatim
  1102. * @{
  1103. */
  1104. /**
  1105. * @brief Connect the USB device
  1106. * @param hpcd PCD handle
  1107. * @retval HAL status
  1108. */
  1109. HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
  1110. {
  1111. __HAL_LOCK(hpcd);
  1112. (void)USB_DevConnect(hpcd->Instance);
  1113. __HAL_UNLOCK(hpcd);
  1114. return HAL_OK;
  1115. }
  1116. /**
  1117. * @brief Disconnect the USB device.
  1118. * @param hpcd PCD handle
  1119. * @retval HAL status
  1120. */
  1121. HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
  1122. {
  1123. __HAL_LOCK(hpcd);
  1124. (void)USB_DevDisconnect(hpcd->Instance);
  1125. __HAL_UNLOCK(hpcd);
  1126. return HAL_OK;
  1127. }
  1128. /**
  1129. * @brief Set the USB Device address.
  1130. * @param hpcd PCD handle
  1131. * @param address new device address
  1132. * @retval HAL status
  1133. */
  1134. HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
  1135. {
  1136. __HAL_LOCK(hpcd);
  1137. hpcd->USB_Address = address;
  1138. (void)USB_SetDevAddress(hpcd->Instance, address);
  1139. __HAL_UNLOCK(hpcd);
  1140. return HAL_OK;
  1141. }
  1142. /**
  1143. * @brief Open and configure an endpoint.
  1144. * @param hpcd PCD handle
  1145. * @param ep_addr endpoint address
  1146. * @param ep_mps endpoint max packet size
  1147. * @param ep_type endpoint type
  1148. * @retval HAL status
  1149. */
  1150. HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type)
  1151. {
  1152. HAL_StatusTypeDef ret = HAL_OK;
  1153. PCD_EPTypeDef *ep;
  1154. if ((ep_addr & 0x80U) == 0x80U)
  1155. {
  1156. ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1157. ep->is_in = 1U;
  1158. }
  1159. else
  1160. {
  1161. ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
  1162. ep->is_in = 0U;
  1163. }
  1164. ep->num = ep_addr & EP_ADDR_MSK;
  1165. ep->maxpacket = ep_mps;
  1166. ep->type = ep_type;
  1167. if (ep->is_in != 0U)
  1168. {
  1169. /* Assign a Tx FIFO */
  1170. ep->tx_fifo_num = ep->num;
  1171. }
  1172. /* Set initial data PID. */
  1173. if (ep_type == EP_TYPE_BULK)
  1174. {
  1175. ep->data_pid_start = 0U;
  1176. }
  1177. __HAL_LOCK(hpcd);
  1178. (void)USB_ActivateEndpoint(hpcd->Instance, ep);
  1179. __HAL_UNLOCK(hpcd);
  1180. return ret;
  1181. }
  1182. /**
  1183. * @brief Deactivate an endpoint.
  1184. * @param hpcd PCD handle
  1185. * @param ep_addr endpoint address
  1186. * @retval HAL status
  1187. */
  1188. HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1189. {
  1190. PCD_EPTypeDef *ep;
  1191. if ((ep_addr & 0x80U) == 0x80U)
  1192. {
  1193. ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1194. ep->is_in = 1U;
  1195. }
  1196. else
  1197. {
  1198. ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
  1199. ep->is_in = 0U;
  1200. }
  1201. ep->num = ep_addr & EP_ADDR_MSK;
  1202. __HAL_LOCK(hpcd);
  1203. (void)USB_DeactivateEndpoint(hpcd->Instance, ep);
  1204. __HAL_UNLOCK(hpcd);
  1205. return HAL_OK;
  1206. }
  1207. /**
  1208. * @brief Receive an amount of data.
  1209. * @param hpcd PCD handle
  1210. * @param ep_addr endpoint address
  1211. * @param pBuf pointer to the reception buffer
  1212. * @param len amount of data to be received
  1213. * @retval HAL status
  1214. */
  1215. HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
  1216. {
  1217. PCD_EPTypeDef *ep;
  1218. ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
  1219. /*setup and start the Xfer */
  1220. ep->xfer_buff = pBuf;
  1221. ep->xfer_len = len;
  1222. ep->xfer_count = 0U;
  1223. ep->is_in = 0U;
  1224. ep->num = ep_addr & EP_ADDR_MSK;
  1225. if ((ep_addr & EP_ADDR_MSK) == 0U)
  1226. {
  1227. (void)USB_EP0StartXfer(hpcd->Instance, ep);
  1228. }
  1229. else
  1230. {
  1231. (void)USB_EPStartXfer(hpcd->Instance, ep);
  1232. }
  1233. return HAL_OK;
  1234. }
  1235. /**
  1236. * @brief Get Received Data Size
  1237. * @param hpcd PCD handle
  1238. * @param ep_addr endpoint address
  1239. * @retval Data Size
  1240. */
  1241. uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1242. {
  1243. return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].xfer_count;
  1244. }
  1245. /**
  1246. * @brief Send an amount of data
  1247. * @param hpcd PCD handle
  1248. * @param ep_addr endpoint address
  1249. * @param pBuf pointer to the transmission buffer
  1250. * @param len amount of data to be sent
  1251. * @retval HAL status
  1252. */
  1253. HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
  1254. {
  1255. PCD_EPTypeDef *ep;
  1256. ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1257. /*setup and start the Xfer */
  1258. ep->xfer_buff = pBuf;
  1259. ep->xfer_len = len;
  1260. ep->xfer_count = 0U;
  1261. ep->is_in = 1U;
  1262. ep->num = ep_addr & EP_ADDR_MSK;
  1263. if ((ep_addr & EP_ADDR_MSK) == 0U)
  1264. {
  1265. (void)USB_EP0StartXfer(hpcd->Instance, ep);
  1266. }
  1267. else
  1268. {
  1269. (void)USB_EPStartXfer(hpcd->Instance, ep);
  1270. }
  1271. return HAL_OK;
  1272. }
  1273. /**
  1274. * @brief Set a STALL condition over an endpoint
  1275. * @param hpcd PCD handle
  1276. * @param ep_addr endpoint address
  1277. * @retval HAL status
  1278. */
  1279. HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1280. {
  1281. PCD_EPTypeDef *ep;
  1282. if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints)
  1283. {
  1284. return HAL_ERROR;
  1285. }
  1286. if ((0x80U & ep_addr) == 0x80U)
  1287. {
  1288. ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1289. ep->is_in = 1U;
  1290. }
  1291. else
  1292. {
  1293. ep = &hpcd->OUT_ep[ep_addr];
  1294. ep->is_in = 0U;
  1295. }
  1296. ep->is_stall = 1U;
  1297. ep->num = ep_addr & EP_ADDR_MSK;
  1298. __HAL_LOCK(hpcd);
  1299. (void)USB_EPSetStall(hpcd->Instance, ep);
  1300. if ((ep_addr & EP_ADDR_MSK) == 0U)
  1301. {
  1302. (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
  1303. }
  1304. __HAL_UNLOCK(hpcd);
  1305. return HAL_OK;
  1306. }
  1307. /**
  1308. * @brief Clear a STALL condition over in an endpoint
  1309. * @param hpcd PCD handle
  1310. * @param ep_addr endpoint address
  1311. * @retval HAL status
  1312. */
  1313. HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1314. {
  1315. PCD_EPTypeDef *ep;
  1316. if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints)
  1317. {
  1318. return HAL_ERROR;
  1319. }
  1320. if ((0x80U & ep_addr) == 0x80U)
  1321. {
  1322. ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1323. ep->is_in = 1U;
  1324. }
  1325. else
  1326. {
  1327. ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
  1328. ep->is_in = 0U;
  1329. }
  1330. ep->is_stall = 0U;
  1331. ep->num = ep_addr & EP_ADDR_MSK;
  1332. __HAL_LOCK(hpcd);
  1333. (void)USB_EPClearStall(hpcd->Instance, ep);
  1334. __HAL_UNLOCK(hpcd);
  1335. return HAL_OK;
  1336. }
  1337. /**
  1338. * @brief Flush an endpoint
  1339. * @param hpcd PCD handle
  1340. * @param ep_addr endpoint address
  1341. * @retval HAL status
  1342. */
  1343. HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1344. {
  1345. /* Prevent unused argument(s) compilation warning */
  1346. UNUSED(hpcd);
  1347. UNUSED(ep_addr);
  1348. return HAL_OK;
  1349. }
  1350. /**
  1351. * @brief Activate remote wakeup signalling
  1352. * @param hpcd PCD handle
  1353. * @retval HAL status
  1354. */
  1355. HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
  1356. {
  1357. return (USB_ActivateRemoteWakeup(hpcd->Instance));
  1358. }
  1359. /**
  1360. * @brief De-activate remote wakeup signalling.
  1361. * @param hpcd PCD handle
  1362. * @retval HAL status
  1363. */
  1364. HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
  1365. {
  1366. return (USB_DeActivateRemoteWakeup(hpcd->Instance));
  1367. }
  1368. /**
  1369. * @}
  1370. */
  1371. /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
  1372. * @brief Peripheral State functions
  1373. *
  1374. @verbatim
  1375. ===============================================================================
  1376. ##### Peripheral State functions #####
  1377. ===============================================================================
  1378. [..]
  1379. This subsection permits to get in run-time the status of the peripheral
  1380. and the data flow.
  1381. @endverbatim
  1382. * @{
  1383. */
  1384. /**
  1385. * @brief Return the PCD handle state.
  1386. * @param hpcd PCD handle
  1387. * @retval HAL state
  1388. */
  1389. PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
  1390. {
  1391. return hpcd->State;
  1392. }
  1393. /**
  1394. * @}
  1395. */
  1396. /**
  1397. * @}
  1398. */
  1399. /* Private functions ---------------------------------------------------------*/
  1400. /** @addtogroup PCD_Private_Functions
  1401. * @{
  1402. */
  1403. /**
  1404. * @brief This function handles PCD Endpoint interrupt request.
  1405. * @param hpcd PCD handle
  1406. * @retval HAL status
  1407. */
  1408. static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
  1409. {
  1410. PCD_EPTypeDef *ep;
  1411. uint16_t count;
  1412. uint16_t wIstr;
  1413. uint16_t wEPVal;
  1414. uint8_t epindex;
  1415. /* stay in loop while pending interrupts */
  1416. while ((hpcd->Instance->ISTR & USB_ISTR_CTR) != 0U)
  1417. {
  1418. wIstr = hpcd->Instance->ISTR;
  1419. /* extract highest priority endpoint number */
  1420. epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
  1421. if (epindex == 0U)
  1422. {
  1423. /* Decode and service control endpoint interrupt */
  1424. /* DIR bit = origin of the interrupt */
  1425. if ((wIstr & USB_ISTR_DIR) == 0U)
  1426. {
  1427. /* DIR = 0 */
  1428. /* DIR = 0 => IN int */
  1429. /* DIR = 0 implies that (EP_CTR_TX = 1) always */
  1430. PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
  1431. ep = &hpcd->IN_ep[0];
  1432. ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
  1433. ep->xfer_buff += ep->xfer_count;
  1434. /* TX COMPLETE */
  1435. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1436. hpcd->DataInStageCallback(hpcd, 0U);
  1437. #else
  1438. HAL_PCD_DataInStageCallback(hpcd, 0U);
  1439. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1440. if ((hpcd->USB_Address > 0U) && (ep->xfer_len == 0U))
  1441. {
  1442. hpcd->Instance->DADDR = ((uint16_t)hpcd->USB_Address | USB_DADDR_EF);
  1443. hpcd->USB_Address = 0U;
  1444. }
  1445. }
  1446. else
  1447. {
  1448. /* DIR = 1 */
  1449. /* DIR = 1 & CTR_RX => SETUP or OUT int */
  1450. /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
  1451. ep = &hpcd->OUT_ep[0];
  1452. wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
  1453. if ((wEPVal & USB_EP_SETUP) != 0U)
  1454. {
  1455. /* Get SETUP Packet*/
  1456. ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
  1457. USB_ReadPMA(hpcd->Instance, (uint8_t *)hpcd->Setup, ep->pmaadress, (uint16_t)ep->xfer_count);
  1458. /* SETUP bit kept frozen while CTR_RX = 1*/
  1459. PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
  1460. /* Process SETUP Packet*/
  1461. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1462. hpcd->SetupStageCallback(hpcd);
  1463. #else
  1464. HAL_PCD_SetupStageCallback(hpcd);
  1465. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1466. }
  1467. else if ((wEPVal & USB_EP_CTR_RX) != 0U)
  1468. {
  1469. PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
  1470. /* Get Control Data OUT Packet*/
  1471. ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
  1472. if (ep->xfer_count != 0U)
  1473. {
  1474. USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, (uint16_t)ep->xfer_count);
  1475. ep->xfer_buff += ep->xfer_count;
  1476. }
  1477. /* Process Control Data OUT Packet*/
  1478. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1479. hpcd->DataOutStageCallback(hpcd, 0U);
  1480. #else
  1481. HAL_PCD_DataOutStageCallback(hpcd, 0U);
  1482. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1483. PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
  1484. PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
  1485. }
  1486. }
  1487. }
  1488. else
  1489. {
  1490. /* Decode and service non control endpoints interrupt */
  1491. /* process related endpoint register */
  1492. wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);
  1493. if ((wEPVal & USB_EP_CTR_RX) != 0U)
  1494. {
  1495. /* clear int flag */
  1496. PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
  1497. ep = &hpcd->OUT_ep[epindex];
  1498. /* OUT double Buffering*/
  1499. if (ep->doublebuffer == 0U)
  1500. {
  1501. count = (uint16_t)PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
  1502. if (count != 0U)
  1503. {
  1504. USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
  1505. }
  1506. }
  1507. else
  1508. {
  1509. if ((PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX) != 0U)
  1510. {
  1511. /*read from endpoint BUF0Addr buffer*/
  1512. count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
  1513. if (count != 0U)
  1514. {
  1515. USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
  1516. }
  1517. }
  1518. else
  1519. {
  1520. /*read from endpoint BUF1Addr buffer*/
  1521. count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
  1522. if (count != 0U)
  1523. {
  1524. USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
  1525. }
  1526. }
  1527. /* free EP OUT Buffer */
  1528. PCD_FreeUserBuffer(hpcd->Instance, ep->num, 0U);
  1529. }
  1530. /*multi-packet on the NON control OUT endpoint*/
  1531. ep->xfer_count += count;
  1532. ep->xfer_buff += count;
  1533. if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
  1534. {
  1535. /* RX COMPLETE */
  1536. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1537. hpcd->DataOutStageCallback(hpcd, ep->num);
  1538. #else
  1539. HAL_PCD_DataOutStageCallback(hpcd, ep->num);
  1540. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1541. }
  1542. else
  1543. {
  1544. (void)HAL_PCD_EP_Receive(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
  1545. }
  1546. } /* if((wEPVal & EP_CTR_RX) */
  1547. if ((wEPVal & USB_EP_CTR_TX) != 0U)
  1548. {
  1549. ep = &hpcd->IN_ep[epindex];
  1550. /* clear int flag */
  1551. PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
  1552. /*multi-packet on the NON control IN endpoint*/
  1553. ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
  1554. ep->xfer_buff += ep->xfer_count;
  1555. /* Zero Length Packet? */
  1556. if (ep->xfer_len == 0U)
  1557. {
  1558. /* TX COMPLETE */
  1559. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1560. hpcd->DataInStageCallback(hpcd, ep->num);
  1561. #else
  1562. HAL_PCD_DataInStageCallback(hpcd, ep->num);
  1563. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1564. }
  1565. else
  1566. {
  1567. (void)HAL_PCD_EP_Transmit(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
  1568. }
  1569. }
  1570. }
  1571. }
  1572. return HAL_OK;
  1573. }
  1574. /**
  1575. * @}
  1576. */
  1577. #endif /* defined (USB) */
  1578. #endif /* HAL_PCD_MODULE_ENABLED */
  1579. /**
  1580. * @}
  1581. */
  1582. /**
  1583. * @}
  1584. */
  1585. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/