-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
rp2/main.c: Set the default clock frequency at boot. #13718
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
Conversation
ports/rp2/main.c
Outdated
@@ -223,6 +227,12 @@ int main(int argc, char **argv) { | |||
soft_timer_deinit(); | |||
gc_sweep_all(); | |||
mp_deinit(); | |||
// Reset the MCU frequency | |||
set_sys_clock_khz(125000, false); |
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'm not sure it should reset the frequency on soft reset. Soft reset is about resetting all the Python state, whereas it's best to leave a lot of the hardware state as-is. Eg the WiFi is still connected. Eg on stm32 the frequency is not reset on soft reset.
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.
The intention here is to have the device at the same state as when entering the for (;;) {
loop. If code e.g. in boot.py and main.py changes the frequency, it will still do it.
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.
The other discussion which is open in the forum is, whether the peripheral clock should be set to 48MHz. Or should it better follow the CPU freq change. That can be implemented as well by changing the code for machine.freq(). My preference was for the more conservative and less surprising state, but others missed the high speed options.
Could this possibly also include some accommodation for #8208 I'd very much like a board config option to change that default, please! |
e5a8965
to
af7470a
Compare
Code size report:
|
@dpgeorge I dropped resetting the clock at soft reboot. Only at cold boot the clock it set to have the side effect of changing the peripheral frequency to 48MHz. |
ports/rp2/modmachine.c
Outdated
// 0, | ||
// CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS, | ||
// SYS_CLK_KHZ * KHZ, | ||
// SYS_CLK_KHZ * KHZ); |
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'm not sure what this commented-out code is aiming to do. When set_sys_clock_khz()
is called, does that update the PERI clock or not?
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.
The whole change is about the inconsistency, that when machine.freq() is called to change the frequency, then PERI clock is set to 48 MHz as result of calling set_sys_clock_khz()
. The change I suggested would set PERI clock always to 48MHz. Then, changing the CPU frequency would not affect e.g. the UART or PWM settings, at the penalty of limiting the peripherals baud rates.
This commented code is about the alternative suggestion to set PERI clock always to the CPU clock. Then there would be changes to the baud rates of the peripherals when changing the CPU clock, but at known rates. I added that code here just to recall it,
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.
OK, I understand more.
So without this PR (ie current master), what is the value of PERI at start up, is it the system clock, or system clock divided by some factor?
Note that machine.freq()
takes multiple arguments to specify the frequency of the buses (see eg stm32 port). So maybe it's a good idea to allow the user to specify the PERI clock as the second (optional) argument to machine.freq()
? Something like:
machine.freq(sys, peri=48000000)
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.
At the moment the PERI freq at boot is the system clock 125Mhz and it will be set to 48Mhz when calling machine.freq(n).
Note that machine.freq() takes multiple arguments to specify the frequency of the buses (see eg stm32 port).
Actually, the stm32 port lost this feature with commit 7d39db2. machine.freq() takes just 1 argument.
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 changed machine.freq() to have a second boolean type agrument. If set to False or omitted, the peripheral frequency will be 48MHz, which is the default value now at boot. If set to True, the peripheral frequency is the same as the MCU. The clock section for the peripheral clock has no divider. The documentation is wrong. So the peripheral clock can only be one of the other clock sources, like USB clock or SYS clock.
The API could also be changed to accept a frequency instead of a boolean value, with 48_000_000 and the value of the first argument as the permitted values. But then, an error check & message would have to be added.
As a required side change, machine.freq() now accepts up to 4 arguments. I made a separate PR for that 1 char change as well.
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.
The API could also be changed to accept a frequency instead of a boolean value, with 48_000_000 and the value of the first argument as the permitted values. But then, an error check & message would have to be added.
It looks like this is how you ended up implementing it (ie not as a boolean). I think what you did -- specifying a freq -- is the right way to do it. That way is more general, and more consistent with stm32.
But do you think it's better to make the peri frequency a keyword-only argument? That forces the user to be explicit and makes it even more future proof/general. Eg machine.freq(125000000, peri=48000000)
.
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.
But do you think it's better to make the peri frequency a keyword-only argument? That forces the user to be explicit and makes it even more future proof/general. Eg machine.freq(125000000, peri=48000000).
The Python API is is extmod/modmachine.c. Making peri=xxx a keyword only argument would either require to change that or to move the API back to the rp2 port.
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.
The Python API is is extmod/modmachine.c. Making peri=xxx a keyword only argument would either require to change that
Yes, if we want to make this a keyword-only argument, we'd need to change the API in extmod/modmachine.c
. We can do that if we think it's the best option. All other ports can remain as they are (stm32 accepting 4 positional args, all other ports accepting 1 positional arg).
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 do not know if it the best option, and it's a larger change. The STM32 port does not have the keywords.
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.
OK, let's leave it as a positional argument.
f35c4a9
to
c8e4511
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #13718 +/- ##
=======================================
Coverage 98.43% 98.43%
=======================================
Files 161 161
Lines 21281 21281
=======================================
Hits 20948 20948
Misses 333 333 ☔ View full report in Codecov by Sentry. |
9b2a6a9
to
7c53d70
Compare
ports/rp2/modmachine.c
Outdated
mp_obj_new_int(mp_hal_get_cpu_freq()), | ||
mp_obj_new_int(clock_get_hz(clk_peri)), | ||
}; | ||
return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple); |
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.
Returning a 2-tuple here is a big breaking change... not sure how to handle this. My suggestion for now is to just retain the old behaviour here (ie just return the CPU freq), and we can work out how to query the peri frequency in the future (if anyone ever needs it).
(I know stm32 returns a tuple, but a lot of code will be written already for rp2 that expects this to return a single integer.)
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.
Keeping the old behavior is easy. That's why it's a separate commit.
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.
Thanks for removing the additional commit (and returning just a single int).
4956a08
to
4b3e419
Compare
As a side effect, the peripheral clock will be set to 48Mhz and both UART and I2C will not be affected by CPu speed changed using `machine.freq()`. With the change the UART baud rate range is 50 to 3_000_000. Signed-off-by: robert-hh <robert@hammelrath.com>
By default, the peripheral clock for UART and SPI is set to 48 MHz and will not be affected by the MCU clock change. This can be changed by a second argument to `machine.freq(freq, peripheral_freq)`. The second argument must be either 48 MHz or identical with the first argument. Note that UART and SPI baud rates may have to be re-configured after changing the MCU clock. Signed-off-by: robert-hh <robert@hammelrath.com>
4b3e419
to
7270b87
Compare
@Gadgetoid that was not done in this PR (a config option for default CPU freq). That should be pretty easy to do, but someone needs to do it 😄 |
Thank you. |
As a side effect, the peripheral clock will be set to 48Mhz and both UART and I2C baud rates will not be affected any more by CPU speed changes using machine.freq().
With the change the UART baud rate range is 50 to 3_000_000. That is a somewhat breaking change since baud rates beyond 3MBaud are not supported any more.
Addresses the discussion #13679.