Skip to content

Commit 803be58

Browse files
authored
Merge pull request #10699 from dhalbert/spi-sd-race-fixes
finalisers for SPI; clean up sdcardio; reset all pins after finalisers; avoid USB SD races
2 parents 3c34a5d + 2800777 commit 803be58

File tree

40 files changed

+227
-212
lines changed

40 files changed

+227
-212
lines changed

main.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "supervisor/shared/external_flash/external_flash.h"
4444

4545
#include "shared-bindings/microcontroller/__init__.h"
46+
#include "shared-bindings/microcontroller/Pin.h"
4647
#include "shared-bindings/microcontroller/Processor.h"
4748
#include "shared-bindings/supervisor/__init__.h"
4849
#include "shared-bindings/supervisor/Runtime.h"
@@ -124,6 +125,7 @@ static void reset_devices(void) {
124125

125126
static uint8_t *_heap;
126127
static uint8_t *_pystack;
128+
static volatile bool _vm_is_running = false;
127129

128130
static const char line_clear[] = "\x1b[2K\x1b[0G";
129131

@@ -207,9 +209,12 @@ static void start_mp(safe_mode_t safe_mode) {
207209

208210
// Always return to root
209211
common_hal_os_chdir("/");
212+
213+
_vm_is_running = true;
210214
}
211215

212216
static void stop_mp(void) {
217+
_vm_is_running = false;
213218
#if MICROPY_VFS
214219

215220
// Unmount all heap allocated vfs mounts.
@@ -409,8 +414,13 @@ static void cleanup_after_vm(mp_obj_t exception) {
409414

410415
// Free the heap last because other modules may reference heap memory and need to shut down.
411416
filesystem_flush();
417+
418+
// Runs finalisers while shutting down the heap.
412419
stop_mp();
413420

421+
// Don't reset pins until finalisers have run.
422+
reset_all_pins();
423+
414424
// Let the workflows know we've reset in case they want to restart.
415425
supervisor_workflow_reset();
416426
}
@@ -513,6 +523,7 @@ static bool __attribute__((noinline)) run_code_py(safe_mode_t safe_mode, bool *s
513523

514524

515525
// Finished executing python code. Cleanup includes filesystem flush and a board reset.
526+
_vm_is_running = false;
516527
cleanup_after_vm(_exec_result.exception);
517528
_exec_result.exception = NULL;
518529

@@ -1201,6 +1212,10 @@ void NORETURN nlr_jump_fail(void *val) {
12011212
}
12021213
}
12031214

1215+
bool vm_is_running(void) {
1216+
return _vm_is_running;
1217+
}
1218+
12041219
#ifndef NDEBUG
12051220
static void NORETURN __fatal_error(const char *msg) {
12061221
#if CIRCUITPY_DEBUG == 0

ports/analog/common-hal/busio/SPI.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
typedef enum {
4343
SPI_FREE = 0,
4444
SPI_BUSY,
45-
SPI_NEVER_RESET,
4645
} spi_status_t;
4746

4847
// Set each bit to indicate an active SPI
@@ -61,6 +60,9 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
6160
// Check for NULL Pointer
6261
assert(self);
6362

63+
// Ensure the object starts in its deinit state.
64+
common_hal_busio_spi_mark_deinit(self);
65+
6466
// Assign SPI ID based on pins
6567
int spi_id = pinsToSpi(mosi, miso, sck);
6668
if (spi_id == -1) {
@@ -118,15 +120,17 @@ void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) {
118120
common_hal_never_reset_pin(self->miso);
119121
common_hal_never_reset_pin(self->sck);
120122
common_hal_never_reset_pin(self->nss);
121-
122-
spi_status[self->spi_id] = SPI_NEVER_RESET;
123123
}
124124

125125
// Check SPI status, deinited or not
126126
bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
127127
return self->sck == NULL;
128128
}
129129

130+
void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) {
131+
self->sck = NULL;
132+
}
133+
130134
// Deinit SPI obj
131135
void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
132136

@@ -138,8 +142,9 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
138142

139143
self->mosi = NULL;
140144
self->miso = NULL;
141-
self->sck = NULL;
142145
self->nss = NULL;
146+
147+
common_hal_busio_spi_mark_deinit(self);
143148
}
144149

145150
// Configures the SPI bus. The SPI object must be locked.

ports/analog/supervisor/port.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@ void reset_cpu(void) {
166166

167167
// Reset MCU state
168168
void reset_port(void) {
169-
reset_all_pins();
170169
}
171170

172171
// Reset to the bootloader

ports/atmel-samd/common-hal/busio/SPI.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
5353
}
5454

5555
// Ensure the object starts in its deinit state.
56-
self->clock_pin = NO_PIN;
56+
common_hal_busio_spi_mark_deinit(self);
5757

5858
// Special case for SAMR21 boards. (feather_radiofruit_zigbee)
5959
#if defined(PIN_PC19F_SERCOM4_PAD0)
@@ -184,18 +184,24 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
184184
return self->clock_pin == NO_PIN;
185185
}
186186

187+
void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) {
188+
self->clock_pin = NO_PIN;
189+
}
190+
187191
void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
188192
if (common_hal_busio_spi_deinited(self)) {
189193
return;
190194
}
191195
allow_reset_sercom(self->spi_desc.dev.prvt);
192196

