libopencm3
A free/libre/open-source firmware library for various ARM Cortex-M3 microcontrollers.
wdt.c
Go to the documentation of this file.
1/** @defgroup wdg_file Watchdog peripheral API
2 * @brief SWM050 WDT API.
3 * @ingroup peripheral_apis
4 * LGPL License Terms @ref lgpl_license
5 * @author @htmlonly © @endhtmlonly 2019
6 * Caleb Szalacinski <contact@skiboy.net>
7 */
8/*
9 * This file is part of the libopencm3 project.
10 *
11 * Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
12 *
13 * This library is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as published by
15 * the Free Software Foundation, either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with this library. If not, see <http://www.gnu.org/licenses/>.
25 */
26/**@{*/
29
30/**
31 * Sets up the WDT before the call to @ref wdt_enable().
32 * This only prepares the watchdog, it will not start counting until
33 * it is enabled.
34 * @param mode passed to @ref wdt_mode()
35 * @param time1 passed to @ref wdt_set_time()
36 * @param time2 passed to @ref wdt_set_time()
37 */
38void wdt_setup(enum wdt_modes mode, uint8_t time1, uint8_t time2)
39{
41 wdt_set_time(time1, time2);
42 wdt_mode(mode);
43 wdt_reset();
44}
45
46/**
47 * Enables the WDT.
48 * This actually starts the watchdog, you should have already selected
49 * modes and set timeouts.
50 * If @ref WDT_MODE_INT is used, the interrupt should also be enabled
51 * using the NVIC before enabling the WDT.
52 * @sa wdt_setup
53 * @param en enable
54 */
55void wdt_enable(bool en)
56{
57 if (en) {
58 WDT_CR |= 0x1;
59 } else {
60 WDT_CR &= ~0x1;
61 }
62}
63
64/**
65 * Sets the WDT's mode of operation.
66 * @param mode The mode of operation @ref wdt_modes
67 */
68void wdt_mode(enum wdt_modes mode)
69{
70 if (mode == WDT_MODE_INT) {
71 WDT_CR |= (1 << 1);
72 } else {
73 WDT_CR &= ~(1 << 1);
74 }
75}
76
77/**
78 * Reset the WDT's counter.
79 * The "feed the dog" operation. Must be called periodically to avoid a
80 * timeout. Calling this also clears any WDT interrupts.
81 */
82void wdt_reset(void)
83{
84 WDT_CRR = 0x76;
85}
86
87/**
88 * Gets the WDT's interrupt status.
89 * @note Only useful with @ref WDT_MODE_INT
90 * @return The WDT's interrupt status. True if an interrupt has not been cleared.
91 */
93{
94 return WDT_STAT & 0x1;
95}
96
97/**
98 * Clears the WDT's interrupt.
99 * @note Only useful with @ref WDT_MODE_INT
100 */
102{
103 /* Read register to clear the interrupt */
104 uint32_t dummy = WDT_EOI;
105 /* Does nothing, but suppresses a -Wunused-variable warning */
106 (void)dummy;
107}
108
109/**
110 * Enables the WDT's clock.
111 * This only enables the clock to the peripheral.
112 * @sa wdt_setup
113 * @param en True to enable, false to disable
114 */
115void wdt_clock_enable(bool en)
116{
117 if (en) {
119 } else {
120 SYSCTL_SYS_CFG_1 &= ~SYSCTL_SYS_CFG_1_WDT;
121 }
122}
123
124/**
125 * Gets the current WDT counter value.
126 * The vendor-supplied documentation for the @ref WDT_CCVR register appears to be
127 * incorrect, and does not seem to be 1 bit wide, which would make no sense.
128 * @return The current WDT counter value
129 */
130uint32_t wdt_get_value(void)
131{
132 return WDT_CCVR;
133}
134
135/**
136 * Sets the WDT's initial counter values.
137 * Both time1 and time2 follow the equation 2^(8 + i), where i is a value from
138 * 0 to 15, and where the result is in clock cycles.
139 * For example:
140 * time1 = 15
141 * 2^(8 + time1) / 18Mhz = 0.466s
142 * The majority of the vendor-supplied documentation appears to be completely
143 * incorrect about the equation used for these counters.
144 *
145 * Only the least significant 4 bits are used for both values, eg 0 to 15.
146 *
147 * @param time1 The timer value used in both modes. In @ref WDT_MODE_RESET, this
148 * value counts down to 0 and resets the system. In @ref WDT_MODE_INT, this value
149 * counts down to 0, generates a WDT interrupt, loads time2 into the counter,
150 * and counts down.
151 * @param time2 The timer value used after time1 in mode @ref WDT_MODE_INT. If
152 * this counts down to 0, and the WDT interrupt has not been cleared, the
153 * system resets. This has no use in mode @ref WDT_MODE_RESET.
154 */
155void wdt_set_time(uint8_t time1, uint8_t time2)
156{
157 WDT_TORR = ((0xF & time1) << 4) | (0xF & time2);
158}
159
160/**@}*/
#define SYSCTL_SYS_CFG_1_WDT
Definition: sysctl.h:39
#define SYSCTL_SYS_CFG_1
TIMERSE0, TIMERSE1, and WDT enable.
Definition: sysctl.h:48
void wdt_reset(void)
Reset the WDT's counter.
Definition: wdt.c:82
void wdt_mode(enum wdt_modes mode)
Sets the WDT's mode of operation.
Definition: wdt.c:68
void wdt_set_time(uint8_t time1, uint8_t time2)
Sets the WDT's initial counter values.
Definition: wdt.c:155
uint32_t wdt_get_value(void)
Gets the current WDT counter value.
Definition: wdt.c:130
void wdt_clear_int(void)
Clears the WDT's interrupt.
Definition: wdt.c:101
void wdt_enable(bool en)
Enables the WDT.
Definition: wdt.c:55
bool wdt_int_status(void)
Gets the WDT's interrupt status.
Definition: wdt.c:92
void wdt_clock_enable(bool en)
Enables the WDT's clock.
Definition: wdt.c:115
void wdt_setup(enum wdt_modes mode, uint8_t time1, uint8_t time2)
Sets up the WDT before the call to wdt_enable().
Definition: wdt.c:38
wdt_modes
Definition: wdt.h:37
@ WDT_MODE_INT
On timeout, generate an interrupt.
Definition: wdt.h:42
#define WDT_CRR
Definition: wdt.h:51
#define WDT_CR
Definition: wdt.h:48
#define WDT_EOI
Definition: wdt.h:53
#define WDT_TORR
Definition: wdt.h:49
#define WDT_STAT
Definition: wdt.h:52
#define WDT_CCVR
Definition: wdt.h:50