<p>I have a counter in hardware that I can observe for timing considerations. It counts miliseconds and is stored in a 16 bit unsigned value. How do I safely check if a timer value has passed a certain time and safely handle the inevitable rollover:</p>

<pre><code>//this is a bit contrived, but it illustrates what I'm trying to do
const uint16_t print_interval = 5000; // milliseconds
static uint16_t last_print_time;   

if(ms_timer() - last_print_time &gt; print_interval)
{
    printf("Fault!\n");
    last_print_time = ms_timer();
}
</code></pre>

<p>This code will fail when ms_timer overflows to 0.</p>

[{'answer_id': 61444, 'author': 'Jason Punyon', 'author_id': 6212, 'author_profile': 'https://Stackoverflow.com/users/6212', 'pm_score': 1, 'selected': False, 'text': '<p>Just check if ms_timer &lt; last_print_time and if so add 2^16 no?</p>\n\n<p>Edit:  You also need to up to an uint32 for this if you can.</p>\n'}, {'answer_id': 61461, 'author': 'ReaperUnreal', 'author_id': 4218, 'author_profile': 'https://Stackoverflow.com/users/4218', 'pm_score': 1, 'selected': False, 'text': '<p>Probably the safest way to avoid the problem would be to use a signed 32-bit value. To use your example:</p>\n\n<pre><code>const int32 print_interval = 5000;\nstatic int32 last_print_time; // I\'m assuming this gets initialized elsewhere\n\nint32 delta = ((int32)ms_timer()) - last_print_time; //allow a negative interval\nwhile(delta &lt; 0) delta += 65536; // move the difference back into range\nif(delta &lt; print_interval)\n{\n    printf("Fault!\\n");\n    last_print_time = ms_timer();\n}\n</code></pre>\n'}, {'answer_id': 61466, 'author': 'JeffV', 'author_id': 445087, 'author_profile': 'https://Stackoverflow.com/users/445087', 'pm_score': 1, 'selected': False, 'text': '<p>This seems to work for intervals up to 64k/2, which is suitable for me:</p>\n\n<pre><code>const uint16_t print_interval = 5000; // milliseconds\nstatic uint16_t last_print_time;   \n\nint next_print_time = (last_print_time + print_interval);\n\nif((int16_t) (x - next_print_time) &gt;= 0)\n{\n    printf("Fault!\\n");\n    last_print_time = x;\n}\n</code></pre>\n\n<p>Makes use of nature of signed integers. (<a href="http://en.wikipedia.org/wiki/Twos_complement" rel="nofollow noreferrer">twos complement</a>)</p>\n'}, {'answer_id': 61572, 'author': 'smh', 'author_id': 1077, 'author_profile': 'https://Stackoverflow.com/users/1077', 'pm_score': 4, 'selected': False, 'text': "<p>You don't actually need to do anything here. The original code listed in your question will work fine, assuming <code>ms_timer()</code> returns a value of type uint16_t.</p>\n\n<p>(Also assuming that the timer doesn't overflow twice between checks...) </p>\n\n<p>To convince yourself this is the case, try the following test:</p>\n\n<pre><code>uint16_t t1 = 0xFFF0;\nuint16_t t2 = 0x0010;\nuint16_t dt = t2 - t1;\n</code></pre>\n\n<p><code>dt</code> will equal <code>0x20</code>.</p>\n"}, {'answer_id': 164182, 'author': 'Steve Karg', 'author_id': 9016, 'author_profile': 'https://Stackoverflow.com/users/9016', 'pm_score': 0, 'selected': False, 'text': '<p>I found that using a different timer API works better for me. I created a timer module that has two API calls:</p>\n\n<pre><code>void timer_milliseconds_reset(unsigned index);\nbool timer_milliseconds_elapsed(unsigned index, unsigned long value);\n</code></pre>\n\n<p>The timer indices are also defined in the timer header file:</p>\n\n<pre><code>#define TIMER_PRINT 0\n#define TIMER_LED 1\n#define MAX_MILLISECOND_TIMERS 2\n</code></pre>\n\n<p>I use unsigned long int for my timer counters (32-bit) since that is the native sized integer on my hardware platform, and that gives me elapsed times from 1 ms to about 49.7 days.  You could have timer counters that are 16-bit which would give you elapsed times from 1 ms to about 65 seconds.</p>\n\n<p>The timer counters are an array, and are incremented by the hardware timer (interrupt, task, or polling of counter value).  They can be limited to the maximum value of the datatype in the function that handles the increment for a no-rollover timer.</p>\n\n<pre><code>/* variable counts interrupts */\nstatic volatile unsigned long Millisecond_Counter[MAX_MILLISECOND_TIMERS];\nbool timer_milliseconds_elapsed(\n    unsigned index,\n    unsigned long value)\n{\n    if (index &lt; MAX_MILLISECOND_TIMERS) {\n        return (Millisecond_Counter[index] &gt;= value);\n    }\n    return false;\n}\n\nvoid timer_milliseconds_reset(\n    unsigned index)\n{\n    if (index &lt; MAX_MILLISECOND_TIMERS) {\n        Millisecond_Counter[index] = 0;\n    }\n}\n</code></pre>\n\n<p>Then your code becomes:</p>\n\n<pre><code>//this is a bit contrived, but it illustrates what I\'m trying to do\nconst uint16_t print_interval = 5000; // milliseconds\n\nif (timer_milliseconds_elapsed(TIMER_PRINT, print_interval)) \n{\n    printf("Fault!\\n");\n    timer_milliseconds_reset(TIMER_PRINT);\n}\n</code></pre>\n'}, {'answer_id': 2976575, 'author': 'bobc', 'author_id': 358705, 'author_profile': 'https://Stackoverflow.com/users/358705', 'pm_score': 2, 'selected': False, 'text': '<p>I use this code to illustrate the bug and possible solution using a signed comparison.</p>\n\n<pre><code>/* ========================================================================== */\n/*   timers.c                                                                 */\n/*                                                                            */\n/*   Description: Demonstrate unsigned vs signed timers                       */\n/* ========================================================================== */\n\n#include &lt;stdio.h&gt;\n#include &lt;limits.h&gt;\n\nint timer;\n\nint HW_DIGCTL_MICROSECONDS_RD()\n{\n  printf ("timer %x\\n", timer);\n  return timer++;\n}\n\n// delay up to UINT_MAX\n// this fails when start near UINT_MAX\nvoid delay_us (unsigned int us)\n{\n    unsigned int start = HW_DIGCTL_MICROSECONDS_RD();\n\n    while (start + us &gt; HW_DIGCTL_MICROSECONDS_RD()) \n      ;\n}\n\n// works correctly for delay from 0 to INT_MAX\nvoid sdelay_us (int us)\n{\n    int start = HW_DIGCTL_MICROSECONDS_RD();\n\n    while (HW_DIGCTL_MICROSECONDS_RD() - start &lt; us) \n      ;\n}\n\nint main()\n{\n  printf ("UINT_MAX = %x\\n", UINT_MAX);\n  printf ("INT_MAX  = %x\\n\\n", INT_MAX);\n\n  printf ("unsigned, no wrap\\n\\n");\n  timer = 0;\n  delay_us (10);\n\n  printf ("\\nunsigned, wrap\\n\\n");\n  timer = UINT_MAX - 8;\n  delay_us (10);\n\n  printf ("\\nsigned, no wrap\\n\\n");\n  timer = 0;\n  sdelay_us (10);\n\n  printf ("\\nsigned, wrap\\n\\n");\n  timer = INT_MAX - 8;\n  sdelay_us (10);\n\n}\n</code></pre>\n\n<p>Sample output:</p>\n\n<pre><code>bob@hedgehog:~/work2/test$ ./timers|more\nUINT_MAX = ffffffff\nINT_MAX  = 7fffffff\n\nunsigned, no wrap\n\ntimer 0\ntimer 1\ntimer 2\ntimer 3\ntimer 4\ntimer 5\ntimer 6\ntimer 7\ntimer 8\ntimer 9\ntimer a\n\nunsigned, wrap\n\ntimer fffffff7\ntimer fffffff8\n\nsigned, no wrap\n\ntimer 0\ntimer 1\ntimer 2\ntimer 3\ntimer 4\ntimer 5\ntimer 6\ntimer 7\ntimer 8\ntimer 9\ntimer a\n\nsigned, wrap\n\ntimer 7ffffff7\ntimer 7ffffff8\ntimer 7ffffff9\ntimer 7ffffffa\ntimer 7ffffffb\ntimer 7ffffffc\ntimer 7ffffffd\ntimer 7ffffffe\ntimer 7fffffff\ntimer 80000000\ntimer 80000001\nbob@hedgehog:~/work2/test$ \n</code></pre>\n'}, {'answer_id': 11911902, 'author': 'Jeff', 'author_id': 877375, 'author_profile': 'https://Stackoverflow.com/users/877375', 'pm_score': -1, 'selected': False, 'text': '<p>Sometimes I do it like this:</p>\n\n<pre><code>#define LIMIT 10   // Any value less then ULONG_MAX\nulong t1 = tick of last event;\nulong t2 = current tick;\n\n// This code needs to execute every tick\nif ( t1 &gt; t2 ){\n    if ((ULONG_MAX-t1+t2+1)&gt;=LIMIT){\n       do something\n    }\n} else {\nif ( t2 - t1 &gt;= LIMT ){\n    do something\n}\n</code></pre>\n'}, {'answer_id': 45852411, 'author': 'Hill', 'author_id': 3239341, 'author_profile': 'https://Stackoverflow.com/users/3239341', 'pm_score': 2, 'selected': False, 'text': '<p>I used to write code like following for the such case.<br>\nI tested with test case and assure that it works 100%.<br>\nIn addition, change to <code>uint32_t</code> from <code>uint16_t</code> and <code>0xFFFFFFFF</code> from <code>0xFFFF</code> in below code with 32 bits timer tick.</p>\n\n\n\n<pre><code>uint16_t get_diff_tick(uint16_t test_tick, uint16_t prev_tick)\n{\n    if (test_tick &lt; prev_tick)\n    {\n        // time rollover(overflow)\n        return (0xFFFF - prev_tick) + 1 + test_tick;\n    }\n    else\n    {\n        return test_tick - prev_tick;\n    }\n}\n\n/* your code will be.. */\nuint16_t cur_tick = ms_timer();\nif(get_diff_tick(cur_tick, last_print_time) &gt; print_interval)\n{\n    printf("Fault!\\n");\n    last_print_time = cur_tick;\n}\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/61443', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/445087/']