Merge branch 'adafruit:main' into master

This commit is contained in:
Benjamin Shockley 2023-03-16 16:37:14 -05:00 committed by GitHub
commit 20c9edbd63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 460 additions and 166 deletions

View File

@ -67,11 +67,9 @@ jobs:
run: echo "HEAD_SHA=${{ github.event.pull_request.head.sha }}" >> $GITHUB_ENV
- name: Set base sha (pull)
if: github.event_name == 'pull_request'
run: |
git fetch --no-tags --no-recurse-submodules --depth=$((DEPTH + 1)) origin $HEAD_SHA
echo "BASE_SHA=$(git rev-list $HEAD_SHA --skip=$DEPTH --max-count=1)" >> $GITHUB_ENV
run: git cat-file -e $SHA && echo "BASE_SHA=$SHA" >> $GITHUB_ENV || true
env:
DEPTH: ${{ steps.get-last-commit-with-checks.outputs.commit_depth || github.event.pull_request.commits }}
SHA: ${{ steps.get-last-commit-with-checks.outputs.commit_sha || github.event.pull_request.base.sha }}
- name: Set head sha (push)
if: github.event_name == 'push'
run: echo "HEAD_SHA=${{ github.event.after }}" >> $GITHUB_ENV
@ -80,16 +78,11 @@ jobs:
run: git cat-file -e $SHA && echo "BASE_SHA=$SHA" >> $GITHUB_ENV || true
env:
SHA: ${{ github.event.before }}
- name: Get changes
id: get-changes
if: env.BASE_SHA && env.HEAD_SHA
run: echo $(git diff $BASE_SHA...$HEAD_SHA --name-only) | echo "changed_files=[\"$(sed "s/ /\", \"/g")\"]" >> $GITHUB_OUTPUT
- name: Set matrix
id: set-matrix
run: python3 -u ci_set_matrix.py
working-directory: tools
env:
CHANGED_FILES: ${{ steps.get-changes.outputs.changed_files }}
LAST_FAILED_JOBS: ${{ steps.get-last-commit-with-checks.outputs.check_runs }}
tests:

View File

@ -14,7 +14,7 @@ build:
python: "3"
jobs:
post_install:
- python tools/ci_fetch_deps.py build-doc
- python tools/ci_fetch_deps.py docs
formats:
- pdf

View File

