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

Add frequency setting for RP2040 boards. #7430

Merged
merged 4 commits into from
May 2, 2023

Conversation

Lanzaa
Copy link

@Lanzaa Lanzaa commented Jan 8, 2023

Allow setting the cpu frequency for RP2040 boards.

My first PR here. I did very basic testing using a Pico board. Being able to lower the system frequency helps with power usage. At the standard 125MHz my board uses ~20mA and at 20MHz it uses ~6mA.

Copy link
Collaborator

@microdev1 microdev1 left a comment

Choose a reason for hiding this comment

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

Thanks! @Lanzaa, a few things to address.

ports/raspberrypi/common-hal/microcontroller/Processor.c Outdated Show resolved Hide resolved
@microdev1 microdev1 added enhancement rp2 Raspberry Pi RP2 Micros labels Jan 8, 2023
@dhalbert
Copy link
Collaborator

dhalbert commented Jan 8, 2023

One thing to check is if any code is assuming 125000000 as the clock frequency. I searched for 125:

I think this could be fixed:

int result = pwmout_allocate(slice, channel, true, 125000000 / 3);

Another issue is code that has timing derived from assuming 125MHz. This may also be fixable, at least within a certain range:

// empirical-ish from RP2040 @ 125MHz for floppy_flux_readinto
#define FLOPPYIO_SAMPLERATE (24000000)
// empirical-ish from RP2040 @ 125MHz for floppy_mfm_readinto
// my guess is these are slower because the more complex routine falls out of cache, but it's just
// speculation because the loops are very similar. When looking at raw bins with a modified
// version of adafruit_floppy, it can be seen that there are _two_ peaks for T2 and T3, rather
// than a single one, around 36 (mostly) and 43 (rarer), compared to a single peak around 48.
(found due to comment) (@fyi @jepler)

For https://github.com/adafruit/circuitpython/blob/main/ports/raspberrypi/common-hal/neopixel_write/__init__.c, the PIO programs have been tuned assuming 125 MHz.
here may be other PIO uses as well. These are a lot more difficult to parameterize. It should be documented that they assume 125MHz and may not work when the clock frequency is changed.

@jepler
Copy link
Member

jepler commented Jan 8, 2023

Thank you for working on this PR! A number of people would like functionality like this. However, I have some remarks about problems that seem likely to occur when this functionality is made available and would like to see the documentation improved to anticipate them.

Say that I create an object like PWMOut that has an associated frequency (1MHz), then change the CPU frequency from the default (125MHz) to 20MHz. As I understand it, the frequency of the PWMOut will also change, because it uses a divisor of the CPU frequency. In this case, the PWMOut frequency would change from 1MHz to 160kHz (20MHz/125).

(audio, pulseio, spi, i2c, and anything using pio would also be affected)

I am sure this is acceptable for some use cases but it deserves a big caveat in the documentation.

Another concern is that this function will set high frequencies above the datasheet maximum. e.g., this led to the spurious report that calling the function twice didn't work: raspberrypi/pico-sdk#94 and even at frequencies that do "work" it reportedly interferes with USB functionality (reported in the same issue). Should the function allow "above datasheet maximum" settings, or should it reject them? Again, I think this needs a note in the documentation.

