64 bit Timer Class.
Timer64.h@7:381bafbb2218, 2016-04-01 (annotated)
- Committer:
- tedoyle
- Date:
- Fri Apr 01 18:37:38 2016 +0000
- Revision:
- 7:381bafbb2218
- Parent:
- 5:e2a2d9790e36
Minor edits;
Who changed what in which revision?
User | Revision | Line number | New 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 | 7:381bafbb2218 | 20 | #ifndef __TIMER64__ |
tedoyle | 7:381bafbb2218 | 21 | #define __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 | 5:e2a2d9790e36 | 46 | * The Timer64 extends the rollover time to 2^64 microseconds (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 | 7:381bafbb2218 | 92 | |
tedoyle | 7:381bafbb2218 | 93 | class Timer64 |
tedoyle | 0:1e0e79e82839 | 94 | { |
tedoyle | 0:1e0e79e82839 | 95 | |
tedoyle | 0:1e0e79e82839 | 96 | public: |
tedoyle | 0:1e0e79e82839 | 97 | Timer64(); |
tedoyle | 1:497fba179833 | 98 | ~Timer64(); |
tedoyle | 0:1e0e79e82839 | 99 | |
tedoyle | 1:497fba179833 | 100 | /** Initialize the timer - this must be called before the timer can be used |
tedoyle | 4:9ca673a83acb | 101 | * |
tedoyle | 4:9ca673a83acb | 102 | * @param rolloverCheckTimeInMsecc specifies how ofter a rollover check is performed. |
tedoyle | 4:9ca673a83acb | 103 | * This parameter is bounded by TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS and |
tedoyle | 4:9ca673a83acb | 104 | * TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS with a default value of |
tedoyle | 4:9ca673a83acb | 105 | * TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS |
tedoyle | 4:9ca673a83acb | 106 | * |
tedoyle | 4:9ca673a83acb | 107 | * @returns |
tedoyle | 5:e2a2d9790e36 | 108 | * TIMER64_OK, |
tedoyle | 4:9ca673a83acb | 109 | * TIMER64_WARNING_ALREADY_INITIALIZED |
tedoyle | 0:1e0e79e82839 | 110 | */ |
tedoyle | 4:9ca673a83acb | 111 | int init(uint32_t rolloverCheckTimeInMsecc = TIMER64_DEFAULT_ROLLOVER_CHECK_IN_MSECS); |
tedoyle | 0:1e0e79e82839 | 112 | |
tedoyle | 4:9ca673a83acb | 113 | /** Release the timer - must be called from the same thread calling init() |
tedoyle | 4:9ca673a83acb | 114 | * |
tedoyle | 4:9ca673a83acb | 115 | * @returns |
tedoyle | 5:e2a2d9790e36 | 116 | * TIMER64_OK, |
tedoyle | 4:9ca673a83acb | 117 | * TIMER64_WARNING_ALREADY_RELEASED |
tedoyle | 0:1e0e79e82839 | 118 | */ |
tedoyle | 0:1e0e79e82839 | 119 | int release(void); |
tedoyle | 0:1e0e79e82839 | 120 | |
tedoyle | 4:9ca673a83acb | 121 | /** Start the timer - this method is thread safe |
tedoyle | 4:9ca673a83acb | 122 | * |
tedoyle | 4:9ca673a83acb | 123 | * @returns |
tedoyle | 5:e2a2d9790e36 | 124 | * TIMER64_OK, |
tedoyle | 5:e2a2d9790e36 | 125 | * TIMER64_ERROR_NOT_INITIALIZED, |
tedoyle | 4:9ca673a83acb | 126 | * TIMER64_WARNING_ALREADY_RUNNING |
tedoyle | 0:1e0e79e82839 | 127 | */ |
tedoyle | 0:1e0e79e82839 | 128 | int start(void); |
tedoyle | 0:1e0e79e82839 | 129 | |
tedoyle | 4:9ca673a83acb | 130 | /** Stop the timer - this method is thread safe |
tedoyle | 4:9ca673a83acb | 131 | * |
tedoyle | 4:9ca673a83acb | 132 | * @returns |
tedoyle | 5:e2a2d9790e36 | 133 | * TIMER64_OK, |
tedoyle | 5:e2a2d9790e36 | 134 | * TIMER64_ERROR_NOT_INITIALIZED, |
tedoyle | 4:9ca673a83acb | 135 | * TIMER64_WARNING_ALREADY_STOPPED |
tedoyle | 0:1e0e79e82839 | 136 | */ |
tedoyle | 0:1e0e79e82839 | 137 | int stop(void); |
tedoyle | 0:1e0e79e82839 | 138 | |
tedoyle | 4:9ca673a83acb | 139 | /** Reset the timer - this method is thread safe |
tedoyle | 4:9ca673a83acb | 140 | * |
tedoyle | 4:9ca673a83acb | 141 | * @returns |
tedoyle | 5:e2a2d9790e36 | 142 | * TIMER64_OK, |
tedoyle | 4:9ca673a83acb | 143 | * TIMER64_ERROR_NOT_INITIALIZED |
tedoyle | 0:1e0e79e82839 | 144 | */ |
tedoyle | 0:1e0e79e82839 | 145 | int reset(void); |
tedoyle | 0:1e0e79e82839 | 146 | |
tedoyle | 4:9ca673a83acb | 147 | /** Read the timer value in microseconds - this method is thread safe |
tedoyle | 4:9ca673a83acb | 148 | * |
tedoyle | 4:9ca673a83acb | 149 | * @param timeInUsec specifies a pointer to a uint64_t where to save the current time in microseconds |
tedoyle | 4:9ca673a83acb | 150 | * |
tedoyle | 4:9ca673a83acb | 151 | * @returns |
tedoyle | 5:e2a2d9790e36 | 152 | * TIMER64_OK, |
tedoyle | 5:e2a2d9790e36 | 153 | * TIMER64_ERROR_NOT_INITIALIZED, |
tedoyle | 4:9ca673a83acb | 154 | * TIMER64_ERROR_NULL_POINTER |
tedoyle | 0:1e0e79e82839 | 155 | */ |
tedoyle | 3:8396d3e6eb62 | 156 | int read_us(uint64_t* timeInUsec = NULL); |
tedoyle | 0:1e0e79e82839 | 157 | |
tedoyle | 4:9ca673a83acb | 158 | /** Read the timer value in milliseconds - this method is thread safe |
tedoyle | 4:9ca673a83acb | 159 | * |
tedoyle | 4:9ca673a83acb | 160 | * @param timeInMsec specifies a pointer to a uint64_t where to save the current time in milliseconds |
tedoyle | 4:9ca673a83acb | 161 | * |
tedoyle | 4:9ca673a83acb | 162 | * @returns |
tedoyle | 5:e2a2d9790e36 | 163 | * TIMER64_OK, |
tedoyle | 5:e2a2d9790e36 | 164 | * TIMER64_ERROR_NOT_INITIALIZED, |
tedoyle | 4:9ca673a83acb | 165 | * TIMER64_ERROR_NULL_POINTER |
tedoyle | 0:1e0e79e82839 | 166 | */ |
tedoyle | 3:8396d3e6eb62 | 167 | int read_ms(uint64_t* timeInMsec = NULL); |
tedoyle | 0:1e0e79e82839 | 168 | |
tedoyle | 4:9ca673a83acb | 169 | /** Read the timer value in seconds - this method is thread safe |
tedoyle | 4:9ca673a83acb | 170 | * |
tedoyle | 4:9ca673a83acb | 171 | * @param timeInMsec specifies a pointer to a double where to save the current time in seconds |
tedoyle | 4:9ca673a83acb | 172 | * |
tedoyle | 4:9ca673a83acb | 173 | * @returns |
tedoyle | 5:e2a2d9790e36 | 174 | * TIMER64_OK, |
tedoyle | 5:e2a2d9790e36 | 175 | * TIMER64_ERROR_NOT_INITIALIZED, |
tedoyle | 5:e2a2d9790e36 | 176 | * TIMER64_ERROR_NULL_POINTER, |
tedoyle | 0:1e0e79e82839 | 177 | */ |
tedoyle | 3:8396d3e6eb62 | 178 | int read(double* timeInSec = NULL); |
tedoyle | 4:9ca673a83acb | 179 | |
tedoyle | 4:9ca673a83acb | 180 | /** Check to see if timer is running - this method is thread safe |
tedoyle | 4:9ca673a83acb | 181 | * |
tedoyle | 4:9ca673a83acb | 182 | * @param running specifies a pointer to a bool where to save the running status |
tedoyle | 4:9ca673a83acb | 183 | * |
tedoyle | 4:9ca673a83acb | 184 | * @returns |
tedoyle | 5:e2a2d9790e36 | 185 | * TIMER64_OK, |
tedoyle | 5:e2a2d9790e36 | 186 | * TIMER64_ERROR_NOT_INITIALIZED, |
tedoyle | 4:9ca673a83acb | 187 | * TIMER64_ERROR_NULL_POINTER |
tedoyle | 4:9ca673a83acb | 188 | */ |
tedoyle | 4:9ca673a83acb | 189 | int isRunning(bool* running); |
tedoyle | 0:1e0e79e82839 | 190 | |
tedoyle | 0:1e0e79e82839 | 191 | private: |
tedoyle | 0:1e0e79e82839 | 192 | bool _timerInitialized; |
tedoyle | 1:497fba179833 | 193 | bool _timerRunning; // whether the timer is running |
tedoyle | 0:1e0e79e82839 | 194 | timestamp_t _tickerStartTimeUsec; // the start time of the latest slice |
tedoyle | 0:1e0e79e82839 | 195 | uint64_t _totalTimeUsec; // any accumulated time from previous slices |
tedoyle | 0:1e0e79e82839 | 196 | const ticker_data_t *_ticker_data; |
tedoyle | 0:1e0e79e82839 | 197 | RtosTimer* _rollOverCheckTimer; |
tedoyle | 0:1e0e79e82839 | 198 | uint32_t _rollOverCheckTimerPeriodInMsec; |
tedoyle | 3:8396d3e6eb62 | 199 | Semaphore* _sem; |
tedoyle | 3:8396d3e6eb62 | 200 | |
tedoyle | 0:1e0e79e82839 | 201 | static void _rollOverCheck(void const* args); |
tedoyle | 3:8396d3e6eb62 | 202 | static uint64_t _read_us(void const* args); |
tedoyle | 0:1e0e79e82839 | 203 | }; |
tedoyle | 0:1e0e79e82839 | 204 | |
tedoyle | 7:381bafbb2218 | 205 | #endif //__TIMER64__ |