stm32f3xx_ll_usb.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. /**
  2. ******************************************************************************
  3. * @file stm32f3xx_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) 2016 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 "stm32f3xx_hal.h"
  38. /** @addtogroup STM32F3xx_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;
  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;
  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. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
  273. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  274. }
  275. else
  276. {
  277. /* Clear the data toggle bits for the endpoint IN/OUT */
  278. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  279. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  280. if (ep->type != EP_TYPE_ISOC)
  281. {
  282. /* Configure NAK status for the Endpoint */
  283. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
  284. }
  285. else
  286. {
  287. /* Configure TX Endpoint to disabled state */
  288. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  289. }
  290. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  291. }
  292. }
  293. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  294. return ret;
  295. }
  296. /**
  297. * @brief De-activate and de-initialize an endpoint
  298. * @param USBx Selected device
  299. * @param ep pointer to endpoint structure
  300. * @retval HAL status
  301. */
  302. HAL_StatusTypeDef USB_DeactivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  303. {
  304. if (ep->doublebuffer == 0U)
  305. {
  306. if (ep->is_in != 0U)
  307. {
  308. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  309. /* Configure DISABLE status for the Endpoint */
  310. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  311. }
  312. else
  313. {
  314. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  315. /* Configure DISABLE status for the Endpoint */
  316. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  317. }
  318. }
  319. #if (USE_USB_DOUBLE_BUFFER == 1U)
  320. /* Double Buffer */
  321. else
  322. {
  323. if (ep->is_in == 0U)
  324. {
  325. /* Clear the data toggle bits for the endpoint IN/OUT*/
  326. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  327. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  328. /* Reset value of the data toggle bits for the endpoint out*/
  329. PCD_TX_DTOG(USBx, ep->num);
  330. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  331. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  332. }
  333. else
  334. {
  335. /* Clear the data toggle bits for the endpoint IN/OUT*/
  336. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  337. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  338. PCD_RX_DTOG(USBx, ep->num);
  339. /* Configure DISABLE status for the Endpoint*/
  340. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  341. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  342. }
  343. }
  344. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  345. return HAL_OK;
  346. }
  347. /**
  348. * @brief USB_EPStartXfer setup and starts a transfer over an EP
  349. * @param USBx Selected device
  350. * @param ep pointer to endpoint structure
  351. * @retval HAL status
  352. */
  353. HAL_StatusTypeDef USB_EPStartXfer(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  354. {
  355. uint32_t len;
  356. #if (USE_USB_DOUBLE_BUFFER == 1U)
  357. uint16_t pmabuffer;
  358. uint16_t wEPVal;
  359. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  360. /* IN endpoint */
  361. if (ep->is_in == 1U)
  362. {
  363. /*Multi packet transfer*/
  364. if (ep->xfer_len > ep->maxpacket)
  365. {
  366. len = ep->maxpacket;
  367. }
  368. else
  369. {
  370. len = ep->xfer_len;
  371. }
  372. /* configure and validate Tx endpoint */
  373. if (ep->doublebuffer == 0U)
  374. {
  375. USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, (uint16_t)len);
  376. PCD_SET_EP_TX_CNT(USBx, ep->num, len);
  377. }
  378. #if (USE_USB_DOUBLE_BUFFER == 1U)
  379. else
  380. {
  381. /* double buffer bulk management */
  382. if (ep->type == EP_TYPE_BULK)
  383. {
  384. if (ep->xfer_len_db > ep->maxpacket)
  385. {
  386. /* enable double buffer */
  387. PCD_SET_BULK_EP_DBUF(USBx, ep->num);
  388. /* each Time to write in PMA xfer_len_db will */
  389. ep->xfer_len_db -= len;
  390. /* Fill the two first buffer in the Buffer0 & Buffer1 */
  391. if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
  392. {
  393. /* Set the Double buffer counter for pmabuffer1 */
  394. PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
  395. pmabuffer = ep->pmaaddr1;
  396. /* Write the user buffer to USB PMA */
  397. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  398. ep->xfer_buff += len;
  399. if (ep->xfer_len_db > ep->maxpacket)
  400. {
  401. ep->xfer_len_db -= len;
  402. }
  403. else
  404. {
  405. len = ep->xfer_len_db;
  406. ep->xfer_len_db = 0U;
  407. }
  408. /* Set the Double buffer counter for pmabuffer0 */
  409. PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
  410. pmabuffer = ep->pmaaddr0;
  411. /* Write the user buffer to USB PMA */
  412. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  413. }
  414. else
  415. {
  416. /* Set the Double buffer counter for pmabuffer0 */
  417. PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
  418. pmabuffer = ep->pmaaddr0;
  419. /* Write the user buffer to USB PMA */
  420. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  421. ep->xfer_buff += len;
  422. if (ep->xfer_len_db > ep->maxpacket)
  423. {
  424. ep->xfer_len_db -= len;
  425. }
  426. else
  427. {
  428. len = ep->xfer_len_db;
  429. ep->xfer_len_db = 0U;
  430. }
  431. /* Set the Double buffer counter for pmabuffer1 */
  432. PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
  433. pmabuffer = ep->pmaaddr1;
  434. /* Write the user buffer to USB PMA */
  435. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  436. }
  437. }
  438. /* auto Switch to single buffer mode when transfer <Mps no need to manage in double buffer */
  439. else
  440. {
  441. len = ep->xfer_len_db;
  442. /* disable double buffer mode for Bulk endpoint */
  443. PCD_CLEAR_BULK_EP_DBUF(USBx, ep->num);
  444. /* Set Tx count with nbre of byte to be transmitted */
  445. PCD_SET_EP_TX_CNT(USBx, ep->num, len);
  446. pmabuffer = ep->pmaaddr0;
  447. /* Write the user buffer to USB PMA */
  448. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  449. }
  450. }
  451. else /* manage isochronous double buffer IN mode */
  452. {
  453. /* each Time to write in PMA xfer_len_db will */
  454. ep->xfer_len_db -= len;
  455. /* Fill the data buffer */
  456. if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
  457. {
  458. /* Set the Double buffer counter for pmabuffer1 */
  459. PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
  460. pmabuffer = ep->pmaaddr1;
  461. /* Write the user buffer to USB PMA */
  462. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  463. }
  464. else
  465. {
  466. /* Set the Double buffer counter for pmabuffer0 */
  467. PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
  468. pmabuffer = ep->pmaaddr0;
  469. /* Write the user buffer to USB PMA */
  470. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  471. }
  472. }
  473. }
  474. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  475. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID);
  476. }
  477. else /* OUT endpoint */
  478. {
  479. if (ep->doublebuffer == 0U)
  480. {
  481. /* Multi packet transfer */
  482. if (ep->xfer_len > ep->maxpacket)
  483. {
  484. len = ep->maxpacket;
  485. ep->xfer_len -= len;
  486. }
  487. else
  488. {
  489. len = ep->xfer_len;
  490. ep->xfer_len = 0U;
  491. }
  492. /* configure and validate Rx endpoint */
  493. PCD_SET_EP_RX_CNT(USBx, ep->num, len);
  494. }
  495. #if (USE_USB_DOUBLE_BUFFER == 1U)
  496. else
  497. {
  498. /* First Transfer Coming From HAL_PCD_EP_Receive & From ISR */
  499. /* Set the Double buffer counter */
  500. if (ep->type == EP_TYPE_BULK)
  501. {
  502. PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, ep->maxpacket);
  503. /* Coming from ISR */
  504. if (ep->xfer_count != 0U)
  505. {
  506. /* update last value to check if there is blocking state */
  507. wEPVal = PCD_GET_ENDPOINT(USBx, ep->num);
  508. /*Blocking State */
  509. if ((((wEPVal & USB_EP_DTOG_RX) != 0U) && ((wEPVal & USB_EP_DTOG_TX) != 0U)) ||
  510. (((wEPVal & USB_EP_DTOG_RX) == 0U) && ((wEPVal & USB_EP_DTOG_TX) == 0U)))
  511. {
  512. PCD_FREE_USER_BUFFER(USBx, ep->num, 0U);
  513. }
  514. }
  515. }
  516. /* iso out double */
  517. else if (ep->type == EP_TYPE_ISOC)
  518. {
  519. /* Multi packet transfer */
  520. if (ep->xfer_len > ep->maxpacket)
  521. {
  522. len = ep->maxpacket;
  523. ep->xfer_len -= len;
  524. }
  525. else
  526. {
  527. len = ep->xfer_len;
  528. ep->xfer_len = 0U;
  529. }
  530. PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, len);
  531. }
  532. else
  533. {
  534. return HAL_ERROR;
  535. }
  536. }
  537. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  538. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
  539. }
  540. return HAL_OK;
  541. }
  542. /**
  543. * @brief USB_EPSetStall set a stall condition over an EP
  544. * @param USBx Selected device
  545. * @param ep pointer to endpoint structure
  546. * @retval HAL status
  547. */
  548. HAL_StatusTypeDef USB_EPSetStall(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  549. {
  550. if (ep->is_in != 0U)
  551. {
  552. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_STALL);
  553. }
  554. else
  555. {
  556. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_STALL);
  557. }
  558. return HAL_OK;
  559. }
  560. /**
  561. * @brief USB_EPClearStall Clear a stall condition over an EP
  562. * @param USBx Selected device
  563. * @param ep pointer to endpoint structure
  564. * @retval HAL status
  565. */
  566. HAL_StatusTypeDef USB_EPClearStall(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  567. {
  568. if (ep->doublebuffer == 0U)
  569. {
  570. if (ep->is_in != 0U)
  571. {
  572. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  573. if (ep->type != EP_TYPE_ISOC)
  574. {
  575. /* Configure NAK status for the Endpoint */
  576. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
  577. }
  578. }
  579. else
  580. {
  581. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  582. /* Configure VALID status for the Endpoint */
  583. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
  584. }
  585. }
  586. return HAL_OK;
  587. }
  588. /**
  589. * @brief USB_EPStoptXfer Stop transfer on an EP
  590. * @param USBx usb device instance
  591. * @param ep pointer to endpoint structure
  592. * @retval HAL status
  593. */
  594. HAL_StatusTypeDef USB_EPStopXfer(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  595. {
  596. /* IN endpoint */
  597. if (ep->is_in == 1U)
  598. {
  599. if (ep->doublebuffer == 0U)
  600. {
  601. if (ep->type != EP_TYPE_ISOC)
  602. {
  603. /* Configure NAK status for the Endpoint */
  604. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
  605. }
  606. else
  607. {
  608. /* Configure TX Endpoint to disabled state */
  609. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  610. }
  611. }
  612. }
  613. else /* OUT endpoint */
  614. {
  615. if (ep->doublebuffer == 0U)
  616. {
  617. if (ep->type != EP_TYPE_ISOC)
  618. {
  619. /* Configure NAK status for the Endpoint */
  620. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
  621. }
  622. else
  623. {
  624. /* Configure RX Endpoint to disabled state */
  625. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  626. }
  627. }
  628. }
  629. return HAL_OK;
  630. }
  631. #endif /* defined (HAL_PCD_MODULE_ENABLED) */
  632. /**
  633. * @brief USB_StopDevice Stop the usb device mode
  634. * @param USBx Selected device
  635. * @retval HAL status
  636. */
  637. HAL_StatusTypeDef USB_StopDevice(USB_TypeDef *USBx)
  638. {
  639. /* disable all interrupts and force USB reset */
  640. USBx->CNTR = (uint16_t)USB_CNTR_FRES;
  641. /* clear interrupt status register */
  642. USBx->ISTR = 0U;
  643. /* switch-off device */
  644. USBx->CNTR = (uint16_t)(USB_CNTR_FRES | USB_CNTR_PDWN);
  645. return HAL_OK;
  646. }
  647. /**
  648. * @brief USB_SetDevAddress Stop the usb device mode
  649. * @param USBx Selected device
  650. * @param address new device address to be assigned
  651. * This parameter can be a value from 0 to 255
  652. * @retval HAL status
  653. */
  654. HAL_StatusTypeDef USB_SetDevAddress(USB_TypeDef *USBx, uint8_t address)
  655. {
  656. if (address == 0U)
  657. {
  658. /* set device address and enable function */
  659. USBx->DADDR = (uint16_t)USB_DADDR_EF;
  660. }
  661. return HAL_OK;
  662. }
  663. /**
  664. * @brief USB_DevConnect Connect the USB device by enabling the pull-up/pull-down
  665. * @param USBx Selected device
  666. * @retval HAL status
  667. */
  668. HAL_StatusTypeDef USB_DevConnect(USB_TypeDef *USBx)
  669. {
  670. /* Prevent unused argument(s) compilation warning */
  671. UNUSED(USBx);
  672. /* NOTE : - This function is not required by USB Device FS peripheral, it is used
  673. only by USB OTG FS peripheral.
  674. - This function is added to ensure compatibility across platforms.
  675. */
  676. return HAL_OK;
  677. }
  678. /**
  679. * @brief USB_DevDisconnect Disconnect the USB device by disabling the pull-up/pull-down
  680. * @param USBx Selected device
  681. * @retval HAL status
  682. */
  683. HAL_StatusTypeDef USB_DevDisconnect(USB_TypeDef *USBx)
  684. {
  685. /* Prevent unused argument(s) compilation warning */
  686. UNUSED(USBx);
  687. /* NOTE : - This function is not required by USB Device FS peripheral, it is used
  688. only by USB OTG FS peripheral.
  689. - This function is added to ensure compatibility across platforms.
  690. */
  691. return HAL_OK;
  692. }
  693. /**
  694. * @brief USB_ReadInterrupts return the global USB interrupt status
  695. * @param USBx Selected device
  696. * @retval USB Global Interrupt status
  697. */
  698. uint32_t USB_ReadInterrupts(USB_TypeDef const *USBx)
  699. {
  700. uint32_t tmpreg;
  701. tmpreg = USBx->ISTR;
  702. return tmpreg;
  703. }
  704. /**
  705. * @brief USB_ActivateRemoteWakeup : active remote wakeup signalling
  706. * @param USBx Selected device
  707. * @retval HAL status
  708. */
  709. HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_TypeDef *USBx)
  710. {
  711. USBx->CNTR |= (uint16_t)USB_CNTR_RESUME;
  712. return HAL_OK;
  713. }
  714. /**
  715. * @brief USB_DeActivateRemoteWakeup de-active remote wakeup signalling
  716. * @param USBx Selected device
  717. * @retval HAL status
  718. */
  719. HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_TypeDef *USBx)
  720. {
  721. USBx->CNTR &= (uint16_t)(~USB_CNTR_RESUME);
  722. return HAL_OK;
  723. }
  724. /**
  725. * @brief Copy a buffer from user memory area to packet memory area (PMA)
  726. * @param USBx USB peripheral instance register address.
  727. * @param pbUsrBuf pointer to user memory area.
  728. * @param wPMABufAddr address into PMA.
  729. * @param wNBytes no. of bytes to be copied.
  730. * @retval None
  731. */
  732. void USB_WritePMA(USB_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
  733. {
  734. uint32_t n = ((uint32_t)wNBytes + 1U) >> 1;
  735. uint32_t BaseAddr = (uint32_t)USBx;
  736. uint32_t count;
  737. uint16_t WrVal;
  738. __IO uint16_t *pdwVal;
  739. uint8_t *pBuf = pbUsrBuf;
  740. pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
  741. for (count = n; count != 0U; count--)
  742. {
  743. WrVal = pBuf[0];
  744. WrVal |= (uint16_t)pBuf[1] << 8;
  745. *pdwVal = (WrVal & 0xFFFFU);
  746. pdwVal++;
  747. #if PMA_ACCESS > 1U
  748. pdwVal++;
  749. #endif /* PMA_ACCESS */
  750. pBuf++;
  751. pBuf++;
  752. }
  753. }
  754. /**
  755. * @brief Copy data from packet memory area (PMA) to user memory buffer
  756. * @param USBx USB peripheral instance register address.
  757. * @param pbUsrBuf pointer to user memory area.
  758. * @param wPMABufAddr address into PMA.
  759. * @param wNBytes no. of bytes to be copied.
  760. * @retval None
  761. */
  762. void USB_ReadPMA(USB_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
  763. {
  764. uint32_t n = (uint32_t)wNBytes >> 1;
  765. uint32_t BaseAddr = (uint32_t)USBx;
  766. uint32_t count;
  767. uint32_t RdVal;
  768. __IO uint16_t *pdwVal;
  769. uint8_t *pBuf = pbUsrBuf;
  770. pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
  771. for (count = n; count != 0U; count--)
  772. {
  773. RdVal = *(__IO uint16_t *)pdwVal;
  774. pdwVal++;
  775. *pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
  776. pBuf++;
  777. *pBuf = (uint8_t)((RdVal >> 8) & 0xFFU);
  778. pBuf++;
  779. #if PMA_ACCESS > 1U
  780. pdwVal++;
  781. #endif /* PMA_ACCESS */
  782. }
  783. if ((wNBytes % 2U) != 0U)
  784. {
  785. RdVal = *pdwVal;
  786. *pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
  787. }
  788. }
  789. /**
  790. * @}
  791. */
  792. /**
  793. * @}
  794. */
  795. #endif /* defined (USB) */
  796. #endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
  797. /**
  798. * @}
  799. */