1 /*
2  * Copyright (c) 2006-2025, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2024-07-09     QT-one       first version
9  */
10 
11 #include "usb_port.h"
12 
13 /* Global variables ----------------------------------------------------------------------------------------*/
14 USBDCore_TypeDef *gUSBCore;
15 USBD_Driver_TypeDef gUSBDriver;
16 u32 gIsLowPowerAllowed = TRUE;
17 
18 #if (LIBCFG_CKCU_USB_PLL)
19 /*********************************************************************************************************//**
20  * @brief  Configure USB PLL
21  * @retval None
22  ************************************************************************************************************/
USBPLL_Configuration(void)23 static void USBPLL_Configuration(void)
24 {
25     {
26         /* USB PLL configuration                                                                                */
27 
28         /* !!! NOTICE !!!
29            Notice that the local variable (structure) did not have an initial value.
30            Please confirm that there are no missing members in the parameter settings below in this function.
31         */
32         CKCU_PLLInitTypeDef PLLInit;
33 
34         PLLInit.ClockSource = CKCU_PLLSRC_HSE;  // CKCU_PLLSRC_HSE or CKCU_PLLSRC_HSI
35 #if (LIBCFG_CKCU_USB_PLL_96M)
36         PLLInit.CFG = CKCU_USBPLL_8M_96M;
37 #else
38         PLLInit.CFG = CKCU_USBPLL_8M_48M;
39 #endif
40         PLLInit.BYPASSCmd = DISABLE;
41         CKCU_USBPLLInit(&PLLInit);
42     }
43 
44     CKCU_USBPLLCmd(ENABLE);
45 
46     while (CKCU_GetClockReadyStatus(CKCU_FLAG_USBPLLRDY) == RESET);
47     CKCU_USBClockConfig(CKCU_CKUSBPLL);
48 }
49 #endif
50 
51 #if (LIBCFG_PWRCU_VREG)
52 /*********************************************************************************************************//**
53  * @brief  Configure USB Voltage
54  * @retval None
55  ************************************************************************************************************/
USBVRG_Configuration(void)56 static void USBVRG_Configuration(void)
57 {
58     CKCU_PeripClockConfig_TypeDef CKCUClock = {{ 0 }};
59     CKCUClock.Bit.BKP = 1;
60     CKCU_PeripClockConfig(CKCUClock, ENABLE);
61 
62     PWRCU_SetVREG(PWRCU_VREG_3V3);
63 
64     /* !!! NOTICE !!!
65        USB LDO should be enabled (PWRCU_VREG_ENABLE) if the MCU VDD > 3.6 V.
66     */
67     PWRCU_VREGConfig(PWRCU_VREG_BYPASS);
68 }
69 #endif
70 
71 #define REMOTE_WAKEUP      (0)
72 /*********************************************************************************************************//**
73   * @brief  Suspend call back function which enter DeepSleep1
74   * @param  uPara: Parameter for Call back function
75   * @retval None
76   ***********************************************************************************************************/
Suspend(u32 uPara)77 static void Suspend(u32 uPara)
78 {
79 #if (REMOTE_WAKEUP == 1)
80     u32 IsRemoteWakeupAllowed;
81 #endif
82 
83     if (gIsLowPowerAllowed)
84     {
85 
86 #if (REMOTE_WAKEUP == 1)
87         /* Disable EXTI interrupt to prevent interrupt occurred after wakeup                                    */
88         EXTI_IntConfig(KEY1_BUTTON_EXTI_CHANNEL, DISABLE);
89         IsRemoteWakeupAllowed = USBDCore_GetRemoteWakeUpFeature(&gUSBCore);
90 
91         if (IsRemoteWakeupAllowed == TRUE)
92         {
93             /* Enable EXTI wake event and clear wakeup flag                                                       */
94             EXTI_WakeupEventConfig(KEY1_BUTTON_EXTI_CHANNEL, EXTI_WAKEUP_LOW_LEVEL, ENABLE);
95             EXTI_ClearWakeupFlag(KEY1_BUTTON_EXTI_CHANNEL);
96         }
97 #endif
98 
99         __DBG_USBPrintf("%06ld >DEEPSLEEP\r\n", ++__DBG_USBCount);
100 
101         // Add your procedure here which disable related IO to reduce power consumption
102         // ..................
103         //
104 
105         if ((gUSBCore->Info.CurrentStatus == USER_USB_STATE_SUSPENDED) && ((HT_USB->CSR & 0xC0) == 0x40))   // D+ = 1, D- = 0
106         {
107             /* For Bus powered device, you must enter DeepSleep1 when device has been suspended. For self-powered */
108             /* device, you may decide to enter DeepSleep1 or not depended on your application.                    */
109 
110             /* For the convenient during debugging and evaluation stage, the USBDCore_LowPower() is map to a null */
111             /* function by default. In the real product, you must map this function to the low power function of  */
112             /* firmware library by setting USBDCORE_ENABLE_LOW_POWER as 1 (in the ht32fxxxx_usbdconf.h file).     */
113             USBDCore_LowPower();
114         }
115 
116         // Add your procedure here which recovery related IO for application
117         // ..................
118         //
119 
120         __DBG_USBPrintf("%06ld <DEEPSLEEP\r\n", ++__DBG_USBCount);
121 
122 #if (REMOTE_WAKEUP == 1)
123         if (EXTI_GetWakeupFlagStatus(KEY1_BUTTON_EXTI_CHANNEL) == SET)
124         {
125             __DBG_USBPrintf("%06ld WAKEUP\r\n", ++__DBG_USBCount);
126             if (IsRemoteWakeupAllowed == TRUE && USBDCore_IsSuspend(&gUSBCore) == TRUE)
127             {
128                 USBDCore_TriggerRemoteWakeup();
129             }
130         }
131 
132         if (IsRemoteWakeupAllowed == TRUE)
133         {
134             /* Disable EXTI wake event and clear wakeup flag                                                      */
135             EXTI_WakeupEventConfig(KEY1_BUTTON_EXTI_CHANNEL, EXTI_WAKEUP_LOW_LEVEL, DISABLE);
136             EXTI_ClearWakeupFlag(KEY1_BUTTON_EXTI_CHANNEL);
137         }
138 
139         /* Clear EXTI edge flag and enable EXTI interrupt                                                       */
140         EXTI_ClearEdgeFlag(KEY1_BUTTON_EXTI_CHANNEL);
141         EXTI_IntConfig(KEY1_BUTTON_EXTI_CHANNEL, ENABLE);
142 #endif
143     }
144 
145     return;
146 }
147 /*********************************************************************************************************//**
148   * @brief  Configure USB.
149   * @retval None
150   ***********************************************************************************************************/
USB_Configuration(USBDCore_TypeDef * pCore)151 void USB_Configuration(USBDCore_TypeDef *pCore)
152 {
153 
154     /* Enable peripheral clock                                                                              */
155     CKCU_PeripClockConfig_TypeDef CKCUClock = {{ 0 }};
156     CKCUClock.Bit.USBD = 1;
157     CKCUClock.Bit.EXTI = 1;
158     CKCU_PeripClockConfig(CKCUClock, ENABLE);
159 
160     gUSBCore = pCore;
161 
162 #if (LIBCFG_CKCU_USB_PLL)
163     USBPLL_Configuration();
164 #endif
165 
166 #if (LIBCFG_PWRCU_VREG)
167     USBVRG_Configuration();                               /* Voltage of USB setting                           */
168 #endif
169 
170     /* !!! NOTICE !!!
171        Must turn on if the USB clock source is from HSI (PLL clock Source)
172     */
173 #if 0
174 
175     /* Turn on HSI auto trim function                                                                       */
176     CKCU_HSIAutoTrimClkConfig(CKCU_ATC_USB);
177     CKCU_HSIAutoTrimCmd(ENABLE);
178 
179 #endif
180 
181 
182     /* USB Descriptor, Core, and Class initialization                                                       */
183     gUSBCore->pDriver = (u32 *)&gUSBDriver;              /* Initiate memory pointer of USB driver            */
184     gUSBCore->Power.CallBack_Suspend.func  = Suspend;    /* Install suspend call back function into USB core */
185 
186 //    USBDDesc_Init(&gUSBCore.Device.Desc);               /* Initiate memory pointer of descriptor            */
187 //    USBDClass_Init(&gUSBCore.Class);                    /* Initiate USB Class layer                         */
188     USBDCore_Init(gUSBCore);                           /* Initiate USB Core layer                          */
189 
190     NVIC_SetPriority(USB_IRQn,0);
191     NVIC_EnableIRQ(USB_IRQn);                             /* Enable USB device interrupt                      */
192 
193     HT32F_DVB_USBConnect();
194 
195 }
196 
197 
198 
199 
200 
201 
202 
203 
204