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_RCBController 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 /**@brief Compute number of bytes required to hold the application timer data structures. 00066 * 00067 * @param[in] MAX_TIMERS Maximum number of timers that can be created at any given time. 00068 * @param[in] OP_QUEUE_SIZE Size of queues holding timer operations that are pending execution. 00069 * NOTE: Due to the queue implementation, this size must be one more 00070 * than the size that is actually needed. 00071 * 00072 * @return Required application timer buffer size (in bytes). 00073 */ 00074 #define APP_TIMER_BUF_SIZE(MAX_TIMERS, OP_QUEUE_SIZE) \ 00075 ( \ 00076 ((MAX_TIMERS) * APP_TIMER_NODE_SIZE) \ 00077 + \ 00078 ( \ 00079 APP_TIMER_INT_LEVELS \ 00080 * \ 00081 (APP_TIMER_USER_SIZE + ((OP_QUEUE_SIZE) + 1) * APP_TIMER_USER_OP_SIZE) \ 00082 ) \ 00083 ) 00084 00085 /**@brief Convert milliseconds to timer ticks. 00086 * 00087 * @note This macro uses 64 bit integer arithmetic, but as long as the macro parameters are 00088 * constants (i.e. defines), the computation will be done by the preprocessor. 00089 * 00090 * @param[in] MS Milliseconds. 00091 * @param[in] PRESCALER Value of the RTC1 PRESCALER register (must be the same value that was 00092 * passed to APP_TIMER_INIT()). 00093 * 00094 * @note When using this macro, it is the responsibility of the developer to ensure that the 00095 * values provided as input result in an output value that is supported by the 00096 * @ref app_timer_start function. For example, when the ticks for 1 ms is needed, the 00097 * maximum possible value of PRESCALER must be 6, when @ref APP_TIMER_CLOCK_FREQ is 32768. 00098 * This will result in a ticks value as 5. Any higher value for PRESCALER will result in a 00099 * ticks value that is not supported by this module. 00100 * 00101 * @return Number of timer ticks. 00102 */ 00103 #define APP_TIMER_TICKS(MS, PRESCALER)\ 00104 ((uint32_t)ROUNDED_DIV((MS) * (uint64_t)APP_TIMER_CLOCK_FREQ, ((PRESCALER) + 1) * 1000)) 00105 00106 /**@brief Timer id type. */ 00107 typedef uint32_t app_timer_id_t; 00108 00109 /**@brief Application timeout handler type. */ 00110 typedef void (*app_timer_timeout_handler_t)(void * p_context); 00111 00112 /**@brief Type of function for passing events from the timer module to the scheduler. */ 00113 typedef uint32_t (*app_timer_evt_schedule_func_t) (app_timer_timeout_handler_t timeout_handler, 00114 void * p_context); 00115 00116 /**@brief Timer modes. */ 00117 typedef enum 00118 { 00119 APP_TIMER_MODE_SINGLE_SHOT, /**< The timer will expire only once. */ 00120 APP_TIMER_MODE_REPEATED /**< The timer will restart each time it expires. */ 00121 } app_timer_mode_t; 00122 00123 /**@brief Macro for initializing the application timer module. 00124 * 00125 * @details It will handle dimensioning and allocation of the memory buffer required by the timer, 00126 * making sure that the buffer is correctly aligned. It will also connect the timer module 00127 * to the scheduler (if specified). 00128 * 00129 * @note This module assumes that the LFCLK is already running. If it isn't, the module will 00130 * be non-functional, since the RTC will not run. If you don't use a softdevice, you'll 00131 * have to start the LFCLK manually. See the rtc_example's \ref lfclk_config() function 00132 * for an example of how to do this. If you use a softdevice, the LFCLK is started on 00133 * softdevice init. 00134 * 00135 * 00136 * @param[in] PRESCALER Value of the RTC1 PRESCALER register. This will decide the 00137 * timer tick rate. Set to 0 for no prescaling. 00138 * @param[in] MAX_TIMERS Maximum number of timers that can be created at any given time. 00139 * @param[in] OP_QUEUES_SIZE Size of queues holding timer operations that are pending execution. 00140 * @param[in] USE_SCHEDULER TRUE if the application is using the event scheduler, 00141 * FALSE otherwise. 00142 * 00143 * @note Since this macro allocates a buffer, it must only be called once (it is OK to call it 00144 * several times as long as it is from the same location, e.g. to do a reinitialization). 00145 */ 00146 /*lint -emacro(506, APP_TIMER_INIT) */ /* Suppress "Constant value Boolean */ 00147 #define APP_TIMER_INIT(PRESCALER, MAX_TIMERS, OP_QUEUES_SIZE, USE_SCHEDULER) \ 00148 do \ 00149 { \ 00150 static uint32_t APP_TIMER_BUF[CEIL_DIV(APP_TIMER_BUF_SIZE((MAX_TIMERS), \ 00151 (OP_QUEUES_SIZE) + 1), \ 00152 sizeof(uint32_t))]; \ 00153 uint32_t ERR_CODE = app_timer_init((PRESCALER), \ 00154 (MAX_TIMERS), \ 00155 (OP_QUEUES_SIZE) + 1, \ 00156 APP_TIMER_BUF, \ 00157 (USE_SCHEDULER) ? app_timer_evt_schedule : NULL); \ 00158 APP_ERROR_CHECK(ERR_CODE); \ 00159 } while (0) 00160 00161 /**@brief Function for initializing the timer module. 00162 * 00163 * @note Normally initialization should be done using the APP_TIMER_INIT() macro, as that will both 00164 * allocate the buffers needed by the timer module (including aligning the buffers correctly, 00165 * and also take care of connecting the timer module to the scheduler (if specified). 00166 * 00167 * @param[in] prescaler Value of the RTC1 PRESCALER register. Set to 0 for no prescaling. 00168 * @param[in] max_timers Maximum number of timers that can be created at any given time. 00169 * @param[in] op_queues_size Size of queues holding timer operations that are pending 00170 * execution. NOTE: Due to the queue implementation, this size must 00171 * be one more than the size that is actually needed. 00172 * @param[in] p_buffer Pointer to memory buffer for internal use in the app_timer 00173 * module. The size of the buffer can be computed using the 00174 * APP_TIMER_BUF_SIZE() macro. The buffer must be aligned to a 00175 * 4 byte boundary. 00176 * @param[in] evt_schedule_func Function for passing timeout events to the scheduler. Point to 00177 * app_timer_evt_schedule() to connect to the scheduler. Set to NULL 00178 * to make the timer module call the timeout handler directly from 00179 * the timer interrupt handler. 00180 * 00181 * @retval NRF_SUCCESS Successful initialization. 00182 * @retval NRF_ERROR_INVALID_PARAM Invalid parameter (buffer not aligned to a 4 byte 00183 * boundary or NULL). 00184 */ 00185 uint32_t app_timer_init(uint32_t prescaler, 00186 uint8_t max_timers, 00187 uint8_t op_queues_size, 00188 void * p_buffer, 00189 app_timer_evt_schedule_func_t evt_schedule_func); 00190 00191 /**@brief Function for creating a timer instance. 00192 * 00193 * @param[out] p_timer_id Id of the newly created timer. 00194 * @param[in] mode Timer mode. 00195 * @param[in] timeout_handler Function to be executed when the timer expires. 00196 * 00197 * @retval NRF_SUCCESS Timer was successfully created. 00198 * @retval NRF_ERROR_INVALID_PARAM Invalid parameter. 00199 * @retval NRF_ERROR_INVALID_STATE Application timer module has not been initialized. 00200 * @retval NRF_ERROR_NO_MEM Maximum number of timers has already been reached. 00201 * 00202 * @note This function does the timer allocation in the caller's context. It is also not protected 00203 * by a critical region. Therefore care must be taken not to call it from several interrupt 00204 * levels simultaneously. 00205 */ 00206 uint32_t app_timer_create(app_timer_id_t * p_timer_id, 00207 app_timer_mode_t mode, 00208 app_timer_timeout_handler_t timeout_handler); 00209 00210 /**@brief Function for starting a timer. 00211 * 00212 * @param[in] timer_id Id of timer to start. 00213 * @param[in] timeout_ticks Number of ticks (of RTC1, including prescaling) to timeout event 00214 * (minimum 5 ticks). 00215 * @param[in] p_context General purpose pointer. Will be passed to the timeout handler when 00216 * the timer expires. 00217 * 00218 * @retval NRF_SUCCESS Timer was successfully started. 00219 * @retval NRF_ERROR_INVALID_PARAM Invalid parameter. 00220 * @retval NRF_ERROR_INVALID_STATE Application timer module has not been initialized, or timer 00221 * has not been created. 00222 * @retval NRF_ERROR_NO_MEM Timer operations queue was full. 00223 * 00224 * @note The minimum timeout_ticks value is 5. 00225 * @note For multiple active timers, timeouts occurring in close proximity to each other (in the 00226 * range of 1 to 3 ticks) will have a positive jitter of maximum 3 ticks. 00227 * @note When calling this method on a timer which is already running, the second start operation 00228 * will be ignored. 00229 */ 00230 uint32_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context); 00231 00232 /**@brief Function for stopping the specified timer. 00233 * 00234 * @param[in] timer_id Id of timer to stop. 00235 * 00236 * @retval NRF_SUCCESS Timer was successfully stopped. 00237 * @retval NRF_ERROR_INVALID_PARAM Invalid parameter. 00238 * @retval NRF_ERROR_INVALID_STATE Application timer module has not been initialized, or timer 00239 * has not been created. 00240 * @retval NRF_ERROR_NO_MEM Timer operations queue was full. 00241 */ 00242 uint32_t app_timer_stop(app_timer_id_t timer_id); 00243 00244 /**@brief Function for stopping all running timers. 00245 * 00246 * @retval NRF_SUCCESS All timers were successfully stopped. 00247 * @retval NRF_ERROR_INVALID_STATE Application timer module has not been initialized. 00248 * @retval NRF_ERROR_NO_MEM Timer operations queue was full. 00249 */ 00250 uint32_t app_timer_stop_all(void); 00251 00252 /**@brief Function for returning the current value of the RTC1 counter. 00253 * 00254 * @param[out] p_ticks Current value of the RTC1 counter. 00255 * 00256 * @retval NRF_SUCCESS Counter was successfully read. 00257 */ 00258 uint32_t app_timer_cnt_get(uint32_t * p_ticks); 00259 00260 /**@brief Function for computing the difference between two RTC1 counter values. 00261 * 00262 * @param[in] ticks_to Value returned by app_timer_cnt_get(). 00263 * @param[in] ticks_from Value returned by app_timer_cnt_get(). 00264 * @param[out] p_ticks_diff Number of ticks from ticks_from to ticks_to. 00265 * 00266 * @retval NRF_SUCCESS Counter difference was successfully computed. 00267 */ 00268 uint32_t app_timer_cnt_diff_compute(uint32_t ticks_to, 00269 uint32_t ticks_from, 00270 uint32_t * p_ticks_diff); 00271 00272 00273 // Type and functions for connecting the timer to the scheduler: 00274 00275 /**@cond NO_DOXYGEN */ 00276 typedef struct 00277 { 00278 app_timer_timeout_handler_t timeout_handler; 00279 void * p_context; 00280 } app_timer_event_t; 00281 00282 static __INLINE void app_timer_evt_get(void * p_event_data, uint16_t event_size) 00283 { 00284 app_timer_event_t * p_timer_event = (app_timer_event_t *)p_event_data; 00285 00286 APP_ERROR_CHECK_BOOL(event_size == sizeof(app_timer_event_t)); 00287 p_timer_event->timeout_handler(p_timer_event->p_context); 00288 } 00289 00290 static __INLINE uint32_t app_timer_evt_schedule(app_timer_timeout_handler_t timeout_handler, 00291 void * p_context) 00292 { 00293 app_timer_event_t timer_event; 00294 00295 timer_event.timeout_handler = timeout_handler; 00296 timer_event.p_context = p_context; 00297 00298 return app_sched_event_put(&timer_event, sizeof(timer_event), app_timer_evt_get); 00299 } 00300 /**@endcond */ 00301 00302 #ifdef __cplusplus 00303 } 00304 #endif // #ifdef __cplusplus 00305 00306 #endif // APP_TIMER_H__ 00307 00308 /** @} */
Generated on Tue Jul 12 2022 19:06:03 by
