Example
Dependencies: FXAS21002 FXOS8700Q
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/ns_timer.c@0:11cc2b7889af, 2019-11-19 (annotated)
- Committer:
- maygup01
- Date:
- Tue Nov 19 09:49:38 2019 +0000
- Revision:
- 0:11cc2b7889af
Example
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
maygup01 | 0:11cc2b7889af | 1 | /* |
maygup01 | 0:11cc2b7889af | 2 | * Copyright (c) 2014-2015 ARM Limited. All rights reserved. |
maygup01 | 0:11cc2b7889af | 3 | * SPDX-License-Identifier: Apache-2.0 |
maygup01 | 0:11cc2b7889af | 4 | * Licensed under the Apache License, Version 2.0 (the License); you may |
maygup01 | 0:11cc2b7889af | 5 | * not use this file except in compliance with the License. |
maygup01 | 0:11cc2b7889af | 6 | * You may obtain a copy of the License at |
maygup01 | 0:11cc2b7889af | 7 | * |
maygup01 | 0:11cc2b7889af | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
maygup01 | 0:11cc2b7889af | 9 | * |
maygup01 | 0:11cc2b7889af | 10 | * Unless required by applicable law or agreed to in writing, software |
maygup01 | 0:11cc2b7889af | 11 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT |
maygup01 | 0:11cc2b7889af | 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
maygup01 | 0:11cc2b7889af | 13 | * See the License for the specific language governing permissions and |
maygup01 | 0:11cc2b7889af | 14 | * limitations under the License. |
maygup01 | 0:11cc2b7889af | 15 | */ |
maygup01 | 0:11cc2b7889af | 16 | |
maygup01 | 0:11cc2b7889af | 17 | #include "ns_types.h" |
maygup01 | 0:11cc2b7889af | 18 | #include "ns_list.h" |
maygup01 | 0:11cc2b7889af | 19 | #include "ns_timer.h" |
maygup01 | 0:11cc2b7889af | 20 | #include "eventOS_callback_timer.h" |
maygup01 | 0:11cc2b7889af | 21 | #include "platform/arm_hal_interrupt.h" |
maygup01 | 0:11cc2b7889af | 22 | #include "platform/arm_hal_timer.h" |
maygup01 | 0:11cc2b7889af | 23 | #include "nsdynmemLIB.h" |
maygup01 | 0:11cc2b7889af | 24 | |
maygup01 | 0:11cc2b7889af | 25 | #ifndef NS_EXCLUDE_HIGHRES_TIMER |
maygup01 | 0:11cc2b7889af | 26 | typedef enum ns_timer_state_e { |
maygup01 | 0:11cc2b7889af | 27 | NS_TIMER_ACTIVE = 0, // Will run on the next HAL interrupt |
maygup01 | 0:11cc2b7889af | 28 | NS_TIMER_HOLD, // Will run on a later HAL interrupt |
maygup01 | 0:11cc2b7889af | 29 | NS_TIMER_RUN_INTERRUPT, // Running on the interrupt we're currently handling |
maygup01 | 0:11cc2b7889af | 30 | NS_TIMER_STOP // Timer not scheduled ("start" not called since last callback) |
maygup01 | 0:11cc2b7889af | 31 | } ns_timer_state_e; |
maygup01 | 0:11cc2b7889af | 32 | |
maygup01 | 0:11cc2b7889af | 33 | typedef struct ns_timer_struct { |
maygup01 | 0:11cc2b7889af | 34 | int8_t ns_timer_id; |
maygup01 | 0:11cc2b7889af | 35 | ns_timer_state_e timer_state; |
maygup01 | 0:11cc2b7889af | 36 | uint16_t slots; |
maygup01 | 0:11cc2b7889af | 37 | uint16_t remaining_slots; |
maygup01 | 0:11cc2b7889af | 38 | void (*interrupt_handler)(int8_t, uint16_t); |
maygup01 | 0:11cc2b7889af | 39 | ns_list_link_t link; |
maygup01 | 0:11cc2b7889af | 40 | } ns_timer_struct; |
maygup01 | 0:11cc2b7889af | 41 | |
maygup01 | 0:11cc2b7889af | 42 | static NS_LIST_DEFINE(ns_timer_list, ns_timer_struct, link); |
maygup01 | 0:11cc2b7889af | 43 | |
maygup01 | 0:11cc2b7889af | 44 | #define NS_TIMER_RUNNING 1 |
maygup01 | 0:11cc2b7889af | 45 | static uint8_t ns_timer_state = 0; |
maygup01 | 0:11cc2b7889af | 46 | |
maygup01 | 0:11cc2b7889af | 47 | #ifdef ATMEGA256RFR2 |
maygup01 | 0:11cc2b7889af | 48 | #define COMPENSATION 3 |
maygup01 | 0:11cc2b7889af | 49 | #define COMPENSATION_TUNE 1 |
maygup01 | 0:11cc2b7889af | 50 | #else |
maygup01 | 0:11cc2b7889af | 51 | #define COMPENSATION 0 |
maygup01 | 0:11cc2b7889af | 52 | #define COMPENSATION_TUNE 0 |
maygup01 | 0:11cc2b7889af | 53 | #endif |
maygup01 | 0:11cc2b7889af | 54 | |
maygup01 | 0:11cc2b7889af | 55 | static void ns_timer_interrupt_handler(void); |
maygup01 | 0:11cc2b7889af | 56 | static ns_timer_struct *ns_timer_get_pointer_to_timer_struct(int8_t timer_id); |
maygup01 | 0:11cc2b7889af | 57 | static bool ns_timer_initialized = 0; |
maygup01 | 0:11cc2b7889af | 58 | |
maygup01 | 0:11cc2b7889af | 59 | int8_t eventOS_callback_timer_register(void (*timer_interrupt_handler)(int8_t, uint16_t)) |
maygup01 | 0:11cc2b7889af | 60 | { |
maygup01 | 0:11cc2b7889af | 61 | int8_t retval = -1; |
maygup01 | 0:11cc2b7889af | 62 | |
maygup01 | 0:11cc2b7889af | 63 | if (!ns_timer_initialized) { |
maygup01 | 0:11cc2b7889af | 64 | /*Set interrupt handler in HAL driver*/ |
maygup01 | 0:11cc2b7889af | 65 | platform_timer_set_cb(ns_timer_interrupt_handler); |
maygup01 | 0:11cc2b7889af | 66 | ns_timer_initialized = 1; |
maygup01 | 0:11cc2b7889af | 67 | } |
maygup01 | 0:11cc2b7889af | 68 | |
maygup01 | 0:11cc2b7889af | 69 | /*Find first free timer ID in timer list*/ |
maygup01 | 0:11cc2b7889af | 70 | /*(Note use of uint8_t to avoid overflow if we reach 0x7F)*/ |
maygup01 | 0:11cc2b7889af | 71 | for (uint8_t i = 0; i <= INT8_MAX; i++) { |
maygup01 | 0:11cc2b7889af | 72 | if (!ns_timer_get_pointer_to_timer_struct(i)) { |
maygup01 | 0:11cc2b7889af | 73 | retval = i; |
maygup01 | 0:11cc2b7889af | 74 | break; |
maygup01 | 0:11cc2b7889af | 75 | } |
maygup01 | 0:11cc2b7889af | 76 | } |
maygup01 | 0:11cc2b7889af | 77 | |
maygup01 | 0:11cc2b7889af | 78 | if (retval == -1) { |
maygup01 | 0:11cc2b7889af | 79 | return -1; |
maygup01 | 0:11cc2b7889af | 80 | } |
maygup01 | 0:11cc2b7889af | 81 | |
maygup01 | 0:11cc2b7889af | 82 | ns_timer_struct *new_timer = ns_dyn_mem_alloc(sizeof(ns_timer_struct)); |
maygup01 | 0:11cc2b7889af | 83 | if (!new_timer) { |
maygup01 | 0:11cc2b7889af | 84 | return -1; |
maygup01 | 0:11cc2b7889af | 85 | } |
maygup01 | 0:11cc2b7889af | 86 | |
maygup01 | 0:11cc2b7889af | 87 | /*Initialise new timer*/ |
maygup01 | 0:11cc2b7889af | 88 | new_timer->ns_timer_id = retval; |
maygup01 | 0:11cc2b7889af | 89 | new_timer->timer_state = NS_TIMER_STOP; |
maygup01 | 0:11cc2b7889af | 90 | new_timer->remaining_slots = 0; |
maygup01 | 0:11cc2b7889af | 91 | new_timer->interrupt_handler = timer_interrupt_handler; |
maygup01 | 0:11cc2b7889af | 92 | |
maygup01 | 0:11cc2b7889af | 93 | // Critical section sufficient as long as list can't be reordered from |
maygup01 | 0:11cc2b7889af | 94 | // interrupt, otherwise will need to cover whole routine |
maygup01 | 0:11cc2b7889af | 95 | platform_enter_critical(); |
maygup01 | 0:11cc2b7889af | 96 | ns_list_add_to_end(&ns_timer_list, new_timer); |
maygup01 | 0:11cc2b7889af | 97 | platform_exit_critical(); |
maygup01 | 0:11cc2b7889af | 98 | |
maygup01 | 0:11cc2b7889af | 99 | /*Return timer ID*/ |
maygup01 | 0:11cc2b7889af | 100 | return retval; |
maygup01 | 0:11cc2b7889af | 101 | } |
maygup01 | 0:11cc2b7889af | 102 | |
maygup01 | 0:11cc2b7889af | 103 | int8_t eventOS_callback_timer_unregister(int8_t ns_timer_id) |
maygup01 | 0:11cc2b7889af | 104 | { |
maygup01 | 0:11cc2b7889af | 105 | ns_timer_struct *current_timer; |
maygup01 | 0:11cc2b7889af | 106 | |
maygup01 | 0:11cc2b7889af | 107 | current_timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id); |
maygup01 | 0:11cc2b7889af | 108 | if (!current_timer) { |
maygup01 | 0:11cc2b7889af | 109 | return -1; |
maygup01 | 0:11cc2b7889af | 110 | } |
maygup01 | 0:11cc2b7889af | 111 | |
maygup01 | 0:11cc2b7889af | 112 | // Critical section sufficient as long as list can't be reordered from |
maygup01 | 0:11cc2b7889af | 113 | // interrupt, otherwise will need to cover whole routine |
maygup01 | 0:11cc2b7889af | 114 | platform_enter_critical(); |
maygup01 | 0:11cc2b7889af | 115 | ns_list_remove(&ns_timer_list, current_timer); |
maygup01 | 0:11cc2b7889af | 116 | platform_exit_critical(); |
maygup01 | 0:11cc2b7889af | 117 | |
maygup01 | 0:11cc2b7889af | 118 | ns_dyn_mem_free(current_timer); |
maygup01 | 0:11cc2b7889af | 119 | return 0; |
maygup01 | 0:11cc2b7889af | 120 | } |
maygup01 | 0:11cc2b7889af | 121 | |
maygup01 | 0:11cc2b7889af | 122 | |
maygup01 | 0:11cc2b7889af | 123 | static int8_t ns_timer_start_pl_timer(uint16_t pl_timer_start_slots) |
maygup01 | 0:11cc2b7889af | 124 | { |
maygup01 | 0:11cc2b7889af | 125 | /*Don't start timer with 0 slots*/ |
maygup01 | 0:11cc2b7889af | 126 | if (!pl_timer_start_slots) { |
maygup01 | 0:11cc2b7889af | 127 | pl_timer_start_slots = 1; |
maygup01 | 0:11cc2b7889af | 128 | } |
maygup01 | 0:11cc2b7889af | 129 | |
maygup01 | 0:11cc2b7889af | 130 | /*Start HAL timer*/ |
maygup01 | 0:11cc2b7889af | 131 | platform_timer_start(pl_timer_start_slots); |
maygup01 | 0:11cc2b7889af | 132 | /*Set HAL timer state to running*/ |
maygup01 | 0:11cc2b7889af | 133 | ns_timer_state |= NS_TIMER_RUNNING; |
maygup01 | 0:11cc2b7889af | 134 | return 0; |
maygup01 | 0:11cc2b7889af | 135 | } |
maygup01 | 0:11cc2b7889af | 136 | |
maygup01 | 0:11cc2b7889af | 137 | int8_t ns_timer_sleep(void) |
maygup01 | 0:11cc2b7889af | 138 | { |
maygup01 | 0:11cc2b7889af | 139 | int8_t ret_val = -1; |
maygup01 | 0:11cc2b7889af | 140 | if (ns_timer_state & NS_TIMER_RUNNING) { |
maygup01 | 0:11cc2b7889af | 141 | /*Start HAL timer*/ |
maygup01 | 0:11cc2b7889af | 142 | platform_timer_disable(); |
maygup01 | 0:11cc2b7889af | 143 | /*Set HAL timer state to running*/ |
maygup01 | 0:11cc2b7889af | 144 | ns_timer_state &= ~NS_TIMER_RUNNING; |
maygup01 | 0:11cc2b7889af | 145 | ret_val = 0; |
maygup01 | 0:11cc2b7889af | 146 | } |
maygup01 | 0:11cc2b7889af | 147 | return ret_val; |
maygup01 | 0:11cc2b7889af | 148 | } |
maygup01 | 0:11cc2b7889af | 149 | |
maygup01 | 0:11cc2b7889af | 150 | static int8_t ns_timer_get_next_running_to(void) |
maygup01 | 0:11cc2b7889af | 151 | { |
maygup01 | 0:11cc2b7889af | 152 | uint8_t hold_count = 0; |
maygup01 | 0:11cc2b7889af | 153 | ns_timer_struct *first_timer = NULL; |
maygup01 | 0:11cc2b7889af | 154 | |
maygup01 | 0:11cc2b7889af | 155 | /*Find hold-labelled timer with the least remaining slots*/ |
maygup01 | 0:11cc2b7889af | 156 | ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { |
maygup01 | 0:11cc2b7889af | 157 | if (current_timer->timer_state == NS_TIMER_HOLD) { |
maygup01 | 0:11cc2b7889af | 158 | if (!first_timer || current_timer->remaining_slots < first_timer->remaining_slots) { |
maygup01 | 0:11cc2b7889af | 159 | first_timer = current_timer; |
maygup01 | 0:11cc2b7889af | 160 | } |
maygup01 | 0:11cc2b7889af | 161 | /*For optimisation, count the found timers*/ |
maygup01 | 0:11cc2b7889af | 162 | hold_count++; |
maygup01 | 0:11cc2b7889af | 163 | } |
maygup01 | 0:11cc2b7889af | 164 | } |
maygup01 | 0:11cc2b7889af | 165 | |
maygup01 | 0:11cc2b7889af | 166 | if (!first_timer) { |
maygup01 | 0:11cc2b7889af | 167 | return 0; |
maygup01 | 0:11cc2b7889af | 168 | } |
maygup01 | 0:11cc2b7889af | 169 | |
maygup01 | 0:11cc2b7889af | 170 | /*If hold-labelled timer found, set it active and start the HAL driver*/ |
maygup01 | 0:11cc2b7889af | 171 | hold_count--; |
maygup01 | 0:11cc2b7889af | 172 | first_timer->timer_state = NS_TIMER_ACTIVE; |
maygup01 | 0:11cc2b7889af | 173 | /*Compensate time spent in timer function*/ |
maygup01 | 0:11cc2b7889af | 174 | if (first_timer->remaining_slots > COMPENSATION) { |
maygup01 | 0:11cc2b7889af | 175 | first_timer->remaining_slots -= COMPENSATION; |
maygup01 | 0:11cc2b7889af | 176 | } |
maygup01 | 0:11cc2b7889af | 177 | /*Start HAL timer*/ |
maygup01 | 0:11cc2b7889af | 178 | ns_timer_start_pl_timer(first_timer->remaining_slots); |
maygup01 | 0:11cc2b7889af | 179 | |
maygup01 | 0:11cc2b7889af | 180 | /*Update other hold-labelled timers*/ |
maygup01 | 0:11cc2b7889af | 181 | ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { |
maygup01 | 0:11cc2b7889af | 182 | if (hold_count == 0) { // early termination optimisation |
maygup01 | 0:11cc2b7889af | 183 | break; |
maygup01 | 0:11cc2b7889af | 184 | } |
maygup01 | 0:11cc2b7889af | 185 | if (current_timer->timer_state == NS_TIMER_HOLD) { |
maygup01 | 0:11cc2b7889af | 186 | if (current_timer->remaining_slots == first_timer->remaining_slots) { |
maygup01 | 0:11cc2b7889af | 187 | current_timer->timer_state = NS_TIMER_ACTIVE; |
maygup01 | 0:11cc2b7889af | 188 | } else { |
maygup01 | 0:11cc2b7889af | 189 | current_timer->remaining_slots -= first_timer->remaining_slots; |
maygup01 | 0:11cc2b7889af | 190 | /*Compensate time spent in timer function*/ |
maygup01 | 0:11cc2b7889af | 191 | if (current_timer->remaining_slots > COMPENSATION) { |
maygup01 | 0:11cc2b7889af | 192 | current_timer->remaining_slots -= COMPENSATION; |
maygup01 | 0:11cc2b7889af | 193 | } |
maygup01 | 0:11cc2b7889af | 194 | } |
maygup01 | 0:11cc2b7889af | 195 | hold_count--; |
maygup01 | 0:11cc2b7889af | 196 | } |
maygup01 | 0:11cc2b7889af | 197 | } |
maygup01 | 0:11cc2b7889af | 198 | |
maygup01 | 0:11cc2b7889af | 199 | return 0; |
maygup01 | 0:11cc2b7889af | 200 | } |
maygup01 | 0:11cc2b7889af | 201 | |
maygup01 | 0:11cc2b7889af | 202 | |
maygup01 | 0:11cc2b7889af | 203 | static ns_timer_struct *ns_timer_get_pointer_to_timer_struct(int8_t timer_id) |
maygup01 | 0:11cc2b7889af | 204 | { |
maygup01 | 0:11cc2b7889af | 205 | /*Find timer with the given ID*/ |
maygup01 | 0:11cc2b7889af | 206 | ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { |
maygup01 | 0:11cc2b7889af | 207 | if (current_timer->ns_timer_id == timer_id) { |
maygup01 | 0:11cc2b7889af | 208 | return current_timer; |
maygup01 | 0:11cc2b7889af | 209 | } |
maygup01 | 0:11cc2b7889af | 210 | } |
maygup01 | 0:11cc2b7889af | 211 | return NULL; |
maygup01 | 0:11cc2b7889af | 212 | } |
maygup01 | 0:11cc2b7889af | 213 | |
maygup01 | 0:11cc2b7889af | 214 | int8_t eventOS_callback_timer_start(int8_t ns_timer_id, uint16_t slots) |
maygup01 | 0:11cc2b7889af | 215 | { |
maygup01 | 0:11cc2b7889af | 216 | int8_t ret_val = 0; |
maygup01 | 0:11cc2b7889af | 217 | uint16_t pl_timer_remaining_slots; |
maygup01 | 0:11cc2b7889af | 218 | ns_timer_struct *timer; |
maygup01 | 0:11cc2b7889af | 219 | platform_enter_critical(); |
maygup01 | 0:11cc2b7889af | 220 | |
maygup01 | 0:11cc2b7889af | 221 | /*Find timer to be activated*/ |
maygup01 | 0:11cc2b7889af | 222 | timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id); |
maygup01 | 0:11cc2b7889af | 223 | if (!timer) { |
maygup01 | 0:11cc2b7889af | 224 | ret_val = -1; |
maygup01 | 0:11cc2b7889af | 225 | goto exit; |
maygup01 | 0:11cc2b7889af | 226 | } |
maygup01 | 0:11cc2b7889af | 227 | |
maygup01 | 0:11cc2b7889af | 228 | // XXX this assumes the timer currently isn't running? |
maygup01 | 0:11cc2b7889af | 229 | // Is event.c relying on this restarting HAL timer after ns_timer_sleep()? |
maygup01 | 0:11cc2b7889af | 230 | |
maygup01 | 0:11cc2b7889af | 231 | /*If any timers are active*/ |
maygup01 | 0:11cc2b7889af | 232 | if (ns_timer_state & NS_TIMER_RUNNING) { |
maygup01 | 0:11cc2b7889af | 233 | /*Get remaining slots of the currently activated timeout*/ |
maygup01 | 0:11cc2b7889af | 234 | pl_timer_remaining_slots = platform_timer_get_remaining_slots(); |
maygup01 | 0:11cc2b7889af | 235 | |
maygup01 | 0:11cc2b7889af | 236 | /*New timeout is shorter than currently enabled timeout*/ |
maygup01 | 0:11cc2b7889af | 237 | if (pl_timer_remaining_slots > slots) { |
maygup01 | 0:11cc2b7889af | 238 | /*Start HAL timer*/ |
maygup01 | 0:11cc2b7889af | 239 | ns_timer_start_pl_timer(slots - 0); |
maygup01 | 0:11cc2b7889af | 240 | |
maygup01 | 0:11cc2b7889af | 241 | ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { |
maygup01 | 0:11cc2b7889af | 242 | /*Switch active timers to hold*/ |
maygup01 | 0:11cc2b7889af | 243 | if (current_timer->timer_state == NS_TIMER_ACTIVE) { |
maygup01 | 0:11cc2b7889af | 244 | current_timer->timer_state = NS_TIMER_HOLD; |
maygup01 | 0:11cc2b7889af | 245 | current_timer->remaining_slots = 0; |
maygup01 | 0:11cc2b7889af | 246 | } |
maygup01 | 0:11cc2b7889af | 247 | /*Update hold-labelled timers*/ |
maygup01 | 0:11cc2b7889af | 248 | if (current_timer->timer_state == NS_TIMER_HOLD) { |
maygup01 | 0:11cc2b7889af | 249 | current_timer->remaining_slots += (pl_timer_remaining_slots - slots); |
maygup01 | 0:11cc2b7889af | 250 | /*Compensate time spent in timer function*/ |
maygup01 | 0:11cc2b7889af | 251 | if (current_timer->remaining_slots > (COMPENSATION - COMPENSATION_TUNE)) { |
maygup01 | 0:11cc2b7889af | 252 | current_timer->remaining_slots -= (COMPENSATION - COMPENSATION_TUNE); |
maygup01 | 0:11cc2b7889af | 253 | } |
maygup01 | 0:11cc2b7889af | 254 | } |
maygup01 | 0:11cc2b7889af | 255 | } |
maygup01 | 0:11cc2b7889af | 256 | /*Mark active and start the timer*/ |
maygup01 | 0:11cc2b7889af | 257 | timer->timer_state = NS_TIMER_ACTIVE; |
maygup01 | 0:11cc2b7889af | 258 | timer->slots = slots; |
maygup01 | 0:11cc2b7889af | 259 | timer->remaining_slots = slots; |
maygup01 | 0:11cc2b7889af | 260 | } |
maygup01 | 0:11cc2b7889af | 261 | |
maygup01 | 0:11cc2b7889af | 262 | /*New timeout is longer than currently enabled timeout*/ |
maygup01 | 0:11cc2b7889af | 263 | else if (pl_timer_remaining_slots < slots) { |
maygup01 | 0:11cc2b7889af | 264 | /*Mark hold and update remaining slots*/ |
maygup01 | 0:11cc2b7889af | 265 | timer->timer_state = NS_TIMER_HOLD; |
maygup01 | 0:11cc2b7889af | 266 | timer->slots = slots; |
maygup01 | 0:11cc2b7889af | 267 | timer->remaining_slots = (slots - pl_timer_remaining_slots); |
maygup01 | 0:11cc2b7889af | 268 | } |
maygup01 | 0:11cc2b7889af | 269 | /*New timeout is equal to currently enabled timeout*/ |
maygup01 | 0:11cc2b7889af | 270 | else { |
maygup01 | 0:11cc2b7889af | 271 | /*Mark it active and it will be handled in next interrupt*/ |
maygup01 | 0:11cc2b7889af | 272 | timer->timer_state = NS_TIMER_ACTIVE; |
maygup01 | 0:11cc2b7889af | 273 | timer->slots = slots; |
maygup01 | 0:11cc2b7889af | 274 | timer->remaining_slots = slots; |
maygup01 | 0:11cc2b7889af | 275 | } |
maygup01 | 0:11cc2b7889af | 276 | } else { |
maygup01 | 0:11cc2b7889af | 277 | /*No timers running*/ |
maygup01 | 0:11cc2b7889af | 278 | timer->timer_state = NS_TIMER_HOLD; |
maygup01 | 0:11cc2b7889af | 279 | timer->slots = slots; |
maygup01 | 0:11cc2b7889af | 280 | timer->remaining_slots = slots; |
maygup01 | 0:11cc2b7889af | 281 | /*Start next timeout*/ |
maygup01 | 0:11cc2b7889af | 282 | ns_timer_get_next_running_to(); |
maygup01 | 0:11cc2b7889af | 283 | } |
maygup01 | 0:11cc2b7889af | 284 | exit: |
maygup01 | 0:11cc2b7889af | 285 | platform_exit_critical(); |
maygup01 | 0:11cc2b7889af | 286 | return ret_val; |
maygup01 | 0:11cc2b7889af | 287 | } |
maygup01 | 0:11cc2b7889af | 288 | |
maygup01 | 0:11cc2b7889af | 289 | static void ns_timer_interrupt_handler(void) |
maygup01 | 0:11cc2b7889af | 290 | { |
maygup01 | 0:11cc2b7889af | 291 | uint8_t i = 0; |
maygup01 | 0:11cc2b7889af | 292 | |
maygup01 | 0:11cc2b7889af | 293 | platform_enter_critical(); |
maygup01 | 0:11cc2b7889af | 294 | /*Clear timer running state*/ |
maygup01 | 0:11cc2b7889af | 295 | ns_timer_state &= ~NS_TIMER_RUNNING; |
maygup01 | 0:11cc2b7889af | 296 | /*Mark active timers as NS_TIMER_RUN_INTERRUPT, interrupt functions are called at the end of this function*/ |
maygup01 | 0:11cc2b7889af | 297 | ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { |
maygup01 | 0:11cc2b7889af | 298 | if (current_timer->timer_state == NS_TIMER_ACTIVE) { |
maygup01 | 0:11cc2b7889af | 299 | current_timer->timer_state = NS_TIMER_RUN_INTERRUPT; |
maygup01 | 0:11cc2b7889af | 300 | /*For optimisation, count the found timers*/ |
maygup01 | 0:11cc2b7889af | 301 | i++; |
maygup01 | 0:11cc2b7889af | 302 | } |
maygup01 | 0:11cc2b7889af | 303 | } |
maygup01 | 0:11cc2b7889af | 304 | |
maygup01 | 0:11cc2b7889af | 305 | /*Start next timeout*/ |
maygup01 | 0:11cc2b7889af | 306 | ns_timer_get_next_running_to(); |
maygup01 | 0:11cc2b7889af | 307 | |
maygup01 | 0:11cc2b7889af | 308 | /*Call interrupt functions*/ |
maygup01 | 0:11cc2b7889af | 309 | ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { |
maygup01 | 0:11cc2b7889af | 310 | if (i == 0) { |
maygup01 | 0:11cc2b7889af | 311 | break; |
maygup01 | 0:11cc2b7889af | 312 | } |
maygup01 | 0:11cc2b7889af | 313 | if (current_timer->timer_state == NS_TIMER_RUN_INTERRUPT) { |
maygup01 | 0:11cc2b7889af | 314 | current_timer->timer_state = NS_TIMER_STOP; |
maygup01 | 0:11cc2b7889af | 315 | current_timer->interrupt_handler(current_timer->ns_timer_id, current_timer->slots); |
maygup01 | 0:11cc2b7889af | 316 | i--; |
maygup01 | 0:11cc2b7889af | 317 | } |
maygup01 | 0:11cc2b7889af | 318 | } |
maygup01 | 0:11cc2b7889af | 319 | |
maygup01 | 0:11cc2b7889af | 320 | platform_exit_critical(); |
maygup01 | 0:11cc2b7889af | 321 | } |
maygup01 | 0:11cc2b7889af | 322 | |
maygup01 | 0:11cc2b7889af | 323 | int8_t eventOS_callback_timer_stop(int8_t ns_timer_id) |
maygup01 | 0:11cc2b7889af | 324 | { |
maygup01 | 0:11cc2b7889af | 325 | uint16_t pl_timer_remaining_slots; |
maygup01 | 0:11cc2b7889af | 326 | bool active_timer_found = false; |
maygup01 | 0:11cc2b7889af | 327 | ns_timer_struct *current_timer; |
maygup01 | 0:11cc2b7889af | 328 | ns_timer_struct *first_timer = NULL; |
maygup01 | 0:11cc2b7889af | 329 | int8_t retval = -1; |
maygup01 | 0:11cc2b7889af | 330 | |
maygup01 | 0:11cc2b7889af | 331 | platform_enter_critical(); |
maygup01 | 0:11cc2b7889af | 332 | /*Find timer with given timer ID*/ |
maygup01 | 0:11cc2b7889af | 333 | current_timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id); |
maygup01 | 0:11cc2b7889af | 334 | if (!current_timer) { |
maygup01 | 0:11cc2b7889af | 335 | goto exit; |
maygup01 | 0:11cc2b7889af | 336 | } |
maygup01 | 0:11cc2b7889af | 337 | |
maygup01 | 0:11cc2b7889af | 338 | retval = 0; |
maygup01 | 0:11cc2b7889af | 339 | |
maygup01 | 0:11cc2b7889af | 340 | /*Check if already stopped*/ |
maygup01 | 0:11cc2b7889af | 341 | if (current_timer->timer_state == NS_TIMER_STOP) { |
maygup01 | 0:11cc2b7889af | 342 | goto exit; |
maygup01 | 0:11cc2b7889af | 343 | } |
maygup01 | 0:11cc2b7889af | 344 | |
maygup01 | 0:11cc2b7889af | 345 | current_timer->timer_state = NS_TIMER_STOP; |
maygup01 | 0:11cc2b7889af | 346 | current_timer->remaining_slots = 0; |
maygup01 | 0:11cc2b7889af | 347 | |
maygup01 | 0:11cc2b7889af | 348 | /*Check if some timer is already active*/ |
maygup01 | 0:11cc2b7889af | 349 | ns_list_foreach(ns_timer_struct, curr_timer, &ns_timer_list) { |
maygup01 | 0:11cc2b7889af | 350 | if (curr_timer->timer_state == NS_TIMER_ACTIVE) { |
maygup01 | 0:11cc2b7889af | 351 | active_timer_found = true; |
maygup01 | 0:11cc2b7889af | 352 | break; |
maygup01 | 0:11cc2b7889af | 353 | } |
maygup01 | 0:11cc2b7889af | 354 | } |
maygup01 | 0:11cc2b7889af | 355 | /*If no active timers found, start one*/ |
maygup01 | 0:11cc2b7889af | 356 | if (!active_timer_found) { |
maygup01 | 0:11cc2b7889af | 357 | pl_timer_remaining_slots = platform_timer_get_remaining_slots(); |
maygup01 | 0:11cc2b7889af | 358 | /*Find hold-labelled timer with the least remaining slots*/ |
maygup01 | 0:11cc2b7889af | 359 | ns_list_foreach(ns_timer_struct, cur_timer, &ns_timer_list) { |
maygup01 | 0:11cc2b7889af | 360 | if (cur_timer->timer_state == NS_TIMER_HOLD) { |
maygup01 | 0:11cc2b7889af | 361 | cur_timer->remaining_slots += pl_timer_remaining_slots; |
maygup01 | 0:11cc2b7889af | 362 | |
maygup01 | 0:11cc2b7889af | 363 | if (!first_timer || cur_timer->remaining_slots < first_timer->remaining_slots) { |
maygup01 | 0:11cc2b7889af | 364 | first_timer = cur_timer; |
maygup01 | 0:11cc2b7889af | 365 | } |
maygup01 | 0:11cc2b7889af | 366 | } |
maygup01 | 0:11cc2b7889af | 367 | } |
maygup01 | 0:11cc2b7889af | 368 | /*If hold-labelled timer found, set it active and start the HAL driver*/ |
maygup01 | 0:11cc2b7889af | 369 | if (first_timer) { |
maygup01 | 0:11cc2b7889af | 370 | first_timer->timer_state = NS_TIMER_ACTIVE; |
maygup01 | 0:11cc2b7889af | 371 | /*Start HAL timer*/ |
maygup01 | 0:11cc2b7889af | 372 | ns_timer_start_pl_timer(first_timer->remaining_slots); |
maygup01 | 0:11cc2b7889af | 373 | /*If some of the other hold-labelled timers have the same remaining slots as the timer_tmp, mark them active*/ |
maygup01 | 0:11cc2b7889af | 374 | ns_list_foreach(ns_timer_struct, cur_timer, &ns_timer_list) { |
maygup01 | 0:11cc2b7889af | 375 | if (cur_timer->timer_state == NS_TIMER_HOLD) { |
maygup01 | 0:11cc2b7889af | 376 | if (cur_timer->remaining_slots == first_timer->remaining_slots) { |
maygup01 | 0:11cc2b7889af | 377 | cur_timer->timer_state = NS_TIMER_ACTIVE; |
maygup01 | 0:11cc2b7889af | 378 | } else { |
maygup01 | 0:11cc2b7889af | 379 | cur_timer->remaining_slots -= first_timer->remaining_slots; |
maygup01 | 0:11cc2b7889af | 380 | } |
maygup01 | 0:11cc2b7889af | 381 | } |
maygup01 | 0:11cc2b7889af | 382 | } |
maygup01 | 0:11cc2b7889af | 383 | } |
maygup01 | 0:11cc2b7889af | 384 | } |
maygup01 | 0:11cc2b7889af | 385 | |
maygup01 | 0:11cc2b7889af | 386 | exit: |
maygup01 | 0:11cc2b7889af | 387 | platform_exit_critical(); |
maygup01 | 0:11cc2b7889af | 388 | |
maygup01 | 0:11cc2b7889af | 389 | return retval; |
maygup01 | 0:11cc2b7889af | 390 | } |
maygup01 | 0:11cc2b7889af | 391 | #endif // NS_EXCLUDE_HIGHRES_TIMER |