Skip to content

Commit d708bdf

Browse files
committed
finalisers for SPI; clean up sdcardio; reset all pins after finalisers; avoid USB SD races
1 parent 3c34a5d commit d708bdf

File tree

40 files changed

+228
-185
lines changed

40 files changed

+228
-185
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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
6161
// Check for NULL Pointer
6262
assert(self);
6363

64+
// Ensure the object starts in its deinit state.
65+
common_hal_busio_spi_mark_deinit(self);
66+
6467
// Assign SPI ID based on pins
6568
int spi_id = pinsToSpi(mosi, miso, sck);
6669
if (spi_id == -1) {
@@ -127,6 +130,10 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
127130
return self->sck == NULL;
128131
}
129132

133+
void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) {
134+
self->sck = NULL;
135+
}
136+
130137
// Deinit SPI obj
131138
void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
132139

@@ -138,8 +145,9 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
138145

139146
self->mosi = NULL;
140147
self->miso = NULL;
141-
self->sck = NULL;
142148
self->nss = NULL;
149+
150+
common_hal_busio_spi_mark_deinit(self);
143151
}
144152

145153
// 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 & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,6 @@ static SPI1_Type *aux_spi[NUM_SPI] = {NULL, SPI1, SPI2};
3333
static bool never_reset_spi[NUM_SPI];
3434
static bool spi_in_use[NUM_SPI];
3535

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-
5836
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
5937
const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi,
6038
const mcu_pin_obj_t *miso, bool half_duplex) {
@@ -67,6 +45,9 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
6745
mp_raise_NotImplementedError(MP_ERROR_TEXT("Half duplex SPI is not implemented"));
6846
}
6947

48+
// Ensure the object starts in its deinit state.
49+
common_hal_busio_spi_mark_deinit(self);
50+
7051
// BCM_VERSION != 2711 have 3 SPI but as listed in peripherals/gen/pins.c two are on
7152
// index 0, once one index 0 SPI is found the other will throw an invalid_pins error.
7253
for (size_t i = 0; i < NUM_SPI; i++) {
@@ -129,6 +110,10 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
129110
return self->clock == NULL;
130111
}
131112

113+
void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) {
114+
self->clock = NULL;
115+
}
116+
132117
void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
133118
if (common_hal_busio_spi_deinited(self)) {
134119
return;
@@ -138,7 +123,7 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
138123
common_hal_reset_pin(self->clock);
139124
common_hal_reset_pin(self->MOSI);
140125
common_hal_reset_pin(self->MISO);
141-
self->clock = NULL;
126+
142127
spi_in_use[self->index] = false;
143128

144129
if (self->index == 1 ||
@@ -149,7 +134,12 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
149134
} else if (self->index == 2) {
150135
AUX->ENABLES_b.SPI_2 = false;
151136
}
137+
} else {
138+
// Set CS back to default. All 0 except read enable.
139+
spi[i]->CS = SPI0_CS_REN_Msk;
152140
}
141+
142+
common_hal_busio_spi_mark_deinit(self);
153143
}
154144

155145
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)