Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .github/build-each-commit.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,15 @@

# update only required submodules
pybricks.git.submodule("update", "--init", "micropython")
if args.hub in ["cityhub", "movehub", "technichub", "primehub", "essentialhub", "nxt", "ev3"]:
if args.hub in [
"cityhub",
"movehub",
"technichub",
"primehub",
"essentialhub",
"nxt",
"ev3",
]:
pybricks.submodule("micropython").module().git.submodule(
"update", "--init", "lib/micropython-lib"
)
Expand All @@ -66,7 +74,9 @@
)
if args.hub == "primehub" or args.hub == "essentialhub":
pybricks.git.submodule("update", "--init", "--checkout", "lib/btstack")
pybricks.git.submodule("update", "--init", "--checkout", "lib/STM32_USB_Device_Library")
pybricks.git.submodule(
"update", "--init", "--checkout", "lib/STM32_USB_Device_Library"
)

# build the firmware
subprocess.check_call(
Expand Down
4 changes: 3 additions & 1 deletion .github/build-missing-commits.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@
"update", "--init", "lib/stm32lib"
)
pybricks.git.submodule("update", "--init", "--checkout", "lib/btstack")
pybricks.git.submodule("update", "--init", "--checkout", "lib/STM32_USB_Device_Library")
pybricks.git.submodule(
"update", "--init", "--checkout", "lib/STM32_USB_Device_Library"
)

