KallistiOS git master
Independent SDK for the Sega Dreamcast
Loading...
Searching...
No Matches
timer.h
Go to the documentation of this file.
1/* KallistiOS ##version##
2
3 arch/dreamcast/include/timer.h
4 Copyright (c) 2000, 2001 Megan Potter
5 Copyright (c) 2023 Falco Girgis
6 Copyright (c) 2024 Paul Cercueil
7
8*/
9
10/** \file arch/timer.h
11 \brief Low-level timer functionality.
12 \ingroup timers
13
14 This file contains functions for interacting with the timer sources on the
15 SH4. Many of these functions may interfere with thread operation or other
16 such things, and should thus be used with caution. Basically, the only
17 functionality that you might use in practice in here in normal programs is
18 the gettime functions.
19
20 \sa arch/rtc.h
21 \sa arch/wdt.h
22
23 \author Megan Potter
24 \author Falco Girgis
25*/
26
27#ifndef __ARCH_TIMER_H
28#define __ARCH_TIMER_H
29
30
31#include <stdint.h>
32#include <sys/cdefs.h>
33__BEGIN_DECLS
34
35#include <arch/irq.h>
36
37/** \defgroup timers Timer Unit
38 \brief SH4 CPU peripheral providing timers and counters
39 \ingroup timing
40
41 The Dreamcast's SH4 includes an on-chip Timer Unit (TMU) containing 3
42 independent 32-bit channels (TMU0-TMU2). Each channel provides a
43 down-counter with automatic reload and can be configured to use 1 of
44 7 divider circuits for its input clock. By default, KOS uses the fastest
45 input clock for each TMU channel, providing a maximum internal resolution
46 of 80ns ticks.
47
48 \warning
49 Under normal circumstances, all 3 TMU channels are reserved by KOS for
50 various OS-related purposes. If you need a free general-purpose interval
51 timer, consider using the Watchdog Timer.
52
53 \note
54 90% of the time, you will never have a need to directly interact with this
55 API, as it's mostly used as a kernel-level driver which backs other APIs.
56 For example, querying for ticks, fetching the current timestamp, or putting
57 a thread to sleep is typically done via the standard C, C++, or POSIX APIs.
58
59*/
60
61/** \defgroup tmus Channels
62 \brief TMU channel constants
63 \ingroup timers
64
65 The following are the constant `#define` identifiers for the 3 TMU channels.
66
67 \warning
68 All three of these channels are typically reserved and are by KOS for
69 OS-related tasks.
70
71 @{
72*/
73
74/** \brief SH4 Timer Channel 0.
75
76 \warning
77 This timer is used by the kernel's scheduler for thread operation, and thus
78 is off limits if you want that to work properly.
79*/
80#define TMU0 0
81
82/** \brief SH4 Timer Channel 1.
83
84 \warning
85 This timer channel is used for the timer_spin_sleep() function, which also
86 backs the kthread, C, C++, and POSIX sleep functions.
87*/
88#define TMU1 1
89
90/** \brief SH4 Timer Channel 2.
91
92 \warning
93 This timer channel is used by the various gettime functions in this header.
94 It also backs the standard C, C++, and POSIX date/time and clock functions.
95*/
96#define TMU2 2
97
98/** @} */
99
100/** \cond Which timer does the thread system use? */
101#define TIMER_ID TMU0
102/** \endcond */
103
104/** \defgroup tmu_direct Direct-Access
105 \brief Low-level timer driver
106 \ingroup timers
107
108 This API provides a low-level driver abstraction around the TMU peripheral
109 and the control, counter, and reload registers of its 3 channels.
110
111 \note
112 You typically want to use the higher-level APIs associated with the
113 functionality implemented by each timer channel.
114*/
115
116/** \brief Pre-initialize a timer channel, but do not start it.
117 \ingroup tmu_direct
118
119 This function sets up a timer channel for use, but does not start it.
120
121 \param channel The timer channel to set up (\ref tmus).
122 \param speed The number of ticks per second.
123 \param interrupts Set to 1 to receive interrupts when the timer ticks.
124 \retval 0 On success.
125*/
126int timer_prime(int channel, uint32_t speed, int interrupts);
127
128/** \brief Start a timer channel.
129 \ingroup tmu_direct
130
131 This function starts a timer channel that has been initialized with
132 timer_prime(), starting raising interrupts if applicable.
133
134 \param channel The timer channel to start (\ref tmus).
135 \retval 0 On success.
136*/
137int timer_start(int channel);
138
139/** \brief Stop a timer channel.
140 \ingroup tmu_direct
141
142 This function stops a timer channel that was started with timer_start(),
143 and as a result stops interrupts coming in from the timer.
144
145 \param channel The timer channel to stop (\ref tmus).
146 \retval 0 On success.
147*/
148int timer_stop(int channel);
149
150/** \brief Checks whether a timer channel is running.
151 \ingroup tmu_direct
152
153 This function checks whether the given timer channel is actively counting.
154
155 \param channel The timer channel to check (\ref tmus).
156 \retval 0 The timer channel is stopped.
157 \retval 1 The timer channel is running.
158*/
159int timer_running(int channel);
160
161/** \brief Obtain the count of a timer channel.
162 \ingroup tmu_direct
163
164 This function simply returns the count of the timer channel.
165
166 \param channel The timer channel to inspect (\ref tmus).
167 \return The timer's count.
168*/
169uint32_t timer_count(int channel);
170
171/** \brief Clear the underflow bit of a timer channel.
172 \ingroup tmu_direct
173
174 This function clears the underflow bit of a timer channel if it was set.
175
176 \param channel The timer channel to clear (\ref tmus).
177 \retval 0 If the underflow bit was clear (prior to calling).
178 \retval 1 If the underflow bit was set (prior to calling).
179*/
180int timer_clear(int channel);
181
182/** \brief Enable high-priority timer interrupts.
183 \ingroup tmu_direct
184
185 This function enables interrupts on the specified timer.
186
187 \param channel The timer channel to enable interrupts on (\ref tmus).
188*/
189void timer_enable_ints(int channel);
190
191/** \brief Disable timer interrupts.
192 \ingroup tmu_direct
193
194 This function disables interrupts on the specified timer channel.
195
196 \param channel The timer channel to disable interrupts on
197 (\ref tmus).
198*/
199void timer_disable_ints(int channel);
200
201/** \brief Check whether interrupts are enabled on a timer channel.
202 \ingroup tmu_direct
203
204 This function checks whether or not interrupts are enabled on the specified
205 timer channel.
206
207 \param channel The timer channel to inspect (\ref tmus).
208 \retval 0 If interrupts are disabled on the timer.
209 \retval 1 If interrupts are enabled on the timer.
210*/
211int timer_ints_enabled(int channel);
212
213/** \defgroup tmu_uptime Uptime
214 \brief Maintaining time since system boot.
215 \ingroup timers
216
217 This API provides methods for querying the current system boot time or
218 uptime since KOS started at various resolutions. You can use this timing
219 for ticks, delta time, or frame deltas for games, profilers, or media
220 decoding.
221
222 \note
223 This API is used to back the C, C++, and POSIX standard date/time
224 APIs. You may wish to favor these for platform independence.
225
226 \warning
227 This API and its underlying functionality are using \ref TMU2, so any
228 direct manipulation of it will interfere with the API's proper functioning.
229
230 \note
231 The highest actual tick resolution of \ref TMU2 is 80ns.
232*/
233
234/** \brief Enable the millisecond timer.
235 \ingroup tmu_uptime
236
237 This function enables the timer used for the gettime functions. This is on
238 by default. These functions use \ref TMU2 to do their work.
239*/
241
242/** \brief Disable the millisecond timer.
243 \ingroup tmu_uptime
244
245 This function disables the timer used for the gettime functions. Generally,
246 you will not want to do this, unless you have some need to use the timer
247 \ref TMU2 for something else.
248*/
250
251/** \brief Get the current uptime of the system (in secs and millisecs).
252 \ingroup tmu_uptime
253
254 This function retrieves the number of seconds and milliseconds since KOS was
255 started.
256
257 \param secs A pointer to store the number of seconds since boot
258 into.
259 \param msecs A pointer to store the number of milliseconds past
260 a second since boot.
261 \note To get the total number of milliseconds since boot,
262 calculate (*secs * 1000) + *msecs, or use the
263 timer_ms_gettime64() function.
264*/
265void timer_ms_gettime(uint32_t *secs, uint32_t *msecs);
266
267/** \brief Get the current uptime of the system (in milliseconds).
268 \ingroup tmu_uptime
269
270 This function retrieves the number of milliseconds since KOS was started. It
271 is equivalent to calling timer_ms_gettime() and combining the number of
272 seconds and milliseconds into one 64-bit value.
273
274 \return The number of milliseconds since KOS started.
275*/
276uint64_t timer_ms_gettime64(void);
277
278/** \brief Get the current uptime of the system (in secs and microsecs).
279 \ingroup tmu_uptime
280
281 This function retrieves the number of seconds and microseconds since KOS was
282 started.
283
284 \note To get the total number of microseconds since boot,
285 calculate (*secs * 1000000) + *usecs, or use the
286 timer_us_gettime64() function.
287
288 \param secs A pointer to store the number of seconds since boot
289 into.
290 \param usecs A pointer to store the number of microseconds past
291 a second since boot.
292*/
293void timer_us_gettime(uint32_t *secs, uint32_t *usecs);
294
295/** \brief Get the current uptime of the system (in microseconds).
296 \ingroup tmu_uptime
297
298 This function retrieves the number of microseconds since KOS was started.
299
300 \return The number of microseconds since KOS started.
301*/
302uint64_t timer_us_gettime64(void);
303
304/** \brief Get the current uptime of the system (in secs and nanosecs).
305 \ingroup tmu_uptime
306
307 This function retrieves the number of seconds and nanoseconds since KOS was
308 started.
309
310 \note To get the total number of nanoseconds since boot,
311 calculate (*secs * 1000000000) + *nsecs, or use the
312 timer_ns_gettime64() function.
313
314 \param secs A pointer to store the number of seconds since boot
315 into.
316 \param nsecs A pointer to store the number of nanoseconds past
317 a second since boot.
318*/
319void timer_ns_gettime(uint32_t *secs, uint32_t *nsecs);
320
321/** \brief Get the current uptime of the system (in nanoseconds).
322 \ingroup tmu_uptime
323
324 This function retrieves the number of nanoseconds since KOS was started.
325
326 \return The number of nanoseconds since KOS started.
327*/
328uint64_t timer_ns_gettime64(void);
329
330/** \defgroup tmu_sleep Sleeping
331 \brief Low-level thread sleeping
332 \ingroup timers
333
334 This API provides the low-level functionality used to implement thread
335 sleeping, used by the KOS, C, C++, and POSIX threading APIs.
336
337 \warning
338 This API and its underlying functionality are using \ref TMU1, so any
339 direct manipulation of it will interfere with the API's proper functioning.
340*/
341
342/** \brief Spin-loop sleep function.
343 \ingroup tmu_sleep
344
345 This function is meant as a very accurate delay function, even if threading
346 and interrupts are disabled. It uses \ref TMU1 to sleep.
347
348 \param ms The number of milliseconds to sleep.
349*/
350void timer_spin_sleep(int ms);
351
352/** \brief Spin-loop delay function with microsecond granularity
353 \ingroup tmu_sleep
354
355 This function is meant as a very accurate delay function, even if threading
356 and interrupts are disabled. It is a delay and not a sleep, which means that
357 the CPU will be busy-looping during that time frame. For any time frame
358 bigger than a few hundred microseconds, it is recommended to sleep instead.
359
360 \param us The number of microseconds to wait for.
361 \sa timer_spin_delay_ns, thd_sleep
362*/
363void timer_spin_delay_us(unsigned short us);
364
365/** \brief Spin-loop delay function with nanosecond granularity
366 \ingroup tmu_sleep
367
368 This function is meant as a very accurate delay function, even if threading
369 and interrupts are disabled. It is a delay and not a sleep, which means that
370 the CPU will be busy-looping during that time frame.
371
372 \param ns The number of nanoseconds to wait for.
373 \sa timer_spin_delay_us, thd_sleep
374*/
375void timer_spin_delay_ns(unsigned short ns);
376
377/** \defgroup tmu_primary Primary Timer
378 \brief Primary timer used by the kernel.
379 \ingroup timers
380
381 This API provides a callback notification mechanism that can be hooked into
382 the primary timer (TMU0). It is used by the KOS kernel for threading and
383 scheduling.
384
385 \warning
386 This API and its underlying functionality are using \ref TMU0, so any
387 direct manipulation of it will interfere with the API's proper functioning.
388*/
389
390/** \brief Primary timer callback type.
391 \ingroup tmu_primary
392
393 This is the type of function which may be passed to
394 timer_primary_set_callback() as the function that gets invoked
395 upon interrupt.
396*/
398
399/** \brief Set the primary timer callback.
400 \ingroup tmu_primary
401
402 This function sets the primary timer callback to the specified function
403 pointer.
404
405 \warning
406 Generally, you should not do this, as the threading system relies
407 on the primary timer to work.
408
409 \param callback The new timer callback (set to NULL to disable).
410 \return The old timer callback.
411*/
413
414/** \brief Request a primary timer wakeup.
415 \ingroup tmu_primary
416
417 This function will wake the caller (by calling the primary timer callback)
418 in approximately the number of milliseconds specified. You can only have one
419 timer wakeup scheduled at a time. Any subsequently scheduled wakeups will
420 replace any existing one.
421
422 \param millis The number of milliseconds to schedule for.
423*/
424void timer_primary_wakeup(uint32_t millis);
425
426/** \cond */
427/* Init function */
428int timer_init(void);
429
430/* Shutdown */
431void timer_shutdown(void);
432/** \endcond */
433
434__END_DECLS
435
436#endif /* __ARCH_TIMER_H */
437
void timer_disable_ints(int channel)
Disable timer interrupts.
int timer_prime(int channel, uint32_t speed, int interrupts)
Pre-initialize a timer channel, but do not start it.
int timer_running(int channel)
Checks whether a timer channel is running.
uint32_t timer_count(int channel)
Obtain the count of a timer channel.
int timer_start(int channel)
Start a timer channel.
int timer_stop(int channel)
Stop a timer channel.
void timer_enable_ints(int channel)
Enable high-priority timer interrupts.
int timer_ints_enabled(int channel)
Check whether interrupts are enabled on a timer channel.
int timer_clear(int channel)
Clear the underflow bit of a timer channel.
timer_primary_callback_t timer_primary_set_callback(timer_primary_callback_t callback)
Set the primary timer callback.
void timer_primary_wakeup(uint32_t millis)
Request a primary timer wakeup.
void(* timer_primary_callback_t)(irq_context_t *)
Primary timer callback type.
Definition timer.h:397
void timer_spin_delay_us(unsigned short us)
Spin-loop delay function with microsecond granularity.
void timer_spin_sleep(int ms)
Spin-loop sleep function.
void timer_spin_delay_ns(unsigned short ns)
Spin-loop delay function with nanosecond granularity.
uint64_t timer_us_gettime64(void)
Get the current uptime of the system (in microseconds).
uint64_t timer_ms_gettime64(void)
Get the current uptime of the system (in milliseconds).
void timer_ms_disable(void)
Disable the millisecond timer.
void timer_ms_enable(void)
Enable the millisecond timer.
uint64_t timer_ns_gettime64(void)
Get the current uptime of the system (in nanoseconds).
void timer_ns_gettime(uint32_t *secs, uint32_t *nsecs)
Get the current uptime of the system (in secs and nanosecs).
void timer_us_gettime(uint32_t *secs, uint32_t *usecs)
Get the current uptime of the system (in secs and microsecs).
void timer_ms_gettime(uint32_t *secs, uint32_t *msecs)
Get the current uptime of the system (in secs and millisecs).
Interrupt and exception handling.
Architecture-specific structure for holding the processor state.
Definition irq.h:86