Merge pull request #5422 from Neradoc/nera-secondary-I2C

Allow multiple board buses
This commit is contained in:
Scott Shawcroft 2022-01-21 11:08:14 -08:00 committed by GitHub
commit 9a353a4f56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 255 additions and 201 deletions

4
main.c
View File

@ -290,10 +290,10 @@ STATIC void cleanup_after_vm(supervisor_allocation *heap, mp_obj_t exception) {
keypad_reset(); keypad_reset();
#endif #endif
// reset_board_busses() first because it may release pins from the never_reset state, so that // reset_board_buses() first because it may release pins from the never_reset state, so that
// reset_port() can reset them. // reset_port() can reset them.
#if CIRCUITPY_BOARD #if CIRCUITPY_BOARD
reset_board_busses(); reset_board_buses();
#endif #endif
reset_port(); reset_port();
reset_board(); reset_board();

View File

@ -71,7 +71,7 @@ uint8_t display_init_sequence[] = {
void board_init(void) { void board_init(void) {
displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus; displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus;
bus->base.type = &displayio_fourwire_type; bus->base.type = &displayio_fourwire_type;
busio_spi_obj_t *spi = common_hal_board_create_spi(); busio_spi_obj_t *spi = common_hal_board_create_spi(0);
common_hal_busio_spi_never_reset(spi); common_hal_busio_spi_never_reset(spi);
common_hal_displayio_fourwire_construct(bus, common_hal_displayio_fourwire_construct(bus,
spi, spi,

View File

@ -72,7 +72,7 @@ uint8_t display_init_sequence[] = {
void board_init(void) { void board_init(void) {
displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus; displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus;
bus->base.type = &displayio_fourwire_type; bus->base.type = &displayio_fourwire_type;
busio_spi_obj_t *spi = common_hal_board_create_spi(); busio_spi_obj_t *spi = common_hal_board_create_spi(0);
common_hal_displayio_fourwire_construct(bus, common_hal_displayio_fourwire_construct(bus,
spi, spi,
&pin_PA09, // Command or data &pin_PA09, // Command or data

View File

@ -51,7 +51,7 @@ uint8_t display_init_sequence[] = {
}; };
void board_init(void) { void board_init(void) {
busio_spi_obj_t *spi = common_hal_board_create_spi(); busio_spi_obj_t *spi = common_hal_board_create_spi(0);
displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus; displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus;
bus->base.type = &displayio_fourwire_type; bus->base.type = &displayio_fourwire_type;
common_hal_displayio_fourwire_construct(bus, common_hal_displayio_fourwire_construct(bus,

View File

@ -78,7 +78,7 @@ void board_init(void) {
gpio_set_direction(21, GPIO_MODE_DEF_OUTPUT); gpio_set_direction(21, GPIO_MODE_DEF_OUTPUT);
gpio_set_level(21, true); gpio_set_level(21, true);
busio_spi_obj_t *spi = common_hal_board_create_spi(); busio_spi_obj_t *spi = common_hal_board_create_spi(0);
displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus; displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus;
bus->base.type = &displayio_fourwire_type; bus->base.type = &displayio_fourwire_type;

View File

@ -4,12 +4,12 @@
#define MICROPY_HW_NEOPIXEL (&pin_GPIO12) #define MICROPY_HW_NEOPIXEL (&pin_GPIO12)
#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO11) #define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO11)
#define DEFAULT_I2C_BUS_SCL (&pin_GPIO25) #define CIRCUITPY_BOARD_I2C (2)
#define DEFAULT_I2C_BUS_SDA (&pin_GPIO24) #define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO25, .sda = &pin_GPIO24}, \
{.scl = &pin_GPIO23, .sda = &pin_GPIO22}}
#define DEFAULT_SPI_BUS_SCK (&pin_GPIO6) #define CIRCUITPY_BOARD_SPI (1)
#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO3) #define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO6, .mosi = &pin_GPIO3, .miso = &pin_GPIO4}}
#define DEFAULT_SPI_BUS_MISO (&pin_GPIO4)
#define DEFAULT_UART_BUS_RX (&pin_GPIO5) #define CIRCUITPY_BOARD_UART (1)
#define DEFAULT_UART_BUS_TX (&pin_GPIO20) #define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO20, .rx = &pin_GPIO5}}

View File

@ -1,5 +1,7 @@
#include "shared-bindings/board/__init__.h" #include "shared-bindings/board/__init__.h"
CIRCUITPY_BOARD_BUS_SINGLETON(stemma_i2c, i2c, 1)
STATIC const mp_rom_map_elem_t board_module_globals_table[] = { STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
@ -47,5 +49,7 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
{ MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_stemma_i2c_obj) },
}; };
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -259,23 +259,42 @@ typedef long mp_off_t;
#error No *_FLASH_FILESYSTEM set! #error No *_FLASH_FILESYSTEM set!
#endif #endif
// Default board buses.
#ifndef CIRCUITPY_BOARD_I2C
#if defined(DEFAULT_I2C_BUS_SCL) && defined(DEFAULT_I2C_BUS_SDA)
#define CIRCUITPY_BOARD_I2C (1)
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = DEFAULT_I2C_BUS_SCL, .sda = DEFAULT_I2C_BUS_SDA}}
#else
#define CIRCUITPY_BOARD_I2C (0)
#endif
#endif
#ifndef CIRCUITPY_BOARD_SPI
#if defined(DEFAULT_SPI_BUS_SCK) && defined(DEFAULT_SPI_BUS_MOSI) && defined(DEFAULT_SPI_BUS_MISO)
#define CIRCUITPY_BOARD_SPI (1)
#define CIRCUITPY_BOARD_SPI_PIN {{.clock = DEFAULT_SPI_BUS_SCK, .mosi = DEFAULT_SPI_BUS_MOSI, .miso = DEFAULT_SPI_BUS_MISO}}
#else
#define CIRCUITPY_BOARD_SPI (0)
#endif
#endif
#ifndef CIRCUITPY_BOARD_UART
#if defined(DEFAULT_UART_BUS_TX) && defined(DEFAULT_UART_BUS_RX)
#define CIRCUITPY_BOARD_UART (1)
#define CIRCUITPY_BOARD_UART_PIN {{.tx = DEFAULT_UART_BUS_TX, .rx = DEFAULT_UART_BUS_RX}}
#define BOARD_UART_ROOT_POINTER mp_obj_t board_uart_bus;
#else
#define CIRCUITPY_BOARD_UART (0)
#define BOARD_UART_ROOT_POINTER
#endif
#else
#define BOARD_UART_ROOT_POINTER mp_obj_t board_uart_bus;
#endif
// These CIRCUITPY_xxx values should all be defined in the *.mk files as being on or off. // These CIRCUITPY_xxx values should all be defined in the *.mk files as being on or off.
// So if any are not defined in *.mk, they'll throw an error here. // So if any are not defined in *.mk, they'll throw an error here.
#if CIRCUITPY_BOARD
#define BOARD_I2C (defined(DEFAULT_I2C_BUS_SDA) && defined(DEFAULT_I2C_BUS_SCL))
#define BOARD_SPI (defined(DEFAULT_SPI_BUS_SCK) && defined(DEFAULT_SPI_BUS_MISO) && defined(DEFAULT_SPI_BUS_MOSI))
#define BOARD_UART (defined(DEFAULT_UART_BUS_RX) && defined(DEFAULT_UART_BUS_TX))
// I2C and SPI are always allocated off the heap.
#if BOARD_UART
#define BOARD_UART_ROOT_POINTER mp_obj_t shared_uart_bus;
#else
#define BOARD_UART_ROOT_POINTER
#endif
#else
#define BOARD_UART_ROOT_POINTER
#endif
#if CIRCUITPY_DISPLAYIO #if CIRCUITPY_DISPLAYIO
#ifndef CIRCUITPY_DISPLAY_LIMIT #ifndef CIRCUITPY_DISPLAY_LIMIT
#define CIRCUITPY_DISPLAY_LIMIT (1) #define CIRCUITPY_DISPLAY_LIMIT (1)

View File

@ -28,12 +28,15 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "shared-bindings/board/__init__.h" #include "shared-bindings/board/__init__.h"
#if BOARD_I2C #if CIRCUITPY_BOARD_I2C
#include "shared-bindings/busio/I2C.h" #include "shared-bindings/busio/I2C.h"
#endif #endif
#if BOARD_SPI #if CIRCUITPY_BOARD_SPI
#include "shared-bindings/busio/SPI.h" #include "shared-bindings/busio/SPI.h"
#endif #endif
#if CIRCUITPY_BOARD_UART
#include "shared-bindings/busio/UART.h"
#endif
//| """Board specific pin names //| """Board specific pin names
//| //|
@ -47,84 +50,57 @@
//| """Board ID string. The unique identifier for the board model in //| """Board ID string. The unique identifier for the board model in
//| circuitpython, as well as on circuitpython.org. //| circuitpython, as well as on circuitpython.org.
//| Example: "hallowing_m0_express".""" //| Example: "hallowing_m0_express"."""
//|
//| def I2C() -> busio.I2C: //| def I2C() -> busio.I2C:
//| """Returns the `busio.I2C` object for the board designated SDA and SCL pins. It is a singleton.""" //| """Returns the `busio.I2C` object for the board's designated I2C bus(es).
//| The object created is a singleton, and uses the default parameter values for `busio.I2C`."""
//| ... //| ...
//| //|
#if CIRCUITPY_BOARD_I2C
#if BOARD_I2C STATIC mp_obj_t board_i2c_0(void) {
mp_obj_t board_i2c(void) { return common_hal_board_create_i2c(0);
mp_obj_t singleton = common_hal_board_get_i2c();
if (singleton != NULL && !common_hal_busio_i2c_deinited(singleton)) {
return singleton;
}
assert_pin_free(DEFAULT_I2C_BUS_SDA);
assert_pin_free(DEFAULT_I2C_BUS_SCL);
return common_hal_board_create_i2c();
} }
#else #else
mp_obj_t board_i2c(void) { STATIC mp_obj_t board_i2c_0(void) {
mp_raise_NotImplementedError_varg(translate("No default %q bus"), MP_QSTR_I2C); mp_raise_NotImplementedError_varg(translate("No default %q bus"), MP_QSTR_I2C);
return MP_ROM_NONE; return MP_ROM_NONE;
} }
#endif #endif
MP_DEFINE_CONST_FUN_OBJ_0(board_i2c_obj, board_i2c); MP_DEFINE_CONST_FUN_OBJ_0(board_i2c_obj, board_i2c_0);
//| def SPI() -> busio.SPI: //| def SPI() -> busio.SPI:
//| """Returns the `busio.SPI` object for the board designated SCK, MOSI and MISO pins. It is a //| """Returns the `busio.SPI` object for the board's designated SPI bus(es).
//| singleton.""" //| The object created is a singleton, and uses the default parameter values for `busio.SPI`."""
//| ... //| ...
//| //|
#if BOARD_SPI #if CIRCUITPY_BOARD_SPI
mp_obj_t board_spi(void) { STATIC mp_obj_t board_spi_0(void) {
mp_obj_t singleton = common_hal_board_get_spi(); return common_hal_board_create_spi(0);
if (singleton != NULL && !common_hal_busio_spi_deinited(singleton)) {
return singleton;
}
assert_pin_free(DEFAULT_SPI_BUS_SCK);
assert_pin_free(DEFAULT_SPI_BUS_MOSI);
assert_pin_free(DEFAULT_SPI_BUS_MISO);
return common_hal_board_create_spi();
} }
#else #else
mp_obj_t board_spi(void) { STATIC mp_obj_t board_spi_0(void) {
mp_raise_NotImplementedError_varg(translate("No default %q bus"), MP_QSTR_SPI); mp_raise_NotImplementedError_varg(translate("No default %q bus"), MP_QSTR_SPI);
return MP_ROM_NONE; return MP_ROM_NONE;
} }
#endif #endif
MP_DEFINE_CONST_FUN_OBJ_0(board_spi_obj, board_spi); MP_DEFINE_CONST_FUN_OBJ_0(board_spi_obj, board_spi_0);
//| def UART() -> busio.UART: //| def UART() -> busio.UART:
//| """Returns the `busio.UART` object for the board designated TX and RX pins. It is a singleton. //| """Returns the `busio.UART` object for the board's designated UART bus(es).
//| //| The object created is a singleton, and uses the default parameter values for `busio.UART`."""
//| The object created uses the default parameter values for `busio.UART`. If you need to set
//| parameters that are not changeable after creation, such as ``receiver_buffer_size``,
//| do not use `board.UART()`; instead create a `busio.UART` object explicitly with the
//| desired parameters."""
//| ... //| ...
//| //|
#if BOARD_UART #if CIRCUITPY_BOARD_UART
mp_obj_t board_uart(void) { STATIC mp_obj_t board_uart_0(void) {
mp_obj_t singleton = common_hal_board_get_uart(); return common_hal_board_create_uart(0);
if (singleton != NULL) {
return singleton;
}
assert_pin_free(DEFAULT_UART_BUS_RX);
assert_pin_free(DEFAULT_UART_BUS_TX);
return common_hal_board_create_uart();
} }
#else #else
mp_obj_t board_uart(void) { STATIC mp_obj_t board_uart_0(void) {
mp_raise_NotImplementedError_varg(translate("No default %q bus"), MP_QSTR_UART); mp_raise_NotImplementedError_varg(translate("No default %q bus"), MP_QSTR_UART);
return MP_ROM_NONE; return MP_ROM_NONE;
} }
#endif #endif
MP_DEFINE_CONST_FUN_OBJ_0(board_uart_obj, board_uart); MP_DEFINE_CONST_FUN_OBJ_0(board_uart_obj, board_uart_0);
const mp_obj_module_t board_module = { const mp_obj_module_t board_module = {
.base = { &mp_type_module }, .base = { &mp_type_module },

View File

@ -35,21 +35,29 @@
extern const mp_obj_dict_t board_module_globals; extern const mp_obj_dict_t board_module_globals;
STATIC const MP_DEFINE_STR_OBJ(board_module_id_obj, CIRCUITPY_BOARD_ID); STATIC const MP_DEFINE_STR_OBJ(board_module_id_obj, CIRCUITPY_BOARD_ID);
mp_obj_t common_hal_board_get_i2c(void); bool common_hal_board_is_i2c(mp_obj_t obj);
mp_obj_t common_hal_board_create_i2c(void); mp_obj_t common_hal_board_get_i2c(const mp_int_t instance);
mp_obj_t common_hal_board_create_i2c(const mp_int_t instance);
mp_obj_t board_i2c(size_t n_args, const mp_obj_t *args);
MP_DECLARE_CONST_FUN_OBJ_0(board_i2c_obj); MP_DECLARE_CONST_FUN_OBJ_0(board_i2c_obj);
mp_obj_t common_hal_board_get_spi(void); bool common_hal_board_is_spi(mp_obj_t obj);
mp_obj_t common_hal_board_create_spi(void); mp_obj_t common_hal_board_get_spi(const mp_int_t instance);
mp_obj_t common_hal_board_create_spi(const mp_int_t instance);
mp_obj_t board_spi(size_t n_args, const mp_obj_t *args);
MP_DECLARE_CONST_FUN_OBJ_0(board_spi_obj); MP_DECLARE_CONST_FUN_OBJ_0(board_spi_obj);
mp_obj_t common_hal_board_get_uart(void); bool common_hal_board_is_uart(mp_obj_t obj);
mp_obj_t common_hal_board_create_uart(void); mp_obj_t common_hal_board_get_uart(const mp_int_t instance);
mp_obj_t common_hal_board_create_uart(const mp_int_t instance);
mp_obj_t board_uart(size_t n_args, const mp_obj_t *args);
MP_DECLARE_CONST_FUN_OBJ_0(board_uart_obj); MP_DECLARE_CONST_FUN_OBJ_0(board_uart_obj);
mp_obj_t board_i2c(void); #define CIRCUITPY_BOARD_BUS_SINGLETON(name, bus, instance) \
mp_obj_t board_spi(void); STATIC mp_obj_t board_##name(void) { \
mp_obj_t board_uart(void); return common_hal_board_create_##bus(instance); \
} \
MP_DEFINE_CONST_FUN_OBJ_0(board_##name##_obj, board_##name);
#define CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS \ #define CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS \
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_board) }, \ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_board) }, \

View File

@ -46,141 +46,189 @@
#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h" #include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h"
#endif #endif
#if BOARD_I2C #if CIRCUITPY_BOARD_I2C
// Statically allocate the I2C object so it can live past the end of the heap and into the next VM. // Statically allocate the I2C object so it can live past the end of the heap and into the next VM.
// That way it can be used by built-in I2CDisplay displays and be accessible through board.I2C(). // That way it can be used by built-in I2CDisplay displays and be accessible through board.I2C().
STATIC busio_i2c_obj_t i2c_obj;
STATIC mp_obj_t i2c_singleton = NULL;
mp_obj_t common_hal_board_get_i2c(void) { typedef struct {
return i2c_singleton; const mcu_pin_obj_t *scl;
const mcu_pin_obj_t *sda;
} board_i2c_pin_t;
static const board_i2c_pin_t i2c_pin[CIRCUITPY_BOARD_I2C] = CIRCUITPY_BOARD_I2C_PIN;
static busio_i2c_obj_t i2c_obj[CIRCUITPY_BOARD_I2C];
bool common_hal_board_is_i2c(mp_obj_t obj) {
for (uint8_t instance = 0; instance < CIRCUITPY_BOARD_I2C; instance++) {
if (obj == &i2c_obj[instance]) {
return true;
}
}
return false;
} }
mp_obj_t common_hal_board_create_i2c(void) { mp_obj_t common_hal_board_get_i2c(const mp_int_t instance) {
// All callers have either already verified this or come so early that it can't be otherwise. return &i2c_obj[instance];
assert(i2c_singleton == NULL || common_hal_busio_i2c_deinited(i2c_singleton)); }
busio_i2c_obj_t *self = &i2c_obj;
mp_obj_t common_hal_board_create_i2c(const mp_int_t instance) {
const mp_obj_t singleton = common_hal_board_get_i2c(instance);
if (singleton != NULL && !common_hal_busio_i2c_deinited(singleton)) {
return singleton;
}
busio_i2c_obj_t *self = &i2c_obj[instance];
self->base.type = &busio_i2c_type; self->base.type = &busio_i2c_type;
common_hal_busio_i2c_construct(self, DEFAULT_I2C_BUS_SCL, DEFAULT_I2C_BUS_SDA, 100000, 255); assert_pin_free(i2c_pin[instance].scl);
i2c_singleton = (mp_obj_t)self; assert_pin_free(i2c_pin[instance].sda);
return i2c_singleton;
common_hal_busio_i2c_construct(self, i2c_pin[instance].scl, i2c_pin[instance].sda, 100000, 255);
return &i2c_obj[instance];
} }
#endif #endif
#if CIRCUITPY_BOARD_SPI
#if BOARD_SPI
// Statically allocate the SPI object so it can live past the end of the heap and into the next VM. // Statically allocate the SPI object so it can live past the end of the heap and into the next VM.
// That way it can be used by built-in FourWire displays and be accessible through board.SPI(). // That way it can be used by built-in FourWire displays and be accessible through board.SPI().
STATIC busio_spi_obj_t spi_obj;
STATIC mp_obj_t spi_singleton = NULL;
mp_obj_t common_hal_board_get_spi(void) { typedef struct {
return spi_singleton; const mcu_pin_obj_t *clock;
const mcu_pin_obj_t *mosi;
const mcu_pin_obj_t *miso;
} board_spi_pin_t;
static const board_spi_pin_t spi_pin[CIRCUITPY_BOARD_SPI] = CIRCUITPY_BOARD_SPI_PIN;
static busio_spi_obj_t spi_obj[CIRCUITPY_BOARD_SPI];
bool common_hal_board_is_spi(mp_obj_t obj) {
for (uint8_t instance = 0; instance < CIRCUITPY_BOARD_SPI; instance++) {
if (obj == &spi_obj[instance]) {
return true;
}
}
return false;
} }
mp_obj_t common_hal_board_create_spi(void) { mp_obj_t common_hal_board_get_spi(const mp_int_t instance) {
// All callers have either already verified this or come so early that it can't be otherwise. return &spi_obj[instance];
assert(spi_singleton == NULL || common_hal_busio_spi_deinited(spi_singleton)); }
busio_spi_obj_t *self = &spi_obj;
mp_obj_t common_hal_board_create_spi(const mp_int_t instance) {
const mp_obj_t singleton = common_hal_board_get_spi(instance);
if (singleton != NULL && !common_hal_busio_spi_deinited(singleton)) {
return singleton;
}
busio_spi_obj_t *self = &spi_obj[instance];
self->base.type = &busio_spi_type; self->base.type = &busio_spi_type;
const mcu_pin_obj_t *clock = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_SCK); assert_pin_free(spi_pin[instance].clock);
const mcu_pin_obj_t *mosi = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_MOSI); assert_pin_free(spi_pin[instance].mosi);
const mcu_pin_obj_t *miso = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_MISO); assert_pin_free(spi_pin[instance].miso);
common_hal_busio_spi_construct(self, clock, mosi, miso);
spi_singleton = (mp_obj_t)self; common_hal_busio_spi_construct(self, spi_pin[instance].clock, spi_pin[instance].mosi, spi_pin[instance].miso);
return spi_singleton;
return &spi_obj[instance];
} }
#endif #endif
#if BOARD_UART #if CIRCUITPY_BOARD_UART
mp_obj_t common_hal_board_get_uart(void) {
return MP_STATE_VM(shared_uart_bus); typedef struct {
const mcu_pin_obj_t *tx;
const mcu_pin_obj_t *rx;
} board_uart_pin_t;
static const board_uart_pin_t uart_pin[CIRCUITPY_BOARD_UART] = CIRCUITPY_BOARD_UART_PIN;
static busio_uart_obj_t uart_obj[CIRCUITPY_BOARD_UART];
bool common_hal_board_is_uart(mp_obj_t obj) {
for (uint8_t instance = 0; instance < CIRCUITPY_BOARD_UART; instance++) {
if (obj == &uart_obj[instance]) {
return true;
}
}
return false;
} }
mp_obj_t common_hal_board_create_uart(void) { mp_obj_t common_hal_board_get_uart(const mp_int_t instance) {
busio_uart_obj_t *self = m_new_ll_obj(busio_uart_obj_t); return &uart_obj[instance];
}
mp_obj_t common_hal_board_create_uart(const mp_int_t instance) {
const mp_obj_t singleton = common_hal_board_get_uart(instance);
if (singleton != NULL && !common_hal_busio_uart_deinited(singleton)) {
return singleton;
}
busio_uart_obj_t *self = &uart_obj[instance];
self->base.type = &busio_uart_type; self->base.type = &busio_uart_type;
const mcu_pin_obj_t *rx = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_RX); MP_STATE_VM(board_uart_bus) = &uart_obj;
const mcu_pin_obj_t *tx = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_TX);
#ifdef DEFAULT_UART_BUS_RTS
const mcu_pin_obj_t *rts = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_RTS);
#else
const mcu_pin_obj_t *rts = NULL;
#endif
#ifdef DEFAULT_UART_BUS_CTS
const mcu_pin_obj_t *cts = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_CTS);
#else
const mcu_pin_obj_t *cts = NULL;
#endif
#ifdef DEFAULT_UART_IS_RS485
const mcu_pin_obj_t *rs485_dir = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_RS485DIR);
#ifdef DEFAULT_UART_RS485_INVERT
const bool rs485_invert = true;
#else
const bool rs485_invert = false;
#endif
#else
const mcu_pin_obj_t *rs485_dir = NULL;
const bool rs485_invert = false;
#endif
common_hal_busio_uart_construct(self, tx, rx, rts, cts, rs485_dir, rs485_invert, assert_pin_free(uart_pin[instance].tx);
9600, 8, BUSIO_UART_PARITY_NONE, 1, 1.0f, 64, NULL, false); assert_pin_free(uart_pin[instance].rx);
MP_STATE_VM(shared_uart_bus) = MP_OBJ_FROM_PTR(self);
return MP_STATE_VM(shared_uart_bus); common_hal_busio_uart_construct(self, uart_pin[instance].tx, uart_pin[instance].rx,
NULL, NULL, NULL, false, 9600, 8, BUSIO_UART_PARITY_NONE, 1, 1.0f, 64, NULL, false);
return &uart_obj[instance];
} }
#endif #endif
void reset_board_busses(void) { void reset_board_buses(void) {
#if BOARD_I2C #if CIRCUITPY_BOARD_I2C
for (uint8_t instance = 0; instance < CIRCUITPY_BOARD_I2C; instance++) {
bool display_using_i2c = false; bool display_using_i2c = false;
#if CIRCUITPY_DISPLAYIO #if CIRCUITPY_DISPLAYIO
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
if (displays[i].bus_base.type == &displayio_i2cdisplay_type && displays[i].i2cdisplay_bus.bus == i2c_singleton) { if (displays[i].bus_base.type == &displayio_i2cdisplay_type && displays[i].i2cdisplay_bus.bus == &i2c_obj[instance]) {
display_using_i2c = true; display_using_i2c = true;
break; break;
} }
} }
#endif #endif
if (!common_hal_busio_i2c_deinited(&i2c_obj[instance])) {
// make sure I2C lock is not held over a soft reset // make sure I2C lock is not held over a soft reset
if (i2c_singleton != NULL) { common_hal_busio_i2c_unlock(&i2c_obj[instance]);
common_hal_busio_i2c_unlock(i2c_singleton);
if (!display_using_i2c) { if (!display_using_i2c) {
common_hal_busio_i2c_deinit(i2c_singleton); common_hal_busio_i2c_deinit(&i2c_obj[instance]);
i2c_singleton = NULL; }
} }
} }
#endif #endif
#if BOARD_SPI #if CIRCUITPY_BOARD_SPI
for (uint8_t instance = 0; instance < CIRCUITPY_BOARD_SPI; instance++) {
bool display_using_spi = false; bool display_using_spi = false;
#if CIRCUITPY_DISPLAYIO #if CIRCUITPY_DISPLAYIO
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
mp_const_obj_t bus_type = displays[i].bus_base.type; mp_const_obj_t bus_type = displays[i].bus_base.type;
if (bus_type == &displayio_fourwire_type && displays[i].fourwire_bus.bus == spi_singleton) { if (bus_type == &displayio_fourwire_type && displays[i].fourwire_bus.bus == &spi_obj[instance]) {
display_using_spi = true; display_using_spi = true;
break; break;
} }
#if CIRCUITPY_SHARPDISPLAY #if CIRCUITPY_SHARPDISPLAY
if (displays[i].bus_base.type == &sharpdisplay_framebuffer_type && displays[i].sharpdisplay.bus == spi_singleton) { if (displays[i].bus_base.type == &sharpdisplay_framebuffer_type && displays[i].sharpdisplay.bus == &spi_obj[instance]) {
display_using_spi = true; display_using_spi = true;
break; break;
} }
#endif #endif
} }
#endif #endif
if (!common_hal_busio_spi_deinited(&spi_obj[instance])) {
// make sure SPI lock is not held over a soft reset // make sure SPI lock is not held over a soft reset
if (spi_singleton != NULL) { common_hal_busio_spi_unlock(&spi_obj[instance]);
common_hal_busio_spi_unlock(spi_singleton);
if (!display_using_spi) { if (!display_using_spi) {
common_hal_busio_spi_deinit(spi_singleton); common_hal_busio_spi_deinit(&spi_obj[instance]);
spi_singleton = NULL; }
} }
} }
#endif #endif
#if BOARD_UART #if CIRCUITPY_BOARD_UART
MP_STATE_VM(shared_uart_bus) = NULL; for (uint8_t instance = 0; instance < CIRCUITPY_BOARD_UART; instance++) {
common_hal_busio_uart_deinit(&uart_obj[instance]);
}
#endif #endif
} }

