1 /**
2 ******************************************************************************
3 * @file stm32l1xx_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) 2016 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 "stm32l1xx_hal.h"
43
44 /** @addtogroup STM32L1xx_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;
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;
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 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
323 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
324 }
325 else
326 {
327 /* Clear the data toggle bits for the endpoint IN/OUT */
328 PCD_CLEAR_RX_DTOG(USBx, ep->num);
329 PCD_CLEAR_TX_DTOG(USBx, ep->num);
330
331 if (ep->type != EP_TYPE_ISOC)
332 {
333 /* Configure NAK status for the Endpoint */
334 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
335 }
336 else
337 {
338 /* Configure TX Endpoint to disabled state */
339 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
340 }
341
342 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
343 }
344 }
345 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
346
347 return ret;
348 }
349
350 /**
351 * @brief De-activate and de-initialize an endpoint
352 * @param USBx Selected device
353 * @param ep pointer to endpoint structure
354 * @retval HAL status
355 */
USB_DeactivateEndpoint(USB_TypeDef * USBx,USB_EPTypeDef * ep)356 HAL_StatusTypeDef USB_DeactivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep)
357 {
358 if (ep->doublebuffer == 0U)
359 {
360 if (ep->is_in != 0U)
361 {
362 PCD_CLEAR_TX_DTOG(USBx, ep->num);
363
364 /* Configure DISABLE status for the Endpoint */
365 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
366 }
367
368 else
369 {
370 PCD_CLEAR_RX_DTOG(USBx, ep->num);
371
372 /* Configure DISABLE status for the Endpoint */
373 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
374 }
375 }
376 #if (USE_USB_DOUBLE_BUFFER == 1U)
377 /* Double Buffer */
378 else
379 {
380 if (ep->is_in == 0U)
381 {
382 /* Clear the data toggle bits for the endpoint IN/OUT*/
383 PCD_CLEAR_RX_DTOG(USBx, ep->num);
384 PCD_CLEAR_TX_DTOG(USBx, ep->num);
385
386 /* Reset value of the data toggle bits for the endpoint out*/
387 PCD_TX_DTOG(USBx, ep->num);
388
389 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
390 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
391 }
392 else
393 {
394 /* Clear the data toggle bits for the endpoint IN/OUT*/
395 PCD_CLEAR_RX_DTOG(USBx, ep->num);
396 PCD_CLEAR_TX_DTOG(USBx, ep->num);
397 PCD_RX_DTOG(USBx, ep->num);
398
399 /* Configure DISABLE status for the Endpoint*/
400 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
401 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
402 }
403 }
404 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
405
406 return HAL_OK;
407 }
408
409 /**
410 * @brief USB_EPStartXfer setup and starts a transfer over an EP
411 * @param USBx Selected device
412 * @param ep pointer to endpoint structure
413 * @retval HAL status
414 */
USB_EPStartXfer(USB_TypeDef * USBx,USB_EPTypeDef * ep)415 HAL_StatusTypeDef USB_EPStartXfer(USB_TypeDef *USBx, USB_EPTypeDef *ep)
416 {
417 uint32_t len;
418 #if (USE_USB_DOUBLE_BUFFER == 1U)
419 uint16_t pmabuffer;
420 uint16_t wEPVal;
421 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
422
423 /* IN endpoint */
424 if (ep->is_in == 1U)
425 {
426 /*Multi packet transfer*/
427 if (ep->xfer_len > ep->maxpacket)
428 {
429 len = ep->maxpacket;
430 }
431 else
432 {
433 len = ep->xfer_len;
434 }
435
436 /* configure and validate Tx endpoint */
437 if (ep->doublebuffer == 0U)
438 {
439 USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, (uint16_t)len);
440 PCD_SET_EP_TX_CNT(USBx, ep->num, len);
441 }
442 #if (USE_USB_DOUBLE_BUFFER == 1U)
443 else
444 {
445 /* double buffer bulk management */
446 if (ep->type == EP_TYPE_BULK)
447 {
448 if (ep->xfer_len_db > ep->maxpacket)
449 {
450 /* enable double buffer */
451 PCD_SET_BULK_EP_DBUF(USBx, ep->num);
452
453 /* each Time to write in PMA xfer_len_db will */
454 ep->xfer_len_db -= len;
455
456 /* Fill the two first buffer in the Buffer0 & Buffer1 */
457 if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
458 {
459 /* Set the Double buffer counter for pmabuffer1 */
460 PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
461 pmabuffer = ep->pmaaddr1;
462
463 /* Write the user buffer to USB PMA */
464 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
465 ep->xfer_buff += len;
466
467 if (ep->xfer_len_db > ep->maxpacket)
468 {
469 ep->xfer_len_db -= len;
470 }
471 else
472 {
473 len = ep->xfer_len_db;
474 ep->xfer_len_db = 0U;
475 }
476
477 /* Set the Double buffer counter for pmabuffer0 */
478 PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
479 pmabuffer = ep->pmaaddr0;
480
481 /* Write the user buffer to USB PMA */
482 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
483 }
484 else
485 {
486 /* Set the Double buffer counter for pmabuffer0 */
487 PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
488 pmabuffer = ep->pmaaddr0;
489
490 /* Write the user buffer to USB PMA */
491 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
492 ep->xfer_buff += len;
493
494 if (ep->xfer_len_db > ep->maxpacket)
495 {
496 ep->xfer_len_db -= len;
497 }
498 else
499 {
500 len = ep->xfer_len_db;
501 ep->xfer_len_db = 0U;
502 }
503
504 /* Set the Double buffer counter for pmabuffer1 */
505 PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
506 pmabuffer = ep->pmaaddr1;
507
508 /* Write the user buffer to USB PMA */
509 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
510 }
511 }
512 /* auto Switch to single buffer mode when transfer <Mps no need to manage in double buffer */
513 else
514 {
515 len = ep->xfer_len_db;
516
517 /* disable double buffer mode for Bulk endpoint */
518 PCD_CLEAR_BULK_EP_DBUF(USBx, ep->num);
519
520 /* Set Tx count with nbre of byte to be transmitted */
521 PCD_SET_EP_TX_CNT(USBx, ep->num, len);
522 pmabuffer = ep->pmaaddr0;
523
524 /* Write the user buffer to USB PMA */
525 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
526 }
527 }
528 else /* manage isochronous double buffer IN mode */
529 {
530 /* each Time to write in PMA xfer_len_db will */
531 ep->xfer_len_db -= len;
532
533 /* Fill the data buffer */
534 if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
535 {
536 /* Set the Double buffer counter for pmabuffer1 */
537 PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
538 pmabuffer = ep->pmaaddr1;
539
540 /* Write the user buffer to USB PMA */
541 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
542 }
543 else
544 {
545 /* Set the Double buffer counter for pmabuffer0 */
546 PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
547 pmabuffer = ep->pmaaddr0;
548
549 /* Write the user buffer to USB PMA */
550 USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
551 }
552 }
553 }
554 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
555
556 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID);
557 }
558 else /* OUT endpoint */
559 {
560 if (ep->doublebuffer == 0U)
561 {
562 /* Multi packet transfer */
563 if (ep->xfer_len > ep->maxpacket)
564 {
565 len = ep->maxpacket;
566 ep->xfer_len -= len;
567 }
568 else
569 {
570 len = ep->xfer_len;
571 ep->xfer_len = 0U;
572 }
573 /* configure and validate Rx endpoint */
574 PCD_SET_EP_RX_CNT(USBx, ep->num, len);
575 }
576 #if (USE_USB_DOUBLE_BUFFER == 1U)
577 else
578 {
579 /* First Transfer Coming From HAL_PCD_EP_Receive & From ISR */
580 /* Set the Double buffer counter */
581 if (ep->type == EP_TYPE_BULK)
582 {
583 PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, ep->maxpacket);
584
585 /* Coming from ISR */
586 if (ep->xfer_count != 0U)
587 {
588 /* update last value to check if there is blocking state */
589 wEPVal = PCD_GET_ENDPOINT(USBx, ep->num);
590
591 /*Blocking State */
592 if ((((wEPVal & USB_EP_DTOG_RX) != 0U) && ((wEPVal & USB_EP_DTOG_TX) != 0U)) ||
593 (((wEPVal & USB_EP_DTOG_RX) == 0U) && ((wEPVal & USB_EP_DTOG_TX) == 0U)))
594 {
595 PCD_FREE_USER_BUFFER(USBx, ep->num, 0U);
596 }
597 }
598 }
599 /* iso out double */
600 else if (ep->type == EP_TYPE_ISOC)
601 {
602 /* Multi packet transfer */
603 if (ep->xfer_len > ep->maxpacket)
604 {
605 len = ep->maxpacket;
606 ep->xfer_len -= len;
607 }
608 else
609 {
610 len = ep->xfer_len;
611 ep->xfer_len = 0U;
612 }
613 PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, len);
614 }
615 else
616 {
617 return HAL_ERROR;
618 }
619 }
620 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
621
622 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
623 }
624
625 return HAL_OK;
626 }
627
628
629 /**
630 * @brief USB_EPSetStall set a stall condition over an EP
631 * @param USBx Selected device
632 * @param ep pointer to endpoint structure
633 * @retval HAL status
634 */
USB_EPSetStall(USB_TypeDef * USBx,USB_EPTypeDef * ep)635 HAL_StatusTypeDef USB_EPSetStall(USB_TypeDef *USBx, USB_EPTypeDef *ep)
636 {
637 if (ep->is_in != 0U)
638 {
639 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_STALL);
640 }
641 else
642 {
643 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_STALL);
644 }
645
646 return HAL_OK;
647 }
648
649 /**
650 * @brief USB_EPClearStall Clear a stall condition over an EP
651 * @param USBx Selected device
652 * @param ep pointer to endpoint structure
653 * @retval HAL status
654 */
USB_EPClearStall(USB_TypeDef * USBx,USB_EPTypeDef * ep)655 HAL_StatusTypeDef USB_EPClearStall(USB_TypeDef *USBx, USB_EPTypeDef *ep)
656 {
657 if (ep->doublebuffer == 0U)
658 {
659 if (ep->is_in != 0U)
660 {
661 PCD_CLEAR_TX_DTOG(USBx, ep->num);
662
663 if (ep->type != EP_TYPE_ISOC)
664 {
665 /* Configure NAK status for the Endpoint */
666 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
667 }
668 }
669 else
670 {
671 PCD_CLEAR_RX_DTOG(USBx, ep->num);
672
673 /* Configure VALID status for the Endpoint */
674 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
675 }
676 }
677
678 return HAL_OK;
679 }
680
681 /**
682 * @brief USB_EPStoptXfer Stop transfer on an EP
683 * @param USBx usb device instance
684 * @param ep pointer to endpoint structure
685 * @retval HAL status
686 */
USB_EPStopXfer(USB_TypeDef * USBx,USB_EPTypeDef * ep)687 HAL_StatusTypeDef USB_EPStopXfer(USB_TypeDef *USBx, USB_EPTypeDef *ep)
688 {
689 /* IN endpoint */
690 if (ep->is_in == 1U)
691 {
692 if (ep->doublebuffer == 0U)
693 {
694 if (ep->type != EP_TYPE_ISOC)
695 {
696 /* Configure NAK status for the Endpoint */
697 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
698 }
699 else
700 {
701 /* Configure TX Endpoint to disabled state */
702 PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
703 }
704 }
705 }
706 else /* OUT endpoint */
707 {
708 if (ep->doublebuffer == 0U)
709 {
710 if (ep->type != EP_TYPE_ISOC)
711 {
712 /* Configure NAK status for the Endpoint */
713 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
714 }
715 else
716 {
717 /* Configure RX Endpoint to disabled state */
718 PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
719 }
720 }
721 }
722
723 return HAL_OK;
724 }
725 #endif /* defined (HAL_PCD_MODULE_ENABLED) */
726
727 /**
728 * @brief USB_StopDevice Stop the usb device mode
729 * @param USBx Selected device
730 * @retval HAL status
731 */
USB_StopDevice(USB_TypeDef * USBx)732 HAL_StatusTypeDef USB_StopDevice(USB_TypeDef *USBx)
733 {
734 /* disable all interrupts and force USB reset */
735 USBx->CNTR = (uint16_t)USB_CNTR_FRES;
736
737 /* clear interrupt status register */
738 USBx->ISTR = 0U;
739
740 /* switch-off device */
741 USBx->CNTR = (uint16_t)(USB_CNTR_FRES | USB_CNTR_PDWN);
742
743 return HAL_OK;
744 }
745
746 /**
747 * @brief USB_SetDevAddress Stop the usb device mode
748 * @param USBx Selected device
749 * @param address new device address to be assigned
750 * This parameter can be a value from 0 to 255
751 * @retval HAL status
752 */
USB_SetDevAddress(USB_TypeDef * USBx,uint8_t address)753 HAL_StatusTypeDef USB_SetDevAddress(USB_TypeDef *USBx, uint8_t address)
754 {
755 if (address == 0U)
756 {
757 /* set device address and enable function */
758 USBx->DADDR = (uint16_t)USB_DADDR_EF;
759 }
760
761 return HAL_OK;
762 }
763
764 /**
765 * @brief USB_DevConnect Connect the USB device by enabling the pull-up/pull-down
766 * @param USBx Selected device
767 * @retval HAL status
768 */
USB_DevConnect(USB_TypeDef * USBx)769 HAL_StatusTypeDef USB_DevConnect(USB_TypeDef *USBx)
770 {
771 /* Prevent unused argument(s) compilation warning */
772 UNUSED(USBx);
773
774 /* NOTE : - This function is not required by USB Device FS peripheral, it is used
775 only by USB OTG FS peripheral.
776 - This function is added to ensure compatibility across platforms.
777 */
778
779 return HAL_OK;
780 }
781
782 /**
783 * @brief USB_DevDisconnect Disconnect the USB device by disabling the pull-up/pull-down
784 * @param USBx Selected device
785 * @retval HAL status
786 */
USB_DevDisconnect(USB_TypeDef * USBx)787 HAL_StatusTypeDef USB_DevDisconnect(USB_TypeDef *USBx)
788 {
789 /* Prevent unused argument(s) compilation warning */
790 UNUSED(USBx);
791
792 /* NOTE : - This function is not required by USB Device FS peripheral, it is used
793 only by USB OTG FS peripheral.
794 - This function is added to ensure compatibility across platforms.
795 */
796
797 return HAL_OK;
798 }
799
800 /**
801 * @brief USB_ReadInterrupts return the global USB interrupt status
802 * @param USBx Selected device
803 * @retval USB Global Interrupt status
804 */
USB_ReadInterrupts(USB_TypeDef const * USBx)805 uint32_t USB_ReadInterrupts(USB_TypeDef const *USBx)
806 {
807 uint32_t tmpreg;
808
809 tmpreg = USBx->ISTR;
810 return tmpreg;
811 }
812
813 /**
814 * @brief USB_ActivateRemoteWakeup : active remote wakeup signalling
815 * @param USBx Selected device
816 * @retval HAL status
817 */
USB_ActivateRemoteWakeup(USB_TypeDef * USBx)818 HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_TypeDef *USBx)
819 {
820 USBx->CNTR |= (uint16_t)USB_CNTR_RESUME;
821
822 return HAL_OK;
823 }
824
825 /**
826 * @brief USB_DeActivateRemoteWakeup de-active remote wakeup signalling
827 * @param USBx Selected device
828 * @retval HAL status
829 */
USB_DeActivateRemoteWakeup(USB_TypeDef * USBx)830 HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_TypeDef *USBx)
831 {
832 USBx->CNTR &= (uint16_t)(~USB_CNTR_RESUME);
833
834 return HAL_OK;
835 }
836
837 /**
838 * @brief Copy a buffer from user memory area to packet memory area (PMA)
839 * @param USBx USB peripheral instance register address.
840 * @param pbUsrBuf pointer to user memory area.
841 * @param wPMABufAddr address into PMA.
842 * @param wNBytes no. of bytes to be copied.
843 * @retval None
844 */
USB_WritePMA(USB_TypeDef const * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)845 void USB_WritePMA(USB_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
846 {
847 uint32_t n = ((uint32_t)wNBytes + 1U) >> 1;
848 uint32_t BaseAddr = (uint32_t)USBx;
849 uint32_t count;
850 uint16_t WrVal;
851 __IO uint16_t *pdwVal;
852 uint8_t *pBuf = pbUsrBuf;
853
854 pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
855
856 for (count = n; count != 0U; count--)
857 {
858 WrVal = pBuf[0];
859 WrVal |= (uint16_t)pBuf[1] << 8;
860 *pdwVal = (WrVal & 0xFFFFU);
861 pdwVal++;
862
863 #if PMA_ACCESS > 1U
864 pdwVal++;
865 #endif /* PMA_ACCESS */
866
867 pBuf++;
868 pBuf++;
869 }
870 }
871
872 /**
873 * @brief Copy data from packet memory area (PMA) to user memory buffer
874 * @param USBx USB peripheral instance register address.
875 * @param pbUsrBuf pointer to user memory area.
876 * @param wPMABufAddr address into PMA.
877 * @param wNBytes no. of bytes to be copied.
878 * @retval None
879 */
USB_ReadPMA(USB_TypeDef const * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)880 void USB_ReadPMA(USB_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
881 {
882 uint32_t n = (uint32_t)wNBytes >> 1;
883 uint32_t BaseAddr = (uint32_t)USBx;
884 uint32_t count;
885 uint32_t RdVal;
886 __IO uint16_t *pdwVal;
887 uint8_t *pBuf = pbUsrBuf;
888
889 pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
890
891 for (count = n; count != 0U; count--)
892 {
893 RdVal = *(__IO uint16_t *)pdwVal;
894 pdwVal++;
895 *pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
896 pBuf++;
897 *pBuf = (uint8_t)((RdVal >> 8) & 0xFFU);
898 pBuf++;
899
900 #if PMA_ACCESS > 1U
901 pdwVal++;
902 #endif /* PMA_ACCESS */
903 }
904
905 if ((wNBytes % 2U) != 0U)
906 {
907 RdVal = *pdwVal;
908 *pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
909 }
910 }
911
912
913 /**
914 * @}
915 */
916
917 /**
918 * @}
919 */
920 #endif /* defined (USB) */
921 #endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
922
923 /**
924 * @}
925 */
926