diff options
| author | Scott Shawcroft <scott@tannewt.org> | 2019-04-08 16:58:50 -0700 |
|---|---|---|
| committer | Scott Shawcroft <scott@tannewt.org> | 2019-04-08 16:58:50 -0700 |
| commit | 0f003ac5b8312fafb120e86e05eefd2431014d8c (patch) | |
| tree | ed3e9cd062573c0f0f7fcea51f7c4e9971319648 /py | |
| parent | 7686f93ef456aa46f538da3159d0e12cae9fa737 (diff) | |
Reorganize board busses into shared-bindings and shared-module.
Diffstat (limited to 'py')
| -rw-r--r-- | py/circuitpy_defns.mk | 1 | ||||
| -rw-r--r-- | py/circuitpy_mpconfig.h | 23 | ||||
| -rwxr-xr-x | py/gc.c | 32 | ||||
| -rw-r--r-- | py/gc.h | 4 | ||||
| -rw-r--r-- | py/mpstate.h | 2 |
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 \ @@ -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); @@ -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 |
