Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
159 views
in Technique[技术] by (71.8m points)

c - Protecting against overflow in a delay function

I have in a project of mine a small delay function that I have written myself by making use of a timer peripheral of my MCU:

static void delay100Us(void)

{
  uint_64 ctr = TIMER_read(0); //10ns resolution
  uint_64 ctr2 = ctr + 10000;
  while(ctr <= ctr2) //wait 100 microseconds(10000)
  {
      ctr = TIMER_read(0);
  }
}

The counter is a freerunning hw counter with 10ns resolution so I wrote that function as to give approximately 100us delay. I think this should work in principle however there could be the situation where the timer is less than 10000 from overflowing and so ctr2 will get assigned a value which is more than ctr can actually reach and therefore I would end up getting stuck into an infinite loop.

I need to generate a delay using this timer in my project so I need to somehow make sure that I always get the same delay(100us) while at the same time protect myself from getting stuck there.

Is there any way I can do this or is this just a limitation that I can't get passed?

Thank you!

Edit:

ctr_start = TimerRead(); //get initial value for the counter
interval = TimerRead() - ctr_start;
while(interval <= 10000)
{
  interval = ( TimerRead() - ctr_start  + countersize ) % countersize;
}

Where countersize = 0xFFFFFFFFFFFFFFFF;
question from:https://stackoverflow.com/questions/65942665/protecting-against-overflow-in-a-delay-function

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

It can be dangerous to wait for a specific timer value in case an interrupt happens at just that moment and you miss the required count. So it is better to wait until the counter has reached at least the target value. But as noticed, comparing the timer with a target value creates a problem when the target is lower than the initial value.

One way to avoid this problem is to consider the interval that has elapsed with unsigned variables and arithmetic. Their behaviour is well defined when values wrap.

A hardware counter is almost invariably of size 8, 16, 32 or 64 bits, so choose a variable type to suit. Suppose the counter is 32-bit:

void delay(uint32_t period)
{
    uint32_t mark = TIMER_read(0);
    uint32_t interval;
    do {
        interval = TIMER_read(0) - mark;    // underflow is well defined
    } while(interval < period);
}

Obviously, the required period must be less than the counter's period. If not, either scale the timer's clock, or use another method (such as a counter maintained by interrupt).

Sometimes a one-shot timer is used to count down the required period, but using a free-run counter is easy, and using a one-shot timer means it can't be used by another process at the same time.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...