Skip to content

Very incorrect timeout handling in pulseInLong #3830

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
igendel opened this issue Sep 20, 2015 · 7 comments · Fixed by #3864
Closed

Very incorrect timeout handling in pulseInLong #3830

igendel opened this issue Sep 20, 2015 · 7 comments · Fixed by #3864
Assignees
Labels
Component: Core Related to the code for the standard Arduino API Type: Bug
Milestone

Comments

@igendel
Copy link

igendel commented Sep 20, 2015

The three While loops in pulseInLong (at wiring_pulse.c) increase "numloops" from 0 to "maxloops" as a way to check and enforce the timeout parameter. However, "maxloops" is defined in clock cycles, but each loop run takes much more than a single clock cycle.

This results in timeouts that are actually over 20 times longer than the user requests.

Since this function uses micros() anyway for timing the pulse, I suggest replacing the numloops/maxloops method with checks against micros(). For instance:

// After function header and pin definitions...

unsigned long maxMicros = micros() + timeout;

// wait for any previous pulse to end
    while ((*portInputRegister(port) & bit) == stateMask)
        if (micros() > maxMicros)
            return 0;

// etc.

@facchinm
Copy link
Member

Woa! I totally missed it 😄 Fixed by c7b2743
Thank you for pointing out this bug!

@matthijskooijman
Copy link
Collaborator

The fix does not handle micros() overflow properly. If maxMicros = micros() + timeout overflows, then micros() > maxMicros will return true immediately.

Instead, try: startMicros = micros(); and if (micros() - startMicros > timeout), since then the overflow will happen correctly.

@igendel
Copy link
Author

igendel commented Sep 21, 2015

True, matthijskooijman. I suggested my solution off the top of my head... the possibility of overflow should be taken into account as well. Thanks!

facchinm added a commit to facchinm/Arduino that referenced this issue Sep 21, 2015
@facchinm
Copy link
Member

@matthijskooijman , you are totally correct.
While applying your patch (facchinm@480cd22), however, I encountered another issue.
Flash occupation increases by 72 bytes on AVR... Any cleaver idea on why this happens before starting a deeper analysis?

@facchinm facchinm added Component: Core Related to the code for the standard Arduino API Type: Bug labels Sep 21, 2015
@matthijskooijman
Copy link
Collaborator

Nothing springs to mind just now, but it does sound like something to investigate. If you want to investigate, have a look at this script I created to diff .elf file symbol tables (there is also a script to diff ASM output and reducing the amount of junk from differing addresses): https://github.com/matthijskooijman/scripts/blob/master/Arduino/diff-avr-sym

@cmaglie cmaglie added this to the Release 1.6.6 milestone Sep 22, 2015
@facchinm
Copy link
Member

After a loooooong (way longer than a pulse 😄 ) analysis it turned out that the three 32bit arguments involved in the subtraction lead the compiler to allocate these variables in the stack instead than using registers, thus the +72 byte.

Strangely, optimizing the function with -O1 the size increases by only 24 bytes.

No math guru over the web came out with a better implementation so I'm merging @matthijskooijman's one with a note about this strange behaviour

@matthijskooijman
Copy link
Collaborator

Ah, that makes sense - with my suggestion, the program needs to keep both track of startMicros and timeout, while the previous code didn't need timeout any more after the initial calculation of maxMicros, which needs more variables. Not sure why O1 doesn't have this problem, perhaps it does less reordering of the code or something. Oh well.

sandeepmistry pushed a commit to sandeepmistry/Arduino that referenced this issue Sep 29, 2015
ollie1400 pushed a commit to ollie1400/Arduino that referenced this issue May 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Core Related to the code for the standard Arduino API Type: Bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants