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

Files at this revision

API Documentation at this revision

Comitter:
andriym
Date:
Fri Jun 09 13:32:48 2017 +0000
Parent:
8:5d17ff4f9c23
Commit message:
Simplified version (removed semaphore and rollover check timer).

Changed in this revision

Timer64.cpp Show diff for this revision Revisions of this file
Timer64.h Show diff for this revision Revisions of this file
Timer64Simple.cpp Show annotated file Show diff for this revision Revisions of this file
Timer64Simple.h Show annotated file Show diff for this revision Revisions of this file
--- a/Timer64.cpp	Tue Apr 05 19:07:09 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,308 +0,0 @@
- /*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-#include "Timer64.h"
-#include "ticker_api.h"
-#include "us_ticker_api.h"
-
-Timer64::Timer64() :
-    _timerInitialized(false),
-    _timerRunning(false), 
-    _tickerStartTimeUsec(0u), 
-    _totalTimeUsec(0llu), 
-    _ticker_data(get_us_ticker_data()),
-    _rollOverCheckTimer(NULL),
-    _rollOverCheckTimerPeriodInMsec(TIMER64_DEFAULT_ROLLOVER_CHECK_IN_MSECS),
-    _sem(NULL)
-{
-    ;
-}
-
-Timer64::~Timer64()
-{
-    release();
-}
-
-int Timer64::init(uint32_t rolloverCheckTimeInMsec)
-{
-    if (_timerInitialized)
-    {
-        return(TIMER64_WARNING_ALREADY_INITIALIZED);
-    }
-    
-    if (rolloverCheckTimeInMsec < TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS)
-    {
-        rolloverCheckTimeInMsec = TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS;
-    }
-    else if (rolloverCheckTimeInMsec > TIMER64_MAX_ROLLOVER_CHECK_IN_MSECS)
-    {
-        rolloverCheckTimeInMsec = TIMER64_MAX_ROLLOVER_CHECK_IN_MSECS;
-    }
-
-    _timerRunning = false; 
-    _tickerStartTimeUsec = 0u; 
-    _totalTimeUsec = 0llu; 
-    _rollOverCheckTimerPeriodInMsec = rolloverCheckTimeInMsec;
-    _rollOverCheckTimer = new RtosTimer(_rollOverCheck, osTimerPeriodic, this);
-    _sem = new Semaphore(1);
-    _timerInitialized = true;
-    
-    return(TIMER64_OK);
-}
-
-int Timer64::release(void)
-{
-    if (!_timerInitialized)
-    {
-        return(TIMER64_WARNING_ALREADY_RELEASED);
-    }
-    
-    if (_timerRunning)
-    {
-        stop();
-    }
-    
-    _tickerStartTimeUsec = 0u; 
-    _totalTimeUsec = 0llu; 
-    _timerInitialized = false;
-    _rollOverCheckTimer->stop();
-    delete _rollOverCheckTimer;
-    _rollOverCheckTimer = NULL;
-    delete _sem;
-    _sem = NULL;
-    
-    return(TIMER64_OK);
-}
-
-int Timer64::start(void)
-{
-    int status = TIMER64_OK;
-
-    _sem->wait();
-    {
-        if (!_timerInitialized)
-        {
-            status = TIMER64_ERROR_NOT_INITIALIZED;
-        }
-        else if (_timerRunning)
-        {
-            status = TIMER64_WARNING_ALREADY_RUNNING;
-        }
-        else
-        {
-            _tickerStartTimeUsec = ticker_read(_ticker_data);
-            _timerRunning = true;
-            _rollOverCheckTimer->start(_rollOverCheckTimerPeriodInMsec);
-        }
-    }
-    _sem->release();
-    
-    return(status);
-}
-
-int Timer64::stop(void)
-{
-    int status = TIMER64_OK;
-
-    _sem->wait();
-    {
-        if (!_timerInitialized)
-        {
-            status = TIMER64_ERROR_NOT_INITIALIZED;
-        }
-        else if (!_timerRunning)
-        {
-            status = TIMER64_WARNING_ALREADY_STOPPED;
-        }
-        else
-        {
-            _read_us(this);
-            _timerRunning = false;
-            _rollOverCheckTimer->stop();
-        }
-    }
-    _sem->release();
-    
-    return(status);
-}
-
-int Timer64::reset(void)
-{
-    int status = TIMER64_OK;
-
-    _sem->wait();
-    {
-        if (!_timerInitialized)
-        {
-            status = TIMER64_ERROR_NOT_INITIALIZED;
-        }
-        else
-        {
-            if (_timerRunning)
-            {
-                _tickerStartTimeUsec = ticker_read(_ticker_data);
-                _rollOverCheckTimer->start(_rollOverCheckTimerPeriodInMsec);
-            }
-            
-            _totalTimeUsec = 0llu;
-        }
-    }
-    _sem->release();
-    
-    return(status);
-}
-
-int Timer64::read_us(uint64_t* timeInUsec)
-{
-    int status = TIMER64_OK;
-
-    _sem->wait();
-    {
-        if (!_timerInitialized)
-        {
-            status = TIMER64_ERROR_NOT_INITIALIZED;
-        }
-        else if (timeInUsec == NULL)
-        {
-            status = TIMER64_ERROR_NULL_POINTER;
-        }
-        else
-        {
-            if (_timerRunning)
-            {
-                *timeInUsec = _read_us(this);
-            }
-            else
-            {
-                *timeInUsec = _totalTimeUsec;
-            }
-        }
-    }
-    _sem->release();
-    
-    return(status);
-}
-
-int Timer64::read_ms(uint64_t* timeInMsec)
-{
-    int status = TIMER64_OK;
-
-    _sem->wait();
-    {
-        if (!_timerInitialized)
-        {
-            status = TIMER64_ERROR_NOT_INITIALIZED;
-        }
-        else if (timeInMsec == NULL)
-        {
-            status = TIMER64_ERROR_NULL_POINTER;
-        }
-        else
-        {
-            if (_timerRunning)
-            {
-                *timeInMsec = _read_us(this)/1000LU;
-            }
-            else
-            {
-                *timeInMsec = _totalTimeUsec/1000LU;
-            }
-        }
-    }
-    _sem->release();
-    
-    return(status);
-}
-
-int Timer64::read(double* timeInSec)
-{
-    int status = TIMER64_OK;
-
-    _sem->wait();
-    {
-        if (!_timerInitialized)
-        {
-            status = TIMER64_ERROR_NOT_INITIALIZED;
-        }
-        else if (timeInSec == NULL)
-        {
-            status = TIMER64_ERROR_NULL_POINTER;
-        }
-        else
-        {
-            if (_timerRunning)
-            {
-                *timeInSec = (double)_read_us(this)/1000000.0L;
-            }
-            else
-            {
-                *timeInSec = (double)_totalTimeUsec/1000000.0L;
-            }
-        }
-    }
-    _sem->release();
-    
-    return(status);
-}
-
-int Timer64::isRunning(bool* running)
-{
-    int status = TIMER64_OK;
-
-    _sem->wait();
-    {
-        if (!_timerInitialized)
-        {
-            status = TIMER64_ERROR_NOT_INITIALIZED;
-        }
-        else
-        {
-            *running = _timerRunning;
-        }
-    }
-    _sem->release();
-    
-    return(status);
-}
-
-void Timer64::_rollOverCheck(void const* args)
-{
-    Timer64* timer = (Timer64*)args;
-    timer->_read_us(timer);
-    return;
-}
-
-uint64_t Timer64::_read_us(void const* args)
-{
-    Timer64* timer = (Timer64*)args;
-    timestamp_t ticker_current_timeUsec = ticker_read(timer->_ticker_data);
-    
-    // check for ticker time rollover
-    
-    if (ticker_current_timeUsec >= timer->_tickerStartTimeUsec)
-    {
-        timer->_totalTimeUsec += (uint64_t)(ticker_current_timeUsec - timer->_tickerStartTimeUsec);
-    }
-    else
-    {
-        // rollover!
-        timer->_totalTimeUsec += (uint64_t)(4294967296U - timer->_tickerStartTimeUsec) + (uint64_t)ticker_current_timeUsec;
-        
-    }
-    
-    timer->_rollOverCheckTimer->start(timer->_rollOverCheckTimerPeriodInMsec);
-    timer->_tickerStartTimeUsec = ticker_current_timeUsec;
-    return(timer->_totalTimeUsec);
-}
-
--- a/Timer64.h	Tue Apr 05 19:07:09 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,205 +0,0 @@
-/* mbed Microcontroller Library
- * Copyright (c) 2006-2016 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Modified by Tom Doyle    <ThomasEDoyle@gmail.com>
- *
- */
- 
-#ifndef __TIMER64__
-#define __TIMER64__
-
-#include "platform.h"
-#include "ticker_api.h"
-#include <stdint.h>
-#include "rtos.h"
-
-#define TIMER64_OK                                  0
-
-#define TIMER64_ERROR_NOT_INITIALIZED               -1
-#define TIMER64_ERROR_NULL_POINTER                  -2
-
-#define TIMER64_WARNING_ALREADY_INITIALIZED         1
-#define TIMER64_WARNING_ALREADY_RUNNING             2
-#define TIMER64_WARNING_ALREADY_STOPPED             3
-#define TIMER64_WARNING_ALREADY_RELEASED            4
-
-#define TIMER64_DEFAULT_ROLLOVER_CHECK_IN_MSECS     30000
-#define TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS         1000
-#define TIMER64_MAX_ROLLOVER_CHECK_IN_MSECS         65535
-
-/** Timer64 class
- *  Used to define a 64 bit timer64 that is thread safe.  The Timer64 behaves in a 
- *  similiar fashion to the mbed Timer class with the most notable exception that 
- *  the Timer64 will not rollover after 2^31 microseconds (approximately 35.8 minutes).
- *  The Timer64 extends the rollover time to 2^64 microseconds (approximately 585,000 years!)
- *
- *  The Timer64 class is also designed to be thread safe. The following functions can be 
- *  called from any thread after the class is instaniated and initialized:
- *  
- *  - start()
- *  - stop()
- *  - reset()
- *  - read_us()
- *  - read_ms()
- *  - read()
- *  - reset()
- *  - isRunning()
- *
- *  It is to be noted that the init() and release() methods need to be called from the same thread.
- *
- *  Give the Timer64 library a try and let me know if it works for you. Will gladly take suggestions
- *  on how to make it better.
- *
- *  Simple Example
- *  @code
- *  #include "mbed.h"
- *  #include "rtos.h"
- *  #include "Timer64.h"
- *
- * Timer64 timer64;
- *
- *   int main()
- *   {
- *      uint64_t timeInUsec;
- *      timer64.init();
- *      timer64.start();
- *      Thread::wait(100);
- *      timer64.stop();
- *      timer64.read_us(&timeInUsec);
- *      printf("Test - Elapsed time = %llu usec\n\n", timeInUsec);
- *      timer64.reset();
- *      timer64.release();
- *       
- *      while (1)
- *      {
- *          Thread::wait(1000);
- *      }
- *  }
- *  @endcode
-*/
-
-class Timer64
-{
-
-public:
-    Timer64();
-    ~Timer64();
-
-    /** Initialize the timer - this must be called before the timer can be used
-     *  
-     *  @param rolloverCheckTimeInMsecc specifies how ofter a rollover check is performed.
-     *      This parameter is bounded by TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS and 
-     *      TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS with a default value of
-     *      TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS
-     *
-     *  @returns
-     *      TIMER64_OK,
-     *      TIMER64_WARNING_ALREADY_INITIALIZED
-     */
-    int init(uint32_t rolloverCheckTimeInMsecc = TIMER64_DEFAULT_ROLLOVER_CHECK_IN_MSECS);
-
-    /** Release the timer - must be called from the same thread calling init()
-     *  
-     *  @returns
-     *      TIMER64_OK,
-     *      TIMER64_WARNING_ALREADY_RELEASED
-     */
-    int release(void);
-
-    /** Start the timer - this method is thread safe
-     *  
-     *  @returns
-     *      TIMER64_OK,
-     *      TIMER64_ERROR_NOT_INITIALIZED,
-     *      TIMER64_WARNING_ALREADY_RUNNING
-     */
-    int start(void);
-
-    /** Stop the timer - this method is thread safe
-     *  
-     *  @returns
-     *      TIMER64_OK,
-     *      TIMER64_ERROR_NOT_INITIALIZED,
-     *      TIMER64_WARNING_ALREADY_STOPPED
-     */
-    int stop(void);
-
-    /** Reset the timer - this method is thread safe
-     *  
-     *  @returns
-     *      TIMER64_OK,
-     *      TIMER64_ERROR_NOT_INITIALIZED
-     */
-    int reset(void);
-
-    /** Read the timer value in microseconds - this method is thread safe
-     *  
-     *  @param timeInUsec specifies a pointer to a uint64_t where to save the current time in microseconds
-     *
-     *  @returns
-     *      TIMER64_OK,
-     *      TIMER64_ERROR_NOT_INITIALIZED,
-     *      TIMER64_ERROR_NULL_POINTER
-     */
-    int read_us(uint64_t* timeInUsec = NULL);
-
-    /** Read the timer value in milliseconds - this method is thread safe
-     *  
-     *  @param timeInMsec specifies a pointer to a uint64_t where to save the current time in milliseconds
-     *
-     *  @returns
-     *      TIMER64_OK,
-     *      TIMER64_ERROR_NOT_INITIALIZED,
-     *      TIMER64_ERROR_NULL_POINTER
-     */
-    int read_ms(uint64_t* timeInMsec = NULL);
-
-    /** Read the timer value in seconds - this method is thread safe
-     *  
-     *  @param timeInMsec specifies a pointer to a double where to save the current time in seconds
-     *
-     *  @returns
-     *      TIMER64_OK,
-     *      TIMER64_ERROR_NOT_INITIALIZED,
-     *      TIMER64_ERROR_NULL_POINTER,
-     */
-    int read(double* timeInSec = NULL);
-    
-    /** Check to see if timer is running - this method is thread safe
-     *  
-     *  @param running specifies a pointer to a bool where to save the running status
-     *
-     *  @returns
-     *      TIMER64_OK,
-     *      TIMER64_ERROR_NOT_INITIALIZED,
-     *      TIMER64_ERROR_NULL_POINTER
-     */
-    int isRunning(bool* running);
-
-private:
-    bool _timerInitialized;
-    bool _timerRunning;                 // whether the timer is running
-    timestamp_t _tickerStartTimeUsec;   // the start time of the latest slice
-    uint64_t _totalTimeUsec;            // any accumulated time from previous slices
-    const ticker_data_t *_ticker_data;
-    RtosTimer* _rollOverCheckTimer;
-    uint32_t _rollOverCheckTimerPeriodInMsec;
-    Semaphore* _sem;
-    
-    static void _rollOverCheck(void const* args);
-    static uint64_t _read_us(void const* args);
-};
-
-#endif  //__TIMER64__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Timer64Simple.cpp	Fri Jun 09 13:32:48 2017 +0000
@@ -0,0 +1,112 @@
+ /*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#include "Timer64Simple.h"
+#include "ticker_api.h"
+#include "us_ticker_api.h"
+
+Timer64Simple::Timer64Simple() :
+    _timerRunning(false),
+    _tickerLastTimeUsec(0u), 
+    _totalTimeUsec(TIMER64_TOTAL_TIME_INIT), 
+    _ticker_data(get_us_ticker_data())
+{
+    ;
+}
+
+Timer64Simple::~Timer64Simple()
+{
+    ;
+}
+
+void Timer64Simple::start(void)
+{
+    if (!_timerRunning)
+    {
+        _tickerLastTimeUsec = ticker_read(_ticker_data);
+        _timerRunning = true;
+    }
+}
+
+void Timer64Simple::stop(void)
+{
+    if (_timerRunning)
+    {
+        _read_us();
+        _timerRunning = false;
+    }
+}
+
+void Timer64Simple::reset(void)
+{
+    if (_timerRunning)
+    {
+        _tickerLastTimeUsec = ticker_read(_ticker_data);
+    }
+    
+    _totalTimeUsec = TIMER64_TOTAL_TIME_INIT;
+}
+
+uint64_t Timer64Simple::read_us()
+{
+    if (_timerRunning)
+    {
+        return _read_us();
+    }
+    return _totalTimeUsec;
+}
+
+uint64_t Timer64Simple::read_ms()
+{
+    if (_timerRunning)
+    {
+        return _read_us()/1000LU;
+    }
+    return _totalTimeUsec/1000LU;
+}
+
+double Timer64Simple::read()
+{
+    if (_timerRunning)
+    {
+        return (double)_read_us()/1000000.0L;
+    }
+    return (double)_totalTimeUsec/1000000.0L;
+}
+
+bool Timer64Simple::is_running()
+{
+    return(_timerRunning);
+}
+
+uint64_t Timer64Simple::_read_us()
+{
+    timestamp_t tickerCurrentTimeUsec = ticker_read(_ticker_data);
+    
+    // check for ticker time rollover
+    
+    if (tickerCurrentTimeUsec >= _tickerLastTimeUsec)
+    {
+        _totalTimeUsec += (uint64_t)(tickerCurrentTimeUsec - _tickerLastTimeUsec);
+    }
+    else
+    {
+        // rollover!
+        _totalTimeUsec += (uint64_t)(4294967296U - _tickerLastTimeUsec) + (uint64_t)tickerCurrentTimeUsec;
+        
+    }
+    
+    _tickerLastTimeUsec = tickerCurrentTimeUsec;
+    return(_totalTimeUsec);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Timer64Simple.h	Fri Jun 09 13:32:48 2017 +0000
@@ -0,0 +1,129 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2016 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Modified by Tom Doyle, 2016
+ *             <ThomasEDoyle@gmail.com>
+ *
+ * Modified by Andriy Makukha, 2017
+ *             <andriy@mzjtechnology.com>
+ *             Shenzhen MZJ Technology, Co.
+ */
+ 
+#ifndef __TIMER64SIMPLE__
+#define __TIMER64SIMPLE__
+
+#include "platform.h"
+#include "ticker_api.h"
+#include <stdint.h>
+
+#define TIMER64_TOTAL_TIME_INIT                     0llu
+
+/** Timer64Simple class
+ *  Used to define a 64 bit timer that is NOT thread safe.  The Timer64Simple
+ *  behaves in a similiar fashion to the mbed Timer class with the most notable
+ *  exception that the Timer64Simple will not rollover after 2^31 microseconds
+ *  (approximately 35.8 minutes). The Timer64Simple extends the rollover time
+ *  to 2^64 microseconds (more than 584,000 years!)
+ *
+ *  Unlike the Timer64 class by Tom Doyle, Timer64Simple class is simplified to
+ *  be NOT thread safe. It is also assumed that read(), read_ms() or read_us()
+ *  functions are called at least once per 17 minutes (preferably faster!) 
+ *  while the timer is running (since this class lacks internal rollover check 
+ *  timer). In fact, Timer64Simple is simplifed to the point where it's almost 
+ *  trivial.
+ *
+ *  If you need smarter version, check out the original code here:
+ *      https://developer.mbed.org/users/tedoyle/code/Timer64/
+ *
+ *  Demo program:
+ *  @code
+ *  #include "mbed.h"
+ *  #include "Timer64Simple.h"
+ *
+ *  Timer64Simple timer64;
+ *
+ *  int main()
+ *  {
+ *      timer64.start();
+ *      wait_ms(100);
+ *      timer64.stop();
+ *      wait_ms(100);
+ *      printf("Test - Elapsed time = %llu usec\r\n", timer64.read_us());   // %llu -- unsigned long long int
+ *       
+ *      timer64.reset();
+ *      timer64.start();
+ *      while (1)
+ *      {
+ *          wait(60);           // wait 1 minute
+ *          printf("Time = %llu ms\r\n", timer64.read_ms());
+ *      }
+ *  }
+ *  @endcode
+*/
+
+class Timer64Simple
+{
+
+public:
+    Timer64Simple();
+    ~Timer64Simple();
+
+    /** Start the timer */
+    void start(void);
+
+    /** Stop the timer  */
+    void stop(void);
+
+    /** Reset the timer */
+    void reset(void);
+
+    /** Read the timer value in microseconds 
+     *  
+     *  @returns
+     *      timeInUsec - current time in microseconds
+     */
+    uint64_t read_us(void);
+
+    /** Read the timer value in milliseconds
+     *  
+     *  @returns
+     *      timeInMsec - current time in milliseconds
+     */
+    uint64_t read_ms(void);
+
+    /** Read the timer value in seconds
+     *  
+     *  @returns
+     *      timeInMsec - current time in seconds
+     */
+    double read(void);
+    
+    /** Check to see if timer is running
+     *  
+     *  @returns
+     *      boolean running status
+     */
+    bool is_running();
+
+private:
+    bool _timerRunning;                 // whether the timer is running
+    timestamp_t _tickerLastTimeUsec;    // the start time of the latest slice
+    uint64_t _totalTimeUsec;            // any accumulated time from previous slices
+    const ticker_data_t *_ticker_data;
+    
+    uint64_t _read_us(void);
+};
+
+#endif  //__TIMER64SIMPLE__