stm32l1xx_hal_pcd.c 43 KB

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