-
Notifications
You must be signed in to change notification settings - Fork 11
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
Fix integer overflow in microseconds delay, typos #16
Conversation
I think a better method would be to switch the input to In fact, we can switch the input to |
This isn't correct. With a u32 input to
I'm afraid I don't understand the reasoning for this. |
Right, but users could get a longer delay by using
All ruduino does is re-export the module, I don't think it's actually used internally.
I understand that making it private would be a breaking API change (although then again, so is changing its argument type). I do agree with you that it should probably still be available to end users, but at the same time I don't think it should be in the top-level module.
If we make By making tl;dr By ignoring the top 16 bits, we have less overhead, and it's fine to ignore them since: a) we don't actually need those top 16 bits when calling from |
To get a better sense of what I mean, could you take a look at my pull request? Here: #17 |
I disagree with most of this, except for the API changes being breaking (on that a bit further). In particular, I don't think your argument for making If you indeed registered a noticeable overhead for small delays while calling Also, if the |
What do you mean by a compound? I'm not familiar with that terminology.
I really can't think of a scenario where a user would actually want to call
If our internal delay uses 48 bits of a *(262 MHz, the clock speed needed to cause an overflow, is about five to ten times as fast as any 8-bit AVR chip is actually capable of operating) Basically, I want to think of the internal delay function (the one taking a Having said that, I think it would be more consistent with my position to actually make the internal functions totally private, instead of just in a public module, and only leave the old |
Ah, okay, I did in fact misunderstand your explanation of the |
I'm about to merge this. However merge conflict prevented it. Manual labor got us to branch @rkarabut is it OKay that the reworked merge happens? It are these commits stappers@myhost:~/src/rust/RustAVR/delay
$ git format-patch master
0001-typos.patch
0002-Fix-microsecons-delay.patch
0003-Expand-count-parameters-to-u64.patch
stappers@myhost:~/src/rust/RustAVR/delay
$ head -n 200 *.patch
==> 0001-typos.patch <==
From 78d0cece30416de0dde7a156d72acc46148faad1 Mon Sep 17 00:00:00 2001
From: Ratmir Karabut <rkarabut@gmail.com>
Date: Wed, 8 Jun 2022 16:40:12 +0200
Subject: [PATCH 1/3] typos
---
src/lib.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/lib.rs b/src/lib.rs
index c48621a..dd936c2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -50,7 +50,7 @@ pub fn delay(count: u32) {
}
}
-///delay for N miliseconds
+///delay for N milliseconds
/// # Arguments
/// * 'ms' - an u32, number of milliseconds to busy-wait
#[inline(always)]
@@ -62,7 +62,7 @@ pub fn delay_ms(ms: u32) {
///delay for N microseconds
/// # Arguments
-/// * 'ms' - an u32, number of microseconds to busy-wait
+/// * 'us' - an u32, number of microseconds to busy-wait
#[inline(always)]
pub fn delay_us(us: u32) {
// picoseconds
--
2.36.1
==> 0002-Fix-microsecons-delay.patch <==
From 790d9e996140239bad70b38a7394d84dac164a42 Mon Sep 17 00:00:00 2001
From: Ratmir Karabut <rkarabut@gmail.com>
Date: Wed, 8 Jun 2022 18:39:59 +0200
Subject: [PATCH 2/3] Fix microsecons delay
---
src/lib.rs | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/lib.rs b/src/lib.rs
index dd936c2..eee5c3c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -65,10 +65,8 @@ pub fn delay_ms(ms: u32) {
/// * 'us' - an u32, number of microseconds to busy-wait
#[inline(always)]
pub fn delay_us(us: u32) {
- // picoseconds
- let ps = us * 1000;
- let ps_lp = 1000000000 / (avr_config::CPU_FREQUENCY_HZ / 4);
- let loops = (ps / ps_lp) as u32;
+ let us_lp = avr_config::CPU_FREQUENCY_HZ / 1000000 / 4;
+ let loops = (us * us_lp) as u32;
delay(loops);
}
--
2.36.1
==> 0003-Expand-count-parameters-to-u64.patch <==
From 1c4d61565e36708447ba790f84a7f81b41b05c6c Mon Sep 17 00:00:00 2001
From: Ratmir Karabut <rkarabut@gmail.com>
Date: Wed, 8 Jun 2022 18:53:06 +0200
Subject: [PATCH 3/3] Expand count parameters to u64
to accomodate values > ~1000s
---
src/lib.rs | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/lib.rs b/src/lib.rs
index eee5c3c..da57eb3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -25,9 +25,9 @@ use core::arch::asm;
/// Internal function to implement a variable busy-wait loop.
/// # Arguments
-/// * 'count' - an i32, the number of times to cycle the loop.
+/// * 'count' - a u64, the number of times to cycle the loop.
#[inline(always)]
-pub fn delay(count: u32) {
+pub fn delay(count: u64) {
// Our asm busy-wait takes a 16 bit word as an argument,
// so the max number of loops is 2^16
let outer_count = count / 65536;
@@ -52,9 +52,9 @@ pub fn delay(count: u32) {
///delay for N milliseconds
/// # Arguments
-/// * 'ms' - an u32, number of milliseconds to busy-wait
+/// * 'ms' - an u64, number of milliseconds to busy-wait
#[inline(always)]
-pub fn delay_ms(ms: u32) {
+pub fn delay_ms(ms: u64) {
// microseconds
let us = ms * 1000;
delay_us(us);
@@ -62,11 +62,11 @@ pub fn delay_ms(ms: u32) {
///delay for N microseconds
/// # Arguments
-/// * 'us' - an u32, number of microseconds to busy-wait
+/// * 'us' - an u64, number of microseconds to busy-wait
#[inline(always)]
-pub fn delay_us(us: u32) {
- let us_lp = avr_config::CPU_FREQUENCY_HZ / 1000000 / 4;
- let loops = (us * us_lp) as u32;
+pub fn delay_us(us: u64) {
+ let us_in_loop = (avr_config::CPU_FREQUENCY_HZ / 1000000 / 4) as u64;
+ let loops = us * us_in_loop;
delay(loops);
}
--
2.36.1
stappers@myhost:~/src/rust/RustAVR/delay
$ |
@stappersg Fine by me 👍 |
I still have my concerns about this PR that I expressed last year. Namely, there's no point making delay_ms and delay_ms take u64 arguments, since that doesn't actually prevent overflow (since they're public functions, the user can just pass in massive numbers if they feel like it). Instead, they should both take a u32 argument, and then call a private internal delay function that takes a u64, like in my PR. |
On Thu, Jun 09, 2022 at 01:03:16AM -0700, lord-ne wrote:
I still have my concerns about this PR ... like in my PR.
Acknowledge on that.
For what it is worth:
* I'm aware of merge request #17
* I know that there are meanwhile merge conflicts
* That is expressed in #17
* I have seen email with #17 in the Subject line
from after my "there are merge conflicts"
* Those emails / comments haven't yet been read by me
* I might not read them
* It are good merge requests that get us forward
|
@stappersg Okay, I understand. Just be aware that I fixed all the merge conflicts in #17 last night. |
That work is now in branch
Merged and pushed, thanks for your contribution to this project. |
delay_ms() and delay_us() functions don't work correctly (check https://www.reddit.com/r/rust/comments/mjkp9v/arduino_pro_mini_avr_delay_delay_ms_doesnt_work/ for a number of complaints), also making the reference avr-rust implementation broken as-is. The reasons seem to include the possible integer overflow at the line 63 at the requested delay of > ~4.3 seconds.
This pull request changes the math in delay_us(), alleviating the problem. As the overflow could still happen with required us >= 2**30, or at about just 1073 seconds, which doesn't look good enough, I also changed the relevant parameters to u64. Tested on a physical Arduino Uno with seconds-range values.