Merge maintenance-8.x.x fixes into master
[inav.git] / lib / main / STM32H7 / Drivers / STM32H7xx_HAL_Driver / Src / stm32h7xx_hal_hcd.c
blobe1fbd004331a6c7a08ca2e9100f621274ede8d04
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
13 ******************************************************************************
14 * @attention
16 * Copyright (c) 2017 STMicroelectronics.
17 * All rights reserved.
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.
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;
32 (#)Fill parameters of Init structure in HCD handle
34 (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
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)
42 (##) Initialize the related GPIO clocks
43 (##) Configure HCD pin-out
44 (##) Configure HCD NVIC interrupt
46 (#)Associate the Upper USB Host stack to the HAL HCD Driver:
47 (##) hhcd.pData = phost;
49 (#)Enable HCD transmission and reception:
50 (##) HAL_HCD_Start();
52 @endverbatim
53 ******************************************************************************
56 /* Includes ------------------------------------------------------------------*/
57 #include "stm32h7xx_hal.h"
59 /** @addtogroup STM32H7xx_HAL_Driver
60 * @{
63 #ifdef HAL_HCD_MODULE_ENABLED
64 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
66 /** @defgroup HCD HCD
67 * @brief HCD HAL module driver
68 * @{
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 * @{
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 * @}
87 /* Exported functions --------------------------------------------------------*/
88 /** @defgroup HCD_Exported_Functions HCD Exported Functions
89 * @{
92 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
93 * @brief Initialization and Configuration functions
95 @verbatim
96 ===============================================================================
97 ##### Initialization and de-initialization functions #####
98 ===============================================================================
99 [..] This section provides functions allowing to:
101 @endverbatim
102 * @{
106 * @brief Initialize the host driver.
107 * @param hhcd HCD handle
108 * @retval HAL status
110 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
112 /* Check the HCD handle allocation */
113 if (hhcd == NULL)
115 return HAL_ERROR;
118 /* Check the parameters */
119 assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
121 if (hhcd->State == HAL_HCD_STATE_RESET)
123 /* Allocate lock resource and initialize it */
124 hhcd->Lock = HAL_UNLOCKED;
126 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
127 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
128 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
129 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
130 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
131 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
132 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;
134 if (hhcd->MspInitCallback == NULL)
136 hhcd->MspInitCallback = HAL_HCD_MspInit;
139 /* Init the low level hardware */
140 hhcd->MspInitCallback(hhcd);
141 #else
142 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
143 HAL_HCD_MspInit(hhcd);
144 #endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
147 hhcd->State = HAL_HCD_STATE_BUSY;
149 /* Disable the Interrupts */
150 __HAL_HCD_DISABLE(hhcd);
152 /* Init the Core (common init.) */
153 if (USB_CoreInit(hhcd->Instance, hhcd->Init) != HAL_OK)
155 hhcd->State = HAL_HCD_STATE_ERROR;
156 return HAL_ERROR;
159 /* Force Host Mode */
160 if (USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE) != HAL_OK)
162 hhcd->State = HAL_HCD_STATE_ERROR;
163 return HAL_ERROR;
166 /* Init Host */
167 if (USB_HostInit(hhcd->Instance, hhcd->Init) != HAL_OK)
169 hhcd->State = HAL_HCD_STATE_ERROR;
170 return HAL_ERROR;
173 hhcd->State = HAL_HCD_STATE_READY;
175 return HAL_OK;
179 * @brief Initialize a host channel.
180 * @param hhcd HCD handle
181 * @param ch_num Channel number.
182 * This parameter can be a value from 1 to 15
183 * @param epnum Endpoint number.
184 * This parameter can be a value from 1 to 15
185 * @param dev_address Current device address
186 * This parameter can be a value from 0 to 255
187 * @param speed Current device speed.
188 * This parameter can be one of these values:
189 * HCD_DEVICE_SPEED_HIGH: High speed mode,
190 * HCD_DEVICE_SPEED_FULL: Full speed mode,
191 * HCD_DEVICE_SPEED_LOW: Low speed mode
192 * @param ep_type Endpoint Type.
193 * This parameter can be one of these values:
194 * EP_TYPE_CTRL: Control type,
195 * EP_TYPE_ISOC: Isochronous type,
196 * EP_TYPE_BULK: Bulk type,
197 * EP_TYPE_INTR: Interrupt type
198 * @param mps Max Packet Size.
199 * This parameter can be a value from 0 to32K
200 * @retval HAL status
202 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t epnum,
203 uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps)
205 HAL_StatusTypeDef status;
206 uint32_t HostCoreSpeed;
207 uint32_t HCcharMps = mps;
209 __HAL_LOCK(hhcd);
210 hhcd->hc[ch_num].do_ping = 0U;
211 hhcd->hc[ch_num].dev_addr = dev_address;
212 hhcd->hc[ch_num].ch_num = ch_num;
213 hhcd->hc[ch_num].ep_type = ep_type;
214 hhcd->hc[ch_num].ep_num = epnum & 0x7FU;
216 (void)HAL_HCD_HC_ClearHubInfo(hhcd, ch_num);
218 if ((epnum & 0x80U) == 0x80U)
220 hhcd->hc[ch_num].ep_is_in = 1U;
222 else
224 hhcd->hc[ch_num].ep_is_in = 0U;
227 HostCoreSpeed = USB_GetHostSpeed(hhcd->Instance);
229 if (ep_type == EP_TYPE_ISOC)
231 /* FS device plugged to HS HUB */
232 if ((speed == HCD_DEVICE_SPEED_FULL) && (HostCoreSpeed == HPRT0_PRTSPD_HIGH_SPEED))
234 if (HCcharMps > ISO_SPLT_MPS)
236 /* ISO Max Packet Size for Split mode */
237 HCcharMps = ISO_SPLT_MPS;
242 hhcd->hc[ch_num].speed = speed;
243 hhcd->hc[ch_num].max_packet = (uint16_t)HCcharMps;
245 status = USB_HC_Init(hhcd->Instance, ch_num, epnum,
246 dev_address, speed, ep_type, (uint16_t)HCcharMps);
248 __HAL_UNLOCK(hhcd);
250 return status;
254 * @brief Halt a host channel.
255 * @param hhcd HCD handle
256 * @param ch_num Channel number.
257 * This parameter can be a value from 1 to 15
258 * @retval HAL status
260 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
262 HAL_StatusTypeDef status = HAL_OK;
264 __HAL_LOCK(hhcd);
265 (void)USB_HC_Halt(hhcd->Instance, ch_num);
266 __HAL_UNLOCK(hhcd);
268 return status;
272 * @brief DeInitialize the host driver.
273 * @param hhcd HCD handle
274 * @retval HAL status
276 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
278 /* Check the HCD handle allocation */
279 if (hhcd == NULL)
281 return HAL_ERROR;
284 hhcd->State = HAL_HCD_STATE_BUSY;
286 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
287 if (hhcd->MspDeInitCallback == NULL)
289 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */
292 /* DeInit the low level hardware */
293 hhcd->MspDeInitCallback(hhcd);
294 #else
295 /* DeInit the low level hardware: CLOCK, NVIC.*/
296 HAL_HCD_MspDeInit(hhcd);
297 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
299 __HAL_HCD_DISABLE(hhcd);
301 hhcd->State = HAL_HCD_STATE_RESET;
303 return HAL_OK;
307 * @brief Initialize the HCD MSP.
308 * @param hhcd HCD handle
309 * @retval None
311 __weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
313 /* Prevent unused argument(s) compilation warning */
314 UNUSED(hhcd);
316 /* NOTE : This function should not be modified, when the callback is needed,
317 the HAL_HCD_MspInit could be implemented in the user file
322 * @brief DeInitialize the HCD MSP.
323 * @param hhcd HCD handle
324 * @retval None
326 __weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
328 /* Prevent unused argument(s) compilation warning */
329 UNUSED(hhcd);
331 /* NOTE : This function should not be modified, when the callback is needed,
332 the HAL_HCD_MspDeInit could be implemented in the user file
337 * @}
340 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
341 * @brief HCD IO operation functions
343 @verbatim
344 ===============================================================================
345 ##### IO operation functions #####
346 ===============================================================================
347 [..] This subsection provides a set of functions allowing to manage the USB Host Data
348 Transfer
350 @endverbatim
351 * @{
355 * @brief Submit a new URB for processing.
356 * @param hhcd HCD handle
357 * @param ch_num Channel number.
358 * This parameter can be a value from 1 to 15
359 * @param direction Channel number.
360 * This parameter can be one of these values:
361 * 0 : Output / 1 : Input
362 * @param ep_type Endpoint Type.
363 * This parameter can be one of these values:
364 * EP_TYPE_CTRL: Control type/
365 * EP_TYPE_ISOC: Isochronous type/
366 * EP_TYPE_BULK: Bulk type/
367 * EP_TYPE_INTR: Interrupt type/
368 * @param token Endpoint Type.
369 * This parameter can be one of these values:
370 * 0: HC_PID_SETUP / 1: HC_PID_DATA1
371 * @param pbuff pointer to URB data
372 * @param length Length of URB data
373 * @param do_ping activate do ping protocol (for high speed only).
374 * This parameter can be one of these values:
375 * 0 : do ping inactive / 1 : do ping active
376 * @retval HAL status
378 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
379 uint8_t ch_num,
380 uint8_t direction,
381 uint8_t ep_type,
382 uint8_t token,
383 uint8_t *pbuff,
384 uint16_t length,
385 uint8_t do_ping)
387 hhcd->hc[ch_num].ep_is_in = direction;
388 hhcd->hc[ch_num].ep_type = ep_type;
390 if (token == 0U)
392 hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
393 hhcd->hc[ch_num].do_ping = do_ping;
395 else
397 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
400 /* Manage Data Toggle */
401 switch (ep_type)
403 case EP_TYPE_CTRL:
404 if (token == 1U) /* send data */
406 if (direction == 0U)
408 if (length == 0U)
410 /* For Status OUT stage, Length == 0U, Status Out PID = 1 */
411 hhcd->hc[ch_num].toggle_out = 1U;
414 /* Set the Data Toggle bit as per the Flag */
415 if (hhcd->hc[ch_num].toggle_out == 0U)
417 /* Put the PID 0 */
418 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
420 else
422 /* Put the PID 1 */
423 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
426 else
428 if (hhcd->hc[ch_num].do_ssplit == 1U)
430 if (hhcd->hc[ch_num].toggle_in == 0U)
432 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
434 else
436 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
441 break;
443 case EP_TYPE_BULK:
444 if (direction == 0U)
446 /* Set the Data Toggle bit as per the Flag */
447 if (hhcd->hc[ch_num].toggle_out == 0U)
449 /* Put the PID 0 */
450 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
452 else
454 /* Put the PID 1 */
455 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
458 else
460 if (hhcd->hc[ch_num].toggle_in == 0U)
462 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
464 else
466 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
470 break;
471 case EP_TYPE_INTR:
472 if (direction == 0U)
474 /* Set the Data Toggle bit as per the Flag */
475 if (hhcd->hc[ch_num].toggle_out == 0U)
477 /* Put the PID 0 */
478 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
480 else
482 /* Put the PID 1 */
483 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
486 else
488 if (hhcd->hc[ch_num].toggle_in == 0U)
490 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
492 else
494 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
497 break;
499 case EP_TYPE_ISOC:
500 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
501 break;
503 default:
504 break;
507 hhcd->hc[ch_num].xfer_buff = pbuff;
508 hhcd->hc[ch_num].xfer_len = length;
509 hhcd->hc[ch_num].urb_state = URB_IDLE;
510 hhcd->hc[ch_num].xfer_count = 0U;
511 hhcd->hc[ch_num].ch_num = ch_num;
512 hhcd->hc[ch_num].state = HC_IDLE;
514 return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num], (uint8_t)hhcd->Init.dma_enable);
518 * @brief Handle HCD interrupt request.
519 * @param hhcd HCD handle
520 * @retval None
522 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
524 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
525 uint32_t USBx_BASE = (uint32_t)USBx;
526 uint32_t i;
527 uint32_t interrupt;
529 /* Ensure that we are in device mode */
530 if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
532 /* Avoid spurious interrupt */
533 if (__HAL_HCD_IS_INVALID_INTERRUPT(hhcd))
535 return;
538 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
540 /* Incorrect mode, acknowledge the interrupt */
541 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
544 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
546 /* Incorrect mode, acknowledge the interrupt */
547 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
550 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
552 /* Incorrect mode, acknowledge the interrupt */
553 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
556 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
558 /* Incorrect mode, acknowledge the interrupt */
559 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
562 /* Handle Host Disconnect Interrupts */
563 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
565 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
567 if ((USBx_HPRT0 & USB_OTG_HPRT_PCSTS) == 0U)
569 /* Flush USB Fifo */
570 (void)USB_FlushTxFifo(USBx, 0x10U);
571 (void)USB_FlushRxFifo(USBx);
573 if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
575 /* Restore FS Clock */
576 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
579 /* Handle Host Port Disconnect Interrupt */
580 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
581 hhcd->DisconnectCallback(hhcd);
582 #else
583 HAL_HCD_Disconnect_Callback(hhcd);
584 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
588 /* Handle Host Port Interrupts */
589 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
591 HCD_Port_IRQHandler(hhcd);
594 /* Handle Host SOF Interrupt */
595 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
597 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
598 hhcd->SOFCallback(hhcd);
599 #else
600 HAL_HCD_SOF_Callback(hhcd);
601 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
603 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
606 /* Handle Host channel Interrupt */
607 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
609 interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
610 for (i = 0U; i < hhcd->Init.Host_channels; i++)
612 if ((interrupt & (1UL << (i & 0xFU))) != 0U)
614 if ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR)
616 HCD_HC_IN_IRQHandler(hhcd, (uint8_t)i);
618 else
620 HCD_HC_OUT_IRQHandler(hhcd, (uint8_t)i);
624 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
627 /* Handle Rx Queue Level Interrupts */
628 if ((__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) != 0U)
630 USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
632 HCD_RXQLVL_IRQHandler(hhcd);
634 USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
641 * @brief SOF callback.
642 * @param hhcd HCD handle
643 * @retval None
645 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
647 /* Prevent unused argument(s) compilation warning */
648 UNUSED(hhcd);
650 /* NOTE : This function should not be modified, when the callback is needed,
651 the HAL_HCD_SOF_Callback could be implemented in the user file
656 * @brief Connection Event callback.
657 * @param hhcd HCD handle
658 * @retval None
660 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
662 /* Prevent unused argument(s) compilation warning */
663 UNUSED(hhcd);
665 /* NOTE : This function should not be modified, when the callback is needed,
666 the HAL_HCD_Connect_Callback could be implemented in the user file
671 * @brief Disconnection Event callback.
672 * @param hhcd HCD handle
673 * @retval None
675 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
677 /* Prevent unused argument(s) compilation warning */
678 UNUSED(hhcd);
680 /* NOTE : This function should not be modified, when the callback is needed,
681 the HAL_HCD_Disconnect_Callback could be implemented in the user file
686 * @brief Port Enabled Event callback.
687 * @param hhcd HCD handle
688 * @retval None
690 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
692 /* Prevent unused argument(s) compilation warning */
693 UNUSED(hhcd);
695 /* NOTE : This function should not be modified, when the callback is needed,
696 the HAL_HCD_Disconnect_Callback could be implemented in the user file
701 * @brief Port Disabled Event callback.
702 * @param hhcd HCD handle
703 * @retval None
705 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
707 /* Prevent unused argument(s) compilation warning */
708 UNUSED(hhcd);
710 /* NOTE : This function should not be modified, when the callback is needed,
711 the HAL_HCD_Disconnect_Callback could be implemented in the user file
716 * @brief Notify URB state change callback.
717 * @param hhcd HCD handle
718 * @param chnum Channel number.
719 * This parameter can be a value from 1 to 15
720 * @param urb_state:
721 * This parameter can be one of these values:
722 * URB_IDLE/
723 * URB_DONE/
724 * URB_NOTREADY/
725 * URB_NYET/
726 * URB_ERROR/
727 * URB_STALL/
728 * @retval None
730 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
732 /* Prevent unused argument(s) compilation warning */
733 UNUSED(hhcd);
734 UNUSED(chnum);
735 UNUSED(urb_state);
737 /* NOTE : This function should not be modified, when the callback is needed,
738 the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
742 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
744 * @brief Register a User USB HCD Callback
745 * To be used instead of the weak predefined callback
746 * @param hhcd USB HCD handle
747 * @param CallbackID ID of the callback to be registered
748 * This parameter can be one of the following values:
749 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
750 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
751 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
752 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
753 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
754 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
755 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
756 * @param pCallback pointer to the Callback function
757 * @retval HAL status
759 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
760 HAL_HCD_CallbackIDTypeDef CallbackID,
761 pHCD_CallbackTypeDef pCallback)
763 HAL_StatusTypeDef status = HAL_OK;
765 if (pCallback == NULL)
767 /* Update the error code */
768 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
769 return HAL_ERROR;
771 /* Process locked */
772 __HAL_LOCK(hhcd);
774 if (hhcd->State == HAL_HCD_STATE_READY)
776 switch (CallbackID)
778 case HAL_HCD_SOF_CB_ID :
779 hhcd->SOFCallback = pCallback;
780 break;
782 case HAL_HCD_CONNECT_CB_ID :
783 hhcd->ConnectCallback = pCallback;
784 break;
786 case HAL_HCD_DISCONNECT_CB_ID :
787 hhcd->DisconnectCallback = pCallback;
788 break;
790 case HAL_HCD_PORT_ENABLED_CB_ID :
791 hhcd->PortEnabledCallback = pCallback;
792 break;
794 case HAL_HCD_PORT_DISABLED_CB_ID :
795 hhcd->PortDisabledCallback = pCallback;
796 break;
798 case HAL_HCD_MSPINIT_CB_ID :
799 hhcd->MspInitCallback = pCallback;
800 break;
802 case HAL_HCD_MSPDEINIT_CB_ID :
803 hhcd->MspDeInitCallback = pCallback;
804 break;
806 default :
807 /* Update the error code */
808 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
809 /* Return error status */
810 status = HAL_ERROR;
811 break;
814 else if (hhcd->State == HAL_HCD_STATE_RESET)
816 switch (CallbackID)
818 case HAL_HCD_MSPINIT_CB_ID :
819 hhcd->MspInitCallback = pCallback;
820 break;
822 case HAL_HCD_MSPDEINIT_CB_ID :
823 hhcd->MspDeInitCallback = pCallback;
824 break;
826 default :
827 /* Update the error code */
828 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
829 /* Return error status */
830 status = HAL_ERROR;
831 break;
834 else
836 /* Update the error code */
837 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
838 /* Return error status */
839 status = HAL_ERROR;
842 /* Release Lock */
843 __HAL_UNLOCK(hhcd);
844 return status;
848 * @brief Unregister an USB HCD Callback
849 * USB HCD callback is redirected to the weak predefined callback
850 * @param hhcd USB HCD handle
851 * @param CallbackID ID of the callback to be unregistered
852 * This parameter can be one of the following values:
853 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
854 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
855 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
856 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
857 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
858 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
859 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
860 * @retval HAL status
862 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID)
864 HAL_StatusTypeDef status = HAL_OK;
866 /* Process locked */
867 __HAL_LOCK(hhcd);
869 /* Setup Legacy weak Callbacks */
870 if (hhcd->State == HAL_HCD_STATE_READY)
872 switch (CallbackID)
874 case HAL_HCD_SOF_CB_ID :
875 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
876 break;
878 case HAL_HCD_CONNECT_CB_ID :
879 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
880 break;
882 case HAL_HCD_DISCONNECT_CB_ID :
883 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
884 break;
886 case HAL_HCD_PORT_ENABLED_CB_ID :
887 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
888 break;
890 case HAL_HCD_PORT_DISABLED_CB_ID :
891 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
892 break;
894 case HAL_HCD_MSPINIT_CB_ID :
895 hhcd->MspInitCallback = HAL_HCD_MspInit;
896 break;
898 case HAL_HCD_MSPDEINIT_CB_ID :
899 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
900 break;
902 default :
903 /* Update the error code */
904 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
906 /* Return error status */
907 status = HAL_ERROR;
908 break;
911 else if (hhcd->State == HAL_HCD_STATE_RESET)
913 switch (CallbackID)
915 case HAL_HCD_MSPINIT_CB_ID :
916 hhcd->MspInitCallback = HAL_HCD_MspInit;
917 break;
919 case HAL_HCD_MSPDEINIT_CB_ID :
920 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
921 break;
923 default :
924 /* Update the error code */
925 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
927 /* Return error status */
928 status = HAL_ERROR;
929 break;
932 else
934 /* Update the error code */
935 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
937 /* Return error status */
938 status = HAL_ERROR;
941 /* Release Lock */
942 __HAL_UNLOCK(hhcd);
943 return status;
947 * @brief Register USB HCD Host Channel Notify URB Change Callback
948 * To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
949 * @param hhcd HCD handle
950 * @param pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
951 * @retval HAL status
953 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
954 pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
956 HAL_StatusTypeDef status = HAL_OK;
958 if (pCallback == NULL)
960 /* Update the error code */
961 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
963 return HAL_ERROR;
966 /* Process locked */
967 __HAL_LOCK(hhcd);
969 if (hhcd->State == HAL_HCD_STATE_READY)
971 hhcd->HC_NotifyURBChangeCallback = pCallback;
973 else
975 /* Update the error code */
976 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
978 /* Return error status */
979 status = HAL_ERROR;
982 /* Release Lock */
983 __HAL_UNLOCK(hhcd);
985 return status;
989 * @brief Unregister the USB HCD Host Channel Notify URB Change Callback
990 * USB HCD Host Channel Notify URB Change Callback is redirected
991 * to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
992 * @param hhcd HCD handle
993 * @retval HAL status
995 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
997 HAL_StatusTypeDef status = HAL_OK;
999 /* Process locked */
1000 __HAL_LOCK(hhcd);
1002 if (hhcd->State == HAL_HCD_STATE_READY)
1004 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
1006 else
1008 /* Update the error code */
1009 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1011 /* Return error status */
1012 status = HAL_ERROR;
1015 /* Release Lock */
1016 __HAL_UNLOCK(hhcd);
1018 return status;
1020 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1023 * @}
1026 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
1027 * @brief Management functions
1029 @verbatim
1030 ===============================================================================
1031 ##### Peripheral Control functions #####
1032 ===============================================================================
1033 [..]
1034 This subsection provides a set of functions allowing to control the HCD data
1035 transfers.
1037 @endverbatim
1038 * @{
1042 * @brief Start the host driver.
1043 * @param hhcd HCD handle
1044 * @retval HAL status
1046 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
1048 __HAL_LOCK(hhcd);
1049 /* Enable port power */
1050 (void)USB_DriveVbus(hhcd->Instance, 1U);
1052 /* Enable global interrupt */
1053 __HAL_HCD_ENABLE(hhcd);
1054 __HAL_UNLOCK(hhcd);
1056 return HAL_OK;
1060 * @brief Stop the host driver.
1061 * @param hhcd HCD handle
1062 * @retval HAL status
1065 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
1067 __HAL_LOCK(hhcd);
1068 (void)USB_StopHost(hhcd->Instance);
1069 __HAL_UNLOCK(hhcd);
1071 return HAL_OK;
1075 * @brief Reset the host port.
1076 * @param hhcd HCD handle
1077 * @retval HAL status
1079 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
1081 return (USB_ResetPort(hhcd->Instance));
1085 * @}
1088 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
1089 * @brief Peripheral State functions
1091 @verbatim
1092 ===============================================================================
1093 ##### Peripheral State functions #####
1094 ===============================================================================
1095 [..]
1096 This subsection permits to get in run-time the status of the peripheral
1097 and the data flow.
1099 @endverbatim
1100 * @{
1104 * @brief Return the HCD handle state.
1105 * @param hhcd HCD handle
1106 * @retval HAL state
1108 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef const *hhcd)
1110 return hhcd->State;
1114 * @brief Return URB state for a channel.
1115 * @param hhcd HCD handle
1116 * @param chnum Channel number.
1117 * This parameter can be a value from 1 to 15
1118 * @retval URB state.
1119 * This parameter can be one of these values:
1120 * URB_IDLE/
1121 * URB_DONE/
1122 * URB_NOTREADY/
1123 * URB_NYET/
1124 * URB_ERROR/
1125 * URB_STALL
1127 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1129 return hhcd->hc[chnum].urb_state;
1134 * @brief Return the last host transfer size.
1135 * @param hhcd HCD handle
1136 * @param chnum Channel number.
1137 * This parameter can be a value from 1 to 15
1138 * @retval last transfer size in byte
1140 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1142 return hhcd->hc[chnum].xfer_count;
1146 * @brief Return the Host Channel state.
1147 * @param hhcd HCD handle
1148 * @param chnum Channel number.
1149 * This parameter can be a value from 1 to 15
1150 * @retval Host channel state
1151 * This parameter can be one of these values:
1152 * HC_IDLE/
1153 * HC_XFRC/
1154 * HC_HALTED/
1155 * HC_NYET/
1156 * HC_NAK/
1157 * HC_STALL/
1158 * HC_XACTERR/
1159 * HC_BBLERR/
1160 * HC_DATATGLERR
1162 HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1164 return hhcd->hc[chnum].state;
1168 * @brief Return the current Host frame number.
1169 * @param hhcd HCD handle
1170 * @retval Current Host frame number
1172 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
1174 return (USB_GetCurrentFrame(hhcd->Instance));
1178 * @brief Return the Host enumeration speed.
1179 * @param hhcd HCD handle
1180 * @retval Enumeration speed
1182 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
1184 return (USB_GetHostSpeed(hhcd->Instance));
1188 * @brief Set host channel Hub information.
1189 * @param hhcd HCD handle
1190 * @param ch_num Channel number.
1191 * This parameter can be a value from 1 to 15
1192 * @param addr Hub address
1193 * @param PortNbr Hub port number
1194 * @retval HAL status
1196 HAL_StatusTypeDef HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1197 uint8_t addr, uint8_t PortNbr)
1199 uint32_t HostCoreSpeed = USB_GetHostSpeed(hhcd->Instance);
1201 /* LS/FS device plugged to HS HUB */
1202 if ((hhcd->hc[ch_num].speed != HCD_DEVICE_SPEED_HIGH) && (HostCoreSpeed == HPRT0_PRTSPD_HIGH_SPEED))
1204 hhcd->hc[ch_num].do_ssplit = 1U;
1206 if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) && (hhcd->hc[ch_num].ep_is_in != 0U))
1208 hhcd->hc[ch_num].toggle_in = 1U;
1212 hhcd->hc[ch_num].hub_addr = addr;
1213 hhcd->hc[ch_num].hub_port_nbr = PortNbr;
1215 return HAL_OK;
1220 * @brief Clear host channel hub information.
1221 * @param hhcd HCD handle
1222 * @param ch_num Channel number.
1223 * This parameter can be a value from 1 to 15
1224 * @retval HAL status
1226 HAL_StatusTypeDef HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
1228 hhcd->hc[ch_num].do_ssplit = 0U;
1229 hhcd->hc[ch_num].do_csplit = 0U;
1230 hhcd->hc[ch_num].hub_addr = 0U;
1231 hhcd->hc[ch_num].hub_port_nbr = 0U;
1233 return HAL_OK;
1236 * @}
1240 * @}
1243 /** @addtogroup HCD_Private_Functions
1244 * @{
1247 * @brief Handle Host Channel IN interrupt requests.
1248 * @param hhcd HCD handle
1249 * @param chnum Channel number.
1250 * This parameter can be a value from 1 to 15
1251 * @retval none
1253 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1255 const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1256 uint32_t USBx_BASE = (uint32_t)USBx;
1257 uint32_t tmpreg;
1259 if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
1261 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
1262 hhcd->hc[chnum].state = HC_XACTERR;
1263 (void)USB_HC_Halt(hhcd->Instance, chnum);
1265 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_BBERR))
1267 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_BBERR);
1268 hhcd->hc[chnum].state = HC_BBLERR;
1269 (void)USB_HC_Halt(hhcd->Instance, chnum);
1271 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
1273 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
1274 hhcd->hc[chnum].state = HC_STALL;
1275 (void)USB_HC_Halt(hhcd->Instance, chnum);
1277 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
1279 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
1280 hhcd->hc[chnum].state = HC_DATATGLERR;
1281 (void)USB_HC_Halt(hhcd->Instance, chnum);
1283 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
1285 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
1286 hhcd->hc[chnum].state = HC_XACTERR;
1287 (void)USB_HC_Halt(hhcd->Instance, chnum);
1289 else
1291 /* ... */
1294 if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
1296 (void)USB_HC_Halt(hhcd->Instance, chnum);
1297 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
1299 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
1301 /* Clear any pending ACK IT */
1302 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1304 if (hhcd->hc[chnum].do_csplit == 1U)
1306 hhcd->hc[chnum].do_csplit = 0U;
1307 __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1310 if (hhcd->Init.dma_enable != 0U)
1312 hhcd->hc[chnum].xfer_count = hhcd->hc[chnum].XferSize - (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
1315 hhcd->hc[chnum].state = HC_XFRC;
1316 hhcd->hc[chnum].ErrCnt = 0U;
1317 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
1319 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1320 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1322 (void)USB_HC_Halt(hhcd->Instance, chnum);
1323 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1325 else if ((hhcd->hc[chnum].ep_type == EP_TYPE_INTR) ||
1326 (hhcd->hc[chnum].ep_type == EP_TYPE_ISOC))
1328 USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
1329 hhcd->hc[chnum].urb_state = URB_DONE;
1331 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1332 hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1333 #else
1334 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1335 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1337 else
1339 /* ... */
1342 if (hhcd->Init.dma_enable == 1U)
1344 if ((((hhcd->hc[chnum].xfer_count + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet) & 1U) != 0U)
1346 hhcd->hc[chnum].toggle_in ^= 1U;
1349 else
1351 hhcd->hc[chnum].toggle_in ^= 1U;
1354 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
1356 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1358 if (hhcd->hc[chnum].do_ssplit == 1U)
1360 hhcd->hc[chnum].do_csplit = 1U;
1361 hhcd->hc[chnum].state = HC_ACK;
1363 (void)USB_HC_Halt(hhcd->Instance, chnum);
1366 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
1368 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
1370 if (hhcd->hc[chnum].state == HC_XFRC)
1372 hhcd->hc[chnum].state = HC_HALTED;
1373 hhcd->hc[chnum].urb_state = URB_DONE;
1375 else if (hhcd->hc[chnum].state == HC_STALL)
1377 hhcd->hc[chnum].state = HC_HALTED;
1378 hhcd->hc[chnum].urb_state = URB_STALL;
1380 else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
1381 (hhcd->hc[chnum].state == HC_DATATGLERR))
1383 hhcd->hc[chnum].state = HC_HALTED;
1384 hhcd->hc[chnum].ErrCnt++;
1385 if (hhcd->hc[chnum].ErrCnt > 2U)
1387 hhcd->hc[chnum].ErrCnt = 0U;
1389 if (hhcd->hc[chnum].do_ssplit == 1U)
1391 hhcd->hc[chnum].do_csplit = 0U;
1392 hhcd->hc[chnum].ep_ss_schedule = 0U;
1393 __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1396 hhcd->hc[chnum].urb_state = URB_ERROR;
1398 else
1400 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1402 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1403 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1405 /* re-activate the channel */
1406 tmpreg = USBx_HC(chnum)->HCCHAR;
1407 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1408 tmpreg |= USB_OTG_HCCHAR_CHENA;
1409 USBx_HC(chnum)->HCCHAR = tmpreg;
1413 else if (hhcd->hc[chnum].state == HC_NYET)
1415 hhcd->hc[chnum].state = HC_HALTED;
1417 if (hhcd->hc[chnum].do_csplit == 1U)
1419 if (hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
1421 hhcd->hc[chnum].NyetErrCnt++;
1422 if (hhcd->hc[chnum].NyetErrCnt > 2U)
1424 hhcd->hc[chnum].NyetErrCnt = 0U;
1425 hhcd->hc[chnum].do_csplit = 0U;
1427 if (hhcd->hc[chnum].ErrCnt < 3U)
1429 hhcd->hc[chnum].ep_ss_schedule = 1U;
1431 __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1432 hhcd->hc[chnum].urb_state = URB_ERROR;
1434 else
1436 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1439 else
1441 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1444 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1445 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1447 /* re-activate the channel */
1448 tmpreg = USBx_HC(chnum)->HCCHAR;
1449 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1450 tmpreg |= USB_OTG_HCCHAR_CHENA;
1451 USBx_HC(chnum)->HCCHAR = tmpreg;
1455 else if (hhcd->hc[chnum].state == HC_ACK)
1457 hhcd->hc[chnum].state = HC_HALTED;
1459 if (hhcd->hc[chnum].do_csplit == 1U)
1461 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1463 /* Set Complete split and re-activate the channel */
1464 USBx_HC(chnum)->HCSPLT |= USB_OTG_HCSPLT_COMPLSPLT;
1465 USBx_HC(chnum)->HCINTMSK |= USB_OTG_HCINTMSK_NYET;
1466 USBx_HC(chnum)->HCINTMSK &= ~USB_OTG_HCINT_ACK;
1468 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1469 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1471 /* re-activate the channel */
1472 tmpreg = USBx_HC(chnum)->HCCHAR;
1473 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1474 tmpreg |= USB_OTG_HCCHAR_CHENA;
1475 USBx_HC(chnum)->HCCHAR = tmpreg;
1479 else if (hhcd->hc[chnum].state == HC_NAK)
1481 hhcd->hc[chnum].state = HC_HALTED;
1482 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1484 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1485 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1487 /* re-activate the channel */
1488 tmpreg = USBx_HC(chnum)->HCCHAR;
1489 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1490 tmpreg |= USB_OTG_HCCHAR_CHENA;
1491 USBx_HC(chnum)->HCCHAR = tmpreg;
1494 else if (hhcd->hc[chnum].state == HC_BBLERR)
1496 hhcd->hc[chnum].state = HC_HALTED;
1497 hhcd->hc[chnum].ErrCnt++;
1498 hhcd->hc[chnum].urb_state = URB_ERROR;
1500 else
1502 if (hhcd->hc[chnum].state == HC_HALTED)
1504 return;
1508 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1509 hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1510 #else
1511 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1512 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1514 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
1516 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
1517 hhcd->hc[chnum].state = HC_NYET;
1519 if (hhcd->hc[chnum].do_ssplit == 0U)
1521 hhcd->hc[chnum].ErrCnt = 0U;
1524 (void)USB_HC_Halt(hhcd->Instance, chnum);
1526 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
1528 if (hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
1530 hhcd->hc[chnum].ErrCnt = 0U;
1531 hhcd->hc[chnum].state = HC_NAK;
1532 (void)USB_HC_Halt(hhcd->Instance, chnum);
1534 else if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1535 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1537 hhcd->hc[chnum].ErrCnt = 0U;
1539 if ((hhcd->Init.dma_enable == 0U) || (hhcd->hc[chnum].do_csplit == 1U))
1541 hhcd->hc[chnum].state = HC_NAK;
1542 (void)USB_HC_Halt(hhcd->Instance, chnum);
1545 else
1547 /* ... */
1550 if (hhcd->hc[chnum].do_csplit == 1U)
1552 hhcd->hc[chnum].do_csplit = 0U;
1553 __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1554 __HAL_HCD_UNMASK_ACK_HC_INT(chnum);
1557 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1559 else
1561 /* ... */
1566 * @brief Handle Host Channel OUT interrupt requests.
1567 * @param hhcd HCD handle
1568 * @param chnum Channel number.
1569 * This parameter can be a value from 1 to 15
1570 * @retval none
1572 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1574 const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1575 uint32_t USBx_BASE = (uint32_t)USBx;
1576 uint32_t tmpreg;
1577 uint32_t num_packets;
1579 if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
1581 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
1582 hhcd->hc[chnum].state = HC_XACTERR;
1583 (void)USB_HC_Halt(hhcd->Instance, chnum);
1585 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
1587 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1589 if (hhcd->hc[chnum].do_ping == 1U)
1591 hhcd->hc[chnum].do_ping = 0U;
1592 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1593 hhcd->hc[chnum].state = HC_ACK;
1594 (void)USB_HC_Halt(hhcd->Instance, chnum);
1597 if ((hhcd->hc[chnum].do_ssplit == 1U) && (hhcd->hc[chnum].do_csplit == 0U))
1599 if (hhcd->hc[chnum].ep_type != EP_TYPE_ISOC)
1601 hhcd->hc[chnum].do_csplit = 1U;
1604 hhcd->hc[chnum].state = HC_ACK;
1605 (void)USB_HC_Halt(hhcd->Instance, chnum);
1607 /* reset error_count */
1608 hhcd->hc[chnum].ErrCnt = 0U;
1611 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
1613 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
1614 (void)USB_HC_Halt(hhcd->Instance, chnum);
1616 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
1618 hhcd->hc[chnum].ErrCnt = 0U;
1620 /* transaction completed with NYET state, update do ping state */
1621 if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
1623 hhcd->hc[chnum].do_ping = 1U;
1624 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
1627 if (hhcd->hc[chnum].do_csplit != 0U)
1629 hhcd->hc[chnum].do_csplit = 0U;
1630 __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1633 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
1634 hhcd->hc[chnum].state = HC_XFRC;
1635 (void)USB_HC_Halt(hhcd->Instance, chnum);
1637 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
1639 hhcd->hc[chnum].state = HC_NYET;
1641 if (hhcd->hc[chnum].do_ssplit == 0U)
1643 hhcd->hc[chnum].do_ping = 1U;
1646 hhcd->hc[chnum].ErrCnt = 0U;
1647 (void)USB_HC_Halt(hhcd->Instance, chnum);
1648 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
1650 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
1652 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
1653 hhcd->hc[chnum].state = HC_STALL;
1654 (void)USB_HC_Halt(hhcd->Instance, chnum);
1656 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
1658 hhcd->hc[chnum].ErrCnt = 0U;
1659 hhcd->hc[chnum].state = HC_NAK;
1661 if (hhcd->hc[chnum].do_ping == 0U)
1663 if (hhcd->hc[chnum].speed == HCD_DEVICE_SPEED_HIGH)
1665 hhcd->hc[chnum].do_ping = 1U;
1669 (void)USB_HC_Halt(hhcd->Instance, chnum);
1670 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1672 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
1674 if (hhcd->Init.dma_enable == 0U)
1676 hhcd->hc[chnum].state = HC_XACTERR;
1677 (void)USB_HC_Halt(hhcd->Instance, chnum);
1679 else
1681 hhcd->hc[chnum].ErrCnt++;
1682 if (hhcd->hc[chnum].ErrCnt > 2U)
1684 hhcd->hc[chnum].ErrCnt = 0U;
1685 hhcd->hc[chnum].urb_state = URB_ERROR;
1687 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1688 hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1689 #else
1690 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1691 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1693 else
1695 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1697 /* Re-activate the channel */
1698 tmpreg = USBx_HC(chnum)->HCCHAR;
1699 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1700 tmpreg |= USB_OTG_HCCHAR_CHENA;
1701 USBx_HC(chnum)->HCCHAR = tmpreg;
1704 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
1706 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
1708 hhcd->hc[chnum].state = HC_DATATGLERR;
1709 (void)USB_HC_Halt(hhcd->Instance, chnum);
1710 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
1712 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
1714 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
1716 if (hhcd->hc[chnum].state == HC_XFRC)
1718 hhcd->hc[chnum].state = HC_HALTED;
1719 hhcd->hc[chnum].urb_state = URB_DONE;
1721 if ((hhcd->hc[chnum].ep_type == EP_TYPE_BULK) ||
1722 (hhcd->hc[chnum].ep_type == EP_TYPE_INTR))
1724 if (hhcd->Init.dma_enable == 0U)
1726 hhcd->hc[chnum].toggle_out ^= 1U;
1729 if ((hhcd->Init.dma_enable == 1U) && (hhcd->hc[chnum].xfer_len > 0U))
1731 num_packets = (hhcd->hc[chnum].xfer_len + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet;
1733 if ((num_packets & 1U) != 0U)
1735 hhcd->hc[chnum].toggle_out ^= 1U;
1740 else if (hhcd->hc[chnum].state == HC_ACK)
1742 hhcd->hc[chnum].state = HC_HALTED;
1744 if (hhcd->hc[chnum].do_csplit == 1U)
1746 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1749 else if (hhcd->hc[chnum].state == HC_NAK)
1751 hhcd->hc[chnum].state = HC_HALTED;
1752 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1754 if (hhcd->hc[chnum].do_csplit == 1U)
1756 hhcd->hc[chnum].do_csplit = 0U;
1757 __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1760 else if (hhcd->hc[chnum].state == HC_NYET)
1762 hhcd->hc[chnum].state = HC_HALTED;
1763 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1765 else if (hhcd->hc[chnum].state == HC_STALL)
1767 hhcd->hc[chnum].state = HC_HALTED;
1768 hhcd->hc[chnum].urb_state = URB_STALL;
1770 else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
1771 (hhcd->hc[chnum].state == HC_DATATGLERR))
1773 hhcd->hc[chnum].state = HC_HALTED;
1774 hhcd->hc[chnum].ErrCnt++;
1775 if (hhcd->hc[chnum].ErrCnt > 2U)
1777 hhcd->hc[chnum].ErrCnt = 0U;
1778 hhcd->hc[chnum].urb_state = URB_ERROR;
1780 else
1782 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1784 /* re-activate the channel */
1785 tmpreg = USBx_HC(chnum)->HCCHAR;
1786 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1787 tmpreg |= USB_OTG_HCCHAR_CHENA;
1788 USBx_HC(chnum)->HCCHAR = tmpreg;
1791 else
1793 return;
1796 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1797 hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1798 #else
1799 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1800 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1802 else
1804 return;
1809 * @brief Handle Rx Queue Level interrupt requests.
1810 * @param hhcd HCD handle
1811 * @retval none
1813 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
1815 const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1816 uint32_t USBx_BASE = (uint32_t)USBx;
1817 uint32_t pktsts;
1818 uint32_t pktcnt;
1819 uint32_t GrxstspReg;
1820 uint32_t xferSizePktCnt;
1821 uint32_t tmpreg;
1822 uint32_t chnum;
1824 GrxstspReg = hhcd->Instance->GRXSTSP;
1825 chnum = GrxstspReg & USB_OTG_GRXSTSP_EPNUM;
1826 pktsts = (GrxstspReg & USB_OTG_GRXSTSP_PKTSTS) >> 17;
1827 pktcnt = (GrxstspReg & USB_OTG_GRXSTSP_BCNT) >> 4;
1829 switch (pktsts)
1831 case GRXSTS_PKTSTS_IN:
1832 /* Read the data into the host buffer. */
1833 if ((pktcnt > 0U) && (hhcd->hc[chnum].xfer_buff != (void *)0))
1835 if ((hhcd->hc[chnum].xfer_count + pktcnt) <= hhcd->hc[chnum].xfer_len)
1837 (void)USB_ReadPacket(hhcd->Instance,
1838 hhcd->hc[chnum].xfer_buff, (uint16_t)pktcnt);
1840 /* manage multiple Xfer */
1841 hhcd->hc[chnum].xfer_buff += pktcnt;
1842 hhcd->hc[chnum].xfer_count += pktcnt;
1844 /* get transfer size packet count */
1845 xferSizePktCnt = (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19;
1847 if ((hhcd->hc[chnum].max_packet == pktcnt) && (xferSizePktCnt > 0U))
1849 /* re-activate the channel when more packets are expected */
1850 tmpreg = USBx_HC(chnum)->HCCHAR;
1851 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1852 tmpreg |= USB_OTG_HCCHAR_CHENA;
1853 USBx_HC(chnum)->HCCHAR = tmpreg;
1854 hhcd->hc[chnum].toggle_in ^= 1U;
1857 else
1859 hhcd->hc[chnum].urb_state = URB_ERROR;
1862 break;
1864 case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
1865 break;
1867 case GRXSTS_PKTSTS_IN_XFER_COMP:
1868 case GRXSTS_PKTSTS_CH_HALTED:
1869 default:
1870 break;
1875 * @brief Handle Host Port interrupt requests.
1876 * @param hhcd HCD handle
1877 * @retval None
1879 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
1881 const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1882 uint32_t USBx_BASE = (uint32_t)USBx;
1883 __IO uint32_t hprt0;
1884 __IO uint32_t hprt0_dup;
1886 /* Handle Host Port Interrupts */
1887 hprt0 = USBx_HPRT0;
1888 hprt0_dup = USBx_HPRT0;
1890 hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
1891 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
1893 /* Check whether Port Connect detected */
1894 if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
1896 if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
1898 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1899 hhcd->ConnectCallback(hhcd);
1900 #else
1901 HAL_HCD_Connect_Callback(hhcd);
1902 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1904 hprt0_dup |= USB_OTG_HPRT_PCDET;
1907 /* Check whether Port Enable Changed */
1908 if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
1910 hprt0_dup |= USB_OTG_HPRT_PENCHNG;
1912 if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
1914 if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
1916 if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
1918 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
1920 else
1922 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
1925 else
1927 if (hhcd->Init.speed == HCD_SPEED_FULL)
1929 USBx_HOST->HFIR = HFIR_60_MHZ;
1932 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1933 hhcd->PortEnabledCallback(hhcd);
1934 #else
1935 HAL_HCD_PortEnabled_Callback(hhcd);
1936 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1939 else
1941 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1942 hhcd->PortDisabledCallback(hhcd);
1943 #else
1944 HAL_HCD_PortDisabled_Callback(hhcd);
1945 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1949 /* Check for an overcurrent */
1950 if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
1952 hprt0_dup |= USB_OTG_HPRT_POCCHNG;
1955 /* Clear Port Interrupts */
1956 USBx_HPRT0 = hprt0_dup;
1960 * @}
1964 * @}
1967 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1968 #endif /* HAL_HCD_MODULE_ENABLED */
1971 * @}
1975 * @}