Subversion Repositories LedShow

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
  * @brief   PCD HAL module driver.
9 mjames 6
  *          This file provides firmware functions to manage the following
2 mjames 7
  *          functionalities of the USB Peripheral Controller:
8
  *           + Initialization and de-initialization functions
9
  *           + IO operation functions
9 mjames 10
  *           + Peripheral Control functions
2 mjames 11
  *           + Peripheral State functions
12
  *
13
  @verbatim
14
  ==============================================================================
15
                    ##### How to use this driver #####
16
  ==============================================================================
17
    [..]
18
      The PCD HAL driver can be used as follows:
19
 
20
     (#) Declare a PCD_HandleTypeDef handle structure, for example:
21
         PCD_HandleTypeDef  hpcd;
22
 
23
     (#) Fill parameters of Init structure in HCD handle
24
 
9 mjames 25
     (#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...)
2 mjames 26
 
27
     (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
9 mjames 28
         (##) Enable the PCD/USB Low Level interface clock using
29
              (+++) __HAL_RCC_USB_CLK_ENABLE(); For USB Device only FS peripheral
2 mjames 30
 
31
         (##) Initialize the related GPIO clocks
32
         (##) Configure PCD pin-out
33
         (##) Configure PCD NVIC interrupt
34
 
35
     (#)Associate the Upper USB device stack to the HAL PCD Driver:
36
         (##) hpcd.pData = pdev;
37
 
9 mjames 38
     (#)Enable PCD transmission and reception:
2 mjames 39
         (##) HAL_PCD_Start();
40
 
41
  @endverbatim
42
  ******************************************************************************
43
  * @attention
44
  *
9 mjames 45
  * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
46
  * All rights reserved.</center></h2>
2 mjames 47
  *
9 mjames 48
  * This software component is licensed by ST under BSD 3-Clause license,
49
  * the "License"; You may not use this file except in compliance with the
50
  * License. You may obtain a copy of the License at:
51
  *                        opensource.org/licenses/BSD-3-Clause
2 mjames 52
  *
53
  ******************************************************************************
54
  */
55
 
56
/* Includes ------------------------------------------------------------------*/
57
#include "stm32f1xx_hal.h"
58
 
59
/** @addtogroup STM32F1xx_HAL_Driver
60
  * @{
61
  */
62
 
63
/** @defgroup PCD PCD
64
  * @brief PCD HAL module driver
65
  * @{
66
  */
67
 
9 mjames 68
#ifdef HAL_PCD_MODULE_ENABLED
69
 
70
#if defined (USB) || defined (USB_OTG_FS)
71
 
2 mjames 72
/* Private types -------------------------------------------------------------*/
73
/* Private variables ---------------------------------------------------------*/
74
/* Private constants ---------------------------------------------------------*/
75
/* Private macros ------------------------------------------------------------*/
76
/** @defgroup PCD_Private_Macros PCD Private Macros
77
  * @{
9 mjames 78
  */
2 mjames 79
#define PCD_MIN(a, b)  (((a) < (b)) ? (a) : (b))
80
#define PCD_MAX(a, b)  (((a) > (b)) ? (a) : (b))
81
/**
82
  * @}
83
  */
84
 
9 mjames 85
/* Private functions prototypes ----------------------------------------------*/
2 mjames 86
/** @defgroup PCD_Private_Functions PCD Private Functions
87
  * @{
88
  */
89
#if defined (USB_OTG_FS)
90
static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
9 mjames 91
static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
92
static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
93
#endif /* defined (USB_OTG_FS) */
2 mjames 94
 
95
#if defined (USB)
96
static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd);
9 mjames 97
static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef *ep, uint16_t wEPVal);
98
static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef *ep, uint16_t wEPVal);
99
#endif /* defined (USB) */
2 mjames 100
/**
101
  * @}
102
  */
103
 
104
/* Exported functions --------------------------------------------------------*/
105
/** @defgroup PCD_Exported_Functions PCD Exported Functions
106
  * @{
107
  */
108
 
9 mjames 109
/** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
110
  *  @brief    Initialization and Configuration functions
111
  *
2 mjames 112
@verbatim
113
 ===============================================================================
114
            ##### Initialization and de-initialization functions #####
115
 ===============================================================================
116
    [..]  This section provides functions allowing to:
9 mjames 117
 
2 mjames 118
@endverbatim
119
  * @{
120
  */
121
 
122
/**
123
  * @brief  Initializes the PCD according to the specified
9 mjames 124
  *         parameters in the PCD_InitTypeDef and initialize the associated handle.
125
  * @param  hpcd PCD handle
2 mjames 126
  * @retval HAL status
127
  */
128
HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
129
{
9 mjames 130
#if defined (USB_OTG_FS)
131
  USB_OTG_GlobalTypeDef *USBx;
132
#endif /* defined (USB_OTG_FS) */
133
  uint8_t i;
134
 
2 mjames 135
  /* Check the PCD handle allocation */
9 mjames 136
  if (hpcd == NULL)
2 mjames 137
  {
138
    return HAL_ERROR;
139
  }
9 mjames 140
 
2 mjames 141
  /* Check the parameters */
142
  assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
143
 
9 mjames 144
#if defined (USB_OTG_FS)
145
  USBx = hpcd->Instance;
146
#endif /* defined (USB_OTG_FS) */
147
 
148
  if (hpcd->State == HAL_PCD_STATE_RESET)
149
  {
2 mjames 150
    /* Allocate lock resource and initialize it */
151
    hpcd->Lock = HAL_UNLOCKED;
152
 
9 mjames 153
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
154
    hpcd->SOFCallback = HAL_PCD_SOFCallback;
155
    hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
156
    hpcd->ResetCallback = HAL_PCD_ResetCallback;
157
    hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
158
    hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
159
    hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
160
    hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
161
    hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback;
162
    hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback;
163
    hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback;
164
    hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback;
165
 
166
    if (hpcd->MspInitCallback == NULL)
167
    {
168
      hpcd->MspInitCallback = HAL_PCD_MspInit;
169
    }
170
 
171
    /* Init the low level hardware */
172
    hpcd->MspInitCallback(hpcd);
173
#else
2 mjames 174
    /* Init the low level hardware : GPIO, CLOCK, NVIC... */
175
    HAL_PCD_MspInit(hpcd);
9 mjames 176
#endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */
2 mjames 177
  }
9 mjames 178
 
2 mjames 179
  hpcd->State = HAL_PCD_STATE_BUSY;
9 mjames 180
 
181
#if defined (USB_OTG_FS)
182
  /* Disable DMA mode for FS instance */
183
  if ((USBx->CID & (0x1U << 8)) == 0U)
184
  {
185
    hpcd->Init.dma_enable = 0U;
186
  }
187
#endif /* defined (USB_OTG_FS) */
188
 
2 mjames 189
  /* Disable the Interrupts */
190
  __HAL_PCD_DISABLE(hpcd);
191
 
192
  /*Init the Core (common init.) */
9 mjames 193
  if (USB_CoreInit(hpcd->Instance, hpcd->Init) != HAL_OK)
194
  {
195
    hpcd->State = HAL_PCD_STATE_ERROR;
196
    return HAL_ERROR;
197
  }
198
 
2 mjames 199
  /* Force Device Mode*/
9 mjames 200
  (void)USB_SetCurrentMode(hpcd->Instance, USB_DEVICE_MODE);
201
 
2 mjames 202
  /* Init endpoints structures */
9 mjames 203
  for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
2 mjames 204
  {
205
    /* Init ep structure */
9 mjames 206
    hpcd->IN_ep[i].is_in = 1U;
207
    hpcd->IN_ep[i].num = i;
208
    hpcd->IN_ep[i].tx_fifo_num = i;
209
    /* Control until ep is activated */
210
    hpcd->IN_ep[i].type = EP_TYPE_CTRL;
211
    hpcd->IN_ep[i].maxpacket = 0U;
212
    hpcd->IN_ep[i].xfer_buff = 0U;
213
    hpcd->IN_ep[i].xfer_len = 0U;
2 mjames 214
  }
9 mjames 215
 
216
  for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
2 mjames 217
  {
9 mjames 218
    hpcd->OUT_ep[i].is_in = 0U;
219
    hpcd->OUT_ep[i].num = i;
2 mjames 220
    /* Control until ep is activated */
9 mjames 221
    hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
222
    hpcd->OUT_ep[i].maxpacket = 0U;
223
    hpcd->OUT_ep[i].xfer_buff = 0U;
224
    hpcd->OUT_ep[i].xfer_len = 0U;
2 mjames 225
  }
9 mjames 226
 
2 mjames 227
  /* Init Device */
9 mjames 228
  if (USB_DevInit(hpcd->Instance, hpcd->Init) != HAL_OK)
229
  {
230
    hpcd->State = HAL_PCD_STATE_ERROR;
231
    return HAL_ERROR;
232
  }
233
 
2 mjames 234
  hpcd->USB_Address = 0U;
9 mjames 235
  hpcd->State = HAL_PCD_STATE_READY;
236
  (void)USB_DevDisconnect(hpcd->Instance);
237
 
2 mjames 238
  return HAL_OK;
239
}
240
 
241
/**
9 mjames 242
  * @brief  DeInitializes the PCD peripheral.
243
  * @param  hpcd PCD handle
2 mjames 244
  * @retval HAL status
245
  */
246
HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
247
{
248
  /* Check the PCD handle allocation */
9 mjames 249
  if (hpcd == NULL)
2 mjames 250
  {
251
    return HAL_ERROR;
252
  }
253
 
254
  hpcd->State = HAL_PCD_STATE_BUSY;
9 mjames 255
 
2 mjames 256
  /* Stop Device */
9 mjames 257
  if (USB_StopDevice(hpcd->Instance) != HAL_OK)
258
  {
259
    return HAL_ERROR;
260
  }
261
 
262
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
263
  if (hpcd->MspDeInitCallback == NULL)
264
  {
265
    hpcd->MspDeInitCallback = HAL_PCD_MspDeInit; /* Legacy weak MspDeInit  */
266
  }
267
 
2 mjames 268
  /* DeInit the low level hardware */
9 mjames 269
  hpcd->MspDeInitCallback(hpcd);
270
#else
271
  /* DeInit the low level hardware: CLOCK, NVIC.*/
2 mjames 272
  HAL_PCD_MspDeInit(hpcd);
9 mjames 273
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
274
 
275
  hpcd->State = HAL_PCD_STATE_RESET;
276
 
2 mjames 277
  return HAL_OK;
278
}
279
 
280
/**
281
  * @brief  Initializes the PCD MSP.
9 mjames 282
  * @param  hpcd PCD handle
2 mjames 283
  * @retval None
284
  */
285
__weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
286
{
287
  /* Prevent unused argument(s) compilation warning */
288
  UNUSED(hpcd);
9 mjames 289
 
2 mjames 290
  /* NOTE : This function should not be modified, when the callback is needed,
291
            the HAL_PCD_MspInit could be implemented in the user file
292
   */
293
}
294
 
295
/**
296
  * @brief  DeInitializes PCD MSP.
9 mjames 297
  * @param  hpcd PCD handle
2 mjames 298
  * @retval None
299
  */
300
__weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
301
{
302
  /* Prevent unused argument(s) compilation warning */
303
  UNUSED(hpcd);
9 mjames 304
 
2 mjames 305
  /* NOTE : This function should not be modified, when the callback is needed,
306
            the HAL_PCD_MspDeInit could be implemented in the user file
307
   */
308
}
309
 
9 mjames 310
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2 mjames 311
/**
9 mjames 312
  * @brief  Register a User USB PCD Callback
313
  *         To be used instead of the weak predefined callback
314
  * @param  hpcd USB PCD handle
315
  * @param  CallbackID ID of the callback to be registered
316
  *         This parameter can be one of the following values:
317
  *          @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
318
  *          @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
319
  *          @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
320
  *          @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
321
  *          @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
322
  *          @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
323
  *          @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
324
  *          @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
325
  *          @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
326
  * @param  pCallback pointer to the Callback function
327
  * @retval HAL status
328
  */
329
HAL_StatusTypeDef HAL_PCD_RegisterCallback(PCD_HandleTypeDef *hpcd,
330
                                           HAL_PCD_CallbackIDTypeDef CallbackID,
331
                                           pPCD_CallbackTypeDef pCallback)
332
{
333
  HAL_StatusTypeDef status = HAL_OK;
334
 
335
  if (pCallback == NULL)
336
  {
337
    /* Update the error code */
338
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
339
    return HAL_ERROR;
340
  }
341
  /* Process locked */
342
  __HAL_LOCK(hpcd);
343
 
344
  if (hpcd->State == HAL_PCD_STATE_READY)
345
  {
346
    switch (CallbackID)
347
    {
348
      case HAL_PCD_SOF_CB_ID :
349
        hpcd->SOFCallback = pCallback;
350
        break;
351
 
352
      case HAL_PCD_SETUPSTAGE_CB_ID :
353
        hpcd->SetupStageCallback = pCallback;
354
        break;
355
 
356
      case HAL_PCD_RESET_CB_ID :
357
        hpcd->ResetCallback = pCallback;
358
        break;
359
 
360
      case HAL_PCD_SUSPEND_CB_ID :
361
        hpcd->SuspendCallback = pCallback;
362
        break;
363
 
364
      case HAL_PCD_RESUME_CB_ID :
365
        hpcd->ResumeCallback = pCallback;
366
        break;
367
 
368
      case HAL_PCD_CONNECT_CB_ID :
369
        hpcd->ConnectCallback = pCallback;
370
        break;
371
 
372
      case HAL_PCD_DISCONNECT_CB_ID :
373
        hpcd->DisconnectCallback = pCallback;
374
        break;
375
 
376
      case HAL_PCD_MSPINIT_CB_ID :
377
        hpcd->MspInitCallback = pCallback;
378
        break;
379
 
380
      case HAL_PCD_MSPDEINIT_CB_ID :
381
        hpcd->MspDeInitCallback = pCallback;
382
        break;
383
 
384
      default :
385
        /* Update the error code */
386
        hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
387
        /* Return error status */
388
        status =  HAL_ERROR;
389
        break;
390
    }
391
  }
392
  else if (hpcd->State == HAL_PCD_STATE_RESET)
393
  {
394
    switch (CallbackID)
395
    {
396
      case HAL_PCD_MSPINIT_CB_ID :
397
        hpcd->MspInitCallback = pCallback;
398
        break;
399
 
400
      case HAL_PCD_MSPDEINIT_CB_ID :
401
        hpcd->MspDeInitCallback = pCallback;
402
        break;
403
 
404
      default :
405
        /* Update the error code */
406
        hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
407
        /* Return error status */
408
        status =  HAL_ERROR;
409
        break;
410
    }
411
  }
412
  else
413
  {
414
    /* Update the error code */
415
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
416
    /* Return error status */
417
    status =  HAL_ERROR;
418
  }
419
 
420
  /* Release Lock */
421
  __HAL_UNLOCK(hpcd);
422
  return status;
423
}
424
 
425
/**
426
  * @brief  Unregister an USB PCD Callback
427
  *         USB PCD callabck is redirected to the weak predefined callback
428
  * @param  hpcd USB PCD handle
429
  * @param  CallbackID ID of the callback to be unregistered
430
  *         This parameter can be one of the following values:
431
  *          @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
432
  *          @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
433
  *          @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
434
  *          @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
435
  *          @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
436
  *          @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
437
  *          @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
438
  *          @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
439
  *          @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
440
  * @retval HAL status
441
  */
442
HAL_StatusTypeDef HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID)
443
{
444
  HAL_StatusTypeDef status = HAL_OK;
445
 
446
  /* Process locked */
447
  __HAL_LOCK(hpcd);
448
 
449
  /* Setup Legacy weak Callbacks  */
450
  if (hpcd->State == HAL_PCD_STATE_READY)
451
  {
452
    switch (CallbackID)
453
    {
454
      case HAL_PCD_SOF_CB_ID :
455
        hpcd->SOFCallback = HAL_PCD_SOFCallback;
456
        break;
457
 
458
      case HAL_PCD_SETUPSTAGE_CB_ID :
459
        hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
460
        break;
461
 
462
      case HAL_PCD_RESET_CB_ID :
463
        hpcd->ResetCallback = HAL_PCD_ResetCallback;
464
        break;
465
 
466
      case HAL_PCD_SUSPEND_CB_ID :
467
        hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
468
        break;
469
 
470
      case HAL_PCD_RESUME_CB_ID :
471
        hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
472
        break;
473
 
474
      case HAL_PCD_CONNECT_CB_ID :
475
        hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
476
        break;
477
 
478
      case HAL_PCD_DISCONNECT_CB_ID :
479
        hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
480
        break;
481
 
482
      case HAL_PCD_MSPINIT_CB_ID :
483
        hpcd->MspInitCallback = HAL_PCD_MspInit;
484
        break;
485
 
486
      case HAL_PCD_MSPDEINIT_CB_ID :
487
        hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
488
        break;
489
 
490
      default :
491
        /* Update the error code */
492
        hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
493
 
494
        /* Return error status */
495
        status =  HAL_ERROR;
496
        break;
497
    }
498
  }
499
  else if (hpcd->State == HAL_PCD_STATE_RESET)
500
  {
501
    switch (CallbackID)
502
    {
503
      case HAL_PCD_MSPINIT_CB_ID :
504
        hpcd->MspInitCallback = HAL_PCD_MspInit;
505
        break;
506
 
507
      case HAL_PCD_MSPDEINIT_CB_ID :
508
        hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
509
        break;
510
 
511
      default :
512
        /* Update the error code */
513
        hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
514
 
515
        /* Return error status */
516
        status =  HAL_ERROR;
517
        break;
518
    }
519
  }
520
  else
521
  {
522
    /* Update the error code */
523
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
524
 
525
    /* Return error status */
526
    status =  HAL_ERROR;
527
  }
528
 
529
  /* Release Lock */
530
  __HAL_UNLOCK(hpcd);
531
  return status;
532
}
533
 
534
/**
535
  * @brief  Register USB PCD Data OUT Stage Callback
536
  *         To be used instead of the weak HAL_PCD_DataOutStageCallback() predefined callback
537
  * @param  hpcd PCD handle
538
  * @param  pCallback pointer to the USB PCD Data OUT Stage Callback function
539
  * @retval HAL status
540
  */
541
HAL_StatusTypeDef HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd,
542
                                                       pPCD_DataOutStageCallbackTypeDef pCallback)
543
{
544
  HAL_StatusTypeDef status = HAL_OK;
545
 
546
  if (pCallback == NULL)
547
  {
548
    /* Update the error code */
549
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
550
 
551
    return HAL_ERROR;
552
  }
553
 
554
  /* Process locked */
555
  __HAL_LOCK(hpcd);
556
 
557
  if (hpcd->State == HAL_PCD_STATE_READY)
558
  {
559
    hpcd->DataOutStageCallback = pCallback;
560
  }
561
  else
562
  {
563
    /* Update the error code */
564
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
565
 
566
    /* Return error status */
567
    status =  HAL_ERROR;
568
  }
569
 
570
  /* Release Lock */
571
  __HAL_UNLOCK(hpcd);
572
 
573
  return status;
574
}
575
 
576
/**
577
  * @brief  Unregister the USB PCD Data OUT Stage Callback
578
  *         USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataOutStageCallback() predefined callback
579
  * @param  hpcd PCD handle
580
  * @retval HAL status
581
  */
582
HAL_StatusTypeDef HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd)
583
{
584
  HAL_StatusTypeDef status = HAL_OK;
585
 
586
  /* Process locked */
587
  __HAL_LOCK(hpcd);
588
 
589
  if (hpcd->State == HAL_PCD_STATE_READY)
590
  {
591
    hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback; /* Legacy weak DataOutStageCallback  */
592
  }
593
  else
594
  {
595
    /* Update the error code */
596
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
597
 
598
    /* Return error status */
599
    status =  HAL_ERROR;
600
  }
601
 
602
  /* Release Lock */
603
  __HAL_UNLOCK(hpcd);
604
 
605
  return status;
606
}
607
 
608
/**
609
  * @brief  Register USB PCD Data IN Stage Callback
610
  *         To be used instead of the weak HAL_PCD_DataInStageCallback() predefined callback
611
  * @param  hpcd PCD handle
612
  * @param  pCallback pointer to the USB PCD Data IN Stage Callback function
613
  * @retval HAL status
614
  */
615
HAL_StatusTypeDef HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef *hpcd,
616
                                                      pPCD_DataInStageCallbackTypeDef pCallback)
617
{
618
  HAL_StatusTypeDef status = HAL_OK;
619
 
620
  if (pCallback == NULL)
621
  {
622
    /* Update the error code */
623
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
624
 
625
    return HAL_ERROR;
626
  }
627
 
628
  /* Process locked */
629
  __HAL_LOCK(hpcd);
630
 
631
  if (hpcd->State == HAL_PCD_STATE_READY)
632
  {
633
    hpcd->DataInStageCallback = pCallback;
634
  }
635
  else
636
  {
637
    /* Update the error code */
638
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
639
 
640
    /* Return error status */
641
    status =  HAL_ERROR;
642
  }
643
 
644
  /* Release Lock */
645
  __HAL_UNLOCK(hpcd);
646
 
647
  return status;
648
}
649
 
650
/**
651
  * @brief  Unregister the USB PCD Data IN Stage Callback
652
  *         USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataInStageCallback() predefined callback
653
  * @param  hpcd PCD handle
654
  * @retval HAL status
655
  */
656
HAL_StatusTypeDef HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef *hpcd)
657
{
658
  HAL_StatusTypeDef status = HAL_OK;
659
 
660
  /* Process locked */
661
  __HAL_LOCK(hpcd);
662
 
663
  if (hpcd->State == HAL_PCD_STATE_READY)
664
  {
665
    hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback; /* Legacy weak DataInStageCallback  */
666
  }
667
  else
668
  {
669
    /* Update the error code */
670
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
671
 
672
    /* Return error status */
673
    status =  HAL_ERROR;
674
  }
675
 
676
  /* Release Lock */
677
  __HAL_UNLOCK(hpcd);
678
 
679
  return status;
680
}
681
 
682
/**
683
  * @brief  Register USB PCD Iso OUT incomplete Callback
684
  *         To be used instead of the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
685
  * @param  hpcd PCD handle
686
  * @param  pCallback pointer to the USB PCD Iso OUT incomplete Callback function
687
  * @retval HAL status
688
  */
689
HAL_StatusTypeDef HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd,
690
                                                       pPCD_IsoOutIncpltCallbackTypeDef pCallback)
691
{
692
  HAL_StatusTypeDef status = HAL_OK;
693
 
694
  if (pCallback == NULL)
695
  {
696
    /* Update the error code */
697
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
698
 
699
    return HAL_ERROR;
700
  }
701
 
702
  /* Process locked */
703
  __HAL_LOCK(hpcd);
704
 
705
  if (hpcd->State == HAL_PCD_STATE_READY)
706
  {
707
    hpcd->ISOOUTIncompleteCallback = pCallback;
708
  }
709
  else
710
  {
711
    /* Update the error code */
712
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
713
 
714
    /* Return error status */
715
    status =  HAL_ERROR;
716
  }
717
 
718
  /* Release Lock */
719
  __HAL_UNLOCK(hpcd);
720
 
721
  return status;
722
}
723
 
724
/**
725
  * @brief  Unregister the USB PCD Iso OUT incomplete Callback
726
  *         USB PCD Iso OUT incomplete Callback is redirected to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
727
  * @param  hpcd PCD handle
728
  * @retval HAL status
729
  */
730
HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd)
731
{
732
  HAL_StatusTypeDef status = HAL_OK;
733
 
734
  /* Process locked */
735
  __HAL_LOCK(hpcd);
736
 
737
  if (hpcd->State == HAL_PCD_STATE_READY)
738
  {
739
    hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback; /* Legacy weak ISOOUTIncompleteCallback  */
740
  }
741
  else
742
  {
743
    /* Update the error code */
744
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
745
 
746
    /* Return error status */
747
    status =  HAL_ERROR;
748
  }
749
 
750
  /* Release Lock */
751
  __HAL_UNLOCK(hpcd);
752
 
753
  return status;
754
}
755
 
756
/**
757
  * @brief  Register USB PCD Iso IN incomplete Callback
758
  *         To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
759
  * @param  hpcd PCD handle
760
  * @param  pCallback pointer to the USB PCD Iso IN incomplete Callback function
761
  * @retval HAL status
762
  */
763
HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd,
764
                                                      pPCD_IsoInIncpltCallbackTypeDef pCallback)
765
{
766
  HAL_StatusTypeDef status = HAL_OK;
767
 
768
  if (pCallback == NULL)
769
  {
770
    /* Update the error code */
771
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
772
 
773
    return HAL_ERROR;
774
  }
775
 
776
  /* Process locked */
777
  __HAL_LOCK(hpcd);
778
 
779
  if (hpcd->State == HAL_PCD_STATE_READY)
780
  {
781
    hpcd->ISOINIncompleteCallback = pCallback;
782
  }
783
  else
784
  {
785
    /* Update the error code */
786
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
787
 
788
    /* Return error status */
789
    status =  HAL_ERROR;
790
  }
791
 
792
  /* Release Lock */
793
  __HAL_UNLOCK(hpcd);
794
 
795
  return status;
796
}
797
 
798
/**
799
  * @brief  Unregister the USB PCD Iso IN incomplete Callback
800
  *         USB PCD Iso IN incomplete Callback is redirected to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
801
  * @param  hpcd PCD handle
802
  * @retval HAL status
803
  */
804
HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd)
805
{
806
  HAL_StatusTypeDef status = HAL_OK;
807
 
808
  /* Process locked */
809
  __HAL_LOCK(hpcd);
810
 
811
  if (hpcd->State == HAL_PCD_STATE_READY)
812
  {
813
    hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback; /* Legacy weak ISOINIncompleteCallback  */
814
  }
815
  else
816
  {
817
    /* Update the error code */
818
    hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
819
 
820
    /* Return error status */
821
    status =  HAL_ERROR;
822
  }
823
 
824
  /* Release Lock */
825
  __HAL_UNLOCK(hpcd);
826
 
827
  return status;
828
}
829
 
