2 ******************************************************************************
\r
3 * @file stm32f7xx_hal_hcd.c
\r
4 * @author MCD Application Team
\r
6 * @date 06-March-2015
\r
7 * @brief HCD HAL module driver.
\r
8 * This file provides firmware functions to manage the following
\r
9 * functionalities of the USB Peripheral Controller:
\r
10 * + Initialization and de-initialization functions
\r
11 * + IO operation functions
\r
12 * + Peripheral Control functions
\r
13 * + Peripheral State functions
\r
16 ==============================================================================
\r
17 ##### How to use this driver #####
\r
18 ==============================================================================
\r
20 (#)Declare a HCD_HandleTypeDef handle structure, for example:
\r
21 HCD_HandleTypeDef hhcd;
\r
23 (#)Fill parameters of Init structure in HCD handle
\r
25 (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
\r
27 (#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
\r
28 (##) Enable the HCD/USB Low Level interface clock using the following macros
\r
29 (+++) __OTGFS-OTG_CLK_ENABLE() or __OTGHS-OTG_CLK_ENABLE()
\r
30 (+++) __OTGHSULPI_CLK_ENABLE() For High Speed Mode
\r
32 (##) Initialize the related GPIO clocks
\r
33 (##) Configure HCD pin-out
\r
34 (##) Configure HCD NVIC interrupt
\r
36 (#)Associate the Upper USB Host stack to the HAL HCD Driver:
\r
37 (##) hhcd.pData = phost;
\r
39 (#)Enable HCD transmission and reception:
\r
40 (##) HAL_HCD_Start();
\r
43 ******************************************************************************
\r
46 * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
\r
48 * Redistribution and use in source and binary forms, with or without modification,
\r
49 * are permitted provided that the following conditions are met:
\r
50 * 1. Redistributions of source code must retain the above copyright notice,
\r
51 * this list of conditions and the following disclaimer.
\r
52 * 2. Redistributions in binary form must reproduce the above copyright notice,
\r
53 * this list of conditions and the following disclaimer in the documentation
\r
54 * and/or other materials provided with the distribution.
\r
55 * 3. Neither the name of STMicroelectronics nor the names of its contributors
\r
56 * may be used to endorse or promote products derived from this software
\r
57 * without specific prior written permission.
\r
59 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
\r
60 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
\r
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
\r
62 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
\r
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
\r
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
\r
65 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
\r
66 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
\r
67 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
\r
68 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
70 ******************************************************************************
\r
73 /* Includes ------------------------------------------------------------------*/
\r
74 #include "stm32f7xx_hal.h"
\r
76 /** @addtogroup STM32F7xx_HAL_Driver
\r
84 #ifdef HAL_HCD_MODULE_ENABLED
\r
86 /* Private typedef -----------------------------------------------------------*/
\r
87 /* Private define ------------------------------------------------------------*/
\r
88 /* Private macro -------------------------------------------------------------*/
\r
89 /* Private variables ---------------------------------------------------------*/
\r
90 /* Private function ----------------------------------------------------------*/
\r
91 /** @addtogroup HCD_Private_Functions
\r
94 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
\r
95 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
\r
96 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd);
\r
97 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
\r
102 /* Exported functions --------------------------------------------------------*/
\r
103 /** @addtogroup HCD_Exported_Functions
\r
107 /** @addtogroup HCD_Exported_Functions_Group1
\r
108 * @brief Initialization and de-initialization functions
\r
111 ===============================================================================
\r
112 ##### Initialization and de-initialization functions #####
\r
113 ===============================================================================
\r
114 [..] This section provides functions allowing to:
\r
121 * @brief Initialize the host driver
\r
122 * @param hhcd: HCD handle
\r
123 * @retval HAL status
\r
125 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
\r
127 /* Check the HCD handle allocation */
\r
133 /* Check the parameters */
\r
134 assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
\r
136 hhcd->State = HAL_HCD_STATE_BUSY;
\r
138 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
\r
139 HAL_HCD_MspInit(hhcd);
\r
141 /* Disable the Interrupts */
\r
142 __HAL_HCD_DISABLE(hhcd);
\r
144 /*Init the Core (common init.) */
\r
145 USB_CoreInit(hhcd->Instance, hhcd->Init);
\r
147 /* Force Host Mode*/
\r
148 USB_SetCurrentMode(hhcd->Instance , USB_OTG_HOST_MODE);
\r
151 USB_HostInit(hhcd->Instance, hhcd->Init);
\r
153 hhcd->State= HAL_HCD_STATE_READY;
\r
159 * @brief Initialize a host channel
\r
160 * @param hhcd: HCD handle
\r
161 * @param ch_num: Channel number.
\r
162 * This parameter can be a value from 1 to 15
\r
163 * @param epnum: Endpoint number.
\r
164 * This parameter can be a value from 1 to 15
\r
165 * @param dev_address : Current device address
\r
166 * This parameter can be a value from 0 to 255
\r
167 * @param speed: Current device speed.
\r
168 * This parameter can be one of these values:
\r
169 * HCD_SPEED_HIGH: High speed mode,
\r
170 * HCD_SPEED_FULL: Full speed mode,
\r
171 * HCD_SPEED_LOW: Low speed mode
\r
172 * @param ep_type: Endpoint Type.
\r
173 * This parameter can be one of these values:
\r
174 * EP_TYPE_CTRL: Control type,
\r
175 * EP_TYPE_ISOC: Isochronous type,
\r
176 * EP_TYPE_BULK: Bulk type,
\r
177 * EP_TYPE_INTR: Interrupt type
\r
178 * @param mps: Max Packet Size.
\r
179 * This parameter can be a value from 0 to32K
\r
180 * @retval HAL status
\r
182 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd,
\r
185 uint8_t dev_address,
\r
190 HAL_StatusTypeDef status = HAL_OK;
\r
194 hhcd->hc[ch_num].dev_addr = dev_address;
\r
195 hhcd->hc[ch_num].max_packet = mps;
\r
196 hhcd->hc[ch_num].ch_num = ch_num;
\r
197 hhcd->hc[ch_num].ep_type = ep_type;
\r
198 hhcd->hc[ch_num].ep_num = epnum & 0x7F;
\r
199 hhcd->hc[ch_num].ep_is_in = ((epnum & 0x80) == 0x80);
\r
200 hhcd->hc[ch_num].speed = speed;
\r
202 status = USB_HC_Init(hhcd->Instance,
\r
209 __HAL_UNLOCK(hhcd);
\r
215 * @brief Halt a host channel
\r
216 * @param hhcd: HCD handle
\r
217 * @param ch_num: Channel number.
\r
218 * This parameter can be a value from 1 to 15
\r
219 * @retval HAL status
\r
221 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
\r
223 HAL_StatusTypeDef status = HAL_OK;
\r
226 USB_HC_Halt(hhcd->Instance, ch_num);
\r
227 __HAL_UNLOCK(hhcd);
\r
233 * @brief DeInitialize the host driver
\r
234 * @param hhcd: HCD handle
\r
235 * @retval HAL status
\r
237 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
\r
239 /* Check the HCD handle allocation */
\r
245 hhcd->State = HAL_HCD_STATE_BUSY;
\r
247 /* DeInit the low level hardware */
\r
248 HAL_HCD_MspDeInit(hhcd);
\r
250 __HAL_HCD_DISABLE(hhcd);
\r
252 hhcd->State = HAL_HCD_STATE_RESET;
\r
258 * @brief Initializes the HCD MSP.
\r
259 * @param hhcd: HCD handle
\r
262 __weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
\r
264 /* NOTE : This function Should not be modified, when the callback is needed,
\r
265 the HAL_HCD_MspInit could be implemented in the user file
\r
270 * @brief DeInitializes HCD MSP.
\r
271 * @param hhcd: HCD handle
\r
274 __weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
\r
276 /* NOTE : This function Should not be modified, when the callback is needed,
\r
277 the HAL_HCD_MspDeInit could be implemented in the user file
\r
285 /** @addtogroup HCD_Exported_Functions_Group2
\r
286 * @brief HCD IO operation functions
\r
289 ===============================================================================
\r
290 ##### IO operation functions #####
\r
291 ===============================================================================
\r
292 This subsection provides a set of functions allowing to manage the USB Host Data
\r
300 * @brief Submit a new URB for processing
\r
301 * @param hhcd: HCD handle
\r
302 * @param ch_num: Channel number.
\r
303 * This parameter can be a value from 1 to 15
\r
304 * @param direction: Channel number.
\r
305 * This parameter can be one of these values:
\r
306 * 0 : Output / 1 : Input
\r
307 * @param ep_type: Endpoint Type.
\r
308 * This parameter can be one of these values:
\r
309 * EP_TYPE_CTRL: Control type/
\r
310 * EP_TYPE_ISOC: Isochronous type/
\r
311 * EP_TYPE_BULK: Bulk type/
\r
312 * EP_TYPE_INTR: Interrupt type/
\r
313 * @param token: Endpoint Type.
\r
314 * This parameter can be one of these values:
\r
315 * 0: HC_PID_SETUP / 1: HC_PID_DATA1
\r
316 * @param pbuff: pointer to URB data
\r
317 * @param length: Length of URB data
\r
318 * @param do_ping: activate do ping protocol (for high speed only).
\r
319 * This parameter can be one of these values:
\r
320 * 0 : do ping inactive / 1 : do ping active
\r
321 * @retval HAL status
\r
323 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
\r
325 uint8_t direction ,
\r
332 hhcd->hc[ch_num].ep_is_in = direction;
\r
333 hhcd->hc[ch_num].ep_type = ep_type;
\r
337 hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
\r
341 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
\r
344 /* Manage Data Toggle */
\r
348 if((token == 1) && (direction == 0)) /*send data */
\r
351 { /* For Status OUT stage, Length==0, Status Out PID = 1 */
\r
352 hhcd->hc[ch_num].toggle_out = 1;
\r
355 /* Set the Data Toggle bit as per the Flag */
\r
356 if ( hhcd->hc[ch_num].toggle_out == 0)
\r
357 { /* Put the PID 0 */
\r
358 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
\r
361 { /* Put the PID 1 */
\r
362 hhcd->hc[ch_num].data_pid = HC_PID_DATA1 ;
\r
364 if(hhcd->hc[ch_num].urb_state != URB_NOTREADY)
\r
366 hhcd->hc[ch_num].do_ping = do_ping;
\r
374 /* Set the Data Toggle bit as per the Flag */
\r
375 if ( hhcd->hc[ch_num].toggle_out == 0)
\r
376 { /* Put the PID 0 */
\r
377 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
\r
380 { /* Put the PID 1 */
\r
381 hhcd->hc[ch_num].data_pid = HC_PID_DATA1 ;
\r
383 if(hhcd->hc[ch_num].urb_state != URB_NOTREADY)
\r
385 hhcd->hc[ch_num].do_ping = do_ping;
\r
390 if( hhcd->hc[ch_num].toggle_in == 0)
\r
392 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
\r
396 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
\r
404 /* Set the Data Toggle bit as per the Flag */
\r
405 if ( hhcd->hc[ch_num].toggle_out == 0)
\r
406 { /* Put the PID 0 */
\r
407 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
\r
410 { /* Put the PID 1 */
\r
411 hhcd->hc[ch_num].data_pid = HC_PID_DATA1 ;
\r
416 if( hhcd->hc[ch_num].toggle_in == 0)
\r
418 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
\r
422 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
\r
427 case EP_TYPE_ISOC:
\r
428 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
\r
432 hhcd->hc[ch_num].xfer_buff = pbuff;
\r
433 hhcd->hc[ch_num].xfer_len = length;
\r
434 hhcd->hc[ch_num].urb_state = URB_IDLE;
\r
435 hhcd->hc[ch_num].xfer_count = 0 ;
\r
436 hhcd->hc[ch_num].ch_num = ch_num;
\r
437 hhcd->hc[ch_num].state = HC_IDLE;
\r
439 return USB_HC_StartXfer(hhcd->Instance, &(hhcd->hc[ch_num]), hhcd->Init.dma_enable);
\r
443 * @brief This function handles HCD interrupt request.
\r
444 * @param hhcd: HCD handle
\r
447 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
\r
449 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
\r
450 uint32_t i = 0 , interrupt = 0;
\r
452 /* ensure that we are in device mode */
\r
453 if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
\r
455 /* avoid spurious interrupt */
\r
456 if(__HAL_HCD_IS_INVALID_INTERRUPT(hhcd))
\r
461 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
\r
463 /* incorrect mode, acknowledge the interrupt */
\r
464 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
\r
467 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
\r
469 /* incorrect mode, acknowledge the interrupt */
\r
470 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
\r
473 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
\r
475 /* incorrect mode, acknowledge the interrupt */
\r
476 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
\r
479 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
\r
481 /* incorrect mode, acknowledge the interrupt */
\r
482 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
\r
485 /* Handle Host Disconnect Interrupts */
\r
486 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
\r
490 USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
\r
491 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
\r
493 /* Handle Host Port Interrupts */
\r
494 HAL_HCD_Disconnect_Callback(hhcd);
\r
495 USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ );
\r
496 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
\r
499 /* Handle Host Port Interrupts */
\r
500 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
\r
502 HCD_Port_IRQHandler (hhcd);
\r
505 /* Handle Host SOF Interrupts */
\r
506 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
\r
508 HAL_HCD_SOF_Callback(hhcd);
\r
509 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
\r
512 /* Handle Host channel Interrupts */
\r
513 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
\r
515 interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
\r
516 for (i = 0; i < hhcd->Init.Host_channels ; i++)
\r
518 if (interrupt & (1 << i))
\r
520 if ((USBx_HC(i)->HCCHAR) & USB_OTG_HCCHAR_EPDIR)
\r
522 HCD_HC_IN_IRQHandler (hhcd, i);
\r
526 HCD_HC_OUT_IRQHandler (hhcd, i);
\r
530 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
\r
533 /* Handle Rx Queue Level Interrupts */
\r
534 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL))
\r
536 USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
\r
538 HCD_RXQLVL_IRQHandler (hhcd);
\r
540 USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
\r
546 * @brief SOF callback.
\r
547 * @param hhcd: HCD handle
\r
550 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
\r
552 /* NOTE : This function Should not be modified, when the callback is needed,
\r
553 the HAL_HCD_SOF_Callback could be implemented in the user file
\r
558 * @brief Connexion Event callback.
\r
559 * @param hhcd: HCD handle
\r
562 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
\r
564 /* NOTE : This function Should not be modified, when the callback is needed,
\r
565 the HAL_HCD_Connect_Callback could be implemented in the user file
\r
570 * @brief Disconnexion Event callback.
\r
571 * @param hhcd: HCD handle
\r
574 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
\r
576 /* NOTE : This function Should not be modified, when the callback is needed,
\r
577 the HAL_HCD_Disconnect_Callback could be implemented in the user file
\r
582 * @brief Notify URB state change callback.
\r
583 * @param hhcd: HCD handle
\r
584 * @param chnum: Channel number.
\r
585 * This parameter can be a value from 1 to 15
\r
586 * @param urb_state:
\r
587 * This parameter can be one of these values:
\r
596 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
\r
598 /* NOTE : This function Should not be modified, when the callback is needed,
\r
599 the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
\r
607 /** @addtogroup HCD_Exported_Functions_Group3
\r
608 * @brief Peripheral management functions
\r
611 ===============================================================================
\r
612 ##### Peripheral Control functions #####
\r
613 ===============================================================================
\r
615 This subsection provides a set of functions allowing to control the HCD data
\r
623 * @brief Start the host driver
\r
624 * @param hhcd: HCD handle
\r
625 * @retval HAL status
\r
627 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
\r
630 __HAL_HCD_ENABLE(hhcd);
\r
631 USB_DriveVbus(hhcd->Instance, 1);
\r
632 __HAL_UNLOCK(hhcd);
\r
637 * @brief Stop the host driver
\r
638 * @param hhcd: HCD handle
\r
639 * @retval HAL status
\r
642 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
\r
645 USB_StopHost(hhcd->Instance);
\r
646 __HAL_UNLOCK(hhcd);
\r
651 * @brief Reset the host port
\r
652 * @param hhcd: HCD handle
\r
653 * @retval HAL status
\r
655 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
\r
657 return (USB_ResetPort(hhcd->Instance));
\r
664 /** @addtogroup HCD_Exported_Functions_Group4
\r
665 * @brief Peripheral State functions
\r
668 ===============================================================================
\r
669 ##### Peripheral State functions #####
\r
670 ===============================================================================
\r
672 This subsection permits to get in run-time the status of the peripheral
\r
680 * @brief Return the HCD state
\r
681 * @param hhcd: HCD handle
\r
682 * @retval HAL state
\r
684 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef *hhcd)
\r
686 return hhcd->State;
\r
690 * @brief Return URB state for a channel
\r
691 * @param hhcd: HCD handle
\r
692 * @param chnum: Channel number.
\r
693 * This parameter can be a value from 1 to 15
\r
694 * @retval URB state.
\r
695 * This parameter can be one of these values:
\r
703 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
\r
705 return hhcd->hc[chnum].urb_state;
\r
710 * @brief Return the last host transfer size
\r
711 * @param hhcd: HCD handle
\r
712 * @param chnum: Channel number.
\r
713 * This parameter can be a value from 1 to 15
\r
714 * @retval last transfer size in byte
\r
716 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef *hhcd, uint8_t chnum)
\r
718 return hhcd->hc[chnum].xfer_count;
\r
722 * @brief Return the Host Channel state
\r
723 * @param hhcd: HCD handle
\r
724 * @param chnum: Channel number.
\r
725 * This parameter can be a value from 1 to 15
\r
726 * @retval Host channel state
\r
727 * This parameter can be one of the these values:
\r
738 HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
\r
740 return hhcd->hc[chnum].state;
\r
744 * @brief Return the current Host frame number
\r
745 * @param hhcd: HCD handle
\r
746 * @retval Current Host frame number
\r
748 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
\r
750 return (USB_GetCurrentFrame(hhcd->Instance));
\r
754 * @brief Return the Host enumeration speed
\r
755 * @param hhcd: HCD handle
\r
756 * @retval Enumeration speed
\r
758 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
\r
760 return (USB_GetHostSpeed(hhcd->Instance));
\r
770 /** @addtogroup HCD_Private_Functions
\r
774 * @brief This function handles Host Channel IN interrupt requests.
\r
775 * @param hhcd: HCD handle
\r
776 * @param chnum: Channel number.
\r
777 * This parameter can be a value from 1 to 15
\r
780 static void HCD_HC_IN_IRQHandler (HCD_HandleTypeDef *hhcd, uint8_t chnum)
\r
782 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
\r
784 if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_AHBERR)
\r
786 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
\r
787 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
789 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_ACK)
\r
791 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
\r
794 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_STALL)
\r
796 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
797 hhcd->hc[chnum].state = HC_STALL;
\r
798 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
\r
799 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
\r
800 USB_HC_Halt(hhcd->Instance, chnum);
\r
802 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_DTERR)
\r
804 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
805 USB_HC_Halt(hhcd->Instance, chnum);
\r
806 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
\r
807 hhcd->hc[chnum].state = HC_DATATGLERR;
\r
808 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
\r
811 if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_FRMOR)
\r
813 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
814 USB_HC_Halt(hhcd->Instance, chnum);
\r
815 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
\r
818 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_XFRC)
\r
821 if (hhcd->Init.dma_enable)
\r
823 hhcd->hc[chnum].xfer_count = hhcd->hc[chnum].xfer_len - \
\r
824 (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
\r
827 hhcd->hc[chnum].state = HC_XFRC;
\r
828 hhcd->hc[chnum].ErrCnt = 0;
\r
829 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
\r
832 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL)||
\r
833 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
\r
835 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
836 USB_HC_Halt(hhcd->Instance, chnum);
\r
837 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
\r
840 else if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
\r
842 USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
\r
843 hhcd->hc[chnum].urb_state = URB_DONE;
\r
844 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
\r
846 hhcd->hc[chnum].toggle_in ^= 1;
\r
849 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_CHH)
\r
851 __HAL_HCD_MASK_HALT_HC_INT(chnum);
\r
853 if(hhcd->hc[chnum].state == HC_XFRC)
\r
855 hhcd->hc[chnum].urb_state = URB_DONE;
\r
858 else if (hhcd->hc[chnum].state == HC_STALL)
\r
860 hhcd->hc[chnum].urb_state = URB_STALL;
\r
863 else if((hhcd->hc[chnum].state == HC_XACTERR) ||
\r
864 (hhcd->hc[chnum].state == HC_DATATGLERR))
\r
866 if(hhcd->hc[chnum].ErrCnt++ > 3)
\r
868 hhcd->hc[chnum].ErrCnt = 0;
\r
869 hhcd->hc[chnum].urb_state = URB_ERROR;
\r
873 hhcd->hc[chnum].urb_state = URB_NOTREADY;
\r
876 /* re-activate the channel */
\r
877 USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;
\r
878 USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
\r
880 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
\r
881 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
\r
884 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_TXERR)
\r
886 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
887 hhcd->hc[chnum].ErrCnt++;
\r
888 hhcd->hc[chnum].state = HC_XACTERR;
\r
889 USB_HC_Halt(hhcd->Instance, chnum);
\r
890 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
\r
892 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NAK)
\r
894 if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
\r
896 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
897 USB_HC_Halt(hhcd->Instance, chnum);
\r
899 else if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL)||
\r
900 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
\r
902 /* re-activate the channel */
\r
903 USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;
\r
904 USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
\r
907 hhcd->hc[chnum].state = HC_NAK;
\r
908 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
\r
913 * @brief This function handles Host Channel OUT interrupt requests.
\r
914 * @param hhcd: HCD handle
\r
915 * @param chnum: Channel number.
\r
916 * This parameter can be a value from 1 to 15
\r
919 static void HCD_HC_OUT_IRQHandler (HCD_HandleTypeDef *hhcd, uint8_t chnum)
\r
921 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
\r
923 if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_AHBERR)
\r
925 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
\r
926 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
928 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_ACK)
\r
930 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
\r
932 if( hhcd->hc[chnum].do_ping == 1)
\r
934 hhcd->hc[chnum].state = HC_NYET;
\r
935 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
936 USB_HC_Halt(hhcd->Instance, chnum);
\r
937 hhcd->hc[chnum].urb_state = URB_NOTREADY;
\r
941 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NYET)
\r
943 hhcd->hc[chnum].state = HC_NYET;
\r
944 hhcd->hc[chnum].ErrCnt= 0;
\r
945 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
946 USB_HC_Halt(hhcd->Instance, chnum);
\r
947 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
\r
951 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_FRMOR)
\r
953 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
954 USB_HC_Halt(hhcd->Instance, chnum);
\r
955 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
\r
958 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_XFRC)
\r
960 hhcd->hc[chnum].ErrCnt = 0;
\r
961 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
962 USB_HC_Halt(hhcd->Instance, chnum);
\r
963 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
\r
964 hhcd->hc[chnum].state = HC_XFRC;
\r
968 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_STALL)
\r
970 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
\r
971 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
972 USB_HC_Halt(hhcd->Instance, chnum);
\r
973 hhcd->hc[chnum].state = HC_STALL;
\r
976 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NAK)
\r
978 hhcd->hc[chnum].ErrCnt = 0;
\r
979 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
980 USB_HC_Halt(hhcd->Instance, chnum);
\r
981 hhcd->hc[chnum].state = HC_NAK;
\r
982 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
\r
985 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_TXERR)
\r
987 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
988 USB_HC_Halt(hhcd->Instance, chnum);
\r
989 hhcd->hc[chnum].state = HC_XACTERR;
\r
990 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
\r
993 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_DTERR)
\r
995 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
\r
996 USB_HC_Halt(hhcd->Instance, chnum);
\r
997 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
\r
998 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
\r
999 hhcd->hc[chnum].state = HC_DATATGLERR;
\r
1003 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_CHH)
\r
1005 __HAL_HCD_MASK_HALT_HC_INT(chnum);
\r
1007 if(hhcd->hc[chnum].state == HC_XFRC)
\r
1009 hhcd->hc[chnum].urb_state = URB_DONE;
\r
1010 if (hhcd->hc[chnum].ep_type == EP_TYPE_BULK)
\r
1012 hhcd->hc[chnum].toggle_out ^= 1;
\r
1015 else if (hhcd->hc[chnum].state == HC_NAK)
\r
1017 hhcd->hc[chnum].urb_state = URB_NOTREADY;
\r
1020 else if (hhcd->hc[chnum].state == HC_NYET)
\r
1022 hhcd->hc[chnum].urb_state = URB_NOTREADY;
\r
1023 hhcd->hc[chnum].do_ping = 0;
\r
1026 else if (hhcd->hc[chnum].state == HC_STALL)
\r
1028 hhcd->hc[chnum].urb_state = URB_STALL;
\r
1031 else if((hhcd->hc[chnum].state == HC_XACTERR) ||
\r
1032 (hhcd->hc[chnum].state == HC_DATATGLERR))
\r
1034 if(hhcd->hc[chnum].ErrCnt++ > 3)
\r
1036 hhcd->hc[chnum].ErrCnt = 0;
\r
1037 hhcd->hc[chnum].urb_state = URB_ERROR;
\r
1041 hhcd->hc[chnum].urb_state = URB_NOTREADY;
\r
1044 /* re-activate the channel */
\r
1045 USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;
\r
1046 USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
\r
1049 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
\r
1050 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
\r
1055 * @brief This function handles Rx Queue Level interrupt requests.
\r
1056 * @param hhcd: HCD handle
\r
1059 static void HCD_RXQLVL_IRQHandler (HCD_HandleTypeDef *hhcd)
\r
1061 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
\r
1062 uint8_t channelnum =0;
\r
1065 uint32_t temp = 0;
\r
1067 temp = hhcd->Instance->GRXSTSP ;
\r
1068 channelnum = temp & USB_OTG_GRXSTSP_EPNUM;
\r
1069 pktsts = (temp & USB_OTG_GRXSTSP_PKTSTS) >> 17;
\r
1070 pktcnt = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
\r
1074 case GRXSTS_PKTSTS_IN:
\r
1075 /* Read the data into the host buffer. */
\r
1076 if ((pktcnt > 0) && (hhcd->hc[channelnum].xfer_buff != (void *)0))
\r
1079 USB_ReadPacket(hhcd->Instance, hhcd->hc[channelnum].xfer_buff, pktcnt);
\r
1081 /*manage multiple Xfer */
\r
1082 hhcd->hc[channelnum].xfer_buff += pktcnt;
\r
1083 hhcd->hc[channelnum].xfer_count += pktcnt;
\r
1085 if((USBx_HC(channelnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) > 0)
\r
1087 /* re-activate the channel when more packets are expected */
\r
1088 USBx_HC(channelnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;
\r
1089 USBx_HC(channelnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
\r
1090 hhcd->hc[channelnum].toggle_in ^= 1;
\r
1095 case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
\r
1097 case GRXSTS_PKTSTS_IN_XFER_COMP:
\r
1098 case GRXSTS_PKTSTS_CH_HALTED:
\r
1105 * @brief This function handles Host Port interrupt requests.
\r
1106 * @param hhcd: HCD handle
\r
1109 static void HCD_Port_IRQHandler (HCD_HandleTypeDef *hhcd)
\r
1111 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
\r
1112 __IO uint32_t hprt0, hprt0_dup;
\r
1114 /* Handle Host Port Interrupts */
\r
1115 hprt0 = USBx_HPRT0;
\r
1116 hprt0_dup = USBx_HPRT0;
\r
1118 hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
\r
1119 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
\r
1121 /* Check whether Port Connect detected */
\r
1122 if((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
\r
1124 if((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
\r
1126 USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT);
\r
1127 HAL_HCD_Connect_Callback(hhcd);
\r
1129 hprt0_dup |= USB_OTG_HPRT_PCDET;
\r
1133 /* Check whether Port Enable Changed */
\r
1134 if((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
\r
1136 hprt0_dup |= USB_OTG_HPRT_PENCHNG;
\r
1138 if((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
\r
1140 if(hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
\r
1142 if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
\r
1144 USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_6_MHZ );
\r
1148 USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ );
\r
1153 if(hhcd->Init.speed == HCD_SPEED_FULL)
\r
1155 USBx_HOST->HFIR = (uint32_t)60000;
\r
1158 HAL_HCD_Connect_Callback(hhcd);
\r
1160 if(hhcd->Init.speed == HCD_SPEED_HIGH)
\r
1162 USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT);
\r
1167 /* Cleanup HPRT */
\r
1168 USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
\r
1169 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
\r
1171 USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT);
\r
1175 /* Check For an overcurrent */
\r
1176 if((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
\r
1178 hprt0_dup |= USB_OTG_HPRT_POCCHNG;
\r
1181 /* Clear Port Interrupts */
\r
1182 USBx_HPRT0 = hprt0_dup;
\r
1189 #endif /* HAL_HCD_MODULE_ENABLED */
\r
1198 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
\r