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