830
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
831
 
832
/**
2 mjames 833
  * @}
834
  */
835
 
9 mjames 836
/** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
837
  *  @brief   Data transfers functions
838
  *
2 mjames 839
@verbatim
840
 ===============================================================================
841
                      ##### IO operation functions #####
842
 ===============================================================================
843
    [..]
9 mjames 844
    This subsection provides a set of functions allowing to manage the PCD data
2 mjames 845
    transfers.
846
 
847
@endverbatim
848
  * @{
849
  */
850
 
851
/**
9 mjames 852
  * @brief  Start the USB device
853
  * @param  hpcd PCD handle
2 mjames 854
  * @retval HAL status
855
  */
856
HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
857
{
858
  __HAL_LOCK(hpcd);
859
  __HAL_PCD_ENABLE(hpcd);
9 mjames 860
 
861
#if defined (USB)
862
  HAL_PCDEx_SetConnectionState(hpcd, 1U);
863
#endif /* defined (USB) */
864
 
865
  (void)USB_DevConnect(hpcd->Instance);
2 mjames 866
  __HAL_UNLOCK(hpcd);
9 mjames 867
 
2 mjames 868
  return HAL_OK;
869
}
870
 
871
/**
9 mjames 872
  * @brief  Stop the USB device.
873
  * @param  hpcd PCD handle
2 mjames 874
  * @retval HAL status
875
  */
