Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of BLE_WallbotBLE_Challenge by
app_timer.h
00001 /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. 00002 * 00003 * The information contained herein is property of Nordic Semiconductor ASA. 00004 * Terms and conditions of usage are described in detail in NORDIC 00005 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. 00006 * 00007 * Licensees are granted free, non-transferable use of the information. NO 00008 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from 00009 * the file. 00010 * 00011 */ 00012 00013 /** @file 00014 * 00015 * @defgroup app_timer Application Timer 00016 * @{ 00017 * @ingroup app_common 00018 * 00019 * @brief Application timer functionality. 00020 * 00021 * @details It enables the application to create multiple timer instances based on the RTC1 00022 * peripheral. Checking for timeouts and invokation of user timeout handlers is performed 00023 * in the RTC1 interrupt handler. List handling is done using a software interrupt (SWI0). 00024 * Both interrupt handlers are running in APP_LOW priority level. 00025 * 00026 * @note When calling app_timer_start() or app_timer_stop(), the timer operation is just queued, 00027 * and the software interrupt is triggered. The actual timer start/stop operation is 00028 * executed by the SWI0 interrupt handler. Since the SWI0 interrupt is running in APP_LOW, 00029 * if the application code calling the timer function is running in APP_LOW or APP_HIGH, 00030 * the timer operation will not be performed until the application handler has returned. 00031 * This will be the case e.g. when stopping a timer from a timeout handler when not using 00032 * the scheduler. 00033 * 00034 * @details Use the USE_SCHEDULER parameter of the APP_TIMER_INIT() macro to select if the 00035 * @ref app_scheduler is to be used or not. 00036 * 00037 * @note Even if the scheduler is not used, app_timer.h will include app_scheduler.h, so when 00038 * compiling, app_scheduler.h must be available in one of the compiler include paths. 00039 */ 00040 00041 #ifndef APP_TIMER_H__ 00042 #define APP_TIMER_H__ 00043 00044 #include <stdint.h> 00045 #include <stdbool.h> 00046 #include <stdio.h> 00047 #include "app_error.h " 00048 #include "app_util.h " 00049 #include "app_scheduler.h " 00050 #include "compiler_abstraction.h" 00051 00052 #ifdef __cplusplus 00053 extern "C" { 00054 #endif // #ifdef __cplusplus 00055 00056 #define APP_TIMER_SCHED_EVT_SIZE sizeof(app_timer_event_t) /**< Size of button events being passed through the scheduler (is to be used for computing the maximum size of scheduler events). */ 00057 #define APP_TIMER_CLOCK_FREQ 32768 /**< Clock frequency of the RTC timer used to implement the app timer module. */ 00058 #define APP_TIMER_MIN_TIMEOUT_TICKS 5 /**< Minimum value of the timeout_ticks parameter of app_timer_start(). */ 00059 00060 #define APP_TIMER_NODE_SIZE 40 /**< Size of app_timer.timer_node_t (only for use inside APP_TIMER_BUF_SIZE()). */ 00061 #define APP_TIMER_USER_OP_SIZE 24 /**< Size of app_timer.timer_user_op_t (only for use inside APP_TIMER_BUF_SIZE()). */ 00062 #define APP_TIMER_USER_SIZE 8 /**< Size of app_timer.timer_user_t (only for use inside APP_TIMER_BUF_SIZE()). */ 00063 #define APP_TIMER_INT_LEVELS 3 /**< Number of interrupt levels from where timer operations may be initiated (only for use inside APP_TIMER_BUF_SIZE()). */ 00064 00065 #define MAX_RTC_COUNTER_VAL 0x00FFFFFF /**< Maximum value of the RTC counter. */ 00066 00067 /**@brief Compute number of bytes required to hold the application timer data structures. 00068 * 00069 * @param[in] MAX_TIMERS Maximum number of timers that can be created at any given time. 00070 * @param[in] OP_QUEUE_SIZE Size of queues holding timer operations that are pending execution. 00071 * NOTE: Due to the queue implementation, this size must be one more 00072 * than the size that is actually needed. 00073 * 00074 * @return Required application timer buffer size (in bytes). 00075 */ 00076 #define APP_TIMER_BUF_SIZE(MAX_TIMERS, OP_QUEUE_SIZE) \ 00077 ( \ 00078 ((MAX_TIMERS) * APP_TIMER_NODE_SIZE) \ 00079 + \ 00080 ( \ 00081 APP_TIMER_INT_LEVELS \ 00082 * \ 00083 (APP_TIMER_USER_SIZE + ((OP_QUEUE_SIZE) + 1) * APP_TIMER_USER_OP_SIZE) \ 00084 ) \ 00085 ) 00086 00087 /**@brief Convert milliseconds to timer ticks. 00088 * 00089 * @note This macro uses 64 bit integer arithmetic, but as long as the macro parameters are 00090 * constants (i.e. defines), the computation will be done by the preprocessor. 00091 * 00092 * @param[in] MS Milliseconds. 00093 * @param[in] PRESCALER Value of the RTC1 PRESCALER register (must be the same value that was 00094 * passed to APP_TIMER_INIT()). 00095 * 00096 * @note When using this macro, it is the responsibility of the developer to ensure that the 00097 * values provided as input result in an output value that is supported by the 00098 * @ref app_timer_start function. For example, when the ticks for 1 ms is needed, the 00099 * maximum possible value of PRESCALER must be 6, when @ref APP_TIMER_CLOCK_FREQ is 32768. 00100 * This will result in a ticks value as 5. Any higher value for PRESCALER will result in a 00101 * ticks value that is not supported by this module. 00102 * 00103 * @return Number of timer ticks. 00104 */ 00105 #define APP_TIMER_TICKS(MS, PRESCALER)\ 00106 ((uint32_t)ROUNDED_DIV((MS) * (uint64_t)APP_TIMER_CLOCK_FREQ, ((PRESCALER) + 1) * 1000)) 00107 00108 /**@brief Timer id type. */ 00109 typedef uint32_t app_timer_id_t; 00110 00111 #define TIMER_NULL ((app_timer_id_t)(0 - 1)) /**< Invalid timer id. */ 00112 00113 /**@brief Application timeout handler type. */ 00114 typedef void (*app_timer_timeout_handler_t)(void * p_context); 00115 00116 /**@brief Type of function for passing events from the timer module to the scheduler. */ 00117 typedef uint32_t (*app_timer_evt_schedule_func_t) (app_timer_timeout_handler_t timeout_handler, 00118 void * p_context); 00119 00120 /**@brief Timer modes. */ 00121 typedef enum 00122 { 00123 APP_TIMER_MODE_SINGLE_SHOT, /**< The timer will expire only once. */ 00124 APP_TIMER_MODE_REPEATED /**< The timer will restart each time it expires. */ 00125 } app_timer_mode_t; 00126 00127 /**@brief Macro for initializing the application timer module. 00128 * 00129 * @details It will handle dimensioning and allocation of the memory buffer required by the timer, 00130 * making sure that the buffer is correctly aligned. It will also connect the timer module 00131 * to the scheduler (if specified). 00132 * 00133 * @note This module assumes that the LFCLK is already running. If it isn't, the module will 00134 * be non-functional, since the RTC will not run. If you don't use a softdevice, you'll 00135 * have to start the LFCLK manually. See the rtc_example's \ref lfclk_config() function 00136 * for an example of how to do this. If you use a softdevice, the LFCLK is started on 00137 * softdevice init. 00138 * 00139 * 00140 * @param[in] PRESCALER Value of the RTC1 PRESCALER register. This will decide the 00141 * timer tick rate. Set to 0 for no prescaling. 00142 * @param[in] MAX_TIMERS Maximum number of timers that can be created at any given time. 00143 * @param[in] OP_QUEUES_SIZE Size of queues holding timer operations that are pending execution. 00144 * @param[in] USE_SCHEDULER TRUE if the application is using the event scheduler, 00145 * FALSE otherwise. 00146 * 00147 * @note Since this macro allocates a buffer, it must only be called once (it is OK to call it 00148 * several times as long as it is from the same location, e.g. to do a reinitialization). 00149 */ 00150 /*lint -emacro(506, APP_TIMER_INIT) */ /* Suppress "Constant value Boolean */ 00151 #define APP_TIMER_INIT(PRESCALER, MAX_TIMERS, OP_QUEUES_SIZE, USE_SCHEDULER) \ 00152 do \ 00153 { \ 00154 static uint32_t APP_TIMER_BUF[CEIL_DIV(APP_TIMER_BUF_SIZE((MAX_TIMERS), \ 00155 (OP_QUEUES_SIZE) + 1), \ 00156 sizeof(uint32_t))]; \ 00157 uint32_t ERR_CODE = app_timer_init((PRESCALER), \ 00158 (MAX_TIMERS), \ 00159 (OP_QUEUES_SIZE) + 1, \ 00160 APP_TIMER_BUF, \ 00161 (USE_SCHEDULER) ? app_timer_evt_schedule : NULL); \ 00162 APP_ERROR_CHECK(ERR_CODE); \ 00163 } while (0) 00164 00165 /**@brief Function for initializing the timer module. 00166 * 00167 * @note Normally initialization should be done using the APP_TIMER_INIT() macro, as that will both 00168 * allocate the buffers needed by the timer module (including aligning the buffers correctly, 00169 * and also take care of connecting the timer module to the scheduler (if specified). 00170 * 00171 * @param[in] prescaler Value of the RTC1 PRESCALER register. Set to 0 for no prescaling. 00172 * @param[in] max_timers Maximum number of timers that can be created at any given time. 00173 * @param[in] op_queues_size Size of queues holding timer operations that are pending 00174 * execution. NOTE: Due to the queue implementation, this size must 00175 * be one more than the size that is actually needed. 00176 * @param[in] p_buffer Pointer to memory buffer for internal use in the app_timer 00177 * module. The size of the buffer can be computed using the 00178 * APP_TIMER_BUF_SIZE() macro. The buffer must be aligned to a 00179 * 4 byte boundary. 00180 * @param[in] evt_schedule_func Function for passing timeout events to the scheduler. Point to 00181 * app_timer_evt_schedule() to connect to the scheduler. Set to NULL 00182 * to make the timer module call the timeout handler directly from 00183 * the timer interrupt handler. 00184 * 00185 * @retval NRF_SUCCESS Successful initialization. 00186 * @retval NRF_ERROR_INVALID_PARAM Invalid parameter (buffer not aligned to a 4 byte 00187 * boundary or NULL). 00188 */ 00189 uint32_t app_timer_init(uint32_t prescaler, 00190 uint8_t max_timers, 00191 uint8_t op_queues_size, 00192 void * p_buffer, 00193 app_timer_evt_schedule_func_t evt_schedule_func); 00194 00195 /**@brief Function for creating a timer instance. 00196 * 00197 * @param[out] p_timer_id Id of the newly created timer. 00198 * @param[in] mode Timer mode. 00199 * @param[in] timeout_handler Function to be executed when the timer expires. 00200 * 00201 * @retval NRF_SUCCESS Timer was successfully created. 00202 * @retval NRF_ERROR_INVALID_PARAM Invalid parameter. 00203 * @retval NRF_ERROR_INVALID_STATE Application timer module has not been initialized. 00204 * @retval NRF_ERROR_NO_MEM Maximum number of timers has already been reached. 00205 * 00206 * @note This function does the timer allocation in the caller's context. It is also not protected 00207 * by a critical region. Therefore care must be taken not to call it from several interrupt 00208 * levels simultaneously. 00209 */ 00210 uint32_t app_timer_create(app_timer_id_t * p_timer_id, 00211 app_timer_mode_t mode, 00212 app_timer_timeout_handler_t timeout_handler); 00213 00214 /**@brief Function for starting a timer. 00215 * 00216 * @param[in] timer_id Id of timer to start. 00217 * @param[in] timeout_ticks Number of ticks (of RTC1, including prescaling) to timeout event 00218 * (minimum 5 ticks). 00219 * @param[in] p_context General purpose pointer. Will be passed to the timeout handler when 00220 * the timer expires. 00221 * 00222 * @retval NRF_SUCCESS Timer was successfully started. 00223 * @retval NRF_ERROR_INVALID_PARAM Invalid parameter. 00224 * @retval NRF_ERROR_INVALID_STATE Application timer module has not been initialized, or timer 00225 * has not been created. 00226 * @retval NRF_ERROR_NO_MEM Timer operations queue was full. 00227 * 00228 * @note The minimum timeout_ticks value is 5. 00229 * @note For multiple active timers, timeouts occurring in close proximity to each other (in the 00230 * range of 1 to 3 ticks) will have a positive jitter of maximum 3 ticks. 00231 * @note When calling this method on a timer which is already running, the second start operation 00232 * will be ignored. 00233 */ 00234 uint32_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context); 00235 00236 /**@brief Function for stopping the specified timer. 00237 * 00238 * @param[in] timer_id Id of timer to stop. 00239 * 00240 * @retval NRF_SUCCESS Timer was successfully stopped. 00241 * @retval NRF_ERROR_INVALID_PARAM Invalid parameter. 00242 * @retval NRF_ERROR_INVALID_STATE Application timer module has not been initialized, or timer 00243 * has not been created. 00244 * @retval NRF_ERROR_NO_MEM Timer operations queue was full. 00245 */ 00246 uint32_t app_timer_stop(app_timer_id_t timer_id); 00247 00248 /**@brief Function for stopping all running timers. 00249 * 00250 * @retval NRF_SUCCESS All timers were successfully stopped. 00251 * @retval NRF_ERROR_INVALID_STATE Application timer module has not been initialized. 00252 * @retval NRF_ERROR_NO_MEM Timer operations queue was full. 00253 */ 00254 uint32_t app_timer_stop_all(void); 00255 00256 /**@brief Function for returning the current value of the RTC1 counter. The 00257 * value includes overflow bits to extend the range to 64-bits. 00258 * 00259 * @param[out] p_ticks Current value of the RTC1 counter. 00260 * 00261 * @retval NRF_SUCCESS Counter was successfully read. 00262 */ 00263 uint32_t app_timer_cnt_get(uint64_t * p_ticks); 00264 00265 /**@brief Function for computing the difference between two RTC1 counter values. 00266 * 00267 * @param[in] ticks_to Value returned by app_timer_cnt_get(). 00268 * @param[in] ticks_from Value returned by app_timer_cnt_get(). 00269 * @param[out] p_ticks_diff Number of ticks from ticks_from to ticks_to. 00270 * 00271 * @retval NRF_SUCCESS Counter difference was successfully computed. 00272 */ 00273 uint32_t app_timer_cnt_diff_compute(uint32_t ticks_to, 00274 uint32_t ticks_from, 00275 uint32_t * p_ticks_diff); 00276 00277 00278 // Type and functions for connecting the timer to the scheduler: 00279 00280 /**@cond NO_DOXYGEN */ 00281 typedef struct 00282 { 00283 app_timer_timeout_handler_t timeout_handler; 00284 void * p_context; 00285 } app_timer_event_t; 00286 00287 static __INLINE void app_timer_evt_get(void * p_event_data, uint16_t event_size) 00288 { 00289 app_timer_event_t * p_timer_event = (app_timer_event_t *)p_event_data; 00290 00291 APP_ERROR_CHECK_BOOL(event_size == sizeof(app_timer_event_t)); 00292 p_timer_event->timeout_handler(p_timer_event->p_context); 00293 } 00294 00295 static __INLINE uint32_t app_timer_evt_schedule(app_timer_timeout_handler_t timeout_handler, 00296 void * p_context) 00297 { 00298 app_timer_event_t timer_event; 00299 00300 timer_event.timeout_handler = timeout_handler; 00301 timer_event.p_context = p_context; 00302 00303 return app_sched_event_put(&timer_event, sizeof(timer_event), app_timer_evt_get); 00304 } 00305 /**@endcond */ 00306 00307 #ifdef __cplusplus 00308 } 00309 #endif // #ifdef __cplusplus 00310 00311 #endif // APP_TIMER_H__ 00312 00313 /** @} */
Generated on Tue Jul 12 2022 13:52:30 by
