Subversion Repositories DashDisplay

Rev

Go to most recent revision | Details | 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
  * @version V1.0.1
6
  * @date    31-July-2015
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
  *
50
  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
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
{
252
  /* NOTE : This function should not be modified, when the callback is needed,
253
            the HAL_PCD_MspInit could be implemented in the user file
254
   */
255
}
256
 
257
/**
258
  * @brief  DeInitializes PCD MSP.
259
  * @param  hpcd: PCD handle
260
  * @retval None
261
  */
262
__weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
263
{
264
  /* NOTE : This function should not be modified, when the callback is needed,
265
            the HAL_PCD_MspDeInit could be implemented in the user file
266
   */
267
}
268
 
269
/**
270
  * @}
271
  */
272
 
273
/** @defgroup PCD_Exported_Functions_Group2 IO operation functions
274
 *  @brief   Data transfers functions
275
 *
276
@verbatim
277
 ===============================================================================
278
                      ##### IO operation functions #####
279
 ===============================================================================
280
    [..]
281
    This subsection provides a set of functions allowing to manage the PCD data
282
    transfers.
283
 
284
@endverbatim
285
  * @{
286
  */
287
 
288
/**
289
  * @brief  Start The USB Device.
290
  * @param  hpcd: PCD handle
291
  * @retval HAL status
292
  */
293
HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
294
{
295
  __HAL_LOCK(hpcd);
296
  HAL_PCDEx_SetConnectionState (hpcd, 1);
297
  USB_DevConnect (hpcd->Instance);
298
  __HAL_PCD_ENABLE(hpcd);
299
  __HAL_UNLOCK(hpcd);
300
  return HAL_OK;
301
}
302
 
303
/**
304
  * @brief  Stop The USB Device.
305
  * @param  hpcd: PCD handle
306
  * @retval HAL status
307
  */
308
HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
309
{  
310
  __HAL_LOCK(hpcd);
311
  __HAL_PCD_DISABLE(hpcd);
312
  USB_StopDevice(hpcd->Instance);
313
  USB_DevDisconnect (hpcd->Instance);
314
  __HAL_UNLOCK(hpcd);
315
  return HAL_OK;
316
}
317
 
318
#if defined (USB_OTG_FS)
319
/**
320
  * @brief  This function handles PCD interrupt request.
321
  * @param  hpcd: PCD handle
322
  * @retval HAL status
323
  */