876
HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
877
{
878
  __HAL_LOCK(hpcd);
879
  __HAL_PCD_DISABLE(hpcd);
9 mjames 880
 
881
#if defined (USB)
882
  HAL_PCDEx_SetConnectionState(hpcd, 0U);
883
#endif /* defined (USB) */
884
 
885
  (void)USB_DevDisconnect(hpcd->Instance);
886
 
887
#if defined (USB_OTG_FS)
888
  (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
889
#endif /* defined (USB_OTG_FS) */
890
 
2 mjames 891
  __HAL_UNLOCK(hpcd);
9 mjames 892
 
2 mjames 893
  return HAL_OK;
894
}
895
 
896
#if defined (USB_OTG_FS)
897
/**
9 mjames 898
  * @brief  Handles PCD interrupt request.
899
  * @param  hpcd PCD handle
2 mjames 900
  * @retval HAL status
901
  */
902
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
903
{
904
  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
9 mjames 905
  uint32_t USBx_BASE = (uint32_t)USBx;
906
  uint32_t i, ep_intr, epint, epnum;
907
  uint32_t fifoemptymsk, temp;
908
  USB_OTG_EPTypeDef *ep;
909
 
2 mjames 910
  /* ensure that we are in device mode */
911
  if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
912
  {
913
    /* avoid spurious interrupt */
9 mjames 914
    if (__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
2 mjames 915
    {
916
      return;
917
    }
9 mjames 918
 
919
    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
2 mjames 920
    {
9 mjames 921
      /* incorrect mode, acknowledge the interrupt */
2 mjames 922
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
923
    }
9 mjames 924
 
925
    /* Handle RxQLevel Interrupt */
926
    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
2 mjames 927
    {
9 mjames 928
      USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
929
 
930
      temp = USBx->GRXSTSP;
931
 
932
      ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
933
 
934
      if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_DATA_UPDT)
935
      {
936
        if ((temp & USB_OTG_GRXSTSP_BCNT) != 0U)
937
        {
938
          (void)USB_ReadPacket(USBx, ep->xfer_buff,
939
                               (uint16_t)((temp & USB_OTG_GRXSTSP_BCNT) >> 4));
940
 
941
          ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
942
          ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
943
        }
944
      }
945
      else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_SETUP_UPDT)
946
      {
947
        (void)USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
948
        ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
949
      }
950
      else
951
      {
952
        /* ... */
953
      }
954
      USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
955
    }
956
 
957
    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
958
    {
2 mjames 959
      epnum = 0U;
9 mjames 960
 
2 mjames 961
      /* Read in the device interrupt bits */
962
      ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
9 mjames 963
 
964
      while (ep_intr != 0U)
2 mjames 965
      {
9 mjames 966
        if ((ep_intr & 0x1U) != 0U)
2 mjames 967
        {
9 mjames 968
          epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, (uint8_t)epnum);
969
 
970
          if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
2 mjames 971
          {
972
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
9 mjames 973
            (void)PCD_EP_OutXfrComplete_int(hpcd, epnum);
2 mjames 974
          }
9 mjames 975
 
976
          if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
2 mjames 977
          {
978
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
9 mjames 979
            /* Class B setup phase done for previous decoded setup */
980
            (void)PCD_EP_OutSetupPacket_int(hpcd, epnum);
2 mjames 981
          }
9 mjames 982
 
983
          if ((epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
2 mjames 984
          {
985
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
986
          }
9 mjames 987
 
988
          /* Clear Status Phase Received interrupt */
989
          if ((epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
990
          {
991
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
992
          }
993
 
994
          /* Clear OUT NAK interrupt */
995
          if ((epint & USB_OTG_DOEPINT_NAK) == USB_OTG_DOEPINT_NAK)
996
          {
997
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_NAK);
998
          }
2 mjames 999
        }
1000
        epnum++;
1001
        ep_intr >>= 1U;
1002
      }
1003
    }
9 mjames 1004
 
1005
    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
2 mjames 1006
    {
1007
      /* Read in the device interrupt bits */
1008
      ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
9 mjames 1009
 
2 mjames 1010
      epnum = 0U;
9 mjames 1011
 
1012
      while (ep_intr != 0U)
2 mjames 1013
      {
9 mjames 1014
        if ((ep_intr & 0x1U) != 0U) /* In ITR */
2 mjames 1015
        {
9 mjames 1016
          epint = USB_ReadDevInEPInterrupt(hpcd->Instance, (uint8_t)epnum);
2 mjames 1017
 
9 mjames 1018
          if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
2 mjames 1019
          {
9 mjames 1020
            fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
2 mjames 1021
            USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
9 mjames 1022
 
2 mjames 1023
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
9 mjames 1024
 
1025
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1026
            hpcd->DataInStageCallback(hpcd, (uint8_t)epnum);
1027
#else
1028
            HAL_PCD_DataInStageCallback(hpcd, (uint8_t)epnum);
1029
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2 mjames 1030
          }
9 mjames 1031
          if ((epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
2 mjames 1032
          {
1033
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
1034
          }
9 mjames 1035
          if ((epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
2 mjames 1036
          {
1037
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
1038
          }
9 mjames 1039
          if ((epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
2 mjames 1040
          {
1041
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
1042
          }
9 mjames 1043
          if ((epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
2 mjames 1044
          {
1045
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
1046
          }
9 mjames 1047
          if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
2 mjames 1048
          {
9 mjames 1049
            (void)PCD_WriteEmptyTxFifo(hpcd, epnum);
2 mjames 1050
          }
1051
        }
1052
        epnum++;
1053
        ep_intr >>= 1U;
1054
      }
1055
    }
9 mjames 1056
 
2 mjames 1057
    /* Handle Resume Interrupt */
9 mjames 1058
    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
2 mjames 1059
    {
9 mjames 1060
      /* Clear the Remote Wake-up Signaling */
2 mjames 1061
      USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
9 mjames 1062
 
1063
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1064
      hpcd->ResumeCallback(hpcd);
1065
#else
1066
      HAL_PCD_ResumeCallback(hpcd);
1067
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1068
 
1069
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
2 mjames 1070
    }
9 mjames 1071
 
2 mjames 1072
    /* Handle Suspend Interrupt */
9 mjames 1073
    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
2 mjames 1074
    {
9 mjames 1075
      if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
2 mjames 1076
      {
9 mjames 1077
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1078
        hpcd->SuspendCallback(hpcd);
1079
#else
2 mjames 1080
        HAL_PCD_SuspendCallback(hpcd);
9 mjames 1081
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2 mjames 1082
      }
1083
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
1084
    }
1085
    /* Handle Reset Interrupt */
9 mjames 1086
    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
2 mjames 1087
    {
9 mjames 1088
      USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
1089
      (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
1090
 
1091
      for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
2 mjames 1092
      {
9 mjames 1093
        USBx_INEP(i)->DIEPINT = 0xFB7FU;
1094
        USBx_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
1095
        USBx_INEP(i)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
1096
        USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
1097
        USBx_OUTEP(i)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
1098
        USBx_OUTEP(i)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
2 mjames 1099
      }
1100
      USBx_DEVICE->DAINTMSK |= 0x10001U;
9 mjames 1101
 
1102
      if (hpcd->Init.use_dedicated_ep1 != 0U)
1103
      {
1104
        USBx_DEVICE->DOUTEP1MSK |= USB_OTG_DOEPMSK_STUPM |
1105
                                   USB_OTG_DOEPMSK_XFRCM |
1106
                                   USB_OTG_DOEPMSK_EPDM;
1107
 
1108
        USBx_DEVICE->DINEP1MSK |= USB_OTG_DIEPMSK_TOM |
1109
                                  USB_OTG_DIEPMSK_XFRCM |
1110
                                  USB_OTG_DIEPMSK_EPDM;
1111
      }
1112
      else
1113
      {
1114
        USBx_DEVICE->DOEPMSK |= USB_OTG_DOEPMSK_STUPM |
1115
                                USB_OTG_DOEPMSK_XFRCM |
1116
                                USB_OTG_DOEPMSK_EPDM |
1117
                                USB_OTG_DOEPMSK_OTEPSPRM |
1118
                                USB_OTG_DOEPMSK_NAKM;
1119
 
1120
        USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_TOM |
1121
                                USB_OTG_DIEPMSK_XFRCM |
1122
                                USB_OTG_DIEPMSK_EPDM;
1123
      }
1124
 
2 mjames 1125
      /* Set Default Address to 0 */
1126
      USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
9 mjames 1127
 
2 mjames 1128
      /* setup EP0 to receive SETUP packets */
9 mjames 1129
      (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
1130
 
2 mjames 1131
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
1132
    }
9 mjames 1133
 
2 mjames 1134
    /* Handle Enumeration done Interrupt */
9 mjames 1135
    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
2 mjames 1136
    {
9 mjames 1137
      (void)USB_ActivateSetup(hpcd->Instance);
1138
      hpcd->Init.speed = USB_GetDevSpeed(hpcd->Instance);
1139
 
1140
      /* Set USB Turnaround time */
1141
      (void)USB_SetTurnaroundTime(hpcd->Instance,
1142
                                  HAL_RCC_GetHCLKFreq(),
1143
                                  (uint8_t)hpcd->Init.speed);
1144
 
1145
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1146
      hpcd->ResetCallback(hpcd);
1147
#else
2 mjames 1148
      HAL_PCD_ResetCallback(hpcd);
9 mjames 1149
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1150
 
2 mjames 1151
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
1152
    }
1153
 
1154
    /* Handle SOF Interrupt */
9 mjames 1155
    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
2 mjames 1156
    {
9 mjames 1157
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1158
      hpcd->SOFCallback(hpcd);
1159
#else
2 mjames 1160
      HAL_PCD_SOFCallback(hpcd);
9 mjames 1161
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1162
 
2 mjames 1163
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
1164
    }
9 mjames 1165
 
2 mjames 1166
    /* Handle Incomplete ISO IN Interrupt */
9 mjames 1167
    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
2 mjames 1168
    {
9 mjames 1169
      /* Keep application checking the corresponding Iso IN endpoint
1170
      causing the incomplete Interrupt */
1171
      epnum = 0U;
1172
 
1173
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1174
      hpcd->ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
1175
#else
1176
      HAL_PCD_ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
1177
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1178
 
2 mjames 1179
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
1180
    }
9 mjames 1181
 
2 mjames 1182
    /* Handle Incomplete ISO OUT Interrupt */
9 mjames 1183
    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
2 mjames 1184
    {
9 mjames 1185
      /* Keep application checking the corresponding Iso OUT endpoint
1186
      causing the incomplete Interrupt */
1187
      epnum = 0U;
1188
 
1189
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1190
      hpcd->ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
1191
#else
1192
      HAL_PCD_ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
1193
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1194
 
2 mjames 1195
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
1196
    }
9 mjames 1197
 
2 mjames 1198
    /* Handle Connection event Interrupt */
9 mjames 1199
    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
2 mjames 1200
    {
9 mjames 1201
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1202
      hpcd->ConnectCallback(hpcd);
1203
#else
2 mjames 1204
      HAL_PCD_ConnectCallback(hpcd);
9 mjames 1205
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1206
 
2 mjames 1207
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
1208
    }
9 mjames 1209
 
2 mjames 1210
    /* Handle Disconnection event Interrupt */
9 mjames 1211
    if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
2 mjames 1212
    {
1213
      temp = hpcd->Instance->GOTGINT;
9 mjames 1214
 
1215
      if ((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
2 mjames 1216
      {
9 mjames 1217
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1218
        hpcd->DisconnectCallback(hpcd);
1219
#else
2 mjames 1220
        HAL_PCD_DisconnectCallback(hpcd);
9 mjames 1221
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2 mjames 1222
      }
1223
      hpcd->Instance->GOTGINT |= temp;
1224
    }
1225
  }
1226
}
1227
 
9 mjames 1228
 
1229
/**
1230
  * @brief  Handles PCD Wakeup interrupt request.
1231
  * @param  hpcd PCD handle
1232
  * @retval HAL status
1233
  */
1234
void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd)
1235
{
1236
  /* Clear EXTI pending Bit */
1237
  __HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG();
1238
}
1239
#endif /* defined (USB_OTG_FS) */
1240
 
2 mjames 1241
#if defined (USB)
1242
/**
1243
  * @brief  This function handles PCD interrupt request.
9 mjames 1244
  * @param  hpcd PCD handle
2 mjames 1245
  * @retval HAL status
1246
  */
1247
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
9 mjames 1248
{
1249
  uint16_t store_ep[8];
1250
  uint8_t i;
1251
 
1252
  if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_CTR))
2 mjames 1253
  {
1254
    /* servicing of the endpoint correct transfer interrupt */
1255
    /* clear of the CTR flag into the sub */
9 mjames 1256
    (void)PCD_EP_ISR_Handler(hpcd);
2 mjames 1257
  }
1258
 
9 mjames 1259
  if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_RESET))
2 mjames 1260
  {
1261
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
9 mjames 1262
 
1263
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1264
    hpcd->ResetCallback(hpcd);
1265
#else
2 mjames 1266
    HAL_PCD_ResetCallback(hpcd);
9 mjames 1267
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1268
 
1269
    (void)HAL_PCD_SetAddress(hpcd, 0U);
2 mjames 1270
  }
1271
 
9 mjames 1272
  if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_PMAOVR))
2 mjames 1273
  {
9 mjames 1274
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);
2 mjames 1275
  }
9 mjames 1276
 
1277
  if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_ERR))
2 mjames 1278
  {
9 mjames 1279
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR);
2 mjames 1280
  }
1281
 
9 mjames 1282
  if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_WKUP))
2 mjames 1283
  {
9 mjames 1284
    hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_LP_MODE);
1285
    hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_FSUSP);
1286
 
1287
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1288
    hpcd->ResumeCallback(hpcd);
1289
#else
2 mjames 1290
    HAL_PCD_ResumeCallback(hpcd);
9 mjames 1291
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2 mjames 1292
 
9 mjames 1293
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);
2 mjames 1294
  }
