Skip to content

millis() in the example for Arduino Uno resets after 65535 #164

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
ThisIsRex opened this issue Mar 17, 2021 · 6 comments
Closed

millis() in the example for Arduino Uno resets after 65535 #164

ThisIsRex opened this issue Mar 17, 2021 · 6 comments
Labels
compiler-bug Not a bug in avr-hal, but a bug in the rust compiler/LLVM

Comments

@ThisIsRex
Copy link

I tried an example "millis" on Arduino Nano and found out that milliseconds value resets after reaching 65535. But it has a u32 return type. I tried to modify the prescaler value and timer counts, but it's no use. How to make it use all the bits of u32?

@Rahix
Copy link
Owner

Rahix commented Mar 18, 2021

Hey!

I am not entirely certain but this sounds a lot like a miscompilation to me... We'll need to investigate further but the code does not do anything which would induce a 16-bit overflow and we've seen similar issues with u32 in the past.

If you need a quick and dirty workaround, I think storing two u16s and manually doing the overflow is probably the easiest:

static MILLIS_COUNTER: avr_device::interrupt::Mutex<cell::Cell<(u16, u16)>> =
    avr_device::interrupt::Mutex::new(cell::Cell::new((0, 0)));

// ...

let (mut count_upper, mut count_lower) = counter_cell.get();
if count_lower == u16::MAX {
    count_lower = 0;
    count_upper += 1;
} else {
    count_lower += 1;
}
counter_cell.set((count_upper, count_lower));

@Rahix Rahix added bug Something isn't working compiler-bug Not a bug in avr-hal, but a bug in the rust compiler/LLVM labels Mar 18, 2021
@ThisIsRex
Copy link
Author

ThisIsRex commented Mar 18, 2021

I am not entirely certain but this sounds a lot like a miscompilation to me...

You're right. I checked it out and u32 and i32 behave like u16 and i16. I couldn't check u64 and u128 because it is impossible to flash if there is a code that prints these variables

UPD: I managed to check u64 and it behaves like u32

@Rahix Rahix removed the bug Something isn't working label Mar 18, 2021
@Rahix
Copy link
Owner

Rahix commented Mar 24, 2021

Ref: rust-lang/rust#83281

@drmorr0
Copy link
Contributor

drmorr0 commented Apr 9, 2021

@ThisIsRex are you sure this is a bug with rust and not with ufmt? I've seen issues in the past where ufmt doesn't print u32 variables correctly, but if you run the code through a simulator/debugger you can see that it's actually behaving correctly.

@quantumferret
Copy link

Similar to what @drmorr0 mentioned, I found that trying to output u32 variables via ufmt would result in an overflow, displaying the time on the Uno (via a 7-segment display) was not affected by the issue with u32. E.g. writing the current value of millis() to a serial port would result in it always overflowing after u16::MAX, but displaying the same value in the LED display would go well beyond u16::MAX, so the full possible range of u32 values was accessible.

@ThisIsRex
Copy link
Author

@drmorr0 @quantumferret Sorry for delay. I guess, you're right. I wrote a test without ufmt and there was all right. (u32val > 0xFFFF)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler-bug Not a bug in avr-hal, but a bug in the rust compiler/LLVM
Projects
None yet
Development

No branches or pull requests

4 participants