Subversion Repositories DashDisplay

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 mjames 1
/**
2
  ******************************************************************************
3
  * @file    stm32f1xx_hal_pcd.c
4
  * @author  MCD Application Team
5 mjames 5
  * @version V1.0.4
6
  * @date    29-April-2016
2 mjames 7
  * @brief   PCD HAL module driver.
8
  *          This file provides firmware functions to manage the following
9
  *          functionalities of the USB Peripheral Controller:
10
  *           + Initialization and de-initialization functions
11
  *           + IO operation functions
12
  *           + Peripheral Control functions
13
  *           + Peripheral State functions
14
  *
15
  @verbatim
16
  ==============================================================================
17
                    ##### How to use this driver #####
18
  ==============================================================================
19
    [..]
20
      The PCD HAL driver can be used as follows:
21
 
22
     (#) Declare a PCD_HandleTypeDef handle structure, for example:
23
         PCD_HandleTypeDef  hpcd;
24
 
25
     (#) Fill parameters of Init structure in HCD handle
26
 
27
     (#) Call HAL_PCD_Init() API to initialize the HCD peripheral (Core, Device core, ...)
28
 
29
     (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
30
         (##) Enable the PCD/USB Low Level interface clock using the following macro
31
              (+++) __HAL_RCC_USB_CLK_ENABLE(); For USB Device FS peripheral available
32
                    on STM32F102xx and STM32F103xx devices
33
              (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); For USB OTG FS peripheral available
34
                    on STM32F105xx and STM32F107xx devices
35
 
36
         (##) Initialize the related GPIO clocks
37
         (##) Configure PCD pin-out
38
         (##) Configure PCD NVIC interrupt
39
 
40
     (#)Associate the Upper USB device stack to the HAL PCD Driver:
41
         (##) hpcd.pData = pdev;
42
 
43
     (#)Enable HCD transmission and reception:
44
         (##) HAL_PCD_Start();
45
 
46
  @endverbatim
47
  ******************************************************************************
48
  * @attention
49
  *
5 mjames 50
  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
2 mjames 51
  *
52
  * Redistribution and use in source and binary forms, with or without modification,
53
  * are permitted provided that the following conditions are met:
54
  *   1. Redistributions of source code must retain the above copyright notice,
55
  *      this list of conditions and the following disclaimer.
56
  *   2. Redistributions in binary form must reproduce the above copyright notice,
57
  *      this list of conditions and the following disclaimer in the documentation
58
  *      and/or other materials provided with the distribution.
59
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
60
  *      may be used to endorse or promote products derived from this software
61
  *      without specific prior written permission.
62
  *
63
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
64
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
67
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
69
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
70
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
71
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
72
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73
  *
74
  ******************************************************************************
75
  */
76
 
77
/* Includes ------------------------------------------------------------------*/
78
#include "stm32f1xx_hal.h"
79
 
80
/** @addtogroup STM32F1xx_HAL_Driver
81
  * @{
82
  */
83
 
84
 
85
 
86
#ifdef HAL_PCD_MODULE_ENABLED
87
 
88
#if defined(STM32F102x6) || defined(STM32F102xB) || \
89
    defined(STM32F103x6) || defined(STM32F103xB) || \
90
    defined(STM32F103xE) || defined(STM32F103xG) || \
91
    defined(STM32F105xC) || defined(STM32F107xC)
92
 
93
/** @defgroup PCD PCD
94
  * @brief PCD HAL module driver
95
  * @{
96
  */
97
 
98
/* Private types -------------------------------------------------------------*/
99
/* Private variables ---------------------------------------------------------*/
100
/* Private constants ---------------------------------------------------------*/
101
/* Private macros ------------------------------------------------------------*/
102
/** @defgroup PCD_Private_Macros PCD Private Macros
103
  * @{
104
  */
105
#define PCD_MIN(a, b)  (((a) < (b)) ? (a) : (b))
106
#define PCD_MAX(a, b)  (((a) > (b)) ? (a) : (b))
107
/**
108
  * @}
109
  */
110
 
111
/* Private functions ---------------------------------------------------------*/
112
/** @defgroup PCD_Private_Functions PCD Private Functions
113
  * @{
114
  */
115
#if defined (USB_OTG_FS)
116
static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
117
#endif /* USB_OTG_FS */
118
 
119
#if defined (USB)
120
static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd);
121
#endif /* USB */
122
/**
123
  * @}
124
  */
125
 
126
/* Exported functions --------------------------------------------------------*/
127
/** @defgroup PCD_Exported_Functions PCD Exported Functions
128
  * @{
129
  */
130
 
131
/** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
132
 *  @brief    Initialization and Configuration functions
133
 *
134
@verbatim
135
 ===============================================================================
136
            ##### Initialization and de-initialization functions #####
137
 ===============================================================================
138
    [..]  This section provides functions allowing to:
139
 
140
@endverbatim
141
  * @{
142
  */
143
 
144
/**
145
  * @brief  Initializes the PCD according to the specified
146
  *         parameters in the PCD_InitTypeDef and create the associated handle.
147
  * @param  hpcd: PCD handle
148
  * @retval HAL status
149
  */
