1414#include "hardware/structs/qmi.h"
1515#include "hardware/regs/otp_data.h"
1616#endif
17+ #include "hardware/structs/pads_qspi.h"
1718#include "hardware/xip_cache.h"
1819
1920#define FLASH_BLOCK_ERASE_CMD 0xd8
@@ -71,7 +72,23 @@ static void __no_inline_not_in_flash_func(flash_enable_xip_via_boot2)(void) {
7172
7273#endif
7374
74- #if PICO_RP2350
75+ //-----------------------------------------------------------------------------
76+ // State save/restore
77+
78+ // Most functions save and restore the QSPI pad state over the call. (The main
79+ // exception is flash_start_xip() which is explicitly intended to initialise
80+ // them). The expectation is that by the time you do any flash operations,
81+ // you have either gone through a normal flash boot process or (in the case
82+ // of PICO_NO_FLASH=1) you have called flash_start_xip(). Any further
83+ // modifications to the pad state are therefore deliberate changes that we
84+ // should preserve.
85+ //
86+ // Additionally, on RP2350, we save and restore the window 1 QMI configuration
87+ // if the user has not opted into bootrom CS1 support via FLASH_DEVINFO OTP
88+ // flags. This avoids clobbering CS1 setup (e.g. PSRAM) performed by the
89+ // application.
90+
91+ #if !PICO_RP2040
7592// This is specifically for saving/restoring the registers modified by RP2350
7693// flash_exit_xip() ROM func, not the entirety of the QMI window state.
7794typedef struct flash_rp2350_qmi_save_state {
@@ -108,9 +125,69 @@ static void __no_inline_not_in_flash_func(flash_rp2350_restore_qmi_cs1)(const fl
108125}
109126#endif
110127
128+
129+ typedef struct flash_hardware_save_state {
130+ #if !PICO_RP2040
131+ flash_rp2350_qmi_save_state_t qmi_save ;
132+ #endif
133+ uint32_t qspi_pads [count_of (pads_qspi_hw -> io )];
134+ } flash_hardware_save_state_t ;
135+
136+ static void __no_inline_not_in_flash_func (flash_save_hardware_state )(flash_hardware_save_state_t * state ) {
137+ // Commit any pending writes to external RAM, to avoid losing them in a subsequent flush:
138+ xip_cache_clean_all ();
139+ for (size_t i = 0 ; i < count_of (pads_qspi_hw -> io ); ++ i ) {
140+ state -> qspi_pads [i ] = pads_qspi_hw -> io [i ];
141+ }
142+ #if !PICO_RP2040
143+ flash_rp2350_save_qmi_cs1 (& state -> qmi_save );
144+ #endif
145+ }
146+
147+ static void __no_inline_not_in_flash_func (flash_restore_hardware_state )(flash_hardware_save_state_t * state ) {
148+ for (size_t i = 0 ; i < count_of (pads_qspi_hw -> io ); ++ i ) {
149+ pads_qspi_hw -> io [i ] = state -> qspi_pads [i ];
150+ }
151+ #if !PICO_RP2040
152+ // Tail call!
153+ flash_rp2350_restore_qmi_cs1 (& state -> qmi_save );
154+ #endif
155+ }
156+
111157//-----------------------------------------------------------------------------
112158// Actual flash programming shims (work whether or not PICO_NO_FLASH==1)
113159
160+ void __no_inline_not_in_flash_func (flash_start_xip )(void ) {
161+ rom_connect_internal_flash_fn connect_internal_flash_func = (rom_connect_internal_flash_fn )rom_func_lookup_inline (ROM_FUNC_CONNECT_INTERNAL_FLASH );
162+ rom_flash_exit_xip_fn flash_exit_xip_func = (rom_flash_exit_xip_fn )rom_func_lookup_inline (ROM_FUNC_FLASH_EXIT_XIP );
163+ rom_flash_flush_cache_fn flash_flush_cache_func = (rom_flash_flush_cache_fn )rom_func_lookup_inline (ROM_FUNC_FLASH_FLUSH_CACHE );
164+ rom_flash_enter_cmd_xip_fn flash_enter_cmd_xip_func = (rom_flash_enter_cmd_xip_fn )rom_func_lookup_inline (ROM_FUNC_FLASH_ENTER_CMD_XIP );
165+ assert (connect_internal_flash_func && flash_exit_xip_func && flash_flush_cache_func && flash_enter_cmd_xip_func );
166+ // Commit any pending writes to external RAM, to avoid losing them in the subsequent flush:
167+ xip_cache_clean_all ();
168+ #if !PICO_RP2040
169+ flash_rp2350_qmi_save_state_t qmi_save ;
170+ flash_rp2350_save_qmi_cs1 (& qmi_save );
171+ #endif
172+
173+ // Use ROM calls to get from ~any state to a state where low-speed flash access works:
174+ connect_internal_flash_func ();
175+ flash_exit_xip_func ();
176+ flash_flush_cache_func ();
177+ flash_enter_cmd_xip_func ();
178+
179+ // If a boot2 is available then call it now. Slight limitation here is that if this is a
180+ // NO_FLASH binary which was loaded via bootrom LOAD_MAP, we should actually have a better
181+ // flash setup than this available via xip setup func stub left in boot RAM, but we can't
182+ // easily detect this case to take advantage of this.
183+ flash_init_boot2_copyout ();
184+ flash_enable_xip_via_boot2 ();
185+
186+ #if !PICO_RP2040
187+ flash_rp2350_restore_qmi_cs1 (& qmi_save );
188+ #endif
189+ }
190+
114191void __no_inline_not_in_flash_func (flash_range_erase )(uint32_t flash_offs , size_t count ) {
115192#ifdef PICO_FLASH_SIZE_BYTES
116193 hard_assert (flash_offs + count <= PICO_FLASH_SIZE_BYTES );
@@ -123,12 +200,8 @@ void __no_inline_not_in_flash_func(flash_range_erase)(uint32_t flash_offs, size_
123200 rom_flash_flush_cache_fn flash_flush_cache_func = (rom_flash_flush_cache_fn )rom_func_lookup_inline (ROM_FUNC_FLASH_FLUSH_CACHE );
124201 assert (connect_internal_flash_func && flash_exit_xip_func && flash_range_erase_func && flash_flush_cache_func );
125202 flash_init_boot2_copyout ();
126- // Commit any pending writes to external RAM, to avoid losing them in the subsequent flush:
127- xip_cache_clean_all ();
128- #if PICO_RP2350
129- flash_rp2350_qmi_save_state_t qmi_save ;
130- flash_rp2350_save_qmi_cs1 (& qmi_save );
131- #endif
203+ flash_hardware_save_state_t state ;
204+ flash_save_hardware_state (& state );
132205
133206 // No flash accesses after this point
134207 __compiler_memory_barrier ();
@@ -138,9 +211,7 @@ void __no_inline_not_in_flash_func(flash_range_erase)(uint32_t flash_offs, size_
138211 flash_range_erase_func (flash_offs , count , FLASH_BLOCK_SIZE , FLASH_BLOCK_ERASE_CMD );
139212 flash_flush_cache_func (); // Note this is needed to remove CSn IO force as well as cache flushing
140213 flash_enable_xip_via_boot2 ();
141- #if PICO_RP2350
142- flash_rp2350_restore_qmi_cs1 (& qmi_save );
143- #endif
214+ flash_restore_hardware_state (& state );
144215}
145216
146217void __no_inline_not_in_flash_func (flash_flush_cache )(void ) {
@@ -160,11 +231,8 @@ void __no_inline_not_in_flash_func(flash_range_program)(uint32_t flash_offs, con
160231 rom_flash_flush_cache_fn flash_flush_cache_func = (rom_flash_flush_cache_fn )rom_func_lookup_inline (ROM_FUNC_FLASH_FLUSH_CACHE );
161232 assert (connect_internal_flash_func && flash_exit_xip_func && flash_range_program_func && flash_flush_cache_func );
162233 flash_init_boot2_copyout ();
163- xip_cache_clean_all ();
164- #if PICO_RP2350
165- flash_rp2350_qmi_save_state_t qmi_save ;
166- flash_rp2350_save_qmi_cs1 (& qmi_save );
167- #endif
234+ flash_hardware_save_state_t state ;
235+ flash_save_hardware_state (& state );
168236
169237 __compiler_memory_barrier ();
170238
@@ -173,9 +241,8 @@ void __no_inline_not_in_flash_func(flash_range_program)(uint32_t flash_offs, con
173241 flash_range_program_func (flash_offs , data , count );
174242 flash_flush_cache_func (); // Note this is needed to remove CSn IO force as well as cache flushing
175243 flash_enable_xip_via_boot2 ();
176- #if PICO_RP2350
177- flash_rp2350_restore_qmi_cs1 (& qmi_save );
178- #endif
244+
245+ flash_restore_hardware_state (& state );
179246}
180247
181248//-----------------------------------------------------------------------------
@@ -208,11 +275,8 @@ void __no_inline_not_in_flash_func(flash_do_cmd)(const uint8_t *txbuf, uint8_t *
208275 rom_flash_flush_cache_fn flash_flush_cache_func = (rom_flash_flush_cache_fn )rom_func_lookup_inline (ROM_FUNC_FLASH_FLUSH_CACHE );
209276 assert (connect_internal_flash_func && flash_exit_xip_func && flash_flush_cache_func );
210277 flash_init_boot2_copyout ();
211- xip_cache_clean_all ();
212- #if PICO_RP2350
213- flash_rp2350_qmi_save_state_t qmi_save ;
214- flash_rp2350_save_qmi_cs1 (& qmi_save );
215- #endif
278+ flash_hardware_save_state_t state ;
279+ flash_save_hardware_state (& state );
216280
217281 __compiler_memory_barrier ();
218282 connect_internal_flash_func ();
@@ -260,9 +324,7 @@ void __no_inline_not_in_flash_func(flash_do_cmd)(const uint8_t *txbuf, uint8_t *
260324
261325 flash_flush_cache_func ();
262326 flash_enable_xip_via_boot2 ();
263- #if PICO_RP2350
264- flash_rp2350_restore_qmi_cs1 (& qmi_save );
265- #endif
327+ flash_restore_hardware_state (& state );
266328}
267329#endif
268330
0 commit comments