source: rtems/c/src/lib/libbsp/arm/stm32f7x/hal/STM32F7xx_HAL_Driver/Src/stm32f7xx_ll_usb.c @ c20847a5

5
Last change on this file since c20847a5 was c20847a5, checked in by Isaac Gutekunst <isaac.gutekunst@…>, on 09/16/15 at 13:16:02

Add STM32F7 HAL Files

These files originated as:

+ STC32CubeF7 V1.1.0 from http://www.st.com/web/en/catalog/tools/PF261909

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