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

Use fixed-point u64 math to divide the PLL values #212

Merged
merged 3 commits into from
Mar 27, 2024

Conversation

BryanKadzban
Copy link
Contributor

This avoids the need for almost 1K of code to implement division for u64 values (which the Cortex-M7 can't do in hardware). It can multiply u64 values in hardware, so instead of dividing by (integer) x, we find 1/x in fixed-point, multiply, and shift the fixed-point offset back out. It can also divide u32 values, and finding 1/x can be done in a u32 since our shift is small enough.

Fixes #211

This avoids the need for almost 1K of code to implement division for u64
values (which the Cortex-M7 can't do in hardware).  It can multiply u64
values in hardware, so instead of dividing by (integer) x, we find 1/x
in fixed-point, multiply, and shift the fixed-point offset back out.
Finding 1/x can be done in a u32 since our shift is small enough, and
that division *can* be done in hardware on this CPU.

Fixes stm32-rs#211
@BryanKadzban
Copy link
Contributor Author

Hmm, I seem to be failing a bunch of rcc tests. Let's fix that up...

This requires shifting the input frequencies down by 4 bits in order to
fit both the max base_clk*n value, and the 30-bit fractional part, into
a u64.  (base_clk*n is up to 38 bits wide.)  This is OK as long as all
input frequencies are a multiple of 250kHz, which has the bottom 4 bits
clear.
"cargo fmt" does not work because it requires both test mode and
the #![no_std] attribute, which the crate lib.rs doesn't enable in
test mode.  But manually running rustfmt does.
@BryanKadzban
Copy link
Contributor Author

For people not looking at #211, the issue with the tests was that we lost too much precision using only 26 bits for the fractional part of the fixed-point math. It needed at least 30 bits. But the numerator in the division operation needed up to 38 bits, so it would overflow a u64. Fortunately, we could shift the frequency right by 4 bits at the start to make everything fit, as long as the input frequencies are a multiple of 250kHz (they all are in the tests, at least, and I think they are likely to be in people's designs as well).

So now we shift the frequency right by 4 bits and use 30 bits for the fractional part. Tests are all accurate enough to pass.

@maximeborges maximeborges requested review from a team, eldruin, maximeborges and mvertescher and removed request for a team March 22, 2024 18:32
Copy link
Member

@eldruin eldruin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me in principle, but I do not know exactly how it works. If nobody raises any issues, I would merge this.

Copy link
Member

@eldruin eldruin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, let's merge this. Thank you for your work!

@eldruin eldruin merged commit f6a5d1f into stm32-rs:main Mar 27, 2024
15 checks passed
@BryanKadzban BryanKadzban deleted the rm-u64-div branch August 3, 2024 00:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Clock setup code pulls in almost 1K of u64-math builtins
2 participants