@ -31,7 +31,17 @@ import functools
from concurrent.futures import ThreadPoolExecutor
SUPPORTED_PORTS = ['atmel-samd', 'broadcom', 'cxd56', 'espressif', 'litex', 'mimxrt10xx', 'nrf', 'raspberrypi', 'stm']
SUPPORTED_PORTS = [
"atmel-samd",
"broadcom",
"cxd56",
"espressif",
"litex",
"mimxrt10xx",
"nrf",
"raspberrypi",
"stm",
]
ALIASES_BY_BOARD = {
"circuitplayground_express": [
@ -44,16 +54,11 @@ ALIASES_BY_BOARD = {
}
ALIASES_BRAND_NAMES = {
"circuitplayground_express_4h":
"Adafruit Circuit Playground Express 4-H",
"circuitplayground_express_digikey_pycon2019":
"Circuit Playground Express Digi-Key PyCon 2019",
"edgebadge":
"Adafruit EdgeBadge",
"pyportal_pynt":
"Adafruit PyPortal Pynt",
"gemma_m0_pycon2018":
"Adafruit Gemma M0 PyCon 2018",
"circuitplayground_express_4h": "Adafruit Circuit Playground Express 4-H",
"circuitplayground_express_digikey_pycon2019": "Circuit Playground Express Digi-Key PyCon 2019",
"edgebadge": "Adafruit EdgeBadge",
"pyportal_pynt": "Adafruit PyPortal Pynt",
"gemma_m0_pycon2018": "Adafruit Gemma M0 PyCon 2018",
}
ADDITIONAL_MODULES = {
@ -72,7 +77,19 @@ ADDITIONAL_MODULES = {
"usb": "CIRCUITPY_USB_HOST",
}
MODULES_NOT_IN_SHARED_BINDINGS = ["_asyncio", "array", "binascii", "builtins", "collections", "errno", "json", "re", "select", "sys", "ulab"]
MODULES_NOT_IN_BINDINGS = [
"_asyncio",
"array",
"binascii",
"builtins",
"collections",
"errno",
"json",
"re",
"select",
"sys",
"ulab",
]
FROZEN_EXCLUDES = ["examples", "docs", "tests", "utils", "conf.py", "setup.py"]
"""Files and dirs at the root of a frozen directory that should be ignored.
@ -83,16 +100,23 @@ repository_urls = {}
root_dir = pathlib.Path(__file__).resolve().parent.parent
def get_circuitpython_root_dir():
""" The path to the root './circuitpython' directory.
"""
"""The path to the root './circuitpython' directory."""
return root_dir
def get_shared_bindings():
""" Get a list of modules in shared-bindings based on folder names.
"""
shared_bindings_dir = get_circuitpython_root_dir() / "shared-bindings"
return [item.name for item in shared_bindings_dir.iterdir()] + MODULES_NOT_IN_SHARED_BINDINGS
def get_bindings():
"""Get a list of modules in shared-bindings and ports/*/bindings based on folder names."""
shared_bindings_modules = [
module.name
for module in (get_circuitpython_root_dir() / "shared-bindings").iterdir()
if module.is_dir()
]
bindings_modules = []
for d in get_circuitpython_root_dir().glob("ports/*/bindings"):
bindings_modules.extend(module.name for module in d.iterdir() if d.is_dir())
return shared_bindings_modules + bindings_modules + MODULES_NOT_IN_BINDINGS
def get_board_mapping():
@ -124,8 +148,7 @@ def get_board_mapping():
def read_mpconfig():
""" Open 'circuitpy_mpconfig.mk' and return the contents.
"""
"""Open 'circuitpy_mpconfig.mk' and return the contents."""
configs = []
cpy_mpcfg = get_circuitpython_root_dir() / "py" / "circuitpy_mpconfig.mk"
with open(cpy_mpcfg) as mpconfig:
@ -135,14 +158,14 @@ def read_mpconfig():
def build_module_map():
""" Establish the base of the JSON file, based on the contents from
`configs`. Base will contain module names, if they're part of
the `FULL_BUILD`, or their default value (0, 1, or a list of
modules that determine default [see audiocore, audiomixer, etc.]).
"""Establish the base of the JSON file, based on the contents from
`configs`. Base will contain module names, if they're part of
the `FULL_BUILD`, or their default value (0, 1, or a list of
modules that determine default [see audiocore, audiomixer, etc.]).
"""
base = dict()
modules = get_shared_bindings()
modules = get_bindings()
configs = read_mpconfig()
full_build = False
for module in modules:
@ -150,7 +173,7 @@ def build_module_map():
if module in ADDITIONAL_MODULES:
search_identifier = ADDITIONAL_MODULES[module]
else:
search_identifier = 'CIRCUITPY_'+module.lstrip("_").upper()
search_identifier = "CIRCUITPY_" + module.lstrip("_").upper()
re_pattern = f"{re.escape(search_identifier)}\s*\??=\s*(.+)"
find_config = re.findall(re_pattern, configs)
if not find_config:
@ -173,21 +196,22 @@ def build_module_map():
return base
def get_settings_from_makefile(port_dir, board_name):
""" Invoke make in a mode which prints the database, then parse it for
settings.
This means that the effect of all Makefile directives is taken
into account, without having to re-encode the logic that sets them
in this script, something that has proved error-prone
def get_settings_from_makefile(port_dir, board_name):
"""Invoke make in a mode which prints the database, then parse it for
settings.
This means that the effect of all Makefile directives is taken
into account, without having to re-encode the logic that sets them
in this script, something that has proved error-prone
"""
contents = subprocess.run(
["make", "-C", port_dir, f"BOARD={board_name}", "-qp", "print-CC"],
encoding="utf-8",
errors="replace",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
["make", "-C", port_dir, f"BOARD={board_name}", "-qp", "print-CC"],
encoding="utf-8",
errors="replace",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
# Make signals errors with exit status 2; 0 and 1 are "non-error" statuses
if contents.returncode not in (0, 1):
error_msg = (
@ -197,22 +221,23 @@ def get_settings_from_makefile(port_dir, board_name):
raise RuntimeError(error_msg)
settings = {}
for line in contents.stdout.split('\n'):
for line in contents.stdout.split("\n"):
# Handle both = and := definitions.
m = re.match(r'^([A-Z][A-Z0-9_]*) :?= (.*)$', line)
m = re.match(r"^([A-Z][A-Z0-9_]*) :?= (.*)$", line)
if m:
settings[m.group(1)] = m.group(2)
return settings
def get_repository_url(directory):
if directory in repository_urls:
return repository_urls[directory]
readme = None
for readme_path in (
os.path.join(directory, "README.rst"),
os.path.join(os.path.dirname(directory), "README.rst")
):
os.path.join(directory, "README.rst"),
os.path.join(os.path.dirname(directory), "README.rst"),
):
if os.path.exists(readme_path):
readme = readme_path
break
@ -220,7 +245,10 @@ def get_repository_url(directory):
if readme:
with open(readme, "r") as fp:
for line in fp.readlines():
if m := re.match("\s+:target:\s+(http\S+(docs.circuitpython|readthedocs)\S+)\s*", line):
if m := re.match(
"\s+:target:\s+(http\S+(docs.circuitpython|readthedocs)\S+)\s*",
line,
):
path = m.group(1)
break
if m := re.search("<(http[^>]+)>", line):
@ -233,12 +261,13 @@ def get_repository_url(directory):
errors="replace",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=directory
cwd=directory,
)
path = contents.stdout.strip()
repository_urls[directory] = path
return path
def frozen_modules_from_dirs(frozen_mpy_dirs, withurl):
"""
Go through the list of frozen directories and extract the python modules.
@ -261,34 +290,36 @@ def frozen_modules_from_dirs(frozen_mpy_dirs, withurl):
else:
frozen_modules.append(sub.name[:-3])
continue
if next(sub.glob("**/*.py"), None): # tests if not empty
if next(sub.glob("**/*.py"), None): # tests if not empty
if withurl:
frozen_modules.append((sub.name, url_repository))
else:
frozen_modules.append(sub.name)
return frozen_modules
def lookup_setting(settings, key, default=''):
def lookup_setting(settings, key, default=""):
while True:
value = settings.get(key, default)
if not value.startswith('$'):
if not value.startswith("$"):
break
key = value[2:-1]
return value
@functools.cache
def all_ports_all_boards(ports=SUPPORTED_PORTS):
for port in ports:
port_dir = get_circuitpython_root_dir() / "ports" / port
for entry in (port_dir / "boards").iterdir():
if not entry.is_dir():
continue
yield (port, entry)
def support_matrix_by_board(use_branded_name=True, withurl=True):
""" Compiles a list of the available core modules available for each
board.
"""Compiles a list of the available core modules available for each
board.
"""
base = build_module_map()
@ -300,8 +331,9 @@ def support_matrix_by_board(use_branded_name=True, withurl=True):
if use_branded_name:
with open(entry / "mpconfigboard.h") as get_name:
board_contents = get_name.read()
board_name_re = re.search(r"(?<=MICROPY_HW_BOARD_NAME)\s+(.+)",
board_contents)
board_name_re = re.search(
r"(?<=MICROPY_HW_BOARD_NAME)\s+(.+)", board_contents
)
if board_name_re:
board_name = board_name_re.group(1).strip('"')
else:
@ -309,56 +341,69 @@ def support_matrix_by_board(use_branded_name=True, withurl=True):
board_modules = []
for module in base:
key = base[module]['key']
if int(lookup_setting(settings, key, '0')):
board_modules.append(base[module]['name'])
key = base[module]["key"]
if int(lookup_setting(settings, key, "0")):
board_modules.append(base[module]["name"])
board_modules.sort()
if "CIRCUITPY_BUILD_EXTENSIONS" in settings:
board_extensions = [
extension.strip() for extension in
settings["CIRCUITPY_BUILD_EXTENSIONS"].split(",")
extension.strip()
for extension in settings["CIRCUITPY_BUILD_EXTENSIONS"].split(",")
]
else:
raise OSError(f"Board extensions undefined: {board_name}.")
frozen_modules = []
if "FROZEN_MPY_DIRS" in settings:
frozen_modules = frozen_modules_from_dirs(settings["FROZEN_MPY_DIRS"], withurl)
frozen_modules = frozen_modules_from_dirs(
settings["FROZEN_MPY_DIRS"], withurl
)
if frozen_modules:
frozen_modules.sort()
# generate alias boards too
board_matrix = [(
board_name, {
"modules": board_modules,
"frozen_libraries": frozen_modules,
"extensions": board_extensions,
}
)]
board_matrix = [
(
board_name,
{
"modules": board_modules,
"frozen_libraries": frozen_modules,
"extensions": board_extensions,
},
)
]
if entry.name in ALIASES_BY_BOARD:
for alias in ALIASES_BY_BOARD[entry.name]:
if use_branded_name:
if alias in ALIASES_BRAND_NAMES:
alias = ALIASES_BRAND_NAMES[alias]
else:
alias = alias.replace("_"," ").title()
board_matrix.append((
alias, {
"modules": board_modules,
"frozen_libraries": frozen_modules,
"extensions": board_extensions,
},
))
alias = alias.replace("_", " ").title()
board_matrix.append(
(
alias,
{
"modules": board_modules,
"frozen_libraries": frozen_modules,
"extensions": board_extensions,
},
)
)
return board_matrix # this is now a list of (board,modules)
return board_matrix # this is now a list of (board,modules)
executor = ThreadPoolExecutor(max_workers=os.cpu_count())
mapped_exec = executor.map(support_matrix, all_ports_all_boards())
# flatmap with comprehensions
boards = dict(sorted([board for matrix in mapped_exec for board in matrix], key=lambda x: x[0]))
boards = dict(
sorted(
[board for matrix in mapped_exec for board in matrix], key=lambda x: x[0]
)
)
return boards
if __name__ == '__main__':
if __name__ == "__main__":
print(json.dumps(support_matrix_by_board(), indent=2))

@ -1 +1 @@
Subproject commit 73896a3b71c525a3ee4cefa7e35ce3b3a93786ef
Subproject commit ea8ecea59aa60a1028cce16b0f15bb33918b11af

View File

@ -3,9 +3,10 @@
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
// External pins are in silkscreen order, from top to bottom, left side, then right side
// External pins are in silkscreen order, from top to bottom, left side
{MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15)},
{MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2)},
{MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4)},
{MP_ROM_QSTR(MP_QSTR_RX2), MP_ROM_PTR(&pin_GPIO16)},
{MP_ROM_QSTR(MP_QSTR_TX2), MP_ROM_PTR(&pin_GPIO17)},
{MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5)},
@ -16,6 +17,7 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{MP_ROM_QSTR(MP_QSTR_TX0), MP_ROM_PTR(&pin_GPIO3)},
{MP_ROM_QSTR(MP_QSTR_D22), MP_ROM_PTR(&pin_GPIO22)},
{MP_ROM_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_GPIO23)},
// External pins are in silkscreen order, from top to bottom, right side
{MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13)},
{MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12)},
{MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14)},
@ -26,6 +28,8 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{MP_ROM_QSTR(MP_QSTR_D32), MP_ROM_PTR(&pin_GPIO32)},
{MP_ROM_QSTR(MP_QSTR_D35), MP_ROM_PTR(&pin_GPIO35)},
{MP_ROM_QSTR(MP_QSTR_D34), MP_ROM_PTR(&pin_GPIO34)},
{MP_ROM_QSTR(MP_QSTR_VN), MP_ROM_PTR(&pin_GPIO39)},
{MP_ROM_QSTR(MP_QSTR_VP), MP_ROM_PTR(&pin_GPIO36)},
{MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO2)},
@ -39,6 +43,11 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO17)},
{MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO16)},
{MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1)},
{MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3)},
{MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO16)},
{MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17)},
{MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj)},
{MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj)},
{MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj)}

