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