stm32,esp32: In machine_i2s, make object reference arrays root pointers.

This change eliminates the risk of the IRQ callback accessing invalid data.
Discussed here:
https://github.com/micropython/micropython/pull/7183#discussion_r660209875

Signed-off-by: Mike Teachman <mike.teachman@gmail.com>
This commit is contained in:
MikeTeachman 2021-11-09 20:41:34 -08:00 committed by Damien George
parent 0be3b91f11
commit 6d5296e65e
8 changed files with 32 additions and 26 deletions

View File

@ -147,11 +147,9 @@ STATIC const int8_t i2s_frame_map[NUM_I2S_USER_FORMATS][I2S_RX_FRAME_SIZE_IN_BYT
{ 4, 5, 6, 7, 0, 1, 2, 3 }, // Stereo, 32-bits
};
STATIC machine_i2s_obj_t *machine_i2s_obj[I2S_NUM_MAX];
void machine_i2s_init0() {
for (i2s_port_t p = 0; p < I2S_NUM_MAX; p++) {
machine_i2s_obj[p] = NULL;
MP_STATE_PORT(machine_i2s_obj)[p] = NULL;
}
}
@ -507,13 +505,13 @@ STATIC mp_obj_t machine_i2s_make_new(const mp_obj_type_t *type, size_t n_pos_arg
}
machine_i2s_obj_t *self;
if (machine_i2s_obj[port] == NULL) {
if (MP_STATE_PORT(machine_i2s_obj)[port] == NULL) {
self = m_new_obj(machine_i2s_obj_t);
machine_i2s_obj[port] = self;
MP_STATE_PORT(machine_i2s_obj)[port] = self;
self->base.type = &machine_i2s_type;
self->port = port;
} else {
self = machine_i2s_obj[port];
self = MP_STATE_PORT(machine_i2s_obj)[port];
machine_i2s_deinit(self);
}

View File

@ -7,6 +7,8 @@
#include <stdint.h>
#include <alloca.h>
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "driver/i2s.h"
// object representation and NLR handling
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A)
@ -249,6 +251,7 @@ struct mp_bluetooth_nimble_root_pointers_t;
const char *readline_hist[8]; \
mp_obj_t machine_pin_irq_handler[40]; \
struct _machine_timer_obj_t *machine_timer_obj_head; \
struct _machine_i2s_obj_t *machine_i2s_obj[I2S_NUM_MAX]; \
MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE
// type definitions for the specific machine

View File

@ -40,7 +40,6 @@
#define MICROPY_HW_ENABLE_SDCARD (1)
#define MICROPY_HW_ENABLE_MMCARD (1)
#define MICROPY_HW_ENABLE_RF_SWITCH (1)
#define MICROPY_HW_ENABLE_I2S (1)
#define MICROPY_BOARD_EARLY_INIT board_early_init
#define MICROPY_BOARD_ENTER_STOP board_sleep(1);

View File

@ -11,7 +11,6 @@
#define MICROPY_HW_ENABLE_DAC (1)
#define MICROPY_HW_ENABLE_USB (1)
#define MICROPY_HW_ENABLE_SDCARD (1)
#define MICROPY_HW_ENABLE_I2S (1)
// HSE is 8MHz
#define MICROPY_HW_CLK_PLLM (8)

View File

@ -11,7 +11,6 @@
#define MICROPY_HW_ENABLE_DAC (1)
#define MICROPY_HW_ENABLE_USB (1)
#define MICROPY_HW_ENABLE_SDCARD (1)
#define MICROPY_HW_ENABLE_I2S (1)
// HSE is 12MHz
#define MICROPY_HW_CLK_PLLM (12)

View File

