Software APIs
dif_rv_timer.h
Go to the documentation of this file.
1
// Copyright lowRISC contributors (OpenTitan project).
2
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3
// SPDX-License-Identifier: Apache-2.0
4
5
#ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_RV_TIMER_H_
6
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_RV_TIMER_H_
7
8
/**
9
* @file
10
* @brief <a href="/book/hw/ip/rv_timer/">RV Timer</a> Device Interface
11
* Functions
12
*/
13
14
#include <stdint.h>
15
16
#include "
sw/device/lib/base/mmio.h
"
17
#include "
sw/device/lib/dif/dif_base.h
"
18
19
#include "sw/device/lib/dif/autogen/dif_rv_timer_autogen.h"
20
21
#ifdef __cplusplus
22
extern
"C"
{
23
#endif
// __cplusplus
24
25
/**
26
* Represents timekeeping parameters for a particular timer.
27
*/
28
typedef
struct
dif_rv_timer_tick_params
{
29
/**
30
* The prescaler value is the period of the timer tick in clock cycles,
31
* minus one. That is,
32
*
33
* prescale = clock_freq * tick_period - 1
34
*
35
* with |clock_freq| and |tick_period| given in units of hertz and seconds,
36
* respectively.
37
*
38
* For example, if the clock frequency is 50 MHz, and the desired tick
39
* period is 1 microsecond, i.e, a tick frequency of 1 MHz, then the
40
* prescaler should be:
41
*
42
* (50 * 10^6) * (1 * 10^-6) - 1 = 49
43
*
44
* However, since |tick_period| is very small, it is much more convenient to
45
* work with |tick_freq|, its inverse, which will be an integer number of
46
* hertz. In particular,
47
*
48
* prescale = (clock_freq / tick_freq) - 1
49
*
50
* This value is declared as a uint16_t, but only the lowest 12 bits are
51
* actually used.
52
*/
53
uint16_t
prescale
;
54
55
/**
56
* The amount to increment the timer counter at each tick.
57
*/
58
uint8_t
tick_step
;
59
}
dif_rv_timer_tick_params_t
;
60
61
/**
62
* Generates an aproximate `dif_rv_timer_tick_params_t` given the device
63
* clock frequency and desired counter frequency (both given in Hertz).
64
*
65
* For the purposes of this function, "counter frequency" is the frequency
66
* at which software would observe a timer counter to increase. If the
67
* clock has insufficient resolution, high counter frequencies may set a
68
* larger value for `tick_step`. For example, if the clock ticks at 50kHz,
69
* but we want a counter that seems to tick every microsecond (1MHz),
70
* we can achieve this with a prescale of 0 (so that there is a tick per
71
* clock cycle) and a tick step of 20 (since 20 * 50kHz = 1MHz).
72
*
73
* The return value of this function is only an approximation, and the
74
* actual counter frequency ultimately depends on the accuracy of the
75
* clock. The function will return an error if it cannot produce an acceptably
76
* accurate counter frequency using the given clock resolution.
77
*
78
* @param clock_freq The device clock frequency, in Hertz.
79
* @param counter_freq The desired counter frequency, in Hertz.
80
* @param[out] out Tick parameters that will approximately produce the desired
81
* counter frequency.
82
* @return The result of the operation.
83
*/
84
OT_WARN_UNUSED_RESULT
85
dif_result_t
dif_rv_timer_approximate_tick_params
(
86
uint64_t clock_freq, uint64_t counter_freq,
87
dif_rv_timer_tick_params_t
*out);
88
89
/**
90
* Completely resets a timer device, disabling all IRQs, counters, and
91
* comparators.
92
*
93
* @param timer A timer device.
94
* @return The result of the operation.
95
*/
96
OT_WARN_UNUSED_RESULT
97
dif_result_t
dif_rv_timer_reset
(
const
dif_rv_timer_t
*timer);
98
99
/**
100
* Configures the tick params for a particular hart's counter.
101
*
102
* This function should not be called when `hart_id`'s counter is enabled; it is
103
* the caller's responsibility to assert this precondition.
104
* The function `dif_rv_timer_approximate_tick_params()` can be used to generate
105
* tick parameter values.
106
*
107
* @param timer A timer device.
108
* @param hart_id The hart to configure.
109
* @param params The timing parameters.
110
* @return The result of the operation.
111
*/
112
OT_WARN_UNUSED_RESULT
113
dif_result_t
dif_rv_timer_set_tick_params
(
const
dif_rv_timer_t
*timer,
114
uint32_t hart_id,
115
dif_rv_timer_tick_params_t
params);
116
117
/**
118
* Starts or stops a particular hart's counter.
119
*
120
* While a counter is enabled, the counter value will increase each tick, but
121
* its timekeeping values cannot be reconfigured.
122
*
123
* @param timer A timer device.
124
* @param hart_id The hart counter to enable/disable.
125
* @param state The new enablement state.
126
* @return The result of the operation.
127
*/
128
OT_WARN_UNUSED_RESULT
129
dif_result_t
dif_rv_timer_counter_set_enabled
(
const
dif_rv_timer_t
*timer,
130
uint32_t hart_id,
131
dif_toggle_t
state);
132
133
/**
134
* Reads the current value on a particular hart's timer.
135
*
136
* @param timer A timer device.
137
* @param hart_id The hart counter to read.
138
* @param[out] out The counter value.
139
* @return The result of the operation.
140
*/
141
OT_WARN_UNUSED_RESULT
142
dif_result_t
dif_rv_timer_counter_read
(
const
dif_rv_timer_t
*timer,
143
uint32_t hart_id, uint64_t *out);
144
145
/**
146
* Writes the given value to a particular hart's timer.
147
*
148
* @param timer A timer device.
149
* @param hart_id The hart counter to write.
150
* @param count The counter value to write.
151
* @return The result of the operation.
152
*/
153
OT_WARN_UNUSED_RESULT
154
dif_result_t
dif_rv_timer_counter_write
(
const
dif_rv_timer_t
*timer,
155
uint32_t hart_id, uint64_t count);
156
157
/**
158
* Arms the timer to go off once the counter value is greater than
159
* or equal to `threshold`, by setting up the given comparator.
160
*
161
* Beware that the following naive implementation of setting an alarm
162
* contains a bug:
163
* uint64_t time;
164
* dif_rv_timer_counter_read(my_timer, kMyHart, &time);
165
* time += kSomeDuration; // (*)
166
* dif_rv_timer_arm(my_timer, kMyHart, kMyComp, time);
167
*
168
* If `time` wraps around when performing the addition, an interrupt will be
169
* fired immediately upon calling `dif_rv_timer_arm`. Care should be taken to
170
* perform saturating addition at (*), so that the interrupt is fired when the
171
* timer value wraps around; this way, the interrupt handler can re-arm the
172
* timer for the rest of the duration.
173
*
174
* This function makes no effort to protect the caller from setting alarms in
175
* the past that would immediately fire an interrupt. It is the caller's
176
* responsibility to read the current counter value and pick a reasonable alarm
177
* threshold.
178
*
179
* @param timer A timer device.
180
* @param hart_id The hart counter to arm against.
181
* @param comp_id The comparator to set up.
182
* @param threshold The value to go off at.
183
* @return The result of the operation.
184
*/
185
OT_WARN_UNUSED_RESULT
186
dif_result_t
dif_rv_timer_arm
(
const
dif_rv_timer_t
*timer, uint32_t hart_id,
187
uint32_t comp_id, uint64_t threshold);
188
189
#ifdef __cplusplus
190
}
// extern "C"
191
#endif
// __cplusplus
192
193
#endif
// OPENTITAN_SW_DEVICE_LIB_DIF_DIF_RV_TIMER_H_
sw
device
lib
dif
dif_rv_timer.h
Return to
OpenTitan Documentation