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