View File

@ -79,8 +79,7 @@ void common_hal_espcamera_camera_construct(
if (common_hal_espidf_get_reserved_psram() == 0) {
mp_raise_msg(&mp_type_MemoryError, translate(
"espcamera.Camera requires reserved PSRAM to be configured. "
"See the documentation for instructions."));
"espcamera.Camera requires reserved PSRAM to be configured. See the documentation for instructions."));
}
for (int i = 0; i < 8; i++) {
claim_pin_number(data_pins[i]);

View File

@ -0,0 +1,29 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* 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
* 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 "supervisor/board.h"
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.

View File

@ -0,0 +1,14 @@
#define MICROPY_HW_BOARD_NAME "Adafruit Feather RP2040 DVI"
#define MICROPY_HW_MCU_NAME "rp2040"
#define MICROPY_HW_NEOPIXEL (&pin_GPIO16)
#define DEFAULT_I2C_BUS_SCL (&pin_GPIO3)
#define DEFAULT_I2C_BUS_SDA (&pin_GPIO2)
#define DEFAULT_SPI_BUS_SCK (&pin_GPIO14)
#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO15)
#define DEFAULT_SPI_BUS_MISO (&pin_GPIO8)
#define DEFAULT_UART_BUS_RX (&pin_GPIO1)
#define DEFAULT_UART_BUS_TX (&pin_GPIO0)

View File

@ -0,0 +1,9 @@
USB_VID = 0x239A
USB_PID = 0x8128
USB_PRODUCT = "Feather RP2040 DVI"
USB_MANUFACTURER = "Adafruit"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2
EXTERNAL_FLASH_DEVICES = "GD25Q64C,W25Q64JVxQ"

View File

@ -0,0 +1,4 @@
// Put board-specific pico-sdk definitions here. This file must exist.
// Allow extra time for xosc to start.
#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64

View File

@ -0,0 +1,52 @@
#include "shared-bindings/board/__init__.h"
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) },
{ MP_ROM_QSTR(MP_QSTR_D24), MP_ROM_PTR(&pin_GPIO24) },
{ MP_ROM_QSTR(MP_QSTR_D25), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_CKN), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_CKP), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_D0N), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_D0P), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_D1N), MP_ROM_PTR(&pin_GPIO20) },
{ MP_ROM_QSTR(MP_QSTR_D1P), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_D2N), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_D2P), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -0,0 +1,45 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* 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
* 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 "supervisor/board.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
#include "supervisor/shared/board.h"
void board_init(void) {
}
bool board_requests_safe_mode(void) {
return false;
}
void reset_board(void) {
// turn off any left over LED
// board_reset_user_neopixels(&pin_GPIO29, 62);
}
void board_deinit(void) {
}

