1 /**
2 ******************************************************************************
3 * @file stm32u0xx_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) 2023 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 "stm32u0xx_hal.h"
43
44 /** @addtogroup STM32U0xx_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
59 /**
60 * @brief Reset the USB Core (needed after USB clock settings change)
61 * @param USBx Selected device
62 * @retval HAL status
63 */
USB_CoreReset(USB_DRD_TypeDef * USBx)64 static HAL_StatusTypeDef USB_CoreReset(USB_DRD_TypeDef *USBx)
65 {
66 /* Disable Host Mode */
67 USBx->CNTR &= ~USB_CNTR_HOST;
68
69 /* Force Reset IP */
70 USBx->CNTR |= USB_CNTR_USBRST;
71
72 return HAL_OK;
73 }
74
75 /**
76 * @brief Initializes the USB Core
77 * @param USBx USB Instance
78 * @param cfg pointer to a USB_CfgTypeDef structure that contains
79 * the configuration information for the specified USBx peripheral.
80 * @retval HAL status
81 */
USB_CoreInit(USB_DRD_TypeDef * USBx,USB_DRD_CfgTypeDef cfg)82 HAL_StatusTypeDef USB_CoreInit(USB_DRD_TypeDef *USBx, USB_DRD_CfgTypeDef cfg)
83 {
84 HAL_StatusTypeDef ret;
85 UNUSED(cfg);
86
87 if (USBx == NULL)
88 {
89 return HAL_ERROR;
90 }
91
92 /* Reset after a PHY select */
93 ret = USB_CoreReset(USBx);
94
95 /* Clear pending interrupts */
96 USBx->ISTR = 0U;
97
98 return ret;
99 }
100
101 /**
102 * @brief USB_EnableGlobalInt
103 * Enables the controller's Global Int in the AHB Config reg
104 * @param USBx Selected device
105 * @retval HAL status
106 */
USB_EnableGlobalInt(USB_DRD_TypeDef * USBx)107 HAL_StatusTypeDef USB_EnableGlobalInt(USB_DRD_TypeDef *USBx)
108 {
109 uint32_t winterruptmask;
110
111 /* Clear pending interrupts */
112 USBx->ISTR = 0U;
113
114 /* Set winterruptmask variable */
115 winterruptmask = USB_CNTR_CTRM | USB_CNTR_WKUPM |
116 USB_CNTR_SUSPM | USB_CNTR_ERRM |
117 USB_CNTR_SOFM | USB_CNTR_ESOFM |
118 USB_CNTR_RESETM | USB_CNTR_L1REQM;
119
120 /* Set interrupt mask */
121 USBx->CNTR = winterruptmask;
122
123 return HAL_OK;
124 }
125
126 /**
127 * @brief USB_DisableGlobalInt
128 * Disable the controller's Global Int in the AHB Config reg
129 * @param USBx Selected device
130 * @retval HAL status
131 */
USB_DisableGlobalInt(USB_DRD_TypeDef * USBx)132 HAL_StatusTypeDef USB_DisableGlobalInt(USB_DRD_TypeDef *USBx)
133 {
134 uint32_t winterruptmask;
135
136 /* Set winterruptmask variable */
137 winterruptmask = USB_CNTR_CTRM | USB_CNTR_WKUPM |
138 USB_CNTR_SUSPM | USB_CNTR_ERRM |
139 USB_CNTR_SOFM | USB_CNTR_ESOFM |
140 USB_CNTR_RESETM | USB_CNTR_L1REQM;
141
142 /* Clear interrupt mask */
143 USBx->CNTR &= ~winterruptmask;
144
145 return HAL_OK;
146 }
147
148 /**
149 * @brief USB_SetCurrentMode Set functional mode
150 * @param USBx Selected device
151 * @param mode current core mode
152 * This parameter can be one of the these values:
153 * @arg USB_DEVICE_MODE Peripheral mode
154 * @retval HAL status
155 */
USB_SetCurrentMode(USB_DRD_TypeDef * USBx,USB_DRD_ModeTypeDef mode)156 HAL_StatusTypeDef USB_SetCurrentMode(USB_DRD_TypeDef *USBx, USB_DRD_ModeTypeDef mode)
157 {
158 if (mode == USB_DEVICE_MODE)
159 {
160 USBx->CNTR &= ~USB_CNTR_HOST;
161 }
162 else
163 {
164 return HAL_ERROR;
165 }
166
167 return HAL_OK;
168 }
169
170 /**
171 * @brief USB_DevInit Initializes the USB controller registers
172 * for device mode
173 * @param USBx Selected device
174 * @param cfg pointer to a USB_DRD_CfgTypeDef structure that contains
175 * the configuration information for the specified USBx peripheral.
176 * @retval HAL status
177 */
USB_DevInit(USB_DRD_TypeDef * USBx,USB_DRD_CfgTypeDef cfg)178 HAL_StatusTypeDef USB_DevInit(USB_DRD_TypeDef *USBx, USB_DRD_CfgTypeDef cfg)
179 {
180 HAL_StatusTypeDef ret;
181
182 /* Prevent unused argument(s) compilation warning */
183 UNUSED(cfg);
184
185 /* Force Reset */
186 USBx->CNTR = USB_CNTR_USBRST;
187
188 /* Release Reset */
189 USBx->CNTR &= ~USB_CNTR_USBRST;
190
191 /* Set the Device Mode */
192 ret = USB_SetCurrentMode(USBx, USB_DEVICE_MODE);
193
194 /* Clear pending interrupts */
195 USBx->ISTR = 0U;
196
197 return ret;
198 }
199
200 /**
201 * @brief USB_FlushTxFifo : Flush a Tx FIFO
202 * @param USBx : Selected device
203 * @param num : FIFO number
204 * This parameter can be a value from 1 to 15
205 15 means Flush all Tx FIFOs
206 * @retval HAL status
207 */
USB_FlushTxFifo(USB_DRD_TypeDef const * USBx,uint32_t num)208 HAL_StatusTypeDef USB_FlushTxFifo(USB_DRD_TypeDef const *USBx, uint32_t num)
209 {
210 /* Prevent unused argument(s) compilation warning */
211 UNUSED(USBx);
212 UNUSED(num);
213
214 /* NOTE : - This function is not required by USB Device FS peripheral, it is used
215 only by USB OTG FS peripheral.
216 - This function is added to ensure compatibility across platforms.
217 */
218
219 return HAL_OK;
220 }
221
222 /**
223 * @brief USB_FlushRxFifo : Flush Rx FIFO
224 * @param USBx : Selected device
225 * @retval HAL status
226 */
USB_FlushRxFifo(USB_DRD_TypeDef const * USBx)227 HAL_StatusTypeDef USB_FlushRxFifo(USB_DRD_TypeDef const *USBx)
228 {
229 /* Prevent unused argument(s) compilation warning */
230 UNUSED(USBx);
231
232 /* NOTE : - This function is not required by USB Device FS peripheral, it is used
233 only by USB OTG FS peripheral.
234 - This function is added to ensure compatibility across platforms.
235 */
236
237 return HAL_OK;
238 }
239
240
241 #if defined (HAL_PCD_MODULE_ENABLED)
242 /**
243 * @brief Activate and configure an endpoint
244 * @param USBx Selected device
245 * @param ep pointer to endpoint structure
246 * @retval HAL status
247 */
USB_ActivateEndpoint(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)248 HAL_StatusTypeDef USB_ActivateEndpoint(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
249 {
250 HAL_StatusTypeDef ret = HAL_OK;
251 uint32_t wEpRegVal;
252
253 wEpRegVal = PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_T_MASK;
254
255 /* initialize Endpoint */
256 switch (ep->type)
257 {
258 case EP_TYPE_CTRL:
259 wEpRegVal |= USB_EP_CONTROL;
260 break;
261
262 case EP_TYPE_BULK:
263 wEpRegVal |= USB_EP_BULK;
264 break;
265
266 case EP_TYPE_INTR:
267 wEpRegVal |= USB_EP_INTERRUPT;
268 break;
269
270 case EP_TYPE_ISOC:
271 wEpRegVal |= USB_EP_ISOCHRONOUS;
272 break;
273
274 default:
275 ret = HAL_ERROR;
276 break;
277 }
278
279 PCD_SET_ENDPOINT(USBx, ep->num, (wEpRegVal | USB_EP_VTRX | USB_EP_VTTX));
280
281 PCD_SET_EP_ADDRESS(USBx, ep->num, ep->num);
282
283 if (ep->doublebuffer == 0U)
284 {
285 if (ep->is_in != 0U)
286 {
287 /*Set the endpoint Transmit buffer address */
288 PCD_SET_EP_TX_ADDRESS(USBx, ep->num, ep->pmaadress);
289 PCD_CLEAR_TX_DTOG(USBx, ep->num);
290
291 if (ep->type != EP_TYPE_ISOC)
292 {
293 /* Configure NAK status for the Endpoint */
294 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
295 }
296 else
297 {
298 /* Configure TX Endpoint to disabled state */
299 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
300 }
301 }
302 else
303 {
304 /* Set the endpoint Receive buffer address */
305 PCD_SET_EP_RX_ADDRESS(USBx, ep->num, ep->pmaadress);
306
307 /* Set the endpoint Receive buffer counter */
308 PCD_SET_EP_RX_CNT(USBx, ep->num, ep->maxpacket);
309 PCD_CLEAR_RX_DTOG(USBx, ep->num);
310
311 if (ep->num == 0U)
312 {
313 /* Configure VALID status for EP0 */
314 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
315 }
316 else
317 {
318 /* Configure NAK status for OUT Endpoint */
319 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
320 }
321 }
322 }
323 #if (USE_USB_DOUBLE_BUFFER == 1U)
324 /* Double Buffer */
325 else
326 {
327 if (ep->type == EP_TYPE_BULK)
328 {
329 /* Set bulk endpoint as double buffered */
330 PCD_SET_BULK_EP_DBUF(USBx, ep->num);
331 }
332 else
333 {
334 /* Set the ISOC endpoint in double buffer mode */
335 PCD_CLEAR_EP_KIND(USBx, ep->num);
336 }
337
338 /* Set buffer address for double buffered mode */
339 PCD_SET_EP_DBUF_ADDR(USBx, ep->num, ep->pmaaddr0, ep->pmaaddr1);
340
341 if (ep->is_in == 0U)
342 {
343 /* Clear the data toggle bits for the endpoint IN/OUT */
344 PCD_CLEAR_RX_DTOG(USBx, ep->num);
345 PCD_CLEAR_TX_DTOG(USBx, ep->num);
346
347 /* Set endpoint RX count */
348 PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, ep->maxpacket);
349
350 /* Set endpoint RX to valid state */
351 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
352 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
353 }
354 else
355 {
356 /* Clear the data toggle bits for the endpoint IN/OUT */
357 PCD_CLEAR_RX_DTOG(USBx, ep->num);
358 PCD_CLEAR_TX_DTOG(USBx, ep->num);
359
360 if (ep->type != EP_TYPE_ISOC)
361 {
362 /* Configure NAK status for the Endpoint */
363 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
364 }
365 else
366 {
367 /* Configure TX Endpoint to disabled state */
368 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
369 }
370
371 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
372 }
373 }
374 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
375
376 return ret;
377 }
378
379 /**
380 * @brief De-activate and de-initialize an endpoint
381 * @param USBx Selected device
382 * @param ep pointer to endpoint structure
383 * @retval HAL status
384 */
USB_DeactivateEndpoint(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)385 HAL_StatusTypeDef USB_DeactivateEndpoint(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
386 {
387 if (ep->doublebuffer == 0U)
388 {
389 if (ep->is_in != 0U)
390 {
391 PCD_CLEAR_TX_DTOG(USBx, ep->num);
392
393 /* Configure DISABLE status for the Endpoint */
394 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
395 }
396
397 else
398 {
399 PCD_CLEAR_RX_DTOG(USBx, ep->num);
400
401 /* Configure DISABLE status for the Endpoint */
402 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
403 }
404 }
405 #if (USE_USB_DOUBLE_BUFFER == 1U)
406 /* Double Buffer */
407 else
408 {
409 if (ep->is_in == 0U)
410 {
411 /* Clear the data toggle bits for the endpoint IN/OUT*/
412 PCD_CLEAR_RX_DTOG(USBx, ep->num);
413 PCD_CLEAR_TX_DTOG(USBx, ep->num);
414
415 /* Reset value of the data toggle bits for the endpoint out*/
416 PCD_TX_DTOG(USBx, ep->num);
417
418 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
419 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
420 }
421 else
422 {
423 /* Clear the data toggle bits for the endpoint IN/OUT*/
424 PCD_CLEAR_RX_DTOG(USBx, ep->num);
425 PCD_CLEAR_TX_DTOG(USBx, ep->num);
426 PCD_RX_DTOG(USBx, ep->num);
427
428 /* Configure DISABLE status for the Endpoint*/
429 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
430 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
431 }
432 }
433 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
434
435 return HAL_OK;
436 }
437
438 /**
439 * @brief USB_EPStartXfer setup and starts a transfer over an EP
440 * @param USBx Selected device
441 * @param ep pointer to endpoint structure
442 * @retval HAL status
443 */
USB_EPStartXfer(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)444 HAL_StatusTypeDef USB_EPStartXfer(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
445 {
446 uint32_t len;
447 #if (USE_USB_DOUBLE_BUFFER == 1U)
448 uint16_t pmabuffer;
449 uint16_t wEPVal;
450 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
451
452 /* IN endpoint */
453 if (ep->is_in == 1U)
454 {
455 /* Multi packet transfer */
456 if (ep->xfer_len > ep->maxpacket)
457 {
458 len = ep->maxpacket;
459 }
460 else
461 {
462 len = ep->xfer_len;
463 }
464
465 /* configure and validate Tx endpoint */
466 if (ep->doublebuffer == 0U)
467 {
468 USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, (uint16_t)len);
469 PCD_SET_EP_TX_CNT(USBx, ep->num, len);
470 }
471 #if (USE_USB_DOUBLE_BUFFER == 1U)
472 else
473 {
474 /* double buffer bulk management */
475 if (ep->type == EP_TYPE_BULK)
476 {
477 if (ep->xfer_len_db > ep->maxpacket)
478 {
479 /* enable double buffer */
480 PCD_SET_BULK_EP_DBUF(USBx, ep->num);
481
482 /* each Time to write in PMA xfer_len_db will */
483 ep->xfer_len_db -= len;
484
485 /* Fill the two first buffer in the Buffer0 & Buffer1 */
486 if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
487 {
488 /* Set the Double buffer counter for pmabuffer1 */
489 PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
490 pmabuffer = ep->pmaaddr1;
491
492 /* Write the user buffer to USB PMA */
493 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
494 ep->xfer_buff += len;
495
496 if (ep->xfer_len_db > ep->maxpacket)
497 {
498 ep->xfer_len_db -= len;
499 }
500 else
501 {
502 len = ep->xfer_len_db;
503 ep->xfer_len_db = 0U;
504 }
505
506 /* Set the Double buffer counter for pmabuffer0 */
507 PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
508 pmabuffer = ep->pmaaddr0;
509
510 /* Write the user buffer to USB PMA */
511 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
512 }
513 else
514 {
515 /* Set the Double buffer counter for pmabuffer0 */
516 PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
517 pmabuffer = ep->pmaaddr0;
518
519 /* Write the user buffer to USB PMA */
520 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
521 ep->xfer_buff += len;
522
523 if (ep->xfer_len_db > ep->maxpacket)
524 {
525 ep->xfer_len_db -= len;
526 }
527 else
528 {
529 len = ep->xfer_len_db;
530 ep->xfer_len_db = 0U;
531 }
532
533 /* Set the Double buffer counter for pmabuffer1 */
534 PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
535 pmabuffer = ep->pmaaddr1;
536
537 /* Write the user buffer to USB PMA */
538 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
539 }
540 }
541 /* auto Switch to single buffer mode when transfer <Mps no need to manage in double buffer */
542 else
543 {
544 len = ep->xfer_len_db;
545
546 /* disable double buffer mode for Bulk endpoint */
547 PCD_CLEAR_BULK_EP_DBUF(USBx, ep->num);
548
549 /* Set Tx count with nbre of byte to be transmitted */
550 PCD_SET_EP_TX_CNT(USBx, ep->num, len);
551 pmabuffer = ep->pmaaddr0;
552
553 /* Write the user buffer to USB PMA */
554 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
555 }
556 }
557 else /* Manage isochronous double buffer IN mode */
558 {
559 /* Each Time to write in PMA xfer_len_db will */
560 ep->xfer_len_db -= len;
561
562 /* Fill the data buffer */
563 if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
564 {
565 /* Set the Double buffer counter for pmabuffer1 */
566 PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
567 pmabuffer = ep->pmaaddr1;
568
569 /* Write the user buffer to USB PMA */
570 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
571 }
572 else
573 {
574 /* Set the Double buffer counter for pmabuffer0 */
575 PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
576 pmabuffer = ep->pmaaddr0;
577
578 /* Write the user buffer to USB PMA */
579 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
580 }
581 }
582 }
583 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
584
585 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID);
586 }
587 else /* OUT endpoint */
588 {
589 if (ep->doublebuffer == 0U)
590 {
591 if ((ep->xfer_len == 0U) && (ep->type == EP_TYPE_CTRL))
592 {
593 /* This is a status out stage set the OUT_STATUS */
594 PCD_SET_OUT_STATUS(USBx, ep->num);
595 }
596 else
597 {
598 PCD_CLEAR_OUT_STATUS(USBx, ep->num);
599 }
600
601 /* Multi packet transfer */
602 if (ep->xfer_len > ep->maxpacket)
603 {
604 ep->xfer_len -= ep->maxpacket;
605 }
606 else
607 {
608 ep->xfer_len = 0U;
609 }
610 }
611 #if (USE_USB_DOUBLE_BUFFER == 1U)
612 else
613 {
614 /* First Transfer Coming From HAL_PCD_EP_Receive & From ISR */
615 /* Set the Double buffer counter */
616 if (ep->type == EP_TYPE_BULK)
617 {
618 /* Coming from ISR */
619 if (ep->xfer_count != 0U)
620 {
621 /* Update last value to check if there is blocking state */
622 wEPVal = (uint16_t)PCD_GET_ENDPOINT(USBx, ep->num);
623
624 /* Blocking State */
625 if ((((wEPVal & USB_EP_DTOG_RX) != 0U) && ((wEPVal & USB_EP_DTOG_TX) != 0U)) ||
626 (((wEPVal & USB_EP_DTOG_RX) == 0U) && ((wEPVal & USB_EP_DTOG_TX) == 0U)))
627 {
628 PCD_FREE_USER_BUFFER(USBx, ep->num, 0U);
629 }
630 }
631 }
632 /* iso out double */
633 else if (ep->type == EP_TYPE_ISOC)
634 {
635 /* Only single packet transfer supported in FS */
636 ep->xfer_len = 0U;
637 }
638 else
639 {
640 return HAL_ERROR;
641 }
642 }
643 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
644
645 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
646 }
647
648 return HAL_OK;
649 }
650
651
652 /**
653 * @brief USB_EPSetStall set a stall condition over an EP
654 * @param USBx Selected device
655 * @param ep pointer to endpoint structure
656 * @retval HAL status
657 */
USB_EPSetStall(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)658 HAL_StatusTypeDef USB_EPSetStall(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
659 {
660 if (ep->is_in != 0U)
661 {
662 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_STALL);
663 }
664 else
665 {
666 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_STALL);
667 }
668
669 return HAL_OK;
670 }
671
672 /**
673 * @brief USB_EPClearStall Clear a stall condition over an EP
674 * @param USBx Selected device
675 * @param ep pointer to endpoint structure
676 * @retval HAL status
677 */
USB_EPClearStall(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)678 HAL_StatusTypeDef USB_EPClearStall(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
679 {
680 if (ep->is_in != 0U)
681 {
682 PCD_CLEAR_TX_DTOG(USBx, ep->num);
683
684 if (ep->type != EP_TYPE_ISOC)
685 {
686 /* Configure NAK status for the Endpoint */
687 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
688 }
689 }
690 else
691 {
692 PCD_CLEAR_RX_DTOG(USBx, ep->num);
693
694 /* Configure VALID status for the Endpoint */
695 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
696 }
697
698 return HAL_OK;
699 }
700
701 /**
702 * @brief USB_EPStoptXfer Stop transfer on an EP
703 * @param USBx usb device instance
704 * @param ep pointer to endpoint structure
705 * @retval HAL status
706 */
USB_EPStopXfer(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)707 HAL_StatusTypeDef USB_EPStopXfer(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
708 {
709 /* IN endpoint */
710 if (ep->is_in == 1U)
711 {
712 if (ep->doublebuffer == 0U)
713 {
714 if (ep->type != EP_TYPE_ISOC)
715 {
716 /* Configure NAK status for the Endpoint */
717 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
718 }
719 else
720 {
721 /* Configure TX Endpoint to disabled state */
722 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
723 }
724 }
725 }
726 else /* OUT endpoint */
727 {
728 if (ep->doublebuffer == 0U)
729 {
730 if (ep->type != EP_TYPE_ISOC)
731 {
732 /* Configure NAK status for the Endpoint */
733 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
734 }
735 else
736 {
737 /* Configure RX Endpoint to disabled state */
738 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
739 }
740 }
741 }
742
743 return HAL_OK;
744 }
745 #endif /* defined (HAL_PCD_MODULE_ENABLED) */
746
747 /**
748 * @brief USB_StopDevice Stop the usb device mode
749 * @param USBx Selected device
750 * @retval HAL status
751 */
USB_StopDevice(USB_DRD_TypeDef * USBx)752 HAL_StatusTypeDef USB_StopDevice(USB_DRD_TypeDef *USBx)
753 {
754 /* disable all interrupts and force USB reset */
755 USBx->CNTR = USB_CNTR_USBRST;
756
757 /* clear interrupt status register */
758 USBx->ISTR = 0U;
759
760 /* switch-off device */
761 USBx->CNTR = (USB_CNTR_USBRST | USB_CNTR_PDWN);
762
763 return HAL_OK;
764 }
765
766 /**
767 * @brief USB_SetDevAddress Stop the usb device mode
768 * @param USBx Selected device
769 * @param address new device address to be assigned
770 * This parameter can be a value from 0 to 255
771 * @retval HAL status
772 */
USB_SetDevAddress(USB_DRD_TypeDef * USBx,uint8_t address)773 HAL_StatusTypeDef USB_SetDevAddress(USB_DRD_TypeDef *USBx, uint8_t address)
774 {
775 if (address == 0U)
776 {
777 /* set device address and enable function */
778 USBx->DADDR = USB_DADDR_EF;
779 }
780
781 return HAL_OK;
782 }
783
784 /**
785 * @brief USB_DevConnect Connect the USB device by enabling the pull-up/pull-down
786 * @param USBx Selected device
787 * @retval HAL status
788 */
USB_DevConnect(USB_DRD_TypeDef * USBx)789 HAL_StatusTypeDef USB_DevConnect(USB_DRD_TypeDef *USBx)
790 {
791 /* Enabling DP Pull-UP bit to Connect internal PU resistor on USB DP line */
792 USBx->BCDR |= USB_BCDR_DPPU;
793
794 return HAL_OK;
795 }
796
797 /**
798 * @brief USB_DevDisconnect Disconnect the USB device by disabling the pull-up/pull-down
799 * @param USBx Selected device
800 * @retval HAL status
801 */
USB_DevDisconnect(USB_DRD_TypeDef * USBx)802 HAL_StatusTypeDef USB_DevDisconnect(USB_DRD_TypeDef *USBx)
803 {
804 /* Disable DP Pull-Up bit to disconnect the Internal PU resistor on USB DP line */
805 USBx->BCDR &= ~(USB_BCDR_DPPU);
806
807 return HAL_OK;
808 }
809
810 /**
811 * @brief USB_ReadInterrupts return the global USB interrupt status
812 * @param USBx Selected device
813 * @retval USB Global Interrupt status
814 */
USB_ReadInterrupts(USB_DRD_TypeDef const * USBx)815 uint32_t USB_ReadInterrupts(USB_DRD_TypeDef const *USBx)
816 {
817 uint32_t tmpreg;
818
819 tmpreg = USBx->ISTR;
820 return tmpreg;
821 }
822
823 /**
824 * @brief USB_ActivateRemoteWakeup : active remote wakeup signalling
825 * @param USBx Selected device
826 * @retval HAL status
827 */
USB_ActivateRemoteWakeup(USB_DRD_TypeDef * USBx)828 HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_DRD_TypeDef *USBx)
829 {
830 USBx->CNTR |= USB_CNTR_L2RES;
831
832 return HAL_OK;
833 }
834
835 /**
836 * @brief USB_DeActivateRemoteWakeup de-active remote wakeup signalling
837 * @param USBx Selected device
838 * @retval HAL status
839 */
USB_DeActivateRemoteWakeup(USB_DRD_TypeDef * USBx)840 HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_DRD_TypeDef *USBx)
841 {
842 USBx->CNTR &= ~USB_CNTR_L2RES;
843
844 return HAL_OK;
845 }
846
847 /**
848 * @brief Copy a buffer from user memory area to packet memory area (PMA)
849 * @param USBx USB peripheral instance register address.
850 * @param pbUsrBuf pointer to user memory area.
851 * @param wPMABufAddr address into PMA.
852 * @param wNBytes no. of bytes to be copied.
853 * @retval None
854 */
USB_WritePMA(USB_DRD_TypeDef const * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)855 void USB_WritePMA(USB_DRD_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
856 {
857 UNUSED(USBx);
858 uint32_t WrVal;
859 uint32_t count;
860 __IO uint32_t *pdwVal;
861 uint32_t NbWords = ((uint32_t)wNBytes + 3U) >> 2U;
862 /* Due to the PMA access 32bit only so the last non word data should be processed alone */
863 uint16_t remaining_bytes = wNBytes % 4U;
864 uint8_t *pBuf = pbUsrBuf;
865
866 /* Check if there is a remaining byte */
867 if (remaining_bytes != 0U)
868 {
869 NbWords--;
870 }
871
872 /* Get the PMA Buffer pointer */
873 pdwVal = (__IO uint32_t *)(USB_DRD_PMAADDR + (uint32_t)wPMABufAddr);
874
875 /* Write the Calculated Word into the PMA related Buffer */
876 for (count = NbWords; count != 0U; count--)
877 {
878 *pdwVal = __UNALIGNED_UINT32_READ(pBuf);
879 pdwVal++;
880 /* Increment pBuf 4 Time as Word Increment */
881 pBuf++;
882 pBuf++;
883 pBuf++;
884 pBuf++;
885 }
886
887 /* When Number of data is not word aligned, write the remaining Byte */
888 if (remaining_bytes != 0U)
889 {
890 WrVal = 0U;
891
892 do
893 {
894 WrVal |= (uint32_t)(*(uint8_t *)pBuf) << (8U * count);
895 count++;
896 pBuf++;
897 remaining_bytes--;
898 } while (remaining_bytes != 0U);
899
900 *pdwVal = WrVal;
901 }
902 }
903
904 /**
905 * @brief Copy data from packet memory area (PMA) to user memory buffer
906 * @param USBx USB peripheral instance register address.
907 * @param pbUsrBuf pointer to user memory area.
908 * @param wPMABufAddr address into PMA.
909 * @param wNBytes no. of bytes to be copied.
910 * @retval None
911 */
USB_ReadPMA(USB_DRD_TypeDef const * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)912 void USB_ReadPMA(USB_DRD_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
913 {
914 UNUSED(USBx);
915 uint32_t count;
916 uint32_t RdVal;
917 __IO uint32_t *pdwVal;
918 uint32_t NbWords = ((uint32_t)wNBytes + 3U) >> 2U;
919 /*Due to the PMA access 32bit only so the last non word data should be processed alone */
920 uint16_t remaining_bytes = wNBytes % 4U;
921 uint8_t *pBuf = pbUsrBuf;
922
923 /* Get the PMA Buffer pointer */
924 pdwVal = (__IO uint32_t *)(USB_DRD_PMAADDR + (uint32_t)wPMABufAddr);
925
926 /* if nbre of byte is not word aligned decrement the nbre of word*/
927 if (remaining_bytes != 0U)
928 {
929 NbWords--;
930 }
931
932 /*Read the Calculated Word From the PMA related Buffer*/
933 for (count = NbWords; count != 0U; count--)
934 {
935 __UNALIGNED_UINT32_WRITE(pBuf, *pdwVal);
936
937 pdwVal++;
938 pBuf++;
939 pBuf++;
940 pBuf++;
941 pBuf++;
942 }
943
944 /*When Number of data is not word aligned, read the remaining byte*/
945 if (remaining_bytes != 0U)
946 {
947 RdVal = *(__IO uint32_t *)pdwVal;
948
949 do
950 {
951 *(uint8_t *)pBuf = (uint8_t)(RdVal >> (8U * (uint8_t)(count)));
952 count++;
953 pBuf++;
954 remaining_bytes--;
955 } while (remaining_bytes != 0U);
956 }
957 }
958
959
960 /**
961 * @}
962 */
963
964 /**
965 * @}
966 */
967 #endif /* defined (USB_DRD_FS) */
968 #endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
969
970 /**
971 * @}
972 */
973