1295
 
9 mjames 1296
  if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_SUSP))
1297
  {
1298
    /* WA: To Clear Wakeup flag if raised with suspend signal */
1299
 
1300
    /* Store Endpoint register */
1301
    for (i = 0U; i < 8U; i++)
1302
    {
1303
      store_ep[i] = PCD_GET_ENDPOINT(hpcd->Instance, i);
1304
    }
1305
 
1306
    /* FORCE RESET */
1307
    hpcd->Instance->CNTR |= (uint16_t)(USB_CNTR_FRES);
1308
 
1309
    /* CLEAR RESET */
1310
    hpcd->Instance->CNTR &= (uint16_t)(~USB_CNTR_FRES);
1311
 
1312
    /* wait for reset flag in ISTR */
1313
    while ((hpcd->Instance->ISTR & USB_ISTR_RESET) == 0U)
1314
    {
1315
    }
1316
 
1317
    /* Clear Reset Flag */
1318
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
1319
 
1320
    /* Restore Registre */
1321
    for (i = 0U; i < 8U; i++)
1322
    {
1323
      PCD_SET_ENDPOINT(hpcd->Instance, i, store_ep[i]);
1324
    }
1325
 
2 mjames 1326
    /* Force low-power mode in the macrocell */
9 mjames 1327
    hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_FSUSP;
1328
 
2 mjames 1329
    /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
9 mjames 1330
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);
2 mjames 1331
 
9 mjames 1332
    hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_LP_MODE;
1333
 
1334
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1335
    hpcd->SuspendCallback(hpcd);
