-
Notifications
You must be signed in to change notification settings - Fork 241
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
Update lower VCO frequency limit according to datasheet update #684
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -127,10 +127,10 @@ pub mod common_configs { | |
|
||
/// Default, nominal configuration for PLL_USB. | ||
pub const PLL_USB_48MHZ: PLLConfig = PLLConfig { | ||
vco_freq: HertzU32::MHz(480), | ||
vco_freq: HertzU32::MHz(960), | ||
refdiv: 1, | ||
post_div1: 5, | ||
post_div2: 2, | ||
post_div2: 4, | ||
}; | ||
} | ||
|
||
|
@@ -141,18 +141,22 @@ impl<D: PhaseLockedLoopDevice> PhaseLockedLoop<Disabled, D> { | |
xosc_frequency: HertzU32, | ||
config: PLLConfig, | ||
) -> Result<PhaseLockedLoop<Disabled, D>, Error> { | ||
const VCO_FREQ_RANGE: RangeInclusive<HertzU32> = HertzU32::MHz(400)..=HertzU32::MHz(1_600); | ||
const VCO_FREQ_RANGE: RangeInclusive<HertzU32> = HertzU32::MHz(750)..=HertzU32::MHz(1_600); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So you don't think increasing the lower limit here should be considered a semver breaking change? Most users would use the default values anyway, so updating So the question is how to handle the few users which use a custom clock spec outside the new limits. Does the risk of a somehow unstable clock justify the breaking change in a bugfix version? I'd prefer to leave this limit at 400MHz. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm not too sure to be honest. Should we update the semver on the first PR that requires it to be updated or right before a release when we review the changelog ?
I may have missed some discussions around having a bug fix version. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No there was no such discussion. It's just that we could do compatible releases right now without much effort as the last release is only a few days ago, so checking for breaking changes is still easy. Once we start merging breaking changes, we'd need to manually backport fixes to a bugfix branch if we want to do such a release. (Bugfix is not the best term here, as we are pre 1.0, there are no separate numbers for minor and patch releases. Let's call it compatible vs. incompatible, using the terms from https://doc.rust-lang.org/cargo/reference/resolver.html#semver-compatibility.) |
||
const POSTDIV_RANGE: Range<u8> = 1..7; | ||
const FBDIV_RANGE: Range<u16> = 16..320; | ||
|
||
let vco_freq = config.vco_freq; | ||
let PLLConfig { | ||
vco_freq, | ||
refdiv, | ||
post_div1, | ||
post_div2, | ||
} = config; | ||
|
||
if !VCO_FREQ_RANGE.contains(&vco_freq) { | ||
return Err(Error::VcoFreqOutOfRange); | ||
} | ||
|
||
if !POSTDIV_RANGE.contains(&config.post_div1) || !POSTDIV_RANGE.contains(&config.post_div2) | ||
{ | ||
if !POSTDIV_RANGE.contains(&post_div1) || !POSTDIV_RANGE.contains(&post_div2) { | ||
return Err(Error::PostDivOutOfRage); | ||
} | ||
|
||
|
@@ -161,7 +165,7 @@ impl<D: PhaseLockedLoopDevice> PhaseLockedLoop<Disabled, D> { | |
|
||
let ref_freq_hz: HertzU32 = xosc_frequency | ||
.to_Hz() | ||
.checked_div(u32::from(config.refdiv)) | ||
.checked_div(u32::from(refdiv)) | ||
.ok_or(Error::BadArgument)? | ||
.Hz(); | ||
|
||
|
@@ -180,9 +184,6 @@ impl<D: PhaseLockedLoopDevice> PhaseLockedLoop<Disabled, D> { | |
return Err(Error::FeedbackDivOutOfRange); | ||
} | ||
|
||
let refdiv = config.refdiv; | ||
let post_div1 = config.post_div1; | ||
let post_div2 = config.post_div2; | ||
let frequency: HertzU32 = ((ref_freq_hz / u32::from(refdiv)) * u32::from(fbdiv)) | ||
/ (u32::from(post_div1) * u32::from(post_div2)); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that you didn't take the value from https://github.com/raspberrypi/pico-sdk/pull/869/files, but kept it closer to the previous value.
Another possible combination would be a vco_freq of 768 MHz with
post_div1: 4
andpost_div2: 4
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the multiple of 48 between 750 and 1600 only these can be divided by valid post_div1/2 value:
The doc recommends that when the two post_div have different value to preferably use the higher one first.
But it does not say anything about preferring same-divisor vs different-divisors 🤷
I read in the datasheet for another chip that higher internal PLL frequency was better (I can't remember if it was for power consumption or frequency stability).
The pico SDK has used 1200 with same-divisor 5*5.
I doubled the frequency because it required the least mental calculation 💇
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I understand it, higher frequency of the VCO means the resulting output frequency is more stable. At the cost of higher power consumption. So it's a tradeoff.
I don't know anything about the stability requirements of the USB clock, but if it worked reasonably well with the 400MHz VCO in the past, I'd guess that 768 or 960 MHz will be more than enough and 1200MHz would not result in any useful improvement.
But that's all guesswork.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, I just found this in the datasheet:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to measure the jitter depending on the VCO frequency.
The measurement setup is just an oscilloscope which measures the signal frequency at the clock output on gpio21, and calculates a standard deviation from those values. The validity of these measurements is a questionable because the (nominally) 100MHz oscilloscope (Siglent SDS 1104X-E) is probably at its limit for measuring this 48MHz signal. And of course the measurement method is not really suitable to characterize signal jitter.
Anyway, I measured the following standard deviations of the frequency:
My impression is that the differences between 960 and 1400 MHz are just statistical fluctuations. I only measured 1000 cycles, so the values were not yet stable enough to tell it with more precision.
But the increase of the standard deviation at lower VCO frequencies was obvious.
Of course, it might be that the actual values are much lower and the measurements are dominated by errors caused by my measurement setup.
In conclusion, I'd say we should use a VCO frequency of at least 960 MHz. Above that value, this measurement doesn't deliver any meaningful result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest that we first apply the minimal change, #688, to use the same VCO value as the C SDK.
This doesn't invalidate your other changes (updating the valid range & code improvements), but by appying the minimal update first, we can do a bugfix release without breaking changes, first.