150
HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
151
{
152
  uint32_t index = 0;
153
 
154
  /* Check the PCD handle allocation */
155
  if(hpcd == NULL)
156
  {
157
    return HAL_ERROR;
158
  }
159
 
160
  /* Check the parameters */
161
  assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
162
 
163
  if(hpcd->State == HAL_PCD_STATE_RESET)
164
  {  
165
    /* Allocate lock resource and initialize it */
166
    hpcd->Lock = HAL_UNLOCKED;
167
 
168
    /* Init the low level hardware : GPIO, CLOCK, NVIC... */
169
    HAL_PCD_MspInit(hpcd);
170
  }
171
 
172
  hpcd->State = HAL_PCD_STATE_BUSY;
173
 
174
  /* Disable the Interrupts */
175
  __HAL_PCD_DISABLE(hpcd);
176
 
177
  /*Init the Core (common init.) */
178
  USB_CoreInit(hpcd->Instance, hpcd->Init);
179
 
180
  /* Force Device Mode*/
181
  USB_SetCurrentMode(hpcd->Instance , USB_DEVICE_MODE);
182
 
183
  /* Init endpoints structures */
184
  for (index = 0; index < 15 ; index++)
185
  {
186
    /* Init ep structure */
187
    hpcd->IN_ep[index].is_in = 1;
188
    hpcd->IN_ep[index].num = index;
189
    hpcd->IN_ep[index].tx_fifo_num = index;
190
    /* Control until ep is actvated */
191
    hpcd->IN_ep[index].type = EP_TYPE_CTRL;
192
    hpcd->IN_ep[index].maxpacket =  0;
193
    hpcd->IN_ep[index].xfer_buff = 0;
194
    hpcd->IN_ep[index].xfer_len = 0;
195
  }
196
 
197
  for (index = 0; index < 15 ; index++)
198
  {
199
    hpcd->OUT_ep[index].is_in = 0;
200
    hpcd->OUT_ep[index].num = index;
201
    hpcd->IN_ep[index].tx_fifo_num = index;
202
    /* Control until ep is activated */
203
    hpcd->OUT_ep[index].type = EP_TYPE_CTRL;
204
    hpcd->OUT_ep[index].maxpacket = 0;
205
    hpcd->OUT_ep[index].xfer_buff = 0;
206
    hpcd->OUT_ep[index].xfer_len = 0;
207
  }
208
 
209
  /* Init Device */
210
  USB_DevInit(hpcd->Instance, hpcd->Init);
211
 
212
  hpcd->USB_Address = 0;
213
  hpcd->State= HAL_PCD_STATE_READY;
214
 
215
  USB_DevDisconnect (hpcd->Instance);  
216
  return HAL_OK;
217
}
218
 
219
/**
220
  * @brief  DeInitializes the PCD peripheral
221
  * @param  hpcd: PCD handle
222
  * @retval HAL status
223
  */
224
HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
225
{
226
  /* Check the PCD handle allocation */
227
  if(hpcd == NULL)
228
  {
229
    return HAL_ERROR;
230
  }
231
 
232
  hpcd->State = HAL_PCD_STATE_BUSY;
233
 
234
  /* Stop Device */
235
  HAL_PCD_Stop(hpcd);
236
 
237
  /* DeInit the low level hardware */
238
  HAL_PCD_MspDeInit(hpcd);
239
 
240
  hpcd->State = HAL_PCD_STATE_RESET;
241
 
242
  return HAL_OK;
243
}
244
 
245
/**
246
  * @brief  Initializes the PCD MSP.
247
  * @param  hpcd: PCD handle
248
  * @retval None
249
  */
250
__weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
251
{
5 mjames 252
  /* Prevent unused argument(s) compilation warning */
253
  UNUSED(hpcd);
2 mjames 254
  /* NOTE : This function should not be modified, when the callback is needed,
255
            the HAL_PCD_MspInit could be implemented in the user file
256
   */
257
}
258
 
259
/**
260
  * @brief  DeInitializes PCD MSP.
261
  * @param  hpcd: PCD handle
262
  * @retval None
263
  */
264
__weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
265
{
5 mjames 266
  /* Prevent unused argument(s) compilation warning */
267
  UNUSED(hpcd);
2 mjames 268
  /* NOTE : This function should not be modified, when the callback is needed,
269
            the HAL_PCD_MspDeInit could be implemented in the user file
270
   */
271
}
272
 
273
/**
274
  * @}
275
  */
276
 
277
/** @defgroup PCD_Exported_Functions_Group2 IO operation functions
278
 *  @brief   Data transfers functions
279
 *
280
@verbatim
281
 ===============================================================================
282
                      ##### IO operation functions #####
283
 ===============================================================================
284
    [..]
285
    This subsection provides a set of functions allowing to manage the PCD data
286
    transfers.
287
 
288
@endverbatim
289
  * @{
290
  */
291
 
292
/**
293
  * @brief  Start The USB Device.
294
  * @param  hpcd: PCD handle
295
  * @retval HAL status
296
  */
297
HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
298
{
299
  __HAL_LOCK(hpcd);
300
  HAL_PCDEx_SetConnectionState (hpcd, 1);
301
  USB_DevConnect (hpcd->Instance);
302
  __HAL_PCD_ENABLE(hpcd);
303
  __HAL_UNLOCK(hpcd);
304
  return HAL_OK;
305
}
306
 
307
/**
308
  * @brief  Stop The USB Device.
309
  * @param  hpcd: PCD handle
310
  * @retval HAL status
311
  */
312
HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
313
{  
314
  __HAL_LOCK(hpcd);
315
  __HAL_PCD_DISABLE(hpcd);
316
  USB_StopDevice(hpcd->Instance);
317
  USB_DevDisconnect (hpcd->Instance);
318
  __HAL_UNLOCK(hpcd);
319
  return HAL_OK;
320
}
321
 
322
#if defined (USB_OTG_FS)
323
/**
324
  * @brief  This function handles PCD interrupt request.
325
  * @param  hpcd: PCD handle
326
  * @retval HAL status
327
  */
328
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
329
{
330
  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
331
  uint32_t index = 0, ep_intr = 0, epint = 0, epnum = 0;
332
  uint32_t fifoemptymsk = 0, temp = 0;
333
  USB_OTG_EPTypeDef *ep = NULL;
334
 
335
  /* ensure that we are in device mode */
336
  if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
337
  {
338
    /* avoid spurious interrupt */
339
    if(__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
340
    {
341
      return;
342
    }
343
 
344
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
345
    {
346
     /* incorrect mode, acknowledge the interrupt */
347
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
348
    }
349
 
350
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
351
    {
352
      epnum = 0;
353
 
354
      /* Read in the device interrupt bits */
355
      ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
356
 
357
      while ( ep_intr )
358
      {
359
        if (ep_intr & 0x1)
360
        {
361
          epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, epnum);
362
 
363
          if(( epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
364
          {
365
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
366
 
367
            HAL_PCD_DataOutStageCallback(hpcd, epnum);
368
          }
369
 
370
          if(( epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
371
          {
372
            /* Inform the upper layer that a setup packet is available */
373
            HAL_PCD_SetupStageCallback(hpcd);
374
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
375
          }
376
 
377
          if(( epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
378
          {
379
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
380
          }
381
        }
382
        epnum++;
383
        ep_intr >>= 1;
384
      }
385
    }
386
 
387
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
388
    {
389
      /* Read in the device interrupt bits */
390
      ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
391
 
392
      epnum = 0;
393
 
394
      while ( ep_intr )
395
      {
396
        if (ep_intr & 0x1) /* In ITR */
397
        {
398
          epint = USB_ReadDevInEPInterrupt(hpcd->Instance, epnum);
399
 
400
          if(( epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
401
          {
402
            fifoemptymsk = 0x1 << epnum;
403
            USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
404
 
405
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
406
 
407
            HAL_PCD_DataInStageCallback(hpcd, epnum);
408
          }
409
          if(( epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
410
          {
411
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
412
          }
413
          if(( epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
414
          {
415
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
416
          }
417
          if(( epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
418
          {
419
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
420
          }
421
          if(( epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
422
          {
423
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
424
          }
425
          if(( epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
426
          {
427
            PCD_WriteEmptyTxFifo(hpcd , epnum);
428
          }
429
        }
430
        epnum++;
431
        ep_intr >>= 1;
432
      }
433
    }
434
 
435
    /* Handle Resume Interrupt */
436
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
437
    {
438
     /* Clear the Remote Wake-up signalling */
439
      USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
440
 
441
     HAL_PCD_ResumeCallback(hpcd);
442
 
443
     __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
444
    }
445
 
446
    /* Handle Suspend Interrupt */
447
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
448
    {
449
      if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
450
      {
451
 
452
        HAL_PCD_SuspendCallback(hpcd);
453
      }
454
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
455
    }
456
 
457
    /* Handle Reset Interrupt */
458
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
459
    {
460
      USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
461
      USB_FlushTxFifo(hpcd->Instance ,  0 );
462
 
463
      for (index = 0; index < hpcd->Init.dev_endpoints ; index++)
464
      {
465
        USBx_INEP(index)->DIEPINT = 0xFF;
466
        USBx_OUTEP(index)->DOEPINT = 0xFF;
467
      }
468
      USBx_DEVICE->DAINT = 0xFFFFFFFF;
469
      USBx_DEVICE->DAINTMSK |= 0x10001;
470
 
471
      USBx_DEVICE->DOEPMSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM);
472
      USBx_DEVICE->DIEPMSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);
473
 
474
      /* Set Default Address to 0 */
475
      USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
476
 
477
      /* setup EP0 to receive SETUP packets */
478
      USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
479
 
480
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
481
    }
482
 
483
    /* Handle Enumeration done Interrupt */
484
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
485
    {
486
      USB_ActivateSetup(hpcd->Instance);
487
      hpcd->Instance->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
488
 
489
      hpcd->Init.speed            = USB_OTG_SPEED_FULL;
490
      hpcd->Init.ep0_mps          = USB_OTG_FS_MAX_PACKET_SIZE ;
491
      hpcd->Instance->GUSBCFG |= (uint32_t)((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT);
492
 
493
      HAL_PCD_ResetCallback(hpcd);
494
 
495
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
496
    }
497
 
498
    /* Handle RxQLevel Interrupt */
499
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
500
    {
501
      USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
502
      temp = USBx->GRXSTSP;
503
      ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
504
 
505
      if(((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_DATA_UPDT)
506
      {
507
        if((temp & USB_OTG_GRXSTSP_BCNT) != 0)
508
        {
509
          USB_ReadPacket(USBx, ep->xfer_buff, (temp & USB_OTG_GRXSTSP_BCNT) >> 4);
510
          ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
511
          ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
512
        }
513
      }
514
      else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_SETUP_UPDT)
515
      {
516
        USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8);
517
        ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
518
      }
519
      USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
520
    }
521
 
522
    /* Handle SOF Interrupt */
523
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
524
    {
525
      HAL_PCD_SOFCallback(hpcd);
526
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
527
    }
528
 
529
    /* Handle Incomplete ISO IN Interrupt */
530
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
531
    {
532
      HAL_PCD_ISOINIncompleteCallback(hpcd, epnum);
533
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
534
    }
535
 
536
    /* Handle Incomplete ISO OUT Interrupt */
537
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
538
    {
539
      HAL_PCD_ISOOUTIncompleteCallback(hpcd, epnum);
540
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
541
    }
542
 
543
    /* Handle Connection event Interrupt */
544
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
545
    {
546
      HAL_PCD_ConnectCallback(hpcd);
547
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
548
    }
549
 
550
    /* Handle Disconnection event Interrupt */
551
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
552
    {
553
      temp = hpcd->Instance->GOTGINT;
554
 
555
      if((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
556
      {
557
        HAL_PCD_DisconnectCallback(hpcd);
558
      }
559
      hpcd->Instance->GOTGINT |= temp;
560
    }
561
  }
562
}
563
#endif /* USB_OTG_FS */
564
 
565
#if defined (USB)
566
/**
567
  * @brief  This function handles PCD interrupt request.
568
  * @param  hpcd: PCD handle
569
  * @retval HAL status
570
  */
571
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
572
{
573
  uint32_t wInterrupt_Mask = 0;
574
 
575
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_CTR))
576
  {
577
    /* servicing of the endpoint correct transfer interrupt */
578
    /* clear of the CTR flag into the sub */
579
    PCD_EP_ISR_Handler(hpcd);
580
  }
581
 
582
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_RESET))
583
  {
584
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
585
    HAL_PCD_ResetCallback(hpcd);
586
    HAL_PCD_SetAddress(hpcd, 0);
587
  }
588
 
589
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_PMAOVR))
590
  {
591
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);    
592
  }
593
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ERR))
594
  {
595
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR);
596
  }
597
 
598
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP))
599
  {  
600
    hpcd->Instance->CNTR &= ~(USB_CNTR_LP_MODE);
601
 
602
    /*set wInterrupt_Mask global variable*/
603
    wInterrupt_Mask = USB_CNTR_CTRM  | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_ERRM \
604
      | USB_CNTR_ESOFM | USB_CNTR_RESETM;
605
 
606
    /*Set interrupt mask*/
607
    hpcd->Instance->CNTR = wInterrupt_Mask;
608
 
609
    HAL_PCD_ResumeCallback(hpcd);
610
 
611
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);    
612
  }
613
 
614
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SUSP))
615
  {
616
    /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
617
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);  
618
 
619
    /* Force low-power mode in the macrocell */
620
    hpcd->Instance->CNTR |= USB_CNTR_FSUSP;
621
    hpcd->Instance->CNTR |= USB_CNTR_LP_MODE;
622
    if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP) == 0)
623
    {
624
      HAL_PCD_SuspendCallback(hpcd);
625
    }
626
  }
627
 
628
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SOF))
629
  {
630
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);
631
    HAL_PCD_SOFCallback(hpcd);
