3434#include "hardware/flash.h"
3535#include "pico/binary_info.h"
3636#include "rp2_psram.h"
37+ #ifdef PICO_RP2350
38+ #include "hardware/structs/ioqspi.h"
39+ #include "hardware/structs/qmi.h"
40+ #else
41+ #include "hardware/structs/ssi.h"
42+ #endif
3743
3844#define BLOCK_SIZE_BYTES (FLASH_SECTOR_SIZE)
3945
@@ -94,6 +100,48 @@ static bool use_multicore_lockout(void) {
94100 ;
95101}
96102
103+ // Function to set the flash divisor to the correct divisor, assumes interrupts disabled
104+ // and core1 locked out if relevant.
105+ static void __no_inline_not_in_flash_func (rp2_flash_set_timing_internal )(int clock_hz ) {
106+
107+ // Use the minimum divisor assuming a 133MHz flash.
108+ const int max_flash_freq = 133000000 ;
109+ int divisor = (clock_hz + max_flash_freq - 1 ) / max_flash_freq ;
110+
111+ #if PICO_RP2350
112+ // Make sure flash is deselected - QMI doesn't appear to have a busy flag(!)
113+ while ((ioqspi_hw -> io [1 ].status & IO_QSPI_GPIO_QSPI_SS_STATUS_OUTTOPAD_BITS ) != IO_QSPI_GPIO_QSPI_SS_STATUS_OUTTOPAD_BITS ) {
114+ ;
115+ }
116+
117+ // RX delay equal to the divisor means sampling at the same time as the next falling edge of SCK after the
118+ // falling edge that generated the data. This is pretty tight at 133MHz but seems to work with the Winbond flash chips.
119+ const int rxdelay = divisor ;
120+ qmi_hw -> m [0 ].timing = (1 << QMI_M0_TIMING_COOLDOWN_LSB ) |
121+ rxdelay << QMI_M1_TIMING_RXDELAY_LSB |
122+ divisor << QMI_M1_TIMING_CLKDIV_LSB ;
123+
124+ // Force a read through XIP to ensure the timing is applied
125+ volatile uint32_t * ptr = (volatile uint32_t * )0x14000000 ;
126+ (void )* ptr ;
127+ #else
128+ // RP2040 SSI hardware only supports even divisors
129+ if (divisor & 1 ) {
130+ divisor += 1 ;
131+ }
132+
133+ // Wait for SSI not busy
134+ while (ssi_hw -> sr & SSI_SR_BUSY_BITS ) {
135+ ;
136+ }
137+
138+ // Disable, set the new divisor, and re-enable
139+ hw_clear_bits (& ssi_hw -> ssienr , SSI_SSIENR_SSI_EN_BITS );
140+ ssi_hw -> baudr = divisor ;
141+ hw_set_bits (& ssi_hw -> ssienr , SSI_SSIENR_SSI_EN_BITS );
142+ #endif
143+ }
144+
97145// Flash erase and write must run with interrupts disabled and the other core suspended,
98146// because the XIP bit gets disabled.
99147static uint32_t begin_critical_flash_section (void ) {
@@ -117,8 +165,9 @@ static uint32_t begin_critical_flash_section(void) {
117165}
118166
119167static void end_critical_flash_section (uint32_t state ) {
168+ // The ROM function to program flash will have reset flash and PSRAM timings to defaults
169+ rp2_flash_set_timing_internal (clock_get_hz (clk_sys ));
120170 #if MICROPY_HW_ENABLE_PSRAM
121- // The ROM function to program flash will reset PSRAM timings to defaults
122171 psram_init (MICROPY_HW_PSRAM_CS_PIN );
123172 #endif
124173 restore_interrupts (state );
@@ -313,3 +362,23 @@ mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) {
313362 }
314363}
315364#endif
365+
366+ // Modify the flash timing. Ensure flash access is suspended while
367+ // the timings are altered.
368+ void rp2_flash_set_timing_for_freq (int clock_hz ) {
369+ if (multicore_lockout_victim_is_initialized (1 - get_core_num ())) {
370+ multicore_lockout_start_blocking ();
371+ }
372+ uint32_t state = save_and_disable_interrupts ();
373+
374+ rp2_flash_set_timing_internal (clock_hz );
375+
376+ restore_interrupts (state );
377+ if (multicore_lockout_victim_is_initialized (1 - get_core_num ())) {
378+ multicore_lockout_end_blocking ();
379+ }
380+ }
381+
382+ void rp2_flash_set_timing () {
383+ rp2_flash_set_timing_for_freq (clock_get_hz (clk_sys ));
384+ }
0 commit comments