vesper/Makefile.toml

320 lines
10 KiB
TOML

#
# SPDX-License-Identifier: BlueOak-1.0.0
#
# Copyright (c) Berkus Decker <berkus+vesper@metta.systems>
#
# Global workspace configuration
#
[config]
min_version = "0.32.0"
default_to_workspace = true
skip_core_tasks = true
[env]
DEFAULT_TARGET = "aarch64-vesper-metta"
#
# === User-configurable ===
#
# Pass TARGET env var if it does not match the default target above.
TARGET = { value = "${DEFAULT_TARGET}", condition = { env_not_set = ["TARGET"] } }
# Name of the target board "rpi3" or "rpi4"
TARGET_BOARD = { value = "rpi4", condition = { env_not_set = ["TARGET_BOARD"] } }
# Name of the DTB file for target board configuration, use bcm2710-rpi-3-b-plus.dtb for RasPi3B+
TARGET_DTB = { value = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/targets/bcm2711-rpi-4-b.dtb", condition = { env_not_set = ["TARGET_DTB"] } }
# AArch64 QEMU binary
QEMU = { value = "qemu-system-aarch64", condition = { env_not_set = ["QEMU"] } }
# QEMU machine type, defaults to raspi3b but CI runners override it due to ancient QEMU versions they use.
QEMU_MACHINE = { value = "raspi3b", condition = { env_not_set = ["QEMU_MACHINE"] } }
# An aarch64-enabled GDB
GDB = { value = "/usr/local/opt/gdb/HEAD-a2c58332-aarch64/bin/aarch64-unknown-elf-gdb", condition = { env_not_set = ["GDB"] } }
# OpenOCD with JLink support
# (RTT patch from http://openocd.zylin.com/#/c/4055/11 has already been merged into main line)
OPENOCD = { value = "/usr/local/opt/openocd/4d6519593-rtt/bin/openocd", condition = { env_not_set = ["OPENOCD"] } }
# Mounted sdcard partition path
VOLUME = { value = "/Volumes/BOOT", condition = { env_not_set = ["VOLUME"] } }
#
# === Automatic ===
#
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
RUST_STD = "-Zbuild-std=compiler_builtins,core,alloc -Zbuild-std-features=compiler-builtins-mem"
TARGET_JSON = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/targets/${TARGET}.json"
PLATFORM_TARGET="--target=${TARGET_JSON} --features=${TARGET_FEATURES}"
DEVICE_FEATURES = "noserial"
QEMU_FEATURES = "qemu,rpi3"
# Working objcopy from `brew install aarch64-elf-binutils`
#OBJCOPY = "/opt/homebrew/Cellar/aarch64-elf-binutils/2.40/bin/aarch64-elf-objcopy" # Part of `cargo objcopy` in cargo-binutils
# LLVM's objcopy, usually full of bugs like https://github.com/llvm/llvm-project/issues/58407
OBJCOPY = "rust-objcopy" # Part of `cargo objcopy` in cargo-binutils
OBJCOPY_PARAMS = "--strip-all -O binary"
NM = "rust-nm" # Part of `cargo nm` in cargo-binutils
UTILS_CONTAINER = "andrerichter/raspi3-utils"
DOCKER_CMD = "docker run -it --rm -v ${PWD}:/work -w /work -p 5900:5900"
QEMU_CONTAINER_CMD = "qemu-system-aarch64"
#
# Could additionally use -nographic to disable GUI -- this shall be useful for automated tests.
#
# QEMU has renamed the RasPi machines since version 6.2.0, use just `raspi3` for previous versions.
QEMU_OPTS = "-M ${QEMU_MACHINE} -semihosting"
QEMU_ARM_TRACE_OPTS = "arm_gt_cntvoff_write,arm_gt_ctl_write,arm_gt_cval_write,arm_gt_imask_toggle,arm_gt_recalc,arm_gt_recalc_disabled,arm_gt_tval_write,armsse_cpu_pwrctrl_read,armsse_cpu_pwrctrl_write,armsse_cpuid_read,armsse_cpuid_write,armsse_mhu_read,armsse_mhu_write"
QEMU_BCM_TRACE_OPTS = "bcm2835_cprman_read,bcm2835_cprman_write,bcm2835_cprman_write_invalid_magic,bcm2835_ic_set_cpu_irq,bcm2835_ic_set_gpu_irq,bcm2835_mbox_irq,bcm2835_mbox_property,bcm2835_mbox_read,bcm2835_mbox_write,bcm2835_sdhost_edm_change,bcm2835_sdhost_read,bcm2835_sdhost_update_irq,bcm2835_sdhost_write,bcm2835_systmr_irq_ack,bcm2835_systmr_read,bcm2835_systmr_run,bcm2835_systmr_timer_expired,bcm2835_systmr_write"
QEMU_TRACE_OPTS = "trace:${QEMU_ARM_TRACE_OPTS},${QEMU_BCM_TRACE_OPTS}" # @todo trace: prefix for each opt
QEMU_DISASM_OPTS = "-d in_asm,unimp,int,mmu,cpu_reset,guest_errors,nochain,plugin"
QEMU_SERIAL_OPTS = "-serial stdio -serial pty"
QEMU_TESTS_OPTS = "-nographic"
# For gdb connection:
# - if this is set, MUST have gdb attached for SYS_WRITE0 to work, otherwise QEMU will crash.
# - port 5555 used to match JLink configuration, so we can reuse the same GDB command for both QEMU and JTAG.
QEMU_GDB_OPTS = "-gdb tcp::5555 -S"
GDB_CONNECT_FILE = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${TARGET}/gdb-connect"
KERNEL_ELF = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${TARGET}/release/nucleus"
KERNEL_BIN = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/nucleus.bin"
CHAINBOOT_SERIAL = "/dev/tty.SLAB_USBtoUART"
CHAINBOOT_BAUD = 115200
#
# === Base reusable commands ===
#
[tasks.default]
alias = "all"
[tasks.all]
dependencies = ["kernel-binary", "chainboot", "chainofcommand", "ttt"]
[tasks.xtool-modules]
workspace = false
command = "cargo"
args = ["modules", "tree"]
# Disable build in the root by default.
[tasks.build]
workspace = false
alias = "empty"
# Run a target build with current platform configuration.
[tasks.build-target]
workspace = false
command = "cargo"
args = ["build", "@@split(PLATFORM_TARGET, )", "@@split(RUST_STD, )", "--release"]
[tasks.build-device]
workspace = false
env = { "TARGET_FEATURES" = "${TARGET_BOARD}" }
run_task = "build-target"
[tasks.build-qemu]
workspace = false
env = { "TARGET_FEATURES" = "${QEMU_FEATURES}" }
run_task = "build-target"
[tasks.qemu-runner]
workspace = false
dependencies = ["build-qemu", "kernel-binary"]
env = { "TARGET_FEATURES" = "${QEMU_FEATURES}" }
script = [
"echo 🚜 Run QEMU ${QEMU_OPTS} ${QEMU_RUNNER_OPTS} with ${KERNEL_BIN}\n\n\n",
"rm -f qemu.log",
"${QEMU} ${QEMU_OPTS} ${QEMU_RUNNER_OPTS} -dtb ${TARGET_DTB} -kernel ${KERNEL_BIN} 2>&1 | tee qemu.log",
"echo \n\n"
]
[tasks.xtool-expand-target]
workspace = false
env = { "TARGET_FEATURES" = "" }
command = "cargo"
args = ["expand", "@@split(PLATFORM_TARGET, )", "--release"]
[tasks.test]
env = { "TARGET_FEATURES" = "${QEMU_FEATURES}" }
command = "cargo"
args = ["test", "@@split(PLATFORM_TARGET, )", "@@split(RUST_STD, )"]
[tasks.docs]
env = { "TARGET_FEATURES" = "" }
command = "cargo"
args = ["doc", "--open", "--no-deps", "@@split(PLATFORM_TARGET, )"]
[tasks.xtool-clippy]
workspace = false
env = { "TARGET_FEATURES" = "rpi3", "CLIPPY_FEATURES" = { value = "--features=${CLIPPY_FEATURES}", condition = { env_set = ["CLIPPY_FEATURES"] } } }
command = "cargo"
args = ["clippy", "@@split(PLATFORM_TARGET, )", "@@split(RUST_STD, )", "@@remove-empty(CLIPPY_FEATURES)", "--", "--deny", "warnings", "--allow", "deprecated"]
# These tasks are written in cargo-make's own script to make it portable across platforms (no `basename` on Windows)
## Copy and prepare a given ELF file. Convert to binary output format.
[tasks.build-custom-binary]
workspace = false
env = { "BINARY_FILE" = "${BINARY_FILE}" }
script_runner = "@duckscript"
script = [
'''
binaryFile = basename ${BINARY_FILE}
outElf = set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${binaryFile}.elf
outBin = set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${binaryFile}.bin
cp ${BINARY_FILE} ${outElf}
exec --fail-on-error ${OBJCOPY} %{OBJCOPY_PARAMS} ${BINARY_FILE} ${outBin}
elfSize = get_file_size ${outElf}
binSize = get_file_size ${outBin}
echo 🔄 Processing ${BINARY_FILE}:
echo 🔄 Copied ${binaryFile} to ${outElf} (${elfSize} bytes)
echo 💫 Converted ${binaryFile} to ${outBin} (${binSize} bytes)
'''
]
install_crate = { crate_name = "cargo-binutils", binary = "rust-objcopy", test_arg = ["--help"] }
## Copy and prepare binary with tests.
[tasks.test-binary]
workspace = false
env = { "BINARY_FILE" = "${CARGO_MAKE_TASK_ARGS}" }
run_task = "custom-binary"
## Run binary with tests in QEMU.
[tasks.test-runner]
workspace = false
dependencies = ["test-binary"]
script_runner = "@duckscript"
script = [
'''
binaryFile = basename ${CARGO_MAKE_TASK_ARGS}
echo 🏎️ Run QEMU %{QEMU_OPTS} %{QEMU_TESTS_OPTS} with target/${binaryFile}.bin
exec --fail-on-error ${QEMU} %{QEMU_OPTS} %{QEMU_TESTS_OPTS} -dtb ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/targets/bcm2710-rpi-3-b-plus.dtb -kernel ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${binaryFile}.bin
'''
]
## Generate GDB startup configuration file.
[tasks.gdb-config]
workspace = false
script_runner = "@duckscript"
script = [
'''
writefile ${GDB_CONNECT_FILE} "target extended-remote :5555\n"
appendfile ${GDB_CONNECT_FILE} "break *0x80000\n"
appendfile ${GDB_CONNECT_FILE} "break kernel_init\n"
appendfile ${GDB_CONNECT_FILE} "break kernel_main\n"
echo 🖌️ Generated GDB config file
'''
]
#appendfile ${GDB_CONNECT_FILE} "continue\n"
## Generate zellij configuration file.
[tasks.zellij-config]
workspace = false
dependencies = ["build-qemu", "kernel-binary"]
script_runner = "@duckscript"
env = { "ZELLIJ_CONFIG_FILE" = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/emulation/zellij-config.sh" }
script = [
'''
writefile ${ZELLIJ_CONFIG_FILE} "QEMU=${QEMU}\n"
appendfile ${ZELLIJ_CONFIG_FILE} "QEMU_OPTS=\"${QEMU_OPTS}\"\n"
appendfile ${ZELLIJ_CONFIG_FILE} "QEMU_RUNNER_OPTS=${QEMU_RUNNER_OPTS}\n"
appendfile ${ZELLIJ_CONFIG_FILE} "CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}\n"
appendfile ${ZELLIJ_CONFIG_FILE} "TARGET_DTB=${TARGET_DTB}\n"
appendfile ${ZELLIJ_CONFIG_FILE} "KERNEL_BIN=${KERNEL_BIN}\n"
'''
]
install_crate = { crate_name = "zellij", binary = "zellij", test_arg = ["--help"] }
[tasks.openocd]
workspace = false
script = [
"${OPENOCD} -f interface/jlink.cfg -f ../ocd/${TARGET_BOARD}_target.cfg"
]
[tasks.sdeject]
workspace = false
dependencies = ["sdcard"]
script = [
"diskutil ejectAll ${VOLUME}"
]
[tasks.qemu]
alias = "empty"
#
# Per-workspace commands, disabled in the root by efault.
# TODO: defined only in sub-modules with workspace = false
#
# Tasks for nucleus
#[tasks.build-kernel-binary]
#alias = "empty"
# Tasks for chainboot
#[tasks.chainboot]
#alias = "empty"
# sdeject
#[tasks.cb-eject]
#alias = "empty"
# Tasks for chainofcommand
#[tasks.chainofcommand]
#alias = "empty"
# Tasks for ttt
#[tasks.ttt]
#alias = "empty"
# Other tasks
#[tasks.gdb]
#alias = "empty"
#[tasks.gdb-cb]
#alias = "empty"
#[tasks.sdcard]
#alias = "empty"
#[tasks.qemu-gdb]
#alias = "empty"
#[tasks.qemu-cb]
#alias = "empty"
#[tasks.qemu-cb-gdb]
#alias = "empty"
#[tasks.xtool-hopper]
#alias = "empty"
#
#[tasks.xtool-nm]
#alias = "empty"
#[tasks.zellij-cb]
#alias = "empty"
#[tasks.zellij-cb-gdb]
#alias = "empty"
#[tasks.zellij-nucleus]
#alias = "empty"
## Target dependencies:
#[tasks.kernel-binary]
#alias = "empty"
#[tasks.chainboot-binary]
#alias = "empty"
#
#[tasks.chainofcommand-binary]
#alias = "empty"
#[tasks.ttt-binary]
#alias = "empty"