Pico Micropython overclocked twice (250MHz) works fine

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
HermannSW
Posts: 197
Joined: Wed Nov 01, 2017 7:46 am
Contact:

Pico Micropython overclocked twice (250MHz) works fine

Post by HermannSW » Thu Feb 18, 2021 8:57 pm

Pico is rated 133MHz, running at default 125MHz system clock.
I have tested my three Picos, and all allow for >420MHz overclocking (running with 1.3V).
I tested that USB works fine up to 250MHz, at default voltage of 1.1V.
So I added small piece of code to soft reboot part of ports/rp2/main.c.
It switches to 250MHz and initializes uart (again).
Now USB, I2C as well as UART work without issues, details in this forum thread:
https://www.raspberrypi.org/forums/view ... 6&t=304360

For just playing with the change without having to build yourself, .uf2 is available:
https://stamm-wilbrandt.de/en/forum/firmware.250MHZ.uf2

This is short demo of switching to 250MHz via soft reboot.
Before switching timestamp diff is roughly 20us, after it is 10us:
Image


P.S:
Just measured Pico Micropython current with constant voltage power supply.

In REPL doing nothing: 18mA
Running blink switches between 18mA and 19mA.

Then I did soft reboot to switch to 250MHz, and that had an effect:

In REPL doing nothing: 31mA
Running blink switches between 31mA and 32mA.
Pico-W Access Point static file webserver:
https://github.com/Hermann-SW/pico-w

Tiny MicroPython robots (the PCB IS the robot platform)
viewtopic.php?f=5&t=11454

webrepl_client.py
https://github.com/Hermann-SW/webrepl#webrepl-shell

shaoziyang
Posts: 363
Joined: Sun Apr 17, 2016 1:55 pm

Re: Pico Micropython overclocked twice (250MHz) works fine

Post by shaoziyang » Fri Feb 19, 2021 2:23 pm

Yes, it really works, the calculation time of PI is reduced by almost half.

Code: Select all

import gc
from utime import ticks_ms, ticks_diff
 
def pi(places=100):
  # 3 + 3*(1/24) + 3*(1/24)*(9/80) + 3*(1/24)*(9/80)*(25/168)
  # The numerators 1, 9, 25, ... are given by (2x + 1) ^ 2
  # The denominators 24, 80, 168 are given by (16x^2 -24x + 8)
  extra = 8
  one = 10 ** (places+extra)
  t, c, n, na, d, da = 3*one, 3*one, 1, 0, 0, 24
 
  while t > 1: 
    n, na, d, da = n+na, na+8, d+da, da+32
    t = t * n // d
    c += t
  return c // (10 ** extra)
 
def pi_t(n=1000):
    gc.collect()
    t1 = ticks_ms()
    pi(n)
    t2 = ticks_ms()
    print('  ', ticks_diff(t2, t1), 'ms')
 
for i in (100, 500, 1000, 5000, 10000):
    try:
        print('\nCalc {} bits pi'.format(i))
        pi_t(i)
    except:
        print('Calc error!')

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Pico Micropython overclocked twice (250MHz) works fine

Post by Roberthh » Fri Feb 19, 2021 6:14 pm

It works, but to the output is distorted in my tests. So practically not always useful. But it should be exposed via machine.freq.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Pico Micropython overclocked twice (250MHz) works fine

Post by Roberthh » Fri Feb 19, 2021 8:14 pm

For everyone who is interested, here is a modified machine.freq() code, to replace the sections in modmachine.c.

Code: Select all

#include "pico/stdlib.h"

STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
    if (n_args == 0) {
        // get
        return MP_OBJ_NEW_SMALL_INT(clock_get_hz(clk_sys));
    } else {
        // set
        mp_int_t freq = mp_obj_get_int(args[0]);
        if (set_sys_clock_khz(freq / 1000, false)) {
            return mp_const_none;
        } else {
            mp_raise_ValueError("valid range 10-270MHz");
        }
    }
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq);
The additional # include would typically sit in the include section at the file head.
You can set higher and lower frequencies. I tried 270Mhz, 250MHz, 150MHz, 80MHz, 40MHz, 20MHz, 10MHz. In all cases, USB worked fine. Whether higher frequency work is not clear. Sometimes I get an error, sometimes the board is silent. At 250MHz I tried a PIO example which toggles a PIN, and I could get a 125MHz square-about signal. It seems that the I/O driver is at it's limit for that frequency. The same for 270MHz and 10 MHz.
P.S.: The level at the pin is about 3Vpp. I used a 470/56 ohm resistor divider into a 50 Ohm cable cable to pick up the signal, to have a 50Ohm source and no ringing. Together with the 50 Ohm of the cable, that scales down the level by about 20.
Attachments
125Mhz_toggle.png
125Mhz_toggle.png (40.85 KiB) Viewed 11479 times

Georgeskingv
Posts: 3
Joined: Mon Feb 22, 2021 4:48 pm

Re: Pico Micropython overclocked twice (250MHz) works fine

Post by Georgeskingv » Mon Feb 22, 2021 4:51 pm

Hi,

Can we change the clock frequency from a micropython program ?
Like machine.freq(125000000)

Best regards

Georges

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Pico Micropython overclocked twice (250MHz) works fine

Post by Roberthh » Mon Feb 22, 2021 7:00 pm

I made a PR for that. Eventually it will be included.
See: https://github.com/micropython/micropython/pull/6941

HermannSW
Posts: 197
Joined: Wed Nov 01, 2017 7:46 am
Contact:

Re: Pico Micropython overclocked twice (250MHz) works fine

Post by HermannSW » Wed Mar 03, 2021 9:52 pm

