Statistics
| Branch: | Tag: | Revision:

amiro-os / core / src / aos_timer.c @ f3ac1c96

History | View | Annotate | Download (10.2 KB)

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

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
/**
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
#include <aos_timer.h>
29

    
30
/******************************************************************************/
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
#include <aos_system.h>
50

    
51
/*
52
 * forward declarations
53
 */
54
static void _intermediateCb(void* timer);
55
static void _fireCb(void *timer);
56
static void _periodicCb(void* ptimer);
57

    
58
/**
59
 * @brief   Setup a timer according to its configuration.
60
 *
61
 * @param[in] timer   Pointer to the timer to setup.
62
 */
63
static inline void _setupTimer(aos_timer_t* timer)
64
{
65
  aos_timestamp_t uptime;
66

    
67
  // get current system uptime
68
  aosSysGetUptimeX(&uptime);
69

    
70
  // if the wakeup time is more than TIME_IMMEDIATE in the future
71
  if ( (timer->wkuptime > uptime) && ((timer->wkuptime - uptime) > TIME_IMMEDIATE) ) {
72
    // split the time delta if necessary
73
    if ((timer->wkuptime - uptime) > AOS_TIMER_MAX_INTERVAL_US) {
74
      chVTSetI(&(timer->vt), chTimeUS2I(AOS_TIMER_MAX_INTERVAL_US), _intermediateCb, timer);
75
    } else {
76
      chVTSetI(&(timer->vt), chTimeUS2I(timer->wkuptime - uptime), _fireCb, timer);
77
    }
78
  } else {
79
    vtfunc_t fn = timer->callback;
80
    timer->callback = NULL;
81
    fn(timer->cbparam);
82
  }
83

    
84
  return;
85
}
86

    
87
/**
88
 * @brief   Setup a periodic timer according to its configuration.
89
 *
90
 * @param[in] ptimer  Pointer to the periodic timer to setup.
91
 */
92
static inline void _setupPeriodicTimer(aos_periodictimer_t *ptimer)
93
{
94
  // if the periodic timer is being initialized
95
  if (ptimer->timer.wkuptime == 0) {
96
    aos_timestamp_t uptime;
97

    
98
    // get current system uptime
99
    aosSysGetUptimeX(&uptime);
100
    ptimer->timer.wkuptime = uptime + ptimer->interval;
101
  }
102
  // if the peridic timer is reactivated after it has fired
103
  else {
104
    ptimer->timer.wkuptime += ptimer->interval;
105
  }
106

    
107
  // set the callback and parameters
108
  ptimer->timer.callback = _periodicCb;
109
  ptimer->timer.cbparam = ptimer;
110

    
111
  // setup the timer
112
  _setupTimer(&(ptimer->timer));
113

    
114
  return;
115
}
116

    
117
/**
118
 * @brief   Callback function for intermediate interrupts.
119
 * @details This is required if the desired time to fire is too far in the future so that the interval must be split.
120
 *
121
 * @param[in] timer   Pointer to a aos_timer_t to reactivate.
122
 */
123
static void _intermediateCb(void* timer)
124
{
125
  chSysLockFromISR();
126
  _setupTimer((aos_timer_t*)timer);
127
  chSysUnlockFromISR();
128
}
129

    
130
/**
131
 * @brief   Callback function for the final fire event of the timer.
132
 *
133
 * @param[in] timer   Pointer to a aos_timer_t to call its callback.
134
 */
135
static void _fireCb(void *timer)
136
{
137
  chSysLockFromISR();
138
  ((aos_timer_t*)timer)->callback(((aos_timer_t*)timer)->cbparam);
139
  chSysUnlockFromISR();
140
}
141

    
142
/**
143
 * @brief   Callback function for periodic timer interrupts.
144
 * @details This function calls the original callback and reenables the timer afterwards.
145
 *
146
 * @param[in] ptimer  Pointer to a aos_periodictimer_t to reactivate.
147
 */
148
static void _periodicCb(void* ptimer)
149
{
150
  ((aos_periodictimer_t*)ptimer)->callback(((aos_periodictimer_t*)ptimer)->cbparam);
151
  _setupPeriodicTimer((aos_periodictimer_t*)ptimer);
152
}
153

    
154
/******************************************************************************/
155
/* EXPORTED FUNCTIONS                                                         */
156
/******************************************************************************/
157

    
158
/**
159
 * @brief   Initialize a aos_timer_t object.
160
 *
161
 * @param[in] timer   The timer to initialize.
162
 */
163
void aosTimerInit(aos_timer_t* timer)
164
{
165
  aosDbgAssert(timer != NULL);
166

    
167
  chVTObjectInit(&(timer->vt));
168
  timer->wkuptime = 0;
169
  timer->callback = NULL;
170
  timer->cbparam = NULL;
171

    
172
  return;
173
}
174

    
175
/**
176
 * @brief   Set timer to fire at an absolute system time.
177
 *
178
 * @param[in] timer   Pointer to the timer to set.
179
 * @param[in] uptime  Pointer to the absolute system time for the timer to fire.
180
 * @param[in] cb      Pointer to a callback function to be called.
181
 *                    In contrast to ChibiOS callback functions, this gets called from an already ISR locked context.
182
 *                    Thus it may not contain any chSysLockX() or chSysUnlockX() calls and so forth.
183
 * @param[in] par     Pointer to a parameter fpr the callback function (may be NULL).
184
 */
