leo hendrickson
/
S
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/system_timer.c@0:25fa8795676b, 2021-04-18 (annotated)
- Committer:
- leothedragon
- Date:
- Sun Apr 18 15:20:23 2021 +0000
- Revision:
- 0:25fa8795676b
DS
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
leothedragon | 0:25fa8795676b | 1 | /* |
leothedragon | 0:25fa8795676b | 2 | * Copyright (c) 2014-2015 ARM Limited. All rights reserved. |
leothedragon | 0:25fa8795676b | 3 | * SPDX-License-Identifier: Apache-2.0 |
leothedragon | 0:25fa8795676b | 4 | * Licensed under the Apache License, Version 2.0 (the License); you may |
leothedragon | 0:25fa8795676b | 5 | * not use this file except in compliance with the License. |
leothedragon | 0:25fa8795676b | 6 | * You may obtain a copy of the License at |
leothedragon | 0:25fa8795676b | 7 | * |
leothedragon | 0:25fa8795676b | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
leothedragon | 0:25fa8795676b | 9 | * |
leothedragon | 0:25fa8795676b | 10 | * Unless required by applicable law or agreed to in writing, software |
leothedragon | 0:25fa8795676b | 11 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT |
leothedragon | 0:25fa8795676b | 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
leothedragon | 0:25fa8795676b | 13 | * See the License for the specific language governing permissions and |
leothedragon | 0:25fa8795676b | 14 | * limitations under the License. |
leothedragon | 0:25fa8795676b | 15 | */ |
leothedragon | 0:25fa8795676b | 16 | #include "ns_types.h" |
leothedragon | 0:25fa8795676b | 17 | #include "ns_list.h" |
leothedragon | 0:25fa8795676b | 18 | #include "timer_sys.h" |
leothedragon | 0:25fa8795676b | 19 | #include "platform/arm_hal_interrupt.h" |
leothedragon | 0:25fa8795676b | 20 | #include "platform/arm_hal_timer.h" |
leothedragon | 0:25fa8795676b | 21 | #include "nsdynmemLIB.h" |
leothedragon | 0:25fa8795676b | 22 | #include "eventOS_event.h" |
leothedragon | 0:25fa8795676b | 23 | #include "eventOS_event_timer.h" |
leothedragon | 0:25fa8795676b | 24 | #include "event.h" |
leothedragon | 0:25fa8795676b | 25 | #include "eventOS_callback_timer.h" |
leothedragon | 0:25fa8795676b | 26 | |
leothedragon | 0:25fa8795676b | 27 | #include "ns_timer.h" |
leothedragon | 0:25fa8795676b | 28 | |
leothedragon | 0:25fa8795676b | 29 | #ifndef ST_MAX |
leothedragon | 0:25fa8795676b | 30 | #define ST_MAX 6 |
leothedragon | 0:25fa8795676b | 31 | #endif |
leothedragon | 0:25fa8795676b | 32 | |
leothedragon | 0:25fa8795676b | 33 | static sys_timer_struct_s startup_sys_timer_pool[ST_MAX]; |
leothedragon | 0:25fa8795676b | 34 | |
leothedragon | 0:25fa8795676b | 35 | #define TIMER_SLOTS_PER_MS 20 |
leothedragon | 0:25fa8795676b | 36 | NS_STATIC_ASSERT(1000 % EVENTOS_EVENT_TIMER_HZ == 0, "Need whole number of ms per tick") |
leothedragon | 0:25fa8795676b | 37 | #define TIMER_SYS_TICK_PERIOD (1000 / EVENTOS_EVENT_TIMER_HZ) // milliseconds |
leothedragon | 0:25fa8795676b | 38 | |
leothedragon | 0:25fa8795676b | 39 | // timer_sys_ticks must be read in critical section to guarantee |
leothedragon | 0:25fa8795676b | 40 | // atomicity on 16-bit platforms |
leothedragon | 0:25fa8795676b | 41 | static volatile uint32_t timer_sys_ticks; |
leothedragon | 0:25fa8795676b | 42 | |
leothedragon | 0:25fa8795676b | 43 | static NS_LIST_DEFINE(system_timer_free, sys_timer_struct_s, event.link); |
leothedragon | 0:25fa8795676b | 44 | static NS_LIST_DEFINE(system_timer_list, sys_timer_struct_s, event.link); |
leothedragon | 0:25fa8795676b | 45 | |
leothedragon | 0:25fa8795676b | 46 | |
leothedragon | 0:25fa8795676b | 47 | static sys_timer_struct_s *sys_timer_dynamically_allocate(void); |
leothedragon | 0:25fa8795676b | 48 | static void timer_sys_interrupt(void); |
leothedragon | 0:25fa8795676b | 49 | static void timer_sys_add(sys_timer_struct_s *timer); |
leothedragon | 0:25fa8795676b | 50 | |
leothedragon | 0:25fa8795676b | 51 | #ifndef NS_EVENTLOOP_USE_TICK_TIMER |
leothedragon | 0:25fa8795676b | 52 | static int8_t platform_tick_timer_start(uint32_t period_ms); |
leothedragon | 0:25fa8795676b | 53 | /* Implement platform tick timer using eventOS timer */ |
leothedragon | 0:25fa8795676b | 54 | // platform tick timer callback function |
leothedragon | 0:25fa8795676b | 55 | static void (*tick_timer_callback)(void); |
leothedragon | 0:25fa8795676b | 56 | static int8_t tick_timer_id = -1; // eventOS timer id for tick timer |
leothedragon | 0:25fa8795676b | 57 | |
leothedragon | 0:25fa8795676b | 58 | // EventOS timer callback function |
leothedragon | 0:25fa8795676b | 59 | static void tick_timer_eventOS_callback(int8_t timer_id, uint16_t slots) |
leothedragon | 0:25fa8795676b | 60 | { |
leothedragon | 0:25fa8795676b | 61 | // Not interested in timer id or slots |
leothedragon | 0:25fa8795676b | 62 | (void)slots; |
leothedragon | 0:25fa8795676b | 63 | // Call the tick timer callback |
leothedragon | 0:25fa8795676b | 64 | if (tick_timer_callback != NULL && timer_id == tick_timer_id) { |
leothedragon | 0:25fa8795676b | 65 | platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); |
leothedragon | 0:25fa8795676b | 66 | tick_timer_callback(); |
leothedragon | 0:25fa8795676b | 67 | } |
leothedragon | 0:25fa8795676b | 68 | } |
leothedragon | 0:25fa8795676b | 69 | |
leothedragon | 0:25fa8795676b | 70 | static int8_t platform_tick_timer_register(void (*tick_timer_cb)(void)) |
leothedragon | 0:25fa8795676b | 71 | { |
leothedragon | 0:25fa8795676b | 72 | tick_timer_callback = tick_timer_cb; |
leothedragon | 0:25fa8795676b | 73 | tick_timer_id = eventOS_callback_timer_register(tick_timer_eventOS_callback); |
leothedragon | 0:25fa8795676b | 74 | return tick_timer_id; |
leothedragon | 0:25fa8795676b | 75 | } |
leothedragon | 0:25fa8795676b | 76 | |
leothedragon | 0:25fa8795676b | 77 | static int8_t platform_tick_timer_start(uint32_t period_ms) |
leothedragon | 0:25fa8795676b | 78 | { |
leothedragon | 0:25fa8795676b | 79 | return eventOS_callback_timer_start(tick_timer_id, TIMER_SLOTS_PER_MS * period_ms); |
leothedragon | 0:25fa8795676b | 80 | } |
leothedragon | 0:25fa8795676b | 81 | |
leothedragon | 0:25fa8795676b | 82 | static int8_t platform_tick_timer_stop(void) |
leothedragon | 0:25fa8795676b | 83 | { |
leothedragon | 0:25fa8795676b | 84 | return eventOS_callback_timer_stop(tick_timer_id); |
leothedragon | 0:25fa8795676b | 85 | } |
leothedragon | 0:25fa8795676b | 86 | #endif // !NS_EVENTLOOP_USE_TICK_TIMER |
leothedragon | 0:25fa8795676b | 87 | |
leothedragon | 0:25fa8795676b | 88 | /* |
leothedragon | 0:25fa8795676b | 89 | * Initializes timers and starts system timer |
leothedragon | 0:25fa8795676b | 90 | */ |
leothedragon | 0:25fa8795676b | 91 | void timer_sys_init(void) |
leothedragon | 0:25fa8795676b | 92 | { |
leothedragon | 0:25fa8795676b | 93 | for (uint8_t i = 0; i < ST_MAX; i++) { |
leothedragon | 0:25fa8795676b | 94 | ns_list_add_to_start(&system_timer_free, &startup_sys_timer_pool[i]); |
leothedragon | 0:25fa8795676b | 95 | } |
leothedragon | 0:25fa8795676b | 96 | |
leothedragon | 0:25fa8795676b | 97 | platform_tick_timer_register(timer_sys_interrupt); |
leothedragon | 0:25fa8795676b | 98 | platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); |
leothedragon | 0:25fa8795676b | 99 | } |
leothedragon | 0:25fa8795676b | 100 | |
leothedragon | 0:25fa8795676b | 101 | |
leothedragon | 0:25fa8795676b | 102 | |
leothedragon | 0:25fa8795676b | 103 | /*-------------------SYSTEM TIMER FUNCTIONS--------------------------*/ |
leothedragon | 0:25fa8795676b | 104 | void timer_sys_disable(void) |
leothedragon | 0:25fa8795676b | 105 | { |
leothedragon | 0:25fa8795676b | 106 | platform_tick_timer_stop(); |
leothedragon | 0:25fa8795676b | 107 | } |
leothedragon | 0:25fa8795676b | 108 | |
leothedragon | 0:25fa8795676b | 109 | /* |
leothedragon | 0:25fa8795676b | 110 | * Starts ticking system timer interrupts every 10ms |
leothedragon | 0:25fa8795676b | 111 | */ |
leothedragon | 0:25fa8795676b | 112 | int8_t timer_sys_wakeup(void) |
leothedragon | 0:25fa8795676b | 113 | { |
leothedragon | 0:25fa8795676b | 114 | return platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); |
leothedragon | 0:25fa8795676b | 115 | } |
leothedragon | 0:25fa8795676b | 116 | |
leothedragon | 0:25fa8795676b | 117 | |
leothedragon | 0:25fa8795676b | 118 | static void timer_sys_interrupt(void) |
leothedragon | 0:25fa8795676b | 119 | { |
leothedragon | 0:25fa8795676b | 120 | system_timer_tick_update(1); |
leothedragon | 0:25fa8795676b | 121 | } |
leothedragon | 0:25fa8795676b | 122 | |
leothedragon | 0:25fa8795676b | 123 | |
leothedragon | 0:25fa8795676b | 124 | |
leothedragon | 0:25fa8795676b | 125 | /* * * * * * * * * */ |
leothedragon | 0:25fa8795676b | 126 | |
leothedragon | 0:25fa8795676b | 127 | static sys_timer_struct_s *sys_timer_dynamically_allocate(void) |
leothedragon | 0:25fa8795676b | 128 | { |
leothedragon | 0:25fa8795676b | 129 | return ns_dyn_mem_alloc(sizeof(sys_timer_struct_s)); |
leothedragon | 0:25fa8795676b | 130 | } |
leothedragon | 0:25fa8795676b | 131 | |
leothedragon | 0:25fa8795676b | 132 | static sys_timer_struct_s *timer_struct_get(void) |
leothedragon | 0:25fa8795676b | 133 | { |
leothedragon | 0:25fa8795676b | 134 | sys_timer_struct_s *timer; |
leothedragon | 0:25fa8795676b | 135 | platform_enter_critical(); |
leothedragon | 0:25fa8795676b | 136 | timer = ns_list_get_first(&system_timer_free); |
leothedragon | 0:25fa8795676b | 137 | if (timer) { |
leothedragon | 0:25fa8795676b | 138 | ns_list_remove(&system_timer_free, timer); |
leothedragon | 0:25fa8795676b | 139 | } else { |
leothedragon | 0:25fa8795676b | 140 | timer = sys_timer_dynamically_allocate(); |
leothedragon | 0:25fa8795676b | 141 | } |
leothedragon | 0:25fa8795676b | 142 | platform_exit_critical(); |
leothedragon | 0:25fa8795676b | 143 | return timer; |
leothedragon | 0:25fa8795676b | 144 | } |
leothedragon | 0:25fa8795676b | 145 | |
leothedragon | 0:25fa8795676b | 146 | void timer_sys_event_free(arm_event_storage_t *event) |
leothedragon | 0:25fa8795676b | 147 | { |
leothedragon | 0:25fa8795676b | 148 | platform_enter_critical(); |
leothedragon | 0:25fa8795676b | 149 | sys_timer_struct_s *timer = NS_CONTAINER_OF(event, sys_timer_struct_s, event); |
leothedragon | 0:25fa8795676b | 150 | if (timer->period == 0) { |
leothedragon | 0:25fa8795676b | 151 | // Non-periodic - return to free list |
leothedragon | 0:25fa8795676b | 152 | ns_list_add_to_start(&system_timer_free, timer); |
leothedragon | 0:25fa8795676b | 153 | } else { |
leothedragon | 0:25fa8795676b | 154 | // Periodic - check due time of next launch |
leothedragon | 0:25fa8795676b | 155 | timer->launch_time += timer->period; |
leothedragon | 0:25fa8795676b | 156 | if (TICKS_BEFORE_OR_AT(timer->launch_time, timer_sys_ticks)) { |
leothedragon | 0:25fa8795676b | 157 | // next event is overdue - queue event now |
leothedragon | 0:25fa8795676b | 158 | eventOS_event_send_timer_allocated(&timer->event); |
leothedragon | 0:25fa8795676b | 159 | } else { |
leothedragon | 0:25fa8795676b | 160 | // add back to timer queue for the future |
leothedragon | 0:25fa8795676b | 161 | timer_sys_add(timer); |
leothedragon | 0:25fa8795676b | 162 | } |
leothedragon | 0:25fa8795676b | 163 | } |
leothedragon | 0:25fa8795676b | 164 | platform_exit_critical(); |
leothedragon | 0:25fa8795676b | 165 | } |
leothedragon | 0:25fa8795676b | 166 | |
leothedragon | 0:25fa8795676b | 167 | void timer_sys_event_cancel_critical(struct arm_event_storage *event) |
leothedragon | 0:25fa8795676b | 168 | { |
leothedragon | 0:25fa8795676b | 169 | sys_timer_struct_s *timer = NS_CONTAINER_OF(event, sys_timer_struct_s, event); |
leothedragon | 0:25fa8795676b | 170 | timer->period = 0; |
leothedragon | 0:25fa8795676b | 171 | // If its unqueued it is on my timer list, otherwise it is in event-loop. |
leothedragon | 0:25fa8795676b | 172 | if (event->state == ARM_LIB_EVENT_UNQUEUED) { |
leothedragon | 0:25fa8795676b | 173 | ns_list_remove(&system_timer_list, timer); |
leothedragon | 0:25fa8795676b | 174 | } |
leothedragon | 0:25fa8795676b | 175 | } |
leothedragon | 0:25fa8795676b | 176 | |
leothedragon | 0:25fa8795676b | 177 | uint32_t eventOS_event_timer_ticks(void) |
leothedragon | 0:25fa8795676b | 178 | { |
leothedragon | 0:25fa8795676b | 179 | uint32_t ret_val; |
leothedragon | 0:25fa8795676b | 180 | // Enter/exit critical is a bit clunky, but necessary on 16-bit platforms, |
leothedragon | 0:25fa8795676b | 181 | // which won't be able to do an atomic 32-bit read. |
leothedragon | 0:25fa8795676b | 182 | platform_enter_critical(); |
leothedragon | 0:25fa8795676b | 183 | ret_val = timer_sys_ticks; |
leothedragon | 0:25fa8795676b | 184 | platform_exit_critical(); |
leothedragon | 0:25fa8795676b | 185 | return ret_val; |
leothedragon | 0:25fa8795676b | 186 | } |
leothedragon | 0:25fa8795676b | 187 | |
leothedragon | 0:25fa8795676b | 188 | /* Called internally with lock held */ |
leothedragon | 0:25fa8795676b | 189 | static void timer_sys_add(sys_timer_struct_s *timer) |
leothedragon | 0:25fa8795676b | 190 | { |
leothedragon | 0:25fa8795676b | 191 | uint32_t at = timer->launch_time; |
leothedragon | 0:25fa8795676b | 192 | |
leothedragon | 0:25fa8795676b | 193 | // Find first timer scheduled to run after us, and insert before it. |
leothedragon | 0:25fa8795676b | 194 | // (This means timers scheduled for same time run in order of request) |
leothedragon | 0:25fa8795676b | 195 | ns_list_foreach(sys_timer_struct_s, t, &system_timer_list) { |
leothedragon | 0:25fa8795676b | 196 | if (TICKS_BEFORE(at, t->launch_time)) { |
leothedragon | 0:25fa8795676b | 197 | ns_list_add_before(&system_timer_list, t, timer); |
leothedragon | 0:25fa8795676b | 198 | return; |
leothedragon | 0:25fa8795676b | 199 | } |
leothedragon | 0:25fa8795676b | 200 | } |
leothedragon | 0:25fa8795676b | 201 | |
leothedragon | 0:25fa8795676b | 202 | // Didn't insert before another timer, so must be last. |
leothedragon | 0:25fa8795676b | 203 | ns_list_add_to_end(&system_timer_list, timer); |
leothedragon | 0:25fa8795676b | 204 | } |
leothedragon | 0:25fa8795676b | 205 | |
leothedragon | 0:25fa8795676b | 206 | /* Called internally with lock held */ |
leothedragon | 0:25fa8795676b | 207 | static arm_event_storage_t *eventOS_event_timer_request_at_(const arm_event_t *event, uint32_t at, uint32_t period) |
leothedragon | 0:25fa8795676b | 208 | { |
leothedragon | 0:25fa8795676b | 209 | // Because we use user-allocated events, they must get delivered to avoid |
leothedragon | 0:25fa8795676b | 210 | // a leak. Previously this call queued timers for invalid tasks, then they |
leothedragon | 0:25fa8795676b | 211 | // would go undelivered. Now it returns an error. |
leothedragon | 0:25fa8795676b | 212 | if (!event_tasklet_handler_id_valid(event->receiver)) { |
leothedragon | 0:25fa8795676b | 213 | return NULL; |
leothedragon | 0:25fa8795676b | 214 | } |
leothedragon | 0:25fa8795676b | 215 | |
leothedragon | 0:25fa8795676b | 216 | sys_timer_struct_s *timer = timer_struct_get(); |
leothedragon | 0:25fa8795676b | 217 | if (!timer) { |
leothedragon | 0:25fa8795676b | 218 | return NULL; |
leothedragon | 0:25fa8795676b | 219 | } |
leothedragon | 0:25fa8795676b | 220 | |
leothedragon | 0:25fa8795676b | 221 | timer->event.data = *event; |
leothedragon | 0:25fa8795676b | 222 | timer->event.allocator = ARM_LIB_EVENT_TIMER; |
leothedragon | 0:25fa8795676b | 223 | timer->event.state = ARM_LIB_EVENT_UNQUEUED; |
leothedragon | 0:25fa8795676b | 224 | timer->launch_time = at; |
leothedragon | 0:25fa8795676b | 225 | timer->period = period; |
leothedragon | 0:25fa8795676b | 226 | |
leothedragon | 0:25fa8795676b | 227 | if (TICKS_BEFORE_OR_AT(at, timer_sys_ticks)) { |
leothedragon | 0:25fa8795676b | 228 | eventOS_event_send_timer_allocated(&timer->event); |
leothedragon | 0:25fa8795676b | 229 | } else { |
leothedragon | 0:25fa8795676b | 230 | timer_sys_add(timer); |
leothedragon | 0:25fa8795676b | 231 | } |
leothedragon | 0:25fa8795676b | 232 | |
leothedragon | 0:25fa8795676b | 233 | return &timer->event; |
leothedragon | 0:25fa8795676b | 234 | } |
leothedragon | 0:25fa8795676b | 235 | |
leothedragon | 0:25fa8795676b | 236 | arm_event_storage_t *eventOS_event_timer_request_at(const arm_event_t *event, uint32_t at) |
leothedragon | 0:25fa8795676b | 237 | { |
leothedragon | 0:25fa8795676b | 238 | platform_enter_critical(); |
leothedragon | 0:25fa8795676b | 239 | |
leothedragon | 0:25fa8795676b | 240 | arm_event_storage_t *ret = eventOS_event_timer_request_at_(event, at, 0); |
leothedragon | 0:25fa8795676b | 241 | |
leothedragon | 0:25fa8795676b | 242 | platform_exit_critical(); |
leothedragon | 0:25fa8795676b | 243 | |
leothedragon | 0:25fa8795676b | 244 | return ret; |
leothedragon | 0:25fa8795676b | 245 | } |
leothedragon | 0:25fa8795676b | 246 | |
leothedragon | 0:25fa8795676b | 247 | arm_event_storage_t *eventOS_event_timer_request_in(const arm_event_t *event, int32_t in) |
leothedragon | 0:25fa8795676b | 248 | { |
leothedragon | 0:25fa8795676b | 249 | platform_enter_critical(); |
leothedragon | 0:25fa8795676b | 250 | |
leothedragon | 0:25fa8795676b | 251 | arm_event_storage_t *ret = eventOS_event_timer_request_at_(event, timer_sys_ticks + in, 0); |
leothedragon | 0:25fa8795676b | 252 | |
leothedragon | 0:25fa8795676b | 253 | platform_exit_critical(); |
leothedragon | 0:25fa8795676b | 254 | |
leothedragon | 0:25fa8795676b | 255 | return ret; |
leothedragon | 0:25fa8795676b | 256 | |
leothedragon | 0:25fa8795676b | 257 | } |
leothedragon | 0:25fa8795676b | 258 | |
leothedragon | 0:25fa8795676b | 259 | arm_event_storage_t *eventOS_event_timer_request_every(const arm_event_t *event, int32_t period) |
leothedragon | 0:25fa8795676b | 260 | { |
leothedragon | 0:25fa8795676b | 261 | if (period <= 0) { |
leothedragon | 0:25fa8795676b | 262 | return NULL; |
leothedragon | 0:25fa8795676b | 263 | } |
leothedragon | 0:25fa8795676b | 264 | |
leothedragon | 0:25fa8795676b | 265 | platform_enter_critical(); |
leothedragon | 0:25fa8795676b | 266 | |
leothedragon | 0:25fa8795676b | 267 | arm_event_storage_t *ret = eventOS_event_timer_request_at_(event, timer_sys_ticks + period, period); |
leothedragon | 0:25fa8795676b | 268 | |
leothedragon | 0:25fa8795676b | 269 | platform_exit_critical(); |
leothedragon | 0:25fa8795676b | 270 | |
leothedragon | 0:25fa8795676b | 271 | return ret; |
leothedragon | 0:25fa8795676b | 272 | |
leothedragon | 0:25fa8795676b | 273 | } |
leothedragon | 0:25fa8795676b | 274 | |
leothedragon | 0:25fa8795676b | 275 | int8_t eventOS_event_timer_request(uint8_t event_id, uint8_t event_type, int8_t tasklet_id, uint32_t time) |
leothedragon | 0:25fa8795676b | 276 | { |
leothedragon | 0:25fa8795676b | 277 | const arm_event_t event = { |
leothedragon | 0:25fa8795676b | 278 | .event_id = event_id, |
leothedragon | 0:25fa8795676b | 279 | .event_type = event_type, |
leothedragon | 0:25fa8795676b | 280 | .receiver = tasklet_id, |
leothedragon | 0:25fa8795676b | 281 | .sender = 0, |
leothedragon | 0:25fa8795676b | 282 | .data_ptr = NULL, |
leothedragon | 0:25fa8795676b | 283 | .event_data = 0, |
leothedragon | 0:25fa8795676b | 284 | .priority = ARM_LIB_MED_PRIORITY_EVENT, |
leothedragon | 0:25fa8795676b | 285 | }; |
leothedragon | 0:25fa8795676b | 286 | |
leothedragon | 0:25fa8795676b | 287 | // Legacy time behaviour preserved |
leothedragon | 0:25fa8795676b | 288 | |
leothedragon | 0:25fa8795676b | 289 | // Note that someone wanting 20ms gets 2 ticks, thanks to this test. 30ms would be 4 ticks. |
leothedragon | 0:25fa8795676b | 290 | // And why shouldn't they be able to get a 1-tick callback? |
leothedragon | 0:25fa8795676b | 291 | if (time > 2 * TIMER_SYS_TICK_PERIOD) { |
leothedragon | 0:25fa8795676b | 292 | time /= TIMER_SYS_TICK_PERIOD; |
leothedragon | 0:25fa8795676b | 293 | // XXX Why this? Someone wanting 50ms shouldn't get 6 ticks. Round to nearest, maybe? |
leothedragon | 0:25fa8795676b | 294 | time++; |
leothedragon | 0:25fa8795676b | 295 | } else { |
leothedragon | 0:25fa8795676b | 296 | time = 2; |
leothedragon | 0:25fa8795676b | 297 | } |
leothedragon | 0:25fa8795676b | 298 | |
leothedragon | 0:25fa8795676b | 299 | platform_enter_critical(); |
leothedragon | 0:25fa8795676b | 300 | arm_event_storage_t *ret = eventOS_event_timer_request_at_(&event, timer_sys_ticks + time, 0); |
leothedragon | 0:25fa8795676b | 301 | platform_exit_critical(); |
leothedragon | 0:25fa8795676b | 302 | return ret?0:-1; |
leothedragon | 0:25fa8795676b | 303 | } |
leothedragon | 0:25fa8795676b | 304 | |
leothedragon | 0:25fa8795676b | 305 | int8_t eventOS_event_timer_cancel(uint8_t event_id, int8_t tasklet_id) |
leothedragon | 0:25fa8795676b | 306 | { |
leothedragon | 0:25fa8795676b | 307 | platform_enter_critical(); |
leothedragon | 0:25fa8795676b | 308 | |
leothedragon | 0:25fa8795676b | 309 | /* First check pending timers */ |
leothedragon | 0:25fa8795676b | 310 | ns_list_foreach(sys_timer_struct_s, cur, &system_timer_list) { |
leothedragon | 0:25fa8795676b | 311 | if (cur->event.data.receiver == tasklet_id && cur->event.data.event_id == event_id) { |
leothedragon | 0:25fa8795676b | 312 | eventOS_cancel(&cur->event); |
leothedragon | 0:25fa8795676b | 313 | goto done; |
leothedragon | 0:25fa8795676b | 314 | } |
leothedragon | 0:25fa8795676b | 315 | } |
leothedragon | 0:25fa8795676b | 316 | |
leothedragon | 0:25fa8795676b | 317 | /* No pending timer, so check for already-pending event */ |
leothedragon | 0:25fa8795676b | 318 | arm_event_storage_t *event = eventOS_event_find_by_id_critical(tasklet_id, event_id); |
leothedragon | 0:25fa8795676b | 319 | if (event && event->allocator == ARM_LIB_EVENT_TIMER) { |
leothedragon | 0:25fa8795676b | 320 | eventOS_cancel(event); |
leothedragon | 0:25fa8795676b | 321 | goto done; |
leothedragon | 0:25fa8795676b | 322 | } |
leothedragon | 0:25fa8795676b | 323 | |
leothedragon | 0:25fa8795676b | 324 | /* No match found */ |
leothedragon | 0:25fa8795676b | 325 | platform_exit_critical(); |
leothedragon | 0:25fa8795676b | 326 | return -1; |
leothedragon | 0:25fa8795676b | 327 | |
leothedragon | 0:25fa8795676b | 328 | done: |
leothedragon | 0:25fa8795676b | 329 | platform_exit_critical(); |
leothedragon | 0:25fa8795676b | 330 | return 0; |
leothedragon | 0:25fa8795676b | 331 | } |
leothedragon | 0:25fa8795676b | 332 | |
leothedragon | 0:25fa8795676b | 333 | uint32_t eventOS_event_timer_shortest_active_timer(void) |
leothedragon | 0:25fa8795676b | 334 | { |
leothedragon | 0:25fa8795676b | 335 | uint32_t ret_val = 0; |
leothedragon | 0:25fa8795676b | 336 | |
leothedragon | 0:25fa8795676b | 337 | platform_enter_critical(); |
leothedragon | 0:25fa8795676b | 338 | sys_timer_struct_s *first = ns_list_get_first(&system_timer_list); |
leothedragon | 0:25fa8795676b | 339 | if (first == NULL) { |
leothedragon | 0:25fa8795676b | 340 | // Weird API has 0 for "no events" |
leothedragon | 0:25fa8795676b | 341 | ret_val = 0; |
leothedragon | 0:25fa8795676b | 342 | } else if (TICKS_BEFORE_OR_AT(first->launch_time, timer_sys_ticks)) { |
leothedragon | 0:25fa8795676b | 343 | // Which means an immediate/overdue event has to be 1 |
leothedragon | 0:25fa8795676b | 344 | ret_val = 1; |
leothedragon | 0:25fa8795676b | 345 | } else { |
leothedragon | 0:25fa8795676b | 346 | ret_val = first->launch_time - timer_sys_ticks; |
leothedragon | 0:25fa8795676b | 347 | } |
leothedragon | 0:25fa8795676b | 348 | |
leothedragon | 0:25fa8795676b | 349 | platform_exit_critical(); |
leothedragon | 0:25fa8795676b | 350 | return eventOS_event_timer_ticks_to_ms(ret_val); |
leothedragon | 0:25fa8795676b | 351 | } |
leothedragon | 0:25fa8795676b | 352 | |
leothedragon | 0:25fa8795676b | 353 | void system_timer_tick_update(uint32_t ticks) |
leothedragon | 0:25fa8795676b | 354 | { |
leothedragon | 0:25fa8795676b | 355 | platform_enter_critical(); |
leothedragon | 0:25fa8795676b | 356 | //Keep runtime time |
leothedragon | 0:25fa8795676b | 357 | timer_sys_ticks += ticks; |
leothedragon | 0:25fa8795676b | 358 | ns_list_foreach_safe(sys_timer_struct_s, cur, &system_timer_list) { |
leothedragon | 0:25fa8795676b | 359 | if (TICKS_BEFORE_OR_AT(cur->launch_time, timer_sys_ticks)) { |
leothedragon | 0:25fa8795676b | 360 | // Unthread from our list |
leothedragon | 0:25fa8795676b | 361 | ns_list_remove(&system_timer_list, cur); |
leothedragon | 0:25fa8795676b | 362 | // Make it an event (can't fail - no allocation) |
leothedragon | 0:25fa8795676b | 363 | // event system will call our timer_sys_event_free on event delivery. |
leothedragon | 0:25fa8795676b | 364 | eventOS_event_send_timer_allocated(&cur->event); |
leothedragon | 0:25fa8795676b | 365 | } else { |
leothedragon | 0:25fa8795676b | 366 | // List is ordered, so as soon as we see a later event, we're done. |
leothedragon | 0:25fa8795676b | 367 | break; |
leothedragon | 0:25fa8795676b | 368 | } |
leothedragon | 0:25fa8795676b | 369 | } |
leothedragon | 0:25fa8795676b | 370 | |
leothedragon | 0:25fa8795676b | 371 | platform_exit_critical(); |
leothedragon | 0:25fa8795676b | 372 | } |
leothedragon | 0:25fa8795676b | 373 |