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