summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrobert-hh <robert@hammelrath.com>2022-10-13 19:04:37 +0200
committerDamien George <damien@micropython.org>2022-10-25 23:48:37 +1100
commita1eebc507eda8f5ec052d0ef0450c52f2320e106 (patch)
treef71dc0b99ad95602fadbb2816b1cd074f4032227
parentd74215a3137da5e9001aed92c8c1b06d828ff9d2 (diff)
samd/machine_spi: Register SerCom objects as root pointers.
Protect SerCom (UART, SPI, I2C) objects from getting freed by the GC when they go out of scope without being deinitialized. Otherwise the ISR of a Sercom may access an invalid data structure.
-rw-r--r--ports/samd/machine_i2c.c5
-rw-r--r--ports/samd/machine_spi.c10
-rw-r--r--ports/samd/machine_uart.c7
3 files changed, 10 insertions, 12 deletions
diff --git a/ports/samd/machine_i2c.c b/ports/samd/machine_i2c.c
index 0a8f5b94d..d943b6b2f 100644
--- a/ports/samd/machine_i2c.c
+++ b/ports/samd/machine_i2c.c
@@ -69,7 +69,6 @@ typedef struct _machine_i2c_obj_t {
} machine_i2c_obj_t;
extern Sercom *sercom_instance[];
-extern void *sercom_table[SERCOM_INST_NUM];
STATIC void i2c_send_command(Sercom *i2c, uint8_t command) {
i2c->I2CM.CTRLB.bit.CMD = command;
@@ -79,7 +78,7 @@ STATIC void i2c_send_command(Sercom *i2c, uint8_t command) {
void common_i2c_irq_handler(int i2c_id) {
// handle Sercom I2C IRQ
- machine_i2c_obj_t *self = sercom_table[i2c_id];
+ machine_i2c_obj_t *self = MP_STATE_PORT(sercom_table[i2c_id]);
// Handle IRQ
if (self != NULL) {
Sercom *i2c = self->instance;
@@ -159,7 +158,7 @@ mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
if (sda_pad_config.pad_nr != 0 || scl_pad_config.pad_nr != 1) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid pin for sda or scl"));
}
- sercom_table[self->id] = self;
+ MP_STATE_PORT(sercom_table[self->id]) = self;
self->freq = args[ARG_freq].u_int;
// Configure the Pin mux.
diff --git a/ports/samd/machine_spi.c b/ports/samd/machine_spi.c
index d4c7a05bb..4ffc7095c 100644
--- a/ports/samd/machine_spi.c
+++ b/ports/samd/machine_spi.c
@@ -57,11 +57,11 @@ typedef struct _machine_spi_obj_t {
} machine_spi_obj_t;
extern Sercom *sercom_instance[];
-void *sercom_table[SERCOM_INST_NUM] = {};
+MP_REGISTER_ROOT_POINTER(void *sercom_table[SERCOM_INST_NUM]);
void common_spi_irq_handler(int spi_id) {
// handle Sercom IRQ RXC
- machine_spi_obj_t *self = sercom_table[spi_id];
+ machine_spi_obj_t *self = MP_STATE_PORT(sercom_table[spi_id]);
// Handle IRQ
if (self != NULL) {
Sercom *spi = sercom_instance[self->id];
@@ -246,7 +246,7 @@ STATIC mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, s
self->sck = 0xff;
self->new = true;
- sercom_table[spi_id] = self;
+ MP_STATE_PORT(sercom_table[spi_id]) = self;
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
@@ -261,7 +261,7 @@ STATIC void machine_sercom_deinit(mp_obj_base_t *self_in) {
spi->SPI.INTENCLR.reg = 0xff;
sercom_enable(spi, 0);
// clear table entry of spi
- sercom_table[self->id] = NULL;
+ MP_STATE_PORT(sercom_table[self->id]) = NULL;
}
void sercom_deinit_all(void) {
@@ -270,7 +270,7 @@ void sercom_deinit_all(void) {
spi->SPI.INTENCLR.reg = 0xff;
sercom_register_irq(i, NULL);
sercom_enable(spi, 0);
- sercom_table[i] = NULL;
+ MP_STATE_PORT(sercom_table[i]) = NULL;
}
}
diff --git a/ports/samd/machine_uart.c b/ports/samd/machine_uart.c
index 2526b4509..4b8fa3b60 100644
--- a/ports/samd/machine_uart.c
+++ b/ports/samd/machine_uart.c
@@ -59,7 +59,6 @@ typedef struct _machine_uart_obj_t {
} machine_uart_obj_t;
Sercom *sercom_instance[] = SERCOM_INSTS;
-extern void *sercom_table[SERCOM_INST_NUM];
STATIC const char *_parity_name[] = {"None", "", "0", "1"}; // Is defined as 0, 2, 3
@@ -82,7 +81,7 @@ STATIC void uart_drain_rx_fifo(machine_uart_obj_t *self, Sercom *uart) {
}
void common_uart_irq_handler(int uart_id) {
- machine_uart_obj_t *self = sercom_table[uart_id];
+ machine_uart_obj_t *self = MP_STATE_PORT(sercom_table[uart_id]);
// Handle IRQ
if (self != NULL) {
Sercom *uart = sercom_instance[self->id];
@@ -333,7 +332,7 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args,
self->tx = 0xff;
self->rx = 0xff;
self->new = true;
- sercom_table[uart_id] = self;
+ MP_STATE_PORT(sercom_table[uart_id]) = self;
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
@@ -352,7 +351,7 @@ STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) {
// Disable interrupts
uart->USART.INTENCLR.reg = 0xff;
// clear table entry of uart
- sercom_table[self->id] = NULL;
+ MP_STATE_PORT(sercom_table[self->id]) = NULL;
MP_STATE_PORT(samd_uart_rx_buffer[self->id]) = NULL;
#if MICROPY_HW_UART_TXBUF
MP_STATE_PORT(samd_uart_tx_buffer[self->id]) = NULL;