Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SysTimer.h Source File

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