1 /**
2   ******************************************************************************
3   * @file    stm32c0xx_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) 2022 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 "stm32c0xx_hal.h"
43 
44 /** @addtogroup STM32C0xx_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 #if (USE_USB_DOUBLE_BUFFER == 1U)
59 static HAL_StatusTypeDef USB_HC_BULK_DB_StartXfer(USB_DRD_TypeDef *USBx,
60                                                   USB_DRD_HCTypeDef *hc,
61                                                   uint32_t ch_reg,
62                                                   uint32_t *len);
63 
64 static HAL_StatusTypeDef USB_HC_ISO_DB_StartXfer(USB_DRD_TypeDef *USBx,
65                                                  USB_DRD_HCTypeDef *hc,
66                                                  uint32_t len);
67 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
68 
69 /**
70   * @brief  Reset the USB Core (needed after USB clock settings change)
71   * @param  USBx Selected device
72   * @retval HAL status
73   */
USB_CoreReset(USB_DRD_TypeDef * USBx)74 static HAL_StatusTypeDef USB_CoreReset(USB_DRD_TypeDef *USBx)
75 {
76   /* Disable Host Mode */
77   USBx->CNTR &= ~USB_CNTR_HOST;
78 
79   /* Force Reset IP */
80   USBx->CNTR |= USB_CNTR_USBRST;
81 
82   return HAL_OK;
83 }
84 
85 /**
86   * @brief  Initializes the USB Core
87   * @param  USBx USB Instance
88   * @param  cfg pointer to a USB_CfgTypeDef structure that contains
89   *         the configuration information for the specified USBx peripheral.
90   * @retval HAL status
91   */
USB_CoreInit(USB_DRD_TypeDef * USBx,USB_DRD_CfgTypeDef cfg)92 HAL_StatusTypeDef USB_CoreInit(USB_DRD_TypeDef *USBx, USB_DRD_CfgTypeDef cfg)
93 {
94   HAL_StatusTypeDef ret;
95   UNUSED(cfg);
96 
97   if (USBx == NULL)
98   {
99     return HAL_ERROR;
100   }
101 
102   /* Reset after a PHY select */
103   ret = USB_CoreReset(USBx);
104 
105   /* Clear pending interrupts */
106   USBx->ISTR = 0U;
107 
108   return ret;
109 }
110 
111 /**
112   * @brief  USB_EnableGlobalInt
113   *         Enables the controller's Global Int in the AHB Config reg
114   * @param  USBx Selected device
115   * @retval HAL status
116   */
USB_EnableGlobalInt(USB_DRD_TypeDef * USBx)117 HAL_StatusTypeDef USB_EnableGlobalInt(USB_DRD_TypeDef *USBx)
118 {
119   uint32_t winterruptmask;
120 
121   /* Clear pending interrupts */
122   USBx->ISTR = 0U;
123 
124   /* Set winterruptmask variable */
125   winterruptmask = USB_CNTR_CTRM  | USB_CNTR_WKUPM |
126                    USB_CNTR_SUSPM | USB_CNTR_ERRM |
127                    USB_CNTR_SOFM | USB_CNTR_ESOFM |
128                    USB_CNTR_RESETM | USB_CNTR_L1REQM;
129 
130   /* Set interrupt mask */
131   USBx->CNTR = winterruptmask;
132 
133   return HAL_OK;
134 }
135 
136 /**
137   * @brief  USB_DisableGlobalInt
138   *         Disable the controller's Global Int in the AHB Config reg
139   * @param  USBx Selected device
140   * @retval HAL status
141   */
USB_DisableGlobalInt(USB_DRD_TypeDef * USBx)142 HAL_StatusTypeDef USB_DisableGlobalInt(USB_DRD_TypeDef *USBx)
143 {
144   uint32_t winterruptmask;
145 
146   /* Set winterruptmask variable */
147   winterruptmask = USB_CNTR_CTRM  | USB_CNTR_WKUPM |
148                    USB_CNTR_SUSPM | USB_CNTR_ERRM |
149                    USB_CNTR_SOFM | USB_CNTR_ESOFM |
150                    USB_CNTR_RESETM | USB_CNTR_L1REQM;
151 
152   /* Clear interrupt mask */
153   USBx->CNTR &= ~winterruptmask;
154 
155   return HAL_OK;
156 }
157 
158 /**
159   * @brief  USB_SetCurrentMode Set functional mode
160   * @param  USBx Selected device
161   * @param  mode current core mode
162   *          This parameter can be one of the these values:
163   *            @arg USB_DEVICE_MODE Peripheral mode
164   * @retval HAL status
165   */
USB_SetCurrentMode(USB_DRD_TypeDef * USBx,USB_DRD_ModeTypeDef mode)166 HAL_StatusTypeDef USB_SetCurrentMode(USB_DRD_TypeDef *USBx, USB_DRD_ModeTypeDef mode)
167 {
168   if (mode == USB_DEVICE_MODE)
169   {
170     USBx->CNTR &= ~USB_CNTR_HOST;
171   }
172   else if (mode == USB_HOST_MODE)
173   {
174     USBx->CNTR |= USB_CNTR_HOST;
175   }
176   else
177   {
178     return HAL_ERROR;
179   }
180 
181   return HAL_OK;
182 }
183 
184 /**
185   * @brief  USB_DevInit Initializes the USB controller registers
186   *         for device mode
187   * @param  USBx Selected device
188   * @param  cfg  pointer to a USB_DRD_CfgTypeDef structure that contains
189   *         the configuration information for the specified USBx peripheral.
190   * @retval HAL status
191   */
USB_DevInit(USB_DRD_TypeDef * USBx,USB_DRD_CfgTypeDef cfg)192 HAL_StatusTypeDef USB_DevInit(USB_DRD_TypeDef *USBx, USB_DRD_CfgTypeDef cfg)
193 {
194   HAL_StatusTypeDef ret;
195 
196   /* Prevent unused argument(s) compilation warning */
197   UNUSED(cfg);
198 
199   /* Force Reset */
200   USBx->CNTR = USB_CNTR_USBRST;
201 
202   /* Release Reset */
203   USBx->CNTR &= ~USB_CNTR_USBRST;
204 
205   /* Set the Device Mode */
206   ret = USB_SetCurrentMode(USBx, USB_DEVICE_MODE);
207 
208   /* Clear pending interrupts */
209   USBx->ISTR = 0U;
210 
211   return ret;
212 }
213 
214 /**
215   * @brief  USB_FlushTxFifo : Flush a Tx FIFO
216   * @param  USBx : Selected device
217   * @param  num : FIFO number
218   *         This parameter can be a value from 1 to 15
219             15 means Flush all Tx FIFOs
220   * @retval HAL status
221   */
USB_FlushTxFifo(USB_DRD_TypeDef const * USBx,uint32_t num)222 HAL_StatusTypeDef USB_FlushTxFifo(USB_DRD_TypeDef const *USBx, uint32_t num)
223 {
224   /* Prevent unused argument(s) compilation warning */
225   UNUSED(USBx);
226   UNUSED(num);
227 
228   /* NOTE : - This function is not required by USB Device FS peripheral, it is used
229               only by USB OTG FS peripheral.
230             - This function is added to ensure compatibility across platforms.
231    */
232 
233   return HAL_OK;
234 }
235 
236 /**
237   * @brief  USB_FlushRxFifo : Flush Rx FIFO
238   * @param  USBx : Selected device
239   * @retval HAL status
240   */
USB_FlushRxFifo(USB_DRD_TypeDef const * USBx)241 HAL_StatusTypeDef USB_FlushRxFifo(USB_DRD_TypeDef const *USBx)
242 {
243   /* Prevent unused argument(s) compilation warning */
244   UNUSED(USBx);
245 
246   /* NOTE : - This function is not required by USB Device FS peripheral, it is used
247               only by USB OTG FS peripheral.
248             - This function is added to ensure compatibility across platforms.
249    */
250 
251   return HAL_OK;
252 }
253 
254 
255 #if defined (HAL_PCD_MODULE_ENABLED)
256 /**
257   * @brief  Activate and configure an endpoint
258   * @param  USBx Selected device
259   * @param  ep pointer to endpoint structure
260   * @retval HAL status
261   */
USB_ActivateEndpoint(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)262 HAL_StatusTypeDef USB_ActivateEndpoint(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
263 {
264   HAL_StatusTypeDef ret = HAL_OK;
265   uint32_t wEpRegVal;
266 
267   wEpRegVal = PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_T_MASK;
268 
269   /* initialize Endpoint */
270   switch (ep->type)
271   {
272     case EP_TYPE_CTRL:
273       wEpRegVal |= USB_EP_CONTROL;
274       break;
275 
276     case EP_TYPE_BULK:
277       wEpRegVal |= USB_EP_BULK;
278       break;
279 
280     case EP_TYPE_INTR:
281       wEpRegVal |= USB_EP_INTERRUPT;
282       break;
283 
284     case EP_TYPE_ISOC:
285       wEpRegVal |= USB_EP_ISOCHRONOUS;
286       break;
287 
288     default:
289       ret = HAL_ERROR;
290       break;
291   }
292 
293   PCD_SET_ENDPOINT(USBx, ep->num, (wEpRegVal | USB_EP_VTRX | USB_EP_VTTX));
294 
295   PCD_SET_EP_ADDRESS(USBx, ep->num, ep->num);
296 
297   if (ep->doublebuffer == 0U)
298   {
299     if (ep->is_in != 0U)
300     {
301       /*Set the endpoint Transmit buffer address */
302       PCD_SET_EP_TX_ADDRESS(USBx, ep->num, ep->pmaadress);
303       PCD_CLEAR_TX_DTOG(USBx, ep->num);
304 
305       if (ep->type != EP_TYPE_ISOC)
306       {
307         /* Configure NAK status for the Endpoint */
308         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
309       }
310       else
311       {
312         /* Configure TX Endpoint to disabled state */
313         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
314       }
315     }
316     else
317     {
318       /* Set the endpoint Receive buffer address */
319       PCD_SET_EP_RX_ADDRESS(USBx, ep->num, ep->pmaadress);
320 
321       /* Set the endpoint Receive buffer counter */
322       PCD_SET_EP_RX_CNT(USBx, ep->num, ep->maxpacket);
323       PCD_CLEAR_RX_DTOG(USBx, ep->num);
324 
325       if (ep->num == 0U)
326       {
327         /* Configure VALID status for EP0 */
328         PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
329       }
330       else
331       {
332         /* Configure NAK status for OUT Endpoint */
333         PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
334       }
335     }
336   }
337 #if (USE_USB_DOUBLE_BUFFER == 1U)
338   /* Double Buffer */
339   else
340   {
341     if (ep->type == EP_TYPE_BULK)
342     {
343       /* Set bulk endpoint as double buffered */
344       PCD_SET_BULK_EP_DBUF(USBx, ep->num);
345     }
346     else
347     {
348       /* Set the ISOC endpoint in double buffer mode */
349       PCD_CLEAR_EP_KIND(USBx, ep->num);
350     }
351 
352     /* Set buffer address for double buffered mode */
353     PCD_SET_EP_DBUF_ADDR(USBx, ep->num, ep->pmaaddr0, ep->pmaaddr1);
354 
355     if (ep->is_in == 0U)
356     {
357       /* Clear the data toggle bits for the endpoint IN/OUT */
358       PCD_CLEAR_RX_DTOG(USBx, ep->num);
359       PCD_CLEAR_TX_DTOG(USBx, ep->num);
360 
361       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
362       PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
363     }
364     else
365     {
366       /* Clear the data toggle bits for the endpoint IN/OUT */
367       PCD_CLEAR_RX_DTOG(USBx, ep->num);
368       PCD_CLEAR_TX_DTOG(USBx, ep->num);
369 
370       if (ep->type != EP_TYPE_ISOC)
371       {
372         /* Configure NAK status for the Endpoint */
373         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
374       }
375       else
376       {
377         /* Configure TX Endpoint to disabled state */
378         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
379       }
380 
381       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
382     }
383   }
384 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
385 
386   return ret;
387 }
388 
389 /**
390   * @brief  De-activate and de-initialize an endpoint
391   * @param  USBx Selected device
392   * @param  ep pointer to endpoint structure
393   * @retval HAL status
394   */
USB_DeactivateEndpoint(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)395 HAL_StatusTypeDef USB_DeactivateEndpoint(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
396 {
397   if (ep->doublebuffer == 0U)
398   {
399     if (ep->is_in != 0U)
400     {
401       PCD_CLEAR_TX_DTOG(USBx, ep->num);
402 
403       /* Configure DISABLE status for the Endpoint */
404       PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
405     }
406 
407     else
408     {
409       PCD_CLEAR_RX_DTOG(USBx, ep->num);
410 
411       /* Configure DISABLE status for the Endpoint */
412       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
413     }
414   }
415 #if (USE_USB_DOUBLE_BUFFER == 1U)
416   /* Double Buffer */
417   else
418   {
419     if (ep->is_in == 0U)
420     {
421       /* Clear the data toggle bits for the endpoint IN/OUT*/
422       PCD_CLEAR_RX_DTOG(USBx, ep->num);
423       PCD_CLEAR_TX_DTOG(USBx, ep->num);
424 
425       /* Reset value of the data toggle bits for the endpoint out*/
426       PCD_TX_DTOG(USBx, ep->num);
427 
428       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
429       PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
430     }
431     else
432     {
433       /* Clear the data toggle bits for the endpoint IN/OUT*/
434       PCD_CLEAR_RX_DTOG(USBx, ep->num);
435       PCD_CLEAR_TX_DTOG(USBx, ep->num);
436       PCD_RX_DTOG(USBx, ep->num);
437 
438       /* Configure DISABLE status for the Endpoint*/
439       PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
440       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
441     }
442   }
443 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
444 
445   return HAL_OK;
446 }
447 
448 /**
449   * @brief  USB_EPStartXfer setup and starts a transfer over an EP
450   * @param  USBx Selected device
451   * @param  ep pointer to endpoint structure
452   * @retval HAL status
453   */
USB_EPStartXfer(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)454 HAL_StatusTypeDef USB_EPStartXfer(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
455 {
456   uint32_t len;
457 #if (USE_USB_DOUBLE_BUFFER == 1U)
458   uint16_t pmabuffer;
459   uint16_t wEPVal;
460 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
461 
462   /* IN endpoint */
463   if (ep->is_in == 1U)
464   {
465     /*Multi packet transfer*/
466     if (ep->xfer_len > ep->maxpacket)
467     {
468       len = ep->maxpacket;
469     }
470     else
471     {
472       len = ep->xfer_len;
473     }
474 
475     /* configure and validate Tx endpoint */
476     if (ep->doublebuffer == 0U)
477     {
478       USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, (uint16_t)len);
479       PCD_SET_EP_TX_CNT(USBx, ep->num, len);
480     }
481 #if (USE_USB_DOUBLE_BUFFER == 1U)
482     else
483     {
484       /* double buffer bulk management */
485       if (ep->type == EP_TYPE_BULK)
486       {
487         if (ep->xfer_len_db > ep->maxpacket)
488         {
489           /* enable double buffer */
490           PCD_SET_BULK_EP_DBUF(USBx, ep->num);
491 
492           /* each Time to write in PMA xfer_len_db will */
493           ep->xfer_len_db -= len;
494 
495           /* Fill the two first buffer in the Buffer0 & Buffer1 */
496           if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
497           {
498             /* Set the Double buffer counter for pmabuffer1 */
499             PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
500             pmabuffer = ep->pmaaddr1;
501 
502             /* Write the user buffer to USB PMA */
503             USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
504             ep->xfer_buff += len;
505 
506             if (ep->xfer_len_db > ep->maxpacket)
507             {
508               ep->xfer_len_db -= len;
509             }
510             else
511             {
512               len = ep->xfer_len_db;
513               ep->xfer_len_db = 0U;
514             }
515 
516             /* Set the Double buffer counter for pmabuffer0 */
517             PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
518             pmabuffer = ep->pmaaddr0;
519 
520             /* Write the user buffer to USB PMA */
521             USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
522           }
523           else
524           {
525             /* Set the Double buffer counter for pmabuffer0 */
526             PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
527             pmabuffer = ep->pmaaddr0;
528 
529             /* Write the user buffer to USB PMA */
530             USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
531             ep->xfer_buff += len;
532 
533             if (ep->xfer_len_db > ep->maxpacket)
534             {
535               ep->xfer_len_db -= len;
536             }
537             else
538             {
539               len = ep->xfer_len_db;
540               ep->xfer_len_db = 0U;
541             }
542 
543             /* Set the Double buffer counter for pmabuffer1 */
544             PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
545             pmabuffer = ep->pmaaddr1;
546 
547             /* Write the user buffer to USB PMA */
548             USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
549           }
550         }
551         /* auto Switch to single buffer mode when transfer <Mps no need to manage in double buffer */
552         else
553         {
554           len = ep->xfer_len_db;
555 
556           /* disable double buffer mode for Bulk endpoint */
557           PCD_CLEAR_BULK_EP_DBUF(USBx, ep->num);
558 
559           /* Set Tx count with nbre of byte to be transmitted */
560           PCD_SET_EP_TX_CNT(USBx, ep->num, len);
561           pmabuffer = ep->pmaaddr0;
562 
563           /* Write the user buffer to USB PMA */
564           USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
565         }
566       }
567       else /* manage isochronous double buffer IN mode */
568       {
569         /* each Time to write in PMA xfer_len_db will */
570         ep->xfer_len_db -= len;
571 
572         /* Fill the data buffer */
573         if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
574         {
575           /* Set the Double buffer counter for pmabuffer1 */
576           PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
577           pmabuffer = ep->pmaaddr1;
578 
579           /* Write the user buffer to USB PMA */
580           USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
581         }
582         else
583         {
584           /* Set the Double buffer counter for pmabuffer0 */
585           PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
586           pmabuffer = ep->pmaaddr0;
587 
588           /* Write the user buffer to USB PMA */
589           USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
590         }
591       }
592     }
593 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
594 
595     PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID);
596   }
597   else /* OUT endpoint */
598   {
599     if (ep->doublebuffer == 0U)
600     {
601       /* Multi packet transfer */
602       if (ep->xfer_len > ep->maxpacket)
603       {
604         len = ep->maxpacket;
605         ep->xfer_len -= len;
606       }
607       else
608       {
609         len = ep->xfer_len;
610         ep->xfer_len = 0U;
611       }
612       /* configure and validate Rx endpoint */
613       PCD_SET_EP_RX_CNT(USBx, ep->num, len);
614     }
615 #if (USE_USB_DOUBLE_BUFFER == 1U)
616     else
617     {
618       /* First Transfer Coming From HAL_PCD_EP_Receive & From ISR */
619       /* Set the Double buffer counter */
620       if (ep->type == EP_TYPE_BULK)
621       {
622         PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, ep->maxpacket);
623 
624         /* Coming from ISR */
625         if (ep->xfer_count != 0U)
626         {
627           /* update last value to check if there is blocking state */
628           wEPVal = (uint16_t)PCD_GET_ENDPOINT(USBx, ep->num);
629 
630           /*Blocking State */
631           if ((((wEPVal & USB_EP_DTOG_RX) != 0U) && ((wEPVal & USB_EP_DTOG_TX) != 0U)) ||
632               (((wEPVal & USB_EP_DTOG_RX) == 0U) && ((wEPVal & USB_EP_DTOG_TX) == 0U)))
633           {
634             PCD_FREE_USER_BUFFER(USBx, ep->num, 0U);
635           }
636         }
637       }
638       /* iso out double */
639       else if (ep->type == EP_TYPE_ISOC)
640       {
641         /* Multi packet transfer */
642         if (ep->xfer_len > ep->maxpacket)
643         {
644           len = ep->maxpacket;
645           ep->xfer_len -= len;
646         }
647         else
648         {
649           len = ep->xfer_len;
650           ep->xfer_len = 0U;
651         }
652         PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, len);
653       }
654       else
655       {
656         return HAL_ERROR;
657       }
658     }
659 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
660 
661     PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
662   }
663 
664   return HAL_OK;
665 }
666 
667 
668 /**
669   * @brief  USB_EPSetStall set a stall condition over an EP
670   * @param  USBx Selected device
671   * @param  ep pointer to endpoint structure
672   * @retval HAL status
673   */
USB_EPSetStall(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)674 HAL_StatusTypeDef USB_EPSetStall(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
675 {
676   if (ep->is_in != 0U)
677   {
678     PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_STALL);
679   }
680   else
681   {
682     PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_STALL);
683   }
684 
685   return HAL_OK;
686 }
687 
688 /**
689   * @brief  USB_EPClearStall Clear a stall condition over an EP
690   * @param  USBx Selected device
691   * @param  ep pointer to endpoint structure
692   * @retval HAL status
693   */
USB_EPClearStall(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)694 HAL_StatusTypeDef USB_EPClearStall(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
695 {
696   if (ep->doublebuffer == 0U)
697   {
698     if (ep->is_in != 0U)
699     {
700       PCD_CLEAR_TX_DTOG(USBx, ep->num);
701 
702       if (ep->type != EP_TYPE_ISOC)
703       {
704         /* Configure NAK status for the Endpoint */
705         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
706       }
707     }
708     else
709     {
710       PCD_CLEAR_RX_DTOG(USBx, ep->num);
711 
712       /* Configure VALID status for the Endpoint */
713       PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
714     }
715   }
716 
717   return HAL_OK;
718 }
719 
720 /**
721    * @brief  USB_EPStoptXfer  Stop transfer on an EP
722    * @param  USBx  usb device instance
723    * @param  ep pointer to endpoint structure
724    * @retval HAL status
725    */
USB_EPStopXfer(USB_DRD_TypeDef * USBx,USB_DRD_EPTypeDef * ep)726 HAL_StatusTypeDef USB_EPStopXfer(USB_DRD_TypeDef *USBx, USB_DRD_EPTypeDef *ep)
727 {
728   /* IN endpoint */
729   if (ep->is_in == 1U)
730   {
731     if (ep->doublebuffer == 0U)
732     {
733       if (ep->type != EP_TYPE_ISOC)
734       {
735         /* Configure NAK status for the Endpoint */
736         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
737       }
738       else
739       {
740         /* Configure TX Endpoint to disabled state */
741         PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
742       }
743     }
744   }
745   else /* OUT endpoint */
746   {
747     if (ep->doublebuffer == 0U)
748     {
749       if (ep->type != EP_TYPE_ISOC)
750       {
751         /* Configure NAK status for the Endpoint */
752         PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
753       }
754       else
755       {
756         /* Configure RX Endpoint to disabled state */
757         PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
758       }
759     }
760   }
761 
762   return HAL_OK;
763 }
764 #endif /* defined (HAL_PCD_MODULE_ENABLED) */
765 
766 /**
767   * @brief  USB_StopDevice Stop the usb device mode
768   * @param  USBx Selected device
769   * @retval HAL status
770   */
USB_StopDevice(USB_DRD_TypeDef * USBx)771 HAL_StatusTypeDef USB_StopDevice(USB_DRD_TypeDef *USBx)
772 {
773   /* disable all interrupts and force USB reset */
774   USBx->CNTR = USB_CNTR_USBRST;
775 
776   /* clear interrupt status register */
777   USBx->ISTR = 0U;
778 
779   /* switch-off device */
780   USBx->CNTR = (USB_CNTR_USBRST | USB_CNTR_PDWN);
781 
782   return HAL_OK;
783 }
784 
785 /**
786   * @brief  USB_SetDevAddress Stop the usb device mode
787   * @param  USBx Selected device
788   * @param  address new device address to be assigned
789   *          This parameter can be a value from 0 to 255
790   * @retval HAL status
791   */
USB_SetDevAddress(USB_DRD_TypeDef * USBx,uint8_t address)792 HAL_StatusTypeDef  USB_SetDevAddress(USB_DRD_TypeDef *USBx, uint8_t address)
793 {
794   if (address == 0U)
795   {
796     /* set device address and enable function */
797     USBx->DADDR = USB_DADDR_EF;
798   }
799 
800   return HAL_OK;
801 }
802 
803 /**
804   * @brief  USB_DevConnect Connect the USB device by enabling the pull-up/pull-down
805   * @param  USBx Selected device
806   * @retval HAL status
807   */
USB_DevConnect(USB_DRD_TypeDef * USBx)808 HAL_StatusTypeDef  USB_DevConnect(USB_DRD_TypeDef *USBx)
809 {
810   /* Enabling DP Pull-UP bit to Connect internal PU resistor on USB DP line */
811   USBx->BCDR |= USB_BCDR_DPPU;
812 
813   return HAL_OK;
814 }
815 
816 /**
817   * @brief  USB_DevDisconnect Disconnect the USB device by disabling the pull-up/pull-down
818   * @param  USBx Selected device
819   * @retval HAL status
820   */
USB_DevDisconnect(USB_DRD_TypeDef * USBx)821 HAL_StatusTypeDef  USB_DevDisconnect(USB_DRD_TypeDef *USBx)
822 {
823   /* Disable DP Pull-Up bit to disconnect the Internal PU resistor on USB DP line */
824   USBx->BCDR &= ~(USB_BCDR_DPPU);
825 
826   return HAL_OK;
827 }
828 
829 /**
830   * @brief  USB_ReadInterrupts return the global USB interrupt status
831   * @param  USBx Selected device
832   * @retval USB Global Interrupt status
833   */
USB_ReadInterrupts(USB_DRD_TypeDef const * USBx)834 uint32_t USB_ReadInterrupts(USB_DRD_TypeDef const *USBx)
835 {
836   uint32_t tmpreg;
837 
838   tmpreg = USBx->ISTR;
839   return tmpreg;
840 }
841 
842 /**
843   * @brief  USB_ActivateRemoteWakeup : active remote wakeup signalling
844   * @param  USBx Selected device
845   * @retval HAL status
846   */
USB_ActivateRemoteWakeup(USB_DRD_TypeDef * USBx)847 HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_DRD_TypeDef *USBx)
848 {
849   USBx->CNTR |= USB_CNTR_L2RES;
850 
851   return HAL_OK;
852 }
853 
854 /**
855   * @brief  USB_DeActivateRemoteWakeup de-active remote wakeup signalling
856   * @param  USBx Selected device
857   * @retval HAL status
858   */
USB_DeActivateRemoteWakeup(USB_DRD_TypeDef * USBx)859 HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_DRD_TypeDef *USBx)
860 {
861   USBx->CNTR &= ~USB_CNTR_L2RES;
862 
863   return HAL_OK;
864 }
865 
866 /**
867   * @brief Copy a buffer from user memory area to packet memory area (PMA)
868   * @param   USBx USB peripheral instance register address.
869   * @param   pbUsrBuf pointer to user memory area.
870   * @param   wPMABufAddr address into PMA.
871   * @param   wNBytes no. of bytes to be copied.
872   * @retval None
873   */
USB_WritePMA(USB_DRD_TypeDef const * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)874 void USB_WritePMA(USB_DRD_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
875 {
876   UNUSED(USBx);
877   uint32_t WrVal;
878   uint32_t count;
879   __IO uint32_t *pdwVal;
880   uint32_t NbWords = ((uint32_t)wNBytes + 3U) >> 2U;
881   /* Due to the PMA access 32bit only so the last non word data should be processed alone */
882   uint16_t remaining_bytes = wNBytes % 4U;
883   uint8_t *pBuf = pbUsrBuf;
884 
885   /* Check if there is a remaining byte */
886   if (remaining_bytes != 0U)
887   {
888     NbWords--;
889   }
890 
891   /* Get the PMA Buffer pointer */
892   pdwVal = (__IO uint32_t *)(USB_DRD_PMAADDR + (uint32_t)wPMABufAddr);
893 
894   /* Write the Calculated Word into the PMA related Buffer */
895   for (count = NbWords; count != 0U; count--)
896   {
897     *pdwVal = __UNALIGNED_UINT32_READ(pBuf);
898     pdwVal++;
899     /* Increment pBuf 4 Time as Word Increment */
900     pBuf++;
901     pBuf++;
902     pBuf++;
903     pBuf++;
904   }
905 
906   /* When Number of data is not word aligned, write the remaining Byte */
907   if (remaining_bytes != 0U)
908   {
909     WrVal = 0U;
910 
911     do
912     {
913       WrVal |= (uint32_t)(*(uint8_t *)pBuf) << (8U * count);
914       count++;
915       pBuf++;
916       remaining_bytes--;
917     } while (remaining_bytes != 0U);
918 
919     *pdwVal = WrVal;
920   }
921 }
922 
923 /**
924   * @brief Copy data from packet memory area (PMA) to user memory buffer
925   * @param   USBx USB peripheral instance register address.
926   * @param   pbUsrBuf pointer to user memory area.
927   * @param   wPMABufAddr address into PMA.
928   * @param   wNBytes no. of bytes to be copied.
929   * @retval None
930   */
USB_ReadPMA(USB_DRD_TypeDef const * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)931 void USB_ReadPMA(USB_DRD_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
932 {
933   UNUSED(USBx);
934   uint32_t count;
935   uint32_t RdVal;
936   __IO uint32_t *pdwVal;
937   uint32_t NbWords = ((uint32_t)wNBytes + 3U) >> 2U;
938   /*Due to the PMA access 32bit only so the last non word data should be processed alone */
939   uint16_t remaining_bytes = wNBytes % 4U;
940   uint8_t *pBuf = pbUsrBuf;
941 
942   /* Get the PMA Buffer pointer */
943   pdwVal = (__IO uint32_t *)(USB_DRD_PMAADDR + (uint32_t)wPMABufAddr);
944 
945   /* if nbre of byte is not word aligned decrement the nbre of word*/
946   if (remaining_bytes != 0U)
947   {
948     NbWords--;
949   }
950 
951   /*Read the Calculated Word From the PMA related Buffer*/
952   for (count = NbWords; count != 0U; count--)
953   {
954     __UNALIGNED_UINT32_WRITE(pBuf, *pdwVal);
955 
956     pdwVal++;
957     pBuf++;
958     pBuf++;
959     pBuf++;
960     pBuf++;
961   }
962 
963   /*When Number of data is not word aligned, read the remaining byte*/
964   if (remaining_bytes != 0U)
965   {
966     RdVal = *(__IO uint32_t *)pdwVal;
967 
968     do
969     {
970       *(uint8_t *)pBuf = (uint8_t)(RdVal >> (8U * (uint8_t)(count)));
971       count++;
972       pBuf++;
973       remaining_bytes--;
974     } while (remaining_bytes != 0U);
975   }
976 }
977 
978 
979 /*------------------------------------------------------------------------*/
980 /*                                HOST API                                */
981 /*------------------------------------------------------------------------*/
982 
983 /**
984   * @brief  USB_HostInit Initializes the USB DRD controller registers
985   *         for Host mode
986   * @param  USBx Selected device
987   * @param  cfg  pointer to a USB_DRD_CfgTypeDef structure that contains
988   *         the configuration information for the specified USBx peripheral.
989   * @retval HAL status
990   */
USB_HostInit(USB_DRD_TypeDef * USBx,USB_DRD_CfgTypeDef cfg)991 HAL_StatusTypeDef USB_HostInit(USB_DRD_TypeDef *USBx, USB_DRD_CfgTypeDef cfg)
992 {
993   UNUSED(cfg);
994 
995   /* Clear All Pending Interrupt */
996   USBx->ISTR = 0U;
997 
998   /* Disable all interrupts */
999   USBx->CNTR &= ~(USB_CNTR_CTRM | USB_CNTR_PMAOVRM | USB_CNTR_ERRM |
1000                   USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_DCON |
1001                   USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_L1REQM);
1002 
1003   /* Clear All Pending Interrupt */
1004   USBx->ISTR = 0U;
1005 
1006   /* Set the PullDown on the PHY */
1007   USBx->BCDR |= USB_BCDR_DPPD;
1008 
1009   /* Enable Global interrupt */
1010   USBx->CNTR |= (USB_CNTR_CTRM | USB_CNTR_PMAOVRM | USB_CNTR_ERRM |
1011                  USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_DCON |
1012                  USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_L1REQM);
1013 
1014   return HAL_OK;
1015 }
1016 
1017 
1018 /**
1019   * @brief  USB_DRD_ResetPort : Reset Host Port
1020   * @param  USBx Selected device
1021   * @retval HAL status
1022   * @note (1)The application must wait at least 10 ms
1023   *   before clearing the reset bit.
1024   */
USB_ResetPort(USB_DRD_TypeDef * USBx)1025 HAL_StatusTypeDef USB_ResetPort(USB_DRD_TypeDef *USBx)
1026 {
1027   /* Force USB Reset */
1028   USBx->CNTR |= USB_CNTR_USBRST;
1029   HAL_Delay(100);
1030   /* Release USB Reset */
1031   USBx->CNTR &= ~USB_CNTR_USBRST;
1032   HAL_Delay(30);
1033 
1034   return HAL_OK;
1035 }
1036 
1037 /**
1038   * @brief  Return Host Core speed
1039   * @param  USBx Selected device
1040   * @retval speed Host speed
1041   *          This parameter can be one of these values
1042   *            @arg USB_DRD_SPEED_FS Full speed mode
1043   *            @arg USB_DRD_SPEED_LS Low speed mode
1044   */
USB_GetHostSpeed(USB_DRD_TypeDef const * USBx)1045 uint32_t USB_GetHostSpeed(USB_DRD_TypeDef const *USBx)
1046 {
1047   if ((USBx->ISTR & USB_ISTR_LS_DCONN) != 0U)
1048   {
1049     return USB_DRD_SPEED_LS;
1050   }
1051   else
1052   {
1053     return USB_DRD_SPEED_FS;
1054   }
1055 }
1056 
1057 /**
1058   * @brief  Return Host Current Frame number
1059   * @param  USBx Selected device
1060   * @retval current frame number
1061   */
USB_GetCurrentFrame(USB_DRD_TypeDef const * USBx)1062 uint32_t USB_GetCurrentFrame(USB_DRD_TypeDef const *USBx)
1063 {
1064   return USBx->FNR & 0x7FFU;
1065 }
1066 
1067 /**
1068   * @brief  Set the channel Kind (Single/double buffer mode)
1069   * @param  USBx Selected device
1070   * @param  phy_ch_num Selected device
1071   * @param  db_state double state can be USB_DRD_XXX_DBUFF_ENBALE/USB_DRD_XXX_DBUFF_DISABLE
1072   * @retval HAL status
1073   */
USB_HC_DoubleBuffer(USB_DRD_TypeDef * USBx,uint8_t phy_ch_num,uint8_t db_state)1074 HAL_StatusTypeDef USB_HC_DoubleBuffer(USB_DRD_TypeDef *USBx,
1075                                       uint8_t phy_ch_num, uint8_t db_state)
1076 {
1077   uint32_t tmp;
1078 
1079   if ((db_state == USB_DRD_BULK_DBUFF_ENBALE) || (db_state == USB_DRD_ISOC_DBUFF_DISABLE))
1080   {
1081     tmp = (USB_DRD_GET_CHEP(USBx, phy_ch_num) | USB_CH_KIND) & USB_CHEP_DB_MSK;
1082   }
1083   else
1084   {
1085     tmp = USB_DRD_GET_CHEP(USBx, phy_ch_num) & (~USB_CH_KIND) & USB_CHEP_DB_MSK;
1086   }
1087 
1088   /* Set the device speed in case using HUB FS with device LS */
1089   USB_DRD_SET_CHEP(USBx, phy_ch_num, tmp);
1090 
1091   return HAL_OK;
1092 }
1093 
1094 /**
1095   * @brief  Initialize a host channel
1096   * @param  USBx Selected device
1097   * @param  phy_ch_num Channel number
1098   *         This parameter can be a value from 1 to 15
1099   * @param  epnum Endpoint number
1100   *          This parameter can be a value from 1 to 15
1101   * @param  dev_address Current device address
1102   *          This parameter can be a value from 0 to 255
1103   * @param  speed Current device speed
1104   *          This parameter can be one of these values:
1105   *          @arg USB_DRD_SPEED_FULL Full speed mode
1106   *          @arg USB_DRD_SPEED_LOW  Low speed mode
1107   * @param  ep_type Endpoint Type
1108   *          This parameter can be one of these values:
1109   *            @arg EP_TYPE_CTRL Control type
1110   *            @arg EP_TYPE_ISOC Isochronous type
1111   *            @arg EP_TYPE_BULK Bulk type
1112   *            @arg EP_TYPE_INTR Interrupt type
1113   * @param  mps Max Packet Size
1114   *          This parameter can be a value from 0 to 32K
1115   * @retval HAL state
1116   */
USB_HC_Init(USB_DRD_TypeDef * USBx,uint8_t phy_ch_num,uint8_t epnum,uint8_t dev_address,uint8_t speed,uint8_t ep_type,uint16_t mps)1117 HAL_StatusTypeDef USB_HC_Init(USB_DRD_TypeDef *USBx, uint8_t phy_ch_num,
1118                               uint8_t epnum, uint8_t dev_address, uint8_t speed,
1119                               uint8_t ep_type, uint16_t mps)
1120 {
1121   HAL_StatusTypeDef ret = HAL_OK;
1122   uint32_t wChRegVal;
1123   uint32_t HostCoreSpeed;
1124 
1125   UNUSED(mps);
1126 
1127   wChRegVal = USB_DRD_GET_CHEP(USBx, phy_ch_num) & USB_CH_T_MASK;
1128 
1129   /* Initialize host Channel */
1130   switch (ep_type)
1131   {
1132     case EP_TYPE_CTRL:
1133       wChRegVal |= USB_EP_CONTROL;
1134       break;
1135 
1136     case EP_TYPE_BULK:
1137       wChRegVal |= USB_EP_BULK;
1138       break;
1139 
1140     case EP_TYPE_INTR:
1141       wChRegVal |= USB_EP_INTERRUPT;
1142       break;
1143 
1144     case EP_TYPE_ISOC:
1145       wChRegVal |= USB_EP_ISOCHRONOUS;
1146       break;
1147 
1148     default:
1149       ret = HAL_ERROR;
1150       break;
1151   }
1152 
1153   /* Clear device address, Endpoint number and Low Speed Endpoint fields */
1154   wChRegVal &= ~(USB_CHEP_DEVADDR |
1155                  USB_CHEP_ADDR |
1156                  USB_CHEP_LSEP |
1157                  USB_CHEP_NAK |
1158                  USB_CHEP_KIND |
1159                  USB_CHEP_ERRTX |
1160                  USB_CHEP_ERRRX |
1161                  (0xFU << 27));
1162 
1163   /* Set device address and Endpoint number associated to the channel */
1164   wChRegVal |= (((uint32_t)dev_address << USB_CHEP_DEVADDR_Pos) |
1165                 ((uint32_t)epnum & 0x0FU));
1166 
1167   /* Get Host core Speed */
1168   HostCoreSpeed = USB_GetHostSpeed(USBx);
1169 
1170   /* Set the device speed in case using HUB FS with device LS */
1171   if ((speed == USB_DRD_SPEED_LS) && (HostCoreSpeed == USB_DRD_SPEED_FS))
1172   {
1173     wChRegVal |= USB_CHEP_LSEP;
1174   }
1175 
1176   /* Update the channel register value */
1177   USB_DRD_SET_CHEP(USBx, phy_ch_num, (wChRegVal | USB_CH_VTRX | USB_CH_VTTX));
1178 
1179   return ret;
1180 }
1181 
1182 /**
1183   * @brief  Start a transfer over a host channel
1184   * @param  USBx Selected device
1185   * @param  hc pointer to host channel structure
1186   * @retval HAL state
1187   */
USB_HC_StartXfer(USB_DRD_TypeDef * USBx,USB_DRD_HCTypeDef * hc)1188 HAL_StatusTypeDef USB_HC_StartXfer(USB_DRD_TypeDef *USBx, USB_DRD_HCTypeDef *hc)
1189 {
1190   uint32_t len;
1191   uint32_t phy_ch_num = (uint32_t)hc->phy_ch_num;
1192 #if (USE_USB_DOUBLE_BUFFER == 1U)
1193   uint32_t ch_reg = USB_DRD_GET_CHEP(USBx, phy_ch_num);
1194 #endif /* USE_USB_DOUBLE_BUFFER */
1195 
1196   if (hc->ch_dir == CH_IN_DIR)  /* In Channel */
1197   {
1198     /* Multi packet transfer */
1199     if (hc->xfer_len > hc->max_packet)
1200     {
1201       len = hc->max_packet;
1202     }
1203     else
1204     {
1205       len = hc->xfer_len;
1206     }
1207 
1208     if (hc->doublebuffer == 0U)
1209     {
1210       if ((hc->ep_type == EP_TYPE_BULK) ||
1211           (hc->ep_type == EP_TYPE_INTR))
1212       {
1213         USB_DRD_CLEAR_RX_DTOG(USBx, phy_ch_num);
1214 
1215         /* Set Data PID */
1216         if (hc->data_pid == HC_PID_DATA1)
1217         {
1218           USB_DRD_RX_DTOG(USBx, phy_ch_num);
1219         }
1220       }
1221 
1222       /* Set RX buffer count */
1223       USB_DRD_SET_CHEP_RX_CNT(USBx, phy_ch_num, len);
1224     }
1225 #if (USE_USB_DOUBLE_BUFFER == 1U)
1226     else if (hc->ep_type == EP_TYPE_BULK)
1227     {
1228       /* Double buffer activated */
1229       if ((hc->xfer_len > hc->max_packet))
1230       {
1231         (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_ENBALE);
1232 
1233         /* Set the Double buffer counter */
1234         USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 0U, len);
1235         USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 0U, len);
1236       }
1237       else  /* Switch to single buffer mode */
1238       {
1239         (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_DISABLE);
1240 
1241         /* Set RX buffer count */
1242         USB_DRD_SET_CHEP_RX_CNT(USBx, phy_ch_num, len);
1243       }
1244     }
1245     else  /* Isochronous */
1246     {
1247       /* Set the Double buffer counter */
1248       USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 0U, len);
1249       USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 0U, len);
1250     }
1251 #endif /* USE_USB_DOUBLE_BUFFER */
1252 
1253     /* Enable host channel */
1254     USB_DRD_SET_CHEP_RX_STATUS(USBx, phy_ch_num, USB_CH_RX_VALID);
1255   }
1256   else   /* Out Channel */
1257   {
1258     /* Multi packet transfer */
1259     if (hc->xfer_len > hc->max_packet)
1260     {
1261       len = hc->max_packet;
1262     }
1263     else
1264     {
1265       len = hc->xfer_len;
1266     }
1267 
1268     /* Configure and validate Tx endpoint */
1269     if (hc->doublebuffer == 0U)
1270     {
1271       USB_WritePMA(USBx, hc->xfer_buff, hc->pmaadress, (uint16_t)len);
1272       USB_DRD_SET_CHEP_TX_CNT(USBx, phy_ch_num, (uint16_t)len);
1273 
1274       /* SET PID SETUP  */
1275       if ((hc->data_pid) == HC_PID_SETUP)
1276       {
1277         USB_DRD_CHEP_TX_SETUP(USBx,  phy_ch_num);
1278       }
1279 
1280       if ((hc->ep_type == EP_TYPE_BULK) ||
1281           (hc->ep_type == EP_TYPE_INTR))
1282       {
1283         USB_DRD_CLEAR_TX_DTOG(USBx, phy_ch_num);
1284 
1285         /* Set Data PID */
1286         if (hc->data_pid == HC_PID_DATA1)
1287         {
1288           USB_DRD_TX_DTOG(USBx, phy_ch_num);
1289         }
1290       }
1291     }
1292 #if (USE_USB_DOUBLE_BUFFER == 1U)
1293     else if (hc->ep_type == EP_TYPE_BULK)
1294     {
1295       (void)USB_HC_BULK_DB_StartXfer(USBx, hc, ch_reg, &len);
1296     }
1297     else
1298     {
1299       (void)USB_HC_ISO_DB_StartXfer(USBx, hc, len);
1300     }
1301 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1302 
1303     /* Enable host channel */
1304     USB_DRD_SET_CHEP_TX_STATUS(USBx, hc->phy_ch_num, USB_CH_TX_VALID);
1305   }
1306 
1307   return HAL_OK;
1308 }
1309 
1310 #if (USE_USB_DOUBLE_BUFFER == 1U)
1311 /**
1312   * @brief  Start Transfer of Channel isochronous out double buffer
1313   * @param  USBx Selected device
1314   * @param  hc_num Host Channel number
1315   *         This parameter can be a value from 1 to 15
1316   * @param  len Transfer Length
1317   * @retval HAL state
1318   */
USB_HC_ISO_DB_StartXfer(USB_DRD_TypeDef * USBx,USB_DRD_HCTypeDef * hc,uint32_t len)1319 static HAL_StatusTypeDef USB_HC_ISO_DB_StartXfer(USB_DRD_TypeDef *USBx,
1320                                                  USB_DRD_HCTypeDef *hc,
1321                                                  uint32_t len)
1322 {
1323   uint32_t phy_ch_num = (uint32_t)hc->phy_ch_num;
1324 
1325   /* check the DTOG_TX to determine in which buffer we should write */
1326   if ((USB_DRD_GET_CHEP(USBx, phy_ch_num) & USB_CH_DTOG_TX) != 0U)
1327   {
1328     USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 1U, len);
1329     USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)len);
1330   }
1331   else
1332   {
1333     /* DTOGTX=0 */
1334     /* Set the Double buffer counter for pmabuffer0 */
1335     USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 1U, len);
1336     USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr1, (uint16_t)len);
1337   }
1338 
1339   return HAL_OK;
1340 }
1341 
1342 /**
1343   * @brief  Start Transfer of Channel bulk out double buffer
1344   * @param  USBx Selected device
1345   * @param  hc_num Host Channel number
1346   *         This parameter can be a value from 1 to 15
1347   * @param  ch_reg snapshot of the CHEPR register
1348   * @param  len Transfer Length
1349   * @retval HAL state
1350   */
USB_HC_BULK_DB_StartXfer(USB_DRD_TypeDef * USBx,USB_DRD_HCTypeDef * hc,uint32_t ch_reg,uint32_t * len)1351 static HAL_StatusTypeDef USB_HC_BULK_DB_StartXfer(USB_DRD_TypeDef *USBx,
1352                                                   USB_DRD_HCTypeDef *hc,
1353                                                   uint32_t ch_reg,
1354                                                   uint32_t *len)
1355 {
1356   uint32_t phy_ch_num = (uint32_t)hc->phy_ch_num;
1357 
1358   /* -Double Buffer Mangement- */
1359   if (hc->xfer_len_db > hc->max_packet)
1360   {
1361     /* enable double buffer mode */
1362     (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_ENBALE);
1363     *len = hc->max_packet;
1364     hc->xfer_len_db -= *len;
1365 
1366     /* Prepare two buffer before enabling host */
1367     if ((ch_reg & USB_CH_DTOG_TX) == 0U)
1368     {
1369       /* Write Buffer0 */
1370       USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
1371       USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)*len);
1372     }
1373     else
1374     {
1375       /* Write Buffer1 */
1376       USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
1377       USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr1, (uint16_t)*len);
1378     }
1379 
1380     hc->xfer_buff += *len;
1381 
1382     /* Multi packet transfer */
1383     if (hc->xfer_len_db > hc->max_packet)
1384     {
1385       hc->xfer_len_db -= *len;
1386     }
1387     else
1388     {
1389       *len = hc->xfer_len_db;
1390       hc->xfer_len_db = 0U;
1391     }
1392 
1393     if ((ch_reg & USB_CH_DTOG_TX) == 0U)
1394     {
1395       /* Write Buffer1 */
1396       USB_DRD_SET_CHEP_DBUF1_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
1397       USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr1, (uint16_t)*len);
1398     }
1399     else
1400     {
1401       /* Write Buffer0 */
1402       USB_DRD_SET_CHEP_DBUF0_CNT(USBx, phy_ch_num, 1U, (uint16_t)*len);
1403       USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)*len);
1404     }
1405   }
1406   else
1407   {
1408     /* Disable bulk double buffer mode */
1409     (void)USB_HC_DoubleBuffer(USBx, (uint8_t)phy_ch_num, USB_DRD_BULK_DBUFF_DISABLE);
1410     USB_WritePMA(USBx, hc->xfer_buff, hc->pmaaddr0, (uint16_t)*len);
1411     USB_DRD_SET_CHEP_TX_CNT(USBx, phy_ch_num, (uint16_t)*len);
1412   }
1413 
1414   return HAL_OK;
1415 }
1416 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1417 
1418 
1419 /**
1420   * @brief  Halt a host channel in
1421   * @param  USBx Selected device
1422   * @param  hc_num Host Channel number
1423   *         This parameter can be a value from 1 to 15
1424   * @retval HAL state
1425   */
USB_HC_IN_Halt(USB_DRD_TypeDef * USBx,uint8_t phy_ch)1426 HAL_StatusTypeDef USB_HC_IN_Halt(USB_DRD_TypeDef *USBx, uint8_t phy_ch)
1427 {
1428   /* Set disable to Channel */
1429   USB_DRD_SET_CHEP_RX_STATUS(USBx, phy_ch, USB_CH_RX_DIS);
1430 
1431   return HAL_OK;
1432 }
1433 
1434 
1435 /**
1436   * @brief  Halt a host channel out
1437   * @param  USBx Selected device
1438   * @param  hc_num Host Channel number
1439   *         This parameter can be a value from 1 to 15
1440   * @retval HAL state
1441   */
USB_HC_OUT_Halt(USB_DRD_TypeDef * USBx,uint8_t phy_ch)1442 HAL_StatusTypeDef USB_HC_OUT_Halt(USB_DRD_TypeDef *USBx, uint8_t phy_ch)
1443 {
1444   /* Set disable to Channel */
1445   USB_DRD_SET_CHEP_TX_STATUS(USBx, phy_ch, USB_CH_TX_DIS);
1446 
1447   return HAL_OK;
1448 }
1449 
1450 /**
1451   * @brief  Stop Host Core
1452   * @param  USBx Selected device
1453   * @retval HAL state
1454   */
USB_StopHost(USB_DRD_TypeDef * USBx)1455 HAL_StatusTypeDef USB_StopHost(USB_DRD_TypeDef *USBx)
1456 {
1457   USBx->ISTR &= ~(USB_ISTR_DIR | USB_ISTR_L1REQ |
1458                   USB_ISTR_ESOF | USB_ISTR_SOF |
1459                   USB_ISTR_RESET | USB_ISTR_DCON |
1460                   USB_ISTR_SUSP | USB_ISTR_WKUP |
1461                   USB_ISTR_ERR | USB_ISTR_PMAOVR |
1462                   USB_ISTR_CTR);
1463 
1464   /* Set PowerDown */
1465   USBx->CNTR |= USB_CNTR_PDWN;
1466 
1467   /* Force a Reset */
1468   USBx->CNTR |= USB_CNTR_USBRST;
1469 
1470   return HAL_OK;
1471 }
1472 
1473 /**
1474   * @}
1475   */
1476 
1477 /**
1478   * @}
1479   */
1480 #endif /* defined (USB_DRD_FS) */
1481 #endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
1482 
1483 /**
1484   * @}
1485   */
1486