stm32l1xx_hal_pcd.c 36 KB

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