View File

@ -0,0 +1,4 @@
#define MICROPY_HW_BOARD_NAME "BLOK"
#define MICROPY_HW_MCU_NAME "rp2040"
#define MICROPY_HW_NEOPIXEL (&pin_GPIO29)

View File

@ -0,0 +1,14 @@
USB_VID = 0x2E8A
USB_PID = 0x104A
USB_PRODUCT = "BLOK"
USB_MANUFACTURER = "Boardsource"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2
EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ"
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
# CIRCUITPY__EVE = 1

View File

@ -0,0 +1,4 @@
// Put board-specific pico-sdk definitions here. This file must exist.
// Allow extra time for xosc to start.
#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64

View File

@ -0,0 +1,50 @@
#include "shared-bindings/board/__init__.h"
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
{MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0)},
{MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1)},
{MP_ROM_QSTR(MP_QSTR_GP02), MP_ROM_PTR(&pin_GPIO2)},
{MP_ROM_QSTR(MP_QSTR_GP03), MP_ROM_PTR(&pin_GPIO3)},
{MP_ROM_QSTR(MP_QSTR_GP04), MP_ROM_PTR(&pin_GPIO4)},
{MP_ROM_QSTR(MP_QSTR_GP05), MP_ROM_PTR(&pin_GPIO5)},
{MP_ROM_QSTR(MP_QSTR_GP06), MP_ROM_PTR(&pin_GPIO6)},
{MP_ROM_QSTR(MP_QSTR_GP07), MP_ROM_PTR(&pin_GPIO7)},
{MP_ROM_QSTR(MP_QSTR_GP08), MP_ROM_PTR(&pin_GPIO8)},
{MP_ROM_QSTR(MP_QSTR_GP09), MP_ROM_PTR(&pin_GPIO9)},
{MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10)},
{MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11)},
{MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12)},
{MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13)},
{MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14)},
{MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15)},
{MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16)},
{MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17)},
{MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18)},
{MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20)},
{MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21)},
{MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22)},
{MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23)},
{MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24)},
{MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24)},
{MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25)},
{MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO25)},
{MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26)},
{MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27)},
{MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28)},
{MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29)},
{MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO16)},
{MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO17)},
{MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO26)},
{MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO28)},
{MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO27)},
{MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj)},
{MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj)},
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -18,6 +18,8 @@
#define PICO_NO_HARDWARE (0)
#define PICO_ON_DEVICE (1)
#define PICO_PRINTF_ALWAYS_INCLUDED (1)
#define PICO_RP2040_USB_DEVICE_ENUMERATION_FIX (1)
#define PICO_RP2040_USB_DEVICE_UFRAME_FIX (1)
#define PICO_STDIO_IGNORE_NESTED_STDOUT (0)
#define PICO_USE_CRT_PRINTF (0)
#define PICO_USE_OPTIMISTIC_SBRK (0)

View File

@ -39,15 +39,8 @@ STATIC void _usb_irq_wrapper(void) {
}
void post_usb_init(void) {
irq_set_enabled(USBCTRL_IRQ, false);
irq_handler_t usb_handler = irq_get_exclusive_handler(USBCTRL_IRQ);
if (usb_handler) {
irq_remove_handler(USBCTRL_IRQ, usb_handler);
}
irq_set_exclusive_handler(USBCTRL_IRQ, _usb_irq_wrapper);
irq_set_enabled(USBCTRL_IRQ, true);
irq_add_shared_handler(USBCTRL_IRQ, _usb_irq_wrapper,
PICO_SHARED_IRQ_HANDLER_LOWEST_ORDER_PRIORITY);
// There is a small window where the USB interrupt may be handled by the
// pico-sdk instead of CircuitPython. If that is the case, then we'll have

View File

@ -215,7 +215,7 @@ ifneq ($(CIRCUITPY_AUDIOBUSIO_PDMIN),0)
endif
ifneq ($(CIRCUITPY_USB),0)
SRC_C += lib/tinyusb/src/portable/st/synopsys/dcd_synopsys.c
SRC_C += lib/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c
endif
SRC_S = \

View File

@ -45,7 +45,7 @@ mp_obj_t MP_WEAK rtc_get_time_source_time(void) {
//| """Trigger an alarm when the specified time is reached."""
//|
//| def __init__(
//| self, monotonic_time: Optional[float] = None, epoch_time: Optional[int] = None
//| self, *, monotonic_time: Optional[float] = None, epoch_time: Optional[int] = None
//| ) -> None:
//| """Create an alarm that will be triggered when `time.monotonic()` would equal
//| ``monotonic_time``, or when `time.time()` would equal ``epoch_time``.

View File

@ -271,8 +271,7 @@ STATIC mp_obj_t pwmio_pwmout_obj_set_frequency(mp_obj_t self_in, mp_obj_t freque
check_for_deinit(self);
if (!common_hal_pwmio_pwmout_get_variable_frequency(self)) {
mp_raise_AttributeError(translate(
"PWM frequency not writable when variable_frequency is False on "
"construction."));
"PWM frequency not writable when variable_frequency is False on construction."));
}
mp_int_t freq = mp_obj_get_int(frequency);
if (freq == 0) {

View File

@ -61,12 +61,9 @@ uint16_t common_hal_usb_core_device_get_idProduct(usb_core_device_obj_t *self) {
}
STATIC xfer_result_t _get_string_result;
STATIC bool _transfer_done_cb(uint8_t daddr, tusb_control_request_t const *request, xfer_result_t result) {
// Store the result so we stop waiting for the transfer. We don't need the other data for now.
(void)daddr;
(void)request;
_get_string_result = result;
return true;
STATIC void _transfer_done_cb(tuh_xfer_t *xfer) {
// Store the result so we stop waiting for the transfer.
_get_string_result = xfer->result;
}
STATIC void _wait_for_callback(void) {
@ -89,7 +86,7 @@ STATIC mp_obj_t _get_string(const uint16_t *temp_buf) {
mp_obj_t common_hal_usb_core_device_get_serial_number(usb_core_device_obj_t *self) {
_get_string_result = 0xff;
uint16_t temp_buf[127];
if (!tuh_descriptor_string_serial_get(self->device_number, 0, temp_buf, MP_ARRAY_SIZE(temp_buf), _transfer_done_cb)) {
if (!tuh_descriptor_get_serial_string(self->device_number, 0, temp_buf, MP_ARRAY_SIZE(temp_buf), _transfer_done_cb, 0)) {
return mp_const_none;
}
_wait_for_callback();
@ -99,7 +96,7 @@ mp_obj_t common_hal_usb_core_device_get_serial_number(usb_core_device_obj_t *sel
mp_obj_t common_hal_usb_core_device_get_product(usb_core_device_obj_t *self) {
_get_string_result = 0xff;
uint16_t temp_buf[127];
if (!tuh_descriptor_string_product_get(self->device_number, 0, temp_buf, MP_ARRAY_SIZE(temp_buf), _transfer_done_cb)) {
if (!tuh_descriptor_get_product_string(self->device_number, 0, temp_buf, MP_ARRAY_SIZE(temp_buf), _transfer_done_cb, 0)) {
return mp_const_none;
}
_wait_for_callback();
@ -109,7 +106,7 @@ mp_obj_t common_hal_usb_core_device_get_product(usb_core_device_obj_t *self) {
mp_obj_t common_hal_usb_core_device_get_manufacturer(usb_core_device_obj_t *self) {
_get_string_result = 0xff;
uint16_t temp_buf[127];
if (!tuh_descriptor_string_manufacturer_get(self->device_number, 0, temp_buf, MP_ARRAY_SIZE(temp_buf), _transfer_done_cb)) {
if (!tuh_descriptor_get_manufacturer_string(self->device_number, 0, temp_buf, MP_ARRAY_SIZE(temp_buf), _transfer_done_cb, 0)) {
return mp_const_none;
}
_wait_for_callback();
@ -125,11 +122,8 @@ mp_obj_t common_hal_usb_core_device_read(usb_core_device_obj_t *self, mp_int_t e
}
xfer_result_t control_result;
STATIC bool _control_complete_cb(uint8_t dev_addr, tusb_control_request_t const *request, xfer_result_t result) {
(void)dev_addr;
(void)request;
control_result = result;
return true;
STATIC void _control_complete_cb(tuh_xfer_t *xfer) {
control_result = xfer->result;
}
mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self,
@ -145,11 +139,17 @@ mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self,
.wIndex = wIndex,
.wLength = len
};
tuh_xfer_t xfer = {
.daddr = self->device_number,
.ep_addr = 0,
.setup = &request,
.buffer = buffer,
.complete_cb = _control_complete_cb,
};
control_result = XFER_RESULT_STALLED;
bool result = tuh_control_xfer(self->device_number,
&request,
buffer,
_control_complete_cb);
bool result = tuh_control_xfer(&xfer);
if (!result) {
mp_raise_usb_core_USBError(NULL);
}

View File

@ -225,13 +225,17 @@ void usb_background_schedule(void) {
}
void usb_irq_handler(int instance) {
#if CFG_TUSB_MCU != OPT_MCU_RP2040
// For rp2040, IRQ handler is already installed and invoked automatically
if (instance == CIRCUITPY_USB_DEVICE_INSTANCE) {
tud_int_handler(instance);
} else if (instance == CIRCUITPY_USB_HOST_INSTANCE) {
#if CIRCUITPY_USB_HOST
tuh_int_handler(instance);
#endif
}
#if CIRCUITPY_USB_HOST
else if (instance == CIRCUITPY_USB_HOST_INSTANCE) {
tuh_int_handler(instance);
}
#endif
#endif
usb_background_schedule();
}

View File

@ -163,7 +163,6 @@ ifeq ($(CIRCUITPY_USB),1)
SRC_SUPERVISOR += \
lib/tinyusb/src/host/hub.c \
lib/tinyusb/src/host/usbh.c \
lib/tinyusb/src/host/usbh_control.c \
endif
endif

View File

@ -6,6 +6,7 @@
import json
import os
import requests
import subprocess
import sys
import sh
@ -96,7 +97,19 @@ def get_current_info():
response = response.json()
git_info = commit_sha, response["sha"]
current_list = json.loads(base64.b64decode(response["content"]).decode("utf-8"))
if response["content"] != "":
# if the file is there
current_list = json.loads(base64.b64decode(response["content"]).decode("utf-8"))
else:
# if too big, the file is not included
download_url = response["download_url"]
response = requests.get(download_url)
if not response.ok:
print(response.text)
raise RuntimeError("cannot get previous files.json")
current_list = response.json()
current_info = {}
for info in current_list:
current_info[info["id"]] = info

View File

@ -42,51 +42,70 @@ from shared_bindings_matrix import (
all_ports_all_boards,
)
IGNORE = [
"tools/ci_set_matrix.py",
# Files that never influence board builds
IGNORE_BOARD = {
".devcontainer",
"docs",
"tests",
"tools/ci_changes_per_commit.py",
"tools/ci_check_duplicate_usb_vid_pid.py",
]
# Files in these directories never influence board builds
IGNORE_DIRS = ["tests", "docs", ".devcontainer"]
"tools/ci_set_matrix.py",
}
PATTERN_DOCS = (
r"^(?:\.github|docs|extmod\/ulab)|"
r"^(?:(?:ports\/\w+\/bindings|shared-bindings)\S+\.c|tools\/extract_pyi\.py|conf\.py|requirements-doc\.txt)$|"
r"^(?:(?:ports\/\w+\/bindings|shared-bindings)\S+\.c|tools\/extract_pyi\.py|\.readthedocs\.yml|conf\.py|requirements-doc\.txt)$|"
r"(?:-stubs|\.(?:md|MD|rst|RST))$"
)
PATTERN_WINDOWS = [
PATTERN_WINDOWS = {
".github/",
"extmod/",
"lib/",
"mpy-cross/",
"ports/unix/",
"ports/windows/",
"py/",
"requirements",
"tools/",
]
"requirements-dev.txt",
}
def git_diff(pattern: str):
return set(
subprocess.run(
f"git diff {pattern} --name-only",
capture_output=True,
shell=True,
)
.stdout.decode("utf-8")
.split("\n")[:-1]
)
if len(sys.argv) > 1:
print("Using files list on commandline")
changed_files = sys.argv[1:]
last_failed_jobs = {}
changed_files = set(sys.argv[1:])
elif os.environ.get("BASE_SHA") and os.environ.get("HEAD_SHA"):
print("Using files list by computing diff")
changed_files = git_diff("$BASE_SHA...$HEAD_SHA")
if os.environ.get("GITHUB_EVENT_NAME") == "pull_request":
changed_files.intersection_update(git_diff("$GITHUB_SHA~...$GITHUB_SHA"))
else:
c = os.environ["CHANGED_FILES"]
if c == "":
print("CHANGED_FILES is in environment, but value is empty")
changed_files = []
else:
print("Using files list in CHANGED_FILES")
changed_files = json.loads(c.replace("\\", ""))
print("Using files list in CHANGED_FILES")
changed_files = set(json.loads(os.environ.get("CHANGED_FILES") or "[]"))
j = os.environ["LAST_FAILED_JOBS"]
if j == "":
print("LAST_FAILED_JOBS is in environment, but value is empty")
last_failed_jobs = {}
else:
last_failed_jobs = json.loads(j)
print("Using jobs list in LAST_FAILED_JOBS")
last_failed_jobs = json.loads(os.environ.get("LAST_FAILED_JOBS") or "{}")
def print_enclosed(title, content):
print("::group::" + title)
print(content)
print("::endgroup::")
print_enclosed("Log: changed_files", changed_files)
print_enclosed("Log: last_failed_jobs", last_failed_jobs)
def set_output(name: str, value):
@ -155,11 +174,7 @@ def set_boards(build_all: bool):
boards_to_build.update(port_to_boards[port])
continue
# Check the ignore list to see if the file isn't used on board builds.
if p in IGNORE:
continue
if any([p.startswith(d) for d in IGNORE_DIRS]):
if any([p.startswith(d) for d in IGNORE_BOARD]):
continue
# As a (nearly) last resort, for some certain files, we compute the settings from the
@ -269,7 +284,9 @@ def set_windows(build_windows: bool):
else:
for file in changed_files:
for pattern in PATTERN_WINDOWS:
if file.startswith(pattern):
if file.startswith(pattern) and not any(
[file.startswith(d) for d in IGNORE_BOARD]
):
build_windows = True
break
else:
@ -284,11 +301,7 @@ def set_windows(build_windows: bool):
def main():
# Build all if no changed files
build_all = not changed_files
print(
"Building all docs/boards"
if build_all
else "Adding docs/boards to build based on changed files"
)
print("Running: " + ("all" if build_all else "conditionally"))
# Set jobs
set_docs(build_all)