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 const *hhcd, uint8_t phy_chnum, uint8_t dir);
81 static uint8_t HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const *hhcd, uint8_t ch_num);
82 static uint8_t HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t epnum, uint8_t ep_type);
83
84 #if (USE_USB_DOUBLE_BUFFER == 1U)
85 static void HCD_HC_IN_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
86 static void HCD_HC_OUT_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
87 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
88
89 static uint16_t HAL_HCD_GetFreePMA(HCD_HandleTypeDef *hhcd, uint16_t mps);
90 static HAL_StatusTypeDef HAL_HCD_PMAFree(HCD_HandleTypeDef *hhcd, uint32_t pma_base, uint16_t mps);
91 static void inline HCD_HC_IN_ISO(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
92 /**
93 * @}
94 */
95
96 /* Exported functions --------------------------------------------------------*/
97 /** @defgroup HCD_Exported_Functions HCD Exported Functions
98 * @{
99 */
100
101 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
102 * @brief Initialization and Configuration functions
103 *
104 @verbatim
105 ===============================================================================
106 ##### Initialization and de-initialization functions #####
107 ===============================================================================
108 [..] This section provides functions allowing to:
109
110 @endverbatim
111 * @{
112 */
113
114 /**
115 * @brief Initialize the host driver.
116 * @param hhcd HCD handle
117 * @retval HAL status
118 */
HAL_HCD_Init(HCD_HandleTypeDef * hhcd)119 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
120 {
121 /* Check the HCD handle allocation */
122 if (hhcd == NULL)
123 {
124 return HAL_ERROR;
125 }
126
127 /* Check the parameters */
128 assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
129
130 if (hhcd->State == HAL_HCD_STATE_RESET)
131 {
132 /* Allocate lock resource and initialize it */
133 hhcd->Lock = HAL_UNLOCKED;
134
135 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
136 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
137 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
138 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
139 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
140 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
141 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;
142
143 if (hhcd->MspInitCallback == NULL)
144 {
145 hhcd->MspInitCallback = HAL_HCD_MspInit;
146 }
147
148 /* Init the low level hardware */
149 hhcd->MspInitCallback(hhcd);
150 #else
151 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
152 HAL_HCD_MspInit(hhcd);
153 #endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
154 }
155 hhcd->State = HAL_HCD_STATE_BUSY;
156
157 /* Disable the Interrupts */
158 (void)__HAL_HCD_DISABLE(hhcd);
159
160 /* Dma not supported, force to zero */
161 hhcd->Init.dma_enable = 0U;
162
163 /* Init the Core (common init.) */
164 (void)USB_CoreInit(hhcd->Instance, hhcd->Init);
165
166 /* Force Host Mode */
167 (void)USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE);
168
169 /* Init Host */
170 (void)USB_HostInit(hhcd->Instance, hhcd->Init);
171
172 /* 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 > HAL_USB_TIMEOUT)
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 const * hhcd)1441 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef const *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 const * hhcd,uint8_t chnum)1460 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const *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 const * hhcd,uint8_t chnum)1473 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const *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 const * hhcd,uint8_t chnum)1495 HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef const *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 /**
1524 * @brief Set host channel Hub Information.
1525 * @param hhcd HCD handle
1526 * @param ch_num Channel number.
1527 * This parameter can be a value from 1 to 8
1528 * @param addr Hub address
1529 * @param PortNbr Hub port number
1530 * @retval HAL status
1531 */
HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t addr,uint8_t PortNbr)1532 HAL_StatusTypeDef HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1533 uint8_t addr, uint8_t PortNbr)
1534 {
1535 hhcd->hc[ch_num].hub_addr = addr;
1536 hhcd->hc[ch_num].hub_port_nbr = PortNbr;
1537
1538 return HAL_OK;
1539 }
1540
1541
1542 /**
1543 * @brief Clear host channel hub information.
1544 * @param hhcd HCD handle
1545 * @param ch_num Channel number.
1546 * This parameter can be a value from 1 to 8
1547 * @retval HAL status
1548 */
HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num)1549 HAL_StatusTypeDef HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
1550 {
1551 hhcd->hc[ch_num].hub_addr = 0U;
1552 hhcd->hc[ch_num].hub_port_nbr = 0U;
1553
1554 return HAL_OK;
1555 }
1556
1557 #if (USE_USB_DOUBLE_BUFFER == 1U)
1558 /**
1559 * @brief Handle Host Channel OUT Double Buffer Bulk requests.
1560 * @param hhcd HCD handle
1561 * @param ch_num Channel number This parameter can be a value from 1 to 15
1562 * @param phy_chnum Physical Channel number [0..7]
1563 * @param regvalue contain Snapshot of the EPCHn register when ISR is detected
1564 * @retval none
1565 */
HCD_HC_OUT_BulkDb(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)1566 static void HCD_HC_OUT_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1567 uint8_t phy_chnum, uint32_t regvalue)
1568 {
1569 uint16_t data_xfr;
1570 uint16_t len;
1571
1572 /* Send Buffer0 */
1573 if ((regvalue & USB_CH_DTOG_TX) != 0U)
1574 {
1575 data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->TXBD & 0x03FF0000U) >> 16U);
1576
1577 if (hhcd->hc[ch_num & 0xFU].xfer_len >= data_xfr)
1578 {
1579 hhcd->hc[ch_num & 0xFU].xfer_len -= data_xfr;
1580 }
1581 else
1582 {
1583 hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1584 }
1585
1586 /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
1587 if (hhcd->hc[ch_num & 0xFU].xfer_len != 0U)
1588 {
1589 /* manage multiple Xfer */
1590 hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1591
1592 /* check if we need to free user buffer */
1593 if ((regvalue & USB_CH_DTOG_RX) != 0U)
1594 {
1595 /* Toggle SwBuff */
1596 HCD_CLEAR_TX_DTOG(hhcd->Instance, phy_chnum);
1597 HCD_CLEAR_RX_DTOG(hhcd->Instance, phy_chnum);
1598 HCD_TX_DTOG(hhcd->Instance, phy_chnum);
1599 }
1600
1601 /* hhcd->hc[ch_num&0xFU].xfer_len_db==0 ==> when all data are written in the PMA to yet transferred */
1602 if (hhcd->hc[ch_num & 0xFU].xfer_len_db > 0U) /* Still data to fill in the buffer */
1603 {
1604 hhcd->hc[ch_num & 0xFU].xfer_buff += data_xfr;
1605
1606 /* calculate len of new buffer to fill */
1607 if (hhcd->hc[ch_num & 0xFU].xfer_len_db > hhcd->hc[ch_num & 0xFU].max_packet)
1608 {
1609 len = (uint16_t)hhcd->hc[ch_num & 0xFU].max_packet;
1610 hhcd->hc[ch_num & 0xFU].xfer_len_db -= len;
1611 }
1612 else
1613 {
1614 len = (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_len_db;
1615 hhcd->hc[ch_num & 0xFU].xfer_len_db = 0U; /* end of fill buffer */
1616 }
1617
1618 /* Write remaining data to Buffer0 */
1619 HCD_SET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum, 1U, (uint16_t)len);
1620 USB_WritePMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1621 hhcd->hc[ch_num & 0xFU].pmaaddr0, (uint16_t)len);
1622 }
1623 /* start a new transfer */
1624 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_VALID);
1625 }
1626 else
1627 {
1628 /* Transfer complete state */
1629 hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1630 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1631 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1632 hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
1633 /* Close the Channel */
1634 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
1635 }
1636 }
1637 else
1638 {
1639 /* Send Buffer1 */
1640 data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->RXBD & 0x03FF0000U) >> 16U);
1641
1642 if (hhcd->hc[ch_num & 0xFU].xfer_len >= data_xfr) /* updated */
1643 {
1644 hhcd->hc[ch_num & 0xFU].xfer_len -= data_xfr;
1645 }
1646
1647 /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
1648 if (hhcd->hc[ch_num & 0xFU].xfer_len != 0U)
1649 {
1650 /* manage multiple Xfer */
1651 hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1652
1653 /* check if we need to free user buffer */
1654 if ((regvalue & USB_CH_DTOG_RX) == 0U)
1655 {
1656 /* Toggle SwBuff */
1657 HCD_CLEAR_TX_DTOG(hhcd->Instance, phy_chnum);
1658 HCD_CLEAR_RX_DTOG(hhcd->Instance, phy_chnum);
1659 HCD_RX_DTOG(hhcd->Instance, phy_chnum);
1660 }
1661
1662 /* hhcd->hc[ch_num&0xFU].xfer_len_db==0 ==> when all data are written in the PMA to yet transferred */
1663 if (hhcd->hc[ch_num & 0xFU].xfer_len_db > 0U) /* Still data to fill in the buffer */
1664 {
1665 hhcd->hc[ch_num & 0xFU].xfer_buff += data_xfr;
1666
1667 /* calculate len of new buffer to fill */
1668 if (hhcd->hc[ch_num & 0xFU].xfer_len_db > hhcd->hc[ch_num & 0xFU].max_packet)
1669 {
1670 len = hhcd->hc[ch_num & 0xFU].max_packet;
1671 hhcd->hc[ch_num & 0xFU].xfer_len_db -= len;
1672 }
1673 else
1674 {
1675 len = (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_len_db;
1676 hhcd->hc[ch_num & 0xFU].xfer_len_db = 0U; /* end of fill buffer */
1677 }
1678
1679 /* Write remaining data to Buffer0 */
1680 HCD_SET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum, 1U, (uint16_t)len);
1681
1682 USB_WritePMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1683 hhcd->hc[ch_num & 0xFU].pmaaddr1, (uint16_t)len);
1684 }
1685
1686 /* start a new transfer */
1687 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_VALID);
1688 }
1689 else
1690 {
1691 /* Transfer complete state */
1692 hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1693 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1694 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1695 hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
1696
1697 /* Close the channel */
1698 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
1699 }
1700 }
1701 }
1702
1703
1704 /**
1705 * @brief Handle Host Channel IN Double Buffer Bulk requests.
1706 * @param hhcd HCD handle
1707 * @param ch_num Channel number: This parameter can be a value from 1 to 15
1708 * @param phy_chnum Physical Channel number [0..7]
1709 * @param regvalue contain Snapshot of the EPCHn register when ISR is detected
1710 * @retval none
1711 */
HCD_HC_IN_BulkDb(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)1712 static void HCD_HC_IN_BulkDb(HCD_HandleTypeDef *hhcd,
1713 uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue)
1714 {
1715 uint16_t received_bytes;
1716
1717 /* Read from Buffer 0 */
1718 if ((regvalue & USB_CH_DTOG_RX) != 0U)
1719 {
1720 received_bytes = (uint16_t)HCD_GET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum);
1721
1722 if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
1723 {
1724 hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1725 }
1726 else
1727 {
1728 hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
1729 }
1730
1731 /* Check if we Need to free the other buffer for the IP */
1732 if ((hhcd->hc[ch_num & 0xFU].xfer_len != 0U) && ((regvalue & USB_CH_DTOG_TX) != 0U))
1733 {
1734 /* Toggle SwBuff to Allow the IP to submit a new IN */
1735 HCD_FREE_USER_BUFFER(hhcd->Instance, phy_chnum, 0U);
1736 }
1737
1738 /* Read the byte from PMA to user Buffer(System Memory) */
1739 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1740 hhcd->hc[ch_num & 0xFU].pmaaddr0, (uint16_t)received_bytes);
1741 }
1742 else
1743 {
1744 /* Read from Buffer 1 */
1745 received_bytes = (uint16_t) HCD_GET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum);
1746
1747 if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
1748 {
1749 hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1750 }
1751 else
1752 {
1753 hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
1754 }
1755
1756 /* Check if we Need to free the other buffer for the IP */
1757 if ((hhcd->hc[ch_num & 0xFU].xfer_len != 0U) && ((regvalue & USB_CH_DTOG_TX) == 0U))
1758 {
1759 /* Toggle SwBuff */
1760 HCD_FREE_USER_BUFFER(hhcd->Instance, phy_chnum, 0U);
1761 }
1762
1763 /* Read the byte from PMA to user Buffer(System Memory) */
1764 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1765 hhcd->hc[ch_num & 0xFU].pmaaddr1, (uint16_t)received_bytes);
1766 }
1767
1768 /* update the global number of all received bytes */
1769 hhcd->hc[ch_num & 0xFU].xfer_count += received_bytes;
1770
1771 /* Transfer complete state */
1772 hhcd->hc[ch_num & 0xFU].state = HC_ACK;
1773 hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
1774
1775 if ((hhcd->hc[ch_num & 0xFU].xfer_len == 0U) ||
1776 ((received_bytes < hhcd->hc[ch_num & 0xFU].max_packet)))
1777 {
1778 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1779 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1780
1781 /* disable channel */
1782 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1783 }
1784 else
1785 {
1786 hhcd->hc[ch_num & 0xFU].xfer_buff += received_bytes;
1787
1788 /* Reactivate the Channel Submit an other URB since the Transfer is not yet completed */
1789 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_STRX);
1790 }
1791 }
1792 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1793
1794 /**
1795 * @brief Handle Host Channel IN Isochronous Transaction
1796 * @param hhcd HCD handle
1797 * @param ch_num Channel number: This parameter can be a value from 1 to 15
1798 * @param phy_chnum Physical Channel number [0..7]
1799 * @param regvalue contain Snapshot of the EPCHn register when ISR is detected
1800 * @retval none
1801 */
HCD_HC_IN_ISO(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)1802 static void inline HCD_HC_IN_ISO(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1803 uint8_t phy_chnum, uint32_t regvalue)
1804 {
1805 /* Check if Double buffer isochronous */
1806 if ((regvalue & USB_CH_KIND) != 0U)
1807 {
1808 /* Get Data IN Packet */
1809 hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_RX_CNT(hhcd->Instance, phy_chnum);
1810 if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
1811 {
1812 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1813 hhcd->hc[ch_num & 0xFU].pmaadress,
1814 (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
1815
1816 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1817 }
1818 }
1819 #if (USE_USB_DOUBLE_BUFFER == 1U)
1820 else /* double buffer isochronous */
1821 {
1822 /* Read from Buffer0 */
1823 if ((regvalue & USB_CH_DTOG_RX) != 0U)
1824 {
1825 /* Get number of Received byte in buffer0 */
1826 hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum);
1827
1828 if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
1829 {
1830 /* Read from Buffer0 */
1831 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1832 hhcd->hc[ch_num & 0xFU].pmaaddr0,
1833 (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
1834
1835 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1836 }
1837 }
1838 else
1839 {
1840 /* Get number of Received byte in buffer1 */
1841 hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum);
1842
1843 if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
1844 {
1845 /* Read from Buffer1 */
1846 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1847 hhcd->hc[ch_num & 0xFU].pmaaddr1,
1848 (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
1849
1850 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1851 }
1852 }
1853 }
1854 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1855
1856 /* Transfer complete state */
1857 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1858
1859 /* Clear VTRX */
1860 HCD_CLEAR_RX_CH_CTR(hhcd->Instance, phy_chnum);
1861 }
1862
1863 /**
1864 * @brief Handle Host Channel IN interrupt requests.
1865 * @param hhcd HCD handle
1866 * @param ch_num Channel number
1867 * This parameter can be a value from 1 to 15
1868 * @retval none
1869 */
HCD_HC_IN_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t ch_num)1870 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
1871 {
1872 uint16_t received_bytes;
1873 uint8_t phy_chnum = (uint8_t)__HAL_HCD_GET_CHNUM(hhcd);
1874
1875 /*Take a Flag snapshot from the CHEP register, due to STRX bits are used for both control and status */
1876 uint32_t ch_reg = HCD_GET_CHANNEL(hhcd->Instance, phy_chnum);
1877
1878 /* Manage Correct Transaction */
1879 if ((ch_reg & USB_CH_ERRRX) == 0U)
1880 {
1881 /* Isochronous Channel */
1882 if ((ch_reg & USB_CH_UTYPE) == USB_EP_ISOCHRONOUS)
1883 {
1884 HCD_HC_IN_ISO(hhcd, ch_num, phy_chnum, ch_reg);
1885 }
1886 else
1887 {
1888 /* manage ACK response single buffer */
1889 if (((ch_reg) & USB_CH_RX_STRX) == USB_CH_RX_ACK_SBUF)
1890 {
1891 /* Get Control Data OUT Packet */
1892 received_bytes = (uint16_t)HCD_GET_CH_RX_CNT(hhcd->Instance, phy_chnum);
1893
1894 /* Read the byte from PMA to user Buffer(System Memory) */
1895 USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1896 hhcd->hc[ch_num & 0xFU].pmaadress, (uint16_t)received_bytes);
1897
1898 /* update the global number of all received bytes */
1899 hhcd->hc[ch_num & 0xFU].xfer_count += received_bytes;
1900
1901 /* Transfer complete state */
1902 hhcd->hc[ch_num & 0xFU].state = HC_ACK;
1903 hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
1904
1905 if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
1906 {
1907 hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1908 }
1909 else
1910 {
1911 hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
1912 }
1913
1914 if ((hhcd->hc[ch_num & 0xFU].xfer_len == 0U) ||
1915 ((received_bytes < hhcd->hc[ch_num & 0xFU].max_packet)))
1916 {
1917 hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1918 hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1919 }
1920 else
1921 {
1922 hhcd->hc[ch_num & 0xFU].xfer_buff += received_bytes;
1923
1924 /* Reactivate the Channel to Submit another URB since the Transfer is not yet completed */
1925 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_STRX);
1926 }
1927
1928 if ((hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_BULK) ||
1929 (hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_INTR))
1930 {
1931 hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
1932 }
1933 }
1934 /* manage NACK Response */
1935 else if (((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_NAK)
1936 && (hhcd->hc[ch_num & 0xFU].urb_state != URB_DONE))
1937 {
1938 hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
1939 hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
1940 hhcd->hc[ch_num & 0xFU].state = HC_NAK;
1941
1942 if (hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_INTR)
1943 {
1944 /* Close the channel */
1945 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1946 }
1947 }
1948 /* manage STALL Response */
1949 else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_STALL)
1950 {
1951 (void)HAL_HCD_HC_Halt(hhcd, ch_num);
1952 hhcd->hc[ch_num & 0xFU].state = HC_STALL;
1953 hhcd->hc[ch_num & 0xFU].urb_state = URB_STALL;
1954
1955 /* Close the channel */
1956 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1957 }
1958 #if (USE_USB_DOUBLE_BUFFER == 1U)
1959 /* Double Buffer Management in case of Bulk Transaction */
1960 else if (((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_ACK_DBUF)
1961 && ((ch_reg & USB_CH_KIND) != 0U))
1962 {
1963 /* Bulk IN Double Buffer ISR */
1964 HCD_HC_IN_BulkDb(hhcd, ch_num, phy_chnum, ch_reg);
1965 }
1966 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1967 else
1968 {
1969 /*....*/
1970 /* not defined state: STRX=11 in single buffer no iso is not defined */
1971 }
1972
1973 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1974 hhcd->HC_NotifyURBChangeCallback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
1975 #else
1976 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
1977 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1978
1979 /*Clear VTRX */
1980 HCD_CLEAR_RX_CH_CTR(hhcd->Instance, phy_chnum);
1981 }
1982 }
1983 else /* Error detected during last transaction */
1984 {
1985 /* Set URB Error State */
1986 hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
1987 hhcd->hc[ch_num & 0xFU].ErrCnt++;
1988 hhcd->hc[ch_num & 0xFU].state = HC_XACTERR;
1989
1990 /* Clear VTTRX & ERR_RX */
1991 HCD_CLEAR_RX_CH_ERR(hhcd->Instance, phy_chnum);
1992
1993 /* Check Error number */
1994 if (hhcd->hc[ch_num & 0xFU].ErrCnt > 3U)
1995 {
1996 hhcd->hc[ch_num & 0xFU].urb_state = URB_ERROR;
1997 HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1998
1999 /* Clear pending err_tx */
2000 HCD_CLEAR_RX_CH_ERR(hhcd->Instance, phy_chnum);
2001 }
2002
2003 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2004 hhcd->HC_NotifyURBChangeCallback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2005 #else
2006 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2007 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2008 }
2009 }
2010
2011
2012 /**
2013 * @brief Handle Host Channel OUT interrupt requests.
2014 * @param hhcd HCD handle
2015 * @param chnum Channel number
2016 * This parameter can be a value from 1 to 15
2017 * @retval none
2018 */
HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)2019 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
2020 {
2021 uint16_t data_xfr;
2022 __IO uint32_t WregCh;
2023
2024 /* Get Physical Channel number */
2025 uint32_t phy_chnum = (uint8_t)__HAL_HCD_GET_CHNUM(hhcd);
2026
2027 /* Take a Flag snapshot from the CHEP register, due to STRX bits are used for both control &status */
2028 uint32_t ch_reg = *(__IO uint32_t *)(&(hhcd->Instance->CHEP0R) + phy_chnum);
2029
2030 /*------ Manage Correct Transaction ------*/
2031 if ((ch_reg & USB_CH_ERRTX) == 0U)
2032 {
2033 /* Handle Isochronous channel */
2034 if ((ch_reg & USB_CH_UTYPE) == USB_EP_ISOCHRONOUS)
2035 {
2036 /* correct transaction */
2037 if ((hhcd->Instance->ISTR & USB_ISTR_ERR) == 0U)
2038 {
2039 /* Double buffer isochronous out */
2040 if ((ch_reg & USB_CH_KIND) != 0U)
2041 {
2042 HCD_SET_CH_TX_CNT(hhcd->Instance, phy_chnum, 0U);
2043 }
2044 #if (USE_USB_DOUBLE_BUFFER == 1U)
2045 else /* double buffer isochronous out */
2046 {
2047 /* Odd Transaction */
2048 if ((ch_reg & USB_CH_DTOG_TX) != 0U)
2049 {
2050 HCD_SET_CH_TX_CNT(hhcd->Instance, phy_chnum, 0U);
2051 }
2052 /* Even Transaction */
2053 else
2054 {
2055 HCD_SET_CH_RX_CNT(hhcd->Instance, phy_chnum, 0U);
2056 }
2057
2058 USB_DRD_SET_CHEP_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
2059 }
2060 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2061
2062 /* Transfer complete state */
2063 hhcd->hc[chnum & 0xFU].state = HC_XFRC;
2064 hhcd->hc[chnum & 0xFU].urb_state = URB_DONE;
2065 }
2066
2067 /*Clear Correct Transfer */
2068 HCD_CLEAR_TX_CH_CTR(hhcd->Instance, phy_chnum);
2069
2070 /*TX COMPLETE*/
2071 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2072 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
2073 #else
2074 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
2075 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2076
2077 }
2078 else /* Manage all Non Isochronous Transaction */
2079 {
2080 /* Check ACK response */
2081 if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF)
2082 {
2083 data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->TXBD & 0x03FF0000U) >> 16U);
2084
2085 if (hhcd->hc[chnum & 0xFU].xfer_len >= data_xfr)
2086 {
2087 hhcd->hc[chnum & 0xFU].xfer_len -= data_xfr;
2088 }
2089 else
2090 {
2091 hhcd->hc[chnum & 0xFU].xfer_len = 0U;
2092 }
2093
2094 /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
2095 if (hhcd->hc[chnum & 0xFU].xfer_len != 0U)
2096 {
2097 /* manage multiple Xfer */
2098 hhcd->hc[chnum & 0xFU].xfer_buff += data_xfr;
2099 hhcd->hc[chnum & 0xFU].xfer_count += data_xfr;
2100
2101 /* start a new transfer */
2102 (void) USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[chnum & 0xFU]);
2103 }
2104 else
2105 {
2106 /* Transfer complete */
2107 hhcd->hc[chnum & 0xFU].xfer_count += data_xfr;
2108 hhcd->hc[chnum & 0xFU].state = HC_XFRC;
2109 hhcd->hc[chnum & 0xFU].urb_state = URB_DONE;
2110
2111 if ((hhcd->hc[chnum & 0xFU].ep_type == EP_TYPE_BULK) ||
2112 (hhcd->hc[chnum & 0xFU].ep_type == EP_TYPE_INTR))
2113 {
2114 hhcd->hc[chnum & 0xFU].toggle_out ^= 1U;
2115 }
2116 }
2117 }
2118 /* Check NACK Response */
2119 else if (((ch_reg & USB_CHEP_NAK) == USB_CHEP_NAK) ||
2120 ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK))
2121 {
2122 /* Update Channel status */
2123 hhcd->hc[chnum & 0xFU].state = HC_NAK;
2124 hhcd->hc[chnum & 0xFU].urb_state = URB_NOTREADY;
2125 hhcd->hc[chnum & 0xFU].ErrCnt = 0U;
2126
2127 /* Get Channel register value */
2128 WregCh = *(__IO uint32_t *)(&(hhcd->Instance->CHEP0R) + phy_chnum);
2129
2130 /*clear NAK status*/
2131 WregCh &= ~USB_CHEP_NAK & USB_CHEP_REG_MASK;
2132
2133 /* Update channel register Value */
2134 HCD_SET_CHANNEL(hhcd->Instance, phy_chnum, WregCh);
2135
2136 if (hhcd->hc[chnum & 0xFU].doublebuffer == 0U)
2137 {
2138 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2139 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
2140 #else
2141 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
2142 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2143 }
2144 }
2145 /* Check STALL Response */
2146 else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL)
2147 {
2148 (void) HAL_HCD_HC_Halt(hhcd, (uint8_t)chnum);
2149 hhcd->hc[chnum & 0xFU].state = HC_STALL;
2150 hhcd->hc[chnum & 0xFU].urb_state = URB_STALL;
2151 }
2152 #if (USE_USB_DOUBLE_BUFFER == 1U)
2153 /* Check double buffer ACK in case of bulk transaction */
2154 else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_DBUF)
2155 {
2156 /* Double buffer management Bulk Out */
2157 (void) HCD_HC_OUT_BulkDb(hhcd, chnum, (uint8_t)phy_chnum, ch_reg);
2158 }
2159 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2160 else
2161 {
2162 /*...*/
2163 }
2164
2165 if ((ch_reg & USB_CH_TX_STTX) != USB_CH_TX_NAK)
2166 {
2167 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2168 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
2169 #else
2170 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
2171 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2172 }
2173
2174 HCD_CLEAR_TX_CH_CTR(hhcd->Instance, phy_chnum);
2175 } /* end no isochronous */
2176 }
2177 /*------ Manage Transaction Error------*/
2178 else
2179 {
2180 hhcd->hc[chnum & 0xFU].ErrCnt++;
2181 if (hhcd->hc[chnum & 0xFU].ErrCnt > 3U)
2182 {
2183 HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
2184 hhcd->hc[chnum & 0xFU].urb_state = URB_ERROR;
2185 }
2186 else
2187 {
2188 hhcd->hc[chnum & 0xFU].urb_state = URB_NOTREADY;
2189 }
2190
2191 hhcd->hc[chnum & 0xFU].state = HC_XACTERR;
2192
2193 /*Clear ERR_TX*/
2194 HCD_CLEAR_TX_CH_ERR(hhcd->Instance, phy_chnum);
2195
2196 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2197 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
2198 #else
2199 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
2200 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2201 }
2202 }
2203
2204
2205 /**
2206 * @brief Handle Host Port interrupt requests.
2207 * @param hhcd HCD handle
2208 * @retval None
2209 */
HCD_Port_IRQHandler(HCD_HandleTypeDef * hhcd)2210 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
2211 {
2212 uint32_t FnrReg = hhcd->Instance->FNR;
2213 uint32_t IstrReg = hhcd->Instance->ISTR;
2214
2215 /* SE0 detected USB Disconnected state */
2216 if ((FnrReg & (USB_FNR_RXDP | USB_FNR_RXDM)) == 0U)
2217 {
2218 /* Host Port State */
2219 hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
2220
2221 /* clear all allocated virtual channel */
2222 HAL_HCD_ClearPhyChannel(hhcd);
2223
2224 /* Reset the PMA current pointer */
2225 (void)HAL_HCD_PMAReset(hhcd);
2226
2227 /* reset Ep0 Pma allocation state */
2228 hhcd->ep0_PmaAllocState = 0U;
2229
2230 /* Disconnection Callback */
2231 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2232 hhcd->DisconnectCallback(hhcd);
2233 #else
2234 HAL_HCD_Disconnect_Callback(hhcd);
2235 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2236
2237 return;
2238 }
2239
2240 if ((hhcd->HostState == HCD_HCD_STATE_DISCONNECTED) != 0U)
2241 {
2242 /* J-state or K-state detected & LastState=Disconnected */
2243 if (((FnrReg & USB_FNR_RXDP) != 0U) || ((IstrReg & USB_ISTR_LS_DCONN) != 0U))
2244 {
2245 hhcd->HostState = HCD_HCD_STATE_CONNECTED;
2246
2247 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2248 hhcd->ConnectCallback(hhcd);
2249 #else
2250 HAL_HCD_Connect_Callback(hhcd);
2251 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2252 }
2253 }
2254 else
2255 {
2256 /* J-state or K-state detected & lastState=Connected: a Missed disconnection is detected */
2257 if (((FnrReg & USB_FNR_RXDP) != 0U) || ((IstrReg & USB_ISTR_LS_DCONN) != 0U))
2258 {
2259 /* Host Port State */
2260 hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
2261
2262 /* clear all allocated virtual channel */
2263 HAL_HCD_ClearPhyChannel(hhcd);
2264
2265 /* Reset the PMA current pointer */
2266 (void)HAL_HCD_PMAReset(hhcd);
2267
2268 /* reset Ep0 PMA allocation state */
2269 hhcd->ep0_PmaAllocState = 0U;
2270
2271 /* Disconnection Callback */
2272 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2273 hhcd->DisconnectCallback(hhcd);
2274 #else
2275 HAL_HCD_Disconnect_Callback(hhcd);
2276 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2277 }
2278 }
2279 }
2280
2281
2282 /**
2283 * @brief Check if the ch_num are already reserved to a physical channel
2284 * @param hhcd HCD handle
2285 * @param ch_num Channel number
2286 * This parameter can be a value from 1 to 15
2287 * @retval HAL status
2288 */
HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const * hhcd,uint8_t ch_num)2289 static uint8_t HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const *hhcd, uint8_t ch_num)
2290 {
2291 uint8_t idx;
2292
2293 /* Check if the logical channel are already opened */
2294 for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
2295 {
2296 if ((((hhcd->phy_chin_state[idx] & 0xF0U) >> 4U) == ((uint16_t)ch_num + 1U)) &&
2297 (hhcd->phy_chin_state[idx] != 0U))
2298 {
2299 return (1U | (idx << 4U));
2300 }
2301
2302 if ((((hhcd->phy_chout_state[idx] & 0xF0U) >> 4U) == ((uint16_t)ch_num + 1U)) &&
2303 (hhcd->phy_chout_state[idx] != 0U))
2304 {
2305 return (1U | (idx << 4U));
2306 }
2307 }
2308
2309 return 0U;
2310 }
2311
2312
2313 /**
2314 * @brief Get a Logical Channel number from physical Channel
2315 * @param hhcd HCD handle
2316 * @param phy_chnum
2317 * This parameter can be a value from 1 to 15
2318 * @param dir Channel direction
2319 * -0 OUT_Channel
2320 * -1 IN_Channel
2321 * @retval HAL status
2322 */
HAL_HCD_GetLogical_Channel(HCD_HandleTypeDef const * hhcd,uint8_t phy_chnum,uint8_t dir)2323 static uint8_t HAL_HCD_GetLogical_Channel(HCD_HandleTypeDef const *hhcd,
2324 uint8_t phy_chnum, uint8_t dir)
2325 {
2326 /* Out Channel Direction */
2327 if (dir == 0U)
2328 {
2329 if (((hhcd->phy_chout_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) != 0U)
2330 {
2331 return ((uint8_t)((hhcd->phy_chout_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) - 1U);
2332 }
2333 else
2334 {
2335 /* Channel not registered Error */
2336 return HCD_LOGICAL_CH_NOT_OPENED;
2337 }
2338 }
2339 /* IN Channel Direction */
2340 else
2341 {
2342 if (((hhcd->phy_chin_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) != 0U)
2343 {
2344 return ((uint8_t)((hhcd->phy_chin_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) - 1U);
2345 }
2346 else
2347 {
2348 /* Channel not registered Error */
2349 return HCD_LOGICAL_CH_NOT_OPENED;
2350 }
2351 }
2352 }
2353
2354
2355 /**
2356 * @brief Get a free physical Channel number according to the direction
2357 * @param hhcd HCD handle
2358 * @param ch_num Channel number
2359 * This parameter can be a value from 1 to 15
2360 * @param epnum Endpoint number
2361 * This parameter can be a value from 1 to 15
2362 * @param ep_type Endpoint Type
2363 * This parameter can be one of these values:
2364 * EP_TYPE_CTRL Control type,
2365 * EP_TYPE_ISOC Isochronous type,
2366 * EP_TYPE_BULK Bulk type,
2367 * EP_TYPE_INTR Interrupt type
2368 * @retval if physical channel is available return Phy_channel number
2369 else return HCD_FREE_CH_NOT_FOUND
2370 */
HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t epnum,uint8_t ep_type)2371 static uint8_t HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
2372 uint8_t epnum, uint8_t ep_type)
2373 {
2374 uint8_t idx;
2375
2376 if ((epnum & 0x7FU) == 0U)
2377 {
2378 idx = 0U;
2379
2380 if (ch_num == 0U)
2381 {
2382 if (hhcd->phy_chin_state[idx] == 0U)
2383 {
2384 /* chin_state to store the ep_type to be used for the same channel in OUT direction
2385 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2386 hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2387 ((uint16_t)ep_type + 1U) |
2388 (((uint16_t)epnum & 0x0FU) << 8U);
2389 }
2390
2391 if (hhcd->phy_chout_state[idx] == 0U)
2392 {
2393 /* chout_state will store the ep_type to be used for the same channel in IN direction
2394 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2395 hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2396 ((uint16_t)ep_type + 1U) |
2397 (((uint16_t)epnum & 0x0FU) << 8U);
2398 }
2399 }
2400 else
2401 {
2402 if ((epnum & 0x80U) != 0U)
2403 {
2404 if (((hhcd->phy_chin_state[idx] & 0xF0U) >> 4U) != ((uint16_t)ch_num + 1U))
2405 {
2406 /* chin_state to store the ep_type to be used for the same channel in OUT direction
2407 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2408 hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2409 ((uint16_t)ep_type + 1U) |
2410 (((uint16_t)epnum & 0x0FU) << 8U);
2411 }
2412 }
2413 else
2414 {
2415 if (((hhcd->phy_chout_state[idx] & 0xF0U) >> 4U) != ((uint16_t)ch_num + 1U))
2416 {
2417 /* chout_state will store the ep_type to be used for the same channel in IN direction
2418 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2419 hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2420 ((uint16_t)ep_type + 1U) |
2421 (((uint16_t)epnum & 0x0FU) << 8U);
2422 }
2423 }
2424 }
2425
2426 return idx;
2427 }
2428
2429 if ((epnum & 0x80U) != 0U)
2430 {
2431 /* Find a new available physical in channel */
2432 for (idx = 1U; idx < hhcd->Init.Host_channels; idx++)
2433 {
2434 /* Check if the same epnum is allocated then allocate the same physical channel OUT for IN Logical Channel */
2435 if ((hhcd->phy_chin_state[idx] == 0U) &&
2436 ((((hhcd->phy_chout_state[idx] & 0x000FU) == ((uint16_t)ep_type + 1U)) &&
2437 (((hhcd->phy_chout_state[idx] & 0x0F00U) == ((uint16_t)epnum & 0x0FU)))) ||
2438 (hhcd->phy_chout_state[idx] == 0U)))
2439 {
2440 /* chin_state to store the ep_type to be used for the same channel in OUT direction
2441 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2442 hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2443 ((uint16_t)ep_type + 1U) |
2444 (((uint16_t)epnum & 0x0FU) << 8U);
2445
2446 return idx;
2447 }
2448 }
2449 }
2450 else
2451 {
2452 /* Find a new available physical out channel */
2453 for (idx = 1U; idx < hhcd->Init.Host_channels; idx++)
2454 {
2455 /* Check if the same epnum is allocated then allocate the same physical channel IN for OUT Logical Channel */
2456 if ((hhcd->phy_chout_state[idx] == 0U) &&
2457 ((((hhcd->phy_chin_state[idx] & 0x0FU) == ((uint16_t)ep_type + 1U)) &&
2458 ((hhcd->phy_chin_state[idx] & 0x0F00U) == ((uint16_t)epnum & 0x0FU))) ||
2459 (hhcd->phy_chin_state[idx] == 0U)))
2460 {
2461 /* chout_state will store the ep_type to be used for the same channel in IN direction
2462 * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2463 hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2464 ((uint16_t)ep_type + 1U) |
2465 (((uint16_t)epnum & 0x0FU) << 8U);
2466
2467 return idx;
2468 }
2469 }
2470 }
2471
2472 /* in case of Error */
2473 return HCD_FREE_CH_NOT_FOUND;
2474 }
2475
2476 /**
2477 * @brief Free All Channel allocation
2478 * @param hhcd HCD handle
2479 * @retval HAL status
2480 */
HAL_HCD_ClearPhyChannel(HCD_HandleTypeDef * hhcd)2481 static void HAL_HCD_ClearPhyChannel(HCD_HandleTypeDef *hhcd)
2482 {
2483 uint8_t idx;
2484
2485 for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
2486 {
2487 /*Reset channel allocation value */
2488 hhcd->phy_chout_state[idx] = 0U;
2489 hhcd->phy_chin_state[idx] = 0U;
2490 }
2491 }
2492
2493 /*---------------------- PMA Allocation Section --------------------- */
2494 /*
2495 __col31________________col0__ Column-- >
2496 lin0 | entry31.|....... | entry0 | Line
2497 |---------|---------|--------| |
2498 line1| entry63.|....... | entry32| |
2499 |---------|---------|--------| \|/
2500 | entry127|....... | entry64|
2501 |---------|---------|--------|
2502 | entry256|...... |entry128|
2503 ----------------------------
2504 an allocation space of 64byte need 8 Free contiguous Entry in the Matrix
2505 - a Free Entry is a bit with 0 Value/ a busy entry is a bit with 1 value. */
2506
2507 /**
2508 * @brief Fetch in the PMA_LockupTable free space of number of mps byte
2509 * @param hhcd Host instance
2510 * @param mps Channel Max Packet Size
2511 * @retval PMA_Address of the first free block containing mps byte
2512 0xFFFF in case of no space available
2513 */
HAL_HCD_GetFreePMA(HCD_HandleTypeDef * hhcd,uint16_t mps)2514 static uint16_t HAL_HCD_GetFreePMA(HCD_HandleTypeDef *hhcd, uint16_t mps)
2515 {
2516 uint32_t Entry;
2517 uint32_t FreeBlocks = 0U;
2518 uint8_t FirstFreeBlock_col = 0U;
2519 uint8_t FirstFreeBlock_line = 0U;
2520 uint8_t ColIndex;
2521 uint16_t NbrReqBlocks;
2522 uint16_t mps_t = mps;
2523
2524 /* since PMA buffer descriptor RXBD allocate address according to BLSIZE, BLSIZE=1==> mps>64
2525 allocation in PMA is done in 32Bytes each entry */
2526 if ((mps_t > 64U) && ((mps_t % 32U) != 0U))
2527 {
2528 /* Align the mps to 32byte block to match the allocation in PMA,
2529 check Definition of allocation buffer memory in usb user spec */
2530 mps_t = (uint16_t)(((mps_t / 32U) + 1U) * 32U);
2531 }
2532
2533 /* calculate the number of block(8byte) to allocate */
2534 NbrReqBlocks = mps_t / 8U;
2535
2536 /* check if we need remaining Block */
2537 if ((mps_t % 8U) != 0U)
2538 {
2539 NbrReqBlocks++;
2540 }
2541
2542 /* Look For NbrReqBlocks * Empty Block */
2543 for (uint8_t i = 0U; ((i < PMA_BLOCKS) && (FreeBlocks != NbrReqBlocks)); i++)
2544 {
2545 Entry = hhcd->PMALookupTable[i];
2546
2547 /* when parse is in progress, check the first col to look for a contiguous block */
2548 if ((FreeBlocks != 0U) && ((Entry & (uint32_t)1U) != 0U))
2549 {
2550 FreeBlocks = 0U;
2551 }
2552 uint8_t j = 0U;
2553 while ((j <= 31U) && (FreeBlocks != NbrReqBlocks))
2554 {
2555 /* check if block j is free */
2556 if ((Entry & ((uint32_t)1U << j)) == 0U)
2557 {
2558 if (FreeBlocks == 0U)
2559 {
2560 FirstFreeBlock_col = j;
2561 FirstFreeBlock_line = i;
2562 FreeBlocks++;
2563 }
2564 j++;
2565
2566 /* Parse Column PMALockTable */
2567 while ((j <= 31U) && ((Entry & ((uint32_t)1U << j)) == 0U) && (FreeBlocks < NbrReqBlocks))
2568 {
2569 FreeBlocks++;
2570 j++;
2571 }
2572
2573 /* Free contiguous Blocks not found */
2574 if (((FreeBlocks < NbrReqBlocks) && (j < 31U)) ||
2575 ((j == 31U) && ((Entry & ((uint32_t)1U << j)) != 0U)))
2576 {
2577 FreeBlocks = 0U;
2578 }
2579 }
2580 j++;
2581 } /* end for j */
2582 } /* end for i */
2583
2584 /* Free block found */
2585 if (FreeBlocks >= NbrReqBlocks)
2586 {
2587 ColIndex = FirstFreeBlock_col;
2588
2589 for (uint8_t i = FirstFreeBlock_line; ((i < PMA_BLOCKS) && (FreeBlocks > 0U)); i++)
2590 {
2591 for (uint8_t j = ColIndex; j <= 31U; j++)
2592 {
2593 hhcd->PMALookupTable[i] |= ((uint32_t)1U << j);
2594 if (--FreeBlocks == 0U)
2595 {
2596 break;
2597 }
2598 }
2599 ColIndex = 0U;
2600 }
2601
2602 return (uint16_t)((FirstFreeBlock_line * (uint16_t)256U) + (FirstFreeBlock_col * (uint16_t)8U));
2603 }
2604 else
2605 {
2606 return 0xFFFFU;
2607 }
2608 }
2609
2610 /**
2611 * @brief Allocate PMA buffer for Channel
2612 * This API will fetch a free space
2613 * @param hhcd Host instance
2614 * @param ch_num Channel number
2615 * @param ch_kind endpoint Kind
2616 * USB_SNG_BUF Single Buffer used
2617 * USB_DBL_BUF Double Buffer used
2618 * @param mps Channel Max Packet Size
2619 * @retval HAL status
2620 */
HAL_HCD_PMAlloc(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint16_t ch_kind,uint16_t mps)2621 HAL_StatusTypeDef HAL_HCD_PMAlloc(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
2622 uint16_t ch_kind, uint16_t mps)
2623 {
2624 uint16_t pma_addr0;
2625 #if (USE_USB_DOUBLE_BUFFER == 1U)
2626 uint16_t pma_addr1; /* used for double buffer mode if enabled */
2627 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2628
2629 /* Host Channel */
2630 HCD_HCTypeDef *hc = &(hhcd->hc[ch_num]);
2631
2632 /* Get a FreePMA Address */
2633 pma_addr0 = HAL_HCD_GetFreePMA(hhcd, mps);
2634
2635 /* if there is no free space to allocate */
2636 if (pma_addr0 == 0xFFFFU)
2637 {
2638 return HAL_ERROR;
2639 }
2640 else
2641 {
2642 /* Here we check if the endpoint is single or double Buffer */
2643 if (ch_kind == HCD_SNG_BUF)
2644 {
2645 /* Single Buffer */
2646 hc->doublebuffer = 0U;
2647
2648 if (hc->ep_num == 0U)
2649 {
2650 hhcd->ep0_PmaAllocState = ch_num;
2651 hhcd->ep0_PmaAllocState |= (1U << 8);
2652 }
2653
2654 /* Configure the PMA */
2655 if (hc->ch_dir == CH_IN_DIR)
2656 {
2657 hc->pmaaddr1 = pma_addr0;
2658 (USB_DRD_PMA_BUFF + hc->phy_ch_num)->RXBD = hc->pmaaddr1;
2659
2660 if (hc->ep_num == 0U)
2661 {
2662 hhcd->ep0_PmaAllocState |= (CH_IN_DIR << 4);
2663 }
2664 }
2665 else
2666 {
2667 hc->pmaaddr0 = pma_addr0;
2668 (USB_DRD_PMA_BUFF + hc->phy_ch_num)->TXBD = hc->pmaaddr0;
2669 }
2670
2671 /* Set the PmaAddress */
2672 hc->pmaadress = pma_addr0;
2673 }
2674 #if (USE_USB_DOUBLE_BUFFER == 1U)
2675 else /* USB_DBL_BUF */
2676 {
2677 /* Double Buffer Endpoint */
2678 hc->doublebuffer = 1U;
2679
2680 /* Get a FreePMA Address for buffer 2 */
2681 pma_addr1 = HAL_HCD_GetFreePMA(hhcd, mps);
2682
2683 if (pma_addr1 == 0xFFFFU)
2684 {
2685 /* Free the first buffer */
2686 (void)HAL_HCD_PMAFree(hhcd, pma_addr0, mps);
2687 return HAL_ERROR;
2688 }
2689 else
2690 {
2691 /* Configure the PMA */
2692 hc->pmaaddr0 = (uint16_t)(pma_addr0);
2693 hc->pmaaddr1 = (uint16_t)(pma_addr1);
2694
2695 /* Set Buffer0 pma address */
2696 (USB_DRD_PMA_BUFF + hc->phy_ch_num)->TXBD = pma_addr0;
2697
2698 /* Set Buffer1 pma address */
2699 (USB_DRD_PMA_BUFF + hc->phy_ch_num)->RXBD = pma_addr1;
2700
2701 /* Used for Bulk DB MPS < 64bytes */
2702 if (hc->ch_dir == CH_IN_DIR)
2703 {
2704 hc->pmaadress = hc->pmaaddr1;
2705 }
2706 else
2707 {
2708 hc->pmaadress = hc->pmaaddr0;
2709 }
2710 }
2711 }
2712 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2713 }
2714
2715 return HAL_OK;
2716 }
2717
2718 /**
2719 * @brief PMA De-Allocation for Channel Free the reserved block in the PMA-LookupTable
2720 * @param hhcd Host instance
2721 * @param ch_num Channel number
2722 * @retval HAL status
2723 */
HAL_HCD_PMADeAlloc(HCD_HandleTypeDef * hhcd,uint8_t ch_num)2724 HAL_StatusTypeDef HAL_HCD_PMADeAlloc(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
2725 {
2726 HAL_StatusTypeDef status;
2727
2728 #if (USE_USB_DOUBLE_BUFFER == 1U)
2729 uint8_t Err = 0U;
2730 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2731
2732 /* Host Channel */
2733 HCD_HCTypeDef *hc = &(hhcd->hc[ch_num]);
2734
2735 /* Single Buffer */
2736 if (hc->doublebuffer == 0U)
2737 {
2738 status = HAL_HCD_PMAFree(hhcd, hc->pmaadress, hc->max_packet);
2739 }
2740 else /* Double buffer */
2741 {
2742 #if (USE_USB_DOUBLE_BUFFER == 1U)
2743 status = HAL_HCD_PMAFree(hhcd, hc->pmaaddr0, hc->max_packet);
2744 if (status != HAL_OK)
2745 {
2746 Err++;
2747 }
2748
2749 status = HAL_HCD_PMAFree(hhcd, hc->pmaaddr1, hc->max_packet);
2750 if (status != HAL_OK)
2751 {
2752 Err++;
2753 }
2754
2755 if (Err != 0U)
2756 {
2757 return HAL_ERROR;
2758 }
2759 #else
2760 status = HAL_ERROR;
2761 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2762 }
2763
2764 return status;
2765 }
2766
2767
2768 /**
2769 * @brief PMA Reset
2770 * @param hhcd Host instance
2771 * @retval HAL status
2772 */
HAL_HCD_PMAReset(HCD_HandleTypeDef * hhcd)2773 HAL_StatusTypeDef HAL_HCD_PMAReset(HCD_HandleTypeDef *hhcd)
2774 {
2775 /* Reset All PMA Entry */
2776 for (uint8_t i = 0U; i < PMA_BLOCKS; i++)
2777 {
2778 hhcd->PMALookupTable[i] = 0U;
2779 }
2780
2781 /* Allocate a Space for buffer descriptor table depending on the Host channel number */
2782 for (uint8_t i = 0U; i < hhcd->Init.Host_channels; i++)
2783 {
2784 hhcd->PMALookupTable[0] |= ((uint32_t)1U << i);
2785 }
2786
2787 return HAL_OK;
2788 }
2789
2790 /**
2791 * @brief PMA Free
2792 * @param hhcd Host instance
2793 * @param pma_base PMA base offset stored in hhcd->hc.pmaaddr
2794 * @param mps Max Packet Size
2795 * @retval HAL status
2796 */
HAL_HCD_PMAFree(HCD_HandleTypeDef * hhcd,uint32_t pma_base,uint16_t mps)2797 static HAL_StatusTypeDef HAL_HCD_PMAFree(HCD_HandleTypeDef *hhcd, uint32_t pma_base, uint16_t mps)
2798 {
2799 uint32_t block_nbr;
2800 uint8_t ColIndex;
2801 uint8_t LineIndex;
2802 uint16_t mps_t = mps;
2803
2804 /* since PMA buffer descriptor RXBD allocate address according to BLSIZE, BLSIZE=1==> mps>64
2805 allocation in PMA is done in 32Bytes each entry */
2806 if ((mps_t > 64U) && ((mps_t % 32U) != 0U))
2807 {
2808 /* Align the mps to 32byte block to match the allocation in PMA,
2809 check Definition of allocation buffer memory in usb user spec */
2810 mps_t = (uint16_t)(((mps_t / 32U) + 1U) * 32U);
2811 }
2812
2813 /* Calculate the number of needed block to Free */
2814 if ((mps_t / 8U) != 0U)
2815 {
2816 block_nbr = ((uint32_t)mps_t / 8U);
2817
2818 if ((mps_t % 8U) != 0U)
2819 {
2820 block_nbr++;
2821 }
2822 }
2823 else
2824 {
2825 block_nbr = 1U;
2826 }
2827
2828 /* Decode Col/Line of PMA_Base position in the PMA_LookupTable */
2829 if (pma_base > 256U)
2830 {
2831 LineIndex = (uint8_t)(pma_base / 256U);
2832 ColIndex = (uint8_t)((pma_base - ((uint32_t)LineIndex * 256U)) / 8U);
2833 }
2834 else
2835 {
2836 LineIndex = 0U;
2837 ColIndex = (uint8_t)(pma_base / 8U);
2838 }
2839
2840 /* Reset the corresponding bit in the lookupTable */
2841 for (uint8_t i = LineIndex; ((i < PMA_BLOCKS) && (block_nbr > 0U)); i++)
2842 {
2843 for (uint8_t j = ColIndex; j <= 31U; j++)
2844 {
2845 /* Check if the block is not already reserved or it was already closed */
2846 if ((hhcd->PMALookupTable[i] & ((uint32_t)1U << j)) == 0U)
2847 {
2848 return HAL_ERROR;
2849 }
2850 /* Free the reserved block by resetting the corresponding bit */
2851 hhcd->PMALookupTable[i] &= ~(1U << j);
2852
2853 if (--block_nbr == 0U)
2854 {
2855 break;
2856 }
2857 }
2858 ColIndex = 0U;
2859 }
2860
2861 return HAL_OK;
2862 }
2863
2864 /**
2865 * @}
2866 */
2867
2868 /**
2869 * @}
2870 */
2871 #endif /* defined (USB_DRD_FS) */
2872 #endif /* HAL_HCD_MODULE_ENABLED */
2873
2874 /**
2875 * @}
2876 */
2877
2878 /**
2879 * @}
2880 */
2881