Skip to content

Create first BLE-only board, Micro:Bit v2 #5002

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 15, 2021
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
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ jobs:
- "metro_m4_express"
- "metro_m7_1011"
- "metro_nrf52840_express"
- "microbit_v2"
- "mini_sam_m4"
- "monster_m4sk"
- "ndgarage_ndbit6"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ports_windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
pip install wheel
# requirements_dev.txt doesn't install on windows. (with msys2 python)
# instead, pick a subset for what we want to do
pip install cascadetoml jinja2 typer
pip install cascadetoml jinja2 typer intelhex
# check that installed packages work....?
which python; python --version; python -c "import cascadetoml"
which python3; python3 --version; python3 -c "import cascadetoml"
Expand Down
66 changes: 37 additions & 29 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://codewith.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 <https://codewith.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 <https://code.circuitpython.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 <https://github.com/adafruit/Adafruit_Blinka>`_.

CircuitPython is based on `MicroPython <https://micropython.org>`_. See
`below <#differences-from-micropython>`_ for differences. CircuitPython development is sponsored by
`Adafruit <https://adafruit.com>`_ 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 <https://adafruit.com>`_ 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 <https://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 <https://github.com/adafruit/circuitpython/releases>`_ as well.

Documentation
Expand Down Expand Up @@ -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 <https://circuitpython.org>`__ (source
`here <https://github.com/adafruit/circuitpython-org/>`_). 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
Expand All @@ -98,10 +105,11 @@ Differences from `MicroPython <https://github.com/micropython/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
Expand All @@ -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.
Expand All @@ -140,7 +148,7 @@ API

- Unified hardware APIs. Documented on
`ReadTheDocs <https://circuitpython.readthedocs.io/en/latest/shared-bindings/index.html>`_.
- 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
Expand Down
20 changes: 10 additions & 10 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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
Expand All @@ -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.
Expand Down
7 changes: 5 additions & 2 deletions ports/nrf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 $@"
Expand All @@ -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" $^
Expand Down
10 changes: 10 additions & 0 deletions ports/nrf/bluetooth/ble_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -173,4 +180,7 @@ void SD_EVT_IRQHandler(void) {
}
#endif
}
#if CIRCUITPY_SERIAL_BLE && CIRCUITPY_VERBOSE_BLE
ble_serial_enable();
#endif
}
31 changes: 5 additions & 26 deletions supervisor/stub/serial.c → ports/nrf/boards/microbit_v2/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -24,36 +24,15 @@
* THE SOFTWARE.
*/

#include "supervisor/serial.h"
#include "supervisor/workflow.h"

void serial_early_init(void) {

}

void serial_init(void) {
#include "supervisor/board.h"

void board_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;
}
56 changes: 56 additions & 0 deletions ports/nrf/boards/microbit_v2/mpconfigboard.h
Original file line number Diff line number Diff line change
@@ -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)
36 changes: 36 additions & 0 deletions ports/nrf/boards/microbit_v2/mpconfigboard.mk
Original file line number Diff line number Diff line change
@@ -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
Loading