Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (9.332 KB)

1
/*
2
AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
3
Copyright (C) 2016..2020  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 <amiroos.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

    
50
/*
51
 * forward declarations
52
 */
53
static void _intermediateCb(void* timer);
54
static void _triggerCb(void *timer);
55

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

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

    
70
  // 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
    }
80
  }
81

    
82
  // calculate the time delta (may be 'negative' at this point)
83
  timedelta = timer->triggertime - uptime;
84

    
85
  // 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
  }
97

    
98
  return;
99
}
100

    
101
/**
102
 * @brief   Callback function for intermediate interrupts.
103
 * @details This is required if the desired time to trigger is too far in the future so that the interval must be split.
104
 *
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
 * @brief   Callback function for the trigger event of the timer.
116
 *
117
 * @param[in] timer   Pointer to a aos_timer_t to call its callback.
118
 */
119
static void _triggerCb(void *timer)
120
{
121
  chSysLockFromISR();
122
  ((aos_timer_t*)timer)->callback(((aos_timer_t*)timer)->cbparam);
123
  // reenable periodic timers
124
  if (((aos_timer_t*)timer)->interval > 0) {
125
    _setupTimer((aos_timer_t*)timer);
126
  }
127
  chSysUnlockFromISR();
128
}
129

    
130
/******************************************************************************/
131
/* EXPORTED FUNCTIONS                                                         */
132
/******************************************************************************/
133

    
134
/**
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
  timer->triggertime = 0;
145
  timer->interval = 0;
146
  timer->callback = NULL;
147
  timer->cbparam = NULL;
148

    
149
  return;
150
}
151

    
152
/**
153
 * @brief   Set timer to trigger at an absolute system time.
154
 *
155
 * @param[in] timer   Pointer to the timer to set.
156
 * @param[in] uptime  Absolute system time for the timer to trigger.
157
 * @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
 * @param[in] par     Pointer to a parameter for the callback function (may be NULL).
161
 */
162
void aosTimerSetAbsoluteI(aos_timer_t *timer, const aos_timestamp_t uptime, vtfunc_t cb, void *par)
163
{
164
  aosDbgCheck(timer != NULL);
165
  aosDbgCheck(cb != NULL);
166

    
167
  timer->triggertime = uptime;
168
  timer->interval = 0;
169
  timer->callback = cb;
170
  timer->cbparam = par;
171
  _setupTimer(timer);
172

    
173
  return;
174
}
175

    
176
/**
177
 * @brief   Set timer to trigger after a relative interval.
178
 *
179
 * @param[in] timer   Pointer to the timer to set.
180
 * @param[in] offset  Relative interval to set for the timer to trigger.
181
 * @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
void aosTimerSetIntervalI(aos_timer_t *timer, const aos_interval_t offset, vtfunc_t cb, void *par)
187
{
188
  aosDbgCheck(timer != NULL);
189
  aosDbgCheck(cb != NULL);
190

    
191
  aos_timestamp_t uptime;
192

    
193
  aosSysGetUptimeX(&uptime);
194
  timer->triggertime = uptime + offset;
195
  timer->interval = 0;
196
  timer->callback = cb;
197
  timer->cbparam = par;
198
  _setupTimer(timer);
199

    
200
  return;
201
}
202

    
203
/**
204
 * @brief   Set timer to trigger after a long relative interval.
205
 *
206
 * @param[in] timer   Pointer to the timer to set.
207
 * @param[in] offset  Long interval value to set for the timer to trigger.
208
 * @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
void aosTimerSetLongIntervalI(aos_timer_t *timer, const aos_longinterval_t offset, vtfunc_t cb, void *par)
214
{
215
  aosDbgCheck(timer != NULL);
216
  aosDbgCheck(cb != NULL);
217

    
218
  aos_timestamp_t uptime;
219

    
220
  aosSysGetUptimeX(&uptime);
221
  timer->triggertime = uptime + offset;
222
  timer->interval = 0;
223
  timer->callback = cb;
224
  timer->cbparam = par;
225
  _setupTimer(timer);
226

    
227
  return;
228
}
229

    
230
/**
231
 * @brief   Set timer to trigger periodically in the specified interval.
232
 *
233
 * @param[in] timer     Pointer to the periodic timer to set.
234
 * @param[in] interval  Interval for the periodic timer to trigger periodically.
235
 * @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
void aosTimerPeriodicIntervalI(aos_timer_t* timer, const aos_interval_t interval, vtfunc_t cb, void* par)
241
{
242
  aosDbgCheck(timer != NULL);
243
  aosDbgCheck(interval > TIME_IMMEDIATE);
244
  aosDbgCheck(cb != NULL);
245

    
246
  timer->triggertime = 0;
247
  timer->interval = interval;
248
  timer->callback = cb;
249
  timer->cbparam = par;
250
  _setupTimer(timer);
251

    
252
  return;
253
}
254

    
255
/**
256
 * @brief   Set timer to trigger periodically in the specified interval.
257
 *
258
 * @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
 * @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
void aosTimerPeriodicLongIntervalI(aos_timer_t* timer, const aos_longinterval_t interval, vtfunc_t cb, void* par)
266
{
267
  aosDbgCheck(timer != NULL);
268
  aosDbgCheck(interval > TIME_IMMEDIATE);
269
  aosDbgCheck(cb != NULL);
270

    
271
  timer->triggertime = 0;
272
  timer->interval = interval;
273
  timer->callback = cb;
274
  timer->cbparam = par;
275
  _setupTimer(timer);
276

    
277
  return;
278
}
279

    
280
/** @} */