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