1 /**
2   ******************************************************************************
3   * @file    stm32f7xx_ll_usb.c
4   * @author  MCD Application Team
5   * @version V1.0.1
6   * @date    25-June-2015
7   * @brief   USB Low Layer HAL module driver.
8   *
9   *          This file provides firmware functions to manage the following
10   *          functionalities of the USB Peripheral Controller:
11   *           + Initialization/de-initialization functions
12   *           + I/O operation functions
13   *           + Peripheral Control functions
14   *           + Peripheral State functions
15   *
16   @verbatim
17   ==============================================================================
18                     ##### How to use this driver #####
19   ==============================================================================
20     [..]
21       (#) Fill parameters of Init structure in USB_OTG_CfgTypeDef structure.
22 
23       (#) Call USB_CoreInit() API to initialize the USB Core peripheral.
24 
25       (#) The upper HAL HCD/PCD driver will call the right routines for its internal processes.
26 
27   @endverbatim
28   ******************************************************************************
29   * @attention
30   *
31   * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
32   *
33   * Redistribution and use in source and binary forms, with or without modification,
34   * are permitted provided that the following conditions are met:
35   *   1. Redistributions of source code must retain the above copyright notice,
36   *      this list of conditions and the following disclaimer.
37   *   2. Redistributions in binary form must reproduce the above copyright notice,
38   *      this list of conditions and the following disclaimer in the documentation
39   *      and/or other materials provided with the distribution.
40   *   3. Neither the name of STMicroelectronics nor the names of its contributors
41   *      may be used to endorse or promote products derived from this software
42   *      without specific prior written permission.
43   *
44   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
45   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
47   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
48   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
50   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
51   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
52   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54   *
55   ******************************************************************************
56   */
57 
58 /* Includes ------------------------------------------------------------------*/
59 #include "stm32f7xx_hal.h"
60 
61 /** @addtogroup STM32F7xx_LL_USB_DRIVER
62   * @{
63   */
64 
65 #if defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED)
66 
67 /* Private typedef -----------------------------------------------------------*/
68 /* Private define ------------------------------------------------------------*/
69 /* Private macro -------------------------------------------------------------*/
70 /* Private variables ---------------------------------------------------------*/
71 /* Private function prototypes -----------------------------------------------*/
72 /* Private functions ---------------------------------------------------------*/
73 static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx);
74 
75 /** @defgroup PCD_Private_Functions
76   * @{
77   */
78 
79 /** @defgroup LL_USB_Group1 Initialization/de-initialization functions
80  *  @brief    Initialization and Configuration functions
81  *
82 @verbatim
83  ===============================================================================
84               ##### Initialization/de-initialization functions #####
85  ===============================================================================
86     [..]  This section provides functions allowing to:
87 
88 @endverbatim
89   * @{
90   */
91 
92 /**
93   * @brief  Initializes the USB Core
94   * @param  USBx: USB Instance
95   * @param  cfg : pointer to a USB_OTG_CfgTypeDef structure that contains
96   *         the configuration information for the specified USBx peripheral.
97   * @retval HAL status
98   */
USB_CoreInit(USB_OTG_GlobalTypeDef * USBx,USB_OTG_CfgTypeDef cfg)99 HAL_StatusTypeDef USB_CoreInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
100 {
101     if (cfg.phy_itface == USB_OTG_ULPI_PHY) {
102 
103         USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
104 
105         /* Init The ULPI Interface */
106         USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL);
107 
108         /* Select vbus source */
109         USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI);
110         if (cfg.use_external_vbus == 1) {
111             USBx->GUSBCFG |= USB_OTG_GUSBCFG_ULPIEVBUSD;
112         }
113         /* Reset after a PHY select  */
114         USB_CoreReset(USBx);
115     } else { /* FS interface (embedded Phy) */
116 
117         /* Select FS Embedded PHY */
118         USBx->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
119 
120         /* Reset after a PHY select and set Host mode */
121         USB_CoreReset(USBx);
122 
123         /* Deactivate the power down*/
124         USBx->GCCFG = USB_OTG_GCCFG_PWRDWN;
125     }
126 
127     if (cfg.dma_enable == ENABLE) {
128         USBx->GAHBCFG |= (USB_OTG_GAHBCFG_HBSTLEN_1 | USB_OTG_GAHBCFG_HBSTLEN_2);
129         USBx->GAHBCFG |= USB_OTG_GAHBCFG_DMAEN;
130     }
131 
132     return HAL_OK;
133 }
134 
135 /**
136   * @brief  USB_EnableGlobalInt
137   *         Enables the controller's Global Int in the AHB Config reg
138   * @param  USBx : Selected device
139   * @retval HAL status
140   */
USB_EnableGlobalInt(USB_OTG_GlobalTypeDef * USBx)141 HAL_StatusTypeDef USB_EnableGlobalInt(USB_OTG_GlobalTypeDef *USBx)
142 {
143     USBx->GAHBCFG |= USB_OTG_GAHBCFG_GINT;
144     return HAL_OK;
145 }
146 
147 
148 /**
149   * @brief  USB_DisableGlobalInt
150   *         Disable the controller's Global Int in the AHB Config reg
151   * @param  USBx : Selected device
152   * @retval HAL status
153 */
USB_DisableGlobalInt(USB_OTG_GlobalTypeDef * USBx)154 HAL_StatusTypeDef USB_DisableGlobalInt(USB_OTG_GlobalTypeDef *USBx)
155 {
156     USBx->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
157     return HAL_OK;
158 }
159 
160 /**
161   * @brief  USB_SetCurrentMode : Set functional mode
162   * @param  USBx : Selected device
163   * @param  mode :  current core mode
164   *          This parameter can be one of the these values:
165   *            @arg USB_OTG_DEVICE_MODE: Peripheral mode
166   *            @arg USB_OTG_HOST_MODE: Host mode
167   *            @arg USB_OTG_DRD_MODE: Dual Role Device mode
168   * @retval HAL status
169   */
USB_SetCurrentMode(USB_OTG_GlobalTypeDef * USBx,USB_OTG_ModeTypeDef mode)170 HAL_StatusTypeDef USB_SetCurrentMode(USB_OTG_GlobalTypeDef *USBx , USB_OTG_ModeTypeDef mode)
171 {
172     USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD);
173 
174     if ( mode == USB_OTG_HOST_MODE) {
175         USBx->GUSBCFG |= USB_OTG_GUSBCFG_FHMOD;
176     } else if ( mode == USB_OTG_DEVICE_MODE) {
177         USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
178     }
179     HAL_Delay(50);
180 
181     return HAL_OK;
182 }
183 
184 /**
185   * @brief  USB_DevInit : Initializes the USB_OTG controller registers
186   *         for device mode
187   * @param  USBx : Selected device
188   * @param  cfg  : pointer to a USB_OTG_CfgTypeDef structure that contains
189   *         the configuration information for the specified USBx peripheral.
190   * @retval HAL status
191   */
USB_DevInit(USB_OTG_GlobalTypeDef * USBx,USB_OTG_CfgTypeDef cfg)192 HAL_StatusTypeDef USB_DevInit (USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
193 {
194     uint32_t i = 0;
195 
196     /*Activate VBUS Sensing B */
197     USBx->GCCFG |= USB_OTG_GCCFG_VBDEN;
198 
199     if (cfg.vbus_sensing_enable == 0) {
200         /*Desactivate VBUS Sensing B */
201         USBx->GCCFG &= ~ USB_OTG_GCCFG_VBDEN;
202 
203         /* B-peripheral session valid override enable*/
204         USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
205         USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
206     }
207 
208     /* Restart the Phy Clock */
209     USBx_PCGCCTL = 0;
210 
211     /* Device mode configuration */
212     USBx_DEVICE->DCFG |= DCFG_FRAME_INTERVAL_80;
213 
214     if (cfg.phy_itface  == USB_OTG_ULPI_PHY) {
215         if (cfg.speed == USB_OTG_SPEED_HIGH) {
216             /* Set High speed phy */
217             USB_SetDevSpeed (USBx , USB_OTG_SPEED_HIGH);
218         } else {
219             /* set High speed phy in Full speed mode */
220             USB_SetDevSpeed (USBx , USB_OTG_SPEED_HIGH_IN_FULL);
221         }
222     } else {
223         /* Set Full speed phy */
224         USB_SetDevSpeed (USBx , USB_OTG_SPEED_FULL);
225     }
226 
227     /* Flush the FIFOs */
228     USB_FlushTxFifo(USBx , 0x10); /* all Tx FIFOs */
229     USB_FlushRxFifo(USBx);
230 
231 
232     /* Clear all pending Device Interrupts */
233     USBx_DEVICE->DIEPMSK = 0;
234     USBx_DEVICE->DOEPMSK = 0;
235     USBx_DEVICE->DAINT = 0xFFFFFFFF;
236     USBx_DEVICE->DAINTMSK = 0;
237 
238     for (i = 0; i < cfg.dev_endpoints; i++) {
239         if ((USBx_INEP(i)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA) {
240             USBx_INEP(i)->DIEPCTL = (USB_OTG_DIEPCTL_EPDIS | USB_OTG_DIEPCTL_SNAK);
241         } else {
242             USBx_INEP(i)->DIEPCTL = 0;
243         }
244 
245         USBx_INEP(i)->DIEPTSIZ = 0;
246         USBx_INEP(i)->DIEPINT  = 0xFF;
247     }
248 
249     for (i = 0; i < cfg.dev_endpoints; i++) {
250         if ((USBx_OUTEP(i)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA) {
251             USBx_OUTEP(i)->DOEPCTL = (USB_OTG_DOEPCTL_EPDIS | USB_OTG_DOEPCTL_SNAK);
252         } else {
253             USBx_OUTEP(i)->DOEPCTL = 0;
254         }
255 
256         USBx_OUTEP(i)->DOEPTSIZ = 0;
257         USBx_OUTEP(i)->DOEPINT  = 0xFF;
258     }
259 
260     USBx_DEVICE->DIEPMSK &= ~(USB_OTG_DIEPMSK_TXFURM);
261 
262     if (cfg.dma_enable == 1) {
263         /*Set threshold parameters */
264         USBx_DEVICE->DTHRCTL = (USB_OTG_DTHRCTL_TXTHRLEN_6 | USB_OTG_DTHRCTL_RXTHRLEN_6);
265         USBx_DEVICE->DTHRCTL |= (USB_OTG_DTHRCTL_RXTHREN | USB_OTG_DTHRCTL_ISOTHREN | USB_OTG_DTHRCTL_NONISOTHREN);
266 
267         i= USBx_DEVICE->DTHRCTL;
268     }
269 
270     /* Disable all interrupts. */
271     USBx->GINTMSK = 0;
272 
273     /* Clear any pending interrupts */
274     USBx->GINTSTS = 0xBFFFFFFF;
275 
276     /* Enable the common interrupts */
277     if (cfg.dma_enable == DISABLE) {
278         USBx->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
279     }
280 
281     /* Enable interrupts matching to the Device mode ONLY */
282     USBx->GINTMSK |= (USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_USBRST |\
283                       USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_IEPINT |\
284                       USB_OTG_GINTMSK_OEPINT   | USB_OTG_GINTMSK_IISOIXFRM|\
285                       USB_OTG_GINTMSK_PXFRM_IISOOXFRM | USB_OTG_GINTMSK_WUIM);
286 
287     if (cfg.Sof_enable) {
288         USBx->GINTMSK |= USB_OTG_GINTMSK_SOFM;
289     }
290 
291     if (cfg.vbus_sensing_enable == ENABLE) {
292         USBx->GINTMSK |= (USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_OTGINT);
293     }
294 
295     return HAL_OK;
296 }
297 
298 
299 /**
300   * @brief  USB_OTG_FlushTxFifo : Flush a Tx FIFO
301   * @param  USBx : Selected device
302   * @param  num : FIFO number
303   *         This parameter can be a value from 1 to 15
304             15 means Flush all Tx FIFOs
305   * @retval HAL status
306   */
USB_FlushTxFifo(USB_OTG_GlobalTypeDef * USBx,uint32_t num)307 HAL_StatusTypeDef USB_FlushTxFifo (USB_OTG_GlobalTypeDef *USBx, uint32_t num )
308 {
309     uint32_t count = 0;
310 
311     USBx->GRSTCTL = ( USB_OTG_GRSTCTL_TXFFLSH |(uint32_t)( num << 6));
312 
313     do {
314         if (++count > 200000) {
315             return HAL_TIMEOUT;
316         }
317     } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH);
318 
319     return HAL_OK;
320 }
321 
322 
323 /**
324   * @brief  USB_FlushRxFifo : Flush Rx FIFO
325   * @param  USBx : Selected device
326   * @retval HAL status
327   */
USB_FlushRxFifo(USB_OTG_GlobalTypeDef * USBx)328 HAL_StatusTypeDef USB_FlushRxFifo(USB_OTG_GlobalTypeDef *USBx)
329 {
330     uint32_t count = 0;
331 
332     USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH;
333 
334     do {
335         if (++count > 200000) {
336             return HAL_TIMEOUT;
337         }
338     } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH);
339 
340     return HAL_OK;
341 }
342 
343 /**
344   * @brief  USB_SetDevSpeed :Initializes the DevSpd field of DCFG register
345   *         depending the PHY type and the enumeration speed of the device.
346   * @param  USBx : Selected device
347   * @param  speed : device speed
348   *          This parameter can be one of the these values:
349   *            @arg USB_OTG_SPEED_HIGH: High speed mode
350   *            @arg USB_OTG_SPEED_HIGH_IN_FULL: High speed core in Full Speed mode
351   *            @arg USB_OTG_SPEED_FULL: Full speed mode
352   *            @arg USB_OTG_SPEED_LOW: Low speed mode
353   * @retval  Hal status
354   */
USB_SetDevSpeed(USB_OTG_GlobalTypeDef * USBx,uint8_t speed)355 HAL_StatusTypeDef USB_SetDevSpeed(USB_OTG_GlobalTypeDef *USBx , uint8_t speed)
356 {
357     USBx_DEVICE->DCFG |= speed;
358     return HAL_OK;
359 }
360 
361 /**
362   * @brief  USB_GetDevSpeed :Return the  Dev Speed
363   * @param  USBx : Selected device
364   * @retval speed : device speed
365   *          This parameter can be one of the these values:
366   *            @arg USB_OTG_SPEED_HIGH: High speed mode
367   *            @arg USB_OTG_SPEED_FULL: Full speed mode
368   *            @arg USB_OTG_SPEED_LOW: Low speed mode
369   */
USB_GetDevSpeed(USB_OTG_GlobalTypeDef * USBx)370 uint8_t USB_GetDevSpeed(USB_OTG_GlobalTypeDef *USBx)
371 {
372     uint8_t speed = 0;
373 
374     if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ) {
375         speed = USB_OTG_SPEED_HIGH;
376     } else if (((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ)||
377                ((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_FS_PHY_48MHZ)) {
378         speed = USB_OTG_SPEED_FULL;
379     } else if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_LS_PHY_6MHZ) {
380         speed = USB_OTG_SPEED_LOW;
381     }
382 
383     return speed;
384 }
385 
386 /**
387   * @brief  Activate and configure an endpoint
388   * @param  USBx : Selected device
389   * @param  ep: pointer to endpoint structure
390   * @retval HAL status
391   */
USB_ActivateEndpoint(USB_OTG_GlobalTypeDef * USBx,USB_OTG_EPTypeDef * ep)392 HAL_StatusTypeDef USB_ActivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
393 {
394     if (ep->is_in == 1) {
395         USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num)));
396 
397         if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0) {
398             USBx_INEP(ep->num)->DIEPCTL |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\
399                                             ((ep->num) << 22 ) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP));
400         }
401 
402     } else {
403         USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16);
404 
405         if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0) {
406             USBx_OUTEP(ep->num)->DOEPCTL |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\
407                                              (USB_OTG_DIEPCTL_SD0PID_SEVNFRM)| (USB_OTG_DOEPCTL_USBAEP) |\
408                                              (USB_OTG_DOEPCTL_SNAK)); // TKG add to default receive eps as NAK until queued
409         }
410     }
411     return HAL_OK;
412 }
413 /**
414   * @brief  Activate and configure a dedicated endpoint
415   * @param  USBx : Selected device
416   * @param  ep: pointer to endpoint structure
417   * @retval HAL status
418   */
USB_ActivateDedicatedEndpoint(USB_OTG_GlobalTypeDef * USBx,USB_OTG_EPTypeDef * ep)419 HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
420 {
421     static __IO uint32_t debug = 0;
422 
423     /* Read DEPCTLn register */
424     if (ep->is_in == 1) {
425         if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0) {
426             USBx_INEP(ep->num)->DIEPCTL |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\
427                                             ((ep->num) << 22 ) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP));
428         }
429 
430 
431         debug  |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\
432                    ((ep->num) << 22 ) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP));
433 
434         USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num)));
435     } else {
436         if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0) {
437             USBx_OUTEP(ep->num)->DOEPCTL |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\
438                                              ((ep->num) << 22 ) | (USB_OTG_DOEPCTL_USBAEP));
439 
440             debug = (uint32_t)(((uint32_t )USBx) + USB_OTG_OUT_ENDPOINT_BASE + (0)*USB_OTG_EP_REG_SIZE);
441             debug = (uint32_t )&USBx_OUTEP(ep->num)->DOEPCTL;
442             debug |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\
443                       ((ep->num) << 22 ) | (USB_OTG_DOEPCTL_USBAEP));
444         }
445 
446         USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16);
447     }
448 
449     return HAL_OK;
450 }
451 /**
452   * @brief  De-activate and de-initialize an endpoint
453   * @param  USBx : Selected device
454   * @param  ep: pointer to endpoint structure
455   * @retval HAL status
456   */
USB_DeactivateEndpoint(USB_OTG_GlobalTypeDef * USBx,USB_OTG_EPTypeDef * ep)457 HAL_StatusTypeDef USB_DeactivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
458 {
459     /* Read DEPCTLn register */
460     if (ep->is_in == 1) {
461         USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num))));
462         USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num))));
463         USBx_INEP(ep->num)->DIEPCTL &= ~ USB_OTG_DIEPCTL_USBAEP;
464     } else {
465 
466         USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16));
467         USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16));
468         USBx_OUTEP(ep->num)->DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP;
469     }
470     return HAL_OK;
471 }
472 
473 /**
474   * @brief  De-activate and de-initialize a dedicated endpoint
475   * @param  USBx : Selected device
476   * @param  ep: pointer to endpoint structure
477   * @retval HAL status
478   */
USB_DeactivateDedicatedEndpoint(USB_OTG_GlobalTypeDef * USBx,USB_OTG_EPTypeDef * ep)479 HAL_StatusTypeDef USB_DeactivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
480 {
481     /* Read DEPCTLn register */
482     if (ep->is_in == 1) {
483         USBx_INEP(ep->num)->DIEPCTL &= ~ USB_OTG_DIEPCTL_USBAEP;
484         USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num))));
485     } else {
486         USBx_OUTEP(ep->num)->DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP;
487         USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16));
488     }
489     return HAL_OK;
490 }
491 
492 /**
493   * @brief  USB_EPStartXfer : setup and starts a transfer over an EP
494   * @param  USBx : Selected device
495   * @param  ep: pointer to endpoint structure
496   * @param  dma: USB dma enabled or disabled
497   *          This parameter can be one of the these values:
498   *           0 : DMA feature not used
499   *           1 : DMA feature used
500   * @retval HAL status
501   */
USB_EPStartXfer(USB_OTG_GlobalTypeDef * USBx,USB_OTG_EPTypeDef * ep,uint8_t dma)502 HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma)
503 {
504     uint16_t pktcnt = 0;
505 
506     /* IN endpoint */
507     if (ep->is_in == 1) {
508         /* Zero Length Packet? */
509         if (ep->xfer_len == 0) {
510             USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
511             USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) ;
512             USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
513         } else {
514             /* Program the transfer size and packet count
515             * as follows: xfersize = N * maxpacket +
516             * short_packet pktcnt = N + (short_packet
517             * exist ? 1 : 0)
518             */
519             USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
520             USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
521             USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (((ep->xfer_len + ep->maxpacket -1)/ ep->maxpacket) << 19)) ;
522             USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & ep->xfer_len);
523 
524             if (ep->type == EP_TYPE_ISOC) {
525                 USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_MULCNT);
526                 USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & (1 << 29));
527             }
528         }
529 
530         if (dma == 1) {
531             USBx_INEP(ep->num)->DIEPDMA = (uint32_t)(ep->dma_addr);
532         } else {
533             if (ep->type != EP_TYPE_ISOC) {
534                 /* Enable the Tx FIFO Empty Interrupt for this EP */
535                 if (ep->xfer_len > 0) {
536                     USBx_DEVICE->DIEPEMPMSK |= 1 << ep->num;
537                 }
538             }
539         }
540 
541         if (ep->type == EP_TYPE_ISOC) {
542             if ((USBx_DEVICE->DSTS & ( 1 << 8 )) == 0) {
543                 USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM;
544             } else {
545                 USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
546             }
547         }
548 
549         /* EP enable, IN data in FIFO */
550         USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
551 
552         if (ep->type == EP_TYPE_ISOC) {
553             USB_WritePacket(USBx, ep->xfer_buff, ep->num, ep->xfer_len, dma);
554         }
555     } else { /* OUT endpoint */
556         /* Program the transfer size and packet count as follows:
557         * pktcnt = N
558         * xfersize = N * maxpacket
559         */
560         USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ);
561         USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT);
562 
563         if (ep->xfer_len == 0) {
564             USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & ep->maxpacket);
565             USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) ;
566         } else {
567             pktcnt = (ep->xfer_len + ep->maxpacket -1)/ ep->maxpacket;
568             USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (pktcnt << 19));
569             USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & (ep->maxpacket * pktcnt));
570         }
571 
572         if (dma == 1) {
573             USBx_OUTEP(ep->num)->DOEPDMA = (uint32_t)ep->xfer_buff;
574         }
575 
576         if (ep->type == EP_TYPE_ISOC) {
577             if ((USBx_DEVICE->DSTS & ( 1 << 8 )) == 0) {
578                 USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_SODDFRM;
579             } else {
580                 USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
581             }
582         }
583         /* EP enable */
584         USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA);
585     }
586     return HAL_OK;
587 }
588 
589 /**
590   * @brief  USB_EP0StartXfer : setup and starts a transfer over the EP  0
591   * @param  USBx : Selected device
592   * @param  ep: pointer to endpoint structure
593   * @param  dma: USB dma enabled or disabled
594   *          This parameter can be one of the these values:
595   *           0 : DMA feature not used
596   *           1 : DMA feature used
597   * @retval HAL status
598   */
USB_EP0StartXfer(USB_OTG_GlobalTypeDef * USBx,USB_OTG_EPTypeDef * ep,uint8_t dma)599 HAL_StatusTypeDef USB_EP0StartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma)
600 {
601     /* IN endpoint */
602     if (ep->is_in == 1) {
603         /* Zero Length Packet? */
604         if (ep->xfer_len == 0) {
605             USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
606             USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) ;
607             USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
608         } else {
609             /* Program the transfer size and packet count
610             * as follows: xfersize = N * maxpacket +
611             * short_packet pktcnt = N + (short_packet
612             * exist ? 1 : 0)
613             */
614             USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
615             USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
616 
617             if (ep->xfer_len > ep->maxpacket) {
618                 ep->xfer_len = ep->maxpacket;
619             }
620             USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) ;
621             USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & ep->xfer_len);
622 
623         }
624 
625         if (dma == 1) {
626             USBx_INEP(ep->num)->DIEPDMA = (uint32_t)(ep->dma_addr);
627         } else {
628             /* Enable the Tx FIFO Empty Interrupt for this EP */
629             if (ep->xfer_len > 0) {
630                 USBx_DEVICE->DIEPEMPMSK |= 1 << (ep->num);
631             }
632         }
633 
634         /* EP enable, IN data in FIFO */
635         USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
636     } else { /* OUT endpoint */
637         /* Program the transfer size and packet count as follows:
638         * pktcnt = N
639         * xfersize = N * maxpacket
640         */
641         USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ);
642         USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT);
643 
644         if (ep->xfer_len > 0) {
645             ep->xfer_len = ep->maxpacket;
646         }
647 
648         USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19));
649         USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & (ep->maxpacket));
650 
651 
652         if (dma == 1) {
653             USBx_OUTEP(ep->num)->DOEPDMA = (uint32_t)(ep->xfer_buff);
654         }
655 
656         /* EP enable */
657         USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA);
658     }
659     return HAL_OK;
660 }
661 
662 /**
663   * @brief  USB_WritePacket : Writes a packet into the Tx FIFO associated
664   *         with the EP/channel
665   * @param  USBx : Selected device
666   * @param  src :  pointer to source buffer
667   * @param  ch_ep_num : endpoint or host channel number
668   * @param  len : Number of bytes to write
669   * @param  dma: USB dma enabled or disabled
670   *          This parameter can be one of the these values:
671   *           0 : DMA feature not used
672   *           1 : DMA feature used
673   * @retval HAL status
674   */
USB_WritePacket(USB_OTG_GlobalTypeDef * USBx,uint8_t * src,uint8_t ch_ep_num,uint16_t len,uint8_t dma)675 HAL_StatusTypeDef USB_WritePacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *src, uint8_t ch_ep_num, uint16_t len, uint8_t dma)
676 {
677     uint32_t count32b= 0 , i= 0;
678 
679     if (dma == 0) {
680         count32b =  (len + 3) / 4;
681         for (i = 0; i < count32b; i++, src += 4) {
682             USBx_DFIFO(ch_ep_num) = *((__packed uint32_t *)src);
683         }
684     }
685     return HAL_OK;
686 }
687 
688 /**
689   * @brief  USB_ReadPacket : read a packet from the Tx FIFO associated
690   *         with the EP/channel
691   * @param  USBx : Selected device
692   * @param  src : source pointer
693   * @param  ch_ep_num : endpoint or host channel number
694   * @param  len : Number of bytes to read
695   * @param  dma: USB dma enabled or disabled
696   *          This parameter can be one of the these values:
697   *           0 : DMA feature not used
698   *           1 : DMA feature used
699   * @retval pointer to destination buffer
700   */
USB_ReadPacket(USB_OTG_GlobalTypeDef * USBx,uint8_t * dest,uint16_t len)701 void *USB_ReadPacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *dest, uint16_t len)
702 {
703     uint32_t i=0;
704     uint32_t count32b = (len + 3) / 4;
705 
706     for ( i = 0; i < count32b; i++, dest += 4 ) {
707         *(__packed uint32_t *)dest = USBx_DFIFO(0);
708 
709     }
710     return ((void *)dest);
711 }
712 
713 /**
714   * @brief  USB_EPSetStall : set a stall condition over an EP
715   * @param  USBx : Selected device
716   * @param  ep: pointer to endpoint structure
717   * @retval HAL status
718   */
USB_EPSetStall(USB_OTG_GlobalTypeDef * USBx,USB_OTG_EPTypeDef * ep)719 HAL_StatusTypeDef USB_EPSetStall(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep)
720 {
721     if (ep->is_in == 1) {
722         if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_EPENA) == 0) {
723             USBx_INEP(ep->num)->DIEPCTL &= ~(USB_OTG_DIEPCTL_EPDIS);
724         }
725         USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_STALL;
726     } else {
727         if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_EPENA) == 0) {
728             USBx_OUTEP(ep->num)->DOEPCTL &= ~(USB_OTG_DOEPCTL_EPDIS);
729         }
730         USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_STALL;
731     }
732     return HAL_OK;
733 }
734 
735 
736 /**
737   * @brief  USB_EPClearStall : Clear a stall condition over an EP
738   * @param  USBx : Selected device
739   * @param  ep: pointer to endpoint structure
740   * @retval HAL status
741   */
USB_EPClearStall(USB_OTG_GlobalTypeDef * USBx,USB_OTG_EPTypeDef * ep)742 HAL_StatusTypeDef USB_EPClearStall(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
743 {
744     if (ep->is_in == 1) {
745         USBx_INEP(ep->num)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
746         if (ep->type == EP_TYPE_INTR || ep->type == EP_TYPE_BULK) {
747             USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; /* DATA0 */
748         }
749     } else {
750         USBx_OUTEP(ep->num)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
751         if (ep->type == EP_TYPE_INTR || ep->type == EP_TYPE_BULK) {
752             USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; /* DATA0 */
753         }
754     }
755     return HAL_OK;
756 }
757 
758 /**
759   * @brief  USB_StopDevice : Stop the usb device mode
760   * @param  USBx : Selected device
761   * @retval HAL status
762   */
USB_StopDevice(USB_OTG_GlobalTypeDef * USBx)763 HAL_StatusTypeDef USB_StopDevice(USB_OTG_GlobalTypeDef *USBx)
764 {
765     uint32_t i;
766 
767     /* Clear Pending interrupt */
768     for (i = 0; i < 15 ; i++) {
769         USBx_INEP(i)->DIEPINT  = 0xFF;
770         USBx_OUTEP(i)->DOEPINT  = 0xFF;
771     }
772     USBx_DEVICE->DAINT = 0xFFFFFFFF;
773 
774     /* Clear interrupt masks */
775     USBx_DEVICE->DIEPMSK  = 0;
776     USBx_DEVICE->DOEPMSK  = 0;
777     USBx_DEVICE->DAINTMSK = 0;
778 
779     /* Flush the FIFO */
780     USB_FlushRxFifo(USBx);
781     USB_FlushTxFifo(USBx ,  0x10 );
782 
783     return HAL_OK;
784 }
785 
786 /**
787   * @brief  USB_SetDevAddress : Stop the usb device mode
788   * @param  USBx : Selected device
789   * @param  address : new device address to be assigned
790   *          This parameter can be a value from 0 to 255
791   * @retval HAL status
792   */
USB_SetDevAddress(USB_OTG_GlobalTypeDef * USBx,uint8_t address)793 HAL_StatusTypeDef  USB_SetDevAddress (USB_OTG_GlobalTypeDef *USBx, uint8_t address)
794 {
795     USBx_DEVICE->DCFG &= ~ (USB_OTG_DCFG_DAD);
796     USBx_DEVICE->DCFG |= (address << 4) & USB_OTG_DCFG_DAD ;
797 
798     return HAL_OK;
799 }
800 
801 /**
802   * @brief  USB_DevConnect : Connect the USB device by enabling the pull-up/pull-down
803   * @param  USBx : Selected device
804   * @retval HAL status
805   */
USB_DevConnect(USB_OTG_GlobalTypeDef * USBx)806 HAL_StatusTypeDef  USB_DevConnect (USB_OTG_GlobalTypeDef *USBx)
807 {
808     USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_SDIS ;
809     HAL_Delay(3);
810 
811     return HAL_OK;
812 }
813 
814 /**
815   * @brief  USB_DevDisconnect : Disconnect the USB device by disabling the pull-up/pull-down
816   * @param  USBx : Selected device
817   * @retval HAL status
818   */
USB_DevDisconnect(USB_OTG_GlobalTypeDef * USBx)819 HAL_StatusTypeDef  USB_DevDisconnect (USB_OTG_GlobalTypeDef *USBx)
820 {
821     USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS ;
822     HAL_Delay(3);
823 
824     return HAL_OK;
825 }
826 
827 /**
828   * @brief  USB_ReadInterrupts: return the global USB interrupt status
829   * @param  USBx : Selected device
830   * @retval HAL status
831   */
USB_ReadInterrupts(USB_OTG_GlobalTypeDef * USBx)832 uint32_t  USB_ReadInterrupts (USB_OTG_GlobalTypeDef *USBx)
833 {
834     uint32_t v = 0;
835 
836     v = USBx->GINTSTS;
837     v &= USBx->GINTMSK;
838     return v;
839 }
840 
841 /**
842   * @brief  USB_ReadDevAllOutEpInterrupt: return the USB device OUT endpoints interrupt status
843   * @param  USBx : Selected device
844   * @retval HAL status
845   */
USB_ReadDevAllOutEpInterrupt(USB_OTG_GlobalTypeDef * USBx)846 uint32_t USB_ReadDevAllOutEpInterrupt (USB_OTG_GlobalTypeDef *USBx)
847 {
848     uint32_t v;
849     v  = USBx_DEVICE->DAINT;
850     v &= USBx_DEVICE->DAINTMSK;
851     return ((v & 0xffff0000) >> 16);
852 }
853 
854 /**
855   * @brief  USB_ReadDevAllInEpInterrupt: return the USB device IN endpoints interrupt status
856   * @param  USBx : Selected device
857   * @retval HAL status
858   */
USB_ReadDevAllInEpInterrupt(USB_OTG_GlobalTypeDef * USBx)859 uint32_t USB_ReadDevAllInEpInterrupt (USB_OTG_GlobalTypeDef *USBx)
860 {
861     uint32_t v;
862     v  = USBx_DEVICE->DAINT;
863     v &= USBx_DEVICE->DAINTMSK;
864     return ((v & 0xFFFF));
865 }
866 
867 /**
868   * @brief  Returns Device OUT EP Interrupt register
869   * @param  USBx : Selected device
870   * @param  epnum : endpoint number
871   *          This parameter can be a value from 0 to 15
872   * @retval Device OUT EP Interrupt register
873   */
USB_ReadDevOutEPInterrupt(USB_OTG_GlobalTypeDef * USBx,uint8_t epnum)874 uint32_t USB_ReadDevOutEPInterrupt (USB_OTG_GlobalTypeDef *USBx , uint8_t epnum)
875 {
876     uint32_t v;
877     v  = USBx_OUTEP(epnum)->DOEPINT;
878     v &= USBx_DEVICE->DOEPMSK;
879     return v;
880 }
881 
882 /**
883   * @brief  Returns Device IN EP Interrupt register
884   * @param  USBx : Selected device
885   * @param  epnum : endpoint number
886   *          This parameter can be a value from 0 to 15
887   * @retval Device IN EP Interrupt register
888   */
USB_ReadDevInEPInterrupt(USB_OTG_GlobalTypeDef * USBx,uint8_t epnum)889 uint32_t USB_ReadDevInEPInterrupt (USB_OTG_GlobalTypeDef *USBx , uint8_t epnum)
890 {
891     uint32_t v, msk, emp;
892 
893     msk = USBx_DEVICE->DIEPMSK;
894     emp = USBx_DEVICE->DIEPEMPMSK;
895     msk |= ((emp >> epnum) & 0x1) << 7;
896     v = USBx_INEP(epnum)->DIEPINT & msk;
897     return v;
898 }
899 
900 /**
901   * @brief  USB_ClearInterrupts: clear a USB interrupt
902   * @param  USBx : Selected device
903   * @param  interrupt : interrupt flag
904   * @retval None
905   */
USB_ClearInterrupts(USB_OTG_GlobalTypeDef * USBx,uint32_t interrupt)906 void  USB_ClearInterrupts (USB_OTG_GlobalTypeDef *USBx, uint32_t interrupt)
907 {
908     USBx->GINTSTS |= interrupt;
909 }
910 
911 /**
912   * @brief  Returns USB core mode
913   * @param  USBx : Selected device
914   * @retval return core mode : Host or Device
915   *          This parameter can be one of the these values:
916   *           0 : Host
917   *           1 : Device
918   */
USB_GetMode(USB_OTG_GlobalTypeDef * USBx)919 uint32_t USB_GetMode(USB_OTG_GlobalTypeDef *USBx)
920 {
921     return ((USBx->GINTSTS ) & 0x1);
922 }
923 
924 
925 /**
926   * @brief  Activate EP0 for Setup transactions
927   * @param  USBx : Selected device
928   * @retval HAL status
929   */
USB_ActivateSetup(USB_OTG_GlobalTypeDef * USBx)930 HAL_StatusTypeDef  USB_ActivateSetup (USB_OTG_GlobalTypeDef *USBx)
931 {
932     /* Set the MPS of the IN EP based on the enumeration speed */
933     USBx_INEP(0)->DIEPCTL &= ~USB_OTG_DIEPCTL_MPSIZ;
934 
935     if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_LS_PHY_6MHZ) {
936         USBx_INEP(0)->DIEPCTL |= 3;
937     }
938     USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGINAK;
939 
940     return HAL_OK;
941 }
942 
943 
944 /**
945   * @brief  Prepare the EP0 to start the first control setup
946   * @param  USBx : Selected device
947   * @param  dma: USB dma enabled or disabled
948   *          This parameter can be one of the these values:
949   *           0 : DMA feature not used
950   *           1 : DMA feature used
951   * @param  psetup : pointer to setup packet
952   * @retval HAL status
953   */
USB_EP0_OutStart(USB_OTG_GlobalTypeDef * USBx,uint8_t dma,uint8_t * psetup)954 HAL_StatusTypeDef USB_EP0_OutStart(USB_OTG_GlobalTypeDef *USBx, uint8_t dma, uint8_t *psetup)
955 {
956     USBx_OUTEP(0)->DOEPTSIZ = 0;
957     USBx_OUTEP(0)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) ;
958     USBx_OUTEP(0)->DOEPTSIZ |= (3 * 8);
959     USBx_OUTEP(0)->DOEPTSIZ |=  USB_OTG_DOEPTSIZ_STUPCNT;
960 
961     if (dma == 1) {
962         USBx_OUTEP(0)->DOEPDMA = (uint32_t)psetup;
963         /* EP enable */
964         USBx_OUTEP(0)->DOEPCTL = 0x80008000;
965     }
966 
967     return HAL_OK;
968 }
969 
970 
971 /**
972   * @brief  Reset the USB Core (needed after USB clock settings change)
973   * @param  USBx : Selected device
974   * @retval HAL status
975   */
USB_CoreReset(USB_OTG_GlobalTypeDef * USBx)976 static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx)
977 {
978     uint32_t count = 0;
979 
980     /* Wait for AHB master IDLE state. */
981     do {
982         if (++count > 200000) {
983             return HAL_TIMEOUT;
984         }
985     } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0);
986 
987     /* Core Soft Reset */
988     count = 0;
989     USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
990 
991     do {
992         if (++count > 200000) {
993             return HAL_TIMEOUT;
994         }
995     } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);
996 
997     return HAL_OK;
998 }
999 
1000 
1001 /**
1002   * @brief  USB_HostInit : Initializes the USB OTG controller registers
1003   *         for Host mode
1004   * @param  USBx : Selected device
1005   * @param  cfg  : pointer to a USB_OTG_CfgTypeDef structure that contains
1006   *         the configuration information for the specified USBx peripheral.
1007   * @retval HAL status
1008   */
USB_HostInit(USB_OTG_GlobalTypeDef * USBx,USB_OTG_CfgTypeDef cfg)1009 HAL_StatusTypeDef USB_HostInit (USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
1010 {
1011     uint32_t i;
1012 
1013     /* Restart the Phy Clock */
1014     USBx_PCGCCTL = 0;
1015 
1016     /*Activate VBUS Sensing B */
1017     USBx->GCCFG |= USB_OTG_GCCFG_VBDEN;
1018 
1019     /* Disable the FS/LS support mode only */
1020     if ((cfg.speed == USB_OTG_SPEED_FULL)&&
1021             (USBx != USB_OTG_FS)) {
1022         USBx_HOST->HCFG |= USB_OTG_HCFG_FSLSS;
1023     } else {
1024         USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS);
1025     }
1026 
1027     /* Make sure the FIFOs are flushed. */
1028     USB_FlushTxFifo(USBx, 0x10 ); /* all Tx FIFOs */
1029     USB_FlushRxFifo(USBx);
1030 
1031     /* Clear all pending HC Interrupts */
1032     for (i = 0; i < cfg.Host_channels; i++) {
1033         USBx_HC(i)->HCINT = 0xFFFFFFFF;
1034         USBx_HC(i)->HCINTMSK = 0;
1035     }
1036 
1037     /* Enable VBUS driving */
1038     USB_DriveVbus(USBx, 1);
1039 
1040     HAL_Delay(200);
1041 
1042     /* Disable all interrupts. */
1043     USBx->GINTMSK = 0;
1044 
1045     /* Clear any pending interrupts */
1046     USBx->GINTSTS = 0xFFFFFFFF;
1047 
1048 
1049     if (USBx == USB_OTG_FS) {
1050         /* set Rx FIFO size */
1051         USBx->GRXFSIZ  = (uint32_t )0x80;
1052         USBx->DIEPTXF0_HNPTXFSIZ = (uint32_t )(((0x60 << 16)& USB_OTG_NPTXFD) | 0x80);
1053         USBx->HPTXFSIZ = (uint32_t )(((0x40 << 16)& USB_OTG_HPTXFSIZ_PTXFD) | 0xE0);
1054 
1055     }
1056 
1057     else {
1058         /* set Rx FIFO size */
1059         USBx->GRXFSIZ  = (uint32_t )0x200;
1060         USBx->DIEPTXF0_HNPTXFSIZ = (uint32_t )(((0x100 << 16)& USB_OTG_NPTXFD) | 0x200);
1061         USBx->HPTXFSIZ = (uint32_t )(((0xE0 << 16)& USB_OTG_HPTXFSIZ_PTXFD) | 0x300);
1062     }
1063 
1064     /* Enable the common interrupts */
1065     if (cfg.dma_enable == DISABLE) {
1066         USBx->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
1067     }
1068 
1069     /* Enable interrupts matching to the Host mode ONLY */
1070     USBx->GINTMSK |= (USB_OTG_GINTMSK_PRTIM            | USB_OTG_GINTMSK_HCIM |\
1071                       USB_OTG_GINTMSK_SOFM             |USB_OTG_GINTSTS_DISCINT|\
1072                       USB_OTG_GINTMSK_PXFRM_IISOOXFRM  | USB_OTG_GINTMSK_WUIM);
1073 
1074     return HAL_OK;
1075 }
1076 
1077 /**
1078   * @brief  USB_InitFSLSPClkSel : Initializes the FSLSPClkSel field of the
1079   *         HCFG register on the PHY type and set the right frame interval
1080   * @param  USBx : Selected device
1081   * @param  freq : clock frequency
1082   *          This parameter can be one of the these values:
1083   *           HCFG_48_MHZ : Full Speed 48 MHz Clock
1084   *           HCFG_6_MHZ : Low Speed 6 MHz Clock
1085   * @retval HAL status
1086   */
USB_InitFSLSPClkSel(USB_OTG_GlobalTypeDef * USBx,uint8_t freq)1087 HAL_StatusTypeDef USB_InitFSLSPClkSel(USB_OTG_GlobalTypeDef *USBx , uint8_t freq)
1088 {
1089     USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSPCS);
1090     USBx_HOST->HCFG |= (freq & USB_OTG_HCFG_FSLSPCS);
1091 
1092     if (freq ==  HCFG_48_MHZ) {
1093         USBx_HOST->HFIR = (uint32_t)48000;
1094     } else if (freq ==  HCFG_6_MHZ) {
1095         USBx_HOST->HFIR = (uint32_t)6000;
1096     }
1097     return HAL_OK;
1098 }
1099 
1100 /**
1101 * @brief  USB_OTG_ResetPort : Reset Host Port
1102   * @param  USBx : Selected device
1103   * @retval HAL status
1104   * @note : (1)The application must wait at least 10 ms
1105   *   before clearing the reset bit.
1106   */
USB_ResetPort(USB_OTG_GlobalTypeDef * USBx)1107 HAL_StatusTypeDef USB_ResetPort(USB_OTG_GlobalTypeDef *USBx)
1108 {
1109     __IO uint32_t hprt0;
1110 
1111     hprt0 = USBx_HPRT0;
1112 
1113     hprt0 &= ~(USB_OTG_HPRT_PENA    | USB_OTG_HPRT_PCDET |\
1114                USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
1115 
1116     USBx_HPRT0 = (USB_OTG_HPRT_PRST | hprt0);
1117     HAL_Delay (10);                                /* See Note #1 */
1118     USBx_HPRT0 = ((~USB_OTG_HPRT_PRST) & hprt0);
1119     return HAL_OK;
1120 }
1121 
1122 /**
1123   * @brief  USB_DriveVbus : activate or de-activate vbus
1124   * @param  state : VBUS state
1125   *          This parameter can be one of the these values:
1126   *           0 : VBUS Active
1127   *           1 : VBUS Inactive
1128   * @retval HAL status
1129 */
USB_DriveVbus(USB_OTG_GlobalTypeDef * USBx,uint8_t state)1130 HAL_StatusTypeDef USB_DriveVbus (USB_OTG_GlobalTypeDef *USBx, uint8_t state)
1131 {
1132     __IO uint32_t hprt0;
1133 
1134     hprt0 = USBx_HPRT0;
1135     hprt0 &= ~(USB_OTG_HPRT_PENA    | USB_OTG_HPRT_PCDET |\
1136                USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
1137 
1138     if (((hprt0 & USB_OTG_HPRT_PPWR) == 0 ) && (state == 1 )) {
1139         USBx_HPRT0 = (USB_OTG_HPRT_PPWR | hprt0);
1140     }
1141     if (((hprt0 & USB_OTG_HPRT_PPWR) == USB_OTG_HPRT_PPWR) && (state == 0 )) {
1142         USBx_HPRT0 = ((~USB_OTG_HPRT_PPWR) & hprt0);
1143     }
1144     return HAL_OK;
1145 }
1146 
1147 /**
1148   * @brief  Return Host Core speed
1149   * @param  USBx : Selected device
1150   * @retval speed : Host speed
1151   *          This parameter can be one of the these values:
1152   *            @arg USB_OTG_SPEED_HIGH: High speed mode
1153   *            @arg USB_OTG_SPEED_FULL: Full speed mode
1154   *            @arg USB_OTG_SPEED_LOW: Low speed mode
1155   */
USB_GetHostSpeed(USB_OTG_GlobalTypeDef * USBx)1156 uint32_t USB_GetHostSpeed (USB_OTG_GlobalTypeDef *USBx)
1157 {
1158     __IO uint32_t hprt0;
1159 
1160     hprt0 = USBx_HPRT0;
1161     return ((hprt0 & USB_OTG_HPRT_PSPD) >> 17);
1162 }
1163 
1164 /**
1165   * @brief  Return Host Current Frame number
1166   * @param  USBx : Selected device
1167   * @retval current frame number
1168 */
USB_GetCurrentFrame(USB_OTG_GlobalTypeDef * USBx)1169 uint32_t USB_GetCurrentFrame (USB_OTG_GlobalTypeDef *USBx)
1170 {
1171     return (USBx_HOST->HFNUM & USB_OTG_HFNUM_FRNUM);
1172 }
1173 
1174 /**
1175   * @brief  Initialize a host channel
1176   * @param  USBx : Selected device
1177   * @param  ch_num : Channel number
1178   *         This parameter can be a value from 1 to 15
1179   * @param  epnum : Endpoint number
1180   *          This parameter can be a value from 1 to 15
1181   * @param  dev_address : Current device address
1182   *          This parameter can be a value from 0 to 255
1183   * @param  speed : Current device speed
1184   *          This parameter can be one of the these values:
1185   *            @arg USB_OTG_SPEED_HIGH: High speed mode
1186   *            @arg USB_OTG_SPEED_FULL: Full speed mode
1187   *            @arg USB_OTG_SPEED_LOW: Low speed mode
1188   * @param  ep_type : Endpoint Type
1189   *          This parameter can be one of the these values:
1190   *            @arg EP_TYPE_CTRL: Control type
1191   *            @arg EP_TYPE_ISOC: Isochronous type
1192   *            @arg EP_TYPE_BULK: Bulk type
1193   *            @arg EP_TYPE_INTR: Interrupt type
1194   * @param  mps : Max Packet Size
1195   *          This parameter can be a value from 0 to32K
1196   * @retval HAL state
1197   */
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)1198 HAL_StatusTypeDef USB_HC_Init(USB_OTG_GlobalTypeDef *USBx,
1199                               uint8_t ch_num,
1200                               uint8_t epnum,
1201                               uint8_t dev_address,
1202                               uint8_t speed,
1203                               uint8_t ep_type,
1204                               uint16_t mps)
1205 {
1206 
1207     /* Clear old interrupt conditions for this host channel. */
1208     USBx_HC(ch_num)->HCINT = 0xFFFFFFFF;
1209 
1210     /* Enable channel interrupts required for this transfer. */
1211     switch (ep_type) {
1212         case EP_TYPE_CTRL:
1213         case EP_TYPE_BULK:
1214 
1215             USBx_HC(ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM  |\
1216                                         USB_OTG_HCINTMSK_STALLM |\
1217                                         USB_OTG_HCINTMSK_TXERRM |\
1218                                         USB_OTG_HCINTMSK_DTERRM |\
1219                                         USB_OTG_HCINTMSK_AHBERR |\
1220                                         USB_OTG_HCINTMSK_NAKM ;
1221 
1222             if (epnum & 0x80) {
1223                 USBx_HC(ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM;
1224             } else {
1225                 if (USBx != USB_OTG_FS) {
1226                     USBx_HC(ch_num)->HCINTMSK |= (USB_OTG_HCINTMSK_NYET | USB_OTG_HCINTMSK_ACKM);
1227                 }
1228             }
1229             break;
1230         case EP_TYPE_INTR:
1231 
1232             USBx_HC(ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM  |\
1233                                         USB_OTG_HCINTMSK_STALLM |\
1234                                         USB_OTG_HCINTMSK_TXERRM |\
1235                                         USB_OTG_HCINTMSK_DTERRM |\
1236                                         USB_OTG_HCINTMSK_NAKM   |\
1237                                         USB_OTG_HCINTMSK_AHBERR |\
1238                                         USB_OTG_HCINTMSK_FRMORM ;
1239 
1240             if (epnum & 0x80) {
1241                 USBx_HC(ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM;
1242             }
1243 
1244             break;
1245         case EP_TYPE_ISOC:
1246 
1247             USBx_HC(ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM  |\
1248                                         USB_OTG_HCINTMSK_ACKM   |\
1249                                         USB_OTG_HCINTMSK_AHBERR |\
1250                                         USB_OTG_HCINTMSK_FRMORM ;
1251 
1252             if (epnum & 0x80) {
1253                 USBx_HC(ch_num)->HCINTMSK |= (USB_OTG_HCINTMSK_TXERRM | USB_OTG_HCINTMSK_BBERRM);
1254             }
1255             break;
1256     }
1257 
1258     /* Enable the top level host channel interrupt. */
1259     USBx_HOST->HAINTMSK |= (1 << ch_num);
1260 
1261     /* Make sure host channel interrupts are enabled. */
1262     USBx->GINTMSK |= USB_OTG_GINTMSK_HCIM;
1263 
1264     /* Program the HCCHAR register */
1265     USBx_HC(ch_num)->HCCHAR = (((dev_address << 22) & USB_OTG_HCCHAR_DAD)  |\
1266                                (((epnum & 0x7F)<< 11) & USB_OTG_HCCHAR_EPNUM)|\
1267                                ((((epnum & 0x80) == 0x80)<< 15) & USB_OTG_HCCHAR_EPDIR)|\
1268                                (((speed == HPRT0_PRTSPD_LOW_SPEED)<< 17) & USB_OTG_HCCHAR_LSDEV)|\
1269                                ((ep_type << 18) & USB_OTG_HCCHAR_EPTYP)|\
1270                                (mps & USB_OTG_HCCHAR_MPSIZ));
1271 
1272     if (ep_type == EP_TYPE_INTR) {
1273         USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM ;
1274     }
1275 
1276     return HAL_OK;
1277 }
1278 
1279 /**
1280   * @brief  Start a transfer over a host channel
1281   * @param  USBx : Selected device
1282   * @param  hc : pointer to host channel structure
1283   * @param  dma: USB dma enabled or disabled
1284   *          This parameter can be one of the these values:
1285   *           0 : DMA feature not used
1286   *           1 : DMA feature used
1287   * @retval HAL state
1288   */
1289 #if defined   (__CC_ARM) /*!< ARM Compiler */
1290 #pragma O0
1291 #elif defined (__GNUC__) /*!< GNU Compiler */
1292 #pragma GCC optimize ("O0")
1293 #endif /* __CC_ARM */
USB_HC_StartXfer(USB_OTG_GlobalTypeDef * USBx,USB_OTG_HCTypeDef * hc,uint8_t dma)1294 HAL_StatusTypeDef USB_HC_StartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_HCTypeDef *hc, uint8_t dma)
1295 {
1296     uint8_t  is_oddframe = 0;
1297     uint16_t len_words = 0;
1298     uint16_t num_packets = 0;
1299     uint16_t max_hc_pkt_count = 256;
1300     uint32_t tmpreg = 0;
1301 
1302     if ((USBx != USB_OTG_FS) && (hc->speed == USB_OTG_SPEED_HIGH)) {
1303         if ((dma == 0) && (hc->do_ping == 1)) {
1304             USB_DoPing(USBx, hc->ch_num);
1305             return HAL_OK;
1306         } else if (dma == 1) {
1307             USBx_HC(hc->ch_num)->HCINTMSK &= ~(USB_OTG_HCINTMSK_NYET | USB_OTG_HCINTMSK_ACKM);
1308             hc->do_ping = 0;
1309         }
1310     }
1311 
1312     /* Compute the expected number of packets associated to the transfer */
1313     if (hc->xfer_len > 0) {
1314         num_packets = (hc->xfer_len + hc->max_packet - 1) / hc->max_packet;
1315 
1316         if (num_packets > max_hc_pkt_count) {
1317             num_packets = max_hc_pkt_count;
1318             hc->xfer_len = num_packets * hc->max_packet;
1319         }
1320     } else {
1321         num_packets = 1;
1322     }
1323     if (hc->ep_is_in) {
1324         hc->xfer_len = num_packets * hc->max_packet;
1325     }
1326 
1327 
1328 
1329     /* Initialize the HCTSIZn register */
1330     USBx_HC(hc->ch_num)->HCTSIZ = (((hc->xfer_len) & USB_OTG_HCTSIZ_XFRSIZ)) |\
1331                                   ((num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |\
1332                                   (((hc->data_pid) << 29) & USB_OTG_HCTSIZ_DPID);
1333 
1334     if (dma) {
1335         /* xfer_buff MUST be 32-bits aligned */
1336         USBx_HC(hc->ch_num)->HCDMA = (uint32_t)hc->xfer_buff;
1337     }
1338 
1339     is_oddframe = (USBx_HOST->HFNUM & 0x01) ? 0 : 1;
1340     USBx_HC(hc->ch_num)->HCCHAR &= ~USB_OTG_HCCHAR_ODDFRM;
1341     USBx_HC(hc->ch_num)->HCCHAR |= (is_oddframe << 29);
1342 
1343     /* Set host channel enable */
1344     tmpreg = USBx_HC(hc->ch_num)->HCCHAR;
1345     tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1346     tmpreg |= USB_OTG_HCCHAR_CHENA;
1347     USBx_HC(hc->ch_num)->HCCHAR = tmpreg;
1348 
1349     if (dma == 0) { /* Slave mode */
1350         if ((hc->ep_is_in == 0) && (hc->xfer_len > 0)) {
1351             switch (hc->ep_type) {
1352                 /* Non periodic transfer */
1353                 case EP_TYPE_CTRL:
1354                 case EP_TYPE_BULK:
1355 
1356                     len_words = (hc->xfer_len + 3) / 4;
1357 
1358                     /* check if there is enough space in FIFO space */
1359                     if (len_words > (USBx->HNPTXSTS & 0xFFFF)) {
1360                         /* need to process data in nptxfempty interrupt */
1361                         USBx->GINTMSK |= USB_OTG_GINTMSK_NPTXFEM;
1362                     }
1363                     break;
1364                 /* Periodic transfer */
1365                 case EP_TYPE_INTR:
1366                 case EP_TYPE_ISOC:
1367                     len_words = (hc->xfer_len + 3) / 4;
1368                     /* check if there is enough space in FIFO space */
1369                     if (len_words > (USBx_HOST->HPTXSTS & 0xFFFF)) { /* split the transfer */
1370                         /* need to process data in ptxfempty interrupt */
1371                         USBx->GINTMSK |= USB_OTG_GINTMSK_PTXFEM;
1372                     }
1373                     break;
1374 
1375                 default:
1376                     break;
1377             }
1378 
1379             /* Write packet into the Tx FIFO. */
1380             USB_WritePacket(USBx, hc->xfer_buff, hc->ch_num, hc->xfer_len, 0);
1381         }
1382     }
1383 
1384     return HAL_OK;
1385 }
1386 
1387 /**
1388   * @brief Read all host channel interrupts status
1389   * @param  USBx : Selected device
1390   * @retval HAL state
1391   */
USB_HC_ReadInterrupt(USB_OTG_GlobalTypeDef * USBx)1392 uint32_t USB_HC_ReadInterrupt (USB_OTG_GlobalTypeDef *USBx)
1393 {
1394     return ((USBx_HOST->HAINT) & 0xFFFF);
1395 }
1396 
1397 /**
1398   * @brief  Halt a host channel
1399   * @param  USBx : Selected device
1400   * @param  hc_num : Host Channel number
1401   *         This parameter can be a value from 1 to 15
1402   * @retval HAL state
1403   */
USB_HC_Halt(USB_OTG_GlobalTypeDef * USBx,uint8_t hc_num)1404 HAL_StatusTypeDef USB_HC_Halt(USB_OTG_GlobalTypeDef *USBx , uint8_t hc_num)
1405 {
1406     uint32_t count = 0;
1407 
1408     /* Check for space in the request queue to issue the halt. */
1409     if (((USBx_HC(hc_num)->HCCHAR) & (HCCHAR_CTRL << 18)) || ((USBx_HC(hc_num)->HCCHAR) & (HCCHAR_BULK << 18))) {
1410         USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHDIS;
1411 
1412         if ((USBx->HNPTXSTS & 0xFFFF) == 0) {
1413             USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA;
1414             USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
1415             USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_EPDIR;
1416             do {
1417                 if (++count > 1000) {
1418                     break;
1419                 }
1420             } while ((USBx_HC(hc_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
1421         } else {
1422             USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
1423         }
1424     } else {
1425         USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHDIS;
1426 
1427         if ((USBx_HOST->HPTXSTS & 0xFFFF) == 0) {
1428             USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA;
1429             USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
1430             USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_EPDIR;
1431             do {
1432                 if (++count > 1000) {
1433                     break;
1434                 }
1435             } while ((USBx_HC(hc_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
1436         } else {
1437             USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
1438         }
1439     }
1440 
1441     return HAL_OK;
1442 }
1443 
1444 /**
1445   * @brief  Initiate Do Ping protocol
1446   * @param  USBx : Selected device
1447   * @param  hc_num : Host Channel number
1448   *         This parameter can be a value from 1 to 15
1449   * @retval HAL state
1450   */
USB_DoPing(USB_OTG_GlobalTypeDef * USBx,uint8_t ch_num)1451 HAL_StatusTypeDef USB_DoPing(USB_OTG_GlobalTypeDef *USBx , uint8_t ch_num)
1452 {
1453     uint8_t  num_packets = 1;
1454     uint32_t tmpreg = 0;
1455 
1456     USBx_HC(ch_num)->HCTSIZ = ((num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |\
1457                               USB_OTG_HCTSIZ_DOPING;
1458 
1459     /* Set host channel enable */
1460     tmpreg = USBx_HC(ch_num)->HCCHAR;
1461     tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1462     tmpreg |= USB_OTG_HCCHAR_CHENA;
1463     USBx_HC(ch_num)->HCCHAR = tmpreg;
1464 
1465     return HAL_OK;
1466 }
1467 
1468 /**
1469   * @brief  Stop Host Core
1470   * @param  USBx : Selected device
1471   * @retval HAL state
1472   */
USB_StopHost(USB_OTG_GlobalTypeDef * USBx)1473 HAL_StatusTypeDef USB_StopHost(USB_OTG_GlobalTypeDef *USBx)
1474 {
1475     uint8_t i;
1476     uint32_t count = 0;
1477     uint32_t value;
1478 
1479     USB_DisableGlobalInt(USBx);
1480 
1481     /* Flush FIFO */
1482     USB_FlushTxFifo(USBx, 0x10);
1483     USB_FlushRxFifo(USBx);
1484 
1485     /* Flush out any leftover queued requests. */
1486     for (i = 0; i <= 15; i++) {
1487 
1488         value = USBx_HC(i)->HCCHAR ;
1489         value |=  USB_OTG_HCCHAR_CHDIS;
1490         value &= ~USB_OTG_HCCHAR_CHENA;
1491         value &= ~USB_OTG_HCCHAR_EPDIR;
1492         USBx_HC(i)->HCCHAR = value;
1493     }
1494 
1495     /* Halt all channels to put them into a known state. */
1496     for (i = 0; i <= 15; i++) {
1497 
1498         value = USBx_HC(i)->HCCHAR ;
1499 
1500         value |= USB_OTG_HCCHAR_CHDIS;
1501         value |= USB_OTG_HCCHAR_CHENA;
1502         value &= ~USB_OTG_HCCHAR_EPDIR;
1503 
1504         USBx_HC(i)->HCCHAR = value;
1505         do {
1506             if (++count > 1000) {
1507                 break;
1508             }
1509         } while ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
1510     }
1511 
1512     /* Clear any pending Host interrupts */
1513     USBx_HOST->HAINT = 0xFFFFFFFF;
1514     USBx->GINTSTS = 0xFFFFFFFF;
1515     USB_EnableGlobalInt(USBx);
1516     return HAL_OK;
1517 }
1518 /**
1519   * @}
1520   */
1521 
1522 #endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
1523 
1524 /**
1525   * @}
1526   */
1527 
1528 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
1529