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