1336
#else
1337
    HAL_PCD_SuspendCallback(hpcd);
1338
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2 mjames 1339
  }
1340
 
9 mjames 1341
  if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_SOF))
2 mjames 1342
  {
9 mjames 1343
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);
1344
 
1345
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1346
    hpcd->SOFCallback(hpcd);
1347
#else
2 mjames 1348
    HAL_PCD_SOFCallback(hpcd);
9 mjames 1349
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2 mjames 1350
  }
1351
 
9 mjames 1352
  if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_ESOF))
2 mjames 1353
  {
1354
    /* clear ESOF flag in ISTR */
9 mjames 1355
    __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);
2 mjames 1356
  }
1357
}
1358
 
9 mjames 1359
 
2 mjames 1360
/**
9 mjames 1361
  * @brief  Handles PCD Wakeup interrupt request.
1362
  * @param  hpcd PCD handle
1363
  * @retval HAL status
1364
  */
1365
void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd)
1366
{
1367
  /* Clear EXTI pending Bit */
1368
  __HAL_USB_WAKEUP_EXTI_CLEAR_FLAG();
1369
}
1370
#endif /* defined (USB) */
1371
 
1372
/**
1373
  * @brief  Data OUT stage callback.
1374
  * @param  hpcd PCD handle
1375
  * @param  epnum endpoint number
2 mjames 1376
  * @retval None
1377
  */
9 mjames 1378
__weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
2 mjames 1379
{
1380
  /* Prevent unused argument(s) compilation warning */
1381
  UNUSED(hpcd);
1382
  UNUSED(epnum);
9 mjames 1383
 
2 mjames 1384
  /* NOTE : This function should not be modified, when the callback is needed,
1385
            the HAL_PCD_DataOutStageCallback could be implemented in the user file
1386
   */
1387
}
1388
 
1389
/**
9 mjames 1390
  * @brief  Data IN stage callback
1391
  * @param  hpcd PCD handle
1392
  * @param  epnum endpoint number
2 mjames 1393
  * @retval None
1394
  */
9 mjames 1395
__weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
2 mjames 1396
{
1397
  /* Prevent unused argument(s) compilation warning */
1398
  UNUSED(hpcd);
1399
  UNUSED(epnum);
9 mjames 1400
 
2 mjames 1401
  /* NOTE : This function should not be modified, when the callback is needed,
1402
            the HAL_PCD_DataInStageCallback could be implemented in the user file
1403
   */
1404
}
1405
/**
1406
  * @brief  Setup stage callback
9 mjames 1407
  * @param  hpcd PCD handle
2 mjames 1408
  * @retval None
1409
  */
9 mjames 1410
__weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
2 mjames 1411
{
1412
  /* Prevent unused argument(s) compilation warning */
1413
  UNUSED(hpcd);
9 mjames 1414
 
2 mjames 1415
  /* NOTE : This function should not be modified, when the callback is needed,
1416
            the HAL_PCD_SetupStageCallback could be implemented in the user file
1417
   */
1418
}
1419
 
1420
/**
9 mjames 1421
  * @brief  USB Start Of Frame callback.
1422
  * @param  hpcd PCD handle
2 mjames 1423
  * @retval None
1424
  */
9 mjames 1425
__weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
2 mjames 1426
{
1427
  /* Prevent unused argument(s) compilation warning */
1428
  UNUSED(hpcd);
9 mjames 1429
 
2 mjames 1430
  /* NOTE : This function should not be modified, when the callback is needed,
1431
            the HAL_PCD_SOFCallback could be implemented in the user file
1432
   */
1433
}
1434
 
1435
/**
9 mjames 1436
  * @brief  USB Reset callback.
1437
  * @param  hpcd PCD handle
2 mjames 1438
  * @retval None
1439
  */
9 mjames 1440
__weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
2 mjames 1441
{
1442
  /* Prevent unused argument(s) compilation warning */
1443
  UNUSED(hpcd);
9 mjames 1444
 
2 mjames 1445
  /* NOTE : This function should not be modified, when the callback is needed,
1446
            the HAL_PCD_ResetCallback could be implemented in the user file
1447
   */
1448
}
1449
 
1450
/**
9 mjames 1451
  * @brief  Suspend event callback.
1452
  * @param  hpcd PCD handle
2 mjames 1453
  * @retval None
1454
  */
9 mjames 1455
__weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
2 mjames 1456
{
1457
  /* Prevent unused argument(s) compilation warning */
1458
  UNUSED(hpcd);
9 mjames 1459
 
2 mjames 1460
  /* NOTE : This function should not be modified, when the callback is needed,
1461
            the HAL_PCD_SuspendCallback could be implemented in the user file
1462
   */
1463
}
1464
 
1465
/**
9 mjames 1466
  * @brief  Resume event callback.
1467
  * @param  hpcd PCD handle
2 mjames 1468
  * @retval None
1469
  */
9 mjames 1470
__weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
2 mjames 1471
{
1472
  /* Prevent unused argument(s) compilation warning */
1473
  UNUSED(hpcd);
9 mjames 1474
 
2 mjames 1475
  /* NOTE : This function should not be modified, when the callback is needed,
1476
            the HAL_PCD_ResumeCallback could be implemented in the user file
1477
   */
1478
}
1479
 
1480
/**
9 mjames 1481
  * @brief  Incomplete ISO OUT callback.
1482
  * @param  hpcd PCD handle
1483
  * @param  epnum endpoint number
2 mjames 1484
  * @retval None
1485
  */
9 mjames 1486
__weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
2 mjames 1487
{
1488
  /* Prevent unused argument(s) compilation warning */
1489
  UNUSED(hpcd);
1490
  UNUSED(epnum);
9 mjames 1491
 
2 mjames 1492
  /* NOTE : This function should not be modified, when the callback is needed,
1493
            the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
1494
   */
1495
}
1496
 
1497
/**
9 mjames 1498
  * @brief  Incomplete ISO IN callback.
1499
  * @param  hpcd PCD handle
1500
  * @param  epnum endpoint number
2 mjames 1501
  * @retval None
1502
  */
9 mjames 1503
__weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
2 mjames 1504
{
1505
  /* Prevent unused argument(s) compilation warning */
1506
  UNUSED(hpcd);
1507
  UNUSED(epnum);
9 mjames 1508
 
2 mjames 1509
  /* NOTE : This function should not be modified, when the callback is needed,
1510
            the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
1511
   */
1512
}
1513
 
1514
/**
9 mjames 1515
  * @brief  Connection event callback.
1516
  * @param  hpcd PCD handle
2 mjames 1517
  * @retval None
1518
  */
9 mjames 1519
__weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
2 mjames 1520
{
1521
  /* Prevent unused argument(s) compilation warning */
1522
  UNUSED(hpcd);
9 mjames 1523
 
2 mjames 1524
  /* NOTE : This function should not be modified, when the callback is needed,
1525
            the HAL_PCD_ConnectCallback could be implemented in the user file
1526
   */
1527
}
1528
 
1529
/**
9 mjames 1530
  * @brief  Disconnection event callback.
1531
  * @param  hpcd PCD handle
2 mjames 1532
  * @retval None
1533
  */
9 mjames 1534
__weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
2 mjames 1535
{
1536
  /* Prevent unused argument(s) compilation warning */
1537
  UNUSED(hpcd);
9 mjames 1538
 
2 mjames 1539
  /* NOTE : This function should not be modified, when the callback is needed,
1540
            the HAL_PCD_DisconnectCallback could be implemented in the user file
1541
   */
1542
}
1543
 
1544
/**
1545
  * @}
1546
  */
1547
 
1548
/** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
9 mjames 1549
  *  @brief   management functions
1550
  *
2 mjames 1551
@verbatim
1552
 ===============================================================================
1553
                      ##### Peripheral Control functions #####
9 mjames 1554
 ===============================================================================
2 mjames 1555
    [..]
9 mjames 1556
    This subsection provides a set of functions allowing to control the PCD data
2 mjames 1557
    transfers.
1558
 
1559
@endverbatim
1560
  * @{
1561
  */
1562
 
1563
/**
1564
  * @brief  Connect the USB device
9 mjames 1565
  * @param  hpcd PCD handle
2 mjames 1566
  * @retval HAL status
1567
  */
1568
HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
1569
{
1570
  __HAL_LOCK(hpcd);
9 mjames 1571
 
1572
#if defined (USB)
1573
  HAL_PCDEx_SetConnectionState(hpcd, 1U);
1574
#endif /* defined (USB) */
1575
 
1576
  (void)USB_DevConnect(hpcd->Instance);
2 mjames 1577
  __HAL_UNLOCK(hpcd);
9 mjames 1578
 
2 mjames 1579
  return HAL_OK;
1580
}
1581
 
1582
/**
9 mjames 1583
  * @brief  Disconnect the USB device.
1584
  * @param  hpcd PCD handle
2 mjames 1585
  * @retval HAL status
1586
  */
1587
HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
1588
{
1589
  __HAL_LOCK(hpcd);
9 mjames 1590
 
1591
#if defined (USB)
1592
  HAL_PCDEx_SetConnectionState(hpcd, 0U);
1593
#endif /* defined (USB) */
1594
 
1595
  (void)USB_DevDisconnect(hpcd->Instance);
2 mjames 1596
  __HAL_UNLOCK(hpcd);
9 mjames 1597
 
2 mjames 1598
  return HAL_OK;
1599
}
1600
 
1601
/**
9 mjames 1602
  * @brief  Set the USB Device address.
1603
  * @param  hpcd PCD handle
1604
  * @param  address new device address
2 mjames 1605
  * @retval HAL status
1606
  */
1607
HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
1608
{
1609
  __HAL_LOCK(hpcd);
1610
  hpcd->USB_Address = address;
9 mjames 1611
  (void)USB_SetDevAddress(hpcd->Instance, address);
2 mjames 1612
  __HAL_UNLOCK(hpcd);
9 mjames 1613
 
2 mjames 1614
  return HAL_OK;
1615
}
1616
/**
9 mjames 1617
  * @brief  Open and configure an endpoint.
1618
  * @param  hpcd PCD handle
1619
  * @param  ep_addr endpoint address
1620
  * @param  ep_mps endpoint max packet size
1621
  * @param  ep_type endpoint type
2 mjames 1622
  * @retval HAL status
1623
  */
9 mjames 1624
HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
1625
                                  uint16_t ep_mps, uint8_t ep_type)
2 mjames 1626
{
1627
  HAL_StatusTypeDef  ret = HAL_OK;
9 mjames 1628
  PCD_EPTypeDef *ep;
1629
 
2 mjames 1630
  if ((ep_addr & 0x80U) == 0x80U)
1631
  {
9 mjames 1632
    ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1633
    ep->is_in = 1U;
2 mjames 1634
  }
1635
  else
1636
  {
9 mjames 1637
    ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1638
    ep->is_in = 0U;
2 mjames 1639
  }
9 mjames 1640
 
1641
  ep->num = ep_addr & EP_ADDR_MSK;
2 mjames 1642
  ep->maxpacket = ep_mps;
1643
  ep->type = ep_type;
9 mjames 1644
 
1645
  if (ep->is_in != 0U)
1646
  {
1647
    /* Assign a Tx FIFO */
1648
    ep->tx_fifo_num = ep->num;
1649
  }
1650
  /* Set initial data PID. */
1651
  if (ep_type == EP_TYPE_BULK)
1652
  {
1653
    ep->data_pid_start = 0U;
1654
  }
1655
 
2 mjames 1656
  __HAL_LOCK(hpcd);
9 mjames 1657
  (void)USB_ActivateEndpoint(hpcd->Instance, ep);
2 mjames 1658
  __HAL_UNLOCK(hpcd);
9 mjames 1659
 
2 mjames 1660
  return ret;
1661
}
1662
 
1663
/**
9 mjames 1664
  * @brief  Deactivate an endpoint.
1665
  * @param  hpcd PCD handle
1666
  * @param  ep_addr endpoint address
2 mjames 1667
  * @retval HAL status
1668
  */
1669
HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
9 mjames 1670
{
1671
  PCD_EPTypeDef *ep;
1672
 
2 mjames 1673
  if ((ep_addr & 0x80U) == 0x80U)
1674
  {
9 mjames 1675
    ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1676
    ep->is_in = 1U;
2 mjames 1677
  }
1678
  else
1679
  {
9 mjames 1680
    ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1681
    ep->is_in = 0U;
2 mjames 1682
  }
9 mjames 1683
  ep->num   = ep_addr & EP_ADDR_MSK;
1684
 
2 mjames 1685
  __HAL_LOCK(hpcd);
9 mjames 1686
  (void)USB_DeactivateEndpoint(hpcd->Instance, ep);
2 mjames 1687
  __HAL_UNLOCK(hpcd);
1688
  return HAL_OK;
1689
}
1690
 
1691
 
1692
/**
9 mjames 1693
  * @brief  Receive an amount of data.
1694
  * @param  hpcd PCD handle
1695
  * @param  ep_addr endpoint address
1696
  * @param  pBuf pointer to the reception buffer
1697
  * @param  len amount of data to be received
2 mjames 1698
  * @retval HAL status
1699
  */
1700
HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
1701
{
9 mjames 1702
  PCD_EPTypeDef *ep;
1703
 
1704
  ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1705
 
2 mjames 1706
  /*setup and start the Xfer */
9 mjames 1707
  ep->xfer_buff = pBuf;
2 mjames 1708
  ep->xfer_len = len;
1709
  ep->xfer_count = 0U;
1710
  ep->is_in = 0U;
9 mjames 1711
  ep->num = ep_addr & EP_ADDR_MSK;
2 mjames 1712
 
9 mjames 1713
  if ((ep_addr & EP_ADDR_MSK) == 0U)
2 mjames 1714
  {
9 mjames 1715
    (void)USB_EP0StartXfer(hpcd->Instance, ep);
2 mjames 1716
  }
1717
  else
1718
  {
9 mjames 1719
    (void)USB_EPStartXfer(hpcd->Instance, ep);
2 mjames 1720
  }
1721
 
1722
  return HAL_OK;
1723
}
1724
 
1725
/**
1726
  * @brief  Get Received Data Size
9 mjames 1727
  * @param  hpcd PCD handle
1728
  * @param  ep_addr endpoint address
2 mjames 1729
  * @retval Data Size
1730
  */
9 mjames 1731
uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
2 mjames 1732
{
9 mjames 1733
  return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].xfer_count;
2 mjames 1734
}
1735
/**
1736
  * @brief  Send an amount of data
9 mjames 1737
  * @param  hpcd PCD handle
1738
  * @param  ep_addr endpoint address
1739
  * @param  pBuf pointer to the transmission buffer
1740
  * @param  len amount of data to be sent
2 mjames 1741
  * @retval HAL status
1742
  */
1743
HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
1744
{
9 mjames 1745
  PCD_EPTypeDef *ep;
1746
 
1747
  ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1748
 
2 mjames 1749
  /*setup and start the Xfer */
9 mjames 1750
  ep->xfer_buff = pBuf;
2 mjames 1751
  ep->xfer_len = len;
9 mjames 1752
#if defined (USB)
1753
  ep->xfer_fill_db = 1U;
1754
  ep->xfer_len_db = len;
1755
#endif /* defined (USB) */
2 mjames 1756
  ep->xfer_count = 0U;
1757
  ep->is_in = 1U;
9 mjames 1758
  ep->num = ep_addr & EP_ADDR_MSK;
2 mjames 1759
 
9 mjames 1760
  if ((ep_addr & EP_ADDR_MSK) == 0U)
2 mjames 1761
  {
9 mjames 1762
    (void)USB_EP0StartXfer(hpcd->Instance, ep);
2 mjames 1763
  }
1764
  else
1765
  {
9 mjames 1766
    (void)USB_EPStartXfer(hpcd->Instance, ep);
2 mjames 1767
  }
1768
 
1769
  return HAL_OK;
1770
}
1771
 
1772
/**
1773
  * @brief  Set a STALL condition over an endpoint
9 mjames 1774
  * @param  hpcd PCD handle
1775
  * @param  ep_addr endpoint address
2 mjames 1776
  * @retval HAL status
1777
  */
1778
HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1779
{
9 mjames 1780
  PCD_EPTypeDef *ep;
1781
 
1782
  if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints)
1783
  {
1784
    return HAL_ERROR;
1785
  }
1786
 
2 mjames 1787
  if ((0x80U & ep_addr) == 0x80U)
1788
  {
9 mjames 1789
    ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1790
    ep->is_in = 1U;
2 mjames 1791
  }
1792
  else
1793
  {
1794
    ep = &hpcd->OUT_ep[ep_addr];
9 mjames 1795
    ep->is_in = 0U;
2 mjames 1796
  }
9 mjames 1797
 
2 mjames 1798
  ep->is_stall = 1U;
9 mjames 1799
  ep->num = ep_addr & EP_ADDR_MSK;
1800
 
2 mjames 1801
  __HAL_LOCK(hpcd);
9 mjames 1802
 
1803
  (void)USB_EPSetStall(hpcd->Instance, ep);
1804
 
1805
  if ((ep_addr & EP_ADDR_MSK) == 0U)
2 mjames 1806
  {
9 mjames 1807
    (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
2 mjames 1808
  }
9 mjames 1809
 
1810
  __HAL_UNLOCK(hpcd);
1811
 
2 mjames 1812
  return HAL_OK;
1813
}
1814
 
1815
/**
1816
  * @brief  Clear a STALL condition over in an endpoint
9 mjames 1817
  * @param  hpcd PCD handle
1818
  * @param  ep_addr endpoint address
2 mjames 1819
  * @retval HAL status
1820
  */
1821
HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1822
{
9 mjames 1823
  PCD_EPTypeDef *ep;
1824
 
1825
  if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints)
1826
  {
1827
    return HAL_ERROR;
1828
  }
1829
 
2 mjames 1830
  if ((0x80U & ep_addr) == 0x80U)
1831
  {
9 mjames 1832
    ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1833
    ep->is_in = 1U;
2 mjames 1834
  }
1835
  else
1836
  {
9 mjames 1837
    ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1838
    ep->is_in = 0U;
2 mjames 1839
  }
9 mjames 1840
 
2 mjames 1841
  ep->is_stall = 0U;
9 mjames 1842
  ep->num = ep_addr & EP_ADDR_MSK;
1843
 
1844
  __HAL_LOCK(hpcd);
1845
  (void)USB_EPClearStall(hpcd->Instance, ep);
1846
  __HAL_UNLOCK(hpcd);
1847
 
2 mjames 1848
  return HAL_OK;
1849
}
1850
 
1851
/**
1852
  * @brief  Flush an endpoint
9 mjames 1853
  * @param  hpcd PCD handle
1854
  * @param  ep_addr endpoint address
2 mjames 1855
  * @retval HAL status
1856
  */
1857
HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1858
{
1859
  __HAL_LOCK(hpcd);
9 mjames 1860
 
2 mjames 1861
  if ((ep_addr & 0x80U) == 0x80U)
1862
  {
9 mjames 1863
    (void)USB_FlushTxFifo(hpcd->Instance, (uint32_t)ep_addr & EP_ADDR_MSK);
2 mjames 1864
  }
1865
  else
1866
  {
9 mjames 1867
    (void)USB_FlushRxFifo(hpcd->Instance);
2 mjames 1868
  }
9 mjames 1869
 
1870
  __HAL_UNLOCK(hpcd);
1871
 
2 mjames 1872
  return HAL_OK;
1873
}
1874
 
1875
/**
9 mjames 1876
  * @brief  Activate remote wakeup signalling
1877
  * @param  hpcd PCD handle
2 mjames 1878
  * @retval HAL status
1879
  */
1880
HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1881
{
9 mjames 1882
  return (USB_ActivateRemoteWakeup(hpcd->Instance));
2 mjames 1883
}
1884
 
1885
/**
9 mjames 1886
  * @brief  De-activate remote wakeup signalling.
1887
  * @param  hpcd PCD handle
2 mjames 1888
  * @retval HAL status
1889
  */
1890
HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1891
{
9 mjames 1892
  return (USB_DeActivateRemoteWakeup(hpcd->Instance));
2 mjames 1893
}
9 mjames 1894
 
2 mjames 1895
/**
1896
  * @}
1897
  */
9 mjames 1898
 
1899
/** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
1900
  *  @brief   Peripheral State functions
1901
  *
2 mjames 1902
@verbatim
1903
 ===============================================================================
1904
                      ##### Peripheral State functions #####
1905
 ===============================================================================
1906
    [..]
9 mjames 1907
    This subsection permits to get in run-time the status of the peripheral
2 mjames 1908
    and the data flow.
1909
 
1910
@endverbatim
1911
  * @{
1912
  */
1913
 
1914
/**
9 mjames 1915
  * @brief  Return the PCD handle state.
1916
  * @param  hpcd PCD handle
2 mjames 1917
  * @retval HAL state
1918
  */
1919
PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
1920
{
1921
  return hpcd->State;
1922
}
1923
 
1924
/**
1925
  * @}
1926
  */
1927
 
1928
/**
1929
  * @}
1930
  */
1931
 
9 mjames 1932
/* Private functions ---------------------------------------------------------*/
2 mjames 1933
/** @addtogroup PCD_Private_Functions
1934
  * @{
1935
  */
1936
#if defined (USB_OTG_FS)
1937
/**
9 mjames 1938
  * @brief  Check FIFO for the next packet to be loaded.
1939
  * @param  hpcd PCD handle
1940
  * @param  epnum endpoint number
2 mjames 1941
  * @retval HAL status
1942
  */