197+
// Mark as deinit early in case we are used in an interrupt.
198+
common_hal_busio_spi_mark_deinit(self);
199+
193200
spi_m_sync_disable(&self->spi_desc);
194201
spi_m_sync_deinit(&self->spi_desc);
195202
reset_pin_number(self->clock_pin);
196203
reset_pin_number(self->MOSI_pin);
197204
reset_pin_number(self->MISO_pin);
198-
self->clock_pin = NO_PIN;
199205
}
200206

201207
bool common_hal_busio_spi_configure(busio_spi_obj_t *self,

ports/atmel-samd/supervisor/port.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,6 @@ void reset_port(void) {
411411
reset_ticks();
412412
}
413413

414-
reset_all_pins();
415-
416414
// Output clocks for debugging.
417415
// not supported by SAMD51G; uncomment for SAMD51J or update for 51G
418416
// #ifdef SAM_D5X_E5X

ports/broadcom/common-hal/busio/SPI.c

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -30,31 +30,8 @@ static SPI0_Type *spi[NUM_SPI] = {SPI0, NULL, NULL};
3030
static SPI1_Type *aux_spi[NUM_SPI] = {NULL, SPI1, SPI2};
3131
#endif
3232

33-
static bool never_reset_spi[NUM_SPI];
3433
static bool spi_in_use[NUM_SPI];
3534

36-
void reset_spi(void) {
37-
for (size_t i = 0; i < NUM_SPI; i++) {
38-
if (never_reset_spi[i]) {
39-
continue;
40-
}
41-
42-
if (i == 1 || i == 2) {
43-
if (i == 1) {
44-
AUX->ENABLES_b.SPI_1 = false;
45-
} else {
46-
AUX->ENABLES_b.SPI_2 = false;
47-
}
48-
aux_spi[i]->CNTL0 = 0;
49-
} else {
50-
// Set CS back to default. All 0 except read enable.
51-
spi[i]->CS = SPI0_CS_REN_Msk;
52-
}
53-
54-
spi_in_use[i] = false;
55-
}
56-
}
57-
5835
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
5936
const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi,
6037
const mcu_pin_obj_t *miso, bool half_duplex) {
@@ -67,6 +44,9 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
6744
mp_raise_NotImplementedError(MP_ERROR_TEXT("Half duplex SPI is not implemented"));
6845
}
6946

47+
// Ensure the object starts in its deinit state.
48+
common_hal_busio_spi_mark_deinit(self);
49+
7050
// BCM_VERSION != 2711 have 3 SPI but as listed in peripherals/gen/pins.c two are on
7151
// index 0, once one index 0 SPI is found the other will throw an invalid_pins error.
7252
for (size_t i = 0; i < NUM_SPI; i++) {
@@ -118,8 +98,6 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
11898
}
11999

120100
void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) {
121-
never_reset_spi[self->index] = true;
122-
123101
common_hal_never_reset_pin(self->clock);
124102
common_hal_never_reset_pin(self->MOSI);
125103
common_hal_never_reset_pin(self->MISO);
@@ -129,16 +107,19 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
129107
return self->clock == NULL;
130108
}
131109

110+
void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) {
111+
self->clock = NULL;
112+
}
113+
132114
void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
133115
if (common_hal_busio_spi_deinited(self)) {
134116
return;
135117
}
136-
never_reset_spi[self->index] = false;
137118

138119
common_hal_reset_pin(self->clock);
139120
common_hal_reset_pin(self->MOSI);
140121
common_hal_reset_pin(self->MISO);
141-
self->clock = NULL;
122+
142123
spi_in_use[self->index] = false;
143124

144125
if (self->index == 1 ||
@@ -149,7 +130,12 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
149130
} else if (self->index == 2) {
150131
AUX->ENABLES_b.SPI_2 = false;
151132
}
133+
} else {
134+
// Set CS back to default. All 0 except read enable.
135+
spi[self->index]->CS = SPI0_CS_REN_Msk;
152136
}
137+
138+
common_hal_busio_spi_mark_deinit(self);
153139
}
154140

155141
bool common_hal_busio_spi_configure(busio_spi_obj_t *self,

ports/broadcom/common-hal/busio/SPI.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,3 @@ typedef struct {
2323
uint8_t bits;
2424
uint8_t index;
2525
} busio_spi_obj_t;
26-
27-
void reset_spi(void);

ports/broadcom/supervisor/port.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ safe_mode_t port_init(void) {
6767
void reset_port(void) {
6868
#if CIRCUITPY_BUSIO
6969
reset_i2c();
70-
reset_spi();
7170
reset_uart();
7271
#endif
7372

@@ -85,8 +84,6 @@ void reset_port(void) {
8584
#if CIRCUITPY_AUDIOCORE
8685
audio_dma_reset();
8786
#endif
88-
89-
reset_all_pins();
9087
}
9188

9289
void reset_to_bootloader(void) {

ports/cxd56/common-hal/busio/SPI.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
5454
return;
5555
}
5656

57-
self->spi_dev = NULL;
57+
common_hal_busio_spi_mark_deinit(self);
5858

5959
reset_pin_number(self->clock_pin->number);
6060
reset_pin_number(self->mosi_pin->number);
@@ -65,6 +65,10 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
6565
return self->spi_dev == NULL;
6666
}
6767

68+
void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) {
69+
self->spi_dev = NULL;
70+
}
71+
6872
bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) {
6973
uint8_t mode;
7074

ports/cxd56/supervisor/port.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ void reset_port(void) {
6666
#if CIRCUITPY_RTC
6767
rtc_reset();
6868
#endif
69-
70-
reset_all_pins();
7169
}
7270

7371
void reset_to_bootloader(void) {

0 commit comments

Comments
 (0)