1 /**
2 ******************************************************************************
3 * @file stm32l5xx_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 "stm32l5xx_hal.h"
43
44 /** @addtogroup STM32L5xx_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 #if defined (HAL_PCD_MODULE_ENABLED)
176 /**
177 * @brief Activate and configure an endpoint
178 * @param USBx Selected device
179 * @param ep pointer to endpoint structure
180 * @retval HAL status
181 */
USB_ActivateEndpoint(USB_TypeDef * USBx,USB_EPTypeDef * ep)182 HAL_StatusTypeDef USB_ActivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep)
183 {
184 HAL_StatusTypeDef ret = HAL_OK;
185 uint16_t wEpRegVal;
186
187 wEpRegVal = PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_T_MASK;
188
189 /* initialize Endpoint */
190 switch (ep->type)
191 {
192 case EP_TYPE_CTRL:
193 wEpRegVal |= USB_EP_CONTROL;
194 break;
195
196 case EP_TYPE_BULK:
197 wEpRegVal |= USB_EP_BULK;
198 break;
199
200 case EP_TYPE_INTR:
201 wEpRegVal |= USB_EP_INTERRUPT;
202 break;
203
204 case EP_TYPE_ISOC:
205 wEpRegVal |= USB_EP_ISOCHRONOUS;
206 break;
207
208 default:
209 ret = HAL_ERROR;
210 break;
211 }
212
213 PCD_SET_ENDPOINT(USBx, ep->num, (wEpRegVal | USB_EP_CTR_RX | USB_EP_CTR_TX));
214
215 PCD_SET_EP_ADDRESS(USBx, ep->num, ep->num);
216
217 if (ep->doublebuffer == 0U)
218 {
219 if (ep->is_in != 0U)
220 {
221 /*Set the endpoint Transmit buffer address */
222 PCD_SET_EP_TX_ADDRESS(USBx, ep->num, ep->pmaadress);
223 PCD_CLEAR_TX_DTOG(USBx, ep->num);
224
225 if (ep->type != EP_TYPE_ISOC)
226 {
227 /* Configure NAK status for the Endpoint */
228 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
229 }
230 else
231 {
232 /* Configure TX Endpoint to disabled state */
233 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
234 }
235 }
236 else
237 {
238 /* Set the endpoint Receive buffer address */
239 PCD_SET_EP_RX_ADDRESS(USBx, ep->num, ep->pmaadress);
240
241 /* Set the endpoint Receive buffer counter */
242 PCD_SET_EP_RX_CNT(USBx, ep->num, ep->maxpacket);
243 PCD_CLEAR_RX_DTOG(USBx, ep->num);
244
245 if (ep->num == 0U)
246 {
247 /* Configure VALID status for EP0 */
248 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
249 }
250 else
251 {
252 /* Configure NAK status for OUT Endpoint */
253 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
254 }
255 }
256 }
257 #if (USE_USB_DOUBLE_BUFFER == 1U)
258 /* Double Buffer */
259 else
260 {
261 if (ep->type == EP_TYPE_BULK)
262 {
263 /* Set bulk endpoint as double buffered */
264 PCD_SET_BULK_EP_DBUF(USBx, ep->num);
265 }
266 else
267 {
268 /* Set the ISOC endpoint in double buffer mode */
269 PCD_CLEAR_EP_KIND(USBx, ep->num);
270 }
271
272 /* Set buffer address for double buffered mode */
273 PCD_SET_EP_DBUF_ADDR(USBx, ep->num, ep->pmaaddr0, ep->pmaaddr1);
274
275 if (ep->is_in == 0U)
276 {
277 /* Clear the data toggle bits for the endpoint IN/OUT */
278 PCD_CLEAR_RX_DTOG(USBx, ep->num);
279 PCD_CLEAR_TX_DTOG(USBx, ep->num);
280
281 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
282 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
283 }
284 else
285 {
286 /* Clear the data toggle bits for the endpoint IN/OUT */
287 PCD_CLEAR_RX_DTOG(USBx, ep->num);
288 PCD_CLEAR_TX_DTOG(USBx, ep->num);
289
290 if (ep->type != EP_TYPE_ISOC)
291 {
292 /* Configure NAK status for the Endpoint */
293 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
294 }
295 else
296 {
297 /* Configure TX Endpoint to disabled state */
298 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
299 }
300
301 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
302 }
303 }
304 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
305
306 return ret;
307 }
308
309 /**
310 * @brief De-activate and de-initialize an endpoint
311 * @param USBx Selected device
312 * @param ep pointer to endpoint structure
313 * @retval HAL status
314 */
USB_DeactivateEndpoint(USB_TypeDef * USBx,USB_EPTypeDef * ep)315 HAL_StatusTypeDef USB_DeactivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep)
316 {
317 if (ep->doublebuffer == 0U)
318 {
319 if (ep->is_in != 0U)
320 {
321 PCD_CLEAR_TX_DTOG(USBx, ep->num);
322
323 /* Configure DISABLE status for the Endpoint */
324 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
325 }
326
327 else
328 {
329 PCD_CLEAR_RX_DTOG(USBx, ep->num);
330
331 /* Configure DISABLE status for the Endpoint */
332 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
333 }
334 }
335 #if (USE_USB_DOUBLE_BUFFER == 1U)
336 /* Double Buffer */
337 else
338 {
339 if (ep->is_in == 0U)
340 {
341 /* Clear the data toggle bits for the endpoint IN/OUT*/
342 PCD_CLEAR_RX_DTOG(USBx, ep->num);
343 PCD_CLEAR_TX_DTOG(USBx, ep->num);
344
345 /* Reset value of the data toggle bits for the endpoint out*/
346 PCD_TX_DTOG(USBx, ep->num);
347
348 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
349 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
350 }
351 else
352 {
353 /* Clear the data toggle bits for the endpoint IN/OUT*/
354 PCD_CLEAR_RX_DTOG(USBx, ep->num);
355 PCD_CLEAR_TX_DTOG(USBx, ep->num);
356 PCD_RX_DTOG(USBx, ep->num);
357
358 /* Configure DISABLE status for the Endpoint*/
359 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
360 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
361 }
362 }
363 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
364
365 return HAL_OK;
366 }
367
368 /**
369 * @brief USB_EPStartXfer setup and starts a transfer over an EP
370 * @param USBx Selected device
371 * @param ep pointer to endpoint structure
372 * @retval HAL status
373 */
USB_EPStartXfer(USB_TypeDef * USBx,USB_EPTypeDef * ep)374 HAL_StatusTypeDef USB_EPStartXfer(USB_TypeDef *USBx, USB_EPTypeDef *ep)
375 {
376 uint32_t len;
377 #if (USE_USB_DOUBLE_BUFFER == 1U)
378 uint16_t pmabuffer;
379 uint16_t wEPVal;
380 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
381
382 /* IN endpoint */
383 if (ep->is_in == 1U)
384 {
385 /*Multi packet transfer*/
386 if (ep->xfer_len > ep->maxpacket)
387 {
388 len = ep->maxpacket;
389 }
390 else
391 {
392 len = ep->xfer_len;
393 }
394
395 /* configure and validate Tx endpoint */
396 if (ep->doublebuffer == 0U)
397 {
398 USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, (uint16_t)len);
399 PCD_SET_EP_TX_CNT(USBx, ep->num, len);
400 }
401 #if (USE_USB_DOUBLE_BUFFER == 1U)
402 else
403 {
404 /* double buffer bulk management */
405 if (ep->type == EP_TYPE_BULK)
406 {
407 if (ep->xfer_len_db > ep->maxpacket)
408 {
409 /* enable double buffer */
410 PCD_SET_BULK_EP_DBUF(USBx, ep->num);
411
412 /* each Time to write in PMA xfer_len_db will */
413 ep->xfer_len_db -= len;
414
415 /* Fill the two first buffer in the Buffer0 & Buffer1 */
416 if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
417 {
418 /* Set the Double buffer counter for pmabuffer1 */
419 PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
420 pmabuffer = ep->pmaaddr1;
421
422 /* Write the user buffer to USB PMA */
423 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
424 ep->xfer_buff += len;
425
426 if (ep->xfer_len_db > ep->maxpacket)
427 {
428 ep->xfer_len_db -= len;
429 }
430 else
431 {
432 len = ep->xfer_len_db;
433 ep->xfer_len_db = 0U;
434 }
435
436 /* Set the Double buffer counter for pmabuffer0 */
437 PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
438 pmabuffer = ep->pmaaddr0;
439
440 /* Write the user buffer to USB PMA */
441 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
442 }
443 else
444 {
445 /* Set the Double buffer counter for pmabuffer0 */
446 PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
447 pmabuffer = ep->pmaaddr0;
448
449 /* Write the user buffer to USB PMA */
450 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
451 ep->xfer_buff += len;
452
453 if (ep->xfer_len_db > ep->maxpacket)
454 {
455 ep->xfer_len_db -= len;
456 }
457 else
458 {
459 len = ep->xfer_len_db;
460 ep->xfer_len_db = 0U;
461 }
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 }
470 }
471 /* auto Switch to single buffer mode when transfer <Mps no need to manage in double buffer */
472 else
473 {
474 len = ep->xfer_len_db;
475
476 /* disable double buffer mode for Bulk endpoint */
477 PCD_CLEAR_BULK_EP_DBUF(USBx, ep->num);
478
479 /* Set Tx count with nbre of byte to be transmitted */
480 PCD_SET_EP_TX_CNT(USBx, ep->num, len);
481 pmabuffer = ep->pmaaddr0;
482
483 /* Write the user buffer to USB PMA */
484 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
485 }
486 }
487 else /* manage isochronous double buffer IN mode */
488 {
489 /* each Time to write in PMA xfer_len_db will */
490 ep->xfer_len_db -= len;
491
492 /* Fill the data buffer */
493 if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
494 {
495 /* Set the Double buffer counter for pmabuffer1 */
496 PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
497 pmabuffer = ep->pmaaddr1;
498
499 /* Write the user buffer to USB PMA */
500 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
501 }
502 else
503 {
504 /* Set the Double buffer counter for pmabuffer0 */
505 PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
506 pmabuffer = ep->pmaaddr0;
507
508 /* Write the user buffer to USB PMA */
509 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
510 }
511 }
512 }
513 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
514
515 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID);
516 }
517 else /* OUT endpoint */
518 {
519 if (ep->doublebuffer == 0U)
520 {
521 /* Multi packet transfer */
522 if (ep->xfer_len > ep->maxpacket)
523 {
524 len = ep->maxpacket;
525 ep->xfer_len -= len;
526 }
527 else
528 {
529 len = ep->xfer_len;
530 ep->xfer_len = 0U;
531 }
532 /* configure and validate Rx endpoint */
533 PCD_SET_EP_RX_CNT(USBx, ep->num, len);
534 }
535 #if (USE_USB_DOUBLE_BUFFER == 1U)
536 else
537 {
538 /* First Transfer Coming From HAL_PCD_EP_Receive & From ISR */
539 /* Set the Double buffer counter */
540 if (ep->type == EP_TYPE_BULK)
541 {
542 PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, ep->maxpacket);
543
544 /* Coming from ISR */
545 if (ep->xfer_count != 0U)
546 {
547 /* update last value to check if there is blocking state */
548 wEPVal = PCD_GET_ENDPOINT(USBx, ep->num);
549
550 /*Blocking State */
551 if ((((wEPVal & USB_EP_DTOG_RX) != 0U) && ((wEPVal & USB_EP_DTOG_TX) != 0U)) ||
552 (((wEPVal & USB_EP_DTOG_RX) == 0U) && ((wEPVal & USB_EP_DTOG_TX) == 0U)))
553 {
554 PCD_FREE_USER_BUFFER(USBx, ep->num, 0U);
555 }
556 }
557 }
558 /* iso out double */
559 else if (ep->type == EP_TYPE_ISOC)
560 {
561 /* Multi packet transfer */
562 if (ep->xfer_len > ep->maxpacket)
563 {
564 len = ep->maxpacket;
565 ep->xfer_len -= len;
566 }
567 else
568 {
569 len = ep->xfer_len;
570 ep->xfer_len = 0U;
571 }
572 PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, len);
573 }
574 else
575 {
576 return HAL_ERROR;
577 }
578 }
579 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
580
581 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
582 }
583
584 return HAL_OK;
585 }
586
587
588 /**
589 * @brief USB_EPSetStall set a stall condition over an EP
590 * @param USBx Selected device
591 * @param ep pointer to endpoint structure
592 * @retval HAL status
593 */
USB_EPSetStall(USB_TypeDef * USBx,USB_EPTypeDef * ep)594 HAL_StatusTypeDef USB_EPSetStall(USB_TypeDef *USBx, USB_EPTypeDef *ep)
595 {
596 if (ep->is_in != 0U)
597 {
598 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_STALL);
599 }
600 else
601 {
602 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_STALL);
603 }
604
605 return HAL_OK;
606 }
607
608 /**
609 * @brief USB_EPClearStall Clear a stall condition over an EP
610 * @param USBx Selected device
611 * @param ep pointer to endpoint structure
612 * @retval HAL status
613 */
USB_EPClearStall(USB_TypeDef * USBx,USB_EPTypeDef * ep)614 HAL_StatusTypeDef USB_EPClearStall(USB_TypeDef *USBx, USB_EPTypeDef *ep)
615 {
616 if (ep->doublebuffer == 0U)
617 {
618 if (ep->is_in != 0U)
619 {
620 PCD_CLEAR_TX_DTOG(USBx, ep->num);
621
622 if (ep->type != EP_TYPE_ISOC)
623 {
624 /* Configure NAK status for the Endpoint */
625 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
626 }
627 }
628 else
629 {
630 PCD_CLEAR_RX_DTOG(USBx, ep->num);
631
632 /* Configure VALID status for the Endpoint */
633 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
634 }
635 }
636
637 return HAL_OK;
638 }
639
640 /**
641 * @brief USB_EPStoptXfer Stop transfer on an EP
642 * @param USBx usb device instance
643 * @param ep pointer to endpoint structure
644 * @retval HAL status
645 */
USB_EPStopXfer(USB_TypeDef * USBx,USB_EPTypeDef * ep)646 HAL_StatusTypeDef USB_EPStopXfer(USB_TypeDef *USBx, USB_EPTypeDef *ep)
647 {
648 /* IN endpoint */
649 if (ep->is_in == 1U)
650 {
651 if (ep->doublebuffer == 0U)
652 {
653 if (ep->type != EP_TYPE_ISOC)
654 {
655 /* Configure NAK status for the Endpoint */
656 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
657 }
658 else
659 {
660 /* Configure TX Endpoint to disabled state */
661 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
662 }
663 }
664 }
665 else /* OUT endpoint */
666 {
667 if (ep->doublebuffer == 0U)
668 {
669 if (ep->type != EP_TYPE_ISOC)
670 {
671 /* Configure NAK status for the Endpoint */
672 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
673 }
674 else
675 {
676 /* Configure RX Endpoint to disabled state */
677 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
678 }
679 }
680 }
681
682 return HAL_OK;
683 }
684 #endif /* defined (HAL_PCD_MODULE_ENABLED) */
685
686 /**
687 * @brief USB_StopDevice Stop the usb device mode
688 * @param USBx Selected device
689 * @retval HAL status
690 */
USB_StopDevice(USB_TypeDef * USBx)691 HAL_StatusTypeDef USB_StopDevice(USB_TypeDef *USBx)
692 {
693 /* disable all interrupts and force USB reset */
694 USBx->CNTR = (uint16_t)USB_CNTR_FRES;
695
696 /* clear interrupt status register */
697 USBx->ISTR = 0U;
698
699 /* switch-off device */
700 USBx->CNTR = (uint16_t)(USB_CNTR_FRES | USB_CNTR_PDWN);
701
702 return HAL_OK;
703 }
704
705 /**
706 * @brief USB_SetDevAddress Stop the usb device mode
707 * @param USBx Selected device
708 * @param address new device address to be assigned
709 * This parameter can be a value from 0 to 255
710 * @retval HAL status
711 */
USB_SetDevAddress(USB_TypeDef * USBx,uint8_t address)712 HAL_StatusTypeDef USB_SetDevAddress(USB_TypeDef *USBx, uint8_t address)
713 {
714 if (address == 0U)
715 {
716 /* set device address and enable function */
717 USBx->DADDR = (uint16_t)USB_DADDR_EF;
718 }
719
720 return HAL_OK;
721 }
722
723 /**
724 * @brief USB_DevConnect Connect the USB device by enabling the pull-up/pull-down
725 * @param USBx Selected device
726 * @retval HAL status
727 */
USB_DevConnect(USB_TypeDef * USBx)728 HAL_StatusTypeDef USB_DevConnect(USB_TypeDef *USBx)
729 {
730 /* Enabling DP Pull-UP bit to Connect internal PU resistor on USB DP line */
731 USBx->BCDR |= (uint16_t)USB_BCDR_DPPU;
732
733 return HAL_OK;
734 }
735
736 /**
737 * @brief USB_DevDisconnect Disconnect the USB device by disabling the pull-up/pull-down
738 * @param USBx Selected device
739 * @retval HAL status
740 */
USB_DevDisconnect(USB_TypeDef * USBx)741 HAL_StatusTypeDef USB_DevDisconnect(USB_TypeDef *USBx)
742 {
743 /* Disable DP Pull-Up bit to disconnect the Internal PU resistor on USB DP line */
744 USBx->BCDR &= (uint16_t)(~(USB_BCDR_DPPU));
745
746 return HAL_OK;
747 }
748
749 /**
750 * @brief USB_ReadInterrupts return the global USB interrupt status
751 * @param USBx Selected device
752 * @retval USB Global Interrupt status
753 */
USB_ReadInterrupts(USB_TypeDef * USBx)754 uint32_t USB_ReadInterrupts(USB_TypeDef *USBx)
755 {
756 uint32_t tmpreg;
757
758 tmpreg = USBx->ISTR;
759 return tmpreg;
760 }
761
762 /**
763 * @brief USB_ActivateRemoteWakeup : active remote wakeup signalling
764 * @param USBx Selected device
765 * @retval HAL status
766 */
USB_ActivateRemoteWakeup(USB_TypeDef * USBx)767 HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_TypeDef *USBx)
768 {
769 USBx->CNTR |= (uint16_t)USB_CNTR_RESUME;
770
771 return HAL_OK;
772 }
773
774 /**
775 * @brief USB_DeActivateRemoteWakeup de-active remote wakeup signalling
776 * @param USBx Selected device
777 * @retval HAL status
778 */
USB_DeActivateRemoteWakeup(USB_TypeDef * USBx)779 HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_TypeDef *USBx)
780 {
781 USBx->CNTR &= (uint16_t)(~USB_CNTR_RESUME);
782
783 return HAL_OK;
784 }
785
786 /**
787 * @brief Copy a buffer from user memory area to packet memory area (PMA)
788 * @param USBx USB peripheral instance register address.
789 * @param pbUsrBuf pointer to user memory area.
790 * @param wPMABufAddr address into PMA.
791 * @param wNBytes no. of bytes to be copied.
792 * @retval None
793 */
USB_WritePMA(USB_TypeDef * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)794 void USB_WritePMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
795 {
796 uint32_t n = ((uint32_t)wNBytes + 1U) >> 1;
797 uint32_t BaseAddr = (uint32_t)USBx;
798 uint32_t count;
799 uint16_t WrVal;
800 __IO uint16_t *pdwVal;
801 uint8_t *pBuf = pbUsrBuf;
802
803 pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
804
805 for (count = n; count != 0U; count--)
806 {
807 WrVal = pBuf[0];
808 WrVal |= (uint16_t)pBuf[1] << 8;
809 *pdwVal = (WrVal & 0xFFFFU);
810 pdwVal++;
811
812 #if PMA_ACCESS > 1U
813 pdwVal++;
814 #endif /* PMA_ACCESS */
815
816 pBuf++;
817 pBuf++;
818 }
819 }
820
821 /**
822 * @brief Copy data from packet memory area (PMA) to user memory buffer
823 * @param USBx USB peripheral instance register address.
824 * @param pbUsrBuf pointer to user memory area.
825 * @param wPMABufAddr address into PMA.
826 * @param wNBytes no. of bytes to be copied.
827 * @retval None
828 */
USB_ReadPMA(USB_TypeDef * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)829 void USB_ReadPMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
830 {
831 uint32_t n = (uint32_t)wNBytes >> 1;
832 uint32_t BaseAddr = (uint32_t)USBx;
833 uint32_t count;
834 uint32_t RdVal;
835 __IO uint16_t *pdwVal;
836 uint8_t *pBuf = pbUsrBuf;
837
838 pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
839
840 for (count = n; count != 0U; count--)
841 {
842 RdVal = *(__IO uint16_t *)pdwVal;
843 pdwVal++;
844 *pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
845 pBuf++;
846 *pBuf = (uint8_t)((RdVal >> 8) & 0xFFU);
847 pBuf++;
848
849 #if PMA_ACCESS > 1U
850 pdwVal++;
851 #endif /* PMA_ACCESS */
852 }
853
854 if ((wNBytes % 2U) != 0U)
855 {
856 RdVal = *pdwVal;
857 *pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
858 }
859 }
860
861
862 /**
863 * @}
864 */
865
866 /**
867 * @}
868 */
869 #endif /* defined (USB) */
870 #endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
871
872 /**
873 * @}
874 */
875