185
void aosTimerSetAbsoluteI(aos_timer_t *timer, aos_timestamp_t *uptime, vtfunc_t cb, void *par)
186
{
187
  aosDbgCheck(timer != NULL);
188
  aosDbgCheck(uptime != NULL);
189
  aosDbgCheck(cb != NULL);
190

    
191
  timer->wkuptime = *uptime;
192
  timer->callback = cb;
193
  timer->cbparam = par;
194
  _setupTimer(timer);
195

    
196
  return;
197
}
198

    
199
/**
200
 * @brief   Set timer to fire after a relative interval.
201
 *
202
 * @param[in] timer   Pointer to the timer to set.
203
 * @param[in] offset  Relative interval to set for the timer to fire.
204
 * @param[in] cb      Pointer to a callback function to be called.
205
 *                    In contrast to ChibiOS callback functions, this gets called from an already ISR locked context.
206
 *                    Thus it may not contain any chSysLockX() or chSysUnlockX() calls and so forth.
207
 * @param[in] par     Pointer to a parameter for the callback function (may be NULL).
208
 */
209
void aosTimerSetIntervalI(aos_timer_t *timer, aos_interval_t offset, vtfunc_t cb, void *par)
210
{
211
  aosDbgCheck(timer != NULL);
212
  aosDbgCheck(cb != NULL);
213

    
214
  aos_timestamp_t uptime;
215

    
216
  aosSysGetUptimeX(&uptime);
217
  timer->wkuptime = uptime + offset;
218
  timer->callback = cb;
219
  timer->cbparam = par;
220
  _setupTimer(timer);
221

    
222
  return;
223
}
224

    
225
/**
226
 * @brief   Set timer to fire after a long relative interval.
227
 *
228
 * @param[in] timer   Pointer to the timer to set.
229
 * @param[in] offset  Pointer to a long interval value to set for the timer to fire.
230
 * @param[in] cb      Pointer to a callback function to be called.
231
 *                    In contrast to ChibiOS callback functions, this gets called from an already ISR locked context.
232
 *                    Thus it may not contain any chSysLockX() or chSysUnlockX() calls and so forth.
233
 * @param[in] par     Pointer to a parameter for the callback function (may be NULL).
234
 */
235
void aosTimerSetLongIntervalI(aos_timer_t *timer, aos_longinterval_t *offset, vtfunc_t cb, void *par)
236
{
237
  aosDbgCheck(timer != NULL);
238
  aosDbgCheck(offset != NULL);
239
  aosDbgCheck(cb != NULL);
240

    
241
  aos_timestamp_t uptime;
242

    
243
  aosSysGetUptimeX(&uptime);
244
  timer->wkuptime = uptime + *offset;
245
  timer->callback = cb;
246
  timer->cbparam = par;
247
  _setupTimer(timer);
248

    
249
  return;
250
}
251

    
252
/**
253
 * @brief   Initialize a aos_periodictimer_t object.
254
 *
255
 * @param[in] timer   The periodic timer to initialize.
256
 */
257
void aosPeriodicTimerInit(aos_periodictimer_t *ptimer)
258
{
259
  aosDbgAssert(ptimer != NULL);
260

    
261
  aosTimerInit(&(ptimer->timer));
262
  ptimer->interval = 0;
263

    
264
  return;
265
}
266

    
267
/**
268
 * @brief   Set a periodic timer to fire in the specified interval.
269
 *
270
 * @param[in] ptimer    Pointer to the periodic timer to set.
271
 * @param[in] interval  Interval for the periodic timer to fire,
272
 * @param[in] cb        Pointer to a callback function to be called.
273
 *                      In contrast to ChibiOS callback functions, this gets called from an already ISR locked context.
274
 *                      Thus it may not contain any chSysLockX() or chSysUnlockX() calls and so forth.
275
 * @param[in] par       Pointer to a parameter for the callback function (may be NULL).
276
 */
277
void aosPeriodicTimerSetI(aos_periodictimer_t* ptimer, aos_interval_t interval, vtfunc_t cb, void* par)
278
{
279
  aosDbgCheck(ptimer != NULL);
280
  aosDbgCheck(interval > TIME_IMMEDIATE);
281
  aosDbgCheck(cb != NULL);
282

    
283
  ptimer->timer.wkuptime = 0;
284
  ptimer->interval = interval;
285
  ptimer->callback = cb;
286
  ptimer->cbparam = par;
287
  _setupPeriodicTimer(ptimer);
288

    
289
  return;
290
}
291

    
292
/**
293
 * @brief   Set a periodic timer to fire in the specified interval.
294
 *
295
 * @param[in] ptimer    Pointer to the periodic timer to set.
296
 * @param[in] interval  Pointer to a long interval value for the periodic timer to fire,
297
 * @param[in] cb        Pointer to a callback function to be called.
298
 *                      In contrast to other callback functions, this get called from an already ISR locked context.
299
 *                      This it may not contain any chSysLockX() or chSysUnlockX() calls.
300
 * @param[in] par       Pointer to a parameter for the callback function (may be NULL).
301
 */
302
void aosPeriodicTimerSetLongI(aos_periodictimer_t* ptimer, aos_longinterval_t* interval, vtfunc_t cb, void* par)
303
{
304
  aosDbgCheck(ptimer != NULL);
305
  aosDbgCheck(*interval > TIME_IMMEDIATE);
306
  aosDbgCheck(cb != NULL);
307

    
308
  ptimer->timer.wkuptime = 0;
309
  ptimer->interval = *interval;
310
  ptimer->callback = cb;
311
  ptimer->cbparam = par;
312
  _setupPeriodicTimer(ptimer);
313

    
314
  return;
315
}
316

    
317
/** @} */