632
  }
633
 
634
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ESOF))
635
  {
636
    /* clear ESOF flag in ISTR */
637
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);
638
  }
639
}
640
#endif /* USB */
641
 
642
/**
643
  * @brief  Data out stage callbacks
644
  * @param  hpcd: PCD handle
645
  * @param  epnum: endpoint number
646
  * @retval None
647
  */
648
 __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
649
{
5 mjames 650
  /* Prevent unused argument(s) compilation warning */
651
  UNUSED(hpcd);
652
  UNUSED(epnum);
2 mjames 653
  /* NOTE : This function should not be modified, when the callback is needed,
654
            the HAL_PCD_DataOutStageCallback could be implemented in the user file
655
   */
656
}
657
 
658
/**
659
  * @brief  Data IN stage callbacks
660
  * @param  hpcd: PCD handle
661
  * @param  epnum: endpoint number
662
  * @retval None
663
  */
664
 __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
665
{
5 mjames 666
  /* Prevent unused argument(s) compilation warning */
667
  UNUSED(hpcd);
668
  UNUSED(epnum);
2 mjames 669
  /* NOTE : This function should not be modified, when the callback is needed,
670
            the HAL_PCD_DataInStageCallback could be implemented in the user file
671
   */
672
}
673
/**
674
  * @brief  Setup stage callback
675
  * @param  hpcd: PCD handle
676
  * @retval None
677
  */
678
 __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
679
{
5 mjames 680
  /* Prevent unused argument(s) compilation warning */
681
  UNUSED(hpcd);
2 mjames 682
  /* NOTE : This function should not be modified, when the callback is needed,
683
            the HAL_PCD_SetupStageCallback could be implemented in the user file
684
   */
685
}
686
 
687
/**
688
  * @brief  USB Start Of Frame callbacks
689
  * @param  hpcd: PCD handle
690
  * @retval None
691
  */
692
 __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
693
{
5 mjames 694
  /* Prevent unused argument(s) compilation warning */
695
  UNUSED(hpcd);
2 mjames 696
  /* NOTE : This function should not be modified, when the callback is needed,
697
            the HAL_PCD_SOFCallback could be implemented in the user file
698
   */
699
}
700
 
701
/**
702
  * @brief  USB Reset callbacks
703
  * @param  hpcd: PCD handle
704
  * @retval None
705
  */
706
 __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
707
{
5 mjames 708
  /* Prevent unused argument(s) compilation warning */
709
  UNUSED(hpcd);
2 mjames 710
  /* NOTE : This function should not be modified, when the callback is needed,
711
            the HAL_PCD_ResetCallback could be implemented in the user file
712
   */
713
}
714
 
715
/**
716
  * @brief  Suspend event callbacks
717
  * @param  hpcd: PCD handle
718
  * @retval None
719
  */
720
 __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
721
{
5 mjames 722
  /* Prevent unused argument(s) compilation warning */
723
  UNUSED(hpcd);
2 mjames 724
  /* NOTE : This function should not be modified, when the callback is needed,
725
            the HAL_PCD_SuspendCallback could be implemented in the user file
726
   */
727
}
728
 
