-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
rp2/rp2_flash: Add MICROPY_HW_FLASH_MAX_FREQ. #17389
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/rp2_flash.c: Add MICROPY_HW_FLASH_MAX_FREQ to replace the fixed maximum frequency, default to SYS_CLK_HZ / PICO_FLASH_SPI_CLKDIV. Assuming a 133MHz capable flash caused rp2_flash_set_timing_internal to set out of range dividers for some boards (anything with value of 4 and flash that doesn't tolerate higher speeds.) This affected the XIAO RP2350 board, making it non-bootable. Since Pico SDK's PICO_FLASH_SPI_CLKDIV is entirely unreliable on a system with a variable system clock (users can change it at runtime) then use it only to work out a default MICROPY_HW_FLASH_MAX_FREQ. This value can be overridden in board config. Note that RP2350's default clock is 150MHz, RP2040's is 125MHz and it has been certified at 200MHz so it's quite possible that PICO_FLASH_SPI_CLKDIV is unreliable even at standard RP2 clocks. (If flash timings are marginal then this can manifest as instability rather than outright failure.) Signed-off-by: Phil Howard <github@gadgetoid.com>
Thanks for what you did, I can help test it tomorrow (it's already 9pm here) |
Code size report:
|
By the way, the flash clock frequency that XIAO RP2350 can work properly is about 50Mhz, and it cannot work properly at 75Mhz I set it to 60 because 50 is too low and may cause PR not to be accepted ( According to the conversion of the original code, the divisor is still 3 at 60, so the clock frequency is still 50Mhz ( |
Any time! I'm a little embarrassed that we didn't catch this oversight sooner!
Is that a minimum of 50MHz and a maximum of 60MHz? At 150MHz clock sys on the RP2350, and a If we configure:
Then it should always run at 50MHz... in theory! A small performance bump with no risk of user overclock taking it out of range. For tomorrow: If you revert to an older MicroPython and try to hit 250MHz |
Apologies for the oversight that not everyone would be using a 133MHz capable flash. Thanks @Gadgetoid for fixing it up - that change looks sensible to me. Though it's a shame that means most builds will cap the flash frequency at 75MHz (PR2350) or 62.5MHz (RP2040). We should set the |
Agreed! And across the various boards that don't have upstream configs 🤦 I wonder if this change broke any cheap Pico clones... |
Update: The current commit can make XIAO RP2350 work properly |
To be honest, I'm not sure about the specific clock range that might work. Previously, the clock frequency was set according to PICO_FLASH_SPI_CLKDIV, so only cases 2 and 4 were tested, that is, 75 Mhz (not working) and 37.5 Mhz (working properly). Another case is that when 2350 first supported Micropython, the clock frequency was always 50 Mhz (cannot be changed according to PICO_FLASH_SPI_CLKDIV), but this frequency can work normally. The last question: the old firmware doesn't work at all, so there is no way to set Update: I may have misunderstood your meaning. I used Micropython compiled from this commit PROBLEM IN THONNY'S BACK-END: Exception while handling 'execute_source' (serial.serialutil.SerialTimeoutException: Write timeout).
See Thonny's backend.log for more info.
You may need to press "Stop/Restart" or hard-reset your MicroPython device and try again. Update: >>> machine.freq(175000000)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: cannot change frequency |
Do you know the part number for your flash chip? I can look it up and see what the datasheet says (if it says anything at all!). I'll see if I can get my hands on a XIAO RP2350 for future reference, too. machine.freq(170_000_000) Should work, for some reason (can't find a divider?) 175000000 doesn't work for me either. If I should probably rig up a flash stress test script because just changing the clock and hoping it breaks instantly is not very scientific 😆 |
This is our flash datasheet: 310091605_Puya_P25Q16SH-UXH_IR_Datasheet.pdf |
Thanks, I’ve ordered an RP2040 and RP2350 Xaio board (same flash chip on both?) and will see how far I can push them. |
Yes, it is the same flash |
So from the datasheet it looks like the chip should support 133MHz, but there's a min read to read time of 20ns. I suspect if you add Unfortunately I don't see any similar config on the RP2040. Maybe it would make sense to add more parameters to control all this timing? And if we did the same on the PSRAM side it could be used to remove the assumption that the chip used was an APSxx04. |
Definitely a question for the MicroPython maintainers. For PSRAM I don't think we'll have a choice (we could have chip-specific config includes to handle this) but for flash it might be a struggle to eke out performance at the cost of configuration busywork 😆 that said, config includes for flash chips could work there too. This feels more like a Pico SDK problem 😆
Can confirm that 100MHz works for me with that change. If we can dial in the timings then we can potentially add:
And so on, assuming performing tuning flash is something MicroPython on the whole is prepared to care about! That's something for a future PR, though, since this one needs to be minimal enough to serve as a hotfix for the broken XIAO firmware. (Assuming the flash timing change isn't just reverted... I think it can be?) |
I find this to be hard to maintain, and may confuse ppl when they were trying to port boards to micropython. I would suggest to take this approach. As |
This PR already relies on this, and gives setting a specific target max frequency as an optional config value. Nonetheless |
Possibly I shouldn't have confused things on this PR by talking about the wider range of flash timing settings available on RP2350 - we can raise another issue/PR for taking advantage of that. For now, the important thing is to fix the regression on that XIAO RP2350 board. Basing the frequency on the existing |
Yes, I get that part.
No, well, not if the one who is porting a board is doing the right job. As I mentioned in that post, the vendor only have to get this part in
In addition to that, your approach will actually limit the boards flash speed to a fixed value and leave no room for scaling. Since SYS_CLK_MHZ = 125
PICO_FLASH_SPI_CLKDIV = 2
# hence
MICROPY_HW_FLASH_MAX_FREQ = 62.5 MHz Which means, if the clock is later increased to clk_sys = 250 MHz
MICROPY_HW_FLASH_MAX_FREQ = 62.5 MHz
# hence
divider = 4.984f = 4 This limits the flash clock to If you took my approach: SYS_CLK_MHZ = 125
PICO_FLASH_SPI_CLKDIV = 2
# hence, in MHz
divisor = (125 + 133 - 1) / 133 + 2 - 2 = 1.93f = 1 The flash speed is SYS_CLK_MHZ = 250
PICO_FLASH_SPI_CLKDIV = 2
# hence, in MHz
divisor = (250+ 133 - 1) / 133 + 2 - 2 = 2.87f = 2 Flash clock is I actually dig a bit further and got almost all max flash speed for all And lemme mention the most significant benefit again (your approach does this part already, but I just want to point it out again, that mine wouldn't change this nature):Vendors only has to set |
It doesn't matter what they're doing, This is cause for surprise enough that Raspberry Pi are talking about fixes for it - raspberrypi/pico-sdk#1903 Asking the original board vendor for the number they were attempting to hit when they picked "2" (or "3" or "4") (assuming they didn't just copy and paste the pico.h and/or guess) is not an unreasonable burden. (Notably
This is intentional. We are explicitly avoiding scaling because
Where are you getting this information? There are 112 boards with
This could be useful information, got a spreadsheet or otherwise? I can grep for As a vendor, you have entirely too much faith in vendors 😆 |
Ugh... not entirely sure about this part... I think this actually will be used as soon as you compile anything using the
Probably the boards were having some issues at higher cpu clocks so they had to increase the divider by a bit. I.e. vendor probably tested for
Ugh.... to my understanding, again, as soon as you compile the firmware using
Then we could have just removed the commit that brought the dynamic flash clocking feature, set the flash to a fixed frequency, but a little pessimistic i think.
We are using a fixed version of pico-sdk, so won't be a huge problem, but you are right.
My bad, should be "more or equal than 2". And I went through the
I.e. P25Q32SH-UXH-IR which is used by Seeed Studio and Waveshare for some of their boards. Basically I just checked boards with a default divider higher than 2, checked they schematics, see the flash model, searched these.
I trust you! And others! |
On RP2040 it’s always used, as it’s used to configure the flash during boot stage2. On RP2350 you have to explicitly ask for Pico SDK to embed the XIP setup. Otherwise it’s just a dangling define that you could use, but it’s a poor substitute for configuring the flash - including all the other timing settings - properly. And yes the reasonable alternative to this PR is just to revert the breaking change. We have reasons to not want to do that but they’re definitely a bit niche. Probably wouldn’t hurt to find out what Raspberry Pi have planned for flash config because it’s currently - at the risk of causing a diplomatic incident - a bit of a half baked mess. 🤣 |
I wouldn't go so far to say that... but, yes, I agree that the situation is not great with the way flash speed is configured in pico-sdk. I guess it's a case of designing something simple to fit a need (configurable flash speed on RP2040 only) and then that design doesn't scale well in the future (RP2350, max frequency being updated beyond 125MHz). I think the original intent of
We don't have much room to move here. We must assume that a vendor has chosen Really pico-sdk need to solve this issue and require boards to specify at least the flash frequency, if not other timing parameters. But until that happens I think the fix in this PR is the right way forward. It allows boards to get better performance if they tune the value of |
I had planned to make a case for this once I understood the problem and its implications within MicroPython. It's a chicken and egg problem, and having a good case - like this - to point at is as useful starting point to advocate for change. |
Rebased and merged in b725c26 |
Unfortunately this broke SIL_RP2040_SHIM:
This boards does @Gadgetoid are you able to make a PR to fix that? If not then I can. |
🤦 testing tunnel vision strikes again. Might not get a chance until later this week, but will look into that board either way! Edit: I would have thought Pico SDK would set a default
I know this is kinda potato potäto but it feels slightly more correct. |
Opened as #17510 |
Summary
I've tested v1.25.0 (2025-04-15) .uf2 on a XIAO RP2350 and, indeed, it's doesn't boot.
Replaces: #17374
Breakage reported: #17375
Assuming a 133MHz capable flash caused rp2_flash_set_timing_internal to set out of range dividers for some boards (anything with value of 4 and flash that doesn't tolerate higher speeds.)
This affected the XIAO RP2350 board, making it non-bootable.
Since Pico SDK's PICO_FLASH_SPI_CLKDIV is entirely unreliable on a system with a variable system clock (users can change it at runtime) then use it only to work out a default MICROPY_HW_FLASH_MAX_FREQ.
This value can be overridden in board config.
Note that RP2350's default clock is 150MHz, RP2040's is 125MHz and it has been certified at 200MHz so it's quite possible that PICO_FLASH_SPI_CLKDIV is unreliable even at standard RP2 clocks.
(If flash timings are marginal then this can manifest as instability rather than outright failure.)
Testing
I tested boards at 250MHz to make sure we hit the worst case.
Note the failing test was
ports/rp2/rp2_dma.py
which, entirely predictably, failed with some variation of:(Because the chip was clocked too fast)
I'm pretty sure we can crank the Pico, Pico W, Pico 2 and Pico 2 W chips faster, based on nothing but the lack of any loud and consistent shouting about them not working. (Though there might be marginal cases.)
The test suite probably doesn't do much to exercise the flash, save for
ports/rp2/rp2_thread_reset_part1.py
andports/rp2/rp2_thread_reset_part2.py
...@Lesords I don't have a XIAO RP2350. Can you confirm this change works for you?
Since you seemed to suggest that your flash chips work (reliably and repeatably?) at 60MHz, would you like me to include
in
SEEED_XIAO_RP2350/mpconfigboard.h
?Note: I should probably avail myself of some non-Pimoroni RP2 boards to test. This was an unintended consequence of this change, but we definitely could have caught it with more contentious testing and less tunnel vision.
Trade-offs and Alternatives
We don't really have much wiggle room here.
PICO_FLASH_SPI_CLKDIV
can't be relied upon where the end-user has control of the system clock. We can, however, at least use it to derive a default maximum clock value for the flash. Therefore - by my estimation - it's not appropriate to simply revert the breaking change.