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