Statistics
| Branch: | Tag: | Revision:

amiro-os / core / src / aos_timer.c @ 4e8e8462

History | View | Annotate | Download (9.332 KB)

1 e545e620 Thomas Schöpping
/*
2
AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
3 96621a83 Thomas Schöpping
Copyright (C) 2016..2020  Thomas Schöpping et al.
4 e545e620 Thomas Schöpping

5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9

10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14

15
You should have received a copy of the GNU General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19 53710ca3 Marc Rothmann
/**
20
 * @file    aos_timer.c
21
 * @brief   Timer code.
22
 * @details Implementation of aos_timer_t and aos_periodictimer_t functions.
23
 *
24
 * @addtogroup aos_timers
25
 * @{
26
 */
27
28 3940ba8a Thomas Schöpping
#include <amiroos.h>
29 e545e620 Thomas Schöpping
30 f3ac1c96 Thomas Schöpping
/******************************************************************************/
31
/* LOCAL DEFINITIONS                                                          */
32
/******************************************************************************/
33
34
/******************************************************************************/
35
/* EXPORTED VARIABLES                                                         */
36
/******************************************************************************/
37
38
/******************************************************************************/
39
/* LOCAL TYPES                                                                */
40
/******************************************************************************/
41
42
/******************************************************************************/
43
/* LOCAL VARIABLES                                                            */
44
/******************************************************************************/
45
46
/******************************************************************************/
47
/* LOCAL FUNCTIONS                                                            */
48
/******************************************************************************/
49 e545e620 Thomas Schöpping
50
/*
51 f3ac1c96 Thomas Schöpping
 * forward declarations
52 e545e620 Thomas Schöpping
 */
53
static void _intermediateCb(void* timer);
54 23ec8223 Thomas Schöpping
static void _triggerCb(void *timer);
55 e545e620 Thomas Schöpping
56
/**
57
 * @brief   Setup a timer according to its configuration.
58
 *
59
 * @param[in] timer   Pointer to the timer to setup.
60
 */
61 d871cc15 Thomas Schöpping
static void _setupTimer(aos_timer_t* timer)
62 e545e620 Thomas Schöpping
{
63 23ec8223 Thomas Schöpping
  // local variables
64 e545e620 Thomas Schöpping
  aos_timestamp_t uptime;
65 23ec8223 Thomas Schöpping
  aos_timestamp_t timedelta;
66 e545e620 Thomas Schöpping
67
  // get current system uptime
68
  aosSysGetUptimeX(&uptime);
69
70 23ec8223 Thomas Schöpping
  // if this is a periodic timer
71
  if (timer->interval > 0) {
72
    // if the periodic timer is already initialized
73
    if (timer->triggertime > 0) {
74
      timer->triggertime += timer->interval;
75
    }
76
    // if the periodic timer is not initialized yet
77
    else {
78
      timer->triggertime = uptime + timer->interval;
79 e545e620 Thomas Schöpping
    }
80
  }
81
82 23ec8223 Thomas Schöpping
  // calculate the time delta (may be 'negative' at this point)
83
  timedelta = timer->triggertime - uptime;
84 e545e620 Thomas Schöpping
85 23ec8223 Thomas Schöpping
  // if the trigger time is more than TIME_IMMEDIATE in the future
86
  if ((timer->triggertime > uptime) && (timedelta > chTimeI2US(TIME_IMMEDIATE))) {
87
    // split the time delta if necessary
88
    if (timedelta > AOS_TIMER_MAX_INTERVAL_US) {
89
      chVTSetI(&timer->vt, chTimeUS2I(AOS_TIMER_MAX_INTERVAL_US), _intermediateCb, timer);
90
    } else {
91
      chVTSetI(&timer->vt, chTimeUS2I(timedelta), _triggerCb, timer);
92
    }
93
  } else {
94
    // trigger immediately
95
    timer->callback(timer->cbparam);
96 e545e620 Thomas Schöpping
  }
97
98
  return;
99
}
100
101
/**
102
 * @brief   Callback function for intermediate interrupts.
103 23ec8223 Thomas Schöpping
 * @details This is required if the desired time to trigger is too far in the future so that the interval must be split.
104 e545e620 Thomas Schöpping
 *
105
 * @param[in] timer   Pointer to a aos_timer_t to reactivate.
106
 */
