Skip to content
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

wrong inline asm constraint in delayMicroseconds #12

Open
nerdralph opened this issue Jan 3, 2023 · 2 comments
Open

wrong inline asm constraint in delayMicroseconds #12

nerdralph opened this issue Jan 3, 2023 · 2 comments
Labels
bug Something isn't working

Comments

@nerdralph
Copy link
Owner

Bug first discovered in MicroCore, which uses the same code.
MCUdude/MicroCore#136

@nerdralph nerdralph added the bug Something isn't working label Jan 3, 2023
@nerdralph nerdralph changed the title fix inline asm constraint in delayMicroseconds wrong inline asm constraint in delayMicroseconds Jan 3, 2023
nerdralph added a commit that referenced this issue Jan 3, 2023
@MCUdude
Copy link

MCUdude commented Jan 4, 2023

What's the reason for the slightly different delayMicroseconds implementation in ArduinoShrink and picoCore?

ArduinoShrink:

void delayMicroseconds(uint16_t us)
{
// if us is a compile-time constant result is accurate to 1 cycle
if (__builtin_constant_p(us)) {
_delay_us(us);
return;
}
// code below runs when us is not known at compile time
// uses inline asm to guarantee exact cycle counts
const float fMHz = (F_CPU/1000000.0);
delay1us:
// delay 1us per loop, less 4 cycles for overhead
_delay_us(1.0 - (4.0 / fMHz));
asm volatile ("sbiw %[us], 1" : [us]"+w"(us));
asm goto( "brne %l[delay1us]" :::: delay1us);
}

picoCore:

__attribute((always_inline))
static inline void delayMicroseconds(uint16_t us)
{
    // if us is a compile-time constant result is accurate to 1 cycle
    if (__builtin_constant_p(us)) {
        _delay_us(us);
        return;
    }

    // when us is not known at compile time, delay is accurate to +/- 2us
    // plus an overhead of 3 CPU cycles
    const float fMHz = (F_CPU/1000000.0);
    // subtract two for rounding before dividing by 4
    us -= 2;
    delay4us:
        // delay 4us per loop, less 4 cycles for overhead
        _delay_us(4.0 - (4.0 / fMHz));
        asm volatile ("sbiw %[us], 4" : [us]"+d"(us));
    asm goto( "brpl %l[delay4us]" :::: delay4us);
}

@nerdralph
Copy link
Owner Author

nerdralph commented Jan 4, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants