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