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.
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 16:40:11 by
1.7.2