1 /**
2   ******************************************************************************
3   * @file    stm32u5xx_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) 2021 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 "stm32u5xx_hal.h"
43 
44 /** @addtogroup STM32U5xx_LL_USB_DRIVER
45   * @{
46   */
47 
48 #if defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED)
49 #if defined (USB_OTG_FS) || defined (USB_OTG_HS) || defined (USB_DRD_FS)
50 /* Private typedef -----------------------------------------------------------*/
51 /* Private define ------------------------------------------------------------*/
52 /* Private macro -------------------------------------------------------------*/
53 /* Private variables ---------------------------------------------------------*/
54 /* Private function prototypes -----------------------------------------------*/
55 /* Private functions ---------------------------------------------------------*/
56 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
57 static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx);
58 
59 /* Exported functions --------------------------------------------------------*/
60 /** @defgroup USB_LL_Exported_Functions USB Low Layer Exported Functions
61   * @{
62   */
63 
64 /** @defgroup USB_LL_Exported_Functions_Group1 Initialization/de-initialization functions
65   *  @brief    Initialization and Configuration functions
66   *
67 @verbatim
68  ===============================================================================
69                       ##### Initialization/de-initialization functions #####
70  ===============================================================================
71 
72 @endverbatim
73   * @{
74   */
75 
76 /**
77   * @brief  Initializes the USB Core
78   * @param  USBx USB Instance
79   * @param  cfg pointer to a USB_OTG_CfgTypeDef structure that contains
80   *         the configuration information for the specified USBx peripheral.
81   * @retval HAL status
82   */
USB_CoreInit(USB_OTG_GlobalTypeDef * USBx,USB_OTG_CfgTypeDef cfg)83 HAL_StatusTypeDef USB_CoreInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
84 {
85   HAL_StatusTypeDef ret;
86 #if defined (STM32U595xx) || defined (STM32U5A5xx) || defined (STM32U599xx) || defined (STM32U5A9xx) \
87  || defined (STM32U5F7xx) || defined (STM32U5G7xx) || defined (STM32U5F9xx) || defined (STM32U5G9xx)
88   if (cfg.phy_itface == USB_OTG_HS_EMBEDDED_PHY)
89   {
90     /* Init The UTMI Interface */
91     USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS);
92   }
93 
94   /* Reset after a PHY select */
95   ret = USB_CoreReset(USBx);
96 
97   if (cfg.dma_enable == 1U)
98   {
99     USBx->GAHBCFG |= USB_OTG_GAHBCFG_HBSTLEN_2;
100     USBx->GAHBCFG |= USB_OTG_GAHBCFG_DMAEN;
101   }
102 
103 #else
104 
105   /* Select FS Embedded PHY */
106   USBx->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
107 
108   /* Reset after a PHY select */
109   ret = USB_CoreReset(USBx);
110 
111   if (cfg.battery_charging_enable == 0U)
112   {
113     /* Activate the USB Transceiver */
114     USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
115   }
116   else
117   {
118     /* Deactivate the USB Transceiver */
119     USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
120   }
121 #endif /* defined (STM32U595xx) || defined (STM32U5A5xx) || defined (STM32U599xx) || defined (STM32U5A9xx) ||
122           defined (STM32U5F7xx) || defined (STM32U5G7xx) || defined (STM32U5F9xx) || defined (STM32U5G9xx) */
123 
124   return ret;
125 }
126 
127 
128 /**
129   * @brief  Set the USB turnaround time
130   * @param  USBx USB Instance
131   * @param  hclk: AHB clock frequency
132   * @retval USB turnaround time In PHY Clocks number
133   */
USB_SetTurnaroundTime(USB_OTG_GlobalTypeDef * USBx,uint32_t hclk,uint8_t speed)134 HAL_StatusTypeDef USB_SetTurnaroundTime(USB_OTG_GlobalTypeDef *USBx,
135                                         uint32_t hclk, uint8_t speed)
136 {
137   uint32_t UsbTrd;
138 
139   /* The USBTRD is configured according to the tables below, depending on AHB frequency
140   used by application. In the low AHB frequency range it is used to stretch enough the USB response
141   time to IN tokens, the USB turnaround time, so to compensate for the longer AHB read access
142   latency to the Data FIFO */
143   if (speed == USBD_FS_SPEED)
144   {
145     if ((hclk >= 14200000U) && (hclk < 15000000U))
146     {
147       /* hclk Clock Range between 14.2-15 MHz */
148       UsbTrd = 0xFU;
149     }
150     else if ((hclk >= 15000000U) && (hclk < 16000000U))
151     {
152       /* hclk Clock Range between 15-16 MHz */
153       UsbTrd = 0xEU;
154     }
155     else if ((hclk >= 16000000U) && (hclk < 17200000U))
156     {
157       /* hclk Clock Range between 16-17.2 MHz */
158       UsbTrd = 0xDU;
159     }
160     else if ((hclk >= 17200000U) && (hclk < 18500000U))
161     {
162       /* hclk Clock Range between 17.2-18.5 MHz */
163       UsbTrd = 0xCU;
164     }
165     else if ((hclk >= 18500000U) && (hclk < 20000000U))
166     {
167       /* hclk Clock Range between 18.5-20 MHz */
168       UsbTrd = 0xBU;
169     }
170     else if ((hclk >= 20000000U) && (hclk < 21800000U))
171     {
172       /* hclk Clock Range between 20-21.8 MHz */
173       UsbTrd = 0xAU;
174     }
175     else if ((hclk >= 21800000U) && (hclk < 24000000U))
176     {
177       /* hclk Clock Range between 21.8-24 MHz */
178       UsbTrd = 0x9U;
179     }
180     else if ((hclk >= 24000000U) && (hclk < 27700000U))
181     {
182       /* hclk Clock Range between 24-27.7 MHz */
183       UsbTrd = 0x8U;
184     }
185     else if ((hclk >= 27700000U) && (hclk < 32000000U))
186     {
187       /* hclk Clock Range between 27.7-32 MHz */
188       UsbTrd = 0x7U;
189     }
190     else /* if(hclk >= 32000000) */
191     {
192       /* hclk Clock Range between 32-200 MHz */
193       UsbTrd = 0x6U;
194     }
195   }
196   else if (speed == USBD_HS_SPEED)
197   {
198     UsbTrd = USBD_HS_TRDT_VALUE;
199   }
200   else
201   {
202     UsbTrd = USBD_DEFAULT_TRDT_VALUE;
203   }
204 
205   USBx->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
206   USBx->GUSBCFG |= (uint32_t)((UsbTrd << 10) & USB_OTG_GUSBCFG_TRDT);
207 
208   return HAL_OK;
209 }
210 
211 /**
212   * @brief  USB_EnableGlobalInt
213   *         Enables the controller's Global Int in the AHB Config reg
214   * @param  USBx  Selected device
215   * @retval HAL status
216   */
USB_EnableGlobalInt(USB_OTG_GlobalTypeDef * USBx)217 HAL_StatusTypeDef USB_EnableGlobalInt(USB_OTG_GlobalTypeDef *USBx)
218 {
219   USBx->GAHBCFG |= USB_OTG_GAHBCFG_GINT;
220   return HAL_OK;
221 }
222 
223 /**
224   * @brief  USB_DisableGlobalInt
225   *         Disable the controller's Global Int in the AHB Config reg
226   * @param  USBx  Selected device
227   * @retval HAL status
228   */
USB_DisableGlobalInt(USB_OTG_GlobalTypeDef * USBx)229 HAL_StatusTypeDef USB_DisableGlobalInt(USB_OTG_GlobalTypeDef *USBx)
230 {
231   USBx->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
232   return HAL_OK;
233 }
234 
235 /**
236   * @brief  USB_SetCurrentMode Set functional mode
237   * @param  USBx  Selected device
238   * @param  mode  current core mode
239   *          This parameter can be one of these values:
240   *            @arg USB_DEVICE_MODE Peripheral mode
241   *            @arg USB_HOST_MODE Host mode
242   * @retval HAL status
243   */
USB_SetCurrentMode(USB_OTG_GlobalTypeDef * USBx,USB_OTG_ModeTypeDef mode)244 HAL_StatusTypeDef USB_SetCurrentMode(USB_OTG_GlobalTypeDef *USBx, USB_OTG_ModeTypeDef mode)
245 {
246   uint32_t ms = 0U;
247 
248   USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD);
249 
250   if (mode == USB_HOST_MODE)
251   {
252     USBx->GUSBCFG |= USB_OTG_GUSBCFG_FHMOD;
253 
254     do
255     {
256       HAL_Delay(10U);
257       ms += 10U;
258     } while ((USB_GetMode(USBx) != (uint32_t)USB_HOST_MODE) && (ms < HAL_USB_CURRENT_MODE_MAX_DELAY_MS));
259   }
260   else if (mode == USB_DEVICE_MODE)
261   {
262     USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
263 
264     do
265     {
266       HAL_Delay(10U);
267       ms += 10U;
268     } while ((USB_GetMode(USBx) != (uint32_t)USB_DEVICE_MODE) && (ms < HAL_USB_CURRENT_MODE_MAX_DELAY_MS));
269   }
270   else
271   {
272     return HAL_ERROR;
273   }
274 
275   if (ms == HAL_USB_CURRENT_MODE_MAX_DELAY_MS)
276   {
277     return HAL_ERROR;
278   }
279 
280   return HAL_OK;
281 }
282 
283 /**
284   * @brief  USB_DevInit Initializes the USB_OTG controller registers
285   *         for device mode
286   * @param  USBx  Selected device
287   * @param  cfg   pointer to a USB_OTG_CfgTypeDef structure that contains
288   *         the configuration information for the specified USBx peripheral.
289   * @retval HAL status
290   */
USB_DevInit(USB_OTG_GlobalTypeDef * USBx,USB_OTG_CfgTypeDef cfg)291 HAL_StatusTypeDef USB_DevInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
292 {
293   HAL_StatusTypeDef ret = HAL_OK;
294   uint32_t USBx_BASE = (uint32_t)USBx;
295   uint32_t i;
296 
297   for (i = 0U; i < 15U; i++)
298   {
299     USBx->DIEPTXF[i] = 0U;
300   }
301 
302 #if defined (STM32U595xx) || defined (STM32U5A5xx) || defined (STM32U599xx) || defined (STM32U5A9xx) \
303  || defined (STM32U5F7xx) || defined (STM32U5G7xx) || defined (STM32U5F9xx) || defined (STM32U5G9xx)
304   /* Disable USB PHY pulldown resistors */
305   USBx->GCCFG &= ~USB_OTG_GCCFG_PULLDOWNEN;
306 #endif /* defined (STM32U595xx) || defined (STM32U5A5xx) || defined (STM32U599xx) || defined (STM32U5A9xx) ||
307           defined (STM32U5F7xx) || defined (STM32U5G7xx) || defined (STM32U5F9xx) || defined (STM32U5G9xx) */
308 
309   /* VBUS Sensing setup */
310   if (cfg.vbus_sensing_enable == 0U)
311   {
312     USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS;
313 
314     /* Deactivate VBUS Sensing B */
315     USBx->GCCFG &= ~USB_OTG_GCCFG_VBDEN;
316 
317     /* B-peripheral session valid override enable */
318 #if defined (STM32U595xx) || defined (STM32U5A5xx) || defined (STM32U599xx) || defined (STM32U5A9xx) \
319  || defined (STM32U5F7xx) || defined (STM32U5G7xx) || defined (STM32U5F9xx) || defined (STM32U5G9xx)
320     USBx->GCCFG |= USB_OTG_GCCFG_VBVALEXTOEN;
321     USBx->GCCFG |= USB_OTG_GCCFG_VBVALOVAL;
322 #else
323     USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
324     USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
325 #endif /* defined (STM32U595xx) || defined (STM32U5A5xx) || defined (STM32U599xx) || defined (STM32U5A9xx) ||
326           defined (STM32U5F7xx) || defined (STM32U5G7xx) || defined (STM32U5F9xx) || defined (STM32U5G9xx) */
327   }
328   else
329   {
330 #if defined (STM32U595xx) || defined (STM32U5A5xx) || defined (STM32U599xx) || defined (STM32U5A9xx) \
331  || defined (STM32U5F7xx) || defined (STM32U5G7xx) || defined (STM32U5F9xx) || defined (STM32U5G9xx)
332     /* B-peripheral session valid override disable */
333     USBx->GCCFG &= ~USB_OTG_GCCFG_VBVALEXTOEN;
334     USBx->GCCFG &= ~USB_OTG_GCCFG_VBVALOVAL;
335 #endif /* defined (STM32U595xx) || defined (STM32U5A5xx) || defined (STM32U599xx) || defined (STM32U5A9xx) ||
336           defined (STM32U5F7xx) || defined (STM32U5G7xx) || defined (STM32U5F9xx) || defined (STM32U5G9xx) */
337 
338     /* Enable HW VBUS sensing */
339     USBx->GCCFG |= USB_OTG_GCCFG_VBDEN;
340   }
341 
342   /* Restart the Phy Clock */
343   USBx_PCGCCTL = 0U;
344 
345 #if defined (STM32U595xx) || defined (STM32U5A5xx) || defined (STM32U599xx) || defined (STM32U5A9xx) \
346  || defined (STM32U5F7xx) || defined (STM32U5G7xx) || defined (STM32U5F9xx) || defined (STM32U5G9xx)
347   if (cfg.phy_itface == USB_OTG_HS_EMBEDDED_PHY)
348   {
349     if (cfg.speed == USBD_HS_SPEED)
350     {
351       /* Set Core speed to High speed mode */
352       (void)USB_SetDevSpeed(USBx, USB_OTG_SPEED_HIGH);
353     }
354     else
355     {
356       /* Set Core speed to Full speed mode */
357       (void)USB_SetDevSpeed(USBx, USB_OTG_SPEED_HIGH_IN_FULL);
358     }
359   }
360   else
361 #endif /* defined (STM32U595xx) || defined (STM32U5A5xx) || defined (STM32U599xx) || defined (STM32U5A9xx) ||
362           defined (STM32U5F7xx) || defined (STM32U5G7xx) || defined (STM32U5F9xx) || defined (STM32U5G9xx) */
363   {
364     /* Set Core speed to Full speed mode */
365     (void)USB_SetDevSpeed(USBx, USB_OTG_SPEED_FULL);
366   }
367 
368   /* Flush the FIFOs */
369   if (USB_FlushTxFifo(USBx, 0x10U) != HAL_OK) /* all Tx FIFOs */
370   {
371     ret = HAL_ERROR;
372   }
373 
374   if (USB_FlushRxFifo(USBx) != HAL_OK)
375   {
376     ret = HAL_ERROR;
377   }
378 
379   /* Clear all pending Device Interrupts */
380   USBx_DEVICE->DIEPMSK = 0U;
381   USBx_DEVICE->DOEPMSK = 0U;
382   USBx_DEVICE->DAINTMSK = 0U;
383 
384   for (i = 0U; i < cfg.dev_endpoints; i++)
385   {
386     if ((USBx_INEP(i)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
387     {
388       if (i == 0U)
389       {
390         USBx_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_SNAK;
391       }
392       else
393       {
394         USBx_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_EPDIS | USB_OTG_DIEPCTL_SNAK;
395       }
396     }
397     else
398     {
399       USBx_INEP(i)->DIEPCTL = 0U;
400     }
401 
402     USBx_INEP(i)->DIEPTSIZ = 0U;
403     USBx_INEP(i)->DIEPINT  = 0xFB7FU;
404   }
405 
406   for (i = 0U; i < cfg.dev_endpoints; i++)
407   {
408     if ((USBx_OUTEP(i)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
409     {
410       if (i == 0U)
411       {
412         USBx_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_SNAK;
413       }
414       else
415       {
416         USBx_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_EPDIS | USB_OTG_DOEPCTL_SNAK;
417       }
418     }
419     else
420     {
421       USBx_OUTEP(i)->DOEPCTL = 0U;
422     }
423 
424     USBx_OUTEP(i)->DOEPTSIZ = 0U;
425     USBx_OUTEP(i)->DOEPINT  = 0xFB7FU;
426   }
427 
428   USBx_DEVICE->DIEPMSK &= ~(USB_OTG_DIEPMSK_TXFURM);
429 
430   /* Disable all interrupts. */
431   USBx->GINTMSK = 0U;
432 
433   /* Clear any pending interrupts */
434   USBx->GINTSTS = 0xBFFFFFFFU;
435 
436   /* Enable the common interrupts */
437   if (cfg.dma_enable == 0U)
438   {
439     USBx->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
440   }
441 
442   /* Enable interrupts matching to the Device mode ONLY */
443   USBx->GINTMSK |= USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_USBRST |
444                    USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_IEPINT |
445                    USB_OTG_GINTMSK_OEPINT   | USB_OTG_GINTMSK_IISOIXFRM |
446                    USB_OTG_GINTMSK_PXFRM_IISOOXFRM | USB_OTG_GINTMSK_WUIM;
447 
448   if (cfg.Sof_enable != 0U)
449   {
450     USBx->GINTMSK |= USB_OTG_GINTMSK_SOFM;
451   }
452 
453   if (cfg.vbus_sensing_enable == 1U)
454   {
455     USBx->GINTMSK |= (USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_OTGINT);
456   }
457 
458   return ret;
459 }
460 
461 /**
462   * @brief  USB_FlushTxFifo Flush a Tx FIFO
463   * @param  USBx  Selected device
464   * @param  num  FIFO number
465   *         This parameter can be a value from 1 to 15
466             15 means Flush all Tx FIFOs
467   * @retval HAL status
468   */
USB_FlushTxFifo(USB_OTG_GlobalTypeDef * USBx,uint32_t num)469 HAL_StatusTypeDef USB_FlushTxFifo(USB_OTG_GlobalTypeDef *USBx, uint32_t num)
470 {
471   __IO uint32_t count = 0U;
472 
473   /* Wait for AHB master IDLE state. */
474   do
475   {
476     count++;
477 
478     if (count > HAL_USB_TIMEOUT)
479     {
480       return HAL_TIMEOUT;
481     }
482   } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
483 
484   /* Flush TX Fifo */
485   count = 0U;
486   USBx->GRSTCTL = (USB_OTG_GRSTCTL_TXFFLSH | (num << 6));
487 
488   do
489   {
490     count++;
491 
492     if (count > HAL_USB_TIMEOUT)
493     {
494       return HAL_TIMEOUT;
495     }
496   } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH);
497 
498   return HAL_OK;
499 }
500 
501 /**
502   * @brief  USB_FlushRxFifo  Flush Rx FIFO
503   * @param  USBx  Selected device
504   * @retval HAL status
505   */
USB_FlushRxFifo(USB_OTG_GlobalTypeDef * USBx)506 HAL_StatusTypeDef USB_FlushRxFifo(USB_OTG_GlobalTypeDef *USBx)
507 {
508   __IO uint32_t count = 0U;
509 
510   /* Wait for AHB master IDLE state. */
511   do
512   {
513     count++;
514 
515     if (count > HAL_USB_TIMEOUT)
516     {
517       return HAL_TIMEOUT;
518     }
519   } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
520 
521   /* Flush RX Fifo */
522   count = 0U;
523   USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH;
524 
525   do
526   {
527     count++;
528 
529     if (count > HAL_USB_TIMEOUT)
530     {
531       return HAL_TIMEOUT;
532     }
533   } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH);
534 
535   return HAL_OK;
536 }
537 
538 /**
539   * @brief  USB_SetDevSpeed  Initializes the DevSpd field of DCFG register
540   *         depending the PHY type and the enumeration speed of the device.
541   * @param  USBx  Selected device
542   * @param  speed  device speed
543   *          This parameter can be one of these values:
544   *            @arg USB_OTG_SPEED_HIGH: High speed mode
545   *            @arg USB_OTG_SPEED_HIGH_IN_FULL: High speed core in Full Speed mode
546   *            @arg USB_OTG_SPEED_FULL: Full speed mode
547   * @retval  Hal status
548   */
USB_SetDevSpeed(const USB_OTG_GlobalTypeDef * USBx,uint8_t speed)549 HAL_StatusTypeDef USB_SetDevSpeed(const USB_OTG_GlobalTypeDef *USBx, uint8_t speed)
550 {
551   uint32_t USBx_BASE = (uint32_t)USBx;
552 
553   USBx_DEVICE->DCFG |= speed;
554   return HAL_OK;
555 }
556 
557 /**
558   * @brief  USB_GetDevSpeed  Return the Dev Speed
559   * @param  USBx  Selected device
560   * @retval speed  device speed
561   *          This parameter can be one of these values:
562   *            @arg USBD_HS_SPEED: High speed mode
563   *            @arg USBD_FS_SPEED: Full speed mode
564   */
USB_GetDevSpeed(const USB_OTG_GlobalTypeDef * USBx)565 uint8_t USB_GetDevSpeed(const USB_OTG_GlobalTypeDef *USBx)
566 {
567   uint32_t USBx_BASE = (uint32_t)USBx;
568   uint8_t speed;
569   uint32_t DevEnumSpeed = USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD;
570 
571   if (DevEnumSpeed == DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ)
572   {
573     speed = USBD_HS_SPEED;
574   }
575   else if ((DevEnumSpeed == DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ) ||
576            (DevEnumSpeed == DSTS_ENUMSPD_FS_PHY_48MHZ))
577   {
578     speed = USBD_FS_SPEED;
579   }
580   else
581   {
582     speed = 0xFU;
583   }
584 
585   return speed;
586 }
587 
588 /**
589   * @brief  Activate and configure an endpoint
590   * @param  USBx  Selected device
591   * @param  ep pointer to endpoint structure
592   * @retval HAL status
593   */
USB_ActivateEndpoint(const USB_OTG_GlobalTypeDef * USBx,const USB_OTG_EPTypeDef * ep)594 HAL_StatusTypeDef USB_ActivateEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
595 {
596   uint32_t USBx_BASE = (uint32_t)USBx;
597   uint32_t epnum = (uint32_t)ep->num;
598 
599   if (ep->is_in == 1U)
600   {
601     USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK));
602 
603     if ((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_USBAEP) == 0U)
604     {
605       USBx_INEP(epnum)->DIEPCTL |= (ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ) |
606                                    ((uint32_t)ep->type << 18) | (epnum << 22) |
607                                    USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
608                                    USB_OTG_DIEPCTL_USBAEP;
609     }
610   }
611   else
612   {
613     USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16);
614 
615     if (((USBx_OUTEP(epnum)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0U)
616     {
617       USBx_OUTEP(epnum)->DOEPCTL |= (ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ) |
618                                     ((uint32_t)ep->type << 18) |
619                                     USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
620                                     USB_OTG_DOEPCTL_USBAEP;
621     }
622   }
623   return HAL_OK;
624 }
625 
626 /**
627   * @brief  Activate and configure a dedicated endpoint
628   * @param  USBx  Selected device
629   * @param  ep pointer to endpoint structure
630   * @retval HAL status
631   */
USB_ActivateDedicatedEndpoint(const USB_OTG_GlobalTypeDef * USBx,const USB_OTG_EPTypeDef * ep)632 HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
633 {
634   uint32_t USBx_BASE = (uint32_t)USBx;
635   uint32_t epnum = (uint32_t)ep->num;
636 
637   /* Read DEPCTLn register */
638   if (ep->is_in == 1U)
639   {
640     if (((USBx_INEP(epnum)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0U)
641     {
642       USBx_INEP(epnum)->DIEPCTL |= (ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ) |
643                                    ((uint32_t)ep->type << 18) | (epnum << 22) |
644                                    USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
645                                    USB_OTG_DIEPCTL_USBAEP;
646     }
647 
648     USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK));
649   }
650   else
651   {
652     if (((USBx_OUTEP(epnum)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0U)
653     {
654       USBx_OUTEP(epnum)->DOEPCTL |= (ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ) |
655                                     ((uint32_t)ep->type << 18) | (epnum << 22) |
656                                     USB_OTG_DOEPCTL_USBAEP;
657     }
658 
659     USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16);
660   }
661 
662   return HAL_OK;
663 }
664 
665 /**
666   * @brief  De-activate and de-initialize an endpoint
667   * @param  USBx  Selected device
668   * @param  ep pointer to endpoint structure
669   * @retval HAL status
670   */
USB_DeactivateEndpoint(const USB_OTG_GlobalTypeDef * USBx,const USB_OTG_EPTypeDef * ep)671 HAL_StatusTypeDef USB_DeactivateEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
672 {
673   uint32_t USBx_BASE = (uint32_t)USBx;
674   uint32_t epnum = (uint32_t)ep->num;
675 
676   /* Read DEPCTLn register */
677   if (ep->is_in == 1U)
678   {
679     if ((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
680     {
681       USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
682       USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_EPDIS;
683     }
684 
685     USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK)));
686     USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK)));
687     USBx_INEP(epnum)->DIEPCTL &= ~(USB_OTG_DIEPCTL_USBAEP |
688                                    USB_OTG_DIEPCTL_MPSIZ |
689                                    USB_OTG_DIEPCTL_TXFNUM |
690                                    USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
691                                    USB_OTG_DIEPCTL_EPTYP);
692   }
693   else
694   {
695     if ((USBx_OUTEP(epnum)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
696     {
697       USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
698       USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_EPDIS;
699     }
700 
701     USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16));
702     USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16));
703     USBx_OUTEP(epnum)->DOEPCTL &= ~(USB_OTG_DOEPCTL_USBAEP |
704                                     USB_OTG_DOEPCTL_MPSIZ |
705                                     USB_OTG_DOEPCTL_SD0PID_SEVNFRM |
706                                     USB_OTG_DOEPCTL_EPTYP);
707   }
708 
709   return HAL_OK;
710 }
711 
712 /**
713   * @brief  De-activate and de-initialize a dedicated endpoint
714   * @param  USBx  Selected device
715   * @param  ep pointer to endpoint structure
716   * @retval HAL status
717   */
USB_DeactivateDedicatedEndpoint(const USB_OTG_GlobalTypeDef * USBx,const USB_OTG_EPTypeDef * ep)718 HAL_StatusTypeDef USB_DeactivateDedicatedEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
719 {
720   uint32_t USBx_BASE = (uint32_t)USBx;
721   uint32_t epnum = (uint32_t)ep->num;
722 
723   /* Read DEPCTLn register */
724   if (ep->is_in == 1U)
725   {
726     if ((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
727     {
728       USBx_INEP(epnum)->DIEPCTL  |= USB_OTG_DIEPCTL_SNAK;
729       USBx_INEP(epnum)->DIEPCTL  |= USB_OTG_DIEPCTL_EPDIS;
730     }
731 
732     USBx_INEP(epnum)->DIEPCTL &= ~ USB_OTG_DIEPCTL_USBAEP;
733     USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK)));
734   }
735   else
736   {
737     if ((USBx_OUTEP(epnum)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
738     {
739       USBx_OUTEP(epnum)->DOEPCTL  |= USB_OTG_DOEPCTL_SNAK;
740       USBx_OUTEP(epnum)->DOEPCTL  |= USB_OTG_DOEPCTL_EPDIS;
741     }
742 
743     USBx_OUTEP(epnum)->DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP;
744     USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16));
745   }
746 
747   return HAL_OK;
748 }
749 
750 /**
751   * @brief  USB_EPStartXfer : setup and starts a transfer over an EP
752   * @param  USBx  Selected device
753   * @param  ep pointer to endpoint structure
754   * @param  dma USB dma enabled or disabled
755   *          This parameter can be one of these values:
756   *           0 : DMA feature not used
757   *           1 : DMA feature used
758   * @retval HAL status
759   */
USB_EPStartXfer(USB_OTG_GlobalTypeDef * USBx,USB_OTG_EPTypeDef * ep,uint8_t dma)760 HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep, uint8_t dma)
761 {
762   uint32_t USBx_BASE = (uint32_t)USBx;
763   uint32_t epnum = (uint32_t)ep->num;
764   uint16_t pktcnt;
765 
766   /* IN endpoint */
767   if (ep->is_in == 1U)
768   {
769     /* Zero Length Packet? */
770     if (ep->xfer_len == 0U)
771     {
772       USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
773       USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1U << 19));
774       USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
775     }
776     else
777     {
778       /* Program the transfer size and packet count
779       * as follows: xfersize = N * maxpacket +
780       * short_packet pktcnt = N + (short_packet
781       * exist ? 1 : 0)
782       */
783       USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
784       USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
785 
786       if (epnum == 0U)
787       {
788         if (ep->xfer_len > ep->maxpacket)
789         {
790           ep->xfer_len = ep->maxpacket;
791         }
792 
793         USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1U << 19));
794       }
795       else
796       {
797         pktcnt = (uint16_t)((ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket);
798         USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & ((uint32_t)pktcnt << 19));
799 
800         if (ep->type == EP_TYPE_ISOC)
801         {
802           USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_MULCNT);
803           USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & ((uint32_t)pktcnt << 29));
804         }
805       }
806 
807       USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & ep->xfer_len);
808     }
809 
810     if (dma == 1U)
811     {
812       if ((uint32_t)ep->dma_addr != 0U)
813       {
814         USBx_INEP(epnum)->DIEPDMA = (uint32_t)(ep->dma_addr);
815       }
816 
817       if (ep->type == EP_TYPE_ISOC)
818       {
819         if ((USBx_DEVICE->DSTS & (1U << 8)) == 0U)
820         {
821           USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM;
822         }
823         else
824         {
825           USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
826         }
827       }
828 
829       /* EP enable, IN data in FIFO */
830       USBx_INEP(epnum)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
831     }
832     else
833     {
834       /* EP enable, IN data in FIFO */
835       USBx_INEP(epnum)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
836 
837       if (ep->type != EP_TYPE_ISOC)
838       {
839         /* Enable the Tx FIFO Empty Interrupt for this EP */
840         if (ep->xfer_len > 0U)
841         {
842           USBx_DEVICE->DIEPEMPMSK |= 1UL << (ep->num & EP_ADDR_MSK);
843         }
844       }
845       else
846       {
847         if ((USBx_DEVICE->DSTS & (1U << 8)) == 0U)
848         {
849           USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM;
850         }
851         else
852         {
853           USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
854         }
855 
856         (void)USB_WritePacket(USBx, ep->xfer_buff, ep->num, (uint16_t)ep->xfer_len, dma);
857       }
858     }
859   }
860   else /* OUT endpoint */
861   {
862     /* Program the transfer size and packet count as follows:
863     * pktcnt = N
864     * xfersize = N * maxpacket
865     */
866     USBx_OUTEP(epnum)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ);
867     USBx_OUTEP(epnum)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT);
868 
869     if (epnum == 0U)
870     {
871       if (ep->xfer_len > 0U)
872       {
873         ep->xfer_len = ep->maxpacket;
874       }
875 
876       /* Store transfer size, for EP0 this is equal to endpoint max packet size */
877       ep->xfer_size = ep->maxpacket;
878 
879       USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & ep->xfer_size);
880       USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1U << 19));
881     }
882     else
883     {
884       if (ep->xfer_len == 0U)
885       {
886         USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & ep->maxpacket);
887         USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1U << 19));
888       }
889       else
890       {
891         pktcnt = (uint16_t)((ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket);
892         ep->xfer_size = ep->maxpacket * pktcnt;
893 
894         USBx_OUTEP(epnum)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_PKTCNT & ((uint32_t)pktcnt << 19);
895         USBx_OUTEP(epnum)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_XFRSIZ & ep->xfer_size;
896       }
897     }
898 
899     if (dma == 1U)
900     {
901       if ((uint32_t)ep->xfer_buff != 0U)
902       {
903         USBx_OUTEP(epnum)->DOEPDMA = (uint32_t)(ep->xfer_buff);
904       }
905     }
906 
907     if (ep->type == EP_TYPE_ISOC)
908     {
909       if ((USBx_DEVICE->DSTS & (1U << 8)) == 0U)
910       {
911         USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SODDFRM;
912       }
913       else
914       {
915         USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
916       }
917     }
918     /* EP enable */
919     USBx_OUTEP(epnum)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA);
920   }
921 
922   return HAL_OK;
923 }
924 
925 
926 /**
927    * @brief  USB_EPStoptXfer  Stop transfer on an EP
928    * @param  USBx  usb device instance
929    * @param  ep pointer to endpoint structure
930    * @retval HAL status
931    */
USB_EPStopXfer(const USB_OTG_GlobalTypeDef * USBx,USB_OTG_EPTypeDef * ep)932 HAL_StatusTypeDef USB_EPStopXfer(const USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
933 {
934   __IO uint32_t count = 0U;
935   HAL_StatusTypeDef ret = HAL_OK;
936   uint32_t USBx_BASE = (uint32_t)USBx;
937 
938   /* IN endpoint */
939   if (ep->is_in == 1U)
940   {
941     /* EP enable, IN data in FIFO */
942     if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
943     {
944       USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_SNAK);
945       USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_EPDIS);
946 
947       do
948       {
949         count++;
950 
951         if (count > 10000U)
952         {
953           ret = HAL_ERROR;
954           break;
955         }
956       } while (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_EPENA) ==  USB_OTG_DIEPCTL_EPENA);
957     }
958   }
959   else /* OUT endpoint */
960   {
961     if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
962     {
963       USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_SNAK);
964       USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_EPDIS);
965 
966       do
967       {
968         count++;
969 
970         if (count > 10000U)
971         {
972           ret = HAL_ERROR;
973           break;
974         }
975       } while (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_EPENA) ==  USB_OTG_DOEPCTL_EPENA);
976     }
977   }
978 
979   return ret;
980 }
981 
982 
983 /**
984   * @brief  USB_WritePacket : Writes a packet into the Tx FIFO associated
985   *         with the EP/channel
986   * @param  USBx  Selected device
987   * @param  src   pointer to source buffer
988   * @param  ch_ep_num  endpoint or host channel number
989   * @param  len  Number of bytes to write
990   * @param  dma USB dma enabled or disabled
991   *          This parameter can be one of these values:
992   *           0 : DMA feature not used
993   *           1 : DMA feature used
994   * @retval HAL status
995   */
USB_WritePacket(const USB_OTG_GlobalTypeDef * USBx,uint8_t * src,uint8_t ch_ep_num,uint16_t len,uint8_t dma)996 HAL_StatusTypeDef USB_WritePacket(const USB_OTG_GlobalTypeDef *USBx, uint8_t *src,
997                                   uint8_t ch_ep_num, uint16_t len, uint8_t dma)
998 {
999   uint32_t USBx_BASE = (uint32_t)USBx;
1000   uint8_t *pSrc = src;
1001   uint32_t count32b;
1002   uint32_t i;
1003 
1004   if (dma == 0U)
1005   {
1006     count32b = ((uint32_t)len + 3U) / 4U;
1007     for (i = 0U; i < count32b; i++)
1008     {
1009       USBx_DFIFO((uint32_t)ch_ep_num) = __UNALIGNED_UINT32_READ(pSrc);
1010       pSrc++;
1011       pSrc++;
1012       pSrc++;
1013       pSrc++;
1014     }
1015   }
1016 
1017   return HAL_OK;
1018 }
1019 
1020 /**
1021   * @brief  USB_ReadPacket : read a packet from the RX FIFO
1022   * @param  USBx  Selected device
1023   * @param  dest  source pointer
1024   * @param  len  Number of bytes to read
1025   * @retval pointer to destination buffer
1026   */
USB_ReadPacket(const USB_OTG_GlobalTypeDef * USBx,uint8_t * dest,uint16_t len)1027 void *USB_ReadPacket(const USB_OTG_GlobalTypeDef *USBx, uint8_t *dest, uint16_t len)
1028 {
1029   uint32_t USBx_BASE = (uint32_t)USBx;
1030   uint8_t *pDest = dest;
1031   uint32_t pData;
1032   uint32_t i;
1033   uint32_t count32b = (uint32_t)len >> 2U;
1034   uint16_t remaining_bytes = len % 4U;
1035 
1036   for (i = 0U; i < count32b; i++)
1037   {
1038     __UNALIGNED_UINT32_WRITE(pDest, USBx_DFIFO(0U));
1039     pDest++;
1040     pDest++;
1041     pDest++;
1042     pDest++;
1043   }
1044 
1045   /* When Number of data is not word aligned, read the remaining byte */
1046   if (remaining_bytes != 0U)
1047   {
1048     i = 0U;
1049     __UNALIGNED_UINT32_WRITE(&pData, USBx_DFIFO(0U));
1050 
1051     do
1052     {
1053       *(uint8_t *)pDest = (uint8_t)(pData >> (8U * (uint8_t)(i)));
1054       i++;
1055       pDest++;
1056       remaining_bytes--;
1057     } while (remaining_bytes != 0U);
1058   }
1059 
1060   return ((void *)pDest);
1061 }
1062 
1063 /**
1064   * @brief  USB_EPSetStall : set a stall condition over an EP
1065   * @param  USBx  Selected device
1066   * @param  ep pointer to endpoint structure
1067   * @retval HAL status
1068   */
USB_EPSetStall(const USB_OTG_GlobalTypeDef * USBx,const USB_OTG_EPTypeDef * ep)1069 HAL_StatusTypeDef USB_EPSetStall(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
1070 {
1071   uint32_t USBx_BASE = (uint32_t)USBx;
1072   uint32_t epnum = (uint32_t)ep->num;
1073 
1074   if (ep->is_in == 1U)
1075   {
1076     if (((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == 0U) && (epnum != 0U))
1077     {
1078       USBx_INEP(epnum)->DIEPCTL &= ~(USB_OTG_DIEPCTL_EPDIS);
1079     }
1080     USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_STALL;
1081   }
1082   else
1083   {
1084     if (((USBx_OUTEP(epnum)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == 0U) && (epnum != 0U))
1085     {
1086       USBx_OUTEP(epnum)->DOEPCTL &= ~(USB_OTG_DOEPCTL_EPDIS);
1087     }
1088     USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_STALL;
1089   }
1090 
1091   return HAL_OK;
1092 }
1093 
1094 /**
1095   * @brief  USB_EPClearStall : Clear a stall condition over an EP
1096   * @param  USBx  Selected device
1097   * @param  ep pointer to endpoint structure
1098   * @retval HAL status
1099   */
USB_EPClearStall(const USB_OTG_GlobalTypeDef * USBx,const USB_OTG_EPTypeDef * ep)1100 HAL_StatusTypeDef USB_EPClearStall(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
1101 {
1102   uint32_t USBx_BASE = (uint32_t)USBx;
1103   uint32_t epnum = (uint32_t)ep->num;
1104 
1105   if (ep->is_in == 1U)
1106   {
1107     USBx_INEP(epnum)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
1108     if ((ep->type == EP_TYPE_INTR) || (ep->type == EP_TYPE_BULK))
1109     {
1110       USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; /* DATA0 */
1111     }
1112   }
1113   else
1114   {
1115     USBx_OUTEP(epnum)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
1116     if ((ep->type == EP_TYPE_INTR) || (ep->type == EP_TYPE_BULK))
1117     {
1118       USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; /* DATA0 */
1119     }
1120   }
1121   return HAL_OK;
1122 }
1123 
1124 /**
1125   * @brief  USB_StopDevice : Stop the usb device mode
1126   * @param  USBx  Selected device
1127   * @retval HAL status
1128   */
USB_StopDevice(USB_OTG_GlobalTypeDef * USBx)1129 HAL_StatusTypeDef USB_StopDevice(USB_OTG_GlobalTypeDef *USBx)
1130 {
1131   HAL_StatusTypeDef ret;
1132   uint32_t USBx_BASE = (uint32_t)USBx;
1133   uint32_t i;
1134 
1135   /* Clear Pending interrupt */
1136   for (i = 0U; i < 15U; i++)
1137   {
1138     USBx_INEP(i)->DIEPINT = 0xFB7FU;
1139     USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
1140   }
1141 
1142   /* Clear interrupt masks */
1143   USBx_DEVICE->DIEPMSK  = 0U;
1144   USBx_DEVICE->DOEPMSK  = 0U;
1145   USBx_DEVICE->DAINTMSK = 0U;
1146 
1147   /* Flush the FIFO */
1148   ret = USB_FlushRxFifo(USBx);
1149   if (ret != HAL_OK)
1150   {
1151     return ret;
1152   }
1153 
1154   ret = USB_FlushTxFifo(USBx,  0x10U);
1155   if (ret != HAL_OK)
1156   {
1157     return ret;
1158   }
1159 
1160   return ret;
1161 }
1162 
1163 /**
1164   * @brief  USB_SetDevAddress : Stop the usb device mode
1165   * @param  USBx  Selected device
1166   * @param  address  new device address to be assigned
1167   *          This parameter can be a value from 0 to 255
1168   * @retval HAL status
1169   */
USB_SetDevAddress(const USB_OTG_GlobalTypeDef * USBx,uint8_t address)1170 HAL_StatusTypeDef USB_SetDevAddress(const USB_OTG_GlobalTypeDef *USBx, uint8_t address)
1171 {
1172   uint32_t USBx_BASE = (uint32_t)USBx;
1173 
1174   USBx_DEVICE->DCFG &= ~(USB_OTG_DCFG_DAD);
1175   USBx_DEVICE->DCFG |= ((uint32_t)address << 4) & USB_OTG_DCFG_DAD;
1176 
1177   return HAL_OK;
1178 }
1179 
1180 /**
1181   * @brief  USB_DevConnect : Connect the USB device by enabling Rpu
1182   * @param  USBx  Selected device
1183   * @retval HAL status
1184   */
USB_DevConnect(const USB_OTG_GlobalTypeDef * USBx)1185 HAL_StatusTypeDef USB_DevConnect(const USB_OTG_GlobalTypeDef *USBx)
1186 {
1187   uint32_t USBx_BASE = (uint32_t)USBx;
1188 
1189   /* In case phy is stopped, ensure to ungate and restore the phy CLK */
1190   USBx_PCGCCTL &= ~(USB_OTG_PCGCCTL_STOPCLK | USB_OTG_PCGCCTL_GATECLK);
1191 
1192   USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_SDIS;
1193 
1194   return HAL_OK;
1195 }
1196 
1197 /**
1198   * @brief  USB_DevDisconnect : Disconnect the USB device by disabling Rpu
1199   * @param  USBx  Selected device
1200   * @retval HAL status
1201   */
USB_DevDisconnect(const USB_OTG_GlobalTypeDef * USBx)1202 HAL_StatusTypeDef USB_DevDisconnect(const USB_OTG_GlobalTypeDef *USBx)
1203 {
1204   uint32_t USBx_BASE = (uint32_t)USBx;
1205 
1206   /* In case phy is stopped, ensure to ungate and restore the phy CLK */
1207   USBx_PCGCCTL &= ~(USB_OTG_PCGCCTL_STOPCLK | USB_OTG_PCGCCTL_GATECLK);
1208 
1209   USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS;
1210 
1211   return HAL_OK;
1212 }
1213 
1214 /**
1215   * @brief  USB_ReadInterrupts: return the global USB interrupt status
1216   * @param  USBx  Selected device
1217   * @retval USB Global Interrupt status
1218   */
USB_ReadInterrupts(USB_OTG_GlobalTypeDef const * USBx)1219 uint32_t USB_ReadInterrupts(USB_OTG_GlobalTypeDef const *USBx)
1220 {
1221   uint32_t tmpreg;
1222 
1223   tmpreg = USBx->GINTSTS;
1224   tmpreg &= USBx->GINTMSK;
1225 
1226   return tmpreg;
1227 }
1228 
1229 /**
1230   * @brief  USB_ReadChInterrupts: return USB channel interrupt status
1231   * @param  USBx  Selected device
1232   * @param  chnum Channel number
1233   * @retval USB Channel Interrupt status
1234   */
USB_ReadChInterrupts(const USB_OTG_GlobalTypeDef * USBx,uint8_t chnum)1235 uint32_t USB_ReadChInterrupts(const USB_OTG_GlobalTypeDef *USBx, uint8_t chnum)
1236 {
1237   uint32_t USBx_BASE = (uint32_t)USBx;
1238   uint32_t tmpreg;
1239 
1240   tmpreg = USBx_HC(chnum)->HCINT;
1241   tmpreg &= USBx_HC(chnum)->HCINTMSK;
1242 
1243   return tmpreg;
1244 }
1245 
1246 /**
1247   * @brief  USB_ReadDevAllOutEpInterrupt: return the USB device OUT endpoints interrupt status
1248   * @param  USBx  Selected device
1249   * @retval USB Device OUT EP interrupt status
1250   */
USB_ReadDevAllOutEpInterrupt(const USB_OTG_GlobalTypeDef * USBx)1251 uint32_t USB_ReadDevAllOutEpInterrupt(const USB_OTG_GlobalTypeDef *USBx)
1252 {
1253   uint32_t USBx_BASE = (uint32_t)USBx;
1254   uint32_t tmpreg;
1255 
1256   tmpreg  = USBx_DEVICE->DAINT;
1257   tmpreg &= USBx_DEVICE->DAINTMSK;
1258 
1259   return ((tmpreg & 0xffff0000U) >> 16);
1260 }
1261 
1262 /**
1263   * @brief  USB_ReadDevAllInEpInterrupt: return the USB device IN endpoints interrupt status
1264   * @param  USBx  Selected device
1265   * @retval USB Device IN EP interrupt status
1266   */
USB_ReadDevAllInEpInterrupt(const USB_OTG_GlobalTypeDef * USBx)1267 uint32_t USB_ReadDevAllInEpInterrupt(const USB_OTG_GlobalTypeDef *USBx)
1268 {
1269   uint32_t USBx_BASE = (uint32_t)USBx;
1270   uint32_t tmpreg;
1271 
1272   tmpreg  = USBx_DEVICE->DAINT;
1273   tmpreg &= USBx_DEVICE->DAINTMSK;
1274 
1275   return ((tmpreg & 0xFFFFU));
1276 }
1277 
1278 /**
1279   * @brief  Returns Device OUT EP Interrupt register
1280   * @param  USBx  Selected device
1281   * @param  epnum  endpoint number
1282   *          This parameter can be a value from 0 to 15
1283   * @retval Device OUT EP Interrupt register
1284   */
USB_ReadDevOutEPInterrupt(const USB_OTG_GlobalTypeDef * USBx,uint8_t epnum)1285 uint32_t USB_ReadDevOutEPInterrupt(const USB_OTG_GlobalTypeDef *USBx, uint8_t epnum)
1286 {
1287   uint32_t USBx_BASE = (uint32_t)USBx;
1288   uint32_t tmpreg;
1289 
1290   tmpreg  = USBx_OUTEP((uint32_t)epnum)->DOEPINT;
1291   tmpreg &= USBx_DEVICE->DOEPMSK;
1292 
1293   return tmpreg;
1294 }
1295 
1296 /**
1297   * @brief  Returns Device IN EP Interrupt register
1298   * @param  USBx  Selected device
1299   * @param  epnum  endpoint number
1300   *          This parameter can be a value from 0 to 15
1301   * @retval Device IN EP Interrupt register
1302   */
USB_ReadDevInEPInterrupt(const USB_OTG_GlobalTypeDef * USBx,uint8_t epnum)1303 uint32_t USB_ReadDevInEPInterrupt(const USB_OTG_GlobalTypeDef *USBx, uint8_t epnum)
1304 {
1305   uint32_t USBx_BASE = (uint32_t)USBx;
1306   uint32_t tmpreg;
1307   uint32_t msk;
1308   uint32_t emp;
1309 
1310   msk = USBx_DEVICE->DIEPMSK;
1311   emp = USBx_DEVICE->DIEPEMPMSK;
1312   msk |= ((emp >> (epnum & EP_ADDR_MSK)) & 0x1U) << 7;
1313   tmpreg = USBx_INEP((uint32_t)epnum)->DIEPINT & msk;
1314 
1315   return tmpreg;
1316 }
1317 
1318 /**
1319   * @brief  USB_ClearInterrupts: clear a USB interrupt
1320   * @param  USBx  Selected device
1321   * @param  interrupt  flag
1322   * @retval None
1323   */
USB_ClearInterrupts(USB_OTG_GlobalTypeDef * USBx,uint32_t interrupt)1324 void  USB_ClearInterrupts(USB_OTG_GlobalTypeDef *USBx, uint32_t interrupt)
1325 {
1326   USBx->GINTSTS &= interrupt;
1327 }
1328 
1329 /**
1330   * @brief  Returns USB core mode
1331   * @param  USBx  Selected device
1332   * @retval return core mode : Host or Device
1333   *          This parameter can be one of these values:
1334   *           0 : Host
1335   *           1 : Device
1336   */
USB_GetMode(const USB_OTG_GlobalTypeDef * USBx)1337 uint32_t USB_GetMode(const USB_OTG_GlobalTypeDef *USBx)
1338 {
1339   return ((USBx->GINTSTS) & 0x1U);
1340 }
1341 
1342 /**
1343   * @brief  Activate EP0 for Setup transactions
1344   * @param  USBx  Selected device
1345   * @retval HAL status
1346   */
USB_ActivateSetup(const USB_OTG_GlobalTypeDef * USBx)1347 HAL_StatusTypeDef USB_ActivateSetup(const USB_OTG_GlobalTypeDef *USBx)
1348 {
1349   uint32_t USBx_BASE = (uint32_t)USBx;
1350 
1351   /* Set the MPS of the IN EP0 to 64 bytes */
1352   USBx_INEP(0U)->DIEPCTL &= ~USB_OTG_DIEPCTL_MPSIZ;
1353 
1354   USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGINAK;
1355 
1356   return HAL_OK;
1357 }
1358 
1359 /**
1360   * @brief  Prepare the EP0 to start the first control setup
1361   * @param  USBx  Selected device
1362   * @param  dma USB dma enabled or disabled
1363   *          This parameter can be one of these values:
1364   *           0 : DMA feature not used
1365   *           1 : DMA feature used
1366   * @param  psetup  pointer to setup packet
1367   * @retval HAL status
1368   */
USB_EP0_OutStart(const USB_OTG_GlobalTypeDef * USBx,uint8_t dma,const uint8_t * psetup)1369 HAL_StatusTypeDef USB_EP0_OutStart(const USB_OTG_GlobalTypeDef *USBx, uint8_t dma, const uint8_t *psetup)
1370 {
1371   uint32_t USBx_BASE = (uint32_t)USBx;
1372   uint32_t gSNPSiD = *(__IO const uint32_t *)(&USBx->CID + 0x1U);
1373 
1374   if (gSNPSiD > USB_OTG_CORE_ID_300A)
1375   {
1376     if ((USBx_OUTEP(0U)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
1377     {
1378       return HAL_OK;
1379     }
1380   }
1381 
1382   USBx_OUTEP(0U)->DOEPTSIZ = 0U;
1383   USBx_OUTEP(0U)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1U << 19));
1384   USBx_OUTEP(0U)->DOEPTSIZ |= (3U * 8U);
1385   USBx_OUTEP(0U)->DOEPTSIZ |=  USB_OTG_DOEPTSIZ_STUPCNT;
1386 
1387   if (dma == 1U)
1388   {
1389     USBx_OUTEP(0U)->DOEPDMA = (uint32_t)psetup;
1390     /* EP enable */
1391     USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_USBAEP;
1392   }
1393 
1394   return HAL_OK;
1395 }
1396 
1397 /**
1398   * @brief  Reset the USB Core (needed after USB clock settings change)
1399   * @param  USBx  Selected device
1400   * @retval HAL status
1401   */
USB_CoreReset(USB_OTG_GlobalTypeDef * USBx)1402 static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx)
1403 {
1404   __IO uint32_t count = 0U;
1405 
1406   /* Wait for AHB master IDLE state. */
1407   do
1408   {
1409     count++;
1410 
1411     if (count > HAL_USB_TIMEOUT)
1412     {
1413       return HAL_TIMEOUT;
1414     }
1415   } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
1416 
1417   /* Core Soft Reset */
1418   count = 0U;
1419   USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
1420 
1421   do
1422   {
1423     count++;
1424 
1425     if (count > HAL_USB_TIMEOUT)
1426     {
1427       return HAL_TIMEOUT;
1428     }
1429   } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);
1430 
1431   return HAL_OK;
1432 }
1433 
1434 /**
1435   * @brief  USB_HostInit : Initializes the USB OTG controller registers
1436   *         for Host mode
1437   * @param  USBx  Selected device
1438   * @param  cfg   pointer to a USB_OTG_CfgTypeDef structure that contains
1439   *         the configuration information for the specified USBx peripheral.
1440   * @retval HAL status
1441   */
USB_HostInit(USB_OTG_GlobalTypeDef * USBx,USB_OTG_CfgTypeDef cfg)1442 HAL_StatusTypeDef USB_HostInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
1443 {
1444   HAL_StatusTypeDef ret = HAL_OK;
1445   uint32_t USBx_BASE = (uint32_t)USBx;
1446   uint32_t i;
1447 
1448 #if defined (STM32U595xx) || defined (STM32U5A5xx) || defined (STM32U599xx) || defined (STM32U5A9xx) \
1449  || defined (STM32U5F7xx) || defined (STM32U5G7xx) || defined (STM32U5F9xx) || defined (STM32U5G9xx)
1450   /* Enable USB PHY pulldown resistors */
1451   USBx->GCCFG |= USB_OTG_GCCFG_PULLDOWNEN;
1452 #endif /* defined (STM32U595xx) || defined (STM32U5A5xx) || defined (STM32U599xx) || defined (STM32U5A9xx) ||
1453           defined (STM32U5F7xx) || defined (STM32U5G7xx) || defined (STM32U5F9xx) || defined (STM32U5G9xx) */
1454 
1455   /* Restart the Phy Clock */
1456   USBx_PCGCCTL = 0U;
1457 
1458 #if defined (STM32U595xx) || defined (STM32U5A5xx) || defined (STM32U599xx) || defined (STM32U5A9xx) \
1459  || defined (STM32U5F7xx) || defined (STM32U5G7xx) || defined (STM32U5F9xx) || defined (STM32U5G9xx)
1460   /* Disable VBUS override */
1461   USBx->GCCFG &= ~(USB_OTG_GCCFG_VBVALOVAL | USB_OTG_GCCFG_VBVALEXTOEN);
1462 #endif /* defined (STM32U595xx) || defined (STM32U5A5xx) || defined (STM32U599xx) || defined (STM32U5A9xx) ||
1463           defined (STM32U5F7xx) || defined (STM32U5G7xx) || defined (STM32U5F9xx) || defined (STM32U5G9xx) */
1464 
1465   /* Disable VBUS sensing */
1466   USBx->GCCFG &= ~(USB_OTG_GCCFG_VBDEN);
1467 #if defined (STM32U575xx) || defined (STM32U585xx)
1468   /* Disable Battery chargin detector */
1469   USBx->GCCFG &= ~(USB_OTG_GCCFG_BCDEN);
1470 #else
1471   /* Disable Battery chargin detector */
1472   USBx->GCCFG &= ~(USB_OTG_GCCFG_PDEN);
1473   USBx->GCCFG &= ~(USB_OTG_GCCFG_SDEN);
1474 #endif /* defined (STM32U575xx) || defined (STM32U585xx) */
1475 
1476   if ((USBx->GUSBCFG & USB_OTG_GUSBCFG_PHYSEL) == 0U)
1477   {
1478     if (cfg.speed == USBH_FSLS_SPEED)
1479     {
1480       /* Force Device Enumeration to FS/LS mode only */
1481       USBx_HOST->HCFG |= USB_OTG_HCFG_FSLSS;
1482     }
1483     else
1484     {
1485       /* Set default Max speed support */
1486       USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS);
1487     }
1488   }
1489   else
1490   {
1491     /* Set default Max speed support */
1492     USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS);
1493   }
1494 
1495   /* Make sure the FIFOs are flushed. */
1496   if (USB_FlushTxFifo(USBx, 0x10U) != HAL_OK) /* all Tx FIFOs */
1497   {
1498     ret = HAL_ERROR;
1499   }
1500 
1501   if (USB_FlushRxFifo(USBx) != HAL_OK)
1502   {
1503     ret = HAL_ERROR;
1504   }
1505 
1506   /* Clear all pending HC Interrupts */
1507   for (i = 0U; i < cfg.Host_channels; i++)
1508   {
1509     USBx_HC(i)->HCINT = CLEAR_INTERRUPT_MASK;
1510     USBx_HC(i)->HCINTMSK = 0U;
1511   }
1512 
1513   /* Disable all interrupts. */
1514   USBx->GINTMSK = 0U;
1515 
1516   /* Clear any pending interrupts */
1517   USBx->GINTSTS = CLEAR_INTERRUPT_MASK;
1518 #if defined (USB_OTG_HS)
1519   if (USBx == USB_OTG_HS)
1520   {
1521     /* set Rx FIFO size */
1522     USBx->GRXFSIZ  = 0x200U;
1523     USBx->DIEPTXF0_HNPTXFSIZ = (uint32_t)(((0x100U << 16) & USB_OTG_NPTXFD) | 0x200U);
1524     USBx->HPTXFSIZ = (uint32_t)(((0xE0U << 16) & USB_OTG_HPTXFSIZ_PTXFD) | 0x300U);
1525   }
1526   else
1527 #endif /* defined (USB_OTG_HS) */
1528   {
1529     /* set Rx FIFO size */
1530     USBx->GRXFSIZ  = 0x80U;
1531     USBx->DIEPTXF0_HNPTXFSIZ = (uint32_t)(((0x60U << 16) & USB_OTG_NPTXFD) | 0x80U);
1532     USBx->HPTXFSIZ = (uint32_t)(((0x40U << 16)& USB_OTG_HPTXFSIZ_PTXFD) | 0xE0U);
1533   }
1534 
1535   /* Enable the common interrupts */
1536   if (cfg.dma_enable == 0U)
1537   {
1538     USBx->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
1539   }
1540 
1541   /* Enable interrupts matching to the Host mode ONLY */
1542   USBx->GINTMSK |= (USB_OTG_GINTMSK_PRTIM            | USB_OTG_GINTMSK_HCIM | \
1543                     USB_OTG_GINTMSK_SOFM             | USB_OTG_GINTSTS_DISCINT | \
1544                     USB_OTG_GINTMSK_PXFRM_IISOOXFRM  | USB_OTG_GINTMSK_WUIM);
1545 
1546   return ret;
1547 }
1548 
1549 /**
1550   * @brief  USB_InitFSLSPClkSel : Initializes the FSLSPClkSel field of the
1551   *         HCFG register on the PHY type and set the right frame interval
1552   * @param  USBx  Selected device
1553   * @param  freq  clock frequency
1554   *          This parameter can be one of these values:
1555   *           HCFG_48_MHZ : Full Speed 48 MHz Clock
1556   *           HCFG_6_MHZ : Low Speed 6 MHz Clock
1557   * @retval HAL status
1558   */
USB_InitFSLSPClkSel(const USB_OTG_GlobalTypeDef * USBx,uint8_t freq)1559 HAL_StatusTypeDef USB_InitFSLSPClkSel(const USB_OTG_GlobalTypeDef *USBx, uint8_t freq)
1560 {
1561   uint32_t USBx_BASE = (uint32_t)USBx;
1562 
1563   USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSPCS);
1564   USBx_HOST->HCFG |= (uint32_t)freq & USB_OTG_HCFG_FSLSPCS;
1565 
1566   if (freq == HCFG_48_MHZ)
1567   {
1568     USBx_HOST->HFIR = HFIR_48_MHZ;
1569   }
1570   else if (freq == HCFG_6_MHZ)
1571   {
1572     USBx_HOST->HFIR = HFIR_6_MHZ;
1573   }
1574   else
1575   {
1576     return HAL_ERROR;
1577   }
1578 
1579   return HAL_OK;
1580 }
1581 
1582 /**
1583   * @brief  USB_OTG_ResetPort : Reset Host Port
1584   * @param  USBx  Selected device
1585   * @retval HAL status
1586   * @note (1)The application must wait at least 10 ms
1587   *   before clearing the reset bit.
1588   */
USB_ResetPort(const USB_OTG_GlobalTypeDef * USBx)1589 HAL_StatusTypeDef USB_ResetPort(const USB_OTG_GlobalTypeDef *USBx)
1590 {
1591   uint32_t USBx_BASE = (uint32_t)USBx;
1592 
1593   __IO uint32_t hprt0 = 0U;
1594 
1595   hprt0 = USBx_HPRT0;
1596 
1597   hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |
1598              USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
1599 
1600   USBx_HPRT0 = (USB_OTG_HPRT_PRST | hprt0);
1601   HAL_Delay(100U);                                 /* See Note #1 */
1602   USBx_HPRT0 = ((~USB_OTG_HPRT_PRST) & hprt0);
1603   HAL_Delay(10U);
1604 
1605   return HAL_OK;
1606 }
1607 
1608 /**
1609   * @brief  USB_DriveVbus : activate or de-activate vbus
1610   * @param  state  VBUS state
1611   *          This parameter can be one of these values:
1612   *           0 : Deactivate VBUS
1613   *           1 : Activate VBUS
1614   * @retval HAL status
1615   */
USB_DriveVbus(const USB_OTG_GlobalTypeDef * USBx,uint8_t state)1616 HAL_StatusTypeDef USB_DriveVbus(const USB_OTG_GlobalTypeDef *USBx, uint8_t state)
1617 {
1618   uint32_t USBx_BASE = (uint32_t)USBx;
1619   __IO uint32_t hprt0 = 0U;
1620 
1621   hprt0 = USBx_HPRT0;
1622 
1623   hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |
1624              USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
1625 
1626   if (((hprt0 & USB_OTG_HPRT_PPWR) == 0U) && (state == 1U))
1627   {
1628     USBx_HPRT0 = (USB_OTG_HPRT_PPWR | hprt0);
1629   }
1630   if (((hprt0 & USB_OTG_HPRT_PPWR) == USB_OTG_HPRT_PPWR) && (state == 0U))
1631   {
1632     USBx_HPRT0 = ((~USB_OTG_HPRT_PPWR) & hprt0);
1633   }
1634   return HAL_OK;
1635 }
1636 
1637 /**
1638   * @brief  Return Host Core speed
1639   * @param  USBx  Selected device
1640   * @retval speed : Host speed
1641   *          This parameter can be one of these values:
1642   *            @arg HCD_SPEED_HIGH: High speed mode
1643   *            @arg HCD_SPEED_FULL: Full speed mode
1644   *            @arg HCD_SPEED_LOW: Low speed mode
1645   */
USB_GetHostSpeed(USB_OTG_GlobalTypeDef const * USBx)1646 uint32_t USB_GetHostSpeed(USB_OTG_GlobalTypeDef const *USBx)
1647 {
1648   uint32_t USBx_BASE = (uint32_t)USBx;
1649   __IO uint32_t hprt0 = 0U;
1650 
1651   hprt0 = USBx_HPRT0;
1652   return ((hprt0 & USB_OTG_HPRT_PSPD) >> 17);
1653 }
1654 
1655 /**
1656   * @brief  Return Host Current Frame number
1657   * @param  USBx  Selected device
1658   * @retval current frame number
1659   */
USB_GetCurrentFrame(USB_OTG_GlobalTypeDef const * USBx)1660 uint32_t USB_GetCurrentFrame(USB_OTG_GlobalTypeDef const *USBx)
1661 {
1662   uint32_t USBx_BASE = (uint32_t)USBx;
1663 
1664   return (USBx_HOST->HFNUM & USB_OTG_HFNUM_FRNUM);
1665 }
1666 
1667 /**
1668   * @brief  Initialize a host channel
1669   * @param  USBx  Selected device
1670   * @param  ch_num  Channel number
1671   *         This parameter can be a value from 1 to 15
1672   * @param  epnum  Endpoint number
1673   *          This parameter can be a value from 1 to 15
1674   * @param  dev_address  Current device address
1675   *          This parameter can be a value from 0 to 255
1676   * @param  speed  Current device speed
1677   *          This parameter can be one of these values:
1678   *            @arg USB_OTG_SPEED_HIGH: High speed mode
1679   *            @arg USB_OTG_SPEED_FULL: Full speed mode
1680   *            @arg USB_OTG_SPEED_LOW: Low speed mode
1681   * @param  ep_type  Endpoint Type
1682   *          This parameter can be one of these values:
1683   *            @arg EP_TYPE_CTRL: Control type
1684   *            @arg EP_TYPE_ISOC: Isochronous type
1685   *            @arg EP_TYPE_BULK: Bulk type
1686   *            @arg EP_TYPE_INTR: Interrupt type
1687   * @param  mps  Max Packet Size
1688   *          This parameter can be a value from 0 to 32K
1689   * @retval HAL state
1690   */
USB_HC_Init(USB_OTG_GlobalTypeDef * USBx,uint8_t ch_num,uint8_t epnum,uint8_t dev_address,uint8_t speed,uint8_t ep_type,uint16_t mps)1691 HAL_StatusTypeDef USB_HC_Init(USB_OTG_GlobalTypeDef *USBx, uint8_t ch_num,
1692                               uint8_t epnum, uint8_t dev_address, uint8_t speed,
1693                               uint8_t ep_type, uint16_t mps)
1694 {
1695   HAL_StatusTypeDef ret = HAL_OK;
1696   uint32_t USBx_BASE = (uint32_t)USBx;
1697   uint32_t HCcharEpDir;
1698   uint32_t HCcharLowSpeed;
1699   uint32_t HostCoreSpeed;
1700 
1701   /* Clear old interrupt conditions for this host channel. */
1702   USBx_HC((uint32_t)ch_num)->HCINT = CLEAR_INTERRUPT_MASK;
1703 
1704   /* Enable channel interrupts required for this transfer. */
1705   switch (ep_type)
1706   {
1707     case EP_TYPE_CTRL:
1708     case EP_TYPE_BULK:
1709       USBx_HC((uint32_t)ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM  |
1710                                             USB_OTG_HCINTMSK_STALLM |
1711                                             USB_OTG_HCINTMSK_TXERRM |
1712                                             USB_OTG_HCINTMSK_DTERRM |
1713                                             USB_OTG_HCINTMSK_AHBERR |
1714                                             USB_OTG_HCINTMSK_NAKM;
1715 
1716       if ((epnum & 0x80U) == 0x80U)
1717       {
1718         USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM;
1719       }
1720       else
1721       {
1722 #if defined (USB_OTG_HS)
1723         if (USBx == USB_OTG_HS)
1724         {
1725           USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_NYET |
1726                                                  USB_OTG_HCINTMSK_ACKM;
1727         }
1728 #endif /* defined (USB_OTG_HS) */
1729       }
1730       break;
1731 
1732     case EP_TYPE_INTR:
1733       USBx_HC((uint32_t)ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM  |
1734                                             USB_OTG_HCINTMSK_STALLM |
1735                                             USB_OTG_HCINTMSK_TXERRM |
1736                                             USB_OTG_HCINTMSK_DTERRM |
1737                                             USB_OTG_HCINTMSK_NAKM   |
1738                                             USB_OTG_HCINTMSK_AHBERR |
1739                                             USB_OTG_HCINTMSK_FRMORM;
1740 
1741       if ((epnum & 0x80U) == 0x80U)
1742       {
1743         USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM;
1744       }
1745 
1746       break;
1747 
1748     case EP_TYPE_ISOC:
1749       USBx_HC((uint32_t)ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM  |
1750                                             USB_OTG_HCINTMSK_ACKM   |
1751                                             USB_OTG_HCINTMSK_AHBERR |
1752                                             USB_OTG_HCINTMSK_FRMORM;
1753 
1754       if ((epnum & 0x80U) == 0x80U)
1755       {
1756         USBx_HC((uint32_t)ch_num)->HCINTMSK |= (USB_OTG_HCINTMSK_TXERRM | USB_OTG_HCINTMSK_BBERRM);
1757       }
1758       break;
1759 
1760     default:
1761       ret = HAL_ERROR;
1762       break;
1763   }
1764 
1765   /* Clear Hub Start Split transaction */
1766   USBx_HC((uint32_t)ch_num)->HCSPLT = 0U;
1767 
1768   /* Enable host channel Halt interrupt */
1769   USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_CHHM;
1770 
1771   /* Enable the top level host channel interrupt. */
1772   USBx_HOST->HAINTMSK |= 1UL << (ch_num & 0xFU);
1773 
1774   /* Make sure host channel interrupts are enabled. */
1775   USBx->GINTMSK |= USB_OTG_GINTMSK_HCIM;
1776 
1777   /* Program the HCCHAR register */
1778   if ((epnum & 0x80U) == 0x80U)
1779   {
1780     HCcharEpDir = (0x1U << 15) & USB_OTG_HCCHAR_EPDIR;
1781   }
1782   else
1783   {
1784     HCcharEpDir = 0U;
1785   }
1786 
1787   HostCoreSpeed = USB_GetHostSpeed(USBx);
1788 
1789   /* LS device plugged to HUB */
1790   if ((speed == HPRT0_PRTSPD_LOW_SPEED) && (HostCoreSpeed != HPRT0_PRTSPD_LOW_SPEED))
1791   {
1792     HCcharLowSpeed = (0x1U << 17) & USB_OTG_HCCHAR_LSDEV;
1793   }
1794   else
1795   {
1796     HCcharLowSpeed = 0U;
1797   }
1798 
1799   USBx_HC((uint32_t)ch_num)->HCCHAR = (((uint32_t)dev_address << 22) & USB_OTG_HCCHAR_DAD) |
1800                                       ((((uint32_t)epnum & 0x7FU) << 11) & USB_OTG_HCCHAR_EPNUM) |
1801                                       (((uint32_t)ep_type << 18) & USB_OTG_HCCHAR_EPTYP) |
1802                                       ((uint32_t)mps & USB_OTG_HCCHAR_MPSIZ) |
1803                                       USB_OTG_HCCHAR_MC_0 | HCcharEpDir | HCcharLowSpeed;
1804 
1805   if ((ep_type == EP_TYPE_INTR) || (ep_type == EP_TYPE_ISOC))
1806   {
1807     USBx_HC((uint32_t)ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
1808   }
1809 
1810   return ret;
1811 }
1812 
1813 /**
1814   * @brief  Start a transfer over a host channel
1815   * @param  USBx  Selected device
1816   * @param  hc  pointer to host channel structure
1817   * @param  dma USB dma enabled or disabled
1818   *          This parameter can be one of these values:
1819   *           0 : DMA feature not used
1820   *           1 : DMA feature used
1821   * @retval HAL state
1822   */
USB_HC_StartXfer(USB_OTG_GlobalTypeDef * USBx,USB_OTG_HCTypeDef * hc,uint8_t dma)1823 HAL_StatusTypeDef USB_HC_StartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_HCTypeDef *hc, uint8_t dma)
1824 {
1825   uint32_t USBx_BASE = (uint32_t)USBx;
1826   uint32_t ch_num = (uint32_t)hc->ch_num;
1827   __IO uint32_t tmpreg;
1828   uint8_t  is_oddframe;
1829   uint16_t len_words;
1830   uint16_t num_packets;
1831   uint16_t max_hc_pkt_count = HC_MAX_PKT_CNT;
1832 
1833 #if defined (USB_OTG_HS)
1834   if (USBx == USB_OTG_HS)
1835   {
1836     /* in DMA mode host Core automatically issues ping in case of NYET/NAK */
1837     if (dma == 1U)
1838     {
1839       if (((hc->ep_type == EP_TYPE_CTRL) || (hc->ep_type == EP_TYPE_BULK)) && (hc->do_ssplit == 0U))
1840       {
1841 
1842         USBx_HC((uint32_t)ch_num)->HCINTMSK &= ~(USB_OTG_HCINTMSK_NYET |
1843                                                  USB_OTG_HCINTMSK_ACKM |
1844                                                  USB_OTG_HCINTMSK_NAKM);
1845       }
1846     }
1847     else
1848     {
1849       if ((hc->speed == USBH_HS_SPEED) && (hc->do_ping == 1U))
1850       {
1851         (void)USB_DoPing(USBx, hc->ch_num);
1852         return HAL_OK;
1853       }
1854     }
1855   }
1856 #endif /* defined (USB_OTG_HS) */
1857 
1858   if (hc->do_ssplit == 1U)
1859   {
1860     /* Set number of packet to 1 for Split transaction */
1861     num_packets = 1U;
1862 
1863     if (hc->ep_is_in != 0U)
1864     {
1865       hc->XferSize = (uint32_t)num_packets * hc->max_packet;
1866     }
1867     else
1868     {
1869       if (hc->ep_type == EP_TYPE_ISOC)
1870       {
1871         if (hc->xfer_len > ISO_SPLT_MPS)
1872         {
1873           /* Isochrone Max Packet Size for Split mode */
1874           hc->XferSize = hc->max_packet;
1875           hc->xfer_len = hc->XferSize;
1876 
1877           if ((hc->iso_splt_xactPos == HCSPLT_BEGIN) || (hc->iso_splt_xactPos == HCSPLT_MIDDLE))
1878           {
1879             hc->iso_splt_xactPos = HCSPLT_MIDDLE;
1880           }
1881           else
1882           {
1883             hc->iso_splt_xactPos = HCSPLT_BEGIN;
1884           }
1885         }
1886         else
1887         {
1888           hc->XferSize = hc->xfer_len;
1889 
1890           if ((hc->iso_splt_xactPos != HCSPLT_BEGIN) && (hc->iso_splt_xactPos != HCSPLT_MIDDLE))
1891           {
1892             hc->iso_splt_xactPos = HCSPLT_FULL;
1893           }
1894           else
1895           {
1896             hc->iso_splt_xactPos = HCSPLT_END;
1897           }
1898         }
1899       }
1900       else
1901       {
1902         if ((dma == 1U) && (hc->xfer_len > hc->max_packet))
1903         {
1904           hc->XferSize = (uint32_t)num_packets * hc->max_packet;
1905         }
1906         else
1907         {
1908           hc->XferSize = hc->xfer_len;
1909         }
1910       }
1911     }
1912   }
1913   else
1914   {
1915     /* Compute the expected number of packets associated to the transfer */
1916     if (hc->xfer_len > 0U)
1917     {
1918       num_packets = (uint16_t)((hc->xfer_len + hc->max_packet - 1U) / hc->max_packet);
1919 
1920       if (num_packets > max_hc_pkt_count)
1921       {
1922         num_packets = max_hc_pkt_count;
1923         hc->XferSize = (uint32_t)num_packets * hc->max_packet;
1924       }
1925     }
1926     else
1927     {
1928       num_packets = 1U;
1929     }
1930 
1931     /*
1932     * For IN channel HCTSIZ.XferSize is expected to be an integer multiple of
1933     * max_packet size.
1934     */
1935     if (hc->ep_is_in != 0U)
1936     {
1937       hc->XferSize = (uint32_t)num_packets * hc->max_packet;
1938     }
1939     else
1940     {
1941       hc->XferSize = hc->xfer_len;
1942     }
1943   }
1944 
1945   /* Initialize the HCTSIZn register */
1946   USBx_HC(ch_num)->HCTSIZ = (hc->XferSize & USB_OTG_HCTSIZ_XFRSIZ) |
1947                             (((uint32_t)num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |
1948                             (((uint32_t)hc->data_pid << 29) & USB_OTG_HCTSIZ_DPID);
1949 
1950   if (dma != 0U)
1951   {
1952     /* xfer_buff MUST be 32-bits aligned */
1953     USBx_HC(ch_num)->HCDMA = (uint32_t)hc->xfer_buff;
1954   }
1955 
1956   is_oddframe = (((uint32_t)USBx_HOST->HFNUM & 0x01U) != 0U) ? 0U : 1U;
1957   USBx_HC(ch_num)->HCCHAR &= ~USB_OTG_HCCHAR_ODDFRM;
1958   USBx_HC(ch_num)->HCCHAR |= (uint32_t)is_oddframe << 29;
1959 
1960   if (hc->do_ssplit == 1U)
1961   {
1962     /* Set Hub start Split transaction */
1963     USBx_HC((uint32_t)ch_num)->HCSPLT = ((uint32_t)hc->hub_addr << USB_OTG_HCSPLT_HUBADDR_Pos) |
1964                                         (uint32_t)hc->hub_port_nbr | USB_OTG_HCSPLT_SPLITEN;
1965 
1966     /* unmask ack & nyet for IN/OUT transactions */
1967     USBx_HC((uint32_t)ch_num)->HCINTMSK |= (USB_OTG_HCINTMSK_ACKM |
1968                                             USB_OTG_HCINTMSK_NYET);
1969 
1970     if ((hc->do_csplit == 1U) && (hc->ep_is_in == 0U))
1971     {
1972       USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_COMPLSPLT;
1973       USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_NYET;
1974     }
1975 
1976     if (((hc->ep_type == EP_TYPE_ISOC) || (hc->ep_type == EP_TYPE_INTR)) &&
1977         (hc->do_csplit == 1U) && (hc->ep_is_in == 1U))
1978     {
1979       USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_COMPLSPLT;
1980     }
1981 
1982     /* Position management for iso out transaction on split mode */
1983     if ((hc->ep_type == EP_TYPE_ISOC) && (hc->ep_is_in == 0U))
1984     {
1985       /* Set data payload position */
1986       switch (hc->iso_splt_xactPos)
1987       {
1988         case HCSPLT_BEGIN:
1989           /* First data payload for OUT Transaction */
1990           USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_XACTPOS_1;
1991           break;
1992 
1993         case HCSPLT_MIDDLE:
1994           /* Middle data payload for OUT Transaction */
1995           USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_XACTPOS_Pos;
1996           break;
1997 
1998         case HCSPLT_END:
1999           /* End data payload for OUT Transaction */
2000           USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_XACTPOS_0;
2001           break;
2002 
2003         case HCSPLT_FULL:
2004           /* Entire data payload for OUT Transaction */
2005           USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_XACTPOS;
2006           break;
2007 
2008         default:
2009           break;
2010       }
2011     }
2012   }
2013   else
2014   {
2015     /* Clear Hub Start Split transaction */
2016     USBx_HC((uint32_t)ch_num)->HCSPLT = 0U;
2017   }
2018 
2019   /* Set host channel enable */
2020   tmpreg = USBx_HC(ch_num)->HCCHAR;
2021   tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
2022 
2023   /* make sure to set the correct ep direction */
2024   if (hc->ep_is_in != 0U)
2025   {
2026     tmpreg |= USB_OTG_HCCHAR_EPDIR;
2027   }
2028   else
2029   {
2030     tmpreg &= ~USB_OTG_HCCHAR_EPDIR;
2031   }
2032   tmpreg |= USB_OTG_HCCHAR_CHENA;
2033   USBx_HC(ch_num)->HCCHAR = tmpreg;
2034 
2035   if (dma != 0U) /* dma mode */
2036   {
2037     return HAL_OK;
2038   }
2039 
2040   if ((hc->ep_is_in == 0U) && (hc->xfer_len > 0U) && (hc->do_csplit == 0U))
2041   {
2042     switch (hc->ep_type)
2043     {
2044       /* Non periodic transfer */
2045       case EP_TYPE_CTRL:
2046       case EP_TYPE_BULK:
2047 
2048         len_words = (uint16_t)((hc->xfer_len + 3U) / 4U);
2049 
2050         /* check if there is enough space in FIFO space */
2051         if (len_words > (USBx->HNPTXSTS & 0xFFFFU))
2052         {
2053           /* need to process data in nptxfempty interrupt */
2054           USBx->GINTMSK |= USB_OTG_GINTMSK_NPTXFEM;
2055         }
2056         break;
2057 
2058       /* Periodic transfer */
2059       case EP_TYPE_INTR:
2060       case EP_TYPE_ISOC:
2061         len_words = (uint16_t)((hc->xfer_len + 3U) / 4U);
2062         /* check if there is enough space in FIFO space */
2063         if (len_words > (USBx_HOST->HPTXSTS & 0xFFFFU)) /* split the transfer */
2064         {
2065           /* need to process data in ptxfempty interrupt */
2066           USBx->GINTMSK |= USB_OTG_GINTMSK_PTXFEM;
2067         }
2068         break;
2069 
2070       default:
2071         break;
2072     }
2073 
2074     /* Write packet into the Tx FIFO. */
2075     (void)USB_WritePacket(USBx, hc->xfer_buff, hc->ch_num, (uint16_t)hc->xfer_len, 0);
2076   }
2077 
2078   return HAL_OK;
2079 }
2080 
2081 /**
2082   * @brief Read all host channel interrupts status
2083   * @param  USBx  Selected device
2084   * @retval HAL state
2085   */
USB_HC_ReadInterrupt(const USB_OTG_GlobalTypeDef * USBx)2086 uint32_t USB_HC_ReadInterrupt(const USB_OTG_GlobalTypeDef *USBx)
2087 {
2088   uint32_t USBx_BASE = (uint32_t)USBx;
2089 
2090   return ((USBx_HOST->HAINT) & 0xFFFFU);
2091 }
2092 
2093 /**
2094   * @brief  Halt a host channel
2095   * @param  USBx  Selected device
2096   * @param  hc_num  Host Channel number
2097   *         This parameter can be a value from 1 to 15
2098   * @retval HAL state
2099   */
USB_HC_Halt(const USB_OTG_GlobalTypeDef * USBx,uint8_t hc_num)2100 HAL_StatusTypeDef USB_HC_Halt(const USB_OTG_GlobalTypeDef *USBx, uint8_t hc_num)
2101 {
2102   uint32_t USBx_BASE = (uint32_t)USBx;
2103   uint32_t hcnum = (uint32_t)hc_num;
2104   __IO uint32_t count = 0U;
2105   uint32_t HcEpType = (USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_EPTYP) >> 18;
2106   uint32_t ChannelEna = (USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_CHENA) >> 31;
2107   uint32_t SplitEna = (USBx_HC(hcnum)->HCSPLT & USB_OTG_HCSPLT_SPLITEN) >> 31;
2108 
2109   /* In buffer DMA, Channel disable must not be programmed for non-split periodic channels.
2110      At the end of the next uframe/frame (in the worst case), the core generates a channel halted
2111      and disables the channel automatically. */
2112 
2113   if ((((USBx->GAHBCFG & USB_OTG_GAHBCFG_DMAEN) == USB_OTG_GAHBCFG_DMAEN) && (SplitEna == 0U)) &&
2114       ((ChannelEna == 0U) || (((HcEpType == HCCHAR_ISOC) || (HcEpType == HCCHAR_INTR)))))
2115   {
2116     return HAL_OK;
2117   }
2118 
2119   /* Check for space in the request queue to issue the halt. */
2120   if ((HcEpType == HCCHAR_CTRL) || (HcEpType == HCCHAR_BULK))
2121   {
2122     USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHDIS;
2123 
2124     if ((USBx->GAHBCFG & USB_OTG_GAHBCFG_DMAEN) == 0U)
2125     {
2126       if ((USBx->HNPTXSTS & (0xFFU << 16)) == 0U)
2127       {
2128         USBx_HC(hcnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA;
2129         USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
2130         do
2131         {
2132           count++;
2133 
2134           if (count > 1000U)
2135           {
2136             break;
2137           }
2138         } while ((USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
2139       }
2140       else
2141       {
2142         USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
2143       }
2144     }
2145     else
2146     {
2147       USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
2148     }
2149   }
2150   else
2151   {
2152     USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHDIS;
2153 
2154     if ((USBx_HOST->HPTXSTS & (0xFFU << 16)) == 0U)
2155     {
2156       USBx_HC(hcnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA;
2157       USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
2158       do
2159       {
2160         count++;
2161 
2162         if (count > 1000U)
2163         {
2164           break;
2165         }
2166       } while ((USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
2167     }
2168     else
2169     {
2170       USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
2171     }
2172   }
2173 
2174   return HAL_OK;
2175 }
2176 
2177 /**
2178   * @brief  Initiate Do Ping protocol
2179   * @param  USBx  Selected device
2180   * @param  hc_num  Host Channel number
2181   *         This parameter can be a value from 1 to 15
2182   * @retval HAL state
2183   */
USB_DoPing(const USB_OTG_GlobalTypeDef * USBx,uint8_t ch_num)2184 HAL_StatusTypeDef USB_DoPing(const USB_OTG_GlobalTypeDef *USBx, uint8_t ch_num)
2185 {
2186   uint32_t USBx_BASE = (uint32_t)USBx;
2187   uint32_t chnum = (uint32_t)ch_num;
2188   uint32_t num_packets = 1U;
2189   uint32_t tmpreg;
2190 
2191   USBx_HC(chnum)->HCTSIZ = ((num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |
2192                            USB_OTG_HCTSIZ_DOPING;
2193 
2194   /* Set host channel enable */
2195   tmpreg = USBx_HC(chnum)->HCCHAR;
2196   tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
2197   tmpreg |= USB_OTG_HCCHAR_CHENA;
2198   USBx_HC(chnum)->HCCHAR = tmpreg;
2199 
2200   return HAL_OK;
2201 }
2202 
2203 /**
2204   * @brief  Stop Host Core
2205   * @param  USBx  Selected device
2206   * @retval HAL state
2207   */
USB_StopHost(USB_OTG_GlobalTypeDef * USBx)2208 HAL_StatusTypeDef USB_StopHost(USB_OTG_GlobalTypeDef *USBx)
2209 {
2210   HAL_StatusTypeDef ret = HAL_OK;
2211   uint32_t USBx_BASE = (uint32_t)USBx;
2212   __IO uint32_t count = 0U;
2213   uint32_t value;
2214   uint32_t i;
2215 
2216   (void)USB_DisableGlobalInt(USBx);
2217 
2218   /* Flush USB FIFO */
2219   if (USB_FlushTxFifo(USBx, 0x10U) != HAL_OK) /* all Tx FIFOs */
2220   {
2221     ret = HAL_ERROR;
2222   }
2223 
2224   if (USB_FlushRxFifo(USBx) != HAL_OK)
2225   {
2226     ret = HAL_ERROR;
2227   }
2228 
2229   /* Flush out any leftover queued requests. */
2230   for (i = 0U; i <= 15U; i++)
2231   {
2232     value = USBx_HC(i)->HCCHAR;
2233     value |=  USB_OTG_HCCHAR_CHDIS;
2234     value &= ~USB_OTG_HCCHAR_CHENA;
2235     value &= ~USB_OTG_HCCHAR_EPDIR;
2236     USBx_HC(i)->HCCHAR = value;
2237   }
2238 
2239   /* Halt all channels to put them into a known state. */
2240   for (i = 0U; i <= 15U; i++)
2241   {
2242     value = USBx_HC(i)->HCCHAR;
2243     value |= USB_OTG_HCCHAR_CHDIS;
2244     value |= USB_OTG_HCCHAR_CHENA;
2245     value &= ~USB_OTG_HCCHAR_EPDIR;
2246     USBx_HC(i)->HCCHAR = value;
2247 
2248     do
2249     {
2250       count++;
2251 
2252       if (count > 1000U)
2253       {
2254         break;
2255       }
2256     } while ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
2257   }
2258 
2259   /* Clear any pending Host interrupts */
2260   USBx_HOST->HAINT = CLEAR_INTERRUPT_MASK;
2261   USBx->GINTSTS = CLEAR_INTERRUPT_MASK;
2262 
2263   (void)USB_EnableGlobalInt(USBx);
2264 
2265   return ret;
2266 }
2267 
2268 /**
2269   * @brief  USB_ActivateRemoteWakeup active remote wakeup signalling
2270   * @param  USBx Selected device
2271   * @retval HAL status
2272   */
USB_ActivateRemoteWakeup(const USB_OTG_GlobalTypeDef * USBx)2273 HAL_StatusTypeDef USB_ActivateRemoteWakeup(const USB_OTG_GlobalTypeDef *USBx)
2274 {
2275   uint32_t USBx_BASE = (uint32_t)USBx;
2276 
2277   if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
2278   {
2279     /* active Remote wakeup signalling */
2280     USBx_DEVICE->DCTL |= USB_OTG_DCTL_RWUSIG;
2281   }
2282 
2283   return HAL_OK;
2284 }
2285 
2286 /**
2287   * @brief  USB_DeActivateRemoteWakeup de-active remote wakeup signalling
2288   * @param  USBx Selected device
2289   * @retval HAL status
2290   */
USB_DeActivateRemoteWakeup(const USB_OTG_GlobalTypeDef * USBx)2291 HAL_StatusTypeDef USB_DeActivateRemoteWakeup(const USB_OTG_GlobalTypeDef *USBx)
2292 {
2293   uint32_t USBx_BASE = (uint32_t)USBx;
2294 
2295   /* active Remote wakeup signalling */
2296   USBx_DEVICE->DCTL &= ~(USB_OTG_DCTL_RWUSIG);
2297 
2298   return HAL_OK;
2299 }
2300 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
2301 
2302 #if defined (USB_DRD_FS)
2303 static HAL_StatusTypeDef USB_CoreReset(USB_DRD_TypeDef *USBx);
2304 #if (USE_USB_DOUBLE_BUFFER == 1U)
2305 static HAL_StatusTypeDef USB_HC_BULK_DB_StartXfer(USB_DRD_TypeDef *USBx,
2306                                                   USB_DRD_HCTypeDef *hc,
2307                                                   uint32_t ch_reg,
2308                                                   uint32_t *len);
2309 
2310 static HAL_StatusTypeDef USB_HC_ISO_DB_StartXfer(USB_DRD_TypeDef *USBx,
2311                                                  USB_DRD_HCTypeDef *hc,
2312                                                  uint32_t len);
2313 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2314 
2315 /**
2316   * @brief  Reset the USB Core (needed after USB clock settings change)
2317   * @param  USBx Selected device
2318   * @retval HAL status
2319   */
USB_CoreReset(USB_DRD_TypeDef * USBx)2320 static HAL_StatusTypeDef USB_CoreReset(USB_DRD_TypeDef *USBx)
2321 {
2322   /* Disable Host Mode */
2323   USBx->CNTR &= ~USB_CNTR_HOST;
2324 
2325   /* Force Reset IP */
2326   USBx->CNTR |= USB_CNTR_USBRST;
2327 
2328   return HAL_OK;
2329 }
2330 
2331 /**
2332   * @brief  Initializes the USB Core
2333   * @param  USBx USB Instance
2334   * @param  cfg pointer to a USB_CfgTypeDef structure that contains
2335   *         the configuration information for the specified USBx peripheral.
2336   * @retval HAL status
2337   */
USB_CoreInit(USB_DRD_TypeDef * USBx,USB_DRD_CfgTypeDef cfg)2338 HAL_StatusTypeDef USB_CoreInit(USB_DRD_TypeDef *USBx, USB_DRD_CfgTypeDef cfg)
2339 {
2340   HAL_StatusTypeDef ret;
2341   UNUSED(cfg);
2342 
2343   if (USBx == NULL)
2344   {
2345     return HAL_ERROR;
2346   }
2347 
2348   /* Reset after a PHY select */
2349   ret = USB_CoreReset(USBx);
2350 
2351   /* Clear pending interrupts */
2352   USBx->ISTR = 0U;
2353 
2354   return ret;
2355 }
2356 
2357 /**
2358   * @brief  USB_EnableGlobalInt
2359   *         Enables the controller's Global Int in the AHB Config reg
2360   * @param  USBx Selected device
2361   * @retval HAL status
2362   */
USB_EnableGlobalInt(USB_DRD_TypeDef * USBx)2363 HAL_StatusTypeDef USB_EnableGlobalInt(USB_DRD_TypeDef *USBx)
2364 {
2365   uint32_t winterruptmask;
2366 
2367   /* Clear pending interrupts */
2368   USBx->ISTR = 0U;
2369 
2370   /* Set winterruptmask variable */
2371   winterruptmask = USB_CNTR_CTRM  | USB_CNTR_WKUPM |
2372                    USB_CNTR_SUSPM | USB_CNTR_ERRM |
2373                    USB_CNTR_SOFM | USB_CNTR_ESOFM |
2374                    USB_CNTR_RESETM | USB_CNTR_L1REQM;
2375 
2376   /* Set interrupt mask */
2377   USBx->CNTR = winterruptmask;
2378 
2379   return HAL_OK;
2380 }
2381 
2382 /**
2383   * @brief  USB_DisableGlobalInt
2384   *         Disable the controller's Global Int in the AHB Config reg
2385   * @param  USBx Selected device
2386   * @retval HAL status
2387   */
USB_DisableGlobalInt(USB_DRD_TypeDef * USBx)2388 HAL_StatusTypeDef USB_DisableGlobalInt(USB_DRD_TypeDef *USBx)
2389 {
2390   uint32_t winterruptmask;
2391 
2392   /* Set winterruptmask variable */
2393   winterruptmask = USB_CNTR_CTRM  | USB_CNTR_WKUPM |
2394                    USB_CNTR_SUSPM | USB_CNTR_ERRM |
2395                    USB_CNTR_SOFM | USB_CNTR_ESOFM |
2396                    USB_CNTR_RESETM | USB_CNTR_L1REQM;
2397 
2398   /* Clear interrupt mask */
2399   USBx->CNTR &= ~winterruptmask;
2400 
2401   return HAL_OK;
2402 }
2403 
2404 /**
2405   * @brief  USB_SetCurrentMode Set functional mode
2406   * @param  USBx Selected device
2407   * @param  mode current core mode
2408   *          This parameter can be one of the these values:
2409   *            @arg USB_DEVICE_MODE Peripheral mode
2410   * @retval HAL status
2411   */
USB_SetCurrentMode(USB_DRD_TypeDef * USBx,USB_DRD_ModeTypeDef mode)2412 HAL_StatusTypeDef USB_SetCurrentMode(USB_DRD_TypeDef *USBx, USB_DRD_ModeTypeDef mode)
2413 {
2414   if (mode == USB_DEVICE_MODE)
2415   {
2416     USBx->CNTR &= ~USB_CNTR_HOST;
2417   }
2418   else if (mode == USB_HOST_MODE)
2419   {
2420     USBx->CNTR |= USB_CNTR_HOST;
2421   }
2422   else
2423   {
2424     return HAL_ERROR;
2425   }
2426 
2427   return HAL_OK;
2428 }
2429 
2430 /**
2431   * @brief  USB_DevInit Initializes the USB controller registers
2432   *         for device mode
2433   * @param  USBx Selected device
2434   * @param  cfg  pointer to a USB_DRD_CfgTypeDef structure that contains
2435   *         the configuration information for the specified USBx peripheral.
2436   * @retval HAL status
2437   */
USB_DevInit(USB_DRD_TypeDef * USBx,USB_DRD_CfgTypeDef cfg)2438 HAL_StatusTypeDef USB_DevInit(USB_DRD_TypeDef *USBx, USB_DRD_CfgTypeDef cfg)
2439 {
2440   HAL_StatusTypeDef ret;
2441 
2442   /* Prevent unused argument(s) compilation warning */
2443   UNUSED(cfg);
2444 
2445   /* Force Reset */
2446   USBx->CNTR = USB_CNTR_USBRST;
2447 
2448   /* Release Reset */
2449   USBx->CNTR &= ~USB_CNTR_USBRST;
2450 
2451   /* Set the Device Mode */
2452   ret = USB_SetCurrentMode(USBx, USB_DEVICE_MODE);
2453 
2454   /* Clear pending interrupts */
2455   USBx->ISTR = 0U;
2456 
2457   return ret;
2458 }
2459 
2460 /**
2461   * @brief  USB_FlushTxFifo : Flush a Tx FIFO
2462   * @param  USBx : Selected device
2463   * @param  num : FIFO number
2464   *         This parameter can be a value from 1 to 15
2465             15 means Flush all Tx FIFOs
2466   * @retval HAL status
2467   */
USB_FlushTxFifo(USB_DRD_TypeDef const * USBx,uint32_t num)2468 HAL_StatusTypeDef USB_FlushTxFifo(USB_DRD_TypeDef const *USBx, uint32_t num)
2469 {
2470   /* Prevent unused argument(s) compilation warning */
2471   UNUSED(USBx);
2472   UNUSED(num);
2473 
2474   /* NOTE : - This function is not required by USB Device FS peripheral, it is used
2475               only by USB OTG FS peripheral.
2476             - This function is added to ensure compatibility across platforms.
2477    */
2478 
2479   return HAL_OK;
2480 }
2481 
2482 /**
2483   * @brief  USB_FlushRxFifo : Flush Rx FIFO
2484   * @param  USBx : Selected device
2485   * @retval HAL status
2486   */
USB_FlushRxFifo(USB_DRD_TypeDef const * USBx)2487 HAL_StatusTypeDef USB_FlushRxFifo(USB_DRD_TypeDef const *USBx)
2488 {
2489   /* Prevent unused argument(s) compilation warning */
2490   UNUSED(USBx);
2491 
2492   /* NOTE : - This function is not required by USB Device FS peripheral, it is used
2493               only by USB OTG FS peripheral.
2494             - This function is added to ensure compatibility across platforms.
2495    */
2496 
2497   return HAL_OK;
2498 }
2499 
2500 
2501 #if defined (HAL_PCD_MODULE_ENABLED)
2502 /**
2503   * @brief  Activate and configure an endpoint
2504   * @param  USBx Selected device
2505   * @param  ep pointer to endpoint structure
2506   * @retval HAL status
2507   */
USB_ActivateEndpoint(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)2508 HAL_StatusTypeDef USB_ActivateEndpoint(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
2509 {
2510   HAL_StatusTypeDef ret = HAL_OK;
2511   uint32_t wEpRegVal;
2512 
2513   wEpRegVal = PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_T_MASK;
2514 
2515   /* initialize Endpoint */
2516   switch (ep->type)
2517   {
2518     case EP_TYPE_CTRL:
2519       wEpRegVal |= USB_EP_CONTROL;
2520       break;
2521 
2522     case EP_TYPE_BULK:
2523       wEpRegVal |= USB_EP_BULK;
2524       break;
2525 
2526     case EP_TYPE_INTR:
2527       wEpRegVal |= USB_EP_INTERRUPT;
2528       break;
2529 
2530     case EP_TYPE_ISOC:
2531       wEpRegVal |= USB_EP_ISOCHRONOUS;
2532       break;
2533 
2534     default:
2535       ret = HAL_ERROR;
2536       break;
2537   }
2538 
2539   PCD_SET_ENDPOINT(USBx, ep->num, (wEpRegVal | USB_EP_VTRX | USB_EP_VTTX));
2540 
2541   PCD_SET_EP_ADDRESS(USBx, ep->num, ep->num);
2542 
2543   if (ep->doublebuffer == 0U)
2544   {
2545     if (ep->is_in != 0U)
2546     {
2547       /*Set the endpoint Transmit buffer address */
2548       PCD_SET_EP_TX_ADDRESS(USBx, ep->num, ep->pmaadress);
2549       PCD_CLEAR_TX_DTOG(USBx, ep->num);
2550 
2551       if (ep->type != EP_TYPE_ISOC)
2552       {
2553         /* Configure NAK status for the Endpoint */
2554         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
2555       }
2556       else
2557       {
2558         /* Configure TX Endpoint to disabled state */
2559         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
2560       }
2561     }
2562     else
2563     {
2564       /* Set the endpoint Receive buffer address */
2565       PCD_SET_EP_RX_ADDRESS(USBx, ep->num, ep->pmaadress);
2566 
2567       /* Set the endpoint Receive buffer counter */
2568       PCD_SET_EP_RX_CNT(USBx, ep->num, ep->maxpacket);
2569       PCD_CLEAR_RX_DTOG(USBx, ep->num);
2570 
2571       if (ep->num == 0U)
2572       {
2573         /* Configure VALID status for EP0 */
2574         PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
2575       }
2576       else
2577       {
2578         /* Configure NAK status for OUT Endpoint */
2579         PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
2580       }
2581     }
2582   }
2583 #if (USE_USB_DOUBLE_BUFFER == 1U)
2584   /* Double Buffer */
2585   else
2586   {
2587     if (ep->type == EP_TYPE_BULK)
2588     {
2589       /* Set bulk endpoint as double buffered */
2590       PCD_SET_BULK_EP_DBUF(USBx, ep->num);
2591     }
2592     else
2593     {
2594       /* Set the ISOC endpoint in double buffer mode */
2595       PCD_CLEAR_EP_KIND(USBx, ep->num);
2596     }
2597 
2598     /* Set buffer address for double buffered mode */
2599     PCD_SET_EP_DBUF_ADDR(USBx, ep->num, ep->pmaaddr0, ep->pmaaddr1);
2600 
2601     if (ep->is_in == 0U)
2602     {
2603       /* Clear the data toggle bits for the endpoint IN/OUT */
2604       PCD_CLEAR_RX_DTOG(USBx, ep->num);
2605       PCD_CLEAR_TX_DTOG(USBx, ep->num);
2606 
2607       /* Set endpoint RX count */
2608       PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, ep->maxpacket);
2609 
2610       /* Set endpoint RX to valid state */
2611       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
2612       PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
2613     }
2614     else
2615     {
2616       /* Clear the data toggle bits for the endpoint IN/OUT */
2617       PCD_CLEAR_RX_DTOG(USBx, ep->num);
2618       PCD_CLEAR_TX_DTOG(USBx, ep->num);
2619 
2620       if (ep->type != EP_TYPE_ISOC)
2621       {
2622         /* Configure NAK status for the Endpoint */
2623         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
2624       }
2625       else
2626       {
2627         /* Configure TX Endpoint to disabled state */
2628         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
2629       }
2630 
2631       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
2632     }
2633   }
2634 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2635 
2636   return ret;
2637 }
2638 
2639 /**
2640   * @brief  De-activate and de-initialize an endpoint
2641   * @param  USBx Selected device
2642   * @param  ep pointer to endpoint structure
2643   * @retval HAL status
2644   */
USB_DeactivateEndpoint(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)2645 HAL_StatusTypeDef USB_DeactivateEndpoint(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
2646 {
2647   if (ep->doublebuffer == 0U)
2648   {
2649     if (ep->is_in != 0U)
2650     {
2651       PCD_CLEAR_TX_DTOG(USBx, ep->num);
2652 
2653       /* Configure DISABLE status for the Endpoint */
2654       PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
2655     }
2656 
2657     else
2658     {
2659       PCD_CLEAR_RX_DTOG(USBx, ep->num);
2660 
2661       /* Configure DISABLE status for the Endpoint */
2662       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
2663     }
2664   }
2665 #if (USE_USB_DOUBLE_BUFFER == 1U)
2666   /* Double Buffer */
2667   else
2668   {
2669     if (ep->is_in == 0U)
2670     {
2671       /* Clear the data toggle bits for the endpoint IN/OUT*/
2672       PCD_CLEAR_RX_DTOG(USBx, ep->num);
2673       PCD_CLEAR_TX_DTOG(USBx, ep->num);
2674 
2675       /* Reset value of the data toggle bits for the endpoint out*/
2676       PCD_TX_DTOG(USBx, ep->num);
2677 
2678       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
2679       PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
2680     }
2681     else
2682     {
2683       /* Clear the data toggle bits for the endpoint IN/OUT*/
2684       PCD_CLEAR_RX_DTOG(USBx, ep->num);
2685       PCD_CLEAR_TX_DTOG(USBx, ep->num);
2686       PCD_RX_DTOG(USBx, ep->num);
2687 
2688       /* Configure DISABLE status for the Endpoint*/
2689       PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
2690       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
2691     }
2692   }
2693 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2694 
2695   return HAL_OK;
2696 }
2697 
2698 /**
2699   * @brief  USB_EPStartXfer setup and starts a transfer over an EP
2700   * @param  USBx Selected device
2701   * @param  ep pointer to endpoint structure
2702   * @retval HAL status
2703   */
USB_EPStartXfer(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)2704 HAL_StatusTypeDef USB_EPStartXfer(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
2705 {
2706   uint32_t len;
2707 #if (USE_USB_DOUBLE_BUFFER == 1U)
2708   uint16_t pmabuffer;
2709   uint16_t wEPVal;
2710 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2711 
2712   /* IN endpoint */
2713   if (ep->is_in == 1U)
2714   {
2715     /* Multi packet transfer */
2716     if (ep->xfer_len > ep->maxpacket)
2717     {
2718       len = ep->maxpacket;
2719     }
2720     else
2721     {
2722       len = ep->xfer_len;
2723     }
2724 
2725     /* configure and validate Tx endpoint */
2726     if (ep->doublebuffer == 0U)
2727     {
2728       USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, (uint16_t)len);
2729       PCD_SET_EP_TX_CNT(USBx, ep->num, len);
2730     }
2731 #if (USE_USB_DOUBLE_BUFFER == 1U)
2732     else
2733     {
2734       /* double buffer bulk management */
2735       if (ep->type == EP_TYPE_BULK)
2736       {
2737         if (ep->xfer_len_db > ep->maxpacket)
2738         {
2739           /* enable double buffer */
2740           PCD_SET_BULK_EP_DBUF(USBx, ep->num);
2741 
2742           /* each Time to write in PMA xfer_len_db will */
2743           ep->xfer_len_db -= len;
2744 
2745           /* Fill the two first buffer in the Buffer0 & Buffer1 */
2746           if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
2747           {
2748             /* Set the Double buffer counter for pmabuffer1 */
2749             PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
2750             pmabuffer = ep->pmaaddr1;
2751 
2752             /* Write the user buffer to USB PMA */
2753             USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
2754             ep->xfer_buff += len;
2755 
2756             if (ep->xfer_len_db > ep->maxpacket)
2757             {
2758               ep->xfer_len_db -= len;
2759             }
2760             else
2761             {
2762               len = ep->xfer_len_db;
2763               ep->xfer_len_db = 0U;
2764             }
2765 
2766             /* Set the Double buffer counter for pmabuffer0 */
2767             PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
2768             pmabuffer = ep->pmaaddr0;
2769 
2770             /* Write the user buffer to USB PMA */
2771             USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
2772           }
2773           else
2774           {
2775             /* Set the Double buffer counter for pmabuffer0 */
2776             PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
2777             pmabuffer = ep->pmaaddr0;
2778 
2779             /* Write the user buffer to USB PMA */
2780             USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
2781             ep->xfer_buff += len;
2782 
2783             if (ep->xfer_len_db > ep->maxpacket)
2784             {
2785               ep->xfer_len_db -= len;
2786             }
2787             else
2788             {
2789               len = ep->xfer_len_db;
2790               ep->xfer_len_db = 0U;
2791             }
2792 
2793             /* Set the Double buffer counter for pmabuffer1 */
2794             PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
2795             pmabuffer = ep->pmaaddr1;
2796 
2797             /* Write the user buffer to USB PMA */
2798             USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
2799           }
2800         }
2801         /* auto Switch to single buffer mode when transfer <Mps no need to manage in double buffer */
2802         else
2803         {
2804           len = ep->xfer_len_db;
2805 
2806           /* disable double buffer mode for Bulk endpoint */
2807           PCD_CLEAR_BULK_EP_DBUF(USBx, ep->num);
2808 
2809           /* Set Tx count with nbre of byte to be transmitted */
2810           PCD_SET_EP_TX_CNT(USBx, ep->num, len);
2811           pmabuffer = ep->pmaaddr0;
2812 
2813           /* Write the user buffer to USB PMA */
2814           USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
2815         }
2816       }
2817       else /* Manage isochronous double buffer IN mode */
2818       {
2819         /* Each Time to write in PMA xfer_len_db will */
2820         ep->xfer_len_db -= len;
2821 
2822         /* Fill the data buffer */
2823         if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
2824         {
2825           /* Set the Double buffer counter for pmabuffer1 */
2826           PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
2827           pmabuffer = ep->pmaaddr1;
2828 
2829           /* Write the user buffer to USB PMA */
2830           USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
2831         }
2832         else
2833         {
2834           /* Set the Double buffer counter for pmabuffer0 */
2835           PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
2836           pmabuffer = ep->pmaaddr0;
2837 
2838           /* Write the user buffer to USB PMA */
2839           USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
2840         }
2841       }
2842     }
2843 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2844 
2845     PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID);
2846   }
2847   else /* OUT endpoint */
2848   {
2849     if (ep->doublebuffer == 0U)
2850     {
2851       if ((ep->xfer_len == 0U) && (ep->type == EP_TYPE_CTRL))
2852       {
2853         /* This is a status out stage set the OUT_STATUS */
2854         PCD_SET_OUT_STATUS(USBx, ep->num);
2855       }
2856       else
2857       {
2858         PCD_CLEAR_OUT_STATUS(USBx, ep->num);
2859       }
2860 
2861       /* Multi packet transfer */
2862       if (ep->xfer_len > ep->maxpacket)
2863       {
2864         ep->xfer_len -= ep->maxpacket;
2865       }
2866       else
2867       {
2868         ep->xfer_len = 0U;
2869       }
2870     }
2871 #if (USE_USB_DOUBLE_BUFFER == 1U)
2872     else
2873     {
2874       /* First Transfer Coming From HAL_PCD_EP_Receive & From ISR */
2875       /* Set the Double buffer counter */
2876       if (ep->type == EP_TYPE_BULK)
2877       {
2878         /* Coming from ISR */
2879         if (ep->xfer_count != 0U)
2880         {
2881           /* Update last value to check if there is blocking state */
2882           wEPVal = (uint16_t)PCD_GET_ENDPOINT(USBx, ep->num);
2883 
2884           /* Blocking State */
2885           if ((((wEPVal & USB_EP_DTOG_RX) != 0U) && ((wEPVal & USB_EP_DTOG_TX) != 0U)) ||
2886               (((wEPVal & USB_EP_DTOG_RX) == 0U) && ((wEPVal & USB_EP_DTOG_TX) == 0U)))
2887           {
2888             PCD_FREE_USER_BUFFER(USBx, ep->num, 0U);
2889           }
2890         }
2891       }
2892       /* iso out double */
2893       else if (ep->type == EP_TYPE_ISOC)
2894       {
2895         /* Only single packet transfer supported in FS */
2896         ep->xfer_len = 0U;
2897       }
2898       else
2899       {
2900         return HAL_ERROR;
2901       }
2902     }
2903 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2904 
2905     PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
2906   }
2907 
2908   return HAL_OK;
2909 }
2910 
2911 
2912 /**
2913   * @brief  USB_EPSetStall set a stall condition over an EP
2914   * @param  USBx Selected device
2915   * @param  ep pointer to endpoint structure
2916   * @retval HAL status
2917   */
USB_EPSetStall(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)2918 HAL_StatusTypeDef USB_EPSetStall(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
2919 {
2920   if (ep->is_in != 0U)
2921   {
2922     PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_STALL);
2923   }
2924   else
2925   {
2926     PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_STALL);
2927   }
2928 
2929   return HAL_OK;
2930 }
2931 
2932 /**
2933   * @brief  USB_EPClearStall Clear a stall condition over an EP
2934   * @param  USBx Selected device
2935   * @param  ep pointer to endpoint structure
2936   * @retval HAL status
2937   */
USB_EPClearStall(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)2938 HAL_StatusTypeDef USB_EPClearStall(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
2939 {
2940   if (ep->is_in != 0U)
2941   {
2942     PCD_CLEAR_TX_DTOG(USBx, ep->num);
2943 
2944     if (ep->type != EP_TYPE_ISOC)
2945     {
2946       /* Configure NAK status for the Endpoint */
2947       PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
2948     }
2949   }
2950   else
2951   {
2952     PCD_CLEAR_RX_DTOG(USBx, ep->num);
2953 
2954     /* Configure VALID status for the Endpoint */
2955     PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
2956   }
2957 
2958   return HAL_OK;
2959 }
2960 
2961 /**
2962    * @brief  USB_EPStoptXfer  Stop transfer on an EP
2963    * @param  USBx  usb device instance
2964    * @param  ep pointer to endpoint structure
2965    * @retval HAL status
2966    */
USB_EPStopXfer(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)2967 HAL_StatusTypeDef USB_EPStopXfer(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
2968 {
2969   /* IN endpoint */
2970   if (ep->is_in == 1U)
2971   {
2972     if (ep->doublebuffer == 0U)
2973     {
2974       if (ep->type != EP_TYPE_ISOC)
2975       {
2976         /* Configure NAK status for the Endpoint */
2977         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
2978       }
2979       else
2980       {
2981         /* Configure TX Endpoint to disabled state */
2982         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
2983       }
2984     }
2985   }
2986   else /* OUT endpoint */
2987   {
2988     if (ep->doublebuffer == 0U)
2989     {
2990       if (ep->type != EP_TYPE_ISOC)
2991       {
2992         /* Configure NAK status for the Endpoint */
2993         PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
2994       }
2995       else
2996       {
2997         /* Configure RX Endpoint to disabled state */
2998         PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
2999       }
3000     }
3001   }
3002 
3003   return HAL_OK;
3004 }
3005 #endif /* defined (HAL_PCD_MODULE_ENABLED) */
3006 
3007 /**
3008   * @brief  USB_StopDevice Stop the usb device mode
3009   * @param  USBx Selected device
3010   * @retval HAL status
3011   */
USB_StopDevice(USB_DRD_TypeDef * USBx)3012 HAL_StatusTypeDef USB_StopDevice(USB_DRD_TypeDef *USBx)
3013 {
3014   /* disable all interrupts and force USB reset */
3015   USBx->CNTR = USB_CNTR_USBRST;
3016 
3017   /* clear interrupt status register */
3018   USBx->ISTR = 0U;
3019 
3020   /* switch-off device */
3021   USBx->CNTR = (USB_CNTR_USBRST | USB_CNTR_PDWN);
3022 
3023   return HAL_OK;
3024 }
3025 
3026 /**
3027   * @brief  USB_SetDevAddress Stop the usb device mode
3028   * @param  USBx Selected device
3029   * @param  address new device address to be assigned
3030   *          This parameter can be a value from 0 to 255
3031   * @retval HAL status
3032   */
USB_SetDevAddress(USB_DRD_TypeDef * USBx,uint8_t address)3033 HAL_StatusTypeDef  USB_SetDevAddress(USB_DRD_TypeDef *USBx, uint8_t address)
3034 {
3035   if (address == 0U)
3036   {
3037     /* set device address and enable function */
3038     USBx->DADDR = USB_DADDR_EF;
3039   }
3040 
3041   return HAL_OK;
3042 }
3043 
3044 /**
3045   * @brief  USB_DevConnect Connect the USB device by enabling the pull-up/pull-down
3046   * @param  USBx Selected device
3047   * @retval HAL status
3048   */
USB_DevConnect(USB_DRD_TypeDef * USBx)3049 HAL_StatusTypeDef  USB_DevConnect(USB_DRD_TypeDef *USBx)
3050 {
3051   /* Enabling DP Pull-UP bit to Connect internal PU resistor on USB DP line */
3052   USBx->BCDR |= USB_BCDR_DPPU;
3053 
3054   return HAL_OK;
3055 }
3056 
3057 /**
3058   * @brief  USB_DevDisconnect Disconnect the USB device by disabling the pull-up/pull-down
3059   * @param  USBx Selected device
3060   * @retval HAL status
3061   */
USB_DevDisconnect(USB_DRD_TypeDef * USBx)3062 HAL_StatusTypeDef  USB_DevDisconnect(USB_DRD_TypeDef *USBx)
3063 {
3064   /* Disable DP Pull-Up bit to disconnect the Internal PU resistor on USB DP line */
3065   USBx->BCDR &= ~(USB_BCDR_DPPU);
3066 
3067   return HAL_OK;
3068 }
3069 
3070 /**
3071   * @brief  USB_ReadInterrupts return the global USB interrupt status
3072   * @param  USBx Selected device
3073   * @retval USB Global Interrupt status
3074   */
USB_ReadInterrupts(USB_DRD_TypeDef const * USBx)3075 uint32_t USB_ReadInterrupts(USB_DRD_TypeDef const *USBx)
3076 {
3077   uint32_t tmpreg;
3078 
3079   tmpreg = USBx->ISTR;
3080   return tmpreg;
3081 }
3082 
3083 /**
3084   * @brief  USB_ActivateRemoteWakeup : active remote wakeup signalling
3085   * @param  USBx Selected device
3086   * @retval HAL status
3087   */
USB_ActivateRemoteWakeup(USB_DRD_TypeDef * USBx)3088 HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_DRD_TypeDef *USBx)
3089 {
3090   USBx->CNTR |= USB_CNTR_L2RES;
3091 
3092   return HAL_OK;
3093 }
3094 
3095 /**
3096   * @brief  USB_DeActivateRemoteWakeup de-active remote wakeup signalling
3097   * @param  USBx Selected device
3098   * @retval HAL status
3099   */
USB_DeActivateRemoteWakeup(USB_DRD_TypeDef * USBx)3100 HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_DRD_TypeDef *USBx)
3101 {
3102   USBx->CNTR &= ~USB_CNTR_L2RES;
3103 
3104   return HAL_OK;
3105 }
3106 
3107 /**
3108   * @brief Copy a buffer from user memory area to packet memory area (PMA)
3109   * @param   USBx USB peripheral instance register address.
3110   * @param   pbUsrBuf pointer to user memory area.
3111   * @param   wPMABufAddr address into PMA.
3112   * @param   wNBytes no. of bytes to be copied.
3113   * @retval None
3114   */
USB_WritePMA(USB_DRD_TypeDef const * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)3115 void USB_WritePMA(USB_DRD_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
3116 {
3117   UNUSED(USBx);
3118   uint32_t WrVal;
3119   uint32_t count;
3120   __IO uint32_t *pdwVal;
3121   uint32_t NbWords = ((uint32_t)wNBytes + 3U) >> 2U;
3122   /* Due to the PMA access 32bit only so the last non word data should be processed alone */
3123   uint16_t remaining_bytes = wNBytes % 4U;
3124   uint8_t *pBuf = pbUsrBuf;
3125 
3126   /* Check if there is a remaining byte */
3127   if (remaining_bytes != 0U)
3128   {
3129     NbWords--;
3130   }
3131 
3132   /* Get the PMA Buffer pointer */
3133   pdwVal = (__IO uint32_t *)(USB_DRD_PMAADDR + (uint32_t)wPMABufAddr);
3134 
3135   /* Write the Calculated Word into the PMA related Buffer */
3136   for (count = NbWords; count != 0U; count--)
3137   {
3138     *pdwVal = __UNALIGNED_UINT32_READ(pBuf);
3139     pdwVal++;
3140     /* Increment pBuf 4 Time as Word Increment */
3141     pBuf++;
3142     pBuf++;
3143     pBuf++;
3144     pBuf++;
3145   }
3146 
3147   /* When Number of data is not word aligned, write the remaining Byte */
3148   if (remaining_bytes != 0U)
3149   {
3150     WrVal = 0U;
3151 
3152     do
3153     {
3154       WrVal |= (uint32_t)(*(uint8_t *)pBuf) << (8U * count);
3155       count++;
3156       pBuf++;
3157       remaining_bytes--;
3158     } while (remaining_bytes != 0U);
3159 
3160     *pdwVal = WrVal;
3161   }
3162 }
3163 
3164 /**
3165   * @brief Copy data from packet memory area (PMA) to user memory buffer
3166   * @param   USBx USB peripheral instance register address.
3167   * @param   pbUsrBuf pointer to user memory area.
3168   * @param   wPMABufAddr address into PMA.
3169   * @param   wNBytes no. of bytes to be copied.
3170   * @retval None
3171   */
USB_ReadPMA(USB_DRD_TypeDef const * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)3172 void USB_ReadPMA(USB_DRD_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
3173 {
3174   UNUSED(USBx);
3175   uint32_t count;
3176   uint32_t RdVal;
3177   __IO uint32_t *pdwVal;
3178   uint32_t NbWords = ((uint32_t)wNBytes + 3U) >> 2U;
3179   /*Due to the PMA access 32bit only so the last non word data should be processed alone */
3180   uint16_t remaining_bytes = wNBytes % 4U;
3181   uint8_t *pBuf = pbUsrBuf;
3182 
3183   /* Get the PMA Buffer pointer */
3184   pdwVal = (__IO uint32_t *)(USB_DRD_PMAADDR + (uint32_t)wPMABufAddr);
3185 
3186   /* if nbre of byte is not word aligned decrement the nbre of word*/
3187   if (remaining_bytes != 0U)
3188   {
3189     NbWords--;
3190   }
3191 
3192   /*Read the Calculated Word From the PMA related Buffer*/
3193   for (count = NbWords; count != 0U; count--)
3194   {
3195     __UNALIGNED_UINT32_WRITE(pBuf, *pdwVal);
3196 
3197     pdwVal++;
3198     pBuf++;
3199     pBuf++;
3200     pBuf++;
3201     pBuf++;
3202   }
3203 
3204   /*When Number of data is not word aligned, read the remaining byte*/
3205   if (remaining_bytes != 0U)
3206   {
3207     RdVal = *(__IO uint32_t *)pdwVal;
3208 
3209     do
3210     {
3211       *(uint8_t *)pBuf = (uint8_t)(RdVal >> (8U * (uint8_t)(count)));
3212       count++;
3213       pBuf++;
3214       remaining_bytes--;
3215     } while (remaining_bytes != 0U);
3216   }
3217 }
3218 
3219 
3220 /*------------------------------------------------------------------------*/
3221 /*                                HOST API                                */
3222 /*------------------------------------------------------------------------*/
3223 
3224 /**
3225   * @brief  USB_HostInit Initializes the USB DRD controller registers
3226   *         for Host mode
3227   * @param  USBx Selected device
3228   * @param  cfg  pointer to a USB_DRD_CfgTypeDef structure that contains
3229   *         the configuration information for the specified USBx peripheral.
3230   * @retval HAL status
3231   */
USB_HostInit(USB_DRD_TypeDef * USBx,USB_DRD_CfgTypeDef cfg)3232 HAL_StatusTypeDef USB_HostInit(USB_DRD_TypeDef *USBx, USB_DRD_CfgTypeDef cfg)
3233 {
3234   UNUSED(cfg);
3235 
3236   /* Clear All Pending Interrupt */
3237   USBx->ISTR = 0U;
3238 
3239   /* Disable all interrupts */
3240   USBx->CNTR &= ~(USB_CNTR_CTRM | USB_CNTR_PMAOVRM | USB_CNTR_ERRM |
3241                   USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_DCON |
3242                   USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_L1REQM);
3243 
3244   /* Clear All Pending Interrupt */
3245   USBx->ISTR = 0U;
3246 
3247   /* Set the PullDown on the PHY */
3248   USBx->BCDR |= USB_BCDR_DPPD;
3249 
3250   /* Enable Global interrupt */
3251   USBx->CNTR |= (USB_CNTR_CTRM | USB_CNTR_PMAOVRM | USB_CNTR_ERRM |
3252                  USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_DCON |
3253                  USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_L1REQM);
3254 
3255   return HAL_OK;
3256 }
3257 
3258 
3259 /**
3260   * @brief  USB_DRD_ResetPort : Reset Host Port
3261   * @param  USBx Selected device
3262   * @retval HAL status
3263   * @note (1)The application must wait at least 10 ms
3264   *   before clearing the reset bit.
3265   */
USB_ResetPort(USB_DRD_TypeDef * USBx)3266 HAL_StatusTypeDef USB_ResetPort(USB_DRD_TypeDef *USBx)
3267 {
3268   /* Force USB Reset */
3269   USBx->CNTR |= USB_CNTR_USBRST;
3270   HAL_Delay(100);
3271   /* Release USB Reset */
3272   USBx->CNTR &= ~USB_CNTR_USBRST;
3273   HAL_Delay(30);
3274 
3275   return HAL_OK;
3276 }
3277 
3278 /**
3279   * @brief  Return Host Core speed
3280   * @param  USBx Selected device
3281   * @retval speed Host speed
3282   *          This parameter can be one of these values
3283   *            @arg USB_DRD_SPEED_FS Full speed mode
3284   *            @arg USB_DRD_SPEED_LS Low speed mode
3285   */
USB_GetHostSpeed(USB_DRD_TypeDef const * USBx)3286 uint32_t USB_GetHostSpeed(USB_DRD_TypeDef const *USBx)
3287 {
3288   if ((USBx->ISTR & USB_ISTR_LS_DCONN) != 0U)
3289   {
3290     return USB_DRD_SPEED_LS;
3291   }
3292   else
3293   {
3294     return USB_DRD_SPEED_FS;
3295   }
3296 }
3297 
3298 /**
3299   * @brief  Return Host Current Frame number
3300   * @param  USBx Selected device
3301   * @retval current frame number
3302   */
USB_GetCurrentFrame(USB_DRD_TypeDef const * USBx)3303 uint32_t USB_GetCurrentFrame(USB_DRD_TypeDef const *USBx)
3304 {
3305   return USBx->FNR & 0x7FFU;
3306 }
3307 
3308 /**
3309   * @brief  Set the channel Kind (Single/double buffer mode)
3310   * @param  USBx Selected device
3311   * @param  phy_ch_num Selected device
3312   * @param  db_state double state can be USB_DRD_XXX_DBUFF_ENBALE/USB_DRD_XXX_DBUFF_DISABLE
3313   * @retval HAL status
3314   */
USB_HC_DoubleBuffer(USB_DRD_TypeDef * USBx,uint8_t phy_ch_num,uint8_t db_state)3315 HAL_StatusTypeDef USB_HC_DoubleBuffer(USB_DRD_TypeDef *USBx,
3316                                       uint8_t phy_ch_num, uint8_t db_state)
3317 {
3318   uint32_t tmp;
3319 
3320   if ((db_state == USB_DRD_BULK_DBUFF_ENBALE) || (db_state == USB_DRD_ISOC_DBUFF_DISABLE))
3321   {
3322     tmp = (USB_DRD_GET_CHEP(USBx, phy_ch_num) | USB_CH_KIND) & USB_CHEP_DB_MSK;
3323   }
3324   else
3325   {
3326     tmp = USB_DRD_GET_CHEP(USBx, phy_ch_num) & (~USB_CH_KIND) & USB_CHEP_DB_MSK;
3327   }
3328 
3329   /* Set the device speed in case using HUB FS with device LS */
3330   USB_DRD_SET_CHEP(USBx, phy_ch_num, tmp);
3331 
3332   return HAL_OK;
3333 }
3334 
3335 /**
3336   * @brief  Initialize a host channel
3337   * @param  USBx Selected device
3338   * @param  phy_ch_num Channel number
3339   *         This parameter can be a value from 1 to 15
3340   * @param  epnum Endpoint number
3341   *          This parameter can be a value from 1 to 15
3342   * @param  dev_address Current device address
3343   *          This parameter can be a value from 0 to 255
3344   * @param  speed Current device speed
3345   *          This parameter can be one of these values:
3346   *          @arg USB_DRD_SPEED_FULL Full speed mode
3347   *          @arg USB_DRD_SPEED_LOW  Low speed mode
3348   * @param  ep_type Endpoint Type
3349   *          This parameter can be one of these values:
3350   *            @arg EP_TYPE_CTRL Control type
3351   *            @arg EP_TYPE_ISOC Isochronous type
3352   *            @arg EP_TYPE_BULK Bulk type
3353   *            @arg EP_TYPE_INTR Interrupt type
3354   * @param  mps Max Packet Size
3355   *          This parameter can be a value from 0 to 32K
3356   * @retval HAL state
3357   */
USB_HC_Init(USB_DRD_TypeDef * USBx,uint8_t phy_ch_num,uint8_t epnum,uint8_t dev_address,uint8_t speed,uint8_t ep_type,uint16_t mps)3358 HAL_StatusTypeDef USB_HC_Init(USB_DRD_TypeDef *USBx, uint8_t phy_ch_num,
3359                               uint8_t epnum, uint8_t dev_address, uint8_t speed,
3360                               uint8_t ep_type, uint16_t mps)
3361 {
3362   HAL_StatusTypeDef ret = HAL_OK;
3363   uint32_t wChRegVal;
3364   uint32_t HostCoreSpeed;
3365 
3366   UNUSED(mps);
3367 
3368   wChRegVal = USB_DRD_GET_CHEP(USBx, phy_ch_num) & USB_CH_T_MASK;
3369 
3370   /* Initialize host Channel */
3371   switch (ep_type)
3372   {
3373     case EP_TYPE_CTRL:
3374       wChRegVal |= USB_EP_CONTROL;
3375       break;
3376 
3377     case EP_TYPE_BULK:
3378       wChRegVal |= USB_EP_BULK;
3379       break;
3380 
3381     case EP_TYPE_INTR:
3382       wChRegVal |= USB_EP_INTERRUPT;
3383       break;
3384 
3385     case EP_TYPE_ISOC:
3386       wChRegVal |= USB_EP_ISOCHRONOUS;
3387       break;
3388 
3389     default:
3390       ret = HAL_ERROR;
3391       break;
3392   }
3393 
3394   /* Clear device address, Endpoint number and Low Speed Endpoint fields */
3395   wChRegVal &= ~(USB_CHEP_DEVADDR |
3396                  USB_CHEP_ADDR |
3397                  USB_CHEP_LSEP |
3398                  USB_CHEP_NAK |
3399                  USB_CHEP_KIND |
3400                  USB_CHEP_ERRTX |
3401                  USB_CHEP_ERRRX |
3402                  (0xFU << 27));
3403 
3404   /* Set device address and Endpoint number associated to the channel */
3405   wChRegVal |= (((uint32_t)dev_address << USB_CHEP_DEVADDR_Pos) |
3406                 ((uint32_t)epnum & 0x0FU));
3407 
3408   /* Get Host core Speed */
3409   HostCoreSpeed = USB_GetHostSpeed(USBx);
3410 
3411   /* Set the device speed in case using HUB FS with device LS */
3412   if ((speed == USB_DRD_SPEED_LS) && (HostCoreSpeed == USB_DRD_SPEED_FS))
3413   {
3414     wChRegVal |= USB_CHEP_LSEP;
3415   }
3416 
3417   /* Update the channel register value */
3418   USB_DRD_SET_CHEP(USBx, phy_ch_num, (wChRegVal | USB_CH_VTRX | USB_CH_VTTX));
3419 
3420   return ret;
3421 }
3422 
3423 /**
3424   * @brief  Start a transfer over a host channel
3425   * @param  USBx Selected device
3426   * @param  hc pointer to host channel structure
3427   * @retval HAL state
3428   */
USB_HC_StartXfer(USB_DRD_TypeDef * USBx,USB_DRD_HCTypeDef * hc)3429 HAL_StatusTypeDef USB_HC_StartXfer(USB_DRD_TypeDef *USBx, USB_DRD_HCTypeDef *hc)
3430 {
3431   uint32_t len;
3432   uint32_t phy_ch_num = (uint32_t)hc->phy_ch_num;
3433 #if (USE_USB_DOUBLE_BUFFER == 1U)
3434   uint32_t ch_reg = USB_DRD_GET_CHEP(USBx, phy_ch_num);
3435 #endif /* USE_USB_DOUBLE_BUFFER */
3436 
3437   if (hc->ch_dir == CH_IN_DIR)  /* In Channel */
3438   {
3439     /* Multi packet transfer */
3440     if (hc->xfer_len > hc->max_packet)
3441     {
3442       len = hc->max_packet;
3443     }
3444     else
3445     {
3446       len = hc->xfer_len;
3447     }
3448 
3449     if (hc->doublebuffer == 0U)
3450     {
3451       if ((hc->ep_type == EP_TYPE_BULK) ||
3452           (hc->ep_type == EP_TYPE_INTR))
3453       {
3454         USB_DRD_CLEAR_RX_DTOG(USBx, phy_ch_num);
3455 
3456         /* Set Data PID */
3457         if (hc->data_pid == HC_PID_DATA1)
3458         {
3459           USB_DRD_RX_DTOG(USBx, phy_ch_num);
3460         }
3461       }
3462 
3463       /* Set RX buffer count */
3464       USB_DRD_SET_CHEP_RX_CNT(USBx, phy_ch_num, len);
3465     }
3466 #if (USE_USB_DOUBLE_BUFFER == 1U)
3467     else if (hc->ep_type == EP_TYPE_BULK)
3468     {
3469       /* Double buffer activated */
3470       if ((hc->xfer_len > hc->max_packet))
3471       {
3472         (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_ENBALE);
3473 
3474         /* Set the Double buffer counter */
3475         USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 0U, len);
3476         USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 0U, len);
3477       }
3478       else  /* Switch to single buffer mode */
3479       {
3480         (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_DISABLE);
3481 
3482         /* Set RX buffer count */
3483         USB_DRD_SET_CHEP_RX_CNT(USBx, phy_ch_num, len);
3484       }
3485     }
3486     else  /* Isochronous */
3487     {
3488       /* Set the Double buffer counter */
3489       USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 0U, len);
3490       USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 0U, len);
3491     }
3492 #endif /* USE_USB_DOUBLE_BUFFER */
3493 
3494     /* Enable host channel */
3495     USB_DRD_SET_CHEP_RX_STATUS(USBx, phy_ch_num, USB_CH_RX_VALID);
3496   }
3497   else   /* Out Channel */
3498   {
3499     /* Multi packet transfer */
3500     if (hc->xfer_len > hc->max_packet)
3501     {
3502       len = hc->max_packet;
3503     }
3504     else
3505     {
3506       len = hc->xfer_len;
3507     }
3508 
3509     /* Configure and validate Tx endpoint */
3510     if (hc->doublebuffer == 0U)
3511     {
3512       USB_WritePMA(USBx, hc->xfer_buff, hc->pmaadress, (uint16_t)len);
3513       USB_DRD_SET_CHEP_TX_CNT(USBx, phy_ch_num, (uint16_t)len);
3514 
3515       /* SET PID SETUP  */
3516       if ((hc->data_pid) == HC_PID_SETUP)
3517       {
3518         USB_DRD_CHEP_TX_SETUP(USBx,  phy_ch_num);
3519       }
3520 
3521       if ((hc->ep_type == EP_TYPE_BULK) ||
3522           (hc->ep_type == EP_TYPE_INTR))
3523       {
3524         USB_DRD_CLEAR_TX_DTOG(USBx, phy_ch_num);
3525 
3526         /* Set Data PID */
3527         if (hc->data_pid == HC_PID_DATA1)
3528         {
3529           USB_DRD_TX_DTOG(USBx, phy_ch_num);
3530         }
3531       }
3532     }
3533 #if (USE_USB_DOUBLE_BUFFER == 1U)
3534     else if (hc->ep_type == EP_TYPE_BULK)
3535     {
3536       (void)USB_HC_BULK_DB_StartXfer(USBx, hc, ch_reg, &len);
3537     }
3538     else
3539     {
3540       (void)USB_HC_ISO_DB_StartXfer(USBx, hc, len);
3541     }
3542 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
3543 
3544     /* Enable host channel */
3545     USB_DRD_SET_CHEP_TX_STATUS(USBx, hc->phy_ch_num, USB_CH_TX_VALID);
3546   }
3547 
3548   return HAL_OK;
3549 }
3550 
3551 #if (USE_USB_DOUBLE_BUFFER == 1U)
3552 /**
3553   * @brief  Start Transfer of Channel isochronous out double buffer
3554   * @param  USBx Selected device
3555   * @param  hc_num Host Channel number
3556   *         This parameter can be a value from 1 to 15
3557   * @param  len Transfer Length
3558   * @retval HAL state
3559   */
USB_HC_ISO_DB_StartXfer(USB_DRD_TypeDef * USBx,USB_DRD_HCTypeDef * hc,uint32_t len)3560 static HAL_StatusTypeDef USB_HC_ISO_DB_StartXfer(USB_DRD_TypeDef *USBx,
3561                                                  USB_DRD_HCTypeDef *hc,
3562                                                  uint32_t len)
3563 {
3564   uint32_t phy_ch_num = (uint32_t)hc->phy_ch_num;
3565 
3566   /* check the DTOG_TX to determine in which buffer we should write */
3567   if ((USB_DRD_GET_CHEP(USBx, phy_ch_num) & USB_CH_DTOG_TX) != 0U)
3568   {
3569     USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 1U, len);
3570     USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)len);
3571   }
3572   else
3573   {
3574     /* DTOGTX=0 */
3575     /* Set the Double buffer counter for pmabuffer0 */
3576     USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 1U, len);
3577     USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr1, (uint16_t)len);
3578   }
3579 
3580   return HAL_OK;
3581 }
3582 
3583 /**
3584   * @brief  Start Transfer of Channel bulk out double buffer
3585   * @param  USBx Selected device
3586   * @param  hc_num Host Channel number
3587   *         This parameter can be a value from 1 to 15
3588   * @param  ch_reg snapshot of the CHEPR register
3589   * @param  len Transfer Length
3590   * @retval HAL state
3591   */
USB_HC_BULK_DB_StartXfer(USB_DRD_TypeDef * USBx,USB_DRD_HCTypeDef * hc,uint32_t ch_reg,uint32_t * len)3592 static HAL_StatusTypeDef USB_HC_BULK_DB_StartXfer(USB_DRD_TypeDef *USBx,
3593                                                   USB_DRD_HCTypeDef *hc,
3594                                                   uint32_t ch_reg,
3595                                                   uint32_t *len)
3596 {
3597   uint32_t phy_ch_num = (uint32_t)hc->phy_ch_num;
3598 
3599   /* -Double Buffer Mangement- */
3600   if (hc->xfer_len_db > hc->max_packet)
3601   {
3602     /* enable double buffer mode */
3603     (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_ENBALE);
3604     *len = hc->max_packet;
3605     hc->xfer_len_db -= *len;
3606 
3607     /* Prepare two buffer before enabling host */
3608     if ((ch_reg & USB_CH_DTOG_TX) == 0U)
3609     {
3610       /* Write Buffer0 */
3611       USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
3612       USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)*len);
3613     }
3614     else
3615     {
3616       /* Write Buffer1 */
3617       USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
3618       USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr1, (uint16_t)*len);
3619     }
3620 
3621     hc->xfer_buff += *len;
3622 
3623     /* Multi packet transfer */
3624     if (hc->xfer_len_db > hc->max_packet)
3625     {
3626       hc->xfer_len_db -= *len;
3627     }
3628     else
3629     {
3630       *len = hc->xfer_len_db;
3631       hc->xfer_len_db = 0U;
3632     }
3633 
3634     if ((ch_reg & USB_CH_DTOG_TX) == 0U)
3635     {
3636       /* Write Buffer1 */
3637       USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
3638       USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr1, (uint16_t)*len);
3639     }
3640     else
3641     {
3642       /* Write Buffer0 */
3643       USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
3644       USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)*len);
3645     }
3646   }
3647   else
3648   {
3649     /* Disable bulk double buffer mode */
3650     (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_DISABLE);
3651     USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)*len);
3652     USB_DRD_SET_CHEP_TX_CNT(USBx, phy_ch_num, (uint16_t)*len);
3653   }
3654 
3655   return HAL_OK;
3656 }
3657 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
3658 
3659 
3660 /**
3661   * @brief  Halt a host channel in
3662   * @param  USBx Selected device
3663   * @param  hc_num Host Channel number
3664   *         This parameter can be a value from 1 to 15
3665   * @retval HAL state
3666   */
USB_HC_IN_Halt(USB_DRD_TypeDef * USBx,uint8_t phy_ch)3667 HAL_StatusTypeDef USB_HC_IN_Halt(USB_DRD_TypeDef *USBx, uint8_t phy_ch)
3668 {
3669   /* Set disable to Channel */
3670   USB_DRD_SET_CHEP_RX_STATUS(USBx, phy_ch, USB_CH_RX_DIS);
3671 
3672   return HAL_OK;
3673 }
3674 
3675 
3676 /**
3677   * @brief  Halt a host channel out
3678   * @param  USBx Selected device
3679   * @param  hc_num Host Channel number
3680   *         This parameter can be a value from 1 to 15
3681   * @retval HAL state
3682   */
USB_HC_OUT_Halt(USB_DRD_TypeDef * USBx,uint8_t phy_ch)3683 HAL_StatusTypeDef USB_HC_OUT_Halt(USB_DRD_TypeDef *USBx, uint8_t phy_ch)
3684 {
3685   /* Set disable to Channel */
3686   USB_DRD_SET_CHEP_TX_STATUS(USBx, phy_ch, USB_CH_TX_DIS);
3687 
3688   return HAL_OK;
3689 }
3690 
3691 /**
3692   * @brief  Stop Host Core
3693   * @param  USBx Selected device
3694   * @retval HAL state
3695   */
USB_StopHost(USB_DRD_TypeDef * USBx)3696 HAL_StatusTypeDef USB_StopHost(USB_DRD_TypeDef *USBx)
3697 {
3698   USBx->ISTR &= ~(USB_ISTR_DIR | USB_ISTR_L1REQ |
3699                   USB_ISTR_ESOF | USB_ISTR_SOF |
3700                   USB_ISTR_RESET | USB_ISTR_DCON |
3701                   USB_ISTR_SUSP | USB_ISTR_WKUP |
3702                   USB_ISTR_ERR | USB_ISTR_PMAOVR |
3703                   USB_ISTR_CTR);
3704 
3705   /* Set PowerDown */
3706   USBx->CNTR |= USB_CNTR_PDWN;
3707 
3708   /* Force a Reset */
3709   USBx->CNTR |= USB_CNTR_USBRST;
3710 
3711   return HAL_OK;
3712 }
3713 #endif /* defined (USB_DRD_FS) */
3714 /**
3715   * @}
3716   */
3717 
3718 /**
3719   * @}
3720   */
3721 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) || defined (USB_DRD_FS) */
3722 #endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
3723 
3724 /**
3725   * @}
3726   */
3727