mbed library sources

Dependents:   STM32F103C8T6-RangoTec STM32-103C8_Plantilla_USB

Committer:
mbed_official
Date:
Tue Dec 16 08:15:08 2014 +0000
Revision:
441:8a0b45cd594f
Parent:
304:89b9c3a9a045
Synchronized with git revision 67fbbf0b635d0c0d93fbe433306c537c2ad206aa

Full URL: https://github.com/mbedmicro/mbed/commit/67fbbf0b635d0c0d93fbe433306c537c2ad206aa/

Targets: nrf51 - updating app_timer.c from Norid'c SDKv7.1.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 304:89b9c3a9a045 1 /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
mbed_official 304:89b9c3a9a045 2 *
mbed_official 304:89b9c3a9a045 3 * The information contained herein is property of Nordic Semiconductor ASA.
mbed_official 304:89b9c3a9a045 4 * Terms and conditions of usage are described in detail in NORDIC
mbed_official 304:89b9c3a9a045 5 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
mbed_official 304:89b9c3a9a045 6 *
mbed_official 304:89b9c3a9a045 7 * Licensees are granted free, non-transferable use of the information. NO
mbed_official 304:89b9c3a9a045 8 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
mbed_official 304:89b9c3a9a045 9 * the file.
mbed_official 304:89b9c3a9a045 10 *
mbed_official 304:89b9c3a9a045 11 */
mbed_official 304:89b9c3a9a045 12
mbed_official 304:89b9c3a9a045 13 #include "app_timer.h"
mbed_official 304:89b9c3a9a045 14 #include <stdlib.h>
mbed_official 304:89b9c3a9a045 15 #include "nrf51.h"
mbed_official 304:89b9c3a9a045 16 #include "nrf51_bitfields.h"
mbed_official 304:89b9c3a9a045 17 #include "nrf_soc.h"
mbed_official 304:89b9c3a9a045 18 #include "app_error.h"
mbed_official 304:89b9c3a9a045 19 #include "nrf_delay.h"
mbed_official 304:89b9c3a9a045 20 #include "app_util.h"
mbed_official 304:89b9c3a9a045 21 #include "app_util_platform.h"
mbed_official 304:89b9c3a9a045 22
mbed_official 304:89b9c3a9a045 23
mbed_official 304:89b9c3a9a045 24 #define RTC1_IRQ_PRI APP_IRQ_PRIORITY_LOW /**< Priority of the RTC1 interrupt (used for checking for timeouts and executing timeout handlers). */
mbed_official 304:89b9c3a9a045 25 #define SWI0_IRQ_PRI APP_IRQ_PRIORITY_LOW /**< Priority of the SWI0 interrupt (used for updating the timer list). */
mbed_official 304:89b9c3a9a045 26
mbed_official 304:89b9c3a9a045 27 // The current design assumes that both interrupt handlers run at the same interrupt level.
mbed_official 304:89b9c3a9a045 28 // If this is to be changed, protection must be added to prevent them from interrupting each other
mbed_official 304:89b9c3a9a045 29 // (e.g. by using guard/trigger flags).
mbed_official 304:89b9c3a9a045 30 STATIC_ASSERT(RTC1_IRQ_PRI == SWI0_IRQ_PRI);
mbed_official 304:89b9c3a9a045 31
mbed_official 304:89b9c3a9a045 32 #define APP_HIGH_USER_ID 0 /**< User Id for the Application High "user". */
mbed_official 304:89b9c3a9a045 33 #define APP_LOW_USER_ID 1 /**< User Id for the Application Low "user". */
mbed_official 304:89b9c3a9a045 34 #define THREAD_MODE_USER_ID 2 /**< User Id for the Thread Mode "user". */
mbed_official 304:89b9c3a9a045 35
mbed_official 304:89b9c3a9a045 36 #define RTC_COMPARE_OFFSET_MIN 3 /**< Minimum offset between the current RTC counter value and the Capture Compare register. Although the nRF51 Series User Specification recommends this value to be 2, we use 3 to be safer.*/
mbed_official 304:89b9c3a9a045 37
mbed_official 304:89b9c3a9a045 38 #define MAX_RTC_TASKS_DELAY 47 /**< Maximum delay until an RTC task is executed. */
mbed_official 304:89b9c3a9a045 39
mbed_official 304:89b9c3a9a045 40 /**@brief Timer allocation state type. */
mbed_official 304:89b9c3a9a045 41 typedef enum
mbed_official 304:89b9c3a9a045 42 {
mbed_official 304:89b9c3a9a045 43 STATE_FREE, /**< The timer node is available. */
mbed_official 304:89b9c3a9a045 44 STATE_ALLOCATED /**< The timer node has been allocated. */
mbed_official 304:89b9c3a9a045 45 } timer_alloc_state_t;
mbed_official 304:89b9c3a9a045 46
mbed_official 304:89b9c3a9a045 47 /**@brief Timer node type. The nodes will be used form a linked list of running timers. */
mbed_official 304:89b9c3a9a045 48 typedef struct
mbed_official 304:89b9c3a9a045 49 {
mbed_official 304:89b9c3a9a045 50 timer_alloc_state_t state; /**< Timer allocation state. */
mbed_official 304:89b9c3a9a045 51 app_timer_mode_t mode; /**< Timer mode. */
mbed_official 304:89b9c3a9a045 52 uint32_t ticks_to_expire; /**< Number of ticks from previous timer interrupt to timer expiry. */
mbed_official 304:89b9c3a9a045 53 uint32_t ticks_at_start; /**< Current RTC counter value when the timer was started. */
mbed_official 304:89b9c3a9a045 54 uint32_t ticks_first_interval; /**< Number of ticks in the first timer interval. */
mbed_official 304:89b9c3a9a045 55 uint32_t ticks_periodic_interval; /**< Timer period (for repeating timers). */
mbed_official 304:89b9c3a9a045 56 bool is_running; /**< True if timer is running, False otherwise. */
mbed_official 304:89b9c3a9a045 57 app_timer_timeout_handler_t p_timeout_handler; /**< Pointer to function to be executed when the timer expires. */
mbed_official 304:89b9c3a9a045 58 void * p_context; /**< General purpose pointer. Will be passed to the timeout handler when the timer expires. */
mbed_official 304:89b9c3a9a045 59 app_timer_id_t next; /**< Id of next timer in list of running timers. */
mbed_official 304:89b9c3a9a045 60 } timer_node_t;
mbed_official 304:89b9c3a9a045 61
mbed_official 304:89b9c3a9a045 62 STATIC_ASSERT(sizeof(timer_node_t) <= APP_TIMER_NODE_SIZE);
mbed_official 304:89b9c3a9a045 63 STATIC_ASSERT(sizeof(timer_node_t) % 4 == 0);
mbed_official 304:89b9c3a9a045 64
mbed_official 304:89b9c3a9a045 65 /**@brief Set of available timer operation types. */
mbed_official 304:89b9c3a9a045 66 typedef enum
mbed_official 304:89b9c3a9a045 67 {
mbed_official 304:89b9c3a9a045 68 TIMER_USER_OP_TYPE_NONE, /**< Invalid timer operation type. */
mbed_official 304:89b9c3a9a045 69 TIMER_USER_OP_TYPE_START, /**< Timer operation type Start. */
mbed_official 304:89b9c3a9a045 70 TIMER_USER_OP_TYPE_STOP, /**< Timer operation type Stop. */
mbed_official 304:89b9c3a9a045 71 TIMER_USER_OP_TYPE_STOP_ALL /**< Timer operation type Stop All. */
mbed_official 304:89b9c3a9a045 72 } timer_user_op_type_t;
mbed_official 304:89b9c3a9a045 73
mbed_official 304:89b9c3a9a045 74 /**@brief Structure describing a timer start operation. */
mbed_official 304:89b9c3a9a045 75 typedef struct
mbed_official 304:89b9c3a9a045 76 {
mbed_official 304:89b9c3a9a045 77 uint32_t ticks_at_start; /**< Current RTC counter value when the timer was started. */
mbed_official 304:89b9c3a9a045 78 uint32_t ticks_first_interval; /**< Number of ticks in the first timer interval. */
mbed_official 304:89b9c3a9a045 79 uint32_t ticks_periodic_interval; /**< Timer period (for repeating timers). */
mbed_official 304:89b9c3a9a045 80 void * p_context; /**< General purpose pointer. Will be passed to the timeout handler when the timer expires. */
mbed_official 304:89b9c3a9a045 81 } timer_user_op_start_t;
mbed_official 304:89b9c3a9a045 82
mbed_official 304:89b9c3a9a045 83 /**@brief Structure describing a timer operation. */
mbed_official 304:89b9c3a9a045 84 typedef struct
mbed_official 304:89b9c3a9a045 85 {
mbed_official 304:89b9c3a9a045 86 timer_user_op_type_t op_type; /**< Timer operation type. */
mbed_official 304:89b9c3a9a045 87 app_timer_id_t timer_id; /**< Id of timer on which the operation is to be performed. */
mbed_official 304:89b9c3a9a045 88 union
mbed_official 304:89b9c3a9a045 89 {
mbed_official 304:89b9c3a9a045 90 timer_user_op_start_t start; /**< Structure describing a timer start operation. */
mbed_official 304:89b9c3a9a045 91 } params;
mbed_official 304:89b9c3a9a045 92 } timer_user_op_t;
mbed_official 304:89b9c3a9a045 93
mbed_official 304:89b9c3a9a045 94 STATIC_ASSERT(sizeof(timer_user_op_t) <= APP_TIMER_USER_OP_SIZE);
mbed_official 304:89b9c3a9a045 95 STATIC_ASSERT(sizeof(timer_user_op_t) % 4 == 0);
mbed_official 304:89b9c3a9a045 96
mbed_official 304:89b9c3a9a045 97 /**@brief Structure describing a timer user.
mbed_official 304:89b9c3a9a045 98 *
mbed_official 304:89b9c3a9a045 99 * @details For each user of the timer module, there will be a timer operations queue. This queue
mbed_official 304:89b9c3a9a045 100 * will hold timer operations issued by this user until the timer interrupt handler
mbed_official 304:89b9c3a9a045 101 * processes these operations. For the current implementation, there will be one user for
mbed_official 304:89b9c3a9a045 102 * each interrupt level available to the application (APP_HIGH, APP_LOW and THREAD_MODE),
mbed_official 304:89b9c3a9a045 103 * but the module can easily be modified to e.g. have one queue per process when using an
mbed_official 304:89b9c3a9a045 104 * RTOS. The purpose of the queues is to be able to have a completely lockless timer
mbed_official 304:89b9c3a9a045 105 * implementation.
mbed_official 304:89b9c3a9a045 106 */
mbed_official 304:89b9c3a9a045 107 typedef struct
mbed_official 304:89b9c3a9a045 108 {
mbed_official 304:89b9c3a9a045 109 uint8_t first; /**< Index of first entry to have been inserted in the queue (i.e. the next entry to be executed). */
mbed_official 304:89b9c3a9a045 110 uint8_t last; /**< Index of last entry to have been inserted in the queue. */
mbed_official 304:89b9c3a9a045 111 uint8_t user_op_queue_size; /**< Queue size. */
mbed_official 304:89b9c3a9a045 112 timer_user_op_t * p_user_op_queue; /**< Queue buffer. */
mbed_official 304:89b9c3a9a045 113 } timer_user_t;
mbed_official 304:89b9c3a9a045 114
mbed_official 304:89b9c3a9a045 115 STATIC_ASSERT(sizeof(timer_user_t) == APP_TIMER_USER_SIZE);
mbed_official 304:89b9c3a9a045 116 STATIC_ASSERT(sizeof(timer_user_t) % 4 == 0);
mbed_official 304:89b9c3a9a045 117
mbed_official 304:89b9c3a9a045 118 /**@brief User id type.
mbed_official 304:89b9c3a9a045 119 *
mbed_official 304:89b9c3a9a045 120 * @details In the current implementation, this will automatically be generated from the current
mbed_official 304:89b9c3a9a045 121 * interrupt level.
mbed_official 304:89b9c3a9a045 122 */
mbed_official 304:89b9c3a9a045 123 typedef uint32_t timer_user_id_t;
mbed_official 304:89b9c3a9a045 124
mbed_official 304:89b9c3a9a045 125 #define CONTEXT_QUEUE_SIZE_MAX (2) /**< Timer internal elapsed ticks queue size. */
mbed_official 304:89b9c3a9a045 126
mbed_official 304:89b9c3a9a045 127 static uint8_t m_node_array_size; /**< Size of timer node array. */
mbed_official 304:89b9c3a9a045 128 static timer_node_t * mp_nodes = NULL; /**< Array of timer nodes. */
mbed_official 304:89b9c3a9a045 129 static uint8_t m_user_array_size; /**< Size of timer user array. */
mbed_official 304:89b9c3a9a045 130 static timer_user_t * mp_users; /**< Array of timer users. */
mbed_official 304:89b9c3a9a045 131 static app_timer_id_t m_timer_id_head; /**< First timer in list of running timers. */
mbed_official 304:89b9c3a9a045 132 static uint32_t m_ticks_latest; /**< Last known RTC counter value. */
mbed_official 304:89b9c3a9a045 133 static uint32_t m_ticks_elapsed[CONTEXT_QUEUE_SIZE_MAX]; /**< Timer internal elapsed ticks queue. */
mbed_official 304:89b9c3a9a045 134 static uint8_t m_ticks_elapsed_q_read_ind; /**< Timer internal elapsed ticks queue read index. */
mbed_official 304:89b9c3a9a045 135 static uint8_t m_ticks_elapsed_q_write_ind; /**< Timer internal elapsed ticks queue write index. */
mbed_official 304:89b9c3a9a045 136 static app_timer_evt_schedule_func_t m_evt_schedule_func; /**< Pointer to function for propagating timeout events to the scheduler. */
mbed_official 304:89b9c3a9a045 137 static bool m_rtc1_running; /**< Boolean indicating if RTC1 is running. */
mbed_official 441:8a0b45cd594f 138 static bool m_rtc1_reset; /**< Boolean indicating if RTC1 counter has been reset due to last timer removed from timer list during the timer list handling. */
mbed_official 304:89b9c3a9a045 139 static volatile uint64_t overflowBits; /**< The upper 40 bits of the 64-bit value returned by cnt_get() */
mbed_official 304:89b9c3a9a045 140
mbed_official 304:89b9c3a9a045 141
mbed_official 304:89b9c3a9a045 142 /**@brief Function for initializing the RTC1 counter.
mbed_official 304:89b9c3a9a045 143 *
mbed_official 304:89b9c3a9a045 144 * @param[in] prescaler Value of the RTC1 PRESCALER register. Set to 0 for no prescaling.
mbed_official 304:89b9c3a9a045 145 */
mbed_official 304:89b9c3a9a045 146 static void rtc1_init(uint32_t prescaler)
mbed_official 304:89b9c3a9a045 147 {
mbed_official 304:89b9c3a9a045 148 NRF_RTC1->PRESCALER = prescaler;
mbed_official 304:89b9c3a9a045 149 NVIC_SetPriority(RTC1_IRQn, RTC1_IRQ_PRI);
mbed_official 304:89b9c3a9a045 150 }
mbed_official 304:89b9c3a9a045 151
mbed_official 304:89b9c3a9a045 152
mbed_official 304:89b9c3a9a045 153 /**@brief Function for starting the RTC1 timer.
mbed_official 304:89b9c3a9a045 154 */
mbed_official 304:89b9c3a9a045 155 static void rtc1_start(void)
mbed_official 304:89b9c3a9a045 156 {
mbed_official 304:89b9c3a9a045 157 if (m_rtc1_running) {
mbed_official 304:89b9c3a9a045 158 return;
mbed_official 304:89b9c3a9a045 159 }
mbed_official 304:89b9c3a9a045 160
mbed_official 304:89b9c3a9a045 161 NRF_RTC1->EVTENSET = RTC_EVTEN_COMPARE0_Msk;
mbed_official 304:89b9c3a9a045 162 NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk | RTC_INTENSET_OVRFLW_Msk;
mbed_official 304:89b9c3a9a045 163
mbed_official 304:89b9c3a9a045 164 NVIC_ClearPendingIRQ(RTC1_IRQn);
mbed_official 304:89b9c3a9a045 165 NVIC_EnableIRQ(RTC1_IRQn);
mbed_official 304:89b9c3a9a045 166
mbed_official 304:89b9c3a9a045 167 NRF_RTC1->TASKS_START = 1;
mbed_official 304:89b9c3a9a045 168 nrf_delay_us(MAX_RTC_TASKS_DELAY);
mbed_official 304:89b9c3a9a045 169
mbed_official 304:89b9c3a9a045 170 m_rtc1_running = true;
mbed_official 304:89b9c3a9a045 171 }
mbed_official 304:89b9c3a9a045 172
mbed_official 304:89b9c3a9a045 173
mbed_official 304:89b9c3a9a045 174 /**@brief Function for stopping the RTC1 timer.
mbed_official 304:89b9c3a9a045 175 */
mbed_official 304:89b9c3a9a045 176 static void rtc1_stop(void)
mbed_official 304:89b9c3a9a045 177 {
mbed_official 304:89b9c3a9a045 178 if (!m_rtc1_running) {
mbed_official 304:89b9c3a9a045 179 return;
mbed_official 304:89b9c3a9a045 180 }
mbed_official 304:89b9c3a9a045 181
mbed_official 304:89b9c3a9a045 182 NVIC_DisableIRQ(RTC1_IRQn);
mbed_official 304:89b9c3a9a045 183
mbed_official 304:89b9c3a9a045 184 NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
mbed_official 304:89b9c3a9a045 185 NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk | RTC_INTENSET_OVRFLW_Msk;
mbed_official 304:89b9c3a9a045 186
mbed_official 304:89b9c3a9a045 187 NRF_RTC1->TASKS_STOP = 1;
mbed_official 304:89b9c3a9a045 188 nrf_delay_us(MAX_RTC_TASKS_DELAY);
mbed_official 304:89b9c3a9a045 189
mbed_official 304:89b9c3a9a045 190 NRF_RTC1->TASKS_CLEAR = 1;
mbed_official 304:89b9c3a9a045 191 m_ticks_latest = 0;
mbed_official 304:89b9c3a9a045 192 nrf_delay_us(MAX_RTC_TASKS_DELAY);
mbed_official 304:89b9c3a9a045 193
mbed_official 304:89b9c3a9a045 194 m_rtc1_running = false;
mbed_official 304:89b9c3a9a045 195 }
mbed_official 304:89b9c3a9a045 196
mbed_official 304:89b9c3a9a045 197
mbed_official 304:89b9c3a9a045 198 /**@brief Function for returning the current value of the RTC1 counter.
mbed_official 304:89b9c3a9a045 199 *
mbed_official 304:89b9c3a9a045 200 * @return Current value of the RTC1 counter.
mbed_official 304:89b9c3a9a045 201 */
mbed_official 304:89b9c3a9a045 202 static __INLINE uint32_t rtc1_counter_get(void)
mbed_official 304:89b9c3a9a045 203 {
mbed_official 304:89b9c3a9a045 204 return NRF_RTC1->COUNTER;
mbed_official 304:89b9c3a9a045 205 }
mbed_official 304:89b9c3a9a045 206
mbed_official 304:89b9c3a9a045 207
mbed_official 304:89b9c3a9a045 208 /**@brief Function for computing the difference between two RTC1 counter values.
mbed_official 304:89b9c3a9a045 209 *
mbed_official 304:89b9c3a9a045 210 * @return Number of ticks elapsed from ticks_old to ticks_now.
mbed_official 304:89b9c3a9a045 211 */
mbed_official 304:89b9c3a9a045 212 static __INLINE uint32_t ticks_diff_get(uint32_t ticks_now, uint32_t ticks_old)
mbed_official 304:89b9c3a9a045 213 {
mbed_official 304:89b9c3a9a045 214 return ((ticks_now - ticks_old) & MAX_RTC_COUNTER_VAL);
mbed_official 304:89b9c3a9a045 215 }
mbed_official 304:89b9c3a9a045 216
mbed_official 304:89b9c3a9a045 217
mbed_official 304:89b9c3a9a045 218 /**@brief Function for setting the RTC1 Capture Compare register 0, and enabling the corresponding
mbed_official 304:89b9c3a9a045 219 * event.
mbed_official 304:89b9c3a9a045 220 *
mbed_official 304:89b9c3a9a045 221 * @param[in] value New value of Capture Compare register 0.
mbed_official 304:89b9c3a9a045 222 */
mbed_official 304:89b9c3a9a045 223 static __INLINE void rtc1_compare0_set(uint32_t value)
mbed_official 304:89b9c3a9a045 224 {
mbed_official 304:89b9c3a9a045 225 NRF_RTC1->CC[0] = value;
mbed_official 304:89b9c3a9a045 226 }
mbed_official 304:89b9c3a9a045 227
mbed_official 304:89b9c3a9a045 228
mbed_official 304:89b9c3a9a045 229 /**@brief Function for inserting a timer in the timer list.
mbed_official 304:89b9c3a9a045 230 *
mbed_official 304:89b9c3a9a045 231 * @param[in] timer_id Id of timer to insert.
mbed_official 304:89b9c3a9a045 232 */
mbed_official 304:89b9c3a9a045 233 static void timer_list_insert(app_timer_id_t timer_id)
mbed_official 304:89b9c3a9a045 234 {
mbed_official 304:89b9c3a9a045 235 timer_node_t * p_timer = &mp_nodes[timer_id];
mbed_official 304:89b9c3a9a045 236
mbed_official 304:89b9c3a9a045 237 if (m_timer_id_head == TIMER_NULL)
mbed_official 304:89b9c3a9a045 238 {
mbed_official 304:89b9c3a9a045 239 m_timer_id_head = timer_id;
mbed_official 304:89b9c3a9a045 240 }
mbed_official 304:89b9c3a9a045 241 else
mbed_official 304:89b9c3a9a045 242 {
mbed_official 304:89b9c3a9a045 243 if (p_timer->ticks_to_expire <= mp_nodes[m_timer_id_head].ticks_to_expire)
mbed_official 304:89b9c3a9a045 244 {
mbed_official 304:89b9c3a9a045 245 mp_nodes[m_timer_id_head].ticks_to_expire -= p_timer->ticks_to_expire;
mbed_official 304:89b9c3a9a045 246
mbed_official 304:89b9c3a9a045 247 p_timer->next = m_timer_id_head;
mbed_official 304:89b9c3a9a045 248 m_timer_id_head = timer_id;
mbed_official 304:89b9c3a9a045 249 }
mbed_official 304:89b9c3a9a045 250 else
mbed_official 304:89b9c3a9a045 251 {
mbed_official 304:89b9c3a9a045 252 app_timer_id_t previous;
mbed_official 304:89b9c3a9a045 253 app_timer_id_t current;
mbed_official 304:89b9c3a9a045 254 uint32_t ticks_to_expire;
mbed_official 304:89b9c3a9a045 255
mbed_official 304:89b9c3a9a045 256 ticks_to_expire = p_timer->ticks_to_expire;
mbed_official 304:89b9c3a9a045 257 previous = m_timer_id_head;
mbed_official 304:89b9c3a9a045 258 current = m_timer_id_head;
mbed_official 304:89b9c3a9a045 259
mbed_official 304:89b9c3a9a045 260 while ((current != TIMER_NULL) && (ticks_to_expire > mp_nodes[current].ticks_to_expire))
mbed_official 304:89b9c3a9a045 261 {
mbed_official 304:89b9c3a9a045 262 ticks_to_expire -= mp_nodes[current].ticks_to_expire;
mbed_official 304:89b9c3a9a045 263 previous = current;
mbed_official 304:89b9c3a9a045 264 current = mp_nodes[current].next;
mbed_official 304:89b9c3a9a045 265 }
mbed_official 304:89b9c3a9a045 266
mbed_official 304:89b9c3a9a045 267 if (current != TIMER_NULL)
mbed_official 304:89b9c3a9a045 268 {
mbed_official 304:89b9c3a9a045 269 mp_nodes[current].ticks_to_expire -= ticks_to_expire;
mbed_official 304:89b9c3a9a045 270 }
mbed_official 304:89b9c3a9a045 271
mbed_official 304:89b9c3a9a045 272 p_timer->ticks_to_expire = ticks_to_expire;
mbed_official 304:89b9c3a9a045 273 p_timer->next = current;
mbed_official 304:89b9c3a9a045 274 mp_nodes[previous].next = timer_id;
mbed_official 304:89b9c3a9a045 275 }
mbed_official 304:89b9c3a9a045 276 }
mbed_official 304:89b9c3a9a045 277 }
mbed_official 304:89b9c3a9a045 278
mbed_official 304:89b9c3a9a045 279
mbed_official 304:89b9c3a9a045 280 /**@brief Function for removing a timer from the timer queue.
mbed_official 304:89b9c3a9a045 281 *
mbed_official 304:89b9c3a9a045 282 * @param[in] timer_id Id of timer to remove.
mbed_official 304:89b9c3a9a045 283 */
mbed_official 304:89b9c3a9a045 284 static void timer_list_remove(app_timer_id_t timer_id)
mbed_official 304:89b9c3a9a045 285 {
mbed_official 304:89b9c3a9a045 286 app_timer_id_t previous;
mbed_official 304:89b9c3a9a045 287 app_timer_id_t current;
mbed_official 304:89b9c3a9a045 288 uint32_t timeout;
mbed_official 304:89b9c3a9a045 289
mbed_official 304:89b9c3a9a045 290 // Find the timer's position in timer list
mbed_official 304:89b9c3a9a045 291 previous = m_timer_id_head;
mbed_official 304:89b9c3a9a045 292 current = previous;
mbed_official 304:89b9c3a9a045 293
mbed_official 304:89b9c3a9a045 294 while (current != TIMER_NULL)
mbed_official 304:89b9c3a9a045 295 {
mbed_official 304:89b9c3a9a045 296 if (current == timer_id)
mbed_official 304:89b9c3a9a045 297 {
mbed_official 304:89b9c3a9a045 298 break;
mbed_official 304:89b9c3a9a045 299 }
mbed_official 304:89b9c3a9a045 300 previous = current;
mbed_official 304:89b9c3a9a045 301 current = mp_nodes[current].next;
mbed_official 304:89b9c3a9a045 302 }
mbed_official 304:89b9c3a9a045 303
mbed_official 304:89b9c3a9a045 304 // Timer not in active list
mbed_official 304:89b9c3a9a045 305 if (current == TIMER_NULL)
mbed_official 304:89b9c3a9a045 306 {
mbed_official 304:89b9c3a9a045 307 return;
mbed_official 304:89b9c3a9a045 308 }
mbed_official 304:89b9c3a9a045 309
mbed_official 304:89b9c3a9a045 310 // Timer is the first in the list
mbed_official 304:89b9c3a9a045 311 if (previous == current)
mbed_official 304:89b9c3a9a045 312 {
mbed_official 304:89b9c3a9a045 313 m_timer_id_head = mp_nodes[m_timer_id_head].next;
mbed_official 304:89b9c3a9a045 314
mbed_official 441:8a0b45cd594f 315 // No more timers in the list. Reset RTC1 in case Start timer operations are present in the queue.
mbed_official 304:89b9c3a9a045 316 if (m_timer_id_head == TIMER_NULL)
mbed_official 304:89b9c3a9a045 317 {
mbed_official 441:8a0b45cd594f 318 NRF_RTC1->TASKS_CLEAR = 1;
mbed_official 441:8a0b45cd594f 319 m_ticks_latest = 0;
mbed_official 441:8a0b45cd594f 320 m_rtc1_reset = true;
mbed_official 304:89b9c3a9a045 321 }
mbed_official 304:89b9c3a9a045 322 }
mbed_official 304:89b9c3a9a045 323
mbed_official 304:89b9c3a9a045 324 // Remaining timeout between next timeout
mbed_official 304:89b9c3a9a045 325 timeout = mp_nodes[current].ticks_to_expire;
mbed_official 304:89b9c3a9a045 326
mbed_official 304:89b9c3a9a045 327 // Link previous timer with next of this timer, i.e. removing the timer from list
mbed_official 304:89b9c3a9a045 328 mp_nodes[previous].next = mp_nodes[current].next;
mbed_official 304:89b9c3a9a045 329
mbed_official 304:89b9c3a9a045 330 // If this is not the last timer, increment the next timer by this timer timeout
mbed_official 304:89b9c3a9a045 331 current = mp_nodes[previous].next;
mbed_official 304:89b9c3a9a045 332 if (current != TIMER_NULL)
mbed_official 304:89b9c3a9a045 333 {
mbed_official 304:89b9c3a9a045 334 mp_nodes[current].ticks_to_expire += timeout;
mbed_official 304:89b9c3a9a045 335 }
mbed_official 304:89b9c3a9a045 336 }
mbed_official 304:89b9c3a9a045 337
mbed_official 304:89b9c3a9a045 338
mbed_official 304:89b9c3a9a045 339 /**@brief Function for scheduling a check for timeouts by generating a RTC1 interrupt.
mbed_official 304:89b9c3a9a045 340 */
mbed_official 304:89b9c3a9a045 341 static void timer_timeouts_check_sched(void)
mbed_official 304:89b9c3a9a045 342 {
mbed_official 304:89b9c3a9a045 343 NVIC_SetPendingIRQ(RTC1_IRQn);
mbed_official 304:89b9c3a9a045 344 }
mbed_official 304:89b9c3a9a045 345
mbed_official 304:89b9c3a9a045 346
mbed_official 304:89b9c3a9a045 347 /**@brief Function for scheduling a timer list update by generating a SWI0 interrupt.
mbed_official 304:89b9c3a9a045 348 */
mbed_official 304:89b9c3a9a045 349 static void timer_list_handler_sched(void)
mbed_official 304:89b9c3a9a045 350 {
mbed_official 304:89b9c3a9a045 351 NVIC_SetPendingIRQ(SWI0_IRQn);
mbed_official 304:89b9c3a9a045 352 }
mbed_official 304:89b9c3a9a045 353
mbed_official 304:89b9c3a9a045 354
mbed_official 304:89b9c3a9a045 355 /**@brief Function for executing an application timeout handler, either by calling it directly, or
mbed_official 304:89b9c3a9a045 356 * by passing an event to the @ref app_scheduler.
mbed_official 304:89b9c3a9a045 357 *
mbed_official 304:89b9c3a9a045 358 * @param[in] p_timer Pointer to expired timer.
mbed_official 304:89b9c3a9a045 359 */
mbed_official 304:89b9c3a9a045 360 static void timeout_handler_exec(timer_node_t * p_timer)
mbed_official 304:89b9c3a9a045 361 {
mbed_official 304:89b9c3a9a045 362 if (m_evt_schedule_func != NULL)
mbed_official 304:89b9c3a9a045 363 {
mbed_official 304:89b9c3a9a045 364 uint32_t err_code = m_evt_schedule_func(p_timer->p_timeout_handler, p_timer->p_context);
mbed_official 304:89b9c3a9a045 365 APP_ERROR_CHECK(err_code);
mbed_official 304:89b9c3a9a045 366 }
mbed_official 304:89b9c3a9a045 367 else
mbed_official 304:89b9c3a9a045 368 {
mbed_official 304:89b9c3a9a045 369 p_timer->p_timeout_handler(p_timer->p_context);
mbed_official 304:89b9c3a9a045 370 }
mbed_official 304:89b9c3a9a045 371 }
mbed_official 304:89b9c3a9a045 372
mbed_official 304:89b9c3a9a045 373
mbed_official 304:89b9c3a9a045 374 /**@brief Function for checking for expired timers.
mbed_official 304:89b9c3a9a045 375 */
mbed_official 304:89b9c3a9a045 376 static void timer_timeouts_check(void)
mbed_official 304:89b9c3a9a045 377 {
mbed_official 304:89b9c3a9a045 378 // Handle expired of timer
mbed_official 304:89b9c3a9a045 379 if (m_timer_id_head != TIMER_NULL)
mbed_official 304:89b9c3a9a045 380 {
mbed_official 304:89b9c3a9a045 381 app_timer_id_t timer_id;
mbed_official 304:89b9c3a9a045 382 uint32_t ticks_elapsed;
mbed_official 304:89b9c3a9a045 383 uint32_t ticks_expired;
mbed_official 304:89b9c3a9a045 384
mbed_official 304:89b9c3a9a045 385 // Initialize actual elapsed ticks being consumed to 0
mbed_official 304:89b9c3a9a045 386 ticks_expired = 0;
mbed_official 304:89b9c3a9a045 387
mbed_official 304:89b9c3a9a045 388 // ticks_elapsed is collected here, job will use it
mbed_official 304:89b9c3a9a045 389 ticks_elapsed = ticks_diff_get(rtc1_counter_get(), m_ticks_latest);
mbed_official 304:89b9c3a9a045 390
mbed_official 304:89b9c3a9a045 391 // Auto variable containing the head of timers expiring
mbed_official 304:89b9c3a9a045 392 timer_id = m_timer_id_head;
mbed_official 304:89b9c3a9a045 393
mbed_official 304:89b9c3a9a045 394 // Expire all timers within ticks_elapsed and collect ticks_expired
mbed_official 304:89b9c3a9a045 395 while (timer_id != TIMER_NULL)
mbed_official 304:89b9c3a9a045 396 {
mbed_official 304:89b9c3a9a045 397 timer_node_t * p_timer;
mbed_official 304:89b9c3a9a045 398
mbed_official 304:89b9c3a9a045 399 // Auto variable for current timer node
mbed_official 304:89b9c3a9a045 400 p_timer = &mp_nodes[timer_id];
mbed_official 304:89b9c3a9a045 401
mbed_official 304:89b9c3a9a045 402 // Do nothing if timer did not expire
mbed_official 304:89b9c3a9a045 403 if (ticks_elapsed < p_timer->ticks_to_expire)
mbed_official 304:89b9c3a9a045 404 {
mbed_official 304:89b9c3a9a045 405 break;
mbed_official 304:89b9c3a9a045 406 }
mbed_official 304:89b9c3a9a045 407
mbed_official 304:89b9c3a9a045 408 // Decrement ticks_elapsed and collect expired ticks
mbed_official 304:89b9c3a9a045 409 ticks_elapsed -= p_timer->ticks_to_expire;
mbed_official 304:89b9c3a9a045 410 ticks_expired += p_timer->ticks_to_expire;
mbed_official 304:89b9c3a9a045 411
mbed_official 304:89b9c3a9a045 412 // Move to next timer
mbed_official 304:89b9c3a9a045 413 timer_id = p_timer->next;
mbed_official 304:89b9c3a9a045 414
mbed_official 304:89b9c3a9a045 415 // Execute Task
mbed_official 304:89b9c3a9a045 416 timeout_handler_exec(p_timer);
mbed_official 304:89b9c3a9a045 417 }
mbed_official 304:89b9c3a9a045 418
mbed_official 304:89b9c3a9a045 419 // Prepare to queue the ticks expired in the m_ticks_elapsed queue.
mbed_official 304:89b9c3a9a045 420 if (m_ticks_elapsed_q_read_ind == m_ticks_elapsed_q_write_ind)
mbed_official 304:89b9c3a9a045 421 {
mbed_official 304:89b9c3a9a045 422 // The read index of the queue is equal to the write index. This means the new
mbed_official 304:89b9c3a9a045 423 // value of ticks_expired should be stored at a new location in the m_ticks_elapsed
mbed_official 304:89b9c3a9a045 424 // queue (which is implemented as a double buffer).
mbed_official 304:89b9c3a9a045 425
mbed_official 304:89b9c3a9a045 426 // Check if there will be a queue overflow.
mbed_official 304:89b9c3a9a045 427 if (++m_ticks_elapsed_q_write_ind == CONTEXT_QUEUE_SIZE_MAX)
mbed_official 304:89b9c3a9a045 428 {
mbed_official 304:89b9c3a9a045 429 // There will be a queue overflow. Hence the write index should point to the start
mbed_official 304:89b9c3a9a045 430 // of the queue.
mbed_official 304:89b9c3a9a045 431 m_ticks_elapsed_q_write_ind = 0;
mbed_official 304:89b9c3a9a045 432 }
mbed_official 304:89b9c3a9a045 433 }
mbed_official 304:89b9c3a9a045 434
mbed_official 304:89b9c3a9a045 435 // Queue the ticks expired.
mbed_official 304:89b9c3a9a045 436 m_ticks_elapsed[m_ticks_elapsed_q_write_ind] = ticks_expired;
mbed_official 304:89b9c3a9a045 437
mbed_official 304:89b9c3a9a045 438 timer_list_handler_sched();
mbed_official 304:89b9c3a9a045 439 }
mbed_official 304:89b9c3a9a045 440 }
mbed_official 304:89b9c3a9a045 441
mbed_official 304:89b9c3a9a045 442
mbed_official 304:89b9c3a9a045 443 /**@brief Function for acquiring the number of ticks elapsed.
mbed_official 304:89b9c3a9a045 444 *
mbed_official 304:89b9c3a9a045 445 * @param[out] p_ticks_elapsed Number of ticks elapsed.
mbed_official 304:89b9c3a9a045 446 *
mbed_official 304:89b9c3a9a045 447 * @return TRUE if elapsed ticks was read from queue, FALSE otherwise.
mbed_official 304:89b9c3a9a045 448 */
mbed_official 304:89b9c3a9a045 449 static bool elapsed_ticks_acquire(uint32_t * p_ticks_elapsed)
mbed_official 304:89b9c3a9a045 450 {
mbed_official 304:89b9c3a9a045 451 // Pick the elapsed value from queue
mbed_official 304:89b9c3a9a045 452 if (m_ticks_elapsed_q_read_ind != m_ticks_elapsed_q_write_ind)
mbed_official 304:89b9c3a9a045 453 {
mbed_official 304:89b9c3a9a045 454 // Dequeue elapsed value
mbed_official 304:89b9c3a9a045 455 m_ticks_elapsed_q_read_ind++;
mbed_official 304:89b9c3a9a045 456 if (m_ticks_elapsed_q_read_ind == CONTEXT_QUEUE_SIZE_MAX)
mbed_official 304:89b9c3a9a045 457 {
mbed_official 304:89b9c3a9a045 458 m_ticks_elapsed_q_read_ind = 0;
mbed_official 304:89b9c3a9a045 459 }
mbed_official 304:89b9c3a9a045 460
mbed_official 304:89b9c3a9a045 461 *p_ticks_elapsed = m_ticks_elapsed[m_ticks_elapsed_q_read_ind];
mbed_official 304:89b9c3a9a045 462
mbed_official 304:89b9c3a9a045 463 m_ticks_latest += *p_ticks_elapsed;
mbed_official 304:89b9c3a9a045 464 m_ticks_latest &= MAX_RTC_COUNTER_VAL;
mbed_official 304:89b9c3a9a045 465
mbed_official 304:89b9c3a9a045 466 return true;
mbed_official 304:89b9c3a9a045 467 }
mbed_official 304:89b9c3a9a045 468 else
mbed_official 304:89b9c3a9a045 469 {
mbed_official 304:89b9c3a9a045 470 // No elapsed value in queue
mbed_official 304:89b9c3a9a045 471 *p_ticks_elapsed = 0;
mbed_official 304:89b9c3a9a045 472 return false;
mbed_official 304:89b9c3a9a045 473 }
mbed_official 304:89b9c3a9a045 474 }
mbed_official 304:89b9c3a9a045 475
mbed_official 304:89b9c3a9a045 476
mbed_official 304:89b9c3a9a045 477 /**@brief Function for handling the timer list deletions.
mbed_official 304:89b9c3a9a045 478 *
mbed_official 304:89b9c3a9a045 479 * @return TRUE if Capture Compare register must be updated, FALSE otherwise.
mbed_official 304:89b9c3a9a045 480 */
mbed_official 304:89b9c3a9a045 481 static bool list_deletions_handler(void)
mbed_official 304:89b9c3a9a045 482 {
mbed_official 304:89b9c3a9a045 483 app_timer_id_t timer_id_old_head;
mbed_official 304:89b9c3a9a045 484 uint8_t user_id;
mbed_official 304:89b9c3a9a045 485
mbed_official 304:89b9c3a9a045 486 // Remember the old head, so as to decide if new compare needs to be set
mbed_official 304:89b9c3a9a045 487 timer_id_old_head = m_timer_id_head;
mbed_official 304:89b9c3a9a045 488
mbed_official 304:89b9c3a9a045 489 user_id = m_user_array_size;
mbed_official 304:89b9c3a9a045 490 while (user_id--)
mbed_official 304:89b9c3a9a045 491 {
mbed_official 304:89b9c3a9a045 492 timer_user_t * p_user = &mp_users[user_id];
mbed_official 304:89b9c3a9a045 493 uint8_t user_ops_first = p_user->first;
mbed_official 304:89b9c3a9a045 494
mbed_official 304:89b9c3a9a045 495 while (user_ops_first != p_user->last)
mbed_official 304:89b9c3a9a045 496 {
mbed_official 304:89b9c3a9a045 497 timer_node_t * p_timer;
mbed_official 304:89b9c3a9a045 498 timer_user_op_t * p_user_op = &p_user->p_user_op_queue[user_ops_first];
mbed_official 304:89b9c3a9a045 499
mbed_official 304:89b9c3a9a045 500 // Traverse to next operation in queue
mbed_official 304:89b9c3a9a045 501 user_ops_first++;
mbed_official 304:89b9c3a9a045 502 if (user_ops_first == p_user->user_op_queue_size)
mbed_official 304:89b9c3a9a045 503 {
mbed_official 304:89b9c3a9a045 504 user_ops_first = 0;
mbed_official 304:89b9c3a9a045 505 }
mbed_official 304:89b9c3a9a045 506
mbed_official 304:89b9c3a9a045 507 switch (p_user_op->op_type)
mbed_official 304:89b9c3a9a045 508 {
mbed_official 304:89b9c3a9a045 509 case TIMER_USER_OP_TYPE_STOP:
mbed_official 304:89b9c3a9a045 510 // Delete node if timer is running
mbed_official 304:89b9c3a9a045 511 p_timer = &mp_nodes[p_user_op->timer_id];
mbed_official 304:89b9c3a9a045 512 if (p_timer->is_running)
mbed_official 304:89b9c3a9a045 513 {
mbed_official 304:89b9c3a9a045 514 timer_list_remove(p_user_op->timer_id);
mbed_official 304:89b9c3a9a045 515 p_timer->is_running = false;
mbed_official 304:89b9c3a9a045 516 }
mbed_official 304:89b9c3a9a045 517 break;
mbed_official 304:89b9c3a9a045 518
mbed_official 304:89b9c3a9a045 519 case TIMER_USER_OP_TYPE_STOP_ALL:
mbed_official 304:89b9c3a9a045 520 // Delete list of running timers, and mark all timers as not running
mbed_official 304:89b9c3a9a045 521 while (m_timer_id_head != TIMER_NULL)
mbed_official 304:89b9c3a9a045 522 {
mbed_official 304:89b9c3a9a045 523 timer_node_t * p_head = &mp_nodes[m_timer_id_head];
mbed_official 304:89b9c3a9a045 524
mbed_official 304:89b9c3a9a045 525 p_head->is_running = false;
mbed_official 304:89b9c3a9a045 526 m_timer_id_head = p_head->next;
mbed_official 304:89b9c3a9a045 527 }
mbed_official 304:89b9c3a9a045 528 break;
mbed_official 304:89b9c3a9a045 529
mbed_official 304:89b9c3a9a045 530 default:
mbed_official 304:89b9c3a9a045 531 // No implementation needed.
mbed_official 304:89b9c3a9a045 532 break;
mbed_official 304:89b9c3a9a045 533 }
mbed_official 304:89b9c3a9a045 534 }
mbed_official 304:89b9c3a9a045 535 }
mbed_official 304:89b9c3a9a045 536
mbed_official 304:89b9c3a9a045 537 // Detect change in head of the list
mbed_official 304:89b9c3a9a045 538 return (m_timer_id_head != timer_id_old_head);
mbed_official 304:89b9c3a9a045 539 }
mbed_official 304:89b9c3a9a045 540
mbed_official 304:89b9c3a9a045 541
mbed_official 304:89b9c3a9a045 542 /**@brief Function for updating the timer list for expired timers.
mbed_official 304:89b9c3a9a045 543 *
mbed_official 304:89b9c3a9a045 544 * @param[in] ticks_elapsed Number of elapsed ticks.
mbed_official 304:89b9c3a9a045 545 * @param[in] ticks_previous Previous known value of the RTC counter.
mbed_official 304:89b9c3a9a045 546 * @param[out] p_restart_list_head List of repeating timers to be restarted.
mbed_official 304:89b9c3a9a045 547 */
mbed_official 304:89b9c3a9a045 548 static void expired_timers_handler(uint32_t ticks_elapsed,
mbed_official 304:89b9c3a9a045 549 uint32_t ticks_previous,
mbed_official 304:89b9c3a9a045 550 app_timer_id_t * p_restart_list_head)
mbed_official 304:89b9c3a9a045 551 {
mbed_official 304:89b9c3a9a045 552 uint32_t ticks_expired = 0;
mbed_official 304:89b9c3a9a045 553
mbed_official 304:89b9c3a9a045 554 while (m_timer_id_head != TIMER_NULL)
mbed_official 304:89b9c3a9a045 555 {
mbed_official 304:89b9c3a9a045 556 timer_node_t * p_timer;
mbed_official 304:89b9c3a9a045 557 app_timer_id_t id_expired;
mbed_official 304:89b9c3a9a045 558
mbed_official 304:89b9c3a9a045 559 // Auto variable for current timer node
mbed_official 304:89b9c3a9a045 560 p_timer = &mp_nodes[m_timer_id_head];
mbed_official 304:89b9c3a9a045 561
mbed_official 304:89b9c3a9a045 562 // Do nothing if timer did not expire
mbed_official 304:89b9c3a9a045 563 if (ticks_elapsed < p_timer->ticks_to_expire)
mbed_official 304:89b9c3a9a045 564 {
mbed_official 304:89b9c3a9a045 565 p_timer->ticks_to_expire -= ticks_elapsed;
mbed_official 304:89b9c3a9a045 566 break;
mbed_official 304:89b9c3a9a045 567 }
mbed_official 304:89b9c3a9a045 568
mbed_official 304:89b9c3a9a045 569 // Decrement ticks_elapsed and collect expired ticks
mbed_official 304:89b9c3a9a045 570 ticks_elapsed -= p_timer->ticks_to_expire;
mbed_official 304:89b9c3a9a045 571 ticks_expired += p_timer->ticks_to_expire;
mbed_official 304:89b9c3a9a045 572
mbed_official 304:89b9c3a9a045 573 // Timer expired, set ticks_to_expire zero
mbed_official 304:89b9c3a9a045 574 p_timer->ticks_to_expire = 0;
mbed_official 304:89b9c3a9a045 575 p_timer->is_running = false;
mbed_official 304:89b9c3a9a045 576
mbed_official 304:89b9c3a9a045 577 // Remove the expired timer from head
mbed_official 304:89b9c3a9a045 578 id_expired = m_timer_id_head;
mbed_official 304:89b9c3a9a045 579 m_timer_id_head = p_timer->next;
mbed_official 304:89b9c3a9a045 580
mbed_official 304:89b9c3a9a045 581 // Timer will be restarted if periodic
mbed_official 304:89b9c3a9a045 582 if (p_timer->ticks_periodic_interval != 0)
mbed_official 304:89b9c3a9a045 583 {
mbed_official 304:89b9c3a9a045 584 p_timer->ticks_at_start = (ticks_previous + ticks_expired) & MAX_RTC_COUNTER_VAL;
mbed_official 304:89b9c3a9a045 585 p_timer->ticks_first_interval = p_timer->ticks_periodic_interval;
mbed_official 304:89b9c3a9a045 586 p_timer->next = *p_restart_list_head;
mbed_official 304:89b9c3a9a045 587 *p_restart_list_head = id_expired;
mbed_official 304:89b9c3a9a045 588 }
mbed_official 304:89b9c3a9a045 589 }
mbed_official 304:89b9c3a9a045 590 }
mbed_official 304:89b9c3a9a045 591
mbed_official 304:89b9c3a9a045 592
mbed_official 304:89b9c3a9a045 593 /**@brief Function for handling timer list insertions.
mbed_official 304:89b9c3a9a045 594 *
mbed_official 304:89b9c3a9a045 595 * @param[in] p_restart_list_head List of repeating timers to be restarted.
mbed_official 304:89b9c3a9a045 596 *
mbed_official 304:89b9c3a9a045 597 * @return TRUE if Capture Compare register must be updated, FALSE otherwise.
mbed_official 304:89b9c3a9a045 598 */
mbed_official 304:89b9c3a9a045 599 static bool list_insertions_handler(app_timer_id_t restart_list_head)
mbed_official 304:89b9c3a9a045 600 {
mbed_official 304:89b9c3a9a045 601 app_timer_id_t timer_id_old_head;
mbed_official 304:89b9c3a9a045 602 uint8_t user_id;
mbed_official 304:89b9c3a9a045 603
mbed_official 304:89b9c3a9a045 604 // Remember the old head, so as to decide if new compare needs to be set
mbed_official 304:89b9c3a9a045 605 timer_id_old_head = m_timer_id_head;
mbed_official 304:89b9c3a9a045 606
mbed_official 304:89b9c3a9a045 607 user_id = m_user_array_size;
mbed_official 304:89b9c3a9a045 608 while (user_id--)
mbed_official 304:89b9c3a9a045 609 {
mbed_official 304:89b9c3a9a045 610 timer_user_t * p_user = &mp_users[user_id];
mbed_official 304:89b9c3a9a045 611
mbed_official 304:89b9c3a9a045 612 // Handle insertions of timers
mbed_official 304:89b9c3a9a045 613 while ((restart_list_head != TIMER_NULL) || (p_user->first != p_user->last))
mbed_official 304:89b9c3a9a045 614 {
mbed_official 304:89b9c3a9a045 615 app_timer_id_t id_start;
mbed_official 304:89b9c3a9a045 616 timer_node_t * p_timer;
mbed_official 304:89b9c3a9a045 617
mbed_official 304:89b9c3a9a045 618 if (restart_list_head != TIMER_NULL)
mbed_official 304:89b9c3a9a045 619 {
mbed_official 304:89b9c3a9a045 620 id_start = restart_list_head;
mbed_official 304:89b9c3a9a045 621 p_timer = &mp_nodes[id_start];
mbed_official 304:89b9c3a9a045 622 restart_list_head = p_timer->next;
mbed_official 304:89b9c3a9a045 623 }
mbed_official 304:89b9c3a9a045 624 else
mbed_official 304:89b9c3a9a045 625 {
mbed_official 304:89b9c3a9a045 626 timer_user_op_t * p_user_op = &p_user->p_user_op_queue[p_user->first];
mbed_official 304:89b9c3a9a045 627
mbed_official 304:89b9c3a9a045 628 p_user->first++;
mbed_official 304:89b9c3a9a045 629 if (p_user->first == p_user->user_op_queue_size)
mbed_official 304:89b9c3a9a045 630 {
mbed_official 304:89b9c3a9a045 631 p_user->first = 0;
mbed_official 304:89b9c3a9a045 632 }
mbed_official 304:89b9c3a9a045 633
mbed_official 304:89b9c3a9a045 634 id_start = p_user_op->timer_id;
mbed_official 304:89b9c3a9a045 635 p_timer = &mp_nodes[id_start];
mbed_official 304:89b9c3a9a045 636
mbed_official 304:89b9c3a9a045 637 if ((p_user_op->op_type != TIMER_USER_OP_TYPE_START) || p_timer->is_running)
mbed_official 304:89b9c3a9a045 638 {
mbed_official 304:89b9c3a9a045 639 continue;
mbed_official 304:89b9c3a9a045 640 }
mbed_official 304:89b9c3a9a045 641
mbed_official 304:89b9c3a9a045 642 p_timer->ticks_at_start = p_user_op->params.start.ticks_at_start;
mbed_official 304:89b9c3a9a045 643 p_timer->ticks_first_interval = p_user_op->params.start.ticks_first_interval;
mbed_official 304:89b9c3a9a045 644 p_timer->ticks_periodic_interval = p_user_op->params.start.ticks_periodic_interval;
mbed_official 304:89b9c3a9a045 645 p_timer->p_context = p_user_op->params.start.p_context;
mbed_official 441:8a0b45cd594f 646
mbed_official 441:8a0b45cd594f 647 if (m_rtc1_reset)
mbed_official 441:8a0b45cd594f 648 {
mbed_official 441:8a0b45cd594f 649 p_timer->ticks_at_start = 0;
mbed_official 441:8a0b45cd594f 650 }
mbed_official 304:89b9c3a9a045 651 }
mbed_official 304:89b9c3a9a045 652
mbed_official 441:8a0b45cd594f 653 // Prepare the node to be inserted.
mbed_official 304:89b9c3a9a045 654 if (
mbed_official 304:89b9c3a9a045 655 ((p_timer->ticks_at_start - m_ticks_latest) & MAX_RTC_COUNTER_VAL)
mbed_official 304:89b9c3a9a045 656 <
mbed_official 304:89b9c3a9a045 657 (MAX_RTC_COUNTER_VAL / 2)
mbed_official 304:89b9c3a9a045 658 )
mbed_official 304:89b9c3a9a045 659 {
mbed_official 304:89b9c3a9a045 660 p_timer->ticks_to_expire = ticks_diff_get(p_timer->ticks_at_start, m_ticks_latest) +
mbed_official 304:89b9c3a9a045 661 p_timer->ticks_first_interval;
mbed_official 304:89b9c3a9a045 662 }
mbed_official 304:89b9c3a9a045 663 else
mbed_official 304:89b9c3a9a045 664 {
mbed_official 304:89b9c3a9a045 665 uint32_t delta_current_start;
mbed_official 304:89b9c3a9a045 666
mbed_official 304:89b9c3a9a045 667 delta_current_start = ticks_diff_get(m_ticks_latest, p_timer->ticks_at_start);
mbed_official 304:89b9c3a9a045 668 if (p_timer->ticks_first_interval > delta_current_start)
mbed_official 304:89b9c3a9a045 669 {
mbed_official 304:89b9c3a9a045 670 p_timer->ticks_to_expire = p_timer->ticks_first_interval - delta_current_start;
mbed_official 304:89b9c3a9a045 671 }
mbed_official 304:89b9c3a9a045 672 else
mbed_official 304:89b9c3a9a045 673 {
mbed_official 304:89b9c3a9a045 674 p_timer->ticks_to_expire = 0;
mbed_official 304:89b9c3a9a045 675 }
mbed_official 304:89b9c3a9a045 676 }
mbed_official 304:89b9c3a9a045 677
mbed_official 304:89b9c3a9a045 678 p_timer->ticks_at_start = 0;
mbed_official 304:89b9c3a9a045 679 p_timer->ticks_first_interval = 0;
mbed_official 304:89b9c3a9a045 680 p_timer->is_running = true;
mbed_official 304:89b9c3a9a045 681 p_timer->next = TIMER_NULL;
mbed_official 304:89b9c3a9a045 682
mbed_official 304:89b9c3a9a045 683 // Insert into list
mbed_official 304:89b9c3a9a045 684 timer_list_insert(id_start);
mbed_official 304:89b9c3a9a045 685 }
mbed_official 304:89b9c3a9a045 686 }
mbed_official 304:89b9c3a9a045 687
mbed_official 304:89b9c3a9a045 688 return (m_timer_id_head != timer_id_old_head);
mbed_official 304:89b9c3a9a045 689 }
mbed_official 304:89b9c3a9a045 690
mbed_official 304:89b9c3a9a045 691
mbed_official 304:89b9c3a9a045 692 /**@brief Function for updating the Capture Compare register.
mbed_official 304:89b9c3a9a045 693 */
mbed_official 304:89b9c3a9a045 694 static void compare_reg_update(app_timer_id_t timer_id_head_old)
mbed_official 304:89b9c3a9a045 695 {
mbed_official 304:89b9c3a9a045 696 // Setup the timeout for timers on the head of the list
mbed_official 304:89b9c3a9a045 697 if (m_timer_id_head != TIMER_NULL)
mbed_official 304:89b9c3a9a045 698 {
mbed_official 304:89b9c3a9a045 699 uint32_t ticks_to_expire = mp_nodes[m_timer_id_head].ticks_to_expire;
mbed_official 304:89b9c3a9a045 700 uint32_t pre_counter_val = rtc1_counter_get();
mbed_official 304:89b9c3a9a045 701 uint32_t cc = m_ticks_latest;
mbed_official 304:89b9c3a9a045 702 uint32_t ticks_elapsed = ticks_diff_get(pre_counter_val, cc) + RTC_COMPARE_OFFSET_MIN;
mbed_official 304:89b9c3a9a045 703
mbed_official 304:89b9c3a9a045 704 if (!m_rtc1_running)
mbed_official 304:89b9c3a9a045 705 {
mbed_official 304:89b9c3a9a045 706 // No timers were already running, start RTC
mbed_official 304:89b9c3a9a045 707 rtc1_start();
mbed_official 304:89b9c3a9a045 708 }
mbed_official 304:89b9c3a9a045 709
mbed_official 304:89b9c3a9a045 710 cc += (ticks_elapsed < ticks_to_expire) ? ticks_to_expire : ticks_elapsed;
mbed_official 304:89b9c3a9a045 711 cc &= MAX_RTC_COUNTER_VAL;
mbed_official 304:89b9c3a9a045 712
mbed_official 304:89b9c3a9a045 713 rtc1_compare0_set(cc);
mbed_official 304:89b9c3a9a045 714
mbed_official 304:89b9c3a9a045 715 uint32_t post_counter_val = rtc1_counter_get();
mbed_official 304:89b9c3a9a045 716
mbed_official 304:89b9c3a9a045 717 if ((ticks_diff_get(post_counter_val, pre_counter_val) + RTC_COMPARE_OFFSET_MIN) > ticks_diff_get(cc, pre_counter_val))
mbed_official 304:89b9c3a9a045 718 {
mbed_official 304:89b9c3a9a045 719 // When this happens the COMPARE event may not be triggered by the RTC.
mbed_official 304:89b9c3a9a045 720 // The nRF51 Series User Specification states that if the COUNTER value is N
mbed_official 304:89b9c3a9a045 721 // (i.e post_counter_val = N), writing N or N+1 to a CC register may not trigger a
mbed_official 304:89b9c3a9a045 722 // COMPARE event. Hence the RTC interrupt is forcefully pended by calling the following
mbed_official 304:89b9c3a9a045 723 // function.
mbed_official 304:89b9c3a9a045 724 timer_timeouts_check_sched();
mbed_official 304:89b9c3a9a045 725 }
mbed_official 304:89b9c3a9a045 726 }
mbed_official 304:89b9c3a9a045 727 else
mbed_official 304:89b9c3a9a045 728 {
mbed_official 304:89b9c3a9a045 729 // No timers are running, stop RTC
mbed_official 304:89b9c3a9a045 730 rtc1_stop();
mbed_official 304:89b9c3a9a045 731 }
mbed_official 304:89b9c3a9a045 732 }
mbed_official 304:89b9c3a9a045 733
mbed_official 304:89b9c3a9a045 734
mbed_official 304:89b9c3a9a045 735 /**@brief Function for handling changes to the timer list.
mbed_official 304:89b9c3a9a045 736 */
mbed_official 304:89b9c3a9a045 737 static void timer_list_handler(void)
mbed_official 304:89b9c3a9a045 738 {
mbed_official 304:89b9c3a9a045 739 app_timer_id_t restart_list_head = TIMER_NULL;
mbed_official 304:89b9c3a9a045 740 uint32_t ticks_elapsed;
mbed_official 304:89b9c3a9a045 741 uint32_t ticks_previous;
mbed_official 304:89b9c3a9a045 742 bool ticks_have_elapsed;
mbed_official 304:89b9c3a9a045 743 bool compare_update;
mbed_official 304:89b9c3a9a045 744 app_timer_id_t timer_id_head_old;
mbed_official 304:89b9c3a9a045 745
mbed_official 304:89b9c3a9a045 746 // Back up the previous known tick and previous list head
mbed_official 304:89b9c3a9a045 747 ticks_previous = m_ticks_latest;
mbed_official 304:89b9c3a9a045 748 timer_id_head_old = m_timer_id_head;
mbed_official 304:89b9c3a9a045 749
mbed_official 304:89b9c3a9a045 750 // Get number of elapsed ticks
mbed_official 304:89b9c3a9a045 751 ticks_have_elapsed = elapsed_ticks_acquire(&ticks_elapsed);
mbed_official 304:89b9c3a9a045 752
mbed_official 304:89b9c3a9a045 753 // Handle list deletions
mbed_official 304:89b9c3a9a045 754 compare_update = list_deletions_handler();
mbed_official 304:89b9c3a9a045 755
mbed_official 304:89b9c3a9a045 756 // Handle expired timers
mbed_official 304:89b9c3a9a045 757 if (ticks_have_elapsed)
mbed_official 304:89b9c3a9a045 758 {
mbed_official 304:89b9c3a9a045 759 expired_timers_handler(ticks_elapsed, ticks_previous, &restart_list_head);
mbed_official 304:89b9c3a9a045 760 compare_update = true;
mbed_official 304:89b9c3a9a045 761 }
mbed_official 304:89b9c3a9a045 762
mbed_official 304:89b9c3a9a045 763 // Handle list insertions
mbed_official 304:89b9c3a9a045 764 if (list_insertions_handler(restart_list_head))
mbed_official 304:89b9c3a9a045 765 {
mbed_official 304:89b9c3a9a045 766 compare_update = true;
mbed_official 304:89b9c3a9a045 767 }
mbed_official 304:89b9c3a9a045 768
mbed_official 304:89b9c3a9a045 769 // Update compare register if necessary
mbed_official 304:89b9c3a9a045 770 if (compare_update)
mbed_official 304:89b9c3a9a045 771 {
mbed_official 304:89b9c3a9a045 772 compare_reg_update(timer_id_head_old);
mbed_official 304:89b9c3a9a045 773 }
mbed_official 441:8a0b45cd594f 774 m_rtc1_reset = false;
mbed_official 304:89b9c3a9a045 775 }
mbed_official 304:89b9c3a9a045 776
mbed_official 304:89b9c3a9a045 777
mbed_official 304:89b9c3a9a045 778 /**@brief Function for enqueueing a new operations queue entry.
mbed_official 304:89b9c3a9a045 779 *
mbed_official 304:89b9c3a9a045 780 * @param[in] p_user User that the entry is to be enqueued for.
mbed_official 304:89b9c3a9a045 781 * @param[in] last_index Index of the next last index to be enqueued.
mbed_official 304:89b9c3a9a045 782 */
mbed_official 304:89b9c3a9a045 783 static void user_op_enque(timer_user_t * p_user, app_timer_id_t last_index)
mbed_official 304:89b9c3a9a045 784 {
mbed_official 304:89b9c3a9a045 785 p_user->last = last_index;
mbed_official 304:89b9c3a9a045 786 }
mbed_official 304:89b9c3a9a045 787
mbed_official 304:89b9c3a9a045 788
mbed_official 304:89b9c3a9a045 789 /**@brief Function for allocating a new operations queue entry.
mbed_official 304:89b9c3a9a045 790 *
mbed_official 304:89b9c3a9a045 791 * @param[in] p_user User that the entry is to be allocated for.
mbed_official 304:89b9c3a9a045 792 * @param[out] p_last_index Index of the next last index to be enqueued.
mbed_official 304:89b9c3a9a045 793 *
mbed_official 304:89b9c3a9a045 794 * @return Pointer to allocated queue entry, or NULL if queue is full.
mbed_official 304:89b9c3a9a045 795 */
mbed_official 304:89b9c3a9a045 796 static timer_user_op_t * user_op_alloc(timer_user_t * p_user, app_timer_id_t * p_last_index)
mbed_official 304:89b9c3a9a045 797 {
mbed_official 304:89b9c3a9a045 798 app_timer_id_t last;
mbed_official 304:89b9c3a9a045 799 timer_user_op_t * p_user_op;
mbed_official 304:89b9c3a9a045 800
mbed_official 304:89b9c3a9a045 801 last = p_user->last + 1;
mbed_official 304:89b9c3a9a045 802 if (last == p_user->user_op_queue_size)
mbed_official 304:89b9c3a9a045 803 {
mbed_official 304:89b9c3a9a045 804 // Overflow case.
mbed_official 304:89b9c3a9a045 805 last = 0;
mbed_official 304:89b9c3a9a045 806 }
mbed_official 304:89b9c3a9a045 807 if (last == p_user->first)
mbed_official 304:89b9c3a9a045 808 {
mbed_official 304:89b9c3a9a045 809 // Queue is full.
mbed_official 304:89b9c3a9a045 810 return NULL;
mbed_official 304:89b9c3a9a045 811 }
mbed_official 304:89b9c3a9a045 812
mbed_official 304:89b9c3a9a045 813 *p_last_index = last;
mbed_official 304:89b9c3a9a045 814 p_user_op = &p_user->p_user_op_queue[p_user->last];
mbed_official 304:89b9c3a9a045 815
mbed_official 304:89b9c3a9a045 816 return p_user_op;
mbed_official 304:89b9c3a9a045 817 }
mbed_official 304:89b9c3a9a045 818
mbed_official 304:89b9c3a9a045 819
mbed_official 304:89b9c3a9a045 820 /**@brief Function for scheduling a Timer Start operation.
mbed_official 304:89b9c3a9a045 821 *
mbed_official 304:89b9c3a9a045 822 * @param[in] user_id Id of user calling this function.
mbed_official 304:89b9c3a9a045 823 * @param[in] timer_id Id of timer to start.
mbed_official 304:89b9c3a9a045 824 * @param[in] timeout_initial Time (in ticks) to first timer expiry.
mbed_official 304:89b9c3a9a045 825 * @param[in] timeout_periodic Time (in ticks) between periodic expiries.
mbed_official 304:89b9c3a9a045 826 * @param[in] p_context General purpose pointer. Will be passed to the timeout handler when
mbed_official 304:89b9c3a9a045 827 * the timer expires.
mbed_official 304:89b9c3a9a045 828 * @return NRF_SUCCESS on success, otherwise an error code.
mbed_official 304:89b9c3a9a045 829 */
mbed_official 304:89b9c3a9a045 830 static uint32_t timer_start_op_schedule(timer_user_id_t user_id,
mbed_official 304:89b9c3a9a045 831 app_timer_id_t timer_id,
mbed_official 304:89b9c3a9a045 832 uint32_t timeout_initial,
mbed_official 304:89b9c3a9a045 833 uint32_t timeout_periodic,
mbed_official 304:89b9c3a9a045 834 void * p_context)
mbed_official 304:89b9c3a9a045 835 {
mbed_official 304:89b9c3a9a045 836 app_timer_id_t last_index;
mbed_official 304:89b9c3a9a045 837
mbed_official 304:89b9c3a9a045 838 timer_user_op_t * p_user_op = user_op_alloc(&mp_users[user_id], &last_index);
mbed_official 304:89b9c3a9a045 839 if (p_user_op == NULL)
mbed_official 304:89b9c3a9a045 840 {
mbed_official 304:89b9c3a9a045 841 return NRF_ERROR_NO_MEM;
mbed_official 304:89b9c3a9a045 842 }
mbed_official 304:89b9c3a9a045 843
mbed_official 304:89b9c3a9a045 844 p_user_op->op_type = TIMER_USER_OP_TYPE_START;
mbed_official 304:89b9c3a9a045 845 p_user_op->timer_id = timer_id;
mbed_official 304:89b9c3a9a045 846 p_user_op->params.start.ticks_at_start = rtc1_counter_get();
mbed_official 304:89b9c3a9a045 847 p_user_op->params.start.ticks_first_interval = timeout_initial;
mbed_official 304:89b9c3a9a045 848 p_user_op->params.start.ticks_periodic_interval = timeout_periodic;
mbed_official 304:89b9c3a9a045 849 p_user_op->params.start.p_context = p_context;
mbed_official 304:89b9c3a9a045 850
mbed_official 304:89b9c3a9a045 851 user_op_enque(&mp_users[user_id], last_index);
mbed_official 304:89b9c3a9a045 852
mbed_official 304:89b9c3a9a045 853 timer_list_handler_sched();
mbed_official 304:89b9c3a9a045 854
mbed_official 304:89b9c3a9a045 855 return NRF_SUCCESS;
mbed_official 304:89b9c3a9a045 856 }
mbed_official 304:89b9c3a9a045 857
mbed_official 304:89b9c3a9a045 858
mbed_official 304:89b9c3a9a045 859 /**@brief Function for scheduling a Timer Stop operation.
mbed_official 304:89b9c3a9a045 860 *
mbed_official 304:89b9c3a9a045 861 * @param[in] user_id Id of user calling this function.
mbed_official 304:89b9c3a9a045 862 * @param[in] timer_id Id of timer to stop.
mbed_official 304:89b9c3a9a045 863 *
mbed_official 304:89b9c3a9a045 864 * @return NRF_SUCCESS on successful scheduling a timer stop operation. NRF_ERROR_NO_MEM when there
mbed_official 304:89b9c3a9a045 865 * is no memory left to schedule the timer stop operation.
mbed_official 304:89b9c3a9a045 866 */
mbed_official 304:89b9c3a9a045 867 static uint32_t timer_stop_op_schedule(timer_user_id_t user_id, app_timer_id_t timer_id)
mbed_official 304:89b9c3a9a045 868 {
mbed_official 304:89b9c3a9a045 869 app_timer_id_t last_index;
mbed_official 304:89b9c3a9a045 870
mbed_official 304:89b9c3a9a045 871 timer_user_op_t * p_user_op = user_op_alloc(&mp_users[user_id], &last_index);
mbed_official 304:89b9c3a9a045 872 if (p_user_op == NULL)
mbed_official 304:89b9c3a9a045 873 {
mbed_official 304:89b9c3a9a045 874 return NRF_ERROR_NO_MEM;
mbed_official 304:89b9c3a9a045 875 }
mbed_official 304:89b9c3a9a045 876
mbed_official 304:89b9c3a9a045 877 p_user_op->op_type = TIMER_USER_OP_TYPE_STOP;
mbed_official 304:89b9c3a9a045 878 p_user_op->timer_id = timer_id;
mbed_official 304:89b9c3a9a045 879
mbed_official 304:89b9c3a9a045 880 user_op_enque(&mp_users[user_id], last_index);
mbed_official 304:89b9c3a9a045 881
mbed_official 304:89b9c3a9a045 882 timer_list_handler_sched();
mbed_official 304:89b9c3a9a045 883
mbed_official 304:89b9c3a9a045 884 return NRF_SUCCESS;
mbed_official 304:89b9c3a9a045 885 }
mbed_official 304:89b9c3a9a045 886
mbed_official 304:89b9c3a9a045 887
mbed_official 304:89b9c3a9a045 888 /**@brief Function for scheduling a Timer Stop All operation.
mbed_official 304:89b9c3a9a045 889 *
mbed_official 304:89b9c3a9a045 890 * @param[in] user_id Id of user calling this function.
mbed_official 304:89b9c3a9a045 891 */
mbed_official 304:89b9c3a9a045 892 static uint32_t timer_stop_all_op_schedule(timer_user_id_t user_id)
mbed_official 304:89b9c3a9a045 893 {
mbed_official 304:89b9c3a9a045 894 app_timer_id_t last_index;
mbed_official 304:89b9c3a9a045 895
mbed_official 304:89b9c3a9a045 896 timer_user_op_t * p_user_op = user_op_alloc(&mp_users[user_id], &last_index);
mbed_official 304:89b9c3a9a045 897 if (p_user_op == NULL)
mbed_official 304:89b9c3a9a045 898 {
mbed_official 304:89b9c3a9a045 899 return NRF_ERROR_NO_MEM;
mbed_official 304:89b9c3a9a045 900 }
mbed_official 304:89b9c3a9a045 901
mbed_official 304:89b9c3a9a045 902 p_user_op->op_type = TIMER_USER_OP_TYPE_STOP_ALL;
mbed_official 304:89b9c3a9a045 903 p_user_op->timer_id = TIMER_NULL;
mbed_official 304:89b9c3a9a045 904
mbed_official 304:89b9c3a9a045 905 user_op_enque(&mp_users[user_id], last_index);
mbed_official 304:89b9c3a9a045 906
mbed_official 304:89b9c3a9a045 907 timer_list_handler_sched();
mbed_official 304:89b9c3a9a045 908
mbed_official 304:89b9c3a9a045 909 return NRF_SUCCESS;
mbed_official 304:89b9c3a9a045 910 }
mbed_official 304:89b9c3a9a045 911
mbed_official 304:89b9c3a9a045 912
mbed_official 304:89b9c3a9a045 913 /**@brief Function for handling the RTC1 interrupt.
mbed_official 304:89b9c3a9a045 914 *
mbed_official 304:89b9c3a9a045 915 * @details Checks for timeouts, and executes timeout handlers for expired timers.
mbed_official 304:89b9c3a9a045 916 */
mbed_official 304:89b9c3a9a045 917 void RTC1_IRQHandler(void)
mbed_official 304:89b9c3a9a045 918 {
mbed_official 304:89b9c3a9a045 919 // Clear all events (also unexpected ones)
mbed_official 304:89b9c3a9a045 920 NRF_RTC1->EVENTS_COMPARE[0] = 0;
mbed_official 304:89b9c3a9a045 921 NRF_RTC1->EVENTS_COMPARE[1] = 0;
mbed_official 304:89b9c3a9a045 922 NRF_RTC1->EVENTS_COMPARE[2] = 0;
mbed_official 304:89b9c3a9a045 923 NRF_RTC1->EVENTS_COMPARE[3] = 0;
mbed_official 304:89b9c3a9a045 924 NRF_RTC1->EVENTS_TICK = 0;
mbed_official 304:89b9c3a9a045 925 if (NRF_RTC1->EVENTS_OVRFLW) {
mbed_official 304:89b9c3a9a045 926 overflowBits += (1 << 24);
mbed_official 304:89b9c3a9a045 927 }
mbed_official 304:89b9c3a9a045 928 NRF_RTC1->EVENTS_OVRFLW = 0;
mbed_official 304:89b9c3a9a045 929
mbed_official 304:89b9c3a9a045 930 // Check for expired timers
mbed_official 304:89b9c3a9a045 931 timer_timeouts_check();
mbed_official 304:89b9c3a9a045 932 }
mbed_official 304:89b9c3a9a045 933
mbed_official 304:89b9c3a9a045 934 /**@brief Function for handling the SWI0 interrupt.
mbed_official 304:89b9c3a9a045 935 *
mbed_official 304:89b9c3a9a045 936 * @details Performs all updates to the timer list.
mbed_official 304:89b9c3a9a045 937 */
mbed_official 304:89b9c3a9a045 938 void SWI0_IRQHandler(void)
mbed_official 304:89b9c3a9a045 939 {
mbed_official 304:89b9c3a9a045 940 timer_list_handler();
mbed_official 304:89b9c3a9a045 941 }
mbed_official 304:89b9c3a9a045 942
mbed_official 304:89b9c3a9a045 943 uint32_t app_timer_init(uint32_t prescaler,
mbed_official 304:89b9c3a9a045 944 uint8_t max_timers,
mbed_official 304:89b9c3a9a045 945 uint8_t op_queues_size,
mbed_official 304:89b9c3a9a045 946 void * p_buffer,
mbed_official 304:89b9c3a9a045 947 app_timer_evt_schedule_func_t evt_schedule_func)
mbed_official 304:89b9c3a9a045 948 {
mbed_official 304:89b9c3a9a045 949 int i;
mbed_official 304:89b9c3a9a045 950
mbed_official 304:89b9c3a9a045 951 // Check that buffer is correctly aligned
mbed_official 304:89b9c3a9a045 952 if (!is_word_aligned(p_buffer))
mbed_official 304:89b9c3a9a045 953 {
mbed_official 304:89b9c3a9a045 954 return NRF_ERROR_INVALID_PARAM;
mbed_official 304:89b9c3a9a045 955 }
mbed_official 304:89b9c3a9a045 956 // Check for NULL buffer
mbed_official 304:89b9c3a9a045 957 if (p_buffer == NULL)
mbed_official 304:89b9c3a9a045 958 {
mbed_official 304:89b9c3a9a045 959 return NRF_ERROR_INVALID_PARAM;
mbed_official 304:89b9c3a9a045 960 }
mbed_official 304:89b9c3a9a045 961
mbed_official 304:89b9c3a9a045 962 // Stop RTC to prevent any running timers from expiring (in case of reinitialization)
mbed_official 304:89b9c3a9a045 963 rtc1_stop();
mbed_official 304:89b9c3a9a045 964
mbed_official 304:89b9c3a9a045 965 m_evt_schedule_func = evt_schedule_func;
mbed_official 304:89b9c3a9a045 966
mbed_official 304:89b9c3a9a045 967 // Initialize timer node array
mbed_official 304:89b9c3a9a045 968 m_node_array_size = max_timers;
mbed_official 304:89b9c3a9a045 969 mp_nodes = (timer_node_t *) p_buffer;
mbed_official 304:89b9c3a9a045 970
mbed_official 304:89b9c3a9a045 971 for (i = 0; i < max_timers; i++)
mbed_official 304:89b9c3a9a045 972 {
mbed_official 304:89b9c3a9a045 973 mp_nodes[i].state = STATE_FREE;
mbed_official 304:89b9c3a9a045 974 mp_nodes[i].is_running = false;
mbed_official 304:89b9c3a9a045 975 }
mbed_official 304:89b9c3a9a045 976
mbed_official 304:89b9c3a9a045 977 // Skip timer node array
mbed_official 304:89b9c3a9a045 978 p_buffer = &((uint8_t *)p_buffer)[max_timers * sizeof(timer_node_t)];
mbed_official 304:89b9c3a9a045 979
mbed_official 304:89b9c3a9a045 980 // Initialize users array
mbed_official 304:89b9c3a9a045 981 m_user_array_size = APP_TIMER_INT_LEVELS;
mbed_official 304:89b9c3a9a045 982 mp_users = (timer_user_t *) p_buffer;
mbed_official 304:89b9c3a9a045 983
mbed_official 304:89b9c3a9a045 984 // Skip user array
mbed_official 304:89b9c3a9a045 985 p_buffer = &((uint8_t *)p_buffer)[APP_TIMER_INT_LEVELS * sizeof(timer_user_t)];
mbed_official 304:89b9c3a9a045 986
mbed_official 304:89b9c3a9a045 987 // Initialize operation queues
mbed_official 304:89b9c3a9a045 988 for (i = 0; i < APP_TIMER_INT_LEVELS; i++)
mbed_official 304:89b9c3a9a045 989 {
mbed_official 304:89b9c3a9a045 990 timer_user_t * p_user = &mp_users[i];
mbed_official 304:89b9c3a9a045 991
mbed_official 304:89b9c3a9a045 992 p_user->first = 0;
mbed_official 304:89b9c3a9a045 993 p_user->last = 0;
mbed_official 304:89b9c3a9a045 994 p_user->user_op_queue_size = op_queues_size;
mbed_official 304:89b9c3a9a045 995 p_user->p_user_op_queue = (timer_user_op_t *) p_buffer;
mbed_official 304:89b9c3a9a045 996
mbed_official 304:89b9c3a9a045 997 // Skip operation queue
mbed_official 304:89b9c3a9a045 998 p_buffer = &((uint8_t *)p_buffer)[op_queues_size * sizeof(timer_user_op_t)];
mbed_official 304:89b9c3a9a045 999 }
mbed_official 304:89b9c3a9a045 1000
mbed_official 304:89b9c3a9a045 1001 m_timer_id_head = TIMER_NULL;
mbed_official 304:89b9c3a9a045 1002 m_ticks_elapsed_q_read_ind = 0;
mbed_official 304:89b9c3a9a045 1003 m_ticks_elapsed_q_write_ind = 0;
mbed_official 304:89b9c3a9a045 1004
mbed_official 304:89b9c3a9a045 1005 NVIC_ClearPendingIRQ(SWI0_IRQn);
mbed_official 304:89b9c3a9a045 1006 NVIC_SetPriority(SWI0_IRQn, SWI0_IRQ_PRI);
mbed_official 304:89b9c3a9a045 1007 NVIC_EnableIRQ(SWI0_IRQn);
mbed_official 304:89b9c3a9a045 1008
mbed_official 304:89b9c3a9a045 1009 rtc1_init(prescaler);
mbed_official 304:89b9c3a9a045 1010 rtc1_start();
mbed_official 304:89b9c3a9a045 1011
mbed_official 304:89b9c3a9a045 1012 m_ticks_latest = rtc1_counter_get();
mbed_official 304:89b9c3a9a045 1013
mbed_official 304:89b9c3a9a045 1014 return NRF_SUCCESS;
mbed_official 304:89b9c3a9a045 1015 }
mbed_official 304:89b9c3a9a045 1016
mbed_official 304:89b9c3a9a045 1017
mbed_official 304:89b9c3a9a045 1018 uint32_t app_timer_create(app_timer_id_t * p_timer_id,
mbed_official 304:89b9c3a9a045 1019 app_timer_mode_t mode,
mbed_official 304:89b9c3a9a045 1020 app_timer_timeout_handler_t timeout_handler)
mbed_official 304:89b9c3a9a045 1021 {
mbed_official 304:89b9c3a9a045 1022 int i;
mbed_official 304:89b9c3a9a045 1023
mbed_official 304:89b9c3a9a045 1024 // Check state and parameters
mbed_official 304:89b9c3a9a045 1025 if (mp_nodes == NULL)
mbed_official 304:89b9c3a9a045 1026 {
mbed_official 304:89b9c3a9a045 1027 return NRF_ERROR_INVALID_STATE;
mbed_official 304:89b9c3a9a045 1028 }
mbed_official 304:89b9c3a9a045 1029 if (timeout_handler == NULL)
mbed_official 304:89b9c3a9a045 1030 {
mbed_official 304:89b9c3a9a045 1031 return NRF_ERROR_INVALID_PARAM;
mbed_official 304:89b9c3a9a045 1032 }
mbed_official 304:89b9c3a9a045 1033 if (p_timer_id == NULL)
mbed_official 304:89b9c3a9a045 1034 {
mbed_official 304:89b9c3a9a045 1035 return NRF_ERROR_INVALID_PARAM;
mbed_official 304:89b9c3a9a045 1036 }
mbed_official 304:89b9c3a9a045 1037
mbed_official 304:89b9c3a9a045 1038 // Find free timer
mbed_official 304:89b9c3a9a045 1039 for (i = 0; i < m_node_array_size; i++)
mbed_official 304:89b9c3a9a045 1040 {
mbed_official 304:89b9c3a9a045 1041 if (mp_nodes[i].state == STATE_FREE)
mbed_official 304:89b9c3a9a045 1042 {
mbed_official 304:89b9c3a9a045 1043 mp_nodes[i].state = STATE_ALLOCATED;
mbed_official 304:89b9c3a9a045 1044 mp_nodes[i].mode = mode;
mbed_official 304:89b9c3a9a045 1045 mp_nodes[i].p_timeout_handler = timeout_handler;
mbed_official 304:89b9c3a9a045 1046
mbed_official 304:89b9c3a9a045 1047 *p_timer_id = i;
mbed_official 304:89b9c3a9a045 1048 return NRF_SUCCESS;
mbed_official 304:89b9c3a9a045 1049 }
mbed_official 304:89b9c3a9a045 1050 }
mbed_official 304:89b9c3a9a045 1051
mbed_official 304:89b9c3a9a045 1052 return NRF_ERROR_NO_MEM;
mbed_official 304:89b9c3a9a045 1053 }
mbed_official 304:89b9c3a9a045 1054
mbed_official 304:89b9c3a9a045 1055
mbed_official 304:89b9c3a9a045 1056 /**@brief Function for creating a timer user id from the current interrupt level.
mbed_official 304:89b9c3a9a045 1057 *
mbed_official 304:89b9c3a9a045 1058 * @return Timer user id.
mbed_official 304:89b9c3a9a045 1059 */
mbed_official 304:89b9c3a9a045 1060 static timer_user_id_t user_id_get(void)
mbed_official 304:89b9c3a9a045 1061 {
mbed_official 304:89b9c3a9a045 1062 timer_user_id_t ret;
mbed_official 304:89b9c3a9a045 1063
mbed_official 304:89b9c3a9a045 1064 STATIC_ASSERT(APP_TIMER_INT_LEVELS == 3);
mbed_official 304:89b9c3a9a045 1065
mbed_official 304:89b9c3a9a045 1066 switch (current_int_priority_get())
mbed_official 304:89b9c3a9a045 1067 {
mbed_official 304:89b9c3a9a045 1068 case APP_IRQ_PRIORITY_HIGH:
mbed_official 304:89b9c3a9a045 1069 ret = APP_HIGH_USER_ID;
mbed_official 304:89b9c3a9a045 1070 break;
mbed_official 304:89b9c3a9a045 1071
mbed_official 304:89b9c3a9a045 1072 case APP_IRQ_PRIORITY_LOW:
mbed_official 304:89b9c3a9a045 1073 ret = APP_LOW_USER_ID;
mbed_official 304:89b9c3a9a045 1074 break;
mbed_official 304:89b9c3a9a045 1075
mbed_official 304:89b9c3a9a045 1076 default:
mbed_official 304:89b9c3a9a045 1077 ret = THREAD_MODE_USER_ID;
mbed_official 304:89b9c3a9a045 1078 break;
mbed_official 304:89b9c3a9a045 1079 }
mbed_official 304:89b9c3a9a045 1080
mbed_official 304:89b9c3a9a045 1081 return ret;
mbed_official 304:89b9c3a9a045 1082 }
mbed_official 304:89b9c3a9a045 1083
mbed_official 304:89b9c3a9a045 1084
mbed_official 304:89b9c3a9a045 1085 uint32_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context)
mbed_official 304:89b9c3a9a045 1086 {
mbed_official 304:89b9c3a9a045 1087 uint32_t timeout_periodic;
mbed_official 304:89b9c3a9a045 1088
mbed_official 304:89b9c3a9a045 1089 // Check state and parameters
mbed_official 304:89b9c3a9a045 1090 if (mp_nodes == NULL)
mbed_official 304:89b9c3a9a045 1091 {
mbed_official 304:89b9c3a9a045 1092 return NRF_ERROR_INVALID_STATE;
mbed_official 304:89b9c3a9a045 1093 }
mbed_official 304:89b9c3a9a045 1094 if ((timer_id >= m_node_array_size) || (timeout_ticks < APP_TIMER_MIN_TIMEOUT_TICKS))
mbed_official 304:89b9c3a9a045 1095 {
mbed_official 304:89b9c3a9a045 1096 return NRF_ERROR_INVALID_PARAM;
mbed_official 304:89b9c3a9a045 1097 }
mbed_official 304:89b9c3a9a045 1098 if (mp_nodes[timer_id].state != STATE_ALLOCATED)
mbed_official 304:89b9c3a9a045 1099 {
mbed_official 304:89b9c3a9a045 1100 return NRF_ERROR_INVALID_STATE;
mbed_official 304:89b9c3a9a045 1101 }
mbed_official 304:89b9c3a9a045 1102
mbed_official 304:89b9c3a9a045 1103 // Schedule timer start operation
mbed_official 304:89b9c3a9a045 1104 timeout_periodic = (mp_nodes[timer_id].mode == APP_TIMER_MODE_REPEATED) ? timeout_ticks : 0;
mbed_official 304:89b9c3a9a045 1105
mbed_official 304:89b9c3a9a045 1106 return timer_start_op_schedule(user_id_get(),
mbed_official 304:89b9c3a9a045 1107 timer_id,
mbed_official 304:89b9c3a9a045 1108 timeout_ticks,
mbed_official 304:89b9c3a9a045 1109 timeout_periodic,
mbed_official 304:89b9c3a9a045 1110 p_context);
mbed_official 304:89b9c3a9a045 1111 }
mbed_official 304:89b9c3a9a045 1112
mbed_official 304:89b9c3a9a045 1113
mbed_official 304:89b9c3a9a045 1114 uint32_t app_timer_stop(app_timer_id_t timer_id)
mbed_official 304:89b9c3a9a045 1115 {
mbed_official 304:89b9c3a9a045 1116 // Check state and parameters
mbed_official 304:89b9c3a9a045 1117 if (mp_nodes == NULL)
mbed_official 304:89b9c3a9a045 1118 {
mbed_official 304:89b9c3a9a045 1119 return NRF_ERROR_INVALID_STATE;
mbed_official 304:89b9c3a9a045 1120 }
mbed_official 304:89b9c3a9a045 1121 if (timer_id >= m_node_array_size)
mbed_official 304:89b9c3a9a045 1122 {
mbed_official 304:89b9c3a9a045 1123 return NRF_ERROR_INVALID_PARAM;
mbed_official 304:89b9c3a9a045 1124 }
mbed_official 304:89b9c3a9a045 1125 if (mp_nodes[timer_id].state != STATE_ALLOCATED)
mbed_official 304:89b9c3a9a045 1126 {
mbed_official 304:89b9c3a9a045 1127 return NRF_ERROR_INVALID_STATE;
mbed_official 304:89b9c3a9a045 1128 }
mbed_official 304:89b9c3a9a045 1129
mbed_official 304:89b9c3a9a045 1130 // Schedule timer stop operation
mbed_official 304:89b9c3a9a045 1131 return timer_stop_op_schedule(user_id_get(), timer_id);
mbed_official 304:89b9c3a9a045 1132 }
mbed_official 304:89b9c3a9a045 1133
mbed_official 304:89b9c3a9a045 1134
mbed_official 304:89b9c3a9a045 1135 uint32_t app_timer_stop_all(void)
mbed_official 304:89b9c3a9a045 1136 {
mbed_official 304:89b9c3a9a045 1137 // Check state
mbed_official 304:89b9c3a9a045 1138 if (mp_nodes == NULL)
mbed_official 304:89b9c3a9a045 1139 {
mbed_official 304:89b9c3a9a045 1140 return NRF_ERROR_INVALID_STATE;
mbed_official 304:89b9c3a9a045 1141 }
mbed_official 304:89b9c3a9a045 1142
mbed_official 304:89b9c3a9a045 1143 return timer_stop_all_op_schedule(user_id_get());
mbed_official 304:89b9c3a9a045 1144 }
mbed_official 304:89b9c3a9a045 1145
mbed_official 304:89b9c3a9a045 1146
mbed_official 304:89b9c3a9a045 1147 uint32_t app_timer_cnt_get(uint64_t * p_ticks)
mbed_official 304:89b9c3a9a045 1148 {
mbed_official 304:89b9c3a9a045 1149 *p_ticks = overflowBits | rtc1_counter_get();
mbed_official 304:89b9c3a9a045 1150 return NRF_SUCCESS;
mbed_official 304:89b9c3a9a045 1151 }
mbed_official 304:89b9c3a9a045 1152
mbed_official 304:89b9c3a9a045 1153
mbed_official 304:89b9c3a9a045 1154 uint32_t app_timer_cnt_diff_compute(uint32_t ticks_to,
mbed_official 304:89b9c3a9a045 1155 uint32_t ticks_from,
mbed_official 304:89b9c3a9a045 1156 uint32_t * p_ticks_diff)
mbed_official 304:89b9c3a9a045 1157 {
mbed_official 304:89b9c3a9a045 1158 *p_ticks_diff = ticks_diff_get(ticks_to, ticks_from);
mbed_official 304:89b9c3a9a045 1159 return NRF_SUCCESS;
mbed_official 304:89b9c3a9a045 1160 }