Is the delayMicroseconds() function affected by the micros() function overflow?

Hi,

I found this issue, and I noticed that in this code the delayMicroseconds() function uses micros(). On an arduino UNO (ATmega328), can the delayMicroseconds() function suffer any effect every 70 minutes?

void ARDUINO_ISR_ATTR delayMicroseconds(uint32_t us)
{
    uint32_t m = micros();
    uint64_t m = (uint64_t)esp_timer_get_time();
    if(us){
        uint32_t e = (m + us);
        uint64_t e = (m + us);
        if(m > e){ //overflow
            while(micros() > e){
            while((uint64_t)esp_timer_get_time() > e){
                NOP();
            }
        }
        while(micros() < e){
        while((uint64_t)esp_timer_get_time() < e){
            NOP();
        }
    }

Ref.: Exact overflow value for micros() function? - #4 by system

The overflow ‘problem’ is simply that an unsigned long (32 bit integer) can’t hold any more than ~4.2 billion ticks
(11111111 11111111 11111111 11111111)…
When that number overflows, the count ‘rolls over’ to begin from zero again…
(00000000 00000000 00000000 00000000)

Both millis() and micros() suffer the same issue when the counter overflows, as would any other numerical counter with any data type.

What is the size of the micros() counter on ESP?

Where did you get this?

void ARDUINO_ISR_ATTR delayMicroseconds(uint32_t us)
{
    uint32_t m = micros();
    uint64_t m = (uint64_t)esp_timer_get_time();
    if(us){
        uint32_t e = (m + us);
        uint64_t e = (m + us);
        if(m > e){ //overflow
            while(micros() > e){
            while((uint64_t)esp_timer_get_time() > e){
                NOP();
            }
        }
        while(micros() < e){
        while((uint64_t)esp_timer_get_time() < e){
            NOP();
        }
    }

Which m and which e are those supposed to be? Or the others?

        if(m > e){ //overflow

Different variables with the same name is just daft asking for problems!

Rollover is only a problem for those who don't understand unsigned subtraction.

Yes, the explanation about the overflow is understandable.

The question is about the delayMicroseconds() function. I don't want to be susceptible to a time variation every 70 minutes, so I made an improvised timer using while() instead of using delayMicroseconds().

On the STM8S it looked like this:

        u32 u32_pulse = 418;

        u32_pulse += (uint16_t)((pulse_width - 1) * 535);

        //delayMicroseconds(u16_pulse);
        while(u32_pulse--);

Interesting that before I was using a 16-bit variable with the delayMicroseconds() function, and the maximum time I was needing was 50ms, so the value of the 16-bit variable was getting close to 50000.

But using a 16-bit variable and while() every millisecond needed more than 2000 counts so overflow would occur (50x2000=100000), but when using a 32 bit variable, the value of every millisecond dropped to about 500 counts.

In the future, whoever reads this code without knowing the differences in processing time of the variables in relation to the length of the variable, may think that it was unnecessary to use a 32-bit variable to operate with a count with a maximum value of only 25000.

Sorry, I haven't researched this, but I believe the default is 32-bit in the Arduino IDE, regardless of platform/board (STM32, ESP, DUE, UNO etc).

It is referenced in the "Bug in delayMicroseconds()" issue link cited above:

me-no-dev closed this as completed in 8645971 on Apr 5, 2021

With AVR processors largest delayMicroseconds() is 16383, don't know about ESPs:
https://www.arduino.cc/reference/en/language/functions/time/delaymicroseconds/

I had seen this information, but I tried it with 50ms and apparently had no problem. I don't know if the current code is capable of operating with the full 32 bits, and only the documentation is out of date. But there is a caveat in the documentation:

This could change in future Arduino releases

As there is no publication date in the documentation, it is difficult to know.

Hope I found the right place to address this:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.