107
static void _intermediateCb(void* timer)
108
{
109
  chSysLockFromISR();
110
  _setupTimer((aos_timer_t*)timer);
111
  chSysUnlockFromISR();
112
}
113
114
/**
115 23ec8223 Thomas Schöpping
 * @brief   Callback function for the trigger event of the timer.
116 e545e620 Thomas Schöpping
 *
117
 * @param[in] timer   Pointer to a aos_timer_t to call its callback.
118
 */
119 23ec8223 Thomas Schöpping
static void _triggerCb(void *timer)
120 e545e620 Thomas Schöpping
{
121
  chSysLockFromISR();
122
  ((aos_timer_t*)timer)->callback(((aos_timer_t*)timer)->cbparam);
123 23ec8223 Thomas Schöpping
  // reenable periodic timers
124
  if (((aos_timer_t*)timer)->interval > 0) {
125
    _setupTimer((aos_timer_t*)timer);
126
  }
127 e545e620 Thomas Schöpping
  chSysUnlockFromISR();
128
}
129
130 f3ac1c96 Thomas Schöpping
/******************************************************************************/
131
/* EXPORTED FUNCTIONS                                                         */
132
/******************************************************************************/
133
134 e545e620 Thomas Schöpping
/**
135
 * @brief   Initialize a aos_timer_t object.
136
 *
137
 * @param[in] timer   The timer to initialize.
138
 */
139
void aosTimerInit(aos_timer_t* timer)
140
{
141
  aosDbgAssert(timer != NULL);
142
143
  chVTObjectInit(&(timer->vt));
144 23ec8223 Thomas Schöpping
  timer->triggertime = 0;
145
  timer->interval = 0;
146 e545e620 Thomas Schöpping
  timer->callback = NULL;
147
  timer->cbparam = NULL;
148
149
  return;
150
}
151
152
/**
153 23ec8223 Thomas Schöpping
 * @brief   Set timer to trigger at an absolute system time.
154 e545e620 Thomas Schöpping
 *
155
 * @param[in] timer   Pointer to the timer to set.
156 23ec8223 Thomas Schöpping
 * @param[in] uptime  Absolute system time for the timer to trigger.
157 e545e620 Thomas Schöpping
 * @param[in] cb      Pointer to a callback function to be called.
158
 *                    In contrast to ChibiOS callback functions, this gets called from an already ISR locked context.
159
 *                    Thus it may not contain any chSysLockX() or chSysUnlockX() calls and so forth.
160 23ec8223 Thomas Schöpping
 * @param[in] par     Pointer to a parameter for the callback function (may be NULL).
161 e545e620 Thomas Schöpping
 */
162 23ec8223 Thomas Schöpping
void aosTimerSetAbsoluteI(aos_timer_t *timer, const aos_timestamp_t uptime, vtfunc_t cb, void *par)
163 e545e620 Thomas Schöpping
{
164
  aosDbgCheck(timer != NULL);
165
  aosDbgCheck(cb != NULL);
166
167 23ec8223 Thomas Schöpping
  timer->triggertime = uptime;
168
  timer->interval = 0;
169 e545e620 Thomas Schöpping
  timer->callback = cb;
170
  timer->cbparam = par;
171
  _setupTimer(timer);
172
173
  return;
174
}
175
176
/**
177 23ec8223 Thomas Schöpping
 * @brief   Set timer to trigger after a relative interval.
178 e545e620 Thomas Schöpping
 *
179
 * @param[in] timer   Pointer to the timer to set.
180 23ec8223 Thomas Schöpping
 * @param[in] offset  Relative interval to set for the timer to trigger.
181 e545e620 Thomas Schöpping
 * @param[in] cb      Pointer to a callback function to be called.
182
 *                    In contrast to ChibiOS callback functions, this gets called from an already ISR locked context.
183
 *                    Thus it may not contain any chSysLockX() or chSysUnlockX() calls and so forth.
184
 * @param[in] par     Pointer to a parameter for the callback function (may be NULL).
185
 */
186 23ec8223 Thomas Schöpping
void aosTimerSetIntervalI(aos_timer_t *timer, const aos_interval_t offset, vtfunc_t cb, void *par)
187 e545e620 Thomas Schöpping
{
188
  aosDbgCheck(timer != NULL);
189
  aosDbgCheck(cb != NULL);
190
191
  aos_timestamp_t uptime;
192
193
  aosSysGetUptimeX(&uptime);
194 23ec8223 Thomas Schöpping
  timer->triggertime = uptime + offset;
195
  timer->interval = 0;
196 e545e620 Thomas Schöpping
  timer->callback = cb;
197
  timer->cbparam = par;
198
  _setupTimer(timer);
199
200
  return;
201
}
202
203
/**
204 23ec8223 Thomas Schöpping
 * @brief   Set timer to trigger after a long relative interval.
205 e545e620 Thomas Schöpping
 *
206
 * @param[in] timer   Pointer to the timer to set.
207 23ec8223 Thomas Schöpping
 * @param[in] offset  Long interval value to set for the timer to trigger.
208 e545e620 Thomas Schöpping
 * @param[in] cb      Pointer to a callback function to be called.
209
 *                    In contrast to ChibiOS callback functions, this gets called from an already ISR locked context.
210
 *                    Thus it may not contain any chSysLockX() or chSysUnlockX() calls and so forth.
211
 * @param[in] par     Pointer to a parameter for the callback function (may be NULL).
212
 */
