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