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