324
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
325
{
326
  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
327
  uint32_t index = 0, ep_intr = 0, epint = 0, epnum = 0;
328
  uint32_t fifoemptymsk = 0, temp = 0;
329
  USB_OTG_EPTypeDef *ep = NULL;
330
 
331
  /* ensure that we are in device mode */
332
  if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
333
  {
334
    /* avoid spurious interrupt */
335
    if(__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
336
    {
337
      return;
338
    }
339
 
340
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
341
    {
342
     /* incorrect mode, acknowledge the interrupt */
343
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
344
    }
345
 
346
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
347
    {
348
      epnum = 0;
349
 
350
      /* Read in the device interrupt bits */
351
      ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
352
 
353
      while ( ep_intr )
354
      {
355
        if (ep_intr & 0x1)
356
        {
357
          epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, epnum);
358
 
359
          if(( epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
360
          {
361
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
362
 
363
            HAL_PCD_DataOutStageCallback(hpcd, epnum);
364
          }
365
 
366
          if(( epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
367
          {
368
            /* Inform the upper layer that a setup packet is available */
369
            HAL_PCD_SetupStageCallback(hpcd);
370
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
371
          }
372
 
373
          if(( epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
374
          {
375
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
376
          }
377
        }
378
        epnum++;
379
        ep_intr >>= 1;
380
      }
381
    }
382
 
383
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
384
    {
385
      /* Read in the device interrupt bits */
386
      ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
387
 
388
      epnum = 0;
389
 
390
      while ( ep_intr )
391
      {
392
        if (ep_intr & 0x1) /* In ITR */
393
        {
394
          epint = USB_ReadDevInEPInterrupt(hpcd->Instance, epnum);
395
 
396
          if(( epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
397
          {
398
            fifoemptymsk = 0x1 << epnum;
399
            USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
400
 
401
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
402
 
403
            HAL_PCD_DataInStageCallback(hpcd, epnum);
404
          }
405
          if(( epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
406
          {
407
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
408
          }
409
          if(( epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
410
          {
411
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
412
          }
413
          if(( epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
414
          {
415
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
416
          }
417
          if(( epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
418
          {
419
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
420
          }
421
          if(( epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
422
          {
423
            PCD_WriteEmptyTxFifo(hpcd , epnum);
424
          }
425
        }
426
        epnum++;
427
        ep_intr >>= 1;
428
      }
429
    }
430
 
431
    /* Handle Resume Interrupt */
432
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
433
    {
434
     /* Clear the Remote Wake-up signalling */
435
      USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
436
 
437
     HAL_PCD_ResumeCallback(hpcd);
438
 
439
     __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
440
    }
441
 
442
    /* Handle Suspend Interrupt */
443
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
444
    {
445
      if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
446
      {
447
 
448
        HAL_PCD_SuspendCallback(hpcd);
449
      }
450
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
451
    }
452
 
453
    /* Handle Reset Interrupt */
454
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
455
    {
456
      USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
457
      USB_FlushTxFifo(hpcd->Instance ,  0 );
458
 
459
      for (index = 0; index < hpcd->Init.dev_endpoints ; index++)
460
      {
461
        USBx_INEP(index)->DIEPINT = 0xFF;
462
        USBx_OUTEP(index)->DOEPINT = 0xFF;
463
      }
464
      USBx_DEVICE->DAINT = 0xFFFFFFFF;
465
      USBx_DEVICE->DAINTMSK |= 0x10001;
466
 
467
      USBx_DEVICE->DOEPMSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM);
468
      USBx_DEVICE->DIEPMSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);
469
 
470
      /* Set Default Address to 0 */
471
      USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
472
 
473
      /* setup EP0 to receive SETUP packets */
474
      USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
475
 
476
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
477
    }
478
 
479
    /* Handle Enumeration done Interrupt */
480
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
481
    {
482
      USB_ActivateSetup(hpcd->Instance);
483
      hpcd->Instance->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
484
 
485
      hpcd->Init.speed            = USB_OTG_SPEED_FULL;
486
      hpcd->Init.ep0_mps          = USB_OTG_FS_MAX_PACKET_SIZE ;
487
      hpcd->Instance->GUSBCFG |= (uint32_t)((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT);
488
 
489
      HAL_PCD_ResetCallback(hpcd);
490
 
491
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
492
    }
493
 
494
    /* Handle RxQLevel Interrupt */
495
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
496
    {
497
      USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
498
      temp = USBx->GRXSTSP;
499
      ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
500
 
501
      if(((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_DATA_UPDT)
502
      {
503
        if((temp & USB_OTG_GRXSTSP_BCNT) != 0)
504
        {
505
          USB_ReadPacket(USBx, ep->xfer_buff, (temp & USB_OTG_GRXSTSP_BCNT) >> 4);
506
          ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
507
          ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
508
        }
509
      }
510
      else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_SETUP_UPDT)
511
      {
512
        USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8);
513
        ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
514
      }
515
      USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
516
    }
517
 
518
    /* Handle SOF Interrupt */
519
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
520
    {
521
      HAL_PCD_SOFCallback(hpcd);
522
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
523
    }
524
 
525
    /* Handle Incomplete ISO IN Interrupt */
526
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
527
    {
528
      HAL_PCD_ISOINIncompleteCallback(hpcd, epnum);
529
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
530
    }
531
 
532
    /* Handle Incomplete ISO OUT Interrupt */
533
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
534
    {
535
      HAL_PCD_ISOOUTIncompleteCallback(hpcd, epnum);
536
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
537
    }
538
 
539
    /* Handle Connection event Interrupt */
540
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
541
    {
542
      HAL_PCD_ConnectCallback(hpcd);
543
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
544
    }
545
 
546
    /* Handle Disconnection event Interrupt */
547
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
548
    {
549
      temp = hpcd->Instance->GOTGINT;
550
 
551
      if((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
552
      {
553
        HAL_PCD_DisconnectCallback(hpcd);
554
      }
555
      hpcd->Instance->GOTGINT |= temp;
556
    }
557
  }
558
}
559
#endif /* USB_OTG_FS */
560
 
561
#if defined (USB)
562
/**
563
  * @brief  This function handles PCD interrupt request.
564
  * @param  hpcd: PCD handle
565
  * @retval HAL status
566
  */
567
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
568
{
569
  uint32_t wInterrupt_Mask = 0;
570
 
571
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_CTR))
572
  {
573
    /* servicing of the endpoint correct transfer interrupt */
574
    /* clear of the CTR flag into the sub */
575
    PCD_EP_ISR_Handler(hpcd);
576
  }
577
 
578
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_RESET))
579
  {
580
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
581
    HAL_PCD_ResetCallback(hpcd);
582
    HAL_PCD_SetAddress(hpcd, 0);
583
  }
584
 
585
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_PMAOVR))
586
  {
587
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);    
588
  }
589
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ERR))
590
  {
591
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR);
592
  }
593
 
594
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP))
595
  {  
596
    hpcd->Instance->CNTR &= ~(USB_CNTR_LP_MODE);
597
 
598
    /*set wInterrupt_Mask global variable*/
599
    wInterrupt_Mask = USB_CNTR_CTRM  | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_ERRM \
600
      | USB_CNTR_ESOFM | USB_CNTR_RESETM;
601
 
602
    /*Set interrupt mask*/
603
    hpcd->Instance->CNTR = wInterrupt_Mask;
604
 
605
    HAL_PCD_ResumeCallback(hpcd);
606
 
607
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);    
608
  }
609
 
610
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SUSP))
611
  {
612
    /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
613
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);  
614
 
615
    /* Force low-power mode in the macrocell */
616
    hpcd->Instance->CNTR |= USB_CNTR_FSUSP;
617
    hpcd->Instance->CNTR |= USB_CNTR_LP_MODE;
618
    if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP) == 0)
619
    {
620
      HAL_PCD_SuspendCallback(hpcd);
621
    }
622
  }
623
 
624
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SOF))
625
  {
626
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);
627
    HAL_PCD_SOFCallback(hpcd);
628
  }
629
 
630
  if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ESOF))
631
  {
632
    /* clear ESOF flag in ISTR */
633
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);
634
  }
635
}
636
#endif /* USB */
637
 
638
/**
639
  * @brief  Data out stage callbacks
640
  * @param  hpcd: PCD handle
641
  * @param  epnum: endpoint number
642
  * @retval None
643
  */
644
 __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
645
{
646
  /* NOTE : This function should not be modified, when the callback is needed,
647
            the HAL_PCD_DataOutStageCallback could be implemented in the user file
648
   */
649
}
650
 
651
/**
652
  * @brief  Data IN stage callbacks
653
  * @param  hpcd: PCD handle
654
  * @param  epnum: endpoint number
655
  * @retval None
656
  */
657
 __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
658
{
659
  /* NOTE : This function should not be modified, when the callback is needed,
660
            the HAL_PCD_DataInStageCallback could be implemented in the user file
661
   */
662
}
663
/**
664
  * @brief  Setup stage callback
665
  * @param  hpcd: PCD handle
666
  * @retval None
667
  */
668
 __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
669
{
670
  /* NOTE : This function should not be modified, when the callback is needed,
671
            the HAL_PCD_SetupStageCallback could be implemented in the user file
672
   */
673
}
674
 
675
/**
676
  * @brief  USB Start Of Frame callbacks
677
  * @param  hpcd: PCD handle
678
  * @retval None
679
  */
680
 __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
681
{
682
  /* NOTE : This function should not be modified, when the callback is needed,
683
            the HAL_PCD_SOFCallback could be implemented in the user file
684
   */
685
}
686
 
687
/**
688
  * @brief  USB Reset callbacks
689
  * @param  hpcd: PCD handle
690
  * @retval None
691
  */
692
 __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
693
{
694
  /* NOTE : This function should not be modified, when the callback is needed,
695
            the HAL_PCD_ResetCallback could be implemented in the user file
696
   */
697
}
698
 
699
/**
700
  * @brief  Suspend event callbacks
701
  * @param  hpcd: PCD handle
702
  * @retval None
703
  */
704
 __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
705
{
706
  /* NOTE : This function should not be modified, when the callback is needed,
707
            the HAL_PCD_SuspendCallback could be implemented in the user file
708
   */
709
}
710
 
