From 42d64cb963e191fd573745729984ba0c76c21a17 Mon Sep 17 00:00:00 2001 From: Laurens Valk Date: Wed, 28 Aug 2024 11:25:48 +0200 Subject: [PATCH] pbio/sys/protocol: Use single byte for program ID. This will let us include it in the hub status for monitoring by Pybricks Code. Use it for both downloaded and builtin user programs. Also restore the original START_REPL and START_PROGRAMS, and instead introduce a new command for starting both builtin and downloaded user programs. The previous modifications had not been released yet. --- CHANGELOG.md | 8 ++ bricks/_common/micropython.c | 110 +++++++++--------- bricks/ev3rt/app.c | 2 +- lib/pbio/include/pbio/protocol.h | 99 ++++++++++++---- lib/pbio/include/pbsys/config.h | 8 +- lib/pbio/include/pbsys/main.h | 21 +--- lib/pbio/platform/city_hub/pbsysconfig.h | 8 +- lib/pbio/platform/essential_hub/pbsysconfig.h | 8 +- lib/pbio/platform/ev3/pbsysconfig.h | 8 +- lib/pbio/platform/ev3rt/pbsysconfig.h | 8 +- lib/pbio/platform/move_hub/pbsysconfig.h | 8 +- lib/pbio/platform/nxt/pbsysconfig.h | 5 + lib/pbio/platform/prime_hub/pbsysconfig.h | 8 +- lib/pbio/platform/technic_hub/pbsysconfig.h | 8 +- lib/pbio/platform/test/pbsysconfig.h | 8 +- lib/pbio/sys/command.c | 43 ++++--- lib/pbio/sys/hmi.c | 7 +- lib/pbio/sys/main.c | 5 +- 18 files changed, 223 insertions(+), 149 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 971f6d4ae..a736bb65d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,9 +13,16 @@ correction of the `hub.imu.heading()` value ([support#1678]). - Added `update_heading_correction` to interactively set the heading correction value ([support#1678]). +- Added command to start downloaded or builtin user program with a one byte + program identifier. The existing START_PROGRAM and START_REPL are special + cases of this new more generic command, but will remain available for + backwards compatibility. For now, this is added to start various builtin + programs, but it prepares for the ability to start different downloaded + programs too ([pybricks-micropython#254]). ### Changed +- Changed protocol to Pybricks Profile v1.4.0. - When upgrading the firmware to a new version, the user program will now be erased. This avoids issues with incompatible program files ([support#1622]). - The `angular_velocity_threshold`, and `acceleration_threshold` settings @@ -40,6 +47,7 @@ [pybricks-micropython#250]: https://github.com/pybricks/pybricks-micropython/pull/250 [pybricks-micropython#253]: https://github.com/pybricks/pybricks-micropython/pull/253 +[pybricks-micropython#254]: https://github.com/pybricks/pybricks-micropython/pull/254 [support#1429]: https://github.com/pybricks/support/issues/1429 [support#1460]: https://github.com/pybricks/support/issues/1460 [support#1615]: https://github.com/pybricks/support/issues/1615 diff --git a/bricks/_common/micropython.c b/bricks/_common/micropython.c index ef2ca1fd9..6ddc1084d 100644 --- a/bricks/_common/micropython.c +++ b/bricks/_common/micropython.c @@ -117,7 +117,7 @@ static void print_final_exception(mp_obj_t exc) { mp_obj_print_exception(&mp_plat_print, exc); } -#if PYBRICKS_OPT_COMPILER +#if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL static void run_repl(void) { readline_init0(); pyexec_system_exit = 0; @@ -145,7 +145,7 @@ static void run_repl(void) { nlr_set_abort(NULL); } -#endif +#endif // PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL // From micropython/py/builtinimport.c, but copied because it is static. static void do_execute_raw_code(mp_module_context_t *context, const mp_raw_code_t *rc, const mp_module_context_t *mc) { @@ -277,7 +277,7 @@ static void run_user_program(void) { print_final_exception(MP_OBJ_FROM_PTR(nlr.ret_val)); - #if PYBRICKS_OPT_COMPILER + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL // On KeyboardInterrupt, drop to REPL for debugging. if (mp_obj_exception_match(MP_OBJ_FROM_PTR(nlr.ret_val), MP_OBJ_FROM_PTR(&mp_type_KeyboardInterrupt))) { @@ -289,47 +289,39 @@ static void run_user_program(void) { // Enter REPL. run_repl(); } - #endif + #endif // PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL } nlr_set_abort(NULL); } -/** - * Builtin Pybricks MicroPython program identifiers. - */ -typedef enum { - /** - * The MicroPython REPL. - */ - PYBRICKS_MICROPYTHON_BUILTIN_USER_PROGRAM_ID_REPL = 0, - /** - * Program that detects attached devices, displays sensor values, and - * relays sensor data to host if connected. - */ - PYBRICKS_MICROPYTHON_BUILTIN_USER_PROGRAM_ID_PORT_VIEW = 1, - /** - * The number of builtin user programs. - */ - PYBRICKS_MICROPYTHON_BUILTIN_USER_PROGRAM_NUMBER_OF_PROGRAMS, -} pybricks_micropython_builtin_user_program_id_t; - pbio_error_t pbsys_main_program_validate(pbsys_main_program_t *program) { - // Validate builtin user programs for existence. - if (program->type == PBSYS_MAIN_PROGRAM_TYPE_BUILTIN) { - #if PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS - if (program->id < PYBRICKS_MICROPYTHON_BUILTIN_USER_PROGRAM_NUMBER_OF_PROGRAMS) { - return PBIO_SUCCESS; - } - #endif + // For builtin programs, check requested ID against feature flags. + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL + if (program->id == PBIO_PYBRICKS_USER_PROGRAM_ID_REPL) { + return PBIO_SUCCESS; + } + #endif + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW + if (program->id == PBIO_PYBRICKS_USER_PROGRAM_ID_PORT_VIEW) { + return PBIO_SUCCESS; + } + #endif + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION + if (program->id == PBIO_PYBRICKS_USER_PROGRAM_ID_IMU_CALIBRATION) { + return PBIO_SUCCESS; + } + #endif + + // Only user program 0 is supported for now. + if (program->id != PBIO_PYBRICKS_USER_PROGRAM_ID_FIRST_SLOT) { return PBIO_ERROR_NOT_SUPPORTED; } // If requesting a user program, ensure that it exists and is valid. - // Currently, only programs on slot 0 are supported. uint32_t program_size = program->code_end - program->code_start; - if (program->id != 0 || program_size == 0 || program_size > PBSYS_STORAGE_MAX_PROGRAM_SIZE) { + if (program_size == 0 || program_size > PBSYS_STORAGE_MAX_PROGRAM_SIZE) { return PBIO_ERROR_NOT_SUPPORTED; } @@ -361,31 +353,37 @@ void pbsys_main_run_program(pbsys_main_program_t *program) { // Initialize MicroPython. mp_init(); - // Check for run type. - if (program->type == PBSYS_MAIN_PROGRAM_TYPE_USER) { - // Init Pybricks package without auto-import. - pb_package_pybricks_init(false); - // Run loaded user program. - run_user_program(); - } - #if PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS - else { - switch (program->id) { - case PYBRICKS_MICROPYTHON_BUILTIN_USER_PROGRAM_ID_REPL: - // Run REPL with everything auto-imported. - pb_package_pybricks_init(true); - run_repl(); - break; - case PYBRICKS_MICROPYTHON_BUILTIN_USER_PROGRAM_ID_PORT_VIEW: - pyexec_frozen_module("_builtin_port_view.py", false); - break; - default: - // Existence was already validated above, so just quietly exit - // since we can't get here. - break; - } + // Runs the requested downloaded or builtin user program. + switch (program->id) { + + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL + case PBIO_PYBRICKS_USER_PROGRAM_ID_REPL: + // Run REPL with everything auto-imported. + pb_package_pybricks_init(true); + run_repl(); + break; + #endif + + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW + case PBIO_PYBRICKS_USER_PROGRAM_ID_PORT_VIEW: + pb_package_pybricks_init(false); + pyexec_frozen_module("_builtin_port_view.py", false); + break; + #endif + + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION + case PBIO_PYBRICKS_USER_PROGRAM_ID_IMU_CALIBRATION: + // Todo + break; + #endif + + default: + // Init Pybricks package without auto-import. + pb_package_pybricks_init(false); + // Run loaded user program (just slot 0 for now). + run_user_program(); + break; } - #endif // PYBRICKS_OPT_COMPILER // De-init bluetooth resources (including flushing stdout) that may use // memory allocated by MicroPython before we wipe it. diff --git a/bricks/ev3rt/app.c b/bricks/ev3rt/app.c index 93b5ee486..f559aac67 100644 --- a/bricks/ev3rt/app.c +++ b/bricks/ev3rt/app.c @@ -26,7 +26,7 @@ void main_task(intptr_t unused) { while (true) { pbsys_main_program_t program = { - .type = PBSYS_MAIN_PROGRAM_TYPE_BUILTIN, + .id = PBIO_PYBRICKS_USER_PROGRAM_ID_REPL, .code_end = heap, .data_end = heap + sizeof(heap), }; diff --git a/lib/pbio/include/pbio/protocol.h b/lib/pbio/include/pbio/protocol.h index 6a2b9826d..bae7dbaa6 100644 --- a/lib/pbio/include/pbio/protocol.h +++ b/lib/pbio/include/pbio/protocol.h @@ -39,6 +39,38 @@ PBIO_XSTR(PBIO_PROTOCOL_VERSION_MINOR) "." \ PBIO_XSTR(PBIO_PROTOCOL_VERSION_PATCH) + +/** + * User program identifiers. + * + * 0--127: Downloadabled user programs. + * 128--255: Builtin user programs. + */ +typedef enum { + /** + * First possible downloadable user program. + */ + PBIO_PYBRICKS_USER_PROGRAM_ID_FIRST_SLOT = 0, + /** + * Last possible downloadable user program. + */ + PBIO_PYBRICKS_USER_PROGRAM_ID_LAST_SLOT = 127, + /** + * Read-eval-print loop (REPL) interface. + */ + PBIO_PYBRICKS_USER_PROGRAM_ID_REPL = 128, + /** + * Program that detects attached devices, displays sensor values, and + * relays sensor data to host if connected. + */ + PBIO_PYBRICKS_USER_PROGRAM_ID_PORT_VIEW = 129, + /** + * Program that calibrates the internal inertial measurement unit and saves + * data persistently on the hub. + */ + PBIO_PYBRICKS_USER_PROGRAM_ID_IMU_CALIBRATION = 130, +} pbio_pybricks_user_program_id_t; + /** * Pybricks command types. * @@ -53,36 +85,28 @@ typedef enum { PBIO_PYBRICKS_COMMAND_STOP_USER_PROGRAM = 0, /** - * Requests that a specified user program should be started. - * - * Parameters: - * - id (optional): The identifier of the user program (32-bit little-endian unsigned integer). - * Defaults to 0 if no identifier is provided. - * This optional parameter was introduced in Pybricks Profile v1.4.0 + * Requests that the user program should be started. * * Errors: - * - ::PBIO_PYBRICKS_ERROR_BUSY if a program is already running. - * - ::PBIO_PYBRICKS_ERROR_INVALID_COMMAND if the builtin user program is not available (Since Pybricks Profile v1.4.0). + * - ::PBIO_PYBRICKS_ERROR_BUSY if another program is already running. * * @since Pybricks Profile v1.2.0 + * @deprecated in Pybricks Profile v1.4.0. + * Use ::PBIO_PYBRICKS_COMMAND_START_USER_OR_BUILTIN_PROGRAM instead. */ PBIO_PYBRICKS_COMMAND_START_USER_PROGRAM = 1, /** - * Requests that a specified builtin user program should be started. - * - * Parameters: - * - id (optional): The identifier of the builtin user program (32-bit little-endian unsigned integer). - * Defaults to 0 if no identifier is provided. - * This optional parameter was introduced in Pybricks Profile v1.4.0 + * Requests that the REPL should be started. * * Errors: - * - ::PBIO_PYBRICKS_ERROR_BUSY if a program is already running. - * - ::PBIO_PYBRICKS_ERROR_INVALID_COMMAND if the builtin user program is not available (Since Pybricks Profile v1.4.0). + * - ::PBIO_PYBRICKS_ERROR_BUSY if another program is already running. * * @since Pybricks Profile v1.2.0 + * @deprecated in Pybricks Profile v1.4.0. + * Use ::PBIO_PYBRICKS_COMMAND_START_USER_OR_BUILTIN_PROGRAM instead. */ - PBIO_PYBRICKS_COMMAND_START_BUILTIN_USER_PROGRAM = 2, + PBIO_PYBRICKS_COMMAND_START_REPL = 2, /** * Requests to write user program metadata. @@ -159,8 +183,24 @@ typedef enum { * @since Pybricks Profile v1.4.0 */ PBIO_PYBRICKS_COMMAND_WRITE_APP_DATA = 7, -} pbio_pybricks_command_t; + /** + * Requests that a previously downloaded user program or builtin user + * program is started. + * + * Parameters: + * - payload: Program identifier (one byte). Slots 0--127 are reserved for + * downloaded user programs. Slots 128--255 are for builtin user + * programs. + * + * Errors: + * - ::PBIO_PYBRICKS_ERROR_BUSY if another program is already running. + * - ::PBIO_PYBRICKS_ERROR_INVALID_COMMAND if the requested program is not available. + * + * @since Pybricks Profile v1.4.0. + */ + PBIO_PYBRICKS_COMMAND_START_USER_OR_BUILTIN_PROGRAM = 8, +} pbio_pybricks_command_t; /** * Application-specific error codes that are used in ATT_ERROR_RSP. */ @@ -310,14 +350,11 @@ typedef enum { // NB: the values are part of the protocol, so don't change the values! /** - * Hub supports builtin user programs, such as an interactive REPL or Port View. - * - * Prior to version 1.4.0 this flag was exclusively used to indicate REPL - * support since there were no other builtin user programs. + * Hub supports interactive REPL. * * @since Pybricks Profile v1.2.0. */ - PBIO_PYBRICKS_FEATURE_BUILTIN_USER_PROGRAMS = 1 << 0, + PBIO_PYBRICKS_FEATURE_FLAG_BUILTIN_USER_PROGRAM_REPL = 1 << 0, /** * Hub supports user program with multiple MicroPython .mpy files ABI v6 * @@ -326,14 +363,26 @@ typedef enum { * * @since Pybricks Profile v1.2.0. */ - PBIO_PYBRICKS_FEATURE_USER_PROG_FORMAT_MULTI_MPY_V6 = 1 << 1, + PBIO_PYBRICKS_FEATURE_FLAG_USER_PROG_FORMAT_MULTI_MPY_V6 = 1 << 1, /** * Hub supports user program with multiple MicroPython .mpy files ABI v6.1 * including native module support. * * @since Pybricks Profile v1.3.0. */ - PBIO_PYBRICKS_FEATURE_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE = 1 << 2, + PBIO_PYBRICKS_FEATURE_FLAG_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE = 1 << 2, + /** + * Hub supports builtin sensor port view monitoring program. + * + * @since Pybricks Profile v1.4.0. + */ + PBIO_PYBRICKS_FEATURE_FLAG_BUILTIN_USER_PROGRAM_PORT_VIEW = 1 << 3, + /** + * Hub supports builtin IMU calibration program. + * + * @since Pybricks Profile v1.4.0. + */ + PBIO_PYBRICKS_FEATURE_FLAG_BUILTIN_USER_PROGRAM_IMU_CALIBRATION = 1 << 4, } pbio_pybricks_feature_flags_t; void pbio_pybricks_hub_capabilities(uint8_t *buf, diff --git a/lib/pbio/include/pbsys/config.h b/lib/pbio/include/pbsys/config.h index ba27b3dab..5c10a2730 100644 --- a/lib/pbio/include/pbsys/config.h +++ b/lib/pbio/include/pbsys/config.h @@ -11,9 +11,11 @@ #include #define PBSYS_CONFIG_APP_FEATURE_FLAGS (0 \ - + PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS * PBIO_PYBRICKS_FEATURE_BUILTIN_USER_PROGRAMS \ - + PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 * PBIO_PYBRICKS_FEATURE_USER_PROG_FORMAT_MULTI_MPY_V6 \ - + PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE * PBIO_PYBRICKS_FEATURE_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE \ + + PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL * PBIO_PYBRICKS_FEATURE_FLAG_BUILTIN_USER_PROGRAM_REPL \ + + PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW * PBIO_PYBRICKS_FEATURE_FLAG_BUILTIN_USER_PROGRAM_PORT_VIEW \ + + PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION * PBIO_PYBRICKS_FEATURE_FLAG_BUILTIN_USER_PROGRAM_IMU_CALIBRATION \ + + PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 * PBIO_PYBRICKS_FEATURE_FLAG_USER_PROG_FORMAT_MULTI_MPY_V6 \ + + PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE * PBIO_PYBRICKS_FEATURE_FLAG_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE \ ) // When set to (1) PBSYS_CONFIG_STATUS_LIGHT indicates that a hub has a hub status light diff --git a/lib/pbio/include/pbsys/main.h b/lib/pbio/include/pbsys/main.h index e22cc1597..97fe4ebcd 100644 --- a/lib/pbio/include/pbsys/main.h +++ b/lib/pbio/include/pbsys/main.h @@ -16,14 +16,6 @@ #include #include -/** - * Main program types. - */ -typedef enum { - PBSYS_MAIN_PROGRAM_TYPE_USER, // User-defined program - PBSYS_MAIN_PROGRAM_TYPE_BUILTIN // Built-in program -} pbsys_main_program_type_t; - /** * Main application program data information. */ @@ -41,14 +33,9 @@ typedef struct _pbsys_main_program_t { */ void *data_end; /** - * Program identifier (selects one user program or one of the builtins). - */ - uint32_t id; - /** - * Whether to run an application-specific builtin user program instead of the - * program given by the data. The builtin user program may still use the data. + * User program identifier. */ - pbsys_main_program_type_t type; + pbio_pybricks_user_program_id_t id; /** * Whether a request was made to start the program. */ @@ -57,7 +44,7 @@ typedef struct _pbsys_main_program_t { #if PBSYS_CONFIG_MAIN -pbio_error_t pbsys_main_program_request_start(pbsys_main_program_type_t type, uint32_t id); +pbio_error_t pbsys_main_program_request_start(pbio_pybricks_user_program_id_t id); /** * Validates the program that is being requested to start. @@ -101,7 +88,7 @@ bool pbsys_main_stdin_event(uint8_t c); #else // PBSYS_CONFIG_MAIN -static inline pbio_error_t pbsys_main_program_request_start(pbsys_main_program_type_t type, uint32_t id) { +static inline pbio_error_t pbsys_main_program_request_start(pbio_pybricks_user_program_id_t id) { return PBIO_ERROR_NOT_SUPPORTED; } diff --git a/lib/pbio/platform/city_hub/pbsysconfig.h b/lib/pbio/platform/city_hub/pbsysconfig.h index aa7459ccb..72ba157de 100644 --- a/lib/pbio/platform/city_hub/pbsysconfig.h +++ b/lib/pbio/platform/city_hub/pbsysconfig.h @@ -3,9 +3,11 @@ #include "pbdrvconfig.h" -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (0) #define PBSYS_CONFIG_BATTERY_CHARGER (0) #define PBSYS_CONFIG_BLUETOOTH (1) #define PBSYS_CONFIG_HUB_LIGHT_MATRIX (0) diff --git a/lib/pbio/platform/essential_hub/pbsysconfig.h b/lib/pbio/platform/essential_hub/pbsysconfig.h index 9a2ecd785..7726dd886 100644 --- a/lib/pbio/platform/essential_hub/pbsysconfig.h +++ b/lib/pbio/platform/essential_hub/pbsysconfig.h @@ -1,9 +1,11 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2021-2023 The Pybricks Authors -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (1) #define PBSYS_CONFIG_BATTERY_CHARGER (1) #define PBSYS_CONFIG_BLUETOOTH (1) #define PBSYS_CONFIG_HUB_LIGHT_MATRIX (0) diff --git a/lib/pbio/platform/ev3/pbsysconfig.h b/lib/pbio/platform/ev3/pbsysconfig.h index 1a82f5535..90a8bba36 100644 --- a/lib/pbio/platform/ev3/pbsysconfig.h +++ b/lib/pbio/platform/ev3/pbsysconfig.h @@ -1,9 +1,11 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2020-2024 The Pybricks Authors -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (0) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (0) #define PBSYS_CONFIG_MAIN (1) #define PBSYS_CONFIG_STORAGE (1) #define PBSYS_CONFIG_STORAGE_RAM_SIZE (10 * 1024) diff --git a/lib/pbio/platform/ev3rt/pbsysconfig.h b/lib/pbio/platform/ev3rt/pbsysconfig.h index 0e9900a1a..78bb8d799 100644 --- a/lib/pbio/platform/ev3rt/pbsysconfig.h +++ b/lib/pbio/platform/ev3rt/pbsysconfig.h @@ -1,9 +1,11 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2020-2023 The Pybricks Authors -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (0) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (0) #define PBSYS_CONFIG_BATTERY_CHARGER (0) #define PBSYS_CONFIG_BLUETOOTH (0) #define PBSYS_CONFIG_HUB_LIGHT_MATRIX (0) diff --git a/lib/pbio/platform/move_hub/pbsysconfig.h b/lib/pbio/platform/move_hub/pbsysconfig.h index 48ba8fb3f..c26beba8e 100644 --- a/lib/pbio/platform/move_hub/pbsysconfig.h +++ b/lib/pbio/platform/move_hub/pbsysconfig.h @@ -3,9 +3,11 @@ #include "pbdrvconfig.h" -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (0) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (0) #define PBSYS_CONFIG_BATTERY_CHARGER (0) #define PBSYS_CONFIG_BLUETOOTH (1) #define PBSYS_CONFIG_HUB_LIGHT_MATRIX (0) diff --git a/lib/pbio/platform/nxt/pbsysconfig.h b/lib/pbio/platform/nxt/pbsysconfig.h index 381dc993e..b5a11f5e3 100644 --- a/lib/pbio/platform/nxt/pbsysconfig.h +++ b/lib/pbio/platform/nxt/pbsysconfig.h @@ -1,6 +1,11 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2020-2023 The Pybricks Authors +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (0) #define PBSYS_CONFIG_MAIN (1) #define PBSYS_CONFIG_STORAGE (1) #define PBSYS_CONFIG_STORAGE_RAM_SIZE (10 * 1024) diff --git a/lib/pbio/platform/prime_hub/pbsysconfig.h b/lib/pbio/platform/prime_hub/pbsysconfig.h index bd1684420..d5f744ab9 100644 --- a/lib/pbio/platform/prime_hub/pbsysconfig.h +++ b/lib/pbio/platform/prime_hub/pbsysconfig.h @@ -1,9 +1,11 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2020-2023 The Pybricks Authors -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (1) #define PBSYS_CONFIG_BATTERY_CHARGER (1) #define PBSYS_CONFIG_BLUETOOTH (1) #define PBSYS_CONFIG_BLUETOOTH_TOGGLE (1) diff --git a/lib/pbio/platform/technic_hub/pbsysconfig.h b/lib/pbio/platform/technic_hub/pbsysconfig.h index b01ef1e8e..0b77fb356 100644 --- a/lib/pbio/platform/technic_hub/pbsysconfig.h +++ b/lib/pbio/platform/technic_hub/pbsysconfig.h @@ -3,9 +3,11 @@ #include "pbdrvconfig.h" -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (1) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (1) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (0) #define PBSYS_CONFIG_BATTERY_CHARGER (0) #define PBSYS_CONFIG_BLUETOOTH (1) #define PBSYS_CONFIG_HUB_LIGHT_MATRIX (0) diff --git a/lib/pbio/platform/test/pbsysconfig.h b/lib/pbio/platform/test/pbsysconfig.h index 3da4eba60..2f3523848 100644 --- a/lib/pbio/platform/test/pbsysconfig.h +++ b/lib/pbio/platform/test/pbsysconfig.h @@ -1,9 +1,11 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2020-2023 The Pybricks Authors -#define PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS (0) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6 (0) -#define PBSYS_CONFIG_APP_USER_PROG_FORMAT_MULTI_MPY_V6_1_NATIVE (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_PORT_VIEW (0) +#define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (0) +#define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_1_NATIVE (0) #define PBSYS_CONFIG_BLUETOOTH (1) #define PBSYS_CONFIG_HUB_LIGHT_MATRIX (1) #define PBSYS_CONFIG_MAIN (0) diff --git a/lib/pbio/sys/command.c b/lib/pbio/sys/command.c index 638efc9e5..c9f0a1bdf 100644 --- a/lib/pbio/sys/command.c +++ b/lib/pbio/sys/command.c @@ -37,36 +37,37 @@ pbio_pybricks_error_t pbsys_command(const uint8_t *data, uint32_t size) { pbio_pybricks_command_t cmd = data[0]; switch (cmd) { + case PBIO_PYBRICKS_COMMAND_STOP_USER_PROGRAM: pbsys_program_stop(false); return PBIO_PYBRICKS_ERROR_OK; - case PBIO_PYBRICKS_COMMAND_START_USER_PROGRAM: { - uint32_t id = 0; - if (size == (1 + sizeof(uint32_t))) { - id = pbio_get_uint32_le(&data[1]); - } + + case PBIO_PYBRICKS_COMMAND_START_USER_PROGRAM: + // Deprecated. For backwards compatibility with Pybricks + // Profile < v1.4.0, assume we should start user program 0. return pbio_pybricks_error_from_pbio_error( - pbsys_main_program_request_start(PBSYS_MAIN_PROGRAM_TYPE_USER, id)); - } - #if PBSYS_CONFIG_APP_BUILTIN_USER_PROGRAMS - case PBIO_PYBRICKS_COMMAND_START_BUILTIN_USER_PROGRAM: { - uint32_t id = 0; - if (size == (1 + sizeof(uint32_t))) { - id = pbio_get_uint32_le(&data[1]); - } + pbsys_main_program_request_start(PBIO_PYBRICKS_USER_PROGRAM_ID_FIRST_SLOT)); + + #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL + case PBIO_PYBRICKS_COMMAND_START_REPL: + // Deprecated. For backwards compatibility with Pybricks + // Profile < v1.4.0, make it work anyway. return pbio_pybricks_error_from_pbio_error( - pbsys_main_program_request_start(PBSYS_MAIN_PROGRAM_TYPE_BUILTIN, id)); - } - #endif // PBIO_PYBRICKS_FEATURE_TEST(PBIO_PYBRICKS_FEATURE_BUILTIN_USER_PROGRAMS) + pbsys_main_program_request_start(PBIO_PYBRICKS_USER_PROGRAM_ID_REPL)); + #endif // PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL + case PBIO_PYBRICKS_COMMAND_WRITE_USER_PROGRAM_META: return pbio_pybricks_error_from_pbio_error(pbsys_storage_set_program_size( pbio_get_uint32_le(&data[1]))); + case PBIO_PYBRICKS_COMMAND_WRITE_USER_RAM: return pbio_pybricks_error_from_pbio_error(pbsys_storage_set_program_data( pbio_get_uint32_le(&data[1]), &data[5], size - 5)); + case PBIO_PYBRICKS_COMMAND_REBOOT_TO_UPDATE_MODE: pbdrv_reset(PBDRV_RESET_ACTION_RESET_IN_UPDATE_MODE); return PBIO_PYBRICKS_ERROR_OK; + case PBIO_PYBRICKS_COMMAND_WRITE_STDIN: #if PBSYS_CONFIG_BLUETOOTH if (pbsys_bluetooth_rx_get_free() < size - 1) { @@ -76,6 +77,7 @@ pbio_pybricks_error_t pbsys_command(const uint8_t *data, uint32_t size) { #endif // If no consumers are configured, goes to "/dev/null" without error return PBIO_PYBRICKS_ERROR_OK; + case PBIO_PYBRICKS_COMMAND_WRITE_APP_DATA: { if (!write_app_data_callback) { // No errors when no consumer is configured. This avoids errors @@ -93,6 +95,15 @@ pbio_pybricks_error_t pbsys_command(const uint8_t *data, uint32_t size) { const uint8_t *data_to_write = &data[3]; return pbio_pybricks_error_from_pbio_error(write_app_data_callback(offset, data_size, data_to_write)); } + + case PBIO_PYBRICKS_COMMAND_START_USER_OR_BUILTIN_PROGRAM: + // Identifier payload required + if (size != 2) { + return PBIO_PYBRICKS_ERROR_VALUE_NOT_ALLOWED; + } + return pbio_pybricks_error_from_pbio_error( + pbsys_main_program_request_start(data[1])); + default: return PBIO_PYBRICKS_ERROR_INVALID_COMMAND; } diff --git a/lib/pbio/sys/hmi.c b/lib/pbio/sys/hmi.c index 9558e1d39..e26844ce8 100644 --- a/lib/pbio/sys/hmi.c +++ b/lib/pbio/sys/hmi.c @@ -50,9 +50,10 @@ static PT_THREAD(update_program_run_button_wait_state(bool button_pressed)) { PT_WAIT_UNTIL(pt, button_pressed); PT_WAIT_UNTIL(pt, !button_pressed); - // if we made it through a full press and release, without the user - // program running, then start the user program - pbsys_main_program_request_start(PBSYS_MAIN_PROGRAM_TYPE_USER, 0); + // If we made it through a full press and release, without the user + // program running, then start the user program. There is no UI for + // multiple programs yet, so start the one and only program. + pbsys_main_program_request_start(PBIO_PYBRICKS_USER_PROGRAM_ID_FIRST_SLOT); } PT_END(pt); diff --git a/lib/pbio/sys/main.c b/lib/pbio/sys/main.c index 6636dfcda..a668abbbf 100644 --- a/lib/pbio/sys/main.c +++ b/lib/pbio/sys/main.c @@ -22,8 +22,6 @@ static pbsys_main_program_t program; -#include - /** * Requests to start the main user application program. * @@ -33,14 +31,13 @@ static pbsys_main_program_t program; * ::PBIO_ERROR_NOT_SUPPORTED if the program is not available. * Otherwise ::PBIO_SUCCESS. */ -pbio_error_t pbsys_main_program_request_start(pbsys_main_program_type_t type, uint32_t id) { +pbio_error_t pbsys_main_program_request_start(pbio_pybricks_user_program_id_t id) { // Can't start new program if already running or new requested. if (pbsys_status_test(PBIO_PYBRICKS_STATUS_USER_PROGRAM_RUNNING) || program.start_requested) { return PBIO_ERROR_BUSY; } - program.type = type; program.id = id; // Builtin user programs are also allowed to access user program,