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