KallistiOS git master
Independent SDK for the Sega Dreamcast
Loading...
Searching...
No Matches
wdt.h
Go to the documentation of this file.
1/* KallistiOS ##version##
2
3 arch/dreamcast/include/wdt.h
4 Copyright (C) 2023 Falco Girgis
5
6*/
7
8/** \file arch/wdt.h
9 \brief Watchdog Timer API
10 \ingroup wdt
11
12 This file provides an API for configuring and utilizing the SH4's watchdog
13 timer as either a reset or an interval timer.
14
15 \sa arch/timer.h
16 \sa arch/rtc.h
17
18 \author Falco Girgis
19*/
20
21#ifndef __ARCH_WDT_H
22#define __ARCH_WDT_H
23
24#include <sys/cdefs.h>
25__BEGIN_DECLS
26
27#include <stdint.h>
28
29/** \defgroup wdt Watchdog Timer
30 \brief Driver for using the WDT as a reset or interval timer
31 \ingroup timing
32
33 The watchdog timer (WDT) is a special-purpose timer peripheral integrated
34 within the Dreamcast's SH4 CPU.
35
36 \warning
37 At this time, there are no known emulators which are emulating the WDT,
38 as it was never used in commercial games; however, it works perfectly fine
39 on real hardware.
40
41 There are two different modes of operation which are supported:
42 - watchdog mode: counter overflow causes a reset interrupt
43 - interval timer mode: counter overflow invokes a callback function
44
45 To start the WDT in watchdog mode, use wdt_enable_watchdog(). To use the
46 WDT as a general-purpose interval timer, use wdt_enable_timer().
47
48 The timer can be stopped in either mode by calling wdt_disable().
49
50 \sa rtc
51*/
52
53/** \brief Clock divider settings
54 \ingroup wdt
55
56 Denominators used to set the frequency divider
57 for the input clock to the WDT.
58 */
59typedef enum WDT_CLK_DIV {
60 WDT_CLK_DIV_32, /**< \brief Period: 41us */
61 WDT_CLK_DIV_64, /**< \brief Period: 82us */
62 WDT_CLK_DIV_128, /**< \brief Period: 164us */
63 WDT_CLK_DIV_256, /**< \brief Period: 328us */
64 WDT_CLK_DIV_512, /**< \brief Period: 656us */
65 WDT_CLK_DIV_1024, /**< \brief Period: 1.31ms */
66 WDT_CLK_DIV_2048, /**< \brief Period: 2.62ms */
67 WDT_CLK_DIV_4096 /**< \brief Period: 5.25ms */
69
70/** \brief Reset signal type
71 \ingroup wdt
72
73 Specifies the kind of reset to be performed when the WDT
74 overflows in watchdog mode.
75*/
76typedef enum WDT_RST {
77 WDT_RST_POWER_ON, /**< \brief Power-On Reset */
78 WDT_RST_MANUAL /**< \brief Manual Reset */
80
81/* \brief WDT interval timer callback function type
82 \ingroup wdt
83
84 Type of the callback function to be passed to wdt_enable_timer().
85*/
86typedef void (*wdt_callback)(void *user_data);
87
88/** \brief Enables the WDT as an interval timer
89 \ingroup wdt
90
91 Stops the WDT if it was previously running and reconfigures it
92 to be used as a generic interval timer, calling the given callback
93 periodically at the requested interval (or as close to it as possible
94 without calling it prematurely).
95
96 \note
97 The internal resolution for each tick of the WDT in this mode is
98 41us, meaning a requested \p microsec_period of 100us will result
99 in an actual callback interval of 123us.
100
101 \warning
102 \p callback is invoked within an interrupt context, meaning that
103 special care should be taken to not perform any logic requiring
104 additional interrupts. Data that is accessed from both within
105 and outside of the callback should be atomic or protected by a
106 lock.
107
108 \param initial_count Initial value of the WDT counter (Normally 0).
109 \param microsec_period Timer callback interval in microseconds
110 \param irq_prio Priority for the interval timer IRQ (1-15)
111 \param callback User function to invoke periodically
112 \param user_data Arbitrary user-provided data for the callback
113
114 \sa wdt_disable()
115*/
116void wdt_enable_timer(uint8_t initial_count,
117 uint32_t microsec_period,
118 uint8_t irq_prio,
119 wdt_callback callback,
120 void *user_data);
121
122/** \brief Enables the WDT in watchdog mode
123 \ingroup wdt
124
125 Stops the WDT if it was previously running and reconfigures it
126 to be used as a typical watchdog timer, generating a reset
127 interrupt upon counter overflow. To prevent this from happening,
128 the user should be periodically resetting the counter.
129
130 \note
131 Keep in mind the speed of the WDT. With a range of 41us to 5.2ms,
132 the WDT will overflow before a single frame in a typical game.
133
134 \param initial_count Initial value of the WDT counter (Normally 0)
135 \param clk_config Clock divider to set watchdog period
136 \param reset_select The type of reset generated upon overflow
137
138 \sa wdt_disable()
139*/
140void wdt_enable_watchdog(uint8_t initial_count,
141 WDT_CLK_DIV clk_config,
142 WDT_RST reset_select);
143
144/** \brief Fetches the counter value
145 \ingroup wdt
146
147 Returns the current 8-bit value of the WDT counter.
148
149 \return Current counter value
150
151 \sa wdt_set_counter()
152*/
153uint8_t wdt_get_counter(void);
154
155/** \brief Sets the counter value
156 \ingroup wdt
157
158 Sets the current 8-bit value of the WDT counter.
159
160 \param value New value for the counter
161
162 \sa wdt_get_counter(), wdt_pet()
163*/
164void wdt_set_counter(uint8_t value);
165
166/** \brief Resets the counter value
167 \ingroup wdt
168
169 "Petting" or "kicking" the WDT is the same thing as
170 resetting its counter value to 0.
171
172 \sa wdt_set_counter()
173*/
174void wdt_pet(void);
175
176/** \brief Disables the WDT
177 \ingroup wdt
178
179 Disables the WDT if it was previously enabled,
180 otherwise does nothing.
181
182 \sa wdt_enable_timer(), wdt_enable_watchdog()
183*/
184void wdt_disable(void);
185
186/** \brief Returns whether the WDT is enabled
187 \ingroup wdt
188
189 Checks to see whether the WDT has been enabled.
190
191 \return 1 if enabled, 0 if disabled
192*/
194
195__END_DECLS
196
197#endif /* __ARCH_WDT_H */
WDT_CLK_DIV
Clock divider settings.
Definition wdt.h:59
void wdt_pet(void)
Resets the counter value.
void wdt_set_counter(uint8_t value)
Sets the counter value.
void wdt_enable_watchdog(uint8_t initial_count, WDT_CLK_DIV clk_config, WDT_RST reset_select)
Enables the WDT in watchdog mode.
int wdt_is_enabled(void)
Returns whether the WDT is enabled.
WDT_RST
Reset signal type.
Definition wdt.h:76
void wdt_enable_timer(uint8_t initial_count, uint32_t microsec_period, uint8_t irq_prio, wdt_callback callback, void *user_data)
Enables the WDT as an interval timer.
uint8_t wdt_get_counter(void)
Fetches the counter value.
void wdt_disable(void)
Disables the WDT.
@ WDT_CLK_DIV_1024
Period: 1.31ms.
Definition wdt.h:65
@ WDT_CLK_DIV_2048
Period: 2.62ms.
Definition wdt.h:66
@ WDT_CLK_DIV_64
Period: 82us.
Definition wdt.h:61
@ WDT_CLK_DIV_256
Period: 328us.
Definition wdt.h:63
@ WDT_CLK_DIV_4096
Period: 5.25ms.
Definition wdt.h:67
@ WDT_CLK_DIV_512
Period: 656us.
Definition wdt.h:64
@ WDT_CLK_DIV_32
Period: 41us.
Definition wdt.h:60
@ WDT_CLK_DIV_128
Period: 164us.
Definition wdt.h:62
@ WDT_RST_POWER_ON
Power-On Reset.
Definition wdt.h:77
@ WDT_RST_MANUAL
Manual Reset.
Definition wdt.h:78
void(* wdt_callback)(void *user_data)
Definition wdt.h:86