14
14
#include "hardware/structs/qmi.h"
15
15
#include "hardware/regs/otp_data.h"
16
16
#endif
17
+ #include "hardware/structs/pads_qspi.h"
17
18
#include "hardware/xip_cache.h"
18
19
19
20
#define FLASH_BLOCK_ERASE_CMD 0xd8
@@ -71,7 +72,23 @@ static void __no_inline_not_in_flash_func(flash_enable_xip_via_boot2)(void) {
71
72
72
73
#endif
73
74
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
75
92
// This is specifically for saving/restoring the registers modified by RP2350
76
93
// flash_exit_xip() ROM func, not the entirety of the QMI window state.
77
94
typedef 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
108
125
}
109
126
#endif
110
127
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
+
111
157
//-----------------------------------------------------------------------------
112
158
// Actual flash programming shims (work whether or not PICO_NO_FLASH==1)
113
159
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
+
114
191
void __no_inline_not_in_flash_func (flash_range_erase )(uint32_t flash_offs , size_t count ) {
115
192
#ifdef PICO_FLASH_SIZE_BYTES
116
193
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_
123
200
rom_flash_flush_cache_fn flash_flush_cache_func = (rom_flash_flush_cache_fn )rom_func_lookup_inline (ROM_FUNC_FLASH_FLUSH_CACHE );
124
201
assert (connect_internal_flash_func && flash_exit_xip_func && flash_range_erase_func && flash_flush_cache_func );
125
202
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 );
132
205
133
206
// No flash accesses after this point
134
207
__compiler_memory_barrier ();
@@ -138,9 +211,7 @@ void __no_inline_not_in_flash_func(flash_range_erase)(uint32_t flash_offs, size_
138
211
flash_range_erase_func (flash_offs , count , FLASH_BLOCK_SIZE , FLASH_BLOCK_ERASE_CMD );
139
212
flash_flush_cache_func (); // Note this is needed to remove CSn IO force as well as cache flushing
140
213
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 );
144
215
}
145
216
146
217
void __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
160
231
rom_flash_flush_cache_fn flash_flush_cache_func = (rom_flash_flush_cache_fn )rom_func_lookup_inline (ROM_FUNC_FLASH_FLUSH_CACHE );
161
232
assert (connect_internal_flash_func && flash_exit_xip_func && flash_range_program_func && flash_flush_cache_func );
162
233
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 );
168
236
169
237
__compiler_memory_barrier ();
170
238
@@ -173,9 +241,8 @@ void __no_inline_not_in_flash_func(flash_range_program)(uint32_t flash_offs, con
173
241
flash_range_program_func (flash_offs , data , count );
174
242
flash_flush_cache_func (); // Note this is needed to remove CSn IO force as well as cache flushing
175
243
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 );
179
246
}
180
247
181
248
//-----------------------------------------------------------------------------
@@ -208,11 +275,8 @@ void __no_inline_not_in_flash_func(flash_do_cmd)(const uint8_t *txbuf, uint8_t *
208
275
rom_flash_flush_cache_fn flash_flush_cache_func = (rom_flash_flush_cache_fn )rom_func_lookup_inline (ROM_FUNC_FLASH_FLUSH_CACHE );
209
276
assert (connect_internal_flash_func && flash_exit_xip_func && flash_flush_cache_func );
210
277
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 );
216
280
217
281
__compiler_memory_barrier ();
218
282
connect_internal_flash_func ();
@@ -260,9 +324,7 @@ void __no_inline_not_in_flash_func(flash_do_cmd)(const uint8_t *txbuf, uint8_t *
260
324
261
325
flash_flush_cache_func ();
262
326
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 );
266
328
}
267
329
#endif
268
330
0 commit comments