Increment eeprom version
[betaflight.git] / lib / main / STM32F1 / Drivers / STM32F1xx_HAL_Driver / Src / stm32f1xx_hal_hcd.c
blob7fd48eff54705f15134bde869026ef0d9815f3dd
1 /**
2 ******************************************************************************
3 * @file stm32f1xx_hal_hcd.c
4 * @author MCD Application Team
5 * @version V1.1.1
6 * @date 12-May-2017
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
15 @verbatim
16 ==============================================================================
17 ##### How to use this driver #####
18 ==============================================================================
19 [..]
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:
39 (##) HAL_HCD_Start();
41 @endverbatim
42 ******************************************************************************
43 * @attention
45 * <h2><center>&copy; 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
75 * @{
79 #ifdef HAL_HCD_MODULE_ENABLED
81 #if defined(STM32F105xC) || defined(STM32F107xC)
83 /** @defgroup HCD HCD
84 * @brief HCD HAL module driver
85 * @{
88 /* Private types -------------------------------------------------------------*/
89 /* Private variables ---------------------------------------------------------*/
90 /* Private constants ---------------------------------------------------------*/
91 /* Private macros ------------------------------------------------------------*/
92 /* Private function ----------------------------------------------------------*/
93 /** @defgroup HCD_Private_Functions HCD Private Functions
94 * @{
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);
101 * @}
104 /* Exported functions --------------------------------------------------------*/
105 /** @defgroup HCD_Exported_Functions HCD Exported Functions
106 * @{
109 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
110 * @brief Initialization and Configuration functions
112 @verbatim
113 ===============================================================================
114 ##### Initialization and de-initialization functions #####
115 ===============================================================================
116 [..] This section provides functions allowing to:
118 @endverbatim
119 * @{
123 * @brief Initialize the host driver
124 * @param hhcd: HCD handle
125 * @retval HAL status
127 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
129 /* Check the HCD handle allocation */
130 if(hhcd == NULL)
132 return HAL_ERROR;
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);
155 /* Force Host Mode*/
156 USB_SetCurrentMode(hhcd->Instance , USB_HOST_MODE);
158 /* Init Host */
159 USB_HostInit(hhcd->Instance, hhcd->Init);
161 hhcd->State= HAL_HCD_STATE_READY;
163 return HAL_OK;
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
187 * @retval HAL status
189 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd,
190 uint8_t ch_num,
191 uint8_t epnum,
192 uint8_t dev_address,
193 uint8_t speed,
194 uint8_t ep_type,
195 uint16_t mps)
197 HAL_StatusTypeDef status = HAL_OK;
199 __HAL_LOCK(hhcd);
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,
210 ch_num,
211 epnum,
212 dev_address,
213 speed,
214 ep_type,
215 mps);
216 __HAL_UNLOCK(hhcd);
218 return status;
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
226 * @retval HAL status
228 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd,
229 uint8_t ch_num)
231 __HAL_LOCK(hhcd);
232 USB_HC_Halt(hhcd->Instance, ch_num);
233 __HAL_UNLOCK(hhcd);
235 return HAL_OK;
239 * @brief DeInitialize the host driver
240 * @param hhcd: HCD handle
241 * @retval HAL status
243 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
245 /* Check the HCD handle allocation */
246 if(hhcd == NULL)
248 return HAL_ERROR;
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;
260 return HAL_OK;
264 * @brief Initializes the HCD MSP.
265 * @param hhcd: HCD handle
266 * @retval None
268 __weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
270 /* Prevent unused argument(s) compilation warning */
271 UNUSED(hhcd);
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
280 * @retval None
282 __weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
284 /* Prevent unused argument(s) compilation warning */
285 UNUSED(hhcd);
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
292 * @}
295 /** @defgroup HCD_Exported_Functions_Group2 IO operation functions
296 * @brief HCD IO operation functions
298 @verbatim
299 ===============================================================================
300 ##### IO operation functions #####
301 ===============================================================================
302 This subsection provides a set of functions allowing to manage the USB Host Data
303 Transfer
305 @endverbatim
306 * @{
309 /**
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
331 * @retval HAL status
333 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
334 uint8_t ch_num,
335 uint8_t direction,
336 uint8_t ep_type,
337 uint8_t token,
338 uint8_t* pbuff,
339 uint16_t length,
340 uint8_t do_ping)
342 hhcd->hc[ch_num].ep_is_in = direction;
343 hhcd->hc[ch_num].ep_type = ep_type;
345 if(token == 0U)
347 hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
349 else
351 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
354 /* Manage Data Toggle */
355 switch(ep_type)
357 case EP_TYPE_CTRL:
358 if((token == 1U) && (direction == 0U)) /*send data */
360 if (length == 0U)
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;
370 else
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;
379 break;
381 case EP_TYPE_BULK:
382 if(direction == 0U)
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;
389 else
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;
398 else
400 if( hhcd->hc[ch_num].toggle_in == 0U)
402 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
404 else
406 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
409 break;
411 case EP_TYPE_INTR:
412 if(direction == 0U)
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;
419 else
420 { /* Put the PID 1 */
421 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
424 else
426 if( hhcd->hc[ch_num].toggle_in == 0U)
428 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
430 else
432 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
435 break;
437 case EP_TYPE_ISOC:
438 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
439 break;
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
455 * @retval None
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))
469 return;
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))
500 /* Cleanup HPRT */
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);
535 else
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
559 * @retval None
561 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
563 /* Prevent unused argument(s) compilation warning */
564 UNUSED(hhcd);
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
573 * @retval None
575 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
577 /* Prevent unused argument(s) compilation warning */
578 UNUSED(hhcd);
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
587 * @retval None
589 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
591 /* Prevent unused argument(s) compilation warning */
592 UNUSED(hhcd);
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
603 * @param urb_state:
604 * This parameter can be one of these values:
605 * URB_IDLE/
606 * URB_DONE/
607 * URB_NOTREADY/
608 * URB_NYET/
609 * URB_ERROR/
610 * URB_STALL/
611 * @retval None
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 */
616 UNUSED(hhcd);
617 UNUSED(chnum);
618 UNUSED(urb_state);
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
625 * @}
628 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
629 * @brief management functions
631 @verbatim
632 ===============================================================================
633 ##### Peripheral Control functions #####
634 ===============================================================================
635 [..]
636 This subsection provides a set of functions allowing to control the HCD data
637 transfers.
639 @endverbatim
640 * @{
644 * @brief Start the host driver
645 * @param hhcd: HCD handle
646 * @retval HAL status
648 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
650 __HAL_LOCK(hhcd);
651 __HAL_HCD_ENABLE(hhcd);
652 USB_DriveVbus(hhcd->Instance, 1U);
653 __HAL_UNLOCK(hhcd);
654 return HAL_OK;
658 * @brief Stop the host driver
659 * @param hhcd: HCD handle
660 * @retval HAL status
663 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
665 __HAL_LOCK(hhcd);
666 USB_StopHost(hhcd->Instance);
667 __HAL_UNLOCK(hhcd);
668 return HAL_OK;
672 * @brief Reset the host port
673 * @param hhcd: HCD handle
674 * @retval HAL status
676 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
678 return (USB_ResetPort(hhcd->Instance));
682 * @}
685 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
686 * @brief Peripheral State functions
688 @verbatim
689 ===============================================================================
690 ##### Peripheral State functions #####
691 ===============================================================================
692 [..]
693 This subsection permits to get in run-time the status of the peripheral
694 and the data flow.
696 @endverbatim
697 * @{
701 * @brief Return the HCD handle state
702 * @param hhcd: HCD handle
703 * @retval HAL state
705 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef *hhcd)
707 return hhcd->State;
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
715 * @retval URB state.
716 * This parameter can be one of these values:
717 * URB_IDLE/
718 * URB_DONE/
719 * URB_NOTREADY/
720 * URB_NYET/
721 * URB_ERROR/
722 * URB_STALL/
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:
749 * HC_IDLE/
750 * HC_XFRC/
751 * HC_HALTED/
752 * HC_NYET/
753 * HC_NAK/
754 * HC_STALL/
755 * HC_XACTERR/
756 * HC_BBLERR/
757 * HC_DATATGLERR/
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));
785 * @}
788 * @}
791 /** @addtogroup HCD_Private_Functions
792 * @{
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
799 * @retval none
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;
883 else
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
932 * @retval none
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;
1045 else
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
1065 * @retval none
1067 static void HCD_RXQLVL_IRQHandler (HCD_HandleTypeDef *hhcd)
1069 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1070 uint8_t channelnum =0U;
1071 uint32_t pktsts;
1072 uint32_t pktcnt;
1073 uint32_t temp = 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;
1081 switch (pktsts)
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;
1103 break;
1105 case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
1106 break;
1108 case GRXSTS_PKTSTS_IN_XFER_COMP:
1109 case GRXSTS_PKTSTS_CH_HALTED:
1110 default:
1111 break;
1116 * @brief This function handles Host Port interrupt requests.
1117 * @param hhcd: HCD handle
1118 * @retval None
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 */
1126 hprt0 = USBx_HPRT0;
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 );
1154 else
1156 USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ );
1158 HAL_HCD_Connect_Callback(hhcd);
1160 else
1162 /* Cleanup HPRT */
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;
1181 * @}
1185 * @}
1188 #endif /* STM32F105xC || STM32F107xC */
1190 #endif /* HAL_HCD_MODULE_ENABLED */
1193 * @}
1196 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/