summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorScott Shawcroft <scott@tannewt.org>2019-04-08 16:58:50 -0700
committerScott Shawcroft <scott@tannewt.org>2019-04-08 16:58:50 -0700
commit0f003ac5b8312fafb120e86e05eefd2431014d8c (patch)
treeed3e9cd062573c0f0f7fcea51f7c4e9971319648 /py
parent7686f93ef456aa46f538da3159d0e12cae9fa737 (diff)
Reorganize board busses into shared-bindings and shared-module.
Diffstat (limited to 'py')
-rw-r--r--py/circuitpy_defns.mk1
-rw-r--r--py/circuitpy_mpconfig.h23
-rwxr-xr-xpy/gc.c32
-rw-r--r--py/gc.h4
-rw-r--r--py/mpstate.h2
5 files changed, 62 insertions, 0 deletions
diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk
index 7a369817a..342c0ab0c 100644
--- a/py/circuitpy_defns.mk
+++ b/py/circuitpy_defns.mk
@@ -302,6 +302,7 @@ $(filter $(SRC_PATTERNS), \
bitbangio/OneWire.c \
bitbangio/SPI.c \
bitbangio/__init__.c \
+ board/__init__.c \
busio/OneWire.c \
displayio/Bitmap.c \
displayio/ColorConverter.c \
diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h
index 6da3ae910..441dd5bad 100644
--- a/py/circuitpy_mpconfig.h
+++ b/py/circuitpy_mpconfig.h
@@ -252,8 +252,29 @@ extern const struct _mp_obj_module_t bleio_module;
#if CIRCUITPY_BOARD
#define BOARD_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module },
extern const struct _mp_obj_module_t board_module;
+
+#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))
+
+#if BOARD_I2C
+#define BOARD_I2C_ROOT_POINTER mp_obj_t shared_i2c_bus;
+#else
+#define BOARD_I2C_ROOT_POINTER
+#endif
+
+// SPI is 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_MODULE
+#define BOARD_I2C_ROOT_POINTER
+#define BOARD_UART_ROOT_POINTER
#endif
#if CIRCUITPY_BUSIO
@@ -586,6 +607,8 @@ extern const struct _mp_obj_module_t ustack_module;
mp_obj_t gamepad_singleton; \
mp_obj_t pew_singleton; \
mp_obj_t terminal_tilegrid_tiles; \
+ BOARD_I2C_ROOT_POINTER \
+ BOARD_UART_ROOT_POINTER \
FLASH_ROOT_POINTERS \
NETWORK_ROOT_POINTERS \
diff --git a/py/gc.c b/py/gc.c
index 81e609730..246df1503 100755
--- a/py/gc.c
+++ b/py/gc.c
@@ -176,6 +176,8 @@ void gc_init(void *start, void *end) {
mp_thread_mutex_init(&MP_STATE_MEM(gc_mutex));
#endif
+ MP_STATE_MEM(permanent_pointers) = NULL;
+
DEBUG_printf("GC layout:\n");
DEBUG_printf(" alloc table at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", MP_STATE_MEM(gc_alloc_table_start), MP_STATE_MEM(gc_alloc_table_byte_len), MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB);
#if MICROPY_ENABLE_FINALISER
@@ -359,6 +361,10 @@ void gc_collect_start(void) {
size_t root_end = offsetof(mp_state_ctx_t, vm.qstr_last_chunk);
gc_collect_root(ptrs + root_start / sizeof(void*), (root_end - root_start) / sizeof(void*));
+ if (MP_STATE_MEM(permanent_pointers) != NULL) {
+ gc_collect_root(MP_STATE_MEM(permanent_pointers), BYTES_PER_BLOCK / sizeof(void*));
+ }
+
#if MICROPY_ENABLE_PYSTACK
// Trace root pointers from the Python stack.
ptrs = (void**)(void*)MP_STATE_THREAD(pystack_start);
@@ -938,6 +944,32 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) {
}
#endif // Alternative gc_realloc impl
+bool gc_never_free(void *ptr) {
+ // Pointers are stored in a linked list where each block is BYTES_PER_BLOCK long and the first
+ // pointer is the next block of pointers.
+ void ** current_reference_block = MP_STATE_MEM(permanent_pointers);
+ while (current_reference_block != NULL) {
+ for (size_t i = 1; i < BYTES_PER_BLOCK / sizeof(void*); i++) {
+ if (current_reference_block[i] == NULL) {
+ current_reference_block[i] = ptr;
+ return true;
+ }
+ }
+ current_reference_block = current_reference_block[0];
+ }
+ void** next_block = gc_alloc(BYTES_PER_BLOCK, false, true);
+ if (next_block == NULL) {
+ return false;
+ }
+ if (MP_STATE_MEM(permanent_pointers) == NULL) {
+ MP_STATE_MEM(permanent_pointers) = next_block;
+ } else {
+ current_reference_block[0] = next_block;
+ }
+ next_block[1] = ptr;
+ return true;
+}
+
void gc_dump_info(void) {
gc_info_t info;
gc_info(&info);
diff --git a/py/gc.h b/py/gc.h
index c05e006b4..757a2a6e0 100644
--- a/py/gc.h
+++ b/py/gc.h
@@ -57,6 +57,10 @@ bool gc_has_finaliser(const void *ptr);
void *gc_make_long_lived(void *old_ptr);
void *gc_realloc(void *ptr, size_t n_bytes, bool allow_move);
+// Prevents a pointer from ever being freed because it establishes a permanent reference to it. Use
+// very sparingly because it can leak memory.
+bool gc_never_free(void *ptr);
+
typedef struct _gc_info_t {
size_t total;
size_t used;
diff --git a/py/mpstate.h b/py/mpstate.h
index eef8696d3..a3d7e5dcc 100644
--- a/py/mpstate.h
+++ b/py/mpstate.h
@@ -103,6 +103,8 @@ typedef struct _mp_state_mem_t {
// This is a global mutex used to make the GC thread-safe.
mp_thread_mutex_t gc_mutex;
#endif
+
+ void** permanent_pointers;
} mp_state_mem_t;
// This structure hold runtime and VM information. It includes a section