1 /**
2 ******************************************************************************
3 * @file stm32f1xx_hal_hcd.c
4 * @author MCD Application Team
5 * @brief HCD HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the USB Peripheral Controller:
8 * + Initialization and de-initialization functions
9 * + IO operation functions
10 * + Peripheral Control functions
11 * + Peripheral State functions
12 *
13 ******************************************************************************
14 * @attention
15 *
16 * Copyright (c) 2016 STMicroelectronics.
17 * All rights reserved.
18 *
19 * This software is licensed under terms that can be found in the LICENSE file
20 * in the root directory of this software component.
21 * If no LICENSE file comes with this software, it is provided AS-IS.
22 *
23 ******************************************************************************
24 @verbatim
25 ==============================================================================
26 ##### How to use this driver #####
27 ==============================================================================
28 [..]
29 (#)Declare a HCD_HandleTypeDef handle structure, for example:
30 HCD_HandleTypeDef hhcd;
31
32 (#)Fill parameters of Init structure in HCD handle
33
34 (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
35
36 (#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
37 (##) Enable the HCD/USB Low Level interface clock using the following macros
38 (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
39 (##) Initialize the related GPIO clocks
40 (##) Configure HCD pin-out
41 (##) Configure HCD NVIC interrupt
42
43 (#)Associate the Upper USB Host stack to the HAL HCD Driver:
44 (##) hhcd.pData = phost;
45
46 (#)Enable HCD transmission and reception:
47 (##) HAL_HCD_Start();
48
49 @endverbatim
50 ******************************************************************************
51 */
52
53 /* Includes ------------------------------------------------------------------*/
54 #include "stm32f1xx_hal.h"
55
56 /** @addtogroup STM32F1xx_HAL_Driver
57 * @{
58 */
59
60 #ifdef HAL_HCD_MODULE_ENABLED
61 #if defined (USB_OTG_FS)
62
63 /** @defgroup HCD HCD
64 * @brief HCD HAL module driver
65 * @{
66 */
67
68 /* Private typedef -----------------------------------------------------------*/
69 /* Private define ------------------------------------------------------------*/
70 /* Private macro -------------------------------------------------------------*/
71 /* Private variables ---------------------------------------------------------*/
72 /* Private function prototypes -----------------------------------------------*/
73 /** @defgroup HCD_Private_Functions HCD Private Functions
74 * @{
75 */
76 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
77 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
78 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd);
79 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
80 /**
81 * @}
82 */
83
84 /* Exported functions --------------------------------------------------------*/
85 /** @defgroup HCD_Exported_Functions HCD Exported Functions
86 * @{
87 */
88
89 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
90 * @brief Initialization and Configuration functions
91 *
92 @verbatim
93 ===============================================================================
94 ##### Initialization and de-initialization functions #####
95 ===============================================================================
96 [..] This section provides functions allowing to:
97
98 @endverbatim
99 * @{
100 */
101
102 /**
103 * @brief Initialize the host driver.
104 * @param hhcd HCD handle
105 * @retval HAL status
106 */
HAL_HCD_Init(HCD_HandleTypeDef * hhcd)107 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
108 {
109 /* Check the HCD handle allocation */
110 if (hhcd == NULL)
111 {
112 return HAL_ERROR;
113 }
114
115 /* Check the parameters */
116 assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
117
118 if (hhcd->State == HAL_HCD_STATE_RESET)
119 {
120 /* Allocate lock resource and initialize it */
121 hhcd->Lock = HAL_UNLOCKED;
122
123 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
124 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
125 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
126 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
127 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
128 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
129 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;
130
131 if (hhcd->MspInitCallback == NULL)
132 {
133 hhcd->MspInitCallback = HAL_HCD_MspInit;
134 }
135
136 /* Init the low level hardware */
137 hhcd->MspInitCallback(hhcd);
138 #else
139 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
140 HAL_HCD_MspInit(hhcd);
141 #endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
142 }
143
144 hhcd->State = HAL_HCD_STATE_BUSY;
145
146 /* Disable DMA mode for FS instance */
147 hhcd->Init.dma_enable = 0U;
148
149 /* Disable the Interrupts */
150 __HAL_HCD_DISABLE(hhcd);
151
152 /* Init the Core (common init.) */
153 if (USB_CoreInit(hhcd->Instance, hhcd->Init) != HAL_OK)
154 {
155 hhcd->State = HAL_HCD_STATE_ERROR;
156 return HAL_ERROR;
157 }
158
159 /* Force Host Mode */
160 if (USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE) != HAL_OK)
161 {
162 hhcd->State = HAL_HCD_STATE_ERROR;
163 return HAL_ERROR;
164 }
165
166 /* Init Host */
167 if (USB_HostInit(hhcd->Instance, hhcd->Init) != HAL_OK)
168 {
169 hhcd->State = HAL_HCD_STATE_ERROR;
170 return HAL_ERROR;
171 }
172
173 hhcd->State = HAL_HCD_STATE_READY;
174
175 return HAL_OK;
176 }
177
178 /**
179 * @brief Initialize a host channel.
180 * @param hhcd HCD handle
181 * @param ch_num Channel number.
182 * This parameter can be a value from 1 to 15
183 * @param epnum Endpoint number.
184 * This parameter can be a value from 1 to 15
185 * @param dev_address Current device address
186 * This parameter can be a value from 0 to 255
187 * @param speed Current device speed.
188 * This parameter can be one of these values:
189 * HCD_DEVICE_SPEED_FULL: Full speed mode,
190 * HCD_DEVICE_SPEED_LOW: Low speed mode
191 * @param ep_type Endpoint Type.
192 * This parameter can be one of these values:
193 * EP_TYPE_CTRL: Control type,
194 * EP_TYPE_ISOC: Isochronous type,
195 * EP_TYPE_BULK: Bulk type,
196 * EP_TYPE_INTR: Interrupt type
197 * @param mps Max Packet Size.
198 * This parameter can be a value from 0 to32K
199 * @retval HAL status
200 */
HAL_HCD_HC_Init(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t epnum,uint8_t dev_address,uint8_t speed,uint8_t ep_type,uint16_t mps)201 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t epnum,
202 uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps)
203 {
204 HAL_StatusTypeDef status;
205 uint32_t HCcharMps = mps;
206
207 __HAL_LOCK(hhcd);
208 hhcd->hc[ch_num].do_ping = 0U;
209 hhcd->hc[ch_num].dev_addr = dev_address;
210 hhcd->hc[ch_num].ch_num = ch_num;
211 hhcd->hc[ch_num].ep_type = ep_type;
212 hhcd->hc[ch_num].ep_num = epnum & 0x7FU;
213
214 (void)HAL_HCD_HC_ClearHubInfo(hhcd, ch_num);
215
216 if ((epnum & 0x80U) == 0x80U)
217 {
218 hhcd->hc[ch_num].ep_is_in = 1U;
219 }
220 else
221 {
222 hhcd->hc[ch_num].ep_is_in = 0U;
223 }
224
225 hhcd->hc[ch_num].speed = speed;
226 hhcd->hc[ch_num].max_packet = (uint16_t)HCcharMps;
227
228 status = USB_HC_Init(hhcd->Instance, ch_num, epnum,
229 dev_address, speed, ep_type, (uint16_t)HCcharMps);
230
231 __HAL_UNLOCK(hhcd);
232
233 return status;
234 }
235
236 /**
237 * @brief Halt a host channel.
238 * @param hhcd HCD handle
239 * @param ch_num Channel number.
240 * This parameter can be a value from 1 to 15
241 * @retval HAL status
242 */
HAL_HCD_HC_Halt(HCD_HandleTypeDef * hhcd,uint8_t ch_num)243 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
244 {
245 HAL_StatusTypeDef status = HAL_OK;
246
247 __HAL_LOCK(hhcd);
248 (void)USB_HC_Halt(hhcd->Instance, ch_num);
249 __HAL_UNLOCK(hhcd);
250
251 return status;
252 }
253
254 /**
255 * @brief DeInitialize the host driver.
256 * @param hhcd HCD handle
257 * @retval HAL status
258 */
HAL_HCD_DeInit(HCD_HandleTypeDef * hhcd)259 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
260 {
261 /* Check the HCD handle allocation */
262 if (hhcd == NULL)
263 {
264 return HAL_ERROR;
265 }
266
267 hhcd->State = HAL_HCD_STATE_BUSY;
268
269 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
270 if (hhcd->MspDeInitCallback == NULL)
271 {
272 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */
273 }
274
275 /* DeInit the low level hardware */
276 hhcd->MspDeInitCallback(hhcd);
277 #else
278 /* DeInit the low level hardware: CLOCK, NVIC.*/
279 HAL_HCD_MspDeInit(hhcd);
280 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
281
282 __HAL_HCD_DISABLE(hhcd);
283
284 hhcd->State = HAL_HCD_STATE_RESET;
285
286 return HAL_OK;
287 }
288
289 /**
290 * @brief Initialize the HCD MSP.
291 * @param hhcd HCD handle
292 * @retval None
293 */
HAL_HCD_MspInit(HCD_HandleTypeDef * hhcd)294 __weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
295 {
296 /* Prevent unused argument(s) compilation warning */
297 UNUSED(hhcd);
298
299 /* NOTE : This function should not be modified, when the callback is needed,
300 the HAL_HCD_MspInit could be implemented in the user file
301 */
302 }
303
304 /**
305 * @brief DeInitialize the HCD MSP.
306 * @param hhcd HCD handle
307 * @retval None
308 */
HAL_HCD_MspDeInit(HCD_HandleTypeDef * hhcd)309 __weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
310 {
311 /* Prevent unused argument(s) compilation warning */
312 UNUSED(hhcd);
313
314 /* NOTE : This function should not be modified, when the callback is needed,
315 the HAL_HCD_MspDeInit could be implemented in the user file
316 */
317 }
318
319 /**
320 * @}
321 */
322
323 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
324 * @brief HCD IO operation functions
325 *
326 @verbatim
327 ===============================================================================
328 ##### IO operation functions #####
329 ===============================================================================
330 [..] This subsection provides a set of functions allowing to manage the USB Host Data
331 Transfer
332
333 @endverbatim
334 * @{
335 */
336
337 /**
338 * @brief Submit a new URB for processing.
339 * @param hhcd HCD handle
340 * @param ch_num Channel number.
341 * This parameter can be a value from 1 to 15
342 * @param direction Channel number.
343 * This parameter can be one of these values:
344 * 0 : Output / 1 : Input
345 * @param ep_type Endpoint Type.
346 * This parameter can be one of these values:
347 * EP_TYPE_CTRL: Control type/
348 * EP_TYPE_ISOC: Isochronous type/
349 * EP_TYPE_BULK: Bulk type/
350 * EP_TYPE_INTR: Interrupt type/
351 * @param token Endpoint Type.
352 * This parameter can be one of these values:
353 * 0: HC_PID_SETUP / 1: HC_PID_DATA1
354 * @param pbuff pointer to URB data
355 * @param length Length of URB data
356 * @param do_ping activate do ping protocol (for high speed only).
357 * This parameter can be one of these values:
358 * 0 : do ping inactive / 1 : do ping active
359 * @retval HAL status
360 */
HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t direction,uint8_t ep_type,uint8_t token,uint8_t * pbuff,uint16_t length,uint8_t do_ping)361 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
362 uint8_t ch_num,
363 uint8_t direction,
364 uint8_t ep_type,
365 uint8_t token,
366 uint8_t *pbuff,
367 uint16_t length,
368 uint8_t do_ping)
369 {
370 hhcd->hc[ch_num].ep_is_in = direction;
371 hhcd->hc[ch_num].ep_type = ep_type;
372
373 if (token == 0U)
374 {
375 hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
376 hhcd->hc[ch_num].do_ping = do_ping;
377 }
378 else
379 {
380 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
381 }
382
383 /* Manage Data Toggle */
384 switch (ep_type)
385 {
386 case EP_TYPE_CTRL:
387 if (token == 1U) /* send data */
388 {
389 if (direction == 0U)
390 {
391 if (length == 0U)
392 {
393 /* For Status OUT stage, Length == 0U, Status Out PID = 1 */
394 hhcd->hc[ch_num].toggle_out = 1U;
395 }
396
397 /* Set the Data Toggle bit as per the Flag */
398 if (hhcd->hc[ch_num].toggle_out == 0U)
399 {
400 /* Put the PID 0 */
401 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
402 }
403 else
404 {
405 /* Put the PID 1 */
406 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
407 }
408 }
409 }
410 break;
411
412 case EP_TYPE_BULK:
413 if (direction == 0U)
414 {
415 /* Set the Data Toggle bit as per the Flag */
416 if (hhcd->hc[ch_num].toggle_out == 0U)
417 {
418 /* Put the PID 0 */
419 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
420 }
421 else
422 {
423 /* Put the PID 1 */
424 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
425 }
426 }
427 else
428 {
429 if (hhcd->hc[ch_num].toggle_in == 0U)
430 {
431 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
432 }
433 else
434 {
435 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
436 }
437 }
438
439 break;
440 case EP_TYPE_INTR:
441 if (direction == 0U)
442 {
443 /* Set the Data Toggle bit as per the Flag */
444 if (hhcd->hc[ch_num].toggle_out == 0U)
445 {
446 /* Put the PID 0 */
447 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
448 }
449 else
450 {
451 /* Put the PID 1 */
452 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
453 }
454 }
455 else
456 {
457 if (hhcd->hc[ch_num].toggle_in == 0U)
458 {
459 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
460 }
461 else
462 {
463 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
464 }
465 }
466 break;
467
468 case EP_TYPE_ISOC:
469 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
470 break;
471
472 default:
473 break;
474 }
475
476 hhcd->hc[ch_num].xfer_buff = pbuff;
477 hhcd->hc[ch_num].xfer_len = length;
478 hhcd->hc[ch_num].urb_state = URB_IDLE;
479 hhcd->hc[ch_num].xfer_count = 0U;
480 hhcd->hc[ch_num].ch_num = ch_num;
481 hhcd->hc[ch_num].state = HC_IDLE;
482
483 return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num]);
484 }
485
486 /**
487 * @brief Handle HCD interrupt request.
488 * @param hhcd HCD handle
489 * @retval None
490 */
HAL_HCD_IRQHandler(HCD_HandleTypeDef * hhcd)491 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
492 {
493 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
494 uint32_t USBx_BASE = (uint32_t)USBx;
495 uint32_t i;
496 uint32_t interrupt;
497
498 /* Ensure that we are in device mode */
499 if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
500 {
501 /* Avoid spurious interrupt */
502 if (__HAL_HCD_IS_INVALID_INTERRUPT(hhcd))
503 {
504 return;
505 }
506
507 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
508 {
509 /* Incorrect mode, acknowledge the interrupt */
510 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
511 }
512
513 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
514 {
515 /* Incorrect mode, acknowledge the interrupt */
516 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
517 }
518
519 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
520 {
521 /* Incorrect mode, acknowledge the interrupt */
522 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
523 }
524
525 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
526 {
527 /* Incorrect mode, acknowledge the interrupt */
528 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
529 }
530
531 /* Handle Host Disconnect Interrupts */
532 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
533 {
534 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
535
536 if ((USBx_HPRT0 & USB_OTG_HPRT_PCSTS) == 0U)
537 {
538 /* Flush USB Fifo */
539 (void)USB_FlushTxFifo(USBx, 0x10U);
540 (void)USB_FlushRxFifo(USBx);
541
542 if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
543 {
544 /* Restore FS Clock */
545 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
546 }
547
548 /* Handle Host Port Disconnect Interrupt */
549 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
550 hhcd->DisconnectCallback(hhcd);
551 #else
552 HAL_HCD_Disconnect_Callback(hhcd);
553 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
554 }
555 }
556
557 /* Handle Host Port Interrupts */
558 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
559 {
560 HCD_Port_IRQHandler(hhcd);
561 }
562
563 /* Handle Host SOF Interrupt */
564 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
565 {
566 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
567 hhcd->SOFCallback(hhcd);
568 #else
569 HAL_HCD_SOF_Callback(hhcd);
570 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
571
572 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
573 }
574
575 /* Handle Host channel Interrupt */
576 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
577 {
578 interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
579 for (i = 0U; i < hhcd->Init.Host_channels; i++)
580 {
581 if ((interrupt & (1UL << (i & 0xFU))) != 0U)
582 {
583 if ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR)
584 {
585 HCD_HC_IN_IRQHandler(hhcd, (uint8_t)i);
586 }
587 else
588 {
589 HCD_HC_OUT_IRQHandler(hhcd, (uint8_t)i);
590 }
591 }
592 }
593 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
594 }
595
596 /* Handle Rx Queue Level Interrupts */
597 if ((__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) != 0U)
598 {
599 USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
600
601 HCD_RXQLVL_IRQHandler(hhcd);
602
603 USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
604 }
605 }
606 }
607
608
609 /**
610 * @brief Handles HCD Wakeup interrupt request.
611 * @param hhcd HCD handle
612 * @retval HAL status
613 */
HAL_HCD_WKUP_IRQHandler(HCD_HandleTypeDef * hhcd)614 void HAL_HCD_WKUP_IRQHandler(HCD_HandleTypeDef *hhcd)
615 {
616 UNUSED(hhcd);
617 }
618
619
620 /**
621 * @brief SOF callback.
622 * @param hhcd HCD handle
623 * @retval None
624 */
HAL_HCD_SOF_Callback(HCD_HandleTypeDef * hhcd)625 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
626 {
627 /* Prevent unused argument(s) compilation warning */
628 UNUSED(hhcd);
629
630 /* NOTE : This function should not be modified, when the callback is needed,
631 the HAL_HCD_SOF_Callback could be implemented in the user file
632 */
633 }
634
635 /**
636 * @brief Connection Event callback.
637 * @param hhcd HCD handle
638 * @retval None
639 */
HAL_HCD_Connect_Callback(HCD_HandleTypeDef * hhcd)640 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
641 {
642 /* Prevent unused argument(s) compilation warning */
643 UNUSED(hhcd);
644
645 /* NOTE : This function should not be modified, when the callback is needed,
646 the HAL_HCD_Connect_Callback could be implemented in the user file
647 */
648 }
649
650 /**
651 * @brief Disconnection Event callback.
652 * @param hhcd HCD handle
653 * @retval None
654 */
HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef * hhcd)655 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
656 {
657 /* Prevent unused argument(s) compilation warning */
658 UNUSED(hhcd);
659
660 /* NOTE : This function should not be modified, when the callback is needed,
661 the HAL_HCD_Disconnect_Callback could be implemented in the user file
662 */
663 }
664
665 /**
666 * @brief Port Enabled Event callback.
667 * @param hhcd HCD handle
668 * @retval None
669 */
HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef * hhcd)670 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
671 {
672 /* Prevent unused argument(s) compilation warning */
673 UNUSED(hhcd);
674
675 /* NOTE : This function should not be modified, when the callback is needed,
676 the HAL_HCD_Disconnect_Callback could be implemented in the user file
677 */
678 }
679
680 /**
681 * @brief Port Disabled Event callback.
682 * @param hhcd HCD handle
683 * @retval None
684 */
HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef * hhcd)685 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
686 {
687 /* Prevent unused argument(s) compilation warning */
688 UNUSED(hhcd);
689
690 /* NOTE : This function should not be modified, when the callback is needed,
691 the HAL_HCD_Disconnect_Callback could be implemented in the user file
692 */
693 }
694
695 /**
696 * @brief Notify URB state change callback.
697 * @param hhcd HCD handle
698 * @param chnum Channel number.
699 * This parameter can be a value from 1 to 15
700 * @param urb_state:
701 * This parameter can be one of these values:
702 * URB_IDLE/
703 * URB_DONE/
704 * URB_NOTREADY/
705 * URB_NYET/
706 * URB_ERROR/
707 * URB_STALL/
708 * @retval None
709 */
HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef * hhcd,uint8_t chnum,HCD_URBStateTypeDef urb_state)710 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
711 {
712 /* Prevent unused argument(s) compilation warning */
713 UNUSED(hhcd);
714 UNUSED(chnum);
715 UNUSED(urb_state);
716
717 /* NOTE : This function should not be modified, when the callback is needed,
718 the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
719 */
720 }
721
722 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
723 /**
724 * @brief Register a User USB HCD Callback
725 * To be used instead of the weak predefined callback
726 * @param hhcd USB HCD handle
727 * @param CallbackID ID of the callback to be registered
728 * This parameter can be one of the following values:
729 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
730 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
731 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
732 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
733 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
734 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
735 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
736 * @param pCallback pointer to the Callback function
737 * @retval HAL status
738 */
HAL_HCD_RegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID,pHCD_CallbackTypeDef pCallback)739 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
740 HAL_HCD_CallbackIDTypeDef CallbackID,
741 pHCD_CallbackTypeDef pCallback)
742 {
743 HAL_StatusTypeDef status = HAL_OK;
744
745 if (pCallback == NULL)
746 {
747 /* Update the error code */
748 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
749 return HAL_ERROR;
750 }
751 /* Process locked */
752 __HAL_LOCK(hhcd);
753
754 if (hhcd->State == HAL_HCD_STATE_READY)
755 {
756 switch (CallbackID)
757 {
758 case HAL_HCD_SOF_CB_ID :
759 hhcd->SOFCallback = pCallback;
760 break;
761
762 case HAL_HCD_CONNECT_CB_ID :
763 hhcd->ConnectCallback = pCallback;
764 break;
765
766 case HAL_HCD_DISCONNECT_CB_ID :
767 hhcd->DisconnectCallback = pCallback;
768 break;
769
770 case HAL_HCD_PORT_ENABLED_CB_ID :
771 hhcd->PortEnabledCallback = pCallback;
772 break;
773
774 case HAL_HCD_PORT_DISABLED_CB_ID :
775 hhcd->PortDisabledCallback = pCallback;
776 break;
777
778 case HAL_HCD_MSPINIT_CB_ID :
779 hhcd->MspInitCallback = pCallback;
780 break;
781
782 case HAL_HCD_MSPDEINIT_CB_ID :
783 hhcd->MspDeInitCallback = pCallback;
784 break;
785
786 default :
787 /* Update the error code */
788 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
789 /* Return error status */
790 status = HAL_ERROR;
791 break;
792 }
793 }
794 else if (hhcd->State == HAL_HCD_STATE_RESET)
795 {
796 switch (CallbackID)
797 {
798 case HAL_HCD_MSPINIT_CB_ID :
799 hhcd->MspInitCallback = pCallback;
800 break;
801
802 case HAL_HCD_MSPDEINIT_CB_ID :
803 hhcd->MspDeInitCallback = pCallback;
804 break;
805
806 default :
807 /* Update the error code */
808 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
809 /* Return error status */
810 status = HAL_ERROR;
811 break;
812 }
813 }
814 else
815 {
816 /* Update the error code */
817 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
818 /* Return error status */
819 status = HAL_ERROR;
820 }
821
822 /* Release Lock */
823 __HAL_UNLOCK(hhcd);
824 return status;
825 }
826
827 /**
828 * @brief Unregister an USB HCD Callback
829 * USB HCD callback is redirected to the weak predefined callback
830 * @param hhcd USB HCD handle
831 * @param CallbackID ID of the callback to be unregistered
832 * This parameter can be one of the following values:
833 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
834 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
835 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
836 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
837 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
838 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
839 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
840 * @retval HAL status
841 */
HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID)842 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID)
843 {
844 HAL_StatusTypeDef status = HAL_OK;
845
846 /* Process locked */
847 __HAL_LOCK(hhcd);
848
849 /* Setup Legacy weak Callbacks */
850 if (hhcd->State == HAL_HCD_STATE_READY)
851 {
852 switch (CallbackID)
853 {
854 case HAL_HCD_SOF_CB_ID :
855 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
856 break;
857
858 case HAL_HCD_CONNECT_CB_ID :
859 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
860 break;
861
862 case HAL_HCD_DISCONNECT_CB_ID :
863 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
864 break;
865
866 case HAL_HCD_PORT_ENABLED_CB_ID :
867 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
868 break;
869
870 case HAL_HCD_PORT_DISABLED_CB_ID :
871 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
872 break;
873
874 case HAL_HCD_MSPINIT_CB_ID :
875 hhcd->MspInitCallback = HAL_HCD_MspInit;
876 break;
877
878 case HAL_HCD_MSPDEINIT_CB_ID :
879 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
880 break;
881
882 default :
883 /* Update the error code */
884 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
885
886 /* Return error status */
887 status = HAL_ERROR;
888 break;
889 }
890 }
891 else if (hhcd->State == HAL_HCD_STATE_RESET)
892 {
893 switch (CallbackID)
894 {
895 case HAL_HCD_MSPINIT_CB_ID :
896 hhcd->MspInitCallback = HAL_HCD_MspInit;
897 break;
898
899 case HAL_HCD_MSPDEINIT_CB_ID :
900 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
901 break;
902
903 default :
904 /* Update the error code */
905 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
906
907 /* Return error status */
908 status = HAL_ERROR;
909 break;
910 }
911 }
912 else
913 {
914 /* Update the error code */
915 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
916
917 /* Return error status */
918 status = HAL_ERROR;
919 }
920
921 /* Release Lock */
922 __HAL_UNLOCK(hhcd);
923 return status;
924 }
925
926 /**
927 * @brief Register USB HCD Host Channel Notify URB Change Callback
928 * To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
929 * @param hhcd HCD handle
930 * @param pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
931 * @retval HAL status
932 */
HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd,pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)933 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
934 pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
935 {
936 HAL_StatusTypeDef status = HAL_OK;
937
938 if (pCallback == NULL)
939 {
940 /* Update the error code */
941 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
942
943 return HAL_ERROR;
944 }
945
946 /* Process locked */
947 __HAL_LOCK(hhcd);
948
949 if (hhcd->State == HAL_HCD_STATE_READY)
950 {
951 hhcd->HC_NotifyURBChangeCallback = pCallback;
952 }
953 else
954 {
955 /* Update the error code */
956 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
957
958 /* Return error status */
959 status = HAL_ERROR;
960 }
961
962 /* Release Lock */
963 __HAL_UNLOCK(hhcd);
964
965 return status;
966 }
967
968 /**
969 * @brief Unregister the USB HCD Host Channel Notify URB Change Callback
970 * USB HCD Host Channel Notify URB Change Callback is redirected
971 * to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
972 * @param hhcd HCD handle
973 * @retval HAL status
974 */
HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd)975 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
976 {
977 HAL_StatusTypeDef status = HAL_OK;
978
979 /* Process locked */
980 __HAL_LOCK(hhcd);
981
982 if (hhcd->State == HAL_HCD_STATE_READY)
983 {
984 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
985 }
986 else
987 {
988 /* Update the error code */
989 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
990
991 /* Return error status */
992 status = HAL_ERROR;
993 }
994
995 /* Release Lock */
996 __HAL_UNLOCK(hhcd);
997
998 return status;
999 }
1000 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1001
1002 /**
1003 * @}
1004 */
1005
1006 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
1007 * @brief Management functions
1008 *
1009 @verbatim
1010 ===============================================================================
1011 ##### Peripheral Control functions #####
1012 ===============================================================================
1013 [..]
1014 This subsection provides a set of functions allowing to control the HCD data
1015 transfers.
1016
1017 @endverbatim
1018 * @{
1019 */
1020
1021 /**
1022 * @brief Start the host driver.
1023 * @param hhcd HCD handle
1024 * @retval HAL status
1025 */
HAL_HCD_Start(HCD_HandleTypeDef * hhcd)1026 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
1027 {
1028 __HAL_LOCK(hhcd);
1029 /* Enable port power */
1030 (void)USB_DriveVbus(hhcd->Instance, 1U);
1031
1032 /* Enable global interrupt */
1033 __HAL_HCD_ENABLE(hhcd);
1034 __HAL_UNLOCK(hhcd);
1035
1036 return HAL_OK;
1037 }
1038
1039 /**
1040 * @brief Stop the host driver.
1041 * @param hhcd HCD handle
1042 * @retval HAL status
1043 */
1044
HAL_HCD_Stop(HCD_HandleTypeDef * hhcd)1045 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
1046 {
1047 __HAL_LOCK(hhcd);
1048 (void)USB_StopHost(hhcd->Instance);
1049 __HAL_UNLOCK(hhcd);
1050
1051 return HAL_OK;
1052 }
1053
1054 /**
1055 * @brief Reset the host port.
1056 * @param hhcd HCD handle
1057 * @retval HAL status
1058 */
HAL_HCD_ResetPort(HCD_HandleTypeDef * hhcd)1059 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
1060 {
1061 return (USB_ResetPort(hhcd->Instance));
1062 }
1063
1064 /**
1065 * @}
1066 */
1067
1068 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
1069 * @brief Peripheral State functions
1070 *
1071 @verbatim
1072 ===============================================================================
1073 ##### Peripheral State functions #####
1074 ===============================================================================
1075 [..]
1076 This subsection permits to get in run-time the status of the peripheral
1077 and the data flow.
1078
1079 @endverbatim
1080 * @{
1081 */
1082
1083 /**
1084 * @brief Return the HCD handle state.
1085 * @param hhcd HCD handle
1086 * @retval HAL state
1087 */
HAL_HCD_GetState(HCD_HandleTypeDef const * hhcd)1088 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef const *hhcd)
1089 {
1090 return hhcd->State;
1091 }
1092
1093 /**
1094 * @brief Return URB state for a channel.
1095 * @param hhcd HCD handle
1096 * @param chnum Channel number.
1097 * This parameter can be a value from 1 to 15
1098 * @retval URB state.
1099 * This parameter can be one of these values:
1100 * URB_IDLE/
1101 * URB_DONE/
1102 * URB_NOTREADY/
1103 * URB_NYET/
1104 * URB_ERROR/
1105 * URB_STALL
1106 */
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1107 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1108 {
1109 return hhcd->hc[chnum].urb_state;
1110 }
1111
1112
1113 /**
1114 * @brief Return the last host transfer size.
1115 * @param hhcd HCD handle
1116 * @param chnum Channel number.
1117 * This parameter can be a value from 1 to 15
1118 * @retval last transfer size in byte
1119 */
HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1120 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1121 {
1122 return hhcd->hc[chnum].xfer_count;
1123 }
1124
1125 /**
1126 * @brief Return the Host Channel state.
1127 * @param hhcd HCD handle
1128 * @param chnum Channel number.
1129 * This parameter can be a value from 1 to 15
1130 * @retval Host channel state
1131 * This parameter can be one of these values:
1132 * HC_IDLE/
1133 * HC_XFRC/
1134 * HC_HALTED/
1135 * HC_NYET/
1136 * HC_NAK/
1137 * HC_STALL/
1138 * HC_XACTERR/
1139 * HC_BBLERR/
1140 * HC_DATATGLERR
1141 */
HAL_HCD_HC_GetState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1142 HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1143 {
1144 return hhcd->hc[chnum].state;
1145 }
1146
1147 /**
1148 * @brief Return the current Host frame number.
1149 * @param hhcd HCD handle
1150 * @retval Current Host frame number
1151 */
HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef * hhcd)1152 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
1153 {
1154 return (USB_GetCurrentFrame(hhcd->Instance));
1155 }
1156
1157 /**
1158 * @brief Return the Host enumeration speed.
1159 * @param hhcd HCD handle
1160 * @retval Enumeration speed
1161 */
HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef * hhcd)1162 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
1163 {
1164 return (USB_GetHostSpeed(hhcd->Instance));
1165 }
1166
1167 /**
1168 * @brief Set host channel Hub information.
1169 * @param hhcd HCD handle
1170 * @param ch_num Channel number.
1171 * This parameter can be a value from 1 to 15
1172 * @param addr Hub address
1173 * @param PortNbr Hub port number
1174 * @retval HAL status
1175 */
HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t addr,uint8_t PortNbr)1176 HAL_StatusTypeDef HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1177 uint8_t addr, uint8_t PortNbr)
1178 {
1179 hhcd->hc[ch_num].hub_addr = addr;
1180 hhcd->hc[ch_num].hub_port_nbr = PortNbr;
1181
1182 return HAL_OK;
1183 }
1184
1185
1186 /**
1187 * @brief Clear host channel hub information.
1188 * @param hhcd HCD handle
1189 * @param ch_num Channel number.
1190 * This parameter can be a value from 1 to 15
1191 * @retval HAL status
1192 */
HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num)1193 HAL_StatusTypeDef HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
1194 {
1195 hhcd->hc[ch_num].hub_addr = 0U;
1196 hhcd->hc[ch_num].hub_port_nbr = 0U;
1197
1198 return HAL_OK;
1199 }
1200 /**
1201 * @}
1202 */
1203
1204 /**
1205 * @}
1206 */
1207
1208 /** @addtogroup HCD_Private_Functions
1209 * @{
1210 */
1211 /**
1212 * @brief Handle Host Channel IN interrupt requests.
1213 * @param hhcd HCD handle
1214 * @param chnum Channel number.
1215 * This parameter can be a value from 1 to 15
1216 * @retval none
1217 */
HCD_HC_IN_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1218 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1219 {
1220 const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1221 uint32_t USBx_BASE = (uint32_t)USBx;
1222 uint32_t tmpreg;
1223
1224 if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
1225 {
1226 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
1227 hhcd->hc[chnum].state = HC_XACTERR;
1228 (void)USB_HC_Halt(hhcd->Instance, chnum);
1229 }
1230 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_BBERR))
1231 {
1232 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_BBERR);
1233 hhcd->hc[chnum].state = HC_BBLERR;
1234 (void)USB_HC_Halt(hhcd->Instance, chnum);
1235 }
1236 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
1237 {
1238 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
1239 hhcd->hc[chnum].state = HC_STALL;
1240 (void)USB_HC_Halt(hhcd->Instance, chnum);
1241 }
1242 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
1243 {
1244 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
1245 hhcd->hc[chnum].state = HC_DATATGLERR;
1246 (void)USB_HC_Halt(hhcd->Instance, chnum);
1247 }
1248 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
1249 {
1250 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
1251 hhcd->hc[chnum].state = HC_XACTERR;
1252 (void)USB_HC_Halt(hhcd->Instance, chnum);
1253 }
1254 else
1255 {
1256 /* ... */
1257 }
1258
1259 if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
1260 {
1261 (void)USB_HC_Halt(hhcd->Instance, chnum);
1262 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
1263 }
1264 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
1265 {
1266 hhcd->hc[chnum].state = HC_XFRC;
1267 hhcd->hc[chnum].ErrCnt = 0U;
1268 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
1269
1270 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1271 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1272 {
1273 (void)USB_HC_Halt(hhcd->Instance, chnum);
1274 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1275 }
1276 else if ((hhcd->hc[chnum].ep_type == EP_TYPE_INTR) ||
1277 (hhcd->hc[chnum].ep_type == EP_TYPE_ISOC))
1278 {
1279 USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
1280 hhcd->hc[chnum].urb_state = URB_DONE;
1281
1282 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1283 hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1284 #else
1285 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1286 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1287 }
1288 else
1289 {
1290 /* ... */
1291 }
1292
1293 if (hhcd->Init.dma_enable == 1U)
1294 {
1295 if ((((hhcd->hc[chnum].xfer_count + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet) & 1U) != 0U)
1296 {
1297 hhcd->hc[chnum].toggle_in ^= 1U;
1298 }
1299 }
1300 else
1301 {
1302 hhcd->hc[chnum].toggle_in ^= 1U;
1303 }
1304 }
1305 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
1306 {
1307 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1308 }
1309 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
1310 {
1311 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
1312
1313 if (hhcd->hc[chnum].state == HC_XFRC)
1314 {
1315 hhcd->hc[chnum].state = HC_HALTED;
1316 hhcd->hc[chnum].urb_state = URB_DONE;
1317 }
1318 else if (hhcd->hc[chnum].state == HC_STALL)
1319 {
1320 hhcd->hc[chnum].state = HC_HALTED;
1321 hhcd->hc[chnum].urb_state = URB_STALL;
1322 }
1323 else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
1324 (hhcd->hc[chnum].state == HC_DATATGLERR))
1325 {
1326 hhcd->hc[chnum].state = HC_HALTED;
1327 hhcd->hc[chnum].ErrCnt++;
1328 if (hhcd->hc[chnum].ErrCnt > 2U)
1329 {
1330 hhcd->hc[chnum].ErrCnt = 0U;
1331 hhcd->hc[chnum].urb_state = URB_ERROR;
1332 }
1333 else
1334 {
1335 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1336
1337 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1338 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1339 {
1340 /* re-activate the channel */
1341 tmpreg = USBx_HC(chnum)->HCCHAR;
1342 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1343 tmpreg |= USB_OTG_HCCHAR_CHENA;
1344 USBx_HC(chnum)->HCCHAR = tmpreg;
1345 }
1346 }
1347 }
1348 else if (hhcd->hc[chnum].state == HC_NYET)
1349 {
1350 hhcd->hc[chnum].state = HC_HALTED;
1351 }
1352 else if (hhcd->hc[chnum].state == HC_ACK)
1353 {
1354 hhcd->hc[chnum].state = HC_HALTED;
1355 }
1356 else if (hhcd->hc[chnum].state == HC_NAK)
1357 {
1358 hhcd->hc[chnum].state = HC_HALTED;
1359 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1360
1361 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1362 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1363 {
1364 /* re-activate the channel */
1365 tmpreg = USBx_HC(chnum)->HCCHAR;
1366 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1367 tmpreg |= USB_OTG_HCCHAR_CHENA;
1368 USBx_HC(chnum)->HCCHAR = tmpreg;
1369 }
1370 }
1371 else if (hhcd->hc[chnum].state == HC_BBLERR)
1372 {
1373 hhcd->hc[chnum].state = HC_HALTED;
1374 hhcd->hc[chnum].ErrCnt++;
1375 hhcd->hc[chnum].urb_state = URB_ERROR;
1376 }
1377 else
1378 {
1379 if (hhcd->hc[chnum].state == HC_HALTED)
1380 {
1381 return;
1382 }
1383 }
1384
1385 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1386 hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1387 #else
1388 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1389 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1390 }
1391 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
1392 {
1393 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
1394 hhcd->hc[chnum].state = HC_NYET;
1395 hhcd->hc[chnum].ErrCnt = 0U;
1396
1397 (void)USB_HC_Halt(hhcd->Instance, chnum);
1398 }
1399 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
1400 {
1401 if (hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
1402 {
1403 hhcd->hc[chnum].ErrCnt = 0U;
1404 hhcd->hc[chnum].state = HC_NAK;
1405 (void)USB_HC_Halt(hhcd->Instance, chnum);
1406 }
1407 else if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1408 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1409 {
1410 hhcd->hc[chnum].ErrCnt = 0U;
1411 hhcd->hc[chnum].state = HC_NAK;
1412 (void)USB_HC_Halt(hhcd->Instance, chnum);
1413 }
1414 else
1415 {
1416 /* ... */
1417 }
1418
1419 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1420 }
1421 else
1422 {
1423 /* ... */
1424 }
1425 }
1426
1427 /**
1428 * @brief Handle Host Channel OUT interrupt requests.
1429 * @param hhcd HCD handle
1430 * @param chnum Channel number.
1431 * This parameter can be a value from 1 to 15
1432 * @retval none
1433 */
HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1434 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1435 {
1436 const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1437 uint32_t USBx_BASE = (uint32_t)USBx;
1438 uint32_t tmpreg;
1439 uint32_t num_packets;
1440
1441 if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
1442 {
1443 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
1444 hhcd->hc[chnum].state = HC_XACTERR;
1445 (void)USB_HC_Halt(hhcd->Instance, chnum);
1446 }
1447 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
1448 {
1449 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1450 }
1451 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
1452 {
1453 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
1454 (void)USB_HC_Halt(hhcd->Instance, chnum);
1455 }
1456 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
1457 {
1458 hhcd->hc[chnum].ErrCnt = 0U;
1459
1460 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
1461 hhcd->hc[chnum].state = HC_XFRC;
1462 (void)USB_HC_Halt(hhcd->Instance, chnum);
1463 }
1464 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
1465 {
1466 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
1467 hhcd->hc[chnum].state = HC_STALL;
1468 (void)USB_HC_Halt(hhcd->Instance, chnum);
1469 }
1470 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
1471 {
1472 hhcd->hc[chnum].ErrCnt = 0U;
1473 hhcd->hc[chnum].state = HC_NAK;
1474
1475 (void)USB_HC_Halt(hhcd->Instance, chnum);
1476 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1477 }
1478 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
1479 {
1480 hhcd->hc[chnum].state = HC_XACTERR;
1481 (void)USB_HC_Halt(hhcd->Instance, chnum);
1482 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
1483 }
1484 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
1485 {
1486 hhcd->hc[chnum].state = HC_DATATGLERR;
1487 (void)USB_HC_Halt(hhcd->Instance, chnum);
1488 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
1489 }
1490 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
1491 {
1492 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
1493
1494 if (hhcd->hc[chnum].state == HC_XFRC)
1495 {
1496 hhcd->hc[chnum].state = HC_HALTED;
1497 hhcd->hc[chnum].urb_state = URB_DONE;
1498
1499 if ((hhcd->hc[chnum].ep_type == EP_TYPE_BULK) ||
1500 (hhcd->hc[chnum].ep_type == EP_TYPE_INTR))
1501 {
1502 if (hhcd->Init.dma_enable == 0U)
1503 {
1504 hhcd->hc[chnum].toggle_out ^= 1U;
1505 }
1506
1507 if ((hhcd->Init.dma_enable == 1U) && (hhcd->hc[chnum].xfer_len > 0U))
1508 {
1509 num_packets = (hhcd->hc[chnum].xfer_len + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet;
1510
1511 if ((num_packets & 1U) != 0U)
1512 {
1513 hhcd->hc[chnum].toggle_out ^= 1U;
1514 }
1515 }
1516 }
1517 }
1518 else if (hhcd->hc[chnum].state == HC_ACK)
1519 {
1520 hhcd->hc[chnum].state = HC_HALTED;
1521 }
1522 else if (hhcd->hc[chnum].state == HC_NAK)
1523 {
1524 hhcd->hc[chnum].state = HC_HALTED;
1525 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1526 }
1527 else if (hhcd->hc[chnum].state == HC_STALL)
1528 {
1529 hhcd->hc[chnum].state = HC_HALTED;
1530 hhcd->hc[chnum].urb_state = URB_STALL;
1531 }
1532 else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
1533 (hhcd->hc[chnum].state == HC_DATATGLERR))
1534 {
1535 hhcd->hc[chnum].state = HC_HALTED;
1536 hhcd->hc[chnum].ErrCnt++;
1537 if (hhcd->hc[chnum].ErrCnt > 2U)
1538 {
1539 hhcd->hc[chnum].ErrCnt = 0U;
1540 hhcd->hc[chnum].urb_state = URB_ERROR;
1541 }
1542 else
1543 {
1544 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1545
1546 /* re-activate the channel */
1547 tmpreg = USBx_HC(chnum)->HCCHAR;
1548 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1549 tmpreg |= USB_OTG_HCCHAR_CHENA;
1550 USBx_HC(chnum)->HCCHAR = tmpreg;
1551 }
1552 }
1553 else
1554 {
1555 return;
1556 }
1557
1558 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1559 hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1560 #else
1561 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1562 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1563 }
1564 else
1565 {
1566 return;
1567 }
1568 }
1569
1570 /**
1571 * @brief Handle Rx Queue Level interrupt requests.
1572 * @param hhcd HCD handle
1573 * @retval none
1574 */
HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef * hhcd)1575 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
1576 {
1577 const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1578 uint32_t USBx_BASE = (uint32_t)USBx;
1579 uint32_t pktsts;
1580 uint32_t pktcnt;
1581 uint32_t GrxstspReg;
1582 uint32_t xferSizePktCnt;
1583 uint32_t tmpreg;
1584 uint32_t chnum;
1585
1586 GrxstspReg = hhcd->Instance->GRXSTSP;
1587 chnum = GrxstspReg & USB_OTG_GRXSTSP_EPNUM;
1588 pktsts = (GrxstspReg & USB_OTG_GRXSTSP_PKTSTS) >> 17;
1589 pktcnt = (GrxstspReg & USB_OTG_GRXSTSP_BCNT) >> 4;
1590
1591 switch (pktsts)
1592 {
1593 case GRXSTS_PKTSTS_IN:
1594 /* Read the data into the host buffer. */
1595 if ((pktcnt > 0U) && (hhcd->hc[chnum].xfer_buff != (void *)0))
1596 {
1597 if ((hhcd->hc[chnum].xfer_count + pktcnt) <= hhcd->hc[chnum].xfer_len)
1598 {
1599 (void)USB_ReadPacket(hhcd->Instance,
1600 hhcd->hc[chnum].xfer_buff, (uint16_t)pktcnt);
1601
1602 /* manage multiple Xfer */
1603 hhcd->hc[chnum].xfer_buff += pktcnt;
1604 hhcd->hc[chnum].xfer_count += pktcnt;
1605
1606 /* get transfer size packet count */
1607 xferSizePktCnt = (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19;
1608
1609 if ((hhcd->hc[chnum].max_packet == pktcnt) && (xferSizePktCnt > 0U))
1610 {
1611 /* re-activate the channel when more packets are expected */
1612 tmpreg = USBx_HC(chnum)->HCCHAR;
1613 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1614 tmpreg |= USB_OTG_HCCHAR_CHENA;
1615 USBx_HC(chnum)->HCCHAR = tmpreg;
1616 hhcd->hc[chnum].toggle_in ^= 1U;
1617 }
1618 }
1619 else
1620 {
1621 hhcd->hc[chnum].urb_state = URB_ERROR;
1622 }
1623 }
1624 break;
1625
1626 case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
1627 break;
1628
1629 case GRXSTS_PKTSTS_IN_XFER_COMP:
1630 case GRXSTS_PKTSTS_CH_HALTED:
1631 default:
1632 break;
1633 }
1634 }
1635
1636 /**
1637 * @brief Handle Host Port interrupt requests.
1638 * @param hhcd HCD handle
1639 * @retval None
1640 */
HCD_Port_IRQHandler(HCD_HandleTypeDef * hhcd)1641 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
1642 {
1643 const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1644 uint32_t USBx_BASE = (uint32_t)USBx;
1645 __IO uint32_t hprt0;
1646 __IO uint32_t hprt0_dup;
1647
1648 /* Handle Host Port Interrupts */
1649 hprt0 = USBx_HPRT0;
1650 hprt0_dup = USBx_HPRT0;
1651
1652 hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
1653 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
1654
1655 /* Check whether Port Connect detected */
1656 if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
1657 {
1658 if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
1659 {
1660 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1661 hhcd->ConnectCallback(hhcd);
1662 #else
1663 HAL_HCD_Connect_Callback(hhcd);
1664 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1665 }
1666 hprt0_dup |= USB_OTG_HPRT_PCDET;
1667 }
1668
1669 /* Check whether Port Enable Changed */
1670 if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
1671 {
1672 hprt0_dup |= USB_OTG_HPRT_PENCHNG;
1673
1674 if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
1675 {
1676 if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
1677 {
1678 if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
1679 {
1680 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
1681 }
1682 else
1683 {
1684 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
1685 }
1686 }
1687 else
1688 {
1689 if (hhcd->Init.speed == HCD_SPEED_FULL)
1690 {
1691 USBx_HOST->HFIR = HFIR_60_MHZ;
1692 }
1693 }
1694 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1695 hhcd->PortEnabledCallback(hhcd);
1696 #else
1697 HAL_HCD_PortEnabled_Callback(hhcd);
1698 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1699
1700 }
1701 else
1702 {
1703 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1704 hhcd->PortDisabledCallback(hhcd);
1705 #else
1706 HAL_HCD_PortDisabled_Callback(hhcd);
1707 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1708 }
1709 }
1710
1711 /* Check for an overcurrent */
1712 if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
1713 {
1714 hprt0_dup |= USB_OTG_HPRT_POCCHNG;
1715 }
1716
1717 /* Clear Port Interrupts */
1718 USBx_HPRT0 = hprt0_dup;
1719 }
1720
1721 /**
1722 * @}
1723 */
1724
1725 /**
1726 * @}
1727 */
1728
1729 #endif /* defined (USB_OTG_FS) */
1730 #endif /* HAL_HCD_MODULE_ENABLED */
1731
1732 /**
1733 * @}
1734 */
1735
1736 /**
1737 * @}
1738 */
1739