# Make mpy-cross once
print("Building mpy-cross")
Expand Down
4 changes: 3 additions & 1 deletion .github/download-commit-metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ def main():
)
sizes = {
item["RowKey"]: {
k: v.value if isinstance(v, EntityProperty) else v for k, v in item.items() if k in HUBS
k: v.value if isinstance(v, EntityProperty) else v
for k, v in item.items()
if k in HUBS
}
for item in firmware_size_table.query_entities(
"PartitionKey eq 'size'",
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ jobs:
- name: Test
if: ${{ success() }}
run: |
ulimit -n 1024 # needed for micropython/tests/extmod/select_poll_fd.py
cd micropython
make -C ports/unix VARIANT=coverage test_full
(cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-multitests.py multi_net/*.py)
Expand Down
50 changes: 33 additions & 17 deletions bricks/_common/micropython.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ void pbsys_main_stop_program(bool force_stop) {
if (force_stop) {
mp_sched_vm_abort();
} else {
pyexec_system_exit = PYEXEC_FORCED_EXIT;

static mp_obj_exception_t system_exit;
system_exit.base.type = &mp_type_SystemExit;
system_exit.traceback_alloc = system_exit.traceback_len = 0;
Expand Down Expand Up @@ -106,9 +104,9 @@ static void mp_vfs_map_minimal_new_reader(mp_reader_t *reader, mp_vfs_map_minima
}

// Prints the exception that ended the program.
static void print_final_exception(mp_obj_t exc) {
static void print_final_exception(mp_obj_t exc, int ret) {
// Handle graceful stop with button.
if (pyexec_system_exit == PYEXEC_FORCED_EXIT &&
if ((ret & PYEXEC_FORCED_EXIT) &&
mp_obj_exception_match(exc, MP_OBJ_FROM_PTR(&mp_type_SystemExit))) {
mp_printf(&mp_plat_print, "The program was stopped (%q).\n",
((mp_obj_exception_t *)MP_OBJ_TO_PTR(exc))->base.type->name);
Expand All @@ -121,8 +119,9 @@ static void print_final_exception(mp_obj_t exc) {

#if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL
static void run_repl(void) {
int ret = 0;

readline_init0();
pyexec_system_exit = 0;

nlr_buf_t nlr;
nlr.ret_val = NULL;
Expand All @@ -134,12 +133,12 @@ static void run_repl(void) {
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
// Compatibility with mpremote.
mp_printf(&mp_plat_print, "MPY: soft reboot\n");
pyexec_raw_repl();
ret = pyexec_raw_repl();
} else {
pyexec_friendly_repl();
ret = pyexec_friendly_repl();
}
#else // PYBRICKS_OPT_RAW_REPL
pyexec_friendly_repl();
ret = pyexec_friendly_repl();
#endif // PYBRICKS_OPT_RAW_REPL
nlr_pop();
} else {
Expand All @@ -152,7 +151,7 @@ static void run_repl(void) {
// clear any pending exceptions (and run any callbacks).
mp_handle_pending(false);
// Print which exception triggered this.
print_final_exception(MP_OBJ_FROM_PTR(nlr.ret_val));
print_final_exception(MP_OBJ_FROM_PTR(nlr.ret_val), ret);
}

nlr_set_abort(NULL);
Expand All @@ -175,7 +174,7 @@ static void do_execute_raw_code(mp_module_context_t *context, const mp_raw_code_

nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_obj_t module_fun = mp_make_function_from_raw_code(rc, mc, NULL);
mp_obj_t module_fun = mp_make_function_from_proto_fun(rc, mc, NULL);
mp_call_function_0(module_fun);

// finish nlr block, restore context
Expand Down Expand Up @@ -241,7 +240,7 @@ static mpy_info_t *mpy_data_find(qstr name) {
* Runs the __main__ module from user RAM.
*/
static void run_user_program(void) {
pyexec_system_exit = 0;
int ret = 0;

nlr_buf_t nlr;
nlr.ret_val = NULL;
Expand All @@ -264,7 +263,7 @@ static void run_user_program(void) {
mp_compiled_module_t compiled_module;
compiled_module.context = context;
mp_raw_code_load(&reader, &compiled_module);
mp_obj_t module_fun = mp_make_function_from_raw_code(compiled_module.rc, context, NULL);
mp_obj_t module_fun = mp_make_function_from_proto_fun(compiled_module.rc, context, NULL);

// Run the script while letting CTRL-C interrupt it.
mp_hal_set_interrupt_char(CHAR_CTRL_C);
Expand All @@ -287,7 +286,12 @@ static void run_user_program(void) {
// Clear any pending exceptions (and run any callbacks).
mp_handle_pending(false);

print_final_exception(MP_OBJ_FROM_PTR(nlr.ret_val));
if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) {
// at the moment, the value of SystemExit is unused
ret = PYEXEC_FORCED_EXIT;
}

print_final_exception(MP_OBJ_FROM_PTR(nlr.ret_val), ret);

#if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL
// On KeyboardInterrupt, drop to REPL for debugging.
Expand Down Expand Up @@ -430,9 +434,21 @@ mp_obj_t pb_builtin_import(size_t n_args, const mp_obj_t *args) {
mp_raise_NotImplementedError(MP_ERROR_TEXT("relative import"));
}

// Check if module already exists, and return it if it does
// Check if the module is already loaded.
mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_VM(mp_loaded_modules_dict).map, args[0], MP_MAP_LOOKUP);
if (elem) {
return elem->value;
}

// Try the name directly as a non-extensible built-in (e.g. `micropython`).
qstr module_name_qstr = mp_obj_str_get_qstr(args[0]);
mp_obj_t module_obj = mp_module_get_loaded_or_builtin(module_name_qstr);
mp_obj_t module_obj = mp_module_get_builtin(module_name_qstr, false);
if (module_obj != MP_OBJ_NULL) {
return module_obj;
}

// Now try as an extensible built-in (e.g. `struct`/`ustruct`).
module_obj = mp_module_get_builtin(module_name_qstr, true);
if (module_obj != MP_OBJ_NULL) {
return module_obj;
}
Expand Down Expand Up @@ -473,7 +489,7 @@ mp_obj_t pb_builtin_import(size_t n_args, const mp_obj_t *args) {
mp_module_context_t *context = MP_OBJ_TO_PTR(module_obj);
const mp_frozen_module_t *frozen = modref;
context->constants = frozen->constants;
do_execute_raw_code(context, frozen->rc, context);
do_execute_raw_code(context, frozen->proto_fun, context);
return module_obj;
}
#endif
Expand All @@ -486,7 +502,7 @@ mp_import_stat_t mp_import_stat(const char *path) {
return MP_IMPORT_STAT_NO_EXIST;
}

mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
mp_raise_OSError(MP_ENOENT);
}

Expand Down
16 changes: 7 additions & 9 deletions bricks/_common/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
#define MICROPY_PY_MICROPYTHON (PYBRICKS_OPT_EXTRA_LEVEL1)
#define MICROPY_PY_STRUCT (PYBRICKS_OPT_EXTRA_LEVEL1)
#define MICROPY_PY_SYS (PYBRICKS_OPT_EXTRA_LEVEL1)
#define MICROPY_PY_UERRNO (1)
#define MICROPY_PY_UJSON (PYBRICKS_OPT_EXTRA_LEVEL1)
#define MICROPY_PY_URANDOM (PYBRICKS_OPT_EXTRA_LEVEL1)
#define MICROPY_PY_USELECT (PYBRICKS_OPT_EXTRA_LEVEL1)
#define MICROPY_PY_ERRNO (1)
#define MICROPY_PY_JSON (PYBRICKS_OPT_EXTRA_LEVEL1)
#define MICROPY_PY_RANDOM (PYBRICKS_OPT_EXTRA_LEVEL1)
#define MICROPY_PY_SELECT (PYBRICKS_OPT_EXTRA_LEVEL1)

#define MICROPY_PY_UERRNO_LIST \
#define MICROPY_PY_ERRNO_LIST \
X(EPERM) \
X(EIO) \
X(EBUSY) \
Expand Down Expand Up @@ -93,11 +93,9 @@
#define MICROPY_PY_SYS_STDFILES (PYBRICKS_OPT_EXTRA_LEVEL1)
#define MICROPY_PY_SYS_STDIO_BUFFER (PYBRICKS_OPT_EXTRA_LEVEL1)
#define MICROPY_PY_SYS_STDIO_FLUSH (PYBRICKS_OPT_EXTRA_LEVEL1)
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (PYBRICKS_OPT_EXTRA_LEVEL1)
#define MICROPY_PY_URANDOM_SEED_INIT_FUNC ({ extern uint32_t pbdrv_clock_get_us(void); pbdrv_clock_get_us(); })
#define MICROPY_PY_UTIME_MP_HAL (0)
#define MICROPY_PY_RANDOM_EXTRA_FUNCS (PYBRICKS_OPT_EXTRA_LEVEL1)
#define MICROPY_PY_RANDOM_SEED_INIT_FUNC ({ extern uint32_t pbdrv_clock_get_us(void); pbdrv_clock_get_us(); })
#define MICROPY_MODULE_BUILTIN_INIT (1)
#define MICROPY_MODULE_WEAK_LINKS (0)
#define MICROPY_CPYTHON_COMPAT (0)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
#if PYBRICKS_OPT_FLOAT
Expand Down
4 changes: 3 additions & 1 deletion bricks/_common_stm32/mphalport.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,13 @@ int mp_hal_stdin_rx_chr(void) {
}

// Send string of given length
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) {
while (pbsys_host_tx((const uint8_t *)str, len) == PBIO_ERROR_AGAIN) {
MICROPY_EVENT_POLL_HOOK
}
// Not raising the error. This means stdout lost if host is not connected.

return len;
}

void mp_hal_stdout_tx_flush(void) {
Expand Down
18 changes: 12 additions & 6 deletions bricks/ev3/make_bootable_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@


def make_firmware(uboot_blob: bytes, uimage_blob: bytes) -> bytes:

if len(uboot_blob) > UBOOT_MAX_SIZE:
print(
f"u-boot file is bigger than 256KiB ({len(uboot_blob)} bytes), it is not safe to use.",
Expand All @@ -32,13 +31,18 @@ def make_firmware(uboot_blob: bytes, uimage_blob: bytes) -> bytes:
exit(1)

if len(uimage_blob) > UIMAGE_MAX_SIZE:
print(f"uImage file is too big ({len(uimage_blob)} > {UIMAGE_MAX_SIZE}).", file=sys.stderr)
print(
f"uImage file is too big ({len(uimage_blob)} > {UIMAGE_MAX_SIZE}).",
file=sys.stderr,
)
exit(1)

# Gets combined size, rounded to nearest expected size.
combined_size = UIMAGE_OFFSET + len(uimage_blob)
combined_size = (
(combined_size + FIRMWARE_ROUND_SIZE) // FIRMWARE_ROUND_SIZE * FIRMWARE_ROUND_SIZE
(combined_size + FIRMWARE_ROUND_SIZE)
// FIRMWARE_ROUND_SIZE
* FIRMWARE_ROUND_SIZE
)

# Put it all together.
Expand All @@ -59,9 +63,11 @@ def make_firmware(uboot_blob: bytes, uimage_blob: bytes) -> bytes:
parser.add_argument("output", help="The output file")
args = parser.parse_args()

with open(args.uboot, "rb") as uboot_file, open(args.uimage, "rb") as uimage_file, open(
args.output, "wb"
) as output_file:
with (
open(args.uboot, "rb") as uboot_file,
open(args.uimage, "rb") as uimage_file,
open(args.output, "wb") as output_file,
):
combined = make_firmware(uboot_file.read(), uimage_file.read())
output_file.write(combined)
print(f"Created {args.output} with size {len(combined) // 1024} KB.")
4 changes: 3 additions & 1 deletion bricks/ev3/mphalport.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ int mp_hal_stdin_rx_chr(void) {

extern uint32_t pbdrv_usb_write(const uint8_t *data, uint32_t size);

void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) {
pbdrv_uart_debug_printf("%.*s", len, str);

uint32_t done = 0;
Expand All @@ -69,6 +69,8 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
while (!pbdrv_uart_debug_is_done()) {
MICROPY_VM_HOOK_LOOP;
}

return len;
}

extern void pbdrv_usb_tx_flush(void);
Expand Down
6 changes: 4 additions & 2 deletions bricks/nxt/mphalport.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,19 @@ int mp_hal_stdin_rx_chr(void) {
}

// Send string of given length
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) {

// Nothing to do if disconnected or empty data
if (!nx_bt_stream_opened() || len == 0) {
return;
return len;
}

nx_bt_stream_write((uint8_t *)str, len);
while (!nx_bt_stream_data_written()) {
MICROPY_EVENT_POLL_HOOK;
}

return len;
}

void mp_hal_stdout_tx_flush(void) {
Expand Down
6 changes: 3 additions & 3 deletions bricks/primehub/modules/_imu_calibrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,21 @@ def wait_for_stationary(side):


def roll_over_axis(axis, new_side):

global bias, bias_count

print("Roll it towards you, without lifting the hub up!")

angle_start = hub.imu.rotation(axis, calibrated=False)
while hub.imu.up(calibrated=False) != new_side or not hub.imu.stationary():

_, _, z = hub.imu.orientation() * axis
if abs(z) > 0.07:
print(hub.imu.orientation() * axis)
raise RuntimeError("Lifted it!")
wait(100)

uncalibrated_90_deg_rotation = abs(hub.imu.rotation(axis, calibrated=False) - angle_start)
uncalibrated_90_deg_rotation = abs(
hub.imu.rotation(axis, calibrated=False) - angle_start
)
if abs(uncalibrated_90_deg_rotation - 90) > 10:
raise RuntimeError("Not 90 deg!")

Expand Down
13 changes: 7 additions & 6 deletions bricks/virtualhub/mpconfigvariant.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,24 @@
#define MICROPY_DEBUG_PRINTERS (1)
#define MICROPY_MODULE_ATTR_DELEGATION (1)
#define MICROPY_MODULE_BUILTIN_INIT (1)
#define MICROPY_MODULE_BUILTIN_SUBPACKAGES (1)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
#define MICROPY_PY_BUILTINS_HELP (1)
#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
#define MICROPY_PY_SYS_SETTRACE (1)
#define MICROPY_PY_UERRNO (1)
#define MICROPY_PY_UOS (1)
#define MICROPY_PY_UOS_GETENV_PUTENV_UNSETENV (1)
#define MICROPY_PY_UOS_INCLUDEFILE "ports/unix/moduos.c"
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
#define MICROPY_PY_ERRNO (1)
#define MICROPY_PY_OS (1)
#define MICROPY_PY_OS_GETENV_PUTENV_UNSETENV (1)
#define MICROPY_PY_OS_INCLUDEFILE "ports/unix/modos.c"
#define MICROPY_PY_RANDOM_EXTRA_FUNCS (1)
#define MICROPY_PY_BUILTINS_SLICE_INDICES (1)
#define MICROPY_PERSISTENT_CODE_SAVE (1)
#define MICROPY_STREAMS_POSIX_API (1)
#define MICROPY_HELPER_REPL (1)
#define MICROPY_KBD_EXCEPTION (1)

// REVISIT: This list currently matches the stm32 builds.
#define MICROPY_PY_UERRNO_LIST \
#define MICROPY_PY_ERRNO_LIST \
X(EPERM) \
X(EIO) \
X(EBUSY) \
Expand Down
4 changes: 2 additions & 2 deletions bricks/virtualhub/mpconfigvariant.mk
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ MICROPY_PY_SOCKET = 1
# ffi module requires libffi (libffi-dev Debian package)
MICROPY_PY_FFI = 1

# ussl module requires one of the TLS libraries below
MICROPY_PY_USSL = 0
# ssl module requires one of the TLS libraries below
MICROPY_PY_SSL = 0
# axTLS has minimal size but implements only a subset of modern TLS
# functionality, so may have problems with some servers.
MICROPY_SSL_AXTLS = 0
Expand Down
Loading