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