729
/**
730
  * @brief  Resume event callbacks
731
  * @param  hpcd: PCD handle
732
  * @retval None
733
  */
734
 __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
735
{
5 mjames 736
  /* Prevent unused argument(s) compilation warning */
737
  UNUSED(hpcd);
2 mjames 738
  /* NOTE : This function should not be modified, when the callback is needed,
739
            the HAL_PCD_ResumeCallback could be implemented in the user file
740
   */
741
}
742
 
743
/**
744
  * @brief  Incomplete ISO OUT callbacks
745
  * @param  hpcd: PCD handle
746
  * @param  epnum: endpoint number
747
  * @retval None
748
  */
749
 __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
750
{
5 mjames 751
  /* Prevent unused argument(s) compilation warning */
752
  UNUSED(hpcd);
753
  UNUSED(epnum);
2 mjames 754
  /* NOTE : This function should not be modified, when the callback is needed,
755
            the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
756
   */
757
}
758
 
759
/**
760
  * @brief  Incomplete ISO IN  callbacks
761
  * @param  hpcd: PCD handle
762
  * @param  epnum: endpoint number
763
  * @retval None
764
  */
765
 __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
766
{
5 mjames 767
  /* Prevent unused argument(s) compilation warning */
768
  UNUSED(hpcd);
769
  UNUSED(epnum);
2 mjames 770
  /* NOTE : This function should not be modified, when the callback is needed,
771
            the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
772
   */
773
}
774
 
775
/**
776
  * @brief  Connection event callbacks
777
  * @param  hpcd: PCD handle
778
  * @retval None
779
  */
780
 __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
781
{
5 mjames 782
  /* Prevent unused argument(s) compilation warning */
783
  UNUSED(hpcd);
2 mjames 784
  /* NOTE : This function should not be modified, when the callback is needed,
785
            the HAL_PCD_ConnectCallback could be implemented in the user file
786
   */
787
}
788
 
789
/**
790
  * @brief  Disconnection event callbacks
791
  * @param  hpcd: PCD handle
792
  * @retval None
793
  */
794
 __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
795
{
5 mjames 796
  /* Prevent unused argument(s) compilation warning */
797
  UNUSED(hpcd);
2 mjames 798
  /* NOTE : This function should not be modified, when the callback is needed,
799
            the HAL_PCD_DisconnectCallback could be implemented in the user file
800
   */
801
}
802
 
803
/**
804
  * @}
805
  */
806
 
807
/** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
808
 *  @brief   management functions
809
 *
810
@verbatim
811
 ===============================================================================
812
                      ##### Peripheral Control functions #####
813
 ===============================================================================  
814
    [..]
815
    This subsection provides a set of functions allowing to control the PCD data
816
    transfers.
817
 
818
@endverbatim
819
  * @{
820
  */
821
 
822
/**
823
  * @brief  Connect the USB device
824
  * @param  hpcd: PCD handle
825
  * @retval HAL status
826
  */
827
HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
828
{
829
  __HAL_LOCK(hpcd);
830
  HAL_PCDEx_SetConnectionState (hpcd, 1);
831
  USB_DevConnect(hpcd->Instance);
832
  __HAL_UNLOCK(hpcd);
833
  return HAL_OK;
834
}
835
 
836
/**
837
  * @brief  Disconnect the USB device
838
  * @param  hpcd: PCD handle
839
  * @retval HAL status
840
  */
841
HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
842
{
843
  __HAL_LOCK(hpcd);
844
  HAL_PCDEx_SetConnectionState (hpcd, 0);
845
  USB_DevDisconnect(hpcd->Instance);
846
  __HAL_UNLOCK(hpcd);
847
  return HAL_OK;
848
}
849
 
850
/**
851
  * @brief  Set the USB Device address
852
  * @param  hpcd: PCD handle
853
  * @param  address: new device address
854
  * @retval HAL status
855
  */
856
HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
857
{
858
  __HAL_LOCK(hpcd);
859
  hpcd->USB_Address = address;
860
  USB_SetDevAddress(hpcd->Instance, address);
861
  __HAL_UNLOCK(hpcd);
862
  return HAL_OK;
863
}
864
/**
865
  * @brief  Open and configure an endpoint
866
  * @param  hpcd: PCD handle
867
  * @param  ep_addr: endpoint address
868
  * @param  ep_mps: endpoint max packet size
869
  * @param  ep_type: endpoint type  
870
  * @retval HAL status
871
  */
872
HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type)
873
{
874
  HAL_StatusTypeDef  ret = HAL_OK;
875
  PCD_EPTypeDef *ep = NULL;
876
 
877
  if ((ep_addr & 0x80) == 0x80)
878
  {
879
    ep = &hpcd->IN_ep[ep_addr & 0x7F];
880
  }
881
  else
882
  {
883
    ep = &hpcd->OUT_ep[ep_addr & 0x7F];
884
  }
885
  ep->num   = ep_addr & 0x7F;
886
 
887
  ep->is_in = (0x80 & ep_addr) != 0;
888
  ep->maxpacket = ep_mps;
889
  ep->type = ep_type;
890
 
891
  __HAL_LOCK(hpcd);
892
  USB_ActivateEndpoint(hpcd->Instance , ep);
893
  __HAL_UNLOCK(hpcd);
894
  return ret;
895
}
896
 
897
/**
898
  * @brief  Deactivate an endpoint
899
  * @param  hpcd: PCD handle
900
  * @param  ep_addr: endpoint address
901
  * @retval HAL status
902
  */
