stm32l5xx_ll_usb.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  1. /**
  2. ******************************************************************************
  3. * @file stm32l5xx_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 "stm32l5xx_hal.h"
  38. /** @addtogroup STM32L5xx_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. #if defined (HAL_PCD_MODULE_ENABLED)
  148. /**
  149. * @brief Activate and configure an endpoint
  150. * @param USBx Selected device
  151. * @param ep pointer to endpoint structure
  152. * @retval HAL status
  153. */
  154. HAL_StatusTypeDef USB_ActivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  155. {
  156. HAL_StatusTypeDef ret = HAL_OK;
  157. uint16_t wEpRegVal;
  158. wEpRegVal = PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_T_MASK;
  159. /* initialize Endpoint */
  160. switch (ep->type)
  161. {
  162. case EP_TYPE_CTRL:
  163. wEpRegVal |= USB_EP_CONTROL;
  164. break;
  165. case EP_TYPE_BULK:
  166. wEpRegVal |= USB_EP_BULK;
  167. break;
  168. case EP_TYPE_INTR:
  169. wEpRegVal |= USB_EP_INTERRUPT;
  170. break;
  171. case EP_TYPE_ISOC:
  172. wEpRegVal |= USB_EP_ISOCHRONOUS;
  173. break;
  174. default:
  175. ret = HAL_ERROR;
  176. break;
  177. }
  178. PCD_SET_ENDPOINT(USBx, ep->num, (wEpRegVal | USB_EP_CTR_RX | USB_EP_CTR_TX));
  179. PCD_SET_EP_ADDRESS(USBx, ep->num, ep->num);
  180. if (ep->doublebuffer == 0U)
  181. {
  182. if (ep->is_in != 0U)
  183. {
  184. /*Set the endpoint Transmit buffer address */
  185. PCD_SET_EP_TX_ADDRESS(USBx, ep->num, ep->pmaadress);
  186. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  187. if (ep->type != EP_TYPE_ISOC)
  188. {
  189. /* Configure NAK status for the Endpoint */
  190. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
  191. }
  192. else
  193. {
  194. /* Configure TX Endpoint to disabled state */
  195. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  196. }
  197. }
  198. else
  199. {
  200. /* Set the endpoint Receive buffer address */
  201. PCD_SET_EP_RX_ADDRESS(USBx, ep->num, ep->pmaadress);
  202. /* Set the endpoint Receive buffer counter */
  203. PCD_SET_EP_RX_CNT(USBx, ep->num, ep->maxpacket);
  204. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  205. if (ep->num == 0U)
  206. {
  207. /* Configure VALID status for EP0 */
  208. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
  209. }
  210. else
  211. {
  212. /* Configure NAK status for OUT Endpoint */
  213. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
  214. }
  215. }
  216. }
  217. #if (USE_USB_DOUBLE_BUFFER == 1U)
  218. /* Double Buffer */
  219. else
  220. {
  221. if (ep->type == EP_TYPE_BULK)
  222. {
  223. /* Set bulk endpoint as double buffered */
  224. PCD_SET_BULK_EP_DBUF(USBx, ep->num);
  225. }
  226. else
  227. {
  228. /* Set the ISOC endpoint in double buffer mode */
  229. PCD_CLEAR_EP_KIND(USBx, ep->num);
  230. }
  231. /* Set buffer address for double buffered mode */
  232. PCD_SET_EP_DBUF_ADDR(USBx, ep->num, ep->pmaaddr0, ep->pmaaddr1);
  233. if (ep->is_in == 0U)
  234. {
  235. /* Clear the data toggle bits for the endpoint IN/OUT */
  236. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  237. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  238. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
  239. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  240. }
  241. else
  242. {
  243. /* Clear the data toggle bits for the endpoint IN/OUT */
  244. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  245. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  246. if (ep->type != EP_TYPE_ISOC)
  247. {
  248. /* Configure NAK status for the Endpoint */
  249. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
  250. }
  251. else
  252. {
  253. /* Configure TX Endpoint to disabled state */
  254. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  255. }
  256. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  257. }
  258. }
  259. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  260. return ret;
  261. }
  262. /**
  263. * @brief De-activate and de-initialize an endpoint
  264. * @param USBx Selected device
  265. * @param ep pointer to endpoint structure
  266. * @retval HAL status
  267. */
  268. HAL_StatusTypeDef USB_DeactivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  269. {
  270. if (ep->doublebuffer == 0U)
  271. {
  272. if (ep->is_in != 0U)
  273. {
  274. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  275. /* Configure DISABLE status for the Endpoint */
  276. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  277. }
  278. else
  279. {
  280. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  281. /* Configure DISABLE status for the Endpoint */
  282. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  283. }
  284. }
  285. #if (USE_USB_DOUBLE_BUFFER == 1U)
  286. /* Double Buffer */
  287. else
  288. {
  289. if (ep->is_in == 0U)
  290. {
  291. /* Clear the data toggle bits for the endpoint IN/OUT*/
  292. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  293. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  294. /* Reset value of the data toggle bits for the endpoint out*/
  295. PCD_TX_DTOG(USBx, ep->num);
  296. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  297. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  298. }
  299. else
  300. {
  301. /* Clear the data toggle bits for the endpoint IN/OUT*/
  302. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  303. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  304. PCD_RX_DTOG(USBx, ep->num);
  305. /* Configure DISABLE status for the Endpoint*/
  306. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  307. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  308. }
  309. }
  310. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  311. return HAL_OK;
  312. }
  313. /**
  314. * @brief USB_EPStartXfer setup and starts a transfer over an EP
  315. * @param USBx Selected device
  316. * @param ep pointer to endpoint structure
  317. * @retval HAL status
  318. */
  319. HAL_StatusTypeDef USB_EPStartXfer(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  320. {
  321. uint32_t len;
  322. #if (USE_USB_DOUBLE_BUFFER == 1U)
  323. uint16_t pmabuffer;
  324. uint16_t wEPVal;
  325. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  326. /* IN endpoint */
  327. if (ep->is_in == 1U)
  328. {
  329. /*Multi packet transfer*/
  330. if (ep->xfer_len > ep->maxpacket)
  331. {
  332. len = ep->maxpacket;
  333. }
  334. else
  335. {
  336. len = ep->xfer_len;
  337. }
  338. /* configure and validate Tx endpoint */
  339. if (ep->doublebuffer == 0U)
  340. {
  341. USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, (uint16_t)len);
  342. PCD_SET_EP_TX_CNT(USBx, ep->num, len);
  343. }
  344. #if (USE_USB_DOUBLE_BUFFER == 1U)
  345. else
  346. {
  347. /* double buffer bulk management */
  348. if (ep->type == EP_TYPE_BULK)
  349. {
  350. if (ep->xfer_len_db > ep->maxpacket)
  351. {
  352. /* enable double buffer */
  353. PCD_SET_BULK_EP_DBUF(USBx, ep->num);
  354. /* each Time to write in PMA xfer_len_db will */
  355. ep->xfer_len_db -= len;
  356. /* Fill the two first buffer in the Buffer0 & Buffer1 */
  357. if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
  358. {
  359. /* Set the Double buffer counter for pmabuffer1 */
  360. PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
  361. pmabuffer = ep->pmaaddr1;
  362. /* Write the user buffer to USB PMA */
  363. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  364. ep->xfer_buff += len;
  365. if (ep->xfer_len_db > ep->maxpacket)
  366. {
  367. ep->xfer_len_db -= len;
  368. }
  369. else
  370. {
  371. len = ep->xfer_len_db;
  372. ep->xfer_len_db = 0U;
  373. }
  374. /* Set the Double buffer counter for pmabuffer0 */
  375. PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
  376. pmabuffer = ep->pmaaddr0;
  377. /* Write the user buffer to USB PMA */
  378. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  379. }
  380. else
  381. {
  382. /* Set the Double buffer counter for pmabuffer0 */
  383. PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
  384. pmabuffer = ep->pmaaddr0;
  385. /* Write the user buffer to USB PMA */
  386. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  387. ep->xfer_buff += len;
  388. if (ep->xfer_len_db > ep->maxpacket)
  389. {
  390. ep->xfer_len_db -= len;
  391. }
  392. else
  393. {
  394. len = ep->xfer_len_db;
  395. ep->xfer_len_db = 0U;
  396. }
  397. /* Set the Double buffer counter for pmabuffer1 */
  398. PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
  399. pmabuffer = ep->pmaaddr1;
  400. /* Write the user buffer to USB PMA */
  401. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  402. }
  403. }
  404. /* auto Switch to single buffer mode when transfer <Mps no need to manage in double buffer */
  405. else
  406. {
  407. len = ep->xfer_len_db;
  408. /* disable double buffer mode for Bulk endpoint */
  409. PCD_CLEAR_BULK_EP_DBUF(USBx, ep->num);
  410. /* Set Tx count with nbre of byte to be transmitted */
  411. PCD_SET_EP_TX_CNT(USBx, ep->num, len);
  412. pmabuffer = ep->pmaaddr0;
  413. /* Write the user buffer to USB PMA */
  414. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  415. }
  416. }
  417. else /* manage isochronous double buffer IN mode */
  418. {
  419. /* each Time to write in PMA xfer_len_db will */
  420. ep->xfer_len_db -= len;
  421. /* Fill the data buffer */
  422. if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
  423. {
  424. /* Set the Double buffer counter for pmabuffer1 */
  425. PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
  426. pmabuffer = ep->pmaaddr1;
  427. /* Write the user buffer to USB PMA */
  428. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  429. }
  430. else
  431. {
  432. /* Set the Double buffer counter for pmabuffer0 */
  433. PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
  434. pmabuffer = ep->pmaaddr0;
  435. /* Write the user buffer to USB PMA */
  436. USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
  437. }
  438. }
  439. }
  440. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  441. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID);
  442. }
  443. else /* OUT endpoint */
  444. {
  445. if (ep->doublebuffer == 0U)
  446. {
  447. /* Multi packet transfer */
  448. if (ep->xfer_len > ep->maxpacket)
  449. {
  450. len = ep->maxpacket;
  451. ep->xfer_len -= len;
  452. }
  453. else
  454. {
  455. len = ep->xfer_len;
  456. ep->xfer_len = 0U;
  457. }
  458. /* configure and validate Rx endpoint */
  459. PCD_SET_EP_RX_CNT(USBx, ep->num, len);
  460. }
  461. #if (USE_USB_DOUBLE_BUFFER == 1U)
  462. else
  463. {
  464. /* First Transfer Coming From HAL_PCD_EP_Receive & From ISR */
  465. /* Set the Double buffer counter */
  466. if (ep->type == EP_TYPE_BULK)
  467. {
  468. PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, ep->maxpacket);
  469. /* Coming from ISR */
  470. if (ep->xfer_count != 0U)
  471. {
  472. /* update last value to check if there is blocking state */
  473. wEPVal = PCD_GET_ENDPOINT(USBx, ep->num);
  474. /*Blocking State */
  475. if ((((wEPVal & USB_EP_DTOG_RX) != 0U) && ((wEPVal & USB_EP_DTOG_TX) != 0U)) ||
  476. (((wEPVal & USB_EP_DTOG_RX) == 0U) && ((wEPVal & USB_EP_DTOG_TX) == 0U)))
  477. {
  478. PCD_FREE_USER_BUFFER(USBx, ep->num, 0U);
  479. }
  480. }
  481. }
  482. /* iso out double */
  483. else if (ep->type == EP_TYPE_ISOC)
  484. {
  485. /* Multi packet transfer */
  486. if (ep->xfer_len > ep->maxpacket)
  487. {
  488. len = ep->maxpacket;
  489. ep->xfer_len -= len;
  490. }
  491. else
  492. {
  493. len = ep->xfer_len;
  494. ep->xfer_len = 0U;
  495. }
  496. PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, len);
  497. }
  498. else
  499. {
  500. return HAL_ERROR;
  501. }
  502. }
  503. #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
  504. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
  505. }
  506. return HAL_OK;
  507. }
  508. /**
  509. * @brief USB_EPSetStall set a stall condition over an EP
  510. * @param USBx Selected device
  511. * @param ep pointer to endpoint structure
  512. * @retval HAL status
  513. */
  514. HAL_StatusTypeDef USB_EPSetStall(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  515. {
  516. if (ep->is_in != 0U)
  517. {
  518. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_STALL);
  519. }
  520. else
  521. {
  522. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_STALL);
  523. }
  524. return HAL_OK;
  525. }
  526. /**
  527. * @brief USB_EPClearStall Clear a stall condition over an EP
  528. * @param USBx Selected device
  529. * @param ep pointer to endpoint structure
  530. * @retval HAL status
  531. */
  532. HAL_StatusTypeDef USB_EPClearStall(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  533. {
  534. if (ep->doublebuffer == 0U)
  535. {
  536. if (ep->is_in != 0U)
  537. {
  538. PCD_CLEAR_TX_DTOG(USBx, ep->num);
  539. if (ep->type != EP_TYPE_ISOC)
  540. {
  541. /* Configure NAK status for the Endpoint */
  542. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
  543. }
  544. }
  545. else
  546. {
  547. PCD_CLEAR_RX_DTOG(USBx, ep->num);
  548. /* Configure VALID status for the Endpoint */
  549. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
  550. }
  551. }
  552. return HAL_OK;
  553. }
  554. /**
  555. * @brief USB_EPStoptXfer Stop transfer on an EP
  556. * @param USBx usb device instance
  557. * @param ep pointer to endpoint structure
  558. * @retval HAL status
  559. */
  560. HAL_StatusTypeDef USB_EPStopXfer(USB_TypeDef *USBx, USB_EPTypeDef *ep)
  561. {
  562. /* IN endpoint */
  563. if (ep->is_in == 1U)
  564. {
  565. if (ep->doublebuffer == 0U)
  566. {
  567. if (ep->type != EP_TYPE_ISOC)
  568. {
  569. /* Configure NAK status for the Endpoint */
  570. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
  571. }
  572. else
  573. {
  574. /* Configure TX Endpoint to disabled state */
  575. PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
  576. }
  577. }
  578. }
  579. else /* OUT endpoint */
  580. {
  581. if (ep->doublebuffer == 0U)
  582. {
  583. if (ep->type != EP_TYPE_ISOC)
  584. {
  585. /* Configure NAK status for the Endpoint */
  586. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
  587. }
  588. else
  589. {
  590. /* Configure RX Endpoint to disabled state */
  591. PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
  592. }
  593. }
  594. }
  595. return HAL_OK;
  596. }
  597. #endif /* defined (HAL_PCD_MODULE_ENABLED) */
  598. /**
  599. * @brief USB_StopDevice Stop the usb device mode
  600. * @param USBx Selected device
  601. * @retval HAL status
  602. */
  603. HAL_StatusTypeDef USB_StopDevice(USB_TypeDef *USBx)
  604. {
  605. /* disable all interrupts and force USB reset */
  606. USBx->CNTR = (uint16_t)USB_CNTR_FRES;
  607. /* clear interrupt status register */
  608. USBx->ISTR = 0U;
  609. /* switch-off device */
  610. USBx->CNTR = (uint16_t)(USB_CNTR_FRES | USB_CNTR_PDWN);
  611. return HAL_OK;
  612. }
  613. /**
  614. * @brief USB_SetDevAddress Stop the usb device mode
  615. * @param USBx Selected device
  616. * @param address new device address to be assigned
  617. * This parameter can be a value from 0 to 255
  618. * @retval HAL status
  619. */
  620. HAL_StatusTypeDef USB_SetDevAddress(USB_TypeDef *USBx, uint8_t address)
  621. {
  622. if (address == 0U)
  623. {
  624. /* set device address and enable function */
  625. USBx->DADDR = (uint16_t)USB_DADDR_EF;
  626. }
  627. return HAL_OK;
  628. }
  629. /**
  630. * @brief USB_DevConnect Connect the USB device by enabling the pull-up/pull-down
  631. * @param USBx Selected device
  632. * @retval HAL status
  633. */
  634. HAL_StatusTypeDef USB_DevConnect(USB_TypeDef *USBx)
  635. {
  636. /* Enabling DP Pull-UP bit to Connect internal PU resistor on USB DP line */
  637. USBx->BCDR |= (uint16_t)USB_BCDR_DPPU;
  638. return HAL_OK;
  639. }
  640. /**
  641. * @brief USB_DevDisconnect Disconnect the USB device by disabling the pull-up/pull-down
  642. * @param USBx Selected device
  643. * @retval HAL status
  644. */
  645. HAL_StatusTypeDef USB_DevDisconnect(USB_TypeDef *USBx)
  646. {
  647. /* Disable DP Pull-Up bit to disconnect the Internal PU resistor on USB DP line */
  648. USBx->BCDR &= (uint16_t)(~(USB_BCDR_DPPU));
  649. return HAL_OK;
  650. }
  651. /**
  652. * @brief USB_ReadInterrupts return the global USB interrupt status
  653. * @param USBx Selected device
  654. * @retval USB Global Interrupt status
  655. */
  656. uint32_t USB_ReadInterrupts(USB_TypeDef *USBx)
  657. {
  658. uint32_t tmpreg;
  659. tmpreg = USBx->ISTR;
  660. return tmpreg;
  661. }
  662. /**
  663. * @brief USB_ActivateRemoteWakeup : active remote wakeup signalling
  664. * @param USBx Selected device
  665. * @retval HAL status
  666. */
  667. HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_TypeDef *USBx)
  668. {
  669. USBx->CNTR |= (uint16_t)USB_CNTR_RESUME;
  670. return HAL_OK;
  671. }
  672. /**
  673. * @brief USB_DeActivateRemoteWakeup de-active remote wakeup signalling
  674. * @param USBx Selected device
  675. * @retval HAL status
  676. */
  677. HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_TypeDef *USBx)
  678. {
  679. USBx->CNTR &= (uint16_t)(~USB_CNTR_RESUME);
  680. return HAL_OK;
  681. }
  682. /**
  683. * @brief Copy a buffer from user memory area to packet memory area (PMA)
  684. * @param USBx USB peripheral instance register address.
  685. * @param pbUsrBuf pointer to user memory area.
  686. * @param wPMABufAddr address into PMA.
  687. * @param wNBytes no. of bytes to be copied.
  688. * @retval None
  689. */
  690. void USB_WritePMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
  691. {
  692. uint32_t n = ((uint32_t)wNBytes + 1U) >> 1;
  693. uint32_t BaseAddr = (uint32_t)USBx;
  694. uint32_t count;
  695. uint16_t WrVal;
  696. __IO uint16_t *pdwVal;
  697. uint8_t *pBuf = pbUsrBuf;
  698. pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
  699. for (count = n; count != 0U; count--)
  700. {
  701. WrVal = pBuf[0];
  702. WrVal |= (uint16_t)pBuf[1] << 8;
  703. *pdwVal = (WrVal & 0xFFFFU);
  704. pdwVal++;
  705. #if PMA_ACCESS > 1U
  706. pdwVal++;
  707. #endif /* PMA_ACCESS */
  708. pBuf++;
  709. pBuf++;
  710. }
  711. }
  712. /**
  713. * @brief Copy data from packet memory area (PMA) to user memory buffer
  714. * @param USBx USB peripheral instance register address.
  715. * @param pbUsrBuf pointer to user memory area.
  716. * @param wPMABufAddr address into PMA.
  717. * @param wNBytes no. of bytes to be copied.
  718. * @retval None
  719. */
  720. void USB_ReadPMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
  721. {
  722. uint32_t n = (uint32_t)wNBytes >> 1;
  723. uint32_t BaseAddr = (uint32_t)USBx;
  724. uint32_t count;
  725. uint32_t RdVal;
  726. __IO uint16_t *pdwVal;
  727. uint8_t *pBuf = pbUsrBuf;
  728. pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
  729. for (count = n; count != 0U; count--)
  730. {
  731. RdVal = *(__IO uint16_t *)pdwVal;
  732. pdwVal++;
  733. *pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
  734. pBuf++;
  735. *pBuf = (uint8_t)((RdVal >> 8) & 0xFFU);
  736. pBuf++;
  737. #if PMA_ACCESS > 1U
  738. pdwVal++;
  739. #endif /* PMA_ACCESS */
  740. }
  741. if ((wNBytes % 2U) != 0U)
  742. {
  743. RdVal = *pdwVal;
  744. *pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
  745. }
  746. }
  747. /**
  748. * @}
  749. */
  750. /**
  751. * @}
  752. */
  753. #endif /* defined (USB) */
  754. #endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
  755. /**
  756. * @}
  757. */