711
/**
712
  * @brief  Resume event callbacks
713
  * @param  hpcd: PCD handle
714
  * @retval None
715
  */
716
 __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
717
{
718
  /* NOTE : This function should not be modified, when the callback is needed,
719
            the HAL_PCD_ResumeCallback could be implemented in the user file
720
   */
721
}
722
 
723
/**
724
  * @brief  Incomplete ISO OUT callbacks
725
  * @param  hpcd: PCD handle
726
  * @param  epnum: endpoint number
727
  * @retval None
728
  */
729
 __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
730
{
731
  /* NOTE : This function should not be modified, when the callback is needed,
732
            the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
733
   */
734
}
735
 
736
/**
737
  * @brief  Incomplete ISO IN  callbacks
738
  * @param  hpcd: PCD handle
739
  * @param  epnum: endpoint number
740
  * @retval None
741
  */
742
 __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
743
{
744
  /* NOTE : This function should not be modified, when the callback is needed,
745
            the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
746
   */
747
}
748
 
749
/**
750
  * @brief  Connection event callbacks
751
  * @param  hpcd: PCD handle
752
  * @retval None
753
  */
754
 __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
755
{
756
  /* NOTE : This function should not be modified, when the callback is needed,
757
            the HAL_PCD_ConnectCallback could be implemented in the user file
758
   */
759
}
760
 
761
/**
762
  * @brief  Disconnection event callbacks
763
  * @param  hpcd: PCD handle
764
  * @retval None
765
  */
766
 __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
767
{
768
  /* NOTE : This function should not be modified, when the callback is needed,
769
            the HAL_PCD_DisconnectCallback could be implemented in the user file
770
   */
771
}
772
 
773
/**
774
  * @}
775
  */
776
 
777
/** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
778
 *  @brief   management functions
779
 *
780
@verbatim
781
 ===============================================================================
782
                      ##### Peripheral Control functions #####
783
 ===============================================================================  
784
    [..]
785
    This subsection provides a set of functions allowing to control the PCD data
786
    transfers.
787
 
788
@endverbatim
789
  * @{
790
  */
791
 
792
/**
793
  * @brief  Connect the USB device
794
  * @param  hpcd: PCD handle
795
  * @retval HAL status
796
  */
797
HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
798
{
799
  __HAL_LOCK(hpcd);
800
  HAL_PCDEx_SetConnectionState (hpcd, 1);
801
  USB_DevConnect(hpcd->Instance);
802
  __HAL_UNLOCK(hpcd);
803
  return HAL_OK;
804
}
805
 
806
/**
807
  * @brief  Disconnect the USB device
808
  * @param  hpcd: PCD handle
809
  * @retval HAL status
810
  */
811
HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
812
{
813
  __HAL_LOCK(hpcd);
814
  HAL_PCDEx_SetConnectionState (hpcd, 0);
815
  USB_DevDisconnect(hpcd->Instance);
816
  __HAL_UNLOCK(hpcd);
817
  return HAL_OK;
818
}
819
 
820
/**
821
  * @brief  Set the USB Device address
822
  * @param  hpcd: PCD handle
823
  * @param  address: new device address
824
  * @retval HAL status
825
  */
826
HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
827
{
828
  __HAL_LOCK(hpcd);
829
  hpcd->USB_Address = address;
830
  USB_SetDevAddress(hpcd->Instance, address);
831
  __HAL_UNLOCK(hpcd);
832
  return HAL_OK;
833
}
834
/**
835
  * @brief  Open and configure an endpoint
836
  * @param  hpcd: PCD handle
837
  * @param  ep_addr: endpoint address
838
  * @param  ep_mps: endpoint max packet size
839
  * @param  ep_type: endpoint type  
840
  * @retval HAL status
841
  */
842
HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type)
843
{
844
  HAL_StatusTypeDef  ret = HAL_OK;
845
  PCD_EPTypeDef *ep = NULL;
846
 
847
  if ((ep_addr & 0x80) == 0x80)
848
  {
849
    ep = &hpcd->IN_ep[ep_addr & 0x7F];
850
  }
851
  else
852
  {
853
    ep = &hpcd->OUT_ep[ep_addr & 0x7F];
854
  }
855
  ep->num   = ep_addr & 0x7F;
856
 
857
  ep->is_in = (0x80 & ep_addr) != 0;
858
  ep->maxpacket = ep_mps;
859
  ep->type = ep_type;
860
 
861
  __HAL_LOCK(hpcd);
862
  USB_ActivateEndpoint(hpcd->Instance , ep);
863
  __HAL_UNLOCK(hpcd);
864
  return ret;
865
}
866
 
