1 /**
2 ******************************************************************************
3 * @file stm32c0xx_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) 2022 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_CLK_ENABLE();
39 (##) Initialize the related GPIO clocks
40 (##) Configure HCD pin-out
41 (##) Configure HCD NVIC interrupt
42
43 (#)Associate the Upper USB Host stack to the HAL HCD Driver:
44 (##) hhcd.pData = phost;
45
46 (#)Enable HCD transmission and reception:
47 (##) HAL_HCD_Start();
48
49 @endverbatim
50 ******************************************************************************
51 */
52
53 /* Includes ------------------------------------------------------------------*/
54 #include "stm32c0xx_hal.h"
55
56 /** @addtogroup STM32C0xx_HAL_Driver
57 * @{
58 */
59
60 #ifdef HAL_HCD_MODULE_ENABLED
61 #if defined (USB_DRD_FS)
62
63 /** @defgroup HCD HCD
64 * @brief HCD HAL module driver
65 * @{
66 */
67
68 /* Private typedef -----------------------------------------------------------*/
69 /* Private define ------------------------------------------------------------*/
70 /* Private macro -------------------------------------------------------------*/
71 /* Private variables ---------------------------------------------------------*/
72 /* Private function ----------------------------------------------------------*/
73 /** @defgroup HCD_Private_Functions HCD Private Functions
74 * @{
75 */
76 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
77 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
78 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
79 static void HAL_HCD_ClearPhyChannel(HCD_HandleTypeDef *hhcd);
80 static uint8_t HAL_HCD_GetLogical_Channel(HCD_HandleTypeDef const *hhcd, uint8_t phy_chnum, uint8_t dir);
81 static uint8_t HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const *hhcd, uint8_t ch_num);
82 static uint8_t HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t epnum, uint8_t ep_type);
83
84 #if (USE_USB_DOUBLE_BUFFER == 1U)
85 static void HCD_HC_IN_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
86 static void HCD_HC_OUT_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
87 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
88
89 static uint16_t HAL_HCD_GetFreePMA(HCD_HandleTypeDef *hhcd, uint16_t mps);
90 static HAL_StatusTypeDef HAL_HCD_PMAFree(HCD_HandleTypeDef *hhcd, uint32_t pma_base, uint16_t mps);
91 static void inline HCD_HC_IN_ISO(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
92 /**
93 * @}
94 */
95
96 /* Exported functions --------------------------------------------------------*/
97 /** @defgroup HCD_Exported_Functions HCD Exported Functions
98 * @{
99 */
100
101 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
102 * @brief Initialization and Configuration functions
103 *
104 @verbatim
105 ===============================================================================
106 ##### Initialization and de-initialization functions #####
107 ===============================================================================
108 [..] This section provides functions allowing to:
109
110 @endverbatim
111 * @{
112 */
113
114 /**
115 * @brief Initialize the host driver.
116 * @param hhcd HCD handle
117 * @retval HAL status
118 */
HAL_HCD_Init(HCD_HandleTypeDef * hhcd)119 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
120 {
121 /* Check the HCD handle allocation */
122 if (hhcd == NULL)
123 {
124 return HAL_ERROR;
125 }
126
127 /* Check the parameters */
128 assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
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 hhcd->State = HAL_HCD_STATE_BUSY;
156
157 /* Disable the Interrupts */
158 (void)__HAL_HCD_DISABLE(hhcd);
159
160 /* Dma not supported, force to zero */
161 hhcd->Init.dma_enable = 0U;
162
163 /* Init the Core (common init.) */
164 (void)USB_CoreInit(hhcd->Instance, hhcd->Init);
165
166 /* Force Host Mode */
167 (void)USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE);
168
169 /* Init Host */
170 (void)USB_HostInit(hhcd->Instance, hhcd->Init);
171
172 hhcd->State = HAL_HCD_STATE_READY;
173
174 /* Host Port State */
175 hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
176
177 /* Init PMA Address */
178 (void)HAL_HCD_PMAReset(hhcd);
179
180 hhcd->State = HAL_HCD_STATE_READY;
181
182 return HAL_OK;
183 }
184
185 /**
186 * @brief Initialize a host channel.
187 * @param hhcd HCD handle
188 * @param ch_num Channel number.
189 * This parameter can be a value from 1 to 15
190 * @param epnum Endpoint number.
191 * This parameter can be a value from 1 to 15
192 * @param dev_address Current device address
193 * This parameter can be a value from 0 to 255
194 * @param speed Current device speed.
195 * This parameter can be one of these values:
196 * HCD_DEVICE_SPEED_HIGH High speed mode,
197 * HCD_DEVICE_SPEED_FULL Full speed mode,
198 * HCD_DEVICE_SPEED_LOW Low speed mode
199 * @param ep_type Endpoint Type.
200 * This parameter can be one of these values:
201 * USBH_EP_CONTROL Control type,
202 * USBH_EP_ISO Isochronous type,
203 * USBH_EP_BULK Bulk type,
204 * USBH_EP_INTERRUPT Interrupt type
205 * @param mps Max Packet Size.
206 * This parameter can be a value from 0 to32K
207 * @retval HAL status
208 */
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)209 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
210 uint8_t epnum, uint8_t dev_address,
211 uint8_t speed, uint8_t ep_type, uint16_t mps)
212 {
213 HAL_StatusTypeDef status;
214 uint8_t used_channel;
215 uint8_t ep0_virtual_channel;
216
217 __HAL_LOCK(hhcd);
218
219 if (ch_num > 16U)
220 {
221 __HAL_UNLOCK(hhcd);
222 return HAL_ERROR;
223 }
224
225 if (((epnum & 0xFU) == 0U) && ((hhcd->ep0_PmaAllocState & 0xF000U) != 0U))
226 {
227 hhcd->hc[ch_num & 0xFU].pmaadress = hhcd->hc[0U].pmaadress;
228 hhcd->hc[ch_num & 0xFU].pmaaddr0 = hhcd->hc[0U].pmaaddr0;
229 hhcd->hc[ch_num & 0xFU].pmaaddr1 = hhcd->hc[0U].pmaaddr1;
230
231 hhcd->phy_chin_state[0U] = (((uint16_t)ch_num + 1U) << 4U) |
232 ((uint16_t)ep_type + 1U) |
233 (((uint16_t)epnum & 0x0FU) << 8U);
234
235 hhcd->phy_chout_state[0U] = (((uint16_t)ch_num + 1U) << 4U) |
236 ((uint16_t)ep_type + 1U) |
237 (((uint16_t)epnum & 0x0FU) << 8U);
238 }
239
240 /* Check if the logical channel are already allocated */
241 used_channel = HAL_HCD_Check_usedChannel(hhcd, ch_num);
242
243 /* Check if the channel is not already opened */
244 if (used_channel == 0U)
245 {
246 /* Allocate New Physical channel */
247 hhcd->hc[ch_num & 0xFU].phy_ch_num = HAL_HCD_Get_FreePhyChannel(hhcd, ch_num, epnum, ep_type);
248
249 /* No free Channel available, return error */
250 if (hhcd->hc[ch_num & 0xFU].phy_ch_num == HCD_FREE_CH_NOT_FOUND)
251 {
252 __HAL_UNLOCK(hhcd);
253 return HAL_ERROR;
254 }
255 }
256 /* Channel already opened */
257 else
258 {
259 /* Get Physical Channel number */
260 hhcd->hc[ch_num & 0xFU].phy_ch_num = (used_channel & 0xF0U) >> 4U;
261 }
262
263 if ((epnum & 0x80U) != 0U)
264 {
265 hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
266 }
267 else
268 {
269 hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
270 }
271
272 hhcd->hc[ch_num & 0xFU].dev_addr = dev_address;
273 hhcd->hc[ch_num & 0xFU].max_packet = mps;
274 hhcd->hc[ch_num & 0xFU].ep_type = ep_type;
275 hhcd->hc[ch_num & 0xFU].ep_num = epnum & 0x7FU;
276 hhcd->hc[ch_num & 0xFU].speed = speed;
277
278 /* Check if the channel is not already opened */
279 if (used_channel == 0U)
280 {
281 if (((ep_type == EP_TYPE_ISOC) && (hhcd->Init.iso_singlebuffer_enable == 0U)) ||
282 ((ep_type == EP_TYPE_BULK) && (hhcd->Init.bulk_doublebuffer_enable == 1U)))
283 {
284 /* PMA Dynamic Allocation */
285 status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_DBL_BUF, mps);
286
287 if (status == HAL_ERROR)
288 {
289 __HAL_UNLOCK(hhcd);
290 return HAL_ERROR;
291 }
292
293 /* Clear Channel DTOG_TX */
294 HCD_CLEAR_TX_DTOG(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num);
295
296 /* Clear Channel DTOG RX */
297 HCD_CLEAR_RX_DTOG(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num);
298
299 }
300 else
301 {
302 if (hhcd->hc[ch_num & 0xFU].ep_num != 0U)
303 {
304 status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, mps);
305
306 if (status == HAL_ERROR)
307 {
308 __HAL_UNLOCK(hhcd);
309 return HAL_ERROR;
310 }
311 }
312 else
313 {
314 if (ch_num == 0U)
315 {
316 ep0_virtual_channel = (uint8_t)(hhcd->ep0_PmaAllocState & 0xFU);
317
318 if ((ep0_virtual_channel != 0U) && (((hhcd->ep0_PmaAllocState & 0xF0U) >> 4) == CH_IN_DIR))
319 {
320 if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_OUT_DIR)
321 {
322 status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
323
324 if (status == HAL_ERROR)
325 {
326 __HAL_UNLOCK(hhcd);
327 return HAL_ERROR;
328 }
329 }
330 else
331 {
332 __HAL_UNLOCK(hhcd);
333 return HAL_ERROR;
334 }
335 }
336 else
337 {
338 /* This is a dual EP0 PMA allocation */
339 hhcd->ep0_PmaAllocState |= (0x1U << 12);
340
341 /* PMA Dynamic Allocation for EP0 OUT direction */
342 hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
343 status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
344
345 if (status == HAL_ERROR)
346 {
347 __HAL_UNLOCK(hhcd);
348 return HAL_ERROR;
349 }
350
351 /* PMA Dynamic Allocation for EP0 IN direction */
352 hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
353 status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
354
355 if (status == HAL_ERROR)
356 {
357 __HAL_UNLOCK(hhcd);
358 return HAL_ERROR;
359 }
360 }
361 }
362 else
363 {
364 if (((hhcd->ep0_PmaAllocState & 0xF00U) >> 8) == 1U)
365 {
366 ep0_virtual_channel = (uint8_t)(hhcd->ep0_PmaAllocState & 0xFU);
367
368 if (((hhcd->ep0_PmaAllocState & 0xF0U) >> 4) == CH_IN_DIR)
369 {
370 hhcd->hc[ch_num & 0xFU].pmaaddr1 = hhcd->hc[ep0_virtual_channel & 0xFU].pmaaddr1;
371 }
372 else
373 {
374 hhcd->hc[ch_num & 0xFU].pmaaddr0 = hhcd->hc[ep0_virtual_channel & 0xFU].pmaaddr0;
375 }
376 }
377 else
378 {
379 status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
380
381 if (status == HAL_ERROR)
382 {
383 __HAL_UNLOCK(hhcd);
384 return HAL_ERROR;
385 }
386 }
387 }
388 }
389 }
390 }
391
392 if ((epnum & 0x80U) != 0U)
393 {
394 hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
395
396 if (hhcd->hc[ch_num & 0xFU].ep_num == 0U)
397 {
398 hhcd->hc[ch_num & 0xFU].pmaadress = hhcd->hc[ch_num & 0xFU].pmaaddr1;
399 }
400 }
401 else
402 {
403 hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
404
405 if (hhcd->hc[ch_num & 0xFU].ep_num == 0U)
406 {
407 hhcd->hc[ch_num & 0xFU].pmaadress = hhcd->hc[ch_num & 0xFU].pmaaddr0;
408 }
409 }
410
411 /* Init the USB Channel CHEPRx */
412 status = USB_HC_Init(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
413 epnum, dev_address, speed, ep_type, mps);
414
415 /* check single buffer for isochronous channel */
416 if (ep_type == EP_TYPE_ISOC)
417 {
418 if (hhcd->Init.iso_singlebuffer_enable == 1U)
419 {
420 (void)USB_HC_DoubleBuffer(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
421 USB_DRD_ISOC_DBUFF_DISABLE);
422 }
423 }
424
425 /* Bulk double buffer check */
426 if (ep_type == EP_TYPE_BULK)
427 {
428 if (hhcd->Init.bulk_doublebuffer_enable == 1U)
429 {
430 (void)USB_HC_DoubleBuffer(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
431 USB_DRD_BULK_DBUFF_ENBALE);
432 }
433 }
434
435 __HAL_UNLOCK(hhcd);
436
437 return status;
438 }
439
440 /**
441 * @brief HAL_HCD_HC_Close Pipe
442 * @param hhcd HCD handle
443 * @param ch_num Channel number.
444 * This parameter can be a value from 1 to 15
445 * @retval HAL status
446 */
HAL_HCD_HC_Close(HCD_HandleTypeDef * hhcd,uint8_t ch_num)447 HAL_StatusTypeDef HAL_HCD_HC_Close(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
448 {
449 /* Stop the channel */
450 (void) HAL_HCD_HC_Halt(hhcd, ch_num);
451
452 HAL_Delay(3U);
453
454 if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_IN_DIR)
455 {
456 /* Free Allocated Channel */
457 hhcd->phy_chin_state[hhcd->hc[ch_num & 0xFU].phy_ch_num] = 0U;
458 }
459 else
460 {
461 /* Free Allocated Channel */
462 hhcd->phy_chout_state[hhcd->hc[ch_num & 0xFU].phy_ch_num] = 0U;
463 }
464
465 /* Reset PMA Channel_Allocation */
466 (void)HAL_HCD_PMADeAlloc(hhcd, ch_num);
467
468 return HAL_OK;
469 }
470
471 /**
472 * @brief Halt a host channel.
473 * @param hhcd HCD handle
474 * @param ch_num Channel number.
475 * This parameter can be a value from 1 to 15
476 * @retval HAL status
477 */
HAL_HCD_HC_Halt(HCD_HandleTypeDef * hhcd,uint8_t ch_num)478 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
479 {
480 HAL_StatusTypeDef status = HAL_OK;
481
482 __HAL_LOCK(hhcd);
483 if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_IN_DIR)
484 {
485 (void)USB_HC_IN_Halt(hhcd->Instance, (uint8_t) hhcd->hc[ch_num & 0xFU].phy_ch_num);
486 }
487 else
488 {
489 (void)USB_HC_OUT_Halt(hhcd->Instance, (uint8_t) hhcd->hc[ch_num & 0xFU].phy_ch_num);
490 }
491 __HAL_UNLOCK(hhcd);
492
493 return status;
494 }
495
496 /**
497 * @brief DeInitialize the host driver.
498 * @param hhcd HCD handle
499 * @retval HAL status
500 */
HAL_HCD_DeInit(HCD_HandleTypeDef * hhcd)501 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
502 {
503 uint8_t idx;
504
505 /* Check the HCD handle allocation */
506 if (hhcd == NULL)
507 {
508 return HAL_ERROR;
509 }
510
511 /* Host Port State */
512 hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
513
514 /* Reset PMA Address */
515 (void)HAL_HCD_PMAReset(hhcd);
516
517 for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
518 {
519 hhcd->phy_chin_state[idx] = 0U;
520 hhcd->phy_chout_state[idx] = 0U;
521 }
522
523 /* reset Ep0 Pma allocation state */
524 hhcd->ep0_PmaAllocState = 0U;
525
526 hhcd->State = HAL_HCD_STATE_BUSY;
527
528 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
529 if (hhcd->MspDeInitCallback == NULL)
530 {
531 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */
532 }
533
534 /* DeInit the low level hardware */
535 hhcd->MspDeInitCallback(hhcd);
536 #else
537 /* DeInit the low level hardware: CLOCK, NVIC. */
538 HAL_HCD_MspDeInit(hhcd);
539 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
540
541 hhcd->State = HAL_HCD_STATE_RESET;
542
543 return HAL_OK;
544 }
545
546 /**
547 * @brief Initialize the HCD MSP.
548 * @param hhcd HCD handle
549 * @retval None
550 */
HAL_HCD_MspInit(HCD_HandleTypeDef * hhcd)551 __weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
552 {
553 /* Prevent unused argument(s) compilation warning */
554 UNUSED(hhcd);
555
556 /* NOTE : This function Should not be modified, when the callback is needed,
557 the HAL_HCD_MspInit could be implemented in the user file
558 */
559 }
560
561 /**
562 * @brief DeInitialize the HCD MSP.
563 * @param hhcd HCD handle
564 * @retval None
565 */
HAL_HCD_MspDeInit(HCD_HandleTypeDef * hhcd)566 __weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
567 {
568 /* Prevent unused argument(s) compilation warning */
569 UNUSED(hhcd);
570
571 /* NOTE : This function Should not be modified, when the callback is needed,
572 the HAL_HCD_MspDeInit could be implemented in the user file
573 */
574 }
575
HAL_HCD_SuspendCallback(HCD_HandleTypeDef * hhcd)576 __weak void HAL_HCD_SuspendCallback(HCD_HandleTypeDef *hhcd)
577 {
578 /* Prevent unused argument(s) compilation warning */
579 UNUSED(hhcd);
580
581 /* NOTE : This function Should not be modified, when the callback is needed,
582 the HAL_HCD_SuspendCallback could be implemented in the user file
583 */
584
585 }
586
HAL_HCD_ResumeCallback(HCD_HandleTypeDef * hhcd)587 __weak void HAL_HCD_ResumeCallback(HCD_HandleTypeDef *hhcd)
588 {
589 /* Prevent unused argument(s) compilation warning */
590 UNUSED(hhcd);
591
592 /* NOTE : This function Should not be modified, when the callback is needed,
593 the HAL_HCD_ResumeCallback could be implemented in the user file
594 */
595 }
596
597 /**
598 * @}
599 */
600
601 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
602 * @brief HCD IO operation functions
603 *
604 @verbatim
605 ===============================================================================
606 ##### IO operation functions #####
607 ===============================================================================
608 [..] This subsection provides a set of functions allowing to manage the USB Host Data
609 Transfer
610
611 @endverbatim
612 * @{
613 */
614
615 /**
616 * @brief Submit a new URB for processing.
617 * @param hhcd HCD handle
618 * @param ch_num Channel number.
619 * This parameter can be a value from 1 to 15
620 * @param direction Channel number.
621 * This parameter can be one of these values:
622 * 0 : Output / 1 : Input
623 * @param ep_type Endpoint Type.
624 * This parameter can be one of these values:
625 * USBH_EP_CONTROL : Control type/
626 * USBH_EP_ISO : Isochronous type/
627 * USBH_EP_BULK : Bulk type/
628 * USBH_EP_INTERRUPT : Interrupt type/
629 * @param token Endpoint Type.
630 * This parameter can be one of these values:
631 * 0: HC_PID_SETUP / 1: HC_PID_DATA1
632 * @param pbuff pointer to URB data
633 * @param length Length of URB data
634 * @param do_ping activate do ping protocol (for high speed only).
635 * This parameter can be one of these values:
636 * 0 : do ping inactive / 1 : do ping active
637 * @retval HAL status
638 */
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)639 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
640 uint8_t direction, uint8_t ep_type,
641 uint8_t token, uint8_t *pbuff,
642 uint16_t length, uint8_t do_ping)
643 {
644 UNUSED(do_ping);
645
646 if (token == 0U)
647 {
648 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_SETUP;
649 }
650 else
651 {
652 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
653 }
654
655 /* Manage Data Toggle */
656 switch (ep_type)
657 {
658 case EP_TYPE_CTRL:
659 if ((token == 1U) && (direction == 0U)) /* send data */
660 {
661 if (length == 0U)
662 {
663 /* For Status OUT stage, Length==0, Status Out PID = 1 */
664 hhcd->hc[ch_num & 0xFU].toggle_out = 1U;
665 }
666
667 /* Set the Data Toggle bit as per the Flag */
668 if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
669 {
670 /* Put the PID 0 */
671 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
672 }
673 else
674 {
675 /* Put the PID 1 */
676 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
677 }
678 }
679 break;
680
681 case EP_TYPE_BULK:
682 if (direction == 0U)
683 {
684 /* Set the Data Toggle bit as per the Flag */
685 if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
686 {
687 /* Put the PID 0 */
688 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
689 }
690 else
691 {
692 /* Put the PID 1 */
693 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
694 }
695 }
696 else
697 {
698 if (hhcd->hc[ch_num & 0xFU].toggle_in == 0U)
699 {
700 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
701 }
702 else
703 {
704 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
705 }
706 }
707 break;
708
709 case EP_TYPE_INTR:
710 if (direction == 0U)
711 {
712 /* Set the Data Toggle bit as per the Flag */
713 if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
714 {
715 /* Put the PID 0 */
716 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
717 }
718 else
719 {
720 /* Put the PID 1 */
721 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
722 }
723 }
724 else
725 {
726 if (hhcd->hc[ch_num & 0xFU].toggle_in == 0U)
727 {
728 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
729 }
730 else
731 {
732 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
733 }
734 }
735 break;
736
737 case EP_TYPE_ISOC:
738 hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
739 break;
740
741 default:
742 break;
743 }
744
745 hhcd->hc[ch_num & 0xFU].xfer_buff = pbuff;
746 hhcd->hc[ch_num & 0xFU].xfer_len = length;
747 hhcd->hc[ch_num & 0xFU].xfer_len_db = length;
748 hhcd->hc[ch_num & 0xFU].urb_state = URB_IDLE;
749 hhcd->hc[ch_num & 0xFU].xfer_count = 0U;
750 hhcd->hc[ch_num & 0xFU].state = HC_IDLE;
751
752 return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num & 0xFU]);
753 }
754 /**
755 * @brief Handle HCD interrupt request.
756 * @param hhcd HCD handle
757 * @retval None
758 */
HAL_HCD_IRQHandler(HCD_HandleTypeDef * hhcd)759 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
760 {
761 uint8_t phy_chnum;
762 uint8_t ch_dir;
763 uint32_t wIstr = USB_ReadInterrupts(hhcd->Instance);
764
765 /* Port Change Detected (Connection/Disconnection) */
766 if ((wIstr & USB_ISTR_DCON) == USB_ISTR_DCON)
767 {
768 /* Clear Flag */
769 __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_DCON);
770
771 /* Call Port IRQHandler */
772 HCD_Port_IRQHandler(hhcd);
773
774 return;
775 }
776
777 /* Correct Transaction Detected -------*/
778 if ((wIstr & USB_ISTR_CTR) == USB_ISTR_CTR)
779 {
780 /* Get Physical channel */
781 phy_chnum = (uint8_t)__HAL_HCD_GET_CHNUM(hhcd);
782
783 /* Get channel direction */
784 ch_dir = (uint8_t)__HAL_HCD_GET_CHDIR(hhcd);
785
786 if (ch_dir == CH_OUT_DIR)
787 {
788 /* Call Channel_OUT_IRQ() */
789 HCD_HC_OUT_IRQHandler(hhcd, phy_chnum);
790 }
791 else
792 {
793 /* Call Channel_IN_IRQ() */
794 HCD_HC_IN_IRQHandler(hhcd, phy_chnum);
795 }
796
797 return;
798 }
799
800 /* Wakeup Flag Detected */
801 if ((wIstr & USB_ISTR_WKUP) == USB_ISTR_WKUP)
802 {
803 if (hhcd->HostState == HCD_HCD_STATE_SUSPEND)
804 {
805 /* Set The L2Resume bit */
806 hhcd->Instance->CNTR |= USB_CNTR_L2RES;
807
808 /* Clear the wake-up flag */
809 __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_WKUP);
810
811 /* Update the USB Software state machine */
812 HAL_HCD_ResumeCallback(hhcd);
813 hhcd->HostState = HCD_HCD_STATE_RESUME;
814 }
815 else
816 {
817 /* Clear the wake-up flag */
818 __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_WKUP);
819 }
820
821 return;
822 }
823
824 /* Global Error Flag Detected */
825 if ((wIstr & USB_ISTR_ERR) == USB_ISTR_ERR)
826 {
827 __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_ERR);
828
829 return;
830 }
831
832 /* PMA Overrun detected */
833 if ((wIstr & USB_ISTR_PMAOVR) == USB_ISTR_PMAOVR)
834 {
835 __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_PMAOVR);
836
837 return;
838 }
839
840 /* Suspend Detected */
841 if ((wIstr & USB_ISTR_SUSP) == USB_ISTR_SUSP)
842 {
843 /* Set HAL State to Suspend */
844 hhcd->HostState = HCD_HCD_STATE_SUSPEND;
845
846 /* Force low-power mode in the macrocell */
847 hhcd->Instance->CNTR |= USB_CNTR_SUSPEN;
848
849 /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
850 __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_SUSP);
851
852 /* Call suspend Callback */
853 HAL_HCD_SuspendCallback(hhcd);
854
855 return;
856 }
857
858 /* Start Of Frame Detected */
859 if ((wIstr & USB_ISTR_SOF) == USB_ISTR_SOF)
860 {
861 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
862 hhcd->SOFCallback(hhcd);
863 #else
864 HAL_HCD_SOF_Callback(hhcd);
865 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
866
867 __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_SOF);
868
869 /* when first SOF is detected after USB_RESET is asserted */
870 if (hhcd->HostState == HCD_HCD_STATE_RESETED)
871 {
872 /* HAL State */
873 hhcd->HostState = HCD_HCD_STATE_RUN;
874
875 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
876 hhcd->PortEnabledCallback(hhcd);
877 #else
878 HAL_HCD_PortEnabled_Callback(hhcd);
879 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
880 }
881
882 return;
883 }
884 }
885
886 /**
887 * @brief SOF callback.
888 * @param hhcd HCD handle
889 * @retval None
890 */
HAL_HCD_SOF_Callback(HCD_HandleTypeDef * hhcd)891 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
892 {
893 /* Prevent unused argument(s) compilation warning */
894 UNUSED(hhcd);
895
896 /* NOTE : This function Should not be modified, when the callback is needed,
897 the HAL_HCD_SOF_Callback could be implemented in the user file
898 */
899 }
900
901 /**
902 * @brief Connection Event callback.
903 * @param hhcd HCD handle
904 * @retval None
905 */
HAL_HCD_Connect_Callback(HCD_HandleTypeDef * hhcd)906 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
907 {
908 /* Prevent unused argument(s) compilation warning */
909 UNUSED(hhcd);
910
911 /* NOTE : This function Should not be modified, when the callback is needed,
912 the HAL_HCD_Connect_Callback could be implemented in the user file
913 */
914 }
915
916 /**
917 * @brief Disconnection Event callback.
918 * @param hhcd HCD handle
919 * @retval None
920 */
HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef * hhcd)921 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
922 {
923 /* Prevent unused argument(s) compilation warning */
924 UNUSED(hhcd);
925
926 /* NOTE : This function Should not be modified, when the callback is needed,
927 the HAL_HCD_Disconnect_Callback could be implemented in the user file
928 */
929 }
930 /**
931 * @brief Port Enabled Event callback.
932 * @param hhcd HCD handle
933 * @retval None
934 */
HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef * hhcd)935 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
936 {
937 /* Prevent unused argument(s) compilation warning */
938 UNUSED(hhcd);
939
940 /* NOTE : This function should not be modified, when the callback is needed,
941 the HAL_HCD_Disconnect_Callback could be implemented in the user file
942 */
943 }
944 /**
945 * @brief Port Disabled Event callback.
946 * @param hhcd HCD handle
947 * @retval None
948 */
HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef * hhcd)949 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
950 {
951 /* Prevent unused argument(s) compilation warning */
952 UNUSED(hhcd);
953
954 /* NOTE : This function should not be modified, when the callback is needed,
955 the HAL_HCD_Disconnect_Callback could be implemented in the user file
956 */
957 }
958
959 /**
960 * @brief Notify URB state change callback.
961 * @param hhcd HCD handle
962 * @param chnum Channel number.
963 * This parameter can be a value from 1 to 15
964 * @param urb_state
965 * This parameter can be one of these values:
966 * URB_IDLE/
967 * URB_DONE/
968 * URB_NOTREADY/
969 * URB_NYET/
970 * URB_ERROR/
971 * URB_STALL/
972 * @retval None
973 */
HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef * hhcd,uint8_t chnum,HCD_URBStateTypeDef urb_state)974 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd,
975 uint8_t chnum, HCD_URBStateTypeDef urb_state)
976 {
977 /* Prevent unused argument(s) compilation warning */
978 UNUSED(hhcd);
979 UNUSED(chnum);
980 UNUSED(urb_state);
981
982 /* NOTE : This function Should not be modified, when the callback is needed,
983 the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
984 */
985 }
986 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
987 /**
988 * @brief Register a User USB HCD Callback
989 * To be used instead of the weak predefined callback
990 * @param hhcd USB HCD handle
991 * @param CallbackID ID of the callback to be registered
992 * This parameter can be one of the following values:
993 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
994 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
995 * @arg @ref HAL_HCD_DISCONNECT_CB_ID HCD Disconnect callback ID
996 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
997 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
998 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
999 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
1000 * @param pCallback pointer to the Callback function
1001 * @retval HAL status
1002 */
HAL_HCD_RegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID,pHCD_CallbackTypeDef pCallback)1003 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
1004 HAL_HCD_CallbackIDTypeDef CallbackID,
1005 pHCD_CallbackTypeDef pCallback)
1006 {
1007 HAL_StatusTypeDef status = HAL_OK;
1008
1009 if (pCallback == NULL)
1010 {
1011 /* Update the error code */
1012 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1013 return HAL_ERROR;
1014 }
1015 /* Process locked */
1016 __HAL_LOCK(hhcd);
1017
1018 if (hhcd->State == HAL_HCD_STATE_READY)
1019 {
1020 switch (CallbackID)
1021 {
1022 case HAL_HCD_SOF_CB_ID :
1023 hhcd->SOFCallback = pCallback;
1024 break;
1025
1026 case HAL_HCD_CONNECT_CB_ID :
1027 hhcd->ConnectCallback = pCallback;
1028 break;
1029
1030 case HAL_HCD_DISCONNECT_CB_ID :
1031 hhcd->DisconnectCallback = pCallback;
1032 break;
1033
1034 case HAL_HCD_PORT_ENABLED_CB_ID :
1035 hhcd->PortEnabledCallback = pCallback;
1036 break;
1037
1038 case HAL_HCD_PORT_DISABLED_CB_ID :
1039 hhcd->PortDisabledCallback = pCallback;
1040 break;
1041
1042 case HAL_HCD_MSPINIT_CB_ID :
1043 hhcd->MspInitCallback = pCallback;
1044 break;
1045
1046 case HAL_HCD_MSPDEINIT_CB_ID :
1047 hhcd->MspDeInitCallback = pCallback;
1048 break;
1049
1050 default :
1051 /* Update the error code */
1052 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1053 /* Return error status */
1054 status = HAL_ERROR;
1055 break;
1056 }
1057 }
1058 else if (hhcd->State == HAL_HCD_STATE_RESET)
1059 {
1060 switch (CallbackID)
1061 {
1062 case HAL_HCD_MSPINIT_CB_ID :
1063 hhcd->MspInitCallback = pCallback;
1064 break;
1065
1066 case HAL_HCD_MSPDEINIT_CB_ID :
1067 hhcd->MspDeInitCallback = pCallback;
1068 break;
1069
1070 default :
1071 /* Update the error code */
1072 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1073 /* Return error status */
1074 status = HAL_ERROR;
1075 break;
1076 }
1077 }
1078 else
1079 {
1080 /* Update the error code */
1081 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1082 /* Return error status */
1083 status = HAL_ERROR;
1084 }
1085
1086 /* Release Lock */
1087 __HAL_UNLOCK(hhcd);
1088 return status;
1089 }
1090
1091 /**
1092 * @brief Unregister an USB HCD Callback
1093 * USB HCD callback is redirected to the weak predefined callback
1094 * @param hhcd USB HCD handle
1095 * @param CallbackID ID of the callback to be unregistered
1096 * This parameter can be one of the following values:
1097 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
1098 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
1099 * @arg @ref HAL_HCD_DISCONNECT_CB_ID DRD HCD Disconnect callback ID
1100 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
1101 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
1102 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
1103 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
1104 * @retval HAL status
1105 */
HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID)1106 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd,
1107 HAL_HCD_CallbackIDTypeDef CallbackID)
1108 {
1109 HAL_StatusTypeDef status = HAL_OK;
1110
1111 /* Process locked */
1112 __HAL_LOCK(hhcd);
1113
1114 /* Setup Legacy weak Callbacks */
1115 if (hhcd->State == HAL_HCD_STATE_READY)
1116 {
1117 switch (CallbackID)
1118 {
1119 case HAL_HCD_SOF_CB_ID :
1120 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
1121 break;
1122
1123 case HAL_HCD_CONNECT_CB_ID :
1124 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
1125 break;
1126
1127 case HAL_HCD_DISCONNECT_CB_ID :
1128 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
1129 break;
1130
1131 case HAL_HCD_PORT_ENABLED_CB_ID :
1132 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
1133 break;
1134
1135 case HAL_HCD_PORT_DISABLED_CB_ID :
1136 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
1137 break;
1138
1139 case HAL_HCD_MSPINIT_CB_ID :
1140 hhcd->MspInitCallback = HAL_HCD_MspInit;
1141 break;
1142
1143 case HAL_HCD_MSPDEINIT_CB_ID :
1144 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
1145 break;
1146
1147 default :
1148 /* Update the error code */
1149 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1150
1151 /* Return error status */
1152 status = HAL_ERROR;
1153 break;
1154 }
1155 }
1156 else if (hhcd->State == HAL_HCD_STATE_RESET)
1157 {
1158 switch (CallbackID)
1159 {
1160 case HAL_HCD_MSPINIT_CB_ID :
1161 hhcd->MspInitCallback = HAL_HCD_MspInit;
1162 break;
1163
1164 case HAL_HCD_MSPDEINIT_CB_ID :
1165 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
1166 break;
1167
1168 default :
1169 /* Update the error code */
1170 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1171
1172 /* Return error status */
1173 status = HAL_ERROR;
1174 break;
1175 }
1176 }
1177 else
1178 {
1179 /* Update the error code */
1180 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1181
1182 /* Return error status */
1183 status = HAL_ERROR;
1184 }
1185
1186 /* Release Lock */
1187 __HAL_UNLOCK(hhcd);
1188 return status;
1189 }
1190
1191 /**
1192 * @brief Register USB HCD Host Channel Notify URB Change Callback
1193 * To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
1194 * @param hhcd HCD handle
1195 * @param pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
1196 * @retval HAL status
1197 */
HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd,pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)1198 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
1199 pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
1200 {
1201 HAL_StatusTypeDef status = HAL_OK;
1202
1203 if (pCallback == NULL)
1204 {
1205 /* Update the error code */
1206 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1207
1208 return HAL_ERROR;
1209 }
1210
1211 /* Process locked */
1212 __HAL_LOCK(hhcd);
1213
1214 if (hhcd->State == HAL_HCD_STATE_READY)
1215 {
1216 hhcd->HC_NotifyURBChangeCallback = pCallback;
1217 }
1218 else
1219 {
1220 /* Update the error code */
1221 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1222
1223 /* Return error status */
1224 status = HAL_ERROR;
1225 }
1226
1227 /* Release Lock */
1228 __HAL_UNLOCK(hhcd);
1229
1230 return status;
1231 }
1232
1233 /**
1234 * @brief Unregister the USB HCD Host Channel Notify URB Change Callback
1235 * USB HCD Host Channel Notify URB Change Callback is redirected
1236 * to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
1237 * @param hhcd HCD handle
1238 * @retval HAL status
1239 */
HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd)1240 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
1241 {
1242 HAL_StatusTypeDef status = HAL_OK;
1243
1244 /* Process locked */
1245 __HAL_LOCK(hhcd);
1246
1247 if (hhcd->State == HAL_HCD_STATE_READY)
1248 {
1249 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
1250 }
1251 else
1252 {
1253 /* Update the error code */
1254 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1255
1256 /* Return error status */
1257 status = HAL_ERROR;
1258 }
1259
1260 /* Release Lock */
1261 __HAL_UNLOCK(hhcd);
1262
1263 return status;
1264 }
1265 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1266
1267
1268 /**
1269 * @}
1270 */
1271
1272 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
1273 * @brief Management functions
1274 *
1275 @verbatim
1276 ===============================================================================
1277 ##### Peripheral Control functions #####
1278 ===============================================================================
1279 [..]
1280 This subsection provides a set of functions allowing to control the HCD data
1281 transfers.
1282
1283 @endverbatim
1284 * @{
1285 */
1286
1287 /**
1288 * @brief Start the host driver.
1289 * @param hhcd HCD handle
1290 * @retval HAL status
1291 */
HAL_HCD_Start(HCD_HandleTypeDef * hhcd)1292 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
1293 {
1294 __IO uint32_t count = HCD_PDWN_EXIT_CNT;
1295
1296 __HAL_LOCK(hhcd);
1297
1298 /* Remove PowerDown */
1299 hhcd->Instance->CNTR &= ~USB_CNTR_PDWN;
1300
1301 /* Few cycles to ensure exit from powerdown */
1302 while (count > 0U)
1303 {
1304 count--;
1305 }
1306
1307 /* Clear Reset */
1308 hhcd->Instance->CNTR &= ~USB_CNTR_USBRST;
1309
1310 __HAL_UNLOCK(hhcd);
1311
1312 return HAL_OK;
1313 }
1314
1315 /**
1316 * @brief Stop the host driver.
1317 * @param hhcd HCD handle
1318 * @retval HAL status
1319 */
HAL_HCD_Stop(HCD_HandleTypeDef * hhcd)1320 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
1321 {
1322 __HAL_LOCK(hhcd);
1323 /*Stop the Host IP: setting powerdown */
1324 (void)USB_StopHost(hhcd->Instance);
1325
1326 /* clear all allocated virtual channel */
1327 HAL_HCD_ClearPhyChannel(hhcd);
1328
1329 /* Reset the PMA current pointer */
1330 (void)HAL_HCD_PMAReset(hhcd);
1331
1332 /* reset Ep0 Pma allocation state */
1333 hhcd->ep0_PmaAllocState = 0U;
1334
1335 __HAL_UNLOCK(hhcd);
1336 return HAL_OK;
1337 }
1338
1339 /**
1340 * @brief Put the Device in suspend mode
1341 * @param hhcd HCD handle
1342 * @retval HAL status
1343 */
HAL_HCD_Suspend(HCD_HandleTypeDef * hhcd)1344 HAL_StatusTypeDef HAL_HCD_Suspend(HCD_HandleTypeDef *hhcd)
1345 {
1346 __IO uint32_t count = 0U;
1347
1348 /* Set Suspend Mode */
1349 hhcd->Instance->CNTR |= USB_CNTR_SUSPEN;
1350
1351 /* wait for Suspend Ready */
1352 while ((hhcd->Instance->CNTR & USB_CNTR_SUSPRDY) == 0U)
1353 {
1354 if (++count > HAL_USB_TIMEOUT)
1355 {
1356 return HAL_TIMEOUT;
1357 }
1358 }
1359
1360 return HAL_OK;
1361 }
1362
1363 /**
1364 * @brief Resume host port
1365 * @param hhcd HCD handle
1366 * @retval HAL status
1367 */
HAL_HCD_Resume(HCD_HandleTypeDef * hhcd)1368 HAL_StatusTypeDef HAL_HCD_Resume(HCD_HandleTypeDef *hhcd)
1369 {
1370 /* Set Resume bit */
1371 hhcd->Instance->CNTR |= USB_CNTR_L2RES;
1372
1373 return HAL_OK;
1374 }
1375
1376 /**
1377 * @brief Reset the host port.
1378 * @param hhcd HCD handle
1379 * @retval HAL status
1380 */
HAL_HCD_ResetPort(HCD_HandleTypeDef * hhcd)1381 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
1382 {
1383 __HAL_LOCK(hhcd);
1384
1385 /* Reset the USB Port by inserting an SE0 on the bus */
1386 (void)USB_ResetPort(hhcd->Instance);
1387
1388 if (hhcd->HostState == HCD_HCD_STATE_CONNECTED)
1389 {
1390 hhcd->HostState = HCD_HCD_STATE_RESETED;
1391 }
1392 __HAL_UNLOCK(hhcd);
1393
1394 return HAL_OK;
1395 }
1396
1397 /**
1398 * @brief Resme the host port.
1399 * @param hhcd HCD handle
1400 * @retval HAL status
1401 */
HAL_HCD_ResumePort(HCD_HandleTypeDef * hhcd)1402 HAL_StatusTypeDef HAL_HCD_ResumePort(HCD_HandleTypeDef *hhcd)
1403 {
1404 /* Set Resume bit */
1405 hhcd->Instance->CNTR |= USB_CNTR_L2RES;
1406 HAL_Delay(30U);
1407
1408 /* Clear Resume bit */
1409 hhcd->Instance->CNTR &= ~USB_CNTR_L2RES;
1410
1411 return HAL_OK;
1412 }
1413
1414
1415 /**
1416 * @}
1417 */
1418
1419 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
1420 * @brief Peripheral State functions
1421 *
1422 @verbatim
1423 ===============================================================================
1424 ##### Peripheral State functions #####
1425 ===============================================================================
1426 [..]
1427 This subsection permits to get in run-time the status of the peripheral
1428 and the data flow.
1429
1430 @endverbatim
1431 * @{
1432 */
1433
1434 /**
1435 * @brief Return the HCD handle state.
1436 * @param hhcd HCD handle
1437 * @retval HAL state
1438 */
HAL_HCD_GetState(HCD_HandleTypeDef const * hhcd)1439 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef const *hhcd)
1440 {
1441 return hhcd->State;
1442 }
1443
1444 /**
1445 * @brief Return URB state for a channel.
1446 * @param hhcd HCD handle
1447 * @param chnum Channel number.
1448 * This parameter can be a value from 1 to 15
1449 * @retval URB state.
1450 * This parameter can be one of these values:
1451 * URB_IDLE/
1452 * URB_DONE/
1453 * URB_NOTREADY/
1454 * URB_NYET/
1455 * URB_ERROR/
1456 * URB_STALL
1457 */
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1458 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1459 {
1460 return hhcd->hc[chnum].urb_state;
1461 }
1462
1463
1464 /**
1465 * @brief Return the last host transfer size.
1466 * @param hhcd HCD handle
1467 * @param chnum Channel number.
1468 * This parameter can be a value from 1 to 15
1469 * @retval last transfer size in byte
1470 */
HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1471 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1472 {
1473 return hhcd->hc[chnum].xfer_count;
1474 }
1475
1476 /**
1477 * @brief Return the Host Channel state.
1478 * @param hhcd HCD handle
1479 * @param chnum Channel number.
1480 * This parameter can be a value from 1 to 15
1481 * @retval Host channel state
1482 * This parameter can be one of these values:
1483 * HC_IDLE/
1484 * HC_XFRC/
1485 * HC_HALTED/
1486 * HC_NYET/
1487 * HC_NAK/
1488 * HC_STALL/
1489 * HC_XACTERR/
1490 * HC_BBLERR/
1491 * HC_DATATGLERR
1492 */
HAL_HCD_HC_GetState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1493 HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1494 {
1495 return hhcd->hc[chnum].state;
1496 }
1497
1498 /**
1499 * @brief Return the current Host frame number.
1500 * @param hhcd HCD handle
1501 * @retval Current Host frame number
1502 */
HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef * hhcd)1503 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
1504 {
1505 return (USB_GetCurrentFrame(hhcd->Instance));
1506 }
1507
1508 /**
1509 * @brief Return the Host enumeration speed.
1510 * @param hhcd HCD handle
1511 * @retval speed : Device speed after Host enumeration
1512 * This parameter can be one of these values:
1513 * @arg HCD_DEVICE_SPEED_FULL: Full speed mode
1514 * @arg HCD_DEVICE_SPEED_LOW: Low speed mode
1515 */
HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef * hhcd)1516 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
1517 {
1518 return (USB_GetHostSpeed(hhcd->Instance));
1519 }
1520
1521 /**
1522 * @brief Set host channel Hub Information.
1523 * @param hhcd HCD handle
1524 * @param ch_num Channel number.
1525 * This parameter can be a value from 1 to 8
1526 * @param addr Hub address
1527 * @param PortNbr Hub port number
1528 * @retval HAL status
1529 */
HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t addr,uint8_t PortNbr)1530 HAL_StatusTypeDef HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1531 uint8_t addr, uint8_t PortNbr)
1532 {
1533 hhcd->hc[ch_num].hub_addr = addr;
1534 hhcd->hc[ch_num].hub_port_nbr = PortNbr;
1535
1536 return HAL_OK;
1537 }
1538
1539
1540 /**
1541 * @brief Clear host channel hub information.
1542 * @param hhcd HCD handle
1543 * @param ch_num Channel number.
1544 * This parameter can be a value from 1 to 8
1545 * @retval HAL status
1546 */
HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num)1547 HAL_StatusTypeDef HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
1548 {
1549 hhcd->hc[ch_num].hub_addr = 0U;
1550 hhcd->hc[ch_num].hub_port_nbr = 0U;
1551
1552 return HAL_OK;
1553 }
1554
1555 #if (USE_USB_DOUBLE_BUFFER == 1U)
1556 /**
1557 * @brief Handle Host Channel OUT Double Buffer Bulk requests.
1558 * @param hhcd HCD handle
1559 * @param ch_num Channel number This parameter can be a value from 1 to 15
1560 * @param phy_chnum Physical Channel number [0..7]
1561 * @param regvalue contain Snapshot of the EPCHn register when ISR is detected
1562 * @retval none
1563 */
HCD_HC_OUT_BulkDb(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)1564 static void HCD_HC_OUT_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1565 uint8_t phy_chnum, uint32_t regvalue)
1566 {
1567 uint16_t data_xfr;
1568 uint16_t len;
1569
1570 /* Send Buffer0 */
1571 if ((regvalue & USB_CH_DTOG_TX) != 0U)
1572 {
1573 data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->TXBD & 0x03FF0000U) >> 16U);
1574
1575 if (hhcd->hc[ch_num & 0xFU].xfer_len >= data_xfr)
1576 {
1577 hhcd->hc[ch_num & 0xFU].xfer_len -= data_xfr;
1578 }
1579 else
1580 {
1581 hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1582 }
1583
1584 /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
1585 if (hhcd->hc[ch_num & 0xFU].xfer_len != 0U)
1586 {
1587 /* manage multiple Xfer */
1588 hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1589
1590 /* check if we need to free user buffer */
1591 if ((regvalue & USB_CH_DTOG_RX) != 0U)
1592 {
1593 /* Toggle SwBuff */
1594 HCD_CLEAR_TX_DTOG(hhcd->Instance, phy_chnum);
1595 HCD_CLEAR_RX_DTOG(hhcd->Instance, phy_chnum);
1596 HCD_TX_DTOG(hhcd->Instance, phy_chnum);
1597 }
1598
1599 /* hhcd->hc[ch_num&0xFU].xfer_len_db==0 ==> when all data are written in the PMA to yet transferred */
1600 if (hhcd->hc[ch_num & 0xFU].xfer_len_db > 0U) /* Still data to fill in the buffer */
1601 {
1602 hhcd->hc[ch_num & 0xFU].xfer_buff += data_xfr;
1603
1604 /* calculate len of new buffer to fill */
1605 if (hhcd->hc[ch_num & 0xFU].xfer_len_db > hhcd->hc[ch_num & 0xFU].max_packet)
1606 {
1607 len = (uint16_t)hhcd->hc[ch_num & 0xFU].max_packet;
1608 hhcd->hc[ch_num & 0xFU].xfer_len_db -= len;
1609 }
1610 else
1611 {
1612 len = (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_len_db;
1613 hhcd->hc[ch_num & 0xFU].xfer_len_db = 0U; /* end of fill buffer */
1614 }
1615
1616 /* Write remaining data to Buffer0 */
1617 HCD_SET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum, 1U, (uint16_t)len);
1618 USB_WritePMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1619 hhcd->hc[ch_num & 0xFU].pmaaddr0, (uint16_t)len);
1620 }
1621 /* start a new transfer */
1622 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_VALID);
1623 }
1624 else
1625 {
1626 /* Transfer complete state */
1627 hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1628 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1629 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1630 hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
1631 /* Close the Channel */
1632 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
1633 }
1634 }
1635 else
1636 {
1637 /* Send Buffer1 */
1638 data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->RXBD & 0x03FF0000U) >> 16U);
1639
1640 if (hhcd->hc[ch_num & 0xFU].xfer_len >= data_xfr) /* updated */
1641 {
1642 hhcd->hc[ch_num & 0xFU].xfer_len -= data_xfr;
1643 }
1644
1645 /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
1646 if (hhcd->hc[ch_num & 0xFU].xfer_len != 0U)
1647 {
1648 /* manage multiple Xfer */
1649 hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1650
1651 /* check if we need to free user buffer */
1652 if ((regvalue & USB_CH_DTOG_RX) == 0U)
1653 {
1654 /* Toggle SwBuff */
1655 HCD_CLEAR_TX_DTOG(hhcd->Instance, phy_chnum);
1656 HCD_CLEAR_RX_DTOG(hhcd->Instance, phy_chnum);
1657 HCD_RX_DTOG(hhcd->Instance, phy_chnum);
1658 }
1659
1660 /* hhcd->hc[ch_num&0xFU].xfer_len_db==0 ==> when all data are written in the PMA to yet transferred */
1661 if (hhcd->hc[ch_num & 0xFU].xfer_len_db > 0U) /* Still data to fill in the buffer */
1662 {
1663 hhcd->hc[ch_num & 0xFU].xfer_buff += data_xfr;
1664
1665 /* calculate len of new buffer to fill */
1666 if (hhcd->hc[ch_num & 0xFU].xfer_len_db > hhcd->hc[ch_num & 0xFU].max_packet)
1667 {
1668 len = hhcd->hc[ch_num & 0xFU].max_packet;
1669 hhcd->hc[ch_num & 0xFU].xfer_len_db -= len;
1670 }
1671 else
1672 {
1673 len = (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_len_db;
1674 hhcd->hc[ch_num & 0xFU].xfer_len_db = 0U; /* end of fill buffer */
1675 }
1676
1677 /* Write remaining data to Buffer0 */
1678 HCD_SET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum, 1U, (uint16_t)len);
1679
1680 USB_WritePMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1681 hhcd->hc[ch_num & 0xFU].pmaaddr1, (uint16_t)len);
1682 }
1683
1684 /* start a new transfer */
1685 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_VALID);
1686 }
1687 else
1688 {
1689 /* Transfer complete state */
1690 hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1691 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1692 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1693 hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
1694
1695 /* Close the channel */
1696 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
1697 }
1698 }
1699 }
1700
1701
1702 /**
1703 * @brief Handle Host Channel IN Double Buffer Bulk requests.
1704 * @param hhcd HCD handle
1705 * @param ch_num Channel number: This parameter can be a value from 1 to 15
1706 * @param phy_chnum Physical Channel number [0..7]
1707 * @param regvalue contain Snapshot of the EPCHn register when ISR is detected
1708 * @retval none
1709 */
HCD_HC_IN_BulkDb(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)1710 static void HCD_HC_IN_BulkDb(HCD_HandleTypeDef *hhcd,
1711 uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue)
1712 {
1713 uint16_t received_bytes;
1714
1715 /* Read from Buffer 0 */
1716 if ((regvalue & USB_CH_DTOG_RX) != 0U)
1717 {
1718 received_bytes = (uint16_t)HCD_GET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum);
1719
1720 if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
1721 {
1722 hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1723 }
1724 else
1725 {
1726 hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
1727 }
1728
1729 /* Check if we Need to free the other buffer for the IP */
1730 if ((hhcd->hc[ch_num & 0xFU].xfer_len != 0U) && ((regvalue & USB_CH_DTOG_TX) != 0U))
1731 {
1732 /* Toggle SwBuff to Allow the IP to submit a new IN */
1733 HCD_FREE_USER_BUFFER(hhcd->Instance, phy_chnum, 0U);
1734 }
1735
1736 /* Read the byte from PMA to user Buffer(System Memory) */
1737 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1738 hhcd->hc[ch_num & 0xFU].pmaaddr0, (uint16_t)received_bytes);
1739 }
1740 else
1741 {
1742 /* Read from Buffer 1 */
1743 received_bytes = (uint16_t) HCD_GET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum);
1744
1745 if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
1746 {
1747 hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1748 }
1749 else
1750 {
1751 hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
1752 }
1753
1754 /* Check if we Need to free the other buffer for the IP */
1755 if ((hhcd->hc[ch_num & 0xFU].xfer_len != 0U) && ((regvalue & USB_CH_DTOG_TX) == 0U))
1756 {
1757 /* Toggle SwBuff */
1758 HCD_FREE_USER_BUFFER(hhcd->Instance, phy_chnum, 0U);
1759 }
1760
1761 /* Read the byte from PMA to user Buffer(System Memory) */
1762 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1763 hhcd->hc[ch_num & 0xFU].pmaaddr1, (uint16_t)received_bytes);
1764 }
1765
1766 /* update the global number of all received bytes */
1767 hhcd->hc[ch_num & 0xFU].xfer_count += received_bytes;
1768
1769 /* Transfer complete state */
1770 hhcd->hc[ch_num & 0xFU].state = HC_ACK;
1771 hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
1772
1773 if ((hhcd->hc[ch_num & 0xFU].xfer_len == 0U) ||
1774 ((received_bytes < hhcd->hc[ch_num & 0xFU].max_packet)))
1775 {
1776 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1777 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1778
1779 /* disable channel */
1780 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1781 }
1782 else
1783 {
1784 hhcd->hc[ch_num & 0xFU].xfer_buff += received_bytes;
1785
1786 /* Reactivate the Channel Submit an other URB since the Transfer is not yet completed */
1787 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_STRX);
1788 }
1789 }
1790 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1791
1792 /**
1793 * @brief Handle Host Channel IN Isochronous Transaction
1794 * @param hhcd HCD handle
1795 * @param ch_num Channel number: This parameter can be a value from 1 to 15
1796 * @param phy_chnum Physical Channel number [0..7]
1797 * @param regvalue contain Snapshot of the EPCHn register when ISR is detected
1798 * @retval none
1799 */
HCD_HC_IN_ISO(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)1800 static void inline HCD_HC_IN_ISO(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1801 uint8_t phy_chnum, uint32_t regvalue)
1802 {
1803 /* Check if Double buffer isochronous */
1804 if ((regvalue & USB_CH_KIND) != 0U)
1805 {
1806 /* Get Data IN Packet */
1807 hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_RX_CNT(hhcd->Instance, phy_chnum);
1808 if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
1809 {
1810 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1811 hhcd->hc[ch_num & 0xFU].pmaadress,
1812 (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
1813
1814 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1815 }
1816 }
1817 #if (USE_USB_DOUBLE_BUFFER == 1U)
1818 else /* double buffer isochronous */
1819 {
1820 /* Read from Buffer0 */
1821 if ((regvalue & USB_CH_DTOG_RX) != 0U)
1822 {
1823 /* Get number of Received byte in buffer0 */
1824 hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum);
1825
1826 if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
1827 {
1828 /* Read from Buffer0 */
1829 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1830 hhcd->hc[ch_num & 0xFU].pmaaddr0,
1831 (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
1832
1833 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1834 }
1835 }
1836 else
1837 {
1838 /* Get number of Received byte in buffer1 */
1839 hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum);
1840
1841 if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
1842 {
1843 /* Read from Buffer1 */
1844 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1845 hhcd->hc[ch_num & 0xFU].pmaaddr1,
1846 (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
1847
1848 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1849 }
1850 }
1851 }
1852 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1853
1854 /* Transfer complete state */
1855 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1856
1857 /* Clear VTRX */
1858 HCD_CLEAR_RX_CH_CTR(hhcd->Instance, phy_chnum);
1859 }
1860
1861 /**
1862 * @brief Handle Host Channel IN interrupt requests.
1863 * @param hhcd HCD handle
1864 * @param chnum Channel number
1865 * This parameter can be a value from 1 to 8
1866 * @retval none
1867 */
HCD_HC_IN_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1868 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1869 {
1870 uint16_t received_bytes;
1871 uint8_t phy_chnum = chnum;
1872 uint8_t ch_num = HAL_HCD_GetLogical_Channel(hhcd, phy_chnum, 1U);
1873
1874 /* Take a Flag snapshot from the CHEP register, due to STRX bits are used for both control and status */
1875 uint32_t ch_reg = HCD_GET_CHANNEL(hhcd->Instance, phy_chnum);
1876
1877 /* Manage Correct Transaction */
1878 if ((ch_reg & USB_CH_ERRRX) == 0U)
1879 {
1880 /* Isochronous Channel */
1881 if ((ch_reg & USB_CH_UTYPE) == USB_EP_ISOCHRONOUS)
1882 {
1883 HCD_HC_IN_ISO(hhcd, ch_num, phy_chnum, ch_reg);
1884 }
1885 else
1886 {
1887 /* manage ACK response single buffer */
1888 if (((ch_reg) & USB_CH_RX_STRX) == USB_CH_RX_ACK_SBUF)
1889 {
1890 /* Get Control Data OUT Packet */
1891 received_bytes = (uint16_t)HCD_GET_CH_RX_CNT(hhcd->Instance, phy_chnum);
1892
1893 /* Read the byte from PMA to user Buffer(System Memory) */
1894 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1895 hhcd->hc[ch_num & 0xFU].pmaadress, (uint16_t)received_bytes);
1896
1897 /* update the global number of all received bytes */
1898 hhcd->hc[ch_num & 0xFU].xfer_count += received_bytes;
1899
1900 /* Transfer complete state */
1901 hhcd->hc[ch_num & 0xFU].state = HC_ACK;
1902 hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
1903
1904 if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
1905 {
1906 hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1907 }
1908 else
1909 {
1910 hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
1911 }
1912
1913 if ((hhcd->hc[ch_num & 0xFU].xfer_len == 0U) ||
1914 ((received_bytes < hhcd->hc[ch_num & 0xFU].max_packet)))
1915 {
1916 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1917 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1918 }
1919 else
1920 {
1921 hhcd->hc[ch_num & 0xFU].xfer_buff += received_bytes;
1922
1923 /* Reactivate the Channel to Submit another URB since the Transfer is not yet completed */
1924 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_STRX);
1925 }
1926
1927 if ((hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_BULK) ||
1928 (hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_INTR))
1929 {
1930 hhcd->hc[ch_num & 0xFU].toggle_in ^= 1U;
1931 }
1932 }
1933 /* Manage NACK Response */
1934 else if (((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_NAK)
1935 && (hhcd->hc[ch_num & 0xFU].urb_state != URB_DONE))
1936 {
1937 hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
1938 hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
1939 hhcd->hc[ch_num & 0xFU].state = HC_NAK;
1940
1941 if (hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_INTR)
1942 {
1943 /* Close the channel */
1944 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1945 }
1946 }
1947 /* Manage STALL Response */
1948 else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_STALL)
1949 {
1950 (void)HAL_HCD_HC_Halt(hhcd, ch_num);
1951 hhcd->hc[ch_num & 0xFU].state = HC_STALL;
1952 hhcd->hc[ch_num & 0xFU].urb_state = URB_STALL;
1953
1954 /* Close the channel */
1955 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1956 }
1957 #if (USE_USB_DOUBLE_BUFFER == 1U)
1958 /* Double Buffer Management in case of Bulk Transaction */
1959 else if (((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_ACK_DBUF)
1960 && ((ch_reg & USB_CH_KIND) != 0U))
1961 {
1962 /* Bulk IN Double Buffer ISR */
1963 HCD_HC_IN_BulkDb(hhcd, ch_num, phy_chnum, ch_reg);
1964 }
1965 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1966 else
1967 {
1968 /*....*/
1969 /* not defined state: STRX=11 in single buffer no iso is not defined */
1970 }
1971
1972 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1973 hhcd->HC_NotifyURBChangeCallback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
1974 #else
1975 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
1976 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1977
1978 /*Clear VTRX */
1979 HCD_CLEAR_RX_CH_CTR(hhcd->Instance, phy_chnum);
1980 }
1981 }
1982 else /* Error detected during last transaction */
1983 {
1984 /* Set URB Error State */
1985 hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
1986 hhcd->hc[ch_num & 0xFU].ErrCnt++;
1987 hhcd->hc[ch_num & 0xFU].state = HC_XACTERR;
1988
1989 /* Clear VTTRX & ERR_RX */
1990 HCD_CLEAR_RX_CH_ERR(hhcd->Instance, phy_chnum);
1991
1992 /* Check Error number */
1993 if (hhcd->hc[ch_num & 0xFU].ErrCnt > 3U)
1994 {
1995 hhcd->hc[ch_num & 0xFU].urb_state = URB_ERROR;
1996 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1997
1998 /* Clear pending err_tx */
1999 HCD_CLEAR_RX_CH_ERR(hhcd->Instance, phy_chnum);
2000 }
2001
2002 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2003 hhcd->HC_NotifyURBChangeCallback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2004 #else
2005 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2006 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2007 }
2008 }
2009
2010
2011 /**
2012 * @brief Handle Host Channel OUT interrupt requests.
2013 * @param hhcd HCD handle
2014 * @param chnum Channel number
2015 * This parameter can be a value from 1 to 8
2016 * @retval none
2017 */
HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)2018 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
2019 {
2020 __IO uint32_t WregCh;
2021 uint16_t data_xfr;
2022 uint8_t phy_chnum = chnum;
2023
2024 /* Get Virtual Channel number */
2025 uint8_t ch_num = HAL_HCD_GetLogical_Channel(hhcd, phy_chnum, 0U);
2026
2027 /* Take a Flag snapshot from the CHEP register, due to STRX bits are used for both control &status */
2028 uint32_t ch_reg = *(__IO uint32_t *)(&(hhcd->Instance->CHEP0R) + phy_chnum);
2029
2030 /*------ Manage Correct Transaction ------*/
2031 if ((ch_reg & USB_CH_ERRTX) == 0U)
2032 {
2033 /* Handle Isochronous channel */
2034 if ((ch_reg & USB_CH_UTYPE) == USB_EP_ISOCHRONOUS)
2035 {
2036 /* Correct transaction */
2037 if ((hhcd->Instance->ISTR & USB_ISTR_ERR) == 0U)
2038 {
2039 /* Double buffer isochronous out */
2040 if ((ch_reg & USB_CH_KIND) != 0U)
2041 {
2042 HCD_SET_CH_TX_CNT(hhcd->Instance, phy_chnum, 0U);
2043 }
2044 #if (USE_USB_DOUBLE_BUFFER == 1U)
2045 else /* Double buffer isochronous out */
2046 {
2047 /* Odd Transaction */
2048 if ((ch_reg & USB_CH_DTOG_TX) != 0U)
2049 {
2050 HCD_SET_CH_TX_CNT(hhcd->Instance, phy_chnum, 0U);
2051 }
2052 /* Even Transaction */
2053 else
2054 {
2055 HCD_SET_CH_RX_CNT(hhcd->Instance, phy_chnum, 0U);
2056 }
2057
2058 USB_DRD_SET_CHEP_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
2059 }
2060 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2061
2062 /* Transfer complete state */
2063 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
2064 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
2065 }
2066
2067 /*Clear Correct Transfer */
2068 HCD_CLEAR_TX_CH_CTR(hhcd->Instance, phy_chnum);
2069
2070 /*TX COMPLETE*/
2071 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2072 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2073 #else
2074 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2075 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2076
2077 }
2078 else /* Manage all Non Isochronous Transaction */
2079 {
2080 /* Check ACK response */
2081 if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF)
2082 {
2083 data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->TXBD & 0x03FF0000U) >> 16U);
2084
2085 if (hhcd->hc[ch_num & 0xFU].xfer_len >= data_xfr)
2086 {
2087 hhcd->hc[ch_num & 0xFU].xfer_len -= data_xfr;
2088 }
2089 else
2090 {
2091 hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
2092 }
2093
2094 if ((hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_BULK) ||
2095 (hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_INTR))
2096 {
2097 hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
2098 }
2099
2100 /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
2101 if (hhcd->hc[ch_num & 0xFU].xfer_len != 0U)
2102 {
2103 /* Manage multiple Xfer */
2104 hhcd->hc[ch_num & 0xFU].xfer_buff += data_xfr;
2105 hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
2106
2107 /* Start a new transfer */
2108 (void) USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num & 0xFU]);
2109 }
2110 else
2111 {
2112 /* Transfer complete */
2113 hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
2114 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
2115 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
2116 }
2117 }
2118 /* Check NACK Response */
2119 else if (((ch_reg & USB_CHEP_NAK) == USB_CHEP_NAK) ||
2120 ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK))
2121 {
2122 /* Update Channel status */
2123 hhcd->hc[ch_num & 0xFU].state = HC_NAK;
2124 hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
2125 hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
2126
2127 /* Get Channel register value */
2128 WregCh = *(__IO uint32_t *)(&(hhcd->Instance->CHEP0R) + phy_chnum);
2129
2130 /* Clear NAK status */
2131 WregCh &= ~USB_CHEP_NAK & USB_CHEP_REG_MASK;
2132
2133 /* Update channel register Value */
2134 HCD_SET_CHANNEL(hhcd->Instance, phy_chnum, WregCh);
2135
2136 if (hhcd->hc[ch_num & 0xFU].doublebuffer == 0U)
2137 {
2138 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2139 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2140 #else
2141 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2142 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2143 }
2144 }
2145 /* Check STALL Response */
2146 else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL)
2147 {
2148 (void) HAL_HCD_HC_Halt(hhcd, (uint8_t)ch_num);
2149 hhcd->hc[ch_num & 0xFU].state = HC_STALL;
2150 hhcd->hc[ch_num & 0xFU].urb_state = URB_STALL;
2151 }
2152 #if (USE_USB_DOUBLE_BUFFER == 1U)
2153 /* Check double buffer ACK in case of bulk transaction */
2154 else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_DBUF)
2155 {
2156 /* Double buffer management Bulk Out */
2157 (void) HCD_HC_OUT_BulkDb(hhcd, ch_num, (uint8_t)phy_chnum, ch_reg);
2158 }
2159 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2160 else
2161 {
2162 /*...*/
2163 }
2164
2165 if ((ch_reg & USB_CH_TX_STTX) != USB_CH_TX_NAK)
2166 {
2167 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2168 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2169 #else
2170 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2171 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2172 }
2173
2174 HCD_CLEAR_TX_CH_CTR(hhcd->Instance, phy_chnum);
2175 } /* End no isochronous */
2176 }
2177 /*------ Manage Transaction Error------*/
2178 else
2179 {
2180 hhcd->hc[ch_num & 0xFU].ErrCnt++;
2181 if (hhcd->hc[ch_num & 0xFU].ErrCnt > 3U)
2182 {
2183 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
2184 hhcd->hc[ch_num & 0xFU].urb_state = URB_ERROR;
2185 }
2186 else
2187 {
2188 hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
2189 }
2190
2191 hhcd->hc[ch_num & 0xFU].state = HC_XACTERR;
2192
2193 /* Clear ERR_TX */
2194 HCD_CLEAR_TX_CH_ERR(hhcd->Instance, phy_chnum);
2195
2196 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2197 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2198 #else
2199 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2200 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2201 }
2202 }
2203
2204
2205 /**
2206 * @brief Handle Host Port interrupt requests.
2207 * @param hhcd HCD handle
2208 * @retval None
2209 */
HCD_Port_IRQHandler(HCD_HandleTypeDef * hhcd)2210 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
2211 {
2212 uint32_t FnrReg = hhcd->Instance->FNR;
2213 uint32_t IstrReg = hhcd->Instance->ISTR;
2214
2215 /* SE0 detected USB Disconnected state */
2216 if ((FnrReg & (USB_FNR_RXDP | USB_FNR_RXDM)) == 0U)
2217 {
2218 /* Host Port State */
2219 hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
2220
2221 /* Clear all allocated virtual channel */
2222 HAL_HCD_ClearPhyChannel(hhcd);
2223
2224 /* Reset the PMA current pointer */
2225 (void)HAL_HCD_PMAReset(hhcd);
2226
2227 /* Reset Ep0 Pma allocation state */
2228 hhcd->ep0_PmaAllocState = 0U;
2229
2230 /* Disconnection Callback */
2231 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2232 hhcd->DisconnectCallback(hhcd);
2233 #else
2234 HAL_HCD_Disconnect_Callback(hhcd);
2235 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2236
2237 return;
2238 }
2239
2240 if ((hhcd->HostState == HCD_HCD_STATE_DISCONNECTED) != 0U)
2241 {
2242 /* J-state or K-state detected & LastState=Disconnected */
2243 if (((FnrReg & USB_FNR_RXDP) != 0U) || ((IstrReg & USB_ISTR_LS_DCONN) != 0U))
2244 {
2245 hhcd->HostState = HCD_HCD_STATE_CONNECTED;
2246
2247 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2248 hhcd->ConnectCallback(hhcd);
2249 #else
2250 HAL_HCD_Connect_Callback(hhcd);
2251 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2252 }
2253 }
2254 else
2255 {
2256 /* J-state or K-state detected & lastState=Connected: a Missed disconnection is detected */
2257 if (((FnrReg & USB_FNR_RXDP) != 0U) || ((IstrReg & USB_ISTR_LS_DCONN) != 0U))
2258 {
2259 /* Host Port State */
2260 hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
2261
2262 /* clear all allocated virtual channel */
2263 HAL_HCD_ClearPhyChannel(hhcd);
2264
2265 /* Reset the PMA current pointer */
2266 (void)HAL_HCD_PMAReset(hhcd);
2267
2268 /* reset Ep0 PMA allocation state */
2269 hhcd->ep0_PmaAllocState = 0U;
2270
2271 /* Disconnection Callback */
2272 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2273 hhcd->DisconnectCallback(hhcd);
2274 #else
2275 HAL_HCD_Disconnect_Callback(hhcd);
2276 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2277 }
2278 }
2279 }
2280
2281
2282 /**
2283 * @brief Check if the ch_num are already reserved to a physical channel
2284 * @param hhcd HCD handle
2285 * @param ch_num Channel number
2286 * This parameter can be a value from 1 to 15
2287 * @retval HAL status
2288 */
HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const * hhcd,uint8_t ch_num)2289 static uint8_t HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const *hhcd, uint8_t ch_num)
2290 {
2291 uint8_t idx;
2292
2293 /* Check if the logical channel are already opened */
2294 for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
2295 {
2296 if ((((hhcd->phy_chin_state[idx] & 0xF0U) >> 4U) == ((uint16_t)ch_num + 1U)) &&
2297 (hhcd->phy_chin_state[idx] != 0U))
2298 {
2299 return (1U | (idx << 4U));
2300 }
2301
2302 if ((((hhcd->phy_chout_state[idx] & 0xF0U) >> 4U) == ((uint16_t)ch_num + 1U)) &&
2303 (hhcd->phy_chout_state[idx] != 0U))
2304 {
2305 return (1U | (idx << 4U));
2306 }
2307 }
2308
2309 return 0U;
2310 }
2311
2312
2313 /**
2314 * @brief Get a Logical Channel number from physical Channel
2315 * @param hhcd HCD handle
2316 * @param phy_chnum
2317 * This parameter can be a value from 1 to 15
2318 * @param dir Channel direction
2319 * -0 OUT_Channel
2320 * -1 IN_Channel
2321 * @retval HAL status
2322 */
HAL_HCD_GetLogical_Channel(HCD_HandleTypeDef const * hhcd,uint8_t phy_chnum,uint8_t dir)2323 static uint8_t HAL_HCD_GetLogical_Channel(HCD_HandleTypeDef const *hhcd,
2324 uint8_t phy_chnum, uint8_t dir)
2325 {
2326 /* Out Channel Direction */
2327 if (dir == 0U)
2328 {
2329 if (((hhcd->phy_chout_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) != 0U)
2330 {
2331 return ((uint8_t)((hhcd->phy_chout_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) - 1U);
2332 }
2333 else
2334 {
2335 /* Channel not registered Error */
2336 return HCD_LOGICAL_CH_NOT_OPENED;
2337 }
2338 }
2339 /* IN Channel Direction */
2340 else
2341 {
2342 if (((hhcd->phy_chin_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) != 0U)
2343 {
2344 return ((uint8_t)((hhcd->phy_chin_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) - 1U);
2345 }
2346 else
2347 {
2348 /* Channel not registered Error */
2349 return HCD_LOGICAL_CH_NOT_OPENED;
2350 }
2351 }
2352 }
2353
2354
2355 /**
2356 * @brief Get a free physical Channel number according to the direction
2357 * @param hhcd HCD handle
2358 * @param ch_num Channel number
2359 * This parameter can be a value from 1 to 15
2360 * @param epnum Endpoint number
2361 * This parameter can be a value from 1 to 15
2362 * @param ep_type Endpoint Type
2363 * This parameter can be one of these values:
2364 * EP_TYPE_CTRL Control type,
2365 * EP_TYPE_ISOC Isochronous type,
2366 * EP_TYPE_BULK Bulk type,
2367 * EP_TYPE_INTR Interrupt type
2368 * @retval if physical channel is available return Phy_channel number
2369 else return HCD_FREE_CH_NOT_FOUND
2370 */
HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t epnum,uint8_t ep_type)2371 static uint8_t HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
2372 uint8_t epnum, uint8_t ep_type)
2373 {
2374 uint8_t idx;
2375
2376 if ((epnum & 0x7FU) == 0U)
2377 {
2378 idx = 0U;
2379
2380 if (ch_num == 0U)
2381 {
2382 if (hhcd->phy_chin_state[idx] == 0U)
2383 {
2384 /* chin_state to store the ep_type to be used for the same channel in OUT direction
2385 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2386 hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2387 ((uint16_t)ep_type + 1U) |
2388 (((uint16_t)epnum & 0x0FU) << 8U);
2389 }
2390
2391 if (hhcd->phy_chout_state[idx] == 0U)
2392 {
2393 /* chout_state will store the ep_type to be used for the same channel in IN direction
2394 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2395 hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2396 ((uint16_t)ep_type + 1U) |
2397 (((uint16_t)epnum & 0x0FU) << 8U);
2398 }
2399 }
2400 else
2401 {
2402 if ((epnum & 0x80U) != 0U)
2403 {
2404 if (((hhcd->phy_chin_state[idx] & 0xF0U) >> 4U) != ((uint16_t)ch_num + 1U))
2405 {
2406 /* chin_state to store the ep_type to be used for the same channel in OUT direction
2407 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2408 hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2409 ((uint16_t)ep_type + 1U) |
2410 (((uint16_t)epnum & 0x0FU) << 8U);
2411 }
2412 }
2413 else
2414 {
2415 if (((hhcd->phy_chout_state[idx] & 0xF0U) >> 4U) != ((uint16_t)ch_num + 1U))
2416 {
2417 /* chout_state will store the ep_type to be used for the same channel in IN direction
2418 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2419 hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2420 ((uint16_t)ep_type + 1U) |
2421 (((uint16_t)epnum & 0x0FU) << 8U);
2422 }
2423 }
2424 }
2425
2426 return idx;
2427 }
2428
2429 if ((epnum & 0x80U) != 0U)
2430 {
2431 /* Find a new available physical in channel */
2432 for (idx = 1U; idx < hhcd->Init.Host_channels; idx++)
2433 {
2434 /* Check if the same epnum is allocated then allocate the same physical channel OUT for IN Logical Channel */
2435 if ((hhcd->phy_chin_state[idx] == 0U) &&
2436 ((((hhcd->phy_chout_state[idx] & 0x000FU) == ((uint16_t)ep_type + 1U)) &&
2437 (((hhcd->phy_chout_state[idx] & 0x0F00U) == ((uint16_t)epnum & 0x0FU)))) ||
2438 (hhcd->phy_chout_state[idx] == 0U)))
2439 {
2440 /* chin_state to store the ep_type to be used for the same channel in OUT direction
2441 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2442 hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2443 ((uint16_t)ep_type + 1U) |
2444 (((uint16_t)epnum & 0x0FU) << 8U);
2445
2446 return idx;
2447 }
2448 }
2449 }
2450 else
2451 {
2452 /* Find a new available physical out channel */
2453 for (idx = 1U; idx < hhcd->Init.Host_channels; idx++)
2454 {
2455 /* Check if the same epnum is allocated then allocate the same physical channel IN for OUT Logical Channel */
2456 if ((hhcd->phy_chout_state[idx] == 0U) &&
2457 ((((hhcd->phy_chin_state[idx] & 0x0FU) == ((uint16_t)ep_type + 1U)) &&
2458 ((hhcd->phy_chin_state[idx] & 0x0F00U) == ((uint16_t)epnum & 0x0FU))) ||
2459 (hhcd->phy_chin_state[idx] == 0U)))
2460 {
2461 /* chout_state will store the ep_type to be used for the same channel in IN direction
2462 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2463 hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2464 ((uint16_t)ep_type + 1U) |
2465 (((uint16_t)epnum & 0x0FU) << 8U);
2466
2467 return idx;
2468 }
2469 }
2470 }
2471
2472 /* in case of Error */
2473 return HCD_FREE_CH_NOT_FOUND;
2474 }
2475
2476 /**
2477 * @brief Free All Channel allocation
2478 * @param hhcd HCD handle
2479 * @retval HAL status
2480 */
HAL_HCD_ClearPhyChannel(HCD_HandleTypeDef * hhcd)2481 static void HAL_HCD_ClearPhyChannel(HCD_HandleTypeDef *hhcd)
2482 {
2483 uint8_t idx;
2484
2485 for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
2486 {
2487 /*Reset channel allocation value */
2488 hhcd->phy_chout_state[idx] = 0U;
2489 hhcd->phy_chin_state[idx] = 0U;
2490 }
2491 }
2492
2493 /*---------------------- PMA Allocation Section --------------------- */
2494 /*
2495 __col31________________col0__ Column-- >
2496 lin0 | entry31.|....... | entry0 | Line
2497 |---------|---------|--------| |
2498 line1| entry63.|....... | entry32| |
2499 |---------|---------|--------| \|/
2500 | entry127|....... | entry64|
2501 |---------|---------|--------|
2502 | entry256|...... |entry128|
2503 ----------------------------
2504 an allocation space of 64byte need 8 Free contiguous Entry in the Matrix
2505 - a Free Entry is a bit with 0 Value/ a busy entry is a bit with 1 value. */
2506
2507 /**
2508 * @brief Fetch in the PMA_LockupTable free space of number of mps byte
2509 * @param hhcd Host instance
2510 * @param mps Channel Max Packet Size
2511 * @retval PMA_Address of the first free block containing mps byte
2512 0xFFFF in case of no space available
2513 */
HAL_HCD_GetFreePMA(HCD_HandleTypeDef * hhcd,uint16_t mps)2514 static uint16_t HAL_HCD_GetFreePMA(HCD_HandleTypeDef *hhcd, uint16_t mps)
2515 {
2516 uint32_t Entry;
2517 uint32_t FreeBlocks = 0U;
2518 uint8_t FirstFreeBlock_col = 0U;
2519 uint8_t FirstFreeBlock_line = 0U;
2520 uint8_t ColIndex;
2521 uint16_t NbrReqBlocks;
2522 uint16_t mps_t = mps;
2523
2524 /* since PMA buffer descriptor RXBD allocate address according to BLSIZE, BLSIZE=1==> mps>64
2525 allocation in PMA is done in 32Bytes each entry */
2526 if ((mps_t > 64U) && ((mps_t % 32U) != 0U))
2527 {
2528 /* Align the mps to 32byte block to match the allocation in PMA,
2529 check Definition of allocation buffer memory in usb user spec */
2530 mps_t = (uint16_t)(((mps_t / 32U) + 1U) * 32U);
2531 }
2532
2533 /* calculate the number of block(8byte) to allocate */
2534 NbrReqBlocks = mps_t / 8U;
2535
2536 /* check if we need remaining Block */
2537 if ((mps_t % 8U) != 0U)
2538 {
2539 NbrReqBlocks++;
2540 }
2541
2542 /* Look For NbrReqBlocks * Empty Block */
2543 for (uint8_t i = 0U; ((i < PMA_BLOCKS) && (FreeBlocks != NbrReqBlocks)); i++)
2544 {
2545 Entry = hhcd->PMALookupTable[i];
2546
2547 /* when parse is in progress, check the first col to look for a contiguous block */
2548 if ((FreeBlocks != 0U) && ((Entry & (uint32_t)1U) != 0U))
2549 {
2550 FreeBlocks = 0U;
2551 }
2552 uint8_t j = 0U;
2553 while ((j <= 31U) && (FreeBlocks != NbrReqBlocks))
2554 {
2555 /* check if block j is free */
2556 if ((Entry & ((uint32_t)1U << j)) == 0U)
2557 {
2558 if (FreeBlocks == 0U)
2559 {
2560 FirstFreeBlock_col = j;
2561 FirstFreeBlock_line = i;
2562 FreeBlocks++;
2563 }
2564 j++;
2565
2566 /* Parse Column PMALockTable */
2567 while ((j <= 31U) && ((Entry & ((uint32_t)1U << j)) == 0U) && (FreeBlocks < NbrReqBlocks))
2568 {
2569 FreeBlocks++;
2570 j++;
2571 }
2572
2573 /* Free contiguous Blocks not found */
2574 if (((FreeBlocks < NbrReqBlocks) && (j < 31U)) ||
2575 ((j == 31U) && ((Entry & ((uint32_t)1U << j)) != 0U)))
2576 {
2577 FreeBlocks = 0U;
2578 }
2579 }
2580 j++;
2581 } /* end for j */
2582 } /* end for i */
2583
2584 /* Free block found */
2585 if (FreeBlocks >= NbrReqBlocks)
2586 {
2587 ColIndex = FirstFreeBlock_col;
2588
2589 for (uint8_t i = FirstFreeBlock_line; ((i < PMA_BLOCKS) && (FreeBlocks > 0U)); i++)
2590 {
2591 for (uint8_t j = ColIndex; j <= 31U; j++)
2592 {
2593 hhcd->PMALookupTable[i] |= ((uint32_t)1U << j);
2594 if (--FreeBlocks == 0U)
2595 {
2596 break;
2597 }
2598 }
2599 ColIndex = 0U;
2600 }
2601
2602 return (uint16_t)((FirstFreeBlock_line * (uint16_t)256U) + (FirstFreeBlock_col * (uint16_t)8U));
2603 }
2604 else
2605 {
2606 return 0xFFFFU;
2607 }
2608 }
2609
2610 /**
2611 * @brief Allocate PMA buffer for Channel
2612 * This API will fetch a free space
2613 * @param hhcd Host instance
2614 * @param ch_num Channel number
2615 * @param ch_kind endpoint Kind
2616 * USB_SNG_BUF Single Buffer used
2617 * USB_DBL_BUF Double Buffer used
2618 * @param mps Channel Max Packet Size
2619 * @retval HAL status
2620 */
HAL_HCD_PMAlloc(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint16_t ch_kind,uint16_t mps)2621 HAL_StatusTypeDef HAL_HCD_PMAlloc(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
2622 uint16_t ch_kind, uint16_t mps)
2623 {
2624 uint16_t pma_addr0;
2625 #if (USE_USB_DOUBLE_BUFFER == 1U)
2626 uint16_t pma_addr1; /* used for double buffer mode if enabled */
2627 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2628
2629 /* Host Channel */
2630 HCD_HCTypeDef *hc = &(hhcd->hc[ch_num]);
2631
2632 /* Get a FreePMA Address */
2633 pma_addr0 = HAL_HCD_GetFreePMA(hhcd, mps);
2634
2635 /* If there is no free space to allocate */
2636 if (pma_addr0 == 0xFFFFU)
2637 {
2638 return HAL_ERROR;
2639 }
2640 else
2641 {
2642 /* Here we check if the endpoint is single or double Buffer */
2643 if (ch_kind == HCD_SNG_BUF)
2644 {
2645 /* Single Buffer */
2646 hc->doublebuffer = 0U;
2647
2648 if (hc->ep_num == 0U)
2649 {
2650 hhcd->ep0_PmaAllocState &= 0xFFF0U;
2651 hhcd->ep0_PmaAllocState |= ch_num;
2652 hhcd->ep0_PmaAllocState |= (1U << 8);
2653 }
2654
2655 /* Configure the PMA */
2656 if (hc->ch_dir == CH_IN_DIR)
2657 {
2658 hc->pmaaddr1 = pma_addr0;
2659 (USB_DRD_PMA_BUFF + hc->phy_ch_num)->RXBD = hc->pmaaddr1;
2660
2661 if (hc->ep_num == 0U)
2662 {
2663 hhcd->ep0_PmaAllocState |= (CH_IN_DIR << 4);
2664 }
2665 }
2666 else
2667 {
2668 hc->pmaaddr0 = pma_addr0;
2669 (USB_DRD_PMA_BUFF + hc->phy_ch_num)->TXBD = hc->pmaaddr0;
2670 }
2671
2672 /* Set the PmaAddress */
2673 hc->pmaadress = pma_addr0;
2674 }
2675 #if (USE_USB_DOUBLE_BUFFER == 1U)
2676 else /* USB_DBL_BUF */
2677 {
2678 /* Double Buffer Endpoint */
2679 hc->doublebuffer = 1U;
2680
2681 /* Get a FreePMA Address for buffer 2 */
2682 pma_addr1 = HAL_HCD_GetFreePMA(hhcd, mps);
2683
2684 if (pma_addr1 == 0xFFFFU)
2685 {
2686 /* Free the first buffer */
2687 (void)HAL_HCD_PMAFree(hhcd, pma_addr0, mps);
2688 return HAL_ERROR;
2689 }
2690 else
2691 {
2692 /* Configure the PMA */
2693 hc->pmaaddr0 = (uint16_t)(pma_addr0);
2694 hc->pmaaddr1 = (uint16_t)(pma_addr1);
2695
2696 /* Set Buffer0 pma address */
2697 (USB_DRD_PMA_BUFF + hc->phy_ch_num)->TXBD = pma_addr0;
2698
2699 /* Set Buffer1 pma address */
2700 (USB_DRD_PMA_BUFF + hc->phy_ch_num)->RXBD = pma_addr1;
2701
2702 /* Used for Bulk DB MPS < 64bytes */
2703 if (hc->ch_dir == CH_IN_DIR)
2704 {
2705 hc->pmaadress = hc->pmaaddr1;
2706 }
2707 else
2708 {
2709 hc->pmaadress = hc->pmaaddr0;
2710 }
2711 }
2712 }
2713 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2714 }
2715
2716 return HAL_OK;
2717 }
2718
2719 /**
2720 * @brief PMA De-Allocation for Channel Free the reserved block in the PMA-LookupTable
2721 * @param hhcd Host instance
2722 * @param ch_num Channel number
2723 * @retval HAL status
2724 */
HAL_HCD_PMADeAlloc(HCD_HandleTypeDef * hhcd,uint8_t ch_num)2725 HAL_StatusTypeDef HAL_HCD_PMADeAlloc(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
2726 {
2727 HAL_StatusTypeDef status;
2728
2729 #if (USE_USB_DOUBLE_BUFFER == 1U)
2730 uint8_t Err = 0U;
2731 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2732
2733 /* Host Channel */
2734 HCD_HCTypeDef *hc = &(hhcd->hc[ch_num]);
2735
2736 /* Single Buffer */
2737 if (hc->doublebuffer == 0U)
2738 {
2739 status = HAL_HCD_PMAFree(hhcd, hc->pmaadress, hc->max_packet);
2740 }
2741 else /* Double buffer */
2742 {
2743 #if (USE_USB_DOUBLE_BUFFER == 1U)
2744 status = HAL_HCD_PMAFree(hhcd, hc->pmaaddr0, hc->max_packet);
2745 if (status != HAL_OK)
2746 {
2747 Err++;
2748 }
2749
2750 status = HAL_HCD_PMAFree(hhcd, hc->pmaaddr1, hc->max_packet);
2751 if (status != HAL_OK)
2752 {
2753 Err++;
2754 }
2755
2756 if (Err != 0U)
2757 {
2758 return HAL_ERROR;
2759 }
2760 #else
2761 status = HAL_ERROR;
2762 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2763 }
2764
2765 return status;
2766 }
2767
2768
2769 /**
2770 * @brief PMA Reset
2771 * @param hhcd Host instance
2772 * @retval HAL status
2773 */
HAL_HCD_PMAReset(HCD_HandleTypeDef * hhcd)2774 HAL_StatusTypeDef HAL_HCD_PMAReset(HCD_HandleTypeDef *hhcd)
2775 {
2776 /* Reset All PMA Entry */
2777 for (uint8_t i = 0U; i < PMA_BLOCKS; i++)
2778 {
2779 hhcd->PMALookupTable[i] = 0U;
2780 }
2781
2782 /* Allocate a Space for buffer descriptor table depending on the Host channel number */
2783 for (uint8_t i = 0U; i < hhcd->Init.Host_channels; i++)
2784 {
2785 hhcd->PMALookupTable[0] |= ((uint32_t)1U << i);
2786 }
2787
2788 return HAL_OK;
2789 }
2790
2791 /**
2792 * @brief PMA Free
2793 * @param hhcd Host instance
2794 * @param pma_base PMA base offset stored in hhcd->hc.pmaaddr
2795 * @param mps Max Packet Size
2796 * @retval HAL status
2797 */
HAL_HCD_PMAFree(HCD_HandleTypeDef * hhcd,uint32_t pma_base,uint16_t mps)2798 static HAL_StatusTypeDef HAL_HCD_PMAFree(HCD_HandleTypeDef *hhcd, uint32_t pma_base, uint16_t mps)
2799 {
2800 uint32_t block_nbr;
2801 uint8_t ColIndex;
2802 uint8_t LineIndex;
2803 uint16_t mps_t = mps;
2804
2805 /* since PMA buffer descriptor RXBD allocate address according to BLSIZE, BLSIZE=1==> mps>64
2806 allocation in PMA is done in 32Bytes each entry */
2807 if ((mps_t > 64U) && ((mps_t % 32U) != 0U))
2808 {
2809 /* Align the mps to 32byte block to match the allocation in PMA,
2810 check Definition of allocation buffer memory in usb user spec */
2811 mps_t = (uint16_t)(((mps_t / 32U) + 1U) * 32U);
2812 }
2813
2814 /* Calculate the number of needed block to Free */
2815 if ((mps_t / 8U) != 0U)
2816 {
2817 block_nbr = ((uint32_t)mps_t / 8U);
2818
2819 if ((mps_t % 8U) != 0U)
2820 {
2821 block_nbr++;
2822 }
2823 }
2824 else
2825 {
2826 block_nbr = 1U;
2827 }
2828
2829 /* Decode Col/Line of PMA_Base position in the PMA_LookupTable */
2830 if (pma_base > 256U)
2831 {
2832 LineIndex = (uint8_t)(pma_base / 256U);
2833 ColIndex = (uint8_t)((pma_base - ((uint32_t)LineIndex * 256U)) / 8U);
2834 }
2835 else
2836 {
2837 LineIndex = 0U;
2838 ColIndex = (uint8_t)(pma_base / 8U);
2839 }
2840
2841 /* Reset the corresponding bit in the lookupTable */
2842 for (uint8_t i = LineIndex; ((i < PMA_BLOCKS) && (block_nbr > 0U)); i++)
2843 {
2844 for (uint8_t j = ColIndex; j <= 31U; j++)
2845 {
2846 /* Check if the block is not already reserved or it was already closed */
2847 if ((hhcd->PMALookupTable[i] & ((uint32_t)1U << j)) == 0U)
2848 {
2849 return HAL_ERROR;
2850 }
2851 /* Free the reserved block by resetting the corresponding bit */
2852 hhcd->PMALookupTable[i] &= ~(1U << j);
2853
2854 if (--block_nbr == 0U)
2855 {
2856 break;
2857 }
2858 }
2859 ColIndex = 0U;
2860 }
2861
2862 return HAL_OK;
2863 }
2864
2865 /**
2866 * @}
2867 */
2868
2869 /**
2870 * @}
2871 */
2872 #endif /* defined (USB_DRD_FS) */
2873 #endif /* HAL_HCD_MODULE_ENABLED */
2874
2875 /**
2876 * @}
2877 */
2878
2879 /**
2880 * @}
2881 */
2882