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_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 /**
176   * @brief  USB_FlushTxFifo : Flush a Tx FIFO
177   * @param  USBx : Selected device
178   * @param  num : FIFO number
179   *         This parameter can be a value from 1 to 15
180             15 means Flush all Tx FIFOs
181   * @retval HAL status
182   */
USB_FlushTxFifo(USB_TypeDef const * USBx,uint32_t num)183 HAL_StatusTypeDef USB_FlushTxFifo(USB_TypeDef const *USBx, uint32_t num)
184 {
185   /* Prevent unused argument(s) compilation warning */
186   UNUSED(USBx);
187   UNUSED(num);
188 
189   /* NOTE : - This function is not required by USB Device FS peripheral, it is used
190               only by USB OTG FS peripheral.
191             - This function is added to ensure compatibility across platforms.
192    */
193 
194   return HAL_OK;
195 }
196 
197 /**
198   * @brief  USB_FlushRxFifo : Flush Rx FIFO
199   * @param  USBx : Selected device
200   * @retval HAL status
201   */
USB_FlushRxFifo(USB_TypeDef const * USBx)202 HAL_StatusTypeDef USB_FlushRxFifo(USB_TypeDef const *USBx)
203 {
204   /* Prevent unused argument(s) compilation warning */
205   UNUSED(USBx);
206 
207   /* NOTE : - This function is not required by USB Device FS peripheral, it is used
208               only by USB OTG FS peripheral.
209             - This function is added to ensure compatibility across platforms.
210    */
211 
212   return HAL_OK;
213 }
214 
215 
216 #if defined (HAL_PCD_MODULE_ENABLED)
217 /**
218   * @brief  Activate and configure an endpoint
219   * @param  USBx Selected device
220   * @param  ep pointer to endpoint structure
221   * @retval HAL status
222   */
USB_ActivateEndpoint(USB_TypeDef * USBx,USB_EPTypeDef * ep)223 HAL_StatusTypeDef USB_ActivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep)
224 {
225   HAL_StatusTypeDef ret = HAL_OK;
226   uint16_t wEpRegVal;
227 
228   wEpRegVal = PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_T_MASK;
229 
230   /* initialize Endpoint */
231   switch (ep->type)
232   {
233     case EP_TYPE_CTRL:
234       wEpRegVal |= USB_EP_CONTROL;
235       break;
236 
237     case EP_TYPE_BULK:
238       wEpRegVal |= USB_EP_BULK;
239       break;
240 
241     case EP_TYPE_INTR:
242       wEpRegVal |= USB_EP_INTERRUPT;
243       break;
244 
245     case EP_TYPE_ISOC:
246       wEpRegVal |= USB_EP_ISOCHRONOUS;
247       break;
248 
249     default:
250       ret = HAL_ERROR;
251       break;
252   }
253 
254   PCD_SET_ENDPOINT(USBx, ep->num, (wEpRegVal | USB_EP_CTR_RX | USB_EP_CTR_TX));
255 
256   PCD_SET_EP_ADDRESS(USBx, ep->num, ep->num);
257 
258   if (ep->doublebuffer == 0U)
259   {
260     if (ep->is_in != 0U)
261     {
262       /*Set the endpoint Transmit buffer address */
263       PCD_SET_EP_TX_ADDRESS(USBx, ep->num, ep->pmaadress);
264       PCD_CLEAR_TX_DTOG(USBx, ep->num);
265 
266       if (ep->type != EP_TYPE_ISOC)
267       {
268         /* Configure NAK status for the Endpoint */
269         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
270       }
271       else
272       {
273         /* Configure TX Endpoint to disabled state */
274         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
275       }
276     }
277     else
278     {
279       /* Set the endpoint Receive buffer address */
280       PCD_SET_EP_RX_ADDRESS(USBx, ep->num, ep->pmaadress);
281 
282       /* Set the endpoint Receive buffer counter */
283       PCD_SET_EP_RX_CNT(USBx, ep->num, ep->maxpacket);
284       PCD_CLEAR_RX_DTOG(USBx, ep->num);
285 
286       if (ep->num == 0U)
287       {
288         /* Configure VALID status for EP0 */
289         PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
290       }
291       else
292       {
293         /* Configure NAK status for OUT Endpoint */
294         PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
295       }
296     }
297   }
298 #if (USE_USB_DOUBLE_BUFFER == 1U)
299   /* Double Buffer */
300   else
301   {
302     if (ep->type == EP_TYPE_BULK)
303     {
304       /* Set bulk endpoint as double buffered */
305       PCD_SET_BULK_EP_DBUF(USBx, ep->num);
306     }
307     else
308     {
309       /* Set the ISOC endpoint in double buffer mode */
310       PCD_CLEAR_EP_KIND(USBx, ep->num);
311     }
312 
313     /* Set buffer address for double buffered mode */
314     PCD_SET_EP_DBUF_ADDR(USBx, ep->num, ep->pmaaddr0, ep->pmaaddr1);
315 
316     if (ep->is_in == 0U)
317     {
318       /* Clear the data toggle bits for the endpoint IN/OUT */
319       PCD_CLEAR_RX_DTOG(USBx, ep->num);
320       PCD_CLEAR_TX_DTOG(USBx, ep->num);
321 
322       /* Set endpoint RX count */
323       PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, ep->maxpacket);
324 
325       /* Set endpoint RX to valid state */
326       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
327       PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
328     }
329     else
330     {
331       /* Clear the data toggle bits for the endpoint IN/OUT */
332       PCD_CLEAR_RX_DTOG(USBx, ep->num);
333       PCD_CLEAR_TX_DTOG(USBx, ep->num);
334 
335       if (ep->type != EP_TYPE_ISOC)
336       {
337         /* Configure NAK status for the Endpoint */
338         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
339       }
340       else
341       {
342         /* Configure TX Endpoint to disabled state */
343         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
344       }
345 
346       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
347     }
348   }
349 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
350 
351   return ret;
352 }
353 
354 /**
355   * @brief  De-activate and de-initialize an endpoint
356   * @param  USBx Selected device
357   * @param  ep pointer to endpoint structure
358   * @retval HAL status
359   */
USB_DeactivateEndpoint(USB_TypeDef * USBx,USB_EPTypeDef * ep)360 HAL_StatusTypeDef USB_DeactivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep)
361 {
362   if (ep->doublebuffer == 0U)
363   {
364     if (ep->is_in != 0U)
365     {
366       PCD_CLEAR_TX_DTOG(USBx, ep->num);
367 
368       /* Configure DISABLE status for the Endpoint */
369       PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
370     }
371 
372     else
373     {
374       PCD_CLEAR_RX_DTOG(USBx, ep->num);
375 
376       /* Configure DISABLE status for the Endpoint */
377       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
378     }
379   }
380 #if (USE_USB_DOUBLE_BUFFER == 1U)
381   /* Double Buffer */
382   else
383   {
384     if (ep->is_in == 0U)
385     {
386       /* Clear the data toggle bits for the endpoint IN/OUT*/
387       PCD_CLEAR_RX_DTOG(USBx, ep->num);
388       PCD_CLEAR_TX_DTOG(USBx, ep->num);
389 
390       /* Reset value of the data toggle bits for the endpoint out*/
391       PCD_TX_DTOG(USBx, ep->num);
392 
393       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
394       PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
395     }
396     else
397     {
398       /* Clear the data toggle bits for the endpoint IN/OUT*/
399       PCD_CLEAR_RX_DTOG(USBx, ep->num);
400       PCD_CLEAR_TX_DTOG(USBx, ep->num);
401       PCD_RX_DTOG(USBx, ep->num);
402 
403       /* Configure DISABLE status for the Endpoint*/
404       PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
405       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
406     }
407   }
408 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
409 
410   return HAL_OK;
411 }
412 
413 /**
414   * @brief  USB_EPStartXfer setup and starts a transfer over an EP
415   * @param  USBx Selected device
416   * @param  ep pointer to endpoint structure
417   * @retval HAL status
418   */
USB_EPStartXfer(USB_TypeDef * USBx,USB_EPTypeDef * ep)419 HAL_StatusTypeDef USB_EPStartXfer(USB_TypeDef *USBx, USB_EPTypeDef *ep)
420 {
421   uint32_t len;
422 #if (USE_USB_DOUBLE_BUFFER == 1U)
423   uint16_t pmabuffer;
424   uint16_t wEPVal;
425 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
426 
427   /* IN endpoint */
428   if (ep->is_in == 1U)
429   {
430     /* Multi packet transfer */
431     if (ep->xfer_len > ep->maxpacket)
432     {
433       len = ep->maxpacket;
434     }
435     else
436     {
437       len = ep->xfer_len;
438     }
439 
440     /* configure and validate Tx endpoint */
441     if (ep->doublebuffer == 0U)
442     {
443       USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, (uint16_t)len);
444       PCD_SET_EP_TX_CNT(USBx, ep->num, len);
445     }
446 #if (USE_USB_DOUBLE_BUFFER == 1U)
447     else
448     {
449       /* double buffer bulk management */
450       if (ep->type == EP_TYPE_BULK)
451       {
452         if (ep->xfer_len_db > ep->maxpacket)
453         {
454           /* enable double buffer */
455           PCD_SET_BULK_EP_DBUF(USBx, ep->num);
456 
457           /* each Time to write in PMA xfer_len_db will */
458           ep->xfer_len_db -= len;
459 
460           /* Fill the two first buffer in the Buffer0 & Buffer1 */
461           if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
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             ep->xfer_buff += len;
470 
471             if (ep->xfer_len_db > ep->maxpacket)
472             {
473               ep->xfer_len_db -= len;
474             }
475             else
476             {
477               len = ep->xfer_len_db;
478               ep->xfer_len_db = 0U;
479             }
480 
481             /* Set the Double buffer counter for pmabuffer0 */
482             PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
483             pmabuffer = ep->pmaaddr0;
484 
485             /* Write the user buffer to USB PMA */
486             USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
487           }
488           else
489           {
490             /* Set the Double buffer counter for pmabuffer0 */
491             PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
492             pmabuffer = ep->pmaaddr0;
493 
494             /* Write the user buffer to USB PMA */
495             USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
496             ep->xfer_buff += len;
497 
498             if (ep->xfer_len_db > ep->maxpacket)
499             {
500               ep->xfer_len_db -= len;
501             }
502             else
503             {
504               len = ep->xfer_len_db;
505               ep->xfer_len_db = 0U;
506             }
507 
508             /* Set the Double buffer counter for pmabuffer1 */
509             PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
510             pmabuffer = ep->pmaaddr1;
511 
512             /* Write the user buffer to USB PMA */
513             USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
514           }
515         }
516         /* auto Switch to single buffer mode when transfer <Mps no need to manage in double buffer */
517         else
518         {
519           len = ep->xfer_len_db;
520 
521           /* disable double buffer mode for Bulk endpoint */
522           PCD_CLEAR_BULK_EP_DBUF(USBx, ep->num);
523 
524           /* Set Tx count with nbre of byte to be transmitted */
525           PCD_SET_EP_TX_CNT(USBx, ep->num, len);
526           pmabuffer = ep->pmaaddr0;
527 
528           /* Write the user buffer to USB PMA */
529           USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
530         }
531       }
532       else /* Manage isochronous double buffer IN mode */
533       {
534         /* Each Time to write in PMA xfer_len_db will */
535         ep->xfer_len_db -= len;
536 
537         /* Fill the data buffer */
538         if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
539         {
540           /* Set the Double buffer counter for pmabuffer1 */
541           PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
542           pmabuffer = ep->pmaaddr1;
543 
544           /* Write the user buffer to USB PMA */
545           USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
546         }
547         else
548         {
549           /* Set the Double buffer counter for pmabuffer0 */
550           PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
551           pmabuffer = ep->pmaaddr0;
552 
553           /* Write the user buffer to USB PMA */
554           USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
555         }
556       }
557     }
558 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
559 
560     PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID);
561   }
562   else /* OUT endpoint */
563   {
564     if (ep->doublebuffer == 0U)
565     {
566       if ((ep->xfer_len == 0U) && (ep->type == EP_TYPE_CTRL))
567       {
568         /* This is a status out stage set the OUT_STATUS */
569         PCD_SET_OUT_STATUS(USBx, ep->num);
570       }
571       else
572       {
573         PCD_CLEAR_OUT_STATUS(USBx, ep->num);
574       }
575 
576       /* Multi packet transfer */
577       if (ep->xfer_len > ep->maxpacket)
578       {
579         ep->xfer_len -= ep->maxpacket;
580       }
581       else
582       {
583         ep->xfer_len = 0U;
584       }
585     }
586 #if (USE_USB_DOUBLE_BUFFER == 1U)
587     else
588     {
589       /* First Transfer Coming From HAL_PCD_EP_Receive & From ISR */
590       /* Set the Double buffer counter */
591       if (ep->type == EP_TYPE_BULK)
592       {
593         /* Coming from ISR */
594         if (ep->xfer_count != 0U)
595         {
596           /* Update last value to check if there is blocking state */
597           wEPVal = PCD_GET_ENDPOINT(USBx, ep->num);
598 
599           /* Blocking State */
600           if ((((wEPVal & USB_EP_DTOG_RX) != 0U) && ((wEPVal & USB_EP_DTOG_TX) != 0U)) ||
601               (((wEPVal & USB_EP_DTOG_RX) == 0U) && ((wEPVal & USB_EP_DTOG_TX) == 0U)))
602           {
603             PCD_FREE_USER_BUFFER(USBx, ep->num, 0U);
604           }
605         }
606       }
607       /* iso out double */
608       else if (ep->type == EP_TYPE_ISOC)
609       {
610         /* Only single packet transfer supported in FS */
611         ep->xfer_len = 0U;
612       }
613       else
614       {
615         return HAL_ERROR;
616       }
617     }
618 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
619 
620     PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
621   }
622 
623   return HAL_OK;
624 }
625 
626 
627 /**
628   * @brief  USB_EPSetStall set a stall condition over an EP
629   * @param  USBx Selected device
630   * @param  ep pointer to endpoint structure
631   * @retval HAL status
632   */
USB_EPSetStall(USB_TypeDef * USBx,USB_EPTypeDef * ep)633 HAL_StatusTypeDef USB_EPSetStall(USB_TypeDef *USBx, USB_EPTypeDef *ep)
634 {
635   if (ep->is_in != 0U)
636   {
637     PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_STALL);
638   }
639   else
640   {
641     PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_STALL);
642   }
643 
644   return HAL_OK;
645 }
646 
647 /**
648   * @brief  USB_EPClearStall Clear a stall condition over an EP
649   * @param  USBx Selected device
650   * @param  ep pointer to endpoint structure
651   * @retval HAL status
652   */
USB_EPClearStall(USB_TypeDef * USBx,USB_EPTypeDef * ep)653 HAL_StatusTypeDef USB_EPClearStall(USB_TypeDef *USBx, USB_EPTypeDef *ep)
654 {
655   if (ep->is_in != 0U)
656   {
657     PCD_CLEAR_TX_DTOG(USBx, ep->num);
658 
659     if (ep->type != EP_TYPE_ISOC)
660     {
661       /* Configure NAK status for the Endpoint */
662       PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
663     }
664   }
665   else
666   {
667     PCD_CLEAR_RX_DTOG(USBx, ep->num);
668 
669     /* Configure VALID status for the Endpoint */
670     PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
671   }
672 
673   return HAL_OK;
674 }
675 
676 /**
677    * @brief  USB_EPStoptXfer  Stop transfer on an EP
678    * @param  USBx  usb device instance
679    * @param  ep pointer to endpoint structure
680    * @retval HAL status
681    */
USB_EPStopXfer(USB_TypeDef * USBx,USB_EPTypeDef * ep)682 HAL_StatusTypeDef USB_EPStopXfer(USB_TypeDef *USBx, USB_EPTypeDef *ep)
683 {
684   /* IN endpoint */
685   if (ep->is_in == 1U)
686   {
687     if (ep->doublebuffer == 0U)
688     {
689       if (ep->type != EP_TYPE_ISOC)
690       {
691         /* Configure NAK status for the Endpoint */
692         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
693       }
694       else
695       {
696         /* Configure TX Endpoint to disabled state */
697         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
698       }
699     }
700   }
701   else /* OUT endpoint */
702   {
703     if (ep->doublebuffer == 0U)
704     {
705       if (ep->type != EP_TYPE_ISOC)
706       {
707         /* Configure NAK status for the Endpoint */
708         PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
709       }
710       else
711       {
712         /* Configure RX Endpoint to disabled state */
713         PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
714       }
715     }
716   }
717 
718   return HAL_OK;
719 }
720 #endif /* defined (HAL_PCD_MODULE_ENABLED) */
721 
722 /**
723   * @brief  USB_StopDevice Stop the usb device mode
724   * @param  USBx Selected device
725   * @retval HAL status
726   */
USB_StopDevice(USB_TypeDef * USBx)727 HAL_StatusTypeDef USB_StopDevice(USB_TypeDef *USBx)
728 {
729   /* disable all interrupts and force USB reset */
730   USBx->CNTR = (uint16_t)USB_CNTR_FRES;
731 
732   /* clear interrupt status register */
733   USBx->ISTR = 0U;
734 
735   /* switch-off device */
736   USBx->CNTR = (uint16_t)(USB_CNTR_FRES | USB_CNTR_PDWN);
737 
738   return HAL_OK;
739 }
740 
741 /**
742   * @brief  USB_SetDevAddress Stop the usb device mode
743   * @param  USBx Selected device
744   * @param  address new device address to be assigned
745   *          This parameter can be a value from 0 to 255
746   * @retval HAL status
747   */
USB_SetDevAddress(USB_TypeDef * USBx,uint8_t address)748 HAL_StatusTypeDef  USB_SetDevAddress(USB_TypeDef *USBx, uint8_t address)
749 {
750   if (address == 0U)
751   {
752     /* set device address and enable function */
753     USBx->DADDR = (uint16_t)USB_DADDR_EF;
754   }
755 
756   return HAL_OK;
757 }
758 
759 /**
760   * @brief  USB_DevConnect Connect the USB device by enabling the pull-up/pull-down
761   * @param  USBx Selected device
762   * @retval HAL status
763   */
USB_DevConnect(USB_TypeDef * USBx)764 HAL_StatusTypeDef  USB_DevConnect(USB_TypeDef *USBx)
765 {
766   /* Enabling DP Pull-UP bit to Connect internal PU resistor on USB DP line */
767   USBx->BCDR |= (uint16_t)USB_BCDR_DPPU;
768 
769   return HAL_OK;
770 }
771 
772 /**
773   * @brief  USB_DevDisconnect Disconnect the USB device by disabling the pull-up/pull-down
774   * @param  USBx Selected device
775   * @retval HAL status
776   */
USB_DevDisconnect(USB_TypeDef * USBx)777 HAL_StatusTypeDef  USB_DevDisconnect(USB_TypeDef *USBx)
778 {
779   /* Disable DP Pull-Up bit to disconnect the Internal PU resistor on USB DP line */
780   USBx->BCDR &= (uint16_t)(~(USB_BCDR_DPPU));
781 
782   return HAL_OK;
783 }
784 
785 /**
786   * @brief  USB_ReadInterrupts return the global USB interrupt status
787   * @param  USBx Selected device
788   * @retval USB Global Interrupt status
789   */
USB_ReadInterrupts(USB_TypeDef const * USBx)790 uint32_t USB_ReadInterrupts(USB_TypeDef const *USBx)
791 {
792   uint32_t tmpreg;
793 
794   tmpreg = USBx->ISTR;
795   return tmpreg;
796 }
797 
798 /**
799   * @brief  USB_ActivateRemoteWakeup : active remote wakeup signalling
800   * @param  USBx Selected device
801   * @retval HAL status
802   */
USB_ActivateRemoteWakeup(USB_TypeDef * USBx)803 HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_TypeDef *USBx)
804 {
805   USBx->CNTR |= (uint16_t)USB_CNTR_RESUME;
806 
807   return HAL_OK;
808 }
809 
810 /**
811   * @brief  USB_DeActivateRemoteWakeup de-active remote wakeup signalling
812   * @param  USBx Selected device
813   * @retval HAL status
814   */
USB_DeActivateRemoteWakeup(USB_TypeDef * USBx)815 HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_TypeDef *USBx)
816 {
817   USBx->CNTR &= (uint16_t)(~USB_CNTR_RESUME);
818 
819   return HAL_OK;
820 }
821 
822 /**
823   * @brief Copy a buffer from user memory area to packet memory area (PMA)
824   * @param   USBx USB peripheral instance register address.
825   * @param   pbUsrBuf pointer to user memory area.
826   * @param   wPMABufAddr address into PMA.
827   * @param   wNBytes no. of bytes to be copied.
828   * @retval None
829   */
USB_WritePMA(USB_TypeDef const * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)830 void USB_WritePMA(USB_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
831 {
832   uint32_t n = ((uint32_t)wNBytes + 1U) >> 1;
833   uint32_t BaseAddr = (uint32_t)USBx;
834   uint32_t count;
835   uint16_t WrVal;
836   __IO uint16_t *pdwVal;
837   uint8_t *pBuf = pbUsrBuf;
838 
839   pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
840 
841   for (count = n; count != 0U; count--)
842   {
843     WrVal = pBuf[0];
844     WrVal |= (uint16_t)pBuf[1] << 8;
845     *pdwVal = (WrVal & 0xFFFFU);
846     pdwVal++;
847 
848 #if PMA_ACCESS > 1U
849     pdwVal++;
850 #endif /* PMA_ACCESS */
851 
852     pBuf++;
853     pBuf++;
854   }
855 }
856 
857 /**
858   * @brief Copy data from packet memory area (PMA) to user memory buffer
859   * @param   USBx USB peripheral instance register address.
860   * @param   pbUsrBuf pointer to user memory area.
861   * @param   wPMABufAddr address into PMA.
862   * @param   wNBytes no. of bytes to be copied.
863   * @retval None
864   */
USB_ReadPMA(USB_TypeDef const * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)865 void USB_ReadPMA(USB_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
866 {
867   uint32_t n = (uint32_t)wNBytes >> 1;
868   uint32_t BaseAddr = (uint32_t)USBx;
869   uint32_t count;
870   uint32_t RdVal;
871   __IO uint16_t *pdwVal;
872   uint8_t *pBuf = pbUsrBuf;
873 
874   pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
875 
876   for (count = n; count != 0U; count--)
877   {
878     RdVal = *(__IO uint16_t *)pdwVal;
879     pdwVal++;
880     *pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
881     pBuf++;
882     *pBuf = (uint8_t)((RdVal >> 8) & 0xFFU);
883     pBuf++;
884 
885 #if PMA_ACCESS > 1U
886     pdwVal++;
887 #endif /* PMA_ACCESS */
888   }
889 
890   if ((wNBytes % 2U) != 0U)
891   {
892     RdVal = *pdwVal;
893     *pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
894   }
895 }
896 
897 
898 /**
899   * @}
900   */
901 
902 /**
903   * @}
904   */
905 #endif /* defined (USB) */
906 #endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
907 
908 /**
909   * @}
910   */
911