867
/**
868
  * @brief  Deactivate an endpoint
869
  * @param  hpcd: PCD handle
870
  * @param  ep_addr: endpoint address
871
  * @retval HAL status
872
  */
873
HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
874
{  
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
 
889
  __HAL_LOCK(hpcd);
890
  USB_DeactivateEndpoint(hpcd->Instance , ep);
891
  __HAL_UNLOCK(hpcd);
892
  return HAL_OK;
893
}
894
 
895
 
896
/**
897
  * @brief  Receive an amount of data
898
  * @param  hpcd: PCD handle
899
  * @param  ep_addr: endpoint address
900
  * @param  pBuf: pointer to the reception buffer
901
  * @param  len: amount of data to be received
902
  * @retval HAL status
903
  */
904
HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
905
{
906
  PCD_EPTypeDef *ep = NULL;
907
 
908
  ep = &hpcd->OUT_ep[ep_addr & 0x7F];
909
 
910
  /*setup and start the Xfer */
911
  ep->xfer_buff = pBuf;  
912
  ep->xfer_len = len;
913
  ep->xfer_count = 0;
914
  ep->is_in = 0;
915
  ep->num = ep_addr & 0x7F;
916
 
917
  __HAL_LOCK(hpcd);
918
 
919
  if ((ep_addr & 0x7F) == 0 )
920
  {
921
    USB_EP0StartXfer(hpcd->Instance , ep);
922
  }
923
  else
924
  {
925
    USB_EPStartXfer(hpcd->Instance , ep);
926
  }
927
  __HAL_UNLOCK(hpcd);
928
 
929
  return HAL_OK;
930
}
931
 
932
/**
933
  * @brief  Get Received Data Size
934
  * @param  hpcd: PCD handle
935
  * @param  ep_addr: endpoint address
936
  * @retval Data Size
937
  */
938
uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
939
{
940
  return hpcd->OUT_ep[ep_addr & 0x7F].xfer_count;
941
}
942
/**
943
  * @brief  Send an amount of data
944
  * @param  hpcd: PCD handle
945
  * @param  ep_addr: endpoint address
946
  * @param  pBuf: pointer to the transmission buffer
947
  * @param  len: amount of data to be sent
948
  * @retval HAL status
949
  */
950
HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
951
{
952
  PCD_EPTypeDef *ep = NULL;
953
 
954
  ep = &hpcd->IN_ep[ep_addr & 0x7F];
955
 
956
  /*setup and start the Xfer */
957
  ep->xfer_buff = pBuf;  
958
  ep->xfer_len = len;
959
  ep->xfer_count = 0;
960
  ep->is_in = 1;
961
  ep->num = ep_addr & 0x7F;
962
 
963
  __HAL_LOCK(hpcd);
964
 
965
  if ((ep_addr & 0x7F) == 0 )
966
  {
967
    USB_EP0StartXfer(hpcd->Instance , ep);
968
  }
969
  else
970
  {
971
    USB_EPStartXfer(hpcd->Instance , ep);
972
  }
973
 
974
  __HAL_UNLOCK(hpcd);
975
 
976
  return HAL_OK;
977
}
978
 
979
/**
980
  * @brief  Set a STALL condition over an endpoint
981
  * @param  hpcd: PCD handle
982
  * @param  ep_addr: endpoint address
983
  * @retval HAL status
984
  */
985
HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
986
{
987
  PCD_EPTypeDef *ep = NULL;
988
 
989
  if ((0x80 & ep_addr) == 0x80)
990
  {
991
    ep = &hpcd->IN_ep[ep_addr & 0x7F];
992
  }
993
  else
994
  {
995
    ep = &hpcd->OUT_ep[ep_addr];
996
  }
997
 
998
  ep->is_stall = 1;
999
  ep->num   = ep_addr & 0x7F;
1000
  ep->is_in = ((ep_addr & 0x80) == 0x80);
1001
 
1002
  __HAL_LOCK(hpcd);
1003
  USB_EPSetStall(hpcd->Instance , ep);
1004
  if((ep_addr & 0x7F) == 0)
1005
  {
1006
    USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
1007
  }
1008
  __HAL_UNLOCK(hpcd);
1009
 
1010
  return HAL_OK;
1011
}
1012
 
