Add Zephyr port
This port is meant to grow to encompass all existing boards. For now, it is a port while we transition over. It is named `zephyr-cp` to differentiate it from the MicroPython `zephyr` port. They are separate implementations.
This commit is contained in:
parent
11711fd53d
commit
7f0cc9e7b4
140 changed files with 10322 additions and 294 deletions
5
.github/actions/deps/external/action.yml
vendored
5
.github/actions/deps/external/action.yml
vendored
|
|
@ -22,7 +22,8 @@ runs:
|
||||||
if: >-
|
if: >-
|
||||||
inputs.port != 'none' &&
|
inputs.port != 'none' &&
|
||||||
inputs.port != 'litex' &&
|
inputs.port != 'litex' &&
|
||||||
inputs.port != 'espressif'
|
inputs.port != 'espressif' &&
|
||||||
|
inputs.port != 'zephyr-cp'
|
||||||
uses: carlosperate/arm-none-eabi-gcc-action@v1
|
uses: carlosperate/arm-none-eabi-gcc-action@v1
|
||||||
with:
|
with:
|
||||||
# When changing this update what Windows grabs too!
|
# When changing this update what Windows grabs too!
|
||||||
|
|
@ -51,7 +52,7 @@ runs:
|
||||||
|
|
||||||
# common
|
# common
|
||||||
- name: Cache python dependencies
|
- name: Cache python dependencies
|
||||||
if: inputs.port != 'espressif'
|
if: inputs.port != 'espressif' && inputs.port != 'zephyr-cp'
|
||||||
uses: ./.github/actions/deps/python
|
uses: ./.github/actions/deps/python
|
||||||
with:
|
with:
|
||||||
action: ${{ inputs.action }}
|
action: ${{ inputs.action }}
|
||||||
|
|
|
||||||
24
.github/actions/deps/ports/action.yml
vendored
24
.github/actions/deps/ports/action.yml
vendored
|
|
@ -4,33 +4,29 @@ inputs:
|
||||||
board:
|
board:
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
outputs:
|
|
||||||
port:
|
port:
|
||||||
value: ${{ steps.board-to-port.outputs.port }}
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
- name: Board to port
|
|
||||||
id: board-to-port
|
|
||||||
run: |
|
|
||||||
PORT=$(find ports/*/boards/ -type d -name ${{ inputs.board }} | sed 's/^ports\///g;s/\/boards.*//g')
|
|
||||||
if [ -z $PORT ]; then (exit 1); else echo >> $GITHUB_OUTPUT "port=$PORT"; fi
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Set up broadcom
|
- name: Set up broadcom
|
||||||
if: steps.board-to-port.outputs.port == 'broadcom'
|
if: inputs.port == 'broadcom'
|
||||||
uses: ./.github/actions/deps/ports/broadcom
|
uses: ./.github/actions/deps/ports/broadcom
|
||||||
|
|
||||||
- name: Set up espressif
|
- name: Set up espressif
|
||||||
if: steps.board-to-port.outputs.port == 'espressif'
|
if: inputs.port == 'espressif'
|
||||||
uses: ./.github/actions/deps/ports/espressif
|
uses: ./.github/actions/deps/ports/espressif
|
||||||
|
|
||||||
- name: Set up litex
|
- name: Set up litex
|
||||||
if: steps.board-to-port.outputs.port == 'litex'
|
if: inputs.port == 'litex'
|
||||||
uses: ./.github/actions/deps/ports/litex
|
uses: ./.github/actions/deps/ports/litex
|
||||||
|
|
||||||
- name: Set up nordic
|
- name: Set up nordic
|
||||||
if: steps.board-to-port.outputs.port == 'nordic'
|
if: inputs.port == 'nordic'
|
||||||
uses: ./.github/actions/deps/ports/nordic
|
uses: ./.github/actions/deps/ports/nordic
|
||||||
|
|
||||||
|
- name: Set up Zephyr
|
||||||
|
if: inputs.port == 'zephyr-cp'
|
||||||
|
uses: ./.github/actions/deps/ports/zephyr-cp
|
||||||
|
|
|
||||||
15
.github/actions/deps/ports/zephyr-cp/action.yml
vendored
Normal file
15
.github/actions/deps/ports/zephyr-cp/action.yml
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
name: Fetch Zephyr port deps
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: Setup Zephyr project
|
||||||
|
uses: zephyrproject-rtos/action-zephyr-setup@v1
|
||||||
|
with:
|
||||||
|
app-path: zephyr-config
|
||||||
|
base-path: ports/zephyr-cp
|
||||||
|
toolchains: arm-zephyr-eabi
|
||||||
|
- name: Export cmake info
|
||||||
|
run: west zephyr-export
|
||||||
|
shell: bash
|
||||||
|
working-directory: ports/zephyr-cp
|
||||||
2
.github/actions/deps/submodules/action.yml
vendored
2
.github/actions/deps/submodules/action.yml
vendored
|
|
@ -80,7 +80,7 @@ runs:
|
||||||
git fetch --no-recurse-submodules --shallow-since="2021-07-01" origin $GITHUB_SHA
|
git fetch --no-recurse-submodules --shallow-since="2021-07-01" origin $GITHUB_SHA
|
||||||
git repack -d
|
git repack -d
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
CP_VERSION=$(tools/describe)
|
CP_VERSION=$(python py/version.py)
|
||||||
echo "$CP_VERSION"
|
echo "$CP_VERSION"
|
||||||
echo "CP_VERSION=$CP_VERSION" >> $GITHUB_ENV
|
echo "CP_VERSION=$CP_VERSION" >> $GITHUB_ENV
|
||||||
echo "cp-version=$CP_VERSION" >> $GITHUB_OUTPUT
|
echo "cp-version=$CP_VERSION" >> $GITHUB_OUTPUT
|
||||||
|
|
|
||||||
2
.github/workflows/build-board-custom.yml
vendored
2
.github/workflows/build-board-custom.yml
vendored
|
|
@ -97,7 +97,7 @@ jobs:
|
||||||
download: false
|
download: false
|
||||||
- name: Versions
|
- name: Versions
|
||||||
run: |
|
run: |
|
||||||
tools/describe
|
python py/version.py
|
||||||
gcc --version
|
gcc --version
|
||||||
python3 --version
|
python3 --version
|
||||||
cmake --version || true
|
cmake --version || true
|
||||||
|
|
|
||||||
6
.github/workflows/build-boards.yml
vendored
6
.github/workflows/build-boards.yml
vendored
|
|
@ -9,6 +9,9 @@ on:
|
||||||
cp-version:
|
cp-version:
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
|
port:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
secrets:
|
secrets:
|
||||||
AWS_ACCESS_KEY_ID:
|
AWS_ACCESS_KEY_ID:
|
||||||
required: false
|
required: false
|
||||||
|
|
@ -43,6 +46,7 @@ jobs:
|
||||||
uses: ./.github/actions/deps/ports
|
uses: ./.github/actions/deps/ports
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
board: ${{ matrix.board }}
|
||||||
|
port: ${{ inputs.port }}
|
||||||
|
|
||||||
- name: Set up submodules
|
- name: Set up submodules
|
||||||
id: set-up-submodules
|
id: set-up-submodules
|
||||||
|
|
@ -51,7 +55,7 @@ jobs:
|
||||||
- name: Set up external
|
- name: Set up external
|
||||||
uses: ./.github/actions/deps/external
|
uses: ./.github/actions/deps/external
|
||||||
with:
|
with:
|
||||||
port: ${{ steps.set-up-port.outputs.port }}
|
port: ${{ inputs.port }}
|
||||||
- name: Set up mpy-cross
|
- name: Set up mpy-cross
|
||||||
if: steps.set-up-submodules.outputs.frozen == 'True'
|
if: steps.set-up-submodules.outputs.frozen == 'True'
|
||||||
uses: ./.github/actions/mpy_cross
|
uses: ./.github/actions/mpy_cross
|
||||||
|
|
|
||||||
30
.github/workflows/build.yml
vendored
30
.github/workflows/build.yml
vendored
|
|
@ -299,6 +299,35 @@ jobs:
|
||||||
# ERROR: Platform MINGW64_NT-10.0-17763-x86_64 appears to be unsupported
|
# ERROR: Platform MINGW64_NT-10.0-17763-x86_64 appears to be unsupported
|
||||||
# https://github.com/espressif/esp-idf/issues/7062
|
# https://github.com/espressif/esp-idf/issues/7062
|
||||||
|
|
||||||
|
windows-zephyr:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [windows-2022, windows-2025]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
needs: scheduler
|
||||||
|
if: needs.scheduler.outputs.windows == 'True'
|
||||||
|
env:
|
||||||
|
CP_VERSION: ${{ needs.scheduler.outputs.cp-version }}
|
||||||
|
steps:
|
||||||
|
- name: Set up repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: false
|
||||||
|
show-progress: false
|
||||||
|
fetch-depth: 1
|
||||||
|
persist-credentials: false
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.13'
|
||||||
|
- name: Set up Zephyr
|
||||||
|
uses: ./.github/actions/deps/ports/zephyr-cp
|
||||||
|
- name: Set up submodules
|
||||||
|
uses: ./.github/actions/deps/submodules
|
||||||
|
- name: build mpy-cross
|
||||||
|
run: make -j4 -C mpy-cross
|
||||||
|
- name: build ek_ra8d1
|
||||||
|
run: make -j4 -C ports/zephyr-cp BOARD=renesas_ek_ra8d1
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
needs: [scheduler, mpy-cross, tests]
|
needs: [scheduler, mpy-cross, tests]
|
||||||
if: needs.scheduler.outputs.ports != '{}'
|
if: needs.scheduler.outputs.ports != '{}'
|
||||||
|
|
@ -311,3 +340,4 @@ jobs:
|
||||||
with:
|
with:
|
||||||
boards: ${{ toJSON(fromJSON(needs.scheduler.outputs.ports)[matrix.port]) }}
|
boards: ${{ toJSON(fromJSON(needs.scheduler.outputs.ports)[matrix.port]) }}
|
||||||
cp-version: ${{ needs.scheduler.outputs.cp-version }}
|
cp-version: ${{ needs.scheduler.outputs.cp-version }}
|
||||||
|
port: ${{ matrix.port }}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,8 @@ repos:
|
||||||
tests/unicode/data/utf-8_invalid.txt|
|
tests/unicode/data/utf-8_invalid.txt|
|
||||||
tests/extmod/data/qr.pgm|
|
tests/extmod/data/qr.pgm|
|
||||||
tests/basics/bytearray_byte_operations.py|
|
tests/basics/bytearray_byte_operations.py|
|
||||||
ports/raspberrypi/sdk
|
ports/raspberrypi/sdk|
|
||||||
|
ports/zephyr-cp/cptools/compat2driver.py
|
||||||
)
|
)
|
||||||
- repo: local
|
- repo: local
|
||||||
hooks:
|
hooks:
|
||||||
|
|
|
||||||
4
conf.py
4
conf.py
|
|
@ -32,8 +32,6 @@ from docutils import nodes
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.ext import intersphinx
|
from sphinx.ext import intersphinx
|
||||||
|
|
||||||
tools_describe = str(pathlib.Path(__file__).parent / "tools/describe")
|
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
|
@ -145,7 +143,7 @@ copyright = f'2014-{current_date.tm_year}, MicroPython & CircuitPython contribut
|
||||||
|
|
||||||
final_version = ""
|
final_version = ""
|
||||||
git_describe = subprocess.run(
|
git_describe = subprocess.run(
|
||||||
[tools_describe],
|
["python", "py/version.py"],
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
encoding="utf-8"
|
encoding="utf-8"
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import os
|
||||||
import pathlib
|
import pathlib
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import tomllib
|
||||||
|
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
|
||||||
|
|
@ -43,6 +43,7 @@ SUPPORTED_PORTS = [
|
||||||
"renode",
|
"renode",
|
||||||
"silabs",
|
"silabs",
|
||||||
"stm",
|
"stm",
|
||||||
|
"zephyr-cp",
|
||||||
]
|
]
|
||||||
|
|
||||||
ALIASES_BY_BOARD = {
|
ALIASES_BY_BOARD = {
|
||||||
|
|
@ -130,14 +131,21 @@ def get_board_mapping():
|
||||||
boards = {}
|
boards = {}
|
||||||
for port in SUPPORTED_PORTS:
|
for port in SUPPORTED_PORTS:
|
||||||
board_path = root_dir / "ports" / port / "boards"
|
board_path = root_dir / "ports" / port / "boards"
|
||||||
for board_path in os.scandir(board_path):
|
# Zephyr port has vendor specific subdirectories to match zephyr (and
|
||||||
|
# clean up the boards folder.)
|
||||||
|
g = "*/*" if port == "zephyr-cp" else "*"
|
||||||
|
for board_path in board_path.glob(g):
|
||||||
if board_path.is_dir():
|
if board_path.is_dir():
|
||||||
board_id = board_path.name
|
board_id = board_path.name
|
||||||
|
if port == "zephyr-cp":
|
||||||
|
vendor = board_path.parent.name
|
||||||
|
board_id = f"{vendor}_{board_id}"
|
||||||
aliases = ALIASES_BY_BOARD.get(board_path.name, [])
|
aliases = ALIASES_BY_BOARD.get(board_path.name, [])
|
||||||
boards[board_id] = {
|
boards[board_id] = {
|
||||||
"port": port,
|
"port": port,
|
||||||
"download_count": 0,
|
"download_count": 0,
|
||||||
"aliases": aliases,
|
"aliases": aliases,
|
||||||
|
"directory": board_path,
|
||||||
}
|
}
|
||||||
for alias in aliases:
|
for alias in aliases:
|
||||||
boards[alias] = {
|
boards[alias] = {
|
||||||
|
|
@ -145,6 +153,7 @@ def get_board_mapping():
|
||||||
"download_count": 0,
|
"download_count": 0,
|
||||||
"alias": True,
|
"alias": True,
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
"directory": board_path,
|
||||||
}
|
}
|
||||||
return boards
|
return boards
|
||||||
|
|
||||||
|
|
@ -295,15 +304,6 @@ def lookup_setting(settings, key, default=""):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
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,
|
def support_matrix_by_board(use_branded_name=True, withurl=True,
|
||||||
add_port=False, add_chips=False,
|
add_port=False, add_chips=False,
|
||||||
add_pins=False, add_branded_name=False):
|
add_pins=False, add_branded_name=False):
|
||||||
|
|
@ -313,29 +313,44 @@ def support_matrix_by_board(use_branded_name=True, withurl=True,
|
||||||
base = build_module_map()
|
base = build_module_map()
|
||||||
|
|
||||||
def support_matrix(arg):
|
def support_matrix(arg):
|
||||||
port, entry = arg
|
board_id, board_info = arg
|
||||||
port_dir = get_circuitpython_root_dir() / "ports" / port
|
port = board_info["port"]
|
||||||
settings = get_settings_from_makefile(str(port_dir), entry.name)
|
board_directory = board_info["directory"]
|
||||||
|
port_dir = board_directory.parent.parent
|
||||||
|
if port != "zephyr-cp":
|
||||||
|
settings = get_settings_from_makefile(str(port_dir), board_directory.name)
|
||||||
|
autogen_board_info = None
|
||||||
|
else:
|
||||||
|
circuitpython_toml_fn = board_directory / "circuitpython.toml"
|
||||||
|
with circuitpython_toml_fn.open("rb") as f:
|
||||||
|
settings = tomllib.load(f)
|
||||||
|
|
||||||
|
autogen_board_info_fn = board_directory / "autogen_board_info.toml"
|
||||||
|
with autogen_board_info_fn.open("rb") as f:
|
||||||
|
autogen_board_info = tomllib.load(f)
|
||||||
|
|
||||||
if use_branded_name or add_branded_name:
|
if use_branded_name or add_branded_name:
|
||||||
with open(entry / "mpconfigboard.h") as get_name:
|
if autogen_board_info:
|
||||||
board_contents = get_name.read()
|
branded_name = autogen_board_info["name"]
|
||||||
board_name_re = re.search(
|
else:
|
||||||
r"(?<=MICROPY_HW_BOARD_NAME)\s+(.+)", board_contents
|
with open(board_directory / "mpconfigboard.h") as get_name:
|
||||||
)
|
board_contents = get_name.read()
|
||||||
if board_name_re:
|
board_name_re = re.search(
|
||||||
branded_name = board_name_re.group(1).strip('"')
|
r"(?<=MICROPY_HW_BOARD_NAME)\s+(.+)", board_contents
|
||||||
if '"' in branded_name: # sometimes the closing " is not at line end
|
)
|
||||||
branded_name = branded_name[:branded_name.index('"')]
|
if board_name_re:
|
||||||
board_name = branded_name
|
branded_name = board_name_re.group(1).strip('"')
|
||||||
|
if '"' in branded_name: # sometimes the closing " is not at line end
|
||||||
|
branded_name = branded_name[:branded_name.index('"')]
|
||||||
|
board_name = branded_name
|
||||||
|
|
||||||
if use_branded_name:
|
if use_branded_name:
|
||||||
board_name = branded_name
|
board_name = branded_name
|
||||||
else:
|
else:
|
||||||
board_name = entry.name
|
board_name = board_directory.name
|
||||||
|
|
||||||
if add_chips:
|
if add_chips:
|
||||||
with open(entry / "mpconfigboard.h") as get_name:
|
with open(board_directory / "mpconfigboard.h") as get_name:
|
||||||
board_contents = get_name.read()
|
board_contents = get_name.read()
|
||||||
mcu_re = re.search(
|
mcu_re = re.search(
|
||||||
r'(?<=MICROPY_HW_MCU_NAME)\s+(.+)', board_contents
|
r'(?<=MICROPY_HW_MCU_NAME)\s+(.+)', board_contents
|
||||||
|
|
@ -346,7 +361,7 @@ def support_matrix_by_board(use_branded_name=True, withurl=True,
|
||||||
mcu = mcu[:mcu.index('"')]
|
mcu = mcu[:mcu.index('"')]
|
||||||
else:
|
else:
|
||||||
mcu = ""
|
mcu = ""
|
||||||
with open(entry / "mpconfigboard.mk") as get_name:
|
with open(board_directory / "mpconfigboard.mk") as get_name:
|
||||||
board_contents = get_name.read()
|
board_contents = get_name.read()
|
||||||
flash_re = re.search(
|
flash_re = re.search(
|
||||||
r'(?<=EXTERNAL_FLASH_DEVICES)\s+=\s+(.+)', board_contents
|
r'(?<=EXTERNAL_FLASH_DEVICES)\s+=\s+(.+)', board_contents
|
||||||
|
|
@ -363,7 +378,7 @@ def support_matrix_by_board(use_branded_name=True, withurl=True,
|
||||||
if add_pins:
|
if add_pins:
|
||||||
pins = []
|
pins = []
|
||||||
try:
|
try:
|
||||||
with open(entry / "pins.c") as get_name:
|
with open(board_directory / "pins.c") as get_name:
|
||||||
pin_lines = get_name.readlines()
|
pin_lines = get_name.readlines()
|
||||||
except FileNotFoundError: # silabs boards have no pins.c
|
except FileNotFoundError: # silabs boards have no pins.c
|
||||||
pass
|
pass
|
||||||
|
|
@ -376,17 +391,25 @@ def support_matrix_by_board(use_branded_name=True, withurl=True,
|
||||||
pins.append((board_pin, chip_pin))
|
pins.append((board_pin, chip_pin))
|
||||||
|
|
||||||
board_modules = []
|
board_modules = []
|
||||||
for module in base:
|
if autogen_board_info:
|
||||||
key = base[module]["key"]
|
autogen_modules = autogen_board_info["modules"]
|
||||||
if int(lookup_setting(settings, key, "0")):
|
for k in autogen_modules:
|
||||||
board_modules.append(base[module]["name"])
|
if autogen_modules[k]:
|
||||||
|
board_modules.append(k)
|
||||||
|
else:
|
||||||
|
for module in base:
|
||||||
|
key = base[module]["key"]
|
||||||
|
if int(lookup_setting(settings, key, "0")):
|
||||||
|
board_modules.append(base[module]["name"])
|
||||||
board_modules.sort()
|
board_modules.sort()
|
||||||
|
|
||||||
if "CIRCUITPY_BUILD_EXTENSIONS" in settings:
|
if "CIRCUITPY_BUILD_EXTENSIONS" in settings:
|
||||||
board_extensions = [
|
board_extensions = settings["CIRCUITPY_BUILD_EXTENSIONS"]
|
||||||
extension.strip()
|
if isinstance(board_extensions, str):
|
||||||
for extension in settings["CIRCUITPY_BUILD_EXTENSIONS"].split(",")
|
board_extensions = [
|
||||||
]
|
extension.strip()
|
||||||
|
for extension in board_extensions.split(",")
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
raise OSError(f"Board extensions undefined: {board_name}.")
|
raise OSError(f"Board extensions undefined: {board_name}.")
|
||||||
|
|
||||||
|
|
@ -420,8 +443,8 @@ def support_matrix_by_board(use_branded_name=True, withurl=True,
|
||||||
board_info
|
board_info
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
if entry.name in ALIASES_BY_BOARD:
|
if board_id in ALIASES_BY_BOARD:
|
||||||
for alias in ALIASES_BY_BOARD[entry.name]:
|
for alias in ALIASES_BY_BOARD[board_id]:
|
||||||
if use_branded_name:
|
if use_branded_name:
|
||||||
if alias in ALIASES_BRAND_NAMES:
|
if alias in ALIASES_BRAND_NAMES:
|
||||||
alias = ALIASES_BRAND_NAMES[alias]
|
alias = ALIASES_BRAND_NAMES[alias]
|
||||||
|
|
@ -450,8 +473,14 @@ def support_matrix_by_board(use_branded_name=True, withurl=True,
|
||||||
|
|
||||||
return board_matrix # this is now a list of (board,modules)
|
return board_matrix # this is now a list of (board,modules)
|
||||||
|
|
||||||
|
|
||||||
|
board_mapping = get_board_mapping()
|
||||||
|
real_boards = []
|
||||||
|
for board in board_mapping:
|
||||||
|
if not board_mapping[board].get("alias", False):
|
||||||
|
real_boards.append((board, board_mapping[board]))
|
||||||
executor = ThreadPoolExecutor(max_workers=os.cpu_count())
|
executor = ThreadPoolExecutor(max_workers=os.cpu_count())
|
||||||
mapped_exec = executor.map(support_matrix, all_ports_all_boards())
|
mapped_exec = executor.map(support_matrix, real_boards)
|
||||||
# flatmap with comprehensions
|
# flatmap with comprehensions
|
||||||
boards = dict(
|
boards = dict(
|
||||||
sorted(
|
sorted(
|
||||||
|
|
|
||||||
|
|
@ -25,3 +25,4 @@ Additional testing is limited.
|
||||||
../ports/silabs/README
|
../ports/silabs/README
|
||||||
../ports/stm/README
|
../ports/stm/README
|
||||||
../ports/unix/README
|
../ports/unix/README
|
||||||
|
../ports/zephyr-cp/README
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@ static mbedtls_x509_crt s_dummy_crt;
|
||||||
#define LOGD(tag, fmt, ...) do {} while (0)
|
#define LOGD(tag, fmt, ...) do {} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const uint8_t x509_crt_imported_bundle_bin_start[] asm ("_binary_x509_crt_bundle_start");
|
extern const uint8_t x509_crt_imported_bundle_bin_start[] __asm__ ("_binary_x509_crt_bundle_start");
|
||||||
extern const uint8_t x509_crt_imported_bundle_bin_end[] asm ("_binary_x509_crt_bundle_end");
|
extern const uint8_t x509_crt_imported_bundle_bin_end[] __asm__ ("_binary_x509_crt_bundle_end");
|
||||||
|
|
||||||
|
|
||||||
typedef struct crt_bundle_t {
|
typedef struct crt_bundle_t {
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2d7d1070fc9eb8db7061b4f0e20408a453df1f7e
|
Subproject commit eca025f7143141fd2bc99a94619c62a6fd666f28
|
||||||
6
main.c
6
main.c
|
|
@ -974,7 +974,13 @@ static int run_repl(safe_mode_t safe_mode) {
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__ZEPHYR__) && __ZEPHYR__ == 1
|
||||||
|
#include <zephyr/console/console.h>
|
||||||
|
|
||||||
|
int circuitpython_main(void) {
|
||||||
|
#else
|
||||||
int __attribute__((used)) main(void) {
|
int __attribute__((used)) main(void) {
|
||||||
|
#endif
|
||||||
|
|
||||||
// initialise the cpu and peripherals
|
// initialise the cpu and peripherals
|
||||||
set_safe_mode(port_init());
|
set_safe_mode(port_init());
|
||||||
|
|
|
||||||
|
|
@ -70,3 +70,5 @@ CIRCUITPY_BUSDEVICE = 0
|
||||||
|
|
||||||
# For CircuitPython CI
|
# For CircuitPython CI
|
||||||
CIRCUITPY_BUILD_EXTENSIONS ?= elf
|
CIRCUITPY_BUILD_EXTENSIONS ?= elf
|
||||||
|
|
||||||
|
CIRCUITPY_PORT_SERIAL = 1
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,10 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void port_serial_early_init(void) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void port_serial_init(void) {
|
void port_serial_init(void) {
|
||||||
#if MAX32_SERIAL
|
#if MAX32_SERIAL
|
||||||
MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_IBRO_EN;
|
MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_IBRO_EN;
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ CIRCUITPY_WIFI_RADIO_SETTABLE_LISTEN_INTERVAL = 1
|
||||||
# Never use our copy of MBEDTLS
|
# Never use our copy of MBEDTLS
|
||||||
CIRCUITPY_HASHLIB_MBEDTLS_ONLY = 0
|
CIRCUITPY_HASHLIB_MBEDTLS_ONLY = 0
|
||||||
|
|
||||||
|
CIRCUITPY_PORT_SERIAL = 1
|
||||||
|
|
||||||
# These modules are implemented in ports/<port>/common-hal:
|
# These modules are implemented in ports/<port>/common-hal:
|
||||||
CIRCUITPY_ALARM ?= 1
|
CIRCUITPY_ALARM ?= 1
|
||||||
CIRCUITPY_ALARM_TOUCH ?= 0
|
CIRCUITPY_ALARM_TOUCH ?= 0
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@
|
||||||
#include "supervisor/usb_serial_jtag.h"
|
#include "supervisor/usb_serial_jtag.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void port_serial_early_init(void) {
|
||||||
|
}
|
||||||
|
|
||||||
void port_serial_init(void) {
|
void port_serial_init(void) {
|
||||||
#if CIRCUITPY_ESP_USB_SERIAL_JTAG
|
#if CIRCUITPY_ESP_USB_SERIAL_JTAG
|
||||||
usb_serial_jtag_init();
|
usb_serial_jtag_init();
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ CIRCUITPY_RTC ?= 1
|
||||||
CIRCUITPY_USB_DEVICE = 0
|
CIRCUITPY_USB_DEVICE = 0
|
||||||
CIRCUITPY_WATCHDOG ?=1
|
CIRCUITPY_WATCHDOG ?=1
|
||||||
|
|
||||||
|
CIRCUITPY_PORT_SERIAL = 1
|
||||||
|
|
||||||
ifeq ($(MCU_SERIES),MG24)
|
ifeq ($(MCU_SERIES),MG24)
|
||||||
# Not yet implemented common-hal modules:
|
# Not yet implemented common-hal modules:
|
||||||
CIRCUITPY_AUDIOIO ?= 0
|
CIRCUITPY_AUDIOIO ?= 0
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ ifeq ($(MCU_SERIES),F4)
|
||||||
CIRCUITPY_NVM ?= 0
|
CIRCUITPY_NVM ?= 0
|
||||||
CIRCUITPY_ROTARYIO ?= 0
|
CIRCUITPY_ROTARYIO ?= 0
|
||||||
CIRCUITPY_RTC ?= 1
|
CIRCUITPY_RTC ?= 1
|
||||||
|
CIRCUITPY_PORT_SERIAL ?= 1
|
||||||
USB_NUM_ENDPOINT_PAIRS = 4
|
USB_NUM_ENDPOINT_PAIRS = 4
|
||||||
UF2_FAMILY_ID ?= 0x57755a57
|
UF2_FAMILY_ID ?= 0x57755a57
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,10 @@
|
||||||
UART_HandleTypeDef huart2;
|
UART_HandleTypeDef huart2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void port_serial_early_init(void) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void port_serial_init(void) {
|
void port_serial_init(void) {
|
||||||
#if CPY_STM32F4
|
#if CPY_STM32F4
|
||||||
huart2.Instance = USART2;
|
huart2.Instance = USART2;
|
||||||
|
|
|
||||||
7
ports/zephyr-cp/.gitignore
vendored
Normal file
7
ports/zephyr-cp/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# West manages these folders.
|
||||||
|
bootloader
|
||||||
|
build
|
||||||
|
modules
|
||||||
|
tools
|
||||||
|
zephyr
|
||||||
|
.west
|
||||||
64
ports/zephyr-cp/CMakeLists.txt
Normal file
64
ports/zephyr-cp/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
cmake_minimum_required(VERSION 3.20.0)
|
||||||
|
|
||||||
|
find_package(Zephyr REQUIRED HINTS lib/zephyr)
|
||||||
|
project(circuitpython)
|
||||||
|
|
||||||
|
target_sources(app PRIVATE zephyr_main.c)
|
||||||
|
|
||||||
|
# From: https://github.com/zephyrproject-rtos/zephyr/blob/main/samples/application_development/external_lib/CMakeLists.txt
|
||||||
|
# The external static library that we are linking with does not know
|
||||||
|
# how to build for this platform so we export all the flags used in
|
||||||
|
# this zephyr build to the external build system.
|
||||||
|
#
|
||||||
|
# Other external build systems may be self-contained enough that they
|
||||||
|
# do not need any build information from zephyr. Or they may be
|
||||||
|
# incompatible with certain zephyr options and need them to be
|
||||||
|
# filtered out.
|
||||||
|
zephyr_get_include_directories_for_lang_as_string( C includes)
|
||||||
|
zephyr_get_system_include_directories_for_lang_as_string(C system_includes)
|
||||||
|
zephyr_get_compile_definitions_for_lang_as_string( C definitions)
|
||||||
|
zephyr_get_compile_options_for_lang_as_string( C options)
|
||||||
|
|
||||||
|
if(DEFINED CMAKE_C_COMPILER_TARGET)
|
||||||
|
set(target_flag "--target=${CMAKE_C_COMPILER_TARGET}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(external_project_cflags
|
||||||
|
"${target_flag} ${includes} ${definitions} ${options} ${system_includes}"
|
||||||
|
)
|
||||||
|
|
||||||
|
zephyr_get(TRANSLATION SYSBUILD GLOBAL)
|
||||||
|
zephyr_get(CONFIG_LTO SYSBUILD GLOBAL)
|
||||||
|
zephyr_get(BOARD_ALIAS SYSBUILD GLOBAL)
|
||||||
|
|
||||||
|
ExternalProject_Add(circuitpython
|
||||||
|
DOWNLOAD_COMMAND ""
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
BUILD_COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/cptools/build_circuitpython.py
|
||||||
|
CC=${CMAKE_C_COMPILER}
|
||||||
|
AR=${CMAKE_AR}
|
||||||
|
CFLAGS=${external_project_cflags}
|
||||||
|
BOARD=${BOARD}
|
||||||
|
BOARD_ALIAS=${BOARD_ALIAS}
|
||||||
|
BOARD_REVISION=${BOARD_REVISION}
|
||||||
|
BOARD_QUALIFIERS=${BOARD_QUALIFIERS}
|
||||||
|
SOC_DIRECTORIES=${SOC_DIRECTORIES}
|
||||||
|
OUTPUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/libcircuitpython.a
|
||||||
|
PORT_SRC_DIR=${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
TRANSLATION=${TRANSLATION}
|
||||||
|
LTO=${CONFIG_LTO}
|
||||||
|
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/libcircuitpython.a
|
||||||
|
BUILD_JOB_SERVER_AWARE TRUE
|
||||||
|
BUILD_ALWAYS TRUE
|
||||||
|
DEPENDS zephyr
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(circuitpython_wrapper STATIC IMPORTED GLOBAL)
|
||||||
|
add_dependencies(
|
||||||
|
circuitpython_wrapper
|
||||||
|
circuitpython
|
||||||
|
)
|
||||||
|
set_target_properties(circuitpython_wrapper PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/libcircuitpython.a)
|
||||||
|
target_link_libraries(circuitpython_wrapper INTERFACE kernel)
|
||||||
|
target_link_libraries(app PRIVATE circuitpython_wrapper)
|
||||||
15
ports/zephyr-cp/Kconfig.sysbuild
Normal file
15
ports/zephyr-cp/Kconfig.sysbuild
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
# Copyright 2023-2024 Nordic Semiconductor ASA
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
source "share/sysbuild/Kconfig"
|
||||||
|
|
||||||
|
config NET_CORE_BOARD
|
||||||
|
string
|
||||||
|
default "nrf5340dk/nrf5340/cpunet" if $(BOARD) = "nrf5340dk"
|
||||||
|
default "nrf7002dk/nrf5340/cpunet" if $(BOARD) = "nrf7002dk"
|
||||||
|
default "nrf5340_audio_dk/nrf5340/cpunet" if $(BOARD) = "nrf5340_audio_dk"
|
||||||
|
|
||||||
|
config NET_CORE_IMAGE_HCI_IPC
|
||||||
|
bool "HCI IPC image on network core"
|
||||||
|
default y
|
||||||
|
depends on NET_CORE_BOARD != ""
|
||||||
33
ports/zephyr-cp/Makefile
Normal file
33
ports/zephyr-cp/Makefile
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
ALL_BOARDS_IN_PORT := $($(wildcard boards/*/*):boards/=:/=)
|
||||||
|
# An incorrect BOARD might have been specified, so check against the list.
|
||||||
|
# There is deliberately no space after the :=
|
||||||
|
VALID_BOARD :=$(filter $(BOARD),$(ALL_BOARDS_IN_PORT))
|
||||||
|
|
||||||
|
# If the build directory is not given, make it reflect the board name.
|
||||||
|
BUILD ?= build-$(BOARD)
|
||||||
|
|
||||||
|
TRANSLATION ?= en_US
|
||||||
|
|
||||||
|
.PHONY: $(BUILD)/zephyr-cp/zephyr/zephyr.elf flash debug clean menuconfig
|
||||||
|
|
||||||
|
$(BUILD)/zephyr-cp/zephyr/zephyr.elf:
|
||||||
|
python cptools/pre_zephyr_build_prep.py $(BOARD)
|
||||||
|
west build -b $(BOARD) -d $(BUILD) --sysbuild -- -DZEPHYR_BOARD_ALIASES=$(CURDIR)/boards/board_aliases.cmake -Dzephyr-cp_TRANSLATION=$(TRANSLATION)
|
||||||
|
|
||||||
|
$(BUILD)/firmware.elf: $(BUILD)/zephyr-cp/zephyr/zephyr.elf
|
||||||
|
cp $^ $@
|
||||||
|
|
||||||
|
$(BUILD)/firmware.hex: $(BUILD)/zephyr-cp/zephyr/zephyr.elf
|
||||||
|
cp $(BUILD)/zephyr-cp/zephyr/zephyr.hex $@
|
||||||
|
|
||||||
|
flash: $(BUILD)/zephyr-cp/zephyr/zephyr.elf
|
||||||
|
west flash -d $(BUILD)
|
||||||
|
|
||||||
|
debug: $(BUILD)/zephyr-cp/zephyr/zephyr.elf
|
||||||
|
west debug -d $(BUILD)
|
||||||
|
|
||||||
|
menuconfig:
|
||||||
|
west build --sysbuild -d $(BUILD) -t menuconfig
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(BUILD)
|
||||||
47
ports/zephyr-cp/README.md
Normal file
47
ports/zephyr-cp/README.md
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
# Zephyr
|
||||||
|
|
||||||
|
This is an initial port of CircuitPython onto Zephyr. We intend on migrating all
|
||||||
|
existing boards onto Zephyr. To start, we'll only support new boards. Existing
|
||||||
|
boards will be switched as the Zephyr port reaches parity with the existing
|
||||||
|
implementation.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
First, install Zephyr tools (see [Zephyr's Getting Started Guide](https://docs.zephyrproject.org/4.0.0/develop/getting_started/index.html)). (These are `fish` commands because that's what Scott uses.)
|
||||||
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pip install west
|
||||||
|
west init -l zephyr-config
|
||||||
|
west update
|
||||||
|
west zephyr-export
|
||||||
|
pip install -r lib/zephyr/scripts/requirements.txt
|
||||||
|
west sdk install
|
||||||
|
```
|
||||||
|
|
||||||
|
Now to build from the top level:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make BOARD=nordic_nrf7002dk
|
||||||
|
```
|
||||||
|
|
||||||
|
This uses Zephyr's cmake to generate Makefiles that then delegate to
|
||||||
|
`tools/cpbuild/build_circuitpython.py` to build the CircuitPython bits in parallel.
|
||||||
|
|
||||||
|
## Testing other boards
|
||||||
|
|
||||||
|
[Any Zephyr board](https://docs.zephyrproject.org/latest/boards/index.html#) can
|
||||||
|
be used with CircuitPython. To test a different board, use `west` directly to
|
||||||
|
build the board. The build will do its best to support as much as possible. By
|
||||||
|
default the Zephyr console will be used for output. USB support is limited by
|
||||||
|
initialization support in `supervisor/usb.c`. Only flash regions not used by
|
||||||
|
Zephyr are used for CIRCUITPY. A manual `circuitpython` partition can be
|
||||||
|
specified instead.
|
||||||
|
|
||||||
|
For example, to test the `nrf52840dk` board:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
west build -b nrf52840dk/nrf52840
|
||||||
|
```
|
||||||
|
|
||||||
|
This is already supported in `ports/nordic` as `pca10056`.
|
||||||
45
ports/zephyr-cp/background.c
Normal file
45
ports/zephyr-cp/background.c
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "background.h"
|
||||||
|
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "supervisor/port.h"
|
||||||
|
|
||||||
|
#if CIRCUITPY_DISPLAYIO
|
||||||
|
#include "shared-module/displayio/__init__.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CIRCUITPY_AUDIOBUSIO
|
||||||
|
#include "common-hal/audiobusio/I2SOut.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CIRCUITPY_AUDIOPWMIO
|
||||||
|
#include "common-hal/audiopwmio/PWMAudioOut.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void port_start_background_tick(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void port_finish_background_tick(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void port_background_tick(void) {
|
||||||
|
#if CIRCUITPY_AUDIOPWMIO
|
||||||
|
audiopwmout_background();
|
||||||
|
#endif
|
||||||
|
#if CIRCUITPY_AUDIOBUSIO
|
||||||
|
i2s_background();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow boards to override this.
|
||||||
|
MP_WEAK void board_background_task(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void port_background_task(void) {
|
||||||
|
board_background_task();
|
||||||
|
}
|
||||||
9
ports/zephyr-cp/background.h
Normal file
9
ports/zephyr-cp/background.h
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
void board_background_task(void);
|
||||||
12
ports/zephyr-cp/bindings/zephyr_kernel/__init__.c
Normal file
12
ports/zephyr-cp/bindings/zephyr_kernel/__init__.c
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "py/mphal.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "bindings/zephyr_kernel/__init__.h"
|
||||||
15
ports/zephyr-cp/bindings/zephyr_kernel/__init__.h
Normal file
15
ports/zephyr-cp/bindings/zephyr_kernel/__init__.h
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "py/mpconfig.h"
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
#include "common-hal/zephyr_kernel/__init__.h"
|
||||||
|
|
||||||
|
void raise_zephyr_error(int err);
|
||||||
|
#define CHECK_ZEPHYR_RESULT(x) do { int res = (x); if (res < 0) raise_zephyr_error(res); } while (0)
|
||||||
287
ports/zephyr-cp/bindings/zephyr_serial/UART.c
Normal file
287
ports/zephyr-cp/bindings/zephyr_serial/UART.c
Normal file
|
|
@ -0,0 +1,287 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "bindings/zephyr_serial/UART.h"
|
||||||
|
#include "shared-bindings/microcontroller/Pin.h"
|
||||||
|
#include "shared-bindings/util.h"
|
||||||
|
|
||||||
|
#include "shared/runtime/context_manager_helpers.h"
|
||||||
|
#include "shared/runtime/interrupt_char.h"
|
||||||
|
|
||||||
|
#include "py/stream.h"
|
||||||
|
#include "py/objproperty.h"
|
||||||
|
#include "py/objtype.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "py/stream.h"
|
||||||
|
|
||||||
|
#define STREAM_DEBUG(...) (void)0
|
||||||
|
// #define STREAM_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__)
|
||||||
|
|
||||||
|
//| class UART:
|
||||||
|
//| """A bidirectional serial protocol. Already initialized for Zephyr defined
|
||||||
|
//| busses in `board`.
|
||||||
|
//|
|
||||||
|
//| .. raw:: html
|
||||||
|
//|
|
||||||
|
//| <p>
|
||||||
|
//| <details>
|
||||||
|
//| <summary>Available on these boards</summary>
|
||||||
|
//| <ul>
|
||||||
|
//| {% for board in support_matrix_reverse["zephyr_serial.UART"] %}
|
||||||
|
//| <li> {{ board }}
|
||||||
|
//| {% endfor %}
|
||||||
|
//| </ul>
|
||||||
|
//| </details>
|
||||||
|
//| </p>
|
||||||
|
//|
|
||||||
|
//| """
|
||||||
|
//|
|
||||||
|
|
||||||
|
static void validate_timeout(mp_float_t timeout) {
|
||||||
|
mp_arg_validate_int_range((int)timeout, 0, 100, MP_QSTR_timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to ensure we have the native super class instead of a subclass.
|
||||||
|
static zephyr_serial_uart_obj_t *native_uart(mp_obj_t uart_obj) {
|
||||||
|
mp_obj_t native_uart = mp_obj_cast_to_native_base(uart_obj, MP_OBJ_FROM_PTR(&zephyr_serial_uart_type));
|
||||||
|
if (native_uart == MP_OBJ_NULL) {
|
||||||
|
mp_raise_ValueError_varg(MP_ERROR_TEXT("Must be a %q subclass."), MP_QSTR_UART);
|
||||||
|
}
|
||||||
|
mp_obj_assert_native_inited(native_uart);
|
||||||
|
return MP_OBJ_TO_PTR(native_uart);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//| def deinit(self) -> None:
|
||||||
|
//| """Deinitialises the UART and releases any hardware resources for reuse."""
|
||||||
|
//| ...
|
||||||
|
static mp_obj_t _zephyr_serial_uart_obj_deinit(mp_obj_t self_in) {
|
||||||
|
zephyr_serial_uart_obj_t *self = native_uart(self_in);
|
||||||
|
zephyr_serial_uart_deinit(self);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_1(_zephyr_serial_uart_deinit_obj, _zephyr_serial_uart_obj_deinit);
|
||||||
|
|
||||||
|
static void check_for_deinit(zephyr_serial_uart_obj_t *self) {
|
||||||
|
if (zephyr_serial_uart_deinited(self)) {
|
||||||
|
raise_deinited_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//| def __enter__(self) -> UART:
|
||||||
|
//| """No-op used by Context Managers."""
|
||||||
|
//| ...
|
||||||
|
// Provided by context manager helper.
|
||||||
|
|
||||||
|
//| def __exit__(self) -> None:
|
||||||
|
//| """Automatically deinitializes the hardware when exiting a context. See
|
||||||
|
//| :ref:`lifetime-and-contextmanagers` for more info."""
|
||||||
|
//| ...
|
||||||
|
static mp_obj_t _zephyr_serial_uart_obj___exit__(size_t n_args, const mp_obj_t *args) {
|
||||||
|
(void)n_args;
|
||||||
|
zephyr_serial_uart_deinit(MP_OBJ_TO_PTR(args[0]));
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(_zephyr_serial_uart___exit___obj, 4, 4, _zephyr_serial_uart_obj___exit__);
|
||||||
|
|
||||||
|
// These are standard stream methods. Code is in py/stream.c.
|
||||||
|
//
|
||||||
|
//| def read(self, nbytes: Optional[int] = None) -> Optional[bytes]:
|
||||||
|
//| """Read bytes. If ``nbytes`` is specified then read at most that many
|
||||||
|
//| bytes. Otherwise, read everything that arrives until the connection
|
||||||
|
//| times out. Providing the number of bytes expected is highly recommended
|
||||||
|
//| because it will be faster. If no bytes are read, return ``None``.
|
||||||
|
//|
|
||||||
|
//| .. note:: When no bytes are read due to a timeout, this function returns ``None``.
|
||||||
|
//| This matches the behavior of `io.RawIOBase.read` in Python 3, but
|
||||||
|
//| differs from pyserial which returns ``b''`` in that situation.
|
||||||
|
//|
|
||||||
|
//| :return: Data read
|
||||||
|
//| :rtype: bytes or None"""
|
||||||
|
//| ...
|
||||||
|
|
||||||
|
//| def readinto(self, buf: WriteableBuffer) -> Optional[int]:
|
||||||
|
//| """Read bytes into the ``buf``. Read at most ``len(buf)`` bytes.
|
||||||
|
//|
|
||||||
|
//| :return: number of bytes read and stored into ``buf``
|
||||||
|
//| :rtype: int or None (on a non-blocking error)
|
||||||
|
//|
|
||||||
|
//| *New in CircuitPython 4.0:* No length parameter is permitted."""
|
||||||
|
//| ...
|
||||||
|
|
||||||
|
//| def readline(self) -> bytes:
|
||||||
|
//| """Read a line, ending in a newline character, or
|
||||||
|
//| return ``None`` if a timeout occurs sooner, or
|
||||||
|
//| return everything readable if no newline is found and
|
||||||
|
//| ``timeout=0``
|
||||||
|
//|
|
||||||
|
//| :return: the line read
|
||||||
|
//| :rtype: bytes or None"""
|
||||||
|
//| ...
|
||||||
|
|
||||||
|
//| def write(self, buf: ReadableBuffer) -> Optional[int]:
|
||||||
|
//| """Write the buffer of bytes to the bus.
|
||||||
|
//|
|
||||||
|
//| *New in CircuitPython 4.0:* ``buf`` must be bytes, not a string.
|
||||||
|
//|
|
||||||
|
//| :return: the number of bytes written
|
||||||
|
//| :rtype: int or None"""
|
||||||
|
//| ...
|
||||||
|
|
||||||
|
// These three methods are used by the shared stream methods.
|
||||||
|
static mp_uint_t _zephyr_serial_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
|
||||||
|
STREAM_DEBUG("_zephyr_serial_uart_read stream %d\n", size);
|
||||||
|
zephyr_serial_uart_obj_t *self = native_uart(self_in);
|
||||||
|
check_for_deinit(self);
|
||||||
|
byte *buf = buf_in;
|
||||||
|
|
||||||
|
// make sure we want at least 1 char
|
||||||
|
if (size == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return zephyr_serial_uart_read(self, buf, size, errcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_uint_t _zephyr_serial_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
|
||||||
|
zephyr_serial_uart_obj_t *self = native_uart(self_in);
|
||||||
|
check_for_deinit(self);
|
||||||
|
const byte *buf = buf_in;
|
||||||
|
|
||||||
|
return zephyr_serial_uart_write(self, buf, size, errcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_uint_t _zephyr_serial_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
|
||||||
|
zephyr_serial_uart_obj_t *self = native_uart(self_in);
|
||||||
|
check_for_deinit(self);
|
||||||
|
mp_uint_t ret;
|
||||||
|
if (request == MP_STREAM_POLL) {
|
||||||
|
mp_uint_t flags = arg;
|
||||||
|
ret = 0;
|
||||||
|
if ((flags & MP_STREAM_POLL_RD) && zephyr_serial_uart_rx_characters_available(self) > 0) {
|
||||||
|
ret |= MP_STREAM_POLL_RD;
|
||||||
|
}
|
||||||
|
if ((flags & MP_STREAM_POLL_WR) && zephyr_serial_uart_ready_to_tx(self)) {
|
||||||
|
ret |= MP_STREAM_POLL_WR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*errcode = MP_EINVAL;
|
||||||
|
ret = MP_STREAM_ERROR;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//| baudrate: int
|
||||||
|
//| """The current baudrate."""
|
||||||
|
static mp_obj_t _zephyr_serial_uart_obj_get_baudrate(mp_obj_t self_in) {
|
||||||
|
zephyr_serial_uart_obj_t *self = native_uart(self_in);
|
||||||
|
check_for_deinit(self);
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(zephyr_serial_uart_get_baudrate(self));
|
||||||
|
}
|
||||||
|
MP_DEFINE_CONST_FUN_OBJ_1(_zephyr_serial_uart_get_baudrate_obj, _zephyr_serial_uart_obj_get_baudrate);
|
||||||
|
|
||||||
|
static mp_obj_t _zephyr_serial_uart_obj_set_baudrate(mp_obj_t self_in, mp_obj_t baudrate) {
|
||||||
|
zephyr_serial_uart_obj_t *self = native_uart(self_in);
|
||||||
|
check_for_deinit(self);
|
||||||
|
zephyr_serial_uart_set_baudrate(self, mp_obj_get_int(baudrate));
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
MP_DEFINE_CONST_FUN_OBJ_2(_zephyr_serial_uart_set_baudrate_obj, _zephyr_serial_uart_obj_set_baudrate);
|
||||||
|
|
||||||
|
|
||||||
|
MP_PROPERTY_GETSET(_zephyr_serial_uart_baudrate_obj,
|
||||||
|
(mp_obj_t)&_zephyr_serial_uart_get_baudrate_obj,
|
||||||
|
(mp_obj_t)&_zephyr_serial_uart_set_baudrate_obj);
|
||||||
|
|
||||||
|
//| in_waiting: int
|
||||||
|
//| """The number of bytes in the input buffer, available to be read"""
|
||||||
|
static mp_obj_t _zephyr_serial_uart_obj_get_in_waiting(mp_obj_t self_in) {
|
||||||
|
zephyr_serial_uart_obj_t *self = native_uart(self_in);
|
||||||
|
check_for_deinit(self);
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(zephyr_serial_uart_rx_characters_available(self));
|
||||||
|
}
|
||||||
|
MP_DEFINE_CONST_FUN_OBJ_1(_zephyr_serial_uart_get_in_waiting_obj, _zephyr_serial_uart_obj_get_in_waiting);
|
||||||
|
|
||||||
|
MP_PROPERTY_GETTER(_zephyr_serial_uart_in_waiting_obj,
|
||||||
|
(mp_obj_t)&_zephyr_serial_uart_get_in_waiting_obj);
|
||||||
|
|
||||||
|
//| timeout: float
|
||||||
|
//| """The current timeout, in seconds (float)."""
|
||||||
|
static mp_obj_t _zephyr_serial_uart_obj_get_timeout(mp_obj_t self_in) {
|
||||||
|
zephyr_serial_uart_obj_t *self = native_uart(self_in);
|
||||||
|
check_for_deinit(self);
|
||||||
|
return mp_obj_new_float(zephyr_serial_uart_get_timeout(self));
|
||||||
|
}
|
||||||
|
MP_DEFINE_CONST_FUN_OBJ_1(_zephyr_serial_uart_get_timeout_obj, _zephyr_serial_uart_obj_get_timeout);
|
||||||
|
|
||||||
|
static mp_obj_t _zephyr_serial_uart_obj_set_timeout(mp_obj_t self_in, mp_obj_t timeout) {
|
||||||
|
zephyr_serial_uart_obj_t *self = native_uart(self_in);
|
||||||
|
check_for_deinit(self);
|
||||||
|
mp_float_t timeout_float = mp_obj_get_float(timeout);
|
||||||
|
validate_timeout(timeout_float);
|
||||||
|
zephyr_serial_uart_set_timeout(self, timeout_float);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
MP_DEFINE_CONST_FUN_OBJ_2(_zephyr_serial_uart_set_timeout_obj, _zephyr_serial_uart_obj_set_timeout);
|
||||||
|
|
||||||
|
|
||||||
|
MP_PROPERTY_GETSET(_zephyr_serial_uart_timeout_obj,
|
||||||
|
(mp_obj_t)&_zephyr_serial_uart_get_timeout_obj,
|
||||||
|
(mp_obj_t)&_zephyr_serial_uart_set_timeout_obj);
|
||||||
|
|
||||||
|
//| def reset_input_buffer(self) -> None:
|
||||||
|
//| """Discard any unread characters in the input buffer."""
|
||||||
|
//| ...
|
||||||
|
//|
|
||||||
|
static mp_obj_t _zephyr_serial_uart_obj_reset_input_buffer(mp_obj_t self_in) {
|
||||||
|
zephyr_serial_uart_obj_t *self = native_uart(self_in);
|
||||||
|
check_for_deinit(self);
|
||||||
|
zephyr_serial_uart_clear_rx_buffer(self);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_1(_zephyr_serial_uart_reset_input_buffer_obj, _zephyr_serial_uart_obj_reset_input_buffer);
|
||||||
|
|
||||||
|
static const mp_rom_map_elem_t _zephyr_serial_uart_locals_dict_table[] = {
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&_zephyr_serial_uart_deinit_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&_zephyr_serial_uart_deinit_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&_zephyr_serial_uart___exit___obj) },
|
||||||
|
|
||||||
|
// Standard stream methods.
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)},
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
|
||||||
|
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_reset_input_buffer), MP_ROM_PTR(&_zephyr_serial_uart_reset_input_buffer_obj) },
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_baudrate), MP_ROM_PTR(&_zephyr_serial_uart_baudrate_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_in_waiting), MP_ROM_PTR(&_zephyr_serial_uart_in_waiting_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_timeout), MP_ROM_PTR(&_zephyr_serial_uart_timeout_obj) },
|
||||||
|
|
||||||
|
};
|
||||||
|
static MP_DEFINE_CONST_DICT(_zephyr_serial_uart_locals_dict, _zephyr_serial_uart_locals_dict_table);
|
||||||
|
|
||||||
|
static const mp_stream_p_t uart_stream_p = {
|
||||||
|
.read = _zephyr_serial_uart_read,
|
||||||
|
.write = _zephyr_serial_uart_write,
|
||||||
|
.ioctl = _zephyr_serial_uart_ioctl,
|
||||||
|
.is_text = false,
|
||||||
|
// Disallow optional length argument for .readinto()
|
||||||
|
.pyserial_readinto_compatibility = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
MP_DEFINE_CONST_OBJ_TYPE(
|
||||||
|
zephyr_serial_uart_type,
|
||||||
|
MP_QSTR_UART,
|
||||||
|
MP_TYPE_FLAG_ITER_IS_ITERNEXT | MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS,
|
||||||
|
locals_dict, &_zephyr_serial_uart_locals_dict,
|
||||||
|
iter, mp_stream_unbuffered_iter,
|
||||||
|
protocol, &uart_stream_p
|
||||||
|
);
|
||||||
41
ports/zephyr-cp/bindings/zephyr_serial/UART.h
Normal file
41
ports/zephyr-cp/bindings/zephyr_serial/UART.h
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common-hal/microcontroller/Pin.h"
|
||||||
|
#include "common-hal/zephyr_serial/UART.h"
|
||||||
|
#include "py/ringbuf.h"
|
||||||
|
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
|
||||||
|
extern const mp_obj_type_t zephyr_serial_uart_type;
|
||||||
|
|
||||||
|
// Construct an underlying UART object.
|
||||||
|
extern void zephyr_serial_uart_construct(zephyr_serial_uart_obj_t *self,
|
||||||
|
const struct device *const uart_device, uint16_t receiver_buffer_size, byte *receiver_buffer);
|
||||||
|
|
||||||
|
extern void zephyr_serial_uart_deinit(zephyr_serial_uart_obj_t *self);
|
||||||
|
extern bool zephyr_serial_uart_deinited(zephyr_serial_uart_obj_t *self);
|
||||||
|
|
||||||
|
// Read characters. len is in characters NOT bytes!
|
||||||
|
extern size_t zephyr_serial_uart_read(zephyr_serial_uart_obj_t *self,
|
||||||
|
uint8_t *data, size_t len, int *errcode);
|
||||||
|
|
||||||
|
// Write characters. len is in characters NOT bytes!
|
||||||
|
extern size_t zephyr_serial_uart_write(zephyr_serial_uart_obj_t *self,
|
||||||
|
const uint8_t *data, size_t len, int *errcode);
|
||||||
|
|
||||||
|
extern uint32_t zephyr_serial_uart_get_baudrate(zephyr_serial_uart_obj_t *self);
|
||||||
|
extern void zephyr_serial_uart_set_baudrate(zephyr_serial_uart_obj_t *self, uint32_t baudrate);
|
||||||
|
extern mp_float_t zephyr_serial_uart_get_timeout(zephyr_serial_uart_obj_t *self);
|
||||||
|
extern void zephyr_serial_uart_set_timeout(zephyr_serial_uart_obj_t *self, mp_float_t timeout);
|
||||||
|
|
||||||
|
extern uint32_t zephyr_serial_uart_rx_characters_available(zephyr_serial_uart_obj_t *self);
|
||||||
|
extern void zephyr_serial_uart_clear_rx_buffer(zephyr_serial_uart_obj_t *self);
|
||||||
|
extern bool zephyr_serial_uart_ready_to_tx(zephyr_serial_uart_obj_t *self);
|
||||||
|
|
||||||
|
extern void zephyr_serial_uart_never_reset(zephyr_serial_uart_obj_t *self);
|
||||||
33
ports/zephyr-cp/bindings/zephyr_serial/__init__.c
Normal file
33
ports/zephyr-cp/bindings/zephyr_serial/__init__.c
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/microcontroller/Pin.h"
|
||||||
|
#include "bindings/zephyr_serial/__init__.h"
|
||||||
|
#include "bindings/zephyr_serial/UART.h"
|
||||||
|
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
//| """Zephyr UART driver for fixed busses.
|
||||||
|
//| """
|
||||||
|
|
||||||
|
static const mp_rom_map_elem_t zephyr_serial_module_globals_table[] = {
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_zephyr_serial) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&zephyr_serial_uart_type) },
|
||||||
|
};
|
||||||
|
|
||||||
|
static MP_DEFINE_CONST_DICT(zephyr_serial_module_globals, zephyr_serial_module_globals_table);
|
||||||
|
|
||||||
|
const mp_obj_module_t zephyr_serial_module = {
|
||||||
|
.base = { &mp_type_module },
|
||||||
|
.globals = (mp_obj_dict_t *)&zephyr_serial_module_globals,
|
||||||
|
};
|
||||||
|
|
||||||
|
MP_REGISTER_MODULE(MP_QSTR_zephyr_serial, zephyr_serial_module);
|
||||||
7
ports/zephyr-cp/bindings/zephyr_serial/__init__.h
Normal file
7
ports/zephyr-cp/bindings/zephyr_serial/__init__.h
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
8
ports/zephyr-cp/boards/board_aliases.cmake
Normal file
8
ports/zephyr-cp/boards/board_aliases.cmake
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
set(pca10056_BOARD_ALIAS nrf52840dk/nrf52840)
|
||||||
|
set(renesas_ek_ra6m5_BOARD_ALIAS ek_ra6m5)
|
||||||
|
set(renesas_ek_ra8d1_BOARD_ALIAS ek_ra8d1)
|
||||||
|
set(nordic_nrf54l15dk_BOARD_ALIAS nrf54l15dk/nrf54l15/cpuapp)
|
||||||
|
set(nordic_nrf5340dk_BOARD_ALIAS nrf5340dk/nrf5340/cpuapp)
|
||||||
|
set(nordic_nrf7002dk_BOARD_ALIAS nrf7002dk/nrf5340/cpuapp)
|
||||||
|
set(st_stm32h7b3i_dk_BOARD_ALIAS stm32h7b3i_dk)
|
||||||
|
set(st_nucleo_u575zi_q_BOARD_ALIAS nucleo_u575zi_q/stm32u575xx)
|
||||||
3
ports/zephyr-cp/boards/ek_ra8d1.overlay
Normal file
3
ports/zephyr-cp/boards/ek_ra8d1.overlay
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
&s28hl512t {
|
||||||
|
/delete-node/ partitions;
|
||||||
|
};
|
||||||
109
ports/zephyr-cp/boards/nordic/nrf5340dk/autogen_board_info.toml
Normal file
109
ports/zephyr-cp/boards/nordic/nrf5340dk/autogen_board_info.toml
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info.
|
||||||
|
name = "Nordic Semiconductor nRF5340 DK"
|
||||||
|
|
||||||
|
[modules]
|
||||||
|
__future__ = false
|
||||||
|
_bleio = false
|
||||||
|
_eve = false
|
||||||
|
_pew = false
|
||||||
|
_pixelmap = false
|
||||||
|
_stage = false
|
||||||
|
adafruit_bus_device = false
|
||||||
|
adafruit_pixelbuf = false
|
||||||
|
aesio = false
|
||||||
|
alarm = false
|
||||||
|
analogbufio = false
|
||||||
|
analogio = false
|
||||||
|
atexit = false
|
||||||
|
audiobusio = false
|
||||||
|
audiocore = false
|
||||||
|
audiodelays = false
|
||||||
|
audiofilters = false
|
||||||
|
audioio = false
|
||||||
|
audiomixer = false
|
||||||
|
audiomp3 = false
|
||||||
|
audiopwmio = false
|
||||||
|
aurora_epaper = false
|
||||||
|
bitbangio = false
|
||||||
|
bitmapfilter = false
|
||||||
|
bitmaptools = false
|
||||||
|
bitops = false
|
||||||
|
board = false
|
||||||
|
busdisplay = false
|
||||||
|
busio = false
|
||||||
|
camera = false
|
||||||
|
canio = false
|
||||||
|
codeop = false
|
||||||
|
countio = false
|
||||||
|
digitalio = true
|
||||||
|
displayio = false
|
||||||
|
dotclockframebuffer = false
|
||||||
|
dualbank = false
|
||||||
|
epaperdisplay = false
|
||||||
|
floppyio = false
|
||||||
|
fontio = false
|
||||||
|
fourwire = false
|
||||||
|
framebufferio = false
|
||||||
|
frequencyio = false
|
||||||
|
getpass = false
|
||||||
|
gifio = false
|
||||||
|
gnss = false
|
||||||
|
hashlib = false
|
||||||
|
i2cdisplaybus = false
|
||||||
|
i2ctarget = false
|
||||||
|
imagecapture = false
|
||||||
|
ipaddress = false
|
||||||
|
is31fl3741 = false
|
||||||
|
jpegio = false
|
||||||
|
keypad = false
|
||||||
|
keypad_demux = false
|
||||||
|
locale = false
|
||||||
|
math = false
|
||||||
|
max3421e = false
|
||||||
|
mdns = false
|
||||||
|
memorymap = false
|
||||||
|
memorymonitor = false
|
||||||
|
microcontroller = true
|
||||||
|
msgpack = false
|
||||||
|
neopixel_write = false
|
||||||
|
nvm = false
|
||||||
|
onewireio = false
|
||||||
|
os = true
|
||||||
|
paralleldisplaybus = false
|
||||||
|
ps2io = false
|
||||||
|
pulseio = false
|
||||||
|
pwmio = false
|
||||||
|
qrio = false
|
||||||
|
rainbowio = false
|
||||||
|
random = true
|
||||||
|
rgbmatrix = false
|
||||||
|
rotaryio = false
|
||||||
|
rtc = false
|
||||||
|
sdcardio = false
|
||||||
|
sdioio = false
|
||||||
|
sharpdisplay = false
|
||||||
|
socketpool = false
|
||||||
|
ssl = false
|
||||||
|
storage = true # Zephyr board has flash
|
||||||
|
struct = true
|
||||||
|
supervisor = false
|
||||||
|
synthio = false
|
||||||
|
terminalio = false
|
||||||
|
time = true
|
||||||
|
touchio = false
|
||||||
|
traceback = false
|
||||||
|
uheap = false
|
||||||
|
usb = false
|
||||||
|
usb_cdc = true
|
||||||
|
usb_hid = false
|
||||||
|
usb_host = false
|
||||||
|
usb_midi = false
|
||||||
|
usb_video = false
|
||||||
|
ustack = false
|
||||||
|
vectorio = false
|
||||||
|
warnings = false
|
||||||
|
watchdog = false
|
||||||
|
wifi = false
|
||||||
|
zephyr_kernel = false
|
||||||
|
zephyr_serial = true
|
||||||
|
zlib = false
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
CIRCUITPY_BUILD_EXTENSIONS = ["elf"]
|
||||||
|
USB_VID=0x239A
|
||||||
|
USB_PID=0x8166
|
||||||
109
ports/zephyr-cp/boards/nordic/nrf54l15dk/autogen_board_info.toml
Normal file
109
ports/zephyr-cp/boards/nordic/nrf54l15dk/autogen_board_info.toml
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info.
|
||||||
|
name = "Nordic Semiconductor nRF54L15 DK"
|
||||||
|
|
||||||
|
[modules]
|
||||||
|
__future__ = false
|
||||||
|
_bleio = false
|
||||||
|
_eve = false
|
||||||
|
_pew = false
|
||||||
|
_pixelmap = false
|
||||||
|
_stage = false
|
||||||
|
adafruit_bus_device = false
|
||||||
|
adafruit_pixelbuf = false
|
||||||
|
aesio = false
|
||||||
|
alarm = false
|
||||||
|
analogbufio = false
|
||||||
|
analogio = false
|
||||||
|
atexit = false
|
||||||
|
audiobusio = false
|
||||||
|
audiocore = false
|
||||||
|
audiodelays = false
|
||||||
|
audiofilters = false
|
||||||
|
audioio = false
|
||||||
|
audiomixer = false
|
||||||
|
audiomp3 = false
|
||||||
|
audiopwmio = false
|
||||||
|
aurora_epaper = false
|
||||||
|
bitbangio = false
|
||||||
|
bitmapfilter = false
|
||||||
|
bitmaptools = false
|
||||||
|
bitops = false
|
||||||
|
board = false
|
||||||
|
busdisplay = false
|
||||||
|
busio = false
|
||||||
|
camera = false
|
||||||
|
canio = false
|
||||||
|
codeop = false
|
||||||
|
countio = false
|
||||||
|
digitalio = true
|
||||||
|
displayio = false
|
||||||
|
dotclockframebuffer = false
|
||||||
|
dualbank = false
|
||||||
|
epaperdisplay = false
|
||||||
|
floppyio = false
|
||||||
|
fontio = false
|
||||||
|
fourwire = false
|
||||||
|
framebufferio = false
|
||||||
|
frequencyio = false
|
||||||
|
getpass = false
|
||||||
|
gifio = false
|
||||||
|
gnss = false
|
||||||
|
hashlib = false
|
||||||
|
i2cdisplaybus = false
|
||||||
|
i2ctarget = false
|
||||||
|
imagecapture = false
|
||||||
|
ipaddress = false
|
||||||
|
is31fl3741 = false
|
||||||
|
jpegio = false
|
||||||
|
keypad = false
|
||||||
|
keypad_demux = false
|
||||||
|
locale = false
|
||||||
|
math = false
|
||||||
|
max3421e = false
|
||||||
|
mdns = false
|
||||||
|
memorymap = false
|
||||||
|
memorymonitor = false
|
||||||
|
microcontroller = true
|
||||||
|
msgpack = false
|
||||||
|
neopixel_write = false
|
||||||
|
nvm = false
|
||||||
|
onewireio = false
|
||||||
|
os = true
|
||||||
|
paralleldisplaybus = false
|
||||||
|
ps2io = false
|
||||||
|
pulseio = false
|
||||||
|
pwmio = false
|
||||||
|
qrio = false
|
||||||
|
rainbowio = false
|
||||||
|
random = true
|
||||||
|
rgbmatrix = false
|
||||||
|
rotaryio = false
|
||||||
|
rtc = false
|
||||||
|
sdcardio = false
|
||||||
|
sdioio = false
|
||||||
|
sharpdisplay = false
|
||||||
|
socketpool = false
|
||||||
|
ssl = false
|
||||||
|
storage = true # Zephyr board has flash
|
||||||
|
struct = true
|
||||||
|
supervisor = false
|
||||||
|
synthio = false
|
||||||
|
terminalio = false
|
||||||
|
time = true
|
||||||
|
touchio = false
|
||||||
|
traceback = false
|
||||||
|
uheap = false
|
||||||
|
usb = false
|
||||||
|
usb_cdc = false
|
||||||
|
usb_hid = false
|
||||||
|
usb_host = false
|
||||||
|
usb_midi = false
|
||||||
|
usb_video = false
|
||||||
|
ustack = false
|
||||||
|
vectorio = false
|
||||||
|
warnings = false
|
||||||
|
watchdog = false
|
||||||
|
wifi = false
|
||||||
|
zephyr_kernel = false
|
||||||
|
zephyr_serial = true
|
||||||
|
zlib = false
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
CIRCUITPY_BUILD_EXTENSIONS = ["elf"]
|
||||||
109
ports/zephyr-cp/boards/nordic/nrf7002dk/autogen_board_info.toml
Normal file
109
ports/zephyr-cp/boards/nordic/nrf7002dk/autogen_board_info.toml
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info.
|
||||||
|
name = "Nordic Semiconductor nRF7002 DK"
|
||||||
|
|
||||||
|
[modules]
|
||||||
|
__future__ = false
|
||||||
|
_bleio = false
|
||||||
|
_eve = false
|
||||||
|
_pew = false
|
||||||
|
_pixelmap = false
|
||||||
|
_stage = false
|
||||||
|
adafruit_bus_device = false
|
||||||
|
adafruit_pixelbuf = false
|
||||||
|
aesio = false
|
||||||
|
alarm = false
|
||||||
|
analogbufio = false
|
||||||
|
analogio = false
|
||||||
|
atexit = false
|
||||||
|
audiobusio = false
|
||||||
|
audiocore = false
|
||||||
|
audiodelays = false
|
||||||
|
audiofilters = false
|
||||||
|
audioio = false
|
||||||
|
audiomixer = false
|
||||||
|
audiomp3 = false
|
||||||
|
audiopwmio = false
|
||||||
|
aurora_epaper = false
|
||||||
|
bitbangio = false
|
||||||
|
bitmapfilter = false
|
||||||
|
bitmaptools = false
|
||||||
|
bitops = false
|
||||||
|
board = false
|
||||||
|
busdisplay = false
|
||||||
|
busio = false
|
||||||
|
camera = false
|
||||||
|
canio = false
|
||||||
|
codeop = false
|
||||||
|
countio = false
|
||||||
|
digitalio = true
|
||||||
|
displayio = false
|
||||||
|
dotclockframebuffer = false
|
||||||
|
dualbank = false
|
||||||
|
epaperdisplay = false
|
||||||
|
floppyio = false
|
||||||
|
fontio = false
|
||||||
|
fourwire = false
|
||||||
|
framebufferio = false
|
||||||
|
frequencyio = false
|
||||||
|
getpass = false
|
||||||
|
gifio = false
|
||||||
|
gnss = false
|
||||||
|
hashlib = false
|
||||||
|
i2cdisplaybus = false
|
||||||
|
i2ctarget = false
|
||||||
|
imagecapture = false
|
||||||
|
ipaddress = false
|
||||||
|
is31fl3741 = false
|
||||||
|
jpegio = false
|
||||||
|
keypad = false
|
||||||
|
keypad_demux = false
|
||||||
|
locale = false
|
||||||
|
math = false
|
||||||
|
max3421e = false
|
||||||
|
mdns = false
|
||||||
|
memorymap = false
|
||||||
|
memorymonitor = false
|
||||||
|
microcontroller = true
|
||||||
|
msgpack = false
|
||||||
|
neopixel_write = false
|
||||||
|
nvm = false
|
||||||
|
onewireio = false
|
||||||
|
os = true
|
||||||
|
paralleldisplaybus = false
|
||||||
|
ps2io = false
|
||||||
|
pulseio = false
|
||||||
|
pwmio = false
|
||||||
|
qrio = false
|
||||||
|
rainbowio = false
|
||||||
|
random = true
|
||||||
|
rgbmatrix = false
|
||||||
|
rotaryio = false
|
||||||
|
rtc = false
|
||||||
|
sdcardio = false
|
||||||
|
sdioio = false
|
||||||
|
sharpdisplay = false
|
||||||
|
socketpool = true # Zephyr networking enabled
|
||||||
|
ssl = true # Zephyr networking enabled
|
||||||
|
storage = true # Zephyr board has flash
|
||||||
|
struct = true
|
||||||
|
supervisor = false
|
||||||
|
synthio = false
|
||||||
|
terminalio = false
|
||||||
|
time = true
|
||||||
|
touchio = false
|
||||||
|
traceback = false
|
||||||
|
uheap = false
|
||||||
|
usb = false
|
||||||
|
usb_cdc = true
|
||||||
|
usb_hid = false
|
||||||
|
usb_host = false
|
||||||
|
usb_midi = false
|
||||||
|
usb_video = false
|
||||||
|
ustack = false
|
||||||
|
vectorio = false
|
||||||
|
warnings = false
|
||||||
|
watchdog = false
|
||||||
|
wifi = true # Zephyr board has wifi
|
||||||
|
zephyr_kernel = false
|
||||||
|
zephyr_serial = true
|
||||||
|
zlib = false
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
CIRCUITPY_BUILD_EXTENSIONS = ["elf"]
|
||||||
|
USB_VID=0x239A
|
||||||
|
USB_PID=0x8168
|
||||||
|
BLOBS=["nrf_wifi"]
|
||||||
6
ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.conf
Normal file
6
ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.conf
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
CONFIG_BT=y
|
||||||
|
CONFIG_BT_PERIPHERAL=y
|
||||||
|
CONFIG_BT_CENTRAL=y
|
||||||
|
CONFIG_BT_BROADCASTER=y
|
||||||
|
CONFIG_BT_OBSERVER=y
|
||||||
|
CONFIG_BT_EXT_ADV=y
|
||||||
12
ports/zephyr-cp/boards/nrf7002dk_nrf5340_cpuapp.conf
Normal file
12
ports/zephyr-cp/boards/nrf7002dk_nrf5340_cpuapp.conf
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
CONFIG_NETWORKING=y
|
||||||
|
CONFIG_WIFI=y
|
||||||
|
|
||||||
|
CONFIG_MBEDTLS_TLS_VERSION_1_2=y
|
||||||
|
CONFIG_MBEDTLS_USE_PSA_CRYPTO=n
|
||||||
|
|
||||||
|
CONFIG_BT=y
|
||||||
|
CONFIG_BT_PERIPHERAL=y
|
||||||
|
CONFIG_BT_CENTRAL=y
|
||||||
|
CONFIG_BT_BROADCASTER=y
|
||||||
|
CONFIG_BT_OBSERVER=y
|
||||||
|
CONFIG_BT_EXT_ADV=y
|
||||||
109
ports/zephyr-cp/boards/renesas/ek_ra6m5/autogen_board_info.toml
Normal file
109
ports/zephyr-cp/boards/renesas/ek_ra6m5/autogen_board_info.toml
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info.
|
||||||
|
name = "Renesas Electronics Corporation RA6M5 Evaluation Kit"
|
||||||
|
|
||||||
|
[modules]
|
||||||
|
__future__ = false
|
||||||
|
_bleio = false
|
||||||
|
_eve = false
|
||||||
|
_pew = false
|
||||||
|
_pixelmap = false
|
||||||
|
_stage = false
|
||||||
|
adafruit_bus_device = false
|
||||||
|
adafruit_pixelbuf = false
|
||||||
|
aesio = false
|
||||||
|
alarm = false
|
||||||
|
analogbufio = false
|
||||||
|
analogio = false
|
||||||
|
atexit = false
|
||||||
|
audiobusio = false
|
||||||
|
audiocore = false
|
||||||
|
audiodelays = false
|
||||||
|
audiofilters = false
|
||||||
|
audioio = false
|
||||||
|
audiomixer = false
|
||||||
|
audiomp3 = false
|
||||||
|
audiopwmio = false
|
||||||
|
aurora_epaper = false
|
||||||
|
bitbangio = false
|
||||||
|
bitmapfilter = false
|
||||||
|
bitmaptools = false
|
||||||
|
bitops = false
|
||||||
|
board = false
|
||||||
|
busdisplay = false
|
||||||
|
busio = false
|
||||||
|
camera = false
|
||||||
|
canio = false
|
||||||
|
codeop = false
|
||||||
|
countio = false
|
||||||
|
digitalio = true
|
||||||
|
displayio = false
|
||||||
|
dotclockframebuffer = false
|
||||||
|
dualbank = false
|
||||||
|
epaperdisplay = false
|
||||||
|
floppyio = false
|
||||||
|
fontio = false
|
||||||
|
fourwire = false
|
||||||
|
framebufferio = false
|
||||||
|
frequencyio = false
|
||||||
|
getpass = false
|
||||||
|
gifio = false
|
||||||
|
gnss = false
|
||||||
|
hashlib = false
|
||||||
|
i2cdisplaybus = false
|
||||||
|
i2ctarget = false
|
||||||
|
imagecapture = false
|
||||||
|
ipaddress = false
|
||||||
|
is31fl3741 = false
|
||||||
|
jpegio = false
|
||||||
|
keypad = false
|
||||||
|
keypad_demux = false
|
||||||
|
locale = false
|
||||||
|
math = false
|
||||||
|
max3421e = false
|
||||||
|
mdns = false
|
||||||
|
memorymap = false
|
||||||
|
memorymonitor = false
|
||||||
|
microcontroller = true
|
||||||
|
msgpack = false
|
||||||
|
neopixel_write = false
|
||||||
|
nvm = false
|
||||||
|
onewireio = false
|
||||||
|
os = true
|
||||||
|
paralleldisplaybus = false
|
||||||
|
ps2io = false
|
||||||
|
pulseio = false
|
||||||
|
pwmio = false
|
||||||
|
qrio = false
|
||||||
|
rainbowio = false
|
||||||
|
random = true
|
||||||
|
rgbmatrix = false
|
||||||
|
rotaryio = false
|
||||||
|
rtc = false
|
||||||
|
sdcardio = false
|
||||||
|
sdioio = false
|
||||||
|
sharpdisplay = false
|
||||||
|
socketpool = false
|
||||||
|
ssl = false
|
||||||
|
storage = true # Zephyr board has flash
|
||||||
|
struct = true
|
||||||
|
supervisor = false
|
||||||
|
synthio = false
|
||||||
|
terminalio = false
|
||||||
|
time = true
|
||||||
|
touchio = false
|
||||||
|
traceback = false
|
||||||
|
uheap = false
|
||||||
|
usb = false
|
||||||
|
usb_cdc = false # No TinyUSB settings for r7fa6m5bh3cfc
|
||||||
|
usb_hid = false
|
||||||
|
usb_host = false
|
||||||
|
usb_midi = false
|
||||||
|
usb_video = false
|
||||||
|
ustack = false
|
||||||
|
vectorio = false
|
||||||
|
warnings = false
|
||||||
|
watchdog = false
|
||||||
|
wifi = false
|
||||||
|
zephyr_kernel = false
|
||||||
|
zephyr_serial = true
|
||||||
|
zlib = false
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
CIRCUITPY_BUILD_EXTENSIONS = ["elf"]
|
||||||
109
ports/zephyr-cp/boards/renesas/ek_ra8d1/autogen_board_info.toml
Normal file
109
ports/zephyr-cp/boards/renesas/ek_ra8d1/autogen_board_info.toml
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info.
|
||||||
|
name = "Renesas Electronics Corporation RA8D1 Evaluation Kit"
|
||||||
|
|
||||||
|
[modules]
|
||||||
|
__future__ = false
|
||||||
|
_bleio = false
|
||||||
|
_eve = false
|
||||||
|
_pew = false
|
||||||
|
_pixelmap = false
|
||||||
|
_stage = false
|
||||||
|
adafruit_bus_device = false
|
||||||
|
adafruit_pixelbuf = false
|
||||||
|
aesio = false
|
||||||
|
alarm = false
|
||||||
|
analogbufio = false
|
||||||
|
analogio = false
|
||||||
|
atexit = false
|
||||||
|
audiobusio = false
|
||||||
|
audiocore = false
|
||||||
|
audiodelays = false
|
||||||
|
audiofilters = false
|
||||||
|
audioio = false
|
||||||
|
audiomixer = false
|
||||||
|
audiomp3 = false
|
||||||
|
audiopwmio = false
|
||||||
|
aurora_epaper = false
|
||||||
|
bitbangio = false
|
||||||
|
bitmapfilter = false
|
||||||
|
bitmaptools = false
|
||||||
|
bitops = false
|
||||||
|
board = false
|
||||||
|
busdisplay = false
|
||||||
|
busio = false
|
||||||
|
camera = false
|
||||||
|
canio = false
|
||||||
|
codeop = false
|
||||||
|
countio = false
|
||||||
|
digitalio = true
|
||||||
|
displayio = false
|
||||||
|
dotclockframebuffer = false
|
||||||
|
dualbank = false
|
||||||
|
epaperdisplay = false
|
||||||
|
floppyio = false
|
||||||
|
fontio = false
|
||||||
|
fourwire = false
|
||||||
|
framebufferio = false
|
||||||
|
frequencyio = false
|
||||||
|
getpass = false
|
||||||
|
gifio = false
|
||||||
|
gnss = false
|
||||||
|
hashlib = false
|
||||||
|
i2cdisplaybus = false
|
||||||
|
i2ctarget = false
|
||||||
|
imagecapture = false
|
||||||
|
ipaddress = false
|
||||||
|
is31fl3741 = false
|
||||||
|
jpegio = false
|
||||||
|
keypad = false
|
||||||
|
keypad_demux = false
|
||||||
|
locale = false
|
||||||
|
math = false
|
||||||
|
max3421e = false
|
||||||
|
mdns = false
|
||||||
|
memorymap = false
|
||||||
|
memorymonitor = false
|
||||||
|
microcontroller = true
|
||||||
|
msgpack = false
|
||||||
|
neopixel_write = false
|
||||||
|
nvm = false
|
||||||
|
onewireio = false
|
||||||
|
os = true
|
||||||
|
paralleldisplaybus = false
|
||||||
|
ps2io = false
|
||||||
|
pulseio = false
|
||||||
|
pwmio = false
|
||||||
|
qrio = false
|
||||||
|
rainbowio = false
|
||||||
|
random = true
|
||||||
|
rgbmatrix = false
|
||||||
|
rotaryio = false
|
||||||
|
rtc = false
|
||||||
|
sdcardio = false
|
||||||
|
sdioio = false
|
||||||
|
sharpdisplay = false
|
||||||
|
socketpool = false
|
||||||
|
ssl = false
|
||||||
|
storage = true # Zephyr board has flash
|
||||||
|
struct = true
|
||||||
|
supervisor = false
|
||||||
|
synthio = false
|
||||||
|
terminalio = false
|
||||||
|
time = true
|
||||||
|
touchio = false
|
||||||
|
traceback = false
|
||||||
|
uheap = false
|
||||||
|
usb = false
|
||||||
|
usb_cdc = false # No TinyUSB settings for r7fa8d1bhecbd
|
||||||
|
usb_hid = false
|
||||||
|
usb_host = false
|
||||||
|
usb_midi = false
|
||||||
|
usb_video = false
|
||||||
|
ustack = false
|
||||||
|
vectorio = false
|
||||||
|
warnings = false
|
||||||
|
watchdog = false
|
||||||
|
wifi = false
|
||||||
|
zephyr_kernel = false
|
||||||
|
zephyr_serial = true
|
||||||
|
zlib = false
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
CIRCUITPY_BUILD_EXTENSIONS = ["elf"]
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info.
|
||||||
|
name = "STMicroelectronics Nucleo U575ZI Q"
|
||||||
|
|
||||||
|
[modules]
|
||||||
|
__future__ = false
|
||||||
|
_bleio = false
|
||||||
|
_eve = false
|
||||||
|
_pew = false
|
||||||
|
_pixelmap = false
|
||||||
|
_stage = false
|
||||||
|
adafruit_bus_device = false
|
||||||
|
adafruit_pixelbuf = false
|
||||||
|
aesio = false
|
||||||
|
alarm = false
|
||||||
|
analogbufio = false
|
||||||
|
analogio = false
|
||||||
|
atexit = false
|
||||||
|
audiobusio = false
|
||||||
|
audiocore = false
|
||||||
|
audiodelays = false
|
||||||
|
audiofilters = false
|
||||||
|
audioio = false
|
||||||
|
audiomixer = false
|
||||||
|
audiomp3 = false
|
||||||
|
audiopwmio = false
|
||||||
|
aurora_epaper = false
|
||||||
|
bitbangio = false
|
||||||
|
bitmapfilter = false
|
||||||
|
bitmaptools = false
|
||||||
|
bitops = false
|
||||||
|
board = false
|
||||||
|
busdisplay = false
|
||||||
|
busio = false
|
||||||
|
camera = false
|
||||||
|
canio = false
|
||||||
|
codeop = false
|
||||||
|
countio = false
|
||||||
|
digitalio = true
|
||||||
|
displayio = false
|
||||||
|
dotclockframebuffer = false
|
||||||
|
dualbank = false
|
||||||
|
epaperdisplay = false
|
||||||
|
floppyio = false
|
||||||
|
fontio = false
|
||||||
|
fourwire = false
|
||||||
|
framebufferio = false
|
||||||
|
frequencyio = false
|
||||||
|
getpass = false
|
||||||
|
gifio = false
|
||||||
|
gnss = false
|
||||||
|
hashlib = false
|
||||||
|
i2cdisplaybus = false
|
||||||
|
i2ctarget = false
|
||||||
|
imagecapture = false
|
||||||
|
ipaddress = false
|
||||||
|
is31fl3741 = false
|
||||||
|
jpegio = false
|
||||||
|
keypad = false
|
||||||
|
keypad_demux = false
|
||||||
|
locale = false
|
||||||
|
math = false
|
||||||
|
max3421e = false
|
||||||
|
mdns = false
|
||||||
|
memorymap = false
|
||||||
|
memorymonitor = false
|
||||||
|
microcontroller = true
|
||||||
|
msgpack = false
|
||||||
|
neopixel_write = false
|
||||||
|
nvm = false
|
||||||
|
onewireio = false
|
||||||
|
os = true
|
||||||
|
paralleldisplaybus = false
|
||||||
|
ps2io = false
|
||||||
|
pulseio = false
|
||||||
|
pwmio = false
|
||||||
|
qrio = false
|
||||||
|
rainbowio = false
|
||||||
|
random = true
|
||||||
|
rgbmatrix = false
|
||||||
|
rotaryio = false
|
||||||
|
rtc = false
|
||||||
|
sdcardio = false
|
||||||
|
sdioio = false
|
||||||
|
sharpdisplay = false
|
||||||
|
socketpool = false
|
||||||
|
ssl = false
|
||||||
|
storage = false
|
||||||
|
struct = true
|
||||||
|
supervisor = false
|
||||||
|
synthio = false
|
||||||
|
terminalio = false
|
||||||
|
time = true
|
||||||
|
touchio = false
|
||||||
|
traceback = false
|
||||||
|
uheap = false
|
||||||
|
usb = false
|
||||||
|
usb_cdc = true
|
||||||
|
usb_hid = false
|
||||||
|
usb_host = false
|
||||||
|
usb_midi = false
|
||||||
|
usb_video = false
|
||||||
|
ustack = false
|
||||||
|
vectorio = false
|
||||||
|
warnings = false
|
||||||
|
watchdog = false
|
||||||
|
wifi = false
|
||||||
|
zephyr_kernel = false
|
||||||
|
zephyr_serial = true
|
||||||
|
zlib = false
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
CIRCUITPY_BUILD_EXTENSIONS = ["hex"]
|
||||||
|
USB_VID=0x239A
|
||||||
|
USB_PID=0x816A
|
||||||
109
ports/zephyr-cp/boards/st/stm32h7b3i_dk/autogen_board_info.toml
Normal file
109
ports/zephyr-cp/boards/st/stm32h7b3i_dk/autogen_board_info.toml
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info.
|
||||||
|
name = "STMicroelectronics STM32H7B3I Discovery kit"
|
||||||
|
|
||||||
|
[modules]
|
||||||
|
__future__ = false
|
||||||
|
_bleio = false
|
||||||
|
_eve = false
|
||||||
|
_pew = false
|
||||||
|
_pixelmap = false
|
||||||
|
_stage = false
|
||||||
|
adafruit_bus_device = false
|
||||||
|
adafruit_pixelbuf = false
|
||||||
|
aesio = false
|
||||||
|
alarm = false
|
||||||
|
analogbufio = false
|
||||||
|
analogio = false
|
||||||
|
atexit = false
|
||||||
|
audiobusio = false
|
||||||
|
audiocore = false
|
||||||
|
audiodelays = false
|
||||||
|
audiofilters = false
|
||||||
|
audioio = false
|
||||||
|
audiomixer = false
|
||||||
|
audiomp3 = false
|
||||||
|
audiopwmio = false
|
||||||
|
aurora_epaper = false
|
||||||
|
bitbangio = false
|
||||||
|
bitmapfilter = false
|
||||||
|
bitmaptools = false
|
||||||
|
bitops = false
|
||||||
|
board = false
|
||||||
|
busdisplay = false
|
||||||
|
busio = false
|
||||||
|
camera = false
|
||||||
|
canio = false
|
||||||
|
codeop = false
|
||||||
|
countio = false
|
||||||
|
digitalio = true
|
||||||
|
displayio = false
|
||||||
|
dotclockframebuffer = false
|
||||||
|
dualbank = false
|
||||||
|
epaperdisplay = false
|
||||||
|
floppyio = false
|
||||||
|
fontio = false
|
||||||
|
fourwire = false
|
||||||
|
framebufferio = false
|
||||||
|
frequencyio = false
|
||||||
|
getpass = false
|
||||||
|
gifio = false
|
||||||
|
gnss = false
|
||||||
|
hashlib = false
|
||||||
|
i2cdisplaybus = false
|
||||||
|
i2ctarget = false
|
||||||
|
imagecapture = false
|
||||||
|
ipaddress = false
|
||||||
|
is31fl3741 = false
|
||||||
|
jpegio = false
|
||||||
|
keypad = false
|
||||||
|
keypad_demux = false
|
||||||
|
locale = false
|
||||||
|
math = false
|
||||||
|
max3421e = false
|
||||||
|
mdns = false
|
||||||
|
memorymap = false
|
||||||
|
memorymonitor = false
|
||||||
|
microcontroller = true
|
||||||
|
msgpack = false
|
||||||
|
neopixel_write = false
|
||||||
|
nvm = false
|
||||||
|
onewireio = false
|
||||||
|
os = true
|
||||||
|
paralleldisplaybus = false
|
||||||
|
ps2io = false
|
||||||
|
pulseio = false
|
||||||
|
pwmio = false
|
||||||
|
qrio = false
|
||||||
|
rainbowio = false
|
||||||
|
random = true
|
||||||
|
rgbmatrix = false
|
||||||
|
rotaryio = false
|
||||||
|
rtc = false
|
||||||
|
sdcardio = false
|
||||||
|
sdioio = false
|
||||||
|
sharpdisplay = false
|
||||||
|
socketpool = false
|
||||||
|
ssl = false
|
||||||
|
storage = true # Zephyr board has flash
|
||||||
|
struct = true
|
||||||
|
supervisor = false
|
||||||
|
synthio = false
|
||||||
|
terminalio = false
|
||||||
|
time = true
|
||||||
|
touchio = false
|
||||||
|
traceback = false
|
||||||
|
uheap = false
|
||||||
|
usb = false
|
||||||
|
usb_cdc = false
|
||||||
|
usb_hid = false
|
||||||
|
usb_host = false
|
||||||
|
usb_midi = false
|
||||||
|
usb_video = false
|
||||||
|
ustack = false
|
||||||
|
vectorio = false
|
||||||
|
warnings = false
|
||||||
|
watchdog = false
|
||||||
|
wifi = false
|
||||||
|
zephyr_kernel = false
|
||||||
|
zephyr_serial = true
|
||||||
|
zlib = false
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
CIRCUITPY_BUILD_EXTENSIONS = ["hex"]
|
||||||
7
ports/zephyr-cp/boards/stm32h7b3i_dk.overlay
Normal file
7
ports/zephyr-cp/boards/stm32h7b3i_dk.overlay
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
&mx25lm51245 {
|
||||||
|
/delete-node/ partitions;
|
||||||
|
};
|
||||||
|
|
||||||
|
&rng {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
129
ports/zephyr-cp/common-hal/digitalio/DigitalInOut.c
Normal file
129
ports/zephyr-cp/common-hal/digitalio/DigitalInOut.c
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||||
|
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/drivers/gpio.h>
|
||||||
|
|
||||||
|
void common_hal_digitalio_digitalinout_never_reset(
|
||||||
|
digitalio_digitalinout_obj_t *self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalinout_result_t common_hal_digitalio_digitalinout_construct(
|
||||||
|
digitalio_digitalinout_obj_t *self, const mcu_pin_obj_t *pin) {
|
||||||
|
claim_pin(pin);
|
||||||
|
self->pin = pin;
|
||||||
|
|
||||||
|
if (!device_is_ready(pin->port)) {
|
||||||
|
printk("Port device not ready\n");
|
||||||
|
return DIGITALINOUT_PIN_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gpio_pin_configure(pin->port, pin->number, GPIO_INPUT) != 0) {
|
||||||
|
return DIGITALINOUT_PIN_BUSY;
|
||||||
|
}
|
||||||
|
self->direction = DIRECTION_INPUT;
|
||||||
|
|
||||||
|
return DIGITALINOUT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t *self) {
|
||||||
|
return self->pin == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t *self) {
|
||||||
|
if (common_hal_digitalio_digitalinout_deinited(self)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_pin(self->pin);
|
||||||
|
self->pin = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_input(
|
||||||
|
digitalio_digitalinout_obj_t *self, digitalio_pull_t pull) {
|
||||||
|
self->direction = DIRECTION_INPUT;
|
||||||
|
common_hal_digitalio_digitalinout_set_pull(self, pull);
|
||||||
|
return DIGITALINOUT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_output(
|
||||||
|
digitalio_digitalinout_obj_t *self, bool value,
|
||||||
|
digitalio_drive_mode_t drive_mode) {
|
||||||
|
|
||||||
|
self->direction = DIRECTION_OUTPUT;
|
||||||
|
common_hal_digitalio_digitalinout_set_drive_mode(self, drive_mode);
|
||||||
|
common_hal_digitalio_digitalinout_set_value(self, value);
|
||||||
|
return DIGITALINOUT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
|
||||||
|
digitalio_digitalinout_obj_t *self) {
|
||||||
|
return self->direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_digitalio_digitalinout_set_value(
|
||||||
|
digitalio_digitalinout_obj_t *self, bool value) {
|
||||||
|
int res = gpio_pin_set(self->pin->port, self->pin->number, value);
|
||||||
|
if (res != 0) {
|
||||||
|
printk("Failed to set value %d\n", res);
|
||||||
|
}
|
||||||
|
// Not all MCUs can read back the output value, so store it.
|
||||||
|
self->value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_digitalio_digitalinout_get_value(
|
||||||
|
digitalio_digitalinout_obj_t *self) {
|
||||||
|
if (self->direction == DIRECTION_OUTPUT) {
|
||||||
|
return self->value;
|
||||||
|
}
|
||||||
|
return gpio_pin_get(self->pin->port, self->pin->number) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalinout_result_t common_hal_digitalio_digitalinout_set_drive_mode(
|
||||||
|
digitalio_digitalinout_obj_t *self,
|
||||||
|
digitalio_drive_mode_t drive_mode) {
|
||||||
|
// Also INPUT so we can read the value back.
|
||||||
|
gpio_flags_t flags = GPIO_OUTPUT;
|
||||||
|
if (drive_mode == DRIVE_MODE_OPEN_DRAIN) {
|
||||||
|
flags |= GPIO_OPEN_DRAIN;
|
||||||
|
}
|
||||||
|
int res = gpio_pin_configure(self->pin->port, self->pin->number, flags);
|
||||||
|
if (res != 0) {
|
||||||
|
// TODO: Fake open drain.
|
||||||
|
printk("Failed to set drive mode %d\n", res);
|
||||||
|
return DIGITALINOUT_INVALID_DRIVE_MODE;
|
||||||
|
}
|
||||||
|
self->drive_mode = drive_mode;
|
||||||
|
return DIGITALINOUT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
|
||||||
|
digitalio_digitalinout_obj_t *self) {
|
||||||
|
return self->drive_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalinout_result_t common_hal_digitalio_digitalinout_set_pull(
|
||||||
|
digitalio_digitalinout_obj_t *self, digitalio_pull_t pull) {
|
||||||
|
gpio_flags_t pull_flags = 0;
|
||||||
|
if (pull == PULL_UP) {
|
||||||
|
pull_flags = GPIO_PULL_UP;
|
||||||
|
} else if (pull == PULL_DOWN) {
|
||||||
|
pull_flags = GPIO_PULL_DOWN;
|
||||||
|
}
|
||||||
|
if (gpio_pin_configure(self->pin->port, self->pin->number, GPIO_INPUT | pull_flags) != 0) {
|
||||||
|
return DIGITALINOUT_INVALID_PULL;
|
||||||
|
}
|
||||||
|
self->pull = pull;
|
||||||
|
|
||||||
|
return DIGITALINOUT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
|
||||||
|
digitalio_digitalinout_obj_t *self) {
|
||||||
|
return self->pull;
|
||||||
|
}
|
||||||
21
ports/zephyr-cp/common-hal/digitalio/DigitalInOut.h
Normal file
21
ports/zephyr-cp/common-hal/digitalio/DigitalInOut.h
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common-hal/microcontroller/Pin.h"
|
||||||
|
#include "shared-bindings/digitalio/Direction.h"
|
||||||
|
#include "shared-bindings/digitalio/DriveMode.h"
|
||||||
|
#include "shared-bindings/digitalio/Pull.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
const mcu_pin_obj_t *pin;
|
||||||
|
digitalio_direction_t direction;
|
||||||
|
bool value;
|
||||||
|
digitalio_drive_mode_t drive_mode;
|
||||||
|
digitalio_pull_t pull;
|
||||||
|
} digitalio_digitalinout_obj_t;
|
||||||
7
ports/zephyr-cp/common-hal/digitalio/__init__.c
Normal file
7
ports/zephyr-cp/common-hal/digitalio/__init__.c
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
// No digitalio module functions.
|
||||||
73
ports/zephyr-cp/common-hal/microcontroller/Pin.c
Normal file
73
ports/zephyr-cp/common-hal/microcontroller/Pin.c
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "shared-bindings/microcontroller/Pin.h"
|
||||||
|
#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||||
|
|
||||||
|
#include "py/mphal.h"
|
||||||
|
|
||||||
|
// Bit mask of claimed pins on each of up to two ports. nrf52832 has one port; nrf52840 has two.
|
||||||
|
// static uint32_t claimed_pins[GPIO_COUNT];
|
||||||
|
// static uint32_t never_reset_pins[GPIO_COUNT];
|
||||||
|
|
||||||
|
void reset_all_pins(void) {
|
||||||
|
// for (size_t i = 0; i < GPIO_COUNT; i++) {
|
||||||
|
// claimed_pins[i] = never_reset_pins[i];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (uint32_t pin = 0; pin < NUMBER_OF_PINS; ++pin) {
|
||||||
|
// if ((never_reset_pins[nrf_pin_port(pin)] & (1 << nrf_relative_pin_number(pin))) != 0) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// nrf_gpio_cfg_default(pin);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // After configuring SWD because it may be shared.
|
||||||
|
// reset_speaker_enable_pin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark pin as free and return it to a quiescent state.
|
||||||
|
void reset_pin(const mcu_pin_obj_t *pin) {
|
||||||
|
|
||||||
|
// Clear claimed bit.
|
||||||
|
// claimed_pins[nrf_pin_port(pin_number)] &= ~(1 << nrf_relative_pin_number(pin_number));
|
||||||
|
// never_reset_pins[nrf_pin_port(pin_number)] &= ~(1 << nrf_relative_pin_number(pin_number));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void never_reset_pin_number(uint8_t pin_number) {
|
||||||
|
// never_reset_pins[nrf_pin_port(pin_number)] |= 1 << nrf_relative_pin_number(pin_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_never_reset_pin(const mcu_pin_obj_t *pin) {
|
||||||
|
never_reset_pin_number(pin->number);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_reset_pin(const mcu_pin_obj_t *pin) {
|
||||||
|
if (pin == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
reset_pin(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void claim_pin(const mcu_pin_obj_t *pin) {
|
||||||
|
// Set bit in claimed_pins bitmask.
|
||||||
|
// claimed_pins[nrf_pin_port(pin->number)] |= 1 << nrf_relative_pin_number(pin->number);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool pin_number_is_free(uint8_t pin_number) {
|
||||||
|
return false; // !(claimed_pins[nrf_pin_port(pin_number)] & (1 << nrf_relative_pin_number(pin_number)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) {
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) {
|
||||||
|
claim_pin(pin);
|
||||||
|
}
|
||||||
23
ports/zephyr-cp/common-hal/microcontroller/Pin.h
Normal file
23
ports/zephyr-cp/common-hal/microcontroller/Pin.h
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "py/mphal.h"
|
||||||
|
|
||||||
|
#include <zephyr/drivers/gpio.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
const struct device *port;
|
||||||
|
gpio_pin_t number;
|
||||||
|
} mcu_pin_obj_t;
|
||||||
|
|
||||||
|
#include "autogen-pins.h"
|
||||||
|
|
||||||
|
void reset_all_pins(void);
|
||||||
|
void reset_pin(const mcu_pin_obj_t *pin);
|
||||||
|
void claim_pin(const mcu_pin_obj_t *pin);
|
||||||
46
ports/zephyr-cp/common-hal/microcontroller/Processor.c
Normal file
46
ports/zephyr-cp/common-hal/microcontroller/Processor.c
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2017 Dan Halbert for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
#include "common-hal/microcontroller/Processor.h"
|
||||||
|
#include "shared-bindings/microcontroller/Processor.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/microcontroller/ResetReason.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <zephyr/drivers/hwinfo.h>
|
||||||
|
|
||||||
|
|
||||||
|
float common_hal_mcu_processor_get_temperature(void) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern uint32_t SystemCoreClock;
|
||||||
|
uint32_t common_hal_mcu_processor_get_frequency(void) {
|
||||||
|
return SystemCoreClock;
|
||||||
|
}
|
||||||
|
|
||||||
|
float common_hal_mcu_processor_get_voltage(void) {
|
||||||
|
return 3.3f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) {
|
||||||
|
ssize_t len = hwinfo_get_device_id(raw_id, COMMON_HAL_MCU_PROCESSOR_UID_LENGTH);
|
||||||
|
if (len < 0) {
|
||||||
|
printk("UID retrieval failed: %d\n", len);
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
if (len < COMMON_HAL_MCU_PROCESSOR_UID_LENGTH) {
|
||||||
|
printk("UID shorter %d than defined length %d\n", len, COMMON_HAL_MCU_PROCESSOR_UID_LENGTH);
|
||||||
|
memset(raw_id + len, 0, COMMON_HAL_MCU_PROCESSOR_UID_LENGTH - len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) {
|
||||||
|
mcu_reset_reason_t r = RESET_REASON_UNKNOWN;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
23
ports/zephyr-cp/common-hal/microcontroller/Processor.h
Normal file
23
ports/zephyr-cp/common-hal/microcontroller/Processor.h
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2017 Dan Halbert for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if CONFIG_HWINFO_NRF
|
||||||
|
#define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH 8
|
||||||
|
#else
|
||||||
|
// Extra long and the remainder will be left empty. Will print out the actual length.
|
||||||
|
#define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
// Stores no state currently.
|
||||||
|
} mcu_processor_obj_t;
|
||||||
|
|
||||||
|
extern uint32_t reset_reason_saved;
|
||||||
116
ports/zephyr-cp/common-hal/microcontroller/__init__.c
Normal file
116
ports/zephyr-cp/common-hal/microcontroller/__init__.c
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "py/mphal.h"
|
||||||
|
#include "py/obj.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
#include "common-hal/microcontroller/Pin.h"
|
||||||
|
#include "common-hal/microcontroller/Processor.h"
|
||||||
|
|
||||||
|
// #include "shared-bindings/nvm/ByteArray.h"
|
||||||
|
#include "shared-bindings/microcontroller/__init__.h"
|
||||||
|
#include "shared-bindings/microcontroller/Pin.h"
|
||||||
|
#include "shared-bindings/microcontroller/Processor.h"
|
||||||
|
|
||||||
|
#include "supervisor/filesystem.h"
|
||||||
|
#include "supervisor/port.h"
|
||||||
|
#include "supervisor/shared/safe_mode.h"
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
|
||||||
|
// This routine should work even when interrupts are disabled. Used by OneWire
|
||||||
|
// for precise timing.
|
||||||
|
void common_hal_mcu_delay_us(uint32_t delay) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t _irq_key;
|
||||||
|
|
||||||
|
static volatile uint32_t nesting_count = 0;
|
||||||
|
void common_hal_mcu_disable_interrupts() {
|
||||||
|
if (nesting_count == 0) {
|
||||||
|
// Unlike __disable_irq(), this should only be called the first time
|
||||||
|
// "is_nested_critical_region" is sd's equivalent of our nesting count
|
||||||
|
// so a nested call would store 0 in the global and make the later
|
||||||
|
// exit call not actually re-enable interrupts
|
||||||
|
//
|
||||||
|
// This only disables interrupts of priority 2 through 7; levels 0, 1,
|
||||||
|
// and 4, are exclusive to softdevice and should never be used, so
|
||||||
|
// this limitation is not important.
|
||||||
|
// sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||||
|
if (!k_is_in_isr()) {
|
||||||
|
k_sched_lock();
|
||||||
|
}
|
||||||
|
_irq_key = irq_lock();
|
||||||
|
}
|
||||||
|
nesting_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_mcu_enable_interrupts() {
|
||||||
|
if (nesting_count == 0) {
|
||||||
|
// This is very very bad because it means there was mismatched disable/enables.
|
||||||
|
reset_into_safe_mode(SAFE_MODE_INTERRUPT_ERROR);
|
||||||
|
}
|
||||||
|
nesting_count--;
|
||||||
|
if (nesting_count > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
irq_unlock(_irq_key);
|
||||||
|
if (!k_is_in_isr()) {
|
||||||
|
k_sched_unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
|
||||||
|
enum { DFU_MAGIC_UF2_RESET = 0x57 };
|
||||||
|
uint8_t new_value = 0;
|
||||||
|
if (runmode == RUNMODE_BOOTLOADER || runmode == RUNMODE_UF2) {
|
||||||
|
new_value = DFU_MAGIC_UF2_RESET;
|
||||||
|
}
|
||||||
|
// int err_code = sd_power_gpregret_set(0, DFU_MAGIC_UF2_RESET);
|
||||||
|
// if (err_code != NRF_SUCCESS) {
|
||||||
|
// // Set it without the soft device if the SD failed. (It may be off.)
|
||||||
|
// nrf_power_gpregret_set(NRF_POWER, new_value);
|
||||||
|
// }
|
||||||
|
if (runmode == RUNMODE_SAFE_MODE) {
|
||||||
|
safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_mcu_reset(void) {
|
||||||
|
filesystem_flush();
|
||||||
|
reset_cpu();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The singleton microcontroller.Processor object, bound to microcontroller.cpu
|
||||||
|
// It currently only has properties, and no state.
|
||||||
|
const mcu_processor_obj_t common_hal_mcu_processor_obj = {
|
||||||
|
.base = {
|
||||||
|
.type = &mcu_processor_type,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#if CIRCUITPY_NVM && CIRCUITPY_INTERNAL_NVM_SIZE > 0
|
||||||
|
// The singleton nvm.ByteArray object.
|
||||||
|
const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = {
|
||||||
|
.base = {
|
||||||
|
.type = &nvm_bytearray_type,
|
||||||
|
},
|
||||||
|
.start_address = (uint8_t *)CIRCUITPY_INTERNAL_NVM_START_ADDR,
|
||||||
|
.len = CIRCUITPY_INTERNAL_NVM_SIZE,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CIRCUITPY_WATCHDOG
|
||||||
|
// The singleton watchdog.WatchDogTimer object.
|
||||||
|
watchdog_watchdogtimer_obj_t common_hal_mcu_watchdogtimer_obj = {
|
||||||
|
.base = {
|
||||||
|
.type = &watchdog_watchdogtimer_type,
|
||||||
|
},
|
||||||
|
.timeout = 0.0f,
|
||||||
|
.mode = WATCHDOGMODE_NONE,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
48
ports/zephyr-cp/common-hal/os/__init__.c
Normal file
48
ports/zephyr-cp/common-hal/os/__init__.c
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "genhdr/mpversion.h"
|
||||||
|
#include "py/mpconfig.h"
|
||||||
|
#include "py/objstr.h"
|
||||||
|
#include "py/objtuple.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/os/__init__.h"
|
||||||
|
|
||||||
|
#include <zephyr/random/random.h>
|
||||||
|
|
||||||
|
static const qstr os_uname_info_fields[] = {
|
||||||
|
MP_QSTR_sysname, MP_QSTR_nodename,
|
||||||
|
MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine
|
||||||
|
};
|
||||||
|
static const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "nrf52");
|
||||||
|
static const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "nrf52");
|
||||||
|
|
||||||
|
static const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING);
|
||||||
|
static const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE);
|
||||||
|
static const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
|
||||||
|
|
||||||
|
static MP_DEFINE_ATTRTUPLE(
|
||||||
|
os_uname_info_obj,
|
||||||
|
os_uname_info_fields,
|
||||||
|
5,
|
||||||
|
(mp_obj_t)&os_uname_info_sysname_obj,
|
||||||
|
(mp_obj_t)&os_uname_info_nodename_obj,
|
||||||
|
(mp_obj_t)&os_uname_info_release_obj,
|
||||||
|
(mp_obj_t)&os_uname_info_version_obj,
|
||||||
|
(mp_obj_t)&os_uname_info_machine_obj
|
||||||
|
);
|
||||||
|
|
||||||
|
mp_obj_t common_hal_os_uname(void) {
|
||||||
|
return (mp_obj_t)&os_uname_info_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_os_urandom(uint8_t *buffer, mp_uint_t length) {
|
||||||
|
#if !DT_HAS_CHOSEN(zephyr_entropy)
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
return sys_csrand_get(buffer, length) == 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
697
ports/zephyr-cp/common-hal/socketpool/Socket.c
Normal file
697
ports/zephyr-cp/common-hal/socketpool/Socket.c
Normal file
|
|
@ -0,0 +1,697 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2020 Lucian Copeland for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "shared-bindings/socketpool/Socket.h"
|
||||||
|
|
||||||
|
#include "shared/runtime/interrupt_char.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "shared-bindings/socketpool/SocketPool.h"
|
||||||
|
#include "common-hal/socketpool/__init__.h"
|
||||||
|
#include "common-hal/wifi/__init__.h"
|
||||||
|
#if CIRCUITPY_SSL
|
||||||
|
#include "shared-bindings/ssl/SSLSocket.h"
|
||||||
|
#include "shared-module/ssl/SSLSocket.h"
|
||||||
|
#endif
|
||||||
|
#include "supervisor/port.h"
|
||||||
|
#include "supervisor/shared/tick.h"
|
||||||
|
#include "supervisor/workflow.h"
|
||||||
|
|
||||||
|
#include <zephyr/net/net_ip.h>
|
||||||
|
|
||||||
|
// void socketpool_resolve_host_or_throw(int family, int type, const char *hostname, struct sockaddr_storage *addr, int port) {
|
||||||
|
// // struct addrinfo *result_i;
|
||||||
|
// // const struct addrinfo hints = {
|
||||||
|
// // .ai_family = family,
|
||||||
|
// // .ai_socktype = type,
|
||||||
|
// // };
|
||||||
|
// // int error = socketpool_getaddrinfo_common(hostname, port, &hints, &result_i);
|
||||||
|
// if (true) {
|
||||||
|
// common_hal_socketpool_socketpool_raise_gaierror_noname();
|
||||||
|
// }
|
||||||
|
// // memcpy(addr, result_i->ai_addr, sizeof(struct sockaddr_storage));
|
||||||
|
// // lwip_freeaddrinfo(result_i);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static void resolve_host_or_throw(socketpool_socket_obj_t *self, const char *hostname, struct sockaddr_storage *addr, int port) {
|
||||||
|
// socketpool_resolve_host_or_throw(self->family, self->type, hostname, addr, port);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// StackType_t socket_select_stack[2 * configMINIMAL_STACK_SIZE];
|
||||||
|
|
||||||
|
// /* Socket state table:
|
||||||
|
// * 0 := Closed (unused)
|
||||||
|
// * 1 := Open
|
||||||
|
// * 2 := Closing (remove from rfds)
|
||||||
|
// * Index into socket_fd_state is calculated from actual lwip fd. idx := fd - LWIP_SOCKET_OFFSET
|
||||||
|
// */
|
||||||
|
// #define FDSTATE_CLOSED 0
|
||||||
|
// #define FDSTATE_OPEN 1
|
||||||
|
// #define FDSTATE_CLOSING 2
|
||||||
|
// static uint8_t socket_fd_state[CONFIG_LWIP_MAX_SOCKETS];
|
||||||
|
|
||||||
|
// How long to wait between checks for a socket to connect.
|
||||||
|
#define SOCKET_CONNECT_POLL_INTERVAL_MS 100
|
||||||
|
|
||||||
|
// static socketpool_socket_obj_t *user_socket[CONFIG_LWIP_MAX_SOCKETS];
|
||||||
|
// StaticTask_t socket_select_task_buffer;
|
||||||
|
// TaskHandle_t socket_select_task_handle;
|
||||||
|
// static int socket_change_fd = -1;
|
||||||
|
|
||||||
|
// static void socket_select_task(void *arg) {
|
||||||
|
// uint64_t signal;
|
||||||
|
// fd_set readfds;
|
||||||
|
// fd_set excptfds;
|
||||||
|
|
||||||
|
// while (true) {
|
||||||
|
// FD_ZERO(&readfds);
|
||||||
|
// FD_ZERO(&excptfds);
|
||||||
|
// FD_SET(socket_change_fd, &readfds);
|
||||||
|
// int max_fd = socket_change_fd;
|
||||||
|
// for (size_t i = 0; i < MP_ARRAY_SIZE(socket_fd_state); i++) {
|
||||||
|
// if ((socket_fd_state[i] == FDSTATE_OPEN) && (user_socket[i] == NULL)) {
|
||||||
|
// int sockfd = i + LWIP_SOCKET_OFFSET;
|
||||||
|
// max_fd = MAX(max_fd, sockfd);
|
||||||
|
// FD_SET(sockfd, &readfds);
|
||||||
|
// FD_SET(sockfd, &excptfds);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int num_triggered = select(max_fd + 1, &readfds, NULL, &excptfds, NULL);
|
||||||
|
// // Hard error (or someone closed a socket on another thread)
|
||||||
|
// if (num_triggered == -1) {
|
||||||
|
// assert(errno == EBADF);
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// assert(num_triggered > 0);
|
||||||
|
|
||||||
|
// // Notice event trigger
|
||||||
|
// if (FD_ISSET(socket_change_fd, &readfds)) {
|
||||||
|
// read(socket_change_fd, &signal, sizeof(signal));
|
||||||
|
// num_triggered--;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Handle active FDs, close the dead ones
|
||||||
|
// for (size_t i = 0; i < MP_ARRAY_SIZE(socket_fd_state); i++) {
|
||||||
|
// int sockfd = i + LWIP_SOCKET_OFFSET;
|
||||||
|
// if (socket_fd_state[i] != FDSTATE_CLOSED) {
|
||||||
|
// if (FD_ISSET(sockfd, &readfds) || FD_ISSET(sockfd, &excptfds)) {
|
||||||
|
// if (socket_fd_state[i] == FDSTATE_CLOSING) {
|
||||||
|
// socket_fd_state[i] = FDSTATE_CLOSED;
|
||||||
|
// num_triggered--;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (num_triggered > 0) {
|
||||||
|
// // Wake up CircuitPython by queuing request
|
||||||
|
// supervisor_workflow_request_background();
|
||||||
|
// ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// close(socket_change_fd);
|
||||||
|
// socket_change_fd = -1;
|
||||||
|
// vTaskDelete(NULL);
|
||||||
|
// }
|
||||||
|
|
||||||
|
void socket_user_reset(void) {
|
||||||
|
// if (socket_change_fd < 0) {
|
||||||
|
// esp_vfs_eventfd_config_t config = ESP_VFS_EVENTD_CONFIG_DEFAULT();
|
||||||
|
// ESP_ERROR_CHECK(esp_vfs_eventfd_register(&config));
|
||||||
|
|
||||||
|
// // Clear initial socket states
|
||||||
|
// for (size_t i = 0; i < MP_ARRAY_SIZE(socket_fd_state); i++) {
|
||||||
|
// socket_fd_state[i] = FDSTATE_CLOSED;
|
||||||
|
// user_socket[i] = NULL;
|
||||||
|
// }
|
||||||
|
// socket_change_fd = eventfd(0, 0);
|
||||||
|
// // Run this at the same priority as CP so that the web workflow background task can be
|
||||||
|
// // queued while CP is running. Both tasks can still sleep and, therefore, sleep overall.
|
||||||
|
// socket_select_task_handle = xTaskCreateStaticPinnedToCore(socket_select_task,
|
||||||
|
// "socket_select",
|
||||||
|
// 2 * configMINIMAL_STACK_SIZE,
|
||||||
|
// NULL,
|
||||||
|
// uxTaskPriorityGet(NULL),
|
||||||
|
// socket_select_stack,
|
||||||
|
// &socket_select_task_buffer,
|
||||||
|
// xPortGetCoreID());
|
||||||
|
// } else {
|
||||||
|
// // Not init - close open user sockets
|
||||||
|
// for (size_t i = 0; i < MP_ARRAY_SIZE(socket_fd_state); i++) {
|
||||||
|
// if ((socket_fd_state[i] == FDSTATE_OPEN) && user_socket[i]) {
|
||||||
|
// common_hal_socketpool_socket_close(user_socket[i]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unblock select task (ok if not blocked yet)
|
||||||
|
void socketpool_socket_poll_resume(void) {
|
||||||
|
// if (socket_select_task_handle) {
|
||||||
|
// xTaskNotifyGive(socket_select_task_handle);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// The writes below send an event to the socket select task so that it redoes the
|
||||||
|
// select with the new open socket set.
|
||||||
|
|
||||||
|
// static bool register_open_socket(int fd) {
|
||||||
|
// if (fd < FD_SETSIZE) {
|
||||||
|
// socket_fd_state[fd - LWIP_SOCKET_OFFSET] = FDSTATE_OPEN;
|
||||||
|
// user_socket[fd - LWIP_SOCKET_OFFSET] = NULL;
|
||||||
|
|
||||||
|
// uint64_t signal = 1;
|
||||||
|
// write(socket_change_fd, &signal, sizeof(signal));
|
||||||
|
// socketpool_socket_poll_resume();
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static void mark_user_socket(int fd, socketpool_socket_obj_t *obj) {
|
||||||
|
// socket_fd_state[fd - LWIP_SOCKET_OFFSET] = FDSTATE_OPEN;
|
||||||
|
// user_socket[fd - LWIP_SOCKET_OFFSET] = obj;
|
||||||
|
// // No need to wakeup select task
|
||||||
|
// }
|
||||||
|
|
||||||
|
static bool _socketpool_socket(socketpool_socketpool_obj_t *self,
|
||||||
|
socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type,
|
||||||
|
int proto,
|
||||||
|
socketpool_socket_obj_t *sock) {
|
||||||
|
int addr_family;
|
||||||
|
int ipproto;
|
||||||
|
|
||||||
|
if (family == SOCKETPOOL_AF_INET) {
|
||||||
|
addr_family = AF_INET;
|
||||||
|
ipproto = IPPROTO_IP;
|
||||||
|
#if CIRCUITPY_SOCKETPOOL_IPV6
|
||||||
|
} else { // INET6
|
||||||
|
addr_family = AF_INET6;
|
||||||
|
ipproto = IPPROTO_IPV6;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int socket_type;
|
||||||
|
if (type == SOCKETPOOL_SOCK_STREAM) {
|
||||||
|
socket_type = SOCK_STREAM;
|
||||||
|
} else if (type == SOCKETPOOL_SOCK_DGRAM) {
|
||||||
|
socket_type = SOCK_DGRAM;
|
||||||
|
} else { // SOCKETPOOL_SOCK_RAW
|
||||||
|
socket_type = SOCK_RAW;
|
||||||
|
ipproto = proto;
|
||||||
|
}
|
||||||
|
sock->type = socket_type;
|
||||||
|
sock->family = addr_family;
|
||||||
|
sock->ipproto = ipproto;
|
||||||
|
sock->pool = self;
|
||||||
|
sock->timeout_ms = (uint)-1;
|
||||||
|
|
||||||
|
// Create LWIP socket
|
||||||
|
// int socknum = -1;
|
||||||
|
// socknum = lwip_socket(sock->family, sock->type, sock->ipproto);
|
||||||
|
// if (socknum < 0) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// sock->num = socknum;
|
||||||
|
// // Sockets should be nonblocking in most cases
|
||||||
|
// lwip_fcntl(socknum, F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// special entry for workflow listener (register system socket)
|
||||||
|
bool socketpool_socket(socketpool_socketpool_obj_t *self,
|
||||||
|
socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type,
|
||||||
|
int proto, socketpool_socket_obj_t *sock) {
|
||||||
|
|
||||||
|
if (!_socketpool_socket(self, family, type, proto, sock)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This shouldn't happen since we have room for the same number of sockets as LWIP.
|
||||||
|
// if (!register_open_socket(sock->num)) {
|
||||||
|
// lwip_close(sock->num);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_t *self,
|
||||||
|
socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type, int proto) {
|
||||||
|
switch (family) {
|
||||||
|
#if CIRCUITPY_SOCKETPOOL_IPV6
|
||||||
|
case SOCKETPOOL_AF_INET6:
|
||||||
|
#endif
|
||||||
|
case SOCKETPOOL_AF_INET:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mp_raise_NotImplementedError(MP_ERROR_TEXT("Unsupported socket type"));
|
||||||
|
}
|
||||||
|
|
||||||
|
socketpool_socket_obj_t *sock = mp_obj_malloc_with_finaliser(socketpool_socket_obj_t, &socketpool_socket_type);
|
||||||
|
|
||||||
|
if (!_socketpool_socket(self, family, type, proto, sock)) {
|
||||||
|
mp_raise_RuntimeError(MP_ERROR_TEXT("Out of sockets"));
|
||||||
|
}
|
||||||
|
// mark_user_socket(sock->num, sock);
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
int socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out, socketpool_socket_obj_t *accepted) {
|
||||||
|
struct sockaddr_storage peer_addr;
|
||||||
|
// socklen_t socklen = sizeof(peer_addr);
|
||||||
|
int newsoc = -1;
|
||||||
|
bool timed_out = false;
|
||||||
|
uint64_t start_ticks = supervisor_ticks_ms64();
|
||||||
|
|
||||||
|
// Allow timeouts and interrupts
|
||||||
|
while (newsoc == -1 && !timed_out) {
|
||||||
|
if (self->timeout_ms != (uint)-1 && self->timeout_ms != 0) {
|
||||||
|
timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms;
|
||||||
|
}
|
||||||
|
RUN_BACKGROUND_TASKS;
|
||||||
|
// newsoc = lwip_accept(self->num, (struct sockaddr *)&peer_addr, &socklen);
|
||||||
|
// In non-blocking mode, fail instead of timing out
|
||||||
|
if (newsoc == -1 && (self->timeout_ms == 0 || mp_hal_is_interrupted())) {
|
||||||
|
return -MP_EAGAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timed_out) {
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newsoc < 0) {
|
||||||
|
return -MP_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We got a socket. New client socket will not be non-blocking by default, so make it non-blocking.
|
||||||
|
// lwip_fcntl(newsoc, F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
|
if (accepted != NULL) {
|
||||||
|
// Error if called with open socket object.
|
||||||
|
assert(common_hal_socketpool_socket_get_closed(accepted));
|
||||||
|
|
||||||
|
// Register if system socket
|
||||||
|
// if (!register_open_socket(newsoc)) {
|
||||||
|
// lwip_close(newsoc);
|
||||||
|
// return -MP_EBADF;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Replace the old accepted socket with the new one.
|
||||||
|
accepted->num = newsoc;
|
||||||
|
accepted->pool = self->pool;
|
||||||
|
accepted->connected = true;
|
||||||
|
accepted->type = self->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peer_out) {
|
||||||
|
*peer_out = sockaddr_to_tuple(&peer_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newsoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out) {
|
||||||
|
// Set the socket type only after the socketpool_socket_accept succeeds, so that the
|
||||||
|
// finaliser is not called on a bad socket.
|
||||||
|
socketpool_socket_obj_t *sock = mp_obj_malloc_with_finaliser(socketpool_socket_obj_t, NULL);
|
||||||
|
int newsoc = socketpool_socket_accept(self, peer_out, NULL);
|
||||||
|
|
||||||
|
if (newsoc > 0) {
|
||||||
|
// Create the socket
|
||||||
|
// mark_user_socket(newsoc, sock);
|
||||||
|
sock->base.type = &socketpool_socket_type;
|
||||||
|
sock->num = newsoc;
|
||||||
|
sock->pool = self->pool;
|
||||||
|
sock->connected = true;
|
||||||
|
sock->type = self->type;
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
} else {
|
||||||
|
mp_raise_OSError(-newsoc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self,
|
||||||
|
const char *host, size_t hostlen, uint32_t port) {
|
||||||
|
// struct sockaddr_storage bind_addr;
|
||||||
|
const char *broadcast = "<broadcast>";
|
||||||
|
|
||||||
|
// bind_addr.ss_family = self->family;
|
||||||
|
|
||||||
|
#if CIRCUITPY_SOCKETPOOL_IPV6
|
||||||
|
if (self->family == AF_INET6) {
|
||||||
|
struct sockaddr_in6 *addr6 = (void *)&bind_addr;
|
||||||
|
addr6->sin6_port = htons(port);
|
||||||
|
// no ipv6 broadcast
|
||||||
|
if (hostlen == 0) {
|
||||||
|
memset(&addr6->sin6_addr, 0, sizeof(addr6->sin6_addr));
|
||||||
|
} else {
|
||||||
|
socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, port);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// struct sockaddr_in *addr4 = (void *)&bind_addr;
|
||||||
|
// addr4->sin_port = htons(port);
|
||||||
|
if (hostlen == 0) {
|
||||||
|
// addr4->sin_addr.s_addr = IPADDR_ANY;
|
||||||
|
} else if (hostlen == strlen(broadcast) &&
|
||||||
|
memcmp(host, broadcast, strlen(broadcast)) == 0) {
|
||||||
|
// addr4->sin_addr.s_addr = IPADDR_BROADCAST;
|
||||||
|
} else {
|
||||||
|
// socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// int result = lwip_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr));
|
||||||
|
// if (result == 0) {
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
void socketpool_socket_close(socketpool_socket_obj_t *self) {
|
||||||
|
#if CIRCUITPY_SSL
|
||||||
|
if (self->ssl_socket) {
|
||||||
|
ssl_sslsocket_obj_t *ssl_socket = self->ssl_socket;
|
||||||
|
self->ssl_socket = NULL;
|
||||||
|
common_hal_ssl_sslsocket_close(ssl_socket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
self->connected = false;
|
||||||
|
// int fd = self->num;
|
||||||
|
// Ignore bogus/closed sockets
|
||||||
|
// if (fd >= LWIP_SOCKET_OFFSET) {
|
||||||
|
// if (user_socket[fd - LWIP_SOCKET_OFFSET] == NULL) {
|
||||||
|
// socket_fd_state[fd - LWIP_SOCKET_OFFSET] = FDSTATE_CLOSING;
|
||||||
|
// lwip_shutdown(fd, SHUT_RDWR);
|
||||||
|
// lwip_close(fd);
|
||||||
|
// } else {
|
||||||
|
// lwip_shutdown(fd, SHUT_RDWR);
|
||||||
|
// lwip_close(fd);
|
||||||
|
// socket_fd_state[fd - LWIP_SOCKET_OFFSET] = FDSTATE_CLOSED;
|
||||||
|
// user_socket[fd - LWIP_SOCKET_OFFSET] = NULL;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
self->num = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_socketpool_socket_close(socketpool_socket_obj_t *self) {
|
||||||
|
socketpool_socket_close(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self,
|
||||||
|
const char *host, size_t hostlen, uint32_t port) {
|
||||||
|
// struct sockaddr_storage addr;
|
||||||
|
// resolve_host_or_throw(self, host, &addr, port);
|
||||||
|
|
||||||
|
// Replace above with function call -----
|
||||||
|
|
||||||
|
// Emulate SO_CONTIMEO, which is not implemented by lwip.
|
||||||
|
// All our sockets are non-blocking, so we check the timeout ourselves.
|
||||||
|
|
||||||
|
int result = -1;
|
||||||
|
// result = lwip_connect(self->num, (struct sockaddr *)&addr, addr.s2_len);
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
// Connected immediately.
|
||||||
|
self->connected = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result < 0 && errno != EINPROGRESS) {
|
||||||
|
// Some error happened; error is in errno.
|
||||||
|
mp_raise_OSError(errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct timeval timeout = {
|
||||||
|
// .tv_sec = 0,
|
||||||
|
// .tv_usec = SOCKET_CONNECT_POLL_INTERVAL_MS * 1000,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// Keep checking, using select(), until timeout expires, at short intervals.
|
||||||
|
// This allows ctrl-C interrupts to be detected and background tasks to run.
|
||||||
|
mp_uint_t timeout_left = self->timeout_ms;
|
||||||
|
|
||||||
|
while (timeout_left > 0) {
|
||||||
|
RUN_BACKGROUND_TASKS;
|
||||||
|
// Allow ctrl-C interrupt
|
||||||
|
if (mp_hal_is_interrupted()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fd_set fds;
|
||||||
|
// FD_ZERO(&fds);
|
||||||
|
// FD_SET(self->num, &fds);
|
||||||
|
|
||||||
|
// result = select(self->num + 1, NULL, &fds, NULL, &timeout);
|
||||||
|
if (result == 0) {
|
||||||
|
// No change to fd's after waiting for timeout, so try again if some time is still left.
|
||||||
|
// Don't wrap below 0, because we're using a uint.
|
||||||
|
if (timeout_left < SOCKET_CONNECT_POLL_INTERVAL_MS) {
|
||||||
|
timeout_left = 0;
|
||||||
|
} else {
|
||||||
|
timeout_left -= SOCKET_CONNECT_POLL_INTERVAL_MS;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
// Some error happened when doing select(); error is in errno.
|
||||||
|
mp_raise_OSError(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
// select() indicated the socket is writable. Check if any connection error occurred.
|
||||||
|
int error_code = 0;
|
||||||
|
// socklen_t socklen = sizeof(error_code);
|
||||||
|
// result = getsockopt(self->num, SOL_SOCKET, SO_ERROR, &error_code, &socklen);
|
||||||
|
if (result < 0 || error_code != 0) {
|
||||||
|
mp_raise_OSError(errno);
|
||||||
|
}
|
||||||
|
self->connected = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No connection after timeout. The connection attempt is not stopped.
|
||||||
|
// This imitates what happens in Python.
|
||||||
|
mp_raise_OSError(ETIMEDOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_socketpool_socket_get_closed(socketpool_socket_obj_t *self) {
|
||||||
|
return self->num < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_socketpool_socket_get_connected(socketpool_socket_obj_t *self) {
|
||||||
|
return self->connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *self, int backlog) {
|
||||||
|
// return lwip_listen(self->num, backlog) == 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *self,
|
||||||
|
uint8_t *buf, uint32_t len, mp_obj_t *source_out) {
|
||||||
|
|
||||||
|
// struct sockaddr_storage source_addr;
|
||||||
|
// socklen_t socklen = sizeof(source_addr);
|
||||||
|
|
||||||
|
// LWIP Socket
|
||||||
|
uint64_t start_ticks = supervisor_ticks_ms64();
|
||||||
|
int received = -1;
|
||||||
|
bool timed_out = false;
|
||||||
|
while (received == -1 &&
|
||||||
|
!timed_out &&
|
||||||
|
!mp_hal_is_interrupted()) {
|
||||||
|
if (self->timeout_ms != (uint)-1 && self->timeout_ms != 0) {
|
||||||
|
timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms;
|
||||||
|
}
|
||||||
|
RUN_BACKGROUND_TASKS;
|
||||||
|
// received = lwip_recvfrom(self->num, buf, len, 0, (struct sockaddr *)&source_addr, &socklen);
|
||||||
|
|
||||||
|
// In non-blocking mode, fail instead of looping
|
||||||
|
if (received == -1 && self->timeout_ms == 0) {
|
||||||
|
mp_raise_OSError(MP_EAGAIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timed_out) {
|
||||||
|
mp_raise_OSError(ETIMEDOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (received < 0) {
|
||||||
|
mp_raise_BrokenPipeError();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source_out) {
|
||||||
|
// *source_out = sockaddr_to_tuple(&source_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return received;
|
||||||
|
}
|
||||||
|
|
||||||
|
int socketpool_socket_recv_into(socketpool_socket_obj_t *self,
|
||||||
|
const uint8_t *buf, uint32_t len) {
|
||||||
|
int received = 0;
|
||||||
|
bool timed_out = false;
|
||||||
|
|
||||||
|
if (self->num != -1) {
|
||||||
|
// LWIP Socket
|
||||||
|
uint64_t start_ticks = supervisor_ticks_ms64();
|
||||||
|
received = -1;
|
||||||
|
while (received == -1 &&
|
||||||
|
!timed_out) {
|
||||||
|
if (self->timeout_ms != (uint)-1 && self->timeout_ms != 0) {
|
||||||
|
timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms;
|
||||||
|
}
|
||||||
|
RUN_BACKGROUND_TASKS;
|
||||||
|
// received = lwip_recv(self->num, (void *)buf, len, 0);
|
||||||
|
// In non-blocking mode, fail instead of looping
|
||||||
|
if (received < 1 && self->timeout_ms == 0) {
|
||||||
|
if ((received == 0) || (errno == ENOTCONN)) {
|
||||||
|
self->connected = false;
|
||||||
|
return -MP_ENOTCONN;
|
||||||
|
}
|
||||||
|
return -MP_EAGAIN;
|
||||||
|
}
|
||||||
|
// Check this after going through the loop once so it can make
|
||||||
|
// progress while interrupted.
|
||||||
|
if (mp_hal_is_interrupted()) {
|
||||||
|
if (received == -1) {
|
||||||
|
return -MP_EAGAIN;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return -MP_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timed_out) {
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
return received;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len) {
|
||||||
|
int received = socketpool_socket_recv_into(self, buf, len);
|
||||||
|
if (received < 0) {
|
||||||
|
mp_raise_OSError(-received);
|
||||||
|
}
|
||||||
|
return received;
|
||||||
|
}
|
||||||
|
|
||||||
|
int socketpool_socket_send(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len) {
|
||||||
|
int sent = -1;
|
||||||
|
if (self->num != -1) {
|
||||||
|
// LWIP Socket
|
||||||
|
// TODO: deal with potential failure/add timeout?
|
||||||
|
// sent = lwip_send(self->num, buf, len, 0);
|
||||||
|
} else {
|
||||||
|
sent = -MP_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sent < 0) {
|
||||||
|
if (errno == ECONNRESET || errno == ENOTCONN) {
|
||||||
|
self->connected = false;
|
||||||
|
}
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len) {
|
||||||
|
int sent = socketpool_socket_send(self, buf, len);
|
||||||
|
|
||||||
|
if (sent < 0) {
|
||||||
|
mp_raise_OSError(-sent);
|
||||||
|
}
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *self,
|
||||||
|
const char *host, size_t hostlen, uint32_t port, const uint8_t *buf, uint32_t len) {
|
||||||
|
|
||||||
|
// struct sockaddr_storage addr;
|
||||||
|
// resolve_host_or_throw(self, host, &addr, port);
|
||||||
|
|
||||||
|
// int bytes_sent = lwip_sendto(self->num, buf, len, 0, (struct sockaddr *)&addr, addr.s2_len);
|
||||||
|
// if (bytes_sent < 0) {
|
||||||
|
// mp_raise_BrokenPipeError();
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
int bytes_sent = 0;
|
||||||
|
return bytes_sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t *self, uint32_t timeout_ms) {
|
||||||
|
self->timeout_ms = timeout_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_int_t common_hal_socketpool_socket_get_type(socketpool_socket_obj_t *self) {
|
||||||
|
return self->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int common_hal_socketpool_socket_setsockopt(socketpool_socket_obj_t *self, int level, int optname, const void *value, size_t optlen) {
|
||||||
|
int err = 0; // lwip_setsockopt(self->num, level, optname, value, optlen);
|
||||||
|
if (err != 0) {
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_socketpool_readable(socketpool_socket_obj_t *self) {
|
||||||
|
// struct timeval immediate = {0, 0};
|
||||||
|
|
||||||
|
// fd_set fds;
|
||||||
|
// FD_ZERO(&fds);
|
||||||
|
// FD_SET(self->num, &fds);
|
||||||
|
// int num_triggered = select(self->num + 1, &fds, NULL, &fds, &immediate);
|
||||||
|
|
||||||
|
// including returning true in the error case
|
||||||
|
// return num_triggered != 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_socketpool_writable(socketpool_socket_obj_t *self) {
|
||||||
|
// struct timeval immediate = {0, 0};
|
||||||
|
|
||||||
|
// fd_set fds;
|
||||||
|
// FD_ZERO(&fds);
|
||||||
|
// FD_SET(self->num, &fds);
|
||||||
|
// int num_triggered = select(self->num + 1, NULL, &fds, &fds, &immediate);
|
||||||
|
|
||||||
|
// including returning true in the error case
|
||||||
|
// return num_triggered != 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void socketpool_socket_move(socketpool_socket_obj_t *self, socketpool_socket_obj_t *sock) {
|
||||||
|
*sock = *self;
|
||||||
|
self->connected = false;
|
||||||
|
self->num = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void socketpool_socket_reset(socketpool_socket_obj_t *self) {
|
||||||
|
if (self->base.type == &socketpool_socket_type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self->base.type = &socketpool_socket_type;
|
||||||
|
self->connected = false;
|
||||||
|
self->num = -1;
|
||||||
|
}
|
||||||
29
ports/zephyr-cp/common-hal/socketpool/Socket.h
Normal file
29
ports/zephyr-cp/common-hal/socketpool/Socket.h
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
#include "common-hal/socketpool/SocketPool.h"
|
||||||
|
|
||||||
|
typedef struct ssl_sslsocket_obj ssl_sslsocket_obj_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
int num;
|
||||||
|
int type;
|
||||||
|
int family;
|
||||||
|
int ipproto;
|
||||||
|
bool connected;
|
||||||
|
socketpool_socketpool_obj_t *pool;
|
||||||
|
ssl_sslsocket_obj_t *ssl_socket;
|
||||||
|
mp_uint_t timeout_ms;
|
||||||
|
} socketpool_socket_obj_t;
|
||||||
|
|
||||||
|
void socket_user_reset(void);
|
||||||
|
// Unblock workflow socket select thread (platform specific)
|
||||||
|
void socketpool_socket_poll_resume(void);
|
||||||
121
ports/zephyr-cp/common-hal/socketpool/SocketPool.c
Normal file
121
ports/zephyr-cp/common-hal/socketpool/SocketPool.c
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "shared-bindings/socketpool/SocketPool.h"
|
||||||
|
#include "common-hal/socketpool/Socket.h"
|
||||||
|
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "shared-bindings/wifi/__init__.h"
|
||||||
|
#include "common-hal/socketpool/__init__.h"
|
||||||
|
|
||||||
|
void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *self, mp_obj_t radio) {
|
||||||
|
if (radio != MP_OBJ_FROM_PTR(&common_hal_wifi_radio_obj)) {
|
||||||
|
mp_raise_ValueError(MP_ERROR_TEXT("SocketPool can only be used with wifi.radio"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// common_hal_socketpool_socket is in socketpool/Socket.c to centralize open socket tracking.
|
||||||
|
|
||||||
|
// int socketpool_getaddrinfo_common(const char *host, int service, const struct addrinfo *hints, struct addrinfo **res) {
|
||||||
|
// // As of 2022, the version of lwip in esp-idf does not handle the
|
||||||
|
// // trailing-dot syntax of domain names, so emulate it.
|
||||||
|
// // Remove this once https://github.com/espressif/esp-idf/issues/10013 has
|
||||||
|
// // been implemented
|
||||||
|
// if (host) {
|
||||||
|
// size_t strlen_host = strlen(host);
|
||||||
|
// if (strlen_host && host[strlen_host - 1] == '.') {
|
||||||
|
// mp_obj_t nodot = mp_obj_new_str(host, strlen_host - 1);
|
||||||
|
// host = mp_obj_str_get_str(nodot);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // char service_buf[6];
|
||||||
|
// // snprintf(service_buf, sizeof(service_buf), "%d", service);
|
||||||
|
|
||||||
|
// // return lwip_getaddrinfo(host, service_buf, hints, res);
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static mp_obj_t format_address(const struct sockaddr *addr, int family) {
|
||||||
|
// char ip_str[IPADDR_STRLEN_MAX]; // big enough for any supported address type
|
||||||
|
// const struct sockaddr_in *a = (void *)addr;
|
||||||
|
|
||||||
|
// switch (family) {
|
||||||
|
// #if CIRCUITPY_SOCKETPOOL_IPV6
|
||||||
|
// case AF_INET6:
|
||||||
|
// inet_ntop(family, &((const struct sockaddr_in6 *)a)->sin6_addr, ip_str, sizeof(ip_str));
|
||||||
|
// break;
|
||||||
|
// #endif
|
||||||
|
// default:
|
||||||
|
// case AF_INET:
|
||||||
|
// inet_ntop(family, &((const struct sockaddr_in *)a)->sin_addr, ip_str, sizeof(ip_str));
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// return mp_obj_new_str(ip_str, strlen(ip_str));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static mp_obj_t convert_sockaddr(const struct addrinfo *ai, int port) {
|
||||||
|
// #if CIRCUITPY_SOCKETPOOL_IPV6
|
||||||
|
// mp_int_t n_tuple = ai->ai_family == AF_INET6 ? 4 : 2;
|
||||||
|
// #else
|
||||||
|
// mp_int_t n_tuple = 2;
|
||||||
|
// #endif
|
||||||
|
// mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_tuple, NULL));
|
||||||
|
// result->items[0] = format_address(ai->ai_addr, ai->ai_family);
|
||||||
|
// result->items[1] = MP_OBJ_NEW_SMALL_INT(port);
|
||||||
|
// #if CIRCUITPY_SOCKETPOOL_IPV6
|
||||||
|
// if (ai->ai_family == AF_INET6) {
|
||||||
|
// const struct sockaddr_in6 *ai6 = (void *)ai->ai_addr;
|
||||||
|
// result->items[2] = MP_OBJ_NEW_SMALL_INT(ai6->sin6_flowinfo);
|
||||||
|
// result->items[3] = MP_OBJ_NEW_SMALL_INT(ai6->sin6_scope_id);
|
||||||
|
// }
|
||||||
|
// #endif
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static mp_obj_t convert_addrinfo(const struct addrinfo *ai, int port) {
|
||||||
|
// MP_STATIC_ASSERT(AF_INET == SOCKETPOOL_AF_INET);
|
||||||
|
// #if CIRCUITPY_SOCKETPOOL_IPV6
|
||||||
|
// MP_STATIC_ASSERT(AF_INET6 == SOCKETPOOL_AF_INET6);
|
||||||
|
// #endif
|
||||||
|
// // MP_STATIC_ASSERT(AF_UNSPEC == SOCKETPOOL_AF_UNSPEC);
|
||||||
|
// mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL));
|
||||||
|
// result->items[0] = MP_OBJ_NEW_SMALL_INT(ai->ai_family);
|
||||||
|
// result->items[1] = MP_OBJ_NEW_SMALL_INT(ai->ai_socktype);
|
||||||
|
// result->items[2] = MP_OBJ_NEW_SMALL_INT(ai->ai_protocol);
|
||||||
|
// result->items[3] = ai->ai_canonname ? mp_obj_new_str(ai->ai_canonname, strlen(ai->ai_canonname)) : MP_OBJ_NEW_QSTR(MP_QSTR_);
|
||||||
|
// result->items[4] = convert_sockaddr(ai, port);
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
mp_obj_t common_hal_socketpool_getaddrinfo_raise(socketpool_socketpool_obj_t *self, const char *host, int port, int family, int type, int proto, int flags) {
|
||||||
|
// const struct addrinfo hints = {
|
||||||
|
// .ai_flags = flags,
|
||||||
|
// .ai_family = family,
|
||||||
|
// .ai_protocol = proto,
|
||||||
|
// .ai_socktype = type,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// struct addrinfo *res = NULL;
|
||||||
|
// int err = socketpool_getaddrinfo_common(host, port, &hints, &res);
|
||||||
|
if (true) {
|
||||||
|
common_hal_socketpool_socketpool_raise_gaierror_noname();
|
||||||
|
}
|
||||||
|
|
||||||
|
nlr_buf_t nlr;
|
||||||
|
if (nlr_push(&nlr) == 0) {
|
||||||
|
mp_obj_t result = mp_obj_new_list(0, NULL);
|
||||||
|
// for (struct addrinfo *ai = res; ai; ai = ai->ai_next) {
|
||||||
|
// mp_obj_list_append(result, convert_addrinfo(ai, port));
|
||||||
|
// }
|
||||||
|
nlr_pop();
|
||||||
|
// lwip_freeaddrinfo(res);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
// lwip_freeaddrinfo(res);
|
||||||
|
nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val));
|
||||||
|
}
|
||||||
|
}
|
||||||
13
ports/zephyr-cp/common-hal/socketpool/SocketPool.h
Normal file
13
ports/zephyr-cp/common-hal/socketpool/SocketPool.h
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
} socketpool_socketpool_obj_t;
|
||||||
13
ports/zephyr-cp/common-hal/socketpool/__init__.c
Normal file
13
ports/zephyr-cp/common-hal/socketpool/__init__.c
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "shared-bindings/socketpool/__init__.h"
|
||||||
|
|
||||||
|
#include "common-hal/socketpool/Socket.h"
|
||||||
|
|
||||||
|
void socketpool_user_reset(void) {
|
||||||
|
socket_user_reset();
|
||||||
|
}
|
||||||
7
ports/zephyr-cp/common-hal/socketpool/__init__.h
Normal file
7
ports/zephyr-cp/common-hal/socketpool/__init__.h
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
146
ports/zephyr-cp/common-hal/wifi/Monitor.c
Normal file
146
ports/zephyr-cp/common-hal/wifi/Monitor.c
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2021 microDev
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "py/mpstate.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/wifi/Monitor.h"
|
||||||
|
#include "shared-bindings/wifi/Packet.h"
|
||||||
|
|
||||||
|
#define MONITOR_PAYLOAD_FCS_LEN (4)
|
||||||
|
#define MONITOR_QUEUE_TIMEOUT_TICK (0)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *payload;
|
||||||
|
unsigned channel;
|
||||||
|
uint32_t length;
|
||||||
|
signed rssi;
|
||||||
|
} monitor_packet_t;
|
||||||
|
|
||||||
|
// static void wifi_monitor_cb(void *recv_buf, wifi_promiscuous_pkt_type_t type) {
|
||||||
|
// wifi_promiscuous_pkt_t *pkt = (wifi_promiscuous_pkt_t *)recv_buf;
|
||||||
|
|
||||||
|
// // prepare packet
|
||||||
|
// monitor_packet_t packet = {
|
||||||
|
// .channel = pkt->rx_ctrl.channel,
|
||||||
|
// .length = pkt->rx_ctrl.sig_len,
|
||||||
|
// .rssi = pkt->rx_ctrl.rssi,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // for now, the monitor only dumps the length of the MISC type frame
|
||||||
|
// if (type != WIFI_PKT_MISC && !pkt->rx_ctrl.rx_state) {
|
||||||
|
// packet.length -= MONITOR_PAYLOAD_FCS_LEN;
|
||||||
|
// packet.payload = malloc(packet.length);
|
||||||
|
// if (packet.payload) {
|
||||||
|
// memcpy(packet.payload, pkt->payload, packet.length);
|
||||||
|
// wifi_monitor_obj_t *self = MP_STATE_VM(wifi_monitor_singleton);
|
||||||
|
// if (self->queue) {
|
||||||
|
// // send packet
|
||||||
|
// if (xQueueSendFromISR(self->queue, &packet, NULL) != pdTRUE) {
|
||||||
|
// self->lost++;
|
||||||
|
// free(packet.payload);
|
||||||
|
// ESP_LOGE(TAG, "packet queue full");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// ESP_LOGE(TAG, "not enough memory for packet");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
void common_hal_wifi_monitor_construct(wifi_monitor_obj_t *self, uint8_t channel, size_t queue) {
|
||||||
|
// mp_rom_error_text_t monitor_mode_init_error = MP_ERROR_TEXT("monitor init failed");
|
||||||
|
|
||||||
|
// self->queue = xQueueCreate(queue, sizeof(monitor_packet_t));
|
||||||
|
// if (!self->queue) {
|
||||||
|
// mp_raise_RuntimeError(monitor_mode_init_error);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // start wifi promicuous mode
|
||||||
|
// wifi_promiscuous_filter_t wifi_filter = {
|
||||||
|
// .filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT,
|
||||||
|
// };
|
||||||
|
// esp_wifi_set_promiscuous_filter(&wifi_filter);
|
||||||
|
// esp_wifi_set_promiscuous_rx_cb(wifi_monitor_cb);
|
||||||
|
// if (esp_wifi_set_promiscuous(true) != ESP_OK) {
|
||||||
|
// mp_raise_RuntimeError(monitor_mode_init_error);
|
||||||
|
// }
|
||||||
|
// esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
|
||||||
|
|
||||||
|
// self->channel = channel;
|
||||||
|
// self->queue_length = queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_wifi_monitor_deinited(void) {
|
||||||
|
// bool enabled;
|
||||||
|
// return (esp_wifi_get_promiscuous(&enabled) == ESP_ERR_WIFI_NOT_INIT) ? true : !enabled;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_monitor_deinit(wifi_monitor_obj_t *self) {
|
||||||
|
if (common_hal_wifi_monitor_deinited()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // disable wifi promiscuous mode
|
||||||
|
// esp_wifi_set_promiscuous(false);
|
||||||
|
|
||||||
|
// // make sure to free all resources in the left items
|
||||||
|
// UBaseType_t left_items = uxQueueMessagesWaiting(self->queue);
|
||||||
|
// monitor_packet_t packet;
|
||||||
|
// while (left_items--) {
|
||||||
|
// xQueueReceive(self->queue, &packet, MONITOR_QUEUE_TIMEOUT_TICK);
|
||||||
|
// free(packet.payload);
|
||||||
|
// }
|
||||||
|
// vQueueDelete(self->queue);
|
||||||
|
// self->queue = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_monitor_set_channel(wifi_monitor_obj_t *self, uint8_t channel) {
|
||||||
|
self->channel = channel;
|
||||||
|
// esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_monitor_get_channel(wifi_monitor_obj_t *self) {
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(self->channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_monitor_get_queue(wifi_monitor_obj_t *self) {
|
||||||
|
return mp_obj_new_int_from_uint(self->queue_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_monitor_get_lost(wifi_monitor_obj_t *self) {
|
||||||
|
size_t lost = self->lost;
|
||||||
|
self->lost = 0;
|
||||||
|
return mp_obj_new_int_from_uint(lost);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_monitor_get_queued(wifi_monitor_obj_t *self) {
|
||||||
|
return mp_obj_new_int_from_uint(0); // uxQueueMessagesWaiting(self->queue));
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_monitor_get_packet(wifi_monitor_obj_t *self) {
|
||||||
|
monitor_packet_t packet;
|
||||||
|
|
||||||
|
// if (xQueueReceive(self->queue, &packet, MONITOR_QUEUE_TIMEOUT_TICK) != pdTRUE) {
|
||||||
|
// return (mp_obj_t)&mp_const_empty_dict_obj;
|
||||||
|
// }
|
||||||
|
|
||||||
|
mp_obj_dict_t *dict = MP_OBJ_TO_PTR(mp_obj_new_dict(4));
|
||||||
|
|
||||||
|
mp_obj_dict_store(dict, cp_enum_find(&wifi_packet_type, PACKET_CH), MP_OBJ_NEW_SMALL_INT(packet.channel));
|
||||||
|
|
||||||
|
mp_obj_dict_store(dict, cp_enum_find(&wifi_packet_type, PACKET_LEN), MP_OBJ_NEW_SMALL_INT(packet.length));
|
||||||
|
|
||||||
|
mp_obj_dict_store(dict, cp_enum_find(&wifi_packet_type, PACKET_RAW), mp_obj_new_bytes(packet.payload, packet.length));
|
||||||
|
free(packet.payload);
|
||||||
|
|
||||||
|
mp_obj_dict_store(dict, cp_enum_find(&wifi_packet_type, PACKET_RSSI), MP_OBJ_NEW_SMALL_INT(packet.rssi));
|
||||||
|
|
||||||
|
return MP_OBJ_FROM_PTR(dict);
|
||||||
|
}
|
||||||
17
ports/zephyr-cp/common-hal/wifi/Monitor.h
Normal file
17
ports/zephyr-cp/common-hal/wifi/Monitor.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2021 microDev
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
uint8_t channel;
|
||||||
|
size_t lost;
|
||||||
|
size_t queue_length;
|
||||||
|
// QueueHandle_t queue;
|
||||||
|
} wifi_monitor_obj_t;
|
||||||
75
ports/zephyr-cp/common-hal/wifi/Network.c
Normal file
75
ports/zephyr-cp/common-hal/wifi/Network.c
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "shared-bindings/wifi/Network.h"
|
||||||
|
#include "shared-bindings/wifi/AuthMode.h"
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_network_get_ssid(wifi_network_obj_t *self) {
|
||||||
|
const char *cstr = (const char *)self->scan_result.ssid;
|
||||||
|
return mp_obj_new_str(cstr, self->scan_result.ssid_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_network_get_bssid(wifi_network_obj_t *self) {
|
||||||
|
return mp_obj_new_bytes(self->scan_result.mac, self->scan_result.mac_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_network_get_rssi(wifi_network_obj_t *self) {
|
||||||
|
return mp_obj_new_int(self->scan_result.rssi);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_network_get_channel(wifi_network_obj_t *self) {
|
||||||
|
return mp_obj_new_int(self->scan_result.channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_network_get_country(wifi_network_obj_t *self) {
|
||||||
|
// const char *cstr = (const char *)self->record.country.cc;
|
||||||
|
// 2 instead of strlen(cstr) as this gives us only the country-code
|
||||||
|
// return mp_obj_new_str(cstr, 2);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_network_get_authmode(wifi_network_obj_t *self) {
|
||||||
|
uint32_t authmode_mask = 0;
|
||||||
|
// switch (self->record.authmode) {
|
||||||
|
// case WIFI_AUTH_OPEN:
|
||||||
|
// authmode_mask = AUTHMODE_OPEN;
|
||||||
|
// break;
|
||||||
|
// case WIFI_AUTH_WEP:
|
||||||
|
// authmode_mask = AUTHMODE_WEP;
|
||||||
|
// break;
|
||||||
|
// case WIFI_AUTH_WPA_PSK:
|
||||||
|
// authmode_mask = AUTHMODE_WPA | AUTHMODE_PSK;
|
||||||
|
// break;
|
||||||
|
// case WIFI_AUTH_WPA2_PSK:
|
||||||
|
// authmode_mask = AUTHMODE_WPA2 | AUTHMODE_PSK;
|
||||||
|
// break;
|
||||||
|
// case WIFI_AUTH_WPA_WPA2_PSK:
|
||||||
|
// authmode_mask = AUTHMODE_WPA | AUTHMODE_WPA2 | AUTHMODE_PSK;
|
||||||
|
// break;
|
||||||
|
// case WIFI_AUTH_WPA2_ENTERPRISE:
|
||||||
|
// authmode_mask = AUTHMODE_WPA2 | AUTHMODE_ENTERPRISE;
|
||||||
|
// break;
|
||||||
|
// case WIFI_AUTH_WPA3_PSK:
|
||||||
|
// authmode_mask = AUTHMODE_WPA3 | AUTHMODE_PSK;
|
||||||
|
// break;
|
||||||
|
// case WIFI_AUTH_WPA2_WPA3_PSK:
|
||||||
|
// authmode_mask = AUTHMODE_WPA2 | AUTHMODE_WPA3 | AUTHMODE_PSK;
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
mp_obj_t authmode_list = mp_obj_new_list(0, NULL);
|
||||||
|
if (authmode_mask != 0) {
|
||||||
|
for (uint8_t i = 0; i < 32; i++) {
|
||||||
|
if ((authmode_mask >> i) & 1) {
|
||||||
|
mp_obj_list_append(authmode_list, cp_enum_find(&wifi_authmode_type, 1 << i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return authmode_list;
|
||||||
|
}
|
||||||
16
ports/zephyr-cp/common-hal/wifi/Network.h
Normal file
16
ports/zephyr-cp/common-hal/wifi/Network.h
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
#include <zephyr/net/wifi_mgmt.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
struct wifi_scan_result scan_result;
|
||||||
|
} wifi_network_obj_t;
|
||||||
740
ports/zephyr-cp/common-hal/wifi/Radio.c
Normal file
740
ports/zephyr-cp/common-hal/wifi/Radio.c
Normal file
|
|
@ -0,0 +1,740 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "shared-bindings/wifi/Radio.h"
|
||||||
|
#include "ports/zephyr-cp/common-hal/wifi/ScannedNetworks.h"
|
||||||
|
#include "shared-bindings/wifi/Network.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "common-hal/wifi/__init__.h"
|
||||||
|
#include "shared/runtime/interrupt_char.h"
|
||||||
|
#include "py/gc.h"
|
||||||
|
#include "py/obj.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "shared-bindings/ipaddress/IPv4Address.h"
|
||||||
|
#include "shared-bindings/wifi/ScannedNetworks.h"
|
||||||
|
#include "shared-bindings/wifi/AuthMode.h"
|
||||||
|
#include "shared-bindings/time/__init__.h"
|
||||||
|
#include "shared-module/ipaddress/__init__.h"
|
||||||
|
#include "common-hal/socketpool/__init__.h"
|
||||||
|
|
||||||
|
#include "bindings/zephyr_kernel/__init__.h"
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/net/hostname.h>
|
||||||
|
#include <zephyr/net/wifi.h>
|
||||||
|
#include <zephyr/net/wifi_mgmt.h>
|
||||||
|
|
||||||
|
#if CIRCUITPY_MDNS
|
||||||
|
#include "common-hal/mdns/Server.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAC_ADDRESS_LENGTH 6
|
||||||
|
|
||||||
|
// static void set_mode_station(wifi_radio_obj_t *self, bool state) {
|
||||||
|
// wifi_mode_t next_mode;
|
||||||
|
// if (state) {
|
||||||
|
// if (self->ap_mode) {
|
||||||
|
// next_mode = WIFI_MODE_APSTA;
|
||||||
|
// } else {
|
||||||
|
// next_mode = WIFI_MODE_STA;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// if (self->ap_mode) {
|
||||||
|
// next_mode = WIFI_MODE_AP;
|
||||||
|
// } else {
|
||||||
|
// next_mode = WIFI_MODE_NULL;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// esp_wifi_set_mode(next_mode);
|
||||||
|
// self->sta_mode = state;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static void set_mode_ap(wifi_radio_obj_t *self, bool state) {
|
||||||
|
// wifi_mode_t next_mode;
|
||||||
|
// if (state) {
|
||||||
|
// if (self->sta_mode) {
|
||||||
|
// next_mode = WIFI_MODE_APSTA;
|
||||||
|
// } else {
|
||||||
|
// next_mode = WIFI_MODE_AP;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// if (self->sta_mode) {
|
||||||
|
// next_mode = WIFI_MODE_STA;
|
||||||
|
// } else {
|
||||||
|
// next_mode = WIFI_MODE_NULL;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// esp_wifi_set_mode(next_mode);
|
||||||
|
// self->ap_mode = state;
|
||||||
|
// }
|
||||||
|
|
||||||
|
bool common_hal_wifi_radio_get_enabled(wifi_radio_obj_t *self) {
|
||||||
|
return self->started;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_set_enabled(wifi_radio_obj_t *self, bool enabled) {
|
||||||
|
if (self->started && !enabled) {
|
||||||
|
if (self->current_scan != NULL) {
|
||||||
|
common_hal_wifi_radio_stop_scanning_networks(self);
|
||||||
|
}
|
||||||
|
// #if CIRCUITPY_MDNS
|
||||||
|
// mdns_server_deinit_singleton();
|
||||||
|
// #endif
|
||||||
|
printk("net_if_down\n");
|
||||||
|
CHECK_ZEPHYR_RESULT(net_if_down(self->sta_netif));
|
||||||
|
self->started = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!self->started && enabled) {
|
||||||
|
printk("net_if_up\n");
|
||||||
|
CHECK_ZEPHYR_RESULT(net_if_up(self->sta_netif));
|
||||||
|
self->started = true;
|
||||||
|
self->current_scan = NULL;
|
||||||
|
// common_hal_wifi_radio_set_tx_power(self, CIRCUITPY_WIFI_DEFAULT_TX_POWER);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_hostname(wifi_radio_obj_t *self) {
|
||||||
|
const char *hostname = net_hostname_get();
|
||||||
|
return mp_obj_new_str(hostname, strlen(hostname));
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_set_hostname(wifi_radio_obj_t *self, const char *hostname) {
|
||||||
|
if (net_hostname_set((char *)hostname, strlen(hostname)) != 0) {
|
||||||
|
mp_raise_RuntimeError(MP_ERROR_TEXT("Failed to set hostname"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_mac_address(wifi_radio_obj_t *self) {
|
||||||
|
uint8_t mac[MAC_ADDRESS_LENGTH];
|
||||||
|
// esp_wifi_get_mac(ESP_IF_WIFI_STA, mac);
|
||||||
|
return mp_obj_new_bytes(mac, MAC_ADDRESS_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_set_mac_address(wifi_radio_obj_t *self, const uint8_t *mac) {
|
||||||
|
if (!self->sta_mode) {
|
||||||
|
mp_raise_RuntimeError(MP_ERROR_TEXT("Interface must be started"));
|
||||||
|
}
|
||||||
|
if ((mac[0] & 0b1) == 0b1) {
|
||||||
|
mp_raise_RuntimeError(MP_ERROR_TEXT("Invalid multicast MAC address"));
|
||||||
|
}
|
||||||
|
// esp_wifi_set_mac(ESP_IF_WIFI_STA, mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_float_t common_hal_wifi_radio_get_tx_power(wifi_radio_obj_t *self) {
|
||||||
|
int8_t tx_power = 0;
|
||||||
|
// esp_wifi_get_max_tx_power(&tx_power);
|
||||||
|
return tx_power / 4.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_set_tx_power(wifi_radio_obj_t *self, const mp_float_t tx_power) {
|
||||||
|
// esp_wifi_set_max_tx_power(tx_power * 4.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_int_t common_hal_wifi_radio_get_listen_interval(wifi_radio_obj_t *self) {
|
||||||
|
// wifi_config_t *config = &self->sta_config;
|
||||||
|
// return config->sta.listen_interval;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_set_listen_interval(wifi_radio_obj_t *self, const mp_int_t listen_interval) {
|
||||||
|
// wifi_config_t *config = &self->sta_config;
|
||||||
|
// config->sta.listen_interval = listen_interval;
|
||||||
|
// if (listen_interval == 1) {
|
||||||
|
// esp_wifi_set_ps(WIFI_PS_MIN_MODEM);
|
||||||
|
// } else if (listen_interval > 1) {
|
||||||
|
// esp_wifi_set_ps(WIFI_PS_MAX_MODEM);
|
||||||
|
// } else {
|
||||||
|
// esp_wifi_set_ps(WIFI_PS_NONE);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// esp_wifi_set_config(ESP_IF_WIFI_STA, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_mac_address_ap(wifi_radio_obj_t *self) {
|
||||||
|
uint8_t mac[MAC_ADDRESS_LENGTH];
|
||||||
|
// esp_wifi_get_mac(ESP_IF_WIFI_AP, mac);
|
||||||
|
return mp_obj_new_bytes(mac, MAC_ADDRESS_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_set_mac_address_ap(wifi_radio_obj_t *self, const uint8_t *mac) {
|
||||||
|
if (!self->ap_mode) {
|
||||||
|
mp_raise_RuntimeError(MP_ERROR_TEXT("Interface must be started"));
|
||||||
|
}
|
||||||
|
if ((mac[0] & 0b1) == 0b1) {
|
||||||
|
mp_raise_RuntimeError(MP_ERROR_TEXT("Invalid multicast MAC address"));
|
||||||
|
}
|
||||||
|
// esp_wifi_set_mac(ESP_IF_WIFI_AP, mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_start_scanning_networks(wifi_radio_obj_t *self, uint8_t start_channel, uint8_t stop_channel) {
|
||||||
|
printk("common_hal_wifi_radio_start_scanning_networks\n");
|
||||||
|
if (self->current_scan != NULL) {
|
||||||
|
printk("Already scanning for wifi networks\n");
|
||||||
|
mp_raise_RuntimeError(MP_ERROR_TEXT("Already scanning for wifi networks"));
|
||||||
|
}
|
||||||
|
if (!common_hal_wifi_radio_get_enabled(self)) {
|
||||||
|
printk("wifi is not enabled\n");
|
||||||
|
mp_raise_RuntimeError(MP_ERROR_TEXT("wifi is not enabled"));
|
||||||
|
}
|
||||||
|
|
||||||
|
wifi_scannednetworks_obj_t *scan = mp_obj_malloc(wifi_scannednetworks_obj_t, &wifi_scannednetworks_type);
|
||||||
|
self->current_scan = scan;
|
||||||
|
scan->current_channel_index = 0;
|
||||||
|
scan->start_channel = start_channel;
|
||||||
|
scan->end_channel = stop_channel;
|
||||||
|
scan->done = false;
|
||||||
|
scan->channel_scan_in_progress = false;
|
||||||
|
scan->netif = self->sta_netif;
|
||||||
|
|
||||||
|
k_msgq_init(&scan->msgq, scan->msgq_buffer, sizeof(struct wifi_scan_result), MAX_BUFFERED_SCAN_RESULTS);
|
||||||
|
k_fifo_init(&scan->fifo);
|
||||||
|
|
||||||
|
k_poll_event_init(&scan->events[0],
|
||||||
|
K_POLL_TYPE_SEM_AVAILABLE,
|
||||||
|
K_POLL_MODE_NOTIFY_ONLY,
|
||||||
|
&mp_interrupt_sem);
|
||||||
|
|
||||||
|
k_poll_event_init(&scan->events[1],
|
||||||
|
K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
|
||||||
|
K_POLL_MODE_NOTIFY_ONLY,
|
||||||
|
&scan->msgq);
|
||||||
|
wifi_scannednetworks_scan_next_channel(scan);
|
||||||
|
printk("common_hal_wifi_radio_start_scanning_networks done %p\n", scan);
|
||||||
|
return scan;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_stop_scanning_networks(wifi_radio_obj_t *self) {
|
||||||
|
printk("common_hal_wifi_radio_stop_scanning_networks\n");
|
||||||
|
// Return early if self->current_scan is NULL to avoid hang
|
||||||
|
if (self->current_scan == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Free the memory used to store the found aps.
|
||||||
|
wifi_scannednetworks_deinit(self->current_scan);
|
||||||
|
self->current_scan = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_start_station(wifi_radio_obj_t *self) {
|
||||||
|
// set_mode_station(self, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_stop_station(wifi_radio_obj_t *self) {
|
||||||
|
// set_mode_station(self, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_start_ap(wifi_radio_obj_t *self, uint8_t *ssid, size_t ssid_len, uint8_t *password, size_t password_len, uint8_t channel, uint32_t authmode, uint8_t max_connections) {
|
||||||
|
// set_mode_ap(self, true);
|
||||||
|
|
||||||
|
// uint8_t esp_authmode = 0;
|
||||||
|
// switch (authmode) {
|
||||||
|
// case AUTHMODE_OPEN:
|
||||||
|
// esp_authmode = WIFI_AUTH_OPEN;
|
||||||
|
// break;
|
||||||
|
// case AUTHMODE_WPA | AUTHMODE_PSK:
|
||||||
|
// esp_authmode = WIFI_AUTH_WPA_PSK;
|
||||||
|
// break;
|
||||||
|
// case AUTHMODE_WPA2 | AUTHMODE_PSK:
|
||||||
|
// esp_authmode = WIFI_AUTH_WPA2_PSK;
|
||||||
|
// break;
|
||||||
|
// case AUTHMODE_WPA | AUTHMODE_WPA2 | AUTHMODE_PSK:
|
||||||
|
// esp_authmode = WIFI_AUTH_WPA_WPA2_PSK;
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// mp_arg_error_invalid(MP_QSTR_authmode);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// wifi_config_t *config = &self->ap_config;
|
||||||
|
// memcpy(&config->ap.ssid, ssid, ssid_len);
|
||||||
|
// config->ap.ssid[ssid_len] = 0;
|
||||||
|
// memcpy(&config->ap.password, password, password_len);
|
||||||
|
// config->ap.password[password_len] = 0;
|
||||||
|
// config->ap.channel = channel;
|
||||||
|
// config->ap.authmode = esp_authmode;
|
||||||
|
|
||||||
|
// mp_arg_validate_int_range(max_connections, 0, 10, MP_QSTR_max_connections);
|
||||||
|
|
||||||
|
// config->ap.max_connection = max_connections;
|
||||||
|
|
||||||
|
// esp_wifi_set_config(WIFI_IF_AP, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_wifi_radio_get_ap_active(wifi_radio_obj_t *self) {
|
||||||
|
// return self->ap_mode && esp_netif_is_netif_up(self->ap_netif);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self) {
|
||||||
|
// set_mode_ap(self, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_stations_ap(wifi_radio_obj_t *self) {
|
||||||
|
// wifi_sta_list_t esp_sta_list;
|
||||||
|
// esp_err_t result;
|
||||||
|
|
||||||
|
// result = esp_wifi_ap_get_sta_list(&esp_sta_list);
|
||||||
|
// if (result != ESP_OK) {
|
||||||
|
// return mp_const_none;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// esp_netif_pair_mac_ip_t mac_ip_pair[esp_sta_list.num];
|
||||||
|
// for (int i = 0; i < esp_sta_list.num; i++) {
|
||||||
|
// memcpy(mac_ip_pair[i].mac, esp_sta_list.sta[i].mac, MAC_ADDRESS_LENGTH);
|
||||||
|
// mac_ip_pair[i].ip.addr = 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// result = esp_netif_dhcps_get_clients_by_mac(self->ap_netif, esp_sta_list.num, mac_ip_pair);
|
||||||
|
// if (result != ESP_OK) {
|
||||||
|
// return mp_const_none;
|
||||||
|
// }
|
||||||
|
|
||||||
|
mp_obj_t mp_sta_list = mp_obj_new_list(0, NULL);
|
||||||
|
// for (int i = 0; i < esp_sta_list.num; i++) {
|
||||||
|
// mp_obj_t elems[3] = {
|
||||||
|
// mp_obj_new_bytes(esp_sta_list.sta[i].mac, MAC_ADDRESS_LENGTH),
|
||||||
|
// MP_OBJ_NEW_SMALL_INT(esp_sta_list.sta[i].rssi),
|
||||||
|
// mp_const_none
|
||||||
|
// };
|
||||||
|
|
||||||
|
// if (mac_ip_pair[i].ip.addr) {
|
||||||
|
// elems[2] = common_hal_ipaddress_new_ipv4address(mac_ip_pair[i].ip.addr);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// mp_obj_list_append(mp_sta_list, namedtuple_make_new((const mp_obj_type_t *)&wifi_radio_station_type, 3, 0, elems));
|
||||||
|
// }
|
||||||
|
|
||||||
|
return mp_sta_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t *ssid, size_t ssid_len, uint8_t *password, size_t password_len, uint8_t channel, mp_float_t timeout, uint8_t *bssid, size_t bssid_len) {
|
||||||
|
if (!common_hal_wifi_radio_get_enabled(self)) {
|
||||||
|
mp_raise_RuntimeError(MP_ERROR_TEXT("wifi is not enabled"));
|
||||||
|
}
|
||||||
|
// wifi_config_t *config = &self->sta_config;
|
||||||
|
|
||||||
|
// size_t timeout_ms = timeout * 1000;
|
||||||
|
// uint32_t start_time = common_hal_time_monotonic_ms();
|
||||||
|
// uint32_t end_time = start_time + timeout_ms;
|
||||||
|
|
||||||
|
// EventBits_t bits;
|
||||||
|
// // can't block since both bits are false after wifi_init
|
||||||
|
// // both bits are true after an existing connection stops
|
||||||
|
// bits = xEventGroupWaitBits(self->event_group_handle,
|
||||||
|
// WIFI_CONNECTED_BIT | WIFI_DISCONNECTED_BIT,
|
||||||
|
// pdTRUE,
|
||||||
|
// pdTRUE,
|
||||||
|
// 0);
|
||||||
|
// bool connected = ((bits & WIFI_CONNECTED_BIT) != 0) &&
|
||||||
|
// !((bits & WIFI_DISCONNECTED_BIT) != 0);
|
||||||
|
// if (connected) {
|
||||||
|
// // SSIDs are up to 32 bytes. Assume it is null terminated if it is less.
|
||||||
|
// if (memcmp(ssid, config->sta.ssid, ssid_len) == 0 &&
|
||||||
|
// (ssid_len == 32 || strlen((const char *)config->sta.ssid) == ssid_len)) {
|
||||||
|
// // Already connected to the desired network.
|
||||||
|
// return WIFI_RADIO_ERROR_NONE;
|
||||||
|
// } else {
|
||||||
|
// xEventGroupClearBits(self->event_group_handle, WIFI_DISCONNECTED_BIT);
|
||||||
|
// // Trying to switch networks so disconnect first.
|
||||||
|
// esp_wifi_disconnect();
|
||||||
|
// do {
|
||||||
|
// RUN_BACKGROUND_TASKS;
|
||||||
|
// bits = xEventGroupWaitBits(self->event_group_handle,
|
||||||
|
// WIFI_DISCONNECTED_BIT,
|
||||||
|
// pdTRUE,
|
||||||
|
// pdTRUE,
|
||||||
|
// 0);
|
||||||
|
// } while ((bits & WIFI_DISCONNECTED_BIT) == 0 && !mp_hal_is_interrupted());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // explicitly clear bits since xEventGroupWaitBits may have timed out
|
||||||
|
// xEventGroupClearBits(self->event_group_handle, WIFI_CONNECTED_BIT);
|
||||||
|
// xEventGroupClearBits(self->event_group_handle, WIFI_DISCONNECTED_BIT);
|
||||||
|
// set_mode_station(self, true);
|
||||||
|
|
||||||
|
// memcpy(&config->sta.ssid, ssid, ssid_len);
|
||||||
|
// if (ssid_len < 32) {
|
||||||
|
// config->sta.ssid[ssid_len] = 0;
|
||||||
|
// }
|
||||||
|
// memcpy(&config->sta.password, password, password_len);
|
||||||
|
// config->sta.password[password_len] = 0;
|
||||||
|
// config->sta.channel = channel;
|
||||||
|
// // From esp_wifi_types.h:
|
||||||
|
// // Generally, station_config.bssid_set needs to be 0; and it needs
|
||||||
|
// // to be 1 only when users need to check the MAC address of the AP
|
||||||
|
// if (bssid_len > 0) {
|
||||||
|
// memcpy(&config->sta.bssid, bssid, bssid_len);
|
||||||
|
// config->sta.bssid[bssid_len] = 0;
|
||||||
|
// config->sta.bssid_set = true;
|
||||||
|
// } else {
|
||||||
|
// config->sta.bssid_set = false;
|
||||||
|
// }
|
||||||
|
// // If channel is 0 (default/unset) and BSSID is not given, do a full scan instead of fast scan
|
||||||
|
// // This will ensure that the best AP in range is chosen automatically
|
||||||
|
// if ((config->sta.bssid_set == 0) && (config->sta.channel == 0)) {
|
||||||
|
// config->sta.scan_method = WIFI_ALL_CHANNEL_SCAN;
|
||||||
|
// } else {
|
||||||
|
// config->sta.scan_method = WIFI_FAST_SCAN;
|
||||||
|
// }
|
||||||
|
// esp_wifi_set_config(ESP_IF_WIFI_STA, config);
|
||||||
|
// self->starting_retries = 5;
|
||||||
|
// self->retries_left = 5;
|
||||||
|
// esp_wifi_connect();
|
||||||
|
|
||||||
|
// do {
|
||||||
|
// RUN_BACKGROUND_TASKS;
|
||||||
|
// bits = xEventGroupWaitBits(self->event_group_handle,
|
||||||
|
// WIFI_CONNECTED_BIT | WIFI_DISCONNECTED_BIT,
|
||||||
|
// pdTRUE,
|
||||||
|
// pdTRUE,
|
||||||
|
// 0);
|
||||||
|
// // Don't retry anymore if we're over our time budget.
|
||||||
|
// if (self->retries_left > 0 && common_hal_time_monotonic_ms() > end_time) {
|
||||||
|
// self->retries_left = 0;
|
||||||
|
// }
|
||||||
|
// } while ((bits & (WIFI_CONNECTED_BIT | WIFI_DISCONNECTED_BIT)) == 0 && !mp_hal_is_interrupted());
|
||||||
|
|
||||||
|
// if ((bits & WIFI_DISCONNECTED_BIT) != 0) {
|
||||||
|
// if (
|
||||||
|
// (self->last_disconnect_reason == WIFI_REASON_AUTH_FAIL) ||
|
||||||
|
// (self->last_disconnect_reason == WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT) ||
|
||||||
|
// (self->last_disconnect_reason == WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY) ||
|
||||||
|
// (self->last_disconnect_reason == WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD)
|
||||||
|
// ) {
|
||||||
|
// return WIFI_RADIO_ERROR_AUTH_FAIL;
|
||||||
|
// } else if (self->last_disconnect_reason == WIFI_REASON_NO_AP_FOUND) {
|
||||||
|
// return WIFI_RADIO_ERROR_NO_AP_FOUND;
|
||||||
|
// }
|
||||||
|
// return self->last_disconnect_reason;
|
||||||
|
// } else {
|
||||||
|
// // We're connected, allow us to retry if we get disconnected.
|
||||||
|
// self->retries_left = self->starting_retries;
|
||||||
|
// }
|
||||||
|
return WIFI_RADIO_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_wifi_radio_get_connected(wifi_radio_obj_t *self) {
|
||||||
|
// return self->sta_mode && esp_netif_is_netif_up(self->netif);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_ap_info(wifi_radio_obj_t *self) {
|
||||||
|
// if (!esp_netif_is_netif_up(self->netif)) {
|
||||||
|
return mp_const_none;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Make sure the interface is in STA mode
|
||||||
|
// if (!self->sta_mode) {
|
||||||
|
// return mp_const_none;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// wifi_network_obj_t *ap_info = mp_obj_malloc(wifi_network_obj_t, &wifi_network_type);
|
||||||
|
// // From esp_wifi.h, the possible return values (typos theirs):
|
||||||
|
// // ESP_OK: succeed
|
||||||
|
// // ESP_ERR_WIFI_CONN: The station interface don't initialized
|
||||||
|
// // ESP_ERR_WIFI_NOT_CONNECT: The station is in disconnect status
|
||||||
|
// if (esp_wifi_sta_get_ap_info(&self->ap_info.record) != ESP_OK) {
|
||||||
|
// return mp_const_none;
|
||||||
|
// } else {
|
||||||
|
// if (strlen(self->ap_info.record.country.cc) == 0) {
|
||||||
|
// // Workaround to fill country related information in ap_info until ESP-IDF carries a fix
|
||||||
|
// // esp_wifi_sta_get_ap_info does not appear to fill wifi_country_t (e.g. country.cc) details
|
||||||
|
// // (IDFGH-4437) #6267
|
||||||
|
// // Note: It is possible that Wi-Fi APs don't have a CC set, then even after this workaround
|
||||||
|
// // the element would remain empty.
|
||||||
|
// memset(&self->ap_info.record.country, 0, sizeof(wifi_country_t));
|
||||||
|
// if (esp_wifi_get_country(&self->ap_info.record.country) != ESP_OK) {
|
||||||
|
// return mp_const_none;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// memcpy(&ap_info->record, &self->ap_info.record, sizeof(wifi_ap_record_t));
|
||||||
|
// return MP_OBJ_FROM_PTR(ap_info);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_ipv4_gateway(wifi_radio_obj_t *self) {
|
||||||
|
// if (!esp_netif_is_netif_up(self->netif)) {
|
||||||
|
return mp_const_none;
|
||||||
|
// }
|
||||||
|
// esp_netif_get_ip_info(self->netif, &self->ip_info);
|
||||||
|
// return common_hal_ipaddress_new_ipv4address(self->ip_info.gw.addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_ipv4_gateway_ap(wifi_radio_obj_t *self) {
|
||||||
|
// if (!esp_netif_is_netif_up(self->ap_netif)) {
|
||||||
|
return mp_const_none;
|
||||||
|
// }
|
||||||
|
// esp_netif_get_ip_info(self->ap_netif, &self->ap_ip_info);
|
||||||
|
// return common_hal_ipaddress_new_ipv4address(self->ap_ip_info.gw.addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_ipv4_subnet(wifi_radio_obj_t *self) {
|
||||||
|
// if (!esp_netif_is_netif_up(self->netif)) {
|
||||||
|
return mp_const_none;
|
||||||
|
// }
|
||||||
|
// esp_netif_get_ip_info(self->netif, &self->ip_info);
|
||||||
|
// return common_hal_ipaddress_new_ipv4address(self->ip_info.netmask.addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_ipv4_subnet_ap(wifi_radio_obj_t *self) {
|
||||||
|
// if (!esp_netif_is_netif_up(self->ap_netif)) {
|
||||||
|
return mp_const_none;
|
||||||
|
// }
|
||||||
|
// esp_netif_get_ip_info(self->ap_netif, &self->ap_ip_info);
|
||||||
|
// return common_hal_ipaddress_new_ipv4address(self->ap_ip_info.netmask.addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static mp_obj_t common_hal_wifi_radio_get_addresses_netif(wifi_radio_obj_t *self, esp_netif_t *netif) {
|
||||||
|
// if (!esp_netif_is_netif_up(netif)) {
|
||||||
|
// return mp_const_empty_tuple;
|
||||||
|
// }
|
||||||
|
// esp_netif_ip_info_t ip_info;
|
||||||
|
// esp_netif_get_ip_info(netif, &ip_info);
|
||||||
|
// int n_addresses4 = ip_info.ip.addr != INADDR_NONE;
|
||||||
|
|
||||||
|
// #if CIRCUITPY_SOCKETPOOL_IPV6
|
||||||
|
// esp_ip6_addr_t addresses[LWIP_IPV6_NUM_ADDRESSES];
|
||||||
|
// int n_addresses6 = esp_netif_get_all_ip6(netif, &addresses[0]);
|
||||||
|
// #else
|
||||||
|
// int n_addresses6 = 0;
|
||||||
|
// #endif
|
||||||
|
// int n_addresses = n_addresses4 + n_addresses6;
|
||||||
|
// mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_addresses, NULL));
|
||||||
|
|
||||||
|
// #if CIRCUITPY_SOCKETPOOL_IPV6
|
||||||
|
// for (int i = 0; i < n_addresses6; i++) {
|
||||||
|
// result->items[i] = espaddr6_to_str(&addresses[i]);
|
||||||
|
// }
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// if (n_addresses4) {
|
||||||
|
// result->items[n_addresses6] = espaddr4_to_str(&ip_info.ip);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return MP_OBJ_FROM_PTR(result);
|
||||||
|
// return mp_const_empty_tuple;
|
||||||
|
// }
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_addresses(wifi_radio_obj_t *self) {
|
||||||
|
// return common_hal_wifi_radio_get_addresses_netif(self, self->netif);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_addresses_ap(wifi_radio_obj_t *self) {
|
||||||
|
// return common_hal_wifi_radio_get_addresses_netif(self, self->ap_netif);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t wifi_radio_get_ipv4_address(wifi_radio_obj_t *self) {
|
||||||
|
// if (!esp_netif_is_netif_up(self->netif)) {
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
// esp_netif_get_ip_info(self->netif, &self->ip_info);
|
||||||
|
// return self->ip_info.ip.addr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_ipv4_address(wifi_radio_obj_t *self) {
|
||||||
|
// if (!esp_netif_is_netif_up(self->netif)) {
|
||||||
|
// return mp_const_none;
|
||||||
|
// }
|
||||||
|
// esp_netif_get_ip_info(self->netif, &self->ip_info);
|
||||||
|
// return common_hal_ipaddress_new_ipv4address(self->ip_info.ip.addr);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_ipv4_address_ap(wifi_radio_obj_t *self) {
|
||||||
|
// if (!esp_netif_is_netif_up(self->ap_netif)) {
|
||||||
|
// return mp_const_none;
|
||||||
|
// }
|
||||||
|
// esp_netif_get_ip_info(self->ap_netif, &self->ap_ip_info);
|
||||||
|
// return common_hal_ipaddress_new_ipv4address(self->ap_ip_info.ip.addr);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_ipv4_dns(wifi_radio_obj_t *self) {
|
||||||
|
// if (!esp_netif_is_netif_up(self->netif)) {
|
||||||
|
// return mp_const_none;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// esp_netif_get_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &self->dns_info);
|
||||||
|
|
||||||
|
// if (self->dns_info.ip.type != ESP_IPADDR_TYPE_V4) {
|
||||||
|
// return mp_const_none;
|
||||||
|
// }
|
||||||
|
// // dns_info is of type esp_netif_dns_info_t, which is just ever so slightly
|
||||||
|
// // different than esp_netif_ip_info_t used for
|
||||||
|
// // common_hal_wifi_radio_get_ipv4_address (includes both ipv4 and 6),
|
||||||
|
// // so some extra jumping is required to get to the actual address
|
||||||
|
// return common_hal_ipaddress_new_ipv4address(self->dns_info.ip.u_addr.ip4.addr);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_set_ipv4_dns(wifi_radio_obj_t *self, mp_obj_t ipv4_dns_addr) {
|
||||||
|
// esp_netif_dns_info_t dns_addr;
|
||||||
|
// ipaddress_ipaddress_to_esp_idf_ip4(ipv4_dns_addr, &dns_addr.ip.u_addr.ip4);
|
||||||
|
// esp_netif_set_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &dns_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self, bool ipv4, bool ipv6) {
|
||||||
|
// if (ipv4) {
|
||||||
|
// esp_netif_dhcpc_start(self->netif);
|
||||||
|
// } else {
|
||||||
|
// esp_netif_dhcpc_stop(self->netif);
|
||||||
|
// }
|
||||||
|
// #if LWIP_IPV6_DHCP6
|
||||||
|
// if (ipv6) {
|
||||||
|
// esp_netif_create_ip6_linklocal(self->netif);
|
||||||
|
// dhcp6_enable_stateless(esp_netif_get_netif_impl(self->netif));
|
||||||
|
// } else {
|
||||||
|
// dhcp6_disable(esp_netif_get_netif_impl(self->netif));
|
||||||
|
// }
|
||||||
|
// #else
|
||||||
|
// if (ipv6) {
|
||||||
|
// mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_ipv6);
|
||||||
|
// }
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_stop_dhcp_client(wifi_radio_obj_t *self) {
|
||||||
|
// esp_netif_dhcpc_stop(self->netif);
|
||||||
|
// #if LWIP_IPV6_DHCP6
|
||||||
|
// dhcp6_disable(esp_netif_get_netif_impl(self->netif));
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_start_dhcp_server(wifi_radio_obj_t *self) {
|
||||||
|
// esp_netif_dhcps_start(self->ap_netif);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_stop_dhcp_server(wifi_radio_obj_t *self) {
|
||||||
|
// esp_netif_dhcps_stop(self->ap_netif);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_set_ipv4_address(wifi_radio_obj_t *self, mp_obj_t ipv4, mp_obj_t netmask, mp_obj_t gateway, mp_obj_t ipv4_dns) {
|
||||||
|
// common_hal_wifi_radio_stop_dhcp_client(self); // Must stop station DHCP to set a manual address
|
||||||
|
|
||||||
|
// esp_netif_ip_info_t ip_info;
|
||||||
|
// ipaddress_ipaddress_to_esp_idf_ip4(ipv4, &ip_info.ip);
|
||||||
|
// ipaddress_ipaddress_to_esp_idf_ip4(netmask, &ip_info.netmask);
|
||||||
|
// ipaddress_ipaddress_to_esp_idf_ip4(gateway, &ip_info.gw);
|
||||||
|
|
||||||
|
// esp_netif_set_ip_info(self->netif, &ip_info);
|
||||||
|
|
||||||
|
// if (ipv4_dns != MP_OBJ_NULL) {
|
||||||
|
// common_hal_wifi_radio_set_ipv4_dns(self, ipv4_dns);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_set_ipv4_address_ap(wifi_radio_obj_t *self, mp_obj_t ipv4, mp_obj_t netmask, mp_obj_t gateway) {
|
||||||
|
// common_hal_wifi_radio_stop_dhcp_server(self); // Must stop access point DHCP to set a manual address
|
||||||
|
|
||||||
|
// esp_netif_ip_info_t ip_info;
|
||||||
|
// ipaddress_ipaddress_to_esp_idf_ip4(ipv4, &ip_info.ip);
|
||||||
|
// ipaddress_ipaddress_to_esp_idf_ip4(netmask, &ip_info.netmask);
|
||||||
|
// ipaddress_ipaddress_to_esp_idf_ip4(gateway, &ip_info.gw);
|
||||||
|
|
||||||
|
// esp_netif_set_ip_info(self->ap_netif, &ip_info);
|
||||||
|
|
||||||
|
// common_hal_wifi_radio_start_dhcp_server(self); // restart access point DHCP
|
||||||
|
}
|
||||||
|
|
||||||
|
// static void ping_success_cb(esp_ping_handle_t hdl, void *args) {
|
||||||
|
// wifi_radio_obj_t *self = (wifi_radio_obj_t *)args;
|
||||||
|
// esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &self->ping_elapsed_time, sizeof(self->ping_elapsed_time));
|
||||||
|
// }
|
||||||
|
|
||||||
|
mp_int_t common_hal_wifi_radio_ping(wifi_radio_obj_t *self, mp_obj_t ip_address, mp_float_t timeout) {
|
||||||
|
// esp_ping_config_t ping_config = ESP_PING_DEFAULT_CONFIG();
|
||||||
|
// ipaddress_ipaddress_to_esp_idf(ip_address, &ping_config.target_addr);
|
||||||
|
// ping_config.count = 1;
|
||||||
|
|
||||||
|
// // We must fetch ping information using the callback mechanism, because the session storage is freed when
|
||||||
|
// // the ping session is done, even before esp_ping_delete_session().
|
||||||
|
// esp_ping_callbacks_t ping_callbacks = {
|
||||||
|
// .on_ping_success = ping_success_cb,
|
||||||
|
// .cb_args = (void *)self,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// size_t timeout_ms = timeout * 1000;
|
||||||
|
|
||||||
|
// // ESP-IDF creates a task to do the ping session. It shuts down when done, but only after a one second delay.
|
||||||
|
// // Calling common_hal_wifi_radio_ping() too fast will cause resource exhaustion.
|
||||||
|
// esp_ping_handle_t ping;
|
||||||
|
// if (esp_ping_new_session(&ping_config, &ping_callbacks, &ping) != ESP_OK) {
|
||||||
|
// // Wait for old task to go away and then try again.
|
||||||
|
// // Empirical testing shows we have to wait at least two seconds, despite the task
|
||||||
|
// // having a one-second timeout.
|
||||||
|
// common_hal_time_delay_ms(2000);
|
||||||
|
// // Return if interrupted now, to show the interruption as KeyboardInterrupt instead of the
|
||||||
|
// // IDF error.
|
||||||
|
// if (mp_hal_is_interrupted()) {
|
||||||
|
// return (uint32_t)(-1);
|
||||||
|
// }
|
||||||
|
// CHECK_ESP_RESULT(esp_ping_new_session(&ping_config, &ping_callbacks, &ping));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Use all ones as a flag that the elapsed time was not set (ping failed or timed out).
|
||||||
|
// self->ping_elapsed_time = (uint32_t)(-1);
|
||||||
|
|
||||||
|
// esp_ping_start(ping);
|
||||||
|
|
||||||
|
// uint32_t start_time = common_hal_time_monotonic_ms();
|
||||||
|
// while ((self->ping_elapsed_time == (uint32_t)(-1)) &&
|
||||||
|
// (common_hal_time_monotonic_ms() - start_time < timeout_ms) &&
|
||||||
|
// !mp_hal_is_interrupted()) {
|
||||||
|
// RUN_BACKGROUND_TASKS;
|
||||||
|
// }
|
||||||
|
// esp_ping_stop(ping);
|
||||||
|
// esp_ping_delete_session(ping);
|
||||||
|
|
||||||
|
// return (mp_int_t)self->ping_elapsed_time;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_gc_collect(wifi_radio_obj_t *self) {
|
||||||
|
// Only bother to scan the actual object references.
|
||||||
|
gc_collect_ptr(self->current_scan);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_radio_get_dns(wifi_radio_obj_t *self) {
|
||||||
|
// if (!esp_netif_is_netif_up(self->netif)) {
|
||||||
|
// return mp_const_empty_tuple;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// esp_netif_get_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &self->dns_info);
|
||||||
|
|
||||||
|
// if (self->dns_info.ip.type == ESP_IPADDR_TYPE_V4 && self->dns_info.ip.u_addr.ip4.addr == INADDR_NONE) {
|
||||||
|
// return mp_const_empty_tuple;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// mp_obj_t args[] = {
|
||||||
|
// espaddr_to_str(&self->dns_info.ip),
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return mp_obj_new_tuple(1, args);
|
||||||
|
return mp_const_empty_tuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_wifi_radio_set_dns(wifi_radio_obj_t *self, mp_obj_t dns_addrs_obj) {
|
||||||
|
// mp_int_t len = mp_obj_get_int(mp_obj_len(dns_addrs_obj));
|
||||||
|
// mp_arg_validate_length_max(len, 1, MP_QSTR_dns);
|
||||||
|
// esp_netif_dns_info_t dns_info;
|
||||||
|
// if (len == 0) {
|
||||||
|
// // clear DNS server
|
||||||
|
// dns_info.ip.type = ESP_IPADDR_TYPE_V4;
|
||||||
|
// dns_info.ip.u_addr.ip4.addr = INADDR_NONE;
|
||||||
|
// } else {
|
||||||
|
// mp_obj_t dns_addr_obj = mp_obj_subscr(dns_addrs_obj, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL);
|
||||||
|
// struct sockaddr_storage addr_storage;
|
||||||
|
// socketpool_resolve_host_or_throw(AF_UNSPEC, SOCK_STREAM, mp_obj_str_get_str(dns_addr_obj), &addr_storage, 1);
|
||||||
|
// sockaddr_to_espaddr(&addr_storage, &dns_info.ip);
|
||||||
|
// }
|
||||||
|
// esp_netif_set_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &dns_info);
|
||||||
|
}
|
||||||
43
ports/zephyr-cp/common-hal/wifi/Radio.h
Normal file
43
ports/zephyr-cp/common-hal/wifi/Radio.h
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/wifi/ScannedNetworks.h"
|
||||||
|
#include "shared-bindings/wifi/Network.h"
|
||||||
|
|
||||||
|
#include <zephyr/net/net_if.h>
|
||||||
|
|
||||||
|
// Event bits for the Radio event group.
|
||||||
|
#define WIFI_SCAN_DONE_BIT BIT0
|
||||||
|
#define WIFI_CONNECTED_BIT BIT1
|
||||||
|
#define WIFI_DISCONNECTED_BIT BIT2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
wifi_scannednetworks_obj_t *current_scan;
|
||||||
|
// StaticEventGroup_t event_group;
|
||||||
|
// EventGroupHandle_t event_group_handle;
|
||||||
|
// wifi_config_t sta_config;
|
||||||
|
// wifi_network_obj_t ap_info;
|
||||||
|
// esp_netif_ip_info_t ip_info;
|
||||||
|
// esp_netif_dns_info_t dns_info;
|
||||||
|
struct net_if *sta_netif;
|
||||||
|
// uint32_t ping_elapsed_time;
|
||||||
|
// wifi_config_t ap_config;
|
||||||
|
// esp_netif_ip_info_t ap_ip_info;
|
||||||
|
struct net_if *ap_netif;
|
||||||
|
bool started;
|
||||||
|
bool ap_mode;
|
||||||
|
bool sta_mode;
|
||||||
|
uint8_t retries_left;
|
||||||
|
uint8_t starting_retries;
|
||||||
|
uint8_t last_disconnect_reason;
|
||||||
|
} wifi_radio_obj_t;
|
||||||
|
|
||||||
|
extern void common_hal_wifi_radio_gc_collect(wifi_radio_obj_t *self);
|
||||||
122
ports/zephyr-cp/common-hal/wifi/ScannedNetworks.c
Normal file
122
ports/zephyr-cp/common-hal/wifi/ScannedNetworks.c
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2018 Artur Pacholec
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2017 Glenn Ruben Bakke
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "shared/runtime/interrupt_char.h"
|
||||||
|
#include "py/gc.h"
|
||||||
|
#include "py/objstr.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "shared-bindings/wifi/__init__.h"
|
||||||
|
#include "shared-bindings/wifi/Network.h"
|
||||||
|
#include "shared-bindings/wifi/Radio.h"
|
||||||
|
#include "shared-bindings/wifi/ScannedNetworks.h"
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/net/wifi_mgmt.h>
|
||||||
|
|
||||||
|
|
||||||
|
void wifi_scannednetworks_scan_result(wifi_scannednetworks_obj_t *self, struct wifi_scan_result *result) {
|
||||||
|
if (k_msgq_put(&self->msgq, result, K_NO_WAIT) != 0) {
|
||||||
|
printk("Dropping scan result!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wifi_scannednetworks_done(wifi_scannednetworks_obj_t *self) {
|
||||||
|
self->done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool wifi_scannednetworks_wait_for_scan(wifi_scannednetworks_obj_t *self) {
|
||||||
|
|
||||||
|
return !mp_hal_is_interrupted();
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t common_hal_wifi_scannednetworks_next(wifi_scannednetworks_obj_t *self) {
|
||||||
|
if (self->done) {
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
// If we don't have any results queued, then wait until we do.
|
||||||
|
while (k_fifo_is_empty(&self->fifo) && k_msgq_num_used_get(&self->msgq) == 0) {
|
||||||
|
k_poll(self->events, ARRAY_SIZE(self->events), K_FOREVER);
|
||||||
|
if (mp_hal_is_interrupted()) {
|
||||||
|
wifi_scannednetworks_done(self);
|
||||||
|
}
|
||||||
|
if (k_msgq_num_used_get(&self->msgq) > 0) {
|
||||||
|
// We found something.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int signaled;
|
||||||
|
int result;
|
||||||
|
k_poll_signal_check(&self->channel_done, &signaled, &result);
|
||||||
|
if (signaled) {
|
||||||
|
wifi_scannednetworks_scan_next_channel(self);
|
||||||
|
}
|
||||||
|
if (self->done) {
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Copy everything out of the message queue into the FIFO because it's a
|
||||||
|
// fixed size.
|
||||||
|
while (k_msgq_num_used_get(&self->msgq) > 0) {
|
||||||
|
wifi_network_obj_t *entry = mp_obj_malloc(wifi_network_obj_t, &wifi_network_type);
|
||||||
|
k_msgq_get(&self->msgq, &entry->scan_result, K_NO_WAIT);
|
||||||
|
// This will use the base python object space for the linked list. We
|
||||||
|
// need to reset it before returning this memory as a Python object.
|
||||||
|
k_fifo_put(&self->fifo, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
wifi_network_obj_t *entry = k_fifo_get(&self->fifo, K_NO_WAIT);
|
||||||
|
entry->base.type = &wifi_network_type;
|
||||||
|
return MP_OBJ_FROM_PTR(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't do a linear scan so that we look at a variety of spectrum up front.
|
||||||
|
static uint8_t scan_pattern[] = {6, 1, 11, 3, 9, 13, 2, 4, 8, 12, 5, 7, 10, 14, 0};
|
||||||
|
|
||||||
|
void wifi_scannednetworks_scan_next_channel(wifi_scannednetworks_obj_t *self) {
|
||||||
|
// There is no channel 0, so use that as a flag to indicate we've run out of channels to scan.
|
||||||
|
uint8_t next_channel = 0;
|
||||||
|
while (self->current_channel_index < sizeof(scan_pattern)) {
|
||||||
|
next_channel = scan_pattern[self->current_channel_index];
|
||||||
|
self->current_channel_index++;
|
||||||
|
// Scan only channels that are in the specified range.
|
||||||
|
if (self->start_channel <= next_channel && next_channel <= self->end_channel) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
k_poll_signal_init(&self->channel_done);
|
||||||
|
k_poll_event_init(&self->events[2],
|
||||||
|
K_POLL_TYPE_SIGNAL,
|
||||||
|
K_POLL_MODE_NOTIFY_ONLY,
|
||||||
|
&self->channel_done);
|
||||||
|
|
||||||
|
struct wifi_scan_params params = { 0 };
|
||||||
|
params.band_chan[0].band = WIFI_FREQ_BAND_2_4_GHZ;
|
||||||
|
params.band_chan[0].channel = next_channel;
|
||||||
|
if (next_channel == 0) {
|
||||||
|
wifi_scannednetworks_done(self);
|
||||||
|
} else {
|
||||||
|
int res = net_mgmt(NET_REQUEST_WIFI_SCAN, self->netif, ¶ms, sizeof(params));
|
||||||
|
if (res != 0) {
|
||||||
|
printk("Failed to start wifi scan %d\n", res);
|
||||||
|
raise_zephyr_error(res);
|
||||||
|
wifi_scannednetworks_done(self);
|
||||||
|
} else {
|
||||||
|
self->channel_scan_in_progress = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wifi_scannednetworks_deinit(wifi_scannednetworks_obj_t *self) {
|
||||||
|
// Free any results we don't need.
|
||||||
|
while (!k_fifo_is_empty(&self->fifo)) {
|
||||||
|
wifi_network_obj_t *entry = k_fifo_get(&self->fifo, K_NO_WAIT);
|
||||||
|
m_free(entry);
|
||||||
|
}
|
||||||
|
wifi_scannednetworks_done(self);
|
||||||
|
}
|
||||||
43
ports/zephyr-cp/common-hal/wifi/ScannedNetworks.h
Normal file
43
ports/zephyr-cp/common-hal/wifi/ScannedNetworks.h
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2018 Artur Pacholec
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/net/wifi_mgmt.h>
|
||||||
|
|
||||||
|
#define MAX_BUFFERED_SCAN_RESULTS 10
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
uint8_t current_channel_index;
|
||||||
|
struct k_poll_signal channel_done;
|
||||||
|
struct k_poll_event events[3];
|
||||||
|
|
||||||
|
// Hold results as they move from the callback to the CP thread.
|
||||||
|
char msgq_buffer[MAX_BUFFERED_SCAN_RESULTS * sizeof(struct wifi_scan_result)];
|
||||||
|
struct k_msgq msgq;
|
||||||
|
// Buffer the scan results before we return them. They are stored on the CP heap.
|
||||||
|
struct k_fifo fifo;
|
||||||
|
|
||||||
|
// Limits on what channels to scan.
|
||||||
|
uint8_t start_channel;
|
||||||
|
uint8_t end_channel; // Inclusive
|
||||||
|
|
||||||
|
struct net_if *netif;
|
||||||
|
|
||||||
|
bool done;
|
||||||
|
bool channel_scan_in_progress;
|
||||||
|
} wifi_scannednetworks_obj_t;
|
||||||
|
|
||||||
|
void wifi_scannednetworks_scan_result(wifi_scannednetworks_obj_t *self, struct wifi_scan_result *result);
|
||||||
|
void wifi_scannednetworks_scan_next_channel(wifi_scannednetworks_obj_t *self);
|
||||||
|
void wifi_scannednetworks_deinit(wifi_scannednetworks_obj_t *self);
|
||||||
460
ports/zephyr-cp/common-hal/wifi/__init__.c
Normal file
460
ports/zephyr-cp/common-hal/wifi/__init__.c
Normal file
|
|
@ -0,0 +1,460 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "common-hal/wifi/__init__.h"
|
||||||
|
#include "shared-bindings/wifi/__init__.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/ipaddress/IPv4Address.h"
|
||||||
|
#include "shared-bindings/wifi/Monitor.h"
|
||||||
|
#include "shared-bindings/wifi/Radio.h"
|
||||||
|
#include "bindings/zephyr_kernel/__init__.h"
|
||||||
|
#include "common-hal/socketpool/__init__.h"
|
||||||
|
|
||||||
|
#include "py/gc.h"
|
||||||
|
#include "py/mpstate.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
wifi_radio_obj_t common_hal_wifi_radio_obj;
|
||||||
|
|
||||||
|
#include "supervisor/port.h"
|
||||||
|
#include "supervisor/workflow.h"
|
||||||
|
|
||||||
|
#if CIRCUITPY_STATUS_BAR
|
||||||
|
#include "supervisor/shared/status_bar.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/net/wifi_mgmt.h>
|
||||||
|
|
||||||
|
#define MAC_ADDRESS_LENGTH 6
|
||||||
|
|
||||||
|
static void schedule_background_on_cp_core(void *arg) {
|
||||||
|
#if CIRCUITPY_STATUS_BAR
|
||||||
|
supervisor_status_bar_request_update(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// CircuitPython's VM is run in a separate FreeRTOS task from wifi callbacks. So, we have to
|
||||||
|
// notify the main task every time in case it's waiting for us.
|
||||||
|
port_wake_main_task();
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct net_mgmt_event_callback wifi_cb;
|
||||||
|
static struct net_mgmt_event_callback ipv4_cb;
|
||||||
|
|
||||||
|
static void _event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, struct net_if *iface) {
|
||||||
|
wifi_radio_obj_t *self = &common_hal_wifi_radio_obj;
|
||||||
|
printk("_event_handler cb %p event %08x if %p\n", cb, mgmt_event, iface);
|
||||||
|
|
||||||
|
switch (mgmt_event) {
|
||||||
|
case NET_EVENT_WIFI_SCAN_RESULT:
|
||||||
|
printk("NET_EVENT_WIFI_SCAN_RESULT\n");
|
||||||
|
struct wifi_scan_result *result = (struct wifi_scan_result *)cb->info;
|
||||||
|
if (self->current_scan != NULL) {
|
||||||
|
wifi_scannednetworks_scan_result(self->current_scan, result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NET_EVENT_WIFI_SCAN_DONE:
|
||||||
|
printk("NET_EVENT_WIFI_SCAN_DONE\n");
|
||||||
|
if (self->current_scan != NULL) {
|
||||||
|
k_poll_signal_raise(&self->current_scan->channel_done, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NET_EVENT_WIFI_CONNECT_RESULT:
|
||||||
|
printk("NET_EVENT_WIFI_CONNECT_RESULT\n");
|
||||||
|
break;
|
||||||
|
case NET_EVENT_WIFI_DISCONNECT_RESULT:
|
||||||
|
printk("NET_EVENT_WIFI_DISCONNECT_RESULT\n");
|
||||||
|
break;
|
||||||
|
case NET_EVENT_WIFI_IFACE_STATUS:
|
||||||
|
printk("NET_EVENT_WIFI_IFACE_STATUS\n");
|
||||||
|
break;
|
||||||
|
case NET_EVENT_WIFI_TWT:
|
||||||
|
printk("NET_EVENT_WIFI_TWT\n");
|
||||||
|
break;
|
||||||
|
case NET_EVENT_WIFI_TWT_SLEEP_STATE:
|
||||||
|
printk("NET_EVENT_WIFI_TWT_SLEEP_STATE\n");
|
||||||
|
break;
|
||||||
|
case NET_EVENT_WIFI_RAW_SCAN_RESULT:
|
||||||
|
printk("NET_EVENT_WIFI_RAW_SCAN_RESULT\n");
|
||||||
|
break;
|
||||||
|
case NET_EVENT_WIFI_DISCONNECT_COMPLETE:
|
||||||
|
printk("NET_EVENT_WIFI_DISCONNECT_COMPLETE\n");
|
||||||
|
break;
|
||||||
|
case NET_EVENT_WIFI_SIGNAL_CHANGE:
|
||||||
|
printk("NET_EVENT_WIFI_SIGNAL_CHANGE\n");
|
||||||
|
break;
|
||||||
|
case NET_EVENT_WIFI_NEIGHBOR_REP_COMP:
|
||||||
|
printk("NET_EVENT_WIFI_NEIGHBOR_REP_COMP\n");
|
||||||
|
break;
|
||||||
|
case NET_EVENT_WIFI_AP_ENABLE_RESULT:
|
||||||
|
printk("NET_EVENT_WIFI_AP_ENABLE_RESULT\n");
|
||||||
|
break;
|
||||||
|
case NET_EVENT_WIFI_AP_DISABLE_RESULT:
|
||||||
|
printk("NET_EVENT_WIFI_AP_DISABLE_RESULT\n");
|
||||||
|
break;
|
||||||
|
case NET_EVENT_WIFI_AP_STA_CONNECTED:
|
||||||
|
printk("NET_EVENT_WIFI_AP_STA_CONNECTED\n");
|
||||||
|
break;
|
||||||
|
case NET_EVENT_WIFI_AP_STA_DISCONNECTED:
|
||||||
|
printk("NET_EVENT_WIFI_AP_STA_DISCONNECTED\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static void event_handler(void *arg, esp_event_base_t event_base,
|
||||||
|
// int32_t event_id, void *event_data) {
|
||||||
|
// // This runs on the PRO CORE! It cannot share CP interrupt enable/disable
|
||||||
|
// // directly.
|
||||||
|
// wifi_radio_obj_t *radio = arg;
|
||||||
|
// if (event_base == WIFI_EVENT) {
|
||||||
|
// switch (event_id) {
|
||||||
|
// case WIFI_EVENT_SCAN_DONE:
|
||||||
|
// ESP_LOGW(TAG, "scan");
|
||||||
|
// xEventGroupSetBits(radio->event_group_handle, WIFI_SCAN_DONE_BIT);
|
||||||
|
// break;
|
||||||
|
// case WIFI_EVENT_AP_START:
|
||||||
|
// ESP_LOGW(TAG, "ap start");
|
||||||
|
// break;
|
||||||
|
// case WIFI_EVENT_AP_STOP:
|
||||||
|
// ESP_LOGW(TAG, "ap stop");
|
||||||
|
// break;
|
||||||
|
// case WIFI_EVENT_AP_STACONNECTED:
|
||||||
|
// break;
|
||||||
|
// case WIFI_EVENT_AP_STADISCONNECTED:
|
||||||
|
// break;
|
||||||
|
// case WIFI_EVENT_STA_START:
|
||||||
|
// ESP_LOGW(TAG, "sta start");
|
||||||
|
// break;
|
||||||
|
// case WIFI_EVENT_STA_STOP:
|
||||||
|
// ESP_LOGW(TAG, "sta stop");
|
||||||
|
// break;
|
||||||
|
// case WIFI_EVENT_STA_CONNECTED:
|
||||||
|
// ESP_LOGW(TAG, "connected");
|
||||||
|
// break;
|
||||||
|
// case WIFI_EVENT_STA_DISCONNECTED: {
|
||||||
|
// ESP_LOGW(TAG, "disconnected");
|
||||||
|
// wifi_event_sta_disconnected_t *d = (wifi_event_sta_disconnected_t *)event_data;
|
||||||
|
// uint8_t reason = d->reason;
|
||||||
|
// ESP_LOGW(TAG, "reason %d 0x%02x", reason, reason);
|
||||||
|
// if (radio->retries_left > 0 &&
|
||||||
|
// reason != WIFI_REASON_AUTH_FAIL &&
|
||||||
|
// reason != WIFI_REASON_NO_AP_FOUND &&
|
||||||
|
// reason != WIFI_REASON_ASSOC_LEAVE) {
|
||||||
|
// radio->retries_left--;
|
||||||
|
// ESP_LOGI(TAG, "Retrying connect. %d retries remaining", radio->retries_left);
|
||||||
|
// esp_wifi_connect();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// radio->last_disconnect_reason = reason;
|
||||||
|
// xEventGroupSetBits(radio->event_group_handle, WIFI_DISCONNECTED_BIT);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Cases to handle later.
|
||||||
|
// // case WIFI_EVENT_STA_AUTHMODE_CHANGE:
|
||||||
|
// default: {
|
||||||
|
// ESP_LOGW(TAG, "event %ld 0x%02ld", event_id, event_id);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||||
|
// ESP_LOGW(TAG, "got ip");
|
||||||
|
// radio->retries_left = radio->starting_retries;
|
||||||
|
// xEventGroupSetBits(radio->event_group_handle, WIFI_CONNECTED_BIT);
|
||||||
|
// }
|
||||||
|
// // Use IPC to ensure we run schedule background on the same core as CircuitPython.
|
||||||
|
// #if defined(CONFIG_FREERTOS_UNICORE) && CONFIG_FREERTOS_UNICORE
|
||||||
|
// schedule_background_on_cp_core(NULL);
|
||||||
|
// #else
|
||||||
|
// // This only blocks until the start of the function. That's ok since the PRO
|
||||||
|
// // core shouldn't care what we do.
|
||||||
|
// esp_ipc_call(CONFIG_ESP_MAIN_TASK_AFFINITY, schedule_background_on_cp_core, NULL);
|
||||||
|
// #endif
|
||||||
|
// }
|
||||||
|
|
||||||
|
static bool wifi_inited;
|
||||||
|
static bool wifi_ever_inited;
|
||||||
|
static bool wifi_user_initiated;
|
||||||
|
|
||||||
|
void common_hal_wifi_init(bool user_initiated) {
|
||||||
|
wifi_radio_obj_t *self = &common_hal_wifi_radio_obj;
|
||||||
|
printk("common_hal_wifi_init\n");
|
||||||
|
|
||||||
|
if (wifi_inited) {
|
||||||
|
if (user_initiated && !wifi_user_initiated) {
|
||||||
|
common_hal_wifi_radio_set_enabled(self, true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wifi_inited = true;
|
||||||
|
wifi_user_initiated = user_initiated;
|
||||||
|
self->base.type = &wifi_radio_type;
|
||||||
|
|
||||||
|
// struct net_if *default_iface = net_if_get_default();
|
||||||
|
// printk("default interface %p\n", default_iface);
|
||||||
|
// printk("listing network interfaces\n");
|
||||||
|
// for (int i = 0; i < 10; i++) {
|
||||||
|
// struct net_if* iface = net_if_get_by_index(i);
|
||||||
|
// if (iface == NULL) {
|
||||||
|
// printk("iface %d is NULL\n", i);
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// char name[32];
|
||||||
|
// net_if_get_name(iface, name, 32);
|
||||||
|
// printk("iface %d %s\n", i, name);
|
||||||
|
// }
|
||||||
|
self->sta_netif = net_if_get_wifi_sta();
|
||||||
|
self->ap_netif = net_if_get_wifi_sap();
|
||||||
|
printk("sta_netif %p\n", self->sta_netif);
|
||||||
|
printk("ap_netif %p\n", self->ap_netif);
|
||||||
|
|
||||||
|
|
||||||
|
struct wifi_iface_status status = { 0 };
|
||||||
|
if (self->sta_netif != NULL) {
|
||||||
|
CHECK_ZEPHYR_RESULT(net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, self->sta_netif, &status,
|
||||||
|
sizeof(struct wifi_iface_status)));
|
||||||
|
if (net_if_is_up(self->sta_netif)) {
|
||||||
|
printk("STA is up\n");
|
||||||
|
} else {
|
||||||
|
printk("STA is down\n");
|
||||||
|
}
|
||||||
|
if (net_if_is_carrier_ok(self->sta_netif)) {
|
||||||
|
printk("STA carrier is ok\n");
|
||||||
|
} else {
|
||||||
|
printk("STA carrier is not ok\n");
|
||||||
|
}
|
||||||
|
if (net_if_is_dormant(self->sta_netif)) {
|
||||||
|
printk("STA is dormant\n");
|
||||||
|
} else {
|
||||||
|
printk("STA is not dormant\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self->ap_netif != NULL) {
|
||||||
|
int res = net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, self->ap_netif, &status,
|
||||||
|
sizeof(struct wifi_iface_status));
|
||||||
|
printk("AP status request response %d\n", res);
|
||||||
|
if (net_if_is_up(self->ap_netif)) {
|
||||||
|
printk("AP is up\n");
|
||||||
|
} else {
|
||||||
|
printk("AP is down\n");
|
||||||
|
}
|
||||||
|
if (net_if_is_carrier_ok(self->ap_netif)) {
|
||||||
|
printk("AP carrier is ok\n");
|
||||||
|
} else {
|
||||||
|
printk("AP carrier is not ok\n");
|
||||||
|
}
|
||||||
|
if (net_if_is_dormant(self->ap_netif)) {
|
||||||
|
printk("AP is dormant\n");
|
||||||
|
} else {
|
||||||
|
printk("AP is not dormant\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// self->started = false;
|
||||||
|
|
||||||
|
// // Even though we just called esp_netif_create_default_wifi_sta,
|
||||||
|
// // station mode isn't actually ready for use until esp_wifi_set_mode()
|
||||||
|
// // is called and the configuration is loaded via esp_wifi_set_config().
|
||||||
|
// // Set both convenience flags to false so it's not forgotten.
|
||||||
|
// self->sta_mode = 0;
|
||||||
|
// self->ap_mode = 0;
|
||||||
|
|
||||||
|
net_mgmt_init_event_callback(&wifi_cb, _event_handler,
|
||||||
|
NET_EVENT_WIFI_SCAN_DONE |
|
||||||
|
NET_EVENT_WIFI_CONNECT_RESULT |
|
||||||
|
NET_EVENT_WIFI_DISCONNECT_RESULT |
|
||||||
|
NET_EVENT_WIFI_TWT |
|
||||||
|
NET_EVENT_WIFI_RAW_SCAN_RESULT |
|
||||||
|
NET_EVENT_WIFI_AP_ENABLE_RESULT |
|
||||||
|
NET_EVENT_WIFI_AP_DISABLE_RESULT |
|
||||||
|
NET_EVENT_WIFI_AP_STA_CONNECTED |
|
||||||
|
NET_EVENT_WIFI_AP_STA_DISCONNECTED);
|
||||||
|
|
||||||
|
net_mgmt_init_event_callback(&ipv4_cb, _event_handler, NET_EVENT_IPV4_ADDR_ADD);
|
||||||
|
|
||||||
|
net_mgmt_add_event_callback(&wifi_cb);
|
||||||
|
net_mgmt_add_event_callback(&ipv4_cb);
|
||||||
|
|
||||||
|
// Set the default hostname capped at NET_HOSTNAME_MAX_LEN characters. We trim off
|
||||||
|
// the start of the board name (likely manufacturer) because the end is
|
||||||
|
// often more unique to the board.
|
||||||
|
size_t board_len = MIN(NET_HOSTNAME_MAX_LEN - ((MAC_ADDRESS_LENGTH * 2) + 6), strlen(CIRCUITPY_BOARD_ID));
|
||||||
|
size_t board_trim = strlen(CIRCUITPY_BOARD_ID) - board_len;
|
||||||
|
// Avoid double _ in the hostname.
|
||||||
|
if (CIRCUITPY_BOARD_ID[board_trim] == '_') {
|
||||||
|
board_trim++;
|
||||||
|
}
|
||||||
|
|
||||||
|
char cpy_default_hostname[board_len + (MAC_ADDRESS_LENGTH * 2) + 6];
|
||||||
|
struct net_linkaddr *mac = net_if_get_link_addr(self->sta_netif);
|
||||||
|
if (mac->len < MAC_ADDRESS_LENGTH) {
|
||||||
|
printk("MAC address too short");
|
||||||
|
}
|
||||||
|
snprintf(cpy_default_hostname, sizeof(cpy_default_hostname), "cpy-%s-%02x%02x%02x%02x%02x%02x", CIRCUITPY_BOARD_ID + board_trim, mac->addr[0], mac->addr[1], mac->addr[2], mac->addr[3], mac->addr[4], mac->addr[5]);
|
||||||
|
|
||||||
|
if (net_hostname_set(cpy_default_hostname, strlen(cpy_default_hostname)) != 0) {
|
||||||
|
printk("setting hostname failed\n");
|
||||||
|
}
|
||||||
|
// set station mode to avoid the default SoftAP
|
||||||
|
common_hal_wifi_radio_start_station(self);
|
||||||
|
// start wifi
|
||||||
|
common_hal_wifi_radio_set_enabled(self, true);
|
||||||
|
|
||||||
|
printk("common_hal_wifi_init done\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void wifi_user_reset(void) {
|
||||||
|
if (wifi_user_initiated) {
|
||||||
|
wifi_reset();
|
||||||
|
wifi_user_initiated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wifi_reset(void) {
|
||||||
|
printk("wifi_reset\n");
|
||||||
|
if (!wifi_inited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
common_hal_wifi_monitor_deinit(MP_STATE_VM(wifi_monitor_singleton));
|
||||||
|
wifi_radio_obj_t *radio = &common_hal_wifi_radio_obj;
|
||||||
|
common_hal_wifi_radio_set_enabled(radio, false);
|
||||||
|
// #ifndef CONFIG_IDF_TARGET_ESP32
|
||||||
|
// ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT,
|
||||||
|
// ESP_EVENT_ANY_ID,
|
||||||
|
// radio->handler_instance_all_wifi));
|
||||||
|
// ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT,
|
||||||
|
// IP_EVENT_STA_GOT_IP,
|
||||||
|
// radio->handler_instance_got_ip));
|
||||||
|
// ESP_ERROR_CHECK(esp_wifi_deinit());
|
||||||
|
// esp_netif_destroy(radio->netif);
|
||||||
|
// radio->netif = NULL;
|
||||||
|
// esp_netif_destroy(radio->ap_netif);
|
||||||
|
// radio->ap_netif = NULL;
|
||||||
|
// wifi_inited = false;
|
||||||
|
// #endif
|
||||||
|
supervisor_workflow_request_background();
|
||||||
|
}
|
||||||
|
|
||||||
|
// void ipaddress_ipaddress_to_esp_idf(mp_obj_t ip_address, ip_addr_t *esp_ip_address) {
|
||||||
|
// if (mp_obj_is_type(ip_address, &ipaddress_ipv4address_type)) {
|
||||||
|
// ipaddress_ipaddress_to_esp_idf_ip4(ip_address, (esp_ip4_addr_t *)esp_ip_address);
|
||||||
|
// #if LWIP_IPV6
|
||||||
|
// esp_ip_address->type = IPADDR_TYPE_V4;
|
||||||
|
// #endif
|
||||||
|
// } else {
|
||||||
|
// struct sockaddr_storage addr_storage;
|
||||||
|
// socketpool_resolve_host_or_throw(AF_UNSPEC, SOCK_STREAM, mp_obj_str_get_str(ip_address), &addr_storage, 1);
|
||||||
|
// sockaddr_to_espaddr(&addr_storage, (esp_ip_addr_t *)esp_ip_address);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void ipaddress_ipaddress_to_esp_idf_ip4(mp_obj_t ip_address, esp_ip4_addr_t *esp_ip_address) {
|
||||||
|
// if (!mp_obj_is_type(ip_address, &ipaddress_ipv4address_type)) {
|
||||||
|
// mp_raise_ValueError(MP_ERROR_TEXT("Only IPv4 addresses supported"));
|
||||||
|
// }
|
||||||
|
// mp_obj_t packed = common_hal_ipaddress_ipv4address_get_packed(ip_address);
|
||||||
|
// size_t len;
|
||||||
|
// const char *bytes = mp_obj_str_get_data(packed, &len);
|
||||||
|
// esp_netif_set_ip4_addr(esp_ip_address, bytes[0], bytes[1], bytes[2], bytes[3]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
void common_hal_wifi_gc_collect(void) {
|
||||||
|
common_hal_wifi_radio_gc_collect(&common_hal_wifi_radio_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static mp_obj_t espaddrx_to_str(const void *espaddr, uint8_t esptype) {
|
||||||
|
// char buf[IPADDR_STRLEN_MAX];
|
||||||
|
// inet_ntop(esptype == ESP_IPADDR_TYPE_V6 ? AF_INET6 : AF_INET, espaddr, buf, sizeof(buf));
|
||||||
|
// return mp_obj_new_str(buf, strlen(buf));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// mp_obj_t espaddr_to_str(const esp_ip_addr_t *espaddr) {
|
||||||
|
// return espaddrx_to_str(espaddr, espaddr->type);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// mp_obj_t espaddr4_to_str(const esp_ip4_addr_t *espaddr) {
|
||||||
|
// return espaddrx_to_str(espaddr, ESP_IPADDR_TYPE_V4);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// mp_obj_t espaddr6_to_str(const esp_ip6_addr_t *espaddr) {
|
||||||
|
// return espaddrx_to_str(espaddr, ESP_IPADDR_TYPE_V6);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// mp_obj_t sockaddr_to_str(const struct sockaddr_storage *sockaddr) {
|
||||||
|
// char buf[IPADDR_STRLEN_MAX];
|
||||||
|
// #if CIRCUITPY_SOCKETPOOL_IPV6
|
||||||
|
// if (sockaddr->ss_family == AF_INET6) {
|
||||||
|
// const struct sockaddr_in6 *addr6 = (const void *)sockaddr;
|
||||||
|
// inet_ntop(AF_INET6, &addr6->sin6_addr, buf, sizeof(buf));
|
||||||
|
// } else
|
||||||
|
// #endif
|
||||||
|
// {
|
||||||
|
// const struct sockaddr_in *addr = (const void *)sockaddr;
|
||||||
|
// inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf));
|
||||||
|
// }
|
||||||
|
// return mp_obj_new_str(buf, strlen(buf));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// mp_obj_t sockaddr_to_tuple(const struct sockaddr_storage *sockaddr) {
|
||||||
|
// mp_obj_t args[4] = {
|
||||||
|
// sockaddr_to_str(sockaddr),
|
||||||
|
// };
|
||||||
|
// int n = 2;
|
||||||
|
// #if CIRCUITPY_SOCKETPOOL_IPV6
|
||||||
|
// if (sockaddr->ss_family == AF_INET6) {
|
||||||
|
// const struct sockaddr_in6 *addr6 = (const void *)sockaddr;
|
||||||
|
// args[1] = MP_OBJ_NEW_SMALL_INT(htons(addr6->sin6_port));
|
||||||
|
// args[2] = MP_OBJ_NEW_SMALL_INT(addr6->sin6_flowinfo);
|
||||||
|
// args[3] = MP_OBJ_NEW_SMALL_INT(addr6->sin6_scope_id);
|
||||||
|
// n = 4;
|
||||||
|
// } else
|
||||||
|
// #endif
|
||||||
|
// {
|
||||||
|
// const struct sockaddr_in *addr = (const void *)sockaddr;
|
||||||
|
// args[1] = MP_OBJ_NEW_SMALL_INT(htons(addr->sin_port));
|
||||||
|
// }
|
||||||
|
// return mp_obj_new_tuple(n, args);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void sockaddr_to_espaddr(const struct sockaddr_storage *sockaddr, esp_ip_addr_t *espaddr) {
|
||||||
|
// #if CIRCUITPY_SOCKETPOOL_IPV6
|
||||||
|
// MP_STATIC_ASSERT(IPADDR_TYPE_V4 == ESP_IPADDR_TYPE_V4);
|
||||||
|
// MP_STATIC_ASSERT(IPADDR_TYPE_V6 == ESP_IPADDR_TYPE_V6);
|
||||||
|
// MP_STATIC_ASSERT(sizeof(ip_addr_t) == sizeof(esp_ip_addr_t));
|
||||||
|
// MP_STATIC_ASSERT(offsetof(ip_addr_t, u_addr) == offsetof(esp_ip_addr_t, u_addr));
|
||||||
|
// MP_STATIC_ASSERT(offsetof(ip_addr_t, type) == offsetof(esp_ip_addr_t, type));
|
||||||
|
// if (sockaddr->ss_family == AF_INET6) {
|
||||||
|
// const struct sockaddr_in6 *addr6 = (const void *)sockaddr;
|
||||||
|
// MP_STATIC_ASSERT(sizeof(espaddr->u_addr.ip6.addr) == sizeof(addr6->sin6_addr));
|
||||||
|
// memcpy(&espaddr->u_addr.ip6.addr, &addr6->sin6_addr, sizeof(espaddr->u_addr.ip6.addr));
|
||||||
|
// espaddr->u_addr.ip6.zone = addr6->sin6_scope_id;
|
||||||
|
// espaddr->type = ESP_IPADDR_TYPE_V6;
|
||||||
|
// } else
|
||||||
|
// #endif
|
||||||
|
// {
|
||||||
|
// const struct sockaddr_in *addr = (const void *)sockaddr;
|
||||||
|
// MP_STATIC_ASSERT(sizeof(espaddr->u_addr.ip4.addr) == sizeof(addr->sin_addr));
|
||||||
|
// memcpy(&espaddr->u_addr.ip4.addr, &addr->sin_addr, sizeof(espaddr->u_addr.ip4.addr));
|
||||||
|
// espaddr->type = ESP_IPADDR_TYPE_V4;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void espaddr_to_sockaddr(const esp_ip_addr_t *espaddr, struct sockaddr_storage *sockaddr, int port) {
|
||||||
|
// #if CIRCUITPY_SOCKETPOOL_IPV6
|
||||||
|
// if (espaddr->type == ESP_IPADDR_TYPE_V6) {
|
||||||
|
// struct sockaddr_in6 *addr6 = (void *)sockaddr;
|
||||||
|
// memcpy(&addr6->sin6_addr, &espaddr->u_addr.ip6.addr, sizeof(espaddr->u_addr.ip6.addr));
|
||||||
|
// addr6->sin6_scope_id = espaddr->u_addr.ip6.zone;
|
||||||
|
// } else
|
||||||
|
// #endif
|
||||||
|
// {
|
||||||
|
// struct sockaddr_in *addr = (void *)sockaddr;
|
||||||
|
// memcpy(&addr->sin_addr, &espaddr->u_addr.ip4.addr, sizeof(espaddr->u_addr.ip4.addr));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
24
ports/zephyr-cp/common-hal/wifi/__init__.h
Normal file
24
ports/zephyr-cp/common-hal/wifi/__init__.h
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
struct sockaddr_storage;
|
||||||
|
|
||||||
|
void wifi_reset(void);
|
||||||
|
|
||||||
|
// void ipaddress_ipaddress_to_esp_idf(mp_obj_t ip_address, ip_addr_t *esp_ip_address);
|
||||||
|
// void ipaddress_ipaddress_to_esp_idf_ip4(mp_obj_t ip_address, esp_ip4_addr_t *esp_ip_address);
|
||||||
|
|
||||||
|
mp_obj_t sockaddr_to_str(const struct sockaddr_storage *addr);
|
||||||
|
mp_obj_t sockaddr_to_tuple(const struct sockaddr_storage *addr);
|
||||||
|
// mp_obj_t espaddr_to_str(const esp_ip_addr_t *espaddr);
|
||||||
|
// mp_obj_t espaddr4_to_str(const esp_ip4_addr_t *espaddr);
|
||||||
|
// mp_obj_t espaddr6_to_str(const esp_ip6_addr_t *espaddr);
|
||||||
|
// void sockaddr_to_espaddr(const struct sockaddr_storage *sockaddr, esp_ip_addr_t *espaddr);
|
||||||
|
// void espaddr_to_sockaddr(const esp_ip_addr_t *espaddr, struct sockaddr_storage *sockaddr, int port);
|
||||||
92
ports/zephyr-cp/common-hal/zephyr_i2c/I2C.c
Normal file
92
ports/zephyr-cp/common-hal/zephyr_i2c/I2C.c
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2018 Artur Pacholec
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2017 hathach
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2016 Sandeep Mistry All right reserved.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "shared-bindings/busio/I2C.h"
|
||||||
|
#include "shared-bindings/microcontroller/__init__.h"
|
||||||
|
#include "shared-bindings/microcontroller/Pin.h"
|
||||||
|
#include "supervisor/shared/tick.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
|
||||||
|
void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {
|
||||||
|
// never_reset_pin_number(self->scl_pin_number);
|
||||||
|
// never_reset_pin_number(self->sda_pin_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {
|
||||||
|
// return self->sda_pin_number == NO_PIN;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) {
|
||||||
|
if (common_hal_busio_i2c_deinited(self)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nrfx_twim_uninit(&self->twim_peripheral->twim);
|
||||||
|
|
||||||
|
// reset_pin_number(self->sda_pin_number);
|
||||||
|
// reset_pin_number(self->scl_pin_number);
|
||||||
|
|
||||||
|
// self->twim_peripheral->in_use = false;
|
||||||
|
// common_hal_busio_i2c_mark_deinit(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) {
|
||||||
|
// self->sda_pin_number = NO_PIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nrfx_twim_tx doesn't support 0-length data so we fall back to the hal API
|
||||||
|
bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
|
||||||
|
bool found = true;
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) {
|
||||||
|
if (common_hal_busio_i2c_deinited(self)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool grabbed_lock = false;
|
||||||
|
return grabbed_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_busio_i2c_has_lock(busio_i2c_obj_t *self) {
|
||||||
|
return self->has_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
|
||||||
|
self->has_lock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *data, size_t len) {
|
||||||
|
if (len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr,
|
||||||
|
uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len) {
|
||||||
|
uint8_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false);
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return common_hal_busio_i2c_read(self, addr, in_data, in_len);
|
||||||
|
}
|
||||||
17
ports/zephyr-cp/common-hal/zephyr_i2c/I2C.h
Normal file
17
ports/zephyr-cp/common-hal/zephyr_i2c/I2C.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
// twim_peripheral_t *twim_peripheral;
|
||||||
|
bool has_lock;
|
||||||
|
uint8_t scl_pin_number;
|
||||||
|
uint8_t sda_pin_number;
|
||||||
|
} busio_i2c_obj_t;
|
||||||
7
ports/zephyr-cp/common-hal/zephyr_i2c/__init__.c
Normal file
7
ports/zephyr-cp/common-hal/zephyr_i2c/__init__.c
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
// No zephyr_i2c module functions.
|
||||||
45
ports/zephyr-cp/common-hal/zephyr_kernel/__init__.c
Normal file
45
ports/zephyr-cp/common-hal/zephyr_kernel/__init__.c
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2022 Jeff Epler for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "bindings/zephyr_kernel/__init__.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
|
void raise_zephyr_error(int err) {
|
||||||
|
switch (-err) {
|
||||||
|
case EALREADY:
|
||||||
|
printk("EALREADY\n");
|
||||||
|
break;
|
||||||
|
case EDESTADDRREQ:
|
||||||
|
printk("EDESTADDRREQ\n");
|
||||||
|
break;
|
||||||
|
case EMSGSIZE:
|
||||||
|
printk("EMSGSIZE\n");
|
||||||
|
break;
|
||||||
|
case EPROTONOSUPPORT:
|
||||||
|
printk("EPROTONOSUPPORT\n");
|
||||||
|
break;
|
||||||
|
case EADDRNOTAVAIL:
|
||||||
|
printk("EADDRNOTAVAIL\n");
|
||||||
|
break;
|
||||||
|
case ENETRESET:
|
||||||
|
printk("ENETRESET\n");
|
||||||
|
break;
|
||||||
|
case EISCONN:
|
||||||
|
printk("EISCONN\n");
|
||||||
|
break;
|
||||||
|
case ENOTCONN:
|
||||||
|
printk("ENOTCONN\n");
|
||||||
|
break;
|
||||||
|
case ENOTSUP:
|
||||||
|
printk("ENOTSUP\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printk("Zephyr error %d\n", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
7
ports/zephyr-cp/common-hal/zephyr_kernel/__init__.h
Normal file
7
ports/zephyr-cp/common-hal/zephyr_kernel/__init__.h
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2022 Jeff Epler for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
130
ports/zephyr-cp/common-hal/zephyr_serial/UART.c
Normal file
130
ports/zephyr-cp/common-hal/zephyr_serial/UART.c
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "shared-bindings/microcontroller/__init__.h"
|
||||||
|
#include "bindings/zephyr_serial/UART.h"
|
||||||
|
|
||||||
|
#include "shared/runtime/interrupt_char.h"
|
||||||
|
#include "py/mpconfig.h"
|
||||||
|
#include "py/gc.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "py/stream.h"
|
||||||
|
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <zephyr/drivers/uart.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read characters from UART until line end is detected. Afterwards push the
|
||||||
|
* data to the message queue.
|
||||||
|
*/
|
||||||
|
static void serial_cb(const struct device *dev, void *user_data) {
|
||||||
|
zephyr_serial_uart_obj_t *self = (zephyr_serial_uart_obj_t *)user_data;
|
||||||
|
|
||||||
|
uint8_t c;
|
||||||
|
|
||||||
|
if (!uart_irq_update(dev)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!uart_irq_rx_ready(dev)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read until FIFO empty */
|
||||||
|
while (uart_fifo_read(dev, &c, 1) == 1) {
|
||||||
|
if (mp_interrupt_char == c) {
|
||||||
|
zephyr_serial_uart_clear_rx_buffer(self);
|
||||||
|
mp_sched_keyboard_interrupt();
|
||||||
|
} else if (!self->rx_paused) {
|
||||||
|
if (k_msgq_put(&self->msgq, &c, K_NO_WAIT) != 0) {
|
||||||
|
self->rx_paused = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void zephyr_serial_uart_never_reset(zephyr_serial_uart_obj_t *self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void zephyr_serial_uart_construct(zephyr_serial_uart_obj_t *self, const struct device *const uart_device, uint16_t receiver_buffer_size, byte *receiver_buffer) {
|
||||||
|
self->uart_device = uart_device;
|
||||||
|
int ret = uart_irq_callback_user_data_set(uart_device, serial_cb, self);
|
||||||
|
|
||||||
|
|
||||||
|
k_msgq_init(&self->msgq, receiver_buffer, 1, receiver_buffer_size);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
if (ret == -ENOTSUP) {
|
||||||
|
printk("Interrupt-driven UART API support not enabled\n");
|
||||||
|
} else if (ret == -ENOSYS) {
|
||||||
|
printk("UART device does not support interrupt-driven API\n");
|
||||||
|
} else {
|
||||||
|
printk("Error setting UART callback: %d\n", ret);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self->timeout = K_USEC(100);
|
||||||
|
uart_irq_rx_enable(uart_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool zephyr_serial_uart_deinited(zephyr_serial_uart_obj_t *self) {
|
||||||
|
return !device_is_ready(self->uart_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zephyr_serial_uart_deinit(zephyr_serial_uart_obj_t *self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read characters.
|
||||||
|
size_t zephyr_serial_uart_read(zephyr_serial_uart_obj_t *self, uint8_t *data, size_t len, int *errcode) {
|
||||||
|
size_t count = 0;
|
||||||
|
while (count < len && k_msgq_get(&self->msgq, data + count, self->timeout) == 0) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (count > 0) {
|
||||||
|
self->rx_paused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write characters.
|
||||||
|
size_t zephyr_serial_uart_write(zephyr_serial_uart_obj_t *self, const uint8_t *data, size_t len, int *errcode) {
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
uart_poll_out(self->uart_device, data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t zephyr_serial_uart_get_baudrate(zephyr_serial_uart_obj_t *self) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zephyr_serial_uart_set_baudrate(zephyr_serial_uart_obj_t *self, uint32_t baudrate) {
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_float_t zephyr_serial_uart_get_timeout(zephyr_serial_uart_obj_t *self) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zephyr_serial_uart_set_timeout(zephyr_serial_uart_obj_t *self, mp_float_t timeout) {
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t zephyr_serial_uart_rx_characters_available(zephyr_serial_uart_obj_t *self) {
|
||||||
|
return k_msgq_num_used_get(&self->msgq);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zephyr_serial_uart_clear_rx_buffer(zephyr_serial_uart_obj_t *self) {
|
||||||
|
k_msgq_purge(&self->msgq);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool zephyr_serial_uart_ready_to_tx(zephyr_serial_uart_obj_t *self) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
22
ports/zephyr-cp/common-hal/zephyr_serial/UART.h
Normal file
22
ports/zephyr-cp/common-hal/zephyr_serial/UART.h
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
|
||||||
|
const struct device *uart_device;
|
||||||
|
struct k_msgq msgq;
|
||||||
|
|
||||||
|
k_timeout_t timeout;
|
||||||
|
|
||||||
|
bool rx_paused; // set by irq if no space in rbuf
|
||||||
|
} zephyr_serial_uart_obj_t;
|
||||||
7
ports/zephyr-cp/common-hal/zephyr_serial/__init__.c
Normal file
7
ports/zephyr-cp/common-hal/zephyr_serial/__init__.c
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
// No zephyr_serial module functions.
|
||||||
74
ports/zephyr-cp/common-hal/zephyr_spi/SPI.c
Normal file
74
ports/zephyr-cp/common-hal/zephyr_spi/SPI.c
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2018 Artur Pacholec
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "shared-bindings/busio/SPI.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
void spi_reset(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, bool half_duplex) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
|
||||||
|
if (common_hal_busio_spi_deinited(self)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) {
|
||||||
|
if (common_hal_busio_spi_deinited(self)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool grabbed_lock = false;
|
||||||
|
return grabbed_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_busio_spi_has_lock(busio_spi_obj_t *self) {
|
||||||
|
return self->has_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
|
||||||
|
self->has_lock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_busio_spi_write(busio_spi_obj_t *self, const uint8_t *data, size_t len) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len, uint8_t write_value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t *self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t common_hal_busio_spi_get_phase(busio_spi_obj_t *self) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t *self) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
20
ports/zephyr-cp/common-hal/zephyr_spi/SPI.h
Normal file
20
ports/zephyr-cp/common-hal/zephyr_spi/SPI.h
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
// const spim_peripheral_t *spim_peripheral;
|
||||||
|
bool has_lock;
|
||||||
|
uint8_t clock_pin_number;
|
||||||
|
uint8_t MOSI_pin_number;
|
||||||
|
uint8_t MISO_pin_number;
|
||||||
|
} busio_spi_obj_t;
|
||||||
|
|
||||||
|
void spi_reset(void);
|
||||||
7
ports/zephyr-cp/common-hal/zephyr_spi/__init__.c
Normal file
7
ports/zephyr-cp/common-hal/zephyr_spi/__init__.c
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
// No zephyr_spi module functions.
|
||||||
10
ports/zephyr-cp/cptools/board_tools.py
Normal file
10
ports/zephyr-cp/cptools/board_tools.py
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
def find_mpconfigboard(portdir, board_id):
|
||||||
|
next_underscore = board_id.find("_")
|
||||||
|
while next_underscore != -1:
|
||||||
|
vendor = board_id[:next_underscore]
|
||||||
|
board = board_id[next_underscore + 1 :]
|
||||||
|
p = portdir / f"boards/{vendor}/{board}/circuitpython.toml"
|
||||||
|
if p.exists():
|
||||||
|
return p
|
||||||
|
next_underscore = board_id.find("_", next_underscore + 1)
|
||||||
|
return None
|
||||||
613
ports/zephyr-cp/cptools/build_circuitpython.py
Normal file
613
ports/zephyr-cp/cptools/build_circuitpython.py
Normal file
|
|
@ -0,0 +1,613 @@
|
||||||
|
import asyncio
|
||||||
|
import colorlog
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
|
import tomllib
|
||||||
|
import tomlkit
|
||||||
|
import yaml
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
import cpbuild
|
||||||
|
import board_tools
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# print("hello zephyr", sys.argv)
|
||||||
|
|
||||||
|
# print(os.environ)
|
||||||
|
cmake_args = {}
|
||||||
|
for var in sys.argv[1:]:
|
||||||
|
key, value = var.split("=", 1)
|
||||||
|
cmake_args[key] = value
|
||||||
|
|
||||||
|
# Path to ports/zephyr-cp
|
||||||
|
portdir = pathlib.Path(cmake_args["PORT_SRC_DIR"])
|
||||||
|
|
||||||
|
# Path to CP root
|
||||||
|
srcdir = portdir.parent.parent
|
||||||
|
|
||||||
|
# Path to where CMake wants to put our build output.
|
||||||
|
builddir = pathlib.Path.cwd()
|
||||||
|
|
||||||
|
zephyrdir = portdir / "zephyr"
|
||||||
|
|
||||||
|
# Path to where CMake puts Zephyr's build output.
|
||||||
|
zephyrbuilddir = builddir / ".." / ".." / ".." / "zephyr"
|
||||||
|
|
||||||
|
sys.path.append(str(portdir / "zephyr/scripts/dts/python-devicetree/src/"))
|
||||||
|
from zephyr2cp import zephyr_dts_to_cp_board
|
||||||
|
|
||||||
|
compiler = cpbuild.Compiler(srcdir, builddir, cmake_args)
|
||||||
|
|
||||||
|
ALWAYS_ON_MODULES = ["sys", "collections"]
|
||||||
|
DEFAULT_MODULES = [
|
||||||
|
"time",
|
||||||
|
"os",
|
||||||
|
"microcontroller",
|
||||||
|
"struct",
|
||||||
|
"array",
|
||||||
|
"json",
|
||||||
|
"random",
|
||||||
|
"digitalio",
|
||||||
|
"zephyr_serial",
|
||||||
|
]
|
||||||
|
MPCONFIG_FLAGS = ["ulab", "nvm", "displayio", "warnings", "alarm", "array", "json"]
|
||||||
|
|
||||||
|
|
||||||
|
async def preprocess_and_split_defs(compiler, source_file, build_path, flags):
|
||||||
|
build_file = source_file.with_suffix(".pp")
|
||||||
|
build_file = build_path / (build_file.relative_to(srcdir))
|
||||||
|
await compiler.preprocess(source_file, build_file, flags=flags)
|
||||||
|
async with asyncio.TaskGroup() as tg:
|
||||||
|
for mode in ("qstr", "module", "root_pointer"):
|
||||||
|
split_file = build_file.relative_to(build_path).with_suffix(f".{mode}")
|
||||||
|
split_file = build_path / "genhdr" / mode / split_file
|
||||||
|
split_file.parent.mkdir(exist_ok=True, parents=True)
|
||||||
|
tg.create_task(
|
||||||
|
cpbuild.run_command(
|
||||||
|
[
|
||||||
|
"python",
|
||||||
|
srcdir / "py/makeqstrdefs.py",
|
||||||
|
"split",
|
||||||
|
mode,
|
||||||
|
build_file,
|
||||||
|
build_path / "genhdr" / mode,
|
||||||
|
split_file,
|
||||||
|
],
|
||||||
|
srcdir,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def collect_defs(mode, build_path):
|
||||||
|
output_file = build_path / f"{mode}defs.collected"
|
||||||
|
splitdir = build_path / "genhdr" / mode
|
||||||
|
await cpbuild.run_command(
|
||||||
|
["cat", "-s", *splitdir.glob(f"**/*.{mode}"), ">", output_file],
|
||||||
|
splitdir,
|
||||||
|
)
|
||||||
|
return output_file
|
||||||
|
|
||||||
|
|
||||||
|
async def generate_qstr_headers(build_path, compiler, flags, translation):
|
||||||
|
collected = await collect_defs("qstr", build_path)
|
||||||
|
generated = build_path / "genhdr" / "qstrdefs.generated.h"
|
||||||
|
|
||||||
|
await cpbuild.run_command(
|
||||||
|
["python", srcdir / "py" / "makeqstrdata.py", collected, ">", generated],
|
||||||
|
srcdir,
|
||||||
|
)
|
||||||
|
|
||||||
|
compression_level = 9
|
||||||
|
|
||||||
|
# TODO: Do this alongside qstr stuff above.
|
||||||
|
await cpbuild.run_command(
|
||||||
|
[
|
||||||
|
"python",
|
||||||
|
srcdir / "tools" / "msgfmt.py",
|
||||||
|
"-o",
|
||||||
|
build_path / f"{translation}.mo",
|
||||||
|
srcdir / "locale" / f"{translation}.po",
|
||||||
|
],
|
||||||
|
srcdir,
|
||||||
|
)
|
||||||
|
|
||||||
|
await cpbuild.run_command(
|
||||||
|
[
|
||||||
|
"python",
|
||||||
|
srcdir / "py" / "maketranslationdata.py",
|
||||||
|
"--compression_filename",
|
||||||
|
build_path / "genhdr" / "compressed_translations.generated.h",
|
||||||
|
"--translation",
|
||||||
|
build_path / f"{translation}.mo",
|
||||||
|
"--translation_filename",
|
||||||
|
build_path / f"translations-{translation}.c",
|
||||||
|
"--qstrdefs_filename",
|
||||||
|
generated,
|
||||||
|
"--compression_level",
|
||||||
|
compression_level,
|
||||||
|
generated,
|
||||||
|
],
|
||||||
|
srcdir,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def generate_module_header(build_path):
|
||||||
|
collected = await collect_defs("module", build_path)
|
||||||
|
await cpbuild.run_command(
|
||||||
|
[
|
||||||
|
"python",
|
||||||
|
srcdir / "py" / "makemoduledefs.py",
|
||||||
|
collected,
|
||||||
|
">",
|
||||||
|
build_path / "genhdr" / "moduledefs.h",
|
||||||
|
],
|
||||||
|
srcdir,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def generate_root_pointer_header(build_path):
|
||||||
|
collected = await collect_defs("root_pointer", build_path)
|
||||||
|
await cpbuild.run_command(
|
||||||
|
[
|
||||||
|
"python",
|
||||||
|
srcdir / "py" / "make_root_pointers.py",
|
||||||
|
collected,
|
||||||
|
">",
|
||||||
|
build_path / "genhdr" / "root_pointers.h",
|
||||||
|
],
|
||||||
|
srcdir,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
TINYUSB_SETTINGS = {
|
||||||
|
"": {
|
||||||
|
"CFG_TUSB_MCU": "OPT_MCU_MIMXRT10XX",
|
||||||
|
"CFG_TUD_CDC_RX_BUFSIZE": 640,
|
||||||
|
"CFG_TUD_CDC_TX_BUFSIZE": 512,
|
||||||
|
},
|
||||||
|
"stm32u575xx": {"CFG_TUSB_MCU": "OPT_MCU_STM32U5"},
|
||||||
|
"nrf52840": {"CFG_TUSB_MCU": "OPT_MCU_NRF5X"},
|
||||||
|
"nrf5340": {"CFG_TUSB_MCU": "OPT_MCU_NRF5X"},
|
||||||
|
# "r7fa8d1bhecbd": {"CFG_TUSB_MCU": "OPT_MCU_RAXXX", "USB_HIGHSPEED": "1", "USBHS_USB_INT_RESUME_IRQn": "54", "USBFS_INT_IRQn": "54", "CIRCUITPY_USB_DEVICE_INSTANCE": "1"},
|
||||||
|
# ifeq ($(CHIP_FAMILY),$(filter $(CHIP_FAMILY),MIMXRT1011 MIMXRT1015))
|
||||||
|
# CFLAGS += -DCFG_TUD_MIDI_RX_BUFSIZE=512 -DCFG_TUD_MIDI_TX_BUFSIZE=64 -DCFG_TUD_MSC_BUFSIZE=512
|
||||||
|
# else
|
||||||
|
# CFLAGS += -DCFG_TUD_MIDI_RX_BUFSIZE=512 -DCFG_TUD_MIDI_TX_BUFSIZE=512 -DCFG_TUD_MSC_BUFSIZE=1024
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TINYUSB_SOURCE = {
|
||||||
|
"stm32u575xx": [
|
||||||
|
"src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c",
|
||||||
|
"src/portable/synopsys/dwc2/dcd_dwc2.c",
|
||||||
|
"src/portable/synopsys/dwc2/hcd_dwc2.c",
|
||||||
|
"src/portable/synopsys/dwc2/dwc2_common.c",
|
||||||
|
],
|
||||||
|
"nrf52840": [
|
||||||
|
"src/portable/nordic/nrf5x/dcd_nrf5x.c",
|
||||||
|
],
|
||||||
|
"nrf5340": [
|
||||||
|
"src/portable/nordic/nrf5x/dcd_nrf5x.c",
|
||||||
|
],
|
||||||
|
# "r7fa8d1bhecbd": [
|
||||||
|
# "src/portable/renesas/rusb2/dcd_rusb2.c",
|
||||||
|
# "src/portable/renesas/rusb2/hcd_rusb2.c",
|
||||||
|
# "src/portable/renesas/rusb2/rusb2_common.c",
|
||||||
|
# ],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def build_circuitpython():
|
||||||
|
circuitpython_flags = ["-DCIRCUITPY"]
|
||||||
|
port_flags = []
|
||||||
|
enable_mpy_native = False
|
||||||
|
full_build = False
|
||||||
|
usb_host = False
|
||||||
|
tusb_mem_align = 4
|
||||||
|
board = cmake_args["BOARD_ALIAS"]
|
||||||
|
if not board:
|
||||||
|
board = cmake_args["BOARD"]
|
||||||
|
translation = cmake_args["TRANSLATION"]
|
||||||
|
if not translation:
|
||||||
|
translation = "en_US"
|
||||||
|
for module in ALWAYS_ON_MODULES:
|
||||||
|
circuitpython_flags.append(f"-DCIRCUITPY_{module.upper()}=1")
|
||||||
|
lto = cmake_args.get("LTO", "n") == "y"
|
||||||
|
circuitpython_flags.append(f"-DCIRCUITPY_ENABLE_MPY_NATIVE={1 if enable_mpy_native else 0}")
|
||||||
|
circuitpython_flags.append(f"-DCIRCUITPY_FULL_BUILD={1 if full_build else 0}")
|
||||||
|
circuitpython_flags.append(f"-DCIRCUITPY_USB_HOST={1 if usb_host else 0}")
|
||||||
|
circuitpython_flags.append(f'-DCIRCUITPY_BOARD_ID=\\"{board}\\"')
|
||||||
|
circuitpython_flags.append(f"-DCIRCUITPY_TUSB_MEM_ALIGN={tusb_mem_align}")
|
||||||
|
circuitpython_flags.append(f"-DCIRCUITPY_TRANSLATE_OBJECT={1 if lto else 0}")
|
||||||
|
circuitpython_flags.append("-DINTERNAL_FLASH_FILESYSTEM")
|
||||||
|
circuitpython_flags.append("-DLONGINT_IMPL_MPZ")
|
||||||
|
circuitpython_flags.append("-DCIRCUITPY_SSL_MBEDTLS")
|
||||||
|
circuitpython_flags.append('-DFFCONF_H=\\"lib/oofatfs/ffconf.h\\"')
|
||||||
|
circuitpython_flags.extend(("-I", srcdir))
|
||||||
|
circuitpython_flags.extend(("-I", srcdir / "lib/tinyusb/src"))
|
||||||
|
circuitpython_flags.extend(("-I", srcdir / "supervisor/shared/usb"))
|
||||||
|
circuitpython_flags.extend(("-I", builddir))
|
||||||
|
circuitpython_flags.extend(("-I", portdir))
|
||||||
|
# circuitpython_flags.extend(("-I", srcdir / "ports" / port / "peripherals"))
|
||||||
|
|
||||||
|
# circuitpython_flags.extend(("-I", build_path / board_id))
|
||||||
|
|
||||||
|
genhdr = builddir / "genhdr"
|
||||||
|
genhdr.mkdir(exist_ok=True, parents=True)
|
||||||
|
version_header = genhdr / "mpversion.h"
|
||||||
|
async with asyncio.TaskGroup() as tg:
|
||||||
|
tg.create_task(
|
||||||
|
cpbuild.run_command(
|
||||||
|
[
|
||||||
|
"python",
|
||||||
|
srcdir / "py" / "makeversionhdr.py",
|
||||||
|
version_header,
|
||||||
|
"&&",
|
||||||
|
"touch",
|
||||||
|
version_header,
|
||||||
|
],
|
||||||
|
srcdir,
|
||||||
|
check_hash=[version_header],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
board_autogen_task = tg.create_task(zephyr_dts_to_cp_board(builddir, zephyrbuilddir))
|
||||||
|
board_info = board_autogen_task.result()
|
||||||
|
mpconfigboard_fn = board_tools.find_mpconfigboard(portdir, board)
|
||||||
|
mpconfigboard = {
|
||||||
|
"USB_VID": 0x1209,
|
||||||
|
"USB_PID": 0x000C,
|
||||||
|
}
|
||||||
|
if mpconfigboard_fn is None:
|
||||||
|
mpconfigboard_fn = (
|
||||||
|
portdir / "boards" / board_info["vendor_id"] / board / "circuitpython.toml"
|
||||||
|
)
|
||||||
|
logging.warning(
|
||||||
|
f"Could not find board config at: boards/{board_info['vendor_id']}/{board}"
|
||||||
|
)
|
||||||
|
elif mpconfigboard_fn.exists():
|
||||||
|
with mpconfigboard_fn.open("rb") as f:
|
||||||
|
mpconfigboard = tomllib.load(f)
|
||||||
|
|
||||||
|
autogen_board_info_fn = mpconfigboard_fn.parent / "autogen_board_info.toml"
|
||||||
|
|
||||||
|
enabled_modules = set(DEFAULT_MODULES)
|
||||||
|
module_reasons = {}
|
||||||
|
if board_info["wifi"]:
|
||||||
|
enabled_modules.add("wifi")
|
||||||
|
module_reasons["wifi"] = "Zephyr board has wifi"
|
||||||
|
|
||||||
|
if board_info["flash_count"] > 0:
|
||||||
|
enabled_modules.add("storage")
|
||||||
|
module_reasons["storage"] = "Zephyr board has flash"
|
||||||
|
|
||||||
|
if "wifi" in enabled_modules:
|
||||||
|
enabled_modules.add("socketpool")
|
||||||
|
enabled_modules.add("ssl")
|
||||||
|
module_reasons["socketpool"] = "Zephyr networking enabled"
|
||||||
|
module_reasons["ssl"] = "Zephyr networking enabled"
|
||||||
|
|
||||||
|
circuitpython_flags.extend(board_info["cflags"])
|
||||||
|
supervisor_source = [
|
||||||
|
"main.c",
|
||||||
|
"extmod/vfs_fat.c",
|
||||||
|
"lib/tlsf/tlsf.c",
|
||||||
|
portdir / "background.c",
|
||||||
|
portdir / "common-hal/microcontroller/__init__.c",
|
||||||
|
portdir / "common-hal/microcontroller/Pin.c",
|
||||||
|
portdir / "common-hal/microcontroller/Processor.c",
|
||||||
|
portdir / "common-hal/os/__init__.c",
|
||||||
|
"supervisor/stub/misc.c",
|
||||||
|
"shared/readline/readline.c",
|
||||||
|
"shared/runtime/context_manager_helpers.c",
|
||||||
|
"shared/runtime/pyexec.c",
|
||||||
|
"shared/runtime/interrupt_char.c",
|
||||||
|
"shared/runtime/stdout_helpers.c",
|
||||||
|
"shared/runtime/sys_stdio_mphal.c",
|
||||||
|
"shared-bindings/board/__init__.c",
|
||||||
|
"shared-bindings/supervisor/Runtime.c",
|
||||||
|
"shared-bindings/microcontroller/Pin.c",
|
||||||
|
"shared-bindings/util.c",
|
||||||
|
"shared-module/board/__init__.c",
|
||||||
|
"extmod/vfs_reader.c",
|
||||||
|
"extmod/vfs_blockdev.c",
|
||||||
|
"extmod/vfs_fat_file.c",
|
||||||
|
]
|
||||||
|
top = srcdir
|
||||||
|
supervisor_source = [pathlib.Path(p) for p in supervisor_source]
|
||||||
|
supervisor_source.extend(board_info["source_files"])
|
||||||
|
supervisor_source.extend(top.glob("supervisor/shared/*.c"))
|
||||||
|
supervisor_source.append(top / "supervisor/shared/translate/translate.c")
|
||||||
|
# if web_workflow:
|
||||||
|
# supervisor_source.extend(top.glob("supervisor/shared/web_workflow/*.c"))
|
||||||
|
|
||||||
|
usb_num_endpoint_pairs = board_info.get("usb_num_endpoint_pairs", 0)
|
||||||
|
soc = board_info["soc"]
|
||||||
|
usb_ok = usb_num_endpoint_pairs > 0 and soc in TINYUSB_SETTINGS
|
||||||
|
circuitpython_flags.append(f"-DCIRCUITPY_TINYUSB={1 if usb_ok else 0}")
|
||||||
|
circuitpython_flags.append(f"-DCIRCUITPY_USB_DEVICE={1 if usb_ok else 0}")
|
||||||
|
|
||||||
|
tinyusb_files = []
|
||||||
|
if usb_ok:
|
||||||
|
enabled_modules.add("usb_cdc")
|
||||||
|
for setting in TINYUSB_SETTINGS[soc]:
|
||||||
|
circuitpython_flags.append(f"-D{setting}={TINYUSB_SETTINGS[soc][setting]}")
|
||||||
|
tinyusb_files.extend((top / "lib" / "tinyusb" / path for path in TINYUSB_SOURCE[soc]))
|
||||||
|
for macro in ("USB_PID", "USB_VID"):
|
||||||
|
circuitpython_flags.append(f"-D{macro}=0x{mpconfigboard.get(macro):04x}")
|
||||||
|
for macro, limit, value in (
|
||||||
|
("USB_PRODUCT", 16, board_info["name"]),
|
||||||
|
("USB_MANUFACTURER", 8, board_info["vendor"]),
|
||||||
|
):
|
||||||
|
circuitpython_flags.append(f"-D{macro}='\"{value}\"'")
|
||||||
|
circuitpython_flags.append(f"-D{macro}_{limit}='\"{value[:limit]}\"'")
|
||||||
|
|
||||||
|
usb_interface_name = "CircuitPython"
|
||||||
|
|
||||||
|
circuitpython_flags.append("-DCFG_TUSB_OS=OPT_OS_ZEPHYR")
|
||||||
|
circuitpython_flags.append(f"-DUSB_INTERFACE_NAME='\"{usb_interface_name}\"'")
|
||||||
|
circuitpython_flags.append(f"-DUSB_NUM_ENDPOINT_PAIRS={usb_num_endpoint_pairs}")
|
||||||
|
for direction in ("IN", "OUT"):
|
||||||
|
circuitpython_flags.append(f"-DUSB_NUM_{direction}_ENDPOINTS={usb_num_endpoint_pairs}")
|
||||||
|
# USB is special because it doesn't have a matching module.
|
||||||
|
msc_enabled = board_info["flash_count"] > 0
|
||||||
|
if msc_enabled:
|
||||||
|
circuitpython_flags.append("-DCFG_TUD_MSC_BUFSIZE=1024")
|
||||||
|
circuitpython_flags.append("-DCIRCUITPY_USB_MSC_ENABLED_DEFAULT=1")
|
||||||
|
tinyusb_files.append(top / "lib/tinyusb/src/class/msc/msc_device.c")
|
||||||
|
supervisor_source.append(top / "supervisor/shared/usb/usb_msc_flash.c")
|
||||||
|
circuitpython_flags.append(f"-DCIRCUITPY_USB_MSC={1 if msc_enabled else 0}")
|
||||||
|
if "usb_cdc" in enabled_modules:
|
||||||
|
tinyusb_files.extend(top.glob("lib/tinyusb/*.c"))
|
||||||
|
tinyusb_files.append(top / "lib/tinyusb/src/class/cdc/cdc_device.c")
|
||||||
|
circuitpython_flags.append("-DCFG_TUD_CDC_RX_BUFSIZE=640")
|
||||||
|
circuitpython_flags.append("-DCFG_TUD_CDC_TX_BUFSIZE=512")
|
||||||
|
circuitpython_flags.append("-DCFG_TUD_CDC=2")
|
||||||
|
circuitpython_flags.append("-DCIRCUITPY_USB_CDC_CONSOLE_ENABLED_DEFAULT=1")
|
||||||
|
circuitpython_flags.append("-DCIRCUITPY_USB_CDC_DATA_ENABLED_DEFAULT=0")
|
||||||
|
|
||||||
|
if "usb_hid_enabled_default" not in mpconfigboard:
|
||||||
|
mpconfigboard["usb_hid_enabled_default"] = usb_num_endpoint_pairs >= 5
|
||||||
|
if "usb_midi_enabled_default" not in mpconfigboard:
|
||||||
|
mpconfigboard["usb_midi_enabled_default"] = usb_num_endpoint_pairs >= 8
|
||||||
|
|
||||||
|
tinyusb_files.extend(
|
||||||
|
(top / "lib/tinyusb/src/common/tusb_fifo.c", top / "lib/tinyusb/src/tusb.c")
|
||||||
|
)
|
||||||
|
supervisor_source.extend(
|
||||||
|
(portdir / "supervisor/usb.c", top / "supervisor/shared/usb/usb.c")
|
||||||
|
)
|
||||||
|
|
||||||
|
tinyusb_files.extend(
|
||||||
|
(
|
||||||
|
top / "lib/tinyusb/src/device/usbd.c",
|
||||||
|
top / "lib/tinyusb/src/device/usbd_control.c",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
supervisor_source.extend(
|
||||||
|
(top / "supervisor/shared/usb/usb_desc.c", top / "supervisor/shared/usb/usb_device.c")
|
||||||
|
)
|
||||||
|
elif usb_num_endpoint_pairs > 0:
|
||||||
|
module_reasons["usb_cdc"] = f"No TinyUSB settings for {soc}"
|
||||||
|
|
||||||
|
circuitpython_flags.append(f"-DCIRCUITPY_PORT_SERIAL={0 if usb_ok else 1}")
|
||||||
|
# ifeq ($(CIRCUITPY_USB_HID), 1)
|
||||||
|
# SRC_SUPERVISOR += \
|
||||||
|
# lib/tinyusb/src/class/hid/hid_device.c \
|
||||||
|
# shared-bindings/usb_hid/__init__.c \
|
||||||
|
# shared-bindings/usb_hid/Device.c \
|
||||||
|
# shared-module/usb_hid/__init__.c \
|
||||||
|
# shared-module/usb_hid/Device.c \
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifeq ($(CIRCUITPY_USB_MIDI), 1)
|
||||||
|
# SRC_SUPERVISOR += \
|
||||||
|
# lib/tinyusb/src/class/midi/midi_device.c \
|
||||||
|
# shared-bindings/usb_midi/__init__.c \
|
||||||
|
# shared-bindings/usb_midi/PortIn.c \
|
||||||
|
# shared-bindings/usb_midi/PortOut.c \
|
||||||
|
# shared-module/usb_midi/__init__.c \
|
||||||
|
# shared-module/usb_midi/PortIn.c \
|
||||||
|
# shared-module/usb_midi/PortOut.c \
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifeq ($(CIRCUITPY_USB_VIDEO), 1)
|
||||||
|
# SRC_SUPERVISOR += \
|
||||||
|
# shared-bindings/usb_video/__init__.c \
|
||||||
|
# shared-module/usb_video/__init__.c \
|
||||||
|
# shared-bindings/usb_video/USBFramebuffer.c \
|
||||||
|
# shared-module/usb_video/USBFramebuffer.c \
|
||||||
|
# lib/tinyusb/src/class/video/video_device.c \
|
||||||
|
|
||||||
|
# CFLAGS += -DCFG_TUD_VIDEO=1 -DCFG_TUD_VIDEO_STREAMING=1 -DCFG_TUD_VIDEO_STREAMING_EP_BUFSIZE=256 -DCFG_TUD_VIDEO_STREAMING_BULK=1
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifeq ($(CIRCUITPY_USB_VENDOR), 1)
|
||||||
|
# SRC_SUPERVISOR += \
|
||||||
|
# lib/tinyusb/src/class/vendor/vendor_device.c \
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifeq ($(CIRCUITPY_TINYUSB_HOST), 1)
|
||||||
|
# SRC_SUPERVISOR += \
|
||||||
|
# lib/tinyusb/src/host/hub.c \
|
||||||
|
# lib/tinyusb/src/host/usbh.c \
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifeq ($(CIRCUITPY_USB_KEYBOARD_WORKFLOW), 1)
|
||||||
|
# SRC_SUPERVISOR += \
|
||||||
|
# lib/tinyusb/src/class/hid/hid_host.c \
|
||||||
|
# supervisor/shared/usb/host_keyboard.c \
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
if "ssl" in enabled_modules:
|
||||||
|
# TODO: Figure out how to get these paths from zephyr
|
||||||
|
circuitpython_flags.append('-DMBEDTLS_CONFIG_FILE=\\"config-tls-generic.h\\"')
|
||||||
|
circuitpython_flags.extend(
|
||||||
|
("-isystem", portdir / "modules" / "crypto" / "tinycrypt" / "lib" / "include")
|
||||||
|
)
|
||||||
|
circuitpython_flags.extend(
|
||||||
|
("-isystem", portdir / "modules" / "crypto" / "mbedtls" / "include")
|
||||||
|
)
|
||||||
|
circuitpython_flags.extend(
|
||||||
|
("-isystem", portdir / "modules" / "crypto" / "mbedtls" / "configs")
|
||||||
|
)
|
||||||
|
circuitpython_flags.extend(
|
||||||
|
("-isystem", portdir / "modules" / "crypto" / "mbedtls" / "include")
|
||||||
|
)
|
||||||
|
circuitpython_flags.extend(("-isystem", zephyrdir / "modules" / "mbedtls" / "configs"))
|
||||||
|
supervisor_source.append(top / "lib" / "mbedtls_config" / "crt_bundle.c")
|
||||||
|
|
||||||
|
# Make sure all modules have a setting by filling in defaults.
|
||||||
|
hal_source = []
|
||||||
|
autogen_board_info = tomlkit.document()
|
||||||
|
autogen_board_info.add(
|
||||||
|
tomlkit.comment(
|
||||||
|
"This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
autogen_board_info.add("name", board_info["vendor"] + " " + board_info["name"])
|
||||||
|
autogen_modules = tomlkit.table()
|
||||||
|
autogen_board_info.add("modules", autogen_modules)
|
||||||
|
for module in sorted(
|
||||||
|
list(top.glob("shared-bindings/*")) + list(portdir.glob("bindings/*")),
|
||||||
|
key=lambda x: x.name,
|
||||||
|
):
|
||||||
|
if not module.is_dir():
|
||||||
|
continue
|
||||||
|
enabled = module.name in enabled_modules
|
||||||
|
# print(f"Module {module.name} enabled: {enabled}")
|
||||||
|
v = tomlkit.item(enabled)
|
||||||
|
if module.name in module_reasons:
|
||||||
|
v.comment(module_reasons[module.name])
|
||||||
|
autogen_modules.add(module.name, v)
|
||||||
|
circuitpython_flags.append(f"-DCIRCUITPY_{module.name.upper()}={1 if enabled else 0}")
|
||||||
|
|
||||||
|
if enabled:
|
||||||
|
hal_source.extend(portdir.glob(f"bindings/{module.name}/*.c"))
|
||||||
|
hal_source.extend(top.glob(f"ports/zephyr-cp/common-hal/{module.name}/*.c"))
|
||||||
|
hal_source.extend(top.glob(f"shared-bindings/{module.name}/*.c"))
|
||||||
|
hal_source.extend(top.glob(f"shared-module/{module.name}/*.c"))
|
||||||
|
|
||||||
|
if os.environ.get("CI", "false") == "true":
|
||||||
|
# Fail the build if it isn't up to date.
|
||||||
|
if (
|
||||||
|
not autogen_board_info_fn.exists()
|
||||||
|
or autogen_board_info_fn.read_text() != tomlkit.dumps(autogen_board_info)
|
||||||
|
):
|
||||||
|
logger.error(f"autogen_board_info.toml is out of date.")
|
||||||
|
raise RuntimeError(
|
||||||
|
f"autogen_board_info.toml is missing or out of date. Please run `make BOARD={board}` locally and commit {autogen_board_info_fn}."
|
||||||
|
)
|
||||||
|
elif autogen_board_info_fn.parent.exists():
|
||||||
|
autogen_board_info_fn.write_text(tomlkit.dumps(autogen_board_info))
|
||||||
|
|
||||||
|
for mpflag in MPCONFIG_FLAGS:
|
||||||
|
enabled = mpflag in DEFAULT_MODULES
|
||||||
|
circuitpython_flags.append(f"-DCIRCUITPY_{mpflag.upper()}={1 if enabled else 0}")
|
||||||
|
|
||||||
|
source_files = supervisor_source + hal_source + ["extmod/vfs.c"]
|
||||||
|
assembly_files = []
|
||||||
|
for file in top.glob("py/*.c"):
|
||||||
|
source_files.append(file)
|
||||||
|
qstr_flags = "-DNO_QSTR"
|
||||||
|
async with asyncio.TaskGroup() as tg:
|
||||||
|
extra_source_flags = {}
|
||||||
|
for source_file in source_files:
|
||||||
|
tg.create_task(
|
||||||
|
preprocess_and_split_defs(
|
||||||
|
compiler,
|
||||||
|
top / source_file,
|
||||||
|
builddir,
|
||||||
|
[qstr_flags, *circuitpython_flags, *port_flags],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if "ssl" in enabled_modules:
|
||||||
|
crt_bundle = builddir / "x509_crt_bundle.S"
|
||||||
|
roots_pem = srcdir / "lib/certificates/data/roots.pem"
|
||||||
|
generator = srcdir / "tools/gen_crt_bundle.py"
|
||||||
|
tg.create_task(
|
||||||
|
cpbuild.run_command(
|
||||||
|
[
|
||||||
|
"python",
|
||||||
|
generator,
|
||||||
|
"-i",
|
||||||
|
roots_pem,
|
||||||
|
"-o",
|
||||||
|
crt_bundle,
|
||||||
|
"--asm",
|
||||||
|
],
|
||||||
|
srcdir,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assembly_files.append(crt_bundle)
|
||||||
|
|
||||||
|
async with asyncio.TaskGroup() as tg:
|
||||||
|
board_build = builddir
|
||||||
|
tg.create_task(
|
||||||
|
generate_qstr_headers(
|
||||||
|
board_build, compiler, [qstr_flags, *circuitpython_flags, *port_flags], translation
|
||||||
|
)
|
||||||
|
)
|
||||||
|
tg.create_task(generate_module_header(board_build))
|
||||||
|
tg.create_task(generate_root_pointer_header(board_build))
|
||||||
|
|
||||||
|
# This file is generated by the QSTR/translation process.
|
||||||
|
source_files.append(builddir / f"translations-{translation}.c")
|
||||||
|
# These files don't include unique QSTRs. They just need to be compiled.
|
||||||
|
source_files.append(portdir / "supervisor" / "flash.c")
|
||||||
|
source_files.append(portdir / "supervisor" / "port.c")
|
||||||
|
source_files.append(portdir / "supervisor" / "serial.c")
|
||||||
|
source_files.append(srcdir / "lib" / "oofatfs" / "ff.c")
|
||||||
|
source_files.append(srcdir / "lib" / "oofatfs" / "ffunicode.c")
|
||||||
|
source_files.append(srcdir / "extmod" / "vfs_fat_diskio.c")
|
||||||
|
source_files.append(srcdir / "shared/timeutils/timeutils.c")
|
||||||
|
source_files.append(srcdir / "shared-module/time/__init__.c")
|
||||||
|
source_files.append(srcdir / "shared-module/os/__init__.c")
|
||||||
|
source_files.append(srcdir / "shared-module/supervisor/__init__.c")
|
||||||
|
source_files.append(portdir / "bindings/zephyr_kernel/__init__.c")
|
||||||
|
source_files.append(portdir / "common-hal/zephyr_kernel/__init__.c")
|
||||||
|
# source_files.append(srcdir / "ports" / port / "peripherals" / "nrf" / "nrf52840" / "pins.c")
|
||||||
|
|
||||||
|
assembly_files.append(srcdir / "ports/nordic/supervisor/cpu.s")
|
||||||
|
|
||||||
|
source_files.extend(assembly_files)
|
||||||
|
|
||||||
|
source_files.extend(tinyusb_files)
|
||||||
|
|
||||||
|
objects = []
|
||||||
|
async with asyncio.TaskGroup() as tg:
|
||||||
|
for source_file in source_files:
|
||||||
|
source_file = top / source_file
|
||||||
|
build_file = source_file.with_suffix(".o")
|
||||||
|
object_file = builddir / (build_file.relative_to(top))
|
||||||
|
objects.append(object_file)
|
||||||
|
tg.create_task(
|
||||||
|
compiler.compile(source_file, object_file, [*circuitpython_flags, *port_flags])
|
||||||
|
)
|
||||||
|
|
||||||
|
await compiler.archive(objects, pathlib.Path(cmake_args["OUTPUT_FILE"]))
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
try:
|
||||||
|
await build_circuitpython()
|
||||||
|
except* RuntimeError as e:
|
||||||
|
logger.error(e)
|
||||||
|
sys.exit(len(e.exceptions))
|
||||||
|
|
||||||
|
|
||||||
|
handler = colorlog.StreamHandler()
|
||||||
|
handler.setFormatter(colorlog.ColoredFormatter("%(log_color)s%(levelname)s:%(name)s:%(message)s"))
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO, handlers=[handler])
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
2171
ports/zephyr-cp/cptools/compat2driver.py
Normal file
2171
ports/zephyr-cp/cptools/compat2driver.py
Normal file
File diff suppressed because it is too large
Load diff
436
ports/zephyr-cp/cptools/cpbuild.py
Normal file
436
ports/zephyr-cp/cptools/cpbuild.py
Normal file
|
|
@ -0,0 +1,436 @@
|
||||||
|
import asyncio
|
||||||
|
import inspect
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
|
import shlex
|
||||||
|
import time
|
||||||
|
import hashlib
|
||||||
|
import atexit
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
shared_semaphore = None
|
||||||
|
|
||||||
|
trace_entries = []
|
||||||
|
LAST_BUILD_TIMES = {}
|
||||||
|
ALREADY_RUN = {}
|
||||||
|
_last_build_times = pathlib.Path("last_build_times.json")
|
||||||
|
if _last_build_times.exists():
|
||||||
|
with open(_last_build_times) as f:
|
||||||
|
LAST_BUILD_TIMES = json.load(f)
|
||||||
|
logger.info("Build times loaded.")
|
||||||
|
else:
|
||||||
|
logger.warn(
|
||||||
|
"No last build times found. This is normal if you're running this for the first time."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def save_trace():
|
||||||
|
with open("trace.json", "w") as f:
|
||||||
|
json.dump(trace_entries, f)
|
||||||
|
with open("last_build_times.json", "w") as f:
|
||||||
|
json.dump(LAST_BUILD_TIMES, f)
|
||||||
|
logger.info("wrote trace %s", pathlib.Path(".").absolute() / "trace.json")
|
||||||
|
logger.info("wrote build times %s", pathlib.Path(".").absolute() / "last_build_times.json")
|
||||||
|
|
||||||
|
|
||||||
|
atexit.register(save_trace)
|
||||||
|
|
||||||
|
|
||||||
|
class _TokenProtocol(asyncio.Protocol):
|
||||||
|
def __init__(self, client):
|
||||||
|
self.client = client
|
||||||
|
|
||||||
|
def data_received(self, data):
|
||||||
|
# Data can be multiple tokens at once.
|
||||||
|
for i, _ in enumerate(data):
|
||||||
|
self.client.new_token(data[i : i + 1])
|
||||||
|
|
||||||
|
|
||||||
|
class _MakeJobClient:
|
||||||
|
def __init__(self, fifo_path=None, read_fd=None, write_fd=None):
|
||||||
|
self.fifo_path = fifo_path
|
||||||
|
if fifo_path is not None:
|
||||||
|
self.writer = open(fifo_path, "wb")
|
||||||
|
self.reader = open(fifo_path, "rb")
|
||||||
|
self.tokens_in_use = []
|
||||||
|
self.pending_futures = []
|
||||||
|
|
||||||
|
self.read_transport: asyncio.ReadTransport | None = None
|
||||||
|
self.read_protocol = None
|
||||||
|
|
||||||
|
self.started = None
|
||||||
|
|
||||||
|
def new_token(self, token):
|
||||||
|
# Keep a token and reuse it. Ignore cancelled Futures.
|
||||||
|
if self.pending_futures:
|
||||||
|
future = self.pending_futures.pop(0)
|
||||||
|
while future.cancelled() and self.pending_futures:
|
||||||
|
future = self.pending_futures.pop(0)
|
||||||
|
if not future.cancelled():
|
||||||
|
future.set_result(token)
|
||||||
|
return
|
||||||
|
self.read_transport.pause_reading()
|
||||||
|
self.writer.write(token)
|
||||||
|
self.writer.flush()
|
||||||
|
|
||||||
|
async def __aenter__(self):
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
if self.started is None:
|
||||||
|
self.started = asyncio.Event()
|
||||||
|
self.read_transport, self.read_protocol = await loop.connect_read_pipe(
|
||||||
|
lambda: _TokenProtocol(self), self.reader
|
||||||
|
)
|
||||||
|
self.started.set()
|
||||||
|
await self.started.wait()
|
||||||
|
future = loop.create_future()
|
||||||
|
self.pending_futures.append(future)
|
||||||
|
self.read_transport.resume_reading()
|
||||||
|
self.tokens_in_use.append(await future)
|
||||||
|
|
||||||
|
async def __aexit__(self, exc_type, exc, tb):
|
||||||
|
token = self.tokens_in_use.pop()
|
||||||
|
self.new_token(token)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_semaphore():
|
||||||
|
match = re.search(r"fifo:([^\s]+)", os.environ.get("MAKEFLAGS", ""))
|
||||||
|
fifo_path = None
|
||||||
|
if match:
|
||||||
|
fifo_path = match.group(1)
|
||||||
|
return _MakeJobClient(fifo_path=fifo_path)
|
||||||
|
return asyncio.BoundedSemaphore(1)
|
||||||
|
|
||||||
|
|
||||||
|
shared_semaphore = _create_semaphore()
|
||||||
|
tracks = []
|
||||||
|
max_track = 0
|
||||||
|
|
||||||
|
|
||||||
|
async def run_command(command, working_directory, description=None, check_hash=[], extradeps=[]):
|
||||||
|
"""
|
||||||
|
Runs a command asynchronously. The command should ideally be a list of strings
|
||||||
|
and pathlib.Path objects. If all of the paths haven't been modified since the last
|
||||||
|
time the command was run, then it'll be skipped. (The last time a command was run
|
||||||
|
is stored based on the hash of the command.)
|
||||||
|
|
||||||
|
The command is run from the working_directory and the paths are made relative to it.
|
||||||
|
|
||||||
|
Description is used for logging only. If None, the command itself is logged.
|
||||||
|
|
||||||
|
Paths in check_hash are hashed before and after the command. If the hash is
|
||||||
|
the same, then the old mtimes are reset. This is helpful if a command may produce
|
||||||
|
the same result and you don't want the rest of the build impacted.
|
||||||
|
"""
|
||||||
|
paths = []
|
||||||
|
if isinstance(command, list):
|
||||||
|
for i, part in enumerate(command):
|
||||||
|
if isinstance(part, pathlib.Path):
|
||||||
|
paths.append(part)
|
||||||
|
part = part.relative_to(working_directory, walk_up=True)
|
||||||
|
# if isinstance(part, list):
|
||||||
|
|
||||||
|
command[i] = str(part)
|
||||||
|
command = " ".join(command)
|
||||||
|
|
||||||
|
command_hash = hashlib.sha3_256(command.encode("utf-8"))
|
||||||
|
command_hash.update(str(working_directory).encode("utf-8"))
|
||||||
|
command_hash = command_hash.hexdigest()
|
||||||
|
|
||||||
|
# If a command is run multiple times, then wait for the first one to continue. Don't run it again.
|
||||||
|
if command_hash in ALREADY_RUN:
|
||||||
|
logger.debug(f"Already running {command_hash} {command}")
|
||||||
|
await ALREADY_RUN[command_hash].wait()
|
||||||
|
return
|
||||||
|
ALREADY_RUN[command_hash] = asyncio.Event()
|
||||||
|
|
||||||
|
run_reason = None
|
||||||
|
# If the path inputs are all older than the last time we ran them, then we don't have anything to do.
|
||||||
|
if command_hash in LAST_BUILD_TIMES and all((p.exists() for p in paths)):
|
||||||
|
last_build_time = LAST_BUILD_TIMES[command_hash]
|
||||||
|
# Check all paths in the command because one must be modified by the command.
|
||||||
|
newest_file = max((0 if p.is_dir() else p.stat().st_mtime_ns for p in paths))
|
||||||
|
nothing_newer = newest_file <= last_build_time
|
||||||
|
logger.debug(f"Last build time {last_build_time} Newest file {newest_file}")
|
||||||
|
if nothing_newer:
|
||||||
|
# Escape early if an extra dep is newer.
|
||||||
|
for p in extradeps:
|
||||||
|
if p.stat().st_mtime_ns > last_build_time:
|
||||||
|
run_reason = f"{p.relative_to(working_directory, walk_up=True)} is newer"
|
||||||
|
nothing_newer = False
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
for p in paths:
|
||||||
|
if p.stat().st_mtime_ns == newest_file:
|
||||||
|
run_reason = f"{p.relative_to(working_directory, walk_up=True)} is newer"
|
||||||
|
break
|
||||||
|
if nothing_newer:
|
||||||
|
logger.debug(f"Nothing newer {command[-32:]}")
|
||||||
|
ALREADY_RUN[command_hash].set()
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
run_reason = "no previous build time"
|
||||||
|
newest_file = 0
|
||||||
|
|
||||||
|
file_hashes = {}
|
||||||
|
for path in check_hash:
|
||||||
|
if not path.exists():
|
||||||
|
continue
|
||||||
|
with path.open("rb") as f:
|
||||||
|
digest = hashlib.file_digest(f, "sha256")
|
||||||
|
stat = path.stat()
|
||||||
|
mtimes = (stat.st_atime, stat.st_mtime)
|
||||||
|
mtimes_ns = (stat.st_atime_ns, stat.st_mtime_ns)
|
||||||
|
file_hashes[path] = (digest, mtimes, mtimes_ns)
|
||||||
|
|
||||||
|
cancellation = None
|
||||||
|
async with shared_semaphore:
|
||||||
|
global max_track
|
||||||
|
if not tracks:
|
||||||
|
max_track += 1
|
||||||
|
tracks.append(max_track)
|
||||||
|
track = tracks.pop()
|
||||||
|
start_time = time.perf_counter_ns() // 1000
|
||||||
|
process = await asyncio.create_subprocess_shell(
|
||||||
|
command,
|
||||||
|
stdout=asyncio.subprocess.PIPE,
|
||||||
|
stderr=asyncio.subprocess.PIPE,
|
||||||
|
cwd=working_directory,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
stdout, stderr = await process.communicate()
|
||||||
|
except asyncio.CancelledError as e:
|
||||||
|
cancellation = e
|
||||||
|
stdout, stderr = await process.communicate()
|
||||||
|
end_time = time.perf_counter_ns() // 1000
|
||||||
|
trace_entries.append(
|
||||||
|
{
|
||||||
|
"name": command if not description else description,
|
||||||
|
"ph": "X",
|
||||||
|
"pid": 0,
|
||||||
|
"tid": track,
|
||||||
|
"ts": start_time,
|
||||||
|
"dur": end_time - start_time,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
tracks.append(track)
|
||||||
|
|
||||||
|
if process.returncode == 0:
|
||||||
|
old_newest_file = newest_file
|
||||||
|
newest_file = max((p.stat().st_mtime_ns for p in paths))
|
||||||
|
LAST_BUILD_TIMES[command_hash] = newest_file
|
||||||
|
ALREADY_RUN[command_hash].set()
|
||||||
|
|
||||||
|
for path in check_hash:
|
||||||
|
if path not in file_hashes:
|
||||||
|
continue
|
||||||
|
with path.open("rb") as f:
|
||||||
|
digest = hashlib.file_digest(f, "sha256")
|
||||||
|
old_digest, _, old_mtimes_ns = file_hashes[path]
|
||||||
|
if old_digest.digest() == digest.digest():
|
||||||
|
logger.debug(f"{path} is unchanged")
|
||||||
|
os.utime(path, ns=old_mtimes_ns)
|
||||||
|
|
||||||
|
# If something has failed and we've been canceled, hide our success so
|
||||||
|
# the error is clear.
|
||||||
|
if cancellation:
|
||||||
|
raise cancellation
|
||||||
|
if description:
|
||||||
|
logger.info(f"{description} ({run_reason})")
|
||||||
|
logger.debug(command)
|
||||||
|
else:
|
||||||
|
logger.info(f"{command} ({run_reason})")
|
||||||
|
if old_newest_file == newest_file:
|
||||||
|
logger.error("No files were modified by the command.")
|
||||||
|
raise RuntimeError()
|
||||||
|
else:
|
||||||
|
if command_hash in LAST_BUILD_TIMES:
|
||||||
|
del LAST_BUILD_TIMES[command_hash]
|
||||||
|
if stdout:
|
||||||
|
logger.info(stdout.decode("utf-8").strip())
|
||||||
|
if stderr:
|
||||||
|
logger.warning(stderr.decode("utf-8").strip())
|
||||||
|
if not stdout and not stderr:
|
||||||
|
logger.warning("No output")
|
||||||
|
logger.error(command)
|
||||||
|
if cancellation:
|
||||||
|
raise cancellation
|
||||||
|
raise RuntimeError()
|
||||||
|
|
||||||
|
|
||||||
|
async def run_function(
|
||||||
|
function,
|
||||||
|
positional,
|
||||||
|
named,
|
||||||
|
description=None,
|
||||||
|
):
|
||||||
|
async with shared_semaphore:
|
||||||
|
global max_track
|
||||||
|
if not tracks:
|
||||||
|
max_track += 1
|
||||||
|
tracks.append(max_track)
|
||||||
|
track = tracks.pop()
|
||||||
|
start_time = time.perf_counter_ns() // 1000
|
||||||
|
result = await asyncio.to_thread(function, *positional, **named)
|
||||||
|
|
||||||
|
end_time = time.perf_counter_ns() // 1000
|
||||||
|
trace_entries.append(
|
||||||
|
{
|
||||||
|
"name": str(function) if not description else description,
|
||||||
|
"ph": "X",
|
||||||
|
"pid": 0,
|
||||||
|
"tid": track,
|
||||||
|
"ts": start_time,
|
||||||
|
"dur": end_time - start_time,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
tracks.append(track)
|
||||||
|
|
||||||
|
if description:
|
||||||
|
logger.info(description)
|
||||||
|
logger.debug(function)
|
||||||
|
else:
|
||||||
|
logger.info(function)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def run_in_thread(function):
|
||||||
|
def wrapper(*positional, **named):
|
||||||
|
return run_function(function, positional, named)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
cwd = pathlib.Path.cwd()
|
||||||
|
|
||||||
|
|
||||||
|
def parse_depfile(f):
|
||||||
|
depfile_contents = f.read_text().split()
|
||||||
|
extradeps = []
|
||||||
|
for dep in depfile_contents:
|
||||||
|
if dep == "\\" or dep[-1] == ":":
|
||||||
|
continue
|
||||||
|
if dep.startswith("/"):
|
||||||
|
extradeps.append(pathlib.Path(dep))
|
||||||
|
else:
|
||||||
|
extradeps.append(self.srcdir / dep)
|
||||||
|
|
||||||
|
|
||||||
|
class Compiler:
|
||||||
|
def __init__(self, srcdir: pathlib.Path, builddir: pathlib.Path, cmake_args):
|
||||||
|
self.c_compiler = cmake_args["CC"]
|
||||||
|
self.ar = cmake_args["AR"]
|
||||||
|
self.cflags = cmake_args.get("CFLAGS", "")
|
||||||
|
|
||||||
|
self.srcdir = srcdir
|
||||||
|
self.builddir = builddir
|
||||||
|
|
||||||
|
async def preprocess(
|
||||||
|
self, source_file: pathlib.Path, output_file: pathlib.Path, flags: list[pathlib.Path]
|
||||||
|
):
|
||||||
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
depfile = output_file.parent / (output_file.name + ".d")
|
||||||
|
if depfile.exists():
|
||||||
|
pass
|
||||||
|
await run_command(
|
||||||
|
[
|
||||||
|
self.c_compiler,
|
||||||
|
"-E",
|
||||||
|
"-MMD",
|
||||||
|
"-MF",
|
||||||
|
depfile,
|
||||||
|
"-c",
|
||||||
|
source_file,
|
||||||
|
self.cflags,
|
||||||
|
*flags,
|
||||||
|
"-o",
|
||||||
|
output_file,
|
||||||
|
],
|
||||||
|
description=f"Preprocess {source_file.relative_to(self.srcdir)} -> {output_file.relative_to(self.builddir)}",
|
||||||
|
working_directory=self.srcdir,
|
||||||
|
check_hash=[output_file],
|
||||||
|
)
|
||||||
|
|
||||||
|
async def compile(
|
||||||
|
self, source_file: pathlib.Path, output_file: pathlib.Path, flags: list[pathlib.Path] = []
|
||||||
|
):
|
||||||
|
if isinstance(source_file, str):
|
||||||
|
source_file = self.srcdir / source_file
|
||||||
|
if isinstance(output_file, str):
|
||||||
|
output_file = self.builddir / output_file
|
||||||
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
depfile = output_file.with_suffix(".d")
|
||||||
|
extradeps = []
|
||||||
|
if depfile.exists():
|
||||||
|
depfile_contents = depfile.read_text().split()
|
||||||
|
for dep in depfile_contents:
|
||||||
|
if dep == "\\" or dep[-1] == ":":
|
||||||
|
continue
|
||||||
|
if dep.startswith("/"):
|
||||||
|
extradeps.append(pathlib.Path(dep))
|
||||||
|
else:
|
||||||
|
extradeps.append(self.srcdir / dep)
|
||||||
|
await run_command(
|
||||||
|
[self.c_compiler, self.cflags, "-MMD", "-c", source_file, *flags, "-o", output_file],
|
||||||
|
description=f"Compile {source_file.relative_to(self.srcdir)} -> {output_file.relative_to(self.builddir)}",
|
||||||
|
working_directory=self.srcdir,
|
||||||
|
extradeps=extradeps,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def archive(self, objects: list[pathlib.Path], output_file: pathlib.Path):
|
||||||
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
# Do one file at a time so that we don't have a long command line. run_command
|
||||||
|
# should skip unchanged files ok.
|
||||||
|
input_files = output_file.with_suffix(output_file.suffix + ".input_files")
|
||||||
|
input_file_content = "\n".join(str(p) for p in objects)
|
||||||
|
# Windows paths have \ as separator but ar wants them as / (like UNIX)
|
||||||
|
input_file_content = input_file_content.replace("\\", "/")
|
||||||
|
input_files.write_text(input_file_content)
|
||||||
|
await run_command(
|
||||||
|
[self.ar, "rvs", output_file, f"@{input_files}"],
|
||||||
|
description=f"Create archive {output_file.relative_to(self.srcdir)}",
|
||||||
|
working_directory=self.srcdir,
|
||||||
|
extradeps=objects,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def link(
|
||||||
|
self,
|
||||||
|
objects: list[pathlib.Path],
|
||||||
|
output_file: pathlib.Path,
|
||||||
|
linker_script: pathlib.Path,
|
||||||
|
flags: list[str] = [],
|
||||||
|
print_memory_use=True,
|
||||||
|
output_map_file=True,
|
||||||
|
gc_sections=True,
|
||||||
|
):
|
||||||
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
link_flags = []
|
||||||
|
if print_memory_use:
|
||||||
|
link_flags.append("-Wl,--print-memory-usage")
|
||||||
|
if output_map_file:
|
||||||
|
link_flags.append(
|
||||||
|
"-Wl,-Map="
|
||||||
|
+ str(output_file.with_suffix(".elf.map").relative_to(caller_directory))
|
||||||
|
)
|
||||||
|
if gc_sections:
|
||||||
|
link_flags.append("-Wl,--gc-sections")
|
||||||
|
await run_command(
|
||||||
|
[
|
||||||
|
self.c_compiler,
|
||||||
|
*link_flags,
|
||||||
|
*flags,
|
||||||
|
*objects,
|
||||||
|
"-fuse-ld=lld",
|
||||||
|
"-T",
|
||||||
|
linker_script,
|
||||||
|
"-o",
|
||||||
|
output_file,
|
||||||
|
],
|
||||||
|
description=f"Link {output_file.relative_to(cwd)}",
|
||||||
|
working_directory=caller_directory,
|
||||||
|
)
|
||||||
27
ports/zephyr-cp/cptools/gen_compat2driver.py
Normal file
27
ports/zephyr-cp/cptools/gen_compat2driver.py
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
mapping = {}
|
||||||
|
|
||||||
|
drivers = pathlib.Path("lib/zephyr/drivers")
|
||||||
|
for p in drivers.glob("**/*.c"):
|
||||||
|
for line in p.open():
|
||||||
|
if line.startswith("#define DT_DRV_COMPAT"):
|
||||||
|
compat = line.rsplit(None, 1)[-1].strip()
|
||||||
|
driver = str(p.parent.relative_to(drivers))
|
||||||
|
print(compat, "->", driver)
|
||||||
|
mapping[compat] = driver
|
||||||
|
|
||||||
|
with open("cptools/compat2driver.py", "w") as f:
|
||||||
|
f.write("# This file was generated by gen_compat2driver.py\n")
|
||||||
|
f.write("COMPAT_TO_DRIVER = {\n")
|
||||||
|
# Replaces make it pass lint.
|
||||||
|
last_driver = None
|
||||||
|
for key in sorted(mapping.keys(), key=lambda x: (mapping[x], x)):
|
||||||
|
driver = mapping[key]
|
||||||
|
if driver != last_driver:
|
||||||
|
if last_driver:
|
||||||
|
f.write(" #\n")
|
||||||
|
f.write(f" # {driver}\n")
|
||||||
|
last_driver = driver
|
||||||
|
f.write(f' "{key}": "{mapping[key]}",\n')
|
||||||
|
f.write("}\n")
|
||||||
23
ports/zephyr-cp/cptools/pre_zephyr_build_prep.py
Normal file
23
ports/zephyr-cp/cptools/pre_zephyr_build_prep.py
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Called by the Makefile before calling out to `west`.
|
||||||
|
import pathlib
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tomllib
|
||||||
|
|
||||||
|
import board_tools
|
||||||
|
|
||||||
|
portdir = pathlib.Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
board = sys.argv[-1]
|
||||||
|
|
||||||
|
mpconfigboard = board_tools.find_mpconfigboard(portdir, board)
|
||||||
|
if mpconfigboard is None:
|
||||||
|
# Assume it doesn't need any prep.
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
with mpconfigboard.open("rb") as f:
|
||||||
|
mpconfigboard = tomllib.load(f)
|
||||||
|
|
||||||
|
blobs = mpconfigboard.get("BLOBS", [])
|
||||||
|
for blob in blobs:
|
||||||
|
subprocess.run(["west", "blobs", "fetch", blob], check=True)
|
||||||
395
ports/zephyr-cp/cptools/zephyr2cp.py
Normal file
395
ports/zephyr-cp/cptools/zephyr2cp.py
Normal file
|
|
@ -0,0 +1,395 @@
|
||||||
|
import logging
|
||||||
|
import pathlib
|
||||||
|
import cpbuild
|
||||||
|
|
||||||
|
from devicetree import dtlib
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from compat2driver import COMPAT_TO_DRIVER
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
MANUAL_COMPAT_TO_DRIVER = {
|
||||||
|
"renesas_ra_nv_flash": "flash",
|
||||||
|
}
|
||||||
|
|
||||||
|
# These are controllers, not the flash devices themselves.
|
||||||
|
BLOCKED_FLASH_COMPAT = (
|
||||||
|
"renesas,ra-qspi",
|
||||||
|
"renesas,ra-ospi-b",
|
||||||
|
"nordic,nrf-spim",
|
||||||
|
)
|
||||||
|
|
||||||
|
CONNECTORS = {
|
||||||
|
"mikro-bus": [
|
||||||
|
"AN",
|
||||||
|
"RST",
|
||||||
|
"CS",
|
||||||
|
"SCK",
|
||||||
|
"MISO",
|
||||||
|
"MOSI",
|
||||||
|
"PWM",
|
||||||
|
"INT",
|
||||||
|
"RX",
|
||||||
|
"TX",
|
||||||
|
"SCL",
|
||||||
|
"SDA",
|
||||||
|
],
|
||||||
|
"arduino-header-r3": [
|
||||||
|
"A0",
|
||||||
|
"A1",
|
||||||
|
"A2",
|
||||||
|
"A3",
|
||||||
|
"A4",
|
||||||
|
"A5",
|
||||||
|
"D0",
|
||||||
|
"D1",
|
||||||
|
"D2",
|
||||||
|
"D3",
|
||||||
|
"D4",
|
||||||
|
"D5",
|
||||||
|
"D6",
|
||||||
|
"D7",
|
||||||
|
"D8",
|
||||||
|
"D9",
|
||||||
|
"D10",
|
||||||
|
"D11",
|
||||||
|
"D12",
|
||||||
|
"D13",
|
||||||
|
"D14",
|
||||||
|
"D15",
|
||||||
|
],
|
||||||
|
"adafruit-feather-header": [
|
||||||
|
"A0",
|
||||||
|
"A1",
|
||||||
|
"A2",
|
||||||
|
"A3",
|
||||||
|
"A4",
|
||||||
|
"A5",
|
||||||
|
"SCK",
|
||||||
|
"MOSI",
|
||||||
|
"MISO",
|
||||||
|
"RX",
|
||||||
|
"TX",
|
||||||
|
"D4",
|
||||||
|
"SDA",
|
||||||
|
"SCL",
|
||||||
|
"D5",
|
||||||
|
"D6",
|
||||||
|
"D9",
|
||||||
|
"D10",
|
||||||
|
"D11",
|
||||||
|
"D12",
|
||||||
|
"D13",
|
||||||
|
],
|
||||||
|
"renesas,ra-gpio-mipi-header": [
|
||||||
|
"IIC_SDA",
|
||||||
|
"DISP_BLEN",
|
||||||
|
"IIC_SCL",
|
||||||
|
"DISP_INT",
|
||||||
|
"DISP_RST",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@cpbuild.run_in_thread
|
||||||
|
def zephyr_dts_to_cp_board(builddir, zephyrbuilddir):
|
||||||
|
board_dir = builddir / "board"
|
||||||
|
# Auto generate board files from device tree.
|
||||||
|
|
||||||
|
board_info = {
|
||||||
|
"wifi": False,
|
||||||
|
"usb_device": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
runners = zephyrbuilddir / "runners.yaml"
|
||||||
|
runners = yaml.safe_load(runners.read_text())
|
||||||
|
zephyr_board_dir = pathlib.Path(runners["config"]["board_dir"])
|
||||||
|
board_yaml = zephyr_board_dir / "board.yml"
|
||||||
|
board_yaml = yaml.safe_load(board_yaml.read_text())
|
||||||
|
board_info["vendor_id"] = board_yaml["board"]["vendor"]
|
||||||
|
vendor_index = zephyr_board_dir.parent / "index.rst"
|
||||||
|
if vendor_index.exists():
|
||||||
|
vendor_index = vendor_index.read_text()
|
||||||
|
vendor_index = vendor_index.split("\n")
|
||||||
|
vendor_name = vendor_index[2].strip()
|
||||||
|
else:
|
||||||
|
vendor_name = board_info["vendor_id"]
|
||||||
|
board_info["vendor"] = vendor_name
|
||||||
|
soc_name = board_yaml["board"]["socs"][0]["name"]
|
||||||
|
board_info["soc"] = soc_name
|
||||||
|
board_name = board_yaml["board"]["full_name"]
|
||||||
|
board_info["name"] = board_name
|
||||||
|
# board_id_yaml = zephyr_board_dir / (zephyr_board_dir.name + ".yaml")
|
||||||
|
# board_id_yaml = yaml.safe_load(board_id_yaml.read_text())
|
||||||
|
# print(board_id_yaml)
|
||||||
|
# board_name = board_id_yaml["name"]
|
||||||
|
|
||||||
|
enabled_modules = []
|
||||||
|
|
||||||
|
dts = zephyrbuilddir / "zephyr.dts"
|
||||||
|
edt_pickle = dtlib.DT(dts)
|
||||||
|
node2alias = {}
|
||||||
|
for alias in edt_pickle.alias2node:
|
||||||
|
node = edt_pickle.alias2node[alias]
|
||||||
|
if node not in node2alias:
|
||||||
|
node2alias[node] = []
|
||||||
|
node2alias[node].append(alias)
|
||||||
|
ioports = {}
|
||||||
|
all_ioports = []
|
||||||
|
board_names = {}
|
||||||
|
flashes = []
|
||||||
|
rams = []
|
||||||
|
status_led = None
|
||||||
|
path2chosen = {}
|
||||||
|
chosen2path = {}
|
||||||
|
usb_num_endpoint_pairs = 0
|
||||||
|
for k in edt_pickle.root.nodes["chosen"].props:
|
||||||
|
value = edt_pickle.root.nodes["chosen"].props[k]
|
||||||
|
path2chosen[value.to_path()] = k
|
||||||
|
chosen2path[k] = value.to_path()
|
||||||
|
remaining_nodes = set([edt_pickle.root])
|
||||||
|
while remaining_nodes:
|
||||||
|
node = remaining_nodes.pop()
|
||||||
|
remaining_nodes.update(node.nodes.values())
|
||||||
|
gpio = node.props.get("gpio-controller", False)
|
||||||
|
gpio_map = node.props.get("gpio-map", [])
|
||||||
|
status = node.props.get("status", None)
|
||||||
|
if status is None:
|
||||||
|
status = "okay"
|
||||||
|
else:
|
||||||
|
status = status.to_string()
|
||||||
|
|
||||||
|
compatible = []
|
||||||
|
if "compatible" in node.props:
|
||||||
|
compatible = node.props["compatible"].to_strings()
|
||||||
|
logger.debug(node.name, status)
|
||||||
|
chosen = None
|
||||||
|
if node in path2chosen:
|
||||||
|
chosen = path2chosen[node]
|
||||||
|
logger.debug(" chosen:", chosen)
|
||||||
|
for c in compatible:
|
||||||
|
underscored = c.replace(",", "_").replace("-", "_")
|
||||||
|
driver = COMPAT_TO_DRIVER.get(underscored, None)
|
||||||
|
if "mmio" in c:
|
||||||
|
logger.debug(" ", c, node.labels, node.props)
|
||||||
|
address, size = node.props["reg"].to_nums()
|
||||||
|
end = address + size
|
||||||
|
if chosen == "zephyr,sram":
|
||||||
|
start = "z_mapped_end"
|
||||||
|
elif "zephyr,memory-region" in node.props:
|
||||||
|
start = "__" + node.props["zephyr,memory-region"].to_string() + "_end"
|
||||||
|
else:
|
||||||
|
# Check to see if the chosen sram is a subset of this region. If it is,
|
||||||
|
# then do as above for a smaller region and assume the rest is reserved.
|
||||||
|
chosen_sram = chosen2path["zephyr,sram"]
|
||||||
|
chosen_address, chosen_size = chosen_sram.props["reg"].to_nums()
|
||||||
|
chosen_end = chosen_address + chosen_size
|
||||||
|
if address <= chosen_address <= end and address <= chosen_end <= end:
|
||||||
|
start = "z_mapped_end"
|
||||||
|
address = chosen_address
|
||||||
|
size = chosen_size
|
||||||
|
end = chosen_end
|
||||||
|
else:
|
||||||
|
start = address
|
||||||
|
info = (node.labels[0], start, end, size, node.path)
|
||||||
|
if chosen == "zephyr,sram":
|
||||||
|
rams.insert(0, info)
|
||||||
|
else:
|
||||||
|
rams.append(info)
|
||||||
|
if not driver:
|
||||||
|
driver = MANUAL_COMPAT_TO_DRIVER.get(underscored, None)
|
||||||
|
logger.debug(" ", underscored, driver)
|
||||||
|
if not driver:
|
||||||
|
continue
|
||||||
|
if driver == "flash" and status == "okay":
|
||||||
|
if not chosen and compatible[0] not in BLOCKED_FLASH_COMPAT:
|
||||||
|
# Skip chosen nodes because they are used by Zephyr.
|
||||||
|
flashes.append(f"DEVICE_DT_GET(DT_NODELABEL({node.labels[0]}))")
|
||||||
|
else:
|
||||||
|
logger.debug(" skipping due to blocked compat")
|
||||||
|
if driver == "usb/udc" and status == "okay":
|
||||||
|
board_info["usb_device"] = True
|
||||||
|
props = node.props
|
||||||
|
if "num-bidir-endpoints" not in props:
|
||||||
|
props = node.parent.props
|
||||||
|
usb_num_endpoint_pairs = 0
|
||||||
|
if "num-bidir-endpoints" in props:
|
||||||
|
usb_num_endpoint_pairs = props["num-bidir-endpoints"].to_num()
|
||||||
|
single_direction_endpoints = []
|
||||||
|
for d in ("in", "out"):
|
||||||
|
eps = f"num-{d}-endpoints"
|
||||||
|
single_direction_endpoints.append(props[eps].to_num() if eps in props else 0)
|
||||||
|
# Count separate in/out pairs as bidirectional.
|
||||||
|
usb_num_endpoint_pairs += min(single_direction_endpoints)
|
||||||
|
if driver.startswith("wifi") and status == "okay":
|
||||||
|
board_info["wifi"] = True
|
||||||
|
|
||||||
|
if gpio:
|
||||||
|
if "ngpios" in node.props:
|
||||||
|
ngpios = node.props["ngpios"].to_num()
|
||||||
|
else:
|
||||||
|
ngpios = 32
|
||||||
|
all_ioports.append(node.labels[0])
|
||||||
|
if status == "okay":
|
||||||
|
ioports[node.labels[0]] = set(range(0, ngpios))
|
||||||
|
if gpio_map:
|
||||||
|
i = 0
|
||||||
|
for offset, t, label in gpio_map._markers:
|
||||||
|
if not label:
|
||||||
|
continue
|
||||||
|
num = int.from_bytes(gpio_map.value[offset + 4 : offset + 8], "big")
|
||||||
|
if (label, num) not in board_names:
|
||||||
|
board_names[(label, num)] = []
|
||||||
|
board_names[(label, num)].append(CONNECTORS[compatible[0]][i])
|
||||||
|
i += 1
|
||||||
|
if "gpio-leds" in compatible:
|
||||||
|
for led in node.nodes:
|
||||||
|
led = node.nodes[led]
|
||||||
|
props = led.props
|
||||||
|
ioport = props["gpios"]._markers[1][2]
|
||||||
|
num = int.from_bytes(props["gpios"].value[4:8], "big")
|
||||||
|
if "label" in props:
|
||||||
|
if (ioport, num) not in board_names:
|
||||||
|
board_names[(ioport, num)] = []
|
||||||
|
board_names[(ioport, num)].append(props["label"].to_string())
|
||||||
|
if led in node2alias:
|
||||||
|
if (ioport, num) not in board_names:
|
||||||
|
board_names[(ioport, num)] = []
|
||||||
|
if "led0" in node2alias[led]:
|
||||||
|
board_names[(ioport, num)].append("LED")
|
||||||
|
status_led = (ioport, num)
|
||||||
|
board_names[(ioport, num)].extend(node2alias[led])
|
||||||
|
|
||||||
|
if "gpio-keys" in compatible:
|
||||||
|
for key in node.nodes:
|
||||||
|
props = node.nodes[key].props
|
||||||
|
ioport = props["gpios"]._markers[1][2]
|
||||||
|
num = int.from_bytes(props["gpios"].value[4:8], "big")
|
||||||
|
|
||||||
|
if (ioport, num) not in board_names:
|
||||||
|
board_names[(ioport, num)] = []
|
||||||
|
board_names[(ioport, num)].append(props["label"].to_string())
|
||||||
|
if key in node2alias:
|
||||||
|
if "sw0" in node2alias[key]:
|
||||||
|
board_names[(ioport, num)].append("BUTTON")
|
||||||
|
board_names[(ioport, num)].extend(node2alias[key])
|
||||||
|
|
||||||
|
a, b = all_ioports[:2]
|
||||||
|
i = 0
|
||||||
|
while a[i] == b[i]:
|
||||||
|
i += 1
|
||||||
|
shared_prefix = a[:i]
|
||||||
|
for ioport in ioports:
|
||||||
|
if not ioport.startswith(shared_prefix):
|
||||||
|
shared_prefix = ""
|
||||||
|
break
|
||||||
|
|
||||||
|
pin_defs = []
|
||||||
|
pin_declarations = ["#pragma once"]
|
||||||
|
mcu_pin_mapping = []
|
||||||
|
board_pin_mapping = []
|
||||||
|
for ioport in sorted(ioports.keys()):
|
||||||
|
for num in ioports[ioport]:
|
||||||
|
pin_object_name = f"P{ioport[len(shared_prefix):].upper()}_{num:02d}"
|
||||||
|
if status_led and (ioport, num) == status_led:
|
||||||
|
status_led = pin_object_name
|
||||||
|
pin_defs.append(
|
||||||
|
f"const mcu_pin_obj_t pin_{pin_object_name} = {{ .base.type = &mcu_pin_type, .port = DEVICE_DT_GET(DT_NODELABEL({ioport})), .number = {num}}};"
|
||||||
|
)
|
||||||
|
pin_declarations.append(f"extern const mcu_pin_obj_t pin_{pin_object_name};")
|
||||||
|
mcu_pin_mapping.append(
|
||||||
|
f"{{ MP_ROM_QSTR(MP_QSTR_{pin_object_name}), MP_ROM_PTR(&pin_{pin_object_name}) }},"
|
||||||
|
)
|
||||||
|
board_pin_names = board_names.get((ioport, num), [])
|
||||||
|
|
||||||
|
for board_pin_name in board_pin_names:
|
||||||
|
board_pin_name = board_pin_name.upper().replace(" ", "_").replace("-", "_")
|
||||||
|
board_pin_mapping.append(
|
||||||
|
f"{{ MP_ROM_QSTR(MP_QSTR_{board_pin_name}), MP_ROM_PTR(&pin_{pin_object_name}) }},"
|
||||||
|
)
|
||||||
|
|
||||||
|
pin_defs = "\n".join(pin_defs)
|
||||||
|
pin_declarations = "\n".join(pin_declarations)
|
||||||
|
board_pin_mapping = "\n ".join(board_pin_mapping)
|
||||||
|
mcu_pin_mapping = "\n ".join(mcu_pin_mapping)
|
||||||
|
|
||||||
|
board_dir.mkdir(exist_ok=True, parents=True)
|
||||||
|
header = board_dir / "mpconfigboard.h"
|
||||||
|
if status_led:
|
||||||
|
status_led = f"#define MICROPY_HW_LED_STATUS (&pin_{status_led})\n"
|
||||||
|
else:
|
||||||
|
status_led = ""
|
||||||
|
ram_list = []
|
||||||
|
ram_externs = []
|
||||||
|
max_size = 0
|
||||||
|
for ram in rams:
|
||||||
|
device, start, end, size, path = ram
|
||||||
|
max_size = max(max_size, size)
|
||||||
|
if isinstance(start, str):
|
||||||
|
ram_externs.append(f"extern uint32_t {start};")
|
||||||
|
start = "&" + start
|
||||||
|
else:
|
||||||
|
start = f"(uint32_t*) 0x{start:08x}"
|
||||||
|
ram_list.append(f" {start}, (uint32_t*) 0x{end:08x}, // {path}")
|
||||||
|
ram_list = "\n".join(ram_list)
|
||||||
|
ram_externs = "\n".join(ram_externs)
|
||||||
|
|
||||||
|
new_header_content = f"""#pragma once
|
||||||
|
|
||||||
|
#define MICROPY_HW_BOARD_NAME "{board_name}"
|
||||||
|
#define MICROPY_HW_MCU_NAME "{soc_name}"
|
||||||
|
#define CIRCUITPY_RAM_DEVICE_COUNT {len(rams)}
|
||||||
|
{status_led}
|
||||||
|
"""
|
||||||
|
if not header.exists() or header.read_text() != new_header_content:
|
||||||
|
header.write_text(new_header_content)
|
||||||
|
|
||||||
|
pins = board_dir / "autogen-pins.h"
|
||||||
|
if not pins.exists() or pins.read_text() != pin_declarations:
|
||||||
|
pins.write_text(pin_declarations)
|
||||||
|
|
||||||
|
board_c = board_dir / "board.c"
|
||||||
|
new_board_c_content = f"""
|
||||||
|
// This file is autogenerated by build_circuitpython.py
|
||||||
|
|
||||||
|
#include "shared-bindings/board/__init__.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
#include "py/mphal.h"
|
||||||
|
|
||||||
|
const struct device* const flashes[] = {{ {", ".join(flashes)} }};
|
||||||
|
const int circuitpy_flash_device_count = {len(flashes)};
|
||||||
|
|
||||||
|
{ram_externs}
|
||||||
|
const uint32_t* const ram_bounds[] = {{
|
||||||
|
{ram_list}
|
||||||
|
}};
|
||||||
|
const size_t circuitpy_max_ram_size = {max_size};
|
||||||
|
|
||||||
|
{pin_defs}
|
||||||
|
|
||||||
|
static const mp_rom_map_elem_t mcu_pin_globals_table[] = {{
|
||||||
|
{mcu_pin_mapping}
|
||||||
|
}};
|
||||||
|
MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_globals_table);
|
||||||
|
|
||||||
|
static const mp_rom_map_elem_t board_module_globals_table[] = {{
|
||||||
|
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
|
||||||
|
|
||||||
|
{board_pin_mapping}
|
||||||
|
|
||||||
|
// {{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }},
|
||||||
|
}};
|
||||||
|
|
||||||
|
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
|
||||||
|
"""
|
||||||
|
if not board_c.exists() or new_board_c_content != board_c.read_text():
|
||||||
|
board_c.write_text(new_board_c_content)
|
||||||
|
board_info["source_files"] = [board_c]
|
||||||
|
board_info["cflags"] = ("-I", board_dir)
|
||||||
|
board_info["flash_count"] = len(flashes)
|
||||||
|
board_info["usb_num_endpoint_pairs"] = usb_num_endpoint_pairs
|
||||||
|
return board_info
|
||||||
23
ports/zephyr-cp/mpconfigport.h
Normal file
23
ports/zephyr-cp/mpconfigport.h
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2015 Glenn Ruben Bakke
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// 24kiB stack
|
||||||
|
#define CIRCUITPY_DEFAULT_STACK_SIZE (24 * 1024)
|
||||||
|
|
||||||
|
#define MICROPY_PY_SYS_PLATFORM "Zephyr"
|
||||||
|
|
||||||
|
#define CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL (1)
|
||||||
|
#define DIGITALINOUT_INVALID_DRIVE_MODE (1)
|
||||||
|
|
||||||
|
#define CIRCUITPY_DEBUG_TINYUSB 0
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// This also includes mpconfigboard.h.
|
||||||
|
#include "py/circuitpy_mpconfig.h"
|
||||||
19
ports/zephyr-cp/mphalport.h
Normal file
19
ports/zephyr-cp/mphalport.h
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
// This file is part of the CircuitPython project: https://circuitpython.org
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2015 Glenn Ruben Bakke
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "shared/runtime/interrupt_char.h"
|
||||||
|
#include "py/mpconfig.h"
|
||||||
|
#include "supervisor/shared/tick.h"
|
||||||
|
|
||||||
|
#define mp_hal_ticks_ms() ((mp_uint_t)supervisor_ticks_ms32())
|
||||||
|
#define mp_hal_delay_us(us) NRFX_DELAY_US((uint32_t)(us))
|
||||||
|
|
||||||
|
bool mp_hal_stdin_any(void);
|
||||||
28
ports/zephyr-cp/prj.conf
Normal file
28
ports/zephyr-cp/prj.conf
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
CONFIG_SYS_HEAP_RUNTIME_STATS=y
|
||||||
|
CONFIG_FLASH=y
|
||||||
|
CONFIG_FLASH_MAP=y
|
||||||
|
CONFIG_STD_C23=y
|
||||||
|
|
||||||
|
CONFIG_DYNAMIC_INTERRUPTS=y
|
||||||
|
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||||
|
|
||||||
|
CONFIG_FLASH_MAP_LABELS=y
|
||||||
|
CONFIG_MAIN_STACK_SIZE=24288
|
||||||
|
CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
|
||||||
|
CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
|
||||||
|
|
||||||
|
CONFIG_THREAD_STACK_INFO=y
|
||||||
|
CONFIG_STACK_SENTINEL=y
|
||||||
|
CONFIG_DEBUG_THREAD_INFO=y
|
||||||
|
CONFIG_DEBUG_INFO=y
|
||||||
|
|
||||||
|
CONFIG_USB_DEVICE_STACK=n
|
||||||
|
|
||||||
|
CONFIG_HWINFO=y
|
||||||
|
CONFIG_REBOOT=y
|
||||||
|
CONFIG_ENTROPY_GENERATOR=y
|
||||||
|
|
||||||
|
CONFIG_ASSERT=y
|
||||||
|
CONFIG_LOG_BLOCK_IN_THREAD=y
|
||||||
|
|
||||||
|
CONFIG_EVENTS=y
|
||||||
4
ports/zephyr-cp/socs/nrf52840.conf
Normal file
4
ports/zephyr-cp/socs/nrf52840.conf
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
CONFIG_NRFX_UARTE0=y
|
||||||
|
CONFIG_NRFX_UARTE1=y
|
||||||
|
CONFIG_NRFX_POWER=y
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue