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