Skip to content

Commit 4b4f601

Browse files
committed
rp2/rp2_flash: Lockout second core only when doing flash erase/write.
Using the multicore lockout feature in the general atomic section makes it much more difficult to get correct. Signed-off-by: Damien George <damien@micropython.org>
1 parent 9feb068 commit 4b4f601

File tree

2 files changed

+22
-13
lines changed

2 files changed

+22
-13
lines changed

ports/rp2/mpthreadport.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ uint32_t mp_thread_begin_atomic_section(void) {
5252
// When both cores are executing, we also need to provide
5353
// full mutual exclusion.
5454
mp_thread_mutex_lock(&atomic_mutex, 1);
55-
// In case this atomic section is for flash access, then
56-
// suspend the other core.
57-
multicore_lockout_start_blocking();
5855
}
5956

6057
return save_and_disable_interrupts();
@@ -64,7 +61,6 @@ void mp_thread_end_atomic_section(uint32_t state) {
6461
restore_interrupts(state);
6562

6663
if (core1_entry) {
67-
multicore_lockout_end_blocking();
6864
mp_thread_mutex_unlock(&atomic_mutex);
6965
}
7066
}

ports/rp2/rp2_flash.c

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
7389
STATIC 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

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy