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