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.
Dependencies: MAX44000 PWM_Tone_Library nexpaq_mdk
Fork of LED_Demo 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 "ns_timer.h" 00021 #include "nsdynmemLIB.h" 00022 #include "eventOS_event.h" 00023 #include "eventOS_callback_timer.h" 00024 00025 #ifndef ST_MAX 00026 #define ST_MAX 6 00027 #endif 00028 00029 typedef struct sys_timer_struct_s { 00030 uint32_t timer_sys_launch_time; 00031 int8_t timer_sys_launch_receiver; 00032 uint8_t timer_sys_launch_message; 00033 uint8_t timer_event_type; 00034 00035 ns_list_link_t link; 00036 } sys_timer_struct_s; 00037 00038 #define TIMER_SYS_TICK_PERIOD 10 // milliseconds 00039 #define TIMER_SYS_TICK_SLOTS (TIMER_SYS_TICK_PERIOD * 20) // 50us slots 00040 00041 static uint32_t run_time_tick_ticks = 0; 00042 static NS_LIST_DEFINE(system_timer_free, sys_timer_struct_s, link); 00043 static NS_LIST_DEFINE(system_timer_list, sys_timer_struct_s, link); 00044 static int8_t sys_timer_id = -1; 00045 00046 00047 static sys_timer_struct_s *sys_timer_dynamically_allocate(void); 00048 static void timer_sys_interrupt(int8_t timer_id, uint16_t slots); 00049 00050 00051 00052 /* 00053 * Initializes timers and starts system timer 00054 */ 00055 void timer_sys_init(void) 00056 { 00057 run_time_tick_ticks = 0; 00058 00059 sys_timer_id = eventOS_callback_timer_register(timer_sys_interrupt); 00060 00061 // Clear old timers 00062 ns_list_foreach_safe(sys_timer_struct_s, temp, &system_timer_list) { 00063 ns_list_remove(&system_timer_list, temp); 00064 ns_dyn_mem_free(temp); 00065 } 00066 // Clear old free timer entrys 00067 ns_list_foreach_safe(sys_timer_struct_s, temp, &system_timer_free) { 00068 ns_list_remove(&system_timer_free, temp); 00069 ns_dyn_mem_free(temp); 00070 } 00071 00072 for (uint8_t i = 0; i < ST_MAX; i++) { 00073 sys_timer_struct_s *temp = sys_timer_dynamically_allocate(); 00074 if (temp) { 00075 ns_list_add_to_start(&system_timer_free, temp); 00076 } 00077 } 00078 00079 if (sys_timer_id >= 0) { 00080 eventOS_callback_timer_start(sys_timer_id, TIMER_SYS_TICK_SLOTS); 00081 } 00082 } 00083 00084 00085 00086 /*-------------------SYSTEM TIMER FUNCTIONS--------------------------*/ 00087 void timer_sys_disable(void) 00088 { 00089 eventOS_callback_timer_stop(sys_timer_id); 00090 } 00091 00092 /* 00093 * Starts ticking system timer interrupts every 10ms 00094 */ 00095 int8_t timer_sys_wakeup(void) 00096 { 00097 int8_t ret_val = -1; 00098 if (sys_timer_id >= 0) { 00099 ret_val = eventOS_callback_timer_start(sys_timer_id, TIMER_SYS_TICK_SLOTS); 00100 } 00101 return ret_val; 00102 } 00103 00104 00105 static void timer_sys_interrupt(int8_t timer_id, uint16_t slots) 00106 { 00107 (void)timer_id; 00108 (void)slots; 00109 eventOS_callback_timer_start(sys_timer_id, TIMER_SYS_TICK_SLOTS); 00110 00111 system_timer_tick_update(1); 00112 } 00113 00114 00115 00116 /* * * * * * * * * */ 00117 00118 static sys_timer_struct_s *sys_timer_dynamically_allocate(void) 00119 { 00120 return ns_dyn_mem_alloc(sizeof(sys_timer_struct_s)); 00121 } 00122 00123 static sys_timer_struct_s *timer_struct_get(void) 00124 { 00125 sys_timer_struct_s *timer; 00126 platform_enter_critical(); 00127 timer = ns_list_get_first(&system_timer_free); 00128 if (timer) { 00129 ns_list_remove(&system_timer_free, timer); 00130 } else { 00131 timer = sys_timer_dynamically_allocate(); 00132 } 00133 platform_exit_critical(); 00134 return timer; 00135 } 00136 00137 uint32_t timer_get_runtime_ticks(void) // only used in dev_stats_internal.c 00138 { 00139 uint32_t ret_val; 00140 platform_enter_critical(); 00141 ret_val = run_time_tick_ticks; 00142 platform_exit_critical(); 00143 return ret_val; 00144 } 00145 00146 00147 00148 int8_t eventOS_event_timer_request(uint8_t snmessage, uint8_t event_type, int8_t tasklet_id, uint32_t time) 00149 { 00150 int8_t res = -1; 00151 sys_timer_struct_s *timer = NULL; 00152 00153 platform_enter_critical(); 00154 // Note that someone wanting 20ms gets 2 ticks, thanks to this test. 30ms would be 4 ticks. 00155 // And why shouldn't they be able to get a 1-tick callback? 00156 if (time > 2 * TIMER_SYS_TICK_PERIOD) { 00157 time /= TIMER_SYS_TICK_PERIOD; 00158 // XXX Why this? Someone wanting 50ms shouldn't get 6 ticks. Round to nearest, maybe? 00159 time++; 00160 } else { 00161 time = 2; 00162 } 00163 timer = timer_struct_get(); 00164 if (timer) { 00165 timer->timer_sys_launch_message = snmessage; 00166 timer->timer_sys_launch_receiver = tasklet_id; 00167 timer->timer_event_type = event_type; 00168 timer->timer_sys_launch_time = time; 00169 ns_list_add_to_start(&system_timer_list, timer); 00170 res = 0; 00171 } 00172 platform_exit_critical(); 00173 return res; 00174 } 00175 00176 int8_t eventOS_event_timer_cancel(uint8_t snmessage, int8_t tasklet_id) 00177 { 00178 int8_t res = -1; 00179 platform_enter_critical(); 00180 ns_list_foreach(sys_timer_struct_s, cur, &system_timer_list) { 00181 if (cur->timer_sys_launch_receiver == tasklet_id && cur->timer_sys_launch_message == snmessage) { 00182 ns_list_remove(&system_timer_list, cur); 00183 ns_list_add_to_start(&system_timer_free, cur); 00184 res = 0; 00185 break; 00186 } 00187 } 00188 00189 platform_exit_critical(); 00190 return res; 00191 } 00192 00193 00194 uint32_t eventOS_event_timer_shortest_active_timer(void) 00195 { 00196 uint32_t ret_val = 0; 00197 00198 platform_enter_critical(); 00199 ns_list_foreach(sys_timer_struct_s, cur, &system_timer_list) { 00200 if (ret_val == 0 || cur->timer_sys_launch_time < ret_val) { 00201 ret_val = cur->timer_sys_launch_time; 00202 } 00203 } 00204 00205 platform_exit_critical(); 00206 //Convert ticks to ms 00207 ret_val *= TIMER_SYS_TICK_PERIOD; 00208 return ret_val; 00209 } 00210 00211 void system_timer_tick_update(uint32_t ticks) 00212 { 00213 platform_enter_critical(); 00214 //Keep runtime time 00215 run_time_tick_ticks += ticks; 00216 ns_list_foreach_safe(sys_timer_struct_s, cur, &system_timer_list) { 00217 if (cur->timer_sys_launch_time <= ticks) { 00218 arm_event_s event = { 00219 .receiver = cur->timer_sys_launch_receiver, 00220 .sender = 0, /**< Event sender Tasklet ID */ 00221 .data_ptr = NULL, 00222 .event_type = cur->timer_event_type, 00223 .event_id = cur->timer_sys_launch_message, 00224 .event_data = 0, 00225 .priority = ARM_LIB_MED_PRIORITY_EVENT, 00226 }; 00227 eventOS_event_send(&event); 00228 ns_list_remove(&system_timer_list, cur); 00229 ns_list_add_to_start(&system_timer_free, cur); 00230 } else { 00231 cur->timer_sys_launch_time -= ticks; 00232 } 00233 } 00234 00235 platform_exit_critical(); 00236 } 00237
Generated on Tue Jul 12 2022 12:28:51 by
