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