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-11 QT-one first version
9 */
10
11 #include "ht32_usbd_int.h"
12
13 #ifdef RT_USING_USB_DEVICE
14 //#include "ht32_usbd_core.h"
15
16
17
18 static void USBPLL_Configuration(void);
19 static void USBVRG_Configuration(void);
20 static void Suspend(u32 uPara);
21
22
23 static USBDCore_TypeDef *int_p_usbd_code;
24 static USBD_Driver_TypeDef gUSBDriver;
25 static u32 gIsLowPowerAllowed = TRUE;
26
27 /*
28 为了不破坏原本的usb_code文件中的USB中断回调函数
29 此处重构USB中断回调函数
30 除了重构USB的中断回调函数以外,还需要重写一些中断回调功能函数
31 */
32 /*
33 RTT的USB中断回调过程如下
34 USB中断函数 -> USB中断回调函数 -> USB相关功能回调函数
35 -> RTT的USB相关功能回调函数 -> 结束USB中断
36
37 RTT的USB程序运行流程(RTT的USB线程运行流程)
38 USB线程阻塞等待USB获取到消息队列中的消息
39 -> USB中断通过回调函数将接收到的消息传给USB的消息队列
40 -> RTT的USB相关功能回调函数获取到USB中断的消息,并设置USB消息队列的状态
41 -> USB退出中断,USB获取到消息后,线程阻塞被解除
42 -> USB线程根据获取的状态执行对应的功能
43 -> USB线程通过USB操作接口实现对应的功能
44
45 */
46 /*
47 根据RTT的USB中断回调过程和RTT的USB线程执行过程
48 得出完成USB驱动需要实现的两个重要部分
49 1、USB线程实现功能所需要的调用到的USB操作接口函数
50 2、USB中断回调过程使用到的RTT的USB驱动的函数的相关衔接部分
51
52 除了以上两个比较重要的功能外,还需要完成以下的一些必要部分
53 1、USB初始化函数
54 2、USB设备注册函数
55
56 完成以上功能主要涉及到两个文件为:
57 1、drv_usbd.c
58 2、ht32_usbd_int.c
59
60 对两个文件的内容分配以及文件依赖如下:
61 drv_usbd.c
62 主要负责实现USB的操作接口的实现
63 以及初始化函数和USB设备注册函数
64 由于自定义的USB内核挂载点在该文件中
65 所以USB的中断函数也会写在该文件中
66 依赖:
67 ht32_usbd_core.c
68 ht32_usbd_int.c
69 以及RTT的相关文件
70
71 ht32_usbd_int.c
72 主要负责实现USB中断回调以及回调函数
73 中和RTT的USB驱动函数相关衔接部分
74 该文件还会包含USB的初始配置函数以及
75 USB的休眠与唤醒的相关函数
76 依赖:
77 ht32_usbd_core.c
78 以及RTT的相关文件
79 */
80
81 /* 帧起始(SOF)中断回调 */
usbd_sof_callback(USBDCore_TypeDef * pCore)82 void usbd_sof_callback(USBDCore_TypeDef *pCore)
83 {
84 udcd_t udcd = (udcd_t)pCore->pdata;
85 rt_usbd_sof_handler(udcd);
86 }
87 /* USB复位中断 */
usbd_reset_callback(USBDCore_TypeDef * pCore)88 void usbd_reset_callback(USBDCore_TypeDef *pCore)
89 {
90 udcd_t udcd = (udcd_t)pCore->pdata;
91 rt_usbd_reset_handler(udcd);
92 }
93
94 /* USB暂停(断开连接)中断 */
usbd_suspend_callback(USBDCore_TypeDef * pCore)95 void usbd_suspend_callback(USBDCore_TypeDef *pCore)
96 {
97 udcd_t udcd = (udcd_t)pCore->pdata;
98 rt_usbd_disconnect_handler(udcd);
99 }
100
101 /* USB恢复(重新连接)中断 */
usbd_resume_callback(USBDCore_TypeDef * pCore)102 void usbd_resume_callback(USBDCore_TypeDef *pCore)
103 {
104 udcd_t udcd = (udcd_t)pCore->pdata;
105 rt_usbd_connect_handler(udcd);
106 }
107
108 /* USB端点0中断 */
109 /* 端点0控制中断 */
usbd_setup_callback(USBDCore_TypeDef * pCore)110 void usbd_setup_callback(USBDCore_TypeDef *pCore)
111 {
112 udcd_t udcd = (udcd_t)pCore->pdata;
113 rt_usbd_ep0_setup_handler(udcd, (struct urequest *)&pCore->Device.Request);
114 }
115
116 /* 端点0输入中断(可以归入其他端点输入中断) */
usbd_ep0_in_callback(USBDCore_TypeDef * pCore)117 void usbd_ep0_in_callback(USBDCore_TypeDef *pCore)
118 {
119 udcd_t udcd = (udcd_t)pCore->pdata;
120 rt_usbd_ep0_in_handler(udcd);
121 }
122
123 /* 端点0输出中断(可以归入其他端点输出中断) */
usbd_ep0_out_callback(USBDCore_TypeDef * pCore)124 void usbd_ep0_out_callback(USBDCore_TypeDef *pCore)
125 {
126 udcd_t udcd = (udcd_t)pCore->pdata;
127 rt_usbd_ep0_out_handler(udcd, pCore->Device.Transfer.sByteLength);
128 }
129
130 /* USB其他端点中断 */
131 /* 其他端点输入中断 */
usbd_ep_in_callback(USBDCore_TypeDef * pCore,USBD_EPTn_Enum EPTn)132 void usbd_ep_in_callback(USBDCore_TypeDef *pCore, USBD_EPTn_Enum EPTn)
133 {
134 udcd_t udcd = (udcd_t)pCore->pdata;
135 rt_usbd_ep_in_handler(udcd, EPTn | 0x80, pCore->Device.Transfer.sByteLength);
136 }
137
138 /* 其他端点输出中断 */
usbd_ep_out_callback(USBDCore_TypeDef * pCore,USBD_EPTn_Enum EPTn)139 void usbd_ep_out_callback(USBDCore_TypeDef *pCore, USBD_EPTn_Enum EPTn)
140 {
141 udcd_t udcd = (udcd_t)pCore->pdata;
142 rt_usbd_ep_out_handler(udcd, EPTn, pCore->Device.Transfer.sByteLength);
143 }
144
145
146
147
148 //rt_err_t rt_usbd_set_feature(udevice_t device, rt_uint16_t value, rt_uint16_t index);
149 //rt_err_t rt_usbd_clear_feature(udevice_t device, rt_uint16_t value, rt_uint16_t index);
150 //rt_err_t rt_usbd_ep_set_stall(udevice_t device, uep_t ep);
151 //rt_err_t rt_usbd_ep_clear_stall(udevice_t device, uep_t ep);
152 //rt_err_t rt_usbd_ep0_set_stall(udevice_t device);
153 //rt_err_t rt_usbd_ep0_clear_stall(udevice_t device);
154
155
156 /*********************************************************************************************************//**
157 * @brief Configure USB.
158 * @retval None
159 ***********************************************************************************************************/
USB_Configuration(USBDCore_TypeDef * pCore)160 static void USB_Configuration(USBDCore_TypeDef *pCore)
161 {
162 CKCU_PeripClockConfig_TypeDef CKCUClock = {{ 0 }};
163 CKCUClock.Bit.USBD = 1;
164 CKCUClock.Bit.EXTI = 1;
165 CKCU_PeripClockConfig(CKCUClock, ENABLE);
166
167 int_p_usbd_code = pCore;
168
169 #if (LIBCFG_CKCU_USB_PLL)
170 USBPLL_Configuration();
171 #endif
172
173 #if (LIBCFG_PWRCU_VREG)
174 USBVRG_Configuration(); /* Voltage of USB setting */
175 #endif
176
177 pCore->pDriver = (u32 *)&gUSBDriver; /* Initiate memory pointer of USB driver */
178 pCore->Power.CallBack_Suspend.func = Suspend; /* Install suspend call back function into USB core */
179
180 // gUSBCore.pDriver = (u32 *)&gUSBDriver; /* Initiate memory pointer of USB driver */
181 // gUSBCore.Power.CallBack_Suspend.func = Suspend; /* Install suspend call back function into USB core */
182 //gUSBCore.Power.CallBack_Suspend.uPara = (u32)NULL;
183
184 /* 描述符初始化 */
185 // USBDDesc_Init(&pCore->Device.Desc); /* Initiate memory pointer of descriptor */
186 /* USB类初始化 */
187 // USBDClass_Init(&(pCore->Class)); /* Initiate USB Class layer */
188 /* USB内核初始化 */
189 USBDCore_Init(pCore); /* Initiate USB Core layer */
190
191 /* !!! NOTICE !!!
192 Must turn on if the USB clock source is from HSI (PLL clock Source)
193 */
194 #if 0
195 {
196 /* Turn on HSI auto trim function */
197 CKCU_HSIAutoTrimClkConfig(CKCU_ATC_USB);
198 CKCU_HSIAutoTrimCmd(ENABLE);
199 }
200 #endif
201
202 NVIC_EnableIRQ(USB_IRQn); /* Enable USB device interrupt */
203 }
204
205 #if (LIBCFG_CKCU_USB_PLL)
206 /*********************************************************************************************************//**
207 * @brief Configure USB PLL
208 * @retval None
209 ************************************************************************************************************/
USBPLL_Configuration(void)210 static void USBPLL_Configuration(void)
211 {
212 {
213 /* USB PLL configuration */
214
215 /* !!! NOTICE !!!
216 Notice that the local variable (structure) did not have an initial value.
217 Please confirm that there are no missing members in the parameter settings below in this function.
218 */
219 CKCU_PLLInitTypeDef PLLInit;
220
221 PLLInit.ClockSource = CKCU_PLLSRC_HSE; // CKCU_PLLSRC_HSE or CKCU_PLLSRC_HSI
222 #if (LIBCFG_CKCU_USB_PLL_96M)
223 PLLInit.CFG = CKCU_USBPLL_8M_96M;
224 #else
225 PLLInit.CFG = CKCU_USBPLL_8M_48M;
226 #endif
227 PLLInit.BYPASSCmd = DISABLE;
228 CKCU_USBPLLInit(&PLLInit);
229 }
230
231 CKCU_USBPLLCmd(ENABLE);
232
233 while (CKCU_GetClockReadyStatus(CKCU_FLAG_USBPLLRDY) == RESET);
234 CKCU_USBClockConfig(CKCU_CKUSBPLL);
235 }
236 #endif
237
238 #if (LIBCFG_PWRCU_VREG)
239 /*********************************************************************************************************//**
240 * @brief Configure USB Voltage
241 * @retval None
242 ************************************************************************************************************/
USBVRG_Configuration(void)243 static void USBVRG_Configuration(void)
244 {
245 CKCU_PeripClockConfig_TypeDef CKCUClock = {{ 0 }};
246 CKCUClock.Bit.BKP = 1;
247 CKCU_PeripClockConfig(CKCUClock, ENABLE);
248
249 PWRCU_SetVREG(PWRCU_VREG_3V3);
250
251 /* !!! NOTICE !!!
252 USB LDO should be enabled (PWRCU_VREG_ENABLE) if the MCU VDD > 3.6 V.
253 */
254 PWRCU_VREGConfig(PWRCU_VREG_BYPASS);
255 }
256 #endif
257
258 #define REMOTE_WAKEUP (0)
259 /*********************************************************************************************************//**
260 * @brief Suspend call back function which enter DeepSleep1
261 * @param uPara: Parameter for Call back function
262 * @retval None
263 ***********************************************************************************************************/
Suspend(u32 uPara)264 static void Suspend(u32 uPara)
265 {
266 #if (REMOTE_WAKEUP == 1)
267 u32 IsRemoteWakeupAllowed;
268 #endif
269
270 if (gIsLowPowerAllowed)
271 {
272
273 #if (REMOTE_WAKEUP == 1)
274 /* Disable EXTI interrupt to prevent interrupt occurred after wakeup */
275 EXTI_IntConfig(KEY1_BUTTON_EXTI_CHANNEL, DISABLE);
276 IsRemoteWakeupAllowed = USBDCore_GetRemoteWakeUpFeature(&gUSBCore);
277
278 if (IsRemoteWakeupAllowed == TRUE)
279 {
280 /* Enable EXTI wake event and clear wakeup flag */
281 EXTI_WakeupEventConfig(KEY1_BUTTON_EXTI_CHANNEL, EXTI_WAKEUP_LOW_LEVEL, ENABLE);
282 EXTI_ClearWakeupFlag(KEY1_BUTTON_EXTI_CHANNEL);
283 }
284 #endif
285
286 __DBG_USBPrintf("%06ld >DEEPSLEEP\r\n", ++__DBG_USBCount);
287
288 // Add your procedure here which disable related IO to reduce power consumption
289 // ..................
290 //
291
292 if ((int_p_usbd_code->Info.CurrentStatus == USB_STATE_SUSPENDED) && ((HT_USB->CSR & 0xC0) == 0x40)) // D+ = 1, D- = 0
293 {
294 /* For Bus powered device, you must enter DeepSleep1 when device has been suspended. For self-powered */
295 /* device, you may decide to enter DeepSleep1 or not depended on your application. */
296
297 /* For the convenient during debugging and evaluation stage, the USBDCore_LowPower() is map to a null */
298 /* function by default. In the real product, you must map this function to the low power function of */
299 /* firmware library by setting USBDCORE_ENABLE_LOW_POWER as 1 (in the ht32fxxxx_usbdconf.h file). */
300 USBDCore_LowPower();
301 }
302
303 // Add your procedure here which recovery related IO for application
304 // ..................
305 //
306
307 __DBG_USBPrintf("%06ld <DEEPSLEEP\r\n", ++__DBG_USBCount);
308
309 #if (REMOTE_WAKEUP == 1)
310 if (EXTI_GetWakeupFlagStatus(KEY1_BUTTON_EXTI_CHANNEL) == SET)
311 {
312 __DBG_USBPrintf("%06ld WAKEUP\r\n", ++__DBG_USBCount);
313 if (IsRemoteWakeupAllowed == TRUE && USBDCore_IsSuspend(&gUSBCore) == TRUE)
314 {
315 USBDCore_TriggerRemoteWakeup();
316 }
317 }
318
319 if (IsRemoteWakeupAllowed == TRUE)
320 {
321 /* Disable EXTI wake event and clear wakeup flag */
322 EXTI_WakeupEventConfig(KEY1_BUTTON_EXTI_CHANNEL, EXTI_WAKEUP_LOW_LEVEL, DISABLE);
323 EXTI_ClearWakeupFlag(KEY1_BUTTON_EXTI_CHANNEL);
324 }
325
326 /* Clear EXTI edge flag and enable EXTI interrupt */
327 EXTI_ClearEdgeFlag(KEY1_BUTTON_EXTI_CHANNEL);
328 EXTI_IntConfig(KEY1_BUTTON_EXTI_CHANNEL, ENABLE);
329 #endif
330 }
331
332 return;
333 }
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353 #endif /* RT_USING_USB_DEVICE */
354