summaryrefslogtreecommitdiff
path: root/include/timer.h
blob: f8100cda0a55378d36a9676136c3220a1f097013 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/* Copyright 2012 The ChromiumOS Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/* Timer module for Chrome EC operating system */

#ifndef __CROS_EC_TIMER_H
#define __CROS_EC_TIMER_H

#include "common.h"
#include "task_id.h"

/* Time units in microseconds */
#define MSEC         1000
#define SECOND    1000000
#define SEC_UL    1000000ul
#define MINUTE   60000000
#define HOUR   3600000000ull  /* Too big to fit in a signed int */

/* Microsecond timestamp. */
typedef union {
	uint64_t val;
	struct {
		uint32_t lo;
		uint32_t hi;
	} le /* little endian words */;
} timestamp_t;

/* Data type for POSIX style clock() implementation */
typedef long clock_t;

/**
 * Initialize the timer module.
 */
void timer_init(void);

/**
 * Launch a one-shot timer for a task.
 *
 * Note that each task can have only a single active timer.
 *
 * @param tstamp	Expiration timestamp for timer
 * @param tskid		Task to set timer for
 *
 * @return EC_SUCCESS, or non-zero if error.
 */
int timer_arm(timestamp_t tstamp, task_id_t tskid);

/**
 * Cancel a running timer for the specified task id.
 */
void timer_cancel(task_id_t tskid);

/**
 * Check if a timestamp has passed / expired
 *
 * @param deadline	deadline timer value to check
 * @param now		pointer to value of time_now() if known, else NULL
 * @return 0 if deadline has not yet passed, 1 if it has passed
 */
int timestamp_expired(timestamp_t deadline, const timestamp_t *now);

/**
 * Busy-wait.
 *
 * This may be called with interrupts disabled, at any time after timer_init()
 * has been called.
 *
 * Note that calling this with us>1000 may impact system performance; use
 * usleep() for longer delays.
 *
 * @param us		Number of microseconds to delay.
 */
void udelay(unsigned us);

/**
 * Sleep.
 *
 * The current task will be de-scheduled for at least the specified delay (and
 * perhaps longer, if a higher-priority task is running when the delay
 * expires).
 *
 * This may only be called from a task function, with interrupts enabled.
 *
 * @param us		Number of microseconds to sleep.
 */
void usleep(unsigned us);

/**
 * Sleep for milliseconds.
 *
 * Otherwise the same as usleep().
 *
 * @param ms		Number of milliseconds to sleep.
 */
static inline void msleep(unsigned ms)
{
	usleep(ms * MSEC);
}

/**
 * Sleep for seconds
 *
 * Otherwise the same as usleep().
 *
 * @param sec		Number of seconds to sleep.
 */
static inline void sleep(unsigned sec)
{
	usleep(sec * SECOND);
}

/**
 * Get the current timestamp from the system timer.
 */
timestamp_t get_time(void);

/**
 * Force the current value of the system timer.
 *
 * This function is for the power management implementation which wants to fix
 * the system time when waking up from a mode with clocks turned off.
 *
 * Note: must be called with interrupts disabled.
 */
void force_time(timestamp_t ts);

/**
 * Print the current timer information using the command output channel.
 *
 * This may be called from interrupt level.
 */
void timer_print_info(void);

/**
 * Returns a free running millisecond clock counter, which matches tpm2
 * library expectations.
 */
clock_t clock(void);

/**
 * Compute how far to_time is from from_time with rollover taken into account
 *
 * Return us until to_time given from_time, if negative then to_time has
 * passeed from_time.
 */
static inline int time_until(uint32_t from_time, uint32_t to_time)
{
	return (int32_t)(to_time - from_time);
}

/**
 * Returns the number of microseconds that have elapsed from a start time.
 *
 * This function is for timing short delays typically of a few milliseconds
 * or so.
 *
 * Note that this is limited to a maximum of 32 bits, which is around an
 * hour. After that, the value returned will wrap.
 *
 * @param start		Start time to compare against
 * @return number of microseconds that have elapsed since that start time
 */
static inline unsigned time_since32(timestamp_t start)
{
	return time_until(start.le.lo, get_time().le.lo);
}

/**
 * To compare time and deal with rollover
 *
 * Return true if a is after b.
 */
static inline int time_after(uint32_t a, uint32_t b)
{
	return time_until(a, b) < 0;
}

#endif  /* __CROS_EC_TIMER_H */