903
HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
904
{  
905
  PCD_EPTypeDef *ep = NULL;
906
 
907
  if ((ep_addr & 0x80) == 0x80)
908
  {
909
    ep = &hpcd->IN_ep[ep_addr & 0x7F];
910
  }
911
  else
912
  {
913
    ep = &hpcd->OUT_ep[ep_addr & 0x7F];
914
  }
915
  ep->num   = ep_addr & 0x7F;
916
 
917
  ep->is_in = (0x80 & ep_addr) != 0;
918
 
919
  __HAL_LOCK(hpcd);
920
  USB_DeactivateEndpoint(hpcd->Instance , ep);
921
  __HAL_UNLOCK(hpcd);
922
  return HAL_OK;
923
}
924
 
925
 
926
/**
927
  * @brief  Receive an amount of data
928
  * @param  hpcd: PCD handle
929
  * @param  ep_addr: endpoint address
930
  * @param  pBuf: pointer to the reception buffer
931
  * @param  len: amount of data to be received
932
  * @retval HAL status
933
  */
934
HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
935
{
936
  PCD_EPTypeDef *ep = NULL;
937
 
938
  ep = &hpcd->OUT_ep[ep_addr & 0x7F];
939
 
940
  /*setup and start the Xfer */
941
  ep->xfer_buff = pBuf;  
942
  ep->xfer_len = len;
943
  ep->xfer_count = 0;
944
  ep->is_in = 0;
945
  ep->num = ep_addr & 0x7F;
946
 
947
  __HAL_LOCK(hpcd);
948
 
949
  if ((ep_addr & 0x7F) == 0 )
950
  {
951
    USB_EP0StartXfer(hpcd->Instance , ep);
952
  }
953
  else
954
  {
955
    USB_EPStartXfer(hpcd->Instance , ep);
956
  }
957
  __HAL_UNLOCK(hpcd);
958
 
959
  return HAL_OK;
960
}
961
 
962
/**
963
  * @brief  Get Received Data Size
964
  * @param  hpcd: PCD handle
965
  * @param  ep_addr: endpoint address
966
  * @retval Data Size
967
  */
968
uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
969
{
970
  return hpcd->OUT_ep[ep_addr & 0x7F].xfer_count;
971
}
972
/**
973
  * @brief  Send an amount of data
974
  * @param  hpcd: PCD handle
975
  * @param  ep_addr: endpoint address
976
  * @param  pBuf: pointer to the transmission buffer
977
  * @param  len: amount of data to be sent
978
  * @retval HAL status
979
  */
980
HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
981
{
982
  PCD_EPTypeDef *ep = NULL;
983
 
984
  ep = &hpcd->IN_ep[ep_addr & 0x7F];
985
 
986
  /*setup and start the Xfer */
987
  ep->xfer_buff = pBuf;  
988
  ep->xfer_len = len;
989
  ep->xfer_count = 0;
990
  ep->is_in = 1;
991
  ep->num = ep_addr & 0x7F;
992
 
993
  __HAL_LOCK(hpcd);
994
 
995
  if ((ep_addr & 0x7F) == 0 )
996
  {
997
    USB_EP0StartXfer(hpcd->Instance , ep);
998
  }
999
  else
1000
  {
1001
    USB_EPStartXfer(hpcd->Instance , ep);
1002
  }
1003
 
1004
  __HAL_UNLOCK(hpcd);
1005
 
1006
  return HAL_OK;
1007
}
1008
 
1009
/**
1010
  * @brief  Set a STALL condition over an endpoint
1011
  * @param  hpcd: PCD handle
1012
  * @param  ep_addr: endpoint address
1013
  * @retval HAL status
1014
  */
1015
HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1016
{
1017
  PCD_EPTypeDef *ep = NULL;
1018
 
1019
  if ((0x80 & ep_addr) == 0x80)
1020
  {
1021
    ep = &hpcd->IN_ep[ep_addr & 0x7F];
1022
  }
1023
  else
1024
  {
1025
    ep = &hpcd->OUT_ep[ep_addr];
1026
  }
1027
 
1028
  ep->is_stall = 1;
1029
  ep->num   = ep_addr & 0x7F;
1030
  ep->is_in = ((ep_addr & 0x80) == 0x80);
1031
 
1032
  __HAL_LOCK(hpcd);
1033
  USB_EPSetStall(hpcd->Instance , ep);
1034
  if((ep_addr & 0x7F) == 0)
1035
  {
1036
    USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
1037
  }
1038
  __HAL_UNLOCK(hpcd);
1039
 
1040
  return HAL_OK;
1041
}
1042
 
1043
/**
1044
  * @brief  Clear a STALL condition over in an endpoint
1045
  * @param  hpcd: PCD handle
1046
  * @param  ep_addr: endpoint address
1047
  * @retval HAL status
1048
  */
1049
HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1050
{
1051
  PCD_EPTypeDef *ep = NULL;
1052
 
1053
  if ((0x80 & ep_addr) == 0x80)
1054
  {
1055
    ep = &hpcd->IN_ep[ep_addr & 0x7F];
1056
  }
1057
  else
1058
  {
1059
    ep = &hpcd->OUT_ep[ep_addr];
1060
  }
1061
 
1062
  ep->is_stall = 0;
1063
  ep->num   = ep_addr & 0x7F;
1064
  ep->is_in = ((ep_addr & 0x80) == 0x80);
1065
 
1066
  __HAL_LOCK(hpcd);
1067
  USB_EPClearStall(hpcd->Instance , ep);
1068
  __HAL_UNLOCK(hpcd);
1069
 
1070
  return HAL_OK;
1071
}
1072
 
1073
/**
1074
  * @brief  Flush an endpoint
1075
  * @param  hpcd: PCD handle
1076
  * @param  ep_addr: endpoint address
1077
  * @retval HAL status
1078
  */
