2 ******************************************************************************
3 * @file stm32f1xx_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 macro
29 (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE()
31 (##) Initialize the related GPIO clocks
32 (##) Configure HCD pin-out
33 (##) Configure HCD NVIC interrupt
35 (#)Associate the Upper USB Host stack to the HAL HCD Driver:
36 (##) hhcd.pData = phost;
38 (#)Enable HCD transmission and reception:
42 ******************************************************************************
45 * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
47 * Redistribution and use in source and binary forms, with or without modification,
48 * are permitted provided that the following conditions are met:
49 * 1. Redistributions of source code must retain the above copyright notice,
50 * this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright notice,
52 * this list of conditions and the following disclaimer in the documentation
53 * and/or other materials provided with the distribution.
54 * 3. Neither the name of STMicroelectronics nor the names of its contributors
55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission.
58 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
59 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
61 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
64 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
65 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
66 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
67 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69 ******************************************************************************
72 /* Includes ------------------------------------------------------------------*/
73 #include "stm32f1xx_hal.h"
74 /** @addtogroup STM32F1xx_HAL_Driver
79 #ifdef HAL_HCD_MODULE_ENABLED
81 #if defined(STM32F105xC) || defined(STM32F107xC)
84 * @brief HCD HAL module driver
88 /* Private types -------------------------------------------------------------*/
89 /* Private variables ---------------------------------------------------------*/
90 /* Private constants ---------------------------------------------------------*/
91 /* Private macros ------------------------------------------------------------*/
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 if(hhcd
->State
== HAL_HCD_STATE_RESET
)
140 /* Allocate lock resource and initialize it */
141 hhcd
->Lock
= HAL_UNLOCKED
;
143 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
144 HAL_HCD_MspInit(hhcd
);
147 hhcd
->State
= HAL_HCD_STATE_BUSY
;
149 /* Disable the Interrupts */
150 __HAL_HCD_DISABLE(hhcd
);
152 /* Init the Core (common init.) */
153 USB_CoreInit(hhcd
->Instance
, hhcd
->Init
);
156 USB_SetCurrentMode(hhcd
->Instance
, USB_HOST_MODE
);
159 USB_HostInit(hhcd
->Instance
, hhcd
->Init
);
161 hhcd
->State
= HAL_HCD_STATE_READY
;
167 * @brief Initialize a host channel
168 * @param hhcd: HCD handle
169 * @param ch_num: Channel number.
170 * This parameter can be a value from 1 to 15
171 * @param epnum: Endpoint number.
172 * This parameter can be a value from 1 to 15
173 * @param dev_address : Current device address
174 * This parameter can be a value from 0 to 255
175 * @param speed: Current device speed.
176 * This parameter can be one of these values:
177 * HCD_SPEED_FULL: Full speed mode,
178 * HCD_SPEED_LOW: Low speed mode
179 * @param ep_type: Endpoint Type.
180 * This parameter can be one of these values:
181 * EP_TYPE_CTRL: Control type,
182 * EP_TYPE_ISOC: Isochronous type,
183 * EP_TYPE_BULK: Bulk type,
184 * EP_TYPE_INTR: Interrupt type
185 * @param mps: Max Packet Size.
186 * This parameter can be a value from 0 to32K
189 HAL_StatusTypeDef
HAL_HCD_HC_Init(HCD_HandleTypeDef
*hhcd
,
197 HAL_StatusTypeDef status
= HAL_OK
;
201 hhcd
->hc
[ch_num
].dev_addr
= dev_address
;
202 hhcd
->hc
[ch_num
].max_packet
= mps
;
203 hhcd
->hc
[ch_num
].ch_num
= ch_num
;
204 hhcd
->hc
[ch_num
].ep_type
= ep_type
;
205 hhcd
->hc
[ch_num
].ep_num
= epnum
& 0x7FU
;
206 hhcd
->hc
[ch_num
].ep_is_in
= ((epnum
& 0x80U
) == 0x80U
);
207 hhcd
->hc
[ch_num
].speed
= speed
;
209 status
= USB_HC_Init(hhcd
->Instance
,
222 * @brief Halt a host channel
223 * @param hhcd: HCD handle
224 * @param ch_num: Channel number.
225 * This parameter can be a value from 1 to 15
228 HAL_StatusTypeDef
HAL_HCD_HC_Halt(HCD_HandleTypeDef
*hhcd
,
232 USB_HC_Halt(hhcd
->Instance
, ch_num
);
239 * @brief DeInitialize the host driver
240 * @param hhcd: HCD handle
243 HAL_StatusTypeDef
HAL_HCD_DeInit(HCD_HandleTypeDef
*hhcd
)
245 /* Check the HCD handle allocation */
251 hhcd
->State
= HAL_HCD_STATE_BUSY
;
253 /* DeInit the low level hardware */
254 HAL_HCD_MspDeInit(hhcd
);
256 __HAL_HCD_DISABLE(hhcd
);
258 hhcd
->State
= HAL_HCD_STATE_RESET
;
264 * @brief Initializes the HCD MSP.
265 * @param hhcd: HCD handle
268 __weak
void HAL_HCD_MspInit(HCD_HandleTypeDef
*hhcd
)
270 /* Prevent unused argument(s) compilation warning */
272 /* NOTE : This function Should not be modified, when the callback is needed,
273 the HAL_HCD_MspInit could be implemented in the user file
278 * @brief DeInitializes HCD MSP.
279 * @param hhcd: HCD handle
282 __weak
void HAL_HCD_MspDeInit(HCD_HandleTypeDef
*hhcd
)
284 /* Prevent unused argument(s) compilation warning */
286 /* NOTE : This function Should not be modified, when the callback is needed,
287 the HAL_HCD_MspDeInit could be implemented in the user file
295 /** @defgroup HCD_Exported_Functions_Group2 IO operation functions
296 * @brief HCD IO operation functions
299 ===============================================================================
300 ##### IO operation functions #####
301 ===============================================================================
302 This subsection provides a set of functions allowing to manage the USB Host Data
310 * @brief Submit a new URB for processing
311 * @param hhcd: HCD handle
312 * @param ch_num: Channel number.
313 * This parameter can be a value from 1 to 15
314 * @param direction: Channel number.
315 * This parameter can be one of these values:
316 * 0 : Output / 1 : Input
317 * @param ep_type: Endpoint Type.
318 * This parameter can be one of these values:
319 * EP_TYPE_CTRL: Control type/
320 * EP_TYPE_ISOC: Isochronous type/
321 * EP_TYPE_BULK: Bulk type/
322 * EP_TYPE_INTR: Interrupt type/
323 * @param token: Endpoint Type.
324 * This parameter can be one of these values:
325 * 0: HC_PID_SETUP / 1: HC_PID_DATA1
326 * @param pbuff: pointer to URB data
327 * @param length: Length of URB data
328 * @param do_ping: activate do ping protocol (for high speed only).
329 * This parameter can be one of these values:
330 * 0 : do ping inactive / 1 : do ping active
333 HAL_StatusTypeDef
HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef
*hhcd
,
342 hhcd
->hc
[ch_num
].ep_is_in
= direction
;
343 hhcd
->hc
[ch_num
].ep_type
= ep_type
;
347 hhcd
->hc
[ch_num
].data_pid
= HC_PID_SETUP
;
351 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
354 /* Manage Data Toggle */
358 if((token
== 1U) && (direction
== 0U)) /*send data */
361 { /* For Status OUT stage, Length==0, Status Out PID = 1 */
362 hhcd
->hc
[ch_num
].toggle_out
= 1U;
365 /* Set the Data Toggle bit as per the Flag */
366 if ( hhcd
->hc
[ch_num
].toggle_out
== 0U)
367 { /* Put the PID 0 */
368 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
371 { /* Put the PID 1 */
372 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
374 if(hhcd
->hc
[ch_num
].urb_state
!= URB_NOTREADY
)
376 hhcd
->hc
[ch_num
].do_ping
= do_ping
;
384 /* Set the Data Toggle bit as per the Flag */
385 if ( hhcd
->hc
[ch_num
].toggle_out
== 0U)
386 { /* Put the PID 0 */
387 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
390 { /* Put the PID 1 */
391 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
393 if(hhcd
->hc
[ch_num
].urb_state
!= URB_NOTREADY
)
395 hhcd
->hc
[ch_num
].do_ping
= do_ping
;
400 if( hhcd
->hc
[ch_num
].toggle_in
== 0U)
402 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
406 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
414 /* Set the Data Toggle bit as per the Flag */
415 if ( hhcd
->hc
[ch_num
].toggle_out
== 0U)
416 { /* Put the PID 0 */
417 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
420 { /* Put the PID 1 */
421 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
426 if( hhcd
->hc
[ch_num
].toggle_in
== 0U)
428 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
432 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
438 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
442 hhcd
->hc
[ch_num
].xfer_buff
= pbuff
;
443 hhcd
->hc
[ch_num
].xfer_len
= length
;
444 hhcd
->hc
[ch_num
].urb_state
= URB_IDLE
;
445 hhcd
->hc
[ch_num
].xfer_count
= 0U;
446 hhcd
->hc
[ch_num
].ch_num
= ch_num
;
447 hhcd
->hc
[ch_num
].state
= HC_IDLE
;
449 return USB_HC_StartXfer(hhcd
->Instance
, &(hhcd
->hc
[ch_num
]));
453 * @brief handle HCD interrupt request.
454 * @param hhcd: HCD handle
457 void HAL_HCD_IRQHandler(HCD_HandleTypeDef
*hhcd
)
459 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
461 uint32_t index
= 0U, interrupt
= 0U;
463 /* ensure that we are in device mode */
464 if (USB_GetMode(hhcd
->Instance
) == USB_OTG_MODE_HOST
)
466 /* Avoid spurious interrupt */
467 if(__HAL_HCD_IS_INVALID_INTERRUPT(hhcd
))
472 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT
))
474 /* Incorrect mode, acknowledge the interrupt */
475 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT
);
478 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_IISOIXFR
))
480 /* Incorrect mode, acknowledge the interrupt */
481 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_IISOIXFR
);
484 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_PTXFE
))
486 /* Incorrect mode, acknowledge the interrupt */
487 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_PTXFE
);
490 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_MMIS
))
492 /* Incorrect mode, acknowledge the interrupt */
493 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_MMIS
);
496 /* Handle Host Disconnect Interrupts */
497 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_DISCINT
))
501 USBx_HPRT0
&= ~(USB_OTG_HPRT_PENA
| USB_OTG_HPRT_PCDET
|\
502 USB_OTG_HPRT_PENCHNG
| USB_OTG_HPRT_POCCHNG
);
504 /* Handle Host Port Interrupts */
505 HAL_HCD_Disconnect_Callback(hhcd
);
506 USB_InitFSLSPClkSel(hhcd
->Instance
,HCFG_48_MHZ
);
507 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_DISCINT
);
510 /* Handle Host Port Interrupts */
511 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_HPRTINT
))
513 HCD_Port_IRQHandler (hhcd
);
516 /* Handle Host SOF Interrupts */
517 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_SOF
))
519 HAL_HCD_SOF_Callback(hhcd
);
520 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_SOF
);
523 /* Handle Host channel Interrupts */
524 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_HCINT
))
526 interrupt
= USB_HC_ReadInterrupt(hhcd
->Instance
);
527 for (index
= 0U; index
< hhcd
->Init
.Host_channels
; index
++)
529 if (interrupt
& (1 << index
))
531 if ((USBx_HC(index
)->HCCHAR
) & USB_OTG_HCCHAR_EPDIR
)
533 HCD_HC_IN_IRQHandler (hhcd
, index
);
537 HCD_HC_OUT_IRQHandler (hhcd
, index
);
541 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_HCINT
);
544 /* Handle Rx Queue Level Interrupts */
545 if(__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_RXFLVL
))
547 USB_MASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_RXFLVL
);
549 HCD_RXQLVL_IRQHandler (hhcd
);
551 USB_UNMASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_RXFLVL
);
557 * @brief SOF callback.
558 * @param hhcd: HCD handle
561 __weak
void HAL_HCD_SOF_Callback(HCD_HandleTypeDef
*hhcd
)
563 /* Prevent unused argument(s) compilation warning */
565 /* NOTE : This function Should not be modified, when the callback is needed,
566 the HAL_HCD_SOF_Callback could be implemented in the user file
571 * @brief Connexion Event callback.
572 * @param hhcd: HCD handle
575 __weak
void HAL_HCD_Connect_Callback(HCD_HandleTypeDef
*hhcd
)
577 /* Prevent unused argument(s) compilation warning */
579 /* NOTE : This function Should not be modified, when the callback is needed,
580 the HAL_HCD_Connect_Callback could be implemented in the user file
585 * @brief Disonnection Event callback.
586 * @param hhcd: HCD handle
589 __weak
void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef
*hhcd
)
591 /* 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 */
619 /* NOTE : This function Should not be modified, when the callback is needed,
620 the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
628 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
629 * @brief management functions
632 ===============================================================================
633 ##### Peripheral Control functions #####
634 ===============================================================================
636 This subsection provides a set of functions allowing to control the HCD data
644 * @brief Start the host driver
645 * @param hhcd: HCD handle
648 HAL_StatusTypeDef
HAL_HCD_Start(HCD_HandleTypeDef
*hhcd
)
651 __HAL_HCD_ENABLE(hhcd
);
652 USB_DriveVbus(hhcd
->Instance
, 1U);
658 * @brief Stop the host driver
659 * @param hhcd: HCD handle
663 HAL_StatusTypeDef
HAL_HCD_Stop(HCD_HandleTypeDef
*hhcd
)
666 USB_StopHost(hhcd
->Instance
);
672 * @brief Reset the host port
673 * @param hhcd: HCD handle
676 HAL_StatusTypeDef
HAL_HCD_ResetPort(HCD_HandleTypeDef
*hhcd
)
678 return (USB_ResetPort(hhcd
->Instance
));
685 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
686 * @brief Peripheral State functions
689 ===============================================================================
690 ##### Peripheral State functions #####
691 ===============================================================================
693 This subsection permits to get in run-time the status of the peripheral
701 * @brief Return the HCD handle state
702 * @param hhcd: HCD handle
705 HCD_StateTypeDef
HAL_HCD_GetState(HCD_HandleTypeDef
*hhcd
)
711 * @brief Return URB state for a channel
712 * @param hhcd: HCD handle
713 * @param chnum: Channel number.
714 * This parameter can be a value from 1 to 15
716 * This parameter can be one of these values:
724 HCD_URBStateTypeDef
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
726 return hhcd
->hc
[chnum
].urb_state
;
731 * @brief Return the last host transfer size
732 * @param hhcd: HCD handle
733 * @param chnum: Channel number.
734 * This parameter can be a value from 1 to 15
735 * @retval last transfer size in byte
737 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
739 return hhcd
->hc
[chnum
].xfer_count
;
743 * @brief Return the Host Channel state
744 * @param hhcd: HCD handle
745 * @param chnum: Channel number.
746 * This parameter can be a value from 1 to 15
747 * @retval Host channel state
748 * This parameter can be one of the these values:
759 HCD_HCStateTypeDef
HAL_HCD_HC_GetState(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
761 return hhcd
->hc
[chnum
].state
;
765 * @brief Return the current Host frame number
766 * @param hhcd: HCD handle
767 * @retval Current Host frame number
769 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef
*hhcd
)
771 return (USB_GetCurrentFrame(hhcd
->Instance
));
775 * @brief Return the Host enumeration speed
776 * @param hhcd: HCD handle
777 * @retval Enumeration speed
779 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef
*hhcd
)
781 return (USB_GetHostSpeed(hhcd
->Instance
));
791 /** @addtogroup HCD_Private_Functions
795 * @brief This function handles 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
;
804 uint32_t tmpreg
= 0U;
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
)
842 hhcd
->hc
[chnum
].state
= HC_XFRC
;
843 hhcd
->hc
[chnum
].ErrCnt
= 0U;
844 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_XFRC
);
846 if ((hhcd
->hc
[chnum
].ep_type
== EP_TYPE_CTRL
)||
847 (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
))
849 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
850 USB_HC_Halt(hhcd
->Instance
, chnum
);
851 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
854 else if(hhcd
->hc
[chnum
].ep_type
== EP_TYPE_INTR
)
856 USBx_HC(chnum
)->HCCHAR
|= USB_OTG_HCCHAR_ODDFRM
;
857 hhcd
->hc
[chnum
].urb_state
= URB_DONE
;
858 HAL_HCD_HC_NotifyURBChange_Callback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
860 hhcd
->hc
[chnum
].toggle_in
^= 1U;
863 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_CHH
)
865 __HAL_HCD_MASK_HALT_HC_INT(chnum
);
867 if(hhcd
->hc
[chnum
].state
== HC_XFRC
)
869 hhcd
->hc
[chnum
].urb_state
= URB_DONE
;
871 else if (hhcd
->hc
[chnum
].state
== HC_STALL
)
873 hhcd
->hc
[chnum
].urb_state
= URB_STALL
;
875 else if((hhcd
->hc
[chnum
].state
== HC_XACTERR
) ||
876 (hhcd
->hc
[chnum
].state
== HC_DATATGLERR
))
878 if(hhcd
->hc
[chnum
].ErrCnt
++ > 3U)
880 hhcd
->hc
[chnum
].ErrCnt
= 0U;
881 hhcd
->hc
[chnum
].urb_state
= URB_ERROR
;
885 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
888 /* re-activate the channel */
889 tmpreg
= USBx_HC(chnum
)->HCCHAR
;
890 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
891 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
892 USBx_HC(chnum
)->HCCHAR
= tmpreg
;
894 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_CHH
);
895 HAL_HCD_HC_NotifyURBChange_Callback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
898 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_TXERR
)
900 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
901 hhcd
->hc
[chnum
].ErrCnt
++;
902 hhcd
->hc
[chnum
].state
= HC_XACTERR
;
903 USB_HC_Halt(hhcd
->Instance
, chnum
);
904 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_TXERR
);
906 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_NAK
)
908 if(hhcd
->hc
[chnum
].ep_type
== EP_TYPE_INTR
)
910 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
911 USB_HC_Halt(hhcd
->Instance
, chnum
);
913 else if ((hhcd
->hc
[chnum
].ep_type
== EP_TYPE_CTRL
)||
914 (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
))
916 /* re-activate the channel */
917 tmpreg
= USBx_HC(chnum
)->HCCHAR
;
918 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
919 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
920 USBx_HC(chnum
)->HCCHAR
= tmpreg
;
922 hhcd
->hc
[chnum
].state
= HC_NAK
;
923 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
928 * @brief This function handles Host Channel OUT interrupt requests.
929 * @param hhcd: HCD handle
930 * @param chnum: Channel number.
931 * This parameter can be a value from 1 to 15
934 static void HCD_HC_OUT_IRQHandler (HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
936 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
937 uint32_t tmpreg
= 0U;
939 if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_AHBERR
)
941 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_AHBERR
);
942 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
944 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_ACK
)
946 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_ACK
);
948 if( hhcd
->hc
[chnum
].do_ping
== 1U)
950 hhcd
->hc
[chnum
].state
= HC_NYET
;
951 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
952 USB_HC_Halt(hhcd
->Instance
, chnum
);
953 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
957 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_NYET
)
959 hhcd
->hc
[chnum
].state
= HC_NYET
;
960 hhcd
->hc
[chnum
].ErrCnt
= 0U;
961 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
962 USB_HC_Halt(hhcd
->Instance
, chnum
);
963 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NYET
);
967 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_FRMOR
)
969 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
970 USB_HC_Halt(hhcd
->Instance
, chnum
);
971 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_FRMOR
);
974 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_XFRC
)
976 hhcd
->hc
[chnum
].ErrCnt
= 0U;
977 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
978 USB_HC_Halt(hhcd
->Instance
, chnum
);
979 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_XFRC
);
980 hhcd
->hc
[chnum
].state
= HC_XFRC
;
982 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_STALL
)
984 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_STALL
);
985 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
986 USB_HC_Halt(hhcd
->Instance
, chnum
);
987 hhcd
->hc
[chnum
].state
= HC_STALL
;
989 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_NAK
)
991 hhcd
->hc
[chnum
].ErrCnt
= 0U;
992 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
993 USB_HC_Halt(hhcd
->Instance
, chnum
);
994 hhcd
->hc
[chnum
].state
= HC_NAK
;
995 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
997 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_TXERR
)
999 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
1000 USB_HC_Halt(hhcd
->Instance
, chnum
);
1001 hhcd
->hc
[chnum
].state
= HC_XACTERR
;
1002 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_TXERR
);
1004 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_DTERR
)
1006 __HAL_HCD_UNMASK_HALT_HC_INT(chnum
);
1007 USB_HC_Halt(hhcd
->Instance
, chnum
);
1008 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
1009 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_DTERR
);
1010 hhcd
->hc
[chnum
].state
= HC_DATATGLERR
;
1012 else if ((USBx_HC(chnum
)->HCINT
) & USB_OTG_HCINT_CHH
)
1014 __HAL_HCD_MASK_HALT_HC_INT(chnum
);
1016 if(hhcd
->hc
[chnum
].state
== HC_XFRC
)
1018 hhcd
->hc
[chnum
].urb_state
= URB_DONE
;
1019 if (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
)
1021 hhcd
->hc
[chnum
].toggle_out
^= 1U;
1024 else if (hhcd
->hc
[chnum
].state
== HC_NAK
)
1026 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1028 else if (hhcd
->hc
[chnum
].state
== HC_NYET
)
1030 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1031 hhcd
->hc
[chnum
].do_ping
= 0U;
1033 else if (hhcd
->hc
[chnum
].state
== HC_STALL
)
1035 hhcd
->hc
[chnum
].urb_state
= URB_STALL
;
1037 else if((hhcd
->hc
[chnum
].state
== HC_XACTERR
) ||
1038 (hhcd
->hc
[chnum
].state
== HC_DATATGLERR
))
1040 if(hhcd
->hc
[chnum
].ErrCnt
++ > 3U)
1042 hhcd
->hc
[chnum
].ErrCnt
= 0U;
1043 hhcd
->hc
[chnum
].urb_state
= URB_ERROR
;
1047 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1050 /* re-activate the channel */
1051 tmpreg
= USBx_HC(chnum
)->HCCHAR
;
1052 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
1053 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
1054 USBx_HC(chnum
)->HCCHAR
= tmpreg
;
1057 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_CHH
);
1058 HAL_HCD_HC_NotifyURBChange_Callback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
1063 * @brief This function handles Rx Queue Level interrupt requests.
1064 * @param hhcd: HCD handle
1067 static void HCD_RXQLVL_IRQHandler (HCD_HandleTypeDef
*hhcd
)
1069 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
1070 uint8_t channelnum
=0U;
1074 uint32_t tmpreg
= 0U;
1076 temp
= hhcd
->Instance
->GRXSTSP
;
1077 channelnum
= temp
& USB_OTG_GRXSTSP_EPNUM
;
1078 pktsts
= (temp
& USB_OTG_GRXSTSP_PKTSTS
) >> 17U;
1079 pktcnt
= (temp
& USB_OTG_GRXSTSP_BCNT
) >> 4U;
1083 case GRXSTS_PKTSTS_IN
:
1084 /* Read the data into the host buffer. */
1085 if ((pktcnt
> 0U) && (hhcd
->hc
[channelnum
].xfer_buff
!= (void *)0U))
1087 USB_ReadPacket(hhcd
->Instance
, hhcd
->hc
[channelnum
].xfer_buff
, pktcnt
);
1089 /*manage multiple Xfer */
1090 hhcd
->hc
[channelnum
].xfer_buff
+= pktcnt
;
1091 hhcd
->hc
[channelnum
].xfer_count
+= pktcnt
;
1093 if((USBx_HC(channelnum
)->HCTSIZ
& USB_OTG_HCTSIZ_PKTCNT
) > 0U)
1095 /* re-activate the channel when more packets are expected */
1096 tmpreg
= USBx_HC(channelnum
)->HCCHAR
;
1097 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
1098 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
1099 USBx_HC(channelnum
)->HCCHAR
= tmpreg
;
1100 hhcd
->hc
[channelnum
].toggle_in
^= 1U;
1105 case GRXSTS_PKTSTS_DATA_TOGGLE_ERR
:
1108 case GRXSTS_PKTSTS_IN_XFER_COMP
:
1109 case GRXSTS_PKTSTS_CH_HALTED
:
1116 * @brief This function handles Host Port interrupt requests.
1117 * @param hhcd: HCD handle
1120 static void HCD_Port_IRQHandler (HCD_HandleTypeDef
*hhcd
)
1122 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
1123 __IO
uint32_t hprt0
= 0, hprt0_dup
= 0U;
1125 /* Handle Host Port Interrupts */
1127 hprt0_dup
= USBx_HPRT0
;
1129 hprt0_dup
&= ~(USB_OTG_HPRT_PENA
| USB_OTG_HPRT_PCDET
|\
1130 USB_OTG_HPRT_PENCHNG
| USB_OTG_HPRT_POCCHNG
);
1132 /* Check whether Port Connect Detected */
1133 if((hprt0
& USB_OTG_HPRT_PCDET
) == USB_OTG_HPRT_PCDET
)
1135 if((hprt0
& USB_OTG_HPRT_PCSTS
) == USB_OTG_HPRT_PCSTS
)
1137 USB_MASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_DISCINT
);
1138 HAL_HCD_Connect_Callback(hhcd
);
1140 hprt0_dup
|= USB_OTG_HPRT_PCDET
;
1143 /* Check whether Port Enable Changed */
1144 if((hprt0
& USB_OTG_HPRT_PENCHNG
) == USB_OTG_HPRT_PENCHNG
)
1146 hprt0_dup
|= USB_OTG_HPRT_PENCHNG
;
1148 if((hprt0
& USB_OTG_HPRT_PENA
) == USB_OTG_HPRT_PENA
)
1150 if ((hprt0
& USB_OTG_HPRT_PSPD
) == (HPRT0_PRTSPD_LOW_SPEED
<< 17U))
1152 USB_InitFSLSPClkSel(hhcd
->Instance
,HCFG_6_MHZ
);
1156 USB_InitFSLSPClkSel(hhcd
->Instance
,HCFG_48_MHZ
);
1158 HAL_HCD_Connect_Callback(hhcd
);
1163 USBx_HPRT0
&= ~(USB_OTG_HPRT_PENA
| USB_OTG_HPRT_PCDET
|\
1164 USB_OTG_HPRT_PENCHNG
| USB_OTG_HPRT_POCCHNG
);
1166 USB_UNMASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_DISCINT
);
1170 /* Check For an over current */
1171 if((hprt0
& USB_OTG_HPRT_POCCHNG
) == USB_OTG_HPRT_POCCHNG
)
1173 hprt0_dup
|= USB_OTG_HPRT_POCCHNG
;
1176 /* Clear Port Interrupts */
1177 USBx_HPRT0
= hprt0_dup
;
1188 #endif /* STM32F105xC || STM32F107xC */
1190 #endif /* HAL_HCD_MODULE_ENABLED */
1196 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/