1 /*
2 * Copyright (c) 2006-2024, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2024-05-24 QT-one first version
9 */
10
11 #include <rtdbg.h>
12 #include "drv_wdt.h"
13
14 #ifdef BSP_USING_WDT
15
16 struct ht32_wdt
17 {
18 struct rt_watchdog_device ht32_wdt_device;
19 rt_uint8_t ht32_wdt_start_flag;
20 };
21
22 static struct ht32_wdt ht32_wdt_obj;
23
24 /* Initialization functions for wdt */
ht32_wdt_init(rt_watchdog_t * wdt)25 static rt_err_t ht32_wdt_init(rt_watchdog_t *wdt)
26 {
27 return -RT_ERROR;
28 }
29 /* Control function for wdt */
ht32_wdt_control(rt_watchdog_t * wdt,int cmd,void * arg)30 static rt_err_t ht32_wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
31 {
32 rt_uint16_t wdt_time_val = (*((rt_uint16_t*)arg));
33 switch(cmd)
34 {
35 /* get timeout(in seconds) */
36 case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
37 (*((rt_uint16_t*)arg)) = (WDT_GetReloadValue())/250;
38 break;
39 /* set timeout(in seconds) */
40 case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
41 if(ht32_wdt_obj.ht32_wdt_start_flag)
42 {
43 LOG_W("Please stop the WDT device first.");
44 }
45 else
46 {
47 if(wdt_time_val > 16)
48 {
49 LOG_W("Parameter out of settable range.");
50 }
51 else
52 {
53 /* Disable WDT Protection */
54 WDT_ProtectCmd(DISABLE);
55 /* Reset WDT */
56 WDT_DeInit();
57 /* Set Prescaler Value, 32K/128 = 250Hz 4ms */
58 WDT_SetPrescaler(WDT_PRESCALER_128);
59 /* Set Prescaler Value, 250Hz*wdt_time_val*250 = nms */
60 WDT_SetReloadValue((wdt_time_val*250));
61 /* Set Delta Value, 250Hz*wdt_time_val*250 = nms */
62 WDT_SetDeltaValue((wdt_time_val*250));
63 /* Enable the WDT Reset when WDT meets underflow or error */
64 WDT_ResetCmd(ENABLE);
65 /* Reload Counter as WDTV Value */
66 WDT_Restart();
67 }
68 }
69 break;
70 /* get the left time before reboot(in seconds) */
71 case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
72 return -RT_ERROR;
73 /* refresh watchdog */
74 case RT_DEVICE_CTRL_WDT_KEEPALIVE:
75 if(ht32_wdt_obj.ht32_wdt_start_flag)
76 {
77 /* Enable WDT Restart (Reload WDT Counter) */
78 WDT_Restart();
79 }
80 else
81 {
82 LOG_W("WDT device not activated.");
83 }
84 break;
85 /* start watchdog */
86 case RT_DEVICE_CTRL_WDT_START:
87 if(ht32_wdt_obj.ht32_wdt_start_flag)
88 {
89 LOG_W("The WDT device has been activated.");
90 }
91 else
92 {
93 /* Enable WDT */
94 WDT_Cmd(ENABLE);
95 /* Enable WDT Protection */
96 WDT_ProtectCmd(ENABLE);
97 ht32_wdt_obj.ht32_wdt_start_flag = 1;
98 }
99 break;
100 /* stop watchdog */
101 case RT_DEVICE_CTRL_WDT_STOP:
102 if(ht32_wdt_obj.ht32_wdt_start_flag)
103 {
104 /* Disable WDT Protection */
105 WDT_ProtectCmd(DISABLE);
106 /* Disable WDT */
107 WDT_Cmd(DISABLE);
108 ht32_wdt_obj.ht32_wdt_start_flag = 0;
109 }
110 else
111 {
112 LOG_W("WDT is not activated and does not need to be shut down.");
113 }
114 break;
115 default:
116 LOG_W("This command is not supported.");
117 return -RT_ERROR;
118 }
119 return RT_EOK;
120 }
121
122 static struct rt_watchdog_ops ht32_wdt_ops =
123 {
124 .init = ht32_wdt_init,
125 .control = ht32_wdt_control,
126 };
127
rt_hw_wdt_init(void)128 static int rt_hw_wdt_init(void)
129 {
130 CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
131 CKCUClock.Bit.WDT = 1;
132 CKCU_PeripClockConfig(CKCUClock, ENABLE);
133
134 /* wdt operator function */
135 ht32_wdt_obj.ht32_wdt_device.ops = &ht32_wdt_ops;
136 /* wdt activation flag bit */
137 ht32_wdt_obj.ht32_wdt_start_flag = 0;
138 /* register watchdog device */
139 if (rt_hw_watchdog_register(&ht32_wdt_obj.ht32_wdt_device, BSP_USING_WDT_NAME, RT_DEVICE_FLAG_DEACTIVATE, &ht32_wdt_obj) != RT_EOK)
140 {
141 LOG_E("wdt device register failed.");
142 return -RT_ERROR;
143 }
144 LOG_D("wdt device register success.");
145 return RT_EOK;
146 }
147 INIT_BOARD_EXPORT(rt_hw_wdt_init);
148
149 #endif
150