1 /**
2   ******************************************************************************
3   * @file    stm32wbxx_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 "stm32wbxx_hal.h"
43 
44 /** @addtogroup STM32WBxx_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       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   /* Enabling DP Pull-UP bit to Connect internal PU resistor on USB DP line */
772   USBx->BCDR |= (uint16_t)USB_BCDR_DPPU;
773 
774   return HAL_OK;
775 }
776 
777 /**
778   * @brief  USB_DevDisconnect Disconnect the USB device by disabling the pull-up/pull-down
779   * @param  USBx Selected device
780   * @retval HAL status
781   */
USB_DevDisconnect(USB_TypeDef * USBx)782 HAL_StatusTypeDef  USB_DevDisconnect(USB_TypeDef *USBx)
783 {
784   /* Disable DP Pull-Up bit to disconnect the Internal PU resistor on USB DP line */
785   USBx->BCDR &= (uint16_t)(~(USB_BCDR_DPPU));
786 
787   return HAL_OK;
788 }
789 
790 /**
791   * @brief  USB_ReadInterrupts return the global USB interrupt status
792   * @param  USBx Selected device
793   * @retval USB Global Interrupt status
794   */
USB_ReadInterrupts(USB_TypeDef const * USBx)795 uint32_t USB_ReadInterrupts(USB_TypeDef const *USBx)
796 {
797   uint32_t tmpreg;
798 
799   tmpreg = USBx->ISTR;
800   return tmpreg;
801 }
802 
803 /**
804   * @brief  USB_ActivateRemoteWakeup : active remote wakeup signalling
805   * @param  USBx Selected device
806   * @retval HAL status
807   */
USB_ActivateRemoteWakeup(USB_TypeDef * USBx)808 HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_TypeDef *USBx)
809 {
810   USBx->CNTR |= (uint16_t)USB_CNTR_RESUME;
811 
812   return HAL_OK;
813 }
814 
815 /**
816   * @brief  USB_DeActivateRemoteWakeup de-active remote wakeup signalling
817   * @param  USBx Selected device
818   * @retval HAL status
819   */
USB_DeActivateRemoteWakeup(USB_TypeDef * USBx)820 HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_TypeDef *USBx)
821 {
822   USBx->CNTR &= (uint16_t)(~USB_CNTR_RESUME);
823 
824   return HAL_OK;
825 }
826 
827 /**
828   * @brief Copy a buffer from user memory area to packet memory area (PMA)
829   * @param   USBx USB peripheral instance register address.
830   * @param   pbUsrBuf pointer to user memory area.
831   * @param   wPMABufAddr address into PMA.
832   * @param   wNBytes no. of bytes to be copied.
833   * @retval None
834   */
USB_WritePMA(USB_TypeDef const * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)835 void USB_WritePMA(USB_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
836 {
837   uint32_t n = ((uint32_t)wNBytes + 1U) >> 1;
838   uint32_t BaseAddr = (uint32_t)USBx;
839   uint32_t count;
840   uint16_t WrVal;
841   __IO uint16_t *pdwVal;
842   uint8_t *pBuf = pbUsrBuf;
843 
844   pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
845 
846   for (count = n; count != 0U; count--)
847   {
848     WrVal = pBuf[0];
849     WrVal |= (uint16_t)pBuf[1] << 8;
850     *pdwVal = (WrVal & 0xFFFFU);
851     pdwVal++;
852 
853 #if PMA_ACCESS > 1U
854     pdwVal++;
855 #endif /* PMA_ACCESS */
856 
857     pBuf++;
858     pBuf++;
859   }
860 }
861 
862 /**
863   * @brief Copy data from packet memory area (PMA) to user memory buffer
864   * @param   USBx USB peripheral instance register address.
865   * @param   pbUsrBuf pointer to user memory area.
866   * @param   wPMABufAddr address into PMA.
867   * @param   wNBytes no. of bytes to be copied.
868   * @retval None
869   */
USB_ReadPMA(USB_TypeDef const * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)870 void USB_ReadPMA(USB_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
871 {
872   uint32_t n = (uint32_t)wNBytes >> 1;
873   uint32_t BaseAddr = (uint32_t)USBx;
874   uint32_t count;
875   uint32_t RdVal;
876   __IO uint16_t *pdwVal;
877   uint8_t *pBuf = pbUsrBuf;
878 
879   pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
880 
881   for (count = n; count != 0U; count--)
882   {
883     RdVal = *(__IO uint16_t *)pdwVal;
884     pdwVal++;
885     *pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
886     pBuf++;
887     *pBuf = (uint8_t)((RdVal >> 8) & 0xFFU);
888     pBuf++;
889 
890 #if PMA_ACCESS > 1U
891     pdwVal++;
892 #endif /* PMA_ACCESS */
893   }
894 
895   if ((wNBytes % 2U) != 0U)
896   {
897     RdVal = *pdwVal;
898     *pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
899   }
900 }
901 
902 
903 /**
904   * @}
905   */
906 
907 /**
908   * @}
909   */
910 #endif /* defined (USB) */
911 #endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
912 
913 /**
914   * @}
915   */
916