1013
/**
1014
  * @brief  Clear a STALL condition over in an endpoint
1015
  * @param  hpcd: PCD handle
1016
  * @param  ep_addr: endpoint address
1017
  * @retval HAL status
1018
  */
1019
HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1020
{
1021
  PCD_EPTypeDef *ep = NULL;
1022
 
1023
  if ((0x80 & ep_addr) == 0x80)
1024
  {
1025
    ep = &hpcd->IN_ep[ep_addr & 0x7F];
1026
  }
1027
  else
1028
  {
1029
    ep = &hpcd->OUT_ep[ep_addr];
1030
  }
1031
 
1032
  ep->is_stall = 0;
1033
  ep->num   = ep_addr & 0x7F;
1034
  ep->is_in = ((ep_addr & 0x80) == 0x80);
1035
 
1036
  __HAL_LOCK(hpcd);
1037
  USB_EPClearStall(hpcd->Instance , ep);
1038
  __HAL_UNLOCK(hpcd);
1039
 
1040
  return HAL_OK;
1041
}
1042
 
1043
/**
1044
  * @brief  Flush an endpoint
1045
  * @param  hpcd: PCD handle
1046
  * @param  ep_addr: endpoint address
1047
  * @retval HAL status
1048
  */
1049
HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1050
{
1051
  __HAL_LOCK(hpcd);
1052
 
1053
  if ((ep_addr & 0x80) == 0x80)
1054
  {
1055
    USB_FlushTxFifo(hpcd->Instance, ep_addr & 0x7F);
1056
  }
1057
  else
1058
  {
1059
    USB_FlushRxFifo(hpcd->Instance);
1060
  }
1061
 
1062
  __HAL_UNLOCK(hpcd);
1063
 
1064
  return HAL_OK;
1065
}
1066
 
1067
/**
1068
  * @brief  HAL_PCD_ActivateRemoteWakeup : active remote wakeup signalling
1069
  * @param  hpcd: PCD handle
1070
  * @retval HAL status
1071
  */
1072
HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1073
{
1074
  return(USB_ActivateRemoteWakeup(hpcd->Instance));
1075
}
1076
 
1077
/**
1078
  * @brief  HAL_PCD_DeActivateRemoteWakeup : de-active remote wakeup signalling
1079
  * @param  hpcd: PCD handle
1080
  * @retval HAL status
1081
  */
1082
HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1083
{
1084
  return(USB_DeActivateRemoteWakeup(hpcd->Instance));
1085
}
1086
/**
1087
  * @}
1088
  */
1089
 
1090
/** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
1091
 *  @brief   Peripheral State functions
1092
 *
1093
@verbatim
1094
 ===============================================================================
1095
                      ##### Peripheral State functions #####
1096
 ===============================================================================
1097
    [..]
1098
    This subsection permits to get in run-time the status of the peripheral
1099
    and the data flow.
1100
 
1101
@endverbatim
1102
  * @{
1103
  */
1104
 
1105
/**
1106
  * @brief  Return the PCD state
1107
  * @param  hpcd: PCD handle
1108
  * @retval HAL state
1109
  */
1110
PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
1111
{
1112
  return hpcd->State;
1113
}
1114
 
1115
/**
1116
  * @}
1117
  */
1118
 
1119
/**
1120
  * @}
1121
  */
1122
 
1123
/** @addtogroup PCD_Private_Functions
1124
  * @{
1125
  */
1126
#if defined (USB_OTG_FS)
1127
/**
1128
  * @brief  DCD_WriteEmptyTxFifo
1129
  *         check FIFO for the next packet to be loaded
1130
  * @param  hpcd: PCD handle
1131
  * @param  epnum : endpoint number
1132
  *          This parameter can be a value from 0 to 15  
1133
  * @retval HAL status
1134
  */
1135
static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
1136
{
1137
  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;  
1138
  USB_OTG_EPTypeDef *ep = NULL;
1139
  int32_t len = 0;
1140
  uint32_t len32b = 0;
1141
  uint32_t fifoemptymsk = 0;
1142
 
1143
  ep = &hpcd->IN_ep[epnum];
1144
  len = ep->xfer_len - ep->xfer_count;
1145
 
1146
  if (len > ep->maxpacket)
1147
  {
1148
    len = ep->maxpacket;
1149
  }
1150
 
1151
  len32b = (len + 3) / 4;
1152
 
1153
  while ((USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) > len32b &&
1154
         ep->xfer_count < ep->xfer_len &&
1155
         ep->xfer_len != 0)
1156
  {
1157
    /* Write the FIFO */
1158
    len = ep->xfer_len - ep->xfer_count;
1159
 
1160
    if (len > ep->maxpacket)
1161
    {
1162
      len = ep->maxpacket;
1163
    }
1164
    len32b = (len + 3) / 4;
1165
 
1166
    USB_WritePacket(USBx, ep->xfer_buff, epnum, len);
1167
 
1168
    ep->xfer_buff  += len;
1169
    ep->xfer_count += len;
1170
  }
1171
 
1172
  if(len <= 0)
1173
  {
1174
    fifoemptymsk = 0x1 << epnum;
1175
    USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
1176
 
1177
  }
1178
 
1179
  return HAL_OK;
1180
}
1181
#endif /* USB_OTG_FS */
1182
 
1183
#if defined (USB)
1184
/**
1185
  * @brief  This function handles PCD Endpoint interrupt request.
1186
  * @param  hpcd: PCD handle
1187
  * @retval HAL status
1188
  */
1189
static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
1190
{
1191
  PCD_EPTypeDef *ep = NULL;
1192
  uint16_t count = 0;
1193
  uint8_t epindex = 0;
1194
  __IO uint16_t wIstr = 0;  
1195
  __IO uint16_t wEPVal = 0;
1196
 
1197
  /* stay in loop while pending interrupts */
1198
  while (((wIstr = hpcd->Instance->ISTR) & USB_ISTR_CTR) != 0)
1199
  {
1200
    /* extract highest priority endpoint number */
1201
    epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
1202
 
1203
    if (epindex == 0)
1204
    {
1205
      /* Decode and service control endpoint interrupt */
1206
 
1207
      /* DIR bit = origin of the interrupt */  
1208
      if ((wIstr & USB_ISTR_DIR) == 0)
1209
      {
1210
        /* DIR = 0 */
1211
 
1212
        /* DIR = 0      => IN  int */
1213
        /* DIR = 0 implies that (EP_CTR_TX = 1) always  */
1214
        PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1215
        ep = &hpcd->IN_ep[0];
1216
 
1217
        ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1218
        ep->xfer_buff += ep->xfer_count;
1219
 
1220
        /* TX COMPLETE */
1221
        HAL_PCD_DataInStageCallback(hpcd, 0);
1222
 
1223
 
1224
        if((hpcd->USB_Address > 0)&& ( ep->xfer_len == 0))
1225
        {
1226
          hpcd->Instance->DADDR = (hpcd->USB_Address | USB_DADDR_EF);
1227
          hpcd->USB_Address = 0;
1228
        }
1229
 
1230
      }
1231
      else
1232
      {
1233
        /* DIR = 1 */
1234
 
1235
        /* DIR = 1 & CTR_RX       => SETUP or OUT int */
1236
        /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
1237
        ep = &hpcd->OUT_ep[0];
1238
        wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
1239
 
1240
        if ((wEPVal & USB_EP_SETUP) != 0)
1241
        {
1242
          /* Get SETUP Packet*/
1243
          ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1244
          USB_ReadPMA(hpcd->Instance, (uint8_t*)hpcd->Setup ,ep->pmaadress , ep->xfer_count);      
1245
          /* SETUP bit kept frozen while CTR_RX = 1*/
1246
          PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1247
 
1248
          /* Process SETUP Packet*/
1249
          HAL_PCD_SetupStageCallback(hpcd);
1250
        }
1251
 
1252
        else if ((wEPVal & USB_EP_CTR_RX) != 0)
1253
        {
1254
          PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1255
          /* Get Control Data OUT Packet*/
1256
          ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1257
 
1258
          if (ep->xfer_count != 0)
1259
          {
1260
            USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count);
1261
            ep->xfer_buff+=ep->xfer_count;
1262
          }
1263
 
1264
          /* Process Control Data OUT Packet*/
1265
           HAL_PCD_DataOutStageCallback(hpcd, 0);
1266
 
1267
          PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
1268
          PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
1269
        }
1270
      }
1271
    }
1272
    else
1273
    {
1274
      /* Decode and service non control endpoints interrupt  */
1275
 
1276
      /* process related endpoint register */
1277
      wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);
1278
      if ((wEPVal & USB_EP_CTR_RX) != 0)
1279
      {  
1280
        /* clear int flag */
1281
        PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
1282
        ep = &hpcd->OUT_ep[epindex];
1283
 
1284
        /* OUT double Buffering*/
1285
        if (ep->doublebuffer == 0)
1286
        {
1287
          count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1288
          if (count != 0)
1289
          {
1290
            USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
1291
          }
1292
        }
1293
        else
1294
        {
1295
          if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX)
1296
          {
1297
            /*read from endpoint BUF0Addr buffer*/
1298
            count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
1299
            if (count != 0)
1300
            {
1301
              USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
1302
            }
1303
          }
1304
          else
1305
          {
1306
            /*read from endpoint BUF1Addr buffer*/
1307
            count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
1308
            if (count != 0)
1309
            {
1310
              USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
1311
            }
1312
          }
1313
          PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_OUT);  
1314
        }
