pw_package: Arduino core installers and teensy presubmit
Summary of Changes
==================
1. Rename arduino build args to support cores in any location and have
consistent naming.
2. Update docs to reflect above.
3. `pw package install teensy` working with nice status message on how
to use ge pw_arduino_build_* args.
4. Added gn_teensy_build presubmit test step, not run by default.
`pw presubmit --step gn_teensy_build`
5. Added missing system_rpc_server impl for //targets/arduino. This is
just a copy of the stm32f429i one.
Build arg Change Examples
=========================
OLD:
dir_pw_third_party_arduino = "//third_party/arduino"
arduino_core_name = "teensy"
arduino_package_name = "teensy/avr"
arduino_board = "teensy41"
arduino_menu_options = ["menu.usb.serial",
"menu.opt.o2std"]
NEW:
pw_arduino_build_CORE_PATH =
"/mnt/pigweed/pigweed/.environment/packages"
pw_arduino_build_CORE_NAME = "teensy"
pw_arduino_build_PACKAGE_NAME = "teensy/avr"
pw_arduino_build_BOARD = "teensy41"
pw_arduino_build_MENU_OPTIONS = ["menu.usb.serial",
"menu.opt.o2std"]
All BUILD.gn checks for enabled arduino builds changed too:
OLD:
if (dir_pw_third_party_arduino != "") {}
NEW:
if (pw_arduino_build_CORE_PATH != "") {}
All gn target deps on arduino core sources changed.
OLD:
"$dir_pw_third_party_arduino:arduino_core_sources",
NEW:
"$dir_pw_third_party/arduino:arduino_core_sources",
Teensy package post install & status message
============================================
$ pw package status teensy
20210114 11:58:18 INF teensy is installed.
20210114 11:58:18 INF teensy currently installed in:
/mnt/pigweed/pigweed/.environment/packages/teensy
20210114 11:58:18 INF Enable by running "gn args out" and adding
these lines:
pw_arduino_build_CORE_PATH =
"/mnt/pigweed/pigweed/.environment/packages"
pw_arduino_build_CORE_NAME = "teensy"
pw_arduino_build_PACKAGE_NAME = "teensy/avr"
pw_arduino_build_BOARD = "BOARD_NAME"
20210114 11:58:18 INF Where BOARD_NAME is any supported board.
20210114 11:58:18 INF List available boards by running:
arduino_builder
--arduino-package-path
/mnt/pigweed/pigweed/.environment/packages/teensy
--arduino-package-name teensy/avr
list-boards
Requires: pigweed:29490
Change-Id: Ifd0bd214777392a29af3ab24711edf2f2c1086f3
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/26240
Commit-Queue: Anthony DiGirolamo <tonymd@google.com>
Reviewed-by: Keir Mierle <keir@google.com>
Reviewed-by: Rob Mohr <mohrr@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index c2c9796..73c9f40 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -104,7 +104,7 @@
toolchain_prefix = "$dir_pigweed/targets/stm32f429i-disc1:stm32f429i_disc1_"
}
-if (dir_pw_third_party_arduino != "") {
+if (pw_arduino_build_CORE_PATH != "") {
_build_pigweed_default_at_all_optimization_levels("arduino") {
toolchain_prefix = "$dir_pigweed/targets/arduino:arduino_"
}
diff --git a/pw_arduino_build/BUILD.gn b/pw_arduino_build/BUILD.gn
index db72ea8..bbe2003 100644
--- a/pw_arduino_build/BUILD.gn
+++ b/pw_arduino_build/BUILD.gn
@@ -24,7 +24,7 @@
pw_arduino_build_INIT_BACKEND = ""
}
-if (dir_pw_third_party_arduino != "") {
+if (pw_arduino_build_CORE_PATH != "") {
pw_facade("arduino_init") {
backend = pw_arduino_build_INIT_BACKEND
public = [ "public/pw_arduino_build/init.h" ]
@@ -39,7 +39,7 @@
deps = [
":arduino_init",
"$dir_pw_sys_io",
- "$dir_pw_third_party_arduino:arduino_core_sources",
+ "$dir_pw_third_party/arduino:arduino_core_sources",
]
sources = [ "arduino_main_wrapper.cc" ]
}
diff --git a/pw_arduino_build/arduino.gni b/pw_arduino_build/arduino.gni
index dd1e6f7..0d1704c 100644
--- a/pw_arduino_build/arduino.gni
+++ b/pw_arduino_build/arduino.gni
@@ -16,59 +16,85 @@
declare_args() {
# Enable/disable Arduino builds via group("arduino").
- # Set to the full path of ./third_party/arduino
- dir_pw_third_party_arduino = ""
+ # Set to the full path of where cores are installed.
+ pw_arduino_build_CORE_PATH = ""
# Expected args for an Arduino build:
- arduino_core_name = "teensy"
+ pw_arduino_build_CORE_NAME = ""
# TODO(tonymd): "teensy/avr" here should match the folders in this dir:
- # "../third_party/arduino/cores/$arduino_core_name/hardware/*")
+ # "../third_party/arduino/cores/$pw_arduino_build_CORE_NAME/hardware/*")
# For teensy: "teensy/avr", for adafruit-samd: "samd/1.6.2"
- arduino_package_name = "teensy/avr"
- arduino_board = "teensy40"
+ pw_arduino_build_PACKAGE_NAME = ""
+ pw_arduino_build_BOARD = ""
# Menu options should be a list of strings.
- arduino_menu_options = [
- "menu.usb.serial",
- "menu.keys.en-us",
- ]
+ pw_arduino_build_MENU_OPTIONS = []
}
-arduino_builder_script =
- get_path_info("py/pw_arduino_build/__main__.py", "abspath")
+if (pw_arduino_build_CORE_PATH != "") {
+ # Check that enough pw_arduino_build_* args are set to find and use a core.
+ _required_args_message =
+ "The following build args must all be set: " +
+ "pw_arduino_build_CORE_PATH, pw_arduino_build_CORE_NAME, " +
+ "pw_arduino_build_PACKAGE_NAME."
+ assert(pw_arduino_build_CORE_NAME != "",
+ "Missing 'pw_arduino_build_CORE_NAME' build arg. " +
+ _required_args_message)
+ assert(pw_arduino_build_PACKAGE_NAME != "",
+ "Missing 'pw_arduino_build_PACKAGE_NAME' build arg. " +
+ _required_args_message)
-_arduino_core_path =
- rebase_path("../third_party/arduino/cores/$arduino_core_name")
-_compiler_path_override =
- rebase_path(getenv("_PW_ACTUAL_ENVIRONMENT_ROOT") + "/cipd/pigweed/bin")
+ _arduino_selected_core_path =
+ rebase_path("$pw_arduino_build_CORE_PATH/$pw_arduino_build_CORE_NAME")
-arduino_global_args = [
- "--arduino-package-path",
- _arduino_core_path,
- "--arduino-package-name",
- arduino_package_name,
- "--compiler-path-override",
- _compiler_path_override,
+ arduino_builder_script =
+ get_path_info("py/pw_arduino_build/__main__.py", "abspath")
- # Save config files to "out/arduino_debug/gen/arduino_builder_config.json"
- "--config-file",
- rebase_path(root_gen_dir) + "/arduino_builder_config.json",
- "--save-config",
-]
+ # Check pw_arduino_build_BOARD is set
+ assert(pw_arduino_build_BOARD != "",
+ "pw_arduino_build_BOARD build arg not set. " +
+ "To see supported boards run: " +
+ "arduino_builder --arduino-package-path " +
+ _arduino_selected_core_path + " --arduino-package-name " +
+ pw_arduino_build_PACKAGE_NAME + " list-boards")
-arduino_board_args = [
- "--build-path",
- rebase_path(root_build_dir),
- "--board",
- arduino_board,
- "--menu-options",
-]
-arduino_board_args += arduino_menu_options
+ _compiler_path_override =
+ rebase_path(getenv("_PW_ACTUAL_ENVIRONMENT_ROOT") + "/cipd/pigweed/bin")
-arduino_show_command_args = arduino_global_args + [
- "show",
- "--delimit-with-newlines",
- ] + arduino_board_args
+ arduino_core_library_path = "$_arduino_selected_core_path/hardware/" +
+ "$pw_arduino_build_PACKAGE_NAME/libraries"
-arduino_run_command_args = arduino_global_args + [ "run" ] + arduino_board_args
+ arduino_global_args = [
+ "--arduino-package-path",
+ _arduino_selected_core_path,
+ "--arduino-package-name",
+ pw_arduino_build_PACKAGE_NAME,
+ "--compiler-path-override",
+ _compiler_path_override,
+
+ # Save config files to "out/arduino_debug/gen/arduino_builder_config.json"
+ "--config-file",
+ rebase_path(root_gen_dir) + "/arduino_builder_config.json",
+ "--save-config",
+ ]
+
+ arduino_board_args = [
+ "--build-path",
+ rebase_path(root_build_dir),
+ "--board",
+ pw_arduino_build_BOARD,
+ ]
+ if (pw_arduino_build_MENU_OPTIONS != []) {
+ arduino_board_args += [ "--menu-options" ]
+ arduino_board_args += pw_arduino_build_MENU_OPTIONS
+ }
+
+ arduino_show_command_args = arduino_global_args + [
+ "show",
+ "--delimit-with-newlines",
+ ] + arduino_board_args
+
+ arduino_run_command_args =
+ arduino_global_args + [ "run" ] + arduino_board_args
+}
diff --git a/pw_arduino_build/py/pw_arduino_build/__main__.py b/pw_arduino_build/py/pw_arduino_build/__main__.py
index f06506e..e6fa77d 100644
--- a/pw_arduino_build/py/pw_arduino_build/__main__.py
+++ b/pw_arduino_build/py/pw_arduino_build/__main__.py
@@ -23,6 +23,7 @@
import subprocess
import sys
from collections import OrderedDict
+from pathlib import Path
from typing import List
from pw_arduino_build import core_installer, log
@@ -418,6 +419,14 @@
raise argparse.ArgumentTypeError(
f'{arg.upper()} is not a valid log level')
+ def existing_directory(input_string: str):
+ """Argparse type that resolves to an absolute path."""
+ input_path = Path(os.path.expandvars(input_string)).absolute()
+ if not input_path.exists():
+ raise argparse.ArgumentTypeError(
+ "'{}' is not a valid directory.".format(str(input_path)))
+ return input_path.as_posix()
+
parser = argparse.ArgumentParser()
parser.add_argument("-q",
"--quiet",
@@ -434,10 +443,12 @@
# Global command line options
parser.add_argument("--arduino-package-path",
+ type=existing_directory,
help="Path to the arduino IDE install location.")
parser.add_argument("--arduino-package-name",
help="Name of the Arduino board package to use.")
parser.add_argument("--compiler-path-override",
+ type=existing_directory,
help="Path to arm-none-eabi-gcc bin folder. "
"Default: Arduino core specified gcc")
parser.add_argument("-c", "--config-file", help="Path to a config file.")
diff --git a/pw_arduino_build/py/pw_arduino_build/core_installer.py b/pw_arduino_build/py/pw_arduino_build/core_installer.py
index 2b48195..3428ad7 100644
--- a/pw_arduino_build/py/pw_arduino_build/core_installer.py
+++ b/pw_arduino_build/py/pw_arduino_build/core_installer.py
@@ -153,17 +153,21 @@
def install_core_command(args: argparse.Namespace):
- install_prefix = os.path.realpath(
- os.path.expanduser(os.path.expandvars(args.prefix)))
- install_dir = os.path.join(install_prefix, args.core_name)
- cache_dir = os.path.join(install_prefix, ".cache", args.core_name)
+ install_core(args.prefix, args.core_name)
- if args.core_name in supported_cores():
+
+def install_core(prefix, core_name):
+ install_prefix = os.path.realpath(
+ os.path.expanduser(os.path.expandvars(prefix)))
+ install_dir = os.path.join(install_prefix, core_name)
+ cache_dir = os.path.join(install_prefix, ".cache", core_name)
+
+ if core_name in supported_cores():
shutil.rmtree(install_dir, ignore_errors=True)
os.makedirs(install_dir, exist_ok=True)
os.makedirs(cache_dir, exist_ok=True)
- if args.core_name == "teensy":
+ if core_name == "teensy":
if platform.system() == "Linux":
install_teensy_core_linux(install_prefix, install_dir, cache_dir)
elif platform.system() == "Darwin":
@@ -171,16 +175,16 @@
elif platform.system() == "Windows":
install_teensy_core_windows(install_prefix, install_dir, cache_dir)
apply_teensy_patches(install_dir)
- elif args.core_name == "adafruit-samd":
+ elif core_name == "adafruit-samd":
install_adafruit_samd_core(install_prefix, install_dir, cache_dir)
- elif args.core_name == "stm32duino":
+ elif core_name == "stm32duino":
install_stm32duino_core(install_prefix, install_dir, cache_dir)
- elif args.core_name == "arduino-samd":
+ elif core_name == "arduino-samd":
install_arduino_samd_core(install_prefix, install_dir, cache_dir)
else:
raise ArduinoCoreNotSupported(
"Invalid core '{}'. Supported cores: {}".format(
- args.core_name, ", ".join(supported_cores())))
+ core_name, ", ".join(supported_cores())))
def supported_cores():
@@ -322,9 +326,6 @@
def apply_teensy_patches(install_dir):
- # Remember where we are to construct relative paths for running `git apply`
- working_directory_path = Path(os.getcwd())
-
# On Mac the "hardware" directory is a symlink:
# ls -l third_party/arduino/cores/teensy/
# hardware -> Teensyduino.app/Contents/Java/hardware
@@ -339,9 +340,9 @@
# Apply each patch file.
for diff_path in patch_file_paths:
- file_operations.git_apply_patch(
- patch_root_path.relative_to(working_directory_path).as_posix(),
- diff_path.as_posix())
+ file_operations.git_apply_patch(patch_root_path.as_posix(),
+ diff_path.as_posix(),
+ unsafe_paths=True)
def install_arduino_samd_core(install_prefix: str, install_dir: str,
diff --git a/pw_arduino_build/py/pw_arduino_build/file_operations.py b/pw_arduino_build/py/pw_arduino_build/file_operations.py
index 8158a99..e534373 100644
--- a/pw_arduino_build/py/pw_arduino_build/file_operations.py
+++ b/pw_arduino_build/py/pw_arduino_build/file_operations.py
@@ -223,12 +223,17 @@
return json_file_options, file_path
-def git_apply_patch(root_directory, patch_file, ignore_whitespace=True):
+def git_apply_patch(root_directory,
+ patch_file,
+ ignore_whitespace=True,
+ unsafe_paths=False):
"""Use `git apply` to apply a diff file."""
_LOG.info("Applying Patch: %s", patch_file)
git_apply_command = ["git", "apply"]
if ignore_whitespace:
git_apply_command.append("--ignore-whitespace")
+ if unsafe_paths:
+ git_apply_command.append("--unsafe-paths")
git_apply_command += ["--directory", root_directory, patch_file]
subprocess.run(git_apply_command)
diff --git a/pw_package/py/BUILD.gn b/pw_package/py/BUILD.gn
index 0e4296e..309ab2f 100644
--- a/pw_package/py/BUILD.gn
+++ b/pw_package/py/BUILD.gn
@@ -23,6 +23,7 @@
"pw_package/git_repo.py",
"pw_package/package_manager.py",
"pw_package/packages/__init__.py",
+ "pw_package/packages/arduino_core.py",
"pw_package/packages/nanopb.py",
"pw_package/pigweed_packages.py",
]
diff --git a/pw_package/py/pw_package/package_manager.py b/pw_package/py/pw_package/package_manager.py
index f22845b..3f1cc80 100644
--- a/pw_package/py/pw_package/package_manager.py
+++ b/pw_package/py/pw_package/package_manager.py
@@ -66,8 +66,11 @@
_PACKAGES: Dict[str, Package] = {}
-def register(package_class: type) -> None:
- obj = package_class()
+def register(package_class: type, name: str = None) -> None:
+ if name:
+ obj = package_class(name)
+ else:
+ obj = package_class()
_PACKAGES[obj.name] = obj
@@ -167,7 +170,7 @@
return 0
def run(self, command: str, pkg_root: pathlib.Path, **kwargs) -> int:
- self._mgr = PackageManager(pkg_root)
+ self._mgr = PackageManager(pkg_root.resolve())
return getattr(self, command)(**kwargs)
diff --git a/pw_package/py/pw_package/packages/arduino_core.py b/pw_package/py/pw_package/packages/arduino_core.py
new file mode 100644
index 0000000..65c0c91
--- /dev/null
+++ b/pw_package/py/pw_package/packages/arduino_core.py
@@ -0,0 +1,91 @@
+# Copyright 2020 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+"""Install and check status of teensy-core."""
+
+import logging
+import re
+from pathlib import Path
+from typing import Sequence
+
+from pw_arduino_build import core_installer
+
+import pw_package.package_manager
+
+_LOG: logging.Logger = logging.getLogger(__name__)
+
+
+class ArduinoCore(pw_package.package_manager.Package):
+ """Install and check status of arduino cores."""
+ def __init__(self, core_name, *args, **kwargs):
+ super().__init__(*args, name=core_name, **kwargs)
+
+ def status(self, path: Path) -> bool:
+ return (path / 'hardware').is_dir()
+
+ def install(self, path: Path) -> None:
+ if self.status(path):
+ return
+ # Otherwise delete current version and reinstall
+ core_installer.install_core(path.parent.resolve().as_posix(),
+ path.name)
+
+ def info(self, path: Path) -> Sequence[str]:
+ packages_root = path.parent.resolve()
+ arduino_package_path = path
+ arduino_package_name = None
+
+ message = [
+ f'{self.name} currently installed in: {path}',
+ ]
+ # Make gn args sample copy/paste-able by omitting the starting timestamp
+ # and INF log on each line.
+ message_gn_args = [
+ 'Enable by running "gn args out" and adding these lines:',
+ f' pw_arduino_build_CORE_PATH = "{packages_root}"',
+ f' pw_arduino_build_CORE_NAME = "{self.name}"'
+ ]
+
+ # Search for first valid 'package/version' directory
+ for hardware_dir in [
+ path for path in (path / 'hardware').iterdir()
+ if path.is_dir()
+ ]:
+ if path.name in ["arduino", "tools"]:
+ continue
+ for subdir in [
+ path for path in hardware_dir.iterdir() if path.is_dir()
+ ]:
+ if subdir.name == 'avr' or re.match(r'[0-9.]+', subdir.name):
+ arduino_package_name = f'{hardware_dir.name}/{subdir.name}'
+ break
+
+ if arduino_package_name:
+ message_gn_args += [
+ f' pw_arduino_build_PACKAGE_NAME = "{arduino_package_name}"',
+ ' pw_arduino_build_BOARD = "BOARD_NAME"'
+ ]
+ message += ["\n".join(message_gn_args)]
+ message += [
+ 'Where BOARD_NAME is any supported board.',
+ # Have arduino_builder command appear on it's own line.
+ 'List available boards by running:\n'
+ ' arduino_builder '
+ f'--arduino-package-path {arduino_package_path} '
+ f'--arduino-package-name {arduino_package_name} list-boards'
+ ]
+ return message
+
+
+for arduino_core_name in core_installer.supported_cores():
+ pw_package.package_manager.register(ArduinoCore, name=arduino_core_name)
diff --git a/pw_package/py/pw_package/pigweed_packages.py b/pw_package/py/pw_package/pigweed_packages.py
index 3cca0ad..6c39266 100644
--- a/pw_package/py/pw_package/pigweed_packages.py
+++ b/pw_package/py/pw_package/pigweed_packages.py
@@ -17,6 +17,7 @@
from pw_package import package_manager
from pw_package.packages import nanopb
+from pw_package.packages import arduino_core # pylint: disable=unused-import
def initialize():
diff --git a/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py b/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
index e6ec62a..7b593b2 100755
--- a/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
+++ b/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
@@ -122,6 +122,19 @@
@filter_paths(endswith=_BUILD_EXTENSIONS)
+def gn_teensy_build(ctx: PresubmitContext):
+ build.install_package(ctx.package_root, 'teensy')
+ build.gn_gen(ctx.root,
+ ctx.output_dir,
+ pw_arduino_build_CORE_PATH='"{}"'.format(str(
+ ctx.package_root)),
+ pw_arduino_build_CORE_NAME='teensy',
+ pw_arduino_build_PACKAGE_NAME='teensy/avr',
+ pw_arduino_build_BOARD='teensy40')
+ build.ninja(ctx.output_dir, *_at_all_optimization_levels('arduino'))
+
+
+@filter_paths(endswith=_BUILD_EXTENSIONS)
def gn_qemu_build(ctx: PresubmitContext):
build.gn_gen(ctx.root, ctx.output_dir)
build.ninja(ctx.output_dir, *_at_all_optimization_levels('qemu'))
@@ -531,6 +544,9 @@
source_is_in_build_files,
python_checks,
build_env_setup,
+ # Skip gn_teensy_build if running on Windows. The Teensycore installer is
+ # an exe that requires an admin role.
+ gn_teensy_build if sys.platform in ['linux', 'darwin'] else (),
)
PROGRAMS = Programs(broken=BROKEN, quick=QUICK, full=FULL)
diff --git a/pw_sys_io_arduino/BUILD.gn b/pw_sys_io_arduino/BUILD.gn
index ee9b770..eb4b51c 100644
--- a/pw_sys_io_arduino/BUILD.gn
+++ b/pw_sys_io_arduino/BUILD.gn
@@ -22,7 +22,7 @@
include_dirs = [ "public" ]
}
-if (dir_pw_third_party_arduino != "") {
+if (pw_arduino_build_CORE_PATH != "") {
pw_source_set("pw_sys_io_arduino") {
remove_configs = [ "$dir_pw_build:strict_warnings" ]
public_configs = [ ":default_config" ]
@@ -31,7 +31,7 @@
deps = [
"$dir_pw_sys_io:default_putget_bytes",
"$dir_pw_sys_io:facade",
- "$dir_pw_third_party_arduino:arduino_core_sources",
+ "$dir_pw_third_party/arduino:arduino_core_sources",
]
sources = [ "sys_io_arduino.cc" ]
}
diff --git a/pw_tokenizer/BUILD.gn b/pw_tokenizer/BUILD.gn
index d0df948..d4f3708 100644
--- a/pw_tokenizer/BUILD.gn
+++ b/pw_tokenizer/BUILD.gn
@@ -208,7 +208,7 @@
]
deps = [ ":pw_tokenizer" ]
- if (dir_pw_third_party_arduino != "") {
+ if (pw_arduino_build_CORE_PATH != "") {
remove_configs = [ "$dir_pw_build:strict_warnings" ]
}
}
diff --git a/targets/arduino/BUILD b/targets/arduino/BUILD
index 458ddff..7514235 100644
--- a/targets/arduino/BUILD
+++ b/targets/arduino/BUILD
@@ -30,4 +30,13 @@
"//pw_preprocessor",
"//pw_sys_io_arduino",
],
+)
+
+pw_cc_library(
+ name = "system_rpc_server",
+ srcs = ["system_rpc_server.cc"],
+ deps = [
+ "//pw_rpc/system_server:facade",
+ "//pw_hdlc:pw_rpc",
+ ],
)
\ No newline at end of file
diff --git a/targets/arduino/BUILD.gn b/targets/arduino/BUILD.gn
index 1949252..7217dff 100644
--- a/targets/arduino/BUILD.gn
+++ b/targets/arduino/BUILD.gn
@@ -22,7 +22,7 @@
sources = [ "target_docs.rst" ]
}
-if (dir_pw_third_party_arduino != "") {
+if (pw_arduino_build_CORE_PATH != "") {
import("target_toolchains.gni")
generate_toolchains("target_toolchains") {
@@ -91,13 +91,24 @@
sources = [ "init.cc" ]
public_deps = [
"$dir_pw_sys_io_arduino",
- "$dir_pw_third_party_arduino:arduino_core_sources",
+ "$dir_pw_third_party/arduino:arduino_core_sources",
]
deps = [
"$dir_pw_arduino_build:arduino_init.facade",
"$dir_pw_preprocessor",
]
}
+
+ pw_source_set("system_rpc_server") {
+ deps = [
+ "$dir_pw_hdlc:pw_rpc",
+ "$dir_pw_hdlc:rpc_channel_output",
+ "$dir_pw_rpc/system_server:facade",
+ "$dir_pw_stream:sys_io_stream",
+ dir_pw_log,
+ ]
+ sources = [ "system_rpc_server.cc" ]
+ }
}
} else {
config("arduino_build") {
diff --git a/targets/arduino/system_rpc_server.cc b/targets/arduino/system_rpc_server.cc
new file mode 100644
index 0000000..00b9bf9
--- /dev/null
+++ b/targets/arduino/system_rpc_server.cc
@@ -0,0 +1,70 @@
+// Copyright 2020 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#include <cstddef>
+
+#include "pw_hdlc/rpc_channel.h"
+#include "pw_hdlc/rpc_packets.h"
+#include "pw_log/log.h"
+#include "pw_rpc_system_server/rpc_server.h"
+#include "pw_stream/sys_io_stream.h"
+
+namespace pw::rpc::system_server {
+namespace {
+
+constexpr size_t kMaxTransmissionUnit = 256;
+
+// Used to write HDLC data to pw::sys_io.
+stream::SysIoWriter writer;
+stream::SysIoReader reader;
+
+// Set up the output channel for the pw_rpc server to use.
+hdlc::RpcChannelOutputBuffer<kMaxTransmissionUnit> hdlc_channel_output(
+ writer, pw::hdlc::kDefaultRpcAddress, "HDLC channel");
+Channel channels[] = {pw::rpc::Channel::Create<1>(&hdlc_channel_output)};
+rpc::Server server(channels);
+
+} // namespace
+
+void Init() {
+ // Send log messages to HDLC address 1. This prevents logs from interfering
+ // with pw_rpc communications.
+ pw::log_basic::SetOutput([](std::string_view log) {
+ pw::hdlc::WriteUIFrame(1, std::as_bytes(std::span(log)), writer);
+ });
+}
+
+rpc::Server& Server() { return server; }
+
+Status Start() {
+ // Declare a buffer for decoding incoming HDLC frames.
+ std::array<std::byte, kMaxTransmissionUnit> input_buffer;
+ hdlc::Decoder decoder(input_buffer);
+
+ while (true) {
+ std::byte byte;
+ Status ret_val = pw::sys_io::ReadByte(&byte);
+ if (!ret_val.ok()) {
+ return ret_val;
+ }
+ if (auto result = decoder.Process(byte); result.ok()) {
+ hdlc::Frame& frame = result.value();
+ if (frame.address() == hdlc::kDefaultRpcAddress) {
+ server.ProcessPacket(frame.data(), hdlc_channel_output);
+ }
+ }
+ }
+}
+
+} // namespace pw::rpc::system_server
diff --git a/targets/arduino/target_docs.rst b/targets/arduino/target_docs.rst
index 5db55e8..a6f6b0b 100644
--- a/targets/arduino/target_docs.rst
+++ b/targets/arduino/target_docs.rst
@@ -43,8 +43,7 @@
=====
You must first install an Arduino core or let Pigweed know where you have cores
-installed using the ``dir_pw_third_party_arduino`` and ``arduino_package_path``
-build arguments.
+installed using the ``pw_arduino_build_CORE_PATH`` build arg.
Installing Arduino Cores
------------------------
@@ -66,10 +65,12 @@
.. code:: sh
- gn gen out --args='dir_pw_third_party_arduino="//third_party/arduino"
- arduino_core_name="teensy"
- arduino_board="teensy40"
- arduino_menu_options=["menu.usb.serial", "menu.keys.en-us"]'
+ gn gen out --args='
+ pw_arduino_build_CORE_PATH="//third_party/arduino/cores"
+ pw_arduino_build_CORE_NAME="teensy"
+ pw_arduino_build_PACKAGE_NAME="teensy/avr"
+ pw_arduino_build_BOARD="teensy40"
+ pw_arduino_build_MENU_OPTIONS=["menu.usb.serial", "menu.keys.en-us"]'
On a Windows machine it's easier to run:
@@ -81,10 +82,11 @@
.. code:: text
- dir_pw_third_party_arduino="//third_party/arduino"
- arduino_core_name="teensy"
- arduino_board="teensy40"
- arduino_menu_options=["menu.usb.serial", "menu.keys.en-us"]
+ pw_arduino_build_CORE_PATH = "//third_party/arduino/cores"
+ pw_arduino_build_CORE_NAME = "teensy"
+ pw_arduino_build_PACKAGE_NAME="teensy/avr"
+ pw_arduino_build_BOARD = "teensy40"
+ pw_arduino_build_MENU_OPTIONS = ["menu.usb.serial", "menu.keys.en-us"]
Save the file and close the text editor.
@@ -112,7 +114,7 @@
teensy31 Teensy 3.2 / 3.1
You may wish to set different arduino build options in
-``arduino_menu_options``. Run this to see what's available for your core:
+``pw_arduino_build_MENU_OPTIONS``. Run this to see what's available for your core:
.. code:: sh
@@ -161,10 +163,11 @@
#!/bin/bash
gn gen out --export-compile-commands \
- --args='dir_pw_third_party_arduino="//third_party/arduino"
- arduino_core_name="teensy"
- arduino_board="teensy40"
- arduino_menu_options=["menu.usb.serial", "menu.keys.en-us"]' && \
+ --args='pw_arduino_build_CORE_PATH="//third_party/arduino/cores"
+ pw_arduino_build_CORE_NAME="teensy"
+ pw_arduino_build_PACKAGE_NAME="teensy/avr"
+ pw_arduino_build_BOARD="teensy40"
+ pw_arduino_build_MENU_OPTIONS=["menu.usb.serial", "menu.keys.en-us"]' && \
ninja -C out arduino
for f in $(find out/arduino_debug/obj/ -iname "*.elf"); do
@@ -214,9 +217,7 @@
_library_args = [
"--library-path",
- rebase_path(
- "$dir_pw_third_party_arduino/cores/teensy/hardware/teensy/avr/libraries"
- ),
+ rebase_path(arduino_core_library_path),
"--library-names",
"Time",
"Wire",
@@ -250,10 +251,8 @@
[ "--library-include-dirs" ],
"list lines")
- # Required if using Arduino.h and any Arduino API functions
- if (dir_pw_third_party_arduino != "") {
- remove_configs = [ "$dir_pw_build:strict_warnings" ]
- deps += [ "$dir_pw_third_party_arduino:arduino_core_sources" ]
- }
+ # Required for using Arduino.h and any Arduino API functions
+ remove_configs = [ "$dir_pw_build:strict_warnings" ]
+ deps += [ "$dir_pw_third_party/arduino:arduino_core_sources" ]
}
diff --git a/targets/arduino/target_toolchains.gni b/targets/arduino/target_toolchains.gni
index e7cad07..78d3e8e 100644
--- a/targets/arduino/target_toolchains.gni
+++ b/targets/arduino/target_toolchains.gni
@@ -45,6 +45,8 @@
pw_assert_BACKEND = dir_pw_assert_basic
pw_log_BACKEND = dir_pw_log_basic
pw_sys_io_BACKEND = dir_pw_sys_io_arduino
+ pw_rpc_system_server_BACKEND =
+ "$dir_pigweed/targets/arduino:system_rpc_server"
pw_arduino_build_INIT_BACKEND = "$dir_pigweed/targets/arduino:pre_init"
current_cpu = "arm"
diff --git a/third_party/arduino/BUILD.gn b/third_party/arduino/BUILD.gn
index da82742..36a8247 100644
--- a/third_party/arduino/BUILD.gn
+++ b/third_party/arduino/BUILD.gn
@@ -17,7 +17,7 @@
import("$dir_pw_arduino_build/arduino.gni")
import("$dir_pw_build/target_types.gni")
-if (dir_pw_third_party_arduino != "") {
+if (pw_arduino_build_CORE_PATH != "") {
pw_source_set("arduino_core_sources") {
remove_configs = [ "$dir_pw_build:strict_warnings" ]