1 /**
2 ******************************************************************************
3 * @file stm32g0xx_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) 2018 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 "stm32g0xx_hal.h"
43
44 /** @addtogroup STM32G0xx_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 /* Enable Global interrupt */
1007 USBx->CNTR |= (USB_CNTR_CTRM | USB_CNTR_PMAOVRM | USB_CNTR_ERRM |
1008 USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_DCON |
1009 USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_L1REQM);
1010
1011 /* Remove Reset */
1012 USBx->CNTR &= ~USB_CNTR_USBRST;
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 wChRegVal &= ~USB_CHEP_DEVADDR;
1154 wChRegVal |= (((uint32_t)dev_address << USB_CHEP_DEVADDR_Pos) |
1155 ((uint32_t)epnum & 0x0FU));
1156
1157 /* Get Host core Speed */
1158 HostCoreSpeed = USB_GetHostSpeed(USBx);
1159
1160 /* Set the device speed in case using HUB FS with device LS */
1161 if ((speed == USB_DRD_SPEED_LS) && (HostCoreSpeed == USB_DRD_SPEED_FS))
1162 {
1163 wChRegVal |= USB_CHEP_LSEP;
1164 }
1165
1166 /* Set the dev_address & ep type */
1167 USB_DRD_SET_CHEP(USBx, phy_ch_num, (wChRegVal | USB_CH_VTRX | USB_CH_VTTX));
1168
1169 return ret;
1170 }
1171
1172 /**
1173 * @brief Start a transfer over a host channel
1174 * @param USBx Selected device
1175 * @param hc pointer to host channel structure
1176 * @retval HAL state
1177 */
USB_HC_StartXfer(USB_DRD_TypeDef * USBx,USB_DRD_HCTypeDef * hc)1178 HAL_StatusTypeDef USB_HC_StartXfer(USB_DRD_TypeDef *USBx, USB_DRD_HCTypeDef *hc)
1179 {
1180 uint32_t len;
1181 uint32_t phy_ch_num = (uint32_t)hc->phy_ch_num;
1182 #if (USE_USB_DOUBLE_BUFFER == 1U)
1183 uint32_t ch_reg = USB_DRD_GET_CHEP(USBx, phy_ch_num);
1184 #endif /* USE_USB_DOUBLE_BUFFER */
1185
1186 if (hc->ch_dir == CH_IN_DIR) /* In Channel */
1187 {
1188 /* Multi packet transfer */
1189 if (hc->xfer_len > hc->max_packet)
1190 {
1191 len = hc->max_packet;
1192 }
1193 else
1194 {
1195 len = hc->xfer_len;
1196 }
1197
1198 if (hc->doublebuffer == 0U)
1199 {
1200 /* Set RX buffer count */
1201 USB_DRD_SET_CHEP_RX_CNT(USBx, phy_ch_num, len);
1202 }
1203 #if (USE_USB_DOUBLE_BUFFER == 1U)
1204 else if (hc->ep_type == EP_TYPE_BULK)
1205 {
1206 /* Double buffer activated */
1207 if ((hc->xfer_len > hc->max_packet))
1208 {
1209 (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_ENBALE);
1210
1211 /*Set the Double buffer counter*/
1212 USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 0U, len);
1213 USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 0U, len);
1214 }
1215 else /* switch to single buffer mode */
1216 {
1217 (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_DISABLE);
1218
1219 /* Set RX buffer count */
1220 USB_DRD_SET_CHEP_RX_CNT(USBx, phy_ch_num, len);
1221 }
1222 }
1223 else /* isochronous */
1224 {
1225 /* Set the Double buffer counter */
1226 USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 0U, len);
1227 USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 0U, len);
1228 }
1229 #endif /* USE_USB_DOUBLE_BUFFER */
1230
1231 /*Enable host channel */
1232 USB_DRD_SET_CHEP_RX_STATUS(USBx, phy_ch_num, USB_CHEP_RX_STRX);
1233 }
1234 else /* Out Channel */
1235 {
1236 /* Multi packet transfer*/
1237 if (hc->xfer_len > hc->max_packet)
1238 {
1239 len = hc->max_packet;
1240 }
1241 else
1242 {
1243 len = hc->xfer_len;
1244 }
1245
1246 /* configure and validate Tx endpoint */
1247 if (hc->doublebuffer == 0U)
1248 {
1249 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaadress, (uint16_t)len);
1250 USB_DRD_SET_CHEP_TX_CNT(USBx, phy_ch_num, (uint16_t)len);
1251
1252 /*SET PID SETUP */
1253 if ((hc->data_pid) == HC_PID_SETUP)
1254 {
1255 USB_DRD_CHEP_TX_SETUP(USBx, phy_ch_num);
1256 }
1257 }
1258 #if (USE_USB_DOUBLE_BUFFER == 1U)
1259 else if (hc->ep_type == EP_TYPE_BULK)
1260 {
1261 (void)USB_HC_BULK_DB_StartXfer(USBx, hc, ch_reg, &len);
1262 }
1263 else
1264 {
1265 (void)USB_HC_ISO_DB_StartXfer(USBx, hc, len);
1266 }
1267 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1268
1269 /* Enable host channel */
1270 USB_DRD_SET_CHEP_TX_STATUS(USBx, hc->phy_ch_num, USB_CH_TX_VALID);
1271 }
1272
1273 return HAL_OK;
1274 }
1275
1276 #if (USE_USB_DOUBLE_BUFFER == 1U)
1277 /**
1278 * @brief Start Transfer of Channel isochronous out double buffer
1279 * @param USBx Selected device
1280 * @param hc_num Host Channel number
1281 * This parameter can be a value from 1 to 15
1282 * @param len Transfer Length
1283 * @retval HAL state
1284 */
USB_HC_ISO_DB_StartXfer(USB_DRD_TypeDef * USBx,USB_DRD_HCTypeDef * hc,uint32_t len)1285 static HAL_StatusTypeDef USB_HC_ISO_DB_StartXfer(USB_DRD_TypeDef *USBx,
1286 USB_DRD_HCTypeDef *hc,
1287 uint32_t len)
1288 {
1289 uint32_t phy_ch_num = (uint32_t)hc->phy_ch_num;
1290
1291 /* check the DTOG_TX to determine in which buffer we should write */
1292 if ((USB_DRD_GET_CHEP(USBx, phy_ch_num) & USB_CH_DTOG_TX) != 0U)
1293 {
1294 USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 1U, len);
1295 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)len);
1296 }
1297 else
1298 {
1299 /* DTOGTX=0 */
1300 /* Set the Double buffer counter for pmabuffer0 */
1301 USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 1U, len);
1302 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr1, (uint16_t)len);
1303 }
1304
1305 return HAL_OK;
1306 }
1307
1308 /**
1309 * @brief Start Transfer of Channel bulk out double buffer
1310 * @param USBx Selected device
1311 * @param hc_num Host Channel number
1312 * This parameter can be a value from 1 to 15
1313 * @param ch_reg snapshot of the CHEPR register
1314 * @param len Transfer Length
1315 * @retval HAL state
1316 */
USB_HC_BULK_DB_StartXfer(USB_DRD_TypeDef * USBx,USB_DRD_HCTypeDef * hc,uint32_t ch_reg,uint32_t * len)1317 static HAL_StatusTypeDef USB_HC_BULK_DB_StartXfer(USB_DRD_TypeDef *USBx,
1318 USB_DRD_HCTypeDef *hc,
1319 uint32_t ch_reg,
1320 uint32_t *len)
1321 {
1322 uint32_t phy_ch_num = (uint32_t)hc->phy_ch_num;
1323
1324 /* -Double Buffer Mangement- */
1325 if (hc->xfer_len_db > hc->max_packet)
1326 {
1327 /* enable double buffer mode */
1328 (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_ENBALE);
1329 *len = hc->max_packet;
1330 hc->xfer_len_db -= *len;
1331
1332 /* Prepare two buffer before enabling host */
1333 if ((ch_reg & USB_CH_DTOG_TX) == 0U)
1334 {
1335 /* Write Buffer0 */
1336 USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
1337 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)*len);
1338 }
1339 else
1340 {
1341 /* Write Buffer1 */
1342 USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
1343 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr1, (uint16_t)*len);
1344 }
1345
1346 hc->xfer_buff += *len;
1347
1348 /* Multi packet transfer */
1349 if (hc->xfer_len_db > hc->max_packet)
1350 {
1351 hc->xfer_len_db -= *len;
1352 }
1353 else
1354 {
1355 *len = hc->xfer_len_db;
1356 hc->xfer_len_db = 0U;
1357 }
1358
1359 if ((ch_reg & USB_CH_DTOG_TX) == 0U)
1360 {
1361 /* Write Buffer1 */
1362 USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
1363 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr1, (uint16_t)*len);
1364 }
1365 else
1366 {
1367 /* Write Buffer0 */
1368 USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
1369 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)*len);
1370 }
1371 }
1372 else
1373 {
1374 /* Disable bulk double buffer mode */
1375 (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_DISABLE);
1376 USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)*len);
1377 USB_DRD_SET_CHEP_TX_CNT(USBx, phy_ch_num, (uint16_t)*len);
1378 }
1379
1380 return HAL_OK;
1381 }
1382 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1383
1384
1385 /**
1386 * @brief Halt a host channel in
1387 * @param USBx Selected device
1388 * @param hc_num Host Channel number
1389 * This parameter can be a value from 1 to 15
1390 * @retval HAL state
1391 */
USB_HC_IN_Halt(USB_DRD_TypeDef * USBx,uint8_t phy_ch)1392 HAL_StatusTypeDef USB_HC_IN_Halt(USB_DRD_TypeDef *USBx, uint8_t phy_ch)
1393 {
1394 /* Set disable to Channel */
1395 USB_DRD_SET_CHEP_RX_STATUS(USBx, phy_ch, USB_CH_RX_DIS);
1396
1397 return HAL_OK;
1398 }
1399
1400
1401 /**
1402 * @brief Halt a host channel out
1403 * @param USBx Selected device
1404 * @param hc_num Host Channel number
1405 * This parameter can be a value from 1 to 15
1406 * @retval HAL state
1407 */
USB_HC_OUT_Halt(USB_DRD_TypeDef * USBx,uint8_t phy_ch)1408 HAL_StatusTypeDef USB_HC_OUT_Halt(USB_DRD_TypeDef *USBx, uint8_t phy_ch)
1409 {
1410 /* Set disable to Channel */
1411 USB_DRD_SET_CHEP_TX_STATUS(USBx, phy_ch, USB_CH_TX_DIS);
1412
1413 return HAL_OK;
1414 }
1415
1416 /**
1417 * @brief Stop Host Core
1418 * @param USBx Selected device
1419 * @retval HAL state
1420 */
USB_StopHost(USB_DRD_TypeDef * USBx)1421 HAL_StatusTypeDef USB_StopHost(USB_DRD_TypeDef *USBx)
1422 {
1423 USBx->ISTR &= ~(USB_ISTR_DIR | USB_ISTR_L1REQ |
1424 USB_ISTR_ESOF | USB_ISTR_SOF |
1425 USB_ISTR_RESET | USB_ISTR_DCON |
1426 USB_ISTR_SUSP | USB_ISTR_WKUP |
1427 USB_ISTR_ERR | USB_ISTR_PMAOVR |
1428 USB_ISTR_CTR);
1429
1430 /* Set PowerDown */
1431 USBx->CNTR |= USB_CNTR_PDWN;
1432
1433 /* Force a Reset */
1434 USBx->CNTR |= USB_CNTR_USBRST;
1435
1436 return HAL_OK;
1437 }
1438
1439 /**
1440 * @}
1441 */
1442
1443 /**
1444 * @}
1445 */
1446 #endif /* defined (USB_DRD_FS) */
1447 #endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
1448
1449 /**
1450 * @}
1451 */
1452