Roberthh wrote:
Fri Feb 19, 2021 6:14 pm
It works, but to the output is distorted in my tests. So practically not always useful. But it should be exposed via machine.freq.
Hi,
USB works fine at 250MHz, but UART has problems.
I solved that in main.c by calling "setup_default_uart()" and "mp_uart_init()" in case MICROPY_HW_ENABLE_UART_REPL is defined (I did switch to 250MHz on soft reboot):

Code: Select all

diff --git a/ports/rp2/main.c b/ports/rp2/main.c
index 0acab6735..ebbfe93b7 100644
--- a/ports/rp2/main.c
+++ b/ports/rp2/main.c
@@ -105,6 +105,18 @@ int main(int argc, char **argv) {
         machine_pin_deinit();
         gc_sweep_all();
         mp_deinit();
+
+        if (!set_sys_clock_khz(250000, false))
+            mp_printf(MP_PYTHON_PRINTER, "250MHz system clock failed\n");
+        else
+        {
+            #if MICROPY_HW_ENABLE_UART_REPL
+            setup_default_uart();
+            mp_uart_init();
+            #endif
+
+            mp_printf(MP_PYTHON_PRINTER, "system clock now is 250MHz\n");
+        }
     }
 
  

Can you enhance machine.freq() code to do the same for UART?
Pico-W Access Point static file webserver:
https://github.com/Hermann-SW/pico-w

Tiny MicroPython robots (the PCB IS the robot platform)
viewtopic.php?f=5&t=11454

webrepl_client.py
https://github.com/Hermann-SW/webrepl#webrepl-shell

HermannSW
Posts: 197
Joined: Wed Nov 01, 2017 7:46 am
Contact:

Re: Pico Micropython overclocked twice (250MHz) works fine

Post by HermannSW » Thu Mar 04, 2021 5:25 pm

Hi Roberthh,

after I was able to build Micropython, I did copy your changed file and rebuilt for machine.freq() support:
https://raw.githubusercontent.com/rober ... dmachine.c

Then I did enable UART REPL in ports/rp2/mpconfigport.h:

Code: Select all

 #define MICROPY_HW_MCU_NAME                     "RP2040"
-#define MICROPY_HW_ENABLE_UART_REPL             (0) // useful if there is no USB
+#define MICROPY_HW_ENABLE_UART_REPL             (1) // useful if there is no USB
 #define MICROPY_HW_ENABLE_USBDEV                (1)

After building and flashing UART REPL worked fine -- until I changed frequency to 250MHz.
First I added only "mp_uart_init()" to your code, that did not work.
But adding "set_default_uart()" as well made it work ("uart.h" has to be included in modmachine.c as well):

Code: Select all

-STATIC mp_obj_t machine_freq(void) {
-    return MP_OBJ_NEW_SMALL_INT(clock_get_hz(clk_sys));
+STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
+    if (n_args == 0) {
+        return MP_OBJ_NEW_SMALL_INT(clock_get_hz(clk_sys));
+    } else {
+        mp_int_t freq = mp_obj_get_int(args[0]);
+        if (!set_sys_clock_khz(freq / 1000, false)) {
+            mp_raise_ValueError(MP_ERROR_TEXT("cannot change frequency"));
+        }
+        #if MICROPY_HW_ENABLE_UART_REPL
+        setup_default_uart();
+        mp_uart_init();
+        #endif
+        return mp_const_none;
+    }

Here is proof that serial minicom Micropython works after changing to 250MHz.
Can you please add the 4 lines to your pull request?
Peek_2021-03-04_18-15.gif
Peek_2021-03-04_18-15.gif
Peek_2021-03-04_18-15.gif (52.34 KiB) Viewed 11212 times
Pico-W Access Point static file webserver:
https://github.com/Hermann-SW/pico-w

Tiny MicroPython robots (the PCB IS the robot platform)
viewtopic.php?f=5&t=11454

webrepl_client.py
https://github.com/Hermann-SW/webrepl#webrepl-shell

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Pico Micropython overclocked twice (250MHz) works fine

Post by Roberthh » Thu Mar 04, 2021 8:17 pm

Thank you for your hints. I changed the PR accordingly. The frequency change may affect the UART in general, so it's wise to set it up (again) after the MCU frequency was changed.

HermannSW
Posts: 197
Joined: Wed Nov 01, 2017 7:46 am
Contact:

Re: Pico Micropython overclocked twice (250MHz) works fine

Post by HermannSW » Thu Mar 04, 2021 11:31 pm

Thanks.
Works as expected, measured with consecutive microsecond timestamp differences (10/125/250MHz):

Code: Select all

MicroPython v1.14-83-g680ce4532-dirty on 2021-03-04; Raspberry Pi Pico with RP20
Type "help()" for more information.                                             
>>> import machine, time                                                        
>>> tus=time.ticks_us                                                           
>>> machine.freq(10000000)                                                      
>>> print(-tus()+tus(),-tus()+tus(),-tus()+tus(),-tus()+tus(),-tus()+tus())     
188 73 73 73 72                                                                 
>>> machine.freq(125000000)                                                     
>>> print(-tus()+tus(),-tus()+tus(),-tus()+tus(),-tus()+tus(),-tus()+tus())     
10 6 6 5 5                                                                      
>>> machine.freq(250000000)                                                     
>>> print(-tus()+tus(),-tus()+tus(),-tus()+tus(),-tus()+tus(),-tus()+tus())     
4 3 3 3 3                                                                       
>>> 
Pico-W Access Point static file webserver:
https://github.com/Hermann-SW/pico-w

Tiny MicroPython robots (the PCB IS the robot platform)
viewtopic.php?f=5&t=11454

webrepl_client.py
https://github.com/Hermann-SW/webrepl#webrepl-shell

Post Reply