1943
static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
1944
{
9 mjames 1945
  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1946
  uint32_t USBx_BASE = (uint32_t)USBx;
1947
  USB_OTG_EPTypeDef *ep;
1948
  uint32_t len;
1949
  uint32_t len32b;
1950
  uint32_t fifoemptymsk;
1951
 
2 mjames 1952
  ep = &hpcd->IN_ep[epnum];
9 mjames 1953
 
1954
  if (ep->xfer_count > ep->xfer_len)
1955
  {
1956
    return HAL_ERROR;
1957
  }
1958
 
2 mjames 1959
  len = ep->xfer_len - ep->xfer_count;
9 mjames 1960
 
2 mjames 1961
  if (len > ep->maxpacket)
1962
  {
1963
    len = ep->maxpacket;
1964
  }
9 mjames 1965
 
2 mjames 1966
  len32b = (len + 3U) / 4U;
9 mjames 1967
 
1968
  while (((USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= len32b) &&
1969
         (ep->xfer_count < ep->xfer_len) && (ep->xfer_len != 0U))
2 mjames 1970
  {
1971
    /* Write the FIFO */
1972
    len = ep->xfer_len - ep->xfer_count;
9 mjames 1973
 
1974
    if (len > ep->maxpacket)
2 mjames 1975
    {
1976
      len = ep->maxpacket;
1977
    }
1978
    len32b = (len + 3U) / 4U;
9 mjames 1979
 
1980
    (void)USB_WritePacket(USBx, ep->xfer_buff, (uint8_t)epnum, (uint16_t)len);
1981
 
2 mjames 1982
    ep->xfer_buff  += len;
1983
    ep->xfer_count += len;
1984
  }
9 mjames 1985
 
1986
  if (ep->xfer_len <= ep->xfer_count)
2 mjames 1987
  {
9 mjames 1988
    fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
2 mjames 1989
    USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
1990
  }
9 mjames 1991
 
2 mjames 1992
  return HAL_OK;
1993
}
1994
 
9 mjames 1995
 
1996
/**
1997
  * @brief  process EP OUT transfer complete interrupt.
1998
  * @param  hpcd PCD handle
1999
  * @param  epnum endpoint number
2000
  * @retval HAL status
2001
  */
2002
static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
2003
{
2004
  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
2005
  uint32_t USBx_BASE = (uint32_t)USBx;
2006
  uint32_t gSNPSiD = *(__IO uint32_t *)(&USBx->CID + 0x1U);
2007
  uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
2008
 
2009
  if (gSNPSiD == USB_OTG_CORE_ID_310A)
2010
  {
2011
    /* StupPktRcvd = 1 this is a setup packet */
2012
    if ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX)
2013
    {
2014
      CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
2015
    }
2016
    else
2017
    {
2018
      if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
2019
      {
2020
        CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
2021
      }
2022
 
2023
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2024
      hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
2025
#else
2026
      HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
2027
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2028
    }
2029
  }
2030
  else
2031
  {
2032
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2033
    hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
2034
#else
2035
    HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
2036
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2037
  }
2038
 
2039
  return HAL_OK;
2040
}
2041
 
2042
 
2043
/**
2044
  * @brief  process EP OUT setup packet received interrupt.
2045
  * @param  hpcd PCD handle
2046
  * @param  epnum endpoint number
2047
  * @retval HAL status
2048
  */
2049
static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
2050
{
2051
  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
2052
  uint32_t USBx_BASE = (uint32_t)USBx;
2053
  uint32_t gSNPSiD = *(__IO uint32_t *)(&USBx->CID + 0x1U);
2054
  uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
2055
 
2056
  if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
2057
      ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
2058
  {
2059
    CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
2060
  }
2061
 
2062
  /* Inform the upper layer that a setup packet is available */
2063
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2064
  hpcd->SetupStageCallback(hpcd);
2065
#else
2066
  HAL_PCD_SetupStageCallback(hpcd);
2067
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2068
 
2069
  return HAL_OK;
2070
}
2071
#endif /* defined (USB_OTG_FS) */
2072
 
2 mjames 2073
#if defined (USB)
2074
/**
2075
  * @brief  This function handles PCD Endpoint interrupt request.
9 mjames 2076
  * @param  hpcd PCD handle
2 mjames 2077
  * @retval HAL status
2078
  */
2079
static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
2080
{
9 mjames 2081
  PCD_EPTypeDef *ep;
2082
  uint16_t count, wIstr, wEPVal, TxByteNbre;
2083
  uint8_t epindex;
2084
 
2 mjames 2085
  /* stay in loop while pending interrupts */
9 mjames 2086
  while ((hpcd->Instance->ISTR & USB_ISTR_CTR) != 0U)
2 mjames 2087
  {
9 mjames 2088
    wIstr = hpcd->Instance->ISTR;
2089
 
2 mjames 2090
    /* extract highest priority endpoint number */
2091
    epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
9 mjames 2092
 
2093
    if (epindex == 0U)
2 mjames 2094
    {
2095
      /* Decode and service control endpoint interrupt */
9 mjames 2096
 
2097
      /* DIR bit = origin of the interrupt */
2098
      if ((wIstr & USB_ISTR_DIR) == 0U)
2 mjames 2099
      {
2100
        /* DIR = 0 */
9 mjames 2101
 
2102
        /* DIR = 0 => IN  int */
2103
        /* DIR = 0 implies that (EP_CTR_TX = 1) always */
2 mjames 2104
        PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
2105
        ep = &hpcd->IN_ep[0];
9 mjames 2106
 
2 mjames 2107
        ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
2108
        ep->xfer_buff += ep->xfer_count;
9 mjames 2109
 
2 mjames 2110
        /* TX COMPLETE */
9 mjames 2111
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2112
        hpcd->DataInStageCallback(hpcd, 0U);
2113
#else
2 mjames 2114
        HAL_PCD_DataInStageCallback(hpcd, 0U);
9 mjames 2115
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2116
 
2117
        if ((hpcd->USB_Address > 0U) && (ep->xfer_len == 0U))
2 mjames 2118
        {
9 mjames 2119
          hpcd->Instance->DADDR = ((uint16_t)hpcd->USB_Address | USB_DADDR_EF);
2 mjames 2120
          hpcd->USB_Address = 0U;
2121
        }
2122
      }
2123
      else
2124
      {
2125
        /* DIR = 1 */
9 mjames 2126
 
2127
        /* DIR = 1 & CTR_RX => SETUP or OUT int */
2 mjames 2128
        /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
9 mjames 2129
        ep = &hpcd->OUT_ep[0];
2 mjames 2130
        wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
9 mjames 2131
 
2 mjames 2132
        if ((wEPVal & USB_EP_SETUP) != 0U)
2133
        {
9 mjames 2134
          /* Get SETUP Packet */
2 mjames 2135
          ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
9 mjames 2136
 
2137
          USB_ReadPMA(hpcd->Instance, (uint8_t *)hpcd->Setup,
2138
                      ep->pmaadress, (uint16_t)ep->xfer_count);
2139
 
2140
          /* SETUP bit kept frozen while CTR_RX = 1 */
2141
          PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
2142
 
2 mjames 2143
          /* Process SETUP Packet*/
9 mjames 2144
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2145
          hpcd->SetupStageCallback(hpcd);
2146
#else
2 mjames 2147
          HAL_PCD_SetupStageCallback(hpcd);
9 mjames 2148
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2 mjames 2149
        }
2150
        else if ((wEPVal & USB_EP_CTR_RX) != 0U)
2151
        {
2152
          PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
9 mjames 2153
 
2154
          /* Get Control Data OUT Packet */
2 mjames 2155
          ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
9 mjames 2156
 
2157
          if ((ep->xfer_count != 0U) && (ep->xfer_buff != 0U))
2 mjames 2158
          {
9 mjames 2159
            USB_ReadPMA(hpcd->Instance, ep->xfer_buff,
2160
                        ep->pmaadress, (uint16_t)ep->xfer_count);
2161
 
2162
            ep->xfer_buff += ep->xfer_count;
2163
 
2164
            /* Process Control Data OUT Packet */
2165
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2166
            hpcd->DataOutStageCallback(hpcd, 0U);
2167
#else
2168
            HAL_PCD_DataOutStageCallback(hpcd, 0U);
2169
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2 mjames 2170
          }
9 mjames 2171
 
2 mjames 2172
          PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
2173
          PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
2174
        }
2175
      }
2176
    }
2177
    else
2178
    {
9 mjames 2179
      /* Decode and service non control endpoints interrupt */
2 mjames 2180
      /* process related endpoint register */
2181
      wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);
9 mjames 2182
 
2 mjames 2183
      if ((wEPVal & USB_EP_CTR_RX) != 0U)
9 mjames 2184
      {
2 mjames 2185
        /* clear int flag */
2186
        PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
2187
        ep = &hpcd->OUT_ep[epindex];
9 mjames 2188
 
2189
        /* OUT Single Buffering */
2 mjames 2190
        if (ep->doublebuffer == 0U)
2191
        {
9 mjames 2192
          count = (uint16_t)PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
2193
 
2 mjames 2194
          if (count != 0U)
2195
          {
2196
            USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
2197
          }
2198
        }
2199
        else
2200
        {
9 mjames 2201
          /* manage double buffer bulk out */
2202
          if (ep->type == EP_TYPE_BULK)
2 mjames 2203
          {
9 mjames 2204
            count = HAL_PCD_EP_DB_Receive(hpcd, ep, wEPVal);
2 mjames 2205
          }
9 mjames 2206
          else /* manage double buffer iso out */
2 mjames 2207
          {
9 mjames 2208
            /* free EP OUT Buffer */
2209
            PCD_FreeUserBuffer(hpcd->Instance, ep->num, 0U);
2210
 
2211
            if ((PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX) != 0U)
2 mjames 2212
            {
9 mjames 2213
              /* read from endpoint BUF0Addr buffer */
2214
              count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
2215
 
2216
              if (count != 0U)
2217
              {
2218
                USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
2219
              }
2 mjames 2220
            }
9 mjames 2221
            else
2222
            {
2223
              /* read from endpoint BUF1Addr buffer */
2224
              count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2225
 
2226
              if (count != 0U)
2227
              {
2228
                USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
2229
              }
2230
            }
2 mjames 2231
          }
2232
        }
9 mjames 2233
        /* multi-packet on the NON control OUT endpoint */
2234
        ep->xfer_count += count;
2235
        ep->xfer_buff += count;
2236
 
2 mjames 2237
        if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
2238
        {
2239
          /* RX COMPLETE */
9 mjames 2240
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2241
          hpcd->DataOutStageCallback(hpcd, ep->num);
2242
#else
2 mjames 2243
          HAL_PCD_DataOutStageCallback(hpcd, ep->num);
9 mjames 2244
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2 mjames 2245
        }
2246
        else
2247
        {
9 mjames 2248
          (void) USB_EPStartXfer(hpcd->Instance, ep);
2 mjames 2249
        }
9 mjames 2250
 
2251
      }
2252
 
2 mjames 2253
      if ((wEPVal & USB_EP_CTR_TX) != 0U)
2254
      {
2255
        ep = &hpcd->IN_ep[epindex];
9 mjames 2256
 
2 mjames 2257
        /* clear int flag */
2258
        PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
9 mjames 2259
 
2260
        /* Manage all non bulk transaction or Bulk Single Buffer Transaction */
2261
        if ((ep->type != EP_TYPE_BULK) ||
2262
            ((ep->type == EP_TYPE_BULK) && ((wEPVal & USB_EP_KIND) == 0U)))
2 mjames 2263
        {
9 mjames 2264
          /* multi-packet on the NON control IN endpoint */
2265
          TxByteNbre = (uint16_t)PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
2266
 
2267
          if (ep->xfer_len > TxByteNbre)
2 mjames 2268
          {
9 mjames 2269
            ep->xfer_len -= TxByteNbre;
2 mjames 2270
          }
9 mjames 2271
          else
2 mjames 2272
          {
9 mjames 2273
            ep->xfer_len = 0U;
2 mjames 2274
          }
9 mjames 2275
 
2276
          /* Zero Length Packet? */
2277
          if (ep->xfer_len == 0U)
2278
          {
2279
            /* TX COMPLETE */
2280
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2281
            hpcd->DataInStageCallback(hpcd, ep->num);
2282
#else
2283
            HAL_PCD_DataInStageCallback(hpcd, ep->num);
2284
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2285
          }
2 mjames 2286
          else
2287
          {
9 mjames 2288
            /* Transfer is not yet Done */
2289
            ep->xfer_buff += TxByteNbre;
2290
            ep->xfer_count += TxByteNbre;
2291
            (void)USB_EPStartXfer(hpcd->Instance, ep);
2 mjames 2292
          }
2293
        }
9 mjames 2294
        /* bulk in double buffer enable in case of transferLen> Ep_Mps */
2295
        else
2 mjames 2296
        {
9 mjames 2297
          (void)HAL_PCD_EP_DB_Transmit(hpcd, ep, wEPVal);
2 mjames 2298
        }
9 mjames 2299
      }
2300
    }
2301
  }