View File

@ -27,6 +27,6 @@
#ifndef MICROPY_INCLUDED_SHARED_MODULE_BOARD__INIT__H #ifndef MICROPY_INCLUDED_SHARED_MODULE_BOARD__INIT__H
#define MICROPY_INCLUDED_SHARED_MODULE_BOARD__INIT__H #define MICROPY_INCLUDED_SHARED_MODULE_BOARD__INIT__H
void reset_board_busses(void); void reset_board_buses(void);
#endif // MICROPY_INCLUDED_SHARED_MODULE_BOARD__INIT__H #endif // MICROPY_INCLUDED_SHARED_MODULE_BOARD__INIT__H

View File

@ -24,7 +24,6 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include <string.h> #include <string.h>
#include "shared-module/displayio/__init__.h" #include "shared-module/displayio/__init__.h"
@ -169,11 +168,11 @@ void reset_displays(void) {
if (((size_t)fourwire->bus) < ((size_t)&displays) || if (((size_t)fourwire->bus) < ((size_t)&displays) ||
((size_t)fourwire->bus) > ((size_t)&displays + CIRCUITPY_DISPLAY_LIMIT)) { ((size_t)fourwire->bus) > ((size_t)&displays + CIRCUITPY_DISPLAY_LIMIT)) {
busio_spi_obj_t *original_spi = fourwire->bus; busio_spi_obj_t *original_spi = fourwire->bus;
#if BOARD_SPI #if CIRCUITPY_BOARD_SPI
// We don't need to move original_spi if it is the board.SPI object because it is // We don't need to move original_spi if it is a board.SPI object because it is
// statically allocated already. (Doing so would also make it impossible to reference in // statically allocated already. (Doing so would also make it impossible to reference in
// a subsequent VM run.) // a subsequent VM run.)
if (original_spi == common_hal_board_get_spi()) { if (common_hal_board_is_spi(original_spi)) {
continue; continue;
} }
#endif #endif
@ -197,11 +196,11 @@ void reset_displays(void) {
if (((size_t)i2c->bus) < ((size_t)&displays) || if (((size_t)i2c->bus) < ((size_t)&displays) ||
((size_t)i2c->bus) > ((size_t)&displays + CIRCUITPY_DISPLAY_LIMIT)) { ((size_t)i2c->bus) > ((size_t)&displays + CIRCUITPY_DISPLAY_LIMIT)) {
busio_i2c_obj_t *original_i2c = i2c->bus; busio_i2c_obj_t *original_i2c = i2c->bus;
#if BOARD_I2C #if CIRCUITPY_BOARD_I2C
// We don't need to move original_i2c if it is the board.I2C object because it is // We don't need to move original_i2c if it is a board.I2C object because it is
// statically allocated already. (Doing so would also make it impossible to reference in // statically allocated already. (Doing so would also make it impossible to reference in
// a subsequent VM run.) // a subsequent VM run.)
if (original_i2c == common_hal_board_get_i2c()) { if (common_hal_board_is_i2c(original_i2c)) {
continue; continue;
} }
#endif #endif
@ -230,11 +229,11 @@ void reset_displays(void) {
if (((uint32_t)is31->i2c) < ((uint32_t)&displays) || if (((uint32_t)is31->i2c) < ((uint32_t)&displays) ||
((uint32_t)is31->i2c) > ((uint32_t)&displays + CIRCUITPY_DISPLAY_LIMIT)) { ((uint32_t)is31->i2c) > ((uint32_t)&displays + CIRCUITPY_DISPLAY_LIMIT)) {
busio_i2c_obj_t *original_i2c = is31->i2c; busio_i2c_obj_t *original_i2c = is31->i2c;
#if BOARD_I2C #if CIRCUITPY_BOARD_I2C
// We don't need to move original_i2c if it is the board.I2C object because it is // We don't need to move original_i2c if it is the board.I2C object because it is
// statically allocated already. (Doing so would also make it impossible to reference in // statically allocated already. (Doing so would also make it impossible to reference in
// a subsequent VM run.) // a subsequent VM run.)
if (original_i2c == common_hal_board_get_i2c()) { if (common_hal_board_is_i2c(original_i2c)) {
continue; continue;
} }
#endif #endif

View File

@ -71,8 +71,8 @@ STATIC bool common_hal_sharpdisplay_framebuffer_get_pixels_in_byte_share_row(sha
void common_hal_sharpdisplay_framebuffer_reset(sharpdisplay_framebuffer_obj_t *self) { void common_hal_sharpdisplay_framebuffer_reset(sharpdisplay_framebuffer_obj_t *self) {
if (self->bus != &self->inline_bus if (self->bus != &self->inline_bus
#if BOARD_SPI #if CIRCUITPY_BOARD_SPI
&& self->bus != common_hal_board_get_spi() && !common_hal_board_is_spi(self->bus)
#endif #endif
) { ) {
memcpy(&self->inline_bus, self->bus, sizeof(busio_spi_obj_t)); memcpy(&self->inline_bus, self->bus, sizeof(busio_spi_obj_t));