Skip to content

Commit 7686f93

Browse files
committed
Fix crash when getting board.SPI outside the VM
If one of the default pins was already in use it would crash. The internal API has been refined to allow us to get the value without causing an init of the singleton. Fixes adafruit#1753
1 parent 8b9e933 commit 7686f93

File tree

8 files changed

+48
-17
lines changed

8 files changed

+48
-17
lines changed

ports/atmel-samd/boards/hallowing_m0_express/board.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ void board_init(void) {
7272
displayio_fourwire_obj_t* bus = &displays[0].fourwire_bus;
7373
bus->base.type = &displayio_fourwire_type;
7474
common_hal_displayio_fourwire_construct(bus,
75-
board_spi(),
75+
common_hal_board_create_spi(),
7676
&pin_PA28, // Command or data
7777
&pin_PA01, // Chip select
7878
&pin_PA27); // Reset

ports/atmel-samd/common-hal/digitalio/DigitalInOut.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ digitalinout_result_t common_hal_digitalio_digitalinout_construct(
4949
return DIGITALINOUT_OK;
5050
}
5151

52+
void common_hal_digitalio_digitalinout_never_reset(
53+
digitalio_digitalinout_obj_t *self) {
54+
never_reset_pin_number(self->pin->number);
55+
}
56+
5257
bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t* self) {
5358
return self->pin == mp_const_none;
5459
}

shared-bindings/digitalio/DigitalInOut.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,6 @@ void common_hal_digitalio_digitalinout_set_drive_mode(digitalio_digitalinout_obj
5252
digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(digitalio_digitalinout_obj_t* self);
5353
void common_hal_digitalio_digitalinout_set_pull(digitalio_digitalinout_obj_t* self, digitalio_pull_t pull);
5454
digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(digitalio_digitalinout_obj_t* self);
55+
void common_hal_digitalio_digitalinout_never_reset(digitalio_digitalinout_obj_t *self);
5556

5657
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DIGITALIO_DIGITALINOUT_H

shared-module/displayio/__init__.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ void reset_displays(void) {
190190
if (((uint32_t) fourwire->bus) < ((uint32_t) &displays) ||
191191
((uint32_t) fourwire->bus) > ((uint32_t) &displays + CIRCUITPY_DISPLAY_LIMIT)) {
192192
busio_spi_obj_t* original_spi = fourwire->bus;
193-
if (original_spi == board_spi()) {
193+
if (original_spi == common_hal_board_get_spi()) {
194194
continue;
195195
}
196196
memcpy(&fourwire->inline_bus, original_spi, sizeof(busio_spi_obj_t));

supervisor/shared/board_busses.c

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,42 @@ MP_DEFINE_CONST_FUN_OBJ_0(board_i2c_obj, board_i2c);
7171
STATIC busio_spi_obj_t spi_obj;
7272
STATIC mp_obj_t spi_singleton = NULL;
7373

74-
mp_obj_t board_spi(void) {
75-
if (spi_singleton == NULL) {
76-
busio_spi_obj_t *self = &spi_obj;
77-
self->base.type = &busio_spi_type;
78-
assert_pin_free(DEFAULT_SPI_BUS_SCK);
79-
assert_pin_free(DEFAULT_SPI_BUS_MOSI);
80-
assert_pin_free(DEFAULT_SPI_BUS_MISO);
81-
const mcu_pin_obj_t* clock = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_SCK);
82-
const mcu_pin_obj_t* mosi = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_MOSI);
83-
const mcu_pin_obj_t* miso = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_MISO);
84-
common_hal_busio_spi_construct(self, clock, mosi, miso);
85-
spi_singleton = (mp_obj_t)self;
74+
// TODO(tannewt): Move this to shared-bindings/board/__init__.c and corresponding shared-module.
75+
mp_obj_t common_hal_board_get_spi(void) {
76+
return spi_singleton;
77+
}
78+
79+
mp_obj_t common_hal_board_create_spi(void) {
80+
if (spi_singleton != NULL) {
81+
return spi_singleton;
82+
}
83+
busio_spi_obj_t *self = &spi_obj;
84+
self->base.type = &busio_spi_type;
85+
if (!common_hal_mcu_pin_is_free(DEFAULT_SPI_BUS_SCK) ||
86+
!common_hal_mcu_pin_is_free(DEFAULT_SPI_BUS_MOSI) ||
87+
!common_hal_mcu_pin_is_free(DEFAULT_SPI_BUS_MISO)) {
88+
return NULL;
8689
}
90+
const mcu_pin_obj_t* clock = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_SCK);
91+
const mcu_pin_obj_t* mosi = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_MOSI);
92+
const mcu_pin_obj_t* miso = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_MISO);
93+
common_hal_busio_spi_construct(self, clock, mosi, miso);
94+
spi_singleton = (mp_obj_t)self;
8795
return spi_singleton;
8896
}
89-
#else
97+
9098
mp_obj_t board_spi(void) {
99+
mp_obj_t singleton = common_hal_board_get_spi();
100+
if (singleton != NULL) {
101+
return singleton;
102+
}
103+
assert_pin_free(DEFAULT_SPI_BUS_SCK);
104+
assert_pin_free(DEFAULT_SPI_BUS_MOSI);
105+
assert_pin_free(DEFAULT_SPI_BUS_MISO);
106+
return common_hal_board_create_spi();
107+
}
108+
#else
109+
mp_obj_t common_hal_board_spi(void) {
91110
mp_raise_NotImplementedError(translate("No default SPI bus"));
92111
return NULL;
93112
}

supervisor/shared/board_busses.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929

3030
#include "py/obj.h"
3131

32-
mp_obj_t board_i2c(void);
32+
mp_obj_t common_hal_board_get_spi(void);
33+
mp_obj_t common_hal_board_create_spi(void);
3334
MP_DECLARE_CONST_FUN_OBJ_0(board_i2c_obj);
3435

3536
mp_obj_t board_spi(void);

supervisor/shared/external_flash/spi_flash.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,15 @@ bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length)
132132
}
133133

134134
void spi_flash_init(void) {
135+
cs_pin.base.type = &digitalio_digitalinout_type;
135136
common_hal_digitalio_digitalinout_construct(&cs_pin, SPI_FLASH_CS_PIN);
136137

138+
137139
// Set CS high (disabled).
138140
common_hal_digitalio_digitalinout_switch_to_output(&cs_pin, true, DRIVE_MODE_PUSH_PULL);
141+
common_hal_digitalio_digitalinout_never_reset(&cs_pin);
139142

143+
spi.base.type = &busio_spi_type;
140144
common_hal_busio_spi_construct(&spi, SPI_FLASH_SCK_PIN, SPI_FLASH_MOSI_PIN, SPI_FLASH_MISO_PIN);
141145
common_hal_busio_spi_never_reset(&spi);
142146
}

supervisor/shared/safe_mode.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ safe_mode_t wait_for_safe_mode_reset(void) {
7777
return NO_SAFE_MODE;
7878
}
7979

80-
void reset_into_safe_mode(safe_mode_t reason) {
80+
// Inline this so it's easy to break on it from GDB.
81+
void __attribute__((noinline,)) reset_into_safe_mode(safe_mode_t reason) {
8182
if (current_safe_mode > BROWNOUT && reason > BROWNOUT) {
8283
while (true) {
8384
// This very bad because it means running in safe mode didn't save us. Only ignore brownout

0 commit comments

Comments
 (0)