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 nrf51-sdk by
app_timer.h
00001 /* 00002 * Copyright (c) Nordic Semiconductor ASA 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without modification, 00006 * are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright notice, this 00009 * list of conditions and the following disclaimer. 00010 * 00011 * 2. Redistributions in binary form must reproduce the above copyright notice, this 00012 * list of conditions and the following disclaimer in the documentation and/or 00013 * other materials provided with the distribution. 00014 * 00015 * 3. Neither the name of Nordic Semiconductor ASA nor the names of other 00016 * contributors to this software may be used to endorse or promote products 00017 * derived from this software without specific prior written permission. 00018 * 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00021 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00023 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00024 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00027 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 * 00031 */ 00032 00033 /** @file 00034 * 00035 * @defgroup app_timer Application Timer 00036 * @{ 00037 * @ingroup app_common 00038 * 00039 * @brief Application timer functionality. 00040 * 00041 * @details This module enables the application to create multiple timer instances based on the RTC1 00042 * peripheral. Checking for time-outs and invokation of user time-out handlers is performed 00043 * in the RTC1 interrupt handler. List handling is done using a software interrupt (SWI0). 00044 * Both interrupt handlers are running in APP_LOW priority level. 00045 * 00046 * @details When calling app_timer_start() or app_timer_stop(), the timer operation is just queued, 00047 * and the software interrupt is triggered. The actual timer start/stop operation is 00048 * executed by the SWI0 interrupt handler. Since the SWI0 interrupt is running in APP_LOW, 00049 * if the application code calling the timer function is running in APP_LOW or APP_HIGH, 00050 * the timer operation will not be performed until the application handler has returned. 00051 * This will be the case, for example, when stopping a timer from a time-out handler when not using 00052 * the scheduler. 00053 * 00054 * @details Use the USE_SCHEDULER parameter of the APP_TIMER_INIT() macro to select if the 00055 * @ref app_scheduler should be used or not. Even if the scheduler is 00056 * not used, app_timer.h will include app_scheduler.h, so when 00057 * compiling, app_scheduler.h must be available in one of the compiler include paths. 00058 */ 00059 00060 #ifndef APP_TIMER_H__ 00061 #define APP_TIMER_H__ 00062 00063 #include <stdint.h> 00064 #include <stdbool.h> 00065 #include <stdio.h> 00066 #include "app_error.h " 00067 #include "app_util.h " 00068 #include "compiler_abstraction.h" 00069 00070 #define APP_TIMER_CLOCK_FREQ 32768 /**< Clock frequency of the RTC timer used to implement the app timer module. */ 00071 #define APP_TIMER_MIN_TIMEOUT_TICKS 5 /**< Minimum value of the timeout_ticks parameter of app_timer_start(). */ 00072 00073 #define APP_TIMER_NODE_SIZE 32 /**< Size of app_timer.timer_node_t (used to allocate data). */ 00074 #define APP_TIMER_USER_OP_SIZE 24 /**< Size of app_timer.timer_user_op_t (only for use inside APP_TIMER_BUF_SIZE()). */ 00075 #define APP_TIMER_USER_SIZE 8 /**< Size of app_timer.timer_user_t (only for use inside APP_TIMER_BUF_SIZE()). */ 00076 #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()). */ 00077 00078 /**@brief Compute number of bytes required to hold the application timer data structures. 00079 * 00080 * @param[in] OP_QUEUE_SIZE Size of queues holding timer operations that are pending execution. 00081 * Note that due to the queue implementation, this size must be one more 00082 * than the size that is actually needed. 00083 * 00084 * @return Required application timer buffer size (in bytes). 00085 */ 00086 #define APP_TIMER_BUF_SIZE(OP_QUEUE_SIZE) \ 00087 ( \ 00088 ( \ 00089 APP_TIMER_INT_LEVELS \ 00090 * \ 00091 (APP_TIMER_USER_SIZE + ((OP_QUEUE_SIZE) + 1) * APP_TIMER_USER_OP_SIZE) \ 00092 ) \ 00093 ) 00094 00095 /**@brief Convert milliseconds to timer ticks. 00096 * 00097 * This macro uses 64-bit integer arithmetic, but as long as the macro parameters are 00098 * constants (i.e. defines), the computation will be done by the preprocessor. 00099 * 00100 * When using this macro, ensure that the 00101 * values provided as input result in an output value that is supported by the 00102 * @ref app_timer_start function. For example, when the ticks for 1 ms is needed, the 00103 * maximum possible value of PRESCALER must be 6, when @ref APP_TIMER_CLOCK_FREQ is 32768. 00104 * This will result in a ticks value as 5. Any higher value for PRESCALER will result in a 00105 * ticks value that is not supported by this module. 00106 * 00107 * @param[in] MS Milliseconds. 00108 * @param[in] PRESCALER Value of the RTC1 PRESCALER register (must be the same value that was 00109 * passed to APP_TIMER_INIT()). 00110 * 00111 * @return Number of timer ticks. 00112 */ 00113 #define APP_TIMER_TICKS(MS, PRESCALER)\ 00114 ((uint32_t)ROUNDED_DIV((MS) * (uint64_t)APP_TIMER_CLOCK_FREQ, ((PRESCALER) + 1) * 1000)) 00115 00116 typedef struct app_timer_t { uint32_t data[CEIL_DIV(APP_TIMER_NODE_SIZE, sizeof(uint32_t))]; } app_timer_t; 00117 00118 /**@brief Timer ID type. 00119 * Never declare a variable of this type, but use the macro @ref APP_TIMER_DEF instead.*/ 00120 typedef app_timer_t * app_timer_id_t; 00121 00122 /** 00123 * @brief Create a timer identifier and statically allocate memory for the timer. 00124 * 00125 * @param timer_id Name of the timer identifier variable that will be used to control the timer. 00126 */ 00127 #define APP_TIMER_DEF(timer_id) \ 00128 static app_timer_t timer_id##_data = { {0} }; \ 00129 static const app_timer_id_t timer_id = &timer_id##_data 00130 00131 00132 /**@brief Application time-out handler type. */ 00133 typedef void (*app_timer_timeout_handler_t)(void * p_context); 00134 00135 /**@brief Type of function for passing events from the timer module to the scheduler. */ 00136 typedef uint32_t (*app_timer_evt_schedule_func_t) (app_timer_timeout_handler_t timeout_handler, 00137 void * p_context); 00138 00139 /**@brief Timer modes. */ 00140 typedef enum 00141 { 00142 APP_TIMER_MODE_SINGLE_SHOT, /**< The timer will expire only once. */ 00143 APP_TIMER_MODE_REPEATED /**< The timer will restart each time it expires. */ 00144 } app_timer_mode_t; 00145 00146 /**@brief Initialize the application timer module. 00147 * 00148 * @details This macro handles dimensioning and allocation of the memory buffer required by the timer, 00149 * making sure that the buffer is correctly aligned. It will also connect the timer module 00150 * to the scheduler (if specified). 00151 * 00152 * @note This module assumes that the LFCLK is already running. If it is not, the module will 00153 * be non-functional, since the RTC will not run. If you do not use a SoftDevice, you 00154 * must start the LFCLK manually. See the rtc_example's lfclk_config() function 00155 * for an example of how to do this. If you use a SoftDevice, the LFCLK is started on 00156 * SoftDevice init. 00157 * 00158 * 00159 * @param[in] PRESCALER Value of the RTC1 PRESCALER register. This will decide the 00160 * timer tick rate. Set to 0 for no prescaling. 00161 * @param[in] OP_QUEUES_SIZE Size of queues holding timer operations that are pending execution. 00162 * @param[in] SCHEDULER_FUNC Pointer to scheduler event handler 00163 * 00164 * @note Since this macro allocates a buffer, it must only be called once (it is OK to call it 00165 * several times as long as it is from the same location, for example, to do a re-initialization). 00166 */ 00167 /*lint -emacro(506, APP_TIMER_INIT) */ /* Suppress "Constant value Boolean */ 00168 #define APP_TIMER_INIT(PRESCALER, OP_QUEUES_SIZE, SCHEDULER_FUNC) \ 00169 do \ 00170 { \ 00171 static uint32_t APP_TIMER_BUF[CEIL_DIV(APP_TIMER_BUF_SIZE((OP_QUEUES_SIZE) + 1), \ 00172 sizeof(uint32_t))]; \ 00173 uint32_t ERR_CODE = app_timer_init((PRESCALER), \ 00174 (OP_QUEUES_SIZE) + 1, \ 00175 APP_TIMER_BUF, \ 00176 SCHEDULER_FUNC); \ 00177 APP_ERROR_CHECK(ERR_CODE); \ 00178 } while (0) 00179 00180 00181 00182 /**@brief Function for initializing the timer module. 00183 * 00184 * Normally, initialization should be done using the APP_TIMER_INIT() macro, because that macro will both 00185 * allocate the buffers needed by the timer module (including aligning the buffers correctly) 00186 * and take care of connecting the timer module to the scheduler (if specified). 00187 * 00188 * @param[in] prescaler Value of the RTC1 PRESCALER register. Set to 0 for no prescaling. 00189 * @param[in] op_queues_size Size of queues holding timer operations that are pending 00190 * execution. Note that due to the queue implementation, this size must 00191 * be one more than the size that is actually needed. 00192 * @param[in] p_buffer Pointer to memory buffer for internal use in the app_timer 00193 * module. The size of the buffer can be computed using the 00194 * APP_TIMER_BUF_SIZE() macro. The buffer must be aligned to a 00195 * 4 byte boundary. 00196 * @param[in] evt_schedule_func Function for passing time-out events to the scheduler. Point to 00197 * app_timer_evt_schedule() to connect to the scheduler. Set to NULL 00198 * to make the timer module call the time-out handler directly from 00199 * the timer interrupt handler. 00200 * 00201 * @retval NRF_SUCCESS If the module was initialized successfully. 00202 * @retval NRF_ERROR_INVALID_PARAM If a parameter was invalid (buffer not aligned to a 4 byte 00203 * boundary or NULL). 00204 */ 00205 uint32_t app_timer_init(uint32_t prescaler, 00206 uint8_t op_queues_size, 00207 void * p_buffer, 00208 app_timer_evt_schedule_func_t evt_schedule_func); 00209 00210 /**@brief Function for creating a timer instance. 00211 * 00212 * @param[in] p_timer_id Pointer to timer identifier. 00213 * @param[in] mode Timer mode. 00214 * @param[in] timeout_handler Function to be executed when the timer expires. 00215 * 00216 * @retval NRF_SUCCESS If the timer was successfully created. 00217 * @retval NRF_ERROR_INVALID_PARAM If a parameter was invalid. 00218 * @retval NRF_ERROR_INVALID_STATE If the application timer module has not been initialized or 00219 * the timer is running. 00220 * 00221 * @note This function does the timer allocation in the caller's context. It is also not protected 00222 * by a critical region. Therefore care must be taken not to call it from several interrupt 00223 * levels simultaneously. 00224 * @note The function can be called again on the timer instance and will re-initialize the instance if 00225 * the timer is not running. 00226 * @attention The FreeRTOS and RTX app_timer implementation does not allow app_timer_create to 00227 * be called on the previously initialized instance. 00228 */ 00229 uint32_t app_timer_create(app_timer_id_t const * p_timer_id, 00230 app_timer_mode_t mode, 00231 app_timer_timeout_handler_t timeout_handler); 00232 00233 /**@brief Function for starting a timer. 00234 * 00235 * @param[in] timer_id Timer identifier. 00236 * @param[in] timeout_ticks Number of ticks (of RTC1, including prescaling) to time-out event 00237 * (minimum 5 ticks). 00238 * @param[in] p_context General purpose pointer. Will be passed to the time-out handler when 00239 * the timer expires. 00240 * 00241 * @retval NRF_SUCCESS If the timer was successfully started. 00242 * @retval NRF_ERROR_INVALID_PARAM If a parameter was invalid. 00243 * @retval NRF_ERROR_INVALID_STATE If the application timer module has not been initialized or the timer 00244 * has not been created. 00245 * @retval NRF_ERROR_NO_MEM If the timer operations queue was full. 00246 * 00247 * @note The minimum timeout_ticks value is 5. 00248 * @note For multiple active timers, time-outs occurring in close proximity to each other (in the 00249 * range of 1 to 3 ticks) will have a positive jitter of maximum 3 ticks. 00250 * @note When calling this method on a timer that is already running, the second start operation 00251 * is ignored. 00252 */ 00253 uint32_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context); 00254 00255 /**@brief Function for stopping the specified timer. 00256 * 00257 * @param[in] timer_id Timer identifier. 00258 * 00259 * @retval NRF_SUCCESS If the timer was successfully stopped. 00260 * @retval NRF_ERROR_INVALID_PARAM If a parameter was invalid. 00261 * @retval NRF_ERROR_INVALID_STATE If the application timer module has not been initialized or the timer 00262 * has not been created. 00263 * @retval NRF_ERROR_NO_MEM If the timer operations queue was full. 00264 */ 00265 uint32_t app_timer_stop(app_timer_id_t timer_id); 00266 00267 /**@brief Function for stopping all running timers. 00268 * 00269 * @retval NRF_SUCCESS If all timers were successfully stopped. 00270 * @retval NRF_ERROR_INVALID_STATE If the application timer module has not been initialized. 00271 * @retval NRF_ERROR_NO_MEM If the timer operations queue was full. 00272 */ 00273 uint32_t app_timer_stop_all(void); 00274 00275 /**@brief Function for returning the current value of the RTC1 counter. 00276 * 00277 * @param[out] p_ticks Current value of the RTC1 counter. 00278 * 00279 * @retval NRF_SUCCESS If the counter was successfully read. 00280 */ 00281 uint32_t app_timer_cnt_get(uint32_t * p_ticks); 00282 00283 /**@brief Function for computing the difference between two RTC1 counter values. 00284 * 00285 * @param[in] ticks_to Value returned by app_timer_cnt_get(). 00286 * @param[in] ticks_from Value returned by app_timer_cnt_get(). 00287 * @param[out] p_ticks_diff Number of ticks from ticks_from to ticks_to. 00288 * 00289 * @retval NRF_SUCCESS If the counter difference was successfully computed. 00290 */ 00291 uint32_t app_timer_cnt_diff_compute(uint32_t ticks_to, 00292 uint32_t ticks_from, 00293 uint32_t * p_ticks_diff); 00294 00295 #endif // APP_TIMER_H__ 00296 00297 /** @} */
Generated on Tue Jul 12 2022 14:11:18 by