2302
 
2303
  return HAL_OK;
2304
}
2305
 
2306
 
2307
/**
2308
  * @brief  Manage double buffer bulk out transaction from ISR
2309
  * @param  hpcd PCD handle
2310
  * @param  ep current endpoint handle
2311
  * @param  wEPVal Last snapshot of EPRx register value taken in ISR
2312
  * @retval HAL status
2313
  */
2314
static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd,
2315
                                      PCD_EPTypeDef *ep, uint16_t wEPVal)
2316
{
2317
  uint16_t count;
2318
 
2319
  /* Manage Buffer0 OUT */
2320
  if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2321
  {
2322
    /* Get count of received Data on buffer0 */
2323
    count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
2324
 
2325
    if (ep->xfer_len >= count)
2326
    {
2327
      ep->xfer_len -= count;
2328
    }
2329
    else
2330
    {
2331
      ep->xfer_len = 0U;
2332
    }
2333
 
2334
    if (ep->xfer_len == 0U)
2335
    {
2336
      /* set NAK to OUT endpoint since double buffer is enabled */
2337
      PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
2338
    }
2339
 
2340
    /* Check if Buffer1 is in blocked sate which requires to toggle */
2341
    if ((wEPVal & USB_EP_DTOG_TX) != 0U)
2342
    {
2343
      PCD_FreeUserBuffer(hpcd->Instance, ep->num, 0U);
2344
    }
2345
 
2346
    if (count != 0U)
2347
    {
2348
      USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
2349
    }
2350
  }
2351
  /* Manage Buffer 1 DTOG_RX=0 */
2352
  else
2353
  {
2354
    /* Get count of received data */
2355
    count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2356
 
2357
    if (ep->xfer_len >= count)
2358
    {
2359
      ep->xfer_len -= count;
2360
    }
2361
    else
2362
    {
2363
      ep->xfer_len = 0U;
2364
    }
2365
 
2366
    if (ep->xfer_len == 0U)
2367
    {
2368
      /* set NAK on the current endpoint */
2369
      PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
2370
    }
2371
 
2372
    /*Need to FreeUser Buffer*/
2373
    if ((wEPVal & USB_EP_DTOG_TX) == 0U)
2374
    {
2375
      PCD_FreeUserBuffer(hpcd->Instance, ep->num, 0U);
2376
    }
2377
 
2378
    if (count != 0U)
2379
    {
2380
      USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
2381
    }
2382
  }
2383
 
2384
  return count;
2385
}
2386
 
2387
 
2388
/**
2389
  * @brief  Manage double buffer bulk IN transaction from ISR
2390
  * @param  hpcd PCD handle
2391
  * @param  ep current endpoint handle
2392
  * @param  wEPVal Last snapshot of EPRx register value taken in ISR
2393
  * @retval HAL status
2394
  */
2395
static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd,
2396
                                                PCD_EPTypeDef *ep, uint16_t wEPVal)
2397
{
2398
  uint32_t len;
2399
  uint16_t TxByteNbre;
2400
 
2401
  /* Data Buffer0 ACK received */
2402
  if ((wEPVal & USB_EP_DTOG_TX) != 0U)
2403
  {
2404
    /* multi-packet on the NON control IN endpoint */
2405
    TxByteNbre = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
2406
 
2407
    if (ep->xfer_len > TxByteNbre)
2408
    {
2409
      ep->xfer_len -= TxByteNbre;
2410
    }
2411
    else
2412
    {
2413
      ep->xfer_len = 0U;
2414
    }
2415
    /* Transfer is completed */
2416
    if (ep->xfer_len == 0U)
2417
    {
2418
      /* TX COMPLETE */
2419
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2420
      hpcd->DataInStageCallback(hpcd, ep->num);
2421
#else
2422
      HAL_PCD_DataInStageCallback(hpcd, ep->num);
2423
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2424
 
2425
      if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2426
      {
2427
        PCD_FreeUserBuffer(hpcd->Instance, ep->num, 1U);
2428
      }
2429
    }
2430
    else /* Transfer is not yet Done */
2431
    {
2432
      /* need to Free USB Buff */
2433
      if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2434
      {
2435
        PCD_FreeUserBuffer(hpcd->Instance, ep->num, 1U);
2436
      }
2437
 
2438
      /* Still there is data to Fill in the next Buffer */
2439
      if (ep->xfer_fill_db == 1U)
2440
      {
2441
        ep->xfer_buff += TxByteNbre;
2442
        ep->xfer_count += TxByteNbre;
2443
 
2444
        /* Calculate the len of the new buffer to fill */
2445
        if (ep->xfer_len_db >= ep->maxpacket)
2446
        {
2447
          len = ep->maxpacket;
2448
          ep->xfer_len_db -= len;
2449
        }
2450
        else if (ep->xfer_len_db == 0U)
2451
        {
2452
          len = TxByteNbre;
2453
          ep->xfer_fill_db = 0U;
2454
        }
2 mjames 2455
        else
2456
        {
9 mjames 2457
          ep->xfer_fill_db = 0U;
2458
          len = ep->xfer_len_db;
2459
          ep->xfer_len_db = 0U;
2 mjames 2460
        }
9 mjames 2461
 
2462
        /* Write remaining Data to Buffer */
2463
        /* Set the Double buffer counter for pma buffer1 */
2464
        PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, len);
2465
 
2466
        /* Copy user buffer to USB PMA */
2467
        USB_WritePMA(hpcd->Instance, ep->xfer_buff,  ep->pmaaddr0, (uint16_t)len);
2468
      }
2 mjames 2469
    }
2470
  }
9 mjames 2471
  else /* Data Buffer1 ACK received */
2472
  {
2473
    /* multi-packet on the NON control IN endpoint */
2474
    TxByteNbre = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2475
 
2476
    if (ep->xfer_len >= TxByteNbre)
2477
    {
2478
      ep->xfer_len -= TxByteNbre;
2479
    }
2480
    else
2481
    {
2482
      ep->xfer_len = 0U;
2483
    }
2484
 
2485
    /* Transfer is completed */
2486
    if (ep->xfer_len == 0U)
2487
    {
2488
      /* TX COMPLETE */
2489
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2490
      hpcd->DataInStageCallback(hpcd, ep->num);
2491
#else
2492
      HAL_PCD_DataInStageCallback(hpcd, ep->num);
2493
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2494
 
2495
      /*need to Free USB Buff*/
2496
      if ((wEPVal & USB_EP_DTOG_RX) == 0U)
2497
      {
2498
        PCD_FreeUserBuffer(hpcd->Instance, ep->num, 1U);
2499
      }
2500
    }
2501
    else /* Transfer is not yet Done */
2502
    {
2503
      /* need to Free USB Buff */
2504
      if ((wEPVal & USB_EP_DTOG_RX) == 0U)
2505
      {
2506
        PCD_FreeUserBuffer(hpcd->Instance, ep->num, 1U);
2507
      }
2508
 
2509
      /* Still there is data to Fill in the next Buffer */
2510
      if (ep->xfer_fill_db == 1U)
2511
      {
2512
        ep->xfer_buff += TxByteNbre;
2513
        ep->xfer_count += TxByteNbre;
2514
 
2515
        /* Calculate the len of the new buffer to fill */
2516
        if (ep->xfer_len_db >= ep->maxpacket)
2517
        {
2518
          len = ep->maxpacket;
2519
          ep->xfer_len_db -= len;
2520
        }
2521
        else if (ep->xfer_len_db == 0U)
2522
        {
2523
          len = TxByteNbre;
2524
          ep->xfer_fill_db = 0U;
2525
        }
2526
        else
2527
        {
2528
          len = ep->xfer_len_db;
2529
          ep->xfer_len_db = 0U;
2530
          ep->xfer_fill_db = 0;
2531
        }
2532
 
2533
        /* Set the Double buffer counter for pmabuffer1 */
2534
        PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, len);
2535
 
2536
        /* Copy the user buffer to USB PMA */
2537
        USB_WritePMA(hpcd->Instance, ep->xfer_buff,  ep->pmaaddr1, (uint16_t)len);
2538
      }
2539
    }
2540
  }
2541
 
2542
  /*enable endpoint IN*/
2543
  PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_VALID);
2544
 
2 mjames 2545
  return HAL_OK;
2546
}
2547
 
9 mjames 2548
#endif /* defined (USB) */
2549
 
2 mjames 2550
/**
2551
  * @}
2552
  */
9 mjames 2553
#endif /* defined (USB) || defined (USB_OTG_FS) */
2554
#endif /* HAL_PCD_MODULE_ENABLED */
2 mjames 2555
 
2556
/**
2557
  * @}
2558
  */
2559
 
2560
/**
2561
  * @}
2562
  */
2563
 
2564
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/