EVE 1.0
app_timer.h
Go to the documentation of this file.
1 /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
2  *
3  * The information contained herein is property of Nordic Semiconductor ASA.
4  * Terms and conditions of usage are described in detail in NORDIC
5  * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
6  *
7  * Licensees are granted free, non-transferable use of the information. NO
8  * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
9  * the file.
10  *
11  */
12 
13 /** @file
14  *
15  * @defgroup app_timer Application Timer
16  * @{
17  * @ingroup app_common
18  *
19  * @brief Application timer functionality.
20  *
21  * @details This module enables the application to create multiple timer instances based on the RTC1
22  * peripheral. Checking for time-outs and invokation of user time-out handlers is performed
23  * in the RTC1 interrupt handler. List handling is done using a software interrupt (SWI0).
24  * Both interrupt handlers are running in APP_LOW priority level.
25  *
26  * @details When calling app_timer_start() or app_timer_stop(), the timer operation is just queued,
27  * and the software interrupt is triggered. The actual timer start/stop operation is
28  * executed by the SWI0 interrupt handler. Since the SWI0 interrupt is running in APP_LOW,
29  * if the application code calling the timer function is running in APP_LOW or APP_HIGH,
30  * the timer operation will not be performed until the application handler has returned.
31  * This will be the case, for example, when stopping a timer from a time-out handler when not using
32  * the scheduler.
33  *
34  * @details Use the USE_SCHEDULER parameter of the APP_TIMER_INIT() macro to select if the
35  * app_scheduler should be used or not. Even if the scheduler is
36  * not used, app_timer.h will include app_scheduler.h, so when
37  * compiling, app_scheduler.h must be available in one of the compiler include paths.
38  */
39 
40 #ifndef APP_TIMER_H__
41 #define APP_TIMER_H__
42 
43 #include <stdint.h>
44 #include <stdbool.h>
45 #include <stdio.h>
46 #include <sys/clock.h>
47 #include <core/mwork.h>
48 #include "app_error.h"
49 #include "app_util.h"
50 #include "compiler_abstraction.h"
51 
52 #define APP_TIMER_CLOCK_FREQ CLOCK_SECOND /**< Clock frequency of the RTC timer used to implement the app timer module. */
53 #define APP_TIMER_MIN_TIMEOUT_TICKS 1 /**< Minimum value of the timeout_ticks parameter of app_timer_start(). */
54 
55 /**@brief Convert milliseconds to timer ticks.
56  *
57  * This macro uses 64-bit integer arithmetic, but as long as the macro parameters are
58  * constants (i.e. defines), the computation will be done by the preprocessor.
59  *
60  * When using this macro, ensure that the
61  * values provided as input result in an output value that is supported by the
62  * @ref app_timer_start function. For example, when the ticks for 1 ms is needed, the
63  * maximum possible value of PRESCALER must be 6, when @ref APP_TIMER_CLOCK_FREQ is 32768.
64  * This will result in a ticks value as 5. Any higher value for PRESCALER will result in a
65  * ticks value that is not supported by this module.
66  *
67  * @param[in] MS Milliseconds.
68  * @param[in] PRESCALER Value of the RTC1 PRESCALER register (must be the same value that was
69  * passed to APP_TIMER_INIT()).
70  *
71  * @return Number of timer ticks.
72  */
73 #define APP_TIMER_TICKS(MS, PRESCALER)\
74  MS_TO_TICKS(MS)
75 
76 /**@brief Timer ID type.
77  * Never declare a variable of this type, but use the macro @ref APP_TIMER_DEF instead.*/
78 typedef struct app_timer_t * app_timer_id_t;
79 
80 void app_timer_work_cb(struct mwork_t *work);
81 
82 /**
83  * @brief Create a timer identifier and statically allocate memory for the timer.
84  *
85  * @param timer_id Name of the timer identifier variable that will be used to control the timer.
86  */
87 #define APP_TIMER_DEF(timer_id) \
88  static app_timer_t timer_id##_data = { \
89  .work = MWORK_INIT(timer_id##_data.work, app_timer_work_cb), \
90  .mode = (app_timer_mode_t) -1, \
91  }; \
92  static const app_timer_id_t timer_id = &timer_id##_data
93 
94 
95 /**@brief Application time-out handler type. */
96 typedef void (*app_timer_timeout_handler_t)(void * p_context);
97 
98 /**@brief Type of function for passing events from the timer module to the scheduler. */
99 typedef uint32_t (*app_timer_evt_schedule_func_t) (app_timer_timeout_handler_t timeout_handler,
100  void * p_context);
101 
102 /**@brief Timer modes. */
103 typedef enum
104 {
105  APP_TIMER_MODE_SINGLE_SHOT, /**< The timer will expire only once. */
106  APP_TIMER_MODE_REPEATED /**< The timer will restart each time it expires. */
108 
109 typedef struct app_timer_t
110 {
111  struct mwork_t work;
112  app_timer_mode_t mode;
113  uint32_t interval;
114  app_timer_timeout_handler_t p_timeout_handler;
115  void *p_context;
116 } app_timer_t;
117 
118 
119 /**@brief Initialize the application timer module.
120  *
121  * @details This macro handles dimensioning and allocation of the memory buffer required by the timer,
122  * making sure that the buffer is correctly aligned. It will also connect the timer module
123  * to the scheduler (if specified).
124  *
125  * @note This module assumes that the LFCLK is already running. If it is not, the module will
126  * be non-functional, since the RTC will not run. If you do not use a SoftDevice, you
127  * must start the LFCLK manually. See the rtc_example's lfclk_config() function
128  * for an example of how to do this. If you use a SoftDevice, the LFCLK is started on
129  * SoftDevice init.
130  *
131  *
132  * @param[in] PRESCALER Value of the RTC1 PRESCALER register. This will decide the
133  * timer tick rate. Set to 0 for no prescaling.
134  * @param[in] OP_QUEUES_SIZE Size of queues holding timer operations that are pending execution.
135  * @param[in] SCHEDULER_FUNC Pointer to scheduler event handler
136  *
137  * @note Since this macro allocates a buffer, it must only be called once (it is OK to call it
138  * several times as long as it is from the same location, for example, to do a re-initialization).
139  */
140 /*lint -emacro(506, APP_TIMER_INIT) */ /* Suppress "Constant value Boolean */
141 #define APP_TIMER_INIT(PRESCALER, OP_QUEUES_SIZE, SCHEDULER_FUNC) \
142  do \
143  { \
144  uint32_t ERR_CODE = app_timer_init(SCHEDULER_FUNC); \
145  APP_ERROR_CHECK(ERR_CODE); \
146  } while (0)
147 
148 
149 
150 /**@brief Function for initializing the timer module.
151  *
152  * Normally, initialization should be done using the APP_TIMER_INIT() macro, because that macro will both
153  * allocate the buffers needed by the timer module (including aligning the buffers correctly)
154  * and take care of connecting the timer module to the scheduler (if specified).
155  *
156  * @param[in] evt_schedule_func Function for passing time-out events to the scheduler. Point to
157  * app_timer_evt_schedule() to connect to the scheduler. Set to NULL
158  * to make the timer module call the time-out handler directly from
159  * the timer interrupt handler.
160  *
161  * @retval NRF_SUCCESS If the module was initialized successfully.
162  * @retval NRF_ERROR_INVALID_PARAM If a parameter was invalid (buffer not aligned to a 4 byte
163  * boundary or NULL).
164  */
165 uint32_t app_timer_init(app_timer_evt_schedule_func_t evt_schedule_func);
166 
167 /**@brief Function for creating a timer instance.
168  *
169  * @param[in] p_timer_id Pointer to timer identifier.
170  * @param[in] mode Timer mode.
171  * @param[in] timeout_handler Function to be executed when the timer expires.
172  *
173  * @retval NRF_SUCCESS If the timer was successfully created.
174  * @retval NRF_ERROR_INVALID_PARAM If a parameter was invalid.
175  * @retval NRF_ERROR_INVALID_STATE If the application timer module has not been initialized or
176  * the timer is running.
177  *
178  * @note This function does the timer allocation in the caller's context. It is also not protected
179  * by a critical region. Therefore care must be taken not to call it from several interrupt
180  * levels simultaneously.
181  * @note The function can be called again on the timer instance and will re-initialize the instance if
182  * the timer is not running.
183  * @attention The FreeRTOS and RTX app_timer implementation does not allow app_timer_create to
184  * be called on the previously initialized instance.
185  */
186 uint32_t app_timer_create(app_timer_id_t const * p_timer_id,
187  app_timer_mode_t mode,
188  app_timer_timeout_handler_t timeout_handler);
189 
190 /**@brief Function for starting a timer.
191  *
192  * @param[in] timer_id Timer identifier.
193  * @param[in] timeout_ticks Number of ticks (of RTC1, including prescaling) to time-out event
194  * (minimum 5 ticks).
195  * @param[in] p_context General purpose pointer. Will be passed to the time-out handler when
196  * the timer expires.
197  *
198  * @retval NRF_SUCCESS If the timer was successfully started.
199  * @retval NRF_ERROR_INVALID_PARAM If a parameter was invalid.
200  * @retval NRF_ERROR_INVALID_STATE If the application timer module has not been initialized or the timer
201  * has not been created.
202  * @retval NRF_ERROR_NO_MEM If the timer operations queue was full.
203  *
204  * @note The minimum timeout_ticks value is 5.
205  * @note For multiple active timers, time-outs occurring in close proximity to each other (in the
206  * range of 1 to 3 ticks) will have a positive jitter of maximum 3 ticks.
207  * @note When calling this method on a timer that is already running, the second start operation
208  * is ignored.
209  */
210 uint32_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context);
211 
212 /**@brief Function for stopping the specified timer.
213  *
214  * @param[in] timer_id Timer identifier.
215  *
216  * @retval NRF_SUCCESS If the timer was successfully stopped.
217  * @retval NRF_ERROR_INVALID_PARAM If a parameter was invalid.
218  * @retval NRF_ERROR_INVALID_STATE If the application timer module has not been initialized or the timer
219  * has not been created.
220  * @retval NRF_ERROR_NO_MEM If the timer operations queue was full.
221  */
222 uint32_t app_timer_stop(app_timer_id_t timer_id);
223 
224 /**@brief Function for stopping all running timers.
225  *
226  * @retval NRF_SUCCESS If all timers were successfully stopped.
227  * @retval NRF_ERROR_INVALID_STATE If the application timer module has not been initialized.
228  * @retval NRF_ERROR_NO_MEM If the timer operations queue was full.
229  */
230 uint32_t app_timer_stop_all(void);
231 
232 /**@brief Function for returning the current value of the RTC1 counter.
233  *
234  * @param[out] p_ticks Current value of the RTC1 counter.
235  *
236  * @retval NRF_SUCCESS If the counter was successfully read.
237  */
238 uint32_t app_timer_cnt_get(uint32_t * p_ticks);
239 
240 /**@brief Function for computing the difference between two RTC1 counter values.
241  *
242  * @param[in] ticks_to Value returned by app_timer_cnt_get().
243  * @param[in] ticks_from Value returned by app_timer_cnt_get().
244  * @param[out] p_ticks_diff Number of ticks from ticks_from to ticks_to.
245  *
246  * @retval NRF_SUCCESS If the counter difference was successfully computed.
247  */
248 uint32_t app_timer_cnt_diff_compute(uint32_t ticks_to,
249  uint32_t ticks_from,
250  uint32_t * p_ticks_diff);
251 
252 #endif // APP_TIMER_H__
253 
254 /** @} */
uint32_t app_timer_stop(app_timer_id_t timer_id)
Function for stopping the specified timer.
Definition: app_timer.c:56
uint32_t app_timer_init(app_timer_evt_schedule_func_t evt_schedule_func)
Function for initializing the timer module.
Definition: app_timer.c:24
Header file for the EVE millisecond-scale work scheduling.
uint32_t app_timer_create(app_timer_id_t const *p_timer_id, app_timer_mode_t mode, app_timer_timeout_handler_t timeout_handler)
Function for creating a timer instance.
Definition: app_timer.c:30
app_timer_mode_t
Timer modes.
Definition: app_timer.h:103
Definition: mwork.h:182
uint32_t app_timer_cnt_diff_compute(uint32_t ticks_to, uint32_t ticks_from, uint32_t *p_ticks_diff)
Function for computing the difference between two RTC1 counter values.
struct app_timer_t * app_timer_id_t
Timer ID type. Never declare a variable of this type, but use the macro APP_TIMER_DEF instead...
Definition: app_timer.h:78
void(* app_timer_timeout_handler_t)(void *p_context)
Application time-out handler type.
Definition: app_timer.h:96
uint32_t(* app_timer_evt_schedule_func_t)(app_timer_timeout_handler_t timeout_handler, void *p_context)
Type of function for passing events from the timer module to the scheduler.
Definition: app_timer.h:99
uint32_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void *p_context)
Function for starting a timer.
Definition: app_timer.c:43
uint32_t app_timer_cnt_get(uint32_t *p_ticks)
Function for returning the current value of the RTC1 counter.
uint32_t app_timer_stop_all(void)
Function for stopping all running timers.