1315
        /*multi-packet on the NON control OUT endpoint*/
1316
        ep->xfer_count+=count;
1317
        ep->xfer_buff+=count;
1318
 
1319
        if ((ep->xfer_len == 0) || (count < ep->maxpacket))
1320
        {
1321
          /* RX COMPLETE */
1322
          HAL_PCD_DataOutStageCallback(hpcd, ep->num);
1323
        }
1324
        else
1325
        {
1326
          HAL_PCD_EP_Receive(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
1327
        }
1328
 
1329
      } /* if((wEPVal & EP_CTR_RX) */
1330
 
1331
      if ((wEPVal & USB_EP_CTR_TX) != 0)
1332
      {
1333
        ep = &hpcd->IN_ep[epindex];
1334
 
1335
        /* clear int flag */
1336
        PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
1337
 
1338
        /* IN double Buffering*/
1339
        if (ep->doublebuffer == 0)
1340
        {
1341
          ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1342
          if (ep->xfer_count != 0)
1343
          {
1344
            USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count);
1345
          }
1346
        }
1347
        else
1348
        {
1349
          if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_TX)
1350
          {
1351
            /*read from endpoint BUF0Addr buffer*/
1352
            ep->xfer_count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
1353
            if (ep->xfer_count != 0)
1354
            {
1355
              USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, ep->xfer_count);
1356
            }
1357
          }
1358
          else
1359
          {
1360
            /*read from endpoint BUF1Addr buffer*/
1361
            ep->xfer_count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
1362
            if (ep->xfer_count != 0)
1363
            {
1364
              USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, ep->xfer_count);
1365
            }
1366
          }
1367
          PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_IN);  
1368
        }
1369
        /*multi-packet on the NON control IN endpoint*/
1370
        ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1371
        ep->xfer_buff+=ep->xfer_count;
1372
 
1373
        /* Zero Length Packet? */
1374
        if (ep->xfer_len == 0)
1375
        {
1376
          /* TX COMPLETE */
1377
          HAL_PCD_DataInStageCallback(hpcd, ep->num);
1378
        }
1379
        else
1380
        {
1381
          HAL_PCD_EP_Transmit(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
1382
        }
1383
      }
1384
    }
1385
  }
1386
  return HAL_OK;
1387
}
1388
#endif /* USB */
1389
 
1390
/**
1391
  * @}
1392
  */
1393
 
1394
/**
1395
  * @}
1396
  */
1397
 
1398
#endif /* STM32F102x6 || STM32F102xB || */
1399
       /* STM32F103x6 || STM32F103xB || */
1400
       /* STM32F103xE || STM32F103xG || */
1401
       /* STM32F105xC || STM32F107xC    */
1402
 
1403
#endif /* HAL_PCD_MODULE_ENABLED */
1404
 
1405
 
1406
/**
1407
  * @}
1408
  */
1409
 
1410
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/