mbed library sources

Dependents:   frdm_kl05z_gpio_test

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Fri Aug 29 17:15:07 2014 +0100
Revision:
304:89b9c3a9a045
Synchronized with git revision 734f365d7da26ef199751f4b0d91611479b495ea

Full URL: https://github.com/mbedmicro/mbed/commit/734f365d7da26ef199751f4b0d91611479b495ea/

1. timestamp_t as an abstraction for time values managed by
Ticker. Using uint64_t for timestamp_t allows a wraparound-free
Ticker. This change forces us to update the definitions of usTicker
for all platforms; but the changes beyond nRF51822 aren't major.

2. reduce power consumption on the nRF51822 by removing the need for
the high-frequency processor timer; and reimplementing it using the
RTC.

I've also replaced high-frequency clock with low-frequency external
clock during system startup of the nRF51822. This brings a major win
in power consumption.

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