213 23ec8223 Thomas Schöpping
void aosTimerSetLongIntervalI(aos_timer_t *timer, const aos_longinterval_t offset, vtfunc_t cb, void *par)
214 e545e620 Thomas Schöpping
{
215
  aosDbgCheck(timer != NULL);
216
  aosDbgCheck(cb != NULL);
217
218
  aos_timestamp_t uptime;
219
220
  aosSysGetUptimeX(&uptime);
221 23ec8223 Thomas Schöpping
  timer->triggertime = uptime + offset;
222
  timer->interval = 0;
223 e545e620 Thomas Schöpping
  timer->callback = cb;
224
  timer->cbparam = par;
225
  _setupTimer(timer);
226
227
  return;
228
}
229
230
/**
231 23ec8223 Thomas Schöpping
 * @brief   Set timer to trigger periodically in the specified interval.
232 e545e620 Thomas Schöpping
 *
233 23ec8223 Thomas Schöpping
 * @param[in] timer     Pointer to the periodic timer to set.
234
 * @param[in] interval  Interval for the periodic timer to trigger periodically.
235 e545e620 Thomas Schöpping
 * @param[in] cb        Pointer to a callback function to be called.
236
 *                      In contrast to ChibiOS callback functions, this gets called from an already ISR locked context.
237
 *                      Thus it may not contain any chSysLockX() or chSysUnlockX() calls and so forth.
238
 * @param[in] par       Pointer to a parameter for the callback function (may be NULL).
239
 */
240 23ec8223 Thomas Schöpping
void aosTimerPeriodicIntervalI(aos_timer_t* timer, const aos_interval_t interval, vtfunc_t cb, void* par)
241 e545e620 Thomas Schöpping
{
242 23ec8223 Thomas Schöpping
  aosDbgCheck(timer != NULL);
243 e545e620 Thomas Schöpping
  aosDbgCheck(interval > TIME_IMMEDIATE);
244
  aosDbgCheck(cb != NULL);
245
246 23ec8223 Thomas Schöpping
  timer->triggertime = 0;
247
  timer->interval = interval;
248
  timer->callback = cb;
249
  timer->cbparam = par;
250
  _setupTimer(timer);
251 e545e620 Thomas Schöpping
252
  return;
253
}
254
255
/**
256 23ec8223 Thomas Schöpping
 * @brief   Set timer to trigger periodically in the specified interval.
257 e545e620 Thomas Schöpping
 *
258 23ec8223 Thomas Schöpping
 * @param[in] timer     Pointer to the periodic timer to set.
259
 * @param[in] interval  Long interval value for the periodic timer to trigger periodically.
260 e545e620 Thomas Schöpping
 * @param[in] cb        Pointer to a callback function to be called.
261
 *                      In contrast to other callback functions, this get called from an already ISR locked context.
262
 *                      This it may not contain any chSysLockX() or chSysUnlockX() calls.
263
 * @param[in] par       Pointer to a parameter for the callback function (may be NULL).
264
 */
265 23ec8223 Thomas Schöpping
void aosTimerPeriodicLongIntervalI(aos_timer_t* timer, const aos_longinterval_t interval, vtfunc_t cb, void* par)
266 e545e620 Thomas Schöpping
{
267 23ec8223 Thomas Schöpping
  aosDbgCheck(timer != NULL);
268
  aosDbgCheck(interval > TIME_IMMEDIATE);
269 e545e620 Thomas Schöpping
  aosDbgCheck(cb != NULL);
270
271 23ec8223 Thomas Schöpping
  timer->triggertime = 0;
272
  timer->interval = interval;
273
  timer->callback = cb;
274
  timer->cbparam = par;
275
  _setupTimer(timer);
276 e545e620 Thomas Schöpping
277
  return;
278
}
279 53710ca3 Marc Rothmann
280
/** @} */