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