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.
 
 
 

1870 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 |= 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 |= USB_CNTR_LPMODE;
  874. if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_WKUP) == 0U)
  875. {
  876. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  877. hpcd->SuspendCallback(hpcd);
  878. #else
  879. HAL_PCD_SuspendCallback(hpcd);
  880. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  881. }
  882. }
  883. /* Handle LPM Interrupt */
  884. if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_L1REQ))
  885. {
  886. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_L1REQ);
  887. if (hpcd->LPM_State == LPM_L0)
  888. {
  889. /* Force suspend and low-power mode before going to L1 state*/
  890. hpcd->Instance->CNTR |= USB_CNTR_LPMODE;
  891. hpcd->Instance->CNTR |= USB_CNTR_FSUSP;
  892. hpcd->LPM_State = LPM_L1;
  893. hpcd->BESL = ((uint32_t)hpcd->Instance->LPMCSR & USB_LPMCSR_BESL) >> 2;
  894. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  895. hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
  896. #else
  897. HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
  898. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  899. }
  900. else
  901. {
  902. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  903. hpcd->SuspendCallback(hpcd);
  904. #else
  905. HAL_PCD_SuspendCallback(hpcd);
  906. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  907. }
  908. }
  909. if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_SOF))
  910. {
  911. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);
  912. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  913. hpcd->SOFCallback(hpcd);
  914. #else
  915. HAL_PCD_SOFCallback(hpcd);
  916. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  917. }
  918. if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_ESOF))
  919. {
  920. /* clear ESOF flag in ISTR */
  921. __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);
  922. }
  923. }
  924. /**
  925. * @brief Data OUT stage callback.
  926. * @param hpcd PCD handle
  927. * @param epnum endpoint number
  928. * @retval None
  929. */
  930. __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  931. {
  932. /* Prevent unused argument(s) compilation warning */
  933. UNUSED(hpcd);
  934. UNUSED(epnum);
  935. /* NOTE : This function should not be modified, when the callback is needed,
  936. the HAL_PCD_DataOutStageCallback could be implemented in the user file
  937. */
  938. }
  939. /**
  940. * @brief Data IN stage callback
  941. * @param hpcd PCD handle
  942. * @param epnum endpoint number
  943. * @retval None
  944. */
  945. __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  946. {
  947. /* Prevent unused argument(s) compilation warning */
  948. UNUSED(hpcd);
  949. UNUSED(epnum);
  950. /* NOTE : This function should not be modified, when the callback is needed,
  951. the HAL_PCD_DataInStageCallback could be implemented in the user file
  952. */
  953. }
  954. /**
  955. * @brief Setup stage callback
  956. * @param hpcd PCD handle
  957. * @retval None
  958. */
  959. __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
  960. {
  961. /* Prevent unused argument(s) compilation warning */
  962. UNUSED(hpcd);
  963. /* NOTE : This function should not be modified, when the callback is needed,
  964. the HAL_PCD_SetupStageCallback could be implemented in the user file
  965. */
  966. }
  967. /**
  968. * @brief USB Start Of Frame callback.
  969. * @param hpcd PCD handle
  970. * @retval None
  971. */
  972. __weak void HAL_PCD_SOFCallback(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_SOFCallback could be implemented in the user file
  978. */
  979. }
  980. /**
  981. * @brief USB Reset callback.
  982. * @param hpcd PCD handle
  983. * @retval None
  984. */
  985. __weak void HAL_PCD_ResetCallback(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_ResetCallback could be implemented in the user file
  991. */
  992. }
  993. /**
  994. * @brief Suspend event callback.
  995. * @param hpcd PCD handle
  996. * @retval None
  997. */
  998. __weak void HAL_PCD_SuspendCallback(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_SuspendCallback could be implemented in the user file
  1004. */
  1005. }
  1006. /**
  1007. * @brief Resume event callback.
  1008. * @param hpcd PCD handle
  1009. * @retval None
  1010. */
  1011. __weak void HAL_PCD_ResumeCallback(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_ResumeCallback could be implemented in the user file
  1017. */
  1018. }
  1019. /**
  1020. * @brief Incomplete ISO OUT callback.
  1021. * @param hpcd PCD handle
  1022. * @param epnum endpoint number
  1023. * @retval None
  1024. */
  1025. __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  1026. {
  1027. /* Prevent unused argument(s) compilation warning */
  1028. UNUSED(hpcd);
  1029. UNUSED(epnum);
  1030. /* NOTE : This function should not be modified, when the callback is needed,
  1031. the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
  1032. */
  1033. }
  1034. /**
  1035. * @brief Incomplete ISO IN callback.
  1036. * @param hpcd PCD handle
  1037. * @param epnum endpoint number
  1038. * @retval None
  1039. */
  1040. __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  1041. {
  1042. /* Prevent unused argument(s) compilation warning */
  1043. UNUSED(hpcd);
  1044. UNUSED(epnum);
  1045. /* NOTE : This function should not be modified, when the callback is needed,
  1046. the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
  1047. */
  1048. }
  1049. /**
  1050. * @brief Connection event callback.
  1051. * @param hpcd PCD handle
  1052. * @retval None
  1053. */
  1054. __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
  1055. {
  1056. /* Prevent unused argument(s) compilation warning */
  1057. UNUSED(hpcd);
  1058. /* NOTE : This function should not be modified, when the callback is needed,
  1059. the HAL_PCD_ConnectCallback could be implemented in the user file
  1060. */
  1061. }
  1062. /**
  1063. * @brief Disconnection event callback.
  1064. * @param hpcd PCD handle
  1065. * @retval None
  1066. */
  1067. __weak void HAL_PCD_DisconnectCallback(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_DisconnectCallback could be implemented in the user file
  1073. */
  1074. }
  1075. /**
  1076. * @}
  1077. */
  1078. /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
  1079. * @brief management functions
  1080. *
  1081. @verbatim
  1082. ===============================================================================
  1083. ##### Peripheral Control functions #####
  1084. ===============================================================================
  1085. [..]
  1086. This subsection provides a set of functions allowing to control the PCD data
  1087. transfers.
  1088. @endverbatim
  1089. * @{
  1090. */
  1091. /**
  1092. * @brief Connect the USB device
  1093. * @param hpcd PCD handle
  1094. * @retval HAL status
  1095. */
  1096. HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
  1097. {
  1098. __HAL_LOCK(hpcd);
  1099. (void)USB_DevConnect(hpcd->Instance);
  1100. __HAL_UNLOCK(hpcd);
  1101. return HAL_OK;
  1102. }
  1103. /**
  1104. * @brief Disconnect the USB device.
  1105. * @param hpcd PCD handle
  1106. * @retval HAL status
  1107. */
  1108. HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
  1109. {
  1110. __HAL_LOCK(hpcd);
  1111. (void)USB_DevDisconnect(hpcd->Instance);
  1112. __HAL_UNLOCK(hpcd);
  1113. return HAL_OK;
  1114. }
  1115. /**
  1116. * @brief Set the USB Device address.
  1117. * @param hpcd PCD handle
  1118. * @param address new device address
  1119. * @retval HAL status
  1120. */
  1121. HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
  1122. {
  1123. __HAL_LOCK(hpcd);
  1124. hpcd->USB_Address = address;
  1125. (void)USB_SetDevAddress(hpcd->Instance, address);
  1126. __HAL_UNLOCK(hpcd);
  1127. return HAL_OK;
  1128. }
  1129. /**
  1130. * @brief Open and configure an endpoint.
  1131. * @param hpcd PCD handle
  1132. * @param ep_addr endpoint address
  1133. * @param ep_mps endpoint max packet size
  1134. * @param ep_type endpoint type
  1135. * @retval HAL status
  1136. */
  1137. HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type)
  1138. {
  1139. HAL_StatusTypeDef ret = HAL_OK;
  1140. PCD_EPTypeDef *ep;
  1141. if ((ep_addr & 0x80U) == 0x80U)
  1142. {
  1143. ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1144. ep->is_in = 1U;
  1145. }
  1146. else
  1147. {
  1148. ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
  1149. ep->is_in = 0U;
  1150. }
  1151. ep->num = ep_addr & EP_ADDR_MSK;
  1152. ep->maxpacket = ep_mps;
  1153. ep->type = ep_type;
  1154. if (ep->is_in != 0U)
  1155. {
  1156. /* Assign a Tx FIFO */
  1157. ep->tx_fifo_num = ep->num;
  1158. }
  1159. /* Set initial data PID. */
  1160. if (ep_type == EP_TYPE_BULK)
  1161. {
  1162. ep->data_pid_start = 0U;
  1163. }
  1164. __HAL_LOCK(hpcd);
  1165. (void)USB_ActivateEndpoint(hpcd->Instance, ep);
  1166. __HAL_UNLOCK(hpcd);
  1167. return ret;
  1168. }
  1169. /**
  1170. * @brief Deactivate an endpoint.
  1171. * @param hpcd PCD handle
  1172. * @param ep_addr endpoint address
  1173. * @retval HAL status
  1174. */
  1175. HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1176. {
  1177. PCD_EPTypeDef *ep;
  1178. if ((ep_addr & 0x80U) == 0x80U)
  1179. {
  1180. ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1181. ep->is_in = 1U;
  1182. }
  1183. else
  1184. {
  1185. ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
  1186. ep->is_in = 0U;
  1187. }
  1188. ep->num = ep_addr & EP_ADDR_MSK;
  1189. __HAL_LOCK(hpcd);
  1190. (void)USB_DeactivateEndpoint(hpcd->Instance, ep);
  1191. __HAL_UNLOCK(hpcd);
  1192. return HAL_OK;
  1193. }
  1194. /**
  1195. * @brief Receive an amount of data.
  1196. * @param hpcd PCD handle
  1197. * @param ep_addr endpoint address
  1198. * @param pBuf pointer to the reception buffer
  1199. * @param len amount of data to be received
  1200. * @retval HAL status
  1201. */
  1202. HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
  1203. {
  1204. PCD_EPTypeDef *ep;
  1205. ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
  1206. /*setup and start the Xfer */
  1207. ep->xfer_buff = pBuf;
  1208. ep->xfer_len = len;
  1209. ep->xfer_count = 0U;
  1210. ep->is_in = 0U;
  1211. ep->num = ep_addr & EP_ADDR_MSK;
  1212. if ((ep_addr & EP_ADDR_MSK) == 0U)
  1213. {
  1214. (void)USB_EP0StartXfer(hpcd->Instance, ep);
  1215. }
  1216. else
  1217. {
  1218. (void)USB_EPStartXfer(hpcd->Instance, ep);
  1219. }
  1220. return HAL_OK;
  1221. }
  1222. /**
  1223. * @brief Get Received Data Size
  1224. * @param hpcd PCD handle
  1225. * @param ep_addr endpoint address
  1226. * @retval Data Size
  1227. */
  1228. uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1229. {
  1230. return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].xfer_count;
  1231. }
  1232. /**
  1233. * @brief Send an amount of data
  1234. * @param hpcd PCD handle
  1235. * @param ep_addr endpoint address
  1236. * @param pBuf pointer to the transmission buffer
  1237. * @param len amount of data to be sent
  1238. * @retval HAL status
  1239. */
  1240. HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
  1241. {
  1242. PCD_EPTypeDef *ep;
  1243. ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1244. /*setup and start the Xfer */
  1245. ep->xfer_buff = pBuf;
  1246. ep->xfer_len = len;
  1247. ep->xfer_count = 0U;
  1248. ep->is_in = 1U;
  1249. ep->num = ep_addr & EP_ADDR_MSK;
  1250. if ((ep_addr & EP_ADDR_MSK) == 0U)
  1251. {
  1252. (void)USB_EP0StartXfer(hpcd->Instance, ep);
  1253. }
  1254. else
  1255. {
  1256. (void)USB_EPStartXfer(hpcd->Instance, ep);
  1257. }
  1258. return HAL_OK;
  1259. }
  1260. /**
  1261. * @brief Set a STALL condition over an endpoint
  1262. * @param hpcd PCD handle
  1263. * @param ep_addr endpoint address
  1264. * @retval HAL status
  1265. */
  1266. HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1267. {
  1268. PCD_EPTypeDef *ep;
  1269. if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints)
  1270. {
  1271. return HAL_ERROR;
  1272. }
  1273. if ((0x80U & ep_addr) == 0x80U)
  1274. {
  1275. ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1276. ep->is_in = 1U;
  1277. }
  1278. else
  1279. {
  1280. ep = &hpcd->OUT_ep[ep_addr];
  1281. ep->is_in = 0U;
  1282. }
  1283. ep->is_stall = 1U;
  1284. ep->num = ep_addr & EP_ADDR_MSK;
  1285. __HAL_LOCK(hpcd);
  1286. (void)USB_EPSetStall(hpcd->Instance, ep);
  1287. if ((ep_addr & EP_ADDR_MSK) == 0U)
  1288. {
  1289. (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
  1290. }
  1291. __HAL_UNLOCK(hpcd);
  1292. return HAL_OK;
  1293. }
  1294. /**
  1295. * @brief Clear a STALL condition over in an endpoint
  1296. * @param hpcd PCD handle
  1297. * @param ep_addr endpoint address
  1298. * @retval HAL status
  1299. */
  1300. HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1301. {
  1302. PCD_EPTypeDef *ep;
  1303. if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints)
  1304. {
  1305. return HAL_ERROR;
  1306. }
  1307. if ((0x80U & ep_addr) == 0x80U)
  1308. {
  1309. ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1310. ep->is_in = 1U;
  1311. }
  1312. else
  1313. {
  1314. ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
  1315. ep->is_in = 0U;
  1316. }
  1317. ep->is_stall = 0U;
  1318. ep->num = ep_addr & EP_ADDR_MSK;
  1319. __HAL_LOCK(hpcd);
  1320. (void)USB_EPClearStall(hpcd->Instance, ep);
  1321. __HAL_UNLOCK(hpcd);
  1322. return HAL_OK;
  1323. }
  1324. /**
  1325. * @brief Flush an endpoint
  1326. * @param hpcd PCD handle
  1327. * @param ep_addr endpoint address
  1328. * @retval HAL status
  1329. */
  1330. HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1331. {
  1332. /* Prevent unused argument(s) compilation warning */
  1333. UNUSED(hpcd);
  1334. UNUSED(ep_addr);
  1335. return HAL_OK;
  1336. }
  1337. /**
  1338. * @brief Activate remote wakeup signalling
  1339. * @param hpcd PCD handle
  1340. * @retval HAL status
  1341. */
  1342. HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
  1343. {
  1344. return (USB_ActivateRemoteWakeup(hpcd->Instance));
  1345. }
  1346. /**
  1347. * @brief De-activate remote wakeup signalling.
  1348. * @param hpcd PCD handle
  1349. * @retval HAL status
  1350. */
  1351. HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
  1352. {
  1353. return (USB_DeActivateRemoteWakeup(hpcd->Instance));
  1354. }
  1355. /**
  1356. * @}
  1357. */
  1358. /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
  1359. * @brief Peripheral State functions
  1360. *
  1361. @verbatim
  1362. ===============================================================================
  1363. ##### Peripheral State functions #####
  1364. ===============================================================================
  1365. [..]
  1366. This subsection permits to get in run-time the status of the peripheral
  1367. and the data flow.
  1368. @endverbatim
  1369. * @{
  1370. */
  1371. /**
  1372. * @brief Return the PCD handle state.
  1373. * @param hpcd PCD handle
  1374. * @retval HAL state
  1375. */
  1376. PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
  1377. {
  1378. return hpcd->State;
  1379. }
  1380. /**
  1381. * @}
  1382. */
  1383. /**
  1384. * @}
  1385. */
  1386. /* Private functions ---------------------------------------------------------*/
  1387. /** @addtogroup PCD_Private_Functions
  1388. * @{
  1389. */
  1390. /**
  1391. * @brief This function handles PCD Endpoint interrupt request.
  1392. * @param hpcd PCD handle
  1393. * @retval HAL status
  1394. */
  1395. static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
  1396. {
  1397. PCD_EPTypeDef *ep;
  1398. uint16_t count;
  1399. uint16_t wIstr;
  1400. uint16_t wEPVal;
  1401. uint8_t epindex;
  1402. /* stay in loop while pending interrupts */
  1403. while ((hpcd->Instance->ISTR & USB_ISTR_CTR) != 0U)
  1404. {
  1405. wIstr = hpcd->Instance->ISTR;
  1406. /* extract highest priority endpoint number */
  1407. epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
  1408. if (epindex == 0U)
  1409. {
  1410. /* Decode and service control endpoint interrupt */
  1411. /* DIR bit = origin of the interrupt */
  1412. if ((wIstr & USB_ISTR_DIR) == 0U)
  1413. {
  1414. /* DIR = 0 */
  1415. /* DIR = 0 => IN int */
  1416. /* DIR = 0 implies that (EP_CTR_TX = 1) always */
  1417. PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
  1418. ep = &hpcd->IN_ep[0];
  1419. ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
  1420. ep->xfer_buff += ep->xfer_count;
  1421. /* TX COMPLETE */
  1422. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1423. hpcd->DataInStageCallback(hpcd, 0U);
  1424. #else
  1425. HAL_PCD_DataInStageCallback(hpcd, 0U);
  1426. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1427. if ((hpcd->USB_Address > 0U) && (ep->xfer_len == 0U))
  1428. {
  1429. hpcd->Instance->DADDR = ((uint16_t)hpcd->USB_Address | USB_DADDR_EF);
  1430. hpcd->USB_Address = 0U;
  1431. }
  1432. }
  1433. else
  1434. {
  1435. /* DIR = 1 */
  1436. /* DIR = 1 & CTR_RX => SETUP or OUT int */
  1437. /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
  1438. ep = &hpcd->OUT_ep[0];
  1439. wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
  1440. if ((wEPVal & USB_EP_SETUP) != 0U)
  1441. {
  1442. /* Get SETUP Packet*/
  1443. ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
  1444. USB_ReadPMA(hpcd->Instance, (uint8_t *)hpcd->Setup,
  1445. ep->pmaadress, (uint16_t)ep->xfer_count);
  1446. /* SETUP bit kept frozen while CTR_RX = 1*/
  1447. PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
  1448. /* Process SETUP Packet*/
  1449. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1450. hpcd->SetupStageCallback(hpcd);
  1451. #else
  1452. HAL_PCD_SetupStageCallback(hpcd);
  1453. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1454. }
  1455. else if ((wEPVal & USB_EP_CTR_RX) != 0U)
  1456. {
  1457. PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
  1458. /* Get Control Data OUT Packet*/
  1459. ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
  1460. if ((ep->xfer_count != 0U) && (ep->xfer_buff != 0U))
  1461. {
  1462. USB_ReadPMA(hpcd->Instance, ep->xfer_buff,
  1463. ep->pmaadress, (uint16_t)ep->xfer_count);
  1464. ep->xfer_buff += ep->xfer_count;
  1465. /* Process Control Data OUT Packet*/
  1466. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1467. hpcd->DataOutStageCallback(hpcd, 0U);
  1468. #else
  1469. HAL_PCD_DataOutStageCallback(hpcd, 0U);
  1470. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1471. }
  1472. PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
  1473. PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
  1474. }
  1475. }
  1476. }
  1477. else
  1478. {
  1479. /* Decode and service non control endpoints interrupt */
  1480. /* process related endpoint register */
  1481. wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);
  1482. if ((wEPVal & USB_EP_CTR_RX) != 0U)
  1483. {
  1484. /* clear int flag */
  1485. PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
  1486. ep = &hpcd->OUT_ep[epindex];
  1487. /* OUT double Buffering*/
  1488. if (ep->doublebuffer == 0U)
  1489. {
  1490. count = (uint16_t)PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
  1491. if (count != 0U)
  1492. {
  1493. USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
  1494. }
  1495. }
  1496. else
  1497. {
  1498. if ((PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX) != 0U)
  1499. {
  1500. /*read from endpoint BUF0Addr buffer*/
  1501. count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
  1502. if (count != 0U)
  1503. {
  1504. USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
  1505. }
  1506. }
  1507. else
  1508. {
  1509. /*read from endpoint BUF1Addr buffer*/
  1510. count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
  1511. if (count != 0U)
  1512. {
  1513. USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
  1514. }
  1515. }
  1516. /* free EP OUT Buffer */
  1517. PCD_FreeUserBuffer(hpcd->Instance, ep->num, 0U);
  1518. }
  1519. /*multi-packet on the NON control OUT endpoint*/
  1520. ep->xfer_count += count;
  1521. ep->xfer_buff += count;
  1522. if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
  1523. {
  1524. /* RX COMPLETE */
  1525. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1526. hpcd->DataOutStageCallback(hpcd, ep->num);
  1527. #else
  1528. HAL_PCD_DataOutStageCallback(hpcd, ep->num);
  1529. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1530. }
  1531. else
  1532. {
  1533. (void)HAL_PCD_EP_Receive(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
  1534. }
  1535. } /* if((wEPVal & EP_CTR_RX) */
  1536. if ((wEPVal & USB_EP_CTR_TX) != 0U)
  1537. {
  1538. ep = &hpcd->IN_ep[epindex];
  1539. /* clear int flag */
  1540. PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
  1541. /*multi-packet on the NON control IN endpoint*/
  1542. ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
  1543. ep->xfer_buff += ep->xfer_count;
  1544. /* Zero Length Packet? */
  1545. if (ep->xfer_len == 0U)
  1546. {
  1547. /* TX COMPLETE */
  1548. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1549. hpcd->DataInStageCallback(hpcd, ep->num);
  1550. #else
  1551. HAL_PCD_DataInStageCallback(hpcd, ep->num);
  1552. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1553. }
  1554. else
  1555. {
  1556. (void)HAL_PCD_EP_Transmit(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
  1557. }
  1558. }
  1559. }
  1560. }
  1561. return HAL_OK;
  1562. }
  1563. /**
  1564. * @}
  1565. */
  1566. #endif /* defined (USB) */
  1567. #endif /* HAL_PCD_MODULE_ENABLED */
  1568. /**
  1569. * @}
  1570. */
  1571. /**
  1572. * @}
  1573. */
  1574. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/