1079
HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1080
{
1081
  __HAL_LOCK(hpcd);
1082
 
1083
  if ((ep_addr & 0x80) == 0x80)
1084
  {
1085
    USB_FlushTxFifo(hpcd->Instance, ep_addr & 0x7F);
1086
  }
1087
  else
1088
  {
1089
    USB_FlushRxFifo(hpcd->Instance);
1090
  }
1091
 
1092
  __HAL_UNLOCK(hpcd);
1093
 
1094
  return HAL_OK;
1095
}
1096
 
1097
/**
1098
  * @brief  HAL_PCD_ActivateRemoteWakeup : active remote wakeup signalling
1099
  * @param  hpcd: PCD handle
1100
  * @retval HAL status
1101
  */
1102
HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1103
{
1104
  return(USB_ActivateRemoteWakeup(hpcd->Instance));
1105
}
1106
 
1107
/**
1108
  * @brief  HAL_PCD_DeActivateRemoteWakeup : de-active remote wakeup signalling
1109
  * @param  hpcd: PCD handle
1110
  * @retval HAL status
1111
  */
1112
HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1113
{
1114
  return(USB_DeActivateRemoteWakeup(hpcd->Instance));
1115
}
1116
/**
1117
  * @}
1118
  */
1119
 
1120
/** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
1121
 *  @brief   Peripheral State functions
1122
 *
1123
@verbatim
1124
 ===============================================================================
1125
                      ##### Peripheral State functions #####
1126
 ===============================================================================
1127
    [..]
1128
    This subsection permits to get in run-time the status of the peripheral
1129
    and the data flow.
1130
 
1131
@endverbatim
1132
  * @{
1133
  */
1134
 
1135
/**
1136
  * @brief  Return the PCD state
1137
  * @param  hpcd: PCD handle
1138
  * @retval HAL state
1139
  */
1140
PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
1141
{
1142
  return hpcd->State;
1143
}
1144
 
1145
/**
1146
  * @}
1147
  */
1148
 
1149
/**
1150
  * @}
1151
  */
1152
 
1153
/** @addtogroup PCD_Private_Functions
1154
  * @{
1155
  */
1156
#if defined (USB_OTG_FS)
1157
/**
1158
  * @brief  DCD_WriteEmptyTxFifo
1159
  *         check FIFO for the next packet to be loaded
1160
  * @param  hpcd: PCD handle
1161
  * @param  epnum : endpoint number
1162
  *          This parameter can be a value from 0 to 15  
1163
  * @retval HAL status
1164
  */
1165
static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
1166
{
1167
  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;  
1168
  USB_OTG_EPTypeDef *ep = NULL;
1169
  int32_t len = 0;
1170
  uint32_t len32b = 0;
1171
  uint32_t fifoemptymsk = 0;
1172
 
1173
  ep = &hpcd->IN_ep[epnum];
1174
  len = ep->xfer_len - ep->xfer_count;
1175
 
1176
  if (len > ep->maxpacket)
1177
  {
1178
    len = ep->maxpacket;
1179
  }
1180
 
1181
  len32b = (len + 3) / 4;
1182
 
1183
  while ((USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) > len32b &&
1184
         ep->xfer_count < ep->xfer_len &&
1185
         ep->xfer_len != 0)
1186
  {
1187
    /* Write the FIFO */
1188
    len = ep->xfer_len - ep->xfer_count;
1189
 
1190
    if (len > ep->maxpacket)
1191
    {
1192
      len = ep->maxpacket;
1193
    }
1194
    len32b = (len + 3) / 4;
1195
 
1196
    USB_WritePacket(USBx, ep->xfer_buff, epnum, len);
1197
 
1198
    ep->xfer_buff  += len;
1199
    ep->xfer_count += len;
1200
  }
1201
 
1202
  if(len <= 0)
1203
  {
1204
    fifoemptymsk = 0x1 << epnum;
1205
    USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
1206
 
1207
  }
1208
 
1209
  return HAL_OK;
1210
}
1211
#endif /* USB_OTG_FS */
1212
 
1213
#if defined (USB)
1214
/**
1215
  * @brief  This function handles PCD Endpoint interrupt request.
1216
  * @param  hpcd: PCD handle
1217
  * @retval HAL status
1218
  */
