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.
 
 
 

1868 lines
47 KiB

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