@ -81,8 +81,6 @@
// 32 byte address boundary. Not all STM32 devices have a D-Cache. Buffer alignment
// will still happen on these devices to keep this code simple.
#define MAX_I2S_STM32 (2)
// DMA ping-pong buffer size was empirically determined. It is a tradeoff between:
// 1. memory use (smaller buffer size desirable to reduce memory footprint)
// 2. interrupt frequency (larger buffer size desirable to reduce interrupt frequency)
@ -164,11 +162,9 @@ STATIC const int8_t i2s_frame_map[NUM_I2S_USER_FORMATS][I2S_RX_FRAME_SIZE_IN_BYT
{ 2, 3, 0, 1, 6, 7, 4, 5 }, // Stereo, 32-bits
};
STATIC machine_i2s_obj_t *machine_i2s_obj[MAX_I2S_STM32];
void machine_i2s_init0() {
for (uint8_t i = 0; i < MAX_I2S_STM32; i++) {
machine_i2s_obj[i] = NULL;
for (uint8_t i = 0; i < MICROPY_HW_MAX_I2S; i++) {
MP_STATE_PORT(machine_i2s_obj)[i] = NULL;
}
}
@ -601,9 +597,9 @@ void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s) {
void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) {
machine_i2s_obj_t *self;
if (hi2s->Instance == I2S1) {
self = machine_i2s_obj[0];
self = MP_STATE_PORT(machine_i2s_obj)[0];
} else {
self = machine_i2s_obj[1];
self = MP_STATE_PORT(machine_i2s_obj)[1];
}
// bottom half of buffer now filled,
@ -620,9 +616,9 @@ void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) {
void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s) {
machine_i2s_obj_t *self;
if (hi2s->Instance == I2S1) {
self = machine_i2s_obj[0];
self = MP_STATE_PORT(machine_i2s_obj)[0];
} else {
self = machine_i2s_obj[1];
self = MP_STATE_PORT(machine_i2s_obj)[1];
}
// top half of buffer now filled,
@ -640,9 +636,9 @@ void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s) {
machine_i2s_obj_t *self;
if (hi2s->Instance == I2S1) {
self = machine_i2s_obj[0];
self = MP_STATE_PORT(machine_i2s_obj)[0];
} else {
self = machine_i2s_obj[1];
self = MP_STATE_PORT(machine_i2s_obj)[1];
}
// for non-blocking operation, this IRQ-based callback handles
@ -659,9 +655,9 @@ void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s) {
void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s) {
machine_i2s_obj_t *self;
if (hi2s->Instance == I2S1) {
self = machine_i2s_obj[0];
self = MP_STATE_PORT(machine_i2s_obj)[0];
} else {
self = machine_i2s_obj[1];
self = MP_STATE_PORT(machine_i2s_obj)[1];
}
// for non-blocking operation, this IRQ-based callback handles
@ -859,13 +855,13 @@ STATIC mp_obj_t machine_i2s_make_new(const mp_obj_type_t *type, size_t n_pos_arg
}
machine_i2s_obj_t *self;
if (machine_i2s_obj[i2s_id_zero_base] == NULL) {
if (MP_STATE_PORT(machine_i2s_obj)[i2s_id_zero_base] == NULL) {
self = m_new_obj(machine_i2s_obj_t);
machine_i2s_obj[i2s_id_zero_base] = self;
MP_STATE_PORT(machine_i2s_obj)[i2s_id_zero_base] = self;
self->base.type = &machine_i2s_type;
self->i2s_id = i2s_id;
} else {
self = machine_i2s_obj[i2s_id_zero_base];
self = MP_STATE_PORT(machine_i2s_obj)[i2s_id_zero_base];
machine_i2s_deinit(MP_OBJ_FROM_PTR(self));
}

View File

@ -490,6 +490,15 @@
#define MICROPY_HW_MAX_CAN (1)
#endif
// Enable I2S if there are any peripherals defined
#if defined(MICROPY_HW_I2S1) || defined(MICROPY_HW_I2S2)
#define MICROPY_HW_ENABLE_I2S (1)
#define MICROPY_HW_MAX_I2S (2)
#else
#define MICROPY_HW_ENABLE_I2S (0)
#define MICROPY_HW_MAX_I2S (0)
#endif
// Define MICROPY_HW_SDMMCx_CK values if that peripheral is used, so that make-pins.py
// generates the relevant AF constants.
#if MICROPY_HW_SDCARD_SDMMC == 1 || MICROPY_HW_SDIO_SDMMC == 1

View File

@ -342,6 +342,9 @@ struct _mp_bluetooth_btstack_root_pointers_t;
/* pointers to all CAN objects (if they have been created) */ \
struct _pyb_can_obj_t *pyb_can_obj_all[MICROPY_HW_MAX_CAN]; \
\
/* pointers to all I2S objects (if they have been created) */ \
struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_MAX_I2S]; \
\
/* USB_VCP IRQ callbacks (if they have been set) */ \
mp_obj_t pyb_usb_vcp_irq[MICROPY_HW_USB_CDC_NUM]; \
\