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