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.
Dependents: mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more
features/FEATURE_COMMON_PAL/sal-stack-nanostack-eventloop/source/system_timer.c@0:f782d9c66c49, 2018-02-02 (annotated)
- Committer:
- dkato
- Date:
- Fri Feb 02 05:42:23 2018 +0000
- Revision:
- 0:f782d9c66c49
mbed-os for GR-LYCHEE
Who changed what in which revision?
| User | Revision | Line number | New contents of line | 
|---|---|---|---|
| dkato | 0:f782d9c66c49 | 1 | /* | 
| dkato | 0:f782d9c66c49 | 2 | * Copyright (c) 2014-2015 ARM Limited. All rights reserved. | 
| dkato | 0:f782d9c66c49 | 3 | * SPDX-License-Identifier: Apache-2.0 | 
| dkato | 0:f782d9c66c49 | 4 | * Licensed under the Apache License, Version 2.0 (the License); you may | 
| dkato | 0:f782d9c66c49 | 5 | * not use this file except in compliance with the License. | 
| dkato | 0:f782d9c66c49 | 6 | * You may obtain a copy of the License at | 
| dkato | 0:f782d9c66c49 | 7 | * | 
| dkato | 0:f782d9c66c49 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 | 
| dkato | 0:f782d9c66c49 | 9 | * | 
| dkato | 0:f782d9c66c49 | 10 | * Unless required by applicable law or agreed to in writing, software | 
| dkato | 0:f782d9c66c49 | 11 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT | 
| dkato | 0:f782d9c66c49 | 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
| dkato | 0:f782d9c66c49 | 13 | * See the License for the specific language governing permissions and | 
| dkato | 0:f782d9c66c49 | 14 | * limitations under the License. | 
| dkato | 0:f782d9c66c49 | 15 | */ | 
| dkato | 0:f782d9c66c49 | 16 | #include "ns_types.h" | 
| dkato | 0:f782d9c66c49 | 17 | #include "ns_list.h" | 
| dkato | 0:f782d9c66c49 | 18 | #include "timer_sys.h" | 
| dkato | 0:f782d9c66c49 | 19 | #include "platform/arm_hal_interrupt.h" | 
| dkato | 0:f782d9c66c49 | 20 | #include "platform/arm_hal_timer.h" | 
| dkato | 0:f782d9c66c49 | 21 | #include "ns_timer.h" | 
| dkato | 0:f782d9c66c49 | 22 | #include "nsdynmemLIB.h" | 
| dkato | 0:f782d9c66c49 | 23 | #include "eventOS_event.h" | 
| dkato | 0:f782d9c66c49 | 24 | #include "eventOS_callback_timer.h" | 
| dkato | 0:f782d9c66c49 | 25 | |
| dkato | 0:f782d9c66c49 | 26 | #ifndef ST_MAX | 
| dkato | 0:f782d9c66c49 | 27 | #define ST_MAX 6 | 
| dkato | 0:f782d9c66c49 | 28 | #endif | 
| dkato | 0:f782d9c66c49 | 29 | |
| dkato | 0:f782d9c66c49 | 30 | typedef struct sys_timer_struct_s { | 
| dkato | 0:f782d9c66c49 | 31 | uint32_t timer_sys_launch_time; | 
| dkato | 0:f782d9c66c49 | 32 | int8_t timer_sys_launch_receiver; | 
| dkato | 0:f782d9c66c49 | 33 | uint8_t timer_sys_launch_message; | 
| dkato | 0:f782d9c66c49 | 34 | uint8_t timer_event_type; | 
| dkato | 0:f782d9c66c49 | 35 | |
| dkato | 0:f782d9c66c49 | 36 | ns_list_link_t link; | 
| dkato | 0:f782d9c66c49 | 37 | } sys_timer_struct_s; | 
| dkato | 0:f782d9c66c49 | 38 | |
| dkato | 0:f782d9c66c49 | 39 | #define TIMER_SLOTS_PER_MS 20 | 
| dkato | 0:f782d9c66c49 | 40 | #define TIMER_SYS_TICK_PERIOD 10 // milliseconds | 
| dkato | 0:f782d9c66c49 | 41 | |
| dkato | 0:f782d9c66c49 | 42 | static uint32_t run_time_tick_ticks = 0; | 
| dkato | 0:f782d9c66c49 | 43 | static NS_LIST_DEFINE(system_timer_free, sys_timer_struct_s, link); | 
| dkato | 0:f782d9c66c49 | 44 | static NS_LIST_DEFINE(system_timer_list, sys_timer_struct_s, link); | 
| dkato | 0:f782d9c66c49 | 45 | |
| dkato | 0:f782d9c66c49 | 46 | |
| dkato | 0:f782d9c66c49 | 47 | static sys_timer_struct_s *sys_timer_dynamically_allocate(void); | 
| dkato | 0:f782d9c66c49 | 48 | static void timer_sys_interrupt(void); | 
| dkato | 0:f782d9c66c49 | 49 | |
| dkato | 0:f782d9c66c49 | 50 | #ifndef NS_EVENTLOOP_USE_TICK_TIMER | 
| dkato | 0:f782d9c66c49 | 51 | static int8_t platform_tick_timer_start(uint32_t period_ms); | 
| dkato | 0:f782d9c66c49 | 52 | /* Implement platform tick timer using eventOS timer */ | 
| dkato | 0:f782d9c66c49 | 53 | // platform tick timer callback function | 
| dkato | 0:f782d9c66c49 | 54 | static void (*tick_timer_callback)(void); | 
| dkato | 0:f782d9c66c49 | 55 | static int8_t tick_timer_id = -1; // eventOS timer id for tick timer | 
| dkato | 0:f782d9c66c49 | 56 | |
| dkato | 0:f782d9c66c49 | 57 | // EventOS timer callback function | 
| dkato | 0:f782d9c66c49 | 58 | static void tick_timer_eventOS_callback(int8_t timer_id, uint16_t slots) | 
| dkato | 0:f782d9c66c49 | 59 | { | 
| dkato | 0:f782d9c66c49 | 60 | // Not interested in timer id or slots | 
| dkato | 0:f782d9c66c49 | 61 | (void)slots; | 
| dkato | 0:f782d9c66c49 | 62 | // Call the tick timer callback | 
| dkato | 0:f782d9c66c49 | 63 | if (tick_timer_callback != NULL && timer_id == tick_timer_id) { | 
| dkato | 0:f782d9c66c49 | 64 | platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); | 
| dkato | 0:f782d9c66c49 | 65 | tick_timer_callback(); | 
| dkato | 0:f782d9c66c49 | 66 | } | 
| dkato | 0:f782d9c66c49 | 67 | } | 
| dkato | 0:f782d9c66c49 | 68 | |
| dkato | 0:f782d9c66c49 | 69 | static int8_t platform_tick_timer_register(void (*tick_timer_cb)(void)) | 
| dkato | 0:f782d9c66c49 | 70 | { | 
| dkato | 0:f782d9c66c49 | 71 | tick_timer_callback = tick_timer_cb; | 
| dkato | 0:f782d9c66c49 | 72 | tick_timer_id = eventOS_callback_timer_register(tick_timer_eventOS_callback); | 
| dkato | 0:f782d9c66c49 | 73 | return tick_timer_id; | 
| dkato | 0:f782d9c66c49 | 74 | } | 
| dkato | 0:f782d9c66c49 | 75 | |
| dkato | 0:f782d9c66c49 | 76 | static int8_t platform_tick_timer_start(uint32_t period_ms) | 
| dkato | 0:f782d9c66c49 | 77 | { | 
| dkato | 0:f782d9c66c49 | 78 | return eventOS_callback_timer_start(tick_timer_id, TIMER_SLOTS_PER_MS * period_ms); | 
| dkato | 0:f782d9c66c49 | 79 | } | 
| dkato | 0:f782d9c66c49 | 80 | |
| dkato | 0:f782d9c66c49 | 81 | static int8_t platform_tick_timer_stop(void) | 
| dkato | 0:f782d9c66c49 | 82 | { | 
| dkato | 0:f782d9c66c49 | 83 | return eventOS_callback_timer_stop(tick_timer_id); | 
| dkato | 0:f782d9c66c49 | 84 | } | 
| dkato | 0:f782d9c66c49 | 85 | #endif // !NS_EVENTLOOP_USE_TICK_TIMER | 
| dkato | 0:f782d9c66c49 | 86 | |
| dkato | 0:f782d9c66c49 | 87 | /* | 
| dkato | 0:f782d9c66c49 | 88 | * Initializes timers and starts system timer | 
| dkato | 0:f782d9c66c49 | 89 | */ | 
| dkato | 0:f782d9c66c49 | 90 | void timer_sys_init(void) | 
| dkato | 0:f782d9c66c49 | 91 | { | 
| dkato | 0:f782d9c66c49 | 92 | run_time_tick_ticks = 0; | 
| dkato | 0:f782d9c66c49 | 93 | |
| dkato | 0:f782d9c66c49 | 94 | // Clear old timers | 
| dkato | 0:f782d9c66c49 | 95 | ns_list_foreach_safe(sys_timer_struct_s, temp, &system_timer_list) { | 
| dkato | 0:f782d9c66c49 | 96 | ns_list_remove(&system_timer_list, temp); | 
| dkato | 0:f782d9c66c49 | 97 | ns_dyn_mem_free(temp); | 
| dkato | 0:f782d9c66c49 | 98 | } | 
| dkato | 0:f782d9c66c49 | 99 | // Clear old free timer entrys | 
| dkato | 0:f782d9c66c49 | 100 | ns_list_foreach_safe(sys_timer_struct_s, temp, &system_timer_free) { | 
| dkato | 0:f782d9c66c49 | 101 | ns_list_remove(&system_timer_free, temp); | 
| dkato | 0:f782d9c66c49 | 102 | ns_dyn_mem_free(temp); | 
| dkato | 0:f782d9c66c49 | 103 | } | 
| dkato | 0:f782d9c66c49 | 104 | |
| dkato | 0:f782d9c66c49 | 105 | for (uint8_t i = 0; i < ST_MAX; i++) { | 
| dkato | 0:f782d9c66c49 | 106 | sys_timer_struct_s *temp = sys_timer_dynamically_allocate(); | 
| dkato | 0:f782d9c66c49 | 107 | if (temp) { | 
| dkato | 0:f782d9c66c49 | 108 | ns_list_add_to_start(&system_timer_free, temp); | 
| dkato | 0:f782d9c66c49 | 109 | } | 
| dkato | 0:f782d9c66c49 | 110 | } | 
| dkato | 0:f782d9c66c49 | 111 | |
| dkato | 0:f782d9c66c49 | 112 | platform_tick_timer_register(timer_sys_interrupt); | 
| dkato | 0:f782d9c66c49 | 113 | platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); | 
| dkato | 0:f782d9c66c49 | 114 | } | 
| dkato | 0:f782d9c66c49 | 115 | |
| dkato | 0:f782d9c66c49 | 116 | |
| dkato | 0:f782d9c66c49 | 117 | |
| dkato | 0:f782d9c66c49 | 118 | /*-------------------SYSTEM TIMER FUNCTIONS--------------------------*/ | 
| dkato | 0:f782d9c66c49 | 119 | void timer_sys_disable(void) | 
| dkato | 0:f782d9c66c49 | 120 | { | 
| dkato | 0:f782d9c66c49 | 121 | platform_tick_timer_stop(); | 
| dkato | 0:f782d9c66c49 | 122 | } | 
| dkato | 0:f782d9c66c49 | 123 | |
| dkato | 0:f782d9c66c49 | 124 | /* | 
| dkato | 0:f782d9c66c49 | 125 | * Starts ticking system timer interrupts every 10ms | 
| dkato | 0:f782d9c66c49 | 126 | */ | 
| dkato | 0:f782d9c66c49 | 127 | int8_t timer_sys_wakeup(void) | 
| dkato | 0:f782d9c66c49 | 128 | { | 
| dkato | 0:f782d9c66c49 | 129 | return platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); | 
| dkato | 0:f782d9c66c49 | 130 | } | 
| dkato | 0:f782d9c66c49 | 131 | |
| dkato | 0:f782d9c66c49 | 132 | |
| dkato | 0:f782d9c66c49 | 133 | static void timer_sys_interrupt(void) | 
| dkato | 0:f782d9c66c49 | 134 | { | 
| dkato | 0:f782d9c66c49 | 135 | system_timer_tick_update(1); | 
| dkato | 0:f782d9c66c49 | 136 | } | 
| dkato | 0:f782d9c66c49 | 137 | |
| dkato | 0:f782d9c66c49 | 138 | |
| dkato | 0:f782d9c66c49 | 139 | |
| dkato | 0:f782d9c66c49 | 140 | /* * * * * * * * * */ | 
| dkato | 0:f782d9c66c49 | 141 | |
| dkato | 0:f782d9c66c49 | 142 | static sys_timer_struct_s *sys_timer_dynamically_allocate(void) | 
| dkato | 0:f782d9c66c49 | 143 | { | 
| dkato | 0:f782d9c66c49 | 144 | return (sys_timer_struct_s*)ns_dyn_mem_alloc(sizeof(sys_timer_struct_s)); | 
| dkato | 0:f782d9c66c49 | 145 | } | 
| dkato | 0:f782d9c66c49 | 146 | |
| dkato | 0:f782d9c66c49 | 147 | static sys_timer_struct_s *timer_struct_get(void) | 
| dkato | 0:f782d9c66c49 | 148 | { | 
| dkato | 0:f782d9c66c49 | 149 | sys_timer_struct_s *timer; | 
| dkato | 0:f782d9c66c49 | 150 | platform_enter_critical(); | 
| dkato | 0:f782d9c66c49 | 151 | timer = ns_list_get_first(&system_timer_free); | 
| dkato | 0:f782d9c66c49 | 152 | if (timer) { | 
| dkato | 0:f782d9c66c49 | 153 | ns_list_remove(&system_timer_free, timer); | 
| dkato | 0:f782d9c66c49 | 154 | } else { | 
| dkato | 0:f782d9c66c49 | 155 | timer = sys_timer_dynamically_allocate(); | 
| dkato | 0:f782d9c66c49 | 156 | } | 
| dkato | 0:f782d9c66c49 | 157 | platform_exit_critical(); | 
| dkato | 0:f782d9c66c49 | 158 | return timer; | 
| dkato | 0:f782d9c66c49 | 159 | } | 
| dkato | 0:f782d9c66c49 | 160 | |
| dkato | 0:f782d9c66c49 | 161 | uint32_t timer_get_runtime_ticks(void) // only used in dev_stats_internal.c | 
| dkato | 0:f782d9c66c49 | 162 | { | 
| dkato | 0:f782d9c66c49 | 163 | uint32_t ret_val; | 
| dkato | 0:f782d9c66c49 | 164 | platform_enter_critical(); | 
| dkato | 0:f782d9c66c49 | 165 | ret_val = run_time_tick_ticks; | 
| dkato | 0:f782d9c66c49 | 166 | platform_exit_critical(); | 
| dkato | 0:f782d9c66c49 | 167 | return ret_val; | 
| dkato | 0:f782d9c66c49 | 168 | } | 
| dkato | 0:f782d9c66c49 | 169 | |
| dkato | 0:f782d9c66c49 | 170 | |
| dkato | 0:f782d9c66c49 | 171 | |
| dkato | 0:f782d9c66c49 | 172 | int8_t eventOS_event_timer_request(uint8_t snmessage, uint8_t event_type, int8_t tasklet_id, uint32_t time) | 
| dkato | 0:f782d9c66c49 | 173 | { | 
| dkato | 0:f782d9c66c49 | 174 | int8_t res = -1; | 
| dkato | 0:f782d9c66c49 | 175 | sys_timer_struct_s *timer = NULL; | 
| dkato | 0:f782d9c66c49 | 176 | |
| dkato | 0:f782d9c66c49 | 177 | platform_enter_critical(); | 
| dkato | 0:f782d9c66c49 | 178 | // Note that someone wanting 20ms gets 2 ticks, thanks to this test. 30ms would be 4 ticks. | 
| dkato | 0:f782d9c66c49 | 179 | // And why shouldn't they be able to get a 1-tick callback? | 
| dkato | 0:f782d9c66c49 | 180 | if (time > 2 * TIMER_SYS_TICK_PERIOD) { | 
| dkato | 0:f782d9c66c49 | 181 | time /= TIMER_SYS_TICK_PERIOD; | 
| dkato | 0:f782d9c66c49 | 182 | // XXX Why this? Someone wanting 50ms shouldn't get 6 ticks. Round to nearest, maybe? | 
| dkato | 0:f782d9c66c49 | 183 | time++; | 
| dkato | 0:f782d9c66c49 | 184 | } else { | 
| dkato | 0:f782d9c66c49 | 185 | time = 2; | 
| dkato | 0:f782d9c66c49 | 186 | } | 
| dkato | 0:f782d9c66c49 | 187 | timer = timer_struct_get(); | 
| dkato | 0:f782d9c66c49 | 188 | if (timer) { | 
| dkato | 0:f782d9c66c49 | 189 | timer->timer_sys_launch_message = snmessage; | 
| dkato | 0:f782d9c66c49 | 190 | timer->timer_sys_launch_receiver = tasklet_id; | 
| dkato | 0:f782d9c66c49 | 191 | timer->timer_event_type = event_type; | 
| dkato | 0:f782d9c66c49 | 192 | timer->timer_sys_launch_time = time; | 
| dkato | 0:f782d9c66c49 | 193 | ns_list_add_to_start(&system_timer_list, timer); | 
| dkato | 0:f782d9c66c49 | 194 | res = 0; | 
| dkato | 0:f782d9c66c49 | 195 | } | 
| dkato | 0:f782d9c66c49 | 196 | platform_exit_critical(); | 
| dkato | 0:f782d9c66c49 | 197 | return res; | 
| dkato | 0:f782d9c66c49 | 198 | } | 
| dkato | 0:f782d9c66c49 | 199 | |
| dkato | 0:f782d9c66c49 | 200 | int8_t eventOS_event_timer_cancel(uint8_t snmessage, int8_t tasklet_id) | 
| dkato | 0:f782d9c66c49 | 201 | { | 
| dkato | 0:f782d9c66c49 | 202 | int8_t res = -1; | 
| dkato | 0:f782d9c66c49 | 203 | platform_enter_critical(); | 
| dkato | 0:f782d9c66c49 | 204 | ns_list_foreach(sys_timer_struct_s, cur, &system_timer_list) { | 
| dkato | 0:f782d9c66c49 | 205 | if (cur->timer_sys_launch_receiver == tasklet_id && cur->timer_sys_launch_message == snmessage) { | 
| dkato | 0:f782d9c66c49 | 206 | ns_list_remove(&system_timer_list, cur); | 
| dkato | 0:f782d9c66c49 | 207 | ns_list_add_to_start(&system_timer_free, cur); | 
| dkato | 0:f782d9c66c49 | 208 | res = 0; | 
| dkato | 0:f782d9c66c49 | 209 | break; | 
| dkato | 0:f782d9c66c49 | 210 | } | 
| dkato | 0:f782d9c66c49 | 211 | } | 
| dkato | 0:f782d9c66c49 | 212 | |
| dkato | 0:f782d9c66c49 | 213 | platform_exit_critical(); | 
| dkato | 0:f782d9c66c49 | 214 | return res; | 
| dkato | 0:f782d9c66c49 | 215 | } | 
| dkato | 0:f782d9c66c49 | 216 | |
| dkato | 0:f782d9c66c49 | 217 | |
| dkato | 0:f782d9c66c49 | 218 | uint32_t eventOS_event_timer_shortest_active_timer(void) | 
| dkato | 0:f782d9c66c49 | 219 | { | 
| dkato | 0:f782d9c66c49 | 220 | uint32_t ret_val = 0; | 
| dkato | 0:f782d9c66c49 | 221 | |
| dkato | 0:f782d9c66c49 | 222 | platform_enter_critical(); | 
| dkato | 0:f782d9c66c49 | 223 | ns_list_foreach(sys_timer_struct_s, cur, &system_timer_list) { | 
| dkato | 0:f782d9c66c49 | 224 | if (ret_val == 0 || cur->timer_sys_launch_time < ret_val) { | 
| dkato | 0:f782d9c66c49 | 225 | ret_val = cur->timer_sys_launch_time; | 
| dkato | 0:f782d9c66c49 | 226 | } | 
| dkato | 0:f782d9c66c49 | 227 | } | 
| dkato | 0:f782d9c66c49 | 228 | |
| dkato | 0:f782d9c66c49 | 229 | platform_exit_critical(); | 
| dkato | 0:f782d9c66c49 | 230 | //Convert ticks to ms | 
| dkato | 0:f782d9c66c49 | 231 | ret_val *= TIMER_SYS_TICK_PERIOD; | 
| dkato | 0:f782d9c66c49 | 232 | return ret_val; | 
| dkato | 0:f782d9c66c49 | 233 | } | 
| dkato | 0:f782d9c66c49 | 234 | |
| dkato | 0:f782d9c66c49 | 235 | void system_timer_tick_update(uint32_t ticks) | 
| dkato | 0:f782d9c66c49 | 236 | { | 
| dkato | 0:f782d9c66c49 | 237 | platform_enter_critical(); | 
| dkato | 0:f782d9c66c49 | 238 | //Keep runtime time | 
| dkato | 0:f782d9c66c49 | 239 | run_time_tick_ticks += ticks; | 
| dkato | 0:f782d9c66c49 | 240 | ns_list_foreach_safe(sys_timer_struct_s, cur, &system_timer_list) { | 
| dkato | 0:f782d9c66c49 | 241 | if (cur->timer_sys_launch_time <= ticks) { | 
| dkato | 0:f782d9c66c49 | 242 | arm_event_s event = { | 
| dkato | 0:f782d9c66c49 | 243 | .receiver = cur->timer_sys_launch_receiver, | 
| dkato | 0:f782d9c66c49 | 244 | .sender = 0, /**< Event sender Tasklet ID */ | 
| dkato | 0:f782d9c66c49 | 245 | .data_ptr = NULL, | 
| dkato | 0:f782d9c66c49 | 246 | .event_type = cur->timer_event_type, | 
| dkato | 0:f782d9c66c49 | 247 | .event_id = cur->timer_sys_launch_message, | 
| dkato | 0:f782d9c66c49 | 248 | .event_data = 0, | 
| dkato | 0:f782d9c66c49 | 249 | .priority = ARM_LIB_MED_PRIORITY_EVENT, | 
| dkato | 0:f782d9c66c49 | 250 | }; | 
| dkato | 0:f782d9c66c49 | 251 | eventOS_event_send(&event); | 
| dkato | 0:f782d9c66c49 | 252 | ns_list_remove(&system_timer_list, cur); | 
| dkato | 0:f782d9c66c49 | 253 | ns_list_add_to_start(&system_timer_free, cur); | 
| dkato | 0:f782d9c66c49 | 254 | } else { | 
| dkato | 0:f782d9c66c49 | 255 | cur->timer_sys_launch_time -= ticks; | 
| dkato | 0:f782d9c66c49 | 256 | } | 
| dkato | 0:f782d9c66c49 | 257 | } | 
| dkato | 0:f782d9c66c49 | 258 | |
| dkato | 0:f782d9c66c49 | 259 | platform_exit_critical(); | 
| dkato | 0:f782d9c66c49 | 260 | } | 
| dkato | 0:f782d9c66c49 | 261 |