summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2019-04-09 17:47:25 -0400
committerGitHub <noreply@github.com>2019-04-09 17:47:25 -0400
commit9026f13a25d60a2d39f4233f9213f3d49eb5855a (patch)
treec8625d129117b9eda0b960b16a8c5f85551895a2 /py
parent5015036c06e12c158ca0b36a23fade8da6fbbf07 (diff)
parent0e98eeb63b841f8e7b48b4ad50df9f144e7ecf25 (diff)
Merge pull request #1756 from tannewt/fix_cpx_display
Fix crash when getting board.SPI outside the VM
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
-rw-r--r--py/runtime.c8
-rw-r--r--py/runtime.h1
7 files changed, 71 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
diff --git a/py/runtime.c b/py/runtime.c
index 060748f1b..1e0100337 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -1590,6 +1590,14 @@ NORETURN void mp_raise_NotImplementedError(const compressed_string_t *msg) {
mp_raise_msg(&mp_type_NotImplementedError, msg);
}
+NORETURN void mp_raise_NotImplementedError_varg(const compressed_string_t *fmt, ...) {
+ va_list argptr;
+ va_start(argptr,fmt);
+ mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_NotImplementedError, fmt, argptr);
+ va_end(argptr);
+ nlr_raise(exception);
+}
+
#if MICROPY_STACK_CHECK || MICROPY_ENABLE_PYSTACK
NORETURN void mp_raise_recursion_depth(void) {
mp_raise_RuntimeError(translate("maximum recursion depth exceeded"));
diff --git a/py/runtime.h b/py/runtime.h
index e52d3232e..2577c9dd5 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -162,6 +162,7 @@ NORETURN void mp_raise_OSError(int errno_);
NORETURN void mp_raise_OSError_msg(const compressed_string_t *msg);
NORETURN void mp_raise_OSError_msg_varg(const compressed_string_t *fmt, ...);
NORETURN void mp_raise_NotImplementedError(const compressed_string_t *msg);
+NORETURN void mp_raise_NotImplementedError_varg(const compressed_string_t *fmt, ...);
NORETURN void mp_raise_recursion_depth(void);
#if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG