2 ******************************************************************************
3 * @file stm32f4xx_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 (+++) __OTGFS-OTG_CLK_ENABLE() or __OTGHS-OTG_CLK_ENABLE()
30 (+++) __OTGHSULPI_CLK_ENABLE() For High Speed Mode
32 (##) Initialize the related GPIO clocks
33 (##) Configure HCD pin-out
34 (##) Configure HCD NVIC interrupt
36 (#)Associate the Upper USB Host stack to the HAL HCD Driver:
37 (##) hhcd.pData = phost;
39 (#)Enable HCD transmission and reception:
43 ******************************************************************************
46 * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
48 * Redistribution and use in source and binary forms, with or without modification,
49 * are permitted provided that the following conditions are met:
50 * 1. Redistributions of source code must retain the above copyright notice,
51 * this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright notice,
53 * this list of conditions and the following disclaimer in the documentation
54 * and/or other materials provided with the distribution.
55 * 3. Neither the name of STMicroelectronics nor the names of its contributors
56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission.
59 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
60 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
62 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
65 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
66 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
67 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
68 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
70 ******************************************************************************
73 /* Includes ------------------------------------------------------------------*/
74 #include "stm32f4xx_hal.h"
75 /** @addtogroup STM32F4xx_HAL_Driver
80 * @brief HCD HAL module driver
84 #ifdef HAL_HCD_MODULE_ENABLED
86 /* Private typedef -----------------------------------------------------------*/
87 /* Private define ------------------------------------------------------------*/
88 /* Private macro -------------------------------------------------------------*/
89 /* Private variables ---------------------------------------------------------*/
90 /* Private function prototypes -----------------------------------------------*/
91 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
);
92 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
);
93 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef
*hhcd
);
94 static void HCD_Port_IRQHandler(HCD_HandleTypeDef
*hhcd
);
95 /* Private functions ---------------------------------------------------------*/
97 /** @defgroup HCD_Private_Functions
101 /** @defgroup HCD_Group1 Initialization and de-initialization functions
102 * @brief Initialization and Configuration functions
105 ===============================================================================
106 ##### Initialization and de-initialization functions #####
107 ===============================================================================
108 [..] This section provides functions allowing to:
115 * @brief Initialize the host driver
116 * @param hhcd: HCD handle
119 HAL_StatusTypeDef
HAL_HCD_Init(HCD_HandleTypeDef
*hhcd
)
121 /* Check the HCD handle allocation */
127 /* Check the parameters */
128 assert_param(IS_HCD_ALL_INSTANCE(hhcd
->Instance
));
130 hhcd
->State
= HAL_HCD_STATE_BUSY
;
132 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
133 HAL_HCD_MspInit(hhcd
);
135 /* Disable the Interrupts */
136 __HAL_HCD_DISABLE(hhcd
);
138 /*Init the Core (common init.) */
139 USB_CoreInit(hhcd
->Instance
, hhcd
->Init
);
142 USB_SetCurrentMode(hhcd
->Instance
, USB_OTG_HOST_MODE
);
145 USB_HostInit(hhcd
->Instance
, hhcd
->Init
);
147 hhcd
->State
= HAL_HCD_STATE_READY
;
153 * @brief Initialize a host channel
154 * @param hhcd: HCD handle
155 * @param ch_num: Channel number.
156 * This parameter can be a value from 1 to 15
157 * @param epnum: Endpoint number.
158 * This parameter can be a value from 1 to 15
159 * @param dev_address : Current device address
160 * This parameter can be a value from 0 to 255
161 * @param speed: Current device speed.
162 * This parameter can be one of these values:
163 * HCD_SPEED_HIGH: High speed mode,
164 * HCD_SPEED_FULL: Full speed mode,
165 * HCD_SPEED_LOW: Low speed mode
166 * @param ep_type: Endpoint Type.
167 * This parameter can be one of these values:
168 * EP_TYPE_CTRL: Control type,
169 * EP_TYPE_ISOC: Isochrounous type,
170 * EP_TYPE_BULK: Bulk type,
171 * EP_TYPE_INTR: Interrupt type
172 * @param mps: Max Packet Size.
173 * This parameter can be a value from 0 to32K
176 HAL_StatusTypeDef
HAL_HCD_HC_Init(HCD_HandleTypeDef
*hhcd
,
184 HAL_StatusTypeDef status
= HAL_OK
;
188 hhcd
->hc
[ch_num
].dev_addr
= dev_address
;
189 hhcd
->hc
[ch_num
].max_packet
= mps
;
190 hhcd
->hc
[ch_num
].ch_num
= ch_num
;
191 hhcd
->hc
[ch_num
].ep_type
= ep_type
;
192 hhcd
->hc
[ch_num
].ep_num
= epnum
& 0x7F;
193 hhcd
->hc
[ch_num
].ep_is_in
= ((epnum
& 0x80) == 0x80);
194 hhcd
->hc
[ch_num
].speed
= speed
;
196 status
= USB_HC_Init(hhcd
->Instance
,
211 * @brief Halt a host channel
212 * @param hhcd: HCD handle
213 * @param ch_num: Channel number.
214 * This parameter can be a value from 1 to 15
217 HAL_StatusTypeDef
HAL_HCD_HC_Halt(HCD_HandleTypeDef
*hhcd
,
220 HAL_StatusTypeDef status
= HAL_OK
;
223 USB_HC_Halt(hhcd
->Instance
, ch_num
);
229 * @brief DeInitialize the host driver
230 * @param hhcd: HCD handle
233 HAL_StatusTypeDef
HAL_HCD_DeInit(HCD_HandleTypeDef
*hhcd
)
235 /* Check the HCD handle allocation */
241 hhcd
->State
= HAL_HCD_STATE_BUSY
;
243 /* DeInit the low level hardware */
244 HAL_HCD_MspDeInit(hhcd
);
246 __HAL_HCD_DISABLE(hhcd
);
248 hhcd
->State
= HAL_HCD_STATE_RESET
;
254 * @brief Initializes the HCD MSP.
255 * @param hhcd: HCD handle
258 __weak
void HAL_HCD_MspInit(HCD_HandleTypeDef
*hhcd
)
260 /* NOTE : This function Should not be modified, when the callback is needed,
261 the HAL_PCD_MspInit could be implenetd in the user file
266 * @brief DeInitializes HCD MSP.
267 * @param hhcd: HCD handle
270 __weak
void HAL_HCD_MspDeInit(HCD_HandleTypeDef
*hhhcd
)
272 /* NOTE : This function Should not be modified, when the callback is needed,
273 the HAL_PCD_MspDeInit could be implenetd in the user file
281 /** @defgroup HCD_Group2 IO operation functions
282 * @brief HCD IO operation functions
285 ===============================================================================
286 ##### IO operation functions #####
287 ===============================================================================
288 This subsection provides a set of functions allowing to manage the USB Host Data
296 * @brief Submit a new URB for processing
297 * @param hhcd: HCD handle
298 * @param ch_num: Channel number.
299 * This parameter can be a value from 1 to 15
300 * @param direction: Channel number.
301 * This parameter can be one of these values:
302 * 0 : Output / 1 : Input
303 * @param ep_type: Endpoint Type.
304 * This parameter can be one of these values:
305 * EP_TYPE_CTRL: Control type/
306 * EP_TYPE_ISOC: Isochrounous type/
307 * EP_TYPE_BULK: Bulk type/
308 * EP_TYPE_INTR: Interrupt type/
309 * @param token: Endpoint Type.
310 * This parameter can be one of these values:
311 * 0: HC_PID_SETUP / 1: HC_PID_DATA1
312 * @param pbuff: pointer to URB data
313 * @param length: Length of URB data
314 * @param do_ping: activate do ping protocol (for high speed only).
315 * This parameter can be one of these values:
316 * 0 : do ping inactive / 1 : do ping active
319 HAL_StatusTypeDef
HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef
*hhcd
,
328 hhcd
->hc
[ch_num
].ep_is_in
= direction
;
329 hhcd
->hc
[ch_num
].ep_type
= ep_type
;
333 hhcd
->hc
[ch_num
].data_pid
= HC_PID_SETUP
;
337 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
340 /* Manage Data Toggle */
344 if((token
== 1) && (direction
== 0)) /*send data */
347 { /* For Status OUT stage, Length==0, Status Out PID = 1 */
348 hhcd
->hc
[ch_num
].toggle_out
= 1;
351 /* Set the Data Toggle bit as per the Flag */
352 if ( hhcd
->hc
[ch_num
].toggle_out
== 0)
353 { /* Put the PID 0 */
354 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
357 { /* Put the PID 1 */
358 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
360 if(hhcd
->hc
[ch_num
].urb_state
!= URB_NOTREADY
)
362 hhcd
->hc
[ch_num
].do_ping
= do_ping
;
370 /* Set the Data Toggle bit as per the Flag */
371 if ( hhcd
->hc
[ch_num
].toggle_out
== 0)
372 { /* Put the PID 0 */
373 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
376 { /* Put the PID 1 */
377 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
379 if(hhcd
->hc
[ch_num
].urb_state
!= URB_NOTREADY
)
381 hhcd
->hc
[ch_num
].do_ping
= do_ping
;
386 if( hhcd
->hc
[ch_num
].toggle_in
== 0)
388 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
392 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
400 /* Set the Data Toggle bit as per the Flag */
401 if ( hhcd
->hc
[ch_num
].toggle_out
== 0)
402 { /* Put the PID 0 */
403 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
406 { /* Put the PID 1 */
407 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
412 if( hhcd
->hc
[ch_num
].toggle_in
== 0)
414 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
418 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
424 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
429 hhcd
->hc
[ch_num
].xfer_buff
= pbuff
;
430 hhcd
->hc
[ch_num
].xfer_len
= length
;
431 hhcd
->hc
[ch_num
].urb_state
= URB_IDLE
;
432 hhcd
->hc
[ch_num
].xfer_count
= 0 ;
433 hhcd
->hc
[ch_num
].ch_num
= ch_num
;
434 hhcd
->hc
[ch_num
].state
= HC_IDLE
;
436 return USB_HC_StartXfer(hhcd
->Instance
, &(hhcd
->hc
[ch_num
]), hhcd
->Init
.dma_enable
);
440 * @brief This function handles HCD interrupt request.
441 * @param hhcd: HCD handle
444 void HAL_HCD_IRQHandler(HCD_HandleTypeDef
*hhcd
)
446 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
447 uint32_t i
= 0 , interrupt
= 0;
449 /* ensure that we are in device mode */
450 if (USB_GetMode(hhcd
->Instance
) == USB_OTG_MODE_HOST
)
452 /* avoid spurious interrupt */
453 if(__HAL_HCD_IS_INVALID_INTERRUPT(hhcd
))
458 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT
))
460 /* incorrect mode, acknowledge the interrupt */
461 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT
);
464 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_IISOIXFR
))
466 /* incorrect mode, acknowledge the interrupt */
467 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_IISOIXFR
);
470 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_PTXFE
))
472 /* incorrect mode, acknowledge the interrupt */
473 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_PTXFE
);
476 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_MMIS
))
478 /* incorrect mode, acknowledge the interrupt */
479 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_MMIS
);
482 /* Handle Host Disconnect Interrupts */
483 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_DISCINT
))
487 USBx_HPRT0
&= ~(USB_OTG_HPRT_PENA
| USB_OTG_HPRT_PCDET
|\
488 USB_OTG_HPRT_PENCHNG
| USB_OTG_HPRT_POCCHNG
);
490 /* Handle Host Port Interrupts */
491 HAL_HCD_Disconnect_Callback(hhcd
);
492 USB_InitFSLSPClkSel(hhcd
->Instance
,HCFG_48_MHZ
);
493 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_DISCINT
);
496 /* Handle Host Port Interrupts */
497 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_HPRTINT
))
499 HCD_Port_IRQHandler (hhcd
);
502 /* Handle Host SOF Interrupts */
503 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_SOF
))
505 HAL_HCD_SOF_Callback(hhcd
);
506 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_SOF
);
509 /* Handle Host channel Interrupts */
510 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_HCINT
))
513 interrupt
= USB_HC_ReadInterrupt(hhcd
->Instance
);
514 for (i
= 0; i
< hhcd
->Init
.Host_channels
; i
++)
516 if (interrupt
& (1 << i
))
518 if ((USBx_HC(i
)->HCCHAR
) & USB_OTG_HCCHAR_EPDIR
)
520 HCD_HC_IN_IRQHandler (hhcd
, i
);
524 HCD_HC_OUT_IRQHandler (hhcd
, i
);
528 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_HCINT
);
531 /* Handle Rx Queue Level Interrupts */
532 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_RXFLVL
))
534 USB_MASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_RXFLVL
);
536 HCD_RXQLVL_IRQHandler (hhcd
);
538 USB_UNMASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_RXFLVL
);
545 * @brief SOF callback.
546 * @param hhcd: HCD handle
549 __weak
void HAL_HCD_SOF_Callback(HCD_HandleTypeDef
*hhcd
)
551 /* NOTE : This function Should not be modified, when the callback is needed,
552 the HAL_HCD_SOF_Callback could be implenetd in the user file
557 * @brief Connexion Event callback.
558 * @param hhcd: HCD handle
561 __weak
void HAL_HCD_Connect_Callback(HCD_HandleTypeDef
*hhcd
)
563 /* NOTE : This function Should not be modified, when the callback is needed,
564 the HAL_HCD_Connect_Callback could be implenetd in the user file
569 * @brief Disonnexion Event callback.
570 * @param hhcd: HCD handle
573 __weak
void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef
*hhcd
)
575 /* NOTE : This function Should not be modified, when the callback is needed,
576 the HAL_HCD_Disconnect_Callback could be implenetd in the user file
581 * @brief Notify URB state change callback.
582 * @param hhcd: HCD handle
583 * @param chnum: Channel number.
584 * This parameter can be a value from 1 to 15
586 * This parameter can be one of these values:
595 __weak
void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
, HCD_URBStateTypeDef urb_state
)
597 /* NOTE : This function Should not be modified, when the callback is needed,
598 the HAL_HCD_HC_NotifyURBChange_Callback could be implenetd in the user file
606 /** @defgroup HCD_Group3 Peripheral Control functions
607 * @brief management functions
610 ===============================================================================
611 ##### Peripheral Control functions #####
612 ===============================================================================
614 This subsection provides a set of functions allowing to control the HCD data
622 * @brief Start the host driver
623 * @param hhcd: HCD handle
626 HAL_StatusTypeDef
HAL_HCD_Start(HCD_HandleTypeDef
*hhcd
)
629 __HAL_HCD_ENABLE(hhcd
);
630 USB_DriveVbus(hhcd
->Instance
, 1);
636 * @brief Stop the host driver
637 * @param hhcd: HCD handle
641 HAL_StatusTypeDef
HAL_HCD_Stop(HCD_HandleTypeDef
*hhcd
)
644 USB_StopHost(hhcd
->Instance
);
650 * @brief Reset the host port
651 * @param hhcd: HCD handle
654 HAL_StatusTypeDef
HAL_HCD_ResetPort(HCD_HandleTypeDef
*hhcd
)
656 return (USB_ResetPort(hhcd
->Instance
));
663 /** @defgroup HCD_Group4 Peripheral State functions
664 * @brief Peripheral State functions
667 ===============================================================================
668 ##### Peripheral State functions #####
669 ===============================================================================
671 This subsection permits to get in run-time the status of the peripheral
679 * @brief Return the HCD state
680 * @param hhcd: HCD handle
683 HCD_StateTypeDef
HAL_HCD_GetState(HCD_HandleTypeDef
*hhcd
)
689 * @brief Return URB state for a channel
690 * @param hhcd: HCD handle
691 * @param chnum: Channel number.
692 * This parameter can be a value from 1 to 15
694 * This parameter can be one of these values:
702 HCD_URBStateTypeDef
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
704 return hhcd
->hc
[chnum
].urb_state
;
709 * @brief Return the last host transfer size
710 * @param hhcd: HCD handle
711 * @param chnum: Channel number.
712 * This parameter can be a value from 1 to 15
713 * @retval last transfer size in byte
715 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
717 return hhcd
->hc
[chnum
].xfer_count
;
721 * @brief Return the Host Channel state
722 * @param hhcd: HCD handle
723 * @param chnum: Channel number.
724 * This parameter can be a value from 1 to 15
725 * @retval Host channel state
726 * This parameter can be one of the these values:
737 HCD_HCStateTypeDef
HAL_HCD_HC_GetState(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
739 return hhcd
->hc
[chnum
].state
;
743 * @brief Return the current Host frame number
744 * @param hhcd: HCD handle
745 * @retval Current Host frame number
747 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef
*hhcd
)
749 return (USB_GetCurrentFrame(hhcd
->Instance
));
753 * @brief Return the Host enumeration speed
754 * @param hhcd: HCD handle
755 * @retval Enumeration speed
757 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef
*hhcd
)
759 return (USB_GetHostSpeed(hhcd
->Instance
));
767 * @brief This function handles Host Channel IN interrupt requests.
768 * @param hhcd: HCD handle
769 * @param chnum: Channel number.
770 * This parameter can be a value from 1 to 15
773 static void HCD_HC_IN_IRQHandler (HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
775 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
777 if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_AHBERR
)
779 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_AHBERR
);
780 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
782 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_ACK
)
784 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_ACK
);
787 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_STALL
)
789 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
790 hhcd
->hc
[chnum
].state
= HC_STALL
;
791 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
792 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_STALL
);
793 USB_HC_Halt(hhcd
->Instance
, chnum
);
795 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_DTERR
)
797 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
798 USB_HC_Halt(hhcd
->Instance
, chnum
);
799 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
800 hhcd
->hc
[chnum
].state
= HC_DATATGLERR
;
801 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_DTERR
);
804 if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_FRMOR
)
806 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
807 USB_HC_Halt(hhcd
->Instance
, chnum
);
808 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_FRMOR
);
811 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_XFRC
)
814 if (hhcd
->Init
.dma_enable
)
816 hhcd
->hc
[chnum
].xfer_count
= hhcd
->hc
[chnum
].xfer_len
- \
817 (USBx_HC(chnum
)->HCTSIZ
& USB_OTG_HCTSIZ_XFRSIZ
);
820 hhcd
->hc
[chnum
].state
= HC_XFRC
;
821 hhcd
->hc
[chnum
].ErrCnt
= 0;
822 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_XFRC
);
825 if ((hhcd
->hc
[chnum
].ep_type
== EP_TYPE_CTRL
)||
826 (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
))
828 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
829 USB_HC_Halt(hhcd
->Instance
, chnum
);
830 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
833 else if(hhcd
->hc
[chnum
].ep_type
== EP_TYPE_INTR
)
835 USBx_HC(chnum
)->HCCHAR
|= USB_OTG_HCCHAR_ODDFRM
;
836 hhcd
->hc
[chnum
].urb_state
= URB_DONE
;
837 HAL_HCD_HC_NotifyURBChange_Callback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
839 hhcd
->hc
[chnum
].toggle_in
^= 1;
842 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_CHH
)
844 __HAL_HCD_MASK_HALT_HC_INT(chnum
);
846 if(hhcd
->hc
[chnum
].state
== HC_XFRC
)
848 hhcd
->hc
[chnum
].urb_state
= URB_DONE
;
851 else if (hhcd
->hc
[chnum
].state
== HC_STALL
)
853 hhcd
->hc
[chnum
].urb_state
= URB_STALL
;
856 else if((hhcd
->hc
[chnum
].state
== HC_XACTERR
) ||
857 (hhcd
->hc
[chnum
].state
== HC_DATATGLERR
))
859 if(hhcd
->hc
[chnum
].ErrCnt
++ > 3)
861 hhcd
->hc
[chnum
].ErrCnt
= 0;
862 hhcd
->hc
[chnum
].urb_state
= URB_ERROR
;
866 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
869 /* re-activate the channel */
870 USBx_HC(chnum
)->HCCHAR
&= ~USB_OTG_HCCHAR_CHDIS
;
871 USBx_HC(chnum
)->HCCHAR
|= USB_OTG_HCCHAR_CHENA
;
873 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_CHH
);
874 HAL_HCD_HC_NotifyURBChange_Callback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
877 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_TXERR
)
879 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
880 hhcd
->hc
[chnum
].ErrCnt
++;
881 hhcd
->hc
[chnum
].state
= HC_XACTERR
;
882 USB_HC_Halt(hhcd
->Instance
, chnum
);
883 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_TXERR
);
885 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_NAK
)
887 if(hhcd
->hc
[chnum
].ep_type
== EP_TYPE_INTR
)
889 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
890 USB_HC_Halt(hhcd
->Instance
, chnum
);
892 else if ((hhcd
->hc
[chnum
].ep_type
== EP_TYPE_CTRL
)||
893 (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
))
895 /* re-activate the channel */
896 USBx_HC(chnum
)->HCCHAR
&= ~USB_OTG_HCCHAR_CHDIS
;
897 USBx_HC(chnum
)->HCCHAR
|= USB_OTG_HCCHAR_CHENA
;
900 hhcd
->hc
[chnum
].state
= HC_NAK
;
901 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
906 * @brief This function handles Host Channel OUT interrupt requests.
907 * @param hhcd: HCD handle
908 * @param chnum: Channel number.
909 * This parameter can be a value from 1 to 15
912 static void HCD_HC_OUT_IRQHandler (HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
914 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
916 if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_AHBERR
)
918 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_AHBERR
);
919 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
921 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_ACK
)
923 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_ACK
);
925 if( hhcd
->hc
[chnum
].do_ping
== 1)
927 hhcd
->hc
[chnum
].state
= HC_NYET
;
928 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
929 USB_HC_Halt(hhcd
->Instance
, chnum
);
930 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
934 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_NYET
)
936 hhcd
->hc
[chnum
].state
= HC_NYET
;
937 hhcd
->hc
[chnum
].ErrCnt
= 0;
938 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
939 USB_HC_Halt(hhcd
->Instance
, chnum
);
940 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NYET
);
944 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_FRMOR
)
946 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
947 USB_HC_Halt(hhcd
->Instance
, chnum
);
948 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_FRMOR
);
951 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_XFRC
)
953 hhcd
->hc
[chnum
].ErrCnt
= 0;
954 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
955 USB_HC_Halt(hhcd
->Instance
, chnum
);
956 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_XFRC
);
957 hhcd
->hc
[chnum
].state
= HC_XFRC
;
961 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_STALL
)
963 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_STALL
);
964 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
965 USB_HC_Halt(hhcd
->Instance
, chnum
);
966 hhcd
->hc
[chnum
].state
= HC_STALL
;
969 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_NAK
)
971 hhcd
->hc
[chnum
].ErrCnt
= 0;
972 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
973 USB_HC_Halt(hhcd
->Instance
, chnum
);
974 hhcd
->hc
[chnum
].state
= HC_NAK
;
975 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
978 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_TXERR
)
980 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
981 USB_HC_Halt(hhcd
->Instance
, chnum
);
982 hhcd
->hc
[chnum
].state
= HC_XACTERR
;
983 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_TXERR
);
986 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_DTERR
)
988 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
989 USB_HC_Halt(hhcd
->Instance
, chnum
);
990 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
991 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_DTERR
);
992 hhcd
->hc
[chnum
].state
= HC_DATATGLERR
;
996 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_CHH
)
998 __HAL_HCD_MASK_HALT_HC_INT(chnum
);
1000 if(hhcd
->hc
[chnum
].state
== HC_XFRC
)
1002 hhcd
->hc
[chnum
].urb_state
= URB_DONE
;
1003 if (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
)
1005 hhcd
->hc
[chnum
].toggle_out
^= 1;
1008 else if (hhcd
->hc
[chnum
].state
== HC_NAK
)
1010 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1013 else if (hhcd
->hc
[chnum
].state
== HC_NYET
)
1015 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1016 hhcd
->hc
[chnum
].do_ping
= 0;
1019 else if (hhcd
->hc
[chnum
].state
== HC_STALL
)
1021 hhcd
->hc
[chnum
].urb_state
= URB_STALL
;
1024 else if((hhcd
->hc
[chnum
].state
== HC_XACTERR
) ||
1025 (hhcd
->hc
[chnum
].state
== HC_DATATGLERR
))
1027 if(hhcd
->hc
[chnum
].ErrCnt
++ > 3)
1029 hhcd
->hc
[chnum
].ErrCnt
= 0;
1030 hhcd
->hc
[chnum
].urb_state
= URB_ERROR
;
1034 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1037 /* re-activate the channel */
1038 USBx_HC(chnum
)->HCCHAR
&= ~USB_OTG_HCCHAR_CHDIS
;
1039 USBx_HC(chnum
)->HCCHAR
|= USB_OTG_HCCHAR_CHENA
;
1042 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_CHH
);
1043 HAL_HCD_HC_NotifyURBChange_Callback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
1048 * @brief This function handles Rx Queue Level interrupt requests.
1049 * @param hhcd: HCD handle
1052 static void HCD_RXQLVL_IRQHandler (HCD_HandleTypeDef
*hhcd
)
1054 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
1055 uint8_t channelnum
=0;
1060 temp
= hhcd
->Instance
->GRXSTSP
;
1061 channelnum
= temp
& USB_OTG_GRXSTSP_EPNUM
;
1062 pktsts
= (temp
& USB_OTG_GRXSTSP_PKTSTS
) >> 17;
1063 pktcnt
= (temp
& USB_OTG_GRXSTSP_BCNT
) >> 4;
1067 case GRXSTS_PKTSTS_IN
:
1068 /* Read the data into the host buffer. */
1069 if ((pktcnt
> 0) && (hhcd
->hc
[channelnum
].xfer_buff
!= (void *)0))
1072 USB_ReadPacket(hhcd
->Instance
, hhcd
->hc
[channelnum
].xfer_buff
, pktcnt
);
1074 /*manage multiple Xfer */
1075 hhcd
->hc
[channelnum
].xfer_buff
+= pktcnt
;
1076 hhcd
->hc
[channelnum
].xfer_count
+= pktcnt
;
1078 if((USBx_HC(channelnum
)->HCTSIZ
& USB_OTG_HCTSIZ_PKTCNT
) > 0)
1080 /* re-activate the channel when more packets are expected */
1081 USBx_HC(channelnum
)->HCCHAR
&= ~USB_OTG_HCCHAR_CHDIS
;
1082 USBx_HC(channelnum
)->HCCHAR
|= USB_OTG_HCCHAR_CHENA
;
1083 hhcd
->hc
[channelnum
].toggle_in
^= 1;
1088 case GRXSTS_PKTSTS_DATA_TOGGLE_ERR
:
1090 case GRXSTS_PKTSTS_IN_XFER_COMP
:
1091 case GRXSTS_PKTSTS_CH_HALTED
:
1098 * @brief This function handles Host Port interrupt requests.
1099 * @param hhcd: HCD handle
1102 static void HCD_Port_IRQHandler (HCD_HandleTypeDef
*hhcd
)
1104 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
1105 __IO
uint32_t hprt0
, hprt0_dup
;
1107 /* Handle Host Port Interrupts */
1109 hprt0_dup
= USBx_HPRT0
;
1111 hprt0_dup
&= ~(USB_OTG_HPRT_PENA
| USB_OTG_HPRT_PCDET
|\
1112 USB_OTG_HPRT_PENCHNG
| USB_OTG_HPRT_POCCHNG
);
1114 /* Check wether Port Connect Detected */
1115 if((hprt0
& USB_OTG_HPRT_PCDET
) == USB_OTG_HPRT_PCDET
)
1117 if((hprt0
& USB_OTG_HPRT_PCSTS
) == USB_OTG_HPRT_PCSTS
)
1119 USB_MASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_DISCINT
);
1120 HAL_HCD_Connect_Callback(hhcd
);
1122 hprt0_dup
|= USB_OTG_HPRT_PCDET
;
1126 /* Check whether Port Enable Changed */
1127 if((hprt0
& USB_OTG_HPRT_PENCHNG
) == USB_OTG_HPRT_PENCHNG
)
1129 hprt0_dup
|= USB_OTG_HPRT_PENCHNG
;
1131 if((hprt0
& USB_OTG_HPRT_PENA
) == USB_OTG_HPRT_PENA
)
1133 if(hhcd
->Init
.phy_itface
== USB_OTG_EMBEDDED_PHY
)
1135 if ((hprt0
& USB_OTG_HPRT_PSPD
) == (HPRT0_PRTSPD_LOW_SPEED
<< 17))
1137 USB_InitFSLSPClkSel(hhcd
->Instance
,HCFG_6_MHZ
);
1141 USB_InitFSLSPClkSel(hhcd
->Instance
,HCFG_48_MHZ
);
1146 if(hhcd
->Init
.speed
== HCD_SPEED_FULL
)
1148 USBx_HOST
->HFIR
= (uint32_t)60000;
1151 HAL_HCD_Connect_Callback(hhcd
);
1153 if(hhcd
->Init
.speed
== HCD_SPEED_HIGH
)
1155 USB_UNMASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_DISCINT
);
1161 USBx_HPRT0
&= ~(USB_OTG_HPRT_PENA
| USB_OTG_HPRT_PCDET
|\
1162 USB_OTG_HPRT_PENCHNG
| USB_OTG_HPRT_POCCHNG
);
1164 USB_UNMASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_DISCINT
);
1168 /* Check For an overcurrent */
1169 if((hprt0
& USB_OTG_HPRT_POCCHNG
) == USB_OTG_HPRT_POCCHNG
)
1171 hprt0_dup
|= USB_OTG_HPRT_POCCHNG
;
1174 /* Clear Port Interrupts */
1175 USBx_HPRT0
= hprt0_dup
;
1182 #endif /* HAL_HCD_MODULE_ENABLED */
1191 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/