Simple 64-bit timer for mbed. It is a drastically simplified version of Timer64 class by Tom Doyle. It is meant to be used in single-thread applications, where timer is used frequently, while standard 32-bit Timer is not enough.

Fork of Timer64 by Tom Doyle

Committer:
tedoyle
Date:
Mon Mar 28 20:56:40 2016 +0000
Revision:
4:9ca673a83acb
Parent:
3:8396d3e6eb62
Child:
5:e2a2d9790e36
Added documentation.; Added check for NULL pointer.;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tedoyle 4:9ca673a83acb 1 /* mbed Microcontroller Library
tedoyle 4:9ca673a83acb 2 * Copyright (c) 2006-2016 ARM Limited
tedoyle 4:9ca673a83acb 3 *
tedoyle 4:9ca673a83acb 4 * Licensed under the Apache License, Version 2.0 (the "License");
tedoyle 4:9ca673a83acb 5 * you may not use this file except in compliance with the License.
tedoyle 4:9ca673a83acb 6 * You may obtain a copy of the License at
tedoyle 4:9ca673a83acb 7 *
tedoyle 4:9ca673a83acb 8 * http://www.apache.org/licenses/LICENSE-2.0
tedoyle 4:9ca673a83acb 9 *
tedoyle 4:9ca673a83acb 10 * Unless required by applicable law or agreed to in writing, software
tedoyle 4:9ca673a83acb 11 * distributed under the License is distributed on an "AS IS" BASIS,
tedoyle 4:9ca673a83acb 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
tedoyle 4:9ca673a83acb 13 * See the License for the specific language governing permissions and
tedoyle 4:9ca673a83acb 14 * limitations under the License.
tedoyle 4:9ca673a83acb 15 *
tedoyle 4:9ca673a83acb 16 * Modified by Tom Doyle <ThomasEDoyle@gmail.com>
tedoyle 4:9ca673a83acb 17 *
tedoyle 4:9ca673a83acb 18 */
tedoyle 4:9ca673a83acb 19
tedoyle 0:1e0e79e82839 20 #ifndef __NEW_TIMER64__
tedoyle 0:1e0e79e82839 21 #define __NEW_TIMER64__
tedoyle 0:1e0e79e82839 22
tedoyle 0:1e0e79e82839 23 #include "platform.h"
tedoyle 0:1e0e79e82839 24 #include "ticker_api.h"
tedoyle 0:1e0e79e82839 25 #include <stdint.h>
tedoyle 0:1e0e79e82839 26 #include "rtos.h"
tedoyle 0:1e0e79e82839 27
tedoyle 1:497fba179833 28 #define TIMER64_OK 0
tedoyle 0:1e0e79e82839 29
tedoyle 1:497fba179833 30 #define TIMER64_ERROR_NOT_INITIALIZED -1
tedoyle 4:9ca673a83acb 31 #define TIMER64_ERROR_NULL_POINTER -2
tedoyle 0:1e0e79e82839 32
tedoyle 1:497fba179833 33 #define TIMER64_WARNING_ALREADY_INITIALIZED 1
tedoyle 1:497fba179833 34 #define TIMER64_WARNING_ALREADY_RUNNING 2
tedoyle 1:497fba179833 35 #define TIMER64_WARNING_ALREADY_STOPPED 3
tedoyle 2:e89b02820e93 36 #define TIMER64_WARNING_ALREADY_RELEASED 4
tedoyle 0:1e0e79e82839 37
tedoyle 3:8396d3e6eb62 38 #define TIMER64_DEFAULT_ROLLOVER_CHECK_IN_MSECS 30000
tedoyle 3:8396d3e6eb62 39 #define TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS 1000
tedoyle 3:8396d3e6eb62 40 #define TIMER64_MAX_ROLLOVER_CHECK_IN_MSECS 65535
tedoyle 0:1e0e79e82839 41
tedoyle 4:9ca673a83acb 42 /** Timer64 class
tedoyle 4:9ca673a83acb 43 * Used to define a 64 bit timer64 that is thread safe. The Timer64 behaves in a
tedoyle 4:9ca673a83acb 44 * similiar fashion to the mbed Timer class with the most notable exception that
tedoyle 4:9ca673a83acb 45 * the Timer64 will not rollover after 2^31 microseconds (approximately 35.8 minutes).
tedoyle 4:9ca673a83acb 46 * The Timer64 extends the rollover time to 2^64 microsecnods (approximately 585,000 years!)
tedoyle 4:9ca673a83acb 47 *
tedoyle 4:9ca673a83acb 48 * The Timer64 class is also designed to be thread safe. The following functions can be
tedoyle 4:9ca673a83acb 49 * called from any thread after the class is instaniated and initialized:
tedoyle 4:9ca673a83acb 50 *
tedoyle 4:9ca673a83acb 51 * - start()
tedoyle 4:9ca673a83acb 52 * - stop()
tedoyle 4:9ca673a83acb 53 * - reset()
tedoyle 4:9ca673a83acb 54 * - read_us()
tedoyle 4:9ca673a83acb 55 * - read_ms()
tedoyle 4:9ca673a83acb 56 * - read()
tedoyle 4:9ca673a83acb 57 * - reset()
tedoyle 4:9ca673a83acb 58 * - isRunning()
tedoyle 4:9ca673a83acb 59 *
tedoyle 4:9ca673a83acb 60 * It is to be noted that the init() and release() methods need to be called from the same thread.
tedoyle 4:9ca673a83acb 61 *
tedoyle 4:9ca673a83acb 62 * Give the Timer64 library a try and let me know if it works for you. Will gladly take suggestions
tedoyle 4:9ca673a83acb 63 * on how to make it better.
tedoyle 4:9ca673a83acb 64 *
tedoyle 4:9ca673a83acb 65 * Simple Example
tedoyle 4:9ca673a83acb 66 * @code
tedoyle 4:9ca673a83acb 67 * #include "mbed.h"
tedoyle 4:9ca673a83acb 68 * #include "rtos.h"
tedoyle 4:9ca673a83acb 69 * #include "Timer64.h"
tedoyle 4:9ca673a83acb 70 *
tedoyle 4:9ca673a83acb 71 * Timer64 timer64;
tedoyle 4:9ca673a83acb 72 *
tedoyle 4:9ca673a83acb 73 * int main()
tedoyle 4:9ca673a83acb 74 * {
tedoyle 4:9ca673a83acb 75 * uint64_t timeInUsec;
tedoyle 4:9ca673a83acb 76 * timer64.init();
tedoyle 4:9ca673a83acb 77 * timer64.start();
tedoyle 4:9ca673a83acb 78 * Thread::wait(100);
tedoyle 4:9ca673a83acb 79 * timer64.stop();
tedoyle 4:9ca673a83acb 80 * timer64.read_us(&timeInUsec);
tedoyle 4:9ca673a83acb 81 * printf("Test - Elapsed time = %llu usec\n\n", timeInUsec);
tedoyle 4:9ca673a83acb 82 * timer64.reset();
tedoyle 4:9ca673a83acb 83 * timer64.release();
tedoyle 4:9ca673a83acb 84 *
tedoyle 4:9ca673a83acb 85 * while (1)
tedoyle 4:9ca673a83acb 86 * {
tedoyle 4:9ca673a83acb 87 * Thread::wait(1000);
tedoyle 4:9ca673a83acb 88 * }
tedoyle 4:9ca673a83acb 89 * }
tedoyle 4:9ca673a83acb 90 * @endcode
tedoyle 4:9ca673a83acb 91 */
tedoyle 4:9ca673a83acb 92 class Timer64
tedoyle 0:1e0e79e82839 93 {
tedoyle 0:1e0e79e82839 94
tedoyle 0:1e0e79e82839 95 public:
tedoyle 0:1e0e79e82839 96 Timer64();
tedoyle 1:497fba179833 97 ~Timer64();
tedoyle 0:1e0e79e82839 98
tedoyle 1:497fba179833 99 /** Initialize the timer - this must be called before the timer can be used
tedoyle 4:9ca673a83acb 100 *
tedoyle 4:9ca673a83acb 101 * @param rolloverCheckTimeInMsecc specifies how ofter a rollover check is performed.
tedoyle 4:9ca673a83acb 102 * This parameter is bounded by TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS and
tedoyle 4:9ca673a83acb 103 * TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS with a default value of
tedoyle 4:9ca673a83acb 104 * TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS
tedoyle 4:9ca673a83acb 105 *
tedoyle 4:9ca673a83acb 106 * @returns
tedoyle 4:9ca673a83acb 107 * TIMER64_OK
tedoyle 4:9ca673a83acb 108 * TIMER64_WARNING_ALREADY_INITIALIZED
tedoyle 0:1e0e79e82839 109 */
tedoyle 4:9ca673a83acb 110 int init(uint32_t rolloverCheckTimeInMsecc = TIMER64_DEFAULT_ROLLOVER_CHECK_IN_MSECS);
tedoyle 0:1e0e79e82839 111
tedoyle 4:9ca673a83acb 112 /** Release the timer - must be called from the same thread calling init()
tedoyle 4:9ca673a83acb 113 *
tedoyle 4:9ca673a83acb 114 * @returns
tedoyle 4:9ca673a83acb 115 * TIMER64_OK
tedoyle 4:9ca673a83acb 116 * TIMER64_WARNING_ALREADY_RELEASED
tedoyle 0:1e0e79e82839 117 */
tedoyle 0:1e0e79e82839 118 int release(void);
tedoyle 0:1e0e79e82839 119
tedoyle 4:9ca673a83acb 120 /** Start the timer - this method is thread safe
tedoyle 4:9ca673a83acb 121 *
tedoyle 4:9ca673a83acb 122 * @returns
tedoyle 4:9ca673a83acb 123 * TIMER64_OK
tedoyle 4:9ca673a83acb 124 * TIMER64_ERROR_NOT_INITIALIZED
tedoyle 4:9ca673a83acb 125 * TIMER64_WARNING_ALREADY_RUNNING
tedoyle 0:1e0e79e82839 126 */
tedoyle 0:1e0e79e82839 127 int start(void);
tedoyle 0:1e0e79e82839 128
tedoyle 4:9ca673a83acb 129 /** Stop the timer - this method is thread safe
tedoyle 4:9ca673a83acb 130 *
tedoyle 4:9ca673a83acb 131 * @returns
tedoyle 4:9ca673a83acb 132 * TIMER64_OK
tedoyle 4:9ca673a83acb 133 * TIMER64_ERROR_NOT_INITIALIZED
tedoyle 4:9ca673a83acb 134 * TIMER64_WARNING_ALREADY_STOPPED
tedoyle 0:1e0e79e82839 135 */
tedoyle 0:1e0e79e82839 136 int stop(void);
tedoyle 0:1e0e79e82839 137
tedoyle 4:9ca673a83acb 138 /** Reset the timer - this method is thread safe
tedoyle 4:9ca673a83acb 139 *
tedoyle 4:9ca673a83acb 140 * @returns
tedoyle 4:9ca673a83acb 141 * TIMER64_OK
tedoyle 4:9ca673a83acb 142 * TIMER64_ERROR_NOT_INITIALIZED
tedoyle 0:1e0e79e82839 143 */
tedoyle 0:1e0e79e82839 144 int reset(void);
tedoyle 0:1e0e79e82839 145
tedoyle 4:9ca673a83acb 146 /** Read the timer value in microseconds - this method is thread safe
tedoyle 4:9ca673a83acb 147 *
tedoyle 4:9ca673a83acb 148 * @param timeInUsec specifies a pointer to a uint64_t where to save the current time in microseconds
tedoyle 4:9ca673a83acb 149 *
tedoyle 4:9ca673a83acb 150 * @returns
tedoyle 4:9ca673a83acb 151 * TIMER64_OK
tedoyle 4:9ca673a83acb 152 * TIMER64_ERROR_NOT_INITIALIZED
tedoyle 4:9ca673a83acb 153 * TIMER64_ERROR_NULL_POINTER
tedoyle 0:1e0e79e82839 154 */
tedoyle 3:8396d3e6eb62 155 int read_us(uint64_t* timeInUsec = NULL);
tedoyle 0:1e0e79e82839 156
tedoyle 4:9ca673a83acb 157 /** Read the timer value in milliseconds - this method is thread safe
tedoyle 4:9ca673a83acb 158 *
tedoyle 4:9ca673a83acb 159 * @param timeInMsec specifies a pointer to a uint64_t where to save the current time in milliseconds
tedoyle 4:9ca673a83acb 160 *
tedoyle 4:9ca673a83acb 161 * @returns
tedoyle 4:9ca673a83acb 162 * TIMER64_OK
tedoyle 4:9ca673a83acb 163 * TIMER64_ERROR_NOT_INITIALIZED
tedoyle 4:9ca673a83acb 164 * TIMER64_ERROR_NULL_POINTER
tedoyle 0:1e0e79e82839 165 */
tedoyle 3:8396d3e6eb62 166 int read_ms(uint64_t* timeInMsec = NULL);
tedoyle 0:1e0e79e82839 167
tedoyle 4:9ca673a83acb 168 /** Read the timer value in seconds - this method is thread safe
tedoyle 4:9ca673a83acb 169 *
tedoyle 4:9ca673a83acb 170 * @param timeInMsec specifies a pointer to a double where to save the current time in seconds
tedoyle 4:9ca673a83acb 171 *
tedoyle 4:9ca673a83acb 172 * @returns
tedoyle 4:9ca673a83acb 173 * TIMER64_OK
tedoyle 4:9ca673a83acb 174 * TIMER64_ERROR_NOT_INITIALIZED
tedoyle 4:9ca673a83acb 175 * TIMER64_ERROR_NULL_POINTER
tedoyle 0:1e0e79e82839 176 */
tedoyle 3:8396d3e6eb62 177 int read(double* timeInSec = NULL);
tedoyle 4:9ca673a83acb 178
tedoyle 4:9ca673a83acb 179 /** Check to see if timer is running - this method is thread safe
tedoyle 4:9ca673a83acb 180 *
tedoyle 4:9ca673a83acb 181 * @param running specifies a pointer to a bool where to save the running status
tedoyle 4:9ca673a83acb 182 *
tedoyle 4:9ca673a83acb 183 * @returns
tedoyle 4:9ca673a83acb 184 * TIMER64_OK
tedoyle 4:9ca673a83acb 185 * TIMER64_ERROR_NOT_INITIALIZED
tedoyle 4:9ca673a83acb 186 * TIMER64_ERROR_NULL_POINTER
tedoyle 4:9ca673a83acb 187 */
tedoyle 4:9ca673a83acb 188 int isRunning(bool* running);
tedoyle 0:1e0e79e82839 189
tedoyle 0:1e0e79e82839 190 private:
tedoyle 0:1e0e79e82839 191 bool _timerInitialized;
tedoyle 1:497fba179833 192 bool _timerRunning; // whether the timer is running
tedoyle 0:1e0e79e82839 193 timestamp_t _tickerStartTimeUsec; // the start time of the latest slice
tedoyle 0:1e0e79e82839 194 uint64_t _totalTimeUsec; // any accumulated time from previous slices
tedoyle 0:1e0e79e82839 195 const ticker_data_t *_ticker_data;
tedoyle 0:1e0e79e82839 196 RtosTimer* _rollOverCheckTimer;
tedoyle 0:1e0e79e82839 197 uint32_t _rollOverCheckTimerPeriodInMsec;
tedoyle 3:8396d3e6eb62 198 Semaphore* _sem;
tedoyle 3:8396d3e6eb62 199
tedoyle 0:1e0e79e82839 200 static void _rollOverCheck(void const* args);
tedoyle 3:8396d3e6eb62 201 static uint64_t _read_us(void const* args);
tedoyle 0:1e0e79e82839 202 };
tedoyle 0:1e0e79e82839 203
tedoyle 0:1e0e79e82839 204 #endif