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