1 /**
2 ******************************************************************************
3 * @file stm32f4xx_hal_hcd.c
4 * @author MCD Application Team
5 * @brief HCD 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 (#)Declare a HCD_HandleTypeDef handle structure, for example:
19 HCD_HandleTypeDef hhcd;
20
21 (#)Fill parameters of Init structure in HCD handle
22
23 (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
24
25 (#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
26 (##) Enable the HCD/USB Low Level interface clock using the following macros
27 (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
28 (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)
29 (+++) __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); (For High Speed Mode)
30
31 (##) Initialize the related GPIO clocks
32 (##) Configure HCD pin-out
33 (##) Configure HCD NVIC interrupt
34
35 (#)Associate the Upper USB Host stack to the HAL HCD Driver:
36 (##) hhcd.pData = phost;
37
38 (#)Enable HCD transmission and reception:
39 (##) HAL_HCD_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 "stm32f4xx_hal.h"
58
59 /** @addtogroup STM32F4xx_HAL_Driver
60 * @{
61 */
62
63 #ifdef HAL_HCD_MODULE_ENABLED
64 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
65
66 /** @defgroup HCD HCD
67 * @brief HCD HAL module driver
68 * @{
69 */
70
71 /* Private typedef -----------------------------------------------------------*/
72 /* Private define ------------------------------------------------------------*/
73 /* Private macro -------------------------------------------------------------*/
74 /* Private variables ---------------------------------------------------------*/
75 /* Private function prototypes -----------------------------------------------*/
76 /** @defgroup HCD_Private_Functions HCD Private Functions
77 * @{
78 */
79 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
80 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
81 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd);
82 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
83 /**
84 * @}
85 */
86
87 /* Exported functions --------------------------------------------------------*/
88 /** @defgroup HCD_Exported_Functions HCD Exported Functions
89 * @{
90 */
91
92 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
93 * @brief Initialization and Configuration functions
94 *
95 @verbatim
96 ===============================================================================
97 ##### Initialization and de-initialization functions #####
98 ===============================================================================
99 [..] This section provides functions allowing to:
100
101 @endverbatim
102 * @{
103 */
104
105 /**
106 * @brief Initialize the host driver.
107 * @param hhcd HCD handle
108 * @retval HAL status
109 */
HAL_HCD_Init(HCD_HandleTypeDef * hhcd)110 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
111 {
112 USB_OTG_GlobalTypeDef *USBx;
113
114 /* Check the HCD handle allocation */
115 if (hhcd == NULL)
116 {
117 return HAL_ERROR;
118 }
119
120 /* Check the parameters */
121 assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
122
123 USBx = hhcd->Instance;
124
125 if (hhcd->State == HAL_HCD_STATE_RESET)
126 {
127 /* Allocate lock resource and initialize it */
128 hhcd->Lock = HAL_UNLOCKED;
129
130 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
131 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
132 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
133 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
134 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
135 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
136 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;
137
138 if (hhcd->MspInitCallback == NULL)
139 {
140 hhcd->MspInitCallback = HAL_HCD_MspInit;
141 }
142
143 /* Init the low level hardware */
144 hhcd->MspInitCallback(hhcd);
145 #else
146 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
147 HAL_HCD_MspInit(hhcd);
148 #endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
149 }
150
151 hhcd->State = HAL_HCD_STATE_BUSY;
152
153 /* Disable DMA mode for FS instance */
154 if ((USBx->CID & (0x1U << 8)) == 0U)
155 {
156 hhcd->Init.dma_enable = 0U;
157 }
158
159 /* Disable the Interrupts */
160 __HAL_HCD_DISABLE(hhcd);
161
162 /* Init the Core (common init.) */
163 (void)USB_CoreInit(hhcd->Instance, hhcd->Init);
164
165 /* Force Host Mode*/
166 (void)USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE);
167
168 /* Init Host */
169 (void)USB_HostInit(hhcd->Instance, hhcd->Init);
170
171 hhcd->State = HAL_HCD_STATE_READY;
172
173 return HAL_OK;
174 }
175
176 /**
177 * @brief Initialize a host channel.
178 * @param hhcd HCD handle
179 * @param ch_num Channel number.
180 * This parameter can be a value from 1 to 15
181 * @param epnum Endpoint number.
182 * This parameter can be a value from 1 to 15
183 * @param dev_address Current device address
184 * This parameter can be a value from 0 to 255
185 * @param speed Current device speed.
186 * This parameter can be one of these values:
187 * HCD_DEVICE_SPEED_HIGH: High speed mode,
188 * HCD_DEVICE_SPEED_FULL: Full speed mode,
189 * HCD_DEVICE_SPEED_LOW: Low speed mode
190 * @param ep_type Endpoint Type.
191 * This parameter can be one of these values:
192 * EP_TYPE_CTRL: Control type,
193 * EP_TYPE_ISOC: Isochronous type,
194 * EP_TYPE_BULK: Bulk type,
195 * EP_TYPE_INTR: Interrupt type
196 * @param mps Max Packet Size.
197 * This parameter can be a value from 0 to32K
198 * @retval HAL status
199 */
HAL_HCD_HC_Init(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t epnum,uint8_t dev_address,uint8_t speed,uint8_t ep_type,uint16_t mps)200 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd,
201 uint8_t ch_num,
202 uint8_t epnum,
203 uint8_t dev_address,
204 uint8_t speed,
205 uint8_t ep_type,
206 uint16_t mps)
207 {
208 HAL_StatusTypeDef status;
209
210 __HAL_LOCK(hhcd);
211 hhcd->hc[ch_num].do_ping = 0U;
212 hhcd->hc[ch_num].dev_addr = dev_address;
213 hhcd->hc[ch_num].max_packet = mps;
214 hhcd->hc[ch_num].ch_num = ch_num;
215 hhcd->hc[ch_num].ep_type = ep_type;
216 hhcd->hc[ch_num].ep_num = epnum & 0x7FU;
217
218 if ((epnum & 0x80U) == 0x80U)
219 {
220 hhcd->hc[ch_num].ep_is_in = 1U;
221 }
222 else
223 {
224 hhcd->hc[ch_num].ep_is_in = 0U;
225 }
226
227 hhcd->hc[ch_num].speed = speed;
228
229 status = USB_HC_Init(hhcd->Instance,
230 ch_num,
231 epnum,
232 dev_address,
233 speed,
234 ep_type,
235 mps);
236 __HAL_UNLOCK(hhcd);
237
238 return status;
239 }
240
241 /**
242 * @brief Halt a host channel.
243 * @param hhcd HCD handle
244 * @param ch_num Channel number.
245 * This parameter can be a value from 1 to 15
246 * @retval HAL status
247 */
HAL_HCD_HC_Halt(HCD_HandleTypeDef * hhcd,uint8_t ch_num)248 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
249 {
250 HAL_StatusTypeDef status = HAL_OK;
251
252 __HAL_LOCK(hhcd);
253 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
254 __HAL_UNLOCK(hhcd);
255
256 return status;
257 }
258
259 /**
260 * @brief DeInitialize the host driver.
261 * @param hhcd HCD handle
262 * @retval HAL status
263 */
HAL_HCD_DeInit(HCD_HandleTypeDef * hhcd)264 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
265 {
266 /* Check the HCD handle allocation */
267 if (hhcd == NULL)
268 {
269 return HAL_ERROR;
270 }
271
272 hhcd->State = HAL_HCD_STATE_BUSY;
273
274 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
275 if (hhcd->MspDeInitCallback == NULL)
276 {
277 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */
278 }
279
280 /* DeInit the low level hardware */
281 hhcd->MspDeInitCallback(hhcd);
282 #else
283 /* DeInit the low level hardware: CLOCK, NVIC.*/
284 HAL_HCD_MspDeInit(hhcd);
285 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
286
287 __HAL_HCD_DISABLE(hhcd);
288
289 hhcd->State = HAL_HCD_STATE_RESET;
290
291 return HAL_OK;
292 }
293
294 /**
295 * @brief Initialize the HCD MSP.
296 * @param hhcd HCD handle
297 * @retval None
298 */
HAL_HCD_MspInit(HCD_HandleTypeDef * hhcd)299 __weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
300 {
301 /* Prevent unused argument(s) compilation warning */
302 UNUSED(hhcd);
303
304 /* NOTE : This function should not be modified, when the callback is needed,
305 the HAL_HCD_MspInit could be implemented in the user file
306 */
307 }
308
309 /**
310 * @brief DeInitialize the HCD MSP.
311 * @param hhcd HCD handle
312 * @retval None
313 */
HAL_HCD_MspDeInit(HCD_HandleTypeDef * hhcd)314 __weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
315 {
316 /* Prevent unused argument(s) compilation warning */
317 UNUSED(hhcd);
318
319 /* NOTE : This function should not be modified, when the callback is needed,
320 the HAL_HCD_MspDeInit could be implemented in the user file
321 */
322 }
323
324 /**
325 * @}
326 */
327
328 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
329 * @brief HCD IO operation functions
330 *
331 @verbatim
332 ===============================================================================
333 ##### IO operation functions #####
334 ===============================================================================
335 [..] This subsection provides a set of functions allowing to manage the USB Host Data
336 Transfer
337
338 @endverbatim
339 * @{
340 */
341
342 /**
343 * @brief Submit a new URB for processing.
344 * @param hhcd HCD handle
345 * @param ch_num Channel number.
346 * This parameter can be a value from 1 to 15
347 * @param direction Channel number.
348 * This parameter can be one of these values:
349 * 0 : Output / 1 : Input
350 * @param ep_type Endpoint Type.
351 * This parameter can be one of these values:
352 * EP_TYPE_CTRL: Control type/
353 * EP_TYPE_ISOC: Isochronous type/
354 * EP_TYPE_BULK: Bulk type/
355 * EP_TYPE_INTR: Interrupt type/
356 * @param token Endpoint Type.
357 * This parameter can be one of these values:
358 * 0: HC_PID_SETUP / 1: HC_PID_DATA1
359 * @param pbuff pointer to URB data
360 * @param length Length of URB data
361 * @param do_ping activate do ping protocol (for high speed only).
362 * This parameter can be one of these values:
363 * 0 : do ping inactive / 1 : do ping active
364 * @retval HAL status
365 */
HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t direction,uint8_t ep_type,uint8_t token,uint8_t * pbuff,uint16_t length,uint8_t do_ping)366 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
367 uint8_t ch_num,
368 uint8_t direction,
369 uint8_t ep_type,
370 uint8_t token,
371 uint8_t *pbuff,
372 uint16_t length,
373 uint8_t do_ping)
374 {
375 hhcd->hc[ch_num].ep_is_in = direction;
376 hhcd->hc[ch_num].ep_type = ep_type;
377
378 if (token == 0U)
379 {
380 hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
381 hhcd->hc[ch_num].do_ping = do_ping;
382 }
383 else
384 {
385 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
386 }
387
388 /* Manage Data Toggle */
389 switch (ep_type)
390 {
391 case EP_TYPE_CTRL:
392 if ((token == 1U) && (direction == 0U)) /*send data */
393 {
394 if (length == 0U)
395 {
396 /* For Status OUT stage, Length==0, Status Out PID = 1 */
397 hhcd->hc[ch_num].toggle_out = 1U;
398 }
399
400 /* Set the Data Toggle bit as per the Flag */
401 if (hhcd->hc[ch_num].toggle_out == 0U)
402 {
403 /* Put the PID 0 */
404 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
405 }
406 else
407 {
408 /* Put the PID 1 */
409 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
410 }
411 }
412 break;
413
414 case EP_TYPE_BULK:
415 if (direction == 0U)
416 {
417 /* Set the Data Toggle bit as per the Flag */
418 if (hhcd->hc[ch_num].toggle_out == 0U)
419 {
420 /* Put the PID 0 */
421 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
422 }
423 else
424 {
425 /* Put the PID 1 */
426 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
427 }
428 }
429 else
430 {
431 if (hhcd->hc[ch_num].toggle_in == 0U)
432 {
433 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
434 }
435 else
436 {
437 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
438 }
439 }
440
441 break;
442 case EP_TYPE_INTR:
443 if (direction == 0U)
444 {
445 /* Set the Data Toggle bit as per the Flag */
446 if (hhcd->hc[ch_num].toggle_out == 0U)
447 {
448 /* Put the PID 0 */
449 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
450 }
451 else
452 {
453 /* Put the PID 1 */
454 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
455 }
456 }
457 else
458 {
459 if (hhcd->hc[ch_num].toggle_in == 0U)
460 {
461 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
462 }
463 else
464 {
465 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
466 }
467 }
468 break;
469
470 case EP_TYPE_ISOC:
471 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
472 break;
473
474 default:
475 break;
476 }
477
478 hhcd->hc[ch_num].xfer_buff = pbuff;
479 hhcd->hc[ch_num].xfer_len = length;
480 hhcd->hc[ch_num].urb_state = URB_IDLE;
481 hhcd->hc[ch_num].xfer_count = 0U;
482 hhcd->hc[ch_num].ch_num = ch_num;
483 hhcd->hc[ch_num].state = HC_IDLE;
484
485 return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num], (uint8_t)hhcd->Init.dma_enable);
486 }
487
488 /**
489 * @brief Handle HCD interrupt request.
490 * @param hhcd HCD handle
491 * @retval None
492 */
HAL_HCD_IRQHandler(HCD_HandleTypeDef * hhcd)493 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
494 {
495 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
496 uint32_t USBx_BASE = (uint32_t)USBx;
497 uint32_t i;
498 uint32_t interrupt;
499
500 /* Ensure that we are in device mode */
501 if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
502 {
503 /* Avoid spurious interrupt */
504 if (__HAL_HCD_IS_INVALID_INTERRUPT(hhcd))
505 {
506 return;
507 }
508
509 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
510 {
511 /* Incorrect mode, acknowledge the interrupt */
512 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
513 }
514
515 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
516 {
517 /* Incorrect mode, acknowledge the interrupt */
518 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
519 }
520
521 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
522 {
523 /* Incorrect mode, acknowledge the interrupt */
524 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
525 }
526
527 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
528 {
529 /* Incorrect mode, acknowledge the interrupt */
530 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
531 }
532
533 /* Handle Host Disconnect Interrupts */
534 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
535 {
536 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
537
538 if ((USBx_HPRT0 & USB_OTG_HPRT_PCSTS) == 0U)
539 {
540 /* Flush USB Fifo */
541 (void)USB_FlushTxFifo(USBx, 0x10U);
542 (void)USB_FlushRxFifo(USBx);
543
544 /* Restore FS Clock */
545 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
546
547 /* Handle Host Port Disconnect Interrupt */
548 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
549 hhcd->DisconnectCallback(hhcd);
550 #else
551 HAL_HCD_Disconnect_Callback(hhcd);
552 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
553 }
554 }
555
556 /* Handle Host Port Interrupts */
557 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
558 {
559 HCD_Port_IRQHandler(hhcd);
560 }
561
562 /* Handle Host SOF Interrupt */
563 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
564 {
565 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
566 hhcd->SOFCallback(hhcd);
567 #else
568 HAL_HCD_SOF_Callback(hhcd);
569 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
570
571 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
572 }
573
574 /* Handle Rx Queue Level Interrupts */
575 if ((__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) != 0U)
576 {
577 USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
578
579 HCD_RXQLVL_IRQHandler(hhcd);
580
581 USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
582 }
583
584 /* Handle Host channel Interrupt */
585 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
586 {
587 interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
588 for (i = 0U; i < hhcd->Init.Host_channels; i++)
589 {
590 if ((interrupt & (1UL << (i & 0xFU))) != 0U)
591 {
592 if ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR)
593 {
594 HCD_HC_IN_IRQHandler(hhcd, (uint8_t)i);
595 }
596 else
597 {
598 HCD_HC_OUT_IRQHandler(hhcd, (uint8_t)i);
599 }
600 }
601 }
602 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
603 }
604 }
605 }
606
607
608 /**
609 * @brief Handles HCD Wakeup interrupt request.
610 * @param hhcd HCD handle
611 * @retval HAL status
612 */
HAL_HCD_WKUP_IRQHandler(HCD_HandleTypeDef * hhcd)613 void HAL_HCD_WKUP_IRQHandler(HCD_HandleTypeDef *hhcd)
614 {
615 UNUSED(hhcd);
616 }
617
618
619 /**
620 * @brief SOF callback.
621 * @param hhcd HCD handle
622 * @retval None
623 */
HAL_HCD_SOF_Callback(HCD_HandleTypeDef * hhcd)624 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
625 {
626 /* Prevent unused argument(s) compilation warning */
627 UNUSED(hhcd);
628
629 /* NOTE : This function should not be modified, when the callback is needed,
630 the HAL_HCD_SOF_Callback could be implemented in the user file
631 */
632 }
633
634 /**
635 * @brief Connection Event callback.
636 * @param hhcd HCD handle
637 * @retval None
638 */
HAL_HCD_Connect_Callback(HCD_HandleTypeDef * hhcd)639 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
640 {
641 /* Prevent unused argument(s) compilation warning */
642 UNUSED(hhcd);
643
644 /* NOTE : This function should not be modified, when the callback is needed,
645 the HAL_HCD_Connect_Callback could be implemented in the user file
646 */
647 }
648
649 /**
650 * @brief Disconnection Event callback.
651 * @param hhcd HCD handle
652 * @retval None
653 */
HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef * hhcd)654 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
655 {
656 /* Prevent unused argument(s) compilation warning */
657 UNUSED(hhcd);
658
659 /* NOTE : This function should not be modified, when the callback is needed,
660 the HAL_HCD_Disconnect_Callback could be implemented in the user file
661 */
662 }
663
664 /**
665 * @brief Port Enabled Event callback.
666 * @param hhcd HCD handle
667 * @retval None
668 */
HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef * hhcd)669 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
670 {
671 /* Prevent unused argument(s) compilation warning */
672 UNUSED(hhcd);
673
674 /* NOTE : This function should not be modified, when the callback is needed,
675 the HAL_HCD_Disconnect_Callback could be implemented in the user file
676 */
677 }
678
679 /**
680 * @brief Port Disabled Event callback.
681 * @param hhcd HCD handle
682 * @retval None
683 */
HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef * hhcd)684 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
685 {
686 /* Prevent unused argument(s) compilation warning */
687 UNUSED(hhcd);
688
689 /* NOTE : This function should not be modified, when the callback is needed,
690 the HAL_HCD_Disconnect_Callback could be implemented in the user file
691 */
692 }
693
694 /**
695 * @brief Notify URB state change callback.
696 * @param hhcd HCD handle
697 * @param chnum Channel number.
698 * This parameter can be a value from 1 to 15
699 * @param urb_state:
700 * This parameter can be one of these values:
701 * URB_IDLE/
702 * URB_DONE/
703 * URB_NOTREADY/
704 * URB_NYET/
705 * URB_ERROR/
706 * URB_STALL/
707 * @retval None
708 */
HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef * hhcd,uint8_t chnum,HCD_URBStateTypeDef urb_state)709 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
710 {
711 /* Prevent unused argument(s) compilation warning */
712 UNUSED(hhcd);
713 UNUSED(chnum);
714 UNUSED(urb_state);
715
716 /* NOTE : This function should not be modified, when the callback is needed,
717 the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
718 */
719 }
720
721 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
722 /**
723 * @brief Register a User USB HCD Callback
724 * To be used instead of the weak predefined callback
725 * @param hhcd USB HCD handle
726 * @param CallbackID ID of the callback to be registered
727 * This parameter can be one of the following values:
728 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
729 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
730 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
731 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
732 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
733 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
734 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
735 * @param pCallback pointer to the Callback function
736 * @retval HAL status
737 */
HAL_HCD_RegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID,pHCD_CallbackTypeDef pCallback)738 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
739 HAL_HCD_CallbackIDTypeDef CallbackID,
740 pHCD_CallbackTypeDef pCallback)
741 {
742 HAL_StatusTypeDef status = HAL_OK;
743
744 if (pCallback == NULL)
745 {
746 /* Update the error code */
747 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
748 return HAL_ERROR;
749 }
750 /* Process locked */
751 __HAL_LOCK(hhcd);
752
753 if (hhcd->State == HAL_HCD_STATE_READY)
754 {
755 switch (CallbackID)
756 {
757 case HAL_HCD_SOF_CB_ID :
758 hhcd->SOFCallback = pCallback;
759 break;
760
761 case HAL_HCD_CONNECT_CB_ID :
762 hhcd->ConnectCallback = pCallback;
763 break;
764
765 case HAL_HCD_DISCONNECT_CB_ID :
766 hhcd->DisconnectCallback = pCallback;
767 break;
768
769 case HAL_HCD_PORT_ENABLED_CB_ID :
770 hhcd->PortEnabledCallback = pCallback;
771 break;
772
773 case HAL_HCD_PORT_DISABLED_CB_ID :
774 hhcd->PortDisabledCallback = pCallback;
775 break;
776
777 case HAL_HCD_MSPINIT_CB_ID :
778 hhcd->MspInitCallback = pCallback;
779 break;
780
781 case HAL_HCD_MSPDEINIT_CB_ID :
782 hhcd->MspDeInitCallback = pCallback;
783 break;
784
785 default :
786 /* Update the error code */
787 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
788 /* Return error status */
789 status = HAL_ERROR;
790 break;
791 }
792 }
793 else if (hhcd->State == HAL_HCD_STATE_RESET)
794 {
795 switch (CallbackID)
796 {
797 case HAL_HCD_MSPINIT_CB_ID :
798 hhcd->MspInitCallback = pCallback;
799 break;
800
801 case HAL_HCD_MSPDEINIT_CB_ID :
802 hhcd->MspDeInitCallback = pCallback;
803 break;
804
805 default :
806 /* Update the error code */
807 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
808 /* Return error status */
809 status = HAL_ERROR;
810 break;
811 }
812 }
813 else
814 {
815 /* Update the error code */
816 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
817 /* Return error status */
818 status = HAL_ERROR;
819 }
820
821 /* Release Lock */
822 __HAL_UNLOCK(hhcd);
823 return status;
824 }
825
826 /**
827 * @brief Unregister an USB HCD Callback
828 * USB HCD callback is redirected to the weak predefined callback
829 * @param hhcd USB HCD handle
830 * @param CallbackID ID of the callback to be unregistered
831 * This parameter can be one of the following values:
832 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
833 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
834 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
835 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
836 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
837 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
838 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
839 * @retval HAL status
840 */
HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID)841 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID)
842 {
843 HAL_StatusTypeDef status = HAL_OK;
844
845 /* Process locked */
846 __HAL_LOCK(hhcd);
847
848 /* Setup Legacy weak Callbacks */
849 if (hhcd->State == HAL_HCD_STATE_READY)
850 {
851 switch (CallbackID)
852 {
853 case HAL_HCD_SOF_CB_ID :
854 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
855 break;
856
857 case HAL_HCD_CONNECT_CB_ID :
858 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
859 break;
860
861 case HAL_HCD_DISCONNECT_CB_ID :
862 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
863 break;
864
865 case HAL_HCD_PORT_ENABLED_CB_ID :
866 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
867 break;
868
869 case HAL_HCD_PORT_DISABLED_CB_ID :
870 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
871 break;
872
873 case HAL_HCD_MSPINIT_CB_ID :
874 hhcd->MspInitCallback = HAL_HCD_MspInit;
875 break;
876
877 case HAL_HCD_MSPDEINIT_CB_ID :
878 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
879 break;
880
881 default :
882 /* Update the error code */
883 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
884
885 /* Return error status */
886 status = HAL_ERROR;
887 break;
888 }
889 }
890 else if (hhcd->State == HAL_HCD_STATE_RESET)
891 {
892 switch (CallbackID)
893 {
894 case HAL_HCD_MSPINIT_CB_ID :
895 hhcd->MspInitCallback = HAL_HCD_MspInit;
896 break;
897
898 case HAL_HCD_MSPDEINIT_CB_ID :
899 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
900 break;
901
902 default :
903 /* Update the error code */
904 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
905
906 /* Return error status */
907 status = HAL_ERROR;
908 break;
909 }
910 }
911 else
912 {
913 /* Update the error code */
914 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
915
916 /* Return error status */
917 status = HAL_ERROR;
918 }
919
920 /* Release Lock */
921 __HAL_UNLOCK(hhcd);
922 return status;
923 }
924
925 /**
926 * @brief Register USB HCD Host Channel Notify URB Change Callback
927 * To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
928 * @param hhcd HCD handle
929 * @param pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
930 * @retval HAL status
931 */
HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd,pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)932 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
933 pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
934 {
935 HAL_StatusTypeDef status = HAL_OK;
936
937 if (pCallback == NULL)
938 {
939 /* Update the error code */
940 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
941
942 return HAL_ERROR;
943 }
944
945 /* Process locked */
946 __HAL_LOCK(hhcd);
947
948 if (hhcd->State == HAL_HCD_STATE_READY)
949 {
950 hhcd->HC_NotifyURBChangeCallback = pCallback;
951 }
952 else
953 {
954 /* Update the error code */
955 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
956
957 /* Return error status */
958 status = HAL_ERROR;
959 }
960
961 /* Release Lock */
962 __HAL_UNLOCK(hhcd);
963
964 return status;
965 }
966
967 /**
968 * @brief Unregister the USB HCD Host Channel Notify URB Change Callback
969 * USB HCD Host Channel Notify URB Change Callback is redirected
970 * to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
971 * @param hhcd HCD handle
972 * @retval HAL status
973 */
HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd)974 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
975 {
976 HAL_StatusTypeDef status = HAL_OK;
977
978 /* Process locked */
979 __HAL_LOCK(hhcd);
980
981 if (hhcd->State == HAL_HCD_STATE_READY)
982 {
983 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
984 }
985 else
986 {
987 /* Update the error code */
988 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
989
990 /* Return error status */
991 status = HAL_ERROR;
992 }
993
994 /* Release Lock */
995 __HAL_UNLOCK(hhcd);
996
997 return status;
998 }
999 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1000
1001 /**
1002 * @}
1003 */
1004
1005 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
1006 * @brief Management functions
1007 *
1008 @verbatim
1009 ===============================================================================
1010 ##### Peripheral Control functions #####
1011 ===============================================================================
1012 [..]
1013 This subsection provides a set of functions allowing to control the HCD data
1014 transfers.
1015
1016 @endverbatim
1017 * @{
1018 */
1019
1020 /**
1021 * @brief Start the host driver.
1022 * @param hhcd HCD handle
1023 * @retval HAL status
1024 */
HAL_HCD_Start(HCD_HandleTypeDef * hhcd)1025 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
1026 {
1027 __HAL_LOCK(hhcd);
1028 /* Enable port power */
1029 (void)USB_DriveVbus(hhcd->Instance, 1U);
1030
1031 /* Enable global interrupt */
1032 __HAL_HCD_ENABLE(hhcd);
1033 __HAL_UNLOCK(hhcd);
1034
1035 return HAL_OK;
1036 }
1037
1038 /**
1039 * @brief Stop the host driver.
1040 * @param hhcd HCD handle
1041 * @retval HAL status
1042 */
1043
HAL_HCD_Stop(HCD_HandleTypeDef * hhcd)1044 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
1045 {
1046 __HAL_LOCK(hhcd);
1047 (void)USB_StopHost(hhcd->Instance);
1048 __HAL_UNLOCK(hhcd);
1049
1050 return HAL_OK;
1051 }
1052
1053 /**
1054 * @brief Reset the host port.
1055 * @param hhcd HCD handle
1056 * @retval HAL status
1057 */
HAL_HCD_ResetPort(HCD_HandleTypeDef * hhcd)1058 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
1059 {
1060 return (USB_ResetPort(hhcd->Instance));
1061 }
1062
1063 /**
1064 * @}
1065 */
1066
1067 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
1068 * @brief Peripheral State functions
1069 *
1070 @verbatim
1071 ===============================================================================
1072 ##### Peripheral State functions #####
1073 ===============================================================================
1074 [..]
1075 This subsection permits to get in run-time the status of the peripheral
1076 and the data flow.
1077
1078 @endverbatim
1079 * @{
1080 */
1081
1082 /**
1083 * @brief Return the HCD handle state.
1084 * @param hhcd HCD handle
1085 * @retval HAL state
1086 */
HAL_HCD_GetState(HCD_HandleTypeDef * hhcd)1087 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef *hhcd)
1088 {
1089 return hhcd->State;
1090 }
1091
1092 /**
1093 * @brief Return URB state for a channel.
1094 * @param hhcd HCD handle
1095 * @param chnum Channel number.
1096 * This parameter can be a value from 1 to 15
1097 * @retval URB state.
1098 * This parameter can be one of these values:
1099 * URB_IDLE/
1100 * URB_DONE/
1101 * URB_NOTREADY/
1102 * URB_NYET/
1103 * URB_ERROR/
1104 * URB_STALL
1105 */
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef * hhcd,uint8_t chnum)1106 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1107 {
1108 return hhcd->hc[chnum].urb_state;
1109 }
1110
1111
1112 /**
1113 * @brief Return the last host transfer size.
1114 * @param hhcd HCD handle
1115 * @param chnum Channel number.
1116 * This parameter can be a value from 1 to 15
1117 * @retval last transfer size in byte
1118 */
HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef * hhcd,uint8_t chnum)1119 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1120 {
1121 return hhcd->hc[chnum].xfer_count;
1122 }
1123
1124 /**
1125 * @brief Return the Host Channel state.
1126 * @param hhcd HCD handle
1127 * @param chnum Channel number.
1128 * This parameter can be a value from 1 to 15
1129 * @retval Host channel state
1130 * This parameter can be one of these values:
1131 * HC_IDLE/
1132 * HC_XFRC/
1133 * HC_HALTED/
1134 * HC_NYET/
1135 * HC_NAK/
1136 * HC_STALL/
1137 * HC_XACTERR/
1138 * HC_BBLERR/
1139 * HC_DATATGLERR
1140 */
HAL_HCD_HC_GetState(HCD_HandleTypeDef * hhcd,uint8_t chnum)1141 HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1142 {
1143 return hhcd->hc[chnum].state;
1144 }
1145
1146 /**
1147 * @brief Return the current Host frame number.
1148 * @param hhcd HCD handle
1149 * @retval Current Host frame number
1150 */
HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef * hhcd)1151 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
1152 {
1153 return (USB_GetCurrentFrame(hhcd->Instance));
1154 }
1155
1156 /**
1157 * @brief Return the Host enumeration speed.
1158 * @param hhcd HCD handle
1159 * @retval Enumeration speed
1160 */
HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef * hhcd)1161 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
1162 {
1163 return (USB_GetHostSpeed(hhcd->Instance));
1164 }
1165
1166 /**
1167 * @}
1168 */
1169
1170 /**
1171 * @}
1172 */
1173
1174 /** @addtogroup HCD_Private_Functions
1175 * @{
1176 */
1177 /**
1178 * @brief Handle Host Channel IN interrupt requests.
1179 * @param hhcd HCD handle
1180 * @param chnum Channel number.
1181 * This parameter can be a value from 1 to 15
1182 * @retval none
1183 */
HCD_HC_IN_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1184 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1185 {
1186 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1187 uint32_t USBx_BASE = (uint32_t)USBx;
1188 uint32_t ch_num = (uint32_t)chnum;
1189
1190 uint32_t tmpreg;
1191
1192 if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR)
1193 {
1194 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
1195 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1196 }
1197 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR)
1198 {
1199 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR);
1200 hhcd->hc[ch_num].state = HC_BBLERR;
1201 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1202 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1203 }
1204 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK)
1205 {
1206 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
1207 }
1208 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL)
1209 {
1210 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1211 hhcd->hc[ch_num].state = HC_STALL;
1212 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1213 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
1214 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1215 }
1216 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR)
1217 {
1218 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1219 hhcd->hc[ch_num].state = HC_DATATGLERR;
1220 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1221 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
1222 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1223 }
1224 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR)
1225 {
1226 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1227 hhcd->hc[ch_num].state = HC_XACTERR;
1228 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1229 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
1230 }
1231 else
1232 {
1233 /* ... */
1234 }
1235
1236 if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR)
1237 {
1238 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1239 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1240 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
1241 }
1242 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC)
1243 {
1244 if (hhcd->Init.dma_enable != 0U)
1245 {
1246 hhcd->hc[ch_num].xfer_count = hhcd->hc[ch_num].XferSize - \
1247 (USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
1248 }
1249
1250 hhcd->hc[ch_num].state = HC_XFRC;
1251 hhcd->hc[ch_num].ErrCnt = 0U;
1252 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
1253
1254 if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
1255 (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
1256 {
1257 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1258 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1259 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1260 }
1261 else if (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR)
1262 {
1263 USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
1264 hhcd->hc[ch_num].urb_state = URB_DONE;
1265
1266 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1267 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1268 #else
1269 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1270 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1271 }
1272 else if (hhcd->hc[ch_num].ep_type == EP_TYPE_ISOC)
1273 {
1274 hhcd->hc[ch_num].urb_state = URB_DONE;
1275 hhcd->hc[ch_num].toggle_in ^= 1U;
1276
1277 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1278 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1279 #else
1280 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1281 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1282 }
1283 else
1284 {
1285 /* ... */
1286 }
1287
1288 if (hhcd->Init.dma_enable == 1U)
1289 {
1290 if (((hhcd->hc[ch_num].XferSize / hhcd->hc[ch_num].max_packet) & 1U) != 0U)
1291 {
1292 hhcd->hc[ch_num].toggle_in ^= 1U;
1293 }
1294 }
1295 else
1296 {
1297 hhcd->hc[ch_num].toggle_in ^= 1U;
1298 }
1299 }
1300 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH)
1301 {
1302 __HAL_HCD_MASK_HALT_HC_INT(ch_num);
1303
1304 if (hhcd->hc[ch_num].state == HC_XFRC)
1305 {
1306 hhcd->hc[ch_num].urb_state = URB_DONE;
1307 }
1308 else if (hhcd->hc[ch_num].state == HC_STALL)
1309 {
1310 hhcd->hc[ch_num].urb_state = URB_STALL;
1311 }
1312 else if ((hhcd->hc[ch_num].state == HC_XACTERR) ||
1313 (hhcd->hc[ch_num].state == HC_DATATGLERR))
1314 {
1315 hhcd->hc[ch_num].ErrCnt++;
1316 if (hhcd->hc[ch_num].ErrCnt > 2U)
1317 {
1318 hhcd->hc[ch_num].ErrCnt = 0U;
1319 hhcd->hc[ch_num].urb_state = URB_ERROR;
1320 }
1321 else
1322 {
1323 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1324
1325 /* re-activate the channel */
1326 tmpreg = USBx_HC(ch_num)->HCCHAR;
1327 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1328 tmpreg |= USB_OTG_HCCHAR_CHENA;
1329 USBx_HC(ch_num)->HCCHAR = tmpreg;
1330 }
1331 }
1332 else if (hhcd->hc[ch_num].state == HC_NAK)
1333 {
1334 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1335
1336 /* re-activate the channel */
1337 tmpreg = USBx_HC(ch_num)->HCCHAR;
1338 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1339 tmpreg |= USB_OTG_HCCHAR_CHENA;
1340 USBx_HC(ch_num)->HCCHAR = tmpreg;
1341 }
1342 else if (hhcd->hc[ch_num].state == HC_BBLERR)
1343 {
1344 hhcd->hc[ch_num].ErrCnt++;
1345 hhcd->hc[ch_num].urb_state = URB_ERROR;
1346 }
1347 else
1348 {
1349 /* ... */
1350 }
1351 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
1352 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1353 }
1354 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK)
1355 {
1356 if (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR)
1357 {
1358 hhcd->hc[ch_num].ErrCnt = 0U;
1359 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1360 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1361 }
1362 else if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
1363 (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
1364 {
1365 hhcd->hc[ch_num].ErrCnt = 0U;
1366
1367 if (hhcd->Init.dma_enable == 0U)
1368 {
1369 hhcd->hc[ch_num].state = HC_NAK;
1370 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1371 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1372 }
1373 }
1374 else
1375 {
1376 /* ... */
1377 }
1378 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1379 }
1380 else
1381 {
1382 /* ... */
1383 }
1384 }
1385
1386 /**
1387 * @brief Handle Host Channel OUT interrupt requests.
1388 * @param hhcd HCD handle
1389 * @param chnum Channel number.
1390 * This parameter can be a value from 1 to 15
1391 * @retval none
1392 */
HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1393 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1394 {
1395 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1396 uint32_t USBx_BASE = (uint32_t)USBx;
1397 uint32_t ch_num = (uint32_t)chnum;
1398 uint32_t tmpreg;
1399 uint32_t num_packets;
1400
1401 if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR)
1402 {
1403 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
1404 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1405 }
1406 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK)
1407 {
1408 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
1409
1410 if (hhcd->hc[ch_num].do_ping == 1U)
1411 {
1412 hhcd->hc[ch_num].do_ping = 0U;
1413 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1414 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1415 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1416 }
1417 }
1418 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR)
1419 {
1420 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1421 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1422 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
1423 }
1424 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC)
1425 {
1426 hhcd->hc[ch_num].ErrCnt = 0U;
1427
1428 /* transaction completed with NYET state, update do ping state */
1429 if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET)
1430 {
1431 hhcd->hc[ch_num].do_ping = 1U;
1432 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
1433 }
1434 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1435 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1436 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
1437 hhcd->hc[ch_num].state = HC_XFRC;
1438 }
1439 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET)
1440 {
1441 hhcd->hc[ch_num].state = HC_NYET;
1442 hhcd->hc[ch_num].do_ping = 1U;
1443 hhcd->hc[ch_num].ErrCnt = 0U;
1444 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1445 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1446 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
1447 }
1448 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL)
1449 {
1450 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
1451 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1452 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1453 hhcd->hc[ch_num].state = HC_STALL;
1454 }
1455 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK)
1456 {
1457 hhcd->hc[ch_num].ErrCnt = 0U;
1458 hhcd->hc[ch_num].state = HC_NAK;
1459
1460 if (hhcd->hc[ch_num].do_ping == 0U)
1461 {
1462 if (hhcd->hc[ch_num].speed == HCD_DEVICE_SPEED_HIGH)
1463 {
1464 hhcd->hc[ch_num].do_ping = 1U;
1465 }
1466 }
1467
1468 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1469 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1470 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1471 }
1472 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR)
1473 {
1474 if (hhcd->Init.dma_enable == 0U)
1475 {
1476 hhcd->hc[ch_num].state = HC_XACTERR;
1477 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1478 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1479 }
1480 else
1481 {
1482 hhcd->hc[ch_num].ErrCnt++;
1483 if (hhcd->hc[ch_num].ErrCnt > 2U)
1484 {
1485 hhcd->hc[ch_num].ErrCnt = 0U;
1486 hhcd->hc[ch_num].urb_state = URB_ERROR;
1487 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num,
1488 hhcd->hc[ch_num].urb_state);
1489 }
1490 else
1491 {
1492 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1493 }
1494 }
1495 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
1496 }
1497 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR)
1498 {
1499 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1500 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1501 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1502 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
1503 hhcd->hc[ch_num].state = HC_DATATGLERR;
1504 }
1505 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH)
1506 {
1507 __HAL_HCD_MASK_HALT_HC_INT(ch_num);
1508
1509 if (hhcd->hc[ch_num].state == HC_XFRC)
1510 {
1511 hhcd->hc[ch_num].urb_state = URB_DONE;
1512 if ((hhcd->hc[ch_num].ep_type == EP_TYPE_BULK) ||
1513 (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR))
1514 {
1515 if (hhcd->Init.dma_enable == 0U)
1516 {
1517 hhcd->hc[ch_num].toggle_out ^= 1U;
1518 }
1519
1520 if ((hhcd->Init.dma_enable == 1U) && (hhcd->hc[ch_num].xfer_len > 0U))
1521 {
1522 num_packets = (hhcd->hc[ch_num].xfer_len + hhcd->hc[ch_num].max_packet - 1U) / hhcd->hc[ch_num].max_packet;
1523
1524 if ((num_packets & 1U) != 0U)
1525 {
1526 hhcd->hc[ch_num].toggle_out ^= 1U;
1527 }
1528 }
1529 }
1530 }
1531 else if (hhcd->hc[ch_num].state == HC_NAK)
1532 {
1533 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1534 }
1535 else if (hhcd->hc[ch_num].state == HC_NYET)
1536 {
1537 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1538 }
1539 else if (hhcd->hc[ch_num].state == HC_STALL)
1540 {
1541 hhcd->hc[ch_num].urb_state = URB_STALL;
1542 }
1543 else if ((hhcd->hc[ch_num].state == HC_XACTERR) ||
1544 (hhcd->hc[ch_num].state == HC_DATATGLERR))
1545 {
1546 hhcd->hc[ch_num].ErrCnt++;
1547 if (hhcd->hc[ch_num].ErrCnt > 2U)
1548 {
1549 hhcd->hc[ch_num].ErrCnt = 0U;
1550 hhcd->hc[ch_num].urb_state = URB_ERROR;
1551 }
1552 else
1553 {
1554 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1555
1556 /* re-activate the channel */
1557 tmpreg = USBx_HC(ch_num)->HCCHAR;
1558 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1559 tmpreg |= USB_OTG_HCCHAR_CHENA;
1560 USBx_HC(ch_num)->HCCHAR = tmpreg;
1561 }
1562 }
1563 else
1564 {
1565 /* ... */
1566 }
1567
1568 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
1569 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1570 }
1571 else
1572 {
1573 /* ... */
1574 }
1575 }
1576
1577 /**
1578 * @brief Handle Rx Queue Level interrupt requests.
1579 * @param hhcd HCD handle
1580 * @retval none
1581 */
HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef * hhcd)1582 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
1583 {
1584 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1585 uint32_t USBx_BASE = (uint32_t)USBx;
1586 uint32_t pktsts;
1587 uint32_t pktcnt;
1588 uint32_t GrxstspReg;
1589 uint32_t xferSizePktCnt;
1590 uint32_t tmpreg;
1591 uint32_t ch_num;
1592
1593 GrxstspReg = hhcd->Instance->GRXSTSP;
1594 ch_num = GrxstspReg & USB_OTG_GRXSTSP_EPNUM;
1595 pktsts = (GrxstspReg & USB_OTG_GRXSTSP_PKTSTS) >> 17;
1596 pktcnt = (GrxstspReg & USB_OTG_GRXSTSP_BCNT) >> 4;
1597
1598 switch (pktsts)
1599 {
1600 case GRXSTS_PKTSTS_IN:
1601 /* Read the data into the host buffer. */
1602 if ((pktcnt > 0U) && (hhcd->hc[ch_num].xfer_buff != (void *)0))
1603 {
1604 if ((hhcd->hc[ch_num].xfer_count + pktcnt) <= hhcd->hc[ch_num].xfer_len)
1605 {
1606 (void)USB_ReadPacket(hhcd->Instance,
1607 hhcd->hc[ch_num].xfer_buff, (uint16_t)pktcnt);
1608
1609 /* manage multiple Xfer */
1610 hhcd->hc[ch_num].xfer_buff += pktcnt;
1611 hhcd->hc[ch_num].xfer_count += pktcnt;
1612
1613 /* get transfer size packet count */
1614 xferSizePktCnt = (USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19;
1615
1616 if ((hhcd->hc[ch_num].max_packet == pktcnt) && (xferSizePktCnt > 0U))
1617 {
1618 /* re-activate the channel when more packets are expected */
1619 tmpreg = USBx_HC(ch_num)->HCCHAR;
1620 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1621 tmpreg |= USB_OTG_HCCHAR_CHENA;
1622 USBx_HC(ch_num)->HCCHAR = tmpreg;
1623 hhcd->hc[ch_num].toggle_in ^= 1U;
1624 }
1625 }
1626 else
1627 {
1628 hhcd->hc[ch_num].urb_state = URB_ERROR;
1629 }
1630 }
1631 break;
1632
1633 case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
1634 break;
1635
1636 case GRXSTS_PKTSTS_IN_XFER_COMP:
1637 case GRXSTS_PKTSTS_CH_HALTED:
1638 default:
1639 break;
1640 }
1641 }
1642
1643 /**
1644 * @brief Handle Host Port interrupt requests.
1645 * @param hhcd HCD handle
1646 * @retval None
1647 */
HCD_Port_IRQHandler(HCD_HandleTypeDef * hhcd)1648 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
1649 {
1650 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1651 uint32_t USBx_BASE = (uint32_t)USBx;
1652 __IO uint32_t hprt0;
1653 __IO uint32_t hprt0_dup;
1654
1655 /* Handle Host Port Interrupts */
1656 hprt0 = USBx_HPRT0;
1657 hprt0_dup = USBx_HPRT0;
1658
1659 hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
1660 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
1661
1662 /* Check whether Port Connect detected */
1663 if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
1664 {
1665 if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
1666 {
1667 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1668 hhcd->ConnectCallback(hhcd);
1669 #else
1670 HAL_HCD_Connect_Callback(hhcd);
1671 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1672 }
1673 hprt0_dup |= USB_OTG_HPRT_PCDET;
1674 }
1675
1676 /* Check whether Port Enable Changed */
1677 if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
1678 {
1679 hprt0_dup |= USB_OTG_HPRT_PENCHNG;
1680
1681 if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
1682 {
1683 if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
1684 {
1685 if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
1686 {
1687 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
1688 }
1689 else
1690 {
1691 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
1692 }
1693 }
1694 else
1695 {
1696 if (hhcd->Init.speed == HCD_SPEED_FULL)
1697 {
1698 USBx_HOST->HFIR = 60000U;
1699 }
1700 }
1701 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1702 hhcd->PortEnabledCallback(hhcd);
1703 #else
1704 HAL_HCD_PortEnabled_Callback(hhcd);
1705 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1706
1707 }
1708 else
1709 {
1710 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1711 hhcd->PortDisabledCallback(hhcd);
1712 #else
1713 HAL_HCD_PortDisabled_Callback(hhcd);
1714 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1715 }
1716 }
1717
1718 /* Check for an overcurrent */
1719 if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
1720 {
1721 hprt0_dup |= USB_OTG_HPRT_POCCHNG;
1722 }
1723
1724 /* Clear Port Interrupts */
1725 USBx_HPRT0 = hprt0_dup;
1726 }
1727
1728 /**
1729 * @}
1730 */
1731
1732 /**
1733 * @}
1734 */
1735
1736 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1737 #endif /* HAL_HCD_MODULE_ENABLED */
1738
1739 /**
1740 * @}
1741 */
1742
1743 /**
1744 * @}
1745 */
1746
1747 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
1748