1 /**
2 ******************************************************************************
3 * @file stm32c0xx_ll_usb.c
4 * @author MCD Application Team
5 * @brief USB Low Layer HAL module driver.
6 *
7 * This file provides firmware functions to manage the following
8 * functionalities of the USB Peripheral Controller:
9 * + Initialization/de-initialization functions
10 * + I/O operation functions
11 * + Peripheral Control functions
12 * + Peripheral State functions
13 *
14 ******************************************************************************
15 * @attention
16 *
17 * Copyright (c) 2022 STMicroelectronics.
18 * All rights reserved.
19 *
20 * This software is licensed under terms that can be found in the LICENSE file
21 * in the root directory of this software component.
22 * If no LICENSE file comes with this software, it is provided AS-IS.
23 *
24 ******************************************************************************
25 @verbatim
26 ==============================================================================
27 ##### How to use this driver #####
28 ==============================================================================
29 [..]
30 (#) Fill parameters of Init structure in USB_CfgTypeDef structure.
31
32 (#) Call USB_CoreInit() API to initialize the USB Core peripheral.
33
34 (#) The upper HAL HCD/PCD driver will call the right routines for its internal processes.
35
36 @endverbatim
37
38 ******************************************************************************
39 */
40
41 /* Includes ------------------------------------------------------------------*/
42 #include "stm32c0xx_hal.h"
43
44 /** @addtogroup STM32C0xx_LL_USB_DRIVER
45 * @{
46 */
47
48 #if defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED)
49 #if defined (USB_DRD_FS)
50 /* Private typedef -----------------------------------------------------------*/
51 /* Private define ------------------------------------------------------------*/
52 /* Private macro -------------------------------------------------------------*/
53 /* Private variables ---------------------------------------------------------*/
54 /* Private function prototypes -----------------------------------------------*/
55 /* Private functions ---------------------------------------------------------*/
56
57 static HAL_StatusTypeDef USB_CoreReset(USB_DRD_TypeDef *USBx);
58 #if (USE_USB_DOUBLE_BUFFER == 1U)
59 static HAL_StatusTypeDef USB_HC_BULK_DB_StartXfer(USB_DRD_TypeDef *USBx,
60 USB_DRD_HCTypeDef *hc,
61 uint32_t ch_reg,
62 uint32_t *len);
63
64 static HAL_StatusTypeDef USB_HC_ISO_DB_StartXfer(USB_DRD_TypeDef *USBx,
65 USB_DRD_HCTypeDef *hc,
66 uint32_t len);
67 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
68
69 /**
70 * @brief Reset the USB Core (needed after USB clock settings change)
71 * @param USBx Selected device
72 * @retval HAL status
73 */
USB_CoreReset(USB_DRD_TypeDef * USBx)74 static HAL_StatusTypeDef USB_CoreReset(USB_DRD_TypeDef *USBx)
75 {
76 /* Disable Host Mode */
77 USBx->CNTR &= ~USB_CNTR_HOST;
78
79 /* Force Reset IP */
80 USBx->CNTR |= USB_CNTR_USBRST;
81
82 return HAL_OK;
83 }
84
85 /**
86 * @brief Initializes the USB Core
87 * @param USBx USB Instance
88 * @param cfg pointer to a USB_CfgTypeDef structure that contains
89 * the configuration information for the specified USBx peripheral.
90 * @retval HAL status
91 */
USB_CoreInit(USB_DRD_TypeDef * USBx,USB_DRD_CfgTypeDef cfg)92 HAL_StatusTypeDef USB_CoreInit(USB_DRD_TypeDef *USBx, USB_DRD_CfgTypeDef cfg)
93 {
94 HAL_StatusTypeDef ret;
95 UNUSED(cfg);
96
97 if (USBx == NULL)
98 {
99 return HAL_ERROR;
100 }
101
102 /* Reset after a PHY select */
103 ret = USB_CoreReset(USBx);
104
105 /* Clear pending interrupts */
106 USBx->ISTR = 0U;
107
108 return ret;
109 }
110
111 /**
112 * @brief USB_EnableGlobalInt
113 * Enables the controller's Global Int in the AHB Config reg
114 * @param USBx Selected device
115 * @retval HAL status
116 */
USB_EnableGlobalInt(USB_DRD_TypeDef * USBx)117 HAL_StatusTypeDef USB_EnableGlobalInt(USB_DRD_TypeDef *USBx)
118 {
119 uint32_t winterruptmask;
120
121 /* Clear pending interrupts */
122 USBx->ISTR = 0U;
123
124 /* Set winterruptmask variable */
125 winterruptmask = USB_CNTR_CTRM | USB_CNTR_WKUPM |
126 USB_CNTR_SUSPM | USB_CNTR_ERRM |
127 USB_CNTR_SOFM | USB_CNTR_ESOFM |
128 USB_CNTR_RESETM | USB_CNTR_L1REQM;
129
130 /* Set interrupt mask */
131 USBx->CNTR = winterruptmask;
132
133 return HAL_OK;
134 }
135
136 /**
137 * @brief USB_DisableGlobalInt
138 * Disable the controller's Global Int in the AHB Config reg
139 * @param USBx Selected device
140 * @retval HAL status
141 */
USB_DisableGlobalInt(USB_DRD_TypeDef * USBx)142 HAL_StatusTypeDef USB_DisableGlobalInt(USB_DRD_TypeDef *USBx)
143 {
144 uint32_t winterruptmask;
145
146 /* Set winterruptmask variable */
147 winterruptmask = USB_CNTR_CTRM | USB_CNTR_WKUPM |
148 USB_CNTR_SUSPM | USB_CNTR_ERRM |
149 USB_CNTR_SOFM | USB_CNTR_ESOFM |
150 USB_CNTR_RESETM | USB_CNTR_L1REQM;
151
152 /* Clear interrupt mask */
153 USBx->CNTR &= ~winterruptmask;
154
155 return HAL_OK;
156 }
157
158 /**
159 * @brief USB_SetCurrentMode Set functional mode
160 * @param USBx Selected device
161 * @param mode current core mode
162 * This parameter can be one of the these values:
163 * @arg USB_DEVICE_MODE Peripheral mode
164 * @retval HAL status
165 */
USB_SetCurrentMode(USB_DRD_TypeDef * USBx,USB_DRD_ModeTypeDef mode)166 HAL_StatusTypeDef USB_SetCurrentMode(USB_DRD_TypeDef *USBx, USB_DRD_ModeTypeDef mode)
167 {
168 if (mode == USB_DEVICE_MODE)
169 {
170 USBx->CNTR &= ~USB_CNTR_HOST;
171 }
172 else if (mode == USB_HOST_MODE)
173 {
174 USBx->CNTR |= USB_CNTR_HOST;
175 }
176 else
177 {
178 return HAL_ERROR;
179 }
180
181 return HAL_OK;
182 }
183
184 /**
185 * @brief USB_DevInit Initializes the USB controller registers
186 * for device mode
187 * @param USBx Selected device
188 * @param cfg pointer to a USB_DRD_CfgTypeDef structure that contains
189 * the configuration information for the specified USBx peripheral.
190 * @retval HAL status
191 */
USB_DevInit(USB_DRD_TypeDef * USBx,USB_DRD_CfgTypeDef cfg)192 HAL_StatusTypeDef USB_DevInit(USB_DRD_TypeDef *USBx, USB_DRD_CfgTypeDef cfg)
193 {
194 HAL_StatusTypeDef ret;
195
196 /* Prevent unused argument(s) compilation warning */
197 UNUSED(cfg);
198
199 /* Force Reset */
200 USBx->CNTR = USB_CNTR_USBRST;
201
202 /* Release Reset */
203 USBx->CNTR &= ~USB_CNTR_USBRST;
204
205 /* Set the Device Mode */
206 ret = USB_SetCurrentMode(USBx, USB_DEVICE_MODE);
207
208 /* Clear pending interrupts */
209 USBx->ISTR = 0U;
210
211 return ret;
212 }
213
214 /**
215 * @brief USB_FlushTxFifo : Flush a Tx FIFO
216 * @param USBx : Selected device
217 * @param num : FIFO number
218 * This parameter can be a value from 1 to 15
219 15 means Flush all Tx FIFOs
220 * @retval HAL status
221 */
USB_FlushTxFifo(USB_DRD_TypeDef const * USBx,uint32_t num)222 HAL_StatusTypeDef USB_FlushTxFifo(USB_DRD_TypeDef const *USBx, uint32_t num)
223 {
224 /* Prevent unused argument(s) compilation warning */
225 UNUSED(USBx);
226 UNUSED(num);
227
228 /* NOTE : - This function is not required by USB Device FS peripheral, it is used
229 only by USB OTG FS peripheral.
230 - This function is added to ensure compatibility across platforms.
231 */
232
233 return HAL_OK;
234 }
235
236 /**
237 * @brief USB_FlushRxFifo : Flush Rx FIFO
238 * @param USBx : Selected device
239 * @retval HAL status
240 */
USB_FlushRxFifo(USB_DRD_TypeDef const * USBx)241 HAL_StatusTypeDef USB_FlushRxFifo(USB_DRD_TypeDef const *USBx)
242 {
243 /* Prevent unused argument(s) compilation warning */
244 UNUSED(USBx);
245
246 /* NOTE : - This function is not required by USB Device FS peripheral, it is used
247 only by USB OTG FS peripheral.
248 - This function is added to ensure compatibility across platforms.
249 */
250
251 return HAL_OK;
252 }
253
254
255 #if defined (HAL_PCD_MODULE_ENABLED)
256 /**
257 * @brief Activate and configure an endpoint
258 * @param USBx Selected device
259 * @param ep pointer to endpoint structure
260 * @retval HAL status
261 */
USB_ActivateEndpoint(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)262 HAL_StatusTypeDef USB_ActivateEndpoint(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
263 {
264 HAL_StatusTypeDef ret = HAL_OK;
265 uint32_t wEpRegVal;
266
267 wEpRegVal = PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_T_MASK;
268
269 /* initialize Endpoint */
270 switch (ep->type)
271 {
272 case EP_TYPE_CTRL:
273 wEpRegVal |= USB_EP_CONTROL;
274 break;
275
276 case EP_TYPE_BULK:
277 wEpRegVal |= USB_EP_BULK;
278 break;
279
280 case EP_TYPE_INTR:
281 wEpRegVal |= USB_EP_INTERRUPT;
282 break;
283
284 case EP_TYPE_ISOC:
285 wEpRegVal |= USB_EP_ISOCHRONOUS;
286 break;
287
288 default:
289 ret = HAL_ERROR;
290 break;
291 }
292
293 PCD_SET_ENDPOINT(USBx, ep->num, (wEpRegVal | USB_EP_VTRX | USB_EP_VTTX));
294
295 PCD_SET_EP_ADDRESS(USBx, ep->num, ep->num);
296
297 if (ep->doublebuffer == 0U)
298 {
299 if (ep->is_in != 0U)
300 {
301 /*Set the endpoint Transmit buffer address */
302 PCD_SET_EP_TX_ADDRESS(USBx, ep->num, ep->pmaadress);
303 PCD_CLEAR_TX_DTOG(USBx, ep->num);
304
305 if (ep->type != EP_TYPE_ISOC)
306 {
307 /* Configure NAK status for the Endpoint */
308 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
309 }
310 else
311 {
312 /* Configure TX Endpoint to disabled state */
313 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
314 }
315 }
316 else
317 {
318 /* Set the endpoint Receive buffer address */
319 PCD_SET_EP_RX_ADDRESS(USBx, ep->num, ep->pmaadress);
320
321 /* Set the endpoint Receive buffer counter */
322 PCD_SET_EP_RX_CNT(USBx, ep->num, ep->maxpacket);
323 PCD_CLEAR_RX_DTOG(USBx, ep->num);
324
325 if (ep->num == 0U)
326 {
327 /* Configure VALID status for EP0 */
328 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
329 }
330 else
331 {
332 /* Configure NAK status for OUT Endpoint */
333 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
334 }
335 }
336 }
337 #if (USE_USB_DOUBLE_BUFFER == 1U)
338 /* Double Buffer */
339 else
340 {
341 if (ep->type == EP_TYPE_BULK)
342 {
343 /* Set bulk endpoint as double buffered */
344 PCD_SET_BULK_EP_DBUF(USBx, ep->num);
345 }
346 else
347 {
348 /* Set the ISOC endpoint in double buffer mode */
349 PCD_CLEAR_EP_KIND(USBx, ep->num);
350 }
351
352 /* Set buffer address for double buffered mode */
353 PCD_SET_EP_DBUF_ADDR(USBx, ep->num, ep->pmaaddr0, ep->pmaaddr1);
354
355 if (ep->is_in == 0U)
356 {
357 /* Clear the data toggle bits for the endpoint IN/OUT */
358 PCD_CLEAR_RX_DTOG(USBx, ep->num);
359 PCD_CLEAR_TX_DTOG(USBx, ep->num);
360
361 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
362 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
363 }
364 else
365 {
366 /* Clear the data toggle bits for the endpoint IN/OUT */
367 PCD_CLEAR_RX_DTOG(USBx, ep->num);
368 PCD_CLEAR_TX_DTOG(USBx, ep->num);
369
370 if (ep->type != EP_TYPE_ISOC)
371 {
372 /* Configure NAK status for the Endpoint */
373 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
374 }
375 else
376 {
377 /* Configure TX Endpoint to disabled state */
378 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
379 }
380
381 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
382 }
383 }
384 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
385
386 return ret;
387 }
388
389 /**
390 * @brief De-activate and de-initialize an endpoint
391 * @param USBx Selected device
392 * @param ep pointer to endpoint structure
393 * @retval HAL status
394 */
USB_DeactivateEndpoint(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)395 HAL_StatusTypeDef USB_DeactivateEndpoint(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
396 {
397 if (ep->doublebuffer == 0U)
398 {
399 if (ep->is_in != 0U)
400 {
401 PCD_CLEAR_TX_DTOG(USBx, ep->num);
402
403 /* Configure DISABLE status for the Endpoint */
404 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
405 }
406
407 else
408 {
409 PCD_CLEAR_RX_DTOG(USBx, ep->num);
410
411 /* Configure DISABLE status for the Endpoint */
412 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
413 }
414 }
415 #if (USE_USB_DOUBLE_BUFFER == 1U)
416 /* Double Buffer */
417 else
418 {
419 if (ep->is_in == 0U)
420 {
421 /* Clear the data toggle bits for the endpoint IN/OUT*/
422 PCD_CLEAR_RX_DTOG(USBx, ep->num);
423 PCD_CLEAR_TX_DTOG(USBx, ep->num);
424
425 /* Reset value of the data toggle bits for the endpoint out*/
426 PCD_TX_DTOG(USBx, ep->num);
427
428 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
429 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
430 }
431 else
432 {
433 /* Clear the data toggle bits for the endpoint IN/OUT*/
434 PCD_CLEAR_RX_DTOG(USBx, ep->num);
435 PCD_CLEAR_TX_DTOG(USBx, ep->num);
436 PCD_RX_DTOG(USBx, ep->num);
437
438 /* Configure DISABLE status for the Endpoint*/
439 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
440 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
441 }
442 }
443 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
444
445 return HAL_OK;
446 }
447
448 /**
449 * @brief USB_EPStartXfer setup and starts a transfer over an EP
450 * @param USBx Selected device
451 * @param ep pointer to endpoint structure
452 * @retval HAL status
453 */
USB_EPStartXfer(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)454 HAL_StatusTypeDef USB_EPStartXfer(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
455 {
456 uint32_t len;
457 #if (USE_USB_DOUBLE_BUFFER == 1U)
458 uint16_t pmabuffer;
459 uint16_t wEPVal;
460 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
461
462 /* IN endpoint */
463 if (ep->is_in == 1U)
464 {
465 /*Multi packet transfer*/
466 if (ep->xfer_len > ep->maxpacket)
467 {
468 len = ep->maxpacket;
469 }
470 else
471 {
472 len = ep->xfer_len;
473 }
474
475 /* configure and validate Tx endpoint */
476 if (ep->doublebuffer == 0U)
477 {
478 USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, (uint16_t)len);
479 PCD_SET_EP_TX_CNT(USBx, ep->num, len);
480 }
481 #if (USE_USB_DOUBLE_BUFFER == 1U)
482 else
483 {
484 /* double buffer bulk management */
485 if (ep->type == EP_TYPE_BULK)
486 {
487 if (ep->xfer_len_db > ep->maxpacket)
488 {
489 /* enable double buffer */
490 PCD_SET_BULK_EP_DBUF(USBx, ep->num);
491
492 /* each Time to write in PMA xfer_len_db will */
493 ep->xfer_len_db -= len;
494
495 /* Fill the two first buffer in the Buffer0 & Buffer1 */
496 if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
497 {
498 /* Set the Double buffer counter for pmabuffer1 */
499 PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
500 pmabuffer = ep->pmaaddr1;
501
502 /* Write the user buffer to USB PMA */
503 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
504 ep->xfer_buff += len;
505
506 if (ep->xfer_len_db > ep->maxpacket)
507 {
508 ep->xfer_len_db -= len;
509 }
510 else
511 {
512 len = ep->xfer_len_db;
513 ep->xfer_len_db = 0U;
514 }
515
516 /* Set the Double buffer counter for pmabuffer0 */
517 PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
518 pmabuffer = ep->pmaaddr0;
519
520 /* Write the user buffer to USB PMA */
521 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
522 }
523 else
524 {
525 /* Set the Double buffer counter for pmabuffer0 */
526 PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
527 pmabuffer = ep->pmaaddr0;
528
529 /* Write the user buffer to USB PMA */
530 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
531 ep->xfer_buff += len;
532
533 if (ep->xfer_len_db > ep->maxpacket)
534 {
535 ep->xfer_len_db -= len;
536 }
537 else
538 {
539 len = ep->xfer_len_db;
540 ep->xfer_len_db = 0U;
541 }
542
543 /* Set the Double buffer counter for pmabuffer1 */
544 PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
545 pmabuffer = ep->pmaaddr1;
546
547 /* Write the user buffer to USB PMA */
548 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
549 }
550 }
551 /* auto Switch to single buffer mode when transfer <Mps no need to manage in double buffer */
552 else
553 {
554 len = ep->xfer_len_db;
555
556 /* disable double buffer mode for Bulk endpoint */
557 PCD_CLEAR_BULK_EP_DBUF(USBx, ep->num);
558
559 /* Set Tx count with nbre of byte to be transmitted */
560 PCD_SET_EP_TX_CNT(USBx, ep->num, len);
561 pmabuffer = ep->pmaaddr0;
562
563 /* Write the user buffer to USB PMA */
564 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
565 }
566 }
567 else /* manage isochronous double buffer IN mode */
568 {
569 /* each Time to write in PMA xfer_len_db will */
570 ep->xfer_len_db -= len;
571
572 /* Fill the data buffer */
573 if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
574 {
575 /* Set the Double buffer counter for pmabuffer1 */
576 PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
577 pmabuffer = ep->pmaaddr1;
578
579 /* Write the user buffer to USB PMA */
580 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
581 }
582 else
583 {
584 /* Set the Double buffer counter for pmabuffer0 */
585 PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
586 pmabuffer = ep->pmaaddr0;
587
588 /* Write the user buffer to USB PMA */
589 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
590 }
591 }
592 }
593 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
594
595 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID);
596 }
597 else /* OUT endpoint */
598 {
599 if (ep->doublebuffer == 0U)
600 {
601 /* Multi packet transfer */
602 if (ep->xfer_len > ep->maxpacket)
603 {
604 len = ep->maxpacket;
605 ep->xfer_len -= len;
606 }
607 else
608 {
609 len = ep->xfer_len;
610 ep->xfer_len = 0U;
611 }
612 /* configure and validate Rx endpoint */
613 PCD_SET_EP_RX_CNT(USBx, ep->num, len);
614 }
615 #if (USE_USB_DOUBLE_BUFFER == 1U)
616 else
617 {
618 /* First Transfer Coming From HAL_PCD_EP_Receive & From ISR */
619 /* Set the Double buffer counter */
620 if (ep->type == EP_TYPE_BULK)
621 {
622 PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, ep->maxpacket);
623
624 /* Coming from ISR */
625 if (ep->xfer_count != 0U)
626 {
627 /* update last value to check if there is blocking state */
628 wEPVal = (uint16_t)PCD_GET_ENDPOINT(USBx, ep->num);
629
630 /*Blocking State */
631 if ((((wEPVal & USB_EP_DTOG_RX) != 0U) && ((wEPVal & USB_EP_DTOG_TX) != 0U)) ||
632 (((wEPVal & USB_EP_DTOG_RX) == 0U) && ((wEPVal & USB_EP_DTOG_TX) == 0U)))
633 {
634 PCD_FREE_USER_BUFFER(USBx, ep->num, 0U);
635 }
636 }
637 }
638 /* iso out double */
639 else if (ep->type == EP_TYPE_ISOC)
640 {
641 /* Multi packet transfer */
642 if (ep->xfer_len > ep->maxpacket)
643 {
644 len = ep->maxpacket;
645 ep->xfer_len -= len;
646 }
647 else
648 {
649 len = ep->xfer_len;
650 ep->xfer_len = 0U;
651 }
652 PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, len);
653 }
654 else
655 {
656 return HAL_ERROR;
657 }
658 }
659 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
660
661 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
662 }
663
664 return HAL_OK;
665 }
666
667
668 /**
669 * @brief USB_EPSetStall set a stall condition over an EP
670 * @param USBx Selected device
671 * @param ep pointer to endpoint structure
672 * @retval HAL status
673 */
USB_EPSetStall(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)674 HAL_StatusTypeDef USB_EPSetStall(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
675 {
676 if (ep->is_in != 0U)
677 {
678 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_STALL);
679 }
680 else
681 {
682 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_STALL);
683 }
684
685 return HAL_OK;
686 }
687
688 /**
689 * @brief USB_EPClearStall Clear a stall condition over an EP
690 * @param USBx Selected device
691 * @param ep pointer to endpoint structure
692 * @retval HAL status
693 */
USB_EPClearStall(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)694 HAL_StatusTypeDef USB_EPClearStall(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
695 {
696 if (ep->doublebuffer == 0U)
697 {
698 if (ep->is_in != 0U)
699 {
700 PCD_CLEAR_TX_DTOG(USBx, ep->num);
701
702 if (ep->type != EP_TYPE_ISOC)
703 {
704 /* Configure NAK status for the Endpoint */
705 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
706 }
707 }
708 else
709 {
710 PCD_CLEAR_RX_DTOG(USBx, ep->num);
711
712 /* Configure VALID status for the Endpoint */
713 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
714 }
715 }
716
717 return HAL_OK;
718 }
719
720 /**
721 * @brief USB_EPStoptXfer Stop transfer on an EP
722 * @param USBx usb device instance
723 * @param ep pointer to endpoint structure
724 * @retval HAL status
725 */
USB_EPStopXfer(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)726 HAL_StatusTypeDef USB_EPStopXfer(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
727 {
728 /* IN endpoint */
729 if (ep->is_in == 1U)
730 {
731 if (ep->doublebuffer == 0U)
732 {
733 if (ep->type != EP_TYPE_ISOC)
734 {
735 /* Configure NAK status for the Endpoint */
736 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
737 }
738 else
739 {
740 /* Configure TX Endpoint to disabled state */
741 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
742 }
743 }
744 }
745 else /* OUT endpoint */
746 {
747 if (ep->doublebuffer == 0U)
748 {
749 if (ep->type != EP_TYPE_ISOC)
750 {
751 /* Configure NAK status for the Endpoint */
752 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
753 }
754 else
755 {
756 /* Configure RX Endpoint to disabled state */
757 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
758 }
759 }
760 }
761
762 return HAL_OK;
763 }
764 #endif /* defined (HAL_PCD_MODULE_ENABLED) */
765
766 /**
767 * @brief USB_StopDevice Stop the usb device mode
768 * @param USBx Selected device
769 * @retval HAL status
770 */
USB_StopDevice(USB_DRD_TypeDef * USBx)771 HAL_StatusTypeDef USB_StopDevice(USB_DRD_TypeDef *USBx)
772 {
773 /* disable all interrupts and force USB reset */
774 USBx->CNTR = USB_CNTR_USBRST;
775
776 /* clear interrupt status register */
777 USBx->ISTR = 0U;
778
779 /* switch-off device */
780 USBx->CNTR = (USB_CNTR_USBRST | USB_CNTR_PDWN);
781
782 return HAL_OK;
783 }
784
785 /**
786 * @brief USB_SetDevAddress Stop the usb device mode
787 * @param USBx Selected device
788 * @param address new device address to be assigned
789 * This parameter can be a value from 0 to 255
790 * @retval HAL status
791 */
USB_SetDevAddress(USB_DRD_TypeDef * USBx,uint8_t address)792 HAL_StatusTypeDef USB_SetDevAddress(USB_DRD_TypeDef *USBx, uint8_t address)
793 {
794 if (address == 0U)
795 {
796 /* set device address and enable function */
797 USBx->DADDR = USB_DADDR_EF;
798 }
799
800 return HAL_OK;
801 }
802
803 /**
804 * @brief USB_DevConnect Connect the USB device by enabling the pull-up/pull-down
805 * @param USBx Selected device
806 * @retval HAL status
807 */
USB_DevConnect(USB_DRD_TypeDef * USBx)808 HAL_StatusTypeDef USB_DevConnect(USB_DRD_TypeDef *USBx)
809 {
810 /* Enabling DP Pull-UP bit to Connect internal PU resistor on USB DP line */
811 USBx->BCDR |= USB_BCDR_DPPU;
812
813 return HAL_OK;
814 }
815
816 /**
817 * @brief USB_DevDisconnect Disconnect the USB device by disabling the pull-up/pull-down
818 * @param USBx Selected device
819 * @retval HAL status
820 */
USB_DevDisconnect(USB_DRD_TypeDef * USBx)821 HAL_StatusTypeDef USB_DevDisconnect(USB_DRD_TypeDef *USBx)
822 {
823 /* Disable DP Pull-Up bit to disconnect the Internal PU resistor on USB DP line */
824 USBx->BCDR &= ~(USB_BCDR_DPPU);
825
826 return HAL_OK;
827 }
828
829 /**
830 * @brief USB_ReadInterrupts return the global USB interrupt status
831 * @param USBx Selected device
832 * @retval USB Global Interrupt status
833 */
USB_ReadInterrupts(USB_DRD_TypeDef const * USBx)834 uint32_t USB_ReadInterrupts(USB_DRD_TypeDef const *USBx)
835 {
836 uint32_t tmpreg;
837
838 tmpreg = USBx->ISTR;
839 return tmpreg;
840 }
841
842 /**
843 * @brief USB_ActivateRemoteWakeup : active remote wakeup signalling
844 * @param USBx Selected device
845 * @retval HAL status
846 */
USB_ActivateRemoteWakeup(USB_DRD_TypeDef * USBx)847 HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_DRD_TypeDef *USBx)
848 {
849 USBx->CNTR |= USB_CNTR_L2RES;
850
851 return HAL_OK;
852 }
853
854 /**
855 * @brief USB_DeActivateRemoteWakeup de-active remote wakeup signalling
856 * @param USBx Selected device
857 * @retval HAL status
858 */
USB_DeActivateRemoteWakeup(USB_DRD_TypeDef * USBx)859 HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_DRD_TypeDef *USBx)
860 {
861 USBx->CNTR &= ~USB_CNTR_L2RES;
862
863 return HAL_OK;
864 }
865
866 /**
867 * @brief Copy a buffer from user memory area to packet memory area (PMA)
868 * @param USBx USB peripheral instance register address.
869 * @param pbUsrBuf pointer to user memory area.
870 * @param wPMABufAddr address into PMA.
871 * @param wNBytes no. of bytes to be copied.
872 * @retval None
873 */
USB_WritePMA(USB_DRD_TypeDef const * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)874 void USB_WritePMA(USB_DRD_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
875 {
876 UNUSED(USBx);
877 uint32_t WrVal;
878 uint32_t count;
879 __IO uint32_t *pdwVal;
880 uint32_t NbWords = ((uint32_t)wNBytes + 3U) >> 2U;
881 /* Due to the PMA access 32bit only so the last non word data should be processed alone */
882 uint16_t remaining_bytes = wNBytes % 4U;
883 uint8_t *pBuf = pbUsrBuf;
884
885 /* Check if there is a remaining byte */
886 if (remaining_bytes != 0U)
887 {
888 NbWords--;
889 }
890
891 /* Get the PMA Buffer pointer */
892 pdwVal = (__IO uint32_t *)(USB_DRD_PMAADDR + (uint32_t)wPMABufAddr);
893
894 /* Write the Calculated Word into the PMA related Buffer */
895 for (count = NbWords; count != 0U; count--)
896 {
897 *pdwVal = __UNALIGNED_UINT32_READ(pBuf);
898 pdwVal++;
899 /* Increment pBuf 4 Time as Word Increment */
900 pBuf++;
901 pBuf++;
902 pBuf++;
903 pBuf++;
904 }
905
906 /* When Number of data is not word aligned, write the remaining Byte */
907 if (remaining_bytes != 0U)
908 {
909 WrVal = 0U;
910
911 do
912 {
913 WrVal |= (uint32_t)(*(uint8_t *)pBuf) << (8U * count);
914 count++;
915 pBuf++;
916 remaining_bytes--;
917 } while (remaining_bytes != 0U);
918
919 *pdwVal = WrVal;
920 }
921 }
922
923 /**
924 * @brief Copy data from packet memory area (PMA) to user memory buffer
925 * @param USBx USB peripheral instance register address.
926 * @param pbUsrBuf pointer to user memory area.
927 * @param wPMABufAddr address into PMA.
928 * @param wNBytes no. of bytes to be copied.
929 * @retval None
930 */
USB_ReadPMA(USB_DRD_TypeDef const * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)931 void USB_ReadPMA(USB_DRD_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
932 {
933 UNUSED(USBx);
934 uint32_t count;
935 uint32_t RdVal;
936 __IO uint32_t *pdwVal;
937 uint32_t NbWords = ((uint32_t)wNBytes + 3U) >> 2U;
938 /*Due to the PMA access 32bit only so the last non word data should be processed alone */
939 uint16_t remaining_bytes = wNBytes % 4U;
940 uint8_t *pBuf = pbUsrBuf;
941
942 /* Get the PMA Buffer pointer */
943 pdwVal = (__IO uint32_t *)(USB_DRD_PMAADDR + (uint32_t)wPMABufAddr);
944
945 /* if nbre of byte is not word aligned decrement the nbre of word*/
946 if (remaining_bytes != 0U)
947 {
948 NbWords--;
949 }
950
951 /*Read the Calculated Word From the PMA related Buffer*/
952 for (count = NbWords; count != 0U; count--)
953 {
954 __UNALIGNED_UINT32_WRITE(pBuf, *pdwVal);
955
956 pdwVal++;
957 pBuf++;
958 pBuf++;
959 pBuf++;
960 pBuf++;
961 }
962
963 /*When Number of data is not word aligned, read the remaining byte*/
964 if (remaining_bytes != 0U)
965 {
966 RdVal = *(__IO uint32_t *)pdwVal;
967
968 do
969 {
970 *(uint8_t *)pBuf = (uint8_t)(RdVal >> (8U * (uint8_t)(count)));
971 count++;
972 pBuf++;
973 remaining_bytes--;
974 } while (remaining_bytes != 0U);
975 }
976 }
977
978
979 /*------------------------------------------------------------------------*/
980 /* HOST API */
981 /*------------------------------------------------------------------------*/
982
983 /**
984 * @brief USB_HostInit Initializes the USB DRD controller registers
985 * for Host mode
986 * @param USBx Selected device
987 * @param cfg pointer to a USB_DRD_CfgTypeDef structure that contains
988 * the configuration information for the specified USBx peripheral.
989 * @retval HAL status
990 */
USB_HostInit(USB_DRD_TypeDef * USBx,USB_DRD_CfgTypeDef cfg)991 HAL_StatusTypeDef USB_HostInit(USB_DRD_TypeDef *USBx, USB_DRD_CfgTypeDef cfg)
992 {
993 UNUSED(cfg);
994
995 /* Clear All Pending Interrupt */
996 USBx->ISTR = 0U;
997
998 /* Disable all interrupts */
999 USBx->CNTR &= ~(USB_CNTR_CTRM | USB_CNTR_PMAOVRM | USB_CNTR_ERRM |
1000 USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_DCON |
1001 USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_L1REQM);
1002
1003 /* Clear All Pending Interrupt */
1004 USBx->ISTR = 0U;
1005
1006 /* Set the PullDown on the PHY */
1007 USBx->BCDR |= USB_BCDR_DPPD;
1008
1009 /* Enable Global interrupt */
1010 USBx->CNTR |= (USB_CNTR_CTRM | USB_CNTR_PMAOVRM | USB_CNTR_ERRM |
1011 USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_DCON |
1012 USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_L1REQM);
1013
1014 return HAL_OK;
1015 }
1016
1017
1018 /**
1019 * @brief USB_DRD_ResetPort : Reset Host Port
1020 * @param USBx Selected device
1021 * @retval HAL status
1022 * @note (1)The application must wait at least 10 ms
1023 * before clearing the reset bit.
1024 */
USB_ResetPort(USB_DRD_TypeDef * USBx)1025 HAL_StatusTypeDef USB_ResetPort(USB_DRD_TypeDef *USBx)
1026 {
1027 /* Force USB Reset */
1028 USBx->CNTR |= USB_CNTR_USBRST;
1029 HAL_Delay(100);
1030 /* Release USB Reset */
1031 USBx->CNTR &= ~USB_CNTR_USBRST;
1032 HAL_Delay(30);
1033
1034 return HAL_OK;
1035 }
1036
1037 /**
1038 * @brief Return Host Core speed
1039 * @param USBx Selected device
1040 * @retval speed Host speed
1041 * This parameter can be one of these values
1042 * @arg USB_DRD_SPEED_FS Full speed mode
1043 * @arg USB_DRD_SPEED_LS Low speed mode
1044 */
USB_GetHostSpeed(USB_DRD_TypeDef const * USBx)1045 uint32_t USB_GetHostSpeed(USB_DRD_TypeDef const *USBx)
1046 {
1047 if ((USBx->ISTR & USB_ISTR_LS_DCONN) != 0U)
1048 {
1049 return USB_DRD_SPEED_LS;
1050 }
1051 else
1052 {
1053 return USB_DRD_SPEED_FS;
1054 }
1055 }
1056
1057 /**
1058 * @brief Return Host Current Frame number
1059 * @param USBx Selected device
1060 * @retval current frame number
1061 */
USB_GetCurrentFrame(USB_DRD_TypeDef const * USBx)1062 uint32_t USB_GetCurrentFrame(USB_DRD_TypeDef const *USBx)
1063 {
1064 return USBx->FNR & 0x7FFU;
1065 }
1066
1067 /**
1068 * @brief Set the channel Kind (Single/double buffer mode)
1069 * @param USBx Selected device
1070 * @param phy_ch_num Selected device
1071 * @param db_state double state can be USB_DRD_XXX_DBUFF_ENBALE/USB_DRD_XXX_DBUFF_DISABLE
1072 * @retval HAL status
1073 */
USB_HC_DoubleBuffer(USB_DRD_TypeDef * USBx,uint8_t phy_ch_num,uint8_t db_state)1074 HAL_StatusTypeDef USB_HC_DoubleBuffer(USB_DRD_TypeDef *USBx,
1075 uint8_t phy_ch_num, uint8_t db_state)
1076 {
1077 uint32_t tmp;
1078
1079 if ((db_state == USB_DRD_BULK_DBUFF_ENBALE) || (db_state == USB_DRD_ISOC_DBUFF_DISABLE))
1080 {
1081 tmp = (USB_DRD_GET_CHEP(USBx, phy_ch_num) | USB_CH_KIND) & USB_CHEP_DB_MSK;
1082 }
1083 else
1084 {
1085 tmp = USB_DRD_GET_CHEP(USBx, phy_ch_num) & (~USB_CH_KIND) & USB_CHEP_DB_MSK;
1086 }
1087
1088 /* Set the device speed in case using HUB FS with device LS */
1089 USB_DRD_SET_CHEP(USBx, phy_ch_num, tmp);
1090
1091 return HAL_OK;
1092 }
1093
1094 /**
1095 * @brief Initialize a host channel
1096 * @param USBx Selected device
1097 * @param phy_ch_num Channel number
1098 * This parameter can be a value from 1 to 15
1099 * @param epnum Endpoint number
1100 * This parameter can be a value from 1 to 15
1101 * @param dev_address Current device address
1102 * This parameter can be a value from 0 to 255
1103 * @param speed Current device speed
1104 * This parameter can be one of these values:
1105 * @arg USB_DRD_SPEED_FULL Full speed mode
1106 * @arg USB_DRD_SPEED_LOW Low speed mode
1107 * @param ep_type Endpoint Type
1108 * This parameter can be one of these values:
1109 * @arg EP_TYPE_CTRL Control type
1110 * @arg EP_TYPE_ISOC Isochronous type
1111 * @arg EP_TYPE_BULK Bulk type
1112 * @arg EP_TYPE_INTR Interrupt type
1113 * @param mps Max Packet Size
1114 * This parameter can be a value from 0 to 32K
1115 * @retval HAL state
1116 */
USB_HC_Init(USB_DRD_TypeDef * USBx,uint8_t phy_ch_num,uint8_t epnum,uint8_t dev_address,uint8_t speed,uint8_t ep_type,uint16_t mps)1117 HAL_StatusTypeDef USB_HC_Init(USB_DRD_TypeDef *USBx, uint8_t phy_ch_num,
1118 uint8_t epnum, uint8_t dev_address, uint8_t speed,
1119 uint8_t ep_type, uint16_t mps)
1120 {
1121 HAL_StatusTypeDef ret = HAL_OK;
1122 uint32_t wChRegVal;
1123 uint32_t HostCoreSpeed;
1124
1125 UNUSED(mps);
1126
1127 wChRegVal = USB_DRD_GET_CHEP(USBx, phy_ch_num) & USB_CH_T_MASK;
1128
1129 /* Initialize host Channel */
1130 switch (ep_type)
1131 {
1132 case EP_TYPE_CTRL:
1133 wChRegVal |= USB_EP_CONTROL;
1134 break;
1135
1136 case EP_TYPE_BULK:
1137 wChRegVal |= USB_EP_BULK;
1138 break;
1139
1140 case EP_TYPE_INTR:
1141 wChRegVal |= USB_EP_INTERRUPT;
1142 break;
1143
1144 case EP_TYPE_ISOC:
1145 wChRegVal |= USB_EP_ISOCHRONOUS;
1146 break;
1147
1148 default:
1149 ret = HAL_ERROR;
1150 break;
1151 }
1152
1153 /* Clear device address, Endpoint number and Low Speed Endpoint fields */
1154 wChRegVal &= ~(USB_CHEP_DEVADDR |
1155 USB_CHEP_ADDR |
1156 USB_CHEP_LSEP |
1157 USB_CHEP_NAK |
1158 USB_CHEP_KIND |
1159 USB_CHEP_ERRTX |
1160 USB_CHEP_ERRRX |
1161 (0xFU << 27));
1162
1163 /* Set device address and Endpoint number associated to the channel */
1164 wChRegVal |= (((uint32_t)dev_address << USB_CHEP_DEVADDR_Pos) |
1165 ((uint32_t)epnum & 0x0FU));
1166
1167 /* Get Host core Speed */
1168 HostCoreSpeed = USB_GetHostSpeed(USBx);
1169
1170 /* Set the device speed in case using HUB FS with device LS */
1171 if ((speed == USB_DRD_SPEED_LS) && (HostCoreSpeed == USB_DRD_SPEED_FS))
1172 {
1173 wChRegVal |= USB_CHEP_LSEP;
1174 }
1175
1176 /* Update the channel register value */
1177 USB_DRD_SET_CHEP(USBx, phy_ch_num, (wChRegVal | USB_CH_VTRX | USB_CH_VTTX));
1178
1179 return ret;
1180 }
1181
1182 /**
1183 * @brief Start a transfer over a host channel
1184 * @param USBx Selected device
1185 * @param hc pointer to host channel structure
1186 * @retval HAL state
1187 */
USB_HC_StartXfer(USB_DRD_TypeDef * USBx,USB_DRD_HCTypeDef * hc)1188 HAL_StatusTypeDef USB_HC_StartXfer(USB_DRD_TypeDef *USBx, USB_DRD_HCTypeDef *hc)
1189 {
1190 uint32_t len;
1191 uint32_t phy_ch_num = (uint32_t)hc->phy_ch_num;
1192 #if (USE_USB_DOUBLE_BUFFER == 1U)
1193 uint32_t ch_reg = USB_DRD_GET_CHEP(USBx, phy_ch_num);
1194 #endif /* USE_USB_DOUBLE_BUFFER */
1195
1196 if (hc->ch_dir == CH_IN_DIR) /* In Channel */
1197 {
1198 /* Multi packet transfer */
1199 if (hc->xfer_len > hc->max_packet)
1200 {
1201 len = hc->max_packet;
1202 }
1203 else
1204 {
1205 len = hc->xfer_len;
1206 }
1207
1208 if (hc->doublebuffer == 0U)
1209 {
1210 if ((hc->ep_type == EP_TYPE_BULK) ||
1211 (hc->ep_type == EP_TYPE_INTR))
1212 {
1213 USB_DRD_CLEAR_RX_DTOG(USBx, phy_ch_num);
1214
1215 /* Set Data PID */
1216 if (hc->data_pid == HC_PID_DATA1)
1217 {
1218 USB_DRD_RX_DTOG(USBx, phy_ch_num);
1219 }
1220 }
1221
1222 /* Set RX buffer count */
1223 USB_DRD_SET_CHEP_RX_CNT(USBx, phy_ch_num, len);
1224 }
1225 #if (USE_USB_DOUBLE_BUFFER == 1U)
1226 else if (hc->ep_type == EP_TYPE_BULK)
1227 {
1228 /* Double buffer activated */
1229 if ((hc->xfer_len > hc->max_packet))
1230 {
1231 (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_ENBALE);
1232
1233 /* Set the Double buffer counter */
1234 USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 0U, len);
1235 USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 0U, len);
1236 }
1237 else /* Switch to single buffer mode */
1238 {
1239 (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_DISABLE);
1240
1241 /* Set RX buffer count */
1242 USB_DRD_SET_CHEP_RX_CNT(USBx, phy_ch_num, len);
1243 }
1244 }
1245 else /* Isochronous */
1246 {
1247 /* Set the Double buffer counter */
1248 USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 0U, len);
1249 USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 0U, len);
1250 }
1251 #endif /* USE_USB_DOUBLE_BUFFER */
1252
1253 /* Enable host channel */
1254 USB_DRD_SET_CHEP_RX_STATUS(USBx, phy_ch_num, USB_CH_RX_VALID);
1255 }
1256 else /* Out Channel */
1257 {
1258 /* Multi packet transfer */
1259 if (hc->xfer_len > hc->max_packet)
1260 {
1261 len = hc->max_packet;
1262 }
1263 else
1264 {
1265 len = hc->xfer_len;
1266 }
1267
1268 /* Configure and validate Tx endpoint */
1269 if (hc->doublebuffer == 0U)
1270 {
1271 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaadress, (uint16_t)len);
1272 USB_DRD_SET_CHEP_TX_CNT(USBx, phy_ch_num, (uint16_t)len);
1273
1274 /* SET PID SETUP */
1275 if ((hc->data_pid) == HC_PID_SETUP)
1276 {
1277 USB_DRD_CHEP_TX_SETUP(USBx, phy_ch_num);
1278 }
1279
1280 if ((hc->ep_type == EP_TYPE_BULK) ||
1281 (hc->ep_type == EP_TYPE_INTR))
1282 {
1283 USB_DRD_CLEAR_TX_DTOG(USBx, phy_ch_num);
1284
1285 /* Set Data PID */
1286 if (hc->data_pid == HC_PID_DATA1)
1287 {
1288 USB_DRD_TX_DTOG(USBx, phy_ch_num);
1289 }
1290 }
1291 }
1292 #if (USE_USB_DOUBLE_BUFFER == 1U)
1293 else if (hc->ep_type == EP_TYPE_BULK)
1294 {
1295 (void)USB_HC_BULK_DB_StartXfer(USBx, hc, ch_reg, &len);
1296 }
1297 else
1298 {
1299 (void)USB_HC_ISO_DB_StartXfer(USBx, hc, len);
1300 }
1301 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1302
1303 /* Enable host channel */
1304 USB_DRD_SET_CHEP_TX_STATUS(USBx, hc->phy_ch_num, USB_CH_TX_VALID);
1305 }
1306
1307 return HAL_OK;
1308 }
1309
1310 #if (USE_USB_DOUBLE_BUFFER == 1U)
1311 /**
1312 * @brief Start Transfer of Channel isochronous out double buffer
1313 * @param USBx Selected device
1314 * @param hc_num Host Channel number
1315 * This parameter can be a value from 1 to 15
1316 * @param len Transfer Length
1317 * @retval HAL state
1318 */
USB_HC_ISO_DB_StartXfer(USB_DRD_TypeDef * USBx,USB_DRD_HCTypeDef * hc,uint32_t len)1319 static HAL_StatusTypeDef USB_HC_ISO_DB_StartXfer(USB_DRD_TypeDef *USBx,
1320 USB_DRD_HCTypeDef *hc,
1321 uint32_t len)
1322 {
1323 uint32_t phy_ch_num = (uint32_t)hc->phy_ch_num;
1324
1325 /* check the DTOG_TX to determine in which buffer we should write */
1326 if ((USB_DRD_GET_CHEP(USBx, phy_ch_num) & USB_CH_DTOG_TX) != 0U)
1327 {
1328 USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 1U, len);
1329 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)len);
1330 }
1331 else
1332 {
1333 /* DTOGTX=0 */
1334 /* Set the Double buffer counter for pmabuffer0 */
1335 USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 1U, len);
1336 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr1, (uint16_t)len);
1337 }
1338
1339 return HAL_OK;
1340 }
1341
1342 /**
1343 * @brief Start Transfer of Channel bulk out double buffer
1344 * @param USBx Selected device
1345 * @param hc_num Host Channel number
1346 * This parameter can be a value from 1 to 15
1347 * @param ch_reg snapshot of the CHEPR register
1348 * @param len Transfer Length
1349 * @retval HAL state
1350 */
USB_HC_BULK_DB_StartXfer(USB_DRD_TypeDef * USBx,USB_DRD_HCTypeDef * hc,uint32_t ch_reg,uint32_t * len)1351 static HAL_StatusTypeDef USB_HC_BULK_DB_StartXfer(USB_DRD_TypeDef *USBx,
1352 USB_DRD_HCTypeDef *hc,
1353 uint32_t ch_reg,
1354 uint32_t *len)
1355 {
1356 uint32_t phy_ch_num = (uint32_t)hc->phy_ch_num;
1357
1358 /* -Double Buffer Mangement- */
1359 if (hc->xfer_len_db > hc->max_packet)
1360 {
1361 /* enable double buffer mode */
1362 (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_ENBALE);
1363 *len = hc->max_packet;
1364 hc->xfer_len_db -= *len;
1365
1366 /* Prepare two buffer before enabling host */
1367 if ((ch_reg & USB_CH_DTOG_TX) == 0U)
1368 {
1369 /* Write Buffer0 */
1370 USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
1371 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)*len);
1372 }
1373 else
1374 {
1375 /* Write Buffer1 */
1376 USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
1377 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr1, (uint16_t)*len);
1378 }
1379
1380 hc->xfer_buff += *len;
1381
1382 /* Multi packet transfer */
1383 if (hc->xfer_len_db > hc->max_packet)
1384 {
1385 hc->xfer_len_db -= *len;
1386 }
1387 else
1388 {
1389 *len = hc->xfer_len_db;
1390 hc->xfer_len_db = 0U;
1391 }
1392
1393 if ((ch_reg & USB_CH_DTOG_TX) == 0U)
1394 {
1395 /* Write Buffer1 */
1396 USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
1397 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr1, (uint16_t)*len);
1398 }
1399 else
1400 {
1401 /* Write Buffer0 */
1402 USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
1403 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)*len);
1404 }
1405 }
1406 else
1407 {
1408 /* Disable bulk double buffer mode */
1409 (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_DISABLE);
1410 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)*len);
1411 USB_DRD_SET_CHEP_TX_CNT(USBx, phy_ch_num, (uint16_t)*len);
1412 }
1413
1414 return HAL_OK;
1415 }
1416 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1417
1418
1419 /**
1420 * @brief Halt a host channel in
1421 * @param USBx Selected device
1422 * @param hc_num Host Channel number
1423 * This parameter can be a value from 1 to 15
1424 * @retval HAL state
1425 */
USB_HC_IN_Halt(USB_DRD_TypeDef * USBx,uint8_t phy_ch)1426 HAL_StatusTypeDef USB_HC_IN_Halt(USB_DRD_TypeDef *USBx, uint8_t phy_ch)
1427 {
1428 /* Set disable to Channel */
1429 USB_DRD_SET_CHEP_RX_STATUS(USBx, phy_ch, USB_CH_RX_DIS);
1430
1431 return HAL_OK;
1432 }
1433
1434
1435 /**
1436 * @brief Halt a host channel out
1437 * @param USBx Selected device
1438 * @param hc_num Host Channel number
1439 * This parameter can be a value from 1 to 15
1440 * @retval HAL state
1441 */
USB_HC_OUT_Halt(USB_DRD_TypeDef * USBx,uint8_t phy_ch)1442 HAL_StatusTypeDef USB_HC_OUT_Halt(USB_DRD_TypeDef *USBx, uint8_t phy_ch)
1443 {
1444 /* Set disable to Channel */
1445 USB_DRD_SET_CHEP_TX_STATUS(USBx, phy_ch, USB_CH_TX_DIS);
1446
1447 return HAL_OK;
1448 }
1449
1450 /**
1451 * @brief Stop Host Core
1452 * @param USBx Selected device
1453 * @retval HAL state
1454 */
USB_StopHost(USB_DRD_TypeDef * USBx)1455 HAL_StatusTypeDef USB_StopHost(USB_DRD_TypeDef *USBx)
1456 {
1457 USBx->ISTR &= ~(USB_ISTR_DIR | USB_ISTR_L1REQ |
1458 USB_ISTR_ESOF | USB_ISTR_SOF |
1459 USB_ISTR_RESET | USB_ISTR_DCON |
1460 USB_ISTR_SUSP | USB_ISTR_WKUP |
1461 USB_ISTR_ERR | USB_ISTR_PMAOVR |
1462 USB_ISTR_CTR);
1463
1464 /* Set PowerDown */
1465 USBx->CNTR |= USB_CNTR_PDWN;
1466
1467 /* Force a Reset */
1468 USBx->CNTR |= USB_CNTR_USBRST;
1469
1470 return HAL_OK;
1471 }
1472
1473 /**
1474 * @}
1475 */
1476
1477 /**
1478 * @}
1479 */
1480 #endif /* defined (USB_DRD_FS) */
1481 #endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
1482
1483 /**
1484 * @}
1485 */
1486