1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-05-16 shelton first version
9 */
10
11 #include "drivers/dev_watchdog.h"
12 #include "drv_common.h"
13
14 #ifdef RT_USING_WDT
15
16 #define LICK_VALUE 40000
17
18 //#define DRV_DEBUG
19 #define LOG_TAG "drv.wdt"
20 #include <drv_log.h>
21
22 struct at32_wdt_obj
23 {
24 wdt_type *wdt_x;
25 wdt_division_type div;
26 rt_uint32_t reload;
27 rt_uint16_t is_start;
28 };
29 static struct at32_wdt_obj at32_wdt;
30 static struct rt_watchdog_ops ops;
31 static rt_watchdog_t watchdog;
32
wdt_init(rt_watchdog_t * wdt)33 static rt_err_t wdt_init(rt_watchdog_t *wdt)
34 {
35 return RT_EOK;
36 }
37
wdt_control(rt_watchdog_t * wdt,int cmd,void * arg)38 static rt_err_t wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
39 {
40 switch (cmd)
41 {
42 /* feed the watchdog */
43 case RT_DEVICE_CTRL_WDT_KEEPALIVE:
44 wdt_counter_reload();
45 break;
46 /* set watchdog timeout */
47 case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
48 #if defined(LICK_VALUE)
49 if(LICK_VALUE)
50 {
51 at32_wdt.reload = (*((rt_uint32_t*)arg)) * LICK_VALUE / 256 ;
52 }
53 else
54 {
55 LOG_E("Please define the value of LICK_VALUE!");
56 }
57 if(at32_wdt.reload > 0xFFF)
58 {
59 LOG_E("wdg set timeout parameter too large, please less than %ds", 0xFFF * 256 / LICK_VALUE);
60 return -RT_EINVAL;
61 }
62 #else
63 #error "Please define the value of LICK_VALUE!"
64 #endif
65 if(at32_wdt.is_start)
66 {
67 wdt_register_write_enable(TRUE);
68 wdt_divider_set(at32_wdt.div);
69 wdt_reload_value_set(at32_wdt.reload);
70 wdt_counter_reload();
71 wdt_register_write_enable(FALSE);
72 wdt_enable();
73 }
74 break;
75 case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
76 #if defined(LICK_VALUE)
77 if(LICK_VALUE)
78 {
79 (*((rt_uint32_t*)arg)) = at32_wdt.reload * 256 / LICK_VALUE;
80 }
81 else
82 {
83 LOG_E("Please define the value of LICK_VALUE!");
84 }
85 #else
86 #error "Please define the value of LICK_VALUE!"
87 #endif
88 break;
89 case RT_DEVICE_CTRL_WDT_START:
90 wdt_register_write_enable(TRUE);
91 wdt_divider_set(at32_wdt.div);
92 wdt_reload_value_set(at32_wdt.reload);
93 wdt_counter_reload();
94 wdt_register_write_enable(FALSE);
95 wdt_enable();
96 at32_wdt.is_start = 1;
97 break;
98 default:
99 LOG_W("This command is not supported.");
100 return -RT_ERROR;
101 }
102 return RT_EOK;
103 }
104
rt_hw_wdt_init(void)105 int rt_hw_wdt_init(void)
106 {
107 at32_wdt.wdt_x = WDT;
108 at32_wdt.div = WDT_CLK_DIV_256;
109 at32_wdt.reload = 0x00000FFF;
110 at32_wdt.is_start = 0;
111
112 ops.init = &wdt_init;
113 ops.control = &wdt_control;
114 watchdog.ops = &ops;
115 /* register watchdog device */
116 if (rt_hw_watchdog_register(&watchdog, "wdt", RT_DEVICE_FLAG_DEACTIVATE, RT_NULL) != RT_EOK)
117 {
118 LOG_E("wdt device register failed.");
119 return -RT_ERROR;
120 }
121 LOG_D("wdt device register success.");
122 return RT_EOK;
123 }
124
125 INIT_BOARD_EXPORT(rt_hw_wdt_init);
126
127 #endif /* RT_USING_WDT */
128