stm32g4xx_ll_usb.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. /**
  2. ******************************************************************************
  3. * @file stm32g4xx_ll_usb.c
  4. * @author MCD Application Team
  5. * @brief USB Low Layer HAL module driver.
  6. *
  7. * This file provides firmware functions to manage the following
  8. * functionalities of the USB Peripheral Controller:
  9. * + Initialization/de-initialization functions
  10. * + I/O operation functions
  11. * + Peripheral Control functions
  12. * + Peripheral State functions
  13. *
  14. ******************************************************************************
  15. * @attention
  16. *
  17. * Copyright (c) 2019 STMicroelectronics.
  18. * All rights reserved.
  19. *
  20. * This software is licensed under terms that can be found in the LICENSE file
  21. * in the root directory of this software component.
  22. * If no LICENSE file comes with this software, it is provided AS-IS.
  23. *
  24. ******************************************************************************
  25. @verbatim
  26. ==============================================================================
  27. ##### How to use this driver #####
  28. ==============================================================================
  29. [..]
  30. (#) Fill parameters of Init structure in USB_CfgTypeDef structure.
  31. (#) Call USB_CoreInit() API to initialize the USB Core peripheral.
  32. (#) The upper HAL HCD/PCD driver will call the right routines for its internal processes.
  33. @endverbatim
  34. ******************************************************************************
  35. */
  36. /* Includes ------------------------------------------------------------------*/
  37. #include "stm32g4xx_hal.h"
  38. /** @addtogroup STM32G4xx_LL_USB_DRIVER
  39. * @{
  40. */
  41. #if defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED)
  42. #if defined (USB)
  43. /* Private typedef -----------------------------------------------------------*/
  44. /* Private define ------------------------------------------------------------*/
  45. /* Private macro -------------------------------------------------------------*/
  46. /* Private variables ---------------------------------------------------------*/
  47. /* Private function prototypes -----------------------------------------------*/
  48. /* Private functions ---------------------------------------------------------*/
  49. /**
  50. * @brief Initializes the USB Core
  51. * @param USBx USB Instance
  52. * @param cfg pointer to a USB_CfgTypeDef structure that contains
  53. * the configuration information for the specified USBx peripheral.
  54. * @retval HAL status
  55. */
  56. HAL_StatusTypeDef USB_CoreInit(USB_TypeDef *USBx, USB_CfgTypeDef cfg)
  57. {
  58. /* Prevent unused argument(s) compilation warning */
  59. UNUSED(USBx);
  60. UNUSED(cfg);
  61. /* NOTE : - This function is not required by USB Device FS peripheral, it is used
  62. only by USB OTG FS peripheral.
  63. - This function is added to ensure compatibility across platforms.
  64. */
  65. return HAL_OK;
  66. }
  67. /**
  68. * @brief USB_EnableGlobalInt
  69. * Enables the controller's Global Int in the AHB Config reg
  70. * @param USBx Selected device
  71. * @retval HAL status
  72. */
  73. HAL_StatusTypeDef USB_EnableGlobalInt(USB_TypeDef *USBx)
  74. {
  75. uint32_t winterruptmask;
  76. /* Clear pending interrupts */
  77. USBx->ISTR = 0U;
  78. /* Set winterruptmask variable */
  79. winterruptmask = USB_CNTR_CTRM | USB_CNTR_WKUPM |
  80. USB_CNTR_SUSPM | USB_CNTR_ERRM |
  81. USB_CNTR_SOFM | USB_CNTR_ESOFM |
  82. USB_CNTR_RESETM | USB_CNTR_L1REQM;
  83. /* Set interrupt mask */
  84. USBx->CNTR = (uint16_t)winterruptmask;
  85. return HAL_OK;
  86. }
  87. /**
  88. * @brief USB_DisableGlobalInt
  89. * Disable the controller's Global Int in the AHB Config reg
  90. * @param USBx Selected device
  91. * @retval HAL status
  92. */
  93. HAL_StatusTypeDef USB_DisableGlobalInt(USB_TypeDef *USBx)
  94. {
  95. uint32_t winterruptmask;
  96. /* Set winterruptmask variable */
  97. winterruptmask = USB_CNTR_CTRM | USB_CNTR_WKUPM |
  98. USB_CNTR_SUSPM | USB_CNTR_ERRM |
  99. USB_CNTR_SOFM | USB_CNTR_ESOFM |
  100. USB_CNTR_RESETM | USB_CNTR_L1REQM;
  101. /* Clear interrupt mask */
  102. USBx->CNTR &= (uint16_t)(~winterruptmask);
  103. return HAL_OK;
  104. }
  105. /**
  106. * @brief USB_SetCurrentMode Set functional mode
  107. * @param USBx Selected device
  108. * @param mode current core mode
  109. * This parameter can be one of the these values:
  110. * @arg USB_DEVICE_MODE Peripheral mode
  111. * @retval HAL status
  112. */
  113. HAL_StatusTypeDef USB_SetCurrentMode(USB_TypeDef *USBx, USB_ModeTypeDef mode)
  114. {
  115. /* Prevent unused argument(s) compilation warning */
  116. UNUSED(USBx);
  117. UNUSED(mode);
  118. /* NOTE : - This function is not required by USB Device FS peripheral, it is used
  119. only by USB OTG FS peripheral.
  120. - This function is added to ensure compatibility across platforms.
  121. */
  122. return HAL_OK;
  123. }
  124. /**
  125. * @brief USB_DevInit Initializes the USB controller registers
  126. * for device mode
  127. * @param USBx Selected device
  128. * @param cfg pointer to a USB_CfgTypeDef structure that contains
  129. * the configuration information for the specified USBx peripheral.
  130. * @retval HAL status
  131. */
  132. HAL_StatusTypeDef USB_DevInit(USB_TypeDef *USBx, USB_CfgTypeDef cfg)
  133. {
  134. /* Prevent unused argument(s) compilation warning */
  135. UNUSED(cfg);
  136. /* Init Device */
  137. /* CNTR_FRES = 1 */
  138. USBx->CNTR = (uint16_t)USB_CNTR_FRES;
  139. /* CNTR_FRES = 0 */
  140. USBx->CNTR = 0U;
  141. /* Clear pending interrupts */
  142. USBx->ISTR = 0U;
  143. /*Set Btable Address*/
  144. USBx->BTABLE = BTABLE_ADDRESS;
  145. return HAL_OK;
  146. }
  147. /**
  148. * @brief USB_FlushTxFifo : Flush a Tx FIFO
  149. * @param USBx : Selected device
  150. * @param num : FIFO number
  151. * This parameter can be a value from 1 to 15
  152. 15 means Flush all Tx FIFOs
  153. * @retval HAL status
  154. */
  155. HAL_StatusTypeDef USB_FlushTxFifo(USB_TypeDef const *USBx, uint32_t num)
  156. {
  157. /* Prevent unused argument(s) compilation warning */
  158. UNUSED(USBx);
  159. UNUSED(num);
  160. /* NOTE : - This function is not required by USB Device FS peripheral, it is used
  161. only by USB OTG FS peripheral.
  162. - This function is added to ensure compatibility across platforms.
  163. */
  164. return HAL_OK;
  165. }
  166. /**
  167. * @brief USB_FlushRxFifo : Flush Rx FIFO
  168. * @param USBx : Selected device
  169. * @retval HAL status
  170. */
  171. HAL_StatusTypeDef USB_FlushRxFifo(USB_TypeDef const *USBx)
  172. {
  173. /* Prevent unused argument(s) compilation warning */
  174. UNUSED(USBx);
  175. /* NOTE : - This function is not required by USB Device FS peripheral, it is used
  176. only by USB OTG FS peripheral.
  177. - This function is added to ensure compatibility across platforms.
  178. */
  179. return HAL_OK;
  180. }
  181. #if defined (HAL_PCD_MODULE_ENABLED)
  182. /**
  183. * @brief Activate and configure an endpoint
  184. * @param USBx Selected device
  185. * @param ep pointer to endpoint structure
  186. * @retval HAL status
  187. */
  188. HAL_StatusTypeDef USB_ActivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  189. {
  190. HAL_StatusTypeDef ret = HAL_OK;
  191. uint16_t wEpRegVal;
  192. wEpRegVal = PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_T_MASK;
  193. /* initialize Endpoint */
  194. switch (ep->type)
  195. {
  196. case EP_TYPE_CTRL:
  197. wEpRegVal |= USB_EP_CONTROL;
  198. break;
  199. case EP_TYPE_BULK:
  200. wEpRegVal |= USB_EP_BULK;
  201. break;
  202. case EP_TYPE_INTR:
  203. wEpRegVal |= USB_EP_INTERRUPT;
  204. break;
  205. case EP_TYPE_ISOC:
  206. wEpRegVal |= USB_EP_ISOCHRONOUS;
  207. break;
  208. default:
  209. ret = HAL_ERROR;
  210. break;
  211. }
  212. PCD_SET_ENDPOINT(USBx, ep->num, (wEpRegVal | USB_EP_CTR_RX | USB_EP_CTR_TX));
  213. PCD_SET_EP_ADDRESS(USBx, ep->num, ep->num);
  214. if (ep->doublebuffer == 0U)
  215. {
  216. if (ep->is_in != 0U)
  217. {
  218. /*Set the endpoint Transmit buffer address */
  219. PCD_SET_EP_TX_ADDRESS(USBx, ep->num, ep->pmaadress);
  220. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  221. if (ep->type != EP_TYPE_ISOC)
  222. {
  223. /* Configure NAK status for the Endpoint */
  224. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
  225. }
  226. else
  227. {
  228. /* Configure TX Endpoint to disabled state */
  229. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  230. }
  231. }
  232. else
  233. {
  234. /* Set the endpoint Receive buffer address */
  235. PCD_SET_EP_RX_ADDRESS(USBx, ep->num, ep->pmaadress);
  236. /* Set the endpoint Receive buffer counter */
  237. PCD_SET_EP_RX_CNT(USBx, ep->num, ep->maxpacket);
  238. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  239. if (ep->num == 0U)
  240. {
  241. /* Configure VALID status for EP0 */
  242. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
  243. }
  244. else
  245. {
  246. /* Configure NAK status for OUT Endpoint */
  247. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
  248. }
  249. }
  250. }
  251. #if (USE_USB_DOUBLE_BUFFER == 1U)
  252. /* Double Buffer */
  253. else
  254. {
  255. if (ep->type == EP_TYPE_BULK)
  256. {
  257. /* Set bulk endpoint as double buffered */
  258. PCD_SET_BULK_EP_DBUF(USBx, ep->num);
  259. }
  260. else
  261. {
  262. /* Set the ISOC endpoint in double buffer mode */
  263. PCD_CLEAR_EP_KIND(USBx, ep->num);
  264. }
  265. /* Set buffer address for double buffered mode */
  266. PCD_SET_EP_DBUF_ADDR(USBx, ep->num, ep->pmaaddr0, ep->pmaaddr1);
  267. if (ep->is_in == 0U)
  268. {
  269. /* Clear the data toggle bits for the endpoint IN/OUT */
  270. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  271. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  272. /* Set endpoint RX count */
  273. PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, ep->maxpacket);
  274. /* Set endpoint RX to valid state */
  275. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
  276. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  277. }
  278. else
  279. {
  280. /* Clear the data toggle bits for the endpoint IN/OUT */
  281. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  282. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  283. if (ep->type != EP_TYPE_ISOC)
  284. {
  285. /* Configure NAK status for the Endpoint */
  286. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
  287. }
  288. else
  289. {
  290. /* Configure TX Endpoint to disabled state */
  291. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  292. }
  293. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  294. }
  295. }
  296. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  297. return ret;
  298. }
  299. /**
  300. * @brief De-activate and de-initialize an endpoint
  301. * @param USBx Selected device
  302. * @param ep pointer to endpoint structure
  303. * @retval HAL status
  304. */
  305. HAL_StatusTypeDef USB_DeactivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  306. {
  307. if (ep->doublebuffer == 0U)
  308. {
  309. if (ep->is_in != 0U)
  310. {
  311. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  312. /* Configure DISABLE status for the Endpoint */
  313. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  314. }
  315. else
  316. {
  317. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  318. /* Configure DISABLE status for the Endpoint */
  319. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  320. }
  321. }
  322. #if (USE_USB_DOUBLE_BUFFER == 1U)
  323. /* Double Buffer */
  324. else
  325. {
  326. if (ep->is_in == 0U)
  327. {
  328. /* Clear the data toggle bits for the endpoint IN/OUT*/
  329. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  330. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  331. /* Reset value of the data toggle bits for the endpoint out*/
  332. PCD_TX_DTOG(USBx, ep->num);
  333. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  334. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  335. }
  336. else
  337. {
  338. /* Clear the data toggle bits for the endpoint IN/OUT*/
  339. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  340. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  341. PCD_RX_DTOG(USBx, ep->num);
  342. /* Configure DISABLE status for the Endpoint*/
  343. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  344. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  345. }
  346. }
  347. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  348. return HAL_OK;
  349. }
  350. /**
  351. * @brief USB_EPStartXfer setup and starts a transfer over an EP
  352. * @param USBx Selected device
  353. * @param ep pointer to endpoint structure
  354. * @retval HAL status
  355. */
  356. HAL_StatusTypeDef USB_EPStartXfer(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  357. {
  358. uint32_t len;
  359. #if (USE_USB_DOUBLE_BUFFER == 1U)
  360. uint16_t pmabuffer;
  361. uint16_t wEPVal;
  362. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  363. /* IN endpoint */
  364. if (ep->is_in == 1U)
  365. {
  366. /* Multi packet transfer */
  367. if (ep->xfer_len > ep->maxpacket)
  368. {
  369. len = ep->maxpacket;
  370. }
  371. else
  372. {
  373. len = ep->xfer_len;
  374. }
  375. /* configure and validate Tx endpoint */
  376. if (ep->doublebuffer == 0U)
  377. {
  378. USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, (uint16_t)len);
  379. PCD_SET_EP_TX_CNT(USBx, ep->num, len);
  380. }
  381. #if (USE_USB_DOUBLE_BUFFER == 1U)
  382. else
  383. {
  384. /* double buffer bulk management */
  385. if (ep->type == EP_TYPE_BULK)
  386. {
  387. if (ep->xfer_len_db > ep->maxpacket)
  388. {
  389. /* enable double buffer */
  390. PCD_SET_BULK_EP_DBUF(USBx, ep->num);
  391. /* each Time to write in PMA xfer_len_db will */
  392. ep->xfer_len_db -= len;
  393. /* Fill the two first buffer in the Buffer0 & Buffer1 */
  394. if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
  395. {
  396. /* Set the Double buffer counter for pmabuffer1 */
  397. PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
  398. pmabuffer = ep->pmaaddr1;
  399. /* Write the user buffer to USB PMA */
  400. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  401. ep->xfer_buff += len;
  402. if (ep->xfer_len_db > ep->maxpacket)
  403. {
  404. ep->xfer_len_db -= len;
  405. }
  406. else
  407. {
  408. len = ep->xfer_len_db;
  409. ep->xfer_len_db = 0U;
  410. }
  411. /* Set the Double buffer counter for pmabuffer0 */
  412. PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
  413. pmabuffer = ep->pmaaddr0;
  414. /* Write the user buffer to USB PMA */
  415. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  416. }
  417. else
  418. {
  419. /* Set the Double buffer counter for pmabuffer0 */
  420. PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
  421. pmabuffer = ep->pmaaddr0;
  422. /* Write the user buffer to USB PMA */
  423. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  424. ep->xfer_buff += len;
  425. if (ep->xfer_len_db > ep->maxpacket)
  426. {
  427. ep->xfer_len_db -= len;
  428. }
  429. else
  430. {
  431. len = ep->xfer_len_db;
  432. ep->xfer_len_db = 0U;
  433. }
  434. /* Set the Double buffer counter for pmabuffer1 */
  435. PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
  436. pmabuffer = ep->pmaaddr1;
  437. /* Write the user buffer to USB PMA */
  438. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  439. }
  440. }
  441. /* auto Switch to single buffer mode when transfer <Mps no need to manage in double buffer */
  442. else
  443. {
  444. len = ep->xfer_len_db;
  445. /* disable double buffer mode for Bulk endpoint */
  446. PCD_CLEAR_BULK_EP_DBUF(USBx, ep->num);
  447. /* Set Tx count with nbre of byte to be transmitted */
  448. PCD_SET_EP_TX_CNT(USBx, ep->num, len);
  449. pmabuffer = ep->pmaaddr0;
  450. /* Write the user buffer to USB PMA */
  451. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  452. }
  453. }
  454. else /* Manage isochronous double buffer IN mode */
  455. {
  456. /* Each Time to write in PMA xfer_len_db will */
  457. ep->xfer_len_db -= len;
  458. /* Fill the data buffer */
  459. if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
  460. {
  461. /* Set the Double buffer counter for pmabuffer1 */
  462. PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
  463. pmabuffer = ep->pmaaddr1;
  464. /* Write the user buffer to USB PMA */
  465. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  466. }
  467. else
  468. {
  469. /* Set the Double buffer counter for pmabuffer0 */
  470. PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
  471. pmabuffer = ep->pmaaddr0;
  472. /* Write the user buffer to USB PMA */
  473. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  474. }
  475. }
  476. }
  477. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  478. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID);
  479. }
  480. else /* OUT endpoint */
  481. {
  482. if (ep->doublebuffer == 0U)
  483. {
  484. if ((ep->xfer_len == 0U) && (ep->type == EP_TYPE_CTRL))
  485. {
  486. /* This is a status out stage set the OUT_STATUS */
  487. PCD_SET_OUT_STATUS(USBx, ep->num);
  488. }
  489. else
  490. {
  491. PCD_CLEAR_OUT_STATUS(USBx, ep->num);
  492. }
  493. /* Multi packet transfer */
  494. if (ep->xfer_len > ep->maxpacket)
  495. {
  496. ep->xfer_len -= ep->maxpacket;
  497. }
  498. else
  499. {
  500. ep->xfer_len = 0U;
  501. }
  502. }
  503. #if (USE_USB_DOUBLE_BUFFER == 1U)
  504. else
  505. {
  506. /* First Transfer Coming From HAL_PCD_EP_Receive & From ISR */
  507. /* Set the Double buffer counter */
  508. if (ep->type == EP_TYPE_BULK)
  509. {
  510. /* Coming from ISR */
  511. if (ep->xfer_count != 0U)
  512. {
  513. /* Update last value to check if there is blocking state */
  514. wEPVal = PCD_GET_ENDPOINT(USBx, ep->num);
  515. /* Blocking State */
  516. if ((((wEPVal & USB_EP_DTOG_RX) != 0U) && ((wEPVal & USB_EP_DTOG_TX) != 0U)) ||
  517. (((wEPVal & USB_EP_DTOG_RX) == 0U) && ((wEPVal & USB_EP_DTOG_TX) == 0U)))
  518. {
  519. PCD_FREE_USER_BUFFER(USBx, ep->num, 0U);
  520. }
  521. }
  522. }
  523. /* iso out double */
  524. else if (ep->type == EP_TYPE_ISOC)
  525. {
  526. /* Only single packet transfer supported in FS */
  527. ep->xfer_len = 0U;
  528. }
  529. else
  530. {
  531. return HAL_ERROR;
  532. }
  533. }
  534. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  535. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
  536. }
  537. return HAL_OK;
  538. }
  539. /**
  540. * @brief USB_EPSetStall set a stall condition over an EP
  541. * @param USBx Selected device
  542. * @param ep pointer to endpoint structure
  543. * @retval HAL status
  544. */
  545. HAL_StatusTypeDef USB_EPSetStall(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  546. {
  547. if (ep->is_in != 0U)
  548. {
  549. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_STALL);
  550. }
  551. else
  552. {
  553. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_STALL);
  554. }
  555. return HAL_OK;
  556. }
  557. /**
  558. * @brief USB_EPClearStall Clear a stall condition over an EP
  559. * @param USBx Selected device
  560. * @param ep pointer to endpoint structure
  561. * @retval HAL status
  562. */
  563. HAL_StatusTypeDef USB_EPClearStall(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  564. {
  565. if (ep->is_in != 0U)
  566. {
  567. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  568. if (ep->type != EP_TYPE_ISOC)
  569. {
  570. /* Configure NAK status for the Endpoint */
  571. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
  572. }
  573. }
  574. else
  575. {
  576. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  577. /* Configure VALID status for the Endpoint */
  578. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
  579. }
  580. return HAL_OK;
  581. }
  582. /**
  583. * @brief USB_EPStoptXfer Stop transfer on an EP
  584. * @param USBx usb device instance
  585. * @param ep pointer to endpoint structure
  586. * @retval HAL status
  587. */
  588. HAL_StatusTypeDef USB_EPStopXfer(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  589. {
  590. /* IN endpoint */
  591. if (ep->is_in == 1U)
  592. {
  593. if (ep->doublebuffer == 0U)
  594. {
  595. if (ep->type != EP_TYPE_ISOC)
  596. {
  597. /* Configure NAK status for the Endpoint */
  598. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
  599. }
  600. else
  601. {
  602. /* Configure TX Endpoint to disabled state */
  603. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  604. }
  605. }
  606. }
  607. else /* OUT endpoint */
  608. {
  609. if (ep->doublebuffer == 0U)
  610. {
  611. if (ep->type != EP_TYPE_ISOC)
  612. {
  613. /* Configure NAK status for the Endpoint */
  614. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
  615. }
  616. else
  617. {
  618. /* Configure RX Endpoint to disabled state */
  619. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  620. }
  621. }
  622. }
  623. return HAL_OK;
  624. }
  625. #endif /* defined (HAL_PCD_MODULE_ENABLED) */
  626. /**
  627. * @brief USB_StopDevice Stop the usb device mode
  628. * @param USBx Selected device
  629. * @retval HAL status
  630. */
  631. HAL_StatusTypeDef USB_StopDevice(USB_TypeDef *USBx)
  632. {
  633. /* disable all interrupts and force USB reset */
  634. USBx->CNTR = (uint16_t)USB_CNTR_FRES;
  635. /* clear interrupt status register */
  636. USBx->ISTR = 0U;
  637. /* switch-off device */
  638. USBx->CNTR = (uint16_t)(USB_CNTR_FRES | USB_CNTR_PDWN);
  639. return HAL_OK;
  640. }
  641. /**
  642. * @brief USB_SetDevAddress Stop the usb device mode
  643. * @param USBx Selected device
  644. * @param address new device address to be assigned
  645. * This parameter can be a value from 0 to 255
  646. * @retval HAL status
  647. */
  648. HAL_StatusTypeDef USB_SetDevAddress(USB_TypeDef *USBx, uint8_t address)
  649. {
  650. if (address == 0U)
  651. {
  652. /* set device address and enable function */
  653. USBx->DADDR = (uint16_t)USB_DADDR_EF;
  654. }
  655. return HAL_OK;
  656. }
  657. /**
  658. * @brief USB_DevConnect Connect the USB device by enabling the pull-up/pull-down
  659. * @param USBx Selected device
  660. * @retval HAL status
  661. */
  662. HAL_StatusTypeDef USB_DevConnect(USB_TypeDef *USBx)
  663. {
  664. /* Enabling DP Pull-UP bit to Connect internal PU resistor on USB DP line */
  665. USBx->BCDR |= (uint16_t)USB_BCDR_DPPU;
  666. return HAL_OK;
  667. }
  668. /**
  669. * @brief USB_DevDisconnect Disconnect the USB device by disabling the pull-up/pull-down
  670. * @param USBx Selected device
  671. * @retval HAL status
  672. */
  673. HAL_StatusTypeDef USB_DevDisconnect(USB_TypeDef *USBx)
  674. {
  675. /* Disable DP Pull-Up bit to disconnect the Internal PU resistor on USB DP line */
  676. USBx->BCDR &= (uint16_t)(~(USB_BCDR_DPPU));
  677. return HAL_OK;
  678. }
  679. /**
  680. * @brief USB_ReadInterrupts return the global USB interrupt status
  681. * @param USBx Selected device
  682. * @retval USB Global Interrupt status
  683. */
  684. uint32_t USB_ReadInterrupts(USB_TypeDef const *USBx)
  685. {
  686. uint32_t tmpreg;
  687. tmpreg = USBx->ISTR;
  688. return tmpreg;
  689. }
  690. /**
  691. * @brief USB_ActivateRemoteWakeup : active remote wakeup signalling
  692. * @param USBx Selected device
  693. * @retval HAL status
  694. */
  695. HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_TypeDef *USBx)
  696. {
  697. USBx->CNTR |= (uint16_t)USB_CNTR_RESUME;
  698. return HAL_OK;
  699. }
  700. /**
  701. * @brief USB_DeActivateRemoteWakeup de-active remote wakeup signalling
  702. * @param USBx Selected device
  703. * @retval HAL status
  704. */
  705. HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_TypeDef *USBx)
  706. {
  707. USBx->CNTR &= (uint16_t)(~USB_CNTR_RESUME);
  708. return HAL_OK;
  709. }
  710. /**
  711. * @brief Copy a buffer from user memory area to packet memory area (PMA)
  712. * @param USBx USB peripheral instance register address.
  713. * @param pbUsrBuf pointer to user memory area.
  714. * @param wPMABufAddr address into PMA.
  715. * @param wNBytes no. of bytes to be copied.
  716. * @retval None
  717. */
  718. void USB_WritePMA(USB_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
  719. {
  720. uint32_t n = ((uint32_t)wNBytes + 1U) >> 1;
  721. uint32_t BaseAddr = (uint32_t)USBx;
  722. uint32_t count;
  723. uint16_t WrVal;
  724. __IO uint16_t *pdwVal;
  725. uint8_t *pBuf = pbUsrBuf;
  726. pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
  727. for (count = n; count != 0U; count--)
  728. {
  729. WrVal = pBuf[0];
  730. WrVal |= (uint16_t)pBuf[1] << 8;
  731. *pdwVal = (WrVal & 0xFFFFU);
  732. pdwVal++;
  733. #if PMA_ACCESS > 1U
  734. pdwVal++;
  735. #endif /* PMA_ACCESS */
  736. pBuf++;
  737. pBuf++;
  738. }
  739. }
  740. /**
  741. * @brief Copy data from packet memory area (PMA) to user memory buffer
  742. * @param USBx USB peripheral instance register address.
  743. * @param pbUsrBuf pointer to user memory area.
  744. * @param wPMABufAddr address into PMA.
  745. * @param wNBytes no. of bytes to be copied.
  746. * @retval None
  747. */
  748. void USB_ReadPMA(USB_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
  749. {
  750. uint32_t n = (uint32_t)wNBytes >> 1;
  751. uint32_t BaseAddr = (uint32_t)USBx;
  752. uint32_t count;
  753. uint32_t RdVal;
  754. __IO uint16_t *pdwVal;
  755. uint8_t *pBuf = pbUsrBuf;
  756. pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
  757. for (count = n; count != 0U; count--)
  758. {
  759. RdVal = *(__IO uint16_t *)pdwVal;
  760. pdwVal++;
  761. *pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
  762. pBuf++;
  763. *pBuf = (uint8_t)((RdVal >> 8) & 0xFFU);
  764. pBuf++;
  765. #if PMA_ACCESS > 1U
  766. pdwVal++;
  767. #endif /* PMA_ACCESS */
  768. }
  769. if ((wNBytes % 2U) != 0U)
  770. {
  771. RdVal = *pdwVal;
  772. *pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
  773. }
  774. }
  775. /**
  776. * @}
  777. */
  778. /**
  779. * @}
  780. */
  781. #endif /* defined (USB) */
  782. #endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
  783. /**
  784. * @}
  785. */