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