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: TYBLE16_simple_data_logger TYBLE16_MP3_Air
SysTimer.h
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2019 ARM Limited 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 #ifndef MBED_SYS_TIMER_H 00018 #define MBED_SYS_TIMER_H 00019 00020 #include "platform/NonCopyable.h" 00021 #include "platform/mbed_atomic.h" 00022 #include "drivers/TimerEvent.h" 00023 #include "cmsis.h" 00024 00025 extern "C" { 00026 #if defined(TARGET_CORTEX_A) 00027 #include "irq_ctrl.h" 00028 #endif 00029 } 00030 00031 namespace mbed { 00032 namespace internal { 00033 00034 /** 00035 * \defgroup mbed_SysTimer SysTimer class 00036 * \ingroup platform-internal-api 00037 * @{ 00038 */ 00039 00040 /** 00041 * The SysTimer class is used to provide timing for system suspension, and 00042 * the idle loop in TICKLESS mode. 00043 * 00044 * Template for speed for testing - only one instance will be used normally. 00045 * 00046 * @note SysTimer is not the part of Mbed API. 00047 */ 00048 template <uint32_t US_IN_TICK, bool IRQ = true> 00049 class SysTimer: private mbed::TimerEvent, private mbed::NonCopyable<SysTimer<US_IN_TICK, IRQ> > { 00050 public: 00051 00052 /** 00053 * Default constructor uses LPTICKER if available (so the timer will 00054 * continue to run in deep sleep), else USTICKER. 00055 */ 00056 SysTimer(); 00057 00058 SysTimer(const ticker_data_t *data); 00059 00060 virtual ~SysTimer(); 00061 00062 /** 00063 * Get the interrupt number for the tick 00064 * 00065 * @return interrupt number 00066 */ 00067 #if TARGET_CORTEX_A 00068 static IRQn_ID_t get_irq_number(); 00069 #elif TARGET_CORTEX_M 00070 static IRQn_Type get_irq_number(); 00071 #endif 00072 00073 /** 00074 * Set the wake time 00075 * 00076 * Schedules an interrupt to cause wake-up in time for the event. Interrupt 00077 * may be arranged early to account for latency. If the time has already 00078 * passed, no interrupt will be scheduled. 00079 * 00080 * This is called from outside a critical section, as it is known to be 00081 * a slow operation. 00082 * 00083 * If the wake time is already set, this is a no-op. But that check is racy, 00084 * which means wake_time_set() should be rechecked after taking a critical 00085 * section. 00086 * 00087 * As a side-effect, this clears the unacknowledged tick count - the caller 00088 * is expected to use update_and_get_tick() after the suspend operation. 00089 * 00090 * @param at Wake up tick 00091 * @warning If the ticker tick is already scheduled it needs to be cancelled first! 00092 */ 00093 void set_wake_time(uint64_t at); 00094 00095 /** 00096 * Check whether the wake time has passed 00097 * 00098 * This is a fast operation, based on checking whether the wake interrupt 00099 * has run. 00100 * 00101 * @return true if the specified wake tick has passed 00102 */ 00103 bool wake_time_passed() const 00104 { 00105 return core_util_atomic_load_bool (&_wake_time_passed); 00106 } 00107 00108 /** 00109 * Check whether wake timer is active 00110 * 00111 * @return true if the wake timer is active. 00112 */ 00113 bool wake_time_set() const 00114 { 00115 return core_util_atomic_load_bool (&_wake_time_set); 00116 } 00117 00118 /** 00119 * Cancel any pending wake 00120 */ 00121 void cancel_wake(); 00122 00123 /** 00124 * Schedule an os tick to fire 00125 * 00126 * Ticks will be rescheduled automatically every tick until cancel_tick is called. 00127 * 00128 * A tick will be fired immediately if there are any unacknowledged ticks. 00129 * 00130 * @warning If a tick is already scheduled it needs to be cancelled first! 00131 */ 00132 void start_tick(); 00133 00134 /** 00135 * Acknowledge an os tick 00136 * 00137 * This will queue another os tick immediately if the os is running slow 00138 */ 00139 void acknowledge_tick(); 00140 00141 /** 00142 * Prevent any more scheduled ticks from triggering 00143 * 00144 * If called from OS tick context, there may be remaining unacknowledged ticks. 00145 */ 00146 void cancel_tick(); 00147 00148 /** 00149 * Check whether ticker is active 00150 * 00151 * Each time the tick interrupt fires, it is automatically rescheduled, 00152 * so this will remain true once the tick is started, except during 00153 * processing. 00154 * 00155 * @return true if the ticker is active. 00156 */ 00157 bool ticking() const 00158 { 00159 return core_util_atomic_load_bool (&_ticking); 00160 } 00161 00162 /** 00163 * Check unacknowledged ticks 00164 * 00165 * Returns the count of how many times the OS timer has been queued minus 00166 * the number of times is has been acknowledged. 00167 * 00168 * get_tick() - unacknowledged_ticks() should equal the OS's tick count, 00169 * although such a calculation is not atomic if the ticker is currently running. 00170 * 00171 * @return number of unacknowledged ticks 00172 */ 00173 int unacknowledged_ticks() const 00174 { 00175 return core_util_atomic_load_u8(&_unacknowledged_ticks); 00176 } 00177 00178 /** Get the current tick count 00179 * 00180 * This count is updated by the ticker interrupt, if the ticker interrupt 00181 * is running. It the ticker interrupt is not running, update_and_get_tick() 00182 * should be used instead. 00183 * 00184 * This indicates how many ticks have been generated by the tick interrupt. 00185 * The os_timer should equal this number minus the number of unacknowledged ticks. 00186 * 00187 * @return The number of ticks since timer creation. 00188 */ 00189 uint64_t get_tick() const; 00190 00191 /** Update and get the current tick count 00192 * 00193 * This is a slow operation that reads the timer and adjusts for elapsed time. 00194 * Can only be used when the ticker is not running, as there is no IRQ 00195 * synchronization. 00196 * 00197 * This clears the unacknowledged tick counter - the caller is assumed to update 00198 * their timer based on this return. 00199 * 00200 * @return The number of ticks since timer creation. 00201 */ 00202 uint64_t update_and_get_tick(); 00203 00204 /** 00205 * Returns time since last tick 00206 * 00207 * @return Relative time in microseconds 00208 */ 00209 us_timestamp_t get_time_since_tick() const; 00210 00211 /** 00212 * Get the time 00213 * 00214 * Returns the instantaneous precision time from underlying timer. 00215 * This is a slow operation so should not be called from critical sections. 00216 * 00217 * @return Current time in microseconds 00218 */ 00219 us_timestamp_t get_time() const; 00220 00221 protected: 00222 virtual void handler(); 00223 void _increment_tick(); 00224 void _schedule_tick(); 00225 uint64_t _elapsed_ticks() const; 00226 static void _set_irq_pending(); 00227 static void _clear_irq_pending(); 00228 us_timestamp_t _time_us; 00229 uint64_t _tick; 00230 uint8_t _unacknowledged_ticks; 00231 bool _wake_time_set; 00232 bool _wake_time_passed; 00233 bool _wake_early; 00234 bool _ticking; 00235 bool _deep_sleep_locked; 00236 }; 00237 00238 /** @} */ 00239 00240 } 00241 } 00242 00243 #endif
Generated on Tue Jul 12 2022 13:54:55 by
