1 /**
2 ******************************************************************************
3 * @file stm32l4xx_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) 2017 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 "stm32l4xx_hal.h"
55
56 /** @addtogroup STM32L4xx_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 SOF callback.
611 * @param hhcd HCD handle
612 * @retval None
613 */
HAL_HCD_SOF_Callback(HCD_HandleTypeDef * hhcd)614 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
615 {
616 /* Prevent unused argument(s) compilation warning */
617 UNUSED(hhcd);
618
619 /* NOTE : This function should not be modified, when the callback is needed,
620 the HAL_HCD_SOF_Callback could be implemented in the user file
621 */
622 }
623
624 /**
625 * @brief Connection Event callback.
626 * @param hhcd HCD handle
627 * @retval None
628 */
HAL_HCD_Connect_Callback(HCD_HandleTypeDef * hhcd)629 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
630 {
631 /* Prevent unused argument(s) compilation warning */
632 UNUSED(hhcd);
633
634 /* NOTE : This function should not be modified, when the callback is needed,
635 the HAL_HCD_Connect_Callback could be implemented in the user file
636 */
637 }
638
639 /**
640 * @brief Disconnection Event callback.
641 * @param hhcd HCD handle
642 * @retval None
643 */
HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef * hhcd)644 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
645 {
646 /* Prevent unused argument(s) compilation warning */
647 UNUSED(hhcd);
648
649 /* NOTE : This function should not be modified, when the callback is needed,
650 the HAL_HCD_Disconnect_Callback could be implemented in the user file
651 */
652 }
653
654 /**
655 * @brief Port Enabled Event callback.
656 * @param hhcd HCD handle
657 * @retval None
658 */
HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef * hhcd)659 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
660 {
661 /* Prevent unused argument(s) compilation warning */
662 UNUSED(hhcd);
663
664 /* NOTE : This function should not be modified, when the callback is needed,
665 the HAL_HCD_Disconnect_Callback could be implemented in the user file
666 */
667 }
668
669 /**
670 * @brief Port Disabled Event callback.
671 * @param hhcd HCD handle
672 * @retval None
673 */
HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef * hhcd)674 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
675 {
676 /* Prevent unused argument(s) compilation warning */
677 UNUSED(hhcd);
678
679 /* NOTE : This function should not be modified, when the callback is needed,
680 the HAL_HCD_Disconnect_Callback could be implemented in the user file
681 */
682 }
683
684 /**
685 * @brief Notify URB state change callback.
686 * @param hhcd HCD handle
687 * @param chnum Channel number.
688 * This parameter can be a value from 1 to 15
689 * @param urb_state:
690 * This parameter can be one of these values:
691 * URB_IDLE/
692 * URB_DONE/
693 * URB_NOTREADY/
694 * URB_NYET/
695 * URB_ERROR/
696 * URB_STALL/
697 * @retval None
698 */
HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef * hhcd,uint8_t chnum,HCD_URBStateTypeDef urb_state)699 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
700 {
701 /* Prevent unused argument(s) compilation warning */
702 UNUSED(hhcd);
703 UNUSED(chnum);
704 UNUSED(urb_state);
705
706 /* NOTE : This function should not be modified, when the callback is needed,
707 the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
708 */
709 }
710
711 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
712 /**
713 * @brief Register a User USB HCD Callback
714 * To be used instead of the weak predefined callback
715 * @param hhcd USB HCD handle
716 * @param CallbackID ID of the callback to be registered
717 * This parameter can be one of the following values:
718 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
719 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
720 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
721 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
722 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
723 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
724 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
725 * @param pCallback pointer to the Callback function
726 * @retval HAL status
727 */
HAL_HCD_RegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID,pHCD_CallbackTypeDef pCallback)728 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
729 HAL_HCD_CallbackIDTypeDef CallbackID,
730 pHCD_CallbackTypeDef pCallback)
731 {
732 HAL_StatusTypeDef status = HAL_OK;
733
734 if (pCallback == NULL)
735 {
736 /* Update the error code */
737 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
738 return HAL_ERROR;
739 }
740 /* Process locked */
741 __HAL_LOCK(hhcd);
742
743 if (hhcd->State == HAL_HCD_STATE_READY)
744 {
745 switch (CallbackID)
746 {
747 case HAL_HCD_SOF_CB_ID :
748 hhcd->SOFCallback = pCallback;
749 break;
750
751 case HAL_HCD_CONNECT_CB_ID :
752 hhcd->ConnectCallback = pCallback;
753 break;
754
755 case HAL_HCD_DISCONNECT_CB_ID :
756 hhcd->DisconnectCallback = pCallback;
757 break;
758
759 case HAL_HCD_PORT_ENABLED_CB_ID :
760 hhcd->PortEnabledCallback = pCallback;
761 break;
762
763 case HAL_HCD_PORT_DISABLED_CB_ID :
764 hhcd->PortDisabledCallback = pCallback;
765 break;
766
767 case HAL_HCD_MSPINIT_CB_ID :
768 hhcd->MspInitCallback = pCallback;
769 break;
770
771 case HAL_HCD_MSPDEINIT_CB_ID :
772 hhcd->MspDeInitCallback = pCallback;
773 break;
774
775 default :
776 /* Update the error code */
777 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
778 /* Return error status */
779 status = HAL_ERROR;
780 break;
781 }
782 }
783 else if (hhcd->State == HAL_HCD_STATE_RESET)
784 {
785 switch (CallbackID)
786 {
787 case HAL_HCD_MSPINIT_CB_ID :
788 hhcd->MspInitCallback = pCallback;
789 break;
790
791 case HAL_HCD_MSPDEINIT_CB_ID :
792 hhcd->MspDeInitCallback = pCallback;
793 break;
794
795 default :
796 /* Update the error code */
797 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
798 /* Return error status */
799 status = HAL_ERROR;
800 break;
801 }
802 }
803 else
804 {
805 /* Update the error code */
806 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
807 /* Return error status */
808 status = HAL_ERROR;
809 }
810
811 /* Release Lock */
812 __HAL_UNLOCK(hhcd);
813 return status;
814 }
815
816 /**
817 * @brief Unregister an USB HCD Callback
818 * USB HCD callback is redirected to the weak predefined callback
819 * @param hhcd USB HCD handle
820 * @param CallbackID ID of the callback to be unregistered
821 * This parameter can be one of the following values:
822 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
823 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
824 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
825 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
826 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
827 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
828 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
829 * @retval HAL status
830 */
HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID)831 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID)
832 {
833 HAL_StatusTypeDef status = HAL_OK;
834
835 /* Process locked */
836 __HAL_LOCK(hhcd);
837
838 /* Setup Legacy weak Callbacks */
839 if (hhcd->State == HAL_HCD_STATE_READY)
840 {
841 switch (CallbackID)
842 {
843 case HAL_HCD_SOF_CB_ID :
844 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
845 break;
846
847 case HAL_HCD_CONNECT_CB_ID :
848 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
849 break;
850
851 case HAL_HCD_DISCONNECT_CB_ID :
852 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
853 break;
854
855 case HAL_HCD_PORT_ENABLED_CB_ID :
856 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
857 break;
858
859 case HAL_HCD_PORT_DISABLED_CB_ID :
860 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
861 break;
862
863 case HAL_HCD_MSPINIT_CB_ID :
864 hhcd->MspInitCallback = HAL_HCD_MspInit;
865 break;
866
867 case HAL_HCD_MSPDEINIT_CB_ID :
868 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
869 break;
870
871 default :
872 /* Update the error code */
873 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
874
875 /* Return error status */
876 status = HAL_ERROR;
877 break;
878 }
879 }
880 else if (hhcd->State == HAL_HCD_STATE_RESET)
881 {
882 switch (CallbackID)
883 {
884 case HAL_HCD_MSPINIT_CB_ID :
885 hhcd->MspInitCallback = HAL_HCD_MspInit;
886 break;
887
888 case HAL_HCD_MSPDEINIT_CB_ID :
889 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
890 break;
891
892 default :
893 /* Update the error code */
894 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
895
896 /* Return error status */
897 status = HAL_ERROR;
898 break;
899 }
900 }
901 else
902 {
903 /* Update the error code */
904 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
905
906 /* Return error status */
907 status = HAL_ERROR;
908 }
909
910 /* Release Lock */
911 __HAL_UNLOCK(hhcd);
912 return status;
913 }
914
915 /**
916 * @brief Register USB HCD Host Channel Notify URB Change Callback
917 * To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
918 * @param hhcd HCD handle
919 * @param pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
920 * @retval HAL status
921 */
HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd,pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)922 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
923 pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
924 {
925 HAL_StatusTypeDef status = HAL_OK;
926
927 if (pCallback == NULL)
928 {
929 /* Update the error code */
930 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
931
932 return HAL_ERROR;
933 }
934
935 /* Process locked */
936 __HAL_LOCK(hhcd);
937
938 if (hhcd->State == HAL_HCD_STATE_READY)
939 {
940 hhcd->HC_NotifyURBChangeCallback = pCallback;
941 }
942 else
943 {
944 /* Update the error code */
945 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
946
947 /* Return error status */
948 status = HAL_ERROR;
949 }
950
951 /* Release Lock */
952 __HAL_UNLOCK(hhcd);
953
954 return status;
955 }
956
957 /**
958 * @brief Unregister the USB HCD Host Channel Notify URB Change Callback
959 * USB HCD Host Channel Notify URB Change Callback is redirected
960 * to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
961 * @param hhcd HCD handle
962 * @retval HAL status
963 */
HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd)964 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
965 {
966 HAL_StatusTypeDef status = HAL_OK;
967
968 /* Process locked */
969 __HAL_LOCK(hhcd);
970
971 if (hhcd->State == HAL_HCD_STATE_READY)
972 {
973 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
974 }
975 else
976 {
977 /* Update the error code */
978 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
979
980 /* Return error status */
981 status = HAL_ERROR;
982 }
983
984 /* Release Lock */
985 __HAL_UNLOCK(hhcd);
986
987 return status;
988 }
989 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
990
991 /**
992 * @}
993 */
994
995 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
996 * @brief Management functions
997 *
998 @verbatim
999 ===============================================================================
1000 ##### Peripheral Control functions #####
1001 ===============================================================================
1002 [..]
1003 This subsection provides a set of functions allowing to control the HCD data
1004 transfers.
1005
1006 @endverbatim
1007 * @{
1008 */
1009
1010 /**
1011 * @brief Start the host driver.
1012 * @param hhcd HCD handle
1013 * @retval HAL status
1014 */
HAL_HCD_Start(HCD_HandleTypeDef * hhcd)1015 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
1016 {
1017 __HAL_LOCK(hhcd);
1018 /* Enable port power */
1019 (void)USB_DriveVbus(hhcd->Instance, 1U);
1020
1021 /* Enable global interrupt */
1022 __HAL_HCD_ENABLE(hhcd);
1023 __HAL_UNLOCK(hhcd);
1024
1025 return HAL_OK;
1026 }
1027
1028 /**
1029 * @brief Stop the host driver.
1030 * @param hhcd HCD handle
1031 * @retval HAL status
1032 */
1033
HAL_HCD_Stop(HCD_HandleTypeDef * hhcd)1034 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
1035 {
1036 __HAL_LOCK(hhcd);
1037 (void)USB_StopHost(hhcd->Instance);
1038 __HAL_UNLOCK(hhcd);
1039
1040 return HAL_OK;
1041 }
1042
1043 /**
1044 * @brief Reset the host port.
1045 * @param hhcd HCD handle
1046 * @retval HAL status
1047 */
HAL_HCD_ResetPort(HCD_HandleTypeDef * hhcd)1048 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
1049 {
1050 return (USB_ResetPort(hhcd->Instance));
1051 }
1052
1053 /**
1054 * @}
1055 */
1056
1057 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
1058 * @brief Peripheral State functions
1059 *
1060 @verbatim
1061 ===============================================================================
1062 ##### Peripheral State functions #####
1063 ===============================================================================
1064 [..]
1065 This subsection permits to get in run-time the status of the peripheral
1066 and the data flow.
1067
1068 @endverbatim
1069 * @{
1070 */
1071
1072 /**
1073 * @brief Return the HCD handle state.
1074 * @param hhcd HCD handle
1075 * @retval HAL state
1076 */
HAL_HCD_GetState(HCD_HandleTypeDef const * hhcd)1077 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef const *hhcd)
1078 {
1079 return hhcd->State;
1080 }
1081
1082 /**
1083 * @brief Return URB state for a channel.
1084 * @param hhcd HCD handle
1085 * @param chnum Channel number.
1086 * This parameter can be a value from 1 to 15
1087 * @retval URB state.
1088 * This parameter can be one of these values:
1089 * URB_IDLE/
1090 * URB_DONE/
1091 * URB_NOTREADY/
1092 * URB_NYET/
1093 * URB_ERROR/
1094 * URB_STALL
1095 */
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1096 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1097 {
1098 return hhcd->hc[chnum].urb_state;
1099 }
1100
1101
1102 /**
1103 * @brief Return the last host transfer size.
1104 * @param hhcd HCD handle
1105 * @param chnum Channel number.
1106 * This parameter can be a value from 1 to 15
1107 * @retval last transfer size in byte
1108 */
HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1109 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1110 {
1111 return hhcd->hc[chnum].xfer_count;
1112 }
1113
1114 /**
1115 * @brief Return the Host Channel state.
1116 * @param hhcd HCD handle
1117 * @param chnum Channel number.
1118 * This parameter can be a value from 1 to 15
1119 * @retval Host channel state
1120 * This parameter can be one of these values:
1121 * HC_IDLE/
1122 * HC_XFRC/
1123 * HC_HALTED/
1124 * HC_NYET/
1125 * HC_NAK/
1126 * HC_STALL/
1127 * HC_XACTERR/
1128 * HC_BBLERR/
1129 * HC_DATATGLERR
1130 */
HAL_HCD_HC_GetState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1131 HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1132 {
1133 return hhcd->hc[chnum].state;
1134 }
1135
1136 /**
1137 * @brief Return the current Host frame number.
1138 * @param hhcd HCD handle
1139 * @retval Current Host frame number
1140 */
HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef * hhcd)1141 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
1142 {
1143 return (USB_GetCurrentFrame(hhcd->Instance));
1144 }
1145
1146 /**
1147 * @brief Return the Host enumeration speed.
1148 * @param hhcd HCD handle
1149 * @retval Enumeration speed
1150 */
HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef * hhcd)1151 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
1152 {
1153 return (USB_GetHostSpeed(hhcd->Instance));
1154 }
1155
1156 /**
1157 * @brief Set host channel Hub information.
1158 * @param hhcd HCD handle
1159 * @param ch_num Channel number.
1160 * This parameter can be a value from 1 to 15
1161 * @param addr Hub address
1162 * @param PortNbr Hub port number
1163 * @retval HAL status
1164 */
HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t addr,uint8_t PortNbr)1165 HAL_StatusTypeDef HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1166 uint8_t addr, uint8_t PortNbr)
1167 {
1168 hhcd->hc[ch_num].hub_addr = addr;
1169 hhcd->hc[ch_num].hub_port_nbr = PortNbr;
1170
1171 return HAL_OK;
1172 }
1173
1174
1175 /**
1176 * @brief Clear host channel hub information.
1177 * @param hhcd HCD handle
1178 * @param ch_num Channel number.
1179 * This parameter can be a value from 1 to 15
1180 * @retval HAL status
1181 */
HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num)1182 HAL_StatusTypeDef HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
1183 {
1184 hhcd->hc[ch_num].hub_addr = 0U;
1185 hhcd->hc[ch_num].hub_port_nbr = 0U;
1186
1187 return HAL_OK;
1188 }
1189 /**
1190 * @}
1191 */
1192
1193 /**
1194 * @}
1195 */
1196
1197 /** @addtogroup HCD_Private_Functions
1198 * @{
1199 */
1200 /**
1201 * @brief Handle Host Channel IN interrupt requests.
1202 * @param hhcd HCD handle
1203 * @param chnum Channel number.
1204 * This parameter can be a value from 1 to 15
1205 * @retval none
1206 */
HCD_HC_IN_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1207 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1208 {
1209 const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1210 uint32_t USBx_BASE = (uint32_t)USBx;
1211 uint32_t tmpreg;
1212
1213 if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
1214 {
1215 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
1216 hhcd->hc[chnum].state = HC_XACTERR;
1217 (void)USB_HC_Halt(hhcd->Instance, chnum);
1218 }
1219 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_BBERR))
1220 {
1221 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_BBERR);
1222 hhcd->hc[chnum].state = HC_BBLERR;
1223 (void)USB_HC_Halt(hhcd->Instance, chnum);
1224 }
1225 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
1226 {
1227 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
1228 hhcd->hc[chnum].state = HC_STALL;
1229 (void)USB_HC_Halt(hhcd->Instance, chnum);
1230 }
1231 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
1232 {
1233 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
1234 hhcd->hc[chnum].state = HC_DATATGLERR;
1235 (void)USB_HC_Halt(hhcd->Instance, chnum);
1236 }
1237 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
1238 {
1239 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
1240 hhcd->hc[chnum].state = HC_XACTERR;
1241 (void)USB_HC_Halt(hhcd->Instance, chnum);
1242 }
1243 else
1244 {
1245 /* ... */
1246 }
1247
1248 if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
1249 {
1250 (void)USB_HC_Halt(hhcd->Instance, chnum);
1251 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
1252 }
1253 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
1254 {
1255 hhcd->hc[chnum].state = HC_XFRC;
1256 hhcd->hc[chnum].ErrCnt = 0U;
1257 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
1258
1259 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1260 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1261 {
1262 (void)USB_HC_Halt(hhcd->Instance, chnum);
1263 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1264 }
1265 else if ((hhcd->hc[chnum].ep_type == EP_TYPE_INTR) ||
1266 (hhcd->hc[chnum].ep_type == EP_TYPE_ISOC))
1267 {
1268 USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
1269 hhcd->hc[chnum].urb_state = URB_DONE;
1270
1271 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1272 hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1273 #else
1274 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1275 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1276 }
1277 else
1278 {
1279 /* ... */
1280 }
1281
1282 if (hhcd->Init.dma_enable == 1U)
1283 {
1284 if ((((hhcd->hc[chnum].xfer_count + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet) & 1U) != 0U)
1285 {
1286 hhcd->hc[chnum].toggle_in ^= 1U;
1287 }
1288 }
1289 else
1290 {
1291 hhcd->hc[chnum].toggle_in ^= 1U;
1292 }
1293 }
1294 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
1295 {
1296 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1297 }
1298 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
1299 {
1300 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
1301
1302 if (hhcd->hc[chnum].state == HC_XFRC)
1303 {
1304 hhcd->hc[chnum].state = HC_HALTED;
1305 hhcd->hc[chnum].urb_state = URB_DONE;
1306 }
1307 else if (hhcd->hc[chnum].state == HC_STALL)
1308 {
1309 hhcd->hc[chnum].state = HC_HALTED;
1310 hhcd->hc[chnum].urb_state = URB_STALL;
1311 }
1312 else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
1313 (hhcd->hc[chnum].state == HC_DATATGLERR))
1314 {
1315 hhcd->hc[chnum].state = HC_HALTED;
1316 hhcd->hc[chnum].ErrCnt++;
1317 if (hhcd->hc[chnum].ErrCnt > 2U)
1318 {
1319 hhcd->hc[chnum].ErrCnt = 0U;
1320 hhcd->hc[chnum].urb_state = URB_ERROR;
1321 }
1322 else
1323 {
1324 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1325
1326 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1327 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1328 {
1329 /* re-activate the channel */
1330 tmpreg = USBx_HC(chnum)->HCCHAR;
1331 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1332 tmpreg |= USB_OTG_HCCHAR_CHENA;
1333 USBx_HC(chnum)->HCCHAR = tmpreg;
1334 }
1335 }
1336 }
1337 else if (hhcd->hc[chnum].state == HC_NYET)
1338 {
1339 hhcd->hc[chnum].state = HC_HALTED;
1340 }
1341 else if (hhcd->hc[chnum].state == HC_ACK)
1342 {
1343 hhcd->hc[chnum].state = HC_HALTED;
1344 }
1345 else if (hhcd->hc[chnum].state == HC_NAK)
1346 {
1347 hhcd->hc[chnum].state = HC_HALTED;
1348 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1349
1350 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1351 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1352 {
1353 /* re-activate the channel */
1354 tmpreg = USBx_HC(chnum)->HCCHAR;
1355 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1356 tmpreg |= USB_OTG_HCCHAR_CHENA;
1357 USBx_HC(chnum)->HCCHAR = tmpreg;
1358 }
1359 }
1360 else if (hhcd->hc[chnum].state == HC_BBLERR)
1361 {
1362 hhcd->hc[chnum].state = HC_HALTED;
1363 hhcd->hc[chnum].ErrCnt++;
1364 hhcd->hc[chnum].urb_state = URB_ERROR;
1365 }
1366 else
1367 {
1368 if (hhcd->hc[chnum].state == HC_HALTED)
1369 {
1370 return;
1371 }
1372 }
1373
1374 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1375 hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1376 #else
1377 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1378 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1379 }
1380 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
1381 {
1382 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
1383 hhcd->hc[chnum].state = HC_NYET;
1384 hhcd->hc[chnum].ErrCnt = 0U;
1385
1386 (void)USB_HC_Halt(hhcd->Instance, chnum);
1387 }
1388 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
1389 {
1390 if (hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
1391 {
1392 hhcd->hc[chnum].ErrCnt = 0U;
1393 hhcd->hc[chnum].state = HC_NAK;
1394 (void)USB_HC_Halt(hhcd->Instance, chnum);
1395 }
1396 else if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1397 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1398 {
1399 hhcd->hc[chnum].ErrCnt = 0U;
1400 hhcd->hc[chnum].state = HC_NAK;
1401 (void)USB_HC_Halt(hhcd->Instance, chnum);
1402 }
1403 else
1404 {
1405 /* ... */
1406 }
1407
1408 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1409 }
1410 else
1411 {
1412 /* ... */
1413 }
1414 }
1415
1416 /**
1417 * @brief Handle Host Channel OUT interrupt requests.
1418 * @param hhcd HCD handle
1419 * @param chnum Channel number.
1420 * This parameter can be a value from 1 to 15
1421 * @retval none
1422 */
HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1423 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1424 {
1425 const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1426 uint32_t USBx_BASE = (uint32_t)USBx;
1427 uint32_t tmpreg;
1428 uint32_t num_packets;
1429
1430 if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
1431 {
1432 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
1433 hhcd->hc[chnum].state = HC_XACTERR;
1434 (void)USB_HC_Halt(hhcd->Instance, chnum);
1435 }
1436 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
1437 {
1438 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1439 }
1440 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
1441 {
1442 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
1443 (void)USB_HC_Halt(hhcd->Instance, chnum);
1444 }
1445 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
1446 {
1447 hhcd->hc[chnum].ErrCnt = 0U;
1448
1449 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
1450 hhcd->hc[chnum].state = HC_XFRC;
1451 (void)USB_HC_Halt(hhcd->Instance, chnum);
1452 }
1453 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
1454 {
1455 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
1456 hhcd->hc[chnum].state = HC_STALL;
1457 (void)USB_HC_Halt(hhcd->Instance, chnum);
1458 }
1459 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
1460 {
1461 hhcd->hc[chnum].ErrCnt = 0U;
1462 hhcd->hc[chnum].state = HC_NAK;
1463
1464 (void)USB_HC_Halt(hhcd->Instance, chnum);
1465 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1466 }
1467 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
1468 {
1469 hhcd->hc[chnum].state = HC_XACTERR;
1470 (void)USB_HC_Halt(hhcd->Instance, chnum);
1471 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
1472 }
1473 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
1474 {
1475 hhcd->hc[chnum].state = HC_DATATGLERR;
1476 (void)USB_HC_Halt(hhcd->Instance, chnum);
1477 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
1478 }
1479 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
1480 {
1481 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
1482
1483 if (hhcd->hc[chnum].state == HC_XFRC)
1484 {
1485 hhcd->hc[chnum].state = HC_HALTED;
1486 hhcd->hc[chnum].urb_state = URB_DONE;
1487
1488 if ((hhcd->hc[chnum].ep_type == EP_TYPE_BULK) ||
1489 (hhcd->hc[chnum].ep_type == EP_TYPE_INTR))
1490 {
1491 if (hhcd->Init.dma_enable == 0U)
1492 {
1493 hhcd->hc[chnum].toggle_out ^= 1U;
1494 }
1495
1496 if ((hhcd->Init.dma_enable == 1U) && (hhcd->hc[chnum].xfer_len > 0U))
1497 {
1498 num_packets = (hhcd->hc[chnum].xfer_len + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet;
1499
1500 if ((num_packets & 1U) != 0U)
1501 {
1502 hhcd->hc[chnum].toggle_out ^= 1U;
1503 }
1504 }
1505 }
1506 }
1507 else if (hhcd->hc[chnum].state == HC_ACK)
1508 {
1509 hhcd->hc[chnum].state = HC_HALTED;
1510 }
1511 else if (hhcd->hc[chnum].state == HC_NAK)
1512 {
1513 hhcd->hc[chnum].state = HC_HALTED;
1514 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1515 }
1516 else if (hhcd->hc[chnum].state == HC_STALL)
1517 {
1518 hhcd->hc[chnum].state = HC_HALTED;
1519 hhcd->hc[chnum].urb_state = URB_STALL;
1520 }
1521 else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
1522 (hhcd->hc[chnum].state == HC_DATATGLERR))
1523 {
1524 hhcd->hc[chnum].state = HC_HALTED;
1525 hhcd->hc[chnum].ErrCnt++;
1526 if (hhcd->hc[chnum].ErrCnt > 2U)
1527 {
1528 hhcd->hc[chnum].ErrCnt = 0U;
1529 hhcd->hc[chnum].urb_state = URB_ERROR;
1530 }
1531 else
1532 {
1533 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1534
1535 /* re-activate the channel */
1536 tmpreg = USBx_HC(chnum)->HCCHAR;
1537 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1538 tmpreg |= USB_OTG_HCCHAR_CHENA;
1539 USBx_HC(chnum)->HCCHAR = tmpreg;
1540 }
1541 }
1542 else
1543 {
1544 return;
1545 }
1546
1547 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1548 hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1549 #else
1550 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1551 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1552 }
1553 else
1554 {
1555 return;
1556 }
1557 }
1558
1559 /**
1560 * @brief Handle Rx Queue Level interrupt requests.
1561 * @param hhcd HCD handle
1562 * @retval none
1563 */
HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef * hhcd)1564 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
1565 {
1566 const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1567 uint32_t USBx_BASE = (uint32_t)USBx;
1568 uint32_t pktsts;
1569 uint32_t pktcnt;
1570 uint32_t GrxstspReg;
1571 uint32_t xferSizePktCnt;
1572 uint32_t tmpreg;
1573 uint32_t chnum;
1574
1575 GrxstspReg = hhcd->Instance->GRXSTSP;
1576 chnum = GrxstspReg & USB_OTG_GRXSTSP_EPNUM;
1577 pktsts = (GrxstspReg & USB_OTG_GRXSTSP_PKTSTS) >> 17;
1578 pktcnt = (GrxstspReg & USB_OTG_GRXSTSP_BCNT) >> 4;
1579
1580 switch (pktsts)
1581 {
1582 case GRXSTS_PKTSTS_IN:
1583 /* Read the data into the host buffer. */
1584 if ((pktcnt > 0U) && (hhcd->hc[chnum].xfer_buff != (void *)0))
1585 {
1586 if ((hhcd->hc[chnum].xfer_count + pktcnt) <= hhcd->hc[chnum].xfer_len)
1587 {
1588 (void)USB_ReadPacket(hhcd->Instance,
1589 hhcd->hc[chnum].xfer_buff, (uint16_t)pktcnt);
1590
1591 /* manage multiple Xfer */
1592 hhcd->hc[chnum].xfer_buff += pktcnt;
1593 hhcd->hc[chnum].xfer_count += pktcnt;
1594
1595 /* get transfer size packet count */
1596 xferSizePktCnt = (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19;
1597
1598 if ((hhcd->hc[chnum].max_packet == pktcnt) && (xferSizePktCnt > 0U))
1599 {
1600 /* re-activate the channel when more packets are expected */
1601 tmpreg = USBx_HC(chnum)->HCCHAR;
1602 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1603 tmpreg |= USB_OTG_HCCHAR_CHENA;
1604 USBx_HC(chnum)->HCCHAR = tmpreg;
1605 hhcd->hc[chnum].toggle_in ^= 1U;
1606 }
1607 }
1608 else
1609 {
1610 hhcd->hc[chnum].urb_state = URB_ERROR;
1611 }
1612 }
1613 break;
1614
1615 case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
1616 break;
1617
1618 case GRXSTS_PKTSTS_IN_XFER_COMP:
1619 case GRXSTS_PKTSTS_CH_HALTED:
1620 default:
1621 break;
1622 }
1623 }
1624
1625 /**
1626 * @brief Handle Host Port interrupt requests.
1627 * @param hhcd HCD handle
1628 * @retval None
1629 */
HCD_Port_IRQHandler(HCD_HandleTypeDef * hhcd)1630 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
1631 {
1632 const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1633 uint32_t USBx_BASE = (uint32_t)USBx;
1634 __IO uint32_t hprt0;
1635 __IO uint32_t hprt0_dup;
1636
1637 /* Handle Host Port Interrupts */
1638 hprt0 = USBx_HPRT0;
1639 hprt0_dup = USBx_HPRT0;
1640
1641 hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
1642 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
1643
1644 /* Check whether Port Connect detected */
1645 if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
1646 {
1647 if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
1648 {
1649 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1650 hhcd->ConnectCallback(hhcd);
1651 #else
1652 HAL_HCD_Connect_Callback(hhcd);
1653 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1654 }
1655 hprt0_dup |= USB_OTG_HPRT_PCDET;
1656 }
1657
1658 /* Check whether Port Enable Changed */
1659 if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
1660 {
1661 hprt0_dup |= USB_OTG_HPRT_PENCHNG;
1662
1663 if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
1664 {
1665 if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
1666 {
1667 if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
1668 {
1669 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
1670 }
1671 else
1672 {
1673 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
1674 }
1675 }
1676 else
1677 {
1678 if (hhcd->Init.speed == HCD_SPEED_FULL)
1679 {
1680 USBx_HOST->HFIR = HFIR_60_MHZ;
1681 }
1682 }
1683 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1684 hhcd->PortEnabledCallback(hhcd);
1685 #else
1686 HAL_HCD_PortEnabled_Callback(hhcd);
1687 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1688
1689 }
1690 else
1691 {
1692 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1693 hhcd->PortDisabledCallback(hhcd);
1694 #else
1695 HAL_HCD_PortDisabled_Callback(hhcd);
1696 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1697 }
1698 }
1699
1700 /* Check for an overcurrent */
1701 if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
1702 {
1703 hprt0_dup |= USB_OTG_HPRT_POCCHNG;
1704 }
1705
1706 /* Clear Port Interrupts */
1707 USBx_HPRT0 = hprt0_dup;
1708 }
1709
1710 /**
1711 * @}
1712 */
1713
1714 /**
1715 * @}
1716 */
1717
1718 #endif /* defined (USB_OTG_FS) */
1719 #endif /* HAL_HCD_MODULE_ENABLED */
1720
1721 /**
1722 * @}
1723 */
1724
1725 /**
1726 * @}
1727 */
1728