Also only 440 of the 1-kHz granularity frequencies from 1kHz to 133MHz succeed in configuring, the other 132559 fail. Every 1MHz multiple 20MHz or above does succeed. This is because the clock setting routine in the SDK only sets the frequency if it can be exactly attained. But, confusingly, if setting 20_000_000Hz works then setting 20_000_001Hz will also work, because the 1Hz difference has been divided away already. (this is based not on testing on-device but on a standalone program that uses code copied out of pico-sdk: https://gist.github.com/fd42b3b7d99bbb321dd6db6ef77499aa)

@Lanzaa
Copy link
Author

Lanzaa commented Jan 11, 2023

Sounds good. I will see what I can address. Hopefully I will update the PR before the start of next week.

@bill88t
Copy link

bill88t commented Jan 11, 2023

First of all I believe it would be best to 'by-default' prohibit overclocking.
A typo could be very problematic..
One extra digit is all it takes for the rp2040 to become a potato chip.
Ideally an cpu.safety/cpu.overclock/cpu.cook_mah_pi kind of property should be made available.

I think it's good to try to implement this so that all the modules are ready for any future rp2 chips with different frequencies.

Also, @Lanzaa, to fix the pre-commit check run pip install pre-commit && pre-commit install && pre-commit run -a in the repo directory, after that, it will automatically run on every commit for this clone of the repo.
For more information on pre-commit please refer to: https://pre-commit.com/#install

* Add warning about setting RP2040 frequency
@Lanzaa
Copy link
Author

Lanzaa commented Jan 17, 2023

I have changed common_hal_mcu_processor_set_frequency to a void return and improved the documentation:

documentation of frequency 20230116

First of all I believe it would be best to 'by-default' prohibit overclocking. ... Ideally an cpu.safety/cpu.overclock/cpu.cook_mah_pi kind of property should be made available.

Any advice on where to put these properties?

In this case, the PWMOut frequency would change from 1MHz to 160kHz (20MHz/125). (audio, pulseio, spi, i2c, and anything using pio would also be affected)

@jepler Do you have any advice on how I could best test these issues?

@Lanzaa Lanzaa requested a review from microdev1 January 17, 2023 05:45
@tannewt
Copy link
Member

tannewt commented Jan 17, 2023

I have changed common_hal_mcu_processor_set_frequency to a void return and improved the documentation:

Thanks for the note! Please make it generic. The same clock caveat will apply across all micros. Please add a suggestion that one sets the frequency before starting to using anything else. That way they should be able to adjust to the new clock.

Any advice on where to put these properties?

Don't add them. Frequency is enough. The common_hal code should verify the value is somewhat reasonable.

@jepler Do you have any advice on how I could best test these issues?

A logic analyzer or oscilloscope should be able to show you the frequency change in the pwm output.

Copy link
Collaborator

@microdev1 microdev1 left a comment

Choose a reason for hiding this comment

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

Thanks for making the requested changes.

microdev1
microdev1 previously approved these changes Jan 21, 2023
@dhalbert dhalbert added this to the 8.0.0 milestone Jan 27, 2023
@jepler
Copy link
Member

jepler commented Jan 27, 2023

I hadn't even considered the impact on USB. Does changing the frequency at all mean USB won't work any longer?

Copy link
Member

@jepler jepler left a comment

Choose a reason for hiding this comment

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

[20:13:24] >>> microcontroller.cpu.frequency=125_000_000; t0 = time.monotonic_ns(); t0; sum(range(1_000_000)); t1 = time.monotonic_ns(); (t1-t0) / 1e9
[20:13:44] 207238281250
[20:13:54] 499999500000
[20:13:54] 10.6943
[20:13:54] >>> microcontroller.cpu.frequency=300_000_000; t0 = time.monotonic_ns(); t0; sum(range(1_000_000)); t1 = time.monotonic_ns(); (t1-t0) / 1e9
[20:14:03] 226430664062
[20:14:07] 499999500000
[20:14:07] 4.45605
[20:14:07] >>> microcontroller.cpu.frequency=600_000_000; t0 = time.monotonic_ns(); t0; sum(range(1_000_000)); t1 = time.monotonic_ns(); (t1-t0) / 1e9

[tio 20:14:21] Disconnected
  1. Setting the frequency doesn't immediately disconnect USB
  2. and a computational task does get faster
  3. but setting it too high just breaks everything. What 'maximum overclock' should be accepted? Arduino IDE with
  4. before & after frequency changes, neopixel_write continues to work so clocks set up after the frequency change are correct. neopixel_write constructs a fresh StateMachine instance every time
  5. as expected, an existing PIO state machine operates at the wrong frequency. For instance, when using adafruit_neopxl8, changing the frequency after creating a pixel object caused it to malfunction, showing bright white instead of dim blue.

Comment on lines 62 to 63
SystemCoreClock = setarmclock(frequency);
return SystemCoreClock;
Copy link
Member

Choose a reason for hiding this comment

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

why were these lines removed? doesn't it stop the clock setting from becoming effective?

@jepler
Copy link
Member

jepler commented Jan 27, 2023

[20:21:51] >>> n[0] = 0
[20:21:55] >>> n[0] = 1 # correctly changes color
[20:21:57] >>> microcontroller.cpu.frequency
[20:22:03] 250000000
[20:22:03] >>> microcontroller.cpu.frequency = 125_000_000
[20:22:06] >>> n[0] = 0 # sets incorrect color because PIO operating at wrong frequency
[20:22:08] >>> n[0] = 1

@dhalbert dhalbert modified the milestones: 8.0.0, 8.x.x Jan 30, 2023
@dhalbert
Copy link
Collaborator

Changing this to draft for now.

@dhalbert dhalbert marked this pull request as draft February 17, 2023 15:36
@dhalbert dhalbert requested a review from tannewt April 14, 2023 17:50
@tannewt tannewt marked this pull request as ready for review April 20, 2023 00:05
@tannewt
Copy link
Member

tannewt commented Apr 20, 2023

I've polished this up. @dhalbert please re-review since jepler is out.

@dhalbert
Copy link
Collaborator

@tannewt Can we wait for @jepler to also re-review, or do we need this in a build for Pico DVI?

@tannewt
Copy link
Member

tannewt commented Apr 24, 2023

It can wait. It isn't needed for DVI.

@dhalbert dhalbert requested a review from jepler April 24, 2023 18:48
@tannewt tannewt removed the request for review from dhalbert April 24, 2023 19:47
Copy link
Member

@jepler jepler left a comment

Choose a reason for hiding this comment

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

Thanks!

@tannewt tannewt merged commit 750615f into adafruit:main May 2, 2023
407 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement rp2 Raspberry Pi RP2 Micros
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants