Create first BLE-only board, Micro:Bit v2
This fixes build issues with USB off, tweaks the README to allow for BLE-only boards and adds the Micro:Bit v2 definition. Fixes #4546
This commit is contained in:
parent
9fdecacec7
commit
0fadf028ef
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@ -303,6 +303,7 @@ jobs:
|
||||
- "metro_m4_express"
|
||||
- "metro_m7_1011"
|
||||
- "metro_nrf52840_express"
|
||||
- "microbit_v2"
|
||||
- "mini_sam_m4"
|
||||
- "monster_m4sk"
|
||||
- "ndgarage_ndbit6"
|
||||
|
66
README.rst
66
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 <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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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 <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
|
||||
|
20
main.c
20
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.
|
||||
|
@ -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" $^
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
56
ports/nrf/boards/microbit_v2/mpconfigboard.h
Normal file
56
ports/nrf/boards/microbit_v2/mpconfigboard.h
Normal file
@ -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
ports/nrf/boards/microbit_v2/mpconfigboard.mk
Normal file
36
ports/nrf/boards/microbit_v2/mpconfigboard.mk
Normal file
@ -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
|
59
ports/nrf/boards/microbit_v2/pins.c
Normal file
59
ports/nrf/boards/microbit_v2/pins.c
Normal file
@ -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);
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -41,14 +41,11 @@
|
||||
#include "nrf_soc.h"
|
||||
#include <string.h>
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#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*/
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 <string.h>
|
||||
#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
|
@ -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) \
|
||||
|
@ -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)
|
||||
|
@ -32,3 +32,6 @@ mypy
|
||||
|
||||
# For uploading artifacts
|
||||
awscli
|
||||
|
||||
# for combining the Nordic SoftDevice with CircuitPython
|
||||
intelhex
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -30,10 +30,13 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user