arduino-libraries / SD

SD Library for Arduino

Home Page:http://arduino.cc/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Incorrect use of millis() for timeout function

SodaqMoja opened this issue · comments

commented

In Sd2Card.cpp there are a few places where a timeout function is implemented. However, in each of these places the value returend by millis() is truncated to 16 bits. That can't be correct.

commented

It's hard to actually show the effect of this flaw, but I assume that every now and then the timeout takes way too long. I'm guessing the timeout in that case will be 64 seconds instead of the intended 300, 2000.

It's hard to actually show the effect of this flaw, but I assume that every now and then the timeout takes way too long. I'm guessing the timeout in that case will be 64 seconds instead of the intended 300, 2000.

When you compute the time difference, the unsigned subtraction is not affected by a rollover:

uint16_t t0 = (uint16_t)millis();		
...
if (((uint16_t)(millis() - t0)) > SD_INIT_TIMEOUT) {

you can easily verify that even if a rollover happens in the delta is always correct, for instance:

millis() - t0 == 0x00000010 - 0xFFFFFFFE == 0x00000012

but since the upper bits are discarded anyway, you can safely ignore them if you don't need them and avoid the overhead of 32 bit operations on AVR.

commented

There are four occurrences where millis() is truncated. Two of them is missing an essential set of parenthesis, in waitNotBusy and waitStartBlock.

Here is a test sketch that shows what can happen with waitNotBusy.

#include "Arduino.h"
#define MYSERIAL Serial
void waitNotBusy(uint16_t timeoutMillis)
{
    uint16_t t0 = millis();

    do {
        // Do nothing to make sure there is a timeout
    } while (((uint16_t)millis() - t0) < timeoutMillis);
}
void setup()
{
    MYSERIAL.begin(115200);
    delay(1000);
}
void loop()
{
    waitNotBusy(2000);
    MYSERIAL.println(millis());
}

It prints

3001
5001
...
63001
65001

And then hangs.

Two of them is missing an essential set of parenthesis, in waitNotBusy and waitStartBlock.

I see, it seems that you have a point here, thanks for digging it out!

I'm preparing a patch to fix this in a minute.