2 ******************************************************************************
3 * @file stm32f7xx_hal_hcd.c
4 * @author MCD Application Team
7 * @brief HCD HAL module driver.
8 * This file provides firmware functions to manage the following
9 * functionalities of the USB Peripheral Controller:
10 * + Initialization and de-initialization functions
11 * + IO operation functions
12 * + Peripheral Control functions
13 * + Peripheral State functions
16 ==============================================================================
17 ##### How to use this driver #####
18 ==============================================================================
20 (#)Declare a HCD_HandleTypeDef handle structure, for example:
21 HCD_HandleTypeDef hhcd;
23 (#)Fill parameters of Init structure in HCD handle
25 (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
27 (#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
28 (##) Enable the HCD/USB Low Level interface clock using the following macros
29 (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
30 (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)
31 (+++) __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); (For High Speed Mode)
33 (##) Initialize the related GPIO clocks
34 (##) Configure HCD pin-out
35 (##) Configure HCD NVIC interrupt
37 (#)Associate the Upper USB Host stack to the HAL HCD Driver:
38 (##) hhcd.pData = phost;
40 (#)Enable HCD transmission and reception:
44 ******************************************************************************
47 * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
49 * Redistribution and use in source and binary forms, with or without modification,
50 * are permitted provided that the following conditions are met:
51 * 1. Redistributions of source code must retain the above copyright notice,
52 * this list of conditions and the following disclaimer.
53 * 2. Redistributions in binary form must reproduce the above copyright notice,
54 * this list of conditions and the following disclaimer in the documentation
55 * and/or other materials provided with the distribution.
56 * 3. Neither the name of STMicroelectronics nor the names of its contributors
57 * may be used to endorse or promote products derived from this software
58 * without specific prior written permission.
60 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
61 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
63 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
66 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
67 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
68 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
69 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
71 ******************************************************************************
74 /* Includes ------------------------------------------------------------------*/
75 #include "stm32f7xx_hal.h"
77 /** @addtogroup STM32F7xx_HAL_Driver
82 * @brief HCD HAL module driver
86 #ifdef HAL_HCD_MODULE_ENABLED
88 /* Private typedef -----------------------------------------------------------*/
89 /* Private define ------------------------------------------------------------*/
90 /* Private macro -------------------------------------------------------------*/
91 /* Private variables ---------------------------------------------------------*/
92 /* Private function ----------------------------------------------------------*/
93 /** @defgroup HCD_Private_Functions HCD Private Functions
96 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
);
97 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
);
98 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef
*hhcd
);
99 static void HCD_Port_IRQHandler(HCD_HandleTypeDef
*hhcd
);
104 /* Exported functions --------------------------------------------------------*/
105 /** @defgroup HCD_Exported_Functions HCD Exported Functions
109 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
110 * @brief Initialization and Configuration functions
113 ===============================================================================
114 ##### Initialization and de-initialization functions #####
115 ===============================================================================
116 [..] This section provides functions allowing to:
123 * @brief Initialize the host driver.
124 * @param hhcd: HCD handle
127 HAL_StatusTypeDef
HAL_HCD_Init(HCD_HandleTypeDef
*hhcd
)
129 /* Check the HCD handle allocation */
135 /* Check the parameters */
136 assert_param(IS_HCD_ALL_INSTANCE(hhcd
->Instance
));
138 hhcd
->State
= HAL_HCD_STATE_BUSY
;
140 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
141 HAL_HCD_MspInit(hhcd
);
143 /* Disable the Interrupts */
144 __HAL_HCD_DISABLE(hhcd
);
146 /*Init the Core (common init.) */
147 USB_CoreInit(hhcd
->Instance
, hhcd
->Init
);
150 USB_SetCurrentMode(hhcd
->Instance
, USB_OTG_HOST_MODE
);
153 USB_HostInit(hhcd
->Instance
, hhcd
->Init
);
155 hhcd
->State
= HAL_HCD_STATE_READY
;
161 * @brief Initialize a host channel.
162 * @param hhcd: HCD handle
163 * @param ch_num: Channel number.
164 * This parameter can be a value from 1 to 15
165 * @param epnum: Endpoint number.
166 * This parameter can be a value from 1 to 15
167 * @param dev_address : Current device address
168 * This parameter can be a value from 0 to 255
169 * @param speed: Current device speed.
170 * This parameter can be one of these values:
171 * HCD_SPEED_HIGH: High speed mode,
172 * HCD_SPEED_FULL: Full speed mode,
173 * HCD_SPEED_LOW: Low speed mode
174 * @param ep_type: Endpoint Type.
175 * This parameter can be one of these values:
176 * EP_TYPE_CTRL: Control type,
177 * EP_TYPE_ISOC: Isochronous type,
178 * EP_TYPE_BULK: Bulk type,
179 * EP_TYPE_INTR: Interrupt type
180 * @param mps: Max Packet Size.
181 * This parameter can be a value from 0 to32K
184 HAL_StatusTypeDef
HAL_HCD_HC_Init(HCD_HandleTypeDef
*hhcd
,
192 HAL_StatusTypeDef status
= HAL_OK
;
196 hhcd
->hc
[ch_num
].dev_addr
= dev_address
;
197 hhcd
->hc
[ch_num
].max_packet
= mps
;
198 hhcd
->hc
[ch_num
].ch_num
= ch_num
;
199 hhcd
->hc
[ch_num
].ep_type
= ep_type
;
200 hhcd
->hc
[ch_num
].ep_num
= epnum
& 0x7F;
201 hhcd
->hc
[ch_num
].ep_is_in
= ((epnum
& 0x80) == 0x80);
202 hhcd
->hc
[ch_num
].speed
= speed
;
204 status
= USB_HC_Init(hhcd
->Instance
,
217 * @brief Halt a host channel.
218 * @param hhcd: HCD handle
219 * @param ch_num: Channel number.
220 * This parameter can be a value from 1 to 15
223 HAL_StatusTypeDef
HAL_HCD_HC_Halt(HCD_HandleTypeDef
*hhcd
, uint8_t ch_num
)
225 HAL_StatusTypeDef status
= HAL_OK
;
228 USB_HC_Halt(hhcd
->Instance
, ch_num
);
235 * @brief DeInitialize the host driver.
236 * @param hhcd: HCD handle
239 HAL_StatusTypeDef
HAL_HCD_DeInit(HCD_HandleTypeDef
*hhcd
)
241 /* Check the HCD handle allocation */
247 hhcd
->State
= HAL_HCD_STATE_BUSY
;
249 /* DeInit the low level hardware */
250 HAL_HCD_MspDeInit(hhcd
);
252 __HAL_HCD_DISABLE(hhcd
);
254 hhcd
->State
= HAL_HCD_STATE_RESET
;
260 * @brief Initialize the HCD MSP.
261 * @param hhcd: HCD handle
264 __weak
void HAL_HCD_MspInit(HCD_HandleTypeDef
*hhcd
)
266 /* Prevent unused argument(s) compilation warning */
269 /* NOTE : This function Should not be modified, when the callback is needed,
270 the HAL_HCD_MspInit could be implemented in the user file
275 * @brief DeInitialize the HCD MSP.
276 * @param hhcd: HCD handle
279 __weak
void HAL_HCD_MspDeInit(HCD_HandleTypeDef
*hhcd
)
281 /* Prevent unused argument(s) compilation warning */
284 /* NOTE : This function Should not be modified, when the callback is needed,
285 the HAL_HCD_MspDeInit could be implemented in the user file
293 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
294 * @brief HCD IO operation functions
297 ===============================================================================
298 ##### IO operation functions #####
299 ===============================================================================
300 [..] This subsection provides a set of functions allowing to manage the USB Host Data
308 * @brief Submit a new URB for processing.
309 * @param hhcd: HCD handle
310 * @param ch_num: Channel number.
311 * This parameter can be a value from 1 to 15
312 * @param direction: Channel number.
313 * This parameter can be one of these values:
314 * 0 : Output / 1 : Input
315 * @param ep_type: Endpoint Type.
316 * This parameter can be one of these values:
317 * EP_TYPE_CTRL: Control type/
318 * EP_TYPE_ISOC: Isochronous type/
319 * EP_TYPE_BULK: Bulk type/
320 * EP_TYPE_INTR: Interrupt type/
321 * @param token: Endpoint Type.
322 * This parameter can be one of these values:
323 * 0: HC_PID_SETUP / 1: HC_PID_DATA1
324 * @param pbuff: pointer to URB data
325 * @param length: Length of URB data
326 * @param do_ping: activate do ping protocol (for high speed only).
327 * This parameter can be one of these values:
328 * 0 : do ping inactive / 1 : do ping active
331 HAL_StatusTypeDef
HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef
*hhcd
,
340 hhcd
->hc
[ch_num
].ep_is_in
= direction
;
341 hhcd
->hc
[ch_num
].ep_type
= ep_type
;
345 hhcd
->hc
[ch_num
].data_pid
= HC_PID_SETUP
;
349 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
352 /* Manage Data Toggle */
356 if((token
== 1) && (direction
== 0)) /*send data */
359 { /* For Status OUT stage, Length==0, Status Out PID = 1 */
360 hhcd
->hc
[ch_num
].toggle_out
= 1;
363 /* Set the Data Toggle bit as per the Flag */
364 if ( hhcd
->hc
[ch_num
].toggle_out
== 0)
365 { /* Put the PID 0 */
366 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
369 { /* Put the PID 1 */
370 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
372 if(hhcd
->hc
[ch_num
].urb_state
!= URB_NOTREADY
)
374 hhcd
->hc
[ch_num
].do_ping
= do_ping
;
382 /* Set the Data Toggle bit as per the Flag */
383 if ( hhcd
->hc
[ch_num
].toggle_out
== 0)
384 { /* Put the PID 0 */
385 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
388 { /* Put the PID 1 */
389 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
391 if(hhcd
->hc
[ch_num
].urb_state
!= URB_NOTREADY
)
393 hhcd
->hc
[ch_num
].do_ping
= do_ping
;
398 if( hhcd
->hc
[ch_num
].toggle_in
== 0)
400 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
404 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
412 /* Set the Data Toggle bit as per the Flag */
413 if ( hhcd
->hc
[ch_num
].toggle_out
== 0)
414 { /* Put the PID 0 */
415 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
418 { /* Put the PID 1 */
419 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
424 if( hhcd
->hc
[ch_num
].toggle_in
== 0)
426 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
430 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
436 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
440 hhcd
->hc
[ch_num
].xfer_buff
= pbuff
;
441 hhcd
->hc
[ch_num
].xfer_len
= length
;
442 hhcd
->hc
[ch_num
].urb_state
= URB_IDLE
;
443 hhcd
->hc
[ch_num
].xfer_count
= 0 ;
444 hhcd
->hc
[ch_num
].ch_num
= ch_num
;
445 hhcd
->hc
[ch_num
].state
= HC_IDLE
;
447 return USB_HC_StartXfer(hhcd
->Instance
, &(hhcd
->hc
[ch_num
]), hhcd
->Init
.dma_enable
);
451 * @brief Handle HCD interrupt request.
452 * @param hhcd: HCD handle
455 void HAL_HCD_IRQHandler(HCD_HandleTypeDef
*hhcd
)
457 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
458 uint32_t i
= 0 , interrupt
= 0;
460 /* ensure that we are in device mode */
461 if (USB_GetMode(hhcd
->Instance
) == USB_OTG_MODE_HOST
)
463 /* avoid spurious interrupt */
464 if(__HAL_HCD_IS_INVALID_INTERRUPT(hhcd
))
469 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT
))
471 /* incorrect mode, acknowledge the interrupt */
472 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT
);
475 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_IISOIXFR
))
477 /* incorrect mode, acknowledge the interrupt */
478 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_IISOIXFR
);
481 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_PTXFE
))
483 /* incorrect mode, acknowledge the interrupt */
484 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_PTXFE
);
487 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_MMIS
))
489 /* incorrect mode, acknowledge the interrupt */
490 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_MMIS
);
493 /* Handle Host Disconnect Interrupts */
494 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_DISCINT
))
498 USBx_HPRT0
&= ~(USB_OTG_HPRT_PENA
| USB_OTG_HPRT_PCDET
|\
499 USB_OTG_HPRT_PENCHNG
| USB_OTG_HPRT_POCCHNG
);
501 /* Handle Host Port Interrupts */
502 HAL_HCD_Disconnect_Callback(hhcd
);
503 USB_InitFSLSPClkSel(hhcd
->Instance
,HCFG_48_MHZ
);
504 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_DISCINT
);
507 /* Handle Host Port Interrupts */
508 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_HPRTINT
))
510 HCD_Port_IRQHandler (hhcd
);
513 /* Handle Host SOF Interrupts */
514 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_SOF
))
516 HAL_HCD_SOF_Callback(hhcd
);
517 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_SOF
);
520 /* Handle Host channel Interrupts */
521 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_HCINT
))
523 interrupt
= USB_HC_ReadInterrupt(hhcd
->Instance
);
524 for (i
= 0; i
< hhcd
->Init
.Host_channels
; i
++)
526 if (interrupt
& (1 << i
))
528 if ((USBx_HC(i
)->HCCHAR
) & USB_OTG_HCCHAR_EPDIR
)
530 HCD_HC_IN_IRQHandler (hhcd
, i
);
534 HCD_HC_OUT_IRQHandler (hhcd
, i
);
538 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_HCINT
);
541 /* Handle Rx Queue Level Interrupts */
542 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_RXFLVL
))
544 USB_MASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_RXFLVL
);
546 HCD_RXQLVL_IRQHandler (hhcd
);
548 USB_UNMASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_RXFLVL
);
554 * @brief SOF callback.
555 * @param hhcd: HCD handle
558 __weak
void HAL_HCD_SOF_Callback(HCD_HandleTypeDef
*hhcd
)
560 /* Prevent unused argument(s) compilation warning */
563 /* NOTE : This function Should not be modified, when the callback is needed,
564 the HAL_HCD_SOF_Callback could be implemented in the user file
569 * @brief Connection Event callback.
570 * @param hhcd: HCD handle
573 __weak
void HAL_HCD_Connect_Callback(HCD_HandleTypeDef
*hhcd
)
575 /* Prevent unused argument(s) compilation warning */
578 /* NOTE : This function Should not be modified, when the callback is needed,
579 the HAL_HCD_Connect_Callback could be implemented in the user file
584 * @brief Disconnection Event callback.
585 * @param hhcd: HCD handle
588 __weak
void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef
*hhcd
)
590 /* Prevent unused argument(s) compilation warning */
593 /* NOTE : This function Should not be modified, when the callback is needed,
594 the HAL_HCD_Disconnect_Callback could be implemented in the user file
599 * @brief Notify URB state change callback.
600 * @param hhcd: HCD handle
601 * @param chnum: Channel number.
602 * This parameter can be a value from 1 to 15
604 * This parameter can be one of these values:
613 __weak
void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
, HCD_URBStateTypeDef urb_state
)
615 /* Prevent unused argument(s) compilation warning */
618 /* NOTE : This function Should not be modified, when the callback is needed,
619 the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
627 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
628 * @brief Management functions
631 ===============================================================================
632 ##### Peripheral Control functions #####
633 ===============================================================================
635 This subsection provides a set of functions allowing to control the HCD data
643 * @brief Start the host driver.
644 * @param hhcd: HCD handle
647 HAL_StatusTypeDef
HAL_HCD_Start(HCD_HandleTypeDef
*hhcd
)
650 __HAL_HCD_ENABLE(hhcd
);
651 USB_DriveVbus(hhcd
->Instance
, 1);
657 * @brief Stop the host driver.
658 * @param hhcd: HCD handle
662 HAL_StatusTypeDef
HAL_HCD_Stop(HCD_HandleTypeDef
*hhcd
)
665 USB_StopHost(hhcd
->Instance
);
671 * @brief Reset the host port.
672 * @param hhcd: HCD handle
675 HAL_StatusTypeDef
HAL_HCD_ResetPort(HCD_HandleTypeDef
*hhcd
)
677 return (USB_ResetPort(hhcd
->Instance
));
684 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
685 * @brief Peripheral State functions
688 ===============================================================================
689 ##### Peripheral State functions #####
690 ===============================================================================
692 This subsection permits to get in run-time the status of the peripheral
700 * @brief Return the HCD handle state.
701 * @param hhcd: HCD handle
704 HCD_StateTypeDef
HAL_HCD_GetState(HCD_HandleTypeDef
*hhcd
)
710 * @brief Return URB state for a channel.
711 * @param hhcd: HCD handle
712 * @param chnum: Channel number.
713 * This parameter can be a value from 1 to 15
715 * This parameter can be one of these values:
723 HCD_URBStateTypeDef
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
725 return hhcd
->hc
[chnum
].urb_state
;
730 * @brief Return the last host transfer size.
731 * @param hhcd: HCD handle
732 * @param chnum: Channel number.
733 * This parameter can be a value from 1 to 15
734 * @retval last transfer size in byte
736 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
738 return hhcd
->hc
[chnum
].xfer_count
;
742 * @brief Return the Host Channel state.
743 * @param hhcd: HCD handle
744 * @param chnum: Channel number.
745 * This parameter can be a value from 1 to 15
746 * @retval Host channel state
747 * This parameter can be one of these values:
758 HCD_HCStateTypeDef
HAL_HCD_HC_GetState(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
760 return hhcd
->hc
[chnum
].state
;
764 * @brief Return the current Host frame number.
765 * @param hhcd: HCD handle
766 * @retval Current Host frame number
768 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef
*hhcd
)
770 return (USB_GetCurrentFrame(hhcd
->Instance
));
774 * @brief Return the Host enumeration speed.
775 * @param hhcd: HCD handle
776 * @retval Enumeration speed
778 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef
*hhcd
)
780 return (USB_GetHostSpeed(hhcd
->Instance
));
791 /** @addtogroup HCD_Private_Functions
795 * @brief Handle Host Channel IN interrupt requests.
796 * @param hhcd: HCD handle
797 * @param chnum: Channel number.
798 * This parameter can be a value from 1 to 15
801 static void HCD_HC_IN_IRQHandler (HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
803 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
806 if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_AHBERR
)
808 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_AHBERR
);
809 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
811 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_ACK
)
813 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_ACK
);
816 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_STALL
)
818 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
819 hhcd
->hc
[chnum
].state
= HC_STALL
;
820 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
821 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_STALL
);
822 USB_HC_Halt(hhcd
->Instance
, chnum
);
824 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_DTERR
)
826 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
827 USB_HC_Halt(hhcd
->Instance
, chnum
);
828 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
829 hhcd
->hc
[chnum
].state
= HC_DATATGLERR
;
830 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_DTERR
);
833 if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_FRMOR
)
835 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
836 USB_HC_Halt(hhcd
->Instance
, chnum
);
837 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_FRMOR
);
840 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_XFRC
)
843 if (hhcd
->Init
.dma_enable
)
845 hhcd
->hc
[chnum
].xfer_count
= hhcd
->hc
[chnum
].xfer_len
- \
846 (USBx_HC(chnum
)->HCTSIZ
& USB_OTG_HCTSIZ_XFRSIZ
);
849 hhcd
->hc
[chnum
].state
= HC_XFRC
;
850 hhcd
->hc
[chnum
].ErrCnt
= 0;
851 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_XFRC
);
854 if ((hhcd
->hc
[chnum
].ep_type
== EP_TYPE_CTRL
)||
855 (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
))
857 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
858 USB_HC_Halt(hhcd
->Instance
, chnum
);
859 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
862 else if(hhcd
->hc
[chnum
].ep_type
== EP_TYPE_INTR
)
864 USBx_HC(chnum
)->HCCHAR
|= USB_OTG_HCCHAR_ODDFRM
;
865 hhcd
->hc
[chnum
].urb_state
= URB_DONE
;
866 HAL_HCD_HC_NotifyURBChange_Callback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
868 hhcd
->hc
[chnum
].toggle_in
^= 1;
871 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_CHH
)
873 __HAL_HCD_MASK_HALT_HC_INT(chnum
);
875 if(hhcd
->hc
[chnum
].state
== HC_XFRC
)
877 hhcd
->hc
[chnum
].urb_state
= URB_DONE
;
880 else if (hhcd
->hc
[chnum
].state
== HC_STALL
)
882 hhcd
->hc
[chnum
].urb_state
= URB_STALL
;
885 else if((hhcd
->hc
[chnum
].state
== HC_XACTERR
) ||
886 (hhcd
->hc
[chnum
].state
== HC_DATATGLERR
))
888 if(hhcd
->hc
[chnum
].ErrCnt
++ > 3)
890 hhcd
->hc
[chnum
].ErrCnt
= 0;
891 hhcd
->hc
[chnum
].urb_state
= URB_ERROR
;
895 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
898 /* re-activate the channel */
899 tmpreg
= USBx_HC(chnum
)->HCCHAR
;
900 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
901 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
902 USBx_HC(chnum
)->HCCHAR
= tmpreg
;
904 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_CHH
);
905 HAL_HCD_HC_NotifyURBChange_Callback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
908 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_TXERR
)
910 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
911 hhcd
->hc
[chnum
].ErrCnt
++;
912 hhcd
->hc
[chnum
].state
= HC_XACTERR
;
913 USB_HC_Halt(hhcd
->Instance
, chnum
);
914 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_TXERR
);
916 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_NAK
)
918 if(hhcd
->hc
[chnum
].ep_type
== EP_TYPE_INTR
)
920 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
921 USB_HC_Halt(hhcd
->Instance
, chnum
);
923 else if ((hhcd
->hc
[chnum
].ep_type
== EP_TYPE_CTRL
)||
924 (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
))
926 /* re-activate the channel */
927 tmpreg
= USBx_HC(chnum
)->HCCHAR
;
928 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
929 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
930 USBx_HC(chnum
)->HCCHAR
= tmpreg
;
932 hhcd
->hc
[chnum
].state
= HC_NAK
;
933 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
938 * @brief Handle Host Channel OUT interrupt requests.
939 * @param hhcd: HCD handle
940 * @param chnum: Channel number.
941 * This parameter can be a value from 1 to 15
944 static void HCD_HC_OUT_IRQHandler (HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
946 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
949 if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_AHBERR
)
951 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_AHBERR
);
952 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
954 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_ACK
)
956 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_ACK
);
958 if( hhcd
->hc
[chnum
].do_ping
== 1)
960 hhcd
->hc
[chnum
].state
= HC_NYET
;
961 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
962 USB_HC_Halt(hhcd
->Instance
, chnum
);
963 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
967 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_NYET
)
969 hhcd
->hc
[chnum
].state
= HC_NYET
;
970 hhcd
->hc
[chnum
].ErrCnt
= 0;
971 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
972 USB_HC_Halt(hhcd
->Instance
, chnum
);
973 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NYET
);
977 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_FRMOR
)
979 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
980 USB_HC_Halt(hhcd
->Instance
, chnum
);
981 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_FRMOR
);
984 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_XFRC
)
986 hhcd
->hc
[chnum
].ErrCnt
= 0;
987 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
988 USB_HC_Halt(hhcd
->Instance
, chnum
);
989 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_XFRC
);
990 hhcd
->hc
[chnum
].state
= HC_XFRC
;
994 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_STALL
)
996 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_STALL
);
997 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
998 USB_HC_Halt(hhcd
->Instance
, chnum
);
999 hhcd
->hc
[chnum
].state
= HC_STALL
;
1002 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_NAK
)
1004 hhcd
->hc
[chnum
].ErrCnt
= 0;
1005 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
1006 USB_HC_Halt(hhcd
->Instance
, chnum
);
1007 hhcd
->hc
[chnum
].state
= HC_NAK
;
1008 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
1011 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_TXERR
)
1013 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
1014 USB_HC_Halt(hhcd
->Instance
, chnum
);
1015 hhcd
->hc
[chnum
].state
= HC_XACTERR
;
1016 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_TXERR
);
1019 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_DTERR
)
1021 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
1022 USB_HC_Halt(hhcd
->Instance
, chnum
);
1023 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
1024 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_DTERR
);
1025 hhcd
->hc
[chnum
].state
= HC_DATATGLERR
;
1029 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_CHH
)
1031 __HAL_HCD_MASK_HALT_HC_INT(chnum
);
1033 if(hhcd
->hc
[chnum
].state
== HC_XFRC
)
1035 hhcd
->hc
[chnum
].urb_state
= URB_DONE
;
1036 if (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
)
1038 hhcd
->hc
[chnum
].toggle_out
^= 1;
1041 else if (hhcd
->hc
[chnum
].state
== HC_NAK
)
1043 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1046 else if (hhcd
->hc
[chnum
].state
== HC_NYET
)
1048 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1049 hhcd
->hc
[chnum
].do_ping
= 0;
1052 else if (hhcd
->hc
[chnum
].state
== HC_STALL
)
1054 hhcd
->hc
[chnum
].urb_state
= URB_STALL
;
1057 else if((hhcd
->hc
[chnum
].state
== HC_XACTERR
) ||
1058 (hhcd
->hc
[chnum
].state
== HC_DATATGLERR
))
1060 if(hhcd
->hc
[chnum
].ErrCnt
++ > 3)
1062 hhcd
->hc
[chnum
].ErrCnt
= 0;
1063 hhcd
->hc
[chnum
].urb_state
= URB_ERROR
;
1067 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1070 /* re-activate the channel */
1071 tmpreg
= USBx_HC(chnum
)->HCCHAR
;
1072 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
1073 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
1074 USBx_HC(chnum
)->HCCHAR
= tmpreg
;
1077 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_CHH
);
1078 HAL_HCD_HC_NotifyURBChange_Callback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
1083 * @brief Handle Rx Queue Level interrupt requests.
1084 * @param hhcd: HCD handle
1087 static void HCD_RXQLVL_IRQHandler (HCD_HandleTypeDef
*hhcd
)
1089 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
1090 uint8_t channelnum
=0;
1094 uint32_t tmpreg
= 0;
1096 temp
= hhcd
->Instance
->GRXSTSP
;
1097 channelnum
= temp
& USB_OTG_GRXSTSP_EPNUM
;
1098 pktsts
= (temp
& USB_OTG_GRXSTSP_PKTSTS
) >> 17;
1099 pktcnt
= (temp
& USB_OTG_GRXSTSP_BCNT
) >> 4;
1103 case GRXSTS_PKTSTS_IN
:
1104 /* Read the data into the host buffer. */
1105 if ((pktcnt
> 0) && (hhcd
->hc
[channelnum
].xfer_buff
!= (void *)0))
1108 USB_ReadPacket(hhcd
->Instance
, hhcd
->hc
[channelnum
].xfer_buff
, pktcnt
);
1110 /*manage multiple Xfer */
1111 hhcd
->hc
[channelnum
].xfer_buff
+= pktcnt
;
1112 hhcd
->hc
[channelnum
].xfer_count
+= pktcnt
;
1114 if((USBx_HC(channelnum
)->HCTSIZ
& USB_OTG_HCTSIZ_PKTCNT
) > 0)
1116 /* re-activate the channel when more packets are expected */
1117 tmpreg
= USBx_HC(channelnum
)->HCCHAR
;
1118 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
1119 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
1120 USBx_HC(channelnum
)->HCCHAR
= tmpreg
;
1121 hhcd
->hc
[channelnum
].toggle_in
^= 1;
1126 case GRXSTS_PKTSTS_DATA_TOGGLE_ERR
:
1128 case GRXSTS_PKTSTS_IN_XFER_COMP
:
1129 case GRXSTS_PKTSTS_CH_HALTED
:
1136 * @brief Handle Host Port interrupt requests.
1137 * @param hhcd: HCD handle
1140 static void HCD_Port_IRQHandler (HCD_HandleTypeDef
*hhcd
)
1142 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
1143 __IO
uint32_t hprt0
, hprt0_dup
;
1145 /* Handle Host Port Interrupts */
1147 hprt0_dup
= USBx_HPRT0
;
1149 hprt0_dup
&= ~(USB_OTG_HPRT_PENA
| USB_OTG_HPRT_PCDET
|\
1150 USB_OTG_HPRT_PENCHNG
| USB_OTG_HPRT_POCCHNG
);
1152 /* Check whether Port Connect detected */
1153 if((hprt0
& USB_OTG_HPRT_PCDET
) == USB_OTG_HPRT_PCDET
)
1155 if((hprt0
& USB_OTG_HPRT_PCSTS
) == USB_OTG_HPRT_PCSTS
)
1157 USB_MASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_DISCINT
);
1158 HAL_HCD_Connect_Callback(hhcd
);
1160 hprt0_dup
|= USB_OTG_HPRT_PCDET
;
1164 /* Check whether Port Enable Changed */
1165 if((hprt0
& USB_OTG_HPRT_PENCHNG
) == USB_OTG_HPRT_PENCHNG
)
1167 hprt0_dup
|= USB_OTG_HPRT_PENCHNG
;
1169 if((hprt0
& USB_OTG_HPRT_PENA
) == USB_OTG_HPRT_PENA
)
1171 if(hhcd
->Init
.phy_itface
== USB_OTG_EMBEDDED_PHY
)
1173 if ((hprt0
& USB_OTG_HPRT_PSPD
) == (HPRT0_PRTSPD_LOW_SPEED
<< 17))
1175 USB_InitFSLSPClkSel(hhcd
->Instance
,HCFG_6_MHZ
);
1179 USB_InitFSLSPClkSel(hhcd
->Instance
,HCFG_48_MHZ
);
1184 if(hhcd
->Init
.speed
== HCD_SPEED_FULL
)
1186 USBx_HOST
->HFIR
= (uint32_t)60000;
1189 HAL_HCD_Connect_Callback(hhcd
);
1195 USBx_HPRT0
&= ~(USB_OTG_HPRT_PENA
| USB_OTG_HPRT_PCDET
|\
1196 USB_OTG_HPRT_PENCHNG
| USB_OTG_HPRT_POCCHNG
);
1198 USB_UNMASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_DISCINT
);
1202 /* Check For an overcurrent */
1203 if((hprt0
& USB_OTG_HPRT_POCCHNG
) == USB_OTG_HPRT_POCCHNG
)
1205 hprt0_dup
|= USB_OTG_HPRT_POCCHNG
;
1208 /* Clear Port Interrupts */
1209 USBx_HPRT0
= hprt0_dup
;
1220 #endif /* HAL_HCD_MODULE_ENABLED */
1229 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/