1 /**
2 ******************************************************************************
3 * @file stm32u5xx_hal_hcd.c
4 * @author MCD Application Team
5 * @brief HCD HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the USB Peripheral Controller:
8 * + Initialization and de-initialization functions
9 * + IO operation functions
10 * + Peripheral Control functions
11 * + Peripheral State functions
12 *
13 ******************************************************************************
14 * @attention
15 *
16 * Copyright (c) 2021 STMicroelectronics.
17 * All rights reserved.
18 *
19 * This software is licensed under terms that can be found in the LICENSE file
20 * in the root directory of this software component.
21 * If no LICENSE file comes with this software, it is provided AS-IS.
22 *
23 ******************************************************************************
24 @verbatim
25 ==============================================================================
26 ##### How to use this driver #####
27 ==============================================================================
28 [..]
29 (#)Declare a HCD_HandleTypeDef handle structure, for example:
30 HCD_HandleTypeDef hhcd;
31
32 (#)Fill parameters of Init structure in HCD handle
33
34 (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
35
36 (#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
37 (##) Enable the HCD/USB Low Level interface clock using the following macros
38 (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
39 (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)
40 (+++) __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); (For High Speed Mode)
41
42 (+++) __HAL_RCC_USB_CLK_ENABLE();
43 (##) Initialize the related GPIO clocks
44 (##) Configure HCD pin-out
45 (##) Configure HCD NVIC interrupt
46
47 (#)Associate the Upper USB Host stack to the HAL HCD Driver:
48 (##) hhcd.pData = phost;
49
50 (#)Enable HCD transmission and reception:
51 (##) HAL_HCD_Start();
52
53 @endverbatim
54 ******************************************************************************
55 */
56
57 /* Includes ------------------------------------------------------------------*/
58 #include "stm32u5xx_hal.h"
59
60 /** @addtogroup STM32U5xx_HAL_Driver
61 * @{
62 */
63
64 #ifdef HAL_HCD_MODULE_ENABLED
65 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
66
67 /** @defgroup HCD HCD
68 * @brief HCD HAL module driver
69 * @{
70 */
71
72 /* Private typedef -----------------------------------------------------------*/
73 /* Private define ------------------------------------------------------------*/
74 /* Private macro -------------------------------------------------------------*/
75 /* Private variables ---------------------------------------------------------*/
76 /* Private function prototypes -----------------------------------------------*/
77 /** @defgroup HCD_Private_Functions HCD Private Functions
78 * @{
79 */
80 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
81 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
82 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd);
83 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
84 /**
85 * @}
86 */
87
88 /* Exported functions --------------------------------------------------------*/
89 /** @defgroup HCD_Exported_Functions HCD Exported Functions
90 * @{
91 */
92
93 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
94 * @brief Initialization and Configuration functions
95 *
96 @verbatim
97 ===============================================================================
98 ##### Initialization and de-initialization functions #####
99 ===============================================================================
100 [..] This section provides functions allowing to:
101
102 @endverbatim
103 * @{
104 */
105
106 /**
107 * @brief Initialize the host driver.
108 * @param hhcd HCD handle
109 * @retval HAL status
110 */
HAL_HCD_Init(HCD_HandleTypeDef * hhcd)111 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
112 {
113 #if defined (STM32U575xx) || defined (STM32U585xx)
114 USB_OTG_GlobalTypeDef *USBx;
115 #endif /* defined (STM32U575xx) || defined (STM32U585xx) */
116
117 /* Check the HCD handle allocation */
118 if (hhcd == NULL)
119 {
120 return HAL_ERROR;
121 }
122
123 /* Check the parameters */
124 assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
125
126 #if defined (STM32U575xx) || defined (STM32U585xx)
127 USBx = hhcd->Instance;
128 #endif /* defined (STM32U575xx) || defined (STM32U585xx) */
129
130 if (hhcd->State == HAL_HCD_STATE_RESET)
131 {
132 /* Allocate lock resource and initialize it */
133 hhcd->Lock = HAL_UNLOCKED;
134
135 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
136 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
137 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
138 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
139 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
140 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
141 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;
142
143 if (hhcd->MspInitCallback == NULL)
144 {
145 hhcd->MspInitCallback = HAL_HCD_MspInit;
146 }
147
148 /* Init the low level hardware */
149 hhcd->MspInitCallback(hhcd);
150 #else
151 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
152 HAL_HCD_MspInit(hhcd);
153 #endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
154 }
155
156 hhcd->State = HAL_HCD_STATE_BUSY;
157 #if defined (STM32U575xx) || defined (STM32U585xx)
158 /* Disable DMA mode for FS instance */
159 if ((USBx->CID & (0x1U << 14)) == 0U)
160 {
161 hhcd->Init.dma_enable = 0U;
162 }
163 #endif /* defined (STM32U575xx) || defined (STM32U585xx) */
164 /* Disable the Interrupts */
165 __HAL_HCD_DISABLE(hhcd);
166
167 /* Init the Core (common init.) */
168 (void)USB_CoreInit(hhcd->Instance, hhcd->Init);
169
170 /* Force Host Mode*/
171 (void)USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE);
172
173 /* Init Host */
174 (void)USB_HostInit(hhcd->Instance, hhcd->Init);
175
176 hhcd->State = HAL_HCD_STATE_READY;
177
178 return HAL_OK;
179 }
180
181 /**
182 * @brief Initialize a host channel.
183 * @param hhcd HCD handle
184 * @param ch_num Channel number.
185 * This parameter can be a value from 1 to 15
186 * @param epnum Endpoint number.
187 * This parameter can be a value from 1 to 15
188 * @param dev_address Current device address
189 * This parameter can be a value from 0 to 255
190 * @param speed Current device speed.
191 * This parameter can be one of these values:
192 * HCD_DEVICE_SPEED_HIGH: High speed mode,
193 * HCD_DEVICE_SPEED_FULL: Full speed mode,
194 * HCD_DEVICE_SPEED_LOW: Low speed mode
195 * @param ep_type Endpoint Type.
196 * This parameter can be one of these values:
197 * EP_TYPE_CTRL: Control type,
198 * EP_TYPE_ISOC: Isochronous type,
199 * EP_TYPE_BULK: Bulk type,
200 * EP_TYPE_INTR: Interrupt type
201 * @param mps Max Packet Size.
202 * This parameter can be a value from 0 to32K
203 * @retval HAL status
204 */
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)205 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t epnum,
206 uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps)
207 {
208 HAL_StatusTypeDef status;
209 uint32_t HostCoreSpeed;
210 uint32_t HCcharMps = mps;
211
212 __HAL_LOCK(hhcd);
213 hhcd->hc[ch_num].do_ping = 0U;
214 hhcd->hc[ch_num].dev_addr = dev_address;
215 hhcd->hc[ch_num].ch_num = ch_num;
216 hhcd->hc[ch_num].ep_type = ep_type;
217 hhcd->hc[ch_num].ep_num = epnum & 0x7FU;
218
219 (void)HAL_HCD_HC_ClearHubInfo(hhcd, ch_num);
220
221 if ((epnum & 0x80U) == 0x80U)
222 {
223 hhcd->hc[ch_num].ep_is_in = 1U;
224 }
225 else
226 {
227 hhcd->hc[ch_num].ep_is_in = 0U;
228 }
229
230 HostCoreSpeed = USB_GetHostSpeed(hhcd->Instance);
231
232 if (ep_type == EP_TYPE_ISOC)
233 {
234 /* FS device plugged to HS HUB */
235 if ((speed == HCD_DEVICE_SPEED_FULL) && (HostCoreSpeed == HPRT0_PRTSPD_HIGH_SPEED))
236 {
237 if (HCcharMps > ISO_SPLT_MPS)
238 {
239 /* ISO Max Packet Size for Split mode */
240 HCcharMps = ISO_SPLT_MPS;
241 }
242 }
243 }
244
245 hhcd->hc[ch_num].speed = speed;
246 hhcd->hc[ch_num].max_packet = (uint16_t)HCcharMps;
247
248 status = USB_HC_Init(hhcd->Instance, ch_num, epnum,
249 dev_address, speed, ep_type, (uint16_t)HCcharMps);
250
251 __HAL_UNLOCK(hhcd);
252
253 return status;
254 }
255
256 /**
257 * @brief Halt a host channel.
258 * @param hhcd HCD handle
259 * @param ch_num Channel number.
260 * This parameter can be a value from 1 to 15
261 * @retval HAL status
262 */
HAL_HCD_HC_Halt(HCD_HandleTypeDef * hhcd,uint8_t ch_num)263 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
264 {
265 HAL_StatusTypeDef status = HAL_OK;
266
267 __HAL_LOCK(hhcd);
268 (void)USB_HC_Halt(hhcd->Instance, ch_num);
269 __HAL_UNLOCK(hhcd);
270
271 return status;
272 }
273
274 /**
275 * @brief DeInitialize the host driver.
276 * @param hhcd HCD handle
277 * @retval HAL status
278 */
HAL_HCD_DeInit(HCD_HandleTypeDef * hhcd)279 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
280 {
281 /* Check the HCD handle allocation */
282 if (hhcd == NULL)
283 {
284 return HAL_ERROR;
285 }
286
287 hhcd->State = HAL_HCD_STATE_BUSY;
288
289 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
290 if (hhcd->MspDeInitCallback == NULL)
291 {
292 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */
293 }
294
295 /* DeInit the low level hardware */
296 hhcd->MspDeInitCallback(hhcd);
297 #else
298 /* DeInit the low level hardware: CLOCK, NVIC.*/
299 HAL_HCD_MspDeInit(hhcd);
300 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
301
302 __HAL_HCD_DISABLE(hhcd);
303
304 hhcd->State = HAL_HCD_STATE_RESET;
305
306 return HAL_OK;
307 }
308
309 /**
310 * @brief Initialize the HCD MSP.
311 * @param hhcd HCD handle
312 * @retval None
313 */
HAL_HCD_MspInit(HCD_HandleTypeDef * hhcd)314 __weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
315 {
316 /* Prevent unused argument(s) compilation warning */
317 UNUSED(hhcd);
318
319 /* NOTE : This function should not be modified, when the callback is needed,
320 the HAL_HCD_MspInit could be implemented in the user file
321 */
322 }
323
324 /**
325 * @brief DeInitialize the HCD MSP.
326 * @param hhcd HCD handle
327 * @retval None
328 */
HAL_HCD_MspDeInit(HCD_HandleTypeDef * hhcd)329 __weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
330 {
331 /* Prevent unused argument(s) compilation warning */
332 UNUSED(hhcd);
333
334 /* NOTE : This function should not be modified, when the callback is needed,
335 the HAL_HCD_MspDeInit could be implemented in the user file
336 */
337 }
338
339 /**
340 * @}
341 */
342
343 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
344 * @brief HCD IO operation functions
345 *
346 @verbatim
347 ===============================================================================
348 ##### IO operation functions #####
349 ===============================================================================
350 [..] This subsection provides a set of functions allowing to manage the USB Host Data
351 Transfer
352
353 @endverbatim
354 * @{
355 */
356
357 /**
358 * @brief Submit a new URB for processing.
359 * @param hhcd HCD handle
360 * @param ch_num Channel number.
361 * This parameter can be a value from 1 to 15
362 * @param direction Channel number.
363 * This parameter can be one of these values:
364 * 0 : Output / 1 : Input
365 * @param ep_type Endpoint Type.
366 * This parameter can be one of these values:
367 * EP_TYPE_CTRL: Control type/
368 * EP_TYPE_ISOC: Isochronous type/
369 * EP_TYPE_BULK: Bulk type/
370 * EP_TYPE_INTR: Interrupt type/
371 * @param token Endpoint Type.
372 * This parameter can be one of these values:
373 * 0: HC_PID_SETUP / 1: HC_PID_DATA1
374 * @param pbuff pointer to URB data
375 * @param length Length of URB data
376 * @param do_ping activate do ping protocol (for high speed only).
377 * This parameter can be one of these values:
378 * 0 : do ping inactive / 1 : do ping active
379 * @retval HAL status
380 */
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)381 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
382 uint8_t ch_num,
383 uint8_t direction,
384 uint8_t ep_type,
385 uint8_t token,
386 uint8_t *pbuff,
387 uint16_t length,
388 uint8_t do_ping)
389 {
390 hhcd->hc[ch_num].ep_is_in = direction;
391 hhcd->hc[ch_num].ep_type = ep_type;
392
393 if (token == 0U)
394 {
395 hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
396 hhcd->hc[ch_num].do_ping = do_ping;
397 }
398 else
399 {
400 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
401 }
402
403 /* Manage Data Toggle */
404 switch (ep_type)
405 {
406 case EP_TYPE_CTRL:
407 if (token == 1U) /* send data */
408 {
409 if (direction == 0U)
410 {
411 if (length == 0U)
412 {
413 /* For Status OUT stage, Length == 0U, Status Out PID = 1 */
414 hhcd->hc[ch_num].toggle_out = 1U;
415 }
416
417 /* Set the Data Toggle bit as per the Flag */
418 if (hhcd->hc[ch_num].toggle_out == 0U)
419 {
420 /* Put the PID 0 */
421 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
422 }
423 else
424 {
425 /* Put the PID 1 */
426 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
427 }
428 }
429 else
430 {
431 if (hhcd->hc[ch_num].do_ssplit == 1U)
432 {
433 if (hhcd->hc[ch_num].toggle_in == 0U)
434 {
435 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
436 }
437 else
438 {
439 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
440 }
441 }
442 }
443 }
444 break;
445
446 case EP_TYPE_BULK:
447 if (direction == 0U)
448 {
449 /* Set the Data Toggle bit as per the Flag */
450 if (hhcd->hc[ch_num].toggle_out == 0U)
451 {
452 /* Put the PID 0 */
453 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
454 }
455 else
456 {
457 /* Put the PID 1 */
458 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
459 }
460 }
461 else
462 {
463 if (hhcd->hc[ch_num].toggle_in == 0U)
464 {
465 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
466 }
467 else
468 {
469 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
470 }
471 }
472
473 break;
474 case EP_TYPE_INTR:
475 if (direction == 0U)
476 {
477 /* Set the Data Toggle bit as per the Flag */
478 if (hhcd->hc[ch_num].toggle_out == 0U)
479 {
480 /* Put the PID 0 */
481 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
482 }
483 else
484 {
485 /* Put the PID 1 */
486 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
487 }
488 }
489 else
490 {
491 if (hhcd->hc[ch_num].toggle_in == 0U)
492 {
493 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
494 }
495 else
496 {
497 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
498 }
499 }
500 break;
501
502 case EP_TYPE_ISOC:
503 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
504 break;
505
506 default:
507 break;
508 }
509
510 hhcd->hc[ch_num].xfer_buff = pbuff;
511 hhcd->hc[ch_num].xfer_len = length;
512 hhcd->hc[ch_num].urb_state = URB_IDLE;
513 hhcd->hc[ch_num].xfer_count = 0U;
514 hhcd->hc[ch_num].ch_num = ch_num;
515 hhcd->hc[ch_num].state = HC_IDLE;
516
517 return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num], (uint8_t)hhcd->Init.dma_enable);
518 }
519
520 /**
521 * @brief Handle HCD interrupt request.
522 * @param hhcd HCD handle
523 * @retval None
524 */
HAL_HCD_IRQHandler(HCD_HandleTypeDef * hhcd)525 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
526 {
527 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
528 uint32_t USBx_BASE = (uint32_t)USBx;
529 uint32_t i;
530 uint32_t interrupt;
531
532 /* Ensure that we are in device mode */
533 if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
534 {
535 /* Avoid spurious interrupt */
536 if (__HAL_HCD_IS_INVALID_INTERRUPT(hhcd))
537 {
538 return;
539 }
540
541 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
542 {
543 /* Incorrect mode, acknowledge the interrupt */
544 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
545 }
546
547 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
548 {
549 /* Incorrect mode, acknowledge the interrupt */
550 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
551 }
552
553 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
554 {
555 /* Incorrect mode, acknowledge the interrupt */
556 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
557 }
558
559 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
560 {
561 /* Incorrect mode, acknowledge the interrupt */
562 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
563 }
564
565 /* Handle Host Disconnect Interrupts */
566 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
567 {
568 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
569
570 if ((USBx_HPRT0 & USB_OTG_HPRT_PCSTS) == 0U)
571 {
572 /* Flush USB Fifo */
573 (void)USB_FlushTxFifo(USBx, 0x10U);
574 (void)USB_FlushRxFifo(USBx);
575
576 if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
577 {
578 /* Restore FS Clock */
579 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
580 }
581
582 /* Handle Host Port Disconnect Interrupt */
583 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
584 hhcd->DisconnectCallback(hhcd);
585 #else
586 HAL_HCD_Disconnect_Callback(hhcd);
587 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
588 }
589 }
590
591 /* Handle Host Port Interrupts */
592 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
593 {
594 HCD_Port_IRQHandler(hhcd);
595 }
596
597 /* Handle Host SOF Interrupt */
598 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
599 {
600 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
601 hhcd->SOFCallback(hhcd);
602 #else
603 HAL_HCD_SOF_Callback(hhcd);
604 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
605
606 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
607 }
608
609 /* Handle Host channel Interrupt */
610 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
611 {
612 interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
613 for (i = 0U; i < hhcd->Init.Host_channels; i++)
614 {
615 if ((interrupt & (1UL << (i & 0xFU))) != 0U)
616 {
617 if ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR)
618 {
619 HCD_HC_IN_IRQHandler(hhcd, (uint8_t)i);
620 }
621 else
622 {
623 HCD_HC_OUT_IRQHandler(hhcd, (uint8_t)i);
624 }
625 }
626 }
627 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
628 }
629
630 /* Handle Rx Queue Level Interrupts */
631 if ((__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) != 0U)
632 {
633 USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
634
635 HCD_RXQLVL_IRQHandler(hhcd);
636
637 USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
638 }
639 }
640 }
641
642
643 /**
644 * @brief SOF callback.
645 * @param hhcd HCD handle
646 * @retval None
647 */
HAL_HCD_SOF_Callback(HCD_HandleTypeDef * hhcd)648 __weak void HAL_HCD_SOF_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_SOF_Callback could be implemented in the user file
655 */
656 }
657
658 /**
659 * @brief Connection Event callback.
660 * @param hhcd HCD handle
661 * @retval None
662 */
HAL_HCD_Connect_Callback(HCD_HandleTypeDef * hhcd)663 __weak void HAL_HCD_Connect_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_Connect_Callback could be implemented in the user file
670 */
671 }
672
673 /**
674 * @brief Disconnection Event callback.
675 * @param hhcd HCD handle
676 * @retval None
677 */
HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef * hhcd)678 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
679 {
680 /* Prevent unused argument(s) compilation warning */
681 UNUSED(hhcd);
682
683 /* NOTE : This function should not be modified, when the callback is needed,
684 the HAL_HCD_Disconnect_Callback could be implemented in the user file
685 */
686 }
687
688 /**
689 * @brief Port Enabled Event callback.
690 * @param hhcd HCD handle
691 * @retval None
692 */
HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef * hhcd)693 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
694 {
695 /* Prevent unused argument(s) compilation warning */
696 UNUSED(hhcd);
697
698 /* NOTE : This function should not be modified, when the callback is needed,
699 the HAL_HCD_Disconnect_Callback could be implemented in the user file
700 */
701 }
702
703 /**
704 * @brief Port Disabled Event callback.
705 * @param hhcd HCD handle
706 * @retval None
707 */
HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef * hhcd)708 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
709 {
710 /* Prevent unused argument(s) compilation warning */
711 UNUSED(hhcd);
712
713 /* NOTE : This function should not be modified, when the callback is needed,
714 the HAL_HCD_Disconnect_Callback could be implemented in the user file
715 */
716 }
717
718 /**
719 * @brief Notify URB state change callback.
720 * @param hhcd HCD handle
721 * @param chnum Channel number.
722 * This parameter can be a value from 1 to 15
723 * @param urb_state:
724 * This parameter can be one of these values:
725 * URB_IDLE/
726 * URB_DONE/
727 * URB_NOTREADY/
728 * URB_NYET/
729 * URB_ERROR/
730 * URB_STALL/
731 * @retval None
732 */
HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef * hhcd,uint8_t chnum,HCD_URBStateTypeDef urb_state)733 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
734 {
735 /* Prevent unused argument(s) compilation warning */
736 UNUSED(hhcd);
737 UNUSED(chnum);
738 UNUSED(urb_state);
739
740 /* NOTE : This function should not be modified, when the callback is needed,
741 the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
742 */
743 }
744
745 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
746 /**
747 * @brief Register a User USB HCD Callback
748 * To be used instead of the weak predefined callback
749 * @param hhcd USB HCD handle
750 * @param CallbackID ID of the callback to be registered
751 * This parameter can be one of the following values:
752 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
753 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
754 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
755 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
756 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
757 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
758 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
759 * @param pCallback pointer to the Callback function
760 * @retval HAL status
761 */
HAL_HCD_RegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID,pHCD_CallbackTypeDef pCallback)762 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
763 HAL_HCD_CallbackIDTypeDef CallbackID,
764 pHCD_CallbackTypeDef pCallback)
765 {
766 HAL_StatusTypeDef status = HAL_OK;
767
768 if (pCallback == NULL)
769 {
770 /* Update the error code */
771 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
772 return HAL_ERROR;
773 }
774 /* Process locked */
775 __HAL_LOCK(hhcd);
776
777 if (hhcd->State == HAL_HCD_STATE_READY)
778 {
779 switch (CallbackID)
780 {
781 case HAL_HCD_SOF_CB_ID :
782 hhcd->SOFCallback = pCallback;
783 break;
784
785 case HAL_HCD_CONNECT_CB_ID :
786 hhcd->ConnectCallback = pCallback;
787 break;
788
789 case HAL_HCD_DISCONNECT_CB_ID :
790 hhcd->DisconnectCallback = pCallback;
791 break;
792
793 case HAL_HCD_PORT_ENABLED_CB_ID :
794 hhcd->PortEnabledCallback = pCallback;
795 break;
796
797 case HAL_HCD_PORT_DISABLED_CB_ID :
798 hhcd->PortDisabledCallback = pCallback;
799 break;
800
801 case HAL_HCD_MSPINIT_CB_ID :
802 hhcd->MspInitCallback = pCallback;
803 break;
804
805 case HAL_HCD_MSPDEINIT_CB_ID :
806 hhcd->MspDeInitCallback = pCallback;
807 break;
808
809 default :
810 /* Update the error code */
811 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
812 /* Return error status */
813 status = HAL_ERROR;
814 break;
815 }
816 }
817 else if (hhcd->State == HAL_HCD_STATE_RESET)
818 {
819 switch (CallbackID)
820 {
821 case HAL_HCD_MSPINIT_CB_ID :
822 hhcd->MspInitCallback = pCallback;
823 break;
824
825 case HAL_HCD_MSPDEINIT_CB_ID :
826 hhcd->MspDeInitCallback = pCallback;
827 break;
828
829 default :
830 /* Update the error code */
831 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
832 /* Return error status */
833 status = HAL_ERROR;
834 break;
835 }
836 }
837 else
838 {
839 /* Update the error code */
840 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
841 /* Return error status */
842 status = HAL_ERROR;
843 }
844
845 /* Release Lock */
846 __HAL_UNLOCK(hhcd);
847 return status;
848 }
849
850 /**
851 * @brief Unregister an USB HCD Callback
852 * USB HCD callback is redirected to the weak predefined callback
853 * @param hhcd USB HCD handle
854 * @param CallbackID ID of the callback to be unregistered
855 * This parameter can be one of the following values:
856 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
857 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
858 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
859 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
860 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
861 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
862 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
863 * @retval HAL status
864 */
HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID)865 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID)
866 {
867 HAL_StatusTypeDef status = HAL_OK;
868
869 /* Process locked */
870 __HAL_LOCK(hhcd);
871
872 /* Setup Legacy weak Callbacks */
873 if (hhcd->State == HAL_HCD_STATE_READY)
874 {
875 switch (CallbackID)
876 {
877 case HAL_HCD_SOF_CB_ID :
878 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
879 break;
880
881 case HAL_HCD_CONNECT_CB_ID :
882 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
883 break;
884
885 case HAL_HCD_DISCONNECT_CB_ID :
886 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
887 break;
888
889 case HAL_HCD_PORT_ENABLED_CB_ID :
890 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
891 break;
892
893 case HAL_HCD_PORT_DISABLED_CB_ID :
894 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
895 break;
896
897 case HAL_HCD_MSPINIT_CB_ID :
898 hhcd->MspInitCallback = HAL_HCD_MspInit;
899 break;
900
901 case HAL_HCD_MSPDEINIT_CB_ID :
902 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
903 break;
904
905 default :
906 /* Update the error code */
907 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
908
909 /* Return error status */
910 status = HAL_ERROR;
911 break;
912 }
913 }
914 else if (hhcd->State == HAL_HCD_STATE_RESET)
915 {
916 switch (CallbackID)
917 {
918 case HAL_HCD_MSPINIT_CB_ID :
919 hhcd->MspInitCallback = HAL_HCD_MspInit;
920 break;
921
922 case HAL_HCD_MSPDEINIT_CB_ID :
923 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
924 break;
925
926 default :
927 /* Update the error code */
928 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
929
930 /* Return error status */
931 status = HAL_ERROR;
932 break;
933 }
934 }
935 else
936 {
937 /* Update the error code */
938 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
939
940 /* Return error status */
941 status = HAL_ERROR;
942 }
943
944 /* Release Lock */
945 __HAL_UNLOCK(hhcd);
946 return status;
947 }
948
949 /**
950 * @brief Register USB HCD Host Channel Notify URB Change Callback
951 * To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
952 * @param hhcd HCD handle
953 * @param pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
954 * @retval HAL status
955 */
HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd,pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)956 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
957 pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
958 {
959 HAL_StatusTypeDef status = HAL_OK;
960
961 if (pCallback == NULL)
962 {
963 /* Update the error code */
964 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
965
966 return HAL_ERROR;
967 }
968
969 /* Process locked */
970 __HAL_LOCK(hhcd);
971
972 if (hhcd->State == HAL_HCD_STATE_READY)
973 {
974 hhcd->HC_NotifyURBChangeCallback = pCallback;
975 }
976 else
977 {
978 /* Update the error code */
979 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
980
981 /* Return error status */
982 status = HAL_ERROR;
983 }
984
985 /* Release Lock */
986 __HAL_UNLOCK(hhcd);
987
988 return status;
989 }
990
991 /**
992 * @brief Unregister the USB HCD Host Channel Notify URB Change Callback
993 * USB HCD Host Channel Notify URB Change Callback is redirected
994 * to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
995 * @param hhcd HCD handle
996 * @retval HAL status
997 */
HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd)998 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
999 {
1000 HAL_StatusTypeDef status = HAL_OK;
1001
1002 /* Process locked */
1003 __HAL_LOCK(hhcd);
1004
1005 if (hhcd->State == HAL_HCD_STATE_READY)
1006 {
1007 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
1008 }
1009 else
1010 {
1011 /* Update the error code */
1012 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1013
1014 /* Return error status */
1015 status = HAL_ERROR;
1016 }
1017
1018 /* Release Lock */
1019 __HAL_UNLOCK(hhcd);
1020
1021 return status;
1022 }
1023 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1024
1025 /**
1026 * @}
1027 */
1028
1029 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
1030 * @brief Management functions
1031 *
1032 @verbatim
1033 ===============================================================================
1034 ##### Peripheral Control functions #####
1035 ===============================================================================
1036 [..]
1037 This subsection provides a set of functions allowing to control the HCD data
1038 transfers.
1039
1040 @endverbatim
1041 * @{
1042 */
1043
1044 /**
1045 * @brief Start the host driver.
1046 * @param hhcd HCD handle
1047 * @retval HAL status
1048 */
HAL_HCD_Start(HCD_HandleTypeDef * hhcd)1049 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
1050 {
1051 __HAL_LOCK(hhcd);
1052 /* Enable port power */
1053 (void)USB_DriveVbus(hhcd->Instance, 1U);
1054
1055 /* Enable global interrupt */
1056 __HAL_HCD_ENABLE(hhcd);
1057 __HAL_UNLOCK(hhcd);
1058
1059 return HAL_OK;
1060 }
1061
1062 /**
1063 * @brief Stop the host driver.
1064 * @param hhcd HCD handle
1065 * @retval HAL status
1066 */
1067
HAL_HCD_Stop(HCD_HandleTypeDef * hhcd)1068 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
1069 {
1070 __HAL_LOCK(hhcd);
1071 (void)USB_StopHost(hhcd->Instance);
1072 __HAL_UNLOCK(hhcd);
1073
1074 return HAL_OK;
1075 }
1076
1077 /**
1078 * @brief Reset the host port.
1079 * @param hhcd HCD handle
1080 * @retval HAL status
1081 */
HAL_HCD_ResetPort(HCD_HandleTypeDef * hhcd)1082 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
1083 {
1084 return (USB_ResetPort(hhcd->Instance));
1085 }
1086
1087 /**
1088 * @}
1089 */
1090
1091 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
1092 * @brief Peripheral State functions
1093 *
1094 @verbatim
1095 ===============================================================================
1096 ##### Peripheral State functions #####
1097 ===============================================================================
1098 [..]
1099 This subsection permits to get in run-time the status of the peripheral
1100 and the data flow.
1101
1102 @endverbatim
1103 * @{
1104 */
1105
1106 /**
1107 * @brief Return the HCD handle state.
1108 * @param hhcd HCD handle
1109 * @retval HAL state
1110 */
HAL_HCD_GetState(HCD_HandleTypeDef const * hhcd)1111 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef const *hhcd)
1112 {
1113 return hhcd->State;
1114 }
1115
1116 /**
1117 * @brief Return URB state for a channel.
1118 * @param hhcd HCD handle
1119 * @param chnum Channel number.
1120 * This parameter can be a value from 1 to 15
1121 * @retval URB state.
1122 * This parameter can be one of these values:
1123 * URB_IDLE/
1124 * URB_DONE/
1125 * URB_NOTREADY/
1126 * URB_NYET/
1127 * URB_ERROR/
1128 * URB_STALL
1129 */
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1130 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1131 {
1132 return hhcd->hc[chnum].urb_state;
1133 }
1134
1135
1136 /**
1137 * @brief Return the last host transfer size.
1138 * @param hhcd HCD handle
1139 * @param chnum Channel number.
1140 * This parameter can be a value from 1 to 15
1141 * @retval last transfer size in byte
1142 */
HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1143 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1144 {
1145 return hhcd->hc[chnum].xfer_count;
1146 }
1147
1148 /**
1149 * @brief Return the Host Channel state.
1150 * @param hhcd HCD handle
1151 * @param chnum Channel number.
1152 * This parameter can be a value from 1 to 15
1153 * @retval Host channel state
1154 * This parameter can be one of these values:
1155 * HC_IDLE/
1156 * HC_XFRC/
1157 * HC_HALTED/
1158 * HC_NYET/
1159 * HC_NAK/
1160 * HC_STALL/
1161 * HC_XACTERR/
1162 * HC_BBLERR/
1163 * HC_DATATGLERR
1164 */
HAL_HCD_HC_GetState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1165 HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1166 {
1167 return hhcd->hc[chnum].state;
1168 }
1169
1170 /**
1171 * @brief Return the current Host frame number.
1172 * @param hhcd HCD handle
1173 * @retval Current Host frame number
1174 */
HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef * hhcd)1175 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
1176 {
1177 return (USB_GetCurrentFrame(hhcd->Instance));
1178 }
1179
1180 /**
1181 * @brief Return the Host enumeration speed.
1182 * @param hhcd HCD handle
1183 * @retval Enumeration speed
1184 */
HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef * hhcd)1185 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
1186 {
1187 return (USB_GetHostSpeed(hhcd->Instance));
1188 }
1189
1190 /**
1191 * @brief Set host channel Hub information.
1192 * @param hhcd HCD handle
1193 * @param ch_num Channel number.
1194 * This parameter can be a value from 1 to 15
1195 * @param addr Hub address
1196 * @param PortNbr Hub port number
1197 * @retval HAL status
1198 */
HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t addr,uint8_t PortNbr)1199 HAL_StatusTypeDef HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1200 uint8_t addr, uint8_t PortNbr)
1201 {
1202 uint32_t HostCoreSpeed = USB_GetHostSpeed(hhcd->Instance);
1203
1204 /* LS/FS device plugged to HS HUB */
1205 if ((hhcd->hc[ch_num].speed != HCD_DEVICE_SPEED_HIGH) && (HostCoreSpeed == HPRT0_PRTSPD_HIGH_SPEED))
1206 {
1207 hhcd->hc[ch_num].do_ssplit = 1U;
1208
1209 if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) && (hhcd->hc[ch_num].ep_is_in != 0U))
1210 {
1211 hhcd->hc[ch_num].toggle_in = 1U;
1212 }
1213 }
1214
1215 hhcd->hc[ch_num].hub_addr = addr;
1216 hhcd->hc[ch_num].hub_port_nbr = PortNbr;
1217
1218 return HAL_OK;
1219 }
1220
1221
1222 /**
1223 * @brief Clear host channel hub information.
1224 * @param hhcd HCD handle
1225 * @param ch_num Channel number.
1226 * This parameter can be a value from 1 to 15
1227 * @retval HAL status
1228 */
HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num)1229 HAL_StatusTypeDef HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
1230 {
1231 hhcd->hc[ch_num].do_ssplit = 0U;
1232 hhcd->hc[ch_num].do_csplit = 0U;
1233 hhcd->hc[ch_num].hub_addr = 0U;
1234 hhcd->hc[ch_num].hub_port_nbr = 0U;
1235
1236 return HAL_OK;
1237 }
1238 /**
1239 * @}
1240 */
1241
1242 /**
1243 * @}
1244 */
1245
1246 /** @addtogroup HCD_Private_Functions
1247 * @{
1248 */
1249 /**
1250 * @brief Handle Host Channel IN interrupt requests.
1251 * @param hhcd HCD handle
1252 * @param chnum Channel number.
1253 * This parameter can be a value from 1 to 15
1254 * @retval none
1255 */
HCD_HC_IN_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1256 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1257 {
1258 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1259 uint32_t USBx_BASE = (uint32_t)USBx;
1260 uint32_t tmpreg;
1261
1262 if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
1263 {
1264 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
1265 hhcd->hc[chnum].state = HC_XACTERR;
1266 (void)USB_HC_Halt(hhcd->Instance, chnum);
1267 }
1268 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_BBERR))
1269 {
1270 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_BBERR);
1271 hhcd->hc[chnum].state = HC_BBLERR;
1272 (void)USB_HC_Halt(hhcd->Instance, chnum);
1273 }
1274 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
1275 {
1276 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
1277 hhcd->hc[chnum].state = HC_STALL;
1278 (void)USB_HC_Halt(hhcd->Instance, chnum);
1279 }
1280 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
1281 {
1282 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
1283 hhcd->hc[chnum].state = HC_DATATGLERR;
1284 (void)USB_HC_Halt(hhcd->Instance, chnum);
1285 }
1286 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
1287 {
1288 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
1289 hhcd->hc[chnum].state = HC_XACTERR;
1290 (void)USB_HC_Halt(hhcd->Instance, chnum);
1291 }
1292 else
1293 {
1294 /* ... */
1295 }
1296
1297 if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
1298 {
1299 (void)USB_HC_Halt(hhcd->Instance, chnum);
1300 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
1301 }
1302 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
1303 {
1304 /* Clear any pending ACK IT */
1305 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1306
1307 if (hhcd->hc[chnum].do_csplit == 1U)
1308 {
1309 hhcd->hc[chnum].do_csplit = 0U;
1310 __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1311 }
1312
1313 if (hhcd->Init.dma_enable != 0U)
1314 {
1315 hhcd->hc[chnum].xfer_count = hhcd->hc[chnum].XferSize - (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
1316 }
1317
1318 hhcd->hc[chnum].state = HC_XFRC;
1319 hhcd->hc[chnum].ErrCnt = 0U;
1320 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
1321
1322 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1323 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1324 {
1325 (void)USB_HC_Halt(hhcd->Instance, chnum);
1326 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1327 }
1328 else if ((hhcd->hc[chnum].ep_type == EP_TYPE_INTR) ||
1329 (hhcd->hc[chnum].ep_type == EP_TYPE_ISOC))
1330 {
1331 USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
1332 hhcd->hc[chnum].urb_state = URB_DONE;
1333
1334 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1335 hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1336 #else
1337 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1338 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1339 }
1340 else
1341 {
1342 /* ... */
1343 }
1344
1345 if (hhcd->Init.dma_enable == 1U)
1346 {
1347 if ((((hhcd->hc[chnum].xfer_count + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet) & 1U) != 0U)
1348 {
1349 hhcd->hc[chnum].toggle_in ^= 1U;
1350 }
1351 }
1352 else
1353 {
1354 hhcd->hc[chnum].toggle_in ^= 1U;
1355 }
1356 }
1357 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
1358 {
1359 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1360
1361 if (hhcd->hc[chnum].do_ssplit == 1U)
1362 {
1363 hhcd->hc[chnum].do_csplit = 1U;
1364 hhcd->hc[chnum].state = HC_ACK;
1365
1366 (void)USB_HC_Halt(hhcd->Instance, chnum);
1367 }
1368 }
1369 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
1370 {
1371 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
1372
1373 if (hhcd->hc[chnum].state == HC_XFRC)
1374 {
1375 hhcd->hc[chnum].state = HC_HALTED;
1376 hhcd->hc[chnum].urb_state = URB_DONE;
1377 }
1378 else if (hhcd->hc[chnum].state == HC_STALL)
1379 {
1380 hhcd->hc[chnum].state = HC_HALTED;
1381 hhcd->hc[chnum].urb_state = URB_STALL;
1382 }
1383 else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
1384 (hhcd->hc[chnum].state == HC_DATATGLERR))
1385 {
1386 hhcd->hc[chnum].state = HC_HALTED;
1387 hhcd->hc[chnum].ErrCnt++;
1388 if (hhcd->hc[chnum].ErrCnt > 2U)
1389 {
1390 hhcd->hc[chnum].ErrCnt = 0U;
1391
1392 if (hhcd->hc[chnum].do_ssplit == 1U)
1393 {
1394 hhcd->hc[chnum].do_csplit = 0U;
1395 hhcd->hc[chnum].ep_ss_schedule = 0U;
1396 __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1397 }
1398
1399 hhcd->hc[chnum].urb_state = URB_ERROR;
1400 }
1401 else
1402 {
1403 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1404
1405 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1406 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1407 {
1408 /* re-activate the channel */
1409 tmpreg = USBx_HC(chnum)->HCCHAR;
1410 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1411 tmpreg |= USB_OTG_HCCHAR_CHENA;
1412 USBx_HC(chnum)->HCCHAR = tmpreg;
1413 }
1414 }
1415 }
1416 else if (hhcd->hc[chnum].state == HC_NYET)
1417 {
1418 hhcd->hc[chnum].state = HC_HALTED;
1419
1420 if (hhcd->hc[chnum].do_csplit == 1U)
1421 {
1422 if (hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
1423 {
1424 hhcd->hc[chnum].NyetErrCnt++;
1425 if (hhcd->hc[chnum].NyetErrCnt > 2U)
1426 {
1427 hhcd->hc[chnum].NyetErrCnt = 0U;
1428 hhcd->hc[chnum].do_csplit = 0U;
1429
1430 if (hhcd->hc[chnum].ErrCnt < 3U)
1431 {
1432 hhcd->hc[chnum].ep_ss_schedule = 1U;
1433 }
1434 __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1435 hhcd->hc[chnum].urb_state = URB_ERROR;
1436 }
1437 else
1438 {
1439 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1440 }
1441 }
1442 else
1443 {
1444 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1445 }
1446
1447 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1448 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1449 {
1450 /* re-activate the channel */
1451 tmpreg = USBx_HC(chnum)->HCCHAR;
1452 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1453 tmpreg |= USB_OTG_HCCHAR_CHENA;
1454 USBx_HC(chnum)->HCCHAR = tmpreg;
1455 }
1456 }
1457 }
1458 else if (hhcd->hc[chnum].state == HC_ACK)
1459 {
1460 hhcd->hc[chnum].state = HC_HALTED;
1461
1462 if (hhcd->hc[chnum].do_csplit == 1U)
1463 {
1464 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1465
1466 /* Set Complete split and re-activate the channel */
1467 USBx_HC(chnum)->HCSPLT |= USB_OTG_HCSPLT_COMPLSPLT;
1468 USBx_HC(chnum)->HCINTMSK |= USB_OTG_HCINTMSK_NYET;
1469 USBx_HC(chnum)->HCINTMSK &= ~USB_OTG_HCINT_ACK;
1470
1471 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1472 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1473 {
1474 /* re-activate the channel */
1475 tmpreg = USBx_HC(chnum)->HCCHAR;
1476 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1477 tmpreg |= USB_OTG_HCCHAR_CHENA;
1478 USBx_HC(chnum)->HCCHAR = tmpreg;
1479 }
1480 }
1481 }
1482 else if (hhcd->hc[chnum].state == HC_NAK)
1483 {
1484 hhcd->hc[chnum].state = HC_HALTED;
1485 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1486
1487 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1488 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1489 {
1490 /* re-activate the channel */
1491 tmpreg = USBx_HC(chnum)->HCCHAR;
1492 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1493 tmpreg |= USB_OTG_HCCHAR_CHENA;
1494 USBx_HC(chnum)->HCCHAR = tmpreg;
1495 }
1496 }
1497 else if (hhcd->hc[chnum].state == HC_BBLERR)
1498 {
1499 hhcd->hc[chnum].state = HC_HALTED;
1500 hhcd->hc[chnum].ErrCnt++;
1501 hhcd->hc[chnum].urb_state = URB_ERROR;
1502 }
1503 else
1504 {
1505 if (hhcd->hc[chnum].state == HC_HALTED)
1506 {
1507 return;
1508 }
1509 }
1510
1511 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1512 hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1513 #else
1514 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1515 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1516 }
1517 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
1518 {
1519 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
1520 hhcd->hc[chnum].state = HC_NYET;
1521
1522 if (hhcd->hc[chnum].do_ssplit == 0U)
1523 {
1524 hhcd->hc[chnum].ErrCnt = 0U;
1525 }
1526
1527 (void)USB_HC_Halt(hhcd->Instance, chnum);
1528 }
1529 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
1530 {
1531 if (hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
1532 {
1533 hhcd->hc[chnum].ErrCnt = 0U;
1534 hhcd->hc[chnum].state = HC_NAK;
1535 (void)USB_HC_Halt(hhcd->Instance, chnum);
1536 }
1537 else if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1538 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1539 {
1540 hhcd->hc[chnum].ErrCnt = 0U;
1541
1542 if ((hhcd->Init.dma_enable == 0U) || (hhcd->hc[chnum].do_csplit == 1U))
1543 {
1544 hhcd->hc[chnum].state = HC_NAK;
1545 (void)USB_HC_Halt(hhcd->Instance, chnum);
1546 }
1547 }
1548 else
1549 {
1550 /* ... */
1551 }
1552
1553 if (hhcd->hc[chnum].do_csplit == 1U)
1554 {
1555 hhcd->hc[chnum].do_csplit = 0U;
1556 __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1557 __HAL_HCD_UNMASK_ACK_HC_INT(chnum);
1558 }
1559
1560 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1561 }
1562 else
1563 {
1564 /* ... */
1565 }
1566 }
1567
1568 /**
1569 * @brief Handle Host Channel OUT interrupt requests.
1570 * @param hhcd HCD handle
1571 * @param chnum Channel number.
1572 * This parameter can be a value from 1 to 15
1573 * @retval none
1574 */
HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1575 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1576 {
1577 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1578 uint32_t USBx_BASE = (uint32_t)USBx;
1579 uint32_t tmpreg;
1580 uint32_t num_packets;
1581
1582 if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
1583 {
1584 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
1585 hhcd->hc[chnum].state = HC_XACTERR;
1586 (void)USB_HC_Halt(hhcd->Instance, chnum);
1587 }
1588 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
1589 {
1590 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1591
1592 if (hhcd->hc[chnum].do_ping == 1U)
1593 {
1594 hhcd->hc[chnum].do_ping = 0U;
1595 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1596 hhcd->hc[chnum].state = HC_ACK;
1597 (void)USB_HC_Halt(hhcd->Instance, chnum);
1598 }
1599
1600 if ((hhcd->hc[chnum].do_ssplit == 1U) && (hhcd->hc[chnum].do_csplit == 0U))
1601 {
1602 if (hhcd->hc[chnum].ep_type != EP_TYPE_ISOC)
1603 {
1604 hhcd->hc[chnum].do_csplit = 1U;
1605 }
1606
1607 hhcd->hc[chnum].state = HC_ACK;
1608 (void)USB_HC_Halt(hhcd->Instance, chnum);
1609
1610 /* reset error_count */
1611 hhcd->hc[chnum].ErrCnt = 0U;
1612 }
1613 }
1614 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
1615 {
1616 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
1617 (void)USB_HC_Halt(hhcd->Instance, chnum);
1618 }
1619 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
1620 {
1621 hhcd->hc[chnum].ErrCnt = 0U;
1622
1623 /* transaction completed with NYET state, update do ping state */
1624 if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
1625 {
1626 hhcd->hc[chnum].do_ping = 1U;
1627 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
1628 }
1629
1630 if (hhcd->hc[chnum].do_csplit != 0U)
1631 {
1632 hhcd->hc[chnum].do_csplit = 0U;
1633 __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1634 }
1635
1636 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
1637 hhcd->hc[chnum].state = HC_XFRC;
1638 (void)USB_HC_Halt(hhcd->Instance, chnum);
1639 }
1640 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
1641 {
1642 hhcd->hc[chnum].state = HC_NYET;
1643
1644 if (hhcd->hc[chnum].do_ssplit == 0U)
1645 {
1646 hhcd->hc[chnum].do_ping = 1U;
1647 }
1648
1649 hhcd->hc[chnum].ErrCnt = 0U;
1650 (void)USB_HC_Halt(hhcd->Instance, chnum);
1651 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
1652 }
1653 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
1654 {
1655 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
1656 hhcd->hc[chnum].state = HC_STALL;
1657 (void)USB_HC_Halt(hhcd->Instance, chnum);
1658 }
1659 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
1660 {
1661 hhcd->hc[chnum].ErrCnt = 0U;
1662 hhcd->hc[chnum].state = HC_NAK;
1663
1664 if (hhcd->hc[chnum].do_ping == 0U)
1665 {
1666 if (hhcd->hc[chnum].speed == HCD_DEVICE_SPEED_HIGH)
1667 {
1668 hhcd->hc[chnum].do_ping = 1U;
1669 }
1670 }
1671
1672 (void)USB_HC_Halt(hhcd->Instance, chnum);
1673 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1674 }
1675 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
1676 {
1677 if (hhcd->Init.dma_enable == 0U)
1678 {
1679 hhcd->hc[chnum].state = HC_XACTERR;
1680 (void)USB_HC_Halt(hhcd->Instance, chnum);
1681 }
1682 else
1683 {
1684 hhcd->hc[chnum].ErrCnt++;
1685 if (hhcd->hc[chnum].ErrCnt > 2U)
1686 {
1687 hhcd->hc[chnum].ErrCnt = 0U;
1688 hhcd->hc[chnum].urb_state = URB_ERROR;
1689
1690 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1691 hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1692 #else
1693 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1694 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1695 }
1696 else
1697 {
1698 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1699 }
1700 }
1701 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
1702 }
1703 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
1704 {
1705 hhcd->hc[chnum].state = HC_DATATGLERR;
1706 (void)USB_HC_Halt(hhcd->Instance, chnum);
1707 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
1708 }
1709 else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
1710 {
1711 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
1712
1713 if (hhcd->hc[chnum].state == HC_XFRC)
1714 {
1715 hhcd->hc[chnum].state = HC_HALTED;
1716 hhcd->hc[chnum].urb_state = URB_DONE;
1717
1718 if ((hhcd->hc[chnum].ep_type == EP_TYPE_BULK) ||
1719 (hhcd->hc[chnum].ep_type == EP_TYPE_INTR))
1720 {
1721 if (hhcd->Init.dma_enable == 0U)
1722 {
1723 hhcd->hc[chnum].toggle_out ^= 1U;
1724 }
1725
1726 if ((hhcd->Init.dma_enable == 1U) && (hhcd->hc[chnum].xfer_len > 0U))
1727 {
1728 num_packets = (hhcd->hc[chnum].xfer_len + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet;
1729
1730 if ((num_packets & 1U) != 0U)
1731 {
1732 hhcd->hc[chnum].toggle_out ^= 1U;
1733 }
1734 }
1735 }
1736 }
1737 else if (hhcd->hc[chnum].state == HC_ACK)
1738 {
1739 hhcd->hc[chnum].state = HC_HALTED;
1740
1741 if (hhcd->hc[chnum].do_csplit == 1U)
1742 {
1743 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1744 }
1745 }
1746 else if (hhcd->hc[chnum].state == HC_NAK)
1747 {
1748 hhcd->hc[chnum].state = HC_HALTED;
1749 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1750
1751 if (hhcd->hc[chnum].do_csplit == 1U)
1752 {
1753 hhcd->hc[chnum].do_csplit = 0U;
1754 __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1755 }
1756 }
1757 else if (hhcd->hc[chnum].state == HC_NYET)
1758 {
1759 hhcd->hc[chnum].state = HC_HALTED;
1760 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1761 }
1762 else if (hhcd->hc[chnum].state == HC_STALL)
1763 {
1764 hhcd->hc[chnum].state = HC_HALTED;
1765 hhcd->hc[chnum].urb_state = URB_STALL;
1766 }
1767 else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
1768 (hhcd->hc[chnum].state == HC_DATATGLERR))
1769 {
1770 hhcd->hc[chnum].state = HC_HALTED;
1771 hhcd->hc[chnum].ErrCnt++;
1772 if (hhcd->hc[chnum].ErrCnt > 2U)
1773 {
1774 hhcd->hc[chnum].ErrCnt = 0U;
1775 hhcd->hc[chnum].urb_state = URB_ERROR;
1776 }
1777 else
1778 {
1779 hhcd->hc[chnum].urb_state = URB_NOTREADY;
1780
1781 /* re-activate the channel */
1782 tmpreg = USBx_HC(chnum)->HCCHAR;
1783 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1784 tmpreg |= USB_OTG_HCCHAR_CHENA;
1785 USBx_HC(chnum)->HCCHAR = tmpreg;
1786 }
1787 }
1788 else
1789 {
1790 return;
1791 }
1792
1793 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1794 hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1795 #else
1796 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1797 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1798 }
1799 else
1800 {
1801 return;
1802 }
1803 }
1804
1805 /**
1806 * @brief Handle Rx Queue Level interrupt requests.
1807 * @param hhcd HCD handle
1808 * @retval none
1809 */
HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef * hhcd)1810 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
1811 {
1812 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1813 uint32_t USBx_BASE = (uint32_t)USBx;
1814 uint32_t pktsts;
1815 uint32_t pktcnt;
1816 uint32_t GrxstspReg;
1817 uint32_t xferSizePktCnt;
1818 uint32_t tmpreg;
1819 uint32_t chnum;
1820
1821 GrxstspReg = hhcd->Instance->GRXSTSP;
1822 chnum = GrxstspReg & USB_OTG_GRXSTSP_EPNUM;
1823 pktsts = (GrxstspReg & USB_OTG_GRXSTSP_PKTSTS) >> 17;
1824 pktcnt = (GrxstspReg & USB_OTG_GRXSTSP_BCNT) >> 4;
1825
1826 switch (pktsts)
1827 {
1828 case GRXSTS_PKTSTS_IN:
1829 /* Read the data into the host buffer. */
1830 if ((pktcnt > 0U) && (hhcd->hc[chnum].xfer_buff != (void *)0))
1831 {
1832 if ((hhcd->hc[chnum].xfer_count + pktcnt) <= hhcd->hc[chnum].xfer_len)
1833 {
1834 (void)USB_ReadPacket(hhcd->Instance,
1835 hhcd->hc[chnum].xfer_buff, (uint16_t)pktcnt);
1836
1837 /* manage multiple Xfer */
1838 hhcd->hc[chnum].xfer_buff += pktcnt;
1839 hhcd->hc[chnum].xfer_count += pktcnt;
1840
1841 /* get transfer size packet count */
1842 xferSizePktCnt = (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19;
1843
1844 if ((hhcd->hc[chnum].max_packet == pktcnt) && (xferSizePktCnt > 0U))
1845 {
1846 /* re-activate the channel when more packets are expected */
1847 tmpreg = USBx_HC(chnum)->HCCHAR;
1848 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1849 tmpreg |= USB_OTG_HCCHAR_CHENA;
1850 USBx_HC(chnum)->HCCHAR = tmpreg;
1851 hhcd->hc[chnum].toggle_in ^= 1U;
1852 }
1853 }
1854 else
1855 {
1856 hhcd->hc[chnum].urb_state = URB_ERROR;
1857 }
1858 }
1859 break;
1860
1861 case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
1862 break;
1863
1864 case GRXSTS_PKTSTS_IN_XFER_COMP:
1865 case GRXSTS_PKTSTS_CH_HALTED:
1866 default:
1867 break;
1868 }
1869 }
1870
1871 /**
1872 * @brief Handle Host Port interrupt requests.
1873 * @param hhcd HCD handle
1874 * @retval None
1875 */
HCD_Port_IRQHandler(HCD_HandleTypeDef * hhcd)1876 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
1877 {
1878 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1879 uint32_t USBx_BASE = (uint32_t)USBx;
1880 __IO uint32_t hprt0;
1881 __IO uint32_t hprt0_dup;
1882
1883 /* Handle Host Port Interrupts */
1884 hprt0 = USBx_HPRT0;
1885 hprt0_dup = USBx_HPRT0;
1886
1887 hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
1888 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
1889
1890 /* Check whether Port Connect detected */
1891 if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
1892 {
1893 if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
1894 {
1895 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1896 hhcd->ConnectCallback(hhcd);
1897 #else
1898 HAL_HCD_Connect_Callback(hhcd);
1899 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1900 }
1901 hprt0_dup |= USB_OTG_HPRT_PCDET;
1902 }
1903
1904 /* Check whether Port Enable Changed */
1905 if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
1906 {
1907 hprt0_dup |= USB_OTG_HPRT_PENCHNG;
1908
1909 if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
1910 {
1911 if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
1912 {
1913 if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
1914 {
1915 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
1916 }
1917 else
1918 {
1919 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
1920 }
1921 }
1922 else
1923 {
1924 if (hhcd->Init.speed == HCD_SPEED_FULL)
1925 {
1926 USBx_HOST->HFIR = HFIR_60_MHZ;
1927 }
1928 }
1929 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1930 hhcd->PortEnabledCallback(hhcd);
1931 #else
1932 HAL_HCD_PortEnabled_Callback(hhcd);
1933 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1934
1935 }
1936 else
1937 {
1938 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1939 hhcd->PortDisabledCallback(hhcd);
1940 #else
1941 HAL_HCD_PortDisabled_Callback(hhcd);
1942 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1943 }
1944 }
1945
1946 /* Check for an overcurrent */
1947 if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
1948 {
1949 hprt0_dup |= USB_OTG_HPRT_POCCHNG;
1950 }
1951
1952 /* Clear Port Interrupts */
1953 USBx_HPRT0 = hprt0_dup;
1954 }
1955
1956 /**
1957 * @}
1958 */
1959
1960 /**
1961 * @}
1962 */
1963
1964 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1965 #if defined (USB_DRD_FS)
1966
1967 /** @defgroup HCD HCD
1968 * @brief HCD HAL module driver
1969 * @{
1970 */
1971
1972 /* Private typedef -----------------------------------------------------------*/
1973 /* Private define ------------------------------------------------------------*/
1974 /* Private macro -------------------------------------------------------------*/
1975 /* Private variables ---------------------------------------------------------*/
1976 /* Private function ----------------------------------------------------------*/
1977 /** @defgroup HCD_Private_Functions HCD Private Functions
1978 * @{
1979 */
1980 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
1981 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
1982 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
1983 static void HAL_HCD_ClearPhyChannel(HCD_HandleTypeDef *hhcd);
1984 static uint8_t HAL_HCD_GetLogical_Channel(HCD_HandleTypeDef const *hhcd, uint8_t phy_chnum, uint8_t dir);
1985 static uint8_t HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const *hhcd, uint8_t ch_num);
1986 static uint8_t HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t epnum, uint8_t ep_type);
1987
1988 #if (USE_USB_DOUBLE_BUFFER == 1U)
1989 static void HCD_HC_IN_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
1990 static void HCD_HC_OUT_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
1991 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1992
1993 static uint16_t HAL_HCD_GetFreePMA(HCD_HandleTypeDef *hhcd, uint16_t mps);
1994 static HAL_StatusTypeDef HAL_HCD_PMAFree(HCD_HandleTypeDef *hhcd, uint32_t pma_base, uint16_t mps);
1995 static void inline HCD_HC_IN_ISO(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
1996 /**
1997 * @}
1998 */
1999
2000 /* Exported functions --------------------------------------------------------*/
2001 /** @defgroup HCD_Exported_Functions HCD Exported Functions
2002 * @{
2003 */
2004
2005 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
2006 * @brief Initialization and Configuration functions
2007 *
2008 @verbatim
2009 ===============================================================================
2010 ##### Initialization and de-initialization functions #####
2011 ===============================================================================
2012 [..] This section provides functions allowing to:
2013
2014 @endverbatim
2015 * @{
2016 */
2017
2018 /**
2019 * @brief Initialize the host driver.
2020 * @param hhcd HCD handle
2021 * @retval HAL status
2022 */
HAL_HCD_Init(HCD_HandleTypeDef * hhcd)2023 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
2024 {
2025 /* Check the HCD handle allocation */
2026 if (hhcd == NULL)
2027 {
2028 return HAL_ERROR;
2029 }
2030
2031 /* Check the parameters */
2032 assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
2033
2034 if (hhcd->State == HAL_HCD_STATE_RESET)
2035 {
2036 /* Allocate lock resource and initialize it */
2037 hhcd->Lock = HAL_UNLOCKED;
2038
2039 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2040 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
2041 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
2042 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
2043 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
2044 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
2045 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;
2046
2047 if (hhcd->MspInitCallback == NULL)
2048 {
2049 hhcd->MspInitCallback = HAL_HCD_MspInit;
2050 }
2051
2052 /* Init the low level hardware */
2053 hhcd->MspInitCallback(hhcd);
2054 #else
2055 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
2056 HAL_HCD_MspInit(hhcd);
2057 #endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
2058 }
2059 hhcd->State = HAL_HCD_STATE_BUSY;
2060
2061 /* Disable the Interrupts */
2062 (void)__HAL_HCD_DISABLE(hhcd);
2063
2064 /* Dma not supported, force to zero */
2065 hhcd->Init.dma_enable = 0U;
2066
2067 /* Init the Core (common init.) */
2068 (void)USB_CoreInit(hhcd->Instance, hhcd->Init);
2069
2070 /* Force Host Mode */
2071 (void)USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE);
2072
2073 /* Init Host */
2074 (void)USB_HostInit(hhcd->Instance, hhcd->Init);
2075
2076 /* Deactivate the power down */
2077 hhcd->Instance->CNTR &= ~USB_CNTR_PDWN;
2078
2079 hhcd->State = HAL_HCD_STATE_READY;
2080
2081 /* Host Port State */
2082 hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
2083
2084 /* Init PMA Address */
2085 (void)HAL_HCD_PMAReset(hhcd);
2086
2087 hhcd->State = HAL_HCD_STATE_READY;
2088
2089 return HAL_OK;
2090 }
2091
2092 /**
2093 * @brief Initialize a host channel.
2094 * @param hhcd HCD handle
2095 * @param ch_num Channel number.
2096 * This parameter can be a value from 1 to 15
2097 * @param epnum Endpoint number.
2098 * This parameter can be a value from 1 to 15
2099 * @param dev_address Current device address
2100 * This parameter can be a value from 0 to 255
2101 * @param speed Current device speed.
2102 * This parameter can be one of these values:
2103 * HCD_DEVICE_SPEED_HIGH High speed mode,
2104 * HCD_DEVICE_SPEED_FULL Full speed mode,
2105 * HCD_DEVICE_SPEED_LOW Low speed mode
2106 * @param ep_type Endpoint Type.
2107 * This parameter can be one of these values:
2108 * USBH_EP_CONTROL Control type,
2109 * USBH_EP_ISO Isochronous type,
2110 * USBH_EP_BULK Bulk type,
2111 * USBH_EP_INTERRUPT Interrupt type
2112 * @param mps Max Packet Size.
2113 * This parameter can be a value from 0 to32K
2114 * @retval HAL status
2115 */
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)2116 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
2117 uint8_t epnum, uint8_t dev_address,
2118 uint8_t speed, uint8_t ep_type, uint16_t mps)
2119 {
2120 HAL_StatusTypeDef status;
2121 uint8_t used_channel;
2122 uint8_t ep0_virtual_channel;
2123
2124 __HAL_LOCK(hhcd);
2125
2126 /* Check if the logical channel are already allocated */
2127 used_channel = HAL_HCD_Check_usedChannel(hhcd, ch_num);
2128
2129 /* Check if the channel is not already opened */
2130 if (used_channel == 0U)
2131 {
2132 /* Allocate New Physical channel */
2133 hhcd->hc[ch_num & 0xFU].phy_ch_num = HAL_HCD_Get_FreePhyChannel(hhcd, ch_num, epnum, ep_type);
2134
2135 /* No free Channel available, return error */
2136 if (hhcd->hc[ch_num & 0xFU].phy_ch_num == HCD_FREE_CH_NOT_FOUND)
2137 {
2138 return HAL_ERROR;
2139 }
2140 }
2141 /* Channel already opened */
2142 else
2143 {
2144 /* Get Physical Channel number */
2145 hhcd->hc[ch_num & 0xFU].phy_ch_num = (used_channel & 0xF0U) >> 4U;
2146 }
2147
2148 if ((epnum & 0x80U) != 0U)
2149 {
2150 hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
2151 }
2152 else
2153 {
2154 hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
2155 }
2156
2157 hhcd->hc[ch_num & 0xFU].dev_addr = dev_address;
2158 hhcd->hc[ch_num & 0xFU].max_packet = mps;
2159 hhcd->hc[ch_num & 0xFU].ep_type = ep_type;
2160 hhcd->hc[ch_num & 0xFU].ep_num = epnum & 0x7FU;
2161 hhcd->hc[ch_num & 0xFU].speed = speed;
2162
2163 /* Check if the channel is not already opened */
2164 if (used_channel == 0U)
2165 {
2166 if (((ep_type == EP_TYPE_ISOC) && (hhcd->Init.iso_singlebuffer_enable == 0U)) ||
2167 ((ep_type == EP_TYPE_BULK) && (hhcd->Init.bulk_doublebuffer_enable == 1U)))
2168 {
2169 /* PMA Dynamic Allocation */
2170 status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_DBL_BUF, mps);
2171
2172 if (status == HAL_ERROR)
2173 {
2174 return HAL_ERROR;
2175 }
2176
2177 /* Clear Channel DTOG_TX */
2178 HCD_CLEAR_TX_DTOG(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num);
2179
2180 /* Clear Channel DTOG RX */
2181 HCD_CLEAR_RX_DTOG(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num);
2182
2183 }
2184 else
2185 {
2186 if (hhcd->hc[ch_num & 0xFU].ep_num != 0U)
2187 {
2188 status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, mps);
2189
2190 if (status == HAL_ERROR)
2191 {
2192 return HAL_ERROR;
2193 }
2194 }
2195 else
2196 {
2197 if (ch_num == 0U)
2198 {
2199 ep0_virtual_channel = (uint8_t)(hhcd->ep0_PmaAllocState & 0xFU);
2200
2201 if ((ep0_virtual_channel != 0U) && (((hhcd->ep0_PmaAllocState & 0xF0U) >> 4) == CH_IN_DIR))
2202 {
2203 if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_OUT_DIR)
2204 {
2205 status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
2206
2207 if (status == HAL_ERROR)
2208 {
2209 return HAL_ERROR;
2210 }
2211 }
2212 else
2213 {
2214 return HAL_ERROR;
2215 }
2216 }
2217 else
2218 {
2219 /* PMA Dynamic Allocation for EP0 OUT direction */
2220 hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
2221 status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
2222
2223 if (status == HAL_ERROR)
2224 {
2225 return HAL_ERROR;
2226 }
2227
2228 /* PMA Dynamic Allocation for EP0 IN direction */
2229 hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
2230 status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
2231
2232 if (status == HAL_ERROR)
2233 {
2234 return HAL_ERROR;
2235 }
2236 }
2237 }
2238 else
2239 {
2240 if (((hhcd->ep0_PmaAllocState & 0xF00U) >> 8) == 1U)
2241 {
2242 ep0_virtual_channel = (uint8_t)(hhcd->ep0_PmaAllocState & 0xFU);
2243
2244 if (((hhcd->ep0_PmaAllocState & 0xF0U) >> 4) == CH_IN_DIR)
2245 {
2246 hhcd->hc[ch_num & 0xFU].pmaaddr1 = hhcd->hc[ep0_virtual_channel & 0xFU].pmaaddr1;
2247 }
2248 else
2249 {
2250 hhcd->hc[ch_num & 0xFU].pmaaddr0 = hhcd->hc[ep0_virtual_channel & 0xFU].pmaaddr0;
2251 }
2252 }
2253 else
2254 {
2255 status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
2256
2257 if (status == HAL_ERROR)
2258 {
2259 return HAL_ERROR;
2260 }
2261 }
2262 }
2263 }
2264 }
2265 }
2266
2267 if ((epnum & 0x80U) != 0U)
2268 {
2269 hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
2270
2271 if (hhcd->hc[ch_num & 0xFU].ep_num == 0U)
2272 {
2273 hhcd->hc[ch_num & 0xFU].pmaadress = hhcd->hc[ch_num & 0xFU].pmaaddr1;
2274 }
2275 }
2276 else
2277 {
2278 hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
2279
2280 if (hhcd->hc[ch_num & 0xFU].ep_num == 0U)
2281 {
2282 hhcd->hc[ch_num & 0xFU].pmaadress = hhcd->hc[ch_num & 0xFU].pmaaddr0;
2283 }
2284 }
2285
2286 /* Init the USB Channel CHEPRx */
2287 status = USB_HC_Init(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
2288 epnum, dev_address, speed, ep_type, mps);
2289
2290 /* check single buffer for isochronous channel */
2291 if (ep_type == EP_TYPE_ISOC)
2292 {
2293 if (hhcd->Init.iso_singlebuffer_enable == 1U)
2294 {
2295 (void)USB_HC_DoubleBuffer(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
2296 USB_DRD_ISOC_DBUFF_DISABLE);
2297 }
2298 }
2299
2300 /* Bulk double buffer check */
2301 if (ep_type == EP_TYPE_BULK)
2302 {
2303 if (hhcd->Init.bulk_doublebuffer_enable == 1U)
2304 {
2305 (void)USB_HC_DoubleBuffer(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
2306 USB_DRD_BULK_DBUFF_ENBALE);
2307 }
2308 }
2309
2310 __HAL_UNLOCK(hhcd);
2311
2312 return status;
2313 }
2314
2315 /**
2316 * @brief HAL_HCD_HC_Close Pipe
2317 * @param hhcd HCD handle
2318 * @param ch_num Channel number.
2319 * This parameter can be a value from 1 to 15
2320 * @retval HAL status
2321 */
HAL_HCD_HC_Close(HCD_HandleTypeDef * hhcd,uint8_t ch_num)2322 HAL_StatusTypeDef HAL_HCD_HC_Close(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
2323 {
2324 /* Stop the channel */
2325 (void) HAL_HCD_HC_Halt(hhcd, ch_num);
2326
2327 HAL_Delay(3U);
2328
2329 if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_IN_DIR)
2330 {
2331 /* Free Allocated Channel */
2332 hhcd->phy_chin_state[hhcd->hc[ch_num & 0xFU].phy_ch_num] = 0U;
2333 }
2334 else
2335 {
2336 /* Free Allocated Channel */
2337 hhcd->phy_chout_state[hhcd->hc[ch_num & 0xFU].phy_ch_num] = 0U;
2338 }
2339
2340 /* Reset PMA Channel_Allocation */
2341 (void)HAL_HCD_PMADeAlloc(hhcd, ch_num);
2342
2343 return HAL_OK;
2344 }
2345
2346 /**
2347 * @brief Halt a host channel.
2348 * @param hhcd HCD handle
2349 * @param ch_num Channel number.
2350 * This parameter can be a value from 1 to 15
2351 * @retval HAL status
2352 */
HAL_HCD_HC_Halt(HCD_HandleTypeDef * hhcd,uint8_t ch_num)2353 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
2354 {
2355 HAL_StatusTypeDef status = HAL_OK;
2356
2357 __HAL_LOCK(hhcd);
2358 if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_IN_DIR)
2359 {
2360 (void)USB_HC_IN_Halt(hhcd->Instance, (uint8_t) hhcd->hc[ch_num & 0xFU].phy_ch_num);
2361 }
2362 else
2363 {
2364 (void)USB_HC_OUT_Halt(hhcd->Instance, (uint8_t) hhcd->hc[ch_num & 0xFU].phy_ch_num);
2365 }
2366 __HAL_UNLOCK(hhcd);
2367
2368 return status;
2369 }
2370
2371 /**
2372 * @brief DeInitialize the host driver.
2373 * @param hhcd HCD handle
2374 * @retval HAL status
2375 */
HAL_HCD_DeInit(HCD_HandleTypeDef * hhcd)2376 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
2377 {
2378 uint8_t idx;
2379
2380 /* Check the HCD handle allocation */
2381 if (hhcd == NULL)
2382 {
2383 return HAL_ERROR;
2384 }
2385
2386 /* Host Port State */
2387 hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
2388
2389 /* Reset PMA Address */
2390 (void)HAL_HCD_PMAReset(hhcd);
2391
2392 for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
2393 {
2394 hhcd->phy_chin_state[idx] = 0U;
2395 hhcd->phy_chout_state[idx] = 0U;
2396 }
2397
2398 /* reset Ep0 Pma allocation state */
2399 hhcd->ep0_PmaAllocState = 0U;
2400
2401 hhcd->State = HAL_HCD_STATE_BUSY;
2402
2403 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2404 if (hhcd->MspDeInitCallback == NULL)
2405 {
2406 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */
2407 }
2408
2409 /* DeInit the low level hardware */
2410 hhcd->MspDeInitCallback(hhcd);
2411 #else
2412 /* DeInit the low level hardware: CLOCK, NVIC. */
2413 HAL_HCD_MspDeInit(hhcd);
2414 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2415
2416 hhcd->State = HAL_HCD_STATE_RESET;
2417
2418 return HAL_OK;
2419 }
2420
2421 /**
2422 * @brief Initialize the HCD MSP.
2423 * @param hhcd HCD handle
2424 * @retval None
2425 */
HAL_HCD_MspInit(HCD_HandleTypeDef * hhcd)2426 __weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
2427 {
2428 /* Prevent unused argument(s) compilation warning */
2429 UNUSED(hhcd);
2430
2431 /* NOTE : This function Should not be modified, when the callback is needed,
2432 the HAL_HCD_MspInit could be implemented in the user file
2433 */
2434 }
2435
2436 /**
2437 * @brief DeInitialize the HCD MSP.
2438 * @param hhcd HCD handle
2439 * @retval None
2440 */
HAL_HCD_MspDeInit(HCD_HandleTypeDef * hhcd)2441 __weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
2442 {
2443 /* Prevent unused argument(s) compilation warning */
2444 UNUSED(hhcd);
2445
2446 /* NOTE : This function Should not be modified, when the callback is needed,
2447 the HAL_HCD_MspDeInit could be implemented in the user file
2448 */
2449 }
2450
HAL_HCD_SuspendCallback(HCD_HandleTypeDef * hhcd)2451 __weak void HAL_HCD_SuspendCallback(HCD_HandleTypeDef *hhcd)
2452 {
2453 /* Prevent unused argument(s) compilation warning */
2454 UNUSED(hhcd);
2455
2456 /* NOTE : This function Should not be modified, when the callback is needed,
2457 the HAL_HCD_SuspendCallback could be implemented in the user file
2458 */
2459
2460 }
2461
HAL_HCD_ResumeCallback(HCD_HandleTypeDef * hhcd)2462 __weak void HAL_HCD_ResumeCallback(HCD_HandleTypeDef *hhcd)
2463 {
2464 /* Prevent unused argument(s) compilation warning */
2465 UNUSED(hhcd);
2466
2467 /* NOTE : This function Should not be modified, when the callback is needed,
2468 the HAL_HCD_ResumeCallback could be implemented in the user file
2469 */
2470 }
2471
2472 /**
2473 * @}
2474 */
2475
2476 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
2477 * @brief HCD IO operation functions
2478 *
2479 @verbatim
2480 ===============================================================================
2481 ##### IO operation functions #####
2482 ===============================================================================
2483 [..] This subsection provides a set of functions allowing to manage the USB Host Data
2484 Transfer
2485
2486 @endverbatim
2487 * @{
2488 */
2489
2490 /**
2491 * @brief Submit a new URB for processing.
2492 * @param hhcd HCD handle
2493 * @param ch_num Channel number.
2494 * This parameter can be a value from 1 to 15
2495 * @param direction Channel number.
2496 * This parameter can be one of these values:
2497 * 0 : Output / 1 : Input
2498 * @param ep_type Endpoint Type.
2499 * This parameter can be one of these values:
2500 * USBH_EP_CONTROL : Control type/
2501 * USBH_EP_ISO : Isochronous type/
2502 * USBH_EP_BULK : Bulk type/
2503 * USBH_EP_INTERRUPT : Interrupt type/
2504 * @param token Endpoint Type.
2505 * This parameter can be one of these values:
2506 * 0: HC_PID_SETUP / 1: HC_PID_DATA1
2507 * @param pbuff pointer to URB data
2508 * @param length Length of URB data
2509 * @param do_ping activate do ping protocol (for high speed only).
2510 * This parameter can be one of these values:
2511 * 0 : do ping inactive / 1 : do ping active
2512 * @retval HAL status
2513 */
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)2514 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
2515 uint8_t direction, uint8_t ep_type,
2516 uint8_t token, uint8_t *pbuff,
2517 uint16_t length, uint8_t do_ping)
2518 {
2519 UNUSED(do_ping);
2520
2521 if (token == 0U)
2522 {
2523 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_SETUP;
2524 }
2525 else
2526 {
2527 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
2528 }
2529
2530 /* Manage Data Toggle */
2531 switch (ep_type)
2532 {
2533 case EP_TYPE_CTRL:
2534 if ((token == 1U) && (direction == 0U)) /* send data */
2535 {
2536 if (length == 0U)
2537 {
2538 /* For Status OUT stage, Length==0, Status Out PID = 1 */
2539 hhcd->hc[ch_num & 0xFU].toggle_out = 1U;
2540 }
2541
2542 /* Set the Data Toggle bit as per the Flag */
2543 if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
2544 {
2545 /* Put the PID 0 */
2546 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
2547 }
2548 else
2549 {
2550 /* Put the PID 1 */
2551 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
2552 }
2553 }
2554 break;
2555
2556 case EP_TYPE_BULK:
2557 if (direction == 0U)
2558 {
2559 /* Set the Data Toggle bit as per the Flag */
2560 if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
2561 {
2562 /* Put the PID 0 */
2563 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
2564 }
2565 else
2566 {
2567 /* Put the PID 1 */
2568 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
2569 }
2570 }
2571 else
2572 {
2573 if (hhcd->hc[ch_num & 0xFU].toggle_in == 0U)
2574 {
2575 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
2576 }
2577 else
2578 {
2579 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
2580 }
2581 }
2582 break;
2583
2584 case EP_TYPE_INTR:
2585 if (direction == 0U)
2586 {
2587 /* Set the Data Toggle bit as per the Flag */
2588 if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
2589 {
2590 /* Put the PID 0 */
2591 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
2592 }
2593 else
2594 {
2595 /* Put the PID 1 */
2596 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
2597 }
2598 }
2599 else
2600 {
2601 if (hhcd->hc[ch_num & 0xFU].toggle_in == 0U)
2602 {
2603 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
2604 }
2605 else
2606 {
2607 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
2608 }
2609 }
2610 break;
2611
2612 case EP_TYPE_ISOC:
2613 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
2614 break;
2615
2616 default:
2617 break;
2618 }
2619
2620 hhcd->hc[ch_num & 0xFU].xfer_buff = pbuff;
2621 hhcd->hc[ch_num & 0xFU].xfer_len = length;
2622 hhcd->hc[ch_num & 0xFU].xfer_len_db = length;
2623 hhcd->hc[ch_num & 0xFU].urb_state = URB_IDLE;
2624 hhcd->hc[ch_num & 0xFU].xfer_count = 0U;
2625 hhcd->hc[ch_num & 0xFU].state = HC_IDLE;
2626
2627 return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num & 0xFU]);
2628 }
2629 /**
2630 * @brief Handle HCD interrupt request.
2631 * @param hhcd HCD handle
2632 * @retval None
2633 */
HAL_HCD_IRQHandler(HCD_HandleTypeDef * hhcd)2634 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
2635 {
2636 uint8_t phy_chnum;
2637 uint8_t chnum;
2638 uint32_t epch_reg;
2639 uint32_t wIstr = USB_ReadInterrupts(hhcd->Instance);
2640
2641 /* Port Change Detected (Connection/Disconnection) */
2642 if ((wIstr & USB_ISTR_DCON) == USB_ISTR_DCON)
2643 {
2644 /* Clear Flag */
2645 __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_DCON);
2646
2647 /* Call Port IRQHandler */
2648 HCD_Port_IRQHandler(hhcd);
2649
2650 return;
2651 }
2652
2653 /* Correct Transaction Detected -------*/
2654 if ((wIstr & USB_ISTR_CTR) == USB_ISTR_CTR)
2655 {
2656 /* Handle Host channel Interrupt */
2657 for (phy_chnum = 0U; phy_chnum < hhcd->Init.Host_channels; phy_chnum++)
2658 {
2659 if ((HCD_GET_CHANNEL(hhcd->Instance, phy_chnum) & USB_CH_VTRX) != 0U)
2660 {
2661 /* Get Logical channel to check if the channel is already opened */
2662 chnum = HAL_HCD_GetLogical_Channel(hhcd, phy_chnum, 1U);
2663
2664 if (chnum != HCD_LOGICAL_CH_NOT_OPENED)
2665 {
2666 /* Call Channel_IN_IRQ() */
2667 HCD_HC_IN_IRQHandler(hhcd, chnum);
2668 }
2669 else
2670 {
2671 /*Channel was not closed correctly still have interrupt */
2672 epch_reg = HCD_GET_CHANNEL(hhcd->Instance, phy_chnum);
2673 epch_reg = (epch_reg & (USB_CHEP_REG_MASK & (~USB_CH_ERRRX) & (~USB_CH_VTRX))) |
2674 (USB_CH_VTTX | USB_CH_ERRTX);
2675
2676 HCD_SET_CHANNEL(hhcd->Instance, phy_chnum, epch_reg);
2677 }
2678 }
2679
2680 if ((HCD_GET_CHANNEL(hhcd->Instance, phy_chnum) & USB_CH_VTTX) != 0U)
2681 {
2682 /* Get Logical channel to check if the channel is already opened */
2683 chnum = HAL_HCD_GetLogical_Channel(hhcd, phy_chnum, 0U);
2684
2685 if (chnum != HCD_LOGICAL_CH_NOT_OPENED)
2686 {
2687 /*Call Channel_OUT_IRQ()*/
2688 HCD_HC_OUT_IRQHandler(hhcd, chnum);
2689 }
2690 else
2691 {
2692 /* Clear Error & unwanted VTTX or Channel was not closed correctly */
2693 epch_reg = HCD_GET_CHANNEL(hhcd->Instance, phy_chnum);
2694 epch_reg = (epch_reg & (USB_CHEP_REG_MASK & (~USB_CH_ERRTX) & (~USB_CH_VTTX))) |
2695 (USB_CH_VTRX | USB_CH_ERRRX);
2696
2697 HCD_SET_CHANNEL(hhcd->Instance, phy_chnum, epch_reg);
2698 }
2699 }
2700 }
2701
2702 return;
2703 }
2704
2705 /* Wakeup Flag Detected */
2706 if ((wIstr & USB_ISTR_WKUP) == USB_ISTR_WKUP)
2707 {
2708 if (hhcd->HostState == HCD_HCD_STATE_SUSPEND)
2709 {
2710 /* Set The L2Resume bit */
2711 hhcd->Instance->CNTR |= USB_CNTR_L2RES;
2712
2713 /* Clear the wake-up flag */
2714 __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_WKUP);
2715
2716 /* Update the USB Software state machine */
2717 HAL_HCD_ResumeCallback(hhcd);
2718 hhcd->HostState = HCD_HCD_STATE_RESUME;
2719 }
2720 else
2721 {
2722 /* Clear the wake-up flag */
2723 __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_WKUP);
2724 }
2725
2726 return;
2727 }
2728
2729 /* Global Error Flag Detected */
2730 if ((wIstr & USB_ISTR_ERR) == USB_ISTR_ERR)
2731 {
2732 __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_ERR);
2733
2734 return;
2735 }
2736
2737 /* PMA Overrun detected */
2738 if ((wIstr & USB_ISTR_PMAOVR) == USB_ISTR_PMAOVR)
2739 {
2740 __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_PMAOVR);
2741
2742 return;
2743 }
2744
2745 /* Suspend Detected */
2746 if ((wIstr & USB_ISTR_SUSP) == USB_ISTR_SUSP)
2747 {
2748 /* Set HAL State to Suspend */
2749 hhcd->HostState = HCD_HCD_STATE_SUSPEND;
2750
2751 /* Force low-power mode in the macrocell */
2752 hhcd->Instance->CNTR |= USB_CNTR_SUSPEN;
2753
2754 /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
2755 __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_SUSP);
2756
2757 /* Call suspend Callback */
2758 HAL_HCD_SuspendCallback(hhcd);
2759
2760 return;
2761 }
2762
2763 /* Start Of Frame Detected */
2764 if ((wIstr & USB_ISTR_SOF) == USB_ISTR_SOF)
2765 {
2766 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2767 hhcd->SOFCallback(hhcd);
2768 #else
2769 HAL_HCD_SOF_Callback(hhcd);
2770 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2771
2772 __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_SOF);
2773
2774 /* when first SOF is detected after USB_RESET is asserted */
2775 if (hhcd->HostState == HCD_HCD_STATE_RESETED)
2776 {
2777 /* HAL State */
2778 hhcd->HostState = HCD_HCD_STATE_RUN;
2779
2780 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2781 hhcd->PortEnabledCallback(hhcd);
2782 #else
2783 HAL_HCD_PortEnabled_Callback(hhcd);
2784 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2785 }
2786
2787 return;
2788 }
2789 }
2790
2791 /**
2792 * @brief SOF callback.
2793 * @param hhcd HCD handle
2794 * @retval None
2795 */
HAL_HCD_SOF_Callback(HCD_HandleTypeDef * hhcd)2796 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
2797 {
2798 /* Prevent unused argument(s) compilation warning */
2799 UNUSED(hhcd);
2800
2801 /* NOTE : This function Should not be modified, when the callback is needed,
2802 the HAL_HCD_SOF_Callback could be implemented in the user file
2803 */
2804 }
2805
2806 /**
2807 * @brief Connection Event callback.
2808 * @param hhcd HCD handle
2809 * @retval None
2810 */
HAL_HCD_Connect_Callback(HCD_HandleTypeDef * hhcd)2811 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
2812 {
2813 /* Prevent unused argument(s) compilation warning */
2814 UNUSED(hhcd);
2815
2816 /* NOTE : This function Should not be modified, when the callback is needed,
2817 the HAL_HCD_Connect_Callback could be implemented in the user file
2818 */
2819 }
2820
2821 /**
2822 * @brief Disconnection Event callback.
2823 * @param hhcd HCD handle
2824 * @retval None
2825 */
HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef * hhcd)2826 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
2827 {
2828 /* Prevent unused argument(s) compilation warning */
2829 UNUSED(hhcd);
2830
2831 /* NOTE : This function Should not be modified, when the callback is needed,
2832 the HAL_HCD_Disconnect_Callback could be implemented in the user file
2833 */
2834 }
2835 /**
2836 * @brief Port Enabled Event callback.
2837 * @param hhcd HCD handle
2838 * @retval None
2839 */
HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef * hhcd)2840 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
2841 {
2842 /* Prevent unused argument(s) compilation warning */
2843 UNUSED(hhcd);
2844
2845 /* NOTE : This function should not be modified, when the callback is needed,
2846 the HAL_HCD_Disconnect_Callback could be implemented in the user file
2847 */
2848 }
2849 /**
2850 * @brief Port Disabled Event callback.
2851 * @param hhcd HCD handle
2852 * @retval None
2853 */
HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef * hhcd)2854 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
2855 {
2856 /* Prevent unused argument(s) compilation warning */
2857 UNUSED(hhcd);
2858
2859 /* NOTE : This function should not be modified, when the callback is needed,
2860 the HAL_HCD_Disconnect_Callback could be implemented in the user file
2861 */
2862 }
2863
2864 /**
2865 * @brief Notify URB state change callback.
2866 * @param hhcd HCD handle
2867 * @param chnum Channel number.
2868 * This parameter can be a value from 1 to 15
2869 * @param urb_state
2870 * This parameter can be one of these values:
2871 * URB_IDLE/
2872 * URB_DONE/
2873 * URB_NOTREADY/
2874 * URB_NYET/
2875 * URB_ERROR/
2876 * URB_STALL/
2877 * @retval None
2878 */
HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef * hhcd,uint8_t chnum,HCD_URBStateTypeDef urb_state)2879 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd,
2880 uint8_t chnum, HCD_URBStateTypeDef urb_state)
2881 {
2882 /* Prevent unused argument(s) compilation warning */
2883 UNUSED(hhcd);
2884 UNUSED(chnum);
2885 UNUSED(urb_state);
2886
2887 /* NOTE : This function Should not be modified, when the callback is needed,
2888 the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
2889 */
2890 }
2891 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2892 /**
2893 * @brief Register a User USB HCD Callback
2894 * To be used instead of the weak predefined callback
2895 * @param hhcd USB HCD handle
2896 * @param CallbackID ID of the callback to be registered
2897 * This parameter can be one of the following values:
2898 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
2899 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
2900 * @arg @ref HAL_HCD_DISCONNECT_CB_ID HCD Disconnect callback ID
2901 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
2902 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
2903 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
2904 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
2905 * @param pCallback pointer to the Callback function
2906 * @retval HAL status
2907 */
HAL_HCD_RegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID,pHCD_CallbackTypeDef pCallback)2908 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
2909 HAL_HCD_CallbackIDTypeDef CallbackID,
2910 pHCD_CallbackTypeDef pCallback)
2911 {
2912 HAL_StatusTypeDef status = HAL_OK;
2913
2914 if (pCallback == NULL)
2915 {
2916 /* Update the error code */
2917 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
2918 return HAL_ERROR;
2919 }
2920 /* Process locked */
2921 __HAL_LOCK(hhcd);
2922
2923 if (hhcd->State == HAL_HCD_STATE_READY)
2924 {
2925 switch (CallbackID)
2926 {
2927 case HAL_HCD_SOF_CB_ID :
2928 hhcd->SOFCallback = pCallback;
2929 break;
2930
2931 case HAL_HCD_CONNECT_CB_ID :
2932 hhcd->ConnectCallback = pCallback;
2933 break;
2934
2935 case HAL_HCD_DISCONNECT_CB_ID :
2936 hhcd->DisconnectCallback = pCallback;
2937 break;
2938
2939 case HAL_HCD_PORT_ENABLED_CB_ID :
2940 hhcd->PortEnabledCallback = pCallback;
2941 break;
2942
2943 case HAL_HCD_PORT_DISABLED_CB_ID :
2944 hhcd->PortDisabledCallback = pCallback;
2945 break;
2946
2947 case HAL_HCD_MSPINIT_CB_ID :
2948 hhcd->MspInitCallback = pCallback;
2949 break;
2950
2951 case HAL_HCD_MSPDEINIT_CB_ID :
2952 hhcd->MspDeInitCallback = pCallback;
2953 break;
2954
2955 default :
2956 /* Update the error code */
2957 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
2958 /* Return error status */
2959 status = HAL_ERROR;
2960 break;
2961 }
2962 }
2963 else if (hhcd->State == HAL_HCD_STATE_RESET)
2964 {
2965 switch (CallbackID)
2966 {
2967 case HAL_HCD_MSPINIT_CB_ID :
2968 hhcd->MspInitCallback = pCallback;
2969 break;
2970
2971 case HAL_HCD_MSPDEINIT_CB_ID :
2972 hhcd->MspDeInitCallback = pCallback;
2973 break;
2974
2975 default :
2976 /* Update the error code */
2977 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
2978 /* Return error status */
2979 status = HAL_ERROR;
2980 break;
2981 }
2982 }
2983 else
2984 {
2985 /* Update the error code */
2986 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
2987 /* Return error status */
2988 status = HAL_ERROR;
2989 }
2990
2991 /* Release Lock */
2992 __HAL_UNLOCK(hhcd);
2993 return status;
2994 }
2995
2996 /**
2997 * @brief Unregister an USB HCD Callback
2998 * USB HCD callback is redirected to the weak predefined callback
2999 * @param hhcd USB HCD handle
3000 * @param CallbackID ID of the callback to be unregistered
3001 * This parameter can be one of the following values:
3002 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
3003 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
3004 * @arg @ref HAL_HCD_DISCONNECT_CB_ID DRD HCD Disconnect callback ID
3005 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
3006 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
3007 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
3008 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
3009 * @retval HAL status
3010 */
HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID)3011 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd,
3012 HAL_HCD_CallbackIDTypeDef CallbackID)
3013 {
3014 HAL_StatusTypeDef status = HAL_OK;
3015
3016 /* Process locked */
3017 __HAL_LOCK(hhcd);
3018
3019 /* Setup Legacy weak Callbacks */
3020 if (hhcd->State == HAL_HCD_STATE_READY)
3021 {
3022 switch (CallbackID)
3023 {
3024 case HAL_HCD_SOF_CB_ID :
3025 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
3026 break;
3027
3028 case HAL_HCD_CONNECT_CB_ID :
3029 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
3030 break;
3031
3032 case HAL_HCD_DISCONNECT_CB_ID :
3033 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
3034 break;
3035
3036 case HAL_HCD_PORT_ENABLED_CB_ID :
3037 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
3038 break;
3039
3040 case HAL_HCD_PORT_DISABLED_CB_ID :
3041 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
3042 break;
3043
3044 case HAL_HCD_MSPINIT_CB_ID :
3045 hhcd->MspInitCallback = HAL_HCD_MspInit;
3046 break;
3047
3048 case HAL_HCD_MSPDEINIT_CB_ID :
3049 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
3050 break;
3051
3052 default :
3053 /* Update the error code */
3054 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
3055
3056 /* Return error status */
3057 status = HAL_ERROR;
3058 break;
3059 }
3060 }
3061 else if (hhcd->State == HAL_HCD_STATE_RESET)
3062 {
3063 switch (CallbackID)
3064 {
3065 case HAL_HCD_MSPINIT_CB_ID :
3066 hhcd->MspInitCallback = HAL_HCD_MspInit;
3067 break;
3068
3069 case HAL_HCD_MSPDEINIT_CB_ID :
3070 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
3071 break;
3072
3073 default :
3074 /* Update the error code */
3075 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
3076
3077 /* Return error status */
3078 status = HAL_ERROR;
3079 break;
3080 }
3081 }
3082 else
3083 {
3084 /* Update the error code */
3085 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
3086
3087 /* Return error status */
3088 status = HAL_ERROR;
3089 }
3090
3091 /* Release Lock */
3092 __HAL_UNLOCK(hhcd);
3093 return status;
3094 }
3095
3096 /**
3097 * @brief Register USB HCD Host Channel Notify URB Change Callback
3098 * To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
3099 * @param hhcd HCD handle
3100 * @param pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
3101 * @retval HAL status
3102 */
HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd,pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)3103 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
3104 pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
3105 {
3106 HAL_StatusTypeDef status = HAL_OK;
3107
3108 if (pCallback == NULL)
3109 {
3110 /* Update the error code */
3111 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
3112
3113 return HAL_ERROR;
3114 }
3115
3116 /* Process locked */
3117 __HAL_LOCK(hhcd);
3118
3119 if (hhcd->State == HAL_HCD_STATE_READY)
3120 {
3121 hhcd->HC_NotifyURBChangeCallback = pCallback;
3122 }
3123 else
3124 {
3125 /* Update the error code */
3126 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
3127
3128 /* Return error status */
3129 status = HAL_ERROR;
3130 }
3131
3132 /* Release Lock */
3133 __HAL_UNLOCK(hhcd);
3134
3135 return status;
3136 }
3137
3138 /**
3139 * @brief Unregister the USB HCD Host Channel Notify URB Change Callback
3140 * USB HCD Host Channel Notify URB Change Callback is redirected
3141 * to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
3142 * @param hhcd HCD handle
3143 * @retval HAL status
3144 */
HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd)3145 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
3146 {
3147 HAL_StatusTypeDef status = HAL_OK;
3148
3149 /* Process locked */
3150 __HAL_LOCK(hhcd);
3151
3152 if (hhcd->State == HAL_HCD_STATE_READY)
3153 {
3154 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
3155 }
3156 else
3157 {
3158 /* Update the error code */
3159 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
3160
3161 /* Return error status */
3162 status = HAL_ERROR;
3163 }
3164
3165 /* Release Lock */
3166 __HAL_UNLOCK(hhcd);
3167
3168 return status;
3169 }
3170 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
3171
3172
3173 /**
3174 * @}
3175 */
3176
3177 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
3178 * @brief Management functions
3179 *
3180 @verbatim
3181 ===============================================================================
3182 ##### Peripheral Control functions #####
3183 ===============================================================================
3184 [..]
3185 This subsection provides a set of functions allowing to control the HCD data
3186 transfers.
3187
3188 @endverbatim
3189 * @{
3190 */
3191
3192 /**
3193 * @brief Start the host driver.
3194 * @param hhcd HCD handle
3195 * @retval HAL status
3196 */
HAL_HCD_Start(HCD_HandleTypeDef * hhcd)3197 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
3198 {
3199 __HAL_LOCK(hhcd);
3200
3201 /*Set the PullDown on the PHY */
3202 hhcd->Instance->BCDR |= USB_BCDR_DPPD;
3203
3204 /* Clear Reset */
3205 hhcd->Instance->CNTR &= ~USB_CNTR_USBRST;
3206
3207 /*Remove PowerDown */
3208 hhcd->Instance->CNTR &= ~USB_CNTR_PDWN;
3209
3210 __HAL_UNLOCK(hhcd);
3211
3212 return HAL_OK;
3213 }
3214
3215 /**
3216 * @brief Stop the host driver.
3217 * @param hhcd HCD handle
3218 * @retval HAL status
3219 */
HAL_HCD_Stop(HCD_HandleTypeDef * hhcd)3220 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
3221 {
3222 __HAL_LOCK(hhcd);
3223 /*Stop the Host IP: setting powerdown */
3224 (void)USB_StopHost(hhcd->Instance);
3225
3226 /* clear all allocated virtual channel */
3227 HAL_HCD_ClearPhyChannel(hhcd);
3228
3229 /* Reset the PMA current pointer */
3230 (void)HAL_HCD_PMAReset(hhcd);
3231
3232 /* reset Ep0 Pma allocation state */
3233 hhcd->ep0_PmaAllocState = 0U;
3234
3235 __HAL_UNLOCK(hhcd);
3236 return HAL_OK;
3237 }
3238
3239 /**
3240 * @brief Put the Device in suspend mode
3241 * @param hhcd HCD handle
3242 * @retval HAL status
3243 */
HAL_HCD_Suspend(HCD_HandleTypeDef * hhcd)3244 HAL_StatusTypeDef HAL_HCD_Suspend(HCD_HandleTypeDef *hhcd)
3245 {
3246 __IO uint32_t count = 0U;
3247
3248 /* Set Suspend Mode */
3249 hhcd->Instance->CNTR |= USB_CNTR_SUSPEN;
3250
3251 /* wait for Suspend Ready */
3252 while ((hhcd->Instance->CNTR & USB_CNTR_SUSPRDY) == 0U)
3253 {
3254 if (++count > 0xFFFFFFU)
3255 {
3256 return HAL_TIMEOUT;
3257 }
3258 }
3259
3260 return HAL_OK;
3261 }
3262
3263 /**
3264 * @brief Resume host port
3265 * @param hhcd HCD handle
3266 * @retval HAL status
3267 */
HAL_HCD_Resume(HCD_HandleTypeDef * hhcd)3268 HAL_StatusTypeDef HAL_HCD_Resume(HCD_HandleTypeDef *hhcd)
3269 {
3270 /* Set Resume bit */
3271 hhcd->Instance->CNTR |= USB_CNTR_L2RES;
3272
3273 return HAL_OK;
3274 }
3275
3276 /**
3277 * @brief Reset the host port.
3278 * @param hhcd HCD handle
3279 * @retval HAL status
3280 */
HAL_HCD_ResetPort(HCD_HandleTypeDef * hhcd)3281 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
3282 {
3283 __HAL_LOCK(hhcd);
3284
3285 /* Reset the USB Port by inserting an SE0 on the bus */
3286 (void)USB_ResetPort(hhcd->Instance);
3287
3288 if (hhcd->HostState == HCD_HCD_STATE_CONNECTED)
3289 {
3290 hhcd->HostState = HCD_HCD_STATE_RESETED;
3291 }
3292 __HAL_UNLOCK(hhcd);
3293
3294 return HAL_OK;
3295 }
3296
3297 /**
3298 * @brief Resme the host port.
3299 * @param hhcd HCD handle
3300 * @retval HAL status
3301 */
HAL_HCD_ResumePort(HCD_HandleTypeDef * hhcd)3302 HAL_StatusTypeDef HAL_HCD_ResumePort(HCD_HandleTypeDef *hhcd)
3303 {
3304 /* Set Resume bit */
3305 hhcd->Instance->CNTR |= USB_CNTR_L2RES;
3306 HAL_Delay(30U);
3307
3308 /* Clear Resume bit */
3309 hhcd->Instance->CNTR &= ~USB_CNTR_L2RES;
3310
3311 return HAL_OK;
3312 }
3313
3314
3315 /**
3316 * @}
3317 */
3318
3319 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
3320 * @brief Peripheral State functions
3321 *
3322 @verbatim
3323 ===============================================================================
3324 ##### Peripheral State functions #####
3325 ===============================================================================
3326 [..]
3327 This subsection permits to get in run-time the status of the peripheral
3328 and the data flow.
3329
3330 @endverbatim
3331 * @{
3332 */
3333
3334 /**
3335 * @brief Return the HCD handle state.
3336 * @param hhcd HCD handle
3337 * @retval HAL state
3338 */
HAL_HCD_GetState(HCD_HandleTypeDef const * hhcd)3339 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef const *hhcd)
3340 {
3341 return hhcd->State;
3342 }
3343
3344 /**
3345 * @brief Return URB state for a channel.
3346 * @param hhcd HCD handle
3347 * @param chnum Channel number.
3348 * This parameter can be a value from 1 to 15
3349 * @retval URB state.
3350 * This parameter can be one of these values:
3351 * URB_IDLE/
3352 * URB_DONE/
3353 * URB_NOTREADY/
3354 * URB_NYET/
3355 * URB_ERROR/
3356 * URB_STALL
3357 */
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)3358 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
3359 {
3360 return hhcd->hc[chnum].urb_state;
3361 }
3362
3363
3364 /**
3365 * @brief Return the last host transfer size.
3366 * @param hhcd HCD handle
3367 * @param chnum Channel number.
3368 * This parameter can be a value from 1 to 15
3369 * @retval last transfer size in byte
3370 */
HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const * hhcd,uint8_t chnum)3371 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
3372 {
3373 return hhcd->hc[chnum].xfer_count;
3374 }
3375
3376 /**
3377 * @brief Return the Host Channel state.
3378 * @param hhcd HCD handle
3379 * @param chnum Channel number.
3380 * This parameter can be a value from 1 to 15
3381 * @retval Host channel state
3382 * This parameter can be one of these values:
3383 * HC_IDLE/
3384 * HC_XFRC/
3385 * HC_HALTED/
3386 * HC_NYET/
3387 * HC_NAK/
3388 * HC_STALL/
3389 * HC_XACTERR/
3390 * HC_BBLERR/
3391 * HC_DATATGLERR
3392 */
HAL_HCD_HC_GetState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)3393 HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
3394 {
3395 return hhcd->hc[chnum].state;
3396 }
3397
3398 /**
3399 * @brief Return the current Host frame number.
3400 * @param hhcd HCD handle
3401 * @retval Current Host frame number
3402 */
HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef * hhcd)3403 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
3404 {
3405 return (USB_GetCurrentFrame(hhcd->Instance));
3406 }
3407
3408 /**
3409 * @brief Return the Host enumeration speed.
3410 * @param hhcd HCD handle
3411 * @retval speed : Device speed after Host enumeration
3412 * This parameter can be one of these values:
3413 * @arg HCD_DEVICE_SPEED_HIGH: High speed mode
3414 * @arg HCD_DEVICE_SPEED_FULL: Full speed mode
3415 * @arg HCD_DEVICE_SPEED_LOW: Low speed mode
3416 */
HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef * hhcd)3417 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
3418 {
3419 return (USB_GetHostSpeed(hhcd->Instance));
3420 }
3421
3422 /**
3423 * @brief Set host channel Hub Information.
3424 * @param hhcd HCD handle
3425 * @param ch_num Channel number.
3426 * This parameter can be a value from 1 to 15
3427 * @param addr Hub address
3428 * @param PortNbr Hub port number
3429 * @retval HAL status
3430 */
HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t addr,uint8_t PortNbr)3431 HAL_StatusTypeDef HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
3432 uint8_t addr, uint8_t PortNbr)
3433 {
3434 hhcd->hc[ch_num].hub_addr = addr;
3435 hhcd->hc[ch_num].hub_port_nbr = PortNbr;
3436
3437 return HAL_OK;
3438 }
3439
3440
3441 /**
3442 * @brief Clear host channel hub information.
3443 * @param hhcd HCD handle
3444 * @param ch_num Channel number.
3445 * This parameter can be a value from 1 to 15
3446 * @retval HAL status
3447 */
HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num)3448 HAL_StatusTypeDef HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
3449 {
3450 hhcd->hc[ch_num].hub_addr = 0U;
3451 hhcd->hc[ch_num].hub_port_nbr = 0U;
3452
3453 return HAL_OK;
3454 }
3455
3456 #if (USE_USB_DOUBLE_BUFFER == 1U)
3457 /**
3458 * @brief Handle Host Channel OUT Double Buffer Bulk requests.
3459 * @param hhcd HCD handle
3460 * @param ch_num Channel number This parameter can be a value from 1 to 15
3461 * @param phy_chnum Physical Channel number [0..7]
3462 * @param regvalue contain Snapshot of the EPCHn register when ISR is detected
3463 * @retval none
3464 */
HCD_HC_OUT_BulkDb(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)3465 static void HCD_HC_OUT_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
3466 uint8_t phy_chnum, uint32_t regvalue)
3467 {
3468 uint16_t data_xfr;
3469 uint16_t len;
3470
3471 /* Send Buffer0 */
3472 if ((regvalue & USB_CH_DTOG_TX) != 0U)
3473 {
3474 data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->TXBD & 0x03FF0000U) >> 16U);
3475
3476 if (hhcd->hc[ch_num & 0xFU].xfer_len >= data_xfr)
3477 {
3478 hhcd->hc[ch_num & 0xFU].xfer_len -= data_xfr;
3479 }
3480 else
3481 {
3482 hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
3483 }
3484
3485 /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
3486 if (hhcd->hc[ch_num & 0xFU].xfer_len != 0U)
3487 {
3488 /* manage multiple Xfer */
3489 hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
3490
3491 /* check if we need to free user buffer */
3492 if ((regvalue & USB_CH_DTOG_RX) != 0U)
3493 {
3494 /* Toggle SwBuff */
3495 HCD_CLEAR_TX_DTOG(hhcd->Instance, phy_chnum);
3496 HCD_CLEAR_RX_DTOG(hhcd->Instance, phy_chnum);
3497 HCD_TX_DTOG(hhcd->Instance, phy_chnum);
3498 }
3499
3500 /* hhcd->hc[ch_num&0xFU].xfer_len_db==0 ==> when all data are written in the PMA to yet transferred */
3501 if (hhcd->hc[ch_num & 0xFU].xfer_len_db > 0U) /* Still data to fill in the buffer */
3502 {
3503 hhcd->hc[ch_num & 0xFU].xfer_buff += data_xfr;
3504
3505 /* calculate len of new buffer to fill */
3506 if (hhcd->hc[ch_num & 0xFU].xfer_len_db > hhcd->hc[ch_num & 0xFU].max_packet)
3507 {
3508 len = (uint16_t)hhcd->hc[ch_num & 0xFU].max_packet;
3509 hhcd->hc[ch_num & 0xFU].xfer_len_db -= len;
3510 }
3511 else
3512 {
3513 len = (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_len_db;
3514 hhcd->hc[ch_num & 0xFU].xfer_len_db = 0U; /* end of fill buffer */
3515 }
3516
3517 /* Write remaining data to Buffer0 */
3518 HCD_SET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum, 1U, (uint16_t)len);
3519 USB_WritePMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3520 hhcd->hc[ch_num & 0xFU].pmaaddr0, (uint16_t)len);
3521 }
3522 /* start a new transfer */
3523 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_VALID);
3524 }
3525 else
3526 {
3527 /* Transfer complete state */
3528 hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
3529 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
3530 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
3531 hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
3532 /* Close the Channel */
3533 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
3534 }
3535 }
3536 else
3537 {
3538 /* Send Buffer1 */
3539 data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->RXBD & 0x03FF0000U) >> 16U);
3540
3541 if (hhcd->hc[ch_num & 0xFU].xfer_len >= data_xfr) /* updated */
3542 {
3543 hhcd->hc[ch_num & 0xFU].xfer_len -= data_xfr;
3544 }
3545
3546 /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
3547 if (hhcd->hc[ch_num & 0xFU].xfer_len != 0U)
3548 {
3549 /* manage multiple Xfer */
3550 hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
3551
3552 /* check if we need to free user buffer */
3553 if ((regvalue & USB_CH_DTOG_RX) == 0U)
3554 {
3555 /* Toggle SwBuff */
3556 HCD_CLEAR_TX_DTOG(hhcd->Instance, phy_chnum);
3557 HCD_CLEAR_RX_DTOG(hhcd->Instance, phy_chnum);
3558 HCD_RX_DTOG(hhcd->Instance, phy_chnum);
3559 }
3560
3561 /* hhcd->hc[ch_num&0xFU].xfer_len_db==0 ==> when all data are written in the PMA to yet transferred */
3562 if (hhcd->hc[ch_num & 0xFU].xfer_len_db > 0U) /* Still data to fill in the buffer */
3563 {
3564 hhcd->hc[ch_num & 0xFU].xfer_buff += data_xfr;
3565
3566 /* calculate len of new buffer to fill */
3567 if (hhcd->hc[ch_num & 0xFU].xfer_len_db > hhcd->hc[ch_num & 0xFU].max_packet)
3568 {
3569 len = hhcd->hc[ch_num & 0xFU].max_packet;
3570 hhcd->hc[ch_num & 0xFU].xfer_len_db -= len;
3571 }
3572 else
3573 {
3574 len = (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_len_db;
3575 hhcd->hc[ch_num & 0xFU].xfer_len_db = 0U; /* end of fill buffer */
3576 }
3577
3578 /* Write remaining data to Buffer0 */
3579 HCD_SET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum, 1U, (uint16_t)len);
3580
3581 USB_WritePMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3582 hhcd->hc[ch_num & 0xFU].pmaaddr1, (uint16_t)len);
3583 }
3584
3585 /* start a new transfer */
3586 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_VALID);
3587 }
3588 else
3589 {
3590 /* Transfer complete state */
3591 hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
3592 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
3593 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
3594 hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
3595
3596 /* Close the channel */
3597 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
3598 }
3599 }
3600 }
3601
3602
3603 /**
3604 * @brief Handle Host Channel IN Double Buffer Bulk requests.
3605 * @param hhcd HCD handle
3606 * @param ch_num Channel number: This parameter can be a value from 1 to 15
3607 * @param phy_chnum Physical Channel number [0..7]
3608 * @param regvalue contain Snapshot of the EPCHn register when ISR is detected
3609 * @retval none
3610 */
HCD_HC_IN_BulkDb(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)3611 static void HCD_HC_IN_BulkDb(HCD_HandleTypeDef *hhcd,
3612 uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue)
3613 {
3614 uint16_t received_bytes;
3615
3616 /* Read from Buffer 0 */
3617 if ((regvalue & USB_CH_DTOG_RX) != 0U)
3618 {
3619 received_bytes = (uint16_t)HCD_GET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum);
3620
3621 if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
3622 {
3623 hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
3624 }
3625 else
3626 {
3627 hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
3628 }
3629
3630 /* Check if we Need to free the other buffer for the IP */
3631 if ((hhcd->hc[ch_num & 0xFU].xfer_len != 0U) && ((regvalue & USB_CH_DTOG_TX) != 0U))
3632 {
3633 /* Toggle SwBuff to Allow the IP to submit a new IN */
3634 HCD_FREE_USER_BUFFER(hhcd->Instance, phy_chnum, 0U);
3635 }
3636
3637 /* Read the byte from PMA to user Buffer(System Memory) */
3638 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3639 hhcd->hc[ch_num & 0xFU].pmaaddr0, (uint16_t)received_bytes);
3640 }
3641 else
3642 {
3643 /* Read from Buffer 1 */
3644 received_bytes = (uint16_t) HCD_GET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum);
3645
3646 if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
3647 {
3648 hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
3649 }
3650 else
3651 {
3652 hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
3653 }
3654
3655 /* Check if we Need to free the other buffer for the IP */
3656 if ((hhcd->hc[ch_num & 0xFU].xfer_len != 0U) && ((regvalue & USB_CH_DTOG_TX) == 0U))
3657 {
3658 /* Toggle SwBuff */
3659 HCD_FREE_USER_BUFFER(hhcd->Instance, phy_chnum, 0U);
3660 }
3661
3662 /* Read the byte from PMA to user Buffer(System Memory) */
3663 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3664 hhcd->hc[ch_num & 0xFU].pmaaddr1, (uint16_t)received_bytes);
3665 }
3666
3667 /* update the global number of all received bytes */
3668 hhcd->hc[ch_num & 0xFU].xfer_count += received_bytes;
3669
3670 /* Transfer complete state */
3671 hhcd->hc[ch_num & 0xFU].state = HC_ACK;
3672 hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
3673
3674 if ((hhcd->hc[ch_num & 0xFU].xfer_len == 0U) ||
3675 ((received_bytes < hhcd->hc[ch_num & 0xFU].max_packet)))
3676 {
3677 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
3678 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
3679
3680 /* disable channel */
3681 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
3682 }
3683 else
3684 {
3685 hhcd->hc[ch_num & 0xFU].xfer_buff += received_bytes;
3686
3687 /* Reactivate the Channel Submit an other URB since the Transfer is not yet completed */
3688 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_STRX);
3689 }
3690 }
3691 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
3692
3693 /**
3694 * @brief Handle Host Channel IN Isochronous Transaction
3695 * @param hhcd HCD handle
3696 * @param ch_num Channel number: This parameter can be a value from 1 to 15
3697 * @param phy_chnum Physical Channel number [0..7]
3698 * @param regvalue contain Snapshot of the EPCHn register when ISR is detected
3699 * @retval none
3700 */
HCD_HC_IN_ISO(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)3701 static void inline HCD_HC_IN_ISO(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
3702 uint8_t phy_chnum, uint32_t regvalue)
3703 {
3704 /* Check if Double buffer isochronous */
3705 if ((regvalue & USB_CH_KIND) != 0U)
3706 {
3707 /* Get Data IN Packet */
3708 hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_RX_CNT(hhcd->Instance, phy_chnum);
3709 if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
3710 {
3711 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3712 hhcd->hc[ch_num & 0xFU].pmaadress,
3713 (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
3714
3715 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
3716 }
3717 }
3718 #if (USE_USB_DOUBLE_BUFFER == 1U)
3719 else /* double buffer isochronous */
3720 {
3721 /* Read from Buffer0 */
3722 if ((regvalue & USB_CH_DTOG_RX) != 0U)
3723 {
3724 /* Get number of Received byte in buffer0 */
3725 hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum);
3726
3727 if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
3728 {
3729 /* Read from Buffer0 */
3730 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3731 hhcd->hc[ch_num & 0xFU].pmaaddr0,
3732 (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
3733
3734 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
3735 }
3736 }
3737 else
3738 {
3739 /* Get number of Received byte in buffer1 */
3740 hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum);
3741
3742 if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
3743 {
3744 /* Read from Buffer1 */
3745 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3746 hhcd->hc[ch_num & 0xFU].pmaaddr1,
3747 (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
3748
3749 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
3750 }
3751 }
3752 }
3753 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
3754
3755 /* Transfer complete state */
3756 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
3757
3758 /* Clear VTRX */
3759 HCD_CLEAR_RX_CH_CTR(hhcd->Instance, phy_chnum);
3760 }
3761
3762 /**
3763 * @brief Handle Host Channel IN interrupt requests.
3764 * @param hhcd HCD handle
3765 * @param ch_num Channel number
3766 * This parameter can be a value from 1 to 15
3767 * @retval none
3768 */
HCD_HC_IN_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t ch_num)3769 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
3770 {
3771 uint16_t received_bytes;
3772 uint8_t phy_chnum = (uint8_t)__HAL_HCD_GET_CHNUM(hhcd);
3773
3774 /*Take a Flag snapshot from the CHEP register, due to STRX bits are used for both control and status */
3775 uint32_t ch_reg = HCD_GET_CHANNEL(hhcd->Instance, phy_chnum);
3776
3777 /* Manage Correct Transaction */
3778 if ((ch_reg & USB_CH_ERRRX) == 0U)
3779 {
3780 /* Isochronous Channel */
3781 if ((ch_reg & USB_CH_UTYPE) == USB_EP_ISOCHRONOUS)
3782 {
3783 HCD_HC_IN_ISO(hhcd, ch_num, phy_chnum, ch_reg);
3784 }
3785 else
3786 {
3787 /* manage ACK response single buffer */
3788 if (((ch_reg) & USB_CH_RX_STRX) == USB_CH_RX_ACK_SBUF)
3789 {
3790 /* Get Control Data OUT Packet */
3791 received_bytes = (uint16_t)HCD_GET_CH_RX_CNT(hhcd->Instance, phy_chnum);
3792
3793 /* Read the byte from PMA to user Buffer(System Memory) */
3794 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3795 hhcd->hc[ch_num & 0xFU].pmaadress, (uint16_t)received_bytes);
3796
3797 /* update the global number of all received bytes */
3798 hhcd->hc[ch_num & 0xFU].xfer_count += received_bytes;
3799
3800 /* Transfer complete state */
3801 hhcd->hc[ch_num & 0xFU].state = HC_ACK;
3802 hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
3803
3804 if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
3805 {
3806 hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
3807 }
3808 else
3809 {
3810 hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
3811 }
3812
3813 if ((hhcd->hc[ch_num & 0xFU].xfer_len == 0U) ||
3814 ((received_bytes < hhcd->hc[ch_num & 0xFU].max_packet)))
3815 {
3816 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
3817 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
3818 }
3819 else
3820 {
3821 hhcd->hc[ch_num & 0xFU].xfer_buff += received_bytes;
3822
3823 /* Reactivate the Channel to Submit another URB since the Transfer is not yet completed */
3824 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_STRX);
3825 }
3826
3827 if ((hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_BULK) ||
3828 (hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_INTR))
3829 {
3830 hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
3831 }
3832 }
3833 /* manage NACK Response */
3834 else if (((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_NAK)
3835 && (hhcd->hc[ch_num & 0xFU].urb_state != URB_DONE))
3836 {
3837 hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
3838 hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
3839 hhcd->hc[ch_num & 0xFU].state = HC_NAK;
3840 }
3841 /* manage STALL Response */
3842 else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_STALL)
3843 {
3844 (void)HAL_HCD_HC_Halt(hhcd, ch_num);
3845 hhcd->hc[ch_num & 0xFU].state = HC_STALL;
3846 hhcd->hc[ch_num & 0xFU].urb_state = URB_STALL;
3847
3848 /* Close the channel */
3849 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
3850 }
3851 #if (USE_USB_DOUBLE_BUFFER == 1U)
3852 /* Double Buffer Management in case of Bulk Transaction */
3853 else if (((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_ACK_DBUF)
3854 && ((ch_reg & USB_CH_KIND) != 0U))
3855 {
3856 /* Bulk IN Double Buffer ISR */
3857 HCD_HC_IN_BulkDb(hhcd, ch_num, phy_chnum, ch_reg);
3858 }
3859 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
3860 else
3861 {
3862 /*....*/
3863 /* not defined state: STRX=11 in single buffer no iso is not defined */
3864 }
3865
3866 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
3867 hhcd->HC_NotifyURBChangeCallback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
3868 #else
3869 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
3870 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
3871
3872 /*Clear VTRX */
3873 HCD_CLEAR_RX_CH_CTR(hhcd->Instance, phy_chnum);
3874 }
3875 }
3876 else /* Error detected during last transaction */
3877 {
3878 /* Set URB Error State */
3879 hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
3880 hhcd->hc[ch_num & 0xFU].ErrCnt++;
3881 hhcd->hc[ch_num & 0xFU].state = HC_XACTERR;
3882
3883 /* Clear VTTRX & ERR_RX */
3884 HCD_CLEAR_RX_CH_ERR(hhcd->Instance, phy_chnum);
3885
3886 /* Check Error number */
3887 if (hhcd->hc[ch_num & 0xFU].ErrCnt > 3U)
3888 {
3889 hhcd->hc[ch_num & 0xFU].urb_state = URB_ERROR;
3890 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
3891
3892 /* Clear pending err_tx */
3893 HCD_CLEAR_RX_CH_ERR(hhcd->Instance, phy_chnum);
3894 }
3895
3896 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
3897 hhcd->HC_NotifyURBChangeCallback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
3898 #else
3899 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
3900 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
3901 }
3902 }
3903
3904
3905 /**
3906 * @brief Handle Host Channel OUT interrupt requests.
3907 * @param hhcd HCD handle
3908 * @param chnum Channel number
3909 * This parameter can be a value from 1 to 15
3910 * @retval none
3911 */
HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)3912 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
3913 {
3914 uint16_t data_xfr;
3915 __IO uint32_t WregCh;
3916
3917 /* Get Physical Channel number */
3918 uint32_t phy_chnum = (uint8_t)__HAL_HCD_GET_CHNUM(hhcd);
3919
3920 /* Take a Flag snapshot from the CHEP register, due to STRX bits are used for both control &status */
3921 uint32_t ch_reg = *(__IO uint32_t *)(&(hhcd->Instance->CHEP0R) + phy_chnum);
3922
3923 /*------ Manage Correct Transaction ------*/
3924 if ((ch_reg & USB_CH_ERRTX) == 0U)
3925 {
3926 /* Handle Isochronous channel */
3927 if ((ch_reg & USB_CH_UTYPE) == USB_EP_ISOCHRONOUS)
3928 {
3929 /* correct transaction */
3930 if ((hhcd->Instance->ISTR & USB_ISTR_ERR) == 0U)
3931 {
3932 /* Double buffer isochronous out */
3933 if ((ch_reg & USB_CH_KIND) != 0U)
3934 {
3935 HCD_SET_CH_TX_CNT(hhcd->Instance, phy_chnum, 0U);
3936 }
3937 #if (USE_USB_DOUBLE_BUFFER == 1U)
3938 else /* double buffer isochronous out */
3939 {
3940 /* Odd Transaction */
3941 if ((ch_reg & USB_CH_DTOG_TX) != 0U)
3942 {
3943 HCD_SET_CH_TX_CNT(hhcd->Instance, phy_chnum, 0U);
3944 }
3945 /* Even Transaction */
3946 else
3947 {
3948 HCD_SET_CH_RX_CNT(hhcd->Instance, phy_chnum, 0U);
3949 }
3950
3951 USB_DRD_SET_CHEP_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
3952 }
3953 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
3954
3955 /* Transfer complete state */
3956 hhcd->hc[chnum & 0xFU].state = HC_XFRC;
3957 hhcd->hc[chnum & 0xFU].urb_state = URB_DONE;
3958 }
3959
3960 /*Clear Correct Transfer */
3961 HCD_CLEAR_TX_CH_CTR(hhcd->Instance, phy_chnum);
3962
3963 /*TX COMPLETE*/
3964 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
3965 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
3966 #else
3967 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
3968 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
3969
3970 }
3971 else /* Manage all Non Isochronous Transaction */
3972 {
3973 /* Check ACK response */
3974 if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF)
3975 {
3976 data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->TXBD & 0x03FF0000U) >> 16U);
3977
3978 if (hhcd->hc[chnum & 0xFU].xfer_len >= data_xfr)
3979 {
3980 hhcd->hc[chnum & 0xFU].xfer_len -= data_xfr;
3981 }
3982 else
3983 {
3984 hhcd->hc[chnum & 0xFU].xfer_len = 0U;
3985 }
3986
3987 /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
3988 if (hhcd->hc[chnum & 0xFU].xfer_len != 0U)
3989 {
3990 /* manage multiple Xfer */
3991 hhcd->hc[chnum & 0xFU].xfer_buff += data_xfr;
3992 hhcd->hc[chnum & 0xFU].xfer_count += data_xfr;
3993
3994 /* start a new transfer */
3995 (void) USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[chnum & 0xFU]);
3996 }
3997 else
3998 {
3999 /* Transfer complete */
4000 hhcd->hc[chnum & 0xFU].xfer_count += data_xfr;
4001 hhcd->hc[chnum & 0xFU].state = HC_XFRC;
4002 hhcd->hc[chnum & 0xFU].urb_state = URB_DONE;
4003
4004 if ((hhcd->hc[chnum & 0xFU].ep_type == EP_TYPE_BULK) ||
4005 (hhcd->hc[chnum & 0xFU].ep_type == EP_TYPE_INTR))
4006 {
4007 hhcd->hc[chnum & 0xFU].toggle_out ^= 1U;
4008 }
4009 }
4010 }
4011 /* Check NACK Response */
4012 else if (((ch_reg & USB_CHEP_NAK) == USB_CHEP_NAK) ||
4013 ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK))
4014 {
4015 /* Update Channel status */
4016 hhcd->hc[chnum & 0xFU].state = HC_NAK;
4017 hhcd->hc[chnum & 0xFU].urb_state = URB_NOTREADY;
4018 hhcd->hc[chnum & 0xFU].ErrCnt = 0U;
4019
4020 /* Get Channel register value */
4021 WregCh = *(__IO uint32_t *)(&(hhcd->Instance->CHEP0R) + phy_chnum);
4022
4023 /*clear NAK status*/
4024 WregCh &= ~USB_CHEP_NAK & USB_CHEP_REG_MASK;
4025
4026 /* Update channel register Value */
4027 HCD_SET_CHANNEL(hhcd->Instance, phy_chnum, WregCh);
4028
4029 if (hhcd->hc[chnum & 0xFU].doublebuffer == 0U)
4030 {
4031 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
4032 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
4033 #else
4034 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
4035 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
4036 }
4037 }
4038 /* Check STALL Response */
4039 else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL)
4040 {
4041 (void) HAL_HCD_HC_Halt(hhcd, (uint8_t)chnum);
4042 hhcd->hc[chnum & 0xFU].state = HC_STALL;
4043 hhcd->hc[chnum & 0xFU].urb_state = URB_STALL;
4044 }
4045 #if (USE_USB_DOUBLE_BUFFER == 1U)
4046 /* Check double buffer ACK in case of bulk transaction */
4047 else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_DBUF)
4048 {
4049 /* Double buffer management Bulk Out */
4050 (void) HCD_HC_OUT_BulkDb(hhcd, chnum, (uint8_t)phy_chnum, ch_reg);
4051 }
4052 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
4053 else
4054 {
4055 /*...*/
4056 }
4057
4058 if ((ch_reg & USB_CH_TX_STTX) != USB_CH_TX_NAK)
4059 {
4060 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
4061 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
4062 #else
4063 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
4064 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
4065 }
4066
4067 HCD_CLEAR_TX_CH_CTR(hhcd->Instance, phy_chnum);
4068 } /* end no isochronous */
4069 }
4070 /*------ Manage Transaction Error------*/
4071 else
4072 {
4073 hhcd->hc[chnum & 0xFU].ErrCnt++;
4074 if (hhcd->hc[chnum & 0xFU].ErrCnt > 3U)
4075 {
4076 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
4077 hhcd->hc[chnum & 0xFU].urb_state = URB_ERROR;
4078 }
4079 else
4080 {
4081 hhcd->hc[chnum & 0xFU].urb_state = URB_NOTREADY;
4082 }
4083
4084 hhcd->hc[chnum & 0xFU].state = HC_XACTERR;
4085
4086 /*Clear ERR_TX*/
4087 HCD_CLEAR_TX_CH_ERR(hhcd->Instance, phy_chnum);
4088
4089 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
4090 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
4091 #else
4092 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
4093 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
4094 }
4095 }
4096
4097
4098 /**
4099 * @brief Handle Host Port interrupt requests.
4100 * @param hhcd HCD handle
4101 * @retval None
4102 */
HCD_Port_IRQHandler(HCD_HandleTypeDef * hhcd)4103 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
4104 {
4105 uint32_t FnrReg = hhcd->Instance->FNR;
4106 uint32_t IstrReg = hhcd->Instance->ISTR;
4107
4108 /* SE0 detected USB Disconnected state */
4109 if ((FnrReg & (USB_FNR_RXDP | USB_FNR_RXDM)) == 0U)
4110 {
4111 /* Host Port State */
4112 hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
4113
4114 /* clear all allocated virtual channel */
4115 HAL_HCD_ClearPhyChannel(hhcd);
4116
4117 /* Reset the PMA current pointer */
4118 (void)HAL_HCD_PMAReset(hhcd);
4119
4120 /* reset Ep0 Pma allocation state */
4121 hhcd->ep0_PmaAllocState = 0U;
4122
4123 /* Disconnection Callback */
4124 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
4125 hhcd->DisconnectCallback(hhcd);
4126 #else
4127 HAL_HCD_Disconnect_Callback(hhcd);
4128 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
4129
4130 return;
4131 }
4132
4133 if ((hhcd->HostState == HCD_HCD_STATE_DISCONNECTED) != 0U)
4134 {
4135 /* J-state or K-state detected & LastState=Disconnected */
4136 if (((FnrReg & USB_FNR_RXDP) != 0U) || ((IstrReg & USB_ISTR_LS_DCONN) != 0U))
4137 {
4138 hhcd->HostState = HCD_HCD_STATE_CONNECTED;
4139
4140 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
4141 hhcd->ConnectCallback(hhcd);
4142 #else
4143 HAL_HCD_Connect_Callback(hhcd);
4144 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
4145 }
4146 }
4147 else
4148 {
4149 /* J-state or K-state detected & lastState=Connected: a Missed disconnection is detected */
4150 if (((FnrReg & USB_FNR_RXDP) != 0U) || ((IstrReg & USB_ISTR_LS_DCONN) != 0U))
4151 {
4152 /* Host Port State */
4153 hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
4154
4155 /* clear all allocated virtual channel */
4156 HAL_HCD_ClearPhyChannel(hhcd);
4157
4158 /* Reset the PMA current pointer */
4159 (void)HAL_HCD_PMAReset(hhcd);
4160
4161 /* reset Ep0 PMA allocation state */
4162 hhcd->ep0_PmaAllocState = 0U;
4163
4164 /* Disconnection Callback */
4165 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
4166 hhcd->DisconnectCallback(hhcd);
4167 #else
4168 HAL_HCD_Disconnect_Callback(hhcd);
4169 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
4170 }
4171 }
4172 }
4173
4174
4175 /**
4176 * @brief Check if the ch_num are already reserved to a physical channel
4177 * @param hhcd HCD handle
4178 * @param ch_num Channel number
4179 * This parameter can be a value from 1 to 15
4180 * @retval HAL status
4181 */
HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const * hhcd,uint8_t ch_num)4182 static uint8_t HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const *hhcd, uint8_t ch_num)
4183 {
4184 uint8_t idx;
4185
4186 /* Check if the logical channel are already opened */
4187 for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
4188 {
4189 if ((((hhcd->phy_chin_state[idx] & 0xF0U) >> 4U) == ((uint16_t)ch_num + 1U)) &&
4190 (hhcd->phy_chin_state[idx] != 0U))
4191 {
4192 return (1U | (idx << 4U));
4193 }
4194
4195 if ((((hhcd->phy_chout_state[idx] & 0xF0U) >> 4U) == ((uint16_t)ch_num + 1U)) &&
4196 (hhcd->phy_chout_state[idx] != 0U))
4197 {
4198 return (1U | (idx << 4U));
4199 }
4200 }
4201
4202 return 0U;
4203 }
4204
4205
4206 /**
4207 * @brief Get a Logical Channel number from physical Channel
4208 * @param hhcd HCD handle
4209 * @param phy_chnum
4210 * This parameter can be a value from 1 to 15
4211 * @param dir Channel direction
4212 * -0 OUT_Channel
4213 * -1 IN_Channel
4214 * @retval HAL status
4215 */
HAL_HCD_GetLogical_Channel(HCD_HandleTypeDef const * hhcd,uint8_t phy_chnum,uint8_t dir)4216 static uint8_t HAL_HCD_GetLogical_Channel(HCD_HandleTypeDef const *hhcd,
4217 uint8_t phy_chnum, uint8_t dir)
4218 {
4219 /* Out Channel Direction */
4220 if (dir == 0U)
4221 {
4222 if (((hhcd->phy_chout_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) != 0U)
4223 {
4224 return ((uint8_t)((hhcd->phy_chout_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) - 1U);
4225 }
4226 else
4227 {
4228 /* Channel not registered Error */
4229 return HCD_LOGICAL_CH_NOT_OPENED;
4230 }
4231 }
4232 /* IN Channel Direction */
4233 else
4234 {
4235 if (((hhcd->phy_chin_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) != 0U)
4236 {
4237 return ((uint8_t)((hhcd->phy_chin_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) - 1U);
4238 }
4239 else
4240 {
4241 /* Channel not registered Error */
4242 return HCD_LOGICAL_CH_NOT_OPENED;
4243 }
4244 }
4245 }
4246
4247
4248 /**
4249 * @brief Get a free physical Channel number according to the direction
4250 * @param hhcd HCD handle
4251 * @param ch_num Channel number
4252 * This parameter can be a value from 1 to 15
4253 * @param epnum Endpoint number
4254 * This parameter can be a value from 1 to 15
4255 * @param ep_type Endpoint Type
4256 * This parameter can be one of these values:
4257 * EP_TYPE_CTRL Control type,
4258 * EP_TYPE_ISOC Isochronous type,
4259 * EP_TYPE_BULK Bulk type,
4260 * EP_TYPE_INTR Interrupt type
4261 * @retval if physical channel is available return Phy_channel number
4262 else return HCD_FREE_CH_NOT_FOUND
4263 */
HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t epnum,uint8_t ep_type)4264 static uint8_t HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
4265 uint8_t epnum, uint8_t ep_type)
4266 {
4267 uint8_t idx;
4268
4269 if ((epnum & 0x7FU) == 0U)
4270 {
4271 idx = 0U;
4272
4273 if (ch_num == 0U)
4274 {
4275 if (hhcd->phy_chin_state[idx] == 0U)
4276 {
4277 /* chin_state to store the ep_type to be used for the same channel in OUT direction
4278 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
4279 hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
4280 ((uint16_t)ep_type + 1U) |
4281 (((uint16_t)epnum & 0x0FU) << 8U);
4282 }
4283
4284 if (hhcd->phy_chout_state[idx] == 0U)
4285 {
4286 /* chout_state will store the ep_type to be used for the same channel in IN direction
4287 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
4288 hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
4289 ((uint16_t)ep_type + 1U) |
4290 (((uint16_t)epnum & 0x0FU) << 8U);
4291 }
4292 }
4293 else
4294 {
4295 if ((epnum & 0x80U) != 0U)
4296 {
4297 if (((hhcd->phy_chin_state[idx] & 0xF0U) >> 4U) != ((uint16_t)ch_num + 1U))
4298 {
4299 /* chin_state to store the ep_type to be used for the same channel in OUT direction
4300 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
4301 hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
4302 ((uint16_t)ep_type + 1U) |
4303 (((uint16_t)epnum & 0x0FU) << 8U);
4304 }
4305 }
4306 else
4307 {
4308 if (((hhcd->phy_chout_state[idx] & 0xF0U) >> 4U) != ((uint16_t)ch_num + 1U))
4309 {
4310 /* chout_state will store the ep_type to be used for the same channel in IN direction
4311 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
4312 hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
4313 ((uint16_t)ep_type + 1U) |
4314 (((uint16_t)epnum & 0x0FU) << 8U);
4315 }
4316 }
4317 }
4318
4319 return idx;
4320 }
4321
4322 if ((epnum & 0x80U) != 0U)
4323 {
4324 /* Find a new available physical in channel */
4325 for (idx = 1U; idx < hhcd->Init.Host_channels; idx++)
4326 {
4327 /* Check if the same epnum is allocated then allocate the same physical channel OUT for IN Logical Channel */
4328 if ((hhcd->phy_chin_state[idx] == 0U) &&
4329 ((((hhcd->phy_chout_state[idx] & 0x000FU) == ((uint16_t)ep_type + 1U)) &&
4330 (((hhcd->phy_chout_state[idx] & 0x0F00U) == ((uint16_t)epnum & 0x0FU)))) ||
4331 (hhcd->phy_chout_state[idx] == 0U)))
4332 {
4333 /* chin_state to store the ep_type to be used for the same channel in OUT direction
4334 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
4335 hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
4336 ((uint16_t)ep_type + 1U) |
4337 (((uint16_t)epnum & 0x0FU) << 8U);
4338
4339 return idx;
4340 }
4341 }
4342 }
4343 else
4344 {
4345 /* Find a new available physical out channel */
4346 for (idx = 1U; idx < hhcd->Init.Host_channels; idx++)
4347 {
4348 /* Check if the same epnum is allocated then allocate the same physical channel IN for OUT Logical Channel */
4349 if ((hhcd->phy_chout_state[idx] == 0U) &&
4350 ((((hhcd->phy_chin_state[idx] & 0x0FU) == ((uint16_t)ep_type + 1U)) &&
4351 ((hhcd->phy_chin_state[idx] & 0x0F00U) == ((uint16_t)epnum & 0x0FU))) ||
4352 (hhcd->phy_chin_state[idx] == 0U)))
4353 {
4354 /* chout_state will store the ep_type to be used for the same channel in IN direction
4355 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
4356 hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
4357 ((uint16_t)ep_type + 1U) |
4358 (((uint16_t)epnum & 0x0FU) << 8U);
4359
4360 return idx;
4361 }
4362 }
4363 }
4364
4365 /* in case of Error */
4366 return HCD_FREE_CH_NOT_FOUND;
4367 }
4368
4369 /**
4370 * @brief Free All Channel allocation
4371 * @param hhcd HCD handle
4372 * @retval HAL status
4373 */
HAL_HCD_ClearPhyChannel(HCD_HandleTypeDef * hhcd)4374 static void HAL_HCD_ClearPhyChannel(HCD_HandleTypeDef *hhcd)
4375 {
4376 uint8_t idx;
4377
4378 for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
4379 {
4380 /*Reset channel allocation value */
4381 hhcd->phy_chout_state[idx] = 0U;
4382 hhcd->phy_chin_state[idx] = 0U;
4383 }
4384 }
4385
4386 /*---------------------- PMA Allocation Section --------------------- */
4387 /*
4388 __col31________________col0__ Column-- >
4389 lin0 | entry31.|....... | entry0 | Line
4390 |---------|---------|--------| |
4391 line1| entry63.|....... | entry32| |
4392 |---------|---------|--------| \|/
4393 | entry127|....... | entry64|
4394 |---------|---------|--------|
4395 | entry256|...... |entry128|
4396 ----------------------------
4397 an allocation space of 64byte need 8 Free contiguous Entry in the Matrix
4398 - a Free Entry is a bit with 0 Value/ a busy entry is a bit with 1 value. */
4399
4400 /**
4401 * @brief Fetch in the PMA_LockupTable free space of number of mps byte
4402 * @param hhcd Host instance
4403 * @param mps Channel Max Packet Size
4404 * @retval PMA_Address of the first free block containing mps byte
4405 0xFFFF in case of no space available
4406 */
HAL_HCD_GetFreePMA(HCD_HandleTypeDef * hhcd,uint16_t mps)4407 static uint16_t HAL_HCD_GetFreePMA(HCD_HandleTypeDef *hhcd, uint16_t mps)
4408 {
4409 uint32_t Entry;
4410 uint32_t FreeBlocks = 0U;
4411 uint8_t FirstFreeBlock_col = 0U;
4412 uint8_t FirstFreeBlock_line = 0U;
4413 uint8_t ColIndex;
4414 uint16_t NbrReqBlocks;
4415 uint16_t mps_t = mps;
4416
4417 /* since PMA buffer descriptor RXBD allocate address according to BLSIZE, BLSIZE=1==> mps>64
4418 allocation in PMA is done in 32Bytes each entry */
4419 if ((mps_t > 64U) && ((mps_t % 32U) != 0U))
4420 {
4421 /* Align the mps to 32byte block to match the allocation in PMA,
4422 check Definition of allocation buffer memory in usb user spec */
4423 mps_t = (uint16_t)(((mps_t / 32U) + 1U) * 32U);
4424 }
4425
4426 /* calculate the number of block(8byte) to allocate */
4427 NbrReqBlocks = mps_t / 8U;
4428
4429 /* check if we need remaining Block */
4430 if ((mps_t % 8U) != 0U)
4431 {
4432 NbrReqBlocks++;
4433 }
4434
4435 /* Look For NbrReqBlocks * Empty Block */
4436 for (uint8_t i = 0U; ((i < PMA_BLOCKS) && (FreeBlocks != NbrReqBlocks)); i++)
4437 {
4438 Entry = hhcd->PMALookupTable[i];
4439
4440 /* when parse is in progress, check the first col to look for a contiguous block */
4441 if ((FreeBlocks != 0U) && ((Entry & (uint32_t)1U) != 0U))
4442 {
4443 FreeBlocks = 0U;
4444 }
4445 uint8_t j = 0U;
4446 while ((j <= 31U) && (FreeBlocks != NbrReqBlocks))
4447 {
4448 /* check if block j is free */
4449 if ((Entry & ((uint32_t)1U << j)) == 0U)
4450 {
4451 if (FreeBlocks == 0U)
4452 {
4453 FirstFreeBlock_col = j;
4454 FirstFreeBlock_line = i;
4455 FreeBlocks++;
4456 }
4457 j++;
4458
4459 /* Parse Column PMALockTable */
4460 while ((j <= 31U) && ((Entry & ((uint32_t)1U << j)) == 0U) && (FreeBlocks < NbrReqBlocks))
4461 {
4462 FreeBlocks++;
4463 j++;
4464 }
4465
4466 /* Free contiguous Blocks not found */
4467 if (((FreeBlocks < NbrReqBlocks) && (j < 31U)) ||
4468 ((j == 31U) && ((Entry & ((uint32_t)1U << j)) != 0U)))
4469 {
4470 FreeBlocks = 0U;
4471 }
4472 }
4473 j++;
4474 } /* end for j */
4475 } /* end for i */
4476
4477 /* Free block found */
4478 if (FreeBlocks >= NbrReqBlocks)
4479 {
4480 ColIndex = FirstFreeBlock_col;
4481
4482 for (uint8_t i = FirstFreeBlock_line; ((i < PMA_BLOCKS) && (FreeBlocks > 0U)); i++)
4483 {
4484 for (uint8_t j = ColIndex; j <= 31U; j++)
4485 {
4486 hhcd->PMALookupTable[i] |= ((uint32_t)1U << j);
4487 if (--FreeBlocks == 0U)
4488 {
4489 break;
4490 }
4491 }
4492 ColIndex = 0U;
4493 }
4494
4495 return (uint16_t)((FirstFreeBlock_line * (uint16_t)256U) + (FirstFreeBlock_col * (uint16_t)8U));
4496 }
4497 else
4498 {
4499 return 0xFFFFU;
4500 }
4501 }
4502
4503 /**
4504 * @brief Allocate PMA buffer for Channel
4505 * This API will fetch a free space
4506 * @param hhcd Host instance
4507 * @param ch_num Channel number
4508 * @param ch_kind endpoint Kind
4509 * USB_SNG_BUF Single Buffer used
4510 * USB_DBL_BUF Double Buffer used
4511 * @param mps Channel Max Packet Size
4512 * @retval HAL status
4513 */
HAL_HCD_PMAlloc(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint16_t ch_kind,uint16_t mps)4514 HAL_StatusTypeDef HAL_HCD_PMAlloc(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
4515 uint16_t ch_kind, uint16_t mps)
4516 {
4517 uint16_t pma_addr0;
4518 #if (USE_USB_DOUBLE_BUFFER == 1U)
4519 uint16_t pma_addr1; /* used for double buffer mode if enabled */
4520 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
4521
4522 /* Host Channel */
4523 HCD_HCTypeDef *hc = &(hhcd->hc[ch_num]);
4524
4525 /* Get a FreePMA Address */
4526 pma_addr0 = HAL_HCD_GetFreePMA(hhcd, mps);
4527
4528 /* if there is no free space to allocate */
4529 if (pma_addr0 == 0xFFFFU)
4530 {
4531 return HAL_ERROR;
4532 }
4533 else
4534 {
4535 /* Here we check if the endpoint is single or double Buffer */
4536 if (ch_kind == HCD_SNG_BUF)
4537 {
4538 /* Single Buffer */
4539 hc->doublebuffer = 0U;
4540
4541 if (hc->ep_num == 0U)
4542 {
4543 hhcd->ep0_PmaAllocState = ch_num;
4544 hhcd->ep0_PmaAllocState |= (1U << 8);
4545 }
4546
4547 /* Configure the PMA */
4548 if (hc->ch_dir == CH_IN_DIR)
4549 {
4550 hc->pmaaddr1 = pma_addr0;
4551 (USB_DRD_PMA_BUFF + hc->phy_ch_num)->RXBD = hc->pmaaddr1;
4552
4553 if (hc->ep_num == 0U)
4554 {
4555 hhcd->ep0_PmaAllocState |= (CH_IN_DIR << 4);
4556 }
4557 }
4558 else
4559 {
4560 hc->pmaaddr0 = pma_addr0;
4561 (USB_DRD_PMA_BUFF + hc->phy_ch_num)->TXBD = hc->pmaaddr0;
4562 }
4563
4564 /* Set the PmaAddress */
4565 hc->pmaadress = pma_addr0;
4566 }
4567 #if (USE_USB_DOUBLE_BUFFER == 1U)
4568 else /* USB_DBL_BUF */
4569 {
4570 /* Double Buffer Endpoint */
4571 hc->doublebuffer = 1U;
4572
4573 /* Get a FreePMA Address for buffer 2 */
4574 pma_addr1 = HAL_HCD_GetFreePMA(hhcd, mps);
4575
4576 if (pma_addr1 == 0xFFFFU)
4577 {
4578 /* Free the first buffer */
4579 (void)HAL_HCD_PMAFree(hhcd, pma_addr0, mps);
4580 return HAL_ERROR;
4581 }
4582 else
4583 {
4584 /* Configure the PMA */
4585 hc->pmaaddr0 = (uint16_t)(pma_addr0);
4586 hc->pmaaddr1 = (uint16_t)(pma_addr1);
4587
4588 /* Set Buffer0 pma address */
4589 (USB_DRD_PMA_BUFF + hc->phy_ch_num)->TXBD = pma_addr0;
4590
4591 /* Set Buffer1 pma address */
4592 (USB_DRD_PMA_BUFF + hc->phy_ch_num)->RXBD = pma_addr1;
4593
4594 /* Used for Bulk DB MPS < 64bytes */
4595 if (hc->ch_dir == CH_IN_DIR)
4596 {
4597 hc->pmaadress = hc->pmaaddr1;
4598 }
4599 else
4600 {
4601 hc->pmaadress = hc->pmaaddr0;
4602 }
4603 }
4604 }
4605 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
4606 }
4607
4608 return HAL_OK;
4609 }
4610
4611 /**
4612 * @brief PMA De-Allocation for Channel Free the reserved block in the PMA-LookupTable
4613 * @param hhcd Host instance
4614 * @param ch_num Channel number
4615 * @retval HAL status
4616 */
HAL_HCD_PMADeAlloc(HCD_HandleTypeDef * hhcd,uint8_t ch_num)4617 HAL_StatusTypeDef HAL_HCD_PMADeAlloc(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
4618 {
4619 HAL_StatusTypeDef status;
4620
4621 #if (USE_USB_DOUBLE_BUFFER == 1U)
4622 uint8_t Err = 0U;
4623 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
4624
4625 /* Host Channel */
4626 HCD_HCTypeDef *hc = &(hhcd->hc[ch_num]);
4627
4628 /* Single Buffer */
4629 if (hc->doublebuffer == 0U)
4630 {
4631 status = HAL_HCD_PMAFree(hhcd, hc->pmaadress, hc->max_packet);
4632 }
4633 else /* Double buffer */
4634 {
4635 #if (USE_USB_DOUBLE_BUFFER == 1U)
4636 status = HAL_HCD_PMAFree(hhcd, hc->pmaaddr0, hc->max_packet);
4637 if (status != HAL_OK)
4638 {
4639 Err++;
4640 }
4641
4642 status = HAL_HCD_PMAFree(hhcd, hc->pmaaddr1, hc->max_packet);
4643 if (status != HAL_OK)
4644 {
4645 Err++;
4646 }
4647
4648 if (Err != 0U)
4649 {
4650 return HAL_ERROR;
4651 }
4652 #else
4653 status = HAL_ERROR;
4654 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
4655 }
4656
4657 return status;
4658 }
4659
4660
4661 /**
4662 * @brief PMA Reset
4663 * @param hhcd Host instance
4664 * @retval HAL status
4665 */
HAL_HCD_PMAReset(HCD_HandleTypeDef * hhcd)4666 HAL_StatusTypeDef HAL_HCD_PMAReset(HCD_HandleTypeDef *hhcd)
4667 {
4668 /* Reset All PMA Entry */
4669 for (uint8_t i = 0U; i < PMA_BLOCKS; i++)
4670 {
4671 hhcd->PMALookupTable[i] = 0U;
4672 }
4673
4674 /* Allocate a Space for buffer descriptor table depending on the Host channel number */
4675 for (uint8_t i = 0U; i < hhcd->Init.Host_channels; i++)
4676 {
4677 hhcd->PMALookupTable[0] |= ((uint32_t)1U << i);
4678 }
4679
4680 return HAL_OK;
4681 }
4682
4683 /**
4684 * @brief PMA Free
4685 * @param hhcd Host instance
4686 * @param pma_base PMA base offset stored in hhcd->hc.pmaaddr
4687 * @param mps Max Packet Size
4688 * @retval HAL status
4689 */
HAL_HCD_PMAFree(HCD_HandleTypeDef * hhcd,uint32_t pma_base,uint16_t mps)4690 static HAL_StatusTypeDef HAL_HCD_PMAFree(HCD_HandleTypeDef *hhcd, uint32_t pma_base, uint16_t mps)
4691 {
4692 uint32_t block_nbr;
4693 uint8_t ColIndex;
4694 uint8_t LineIndex;
4695 uint16_t mps_t = mps;
4696
4697 /* since PMA buffer descriptor RXBD allocate address according to BLSIZE, BLSIZE=1==> mps>64
4698 allocation in PMA is done in 32Bytes each entry */
4699 if ((mps_t > 64U) && ((mps_t % 32U) != 0U))
4700 {
4701 /* Align the mps to 32byte block to match the allocation in PMA,
4702 check Definition of allocation buffer memory in usb user spec */
4703 mps_t = (uint16_t)(((mps_t / 32U) + 1U) * 32U);
4704 }
4705
4706 /* Calculate the number of needed block to Free */
4707 if ((mps_t / 8U) != 0U)
4708 {
4709 block_nbr = ((uint32_t)mps_t / 8U);
4710
4711 if ((mps_t % 8U) != 0U)
4712 {
4713 block_nbr++;
4714 }
4715 }
4716 else
4717 {
4718 block_nbr = 1U;
4719 }
4720
4721 /* Decode Col/Line of PMA_Base position in the PMA_LookupTable */
4722 if (pma_base > 256U)
4723 {
4724 LineIndex = (uint8_t)(pma_base / 256U);
4725 ColIndex = (uint8_t)((pma_base - ((uint32_t)LineIndex * 256U)) / 8U);
4726 }
4727 else
4728 {
4729 LineIndex = 0U;
4730 ColIndex = (uint8_t)(pma_base / 8U);
4731 }
4732
4733 /* Reset the corresponding bit in the lookupTable */
4734 for (uint8_t i = LineIndex; ((i < PMA_BLOCKS) && (block_nbr > 0U)); i++)
4735 {
4736 for (uint8_t j = ColIndex; j <= 31U; j++)
4737 {
4738 /* Check if the block is not already reserved or it was already closed */
4739 if ((hhcd->PMALookupTable[i] & ((uint32_t)1U << j)) == 0U)
4740 {
4741 return HAL_ERROR;
4742 }
4743 /* Free the reserved block by resetting the corresponding bit */
4744 hhcd->PMALookupTable[i] &= ~(1U << j);
4745
4746 if (--block_nbr == 0U)
4747 {
4748 break;
4749 }
4750 }
4751 ColIndex = 0U;
4752 }
4753
4754 return HAL_OK;
4755 }
4756
4757 /**
4758 * @}
4759 */
4760
4761 /**
4762 * @}
4763 */
4764 #endif /* defined (USB_DRD_FS) */
4765 #endif /* HAL_HCD_MODULE_ENABLED */
4766
4767 /**
4768 * @}
4769 */
4770
4771 /**
4772 * @}
4773 */
4774