summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorScott Shawcroft <scott@tannewt.org>2019-04-16 10:32:38 -0700
committerGitHub <noreply@github.com>2019-04-16 10:32:38 -0700
commitf58446e937ede4735a7ecb0852f2d2739f147cdd (patch)
tree72185232547d424dfe0b61fb7f98ce11378d1e6d /py
parent2d303213ed4ee058c0fc4c541dd7a7181f59d50f (diff)
parent7822d013cd6d379c777f95c73a803b749d1bebe4 (diff)
Merge branch 'master' into master
Diffstat (limited to 'py')
-rw-r--r--py/circuitpy_defns.mk1
-rw-r--r--py/circuitpy_mpconfig.h41
-rw-r--r--py/circuitpy_mpconfig.mk2
-rwxr-xr-xpy/gc.c36
-rw-r--r--py/gc.h4
-rw-r--r--py/mpstate.h2
-rw-r--r--py/objtype.c40
-rw-r--r--py/runtime.c8
-rw-r--r--py/runtime.h1
9 files changed, 112 insertions, 23 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 e96d811ac..441dd5bad 100644
--- a/py/circuitpy_mpconfig.h
+++ b/py/circuitpy_mpconfig.h
@@ -88,6 +88,7 @@
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
#define MICROPY_PY_BUILTINS_MIN_MAX (1)
#define MICROPY_PY_BUILTINS_PROPERTY (1)
+#define MICROPY_PY_BUILTINS_REVERSED (1)
#define MICROPY_PY_BUILTINS_SET (1)
#define MICROPY_PY_BUILTINS_SLICE (1)
#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1)
@@ -182,7 +183,6 @@ typedef long mp_off_t;
#define MICROPY_PY_ALL_SPECIAL_METHODS (CIRCUITPY_FULL_BUILD)
#define MICROPY_PY_BUILTINS_COMPLEX (CIRCUITPY_FULL_BUILD)
#define MICROPY_PY_BUILTINS_FROZENSET (CIRCUITPY_FULL_BUILD)
-#define MICROPY_PY_BUILTINS_REVERSED (CIRCUITPY_FULL_BUILD)
#define MICROPY_PY_BUILTINS_STR_CENTER (CIRCUITPY_FULL_BUILD)
#define MICROPY_PY_BUILTINS_STR_PARTITION (CIRCUITPY_FULL_BUILD)
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (CIRCUITPY_FULL_BUILD)
@@ -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
@@ -360,6 +381,13 @@ extern const struct _mp_obj_module_t os_module;
#define OS_MODULE_ALT_NAME
#endif
+#if CIRCUITPY_PEW
+extern const struct _mp_obj_module_t pew_module;
+#define PEW_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__pew),(mp_obj_t)&pew_module },
+#else
+#define PEW_MODULE
+#endif
+
#if CIRCUITPY_PIXELBUF
extern const struct _mp_obj_module_t pixelbuf_module;
#define PIXELBUF_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__pixelbuf),(mp_obj_t)&pixelbuf_module },
@@ -474,13 +502,6 @@ extern const struct _mp_obj_module_t ustack_module;
#define USTACK_MODULE
#endif
-#if CIRCUITPY_PEW
-extern const struct _mp_obj_module_t pew_module;
-#define PEW_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__pew),(mp_obj_t)&pew_module },
-#else
-#define PEW_MODULE
-#endif
-
// These modules are not yet in shared-bindings, but we prefer the non-uxxx names.
#if MICROPY_PY_UERRNO
#define ERRNO_MODULE { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_uerrno) },
@@ -546,6 +567,7 @@ extern const struct _mp_obj_module_t pew_module;
PULSEIO_MODULE \
RANDOM_MODULE \
RE_MODULE \
+ ROTARYIO_MODULE \
RTC_MODULE \
SAMD_MODULE \
STAGE_MODULE \
@@ -585,6 +607,8 @@ extern const struct _mp_obj_module_t pew_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 \
@@ -597,6 +621,7 @@ void run_background_tasks(void);
#define MICROPY_VM_HOOK_RETURN run_background_tasks();
#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
+#define CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS 1000
#define CIRCUITPY_BOOT_OUTPUT_FILE "/boot_out.txt"
#endif // __INCLUDED_MPCONFIG_CIRCUITPY_H
diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk
index 0df6fff06..8ea72f0bf 100644
--- a/py/circuitpy_mpconfig.mk
+++ b/py/circuitpy_mpconfig.mk
@@ -93,7 +93,7 @@ endif
CFLAGS += -DCIRCUITPY_DISPLAYIO=$(CIRCUITPY_DISPLAYIO)
ifndef CIRCUITPY_FREQUENCYIO
-CIRCUITPY_FREQUENCYIO = 1
+CIRCUITPY_FREQUENCYIO = $(CIRCUITPY_FULL_BUILD)
endif
CFLAGS += -DCIRCUITPY_FREQUENCYIO=$(CIRCUITPY_FREQUENCYIO)
diff --git a/py/gc.c b/py/gc.c
index 81e609730..e0439e945 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,36 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) {
}
#endif // Alternative gc_realloc impl
+bool gc_never_free(void *ptr) {
+ // Check to make sure the pointer is on the heap in the first place.
+ if (gc_nbytes(ptr) == 0) {
+ return false;
+ }
+ // 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/objtype.c b/py/objtype.c
index f205c224e..88e918827 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -964,6 +964,21 @@ STATIC bool check_for_special_accessors(mp_obj_t key, mp_obj_t value) {
#endif
return false;
}
+
+STATIC bool map_has_special_accessors(const mp_map_t *map) {
+ if (map == NULL) {
+ return false;
+ }
+ for (size_t i = 0; i < map->alloc; i++) {
+ if (MP_MAP_SLOT_IS_FILLED(map, i)) {
+ const mp_map_elem_t *elem = &map->table[i];
+ if (check_for_special_accessors(elem->key, elem->value)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
#endif
STATIC void type_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
@@ -1158,20 +1173,6 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
o->locals_dict = make_dict_long_lived(locals_dict, 10);
- #if ENABLE_SPECIAL_ACCESSORS
- // Check if the class has any special accessor methods
- if (!(o->flags & TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) {
- for (size_t i = 0; i < o->locals_dict->map.alloc; i++) {
- if (MP_MAP_SLOT_IS_FILLED(&o->locals_dict->map, i)) {
- const mp_map_elem_t *elem = &o->locals_dict->map.table[i];
- if (check_for_special_accessors(elem->key, elem->value)) {
- o->flags |= TYPE_FLAG_HAS_SPECIAL_ACCESSORS;
- break;
- }
- }
- }
- }
- #endif
const mp_obj_type_t *native_base;
size_t num_native_bases = instance_count_native_bases(o, &native_base);
@@ -1180,6 +1181,17 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
}
mp_map_t *locals_map = &o->locals_dict->map;
+ #if ENABLE_SPECIAL_ACCESSORS
+ // Check if the class has any special accessor methods
+ if (!(o->flags & TYPE_FLAG_HAS_SPECIAL_ACCESSORS) &&
+ (map_has_special_accessors(locals_map) ||
+ (num_native_bases == 1 &&
+ native_base->locals_dict != NULL &&
+ map_has_special_accessors(&native_base->locals_dict->map)))) {
+ o->flags |= TYPE_FLAG_HAS_SPECIAL_ACCESSORS;
+ }
+ #endif
+
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP);
if (elem != NULL) {
// __new__ slot exists; check if it is a function
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