@@ -70,6 +70,22 @@ bi_decl(bi_block_device(
7070 BINARY_INFO_BLOCK_DEV_FLAG_WRITE |
7171 BINARY_INFO_BLOCK_DEV_FLAG_PT_UNKNOWN ));
7272
73+ // Flash erase and write must run with interrupts disabled and the other core suspended,
74+ // because the XIP bit gets disabled.
75+ static uint32_t begin_critical_flash_section (void ) {
76+ if (multicore_lockout_victim_is_initialized (1 - get_core_num ())) {
77+ multicore_lockout_start_blocking ();
78+ }
79+ return save_and_disable_interrupts ();
80+ }
81+
82+ static void end_critical_flash_section (uint32_t state ) {
83+ restore_interrupts (state );
84+ if (multicore_lockout_victim_is_initialized (1 - get_core_num ())) {
85+ multicore_lockout_end_blocking ();
86+ }
87+ }
88+
7389STATIC mp_obj_t rp2_flash_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * all_args ) {
7490 // Parse arguments
7591 enum { ARG_start , ARG_len };
@@ -135,19 +151,17 @@ STATIC mp_obj_t rp2_flash_writeblocks(size_t n_args, const mp_obj_t *args) {
135151 mp_buffer_info_t bufinfo ;
136152 mp_get_buffer_raise (args [2 ], & bufinfo , MP_BUFFER_READ );
137153 if (n_args == 3 ) {
138- // Flash erase/program must run in an atomic section because the XIP bit gets disabled.
139- mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION ();
154+ mp_uint_t atomic_state = begin_critical_flash_section ();
140155 flash_range_erase (self -> flash_base + offset , bufinfo .len );
141- MICROPY_END_ATOMIC_SECTION (atomic_state );
156+ end_critical_flash_section (atomic_state );
142157 mp_event_handle_nowait ();
143158 // TODO check return value
144159 } else {
145160 offset += mp_obj_get_int (args [3 ]);
146161 }
147- // Flash erase/program must run in an atomic section because the XIP bit gets disabled.
148- mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION ();
162+ mp_uint_t atomic_state = begin_critical_flash_section ();
149163 flash_range_program (self -> flash_base + offset , bufinfo .buf , bufinfo .len );
150- MICROPY_END_ATOMIC_SECTION (atomic_state );
164+ end_critical_flash_section (atomic_state );
151165 mp_event_handle_nowait ();
152166 // TODO check return value
153167 return mp_const_none ;
@@ -170,10 +184,9 @@ STATIC mp_obj_t rp2_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_
170184 return MP_OBJ_NEW_SMALL_INT (BLOCK_SIZE_BYTES );
171185 case MP_BLOCKDEV_IOCTL_BLOCK_ERASE : {
172186 uint32_t offset = mp_obj_get_int (arg_in ) * BLOCK_SIZE_BYTES ;
173- // Flash erase/program must run in an atomic section because the XIP bit gets disabled.
174- mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION ();
187+ mp_uint_t atomic_state = begin_critical_flash_section ();
175188 flash_range_erase (self -> flash_base + offset , BLOCK_SIZE_BYTES );
176- MICROPY_END_ATOMIC_SECTION (atomic_state );
189+ end_critical_flash_section (atomic_state );
177190 // TODO check return value
178191 return MP_OBJ_NEW_SMALL_INT (0 );
179192 }
0 commit comments