1219
static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
1220
{
1221
  PCD_EPTypeDef *ep = NULL;
1222
  uint16_t count = 0;
1223
  uint8_t epindex = 0;
1224
  __IO uint16_t wIstr = 0;  
1225
  __IO uint16_t wEPVal = 0;
1226
 
1227
  /* stay in loop while pending interrupts */
1228
  while (((wIstr = hpcd->Instance->ISTR) & USB_ISTR_CTR) != 0)
1229
  {
1230
    /* extract highest priority endpoint number */
1231
    epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
1232
 
1233
    if (epindex == 0)
1234
    {
1235
      /* Decode and service control endpoint interrupt */
1236
 
1237
      /* DIR bit = origin of the interrupt */  
1238
      if ((wIstr & USB_ISTR_DIR) == 0)
1239
      {
1240
        /* DIR = 0 */
1241
 
1242
        /* DIR = 0      => IN  int */
1243
        /* DIR = 0 implies that (EP_CTR_TX = 1) always  */
1244
        PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1245
        ep = &hpcd->IN_ep[0];
1246
 
1247
        ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1248
        ep->xfer_buff += ep->xfer_count;
1249
 
1250
        /* TX COMPLETE */
1251
        HAL_PCD_DataInStageCallback(hpcd, 0);
1252
 
1253
 
1254
        if((hpcd->USB_Address > 0)&& ( ep->xfer_len == 0))
1255
        {
1256
          hpcd->Instance->DADDR = (hpcd->USB_Address | USB_DADDR_EF);
1257
          hpcd->USB_Address = 0;
1258
        }
1259
 
1260
      }
1261
      else
1262
      {
1263
        /* DIR = 1 */
1264
 
1265
        /* DIR = 1 & CTR_RX       => SETUP or OUT int */
1266
        /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
1267
        ep = &hpcd->OUT_ep[0];
1268
        wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
1269
 
1270
        if ((wEPVal & USB_EP_SETUP) != 0)
1271
        {
1272
          /* Get SETUP Packet*/
1273
          ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1274
          USB_ReadPMA(hpcd->Instance, (uint8_t*)hpcd->Setup ,ep->pmaadress , ep->xfer_count);      
1275
          /* SETUP bit kept frozen while CTR_RX = 1*/
1276
          PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1277
 
1278
          /* Process SETUP Packet*/
1279
          HAL_PCD_SetupStageCallback(hpcd);
1280
        }
1281
 
1282
        else if ((wEPVal & USB_EP_CTR_RX) != 0)
1283
        {
1284
          PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1285
          /* Get Control Data OUT Packet*/
1286
          ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1287
 
1288
          if (ep->xfer_count != 0)
1289
          {
1290
            USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count);
1291
            ep->xfer_buff+=ep->xfer_count;
1292
          }
1293
 
1294
          /* Process Control Data OUT Packet*/
1295
           HAL_PCD_DataOutStageCallback(hpcd, 0);
1296
 
1297
          PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
1298
          PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
1299
        }
1300
      }
1301
    }
1302
    else
1303
    {
1304
      /* Decode and service non control endpoints interrupt  */
1305
 
1306
      /* process related endpoint register */
1307
      wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);
1308
      if ((wEPVal & USB_EP_CTR_RX) != 0)
1309
      {  
1310
        /* clear int flag */
1311
        PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
1312
        ep = &hpcd->OUT_ep[epindex];
1313
 
1314
        /* OUT double Buffering*/
1315
        if (ep->doublebuffer == 0)
1316
        {
1317
          count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1318
          if (count != 0)
1319
          {
1320
            USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
1321
          }
1322
        }
1323
        else
1324
        {
1325
          if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX)
1326
          {
1327
            /*read from endpoint BUF0Addr buffer*/
1328
            count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
1329
            if (count != 0)
1330
            {
1331
              USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
1332
            }
1333
          }
1334
          else
1335
          {
1336
            /*read from endpoint BUF1Addr buffer*/
1337
            count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
1338
            if (count != 0)
1339
            {
1340
              USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
1341
            }
1342
          }
1343
          PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_OUT);  
1344
        }
1345
        /*multi-packet on the NON control OUT endpoint*/
1346
        ep->xfer_count+=count;
1347
        ep->xfer_buff+=count;
1348
 
1349
        if ((ep->xfer_len == 0) || (count < ep->maxpacket))
1350
        {
1351
          /* RX COMPLETE */
1352
          HAL_PCD_DataOutStageCallback(hpcd, ep->num);
1353
        }
1354
        else
1355
        {
1356
          HAL_PCD_EP_Receive(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
1357
        }
1358
 
1359
      } /* if((wEPVal & EP_CTR_RX) */
1360
 
1361
      if ((wEPVal & USB_EP_CTR_TX) != 0)
1362
      {
1363
        ep = &hpcd->IN_ep[epindex];
1364
 
1365
        /* clear int flag */
1366
        PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
1367
 
1368
        /* IN double Buffering*/
1369
        if (ep->doublebuffer == 0)
1370
        {
1371
          ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1372
          if (ep->xfer_count != 0)
1373
          {
1374
            USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count);
1375
          }
1376
        }
1377
        else
1378
        {
1379
          if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_TX)
1380
          {
1381
            /*read from endpoint BUF0Addr buffer*/
1382
            ep->xfer_count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
1383
            if (ep->xfer_count != 0)
1384
            {
1385
              USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, ep->xfer_count);
1386
            }
1387
          }
1388
          else
1389
          {
1390
            /*read from endpoint BUF1Addr buffer*/
1391
            ep->xfer_count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
1392
            if (ep->xfer_count != 0)
1393
            {
1394
              USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, ep->xfer_count);
1395
            }
1396
          }
1397
          PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_IN);  
1398
        }
1399
        /*multi-packet on the NON control IN endpoint*/
1400
        ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1401
        ep->xfer_buff+=ep->xfer_count;
1402
 
1403
        /* Zero Length Packet? */
1404
        if (ep->xfer_len == 0)
1405
        {
1406
          /* TX COMPLETE */
1407
          HAL_PCD_DataInStageCallback(hpcd, ep->num);
1408
        }
1409
        else
1410
        {
1411
          HAL_PCD_EP_Transmit(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
1412
        }
1413
      }
1414
    }
1415
  }
1416
  return HAL_OK;
1417
}
1418
#endif /* USB */
1419
 
1420
/**
1421
  * @}
1422
  */
1423
 
1424
/**
1425
  * @}
1426
  */
1427
 
1428
#endif /* STM32F102x6 || STM32F102xB || */
1429
       /* STM32F103x6 || STM32F103xB || */
1430
       /* STM32F103xE || STM32F103xG || */
1431
       /* STM32F105xC || STM32F107xC    */
1432
 
1433
#endif /* HAL_PCD_MODULE_ENABLED */
1434
 
1435
 
1436
/**
1437
  * @}
1438
  */
1439
 
1440
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/