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.
Fork of mbed-os by
system_timer.c
00001 /* 00002 * Copyright (c) 2014-2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "ns_types.h" 00017 #include "ns_list.h" 00018 #include "timer_sys.h" 00019 #include "platform/arm_hal_interrupt.h" 00020 #include "platform/arm_hal_timer.h" 00021 #include "ns_timer.h" 00022 #include "nsdynmemLIB.h" 00023 #include "eventOS_event.h" 00024 #include "eventOS_callback_timer.h" 00025 00026 #ifndef ST_MAX 00027 #define ST_MAX 6 00028 #endif 00029 00030 typedef struct sys_timer_struct_s { 00031 uint32_t timer_sys_launch_time; 00032 int8_t timer_sys_launch_receiver; 00033 uint8_t timer_sys_launch_message; 00034 uint8_t timer_event_type; 00035 00036 ns_list_link_t link; 00037 } sys_timer_struct_s; 00038 00039 #define TIMER_SLOTS_PER_MS 20 00040 #define TIMER_SYS_TICK_PERIOD 10 // milliseconds 00041 00042 static uint32_t run_time_tick_ticks = 0; 00043 static NS_LIST_DEFINE(system_timer_free, sys_timer_struct_s, link); 00044 static NS_LIST_DEFINE(system_timer_list, sys_timer_struct_s, link); 00045 00046 00047 static sys_timer_struct_s *sys_timer_dynamically_allocate(void); 00048 static void timer_sys_interrupt(void); 00049 00050 #ifndef NS_EVENTLOOP_USE_TICK_TIMER 00051 static int8_t platform_tick_timer_start(uint32_t period_ms); 00052 /* Implement platform tick timer using eventOS timer */ 00053 // platform tick timer callback function 00054 static void (*tick_timer_callback)(void); 00055 static int8_t tick_timer_id = -1; // eventOS timer id for tick timer 00056 00057 // EventOS timer callback function 00058 static void tick_timer_eventOS_callback(int8_t timer_id, uint16_t slots) 00059 { 00060 // Not interested in timer id or slots 00061 (void)slots; 00062 // Call the tick timer callback 00063 if (tick_timer_callback != NULL && timer_id == tick_timer_id) { 00064 platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); 00065 tick_timer_callback(); 00066 } 00067 } 00068 00069 static int8_t platform_tick_timer_register(void (*tick_timer_cb)(void)) 00070 { 00071 tick_timer_callback = tick_timer_cb; 00072 tick_timer_id = eventOS_callback_timer_register(tick_timer_eventOS_callback); 00073 return tick_timer_id; 00074 } 00075 00076 static int8_t platform_tick_timer_start(uint32_t period_ms) 00077 { 00078 return eventOS_callback_timer_start(tick_timer_id, TIMER_SLOTS_PER_MS * period_ms); 00079 } 00080 00081 static int8_t platform_tick_timer_stop(void) 00082 { 00083 return eventOS_callback_timer_stop(tick_timer_id); 00084 } 00085 #endif // !NS_EVENTLOOP_USE_TICK_TIMER 00086 00087 /* 00088 * Initializes timers and starts system timer 00089 */ 00090 void timer_sys_init(void) 00091 { 00092 run_time_tick_ticks = 0; 00093 00094 // Clear old timers 00095 ns_list_foreach_safe(sys_timer_struct_s, temp, &system_timer_list) { 00096 ns_list_remove(&system_timer_list, temp); 00097 ns_dyn_mem_free(temp); 00098 } 00099 // Clear old free timer entrys 00100 ns_list_foreach_safe(sys_timer_struct_s, temp, &system_timer_free) { 00101 ns_list_remove(&system_timer_free, temp); 00102 ns_dyn_mem_free(temp); 00103 } 00104 00105 for (uint8_t i = 0; i < ST_MAX; i++) { 00106 sys_timer_struct_s *temp = sys_timer_dynamically_allocate(); 00107 if (temp) { 00108 ns_list_add_to_start(&system_timer_free, temp); 00109 } 00110 } 00111 00112 platform_tick_timer_register(timer_sys_interrupt); 00113 platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); 00114 } 00115 00116 00117 00118 /*-------------------SYSTEM TIMER FUNCTIONS--------------------------*/ 00119 void timer_sys_disable(void) 00120 { 00121 platform_tick_timer_stop(); 00122 } 00123 00124 /* 00125 * Starts ticking system timer interrupts every 10ms 00126 */ 00127 int8_t timer_sys_wakeup(void) 00128 { 00129 return platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); 00130 } 00131 00132 00133 static void timer_sys_interrupt(void) 00134 { 00135 system_timer_tick_update(1); 00136 } 00137 00138 00139 00140 /* * * * * * * * * */ 00141 00142 static sys_timer_struct_s *sys_timer_dynamically_allocate(void) 00143 { 00144 return (sys_timer_struct_s*)ns_dyn_mem_alloc(sizeof(sys_timer_struct_s)); 00145 } 00146 00147 static sys_timer_struct_s *timer_struct_get(void) 00148 { 00149 sys_timer_struct_s *timer; 00150 platform_enter_critical(); 00151 timer = ns_list_get_first(&system_timer_free); 00152 if (timer) { 00153 ns_list_remove(&system_timer_free, timer); 00154 } else { 00155 timer = sys_timer_dynamically_allocate(); 00156 } 00157 platform_exit_critical(); 00158 return timer; 00159 } 00160 00161 uint32_t timer_get_runtime_ticks(void) // only used in dev_stats_internal.c 00162 { 00163 uint32_t ret_val; 00164 platform_enter_critical(); 00165 ret_val = run_time_tick_ticks; 00166 platform_exit_critical(); 00167 return ret_val; 00168 } 00169 00170 00171 00172 int8_t eventOS_event_timer_request(uint8_t snmessage, uint8_t event_type, int8_t tasklet_id, uint32_t time) 00173 { 00174 int8_t res = -1; 00175 sys_timer_struct_s *timer = NULL; 00176 00177 platform_enter_critical(); 00178 // Note that someone wanting 20ms gets 2 ticks, thanks to this test. 30ms would be 4 ticks. 00179 // And why shouldn't they be able to get a 1-tick callback? 00180 if (time > 2 * TIMER_SYS_TICK_PERIOD) { 00181 time /= TIMER_SYS_TICK_PERIOD; 00182 // XXX Why this? Someone wanting 50ms shouldn't get 6 ticks. Round to nearest, maybe? 00183 time++; 00184 } else { 00185 time = 2; 00186 } 00187 timer = timer_struct_get(); 00188 if (timer) { 00189 timer->timer_sys_launch_message = snmessage; 00190 timer->timer_sys_launch_receiver = tasklet_id; 00191 timer->timer_event_type = event_type; 00192 timer->timer_sys_launch_time = time; 00193 ns_list_add_to_start(&system_timer_list, timer); 00194 res = 0; 00195 } 00196 platform_exit_critical(); 00197 return res; 00198 } 00199 00200 int8_t eventOS_event_timer_cancel(uint8_t snmessage, int8_t tasklet_id) 00201 { 00202 int8_t res = -1; 00203 platform_enter_critical(); 00204 ns_list_foreach(sys_timer_struct_s, cur, &system_timer_list) { 00205 if (cur->timer_sys_launch_receiver == tasklet_id && cur->timer_sys_launch_message == snmessage) { 00206 ns_list_remove(&system_timer_list, cur); 00207 ns_list_add_to_start(&system_timer_free, cur); 00208 res = 0; 00209 break; 00210 } 00211 } 00212 00213 platform_exit_critical(); 00214 return res; 00215 } 00216 00217 00218 uint32_t eventOS_event_timer_shortest_active_timer(void) 00219 { 00220 uint32_t ret_val = 0; 00221 00222 platform_enter_critical(); 00223 ns_list_foreach(sys_timer_struct_s, cur, &system_timer_list) { 00224 if (ret_val == 0 || cur->timer_sys_launch_time < ret_val) { 00225 ret_val = cur->timer_sys_launch_time; 00226 } 00227 } 00228 00229 platform_exit_critical(); 00230 //Convert ticks to ms 00231 ret_val *= TIMER_SYS_TICK_PERIOD; 00232 return ret_val; 00233 } 00234 00235 void system_timer_tick_update(uint32_t ticks) 00236 { 00237 platform_enter_critical(); 00238 //Keep runtime time 00239 run_time_tick_ticks += ticks; 00240 ns_list_foreach_safe(sys_timer_struct_s, cur, &system_timer_list) { 00241 if (cur->timer_sys_launch_time <= ticks) { 00242 arm_event_s event = { 00243 .receiver = cur->timer_sys_launch_receiver, 00244 .sender = 0, /**< Event sender Tasklet ID */ 00245 .data_ptr = NULL, 00246 .event_type = cur->timer_event_type, 00247 .event_id = cur->timer_sys_launch_message, 00248 .event_data = 0, 00249 .priority = ARM_LIB_MED_PRIORITY_EVENT, 00250 }; 00251 eventOS_event_send(&event); 00252 ns_list_remove(&system_timer_list, cur); 00253 ns_list_add_to_start(&system_timer_free, cur); 00254 } else { 00255 cur->timer_sys_launch_time -= ticks; 00256 } 00257 } 00258 00259 platform_exit_critical(); 00260 } 00261
Generated on Tue Jul 12 2022 13:16:13 by
