diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index faf243f112..4b9799fbe3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -303,6 +303,7 @@ jobs: - "metro_m4_express" - "metro_m7_1011" - "metro_nrf52840_express" + - "microbit_v2" - "mini_sam_m4" - "monster_m4sk" - "ndgarage_ndbit6" diff --git a/README.rst b/README.rst index 7b8919db1f..86c5660417 100644 --- a/README.rst +++ b/README.rst @@ -14,25 +14,30 @@ CircuitPython computers called microcontrollers. Microcontrollers are the brains of many electronics including a wide variety of development boards used to build hobby projects and prototypes. CircuitPython in electronics is one of the best ways to learn to code because it connects code to reality. Simply -install CircuitPython on a supported board via drag and drop and then edit a ``code.py`` file on -the CIRCUITPY drive. The code will automatically reload. No software installs are needed besides a -text editor (we recommend `Mu `_ for beginners.) +install CircuitPython on a supported USB board usually via drag and drop and then edit a ``code.py`` +file on the CIRCUITPY drive. The code will automatically reload. No software installs are needed +besides a text editor (we recommend `Mu `_ for beginners.) -CircuitPython features unified Python core APIs and a growing list of 150+ device libraries and +Starting with CircuitPython 7.0.0, some boards may only be connectable over Bluetooth Low Energy +(BLE). Those boards provide serial and file access over BLE instead of USB using open protocols. +(Some boards may use both USB and BLE.) BLE access can be done from a variety of apps including +`code.circuitpythonn.org `_. + +CircuitPython features unified Python core APIs and a growing list of 300+ device libraries and drivers that work with it. These libraries also work on single board computers with regular Python via the `Adafruit Blinka Library `_. CircuitPython is based on `MicroPython `_. See -`below <#differences-from-micropython>`_ for differences. CircuitPython development is sponsored by -`Adafruit `_ and is available on their educational development boards. Please -support both MicroPython and Adafruit. +`below <#differences-from-micropython>`_ for differences. Most, but not all, CircuitPython +development is sponsored by `Adafruit `_ and is available on their educational +development boards. Please support both MicroPython and Adafruit. Get CircuitPython ------------------ Official binaries for all supported boards are available through `circuitpython.org/downloads `_. The site includes stable, unstable and -continuous builds. Full release notes and assets are available through +continuous builds. Full release notes are available through `GitHub releases `_ as well. Documentation @@ -85,7 +90,9 @@ If you'd like to use the term "CircuitPython" and Blinka for your product here i * Your product is listed on `circuitpython.org `__ (source `here `_). This is to ensure that a user of your product can always download the latest version of CircuitPython from the standard place. -* Your product has a user accessible USB plug which appears as a CIRCUITPY drive when plugged in. +* Your product has a user accessible USB plug which appears as a CIRCUITPY drive when plugged in + AND/OR provides file and serial access over Bluetooth Low Energy. Boards that do not support USB + should be clearly marked as BLE-only CircuitPython. If you choose not to meet these requirements, then we ask you call your version of CircuitPython something else (for example, SuperDuperPython) and not use the Blinka logo. You can say it is @@ -98,10 +105,11 @@ Differences from `MicroPython `__ CircuitPython: -- Supports native USB on all boards, allowing file editing without special tools. +- Supports native USB on most boards and BLE otherwise, allowing file editing without special tools. - Floats (aka decimals) are enabled for all builds. - Error messages are translated into 10+ languages. -- Does not support concurrency within Python (including interrupts and threading). Some concurrency +- Concurrenncy within Python is not well supported. Interrupts and threading are disabled. + async/await keywords are available on some boards for cooperative multitasking. Some concurrency is achieved with native modules for tasks that require it such as audio file playback. Behavior @@ -110,23 +118,23 @@ Behavior - The order that files are run and the state that is shared between them. CircuitPython's goal is to clarify the role of each file and make each file independent from each other. -- ``boot.py`` (or ``settings.py``) runs only once on start up before - USB is initialized. This lays the ground work for configuring USB at - startup rather than it being fixed. Since serial is not available, - output is written to ``boot_out.txt``. -- ``code.py`` (or ``main.py``) is run after every reload until it - finishes or is interrupted. After it is done running, the vm and - hardware is reinitialized. **This means you cannot read state from** - ``code.py`` **in the REPL anymore, as the REPL is a fresh vm.** CircuitPython's goal for this - change includes reducing confusion about pins and memory being used. -- After the main code is finished the REPL can be entered by pressing any key. -- Autoreload state will be maintained across reload. -- Adds a safe mode that does not run user code after a hard crash or - brown out. The hope is that this will make it easier to fix code that - causes nasty crashes by making it available through mass storage - after the crash. A reset (the button) is needed after it's fixed to - get back into normal mode. -- RGB status LED indicating CircuitPython state, and errors through a sequence of colored flashes. + + - ``boot.py`` (or ``settings.py``) runs only once on start up before + USB is initialized. This lays the ground work for configuring USB at + startup rather than it being fixed. Since serial is not available, + output is written to ``boot_out.txt``. + - ``code.py`` (or ``main.py``) is run after every reload until it + finishes or is interrupted. After it is done running, the vm and + hardware is reinitialized. **This means you cannot read state from** + ``code.py`` **in the REPL anymore, as the REPL is a fresh vm.** CircuitPython's goal for this + change includes reducing confusion about pins and memory being used. + - After the main code is finished the REPL can be entered by pressing any key. + - Autoreload state will be maintained across reload. + +- Adds a safe mode that does not run user code after a hard crash or brown out. This makes it + possible to fix code that causes nasty crashes by making it available through mass storage after + the crash. A reset (the button) is needed after it's fixed to get back into normal mode. +- RGB status LED indicating CircuitPython state. - Re-runs ``code.py`` or other main file after file system writes over USB mass storage. (Disable with ``supervisor.disable_autoreload()``) - Autoreload is disabled while the REPL is active. @@ -140,7 +148,7 @@ API - Unified hardware APIs. Documented on `ReadTheDocs `_. -- API docs are rST within the C files in ``shared-bindings``. +- API docs are Python stubs within the C files in ``shared-bindings``. - No ``machine`` API. Modules diff --git a/main.c b/main.c index 395b8c3057..00cf1acaa7 100755 --- a/main.c +++ b/main.c @@ -348,6 +348,14 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { #endif } + // Print done before resetting everything so that we get the message over + // BLE before it is reset and we have a delay before reconnect. + if (reload_requested && result.return_code == PYEXEC_EXCEPTION) { + serial_write_compressed(translate("\nCode stopped by auto-reload.\n")); + } else { + serial_write_compressed(translate("\nCode done running.\n")); + } + // Finished executing python code. Cleanup includes a board reset. cleanup_after_vm(heap); @@ -361,15 +369,13 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { if (reload_requested) { next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_RELOAD; - } - else if (result.return_code == 0) { + } else if (result.return_code == 0) { next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_SUCCESS; if (next_code_options & SUPERVISOR_NEXT_CODE_OPT_RELOAD_ON_SUCCESS) { skip_repl = true; skip_wait = true; } - } - else { + } else { next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_ERROR; // Deep sleep cannot be skipped // TODO: settings in deep sleep should persist, using a new sleep memory API @@ -383,12 +389,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { skip_repl = reload_requested; skip_wait = true; } - - if (reload_requested && result.return_code == PYEXEC_EXCEPTION) { - serial_write_compressed(translate("\nCode stopped by auto-reload.\n")); - } else { - serial_write_compressed(translate("\nCode done running.\n")); - } } // Program has finished running. diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 290d99386a..27fc413336 100755 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -96,7 +96,6 @@ endif ifeq ($(NRF_DEBUG_PRINT), 1) CFLAGS += -DNRF_DEBUG_PRINT=1 - SRC_SUPERVISOR += supervisor/debug_uart.c endif # option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk @@ -248,7 +247,7 @@ SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(S SRC_QSTR_PREPROCESSOR += -all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 +all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 $(BUILD)/firmware.combined.hex $(BUILD)/firmware.elf: $(OBJ) $(GENERATED_LD_FILE) $(STEPECHO) "LINK $@" @@ -266,6 +265,10 @@ $(BUILD)/firmware.hex: $(BUILD)/firmware.elf $(Q)$(OBJCOPY) -O ihex $^ $@ # $(Q)$(OBJCOPY) -O ihex -j .vectors -j .text -j .data $^ $@ +$(BUILD)/firmware.combined.hex: $(BUILD)/firmware.hex $(SOFTDEV_HEX) + $(STEPECHO) "Create $@" + $(Q)hexmerge.py -o $@ $^ + $(BUILD)/firmware.uf2: $(BUILD)/firmware.hex $(ECHO) "Create $@" $(PYTHON3) $(TOP)/tools/uf2/utils/uf2conv.py -f 0xADA52840 -c -o "$(BUILD)/firmware.uf2" $^ diff --git a/ports/nrf/bluetooth/ble_drv.c b/ports/nrf/bluetooth/ble_drv.c index 9596e45fbb..f5d2f96715 100644 --- a/ports/nrf/bluetooth/ble_drv.c +++ b/ports/nrf/bluetooth/ble_drv.c @@ -38,6 +38,10 @@ #include "py/misc.h" #include "py/mpstate.h" +#if CIRCUITPY_SERIAL_BLE && CIRCUITPY_VERBOSE_BLE +#include "supervisor/shared/bluetooth/serial.h" +#endif + nrf_nvic_state_t nrf_nvic_state = { 0 }; // Flag indicating progress of internal flash operation. @@ -132,6 +136,9 @@ void SD_EVT_IRQHandler(void) { } } + #if CIRCUITPY_SERIAL_BLE && CIRCUITPY_VERBOSE_BLE + ble_serial_disable(); + #endif while (1) { uint16_t evt_len = sizeof(m_ble_evt_buf); const uint32_t err_code = sd_ble_evt_get(m_ble_evt_buf, &evt_len); @@ -173,4 +180,7 @@ void SD_EVT_IRQHandler(void) { } #endif } + #if CIRCUITPY_SERIAL_BLE && CIRCUITPY_VERBOSE_BLE + ble_serial_enable(); + #endif } diff --git a/supervisor/stub/serial.c b/ports/nrf/boards/microbit_v2/board.c similarity index 72% rename from supervisor/stub/serial.c rename to ports/nrf/boards/microbit_v2/board.c index 7d00ae1dc3..568a55e0af 100644 --- a/supervisor/stub/serial.c +++ b/ports/nrf/boards/microbit_v2/board.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,36 +24,15 @@ * THE SOFTWARE. */ -#include "supervisor/serial.h" -#include "supervisor/workflow.h" - -void serial_early_init(void) { +#include "supervisor/board.h" +void board_init(void) { } -void serial_init(void) { - -} - -bool serial_connected(void) { +bool board_requests_safe_mode(void) { return false; } -char serial_read(void) { - return 0; -} +void reset_board(void) { -bool serial_bytes_available(void) { - return false; -} - -void serial_write(const char *text) { - (void)text; -} - -void supervisor_workflow_reset(void) { -} - -bool supervisor_workflow_active(void) { - return false; } diff --git a/ports/nrf/boards/microbit_v2/mpconfigboard.h b/ports/nrf/boards/microbit_v2/mpconfigboard.h new file mode 100644 index 0000000000..48b9ea8699 --- /dev/null +++ b/ports/nrf/boards/microbit_v2/mpconfigboard.h @@ -0,0 +1,56 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "nrfx/hal/nrf_gpio.h" + +#define MICROPY_HW_BOARD_NAME "micro:bit v2" +#define MICROPY_HW_MCU_NAME "nRF52833" + +#define CIRCUITPY_INTERNAL_NVM_SIZE 0 +#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (60 * 1024) + +#define CIRCUITPY_BLE_CONFIG_SIZE (12 * 1024) + +// The RUN_MIC pin +#define MICROPY_HW_LED_STATUS (&pin_P0_20) + +// Reduce nRF SoftRadio memory usage +#define BLEIO_VS_UUID_COUNT 10 +#define BLEIO_HVN_TX_QUEUE_SIZE 2 +#define BLEIO_CENTRAL_ROLE_COUNT 2 +#define BLEIO_PERIPH_ROLE_COUNT 2 +#define BLEIO_TOTAL_CONNECTION_COUNT 2 +#define BLEIO_ATTR_TAB_SIZE (BLE_GATTS_ATTR_TAB_SIZE_DEFAULT * 2) + +#define SOFTDEVICE_RAM_SIZE (32 * 1024) + +#define BOOTLOADER_SIZE (0) +#define BOOTLOADER_SETTING_SIZE (0) + +#define BOARD_HAS_32KHZ_XTAL (0) +#define DEBUG_UART_TX (&pin_P0_06) +#define DEBUG_UART_RX (&pin_P1_08) diff --git a/ports/nrf/boards/microbit_v2/mpconfigboard.mk b/ports/nrf/boards/microbit_v2/mpconfigboard.mk new file mode 100644 index 0000000000..a52aa08f9a --- /dev/null +++ b/ports/nrf/boards/microbit_v2/mpconfigboard.mk @@ -0,0 +1,36 @@ +CIRCUITPY_CREATOR_ID = 0x239A +CIRCUITPY_CREATION_ID = 0x80D8 + +MCU_CHIP = nrf52833 + +INTERNAL_FLASH_FILESYSTEM = 1 + +CIRCUITPY_ALARM = 0 +CIRCUITPY_AUDIOMP3 = 0 +CIRCUITPY_BINASCII = 0 +CIRCUITPY_BITBANGIO = 0 +CIRCUITPY_BUILTINS_POW3=0 +CIRCUITPY_BUSDEVICE = 0 +CIRCUITPY_COUNTIO = 0 +CIRCUITPY_DISPLAYIO = 0 +CIRCUITPY_FRAMEBUFFERIO = 0 +CIRCUITPY_FREQUENCYIO = 0 +CIRCUITPY_I2CPERIPHERAL = 0 +CIRCUITPY_JSON = 0 +CIRCUITPY_KEYPAD = 0 +CIRCUITPY_MSGPACK = 0 +CIRCUITPY_NEOPIXEL_WRITE = 0 +CIRCUITPY_NVM = 0 +CIRCUITPY_PIXELBUF = 0 +CIRCUITPY_RE = 0 +CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_SDCARDIO = 0 +CIRCUITPY_ULAB = 0 +CIRCUITPY_USB = 0 + +MICROPY_PY_ASYNC_AWAIT = 0 + +# Override optimization to keep binary small +OPTIMIZATION_FLAGS = -Os +SUPEROPT_VM = 0 +SUPEROPT_GC = 0 diff --git a/ports/nrf/boards/microbit_v2/pins.c b/ports/nrf/boards/microbit_v2/pins.c new file mode 100644 index 0000000000..4f33b98e5a --- /dev/null +++ b/ports/nrf/boards/microbit_v2/pins.c @@ -0,0 +1,59 @@ +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_map_elem_t board_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR_P0), MP_ROM_PTR(&pin_P0_02) }, // RING0 + { MP_ROM_QSTR(MP_QSTR_P1), MP_ROM_PTR(&pin_P0_03) }, // RING1 + { MP_ROM_QSTR(MP_QSTR_P2), MP_ROM_PTR(&pin_P0_04) }, // RING2 + { MP_ROM_QSTR(MP_QSTR_P3), MP_ROM_PTR(&pin_P0_31) }, // COLR3 + { MP_ROM_QSTR(MP_QSTR_P4), MP_ROM_PTR(&pin_P0_28) }, // COLR1 + { MP_ROM_QSTR(MP_QSTR_BTN_A), MP_ROM_PTR(&pin_P0_14) }, + { MP_ROM_QSTR(MP_QSTR_P5), MP_ROM_PTR(&pin_P0_14) }, // BTN A + { MP_ROM_QSTR(MP_QSTR_P6), MP_ROM_PTR(&pin_P1_05) }, // COLR4 + { MP_ROM_QSTR(MP_QSTR_P7), MP_ROM_PTR(&pin_P0_11) }, // COLR2 + { MP_ROM_QSTR(MP_QSTR_P8), MP_ROM_PTR(&pin_P0_10) }, // GPIO1 + { MP_ROM_QSTR(MP_QSTR_P9), MP_ROM_PTR(&pin_P0_09) }, // GPIO2 + { MP_ROM_QSTR(MP_QSTR_P10), MP_ROM_PTR(&pin_P0_30) }, // COLR5 + { MP_ROM_QSTR(MP_QSTR_BTN_B), MP_ROM_PTR(&pin_P0_23) }, + { MP_ROM_QSTR(MP_QSTR_P11), MP_ROM_PTR(&pin_P0_23) }, // BTN B + { MP_ROM_QSTR(MP_QSTR_P12), MP_ROM_PTR(&pin_P0_12) }, // GPIO4 + { MP_ROM_QSTR(MP_QSTR_P13), MP_ROM_PTR(&pin_P0_17) }, // SPI_EXT_SCK + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_17) }, // SPI_EXT_SCK + { MP_ROM_QSTR(MP_QSTR_P14), MP_ROM_PTR(&pin_P0_01) }, // SPI_EXT_MISO + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P0_01) }, // SPI_EXT_MISO + { MP_ROM_QSTR(MP_QSTR_P15), MP_ROM_PTR(&pin_P0_13) }, // SPI_EXT_MOSI + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P0_13) }, // SPI_EXT_MOSI + { MP_ROM_QSTR(MP_QSTR_P16), MP_ROM_PTR(&pin_P0_05) }, // GPIO3 + + { MP_ROM_QSTR(MP_QSTR_P19), MP_ROM_PTR(&pin_P0_08) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_08) }, + { MP_ROM_QSTR(MP_QSTR_P20), MP_ROM_PTR(&pin_P0_16) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_16) }, + + // Internal I2C + { MP_ROM_QSTR(MP_QSTR_INTERNAL_SCL), MP_ROM_PTR(&pin_P0_26) }, + { MP_ROM_QSTR(MP_QSTR_INTERNAL_SDA), MP_ROM_PTR(&pin_P1_00) }, + { MP_ROM_QSTR(MP_QSTR_INTERNAL_INTERRUPT), MP_ROM_PTR(&pin_P0_25) }, + + { MP_ROM_QSTR(MP_QSTR_MICROPHONE_ENABLE), MP_ROM_PTR(&pin_P0_20) }, + { MP_ROM_QSTR(MP_QSTR_MICROPHONE), MP_ROM_PTR(&pin_P0_05) }, + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_P0_00) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P0_06) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P1_08) }, + + { MP_ROM_QSTR(MP_QSTR_LOGO), MP_ROM_PTR(&pin_P1_04) }, + + { MP_ROM_QSTR(MP_QSTR_COL1), MP_ROM_PTR(&pin_P0_28) }, + { MP_ROM_QSTR(MP_QSTR_COL2), MP_ROM_PTR(&pin_P0_11) }, + { MP_ROM_QSTR(MP_QSTR_COL3), MP_ROM_PTR(&pin_P0_31) }, + { MP_ROM_QSTR(MP_QSTR_COL4), MP_ROM_PTR(&pin_P1_05) }, + { MP_ROM_QSTR(MP_QSTR_COL5), MP_ROM_PTR(&pin_P0_30) }, + + { MP_ROM_QSTR(MP_QSTR_ROW1), MP_ROM_PTR(&pin_P0_21) }, + { MP_ROM_QSTR(MP_QSTR_ROW2), MP_ROM_PTR(&pin_P0_22) }, + { MP_ROM_QSTR(MP_QSTR_ROW3), MP_ROM_PTR(&pin_P0_15) }, + { MP_ROM_QSTR(MP_QSTR_ROW4), MP_ROM_PTR(&pin_P0_24) }, + { MP_ROM_QSTR(MP_QSTR_ROW5), MP_ROM_PTR(&pin_P0_19) }, +}; + +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index bf92c7b3ba..9f5f46f656 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.c +++ b/ports/nrf/common-hal/_bleio/Adapter.c @@ -965,11 +965,22 @@ void bleio_adapter_reset(bleio_adapter_obj_t *adapter) { adapter->connection_objs = NULL; for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { bleio_connection_internal_t *connection = &bleio_connections[i]; - // Disconnect all connections with Python state cleanly. Keep any supervisor-only connections. - if (connection->connection_obj != mp_const_none && - connection->conn_handle != BLE_CONN_HANDLE_INVALID) { + // Disconnect all connections cleanly. + if (connection->conn_handle != BLE_CONN_HANDLE_INVALID) { common_hal_bleio_connection_disconnect(connection); } connection->connection_obj = mp_const_none; } + + // Wait up to 125 ms (128 ticks) for disconnect to complete. This should be + // greater than most connection intervals. + bool any_connected = false; + uint64_t start_ticks = supervisor_ticks_ms64(); + while (any_connected && supervisor_ticks_ms64() - start_ticks < 128) { + any_connected = false; + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &bleio_connections[i]; + any_connected |= connection->conn_handle != BLE_CONN_HANDLE_INVALID; + } + } } diff --git a/ports/nrf/common-hal/_bleio/PacketBuffer.c b/ports/nrf/common-hal/_bleio/PacketBuffer.c index 4a123a7c00..ee786c8292 100644 --- a/ports/nrf/common-hal/_bleio/PacketBuffer.c +++ b/ports/nrf/common-hal/_bleio/PacketBuffer.c @@ -40,6 +40,8 @@ #include "shared-bindings/_bleio/PacketBuffer.h" #include "supervisor/shared/tick.h" +#include "supervisor/shared/bluetooth/serial.h" + STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self, uint8_t *data, uint16_t len) { if (len + sizeof(uint16_t) > ringbuf_capacity(&self->ringbuf)) { // This shouldn't happen but can if our buffer size was much smaller than @@ -482,8 +484,8 @@ mp_int_t common_hal_bleio_packet_buffer_get_outgoing_packet_length(bleio_packet_ } void common_hal_bleio_packet_buffer_flush(bleio_packet_buffer_obj_t *self) { - while (self->pending_size != 0 && - self->packet_queued && + while ((self->pending_size != 0 || + self->packet_queued) && self->conn_handle != BLE_CONN_HANDLE_INVALID && !mp_hal_is_interrupted()) { RUN_BACKGROUND_TASKS; diff --git a/ports/nrf/common-hal/_bleio/__init__.c b/ports/nrf/common-hal/_bleio/__init__.c index 604f0be2e5..e02cf306af 100644 --- a/ports/nrf/common-hal/_bleio/__init__.c +++ b/ports/nrf/common-hal/_bleio/__init__.c @@ -102,6 +102,7 @@ void bleio_reset() { return; } + supervisor_stop_bluetooth(); bleio_adapter_reset(&common_hal_bleio_adapter_obj); common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false); bonding_reset(); diff --git a/ports/nrf/common-hal/alarm/SleepMemory.c b/ports/nrf/common-hal/alarm/SleepMemory.c index 4c7e5af847..40ce1f1a75 100644 --- a/ports/nrf/common-hal/alarm/SleepMemory.c +++ b/ports/nrf/common-hal/alarm/SleepMemory.c @@ -30,11 +30,6 @@ #include "common-hal/alarm/SleepMemory.h" #include "nrf_power.h" -#ifdef NRF_DEBUG_PRINT -extern void dbg_dump_RAMreg(void); -#include "supervisor/serial.h" // dbg_printf() -#endif - __attribute__((section(".uninitialized"))) static uint8_t _sleepmem[SLEEP_MEMORY_LENGTH]; __attribute__((section(".uninitialized"))) uint8_t sleepmem_wakeup_event; __attribute__((section(".uninitialized"))) uint8_t sleepmem_wakeup_pin; @@ -81,9 +76,6 @@ static void initialize_sleep_memory(void) { sleepmem_wakeup_pin = 0; set_memory_retention(); - #ifdef NRF_DEBUG_PRINT - // dbg_dump_RAMreg(); - #endif _sleepmem_magicnum = SLEEP_MEMORY_DATA_GUARD; } @@ -92,7 +84,7 @@ void alarm_sleep_memory_reset(void) { if (!is_sleep_memory_valid()) { initialize_sleep_memory(); #ifdef NRF_DEBUG_PRINT - dbg_printf("sleep memory initialized\r\n"); + mp_printf(&mp_plat_print, "sleep memory initialized\r\n"); #endif } } diff --git a/ports/nrf/common-hal/alarm/__init__.c b/ports/nrf/common-hal/alarm/__init__.c index a601e8768e..8accc88764 100644 --- a/ports/nrf/common-hal/alarm/__init__.c +++ b/ports/nrf/common-hal/alarm/__init__.c @@ -42,10 +42,6 @@ #include "supervisor/port.h" #include "supervisor/serial.h" // serial_connected() -#ifdef NRF_DEBUG_PRINT -#include "supervisor/serial.h" // dbg_printf() -extern int dbg_check_RTCprescaler(void); -#endif #include "supervisor/qspi_flash.h" #include "nrf.h" @@ -102,7 +98,7 @@ static const char *cause_str[] = { }; void print_wakeup_cause(nrf_sleep_source_t cause) { if (cause >= 0 && cause < NRF_SLEEP_WAKEUP_ZZZ) { - dbg_printf("wakeup cause = NRF_SLEEP_WAKEUP_%s\r\n", + mp_printf(&mp_plat_print, "wakeup cause = NRF_SLEEP_WAKEUP_%s\r\n", cause_str[(int)cause]); } } @@ -223,7 +219,7 @@ void system_on_idle_until_alarm(int64_t timediff_ms, uint32_t prescaler) { port_idle_until_interrupt(); #ifdef NRF_DEBUG_PRINT if (ct > 0) { - dbg_printf("_"); + mp_printf(&mp_plat_print, "_"); --ct; } #endif @@ -237,7 +233,7 @@ void system_on_idle_until_alarm(int64_t timediff_ms, uint32_t prescaler) { } } #ifdef NRF_DEBUG_PRINT - dbg_printf("%c\r\n", reason); + mp_printf(&mp_plat_print, "%c\r\n", reason); #endif #if defined(MICROPY_QSPI_CS) @@ -252,7 +248,7 @@ void system_on_idle_until_alarm(int64_t timediff_ms, uint32_t prescaler) { } else { sec = (double)(tickdiff * prescaler) / 1024; } - dbg_printf("lapse %6.1f sec\r\n", sec); + mp_printf(&mp_plat_print, "lapse %6.1f sec\r\n", sec); #endif } @@ -262,7 +258,7 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj _setup_sleep_alarms(false, n_alarms, alarms); #ifdef NRF_DEBUG_PRINT - dbg_printf("\r\nlight sleep..."); + mp_printf(&mp_plat_print, "\r\nlight sleep..."); #endif int64_t timediff_ms = alarm_time_timealarm_get_wakeup_timediff_ms(); @@ -305,17 +301,14 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) { alarm_time_timealarm_prepare_for_deep_sleep(); #ifdef NRF_DEBUG_PRINT - dbg_printf("\r\ndeep sleep..."); + mp_printf(&mp_plat_print, "\r\ndeep sleep..."); #endif int64_t timediff_ms = alarm_time_timealarm_get_wakeup_timediff_ms(); tick_set_prescaler(PRESCALER_VALUE_IN_DEEP_SLEEP - 1); - #ifdef NRF_DEBUG_PRINT - dbg_check_RTCprescaler(); // XXX - #endif system_on_idle_until_alarm(timediff_ms, PRESCALER_VALUE_IN_DEEP_SLEEP); #ifdef NRF_DEBUG_PRINT - dbg_printf("RESET...\r\n\r\n"); + mp_printf(&mp_plat_print, "RESET...\r\n\r\n"); #endif reset_cpu(); @@ -326,30 +319,12 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) { } } -// old version deep sleep code that was used in common_hal_alarm_enter_deep_sleep() -// for anyone who might want true System OFF sleep .. -#if 0 -void OLD_go_system_off(void) { - sleepmem_wakeup_event = SLEEPMEM_WAKEUP_BY_NONE; - sleepmem_wakeup_pin = WAKEUP_PIN_UNDEF; - uint8_t sd_enabled; - sd_softdevice_is_enabled(&sd_enabled); - set_memory_retention(); - dbg_printf("OLD go system off.. %d\r\n", sd_enabled); - if (sd_enabled) { - sd_power_system_off(); - } else { - NRF_POWER->SYSTEMOFF = 1; - } -} -#endif - void common_hal_alarm_pretending_deep_sleep(void) { alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_time_timealarm_prepare_for_deep_sleep(); #ifdef NRF_DEBUG_PRINT - dbg_printf("\r\npretending to deep sleep..."); + mp_printf(&mp_plat_print, "\r\npretending to deep sleep..."); #endif int64_t timediff_ms = alarm_time_timealarm_get_wakeup_timediff_ms(); diff --git a/ports/nrf/common-hal/alarm/pin/PinAlarm.c b/ports/nrf/common-hal/alarm/pin/PinAlarm.c index b09e217c22..300369bb36 100644 --- a/ports/nrf/common-hal/alarm/pin/PinAlarm.c +++ b/ports/nrf/common-hal/alarm/pin/PinAlarm.c @@ -41,14 +41,11 @@ #include "nrf_soc.h" #include -#include "supervisor/serial.h" // dbg_print - #define WPIN_UNUSED 0xFF volatile char _pinhandler_gpiote_count; static bool pins_configured = false; extern uint32_t reset_reason_saved; -extern void dbg_dump_GPIOregs(void); void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, const mcu_pin_obj_t *pin, bool value, bool edge, bool pull) { if (edge) { @@ -205,7 +202,7 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); pin_number = alarm->pin->number; - // dbg_printf("alarm_pin_pinalarm_set_alarms(pin#=%d, val=%d, pull=%d)\r\n", pin_number, alarm->value, alarm->pull); + // mp_printf(&mp_plat_print, "alarm_pin_pinalarm_set_alarms(pin#=%d, val=%d, pull=%d)\r\n", pin_number, alarm->value, alarm->pull); if (alarm->value) { high_alarms |= 1ull << pin_number; high_count++; @@ -227,7 +224,7 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob pins_configured = false; } } else { - // dbg_printf("alarm_pin_pinalarm_set_alarms() no valid pins\r\n"); + // mp_printf(&mp_plat_print, "alarm_pin_pinalarm_set_alarms() no valid pins\r\n"); } } @@ -235,8 +232,5 @@ void alarm_pin_pinalarm_prepare_for_deep_sleep(void) { if (!pins_configured) { configure_pins_for_sleep(); pins_configured = true; - #ifdef NRF_DEBUG_PRINT - // dbg_dump_GPIOregs(); - #endif } } diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c index 6436cb4e70..4e7fd3079e 100644 --- a/ports/nrf/common-hal/busio/UART.c +++ b/ports/nrf/common-hal/busio/UART.c @@ -57,6 +57,8 @@ static nrfx_uarte_t nrfx_uartes[] = { #endif }; +static bool never_reset[NRFX_UARTE0_ENABLED + NRFX_UARTE1_ENABLED]; + static uint32_t get_nrf_baud(uint32_t baudrate) { static const struct { @@ -132,10 +134,28 @@ static void uart_callback_irq(const nrfx_uarte_event_t *event, void *context) { void uart_reset(void) { for (size_t i = 0; i < MP_ARRAY_SIZE(nrfx_uartes); i++) { + if (never_reset[i]) { + continue; + } nrfx_uarte_uninit(&nrfx_uartes[i]); } } +void common_hal_busio_uart_never_reset(busio_uart_obj_t *self) { + // Don't never reset objects on the heap. + if (gc_alloc_possible() && gc_nbytes(self) > 0) { + return; + } + for (size_t i = 0; i < MP_ARRAY_SIZE(nrfx_uartes); i++) { + if (self->uarte == &nrfx_uartes[i]) { + never_reset[i] = true; + break; + } + } + never_reset_pin_number(self->tx_pin_number); + never_reset_pin_number(self->rx_pin_number); +} + void common_hal_busio_uart_construct(busio_uart_obj_t *self, const mcu_pin_obj_t *tx, const mcu_pin_obj_t *rx, const mcu_pin_obj_t *rts, const mcu_pin_obj_t *cts, @@ -186,7 +206,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, .pselrts = (rts == NULL) ? NRF_UARTE_PSEL_DISCONNECTED : rts->number, .p_context = self, .baudrate = get_nrf_baud(baudrate), - .interrupt_priority = 7, + .interrupt_priority = NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY, .hal_cfg = { .hwfc = hwfc ? NRF_UARTE_HWFC_ENABLED : NRF_UARTE_HWFC_DISABLED, .parity = (parity == BUSIO_UART_PARITY_NONE) ? NRF_UARTE_PARITY_EXCLUDED : NRF_UARTE_PARITY_INCLUDED @@ -197,14 +217,22 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, // Init buffer for rx if (rx != NULL) { - // Initially allocate the UART's buffer in the long-lived part of the - // heap. UARTs are generally long-lived objects, but the "make long- - // lived" machinery is incapable of moving internal pointers like - // self->buffer, so do it manually. (However, as long as internal - // pointers like this are NOT moved, allocating the buffer - // in the long-lived pool is not strictly necessary) - // (This is a macro.) - if (!ringbuf_alloc(&self->ringbuf, receiver_buffer_size, true)) { + self->allocated_ringbuf = true; + // Use the provided buffer when given. + if (receiver_buffer != NULL) { + self->ringbuf.buf = receiver_buffer; + self->ringbuf.size = receiver_buffer_size - 1; + self->ringbuf.iput = 0; + self->ringbuf.iget = 0; + self->allocated_ringbuf = false; + // Initially allocate the UART's buffer in the long-lived part of the + // heap. UARTs are generally long-lived objects, but the "make long- + // lived" machinery is incapable of moving internal pointers like + // self->buffer, so do it manually. (However, as long as internal + // pointers like this are NOT moved, allocating the buffer + // in the long-lived pool is not strictly necessary) + // (This is a macro.) + } else if (!ringbuf_alloc(&self->ringbuf, receiver_buffer_size, true)) { nrfx_uarte_uninit(self->uarte); mp_raise_msg(&mp_type_MemoryError, translate("Failed to allocate RX buffer")); } @@ -258,7 +286,16 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { self->rx_pin_number = NO_PIN; self->rts_pin_number = NO_PIN; self->cts_pin_number = NO_PIN; - ringbuf_free(&self->ringbuf); + if (self->allocated_ringbuf) { + ringbuf_free(&self->ringbuf); + } + + for (size_t i = 0; i < MP_ARRAY_SIZE(nrfx_uartes); i++) { + if (self->uarte == &nrfx_uartes[i]) { + never_reset[i] = false; + break; + } + } } } @@ -320,10 +357,19 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, // EasyDMA can only access SRAM uint8_t *tx_buf = (uint8_t *)data; if (!nrfx_is_in_ram(data)) { - // TODO: If this is not too big, we could allocate it on the stack. - tx_buf = (uint8_t *)gc_alloc(len, false, false); + // Allocate long strings on the heap. + if (len > 128 && gc_alloc_possible()) { + tx_buf = (uint8_t *)gc_alloc(len, false, false); + } else { + tx_buf = alloca(len); + } memcpy(tx_buf, data, len); } + // There is a small chance we're called recursively during debugging. In that case, + // a UART write might already be in progress so wait for it to complete. + while (nrfx_uarte_tx_in_progress(self->uarte)) { + RUN_BACKGROUND_TASKS; + } (*errcode) = nrfx_uarte_tx(self->uarte, tx_buf, len); _VERIFY_ERR(*errcode); @@ -334,7 +380,7 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, RUN_BACKGROUND_TASKS; } - if (!nrfx_is_in_ram(data)) { + if (!nrfx_is_in_ram(data) && gc_alloc_possible() && gc_nbytes(tx_buf) > 0) { gc_free(tx_buf); } diff --git a/ports/nrf/common-hal/busio/UART.h b/ports/nrf/common-hal/busio/UART.h index 2eaf584403..140f8d0c0a 100644 --- a/ports/nrf/common-hal/busio/UART.h +++ b/ports/nrf/common-hal/busio/UART.h @@ -44,6 +44,7 @@ typedef struct { ringbuf_t ringbuf; uint8_t rx_char; // EasyDMA buf bool rx_paused; // set by irq if no space in rbuf + bool allocated_ringbuf; uint8_t tx_pin_number; uint8_t rx_pin_number; diff --git a/ports/nrf/nrfx_config.h b/ports/nrf/nrfx_config.h index 912349556e..927b8ff697 100644 --- a/ports/nrf/nrfx_config.h +++ b/ports/nrf/nrfx_config.h @@ -76,6 +76,9 @@ #define NRFX_UARTE_ENABLED 1 #define NRFX_UARTE0_ENABLED 1 #define NRFX_UARTE1_ENABLED 1 +// Higher priority than non-timing sensitive BLE so that we can log over UART +// from it. +#define NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY 3 // PWM #define NRFX_PWM0_ENABLED 1 diff --git a/ports/nrf/supervisor/debug_uart.c b/ports/nrf/supervisor/debug_uart.c deleted file mode 100644 index f5a9b1f47d..0000000000 --- a/ports/nrf/supervisor/debug_uart.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Jun2Sak - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include - -#ifdef NRF_DEBUG_PRINT - -#define DEBUG_UART_TXPIN 26 -#define DEBUG_UART_RXPIN 15 - -#include "nrfx.h" -#include "nrf_uart.h" -#include "nrf_gpio.h" -#include "nrf_rtc.h" -#include "nrfx_uarte.h" -#include "nrfx_rtc.h" -#include "supervisor/serial.h" // dbg_printf() -#include "shared-bindings/microcontroller/Processor.h" -#include "common-hal/alarm/__init__.h" - -extern const nrfx_rtc_t rtc_instance; // port.c -extern uint32_t reset_reason_saved; - -const nrfx_uarte_t _dbg_uart_inst = NRFX_UARTE_INSTANCE(1); -static int _dbg_uart_initialized = 0; -#define DBG_PBUF_LEN 80 -static char _dbg_pbuf[DBG_PBUF_LEN + 1]; - -void _debug_uart_uninit(void) { - nrf_gpio_cfg(DEBUG_UART_TXPIN, - NRF_GPIO_PIN_DIR_INPUT, - NRF_GPIO_PIN_INPUT_DISCONNECT, - NRF_GPIO_PIN_NOPULL, - NRF_GPIO_PIN_S0S1, - NRF_GPIO_PIN_NOSENSE); - nrfx_uarte_uninit(&_dbg_uart_inst); -} - -void _debug_uart_init(void) { - // if (_dbg_uart_initialized) return; - nrfx_uarte_config_t config = { - .pseltxd = DEBUG_UART_TXPIN, - .pselrxd = DEBUG_UART_RXPIN, - .pselcts = NRF_UARTE_PSEL_DISCONNECTED, - .pselrts = NRF_UARTE_PSEL_DISCONNECTED, - .p_context = NULL, - .baudrate = NRF_UART_BAUDRATE_115200, - .interrupt_priority = 7, - .hal_cfg = { - .hwfc = NRF_UARTE_HWFC_DISABLED, - .parity = NRF_UARTE_PARITY_EXCLUDED - } - }; - nrfx_uarte_init(&_dbg_uart_inst, &config, NULL); - // drive config - nrf_gpio_cfg(config.pseltxd, - NRF_GPIO_PIN_DIR_OUTPUT, - NRF_GPIO_PIN_INPUT_DISCONNECT, - NRF_GPIO_PIN_PULLUP, // orig=NOPULL - NRF_GPIO_PIN_H0H1, // orig=S0S1 - NRF_GPIO_PIN_NOSENSE); - _dbg_uart_initialized = 1; - return; -} - -void _debug_print_substr(const char *text, uint32_t length) { - char *data = (char *)text; - int siz; - while (length != 0) { - if (length <= DBG_PBUF_LEN) { - siz = length; - } else { - siz = DBG_PBUF_LEN; - } - memcpy(_dbg_pbuf, data, siz); - _dbg_pbuf[siz] = 0; - nrfx_uarte_tx(&_dbg_uart_inst, (uint8_t const *)_dbg_pbuf, siz); - data += siz; - length -= siz; - } -} - -void _debug_uart_deinit(void) { - nrfx_uarte_uninit(&_dbg_uart_inst); -} - -int dbg_printf(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - int ret = vprintf(fmt, ap); - va_end(ap); - return ret; -} - -void dbg_dump_RTCreg(void) { - dbg_printf("\r\nRTC2\r\n"); - NRF_RTC_Type *r = rtc_instance.p_reg; - dbg_printf("PRESCALER=%08X, ", (int)r->PRESCALER); - dbg_printf("COUNTER=%08X ", (int)r->COUNTER); - dbg_printf("INTENSET=%08X ", (int)r->INTENSET); - dbg_printf("EVTENSET=%08X\r\n", (int)r->EVTENSET); - dbg_printf("EVENTS_COMPARE[0..3]=%X,%X,%X,%X ", (int)r->EVENTS_COMPARE[0], (int)r->EVENTS_COMPARE[1], (int)r->EVENTS_COMPARE[2], (int)r->EVENTS_COMPARE[3]); - dbg_printf("CC[0..3]=%08X,%08X,%08X,%08X\r\n", (int)r->CC[0], (int)r->CC[1], (int)r->CC[2], (int)r->CC[3]); -} - -int dbg_check_RTCprescaler(void) { - NRF_RTC_Type *r = rtc_instance.p_reg; - if ((int)r->PRESCALER == 0) { - dbg_printf("****** PRESCALER == 0\r\n"); - return -1; - } - return 0; -} - -void dbg_dump_RAMreg(void) { - int i; - for (i = 0; i <= 8; ++i) { - dbg_printf(" RAM%d:%08X", i, (int)(NRF_POWER->RAM[i].POWER)); - if (i == 4) { - dbg_printf("\r\n"); - } - } - dbg_printf("\r\n"); -} - -void dbg_dump_GPIOregs(void) { - int i, port, col; - - NRF_GPIO_Type *gpio[] = { NRF_P0, NRF_P1 }; - const char cnf_pull_chr[] = "-D*U"; // pull down, pull up - const char cnf_sense_chr[] = "-?HL"; // sense high, sense low - for (port = 0, col = 0; port <= 1; ++port) { - for (i = 0; i < 32; ++i) { - uint32_t cnf = gpio[port]->PIN_CNF[i]; - if (cnf != 0x0002) { // changed from default value - dbg_printf("[%d_%02d]:%c%c%c%d%c ", port, i, - (cnf & 1) ? 'O' : 'I', // output, input - (cnf & 2) ? 'd' : 'c', // disconnected, connected - cnf_pull_chr[(cnf >> 2) & 3], - (int)((cnf >> 8) & 7), // drive config 0-7 - cnf_sense_chr[(cnf >> 16) & 3]); - if (++col >= 6) { - dbg_printf("\r\n"); - col = 0; - } - } - } - } - if (col > 0) { - dbg_printf("\r\n"); - } - - dbg_printf("GPIOTE\r\n"); - NRF_GPIOTE_Type const *reg = NRF_GPIOTE; - const char config_mode_chr[] = "-E-T"; // event, task - const char config_pol_chr[] = "-HLT"; // low-to-Hi, hi-to-Low, Toggle - const char config_outinit_chr[] = "01"; // initial value is 0 or 1 - for (i = 0, col = 0; i < 8; ++i) { - uint32_t conf = reg->CONFIG[i]; - if (conf != 0) { // changed from default value - dbg_printf("CONFIG[%d]:%d_%02d,%c%c%c ", i, - (int)((conf >> 13) & 1), (int)((conf >> 8) & 0x1F), - config_mode_chr[conf & 3], - config_pol_chr[(conf >> 16) & 3], - (conf & 3) == 3 ? - config_outinit_chr[(conf >> 20) & 1] : '-'); - if (++col >= 4) { - dbg_printf("\r\n"); - col = 0; - } - } - } - if (col > 0) { - dbg_printf("\r\n"); - } - for (i = 0; i < 8; ++i) { - dbg_printf("EVENTS_IN[%d]:%X ", i, (int)(reg->EVENTS_IN[i])); - if ((i & 3) == 3) { - dbg_printf("\r\n"); - } - } - dbg_printf("EVENTS_PORT:%X INTENSET:%08X\r\n", - (int)(reg->EVENTS_PORT), (int)(reg->INTENSET)); -} - -void dbg_dumpQSPIreg(void) { - uint32_t r; - dbg_printf("QSPI\r\n"); - r = NRF_QSPI->IFCONFIG0; - dbg_printf("IFCONFIG0 READ=%ld write=%ld ADDR=%ld DPM=%ld PPSIZE=%ld\r\n", - r & 7, (r >> 3) & 7, (r >> 6) & 1, (r >> 7) & 1, (r >> 12) & 1); - r = NRF_QSPI->IFCONFIG1; - dbg_printf("IFCONFIG1 SCKDELAY=%ld SPIMODE=%ld SCKFREQ=%ld\r\n", - r & 0xFF, (r >> 25) & 1, (r >> 28) & 0xF); - r = NRF_QSPI->STATUS; - dbg_printf("STATUS DPM=%ld READY=%ld SREG=0x%02lX\r\n", - (r >> 2) & 1, (r >> 3) & 1, (r >> 24) & 0xFF); - r = NRF_QSPI->DPMDUR; - dbg_printf("DPMDUR ENTER=%ld EXIT=%ld\r\n", r & 0xFFFF, (r >> 16) & 0xFFFF); -} - -void dbg_dump_reset_reason(void) { - int reset_reason = (int)common_hal_mcu_processor_get_reset_reason(); - const char *rr_str[] = { - "POWER_ON", "BROWNOUT", "SOFTWARE", "DEEPSLEEPALARM", - "RESET_PIN", "WATCHDOG", "UNKNOWN" - }; - dbg_printf("reset_reason=%s\r\n", rr_str[reset_reason]); -} - -#else /*!NRF_DEBUG_PRINT*/ -int dbg_printf(const char *fmt, ...) { - return 0; -} -#endif /*!NRF_DEBUG_PRINT*/ diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c index edf17bacf1..e984c3f326 100644 --- a/ports/nrf/supervisor/port.c +++ b/ports/nrf/supervisor/port.c @@ -75,10 +75,6 @@ static void power_warning_handler(void) { reset_into_safe_mode(BROWNOUT); } -#ifdef NRF_DEBUG_PRINT -extern void _debug_uart_init(void); -#endif - uint32_t reset_reason_saved = 0; const nrfx_rtc_t rtc_instance = NRFX_RTC_INSTANCE(2); @@ -258,10 +254,6 @@ void reset_port(void) { #endif reset_all_pins(); - - #ifdef NRF_DEBUG_PRINT - _debug_uart_init(); - #endif } void reset_to_bootloader(void) { @@ -389,7 +381,11 @@ void port_idle_until_interrupt(void) { // function (whether or not SD is enabled) int nested = __get_PRIMASK(); __disable_irq(); - if (!tud_task_event_ready()) { + bool ok = true; + #if CIRCUITPY_USB + ok = !tud_task_event_ready(); + #endif + if (ok) { __DSB(); __WFI(); } diff --git a/ports/nrf/supervisor/qspi_flash.c b/ports/nrf/supervisor/qspi_flash.c index cb380e6156..632fe4d212 100644 --- a/ports/nrf/supervisor/qspi_flash.c +++ b/ports/nrf/supervisor/qspi_flash.c @@ -37,9 +37,6 @@ #include "supervisor/shared/external_flash/common_commands.h" #include "supervisor/shared/external_flash/qspi_flash.h" -#ifdef NRF_DEBUG_PRINT -#include "supervisor/serial.h" // dbg_printf() -#endif #ifdef QSPI_FLASH_POWERDOWN // Parameters for external QSPI Flash power-down @@ -57,12 +54,6 @@ static int sck_delay_saved = 0; #endif -#ifdef NRF_DEBUG_PRINT -extern void dbg_dumpQSPIreg(void); -#else -#define dbg_dumpQSPIreg(...) -#endif - // When USB is disconnected, disable QSPI in sleep mode to save energy void qspi_disable(void) { // If VBUS is detected, no need to disable QSPI @@ -289,20 +280,18 @@ void qspi_flash_enter_sleep(void) { // enabling IFCONFIG0.DPMENABLE here won't work. // -> do it in spi_flash_init() // NRF_QSPI->IFCONFIG0 |= QSPI_IFCONFIG0_DPMENABLE_Msk; - // dbg_dumpQSPIreg(); // enter deep power-down mode (DPM) NRF_QSPI->IFCONFIG1 |= QSPI_IFCONFIG1_DPMEN_Msk; NRFX_DELAY_US(WAIT_AFTER_DPM_ENTER); if (!(NRF_QSPI->STATUS & QSPI_STATUS_DPM_Msk)) { #ifdef NRF_DEBUG_PRINT - dbg_printf("qspi flash: DPM failed\r\n"); + mp_printf(&mp_plat_print, "qspi flash: DPM failed\r\n"); #endif } #endif qspi_disable(); - // dbg_dumpQSPIreg(); } void qspi_flash_exit_sleep(void) { @@ -316,7 +305,7 @@ void qspi_flash_exit_sleep(void) { if (NRF_QSPI->STATUS & QSPI_STATUS_DPM_Msk) { #ifdef NRF_DEBUG_PRINT - dbg_printf("qspi flash: exiting DPM failed\r\n"); + mp_printf(&mp_plat_print, "qspi flash: exiting DPM failed\r\n"); #endif } // restore sck_delay @@ -327,6 +316,5 @@ void qspi_flash_exit_sleep(void) { = (NRF_QSPI->IFCONFIG1 & ~QSPI_IFCONFIG1_SCKDELAY_Msk) | (sck_delay_saved << QSPI_IFCONFIG1_SCKDELAY_Pos); } - // dbg_dumpQSPIreg(); #endif } diff --git a/ports/nrf/supervisor/serial.c b/ports/nrf/supervisor/serial.c deleted file mode 100644 index 41aa34721a..0000000000 --- a/ports/nrf/supervisor/serial.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017, 2018 Scott Shawcroft for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "py/mphal.h" - -#include "supervisor/serial.h" - -#if CIRCUITPY_CONSOLE_BLE -#include "ble_uart.h" -#elif CIRCUITPY_CONSOLE_UART -#include -#include "nrf_gpio.h" -#include "nrfx_uarte.h" -#endif - -#if CIRCUITPY_CONSOLE_BLE - -void serial_init(void) { - ble_uart_init(); -} - -bool serial_connected(void) { - return ble_uart_connected(); -} - -char serial_read(void) { - return (char)ble_uart_rx_chr(); -} - -bool serial_bytes_available(void) { - return ble_uart_stdin_any(); -} - -void serial_write(const char *text) { - ble_uart_stdout_tx_str(text); -} - -#elif CIRCUITPY_CONSOLE_UART - -uint8_t serial_received_char; -nrfx_uarte_t serial_instance = NRFX_UARTE_INSTANCE(0); - -void serial_init(void) { - nrfx_uarte_config_t config = { - .pseltxd = MICROPY_HW_UART_TX, - .pselrxd = MICROPY_HW_UART_RX, - .pselcts = NRF_UARTE_PSEL_DISCONNECTED, - .pselrts = NRF_UARTE_PSEL_DISCONNECTED, - .p_context = NULL, - .hwfc = NRF_UARTE_HWFC_DISABLED, - .parity = NRF_UARTE_PARITY_EXCLUDED, - .baudrate = NRF_UARTE_BAUDRATE_115200, - .interrupt_priority = 7 - }; - - nrfx_uarte_uninit(&serial_instance); - const nrfx_err_t err = nrfx_uarte_init(&serial_instance, &config, NULL); // no callback for blocking mode - - if (err != NRFX_SUCCESS) { - NRFX_ASSERT(err); - } - - // enabled receiving - nrf_uarte_task_trigger(serial_instance.p_reg, NRF_UARTE_TASK_STARTRX); -} - -bool serial_connected(void) { - return true; -} - -char serial_read(void) { - uint8_t data; - nrfx_uarte_rx(&serial_instance, &data, 1); - return data; -} - -bool serial_bytes_available(void) { - return nrf_uarte_event_check(serial_instance.p_reg, NRF_UARTE_EVENT_RXDRDY); -} - -void serial_write(const char *text) { - serial_write_substring(text, strlen(text)); -} - -void serial_write_substring(const char *text, uint32_t len) { - if (len == 0) { - return; - } - - // EasyDMA can only access SRAM - uint8_t *tx_buf = (uint8_t *)text; - if (!nrfx_is_in_ram(text)) { - tx_buf = (uint8_t *)m_malloc(len, false); - memcpy(tx_buf, text, len); - } - - nrfx_uarte_tx(&serial_instance, tx_buf, len); - - if (!nrfx_is_in_ram(text)) { - m_free(tx_buf); - } -} - -#endif // CIRCUITPY_CONSOLE_UART diff --git a/ports/unix/Makefile b/ports/unix/Makefile index a4374500ef..d966e71327 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -173,7 +173,6 @@ SRC_C += \ fatfs_port.c \ supervisor/stub/filesystem.c \ supervisor/stub/safe_mode.c \ - supervisor/stub/serial.c \ supervisor/stub/stack.c \ supervisor/shared/translate.c \ $(SRC_MOD) \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 6e708b0860..c1526438e8 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -351,7 +351,7 @@ CFLAGS += -DUSB_NUM_IN_ENDPOINTS=$(USB_NUM_IN_ENDPOINTS) USB_NUM_OUT_ENDPOINTS ?= $(USB_NUM_ENDPOINT_PAIRS) CFLAGS += -DUSB_NUM_OUT_ENDPOINTS=$(USB_NUM_OUT_ENDPOINTS) -CIRCUITPY_USB_CDC ?= 1 +CIRCUITPY_USB_CDC ?= $(CIRCUITPY_USB) CFLAGS += -DCIRCUITPY_USB_CDC=$(CIRCUITPY_USB_CDC) CIRCUITPY_USB_CDC_CONSOLE_ENABLED_DEFAULT ?= 1 CFLAGS += -DCIRCUITPY_USB_CDC_CONSOLE_ENABLED_DEFAULT=$(CIRCUITPY_USB_CDC_CONSOLE_ENABLED_DEFAULT) @@ -359,18 +359,18 @@ CIRCUITPY_USB_CDC_DATA_ENABLED_DEFAULT ?= 0 CFLAGS += -DCIRCUITPY_USB_CDC_DATA_ENABLED_DEFAULT=$(CIRCUITPY_USB_CDC_DATA_ENABLED_DEFAULT) # HID is available by default, but is not turned on if there are fewer than 5 endpoints. -CIRCUITPY_USB_HID ?= 1 +CIRCUITPY_USB_HID ?= $(CIRCUITPY_USB) CFLAGS += -DCIRCUITPY_USB_HID=$(CIRCUITPY_USB_HID) CIRCUITPY_USB_HID_ENABLED_DEFAULT ?= $(USB_NUM_ENDPOINT_PAIRS_5_OR_GREATER) CFLAGS += -DCIRCUITPY_USB_HID_ENABLED_DEFAULT=$(CIRCUITPY_USB_HID_ENABLED_DEFAULT) # MIDI is available by default, but is not turned on if there are fewer than 8 endpoints. -CIRCUITPY_USB_MIDI ?= 1 +CIRCUITPY_USB_MIDI ?= $(CIRCUITPY_USB) CFLAGS += -DCIRCUITPY_USB_MIDI=$(CIRCUITPY_USB_MIDI) CIRCUITPY_USB_MIDI_ENABLED_DEFAULT ?= $(USB_NUM_ENDPOINT_PAIRS_8_OR_GREATER) CFLAGS += -DCIRCUITPY_USB_MIDI_ENABLED_DEFAULT=$(CIRCUITPY_USB_MIDI_ENABLED_DEFAULT) -CIRCUITPY_USB_MSC ?= 1 +CIRCUITPY_USB_MSC ?= $(CIRCUITPY_USB) CFLAGS += -DCIRCUITPY_USB_MSC=$(CIRCUITPY_USB_MSC) CIRCUITPY_USB_MSC_ENABLED_DEFAULT ?= $(CIRCUITPY_USB_MSC) CFLAGS += -DCIRCUITPY_USB_MSC_ENABLED_DEFAULT=$(CIRCUITPY_USB_MSC_ENABLED_DEFAULT) diff --git a/requirements-dev.txt b/requirements-dev.txt index f2b1e986d6..6db56d8940 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -32,3 +32,6 @@ mypy # For uploading artifacts awscli + +# for combining the Nordic SoftDevice with CircuitPython +intelhex diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index 5857432a52..620e536ba4 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -137,6 +137,14 @@ bool common_hal_storage_disable_usb_drive(void) { bool common_hal_storage_enable_usb_drive(void) { return usb_drive_set_enabled(true); } +#else +bool common_hal_storage_disable_usb_drive(void) { + return false; +} + +bool common_hal_storage_enable_usb_drive(void) { + return false; +} #endif // CIRCUITPY_USB_MSC STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_args, const mp_obj_t *args) { diff --git a/supervisor/shared/bluetooth/bluetooth.c b/supervisor/shared/bluetooth/bluetooth.c index df57bf691d..49b1a0ac50 100644 --- a/supervisor/shared/bluetooth/bluetooth.c +++ b/supervisor/shared/bluetooth/bluetooth.c @@ -161,6 +161,9 @@ void supervisor_bluetooth_init(void) { common_hal_digitalio_digitalinout_construct(&boot_button, CIRCUITPY_BOOT_BUTTON); common_hal_digitalio_digitalinout_switch_to_input(&boot_button, PULL_UP); #endif + #if CIRCUITPY_STATUS_LED + status_led_init(); + #endif uint64_t start_ticks = supervisor_ticks_ms64(); uint64_t diff = 0; if (ble_mode != 0) { @@ -233,3 +236,13 @@ void supervisor_start_bluetooth(void) { // Kick off advertisments supervisor_bluetooth_background(); } + +void supervisor_stop_bluetooth(void) { + #if !CIRCUITPY_BLE_FILE_SERVICE && !CIRCUITPY_SERIAL_BLE + return; + #endif + + #if CIRCUITPY_SERIAL_BLE + supervisor_stop_bluetooth_serial(); + #endif +} diff --git a/supervisor/shared/bluetooth/bluetooth.h b/supervisor/shared/bluetooth/bluetooth.h index a8f3e8b159..577c0c76a1 100644 --- a/supervisor/shared/bluetooth/bluetooth.h +++ b/supervisor/shared/bluetooth/bluetooth.h @@ -32,5 +32,6 @@ void supervisor_bluetooth_background(void); void supervisor_bluetooth_init(void); void supervisor_start_bluetooth(void); +void supervisor_stop_bluetooth(void); #endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_H diff --git a/supervisor/shared/bluetooth/file_transfer.c b/supervisor/shared/bluetooth/file_transfer.c index 3bd306c5a7..943aed8c0f 100644 --- a/supervisor/shared/bluetooth/file_transfer.c +++ b/supervisor/shared/bluetooth/file_transfer.c @@ -252,7 +252,7 @@ STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) { path[command->path_length] = '\0'; // Check to see if USB has already been mounted. If not, then we "eject" from USB until we're done. - #if CIRCUITPY_USB_MSC + #if CIRCUITPY_USB && CIRCUITPY_USB_MSC if (storage_usb_enabled() && !usb_msc_lock()) { response.status = STATUS_ERROR; common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0); @@ -506,11 +506,13 @@ void supervisor_bluetooth_file_transfer_background(void) { } // TODO: If size < 0 return an error. current_offset += size; - // mp_printf(&mp_plat_print, "buffer[:%d]:", current_offset); - // for (size_t i = 0; i < current_offset; i++) { - // mp_printf(&mp_plat_print, " (%x %c)", current_command[i], current_command[i]); - // } - // mp_printf(&mp_plat_print, "\n"); + #if CIRCUITPY_VERBOSE_BLE + mp_printf(&mp_plat_print, "buffer[:%d]:", current_offset); + for (size_t i = 0; i < current_offset; i++) { + mp_printf(&mp_plat_print, " (%x %c)", current_command[i], current_command[i]); + } + mp_printf(&mp_plat_print, "\n"); + #endif uint8_t current_state = current_command[0]; // mp_printf(&mp_plat_print, "current command 0x%02x\n", current_state); // Check for protocol error. diff --git a/supervisor/shared/bluetooth/serial.c b/supervisor/shared/bluetooth/serial.c index e1d26b89ce..d852a86d74 100644 --- a/supervisor/shared/bluetooth/serial.c +++ b/supervisor/shared/bluetooth/serial.c @@ -60,6 +60,9 @@ STATIC bleio_packet_buffer_obj_t _tx_packet_buffer; STATIC uint32_t _incoming[64]; STATIC bleio_characteristic_buffer_obj_t _rx_buffer; +// Internal enabling so we can disable while printing BLE debugging. +STATIC bool _enabled; + void supervisor_start_bluetooth_serial(void) { supervisor_ble_serial_service_uuid.base.type = &bleio_uuid_type; common_hal_bleio_uuid_construct(&supervisor_ble_serial_service_uuid, 0x0001, nordic_uart_base_uuid); @@ -71,6 +74,7 @@ void supervisor_start_bluetooth_serial(void) { characteristic_list.items = characteristic_list_items; mp_seq_clear(characteristic_list.items, 0, characteristic_list.alloc, sizeof(*characteristic_list.items)); + supervisor_ble_serial_service.base.type = &bleio_service_type; _common_hal_bleio_service_construct(&supervisor_ble_serial_service, &supervisor_ble_serial_service_uuid, false /* is secondary */, &characteristic_list); // RX @@ -117,6 +121,18 @@ void supervisor_start_bluetooth_serial(void) { 0.1f, (uint8_t *)_incoming, sizeof(_incoming) * sizeof(uint32_t), &rx_static_handler_entry); + + _enabled = true; +} + +void supervisor_stop_bluetooth_serial(void) { + if (common_hal_bleio_packet_buffer_deinited(&_tx_packet_buffer)) { + return; + } + if (!_enabled) { + return; + } + common_hal_bleio_packet_buffer_flush(&_tx_packet_buffer); } bool ble_serial_connected(void) { @@ -124,13 +140,18 @@ bool ble_serial_connected(void) { } bool ble_serial_available(void) { - return !common_hal_bleio_characteristic_buffer_deinited(&_rx_buffer) && common_hal_bleio_characteristic_buffer_rx_characters_available(&_rx_buffer); + return _enabled && + !common_hal_bleio_characteristic_buffer_deinited(&_rx_buffer) && + common_hal_bleio_characteristic_buffer_rx_characters_available(&_rx_buffer); } char ble_serial_read_char(void) { if (common_hal_bleio_characteristic_buffer_deinited(&_rx_buffer)) { return -1; } + if (!_enabled) { + return -1; + } uint8_t c; common_hal_bleio_characteristic_buffer_read(&_rx_buffer, &c, 1, NULL); return c; @@ -140,6 +161,9 @@ void ble_serial_write(const char *text, size_t len) { if (common_hal_bleio_packet_buffer_deinited(&_tx_packet_buffer)) { return; } + if (!_enabled) { + return; + } size_t sent = 0; while (sent < len) { uint16_t packet_size = MIN(len, (size_t)common_hal_bleio_packet_buffer_get_outgoing_packet_length(&_tx_packet_buffer)); @@ -151,3 +175,11 @@ void ble_serial_write(const char *text, size_t len) { sent += written; } } + +void ble_serial_enable(void) { + _enabled = true; +} + +void ble_serial_disable(void) { + _enabled = false; +} diff --git a/supervisor/shared/bluetooth/serial.h b/supervisor/shared/bluetooth/serial.h index b5bbcccf10..cc73a15c06 100644 --- a/supervisor/shared/bluetooth/serial.h +++ b/supervisor/shared/bluetooth/serial.h @@ -30,10 +30,13 @@ #include void supervisor_start_bluetooth_serial(void); +void supervisor_stop_bluetooth_serial(void); bool ble_serial_connected(void); bool ble_serial_available(void); char ble_serial_read_char(void); void ble_serial_write(const char *text, size_t len); +void ble_serial_enable(void); +void ble_serial_disable(void); #endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_SERIAL_H diff --git a/supervisor/shared/serial.c b/supervisor/shared/serial.c index 35feacb527..390591eab2 100644 --- a/supervisor/shared/serial.c +++ b/supervisor/shared/serial.c @@ -42,15 +42,9 @@ #include "tusb.h" -#ifdef NRF_DEBUG_PRINT -// XXX these functions are in nrf/supervisor/debug_uart.c -extern void _debug_uart_init(void); -extern void _debug_print_substr(const char *text, uint32_t length); -#endif - /* - * Note: DEBUG_UART currently only works on STM32, - * enabling on another platform will cause a crash. + * Note: DEBUG_UART currently only works on STM32 and nRF. + * Enabling on another platform will cause a crash. */ #if defined(DEBUG_UART_TX) && defined(DEBUG_UART_RX) @@ -75,17 +69,10 @@ void serial_early_init(void) { buf_array, true); common_hal_busio_uart_never_reset(&debug_uart); #endif - - #ifdef NRF_DEBUG_PRINT - _debug_uart_init(); - #endif } void serial_init(void) { // USB serial is set up separately. - #ifdef NRF_DEBUG_PRINT - _debug_uart_init(); - #endif } bool serial_connected(void) { @@ -109,7 +96,7 @@ bool serial_connected(void) { if (usb_cdc_console_enabled() && tud_cdc_connected()) { return true; } - #else + #elif CIRCUITPY_USB if (tud_cdc_connected()) { return true; } @@ -127,13 +114,12 @@ char serial_read(void) { #endif #if defined(DEBUG_UART_TX) && defined(DEBUG_UART_RX) - if (tud_cdc_connected() && tud_cdc_available() > 0) { - return (char)tud_cdc_read_char(); + if (common_hal_busio_uart_rx_characters_available(&debug_uart)) { + int uart_errcode; + char text; + common_hal_busio_uart_read(&debug_uart, (uint8_t *)&text, 1, &uart_errcode); + return text; } - int uart_errcode; - char text; - common_hal_busio_uart_read(&debug_uart, (uint8_t *)&text, 1, &uart_errcode); - return text; #endif #if CIRCUITPY_SERIAL_BLE @@ -147,7 +133,10 @@ char serial_read(void) { return -1; } #endif + #if CIRCUITPY_USB return (char)tud_cdc_read_char(); + #endif + return -1; } bool serial_bytes_available(void) { @@ -173,7 +162,8 @@ bool serial_bytes_available(void) { if (usb_cdc_console_enabled() && tud_cdc_available() > 0) { return true; } - #else + #endif + #if CIRCUITPY_USB if (tud_cdc_available() > 0) { return true; } @@ -202,10 +192,6 @@ void serial_write_substring(const char *text, uint32_t length) { common_hal_busio_uart_write(&debug_uart, (const uint8_t *)text, length, &uart_errcode); #endif - #ifdef NRF_DEBUG_PRINT - _debug_print_substr(text, length); - #endif - #if CIRCUITPY_SERIAL_BLE ble_serial_write(text, length); #endif @@ -216,6 +202,7 @@ void serial_write_substring(const char *text, uint32_t length) { } #endif + #if CIRCUITPY_USB uint32_t count = 0; while (count < length && tud_cdc_connected()) { count += tud_cdc_write(text + count, length - count); @@ -225,6 +212,7 @@ void serial_write_substring(const char *text, uint32_t length) { } usb_background(); } + #endif } void serial_write(const char *text) { diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index 0f53e1ebeb..6d06a9ada9 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -72,7 +72,9 @@ endif ifeq ($(CIRCUITPY_USB),0) ifeq ($(wildcard supervisor/serial.c),) - SRC_SUPERVISOR += supervisor/stub/serial.c + SRC_SUPERVISOR += supervisor/shared/serial.c \ + supervisor/shared/workflow.c \ + else SRC_SUPERVISOR += supervisor/serial.c endif diff --git a/tools/build_board_info.py b/tools/build_board_info.py index f44cf54821..62a33e1dd2 100644 --- a/tools/build_board_info.py +++ b/tools/build_board_info.py @@ -30,6 +30,7 @@ HEX_UF2 = ("hex", "uf2") SPK = ("spk",) DFU = ("dfu",) BIN_DFU = ("bin", "dfu") +COMBINED_HEX = ("combined.hex",) # Default extensions extension_by_port = { @@ -61,6 +62,7 @@ extension_by_board = { "pca10056": BIN_UF2, "pca10059": BIN_UF2, "electronut_labs_blip": HEX, + "microbit_v2": COMBINED_HEX, # stm32 "meowbit_v121": UF2, }