refactor: 📦 Split kernel into machine and nucleus
Move openocd task to upper level and remove kernel build dependency - the qemu runner doesn't really depend on it.
This commit is contained in:
parent
b26d61cb67
commit
4cdeeb8556
|
@ -1,16 +1,12 @@
|
|||
[unstable]
|
||||
build-std = ["core", "compiler_builtins", "alloc"]
|
||||
build-std-features = ["compiler-builtins-mem"]
|
||||
|
||||
[build]
|
||||
# https://internals.rust-lang.org/t/evaluating-pipelined-rustc-compilation/10199/12
|
||||
pipelining = true
|
||||
|
||||
[target.aarch64-vesper-metta]
|
||||
rustflags = [
|
||||
"-C", "target-feature=-fp-armv8",
|
||||
"-C", "target-cpu=cortex-a53",
|
||||
"-C", "embed-bitcode=yes",
|
||||
"-Z", "macro-backtrace",
|
||||
"-C", "target-feature=-fp-armv8",
|
||||
"-C", "target-cpu=cortex-a53",
|
||||
"-C", "embed-bitcode=yes",
|
||||
"-Z", "macro-backtrace",
|
||||
]
|
||||
runner = "cargo make test-runner"
|
||||
|
|
|
@ -44,6 +44,38 @@ dependencies = [
|
|||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "machine"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cortex-a",
|
||||
"qemu-exit",
|
||||
"r0",
|
||||
"snafu",
|
||||
"tock-registers",
|
||||
"usize_conversions",
|
||||
"ux",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nucleus"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cortex-a",
|
||||
"machine",
|
||||
"r0",
|
||||
"snafu",
|
||||
"tock-registers",
|
||||
"usize_conversions",
|
||||
"ux",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.27"
|
||||
|
@ -76,9 +108,9 @@ checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
|||
|
||||
[[package]]
|
||||
name = "snafu"
|
||||
version = "0.7.0-beta.2"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c25527526a3f0e26586508fc008e03929bc74c64fb00f34c6b22922bf39eaca"
|
||||
checksum = "2eba135d2c579aa65364522eb78590cdf703176ef71ad4c32b00f58f7afb2df5"
|
||||
dependencies = [
|
||||
"doc-comment",
|
||||
"snafu-derive",
|
||||
|
@ -86,9 +118,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "snafu-derive"
|
||||
version = "0.7.0-beta.2"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6cdd4a5d0765ccc385665731d230efeb3b7e43df0770b625161da46bd5c9247"
|
||||
checksum = "7a7fe9b0669ef117c5cabc5549638528f36771f058ff977d7689deb517833a75"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
|
@ -136,19 +168,3 @@ name = "ux"
|
|||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88dfeb711b61ce620c0cb6fd9f8e3e678622f0c971da2a63c4b3e25e88ed012f"
|
||||
|
||||
[[package]]
|
||||
name = "vesper"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cortex-a",
|
||||
"qemu-exit",
|
||||
"r0",
|
||||
"snafu",
|
||||
"tock-registers",
|
||||
"usize_conversions",
|
||||
"ux",
|
||||
]
|
||||
|
|
2
Justfile
2
Justfile
|
@ -3,7 +3,7 @@ _default:
|
|||
|
||||
# Build and run kernel in QEMU with serial port emulation
|
||||
zellij:
|
||||
cargo make zellij-config
|
||||
cargo make zellij-nucleus
|
||||
zellij --layout-path emulation/layout.zellij
|
||||
|
||||
# Build and run kernel in QEMU
|
||||
|
|
|
@ -38,7 +38,9 @@ VOLUME = { value = "/Volumes/BOOT", condition = { env_not_set = ["VOLUME"] } }
|
|||
#
|
||||
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
|
||||
|
||||
RUST_LIBS = "-Z build-std=compiler_builtins,core,alloc -Z build-std-features=compiler-builtins-mem"
|
||||
TARGET_JSON = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/targets/${TARGET}.json"
|
||||
PLATFORM_TARGET="--target=${TARGET_JSON} --features=${TARGET_FEATURES} ${RUST_LIBS}"
|
||||
|
||||
DEVICE_FEATURES = "noserial"
|
||||
QEMU_FEATURES = "qemu"
|
||||
|
@ -65,8 +67,8 @@ 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}/kernel8"
|
||||
KERNEL_BIN = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/kernel8.img"
|
||||
KERNEL_ELF = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${TARGET}/release/nucleus"
|
||||
KERNEL_BIN = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/nucleus.bin"
|
||||
|
||||
[tasks.default]
|
||||
alias = "all"
|
||||
|
@ -78,6 +80,83 @@ dependencies = ["kernel-binary"]
|
|||
command = "cargo"
|
||||
args = ["modules", "tree"]
|
||||
|
||||
[tasks.build]
|
||||
env = { "TARGET_FEATURES" = "" }
|
||||
command = "cargo"
|
||||
args = ["build", "@@split(PLATFORM_TARGET, )", "--release"]
|
||||
|
||||
[tasks.build-qemu]
|
||||
env = { "TARGET_FEATURES" = "${QEMU_FEATURES}" }
|
||||
command = "cargo"
|
||||
args = ["build", "@@split(PLATFORM_TARGET, )", "--release"]
|
||||
|
||||
[tasks.expand]
|
||||
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, )"]
|
||||
|
||||
[tasks.docs]
|
||||
env = { "TARGET_FEATURES" = "" }
|
||||
command = "cargo"
|
||||
args = ["doc", "--open", "--no-deps", "@@split(PLATFORM_TARGET, )"]
|
||||
|
||||
[tasks.clippy]
|
||||
env = { "TARGET_FEATURES" = "", "CLIPPY_FEATURES" = { value = "--features=${CLIPPY_FEATURES}", condition = { env_set = ["CLIPPY_FEATURES"] } } }
|
||||
command = "cargo"
|
||||
args = ["clippy", "@@split(PLATFORM_TARGET, )", "@@remove-empty(CLIPPY_FEATURES)", "--", "-D", "warnings"]
|
||||
|
||||
# These tasks are written in cargo-make's own script to make it portable across platforms (no `basename` on Windows)
|
||||
[tasks.custom-binary]
|
||||
env = { "BINARY_FILE" = "${BINARY_FILE}" }
|
||||
script_runner = "@duckscript"
|
||||
script = [
|
||||
'''
|
||||
binaryFile = basename ${BINARY_FILE}
|
||||
cp ${BINARY_FILE} ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${binaryFile}.elf
|
||||
exec --fail-on-error ${OBJCOPY} %{OBJCOPY_PARAMS} ${BINARY_FILE} ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${binaryFile}.bin
|
||||
'''
|
||||
]
|
||||
install_crate = { crate_name = "cargo-binutils", binary = "rust-objcopy", test_arg = ["--help"] }
|
||||
|
||||
[tasks.test-binary]
|
||||
env = { "BINARY_FILE" = "${CARGO_MAKE_TASK_ARGS}" }
|
||||
run_task = "custom-binary"
|
||||
|
||||
[tasks.test-runner]
|
||||
dependencies = ["test-binary"]
|
||||
script_runner = "@duckscript"
|
||||
script = [
|
||||
'''
|
||||
binaryFile = basename ${CARGO_MAKE_TASK_ARGS}
|
||||
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
|
||||
'''
|
||||
]
|
||||
|
||||
[tasks.zellij-config]
|
||||
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} "KERNEL_BIN=${KERNEL_BIN}\n"
|
||||
'''
|
||||
]
|
||||
install_crate = { crate_name = "zellij", binary = "zellij", test_arg = ["--help"] }
|
||||
|
||||
[tasks.openocd]
|
||||
script = [
|
||||
"${OPENOCD} -f interface/jlink.cfg -f ../ocd/${TARGET_BOARD}_target.cfg"
|
||||
]
|
||||
|
||||
[tasks.sdeject]
|
||||
dependencies = ["sdcard"]
|
||||
script = [
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
[package]
|
||||
name = "machine"
|
||||
version = "0.0.1"
|
||||
authors = ["Berkus Decker <berkus+vesper@metta.systems>"]
|
||||
description = "Vesper nanokernel shared code library."
|
||||
documentation = "https://docs.metta.systems/vesper"
|
||||
homepage = "https://github.com/metta-systems/vesper"
|
||||
repository = "https://github.com/metta-systems/vesper"
|
||||
readme = "README.md"
|
||||
license = "BlueOak-1.0.0"
|
||||
categories = ["no-std", "embedded", "os"]
|
||||
publish = false
|
||||
edition = "2021"
|
||||
|
||||
[badges]
|
||||
maintenance = { status = "experimental" }
|
||||
|
||||
[features]
|
||||
noserial = []
|
||||
# Enable JTAG debugging of kernel - enable jtag helpers and
|
||||
# block waiting for JTAG probe attach at the start of kernel main.
|
||||
jtag = []
|
||||
# Build for running under QEMU with semihosting, so various halt/reboot options would for example quit QEMU instead.
|
||||
qemu = []
|
||||
|
||||
[dependencies]
|
||||
r0 = "1.0"
|
||||
qemu-exit = "3.0"
|
||||
cortex-a = "7.0"
|
||||
tock-registers = "0.7"
|
||||
ux = { version = "0.1", default-features = false }
|
||||
usize_conversions = "0.2"
|
||||
bit_field = "0.10"
|
||||
bitflags = "1.3"
|
||||
cfg-if = "1.0"
|
||||
snafu = { version = "0.7", default-features = false }
|
|
@ -7,6 +7,4 @@ mod asid;
|
|||
mod phys_addr;
|
||||
mod virt_addr;
|
||||
|
||||
pub use asid::*;
|
||||
pub use phys_addr::*;
|
||||
pub use virt_addr::*;
|
||||
pub use {asid::*, phys_addr::*, virt_addr::*};
|
|
@ -13,18 +13,12 @@
|
|||
|
||||
use {
|
||||
crate::{
|
||||
arch::aarch64::memory::{
|
||||
get_virt_addr_properties, AttributeFields, /*FrameAllocator, PhysAddr, VirtAddr,*/
|
||||
},
|
||||
arch::aarch64::memory::{get_virt_addr_properties, AttributeFields},
|
||||
println,
|
||||
},
|
||||
// bitflags::bitflags,
|
||||
core::{
|
||||
// convert::TryInto,
|
||||
// fmt,
|
||||
marker::PhantomData,
|
||||
ops::{Index, IndexMut},
|
||||
// ptr::Unique,
|
||||
},
|
||||
cortex_a::{
|
||||
asm::barrier,
|
||||
|
@ -35,12 +29,10 @@ use {
|
|||
interfaces::{ReadWriteable, Readable, Writeable},
|
||||
register_bitfields,
|
||||
},
|
||||
// ux::*,
|
||||
};
|
||||
|
||||
mod mair {
|
||||
use cortex_a::registers::MAIR_EL1;
|
||||
use tock_registers::interfaces::Writeable;
|
||||
use {cortex_a::registers::MAIR_EL1, tock_registers::interfaces::Writeable};
|
||||
|
||||
/// Setup function for the MAIR_EL1 register.
|
||||
pub fn set_up() {
|
|
@ -13,8 +13,7 @@ use {
|
|||
mod addr;
|
||||
pub mod mmu;
|
||||
|
||||
pub use addr::PhysAddr;
|
||||
pub use addr::VirtAddr;
|
||||
pub use addr::{PhysAddr, VirtAddr};
|
||||
|
||||
// aarch64 granules and page sizes howto:
|
||||
// https://stackoverflow.com/questions/34269185/simultaneous-existence-of-different-sized-pages-on-aarch64
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::platform;
|
||||
use core::fmt;
|
||||
use {crate::platform, core::fmt};
|
||||
|
||||
/// A trait that must be implemented by devices that are candidates for the
|
||||
/// global console.
|
|
@ -0,0 +1,55 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(format_args_nl)]
|
||||
#![feature(nonnull_slice_from_raw_parts)]
|
||||
#![feature(custom_test_frameworks)]
|
||||
#![test_runner(crate::tests::test_runner)]
|
||||
#![reexport_test_harness_main = "test_main"]
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
#![allow(clippy::enum_variant_names)]
|
||||
#![allow(clippy::nonstandard_macro_braces)] // https://github.com/shepmaster/snafu/issues/296
|
||||
#![allow(missing_docs)] // Temp: switch to deny
|
||||
#![deny(warnings)]
|
||||
|
||||
#[cfg(not(target_arch = "aarch64"))]
|
||||
use architecture_not_supported_sorry;
|
||||
|
||||
/// Architecture-specific code.
|
||||
#[macro_use]
|
||||
pub mod arch;
|
||||
|
||||
pub use arch::*;
|
||||
|
||||
pub mod devices;
|
||||
pub mod macros;
|
||||
mod mm;
|
||||
pub mod panic;
|
||||
pub mod platform;
|
||||
pub mod qemu;
|
||||
mod sync;
|
||||
pub mod tests;
|
||||
pub mod write_to;
|
||||
|
||||
/// The global console. Output of the kernel print! and println! macros goes here.
|
||||
pub static CONSOLE: sync::NullLock<devices::Console> = sync::NullLock::new(devices::Console::new());
|
||||
|
||||
/// The global allocator for DMA-able memory. That is, memory which is tagged
|
||||
/// non-cacheable in the page tables.
|
||||
static DMA_ALLOCATOR: sync::NullLock<mm::BumpAllocator> =
|
||||
sync::NullLock::new(mm::BumpAllocator::new(
|
||||
// @todo Init this after we loaded boot memory map
|
||||
memory::map::virt::DMA_HEAP_START as usize,
|
||||
memory::map::virt::DMA_HEAP_END as usize,
|
||||
"Global DMA Allocator",
|
||||
// Try the following arguments instead to see all mailbox operations
|
||||
// fail. It will cause the allocator to use memory that are marked
|
||||
// cacheable and therefore not DMA-safe. The answer from the VideoCore
|
||||
// won't be received by the CPU because it reads an old cached value
|
||||
// that resembles an error case instead.
|
||||
|
||||
// 0x00600000 as usize,
|
||||
// 0x007FFFFF as usize,
|
||||
// "Global Non-DMA Allocator",
|
||||
));
|
|
@ -1,14 +1,10 @@
|
|||
#[cfg(not(test))]
|
||||
#[panic_handler]
|
||||
fn panicked(info: &core::panic::PanicInfo) -> ! {
|
||||
pub fn handler(info: &core::panic::PanicInfo) -> ! {
|
||||
// @todo This may fail to print if the panic message is too long for local print buffer.
|
||||
crate::println!("{}", info);
|
||||
crate::endless_sleep()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[panic_handler]
|
||||
fn panicked(info: &core::panic::PanicInfo) -> ! {
|
||||
pub fn handler_for_tests(info: &core::panic::PanicInfo) -> ! {
|
||||
crate::println!("\n[failed]\n");
|
||||
// @todo This may fail to print if the panic message is too long for local print buffer.
|
||||
crate::println!("\nError: {}\n", info);
|
|
@ -361,6 +361,7 @@ impl PreparedMailbox {
|
|||
|
||||
impl Mailbox {
|
||||
/// Create a new mailbox in the DMA-able memory area.
|
||||
#[allow(clippy::result_unit_err)]
|
||||
pub fn new(base_addr: usize) -> ::core::result::Result<Mailbox, ()> {
|
||||
use core::alloc::Allocator;
|
||||
crate::DMA_ALLOCATOR
|
|
@ -64,6 +64,7 @@ impl ops::Deref for Power {
|
|||
}
|
||||
|
||||
impl Power {
|
||||
#[allow(clippy::new_without_default)]
|
||||
pub fn new() -> Power {
|
||||
Power
|
||||
}
|
|
@ -12,7 +12,6 @@ pub mod semihosting {
|
|||
qemu_exit_handle.exit_success()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn exit_failure() -> ! {
|
||||
use qemu_exit::QEMUExit;
|
||||
|
||||
|
@ -22,7 +21,6 @@ pub mod semihosting {
|
|||
qemu_exit_handle.exit_failure()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn sys_write0_call(text: &str) {
|
||||
// SAFETY: text must be \0-terminated!
|
||||
let cmd = 0x04;
|
|
@ -8,7 +8,7 @@
|
|||
use crate::{print, println, qemu};
|
||||
|
||||
pub trait TestFn {
|
||||
fn run(&self) -> ();
|
||||
fn run(&self);
|
||||
}
|
||||
|
||||
impl<T> TestFn for T
|
||||
|
@ -22,7 +22,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn test_runner(tests: &[&dyn TestFn]) {
|
||||
println!("Running {} tests", tests.len());
|
||||
for test in tests {
|
|
@ -1,8 +1,8 @@
|
|||
[package]
|
||||
name = "vesper"
|
||||
name = "nucleus"
|
||||
version = "0.0.1"
|
||||
authors = ["Berkus Decker <berkus+vesper@metta.systems>"]
|
||||
description = "Vesper exokernel"
|
||||
description = "Vesper nanokernel binary"
|
||||
documentation = "https://docs.metta.systems/vesper"
|
||||
homepage = "https://github.com/metta-systems/vesper"
|
||||
repository = "https://github.com/metta-systems/vesper"
|
||||
|
@ -16,21 +16,21 @@ edition = "2021"
|
|||
maintenance = { status = "experimental" }
|
||||
|
||||
[features]
|
||||
noserial = []
|
||||
noserial = ["machine/noserial"]
|
||||
# Enable JTAG debugging of kernel - enable jtag helpers and
|
||||
# block waiting for JTAG probe attach at the start of kernel main.
|
||||
jtag = []
|
||||
jtag = ["machine/jtag"]
|
||||
# Build for running under QEMU with semihosting, so various halt/reboot options would for example quit QEMU instead.
|
||||
qemu = ["qemu-exit"]
|
||||
qemu = ["machine/qemu"]
|
||||
|
||||
[dependencies]
|
||||
machine = { path = "../machine" }
|
||||
r0 = "1.0"
|
||||
qemu-exit = { version = "3.0", optional = true }
|
||||
cortex-a = "7.0"
|
||||
tock-registers = "0.7"
|
||||
ux = { version = "0.1.3", default-features = false }
|
||||
usize_conversions = "0.2.0"
|
||||
bit_field = "0.10.1"
|
||||
ux = { version = "0.1", default-features = false }
|
||||
usize_conversions = "0.2"
|
||||
bit_field = "0.10"
|
||||
bitflags = "1.3"
|
||||
cfg-if = "1.0"
|
||||
snafu = { version = "0.7.0-beta.2", default-features = false }
|
||||
snafu = { version = "0.7", default-features = false }
|
||||
|
|
|
@ -3,92 +3,28 @@
|
|||
#
|
||||
# Copyright (c) Berkus Decker <berkus+vesper@metta.systems>
|
||||
#
|
||||
[tasks.build]
|
||||
env = { "TARGET_FEATURES" = "" }
|
||||
args = ["build", "--target=${TARGET_JSON}", "--release", "--features=${TARGET_FEATURES}"]
|
||||
|
||||
[tasks.expand]
|
||||
env = { "TARGET_FEATURES" = "" }
|
||||
args = ["expand", "--target=${TARGET_JSON}", "--release", "--features=${TARGET_FEATURES}"]
|
||||
|
||||
[tasks.test]
|
||||
env = { "TARGET_FEATURES" = "${QEMU_FEATURES}" }
|
||||
args = ["test", "--target=${TARGET_JSON}", "--features=${TARGET_FEATURES}"]
|
||||
|
||||
[tasks.docs]
|
||||
env = { "TARGET_FEATURES" = "" }
|
||||
args = ["doc", "--open", "--no-deps", "--target=${TARGET_JSON}", "--features=${TARGET_FEATURES}"]
|
||||
|
||||
# These tasks are written in cargo-make's own script to make it portable across platforms (no `basename` on Windows)
|
||||
[tasks.kernel-binary]
|
||||
script_runner = "@duckscript"
|
||||
script = [
|
||||
'''
|
||||
cp ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${TARGET}/release/vesper ${KERNEL_ELF}
|
||||
exec --fail-on-error ${OBJCOPY} %{OBJCOPY_PARAMS} ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${TARGET}/release/vesper ${KERNEL_BIN}
|
||||
'''
|
||||
]
|
||||
|
||||
[tasks.custom-binary]
|
||||
script_runner = "@duckscript"
|
||||
script = [
|
||||
'''
|
||||
binaryFile = basename ${CARGO_MAKE_TASK_ARGS}
|
||||
cp ${CARGO_MAKE_TASK_ARGS} ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${binaryFile}.elf
|
||||
exec --fail-on-error ${OBJCOPY} %{OBJCOPY_PARAMS} ${CARGO_MAKE_TASK_ARGS} ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${binaryFile}.bin
|
||||
'''
|
||||
]
|
||||
|
||||
[tasks.test-runner]
|
||||
dependencies = ["custom-binary"]
|
||||
script_runner = "@duckscript"
|
||||
script = [
|
||||
'''
|
||||
binaryFile = basename ${CARGO_MAKE_TASK_ARGS}
|
||||
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
|
||||
'''
|
||||
]
|
||||
|
||||
[tasks.build-qemu]
|
||||
env = { "TARGET_FEATURES" = "${QEMU_FEATURES}" }
|
||||
command = "cargo"
|
||||
args = ["build", "--target=${TARGET_JSON}", "--release", "--features=${TARGET_FEATURES}"]
|
||||
env = { "BINARY_FILE" = "${KERNEL_ELF}" }
|
||||
run_task = "custom-binary"
|
||||
|
||||
[tasks.qemu-runner]
|
||||
dependencies = ["build-qemu", "kernel-binary"]
|
||||
env = { "TARGET_FEATURES" = "${QEMU_FEATURES}" }
|
||||
script = [
|
||||
"${QEMU} ${QEMU_OPTS} ${QEMU_RUNNER_OPTS} -dtb ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/targets/bcm2710-rpi-3-b-plus.dtb -kernel ${KERNEL_BIN}"
|
||||
]
|
||||
dependencies = ["build-qemu", "kernel-binary"]
|
||||
|
||||
[tasks.qemu]
|
||||
extend = "qemu-runner"
|
||||
env = { "QEMU_RUNNER_OPTS" = "${QEMU_SERIAL_OPTS}" }
|
||||
|
||||
[tasks.zellij-config]
|
||||
extend = "qemu-runner"
|
||||
script_runner = "@duckscript"
|
||||
env = { "ZELLIJ_CONFIG_FILE" = "../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} "KERNEL_BIN=${KERNEL_BIN}\n"
|
||||
'''
|
||||
]
|
||||
install_crate = { crate_name = "zellij", binary = "zellij", test_arg = ["--help"] }
|
||||
|
||||
[tasks.qemu-gdb]
|
||||
extend = "qemu-runner"
|
||||
env = { "QEMU_RUNNER_OPTS" = "${QEMU_SERIAL_OPTS} ${QEMU_GDB_OPTS}" }
|
||||
|
||||
[tasks.openocd]
|
||||
dependencies = ["build", "kernel-binary"]
|
||||
script = [
|
||||
"${OPENOCD} -f interface/jlink.cfg -f ../ocd/${TARGET_BOARD}_target.cfg"
|
||||
]
|
||||
[tasks.zellij-nucleus]
|
||||
env = { "KERNEL_BIN" = "${KERNEL_BIN}" }
|
||||
run_task = "zellij-config"
|
||||
|
||||
[tasks.gdb-config]
|
||||
script_runner = "@duckscript"
|
||||
|
@ -110,7 +46,7 @@ dependencies = ["build", "kernel-binary"]
|
|||
script = [
|
||||
"${NM} -- ${KERNEL_ELF} | sort"
|
||||
]
|
||||
#install_crate = "cargo-binutils"
|
||||
install_crate = { crate_name = "cargo-binutils", binary = "rust-nm", test_arg = ["--help"] }
|
||||
|
||||
[tasks.sdcard]
|
||||
dependencies = ["build", "kernel-binary"]
|
||||
|
@ -122,11 +58,6 @@ script = [
|
|||
'''
|
||||
]
|
||||
|
||||
[tasks.clippy]
|
||||
env = { "TARGET_FEATURES" = { value = "--features=${CLIPPY_FEATURES}", condition = { env_set = ["CLIPPY_FEATURES"] } } }
|
||||
command = "cargo"
|
||||
args = ["clippy", "--target=${TARGET_JSON}", "@@remove-empty(TARGET_FEATURES)", "--", "-D", "warnings"]
|
||||
|
||||
[tasks.hopper]
|
||||
dependencies = ["build", "kernel-binary"]
|
||||
# The cmd line below causes a bug in hopper, see https://www.dropbox.com/s/zyw5mfx0bepcjb1/hopperv4-RAW-bug.mov?dl=0
|
||||
|
|
|
@ -9,71 +9,36 @@
|
|||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(ptr_internals)]
|
||||
#![feature(format_args_nl)]
|
||||
#![feature(nonnull_slice_from_raw_parts)]
|
||||
#![feature(custom_test_frameworks)]
|
||||
#![test_runner(crate::tests::test_runner)]
|
||||
#![test_runner(machine::tests::test_runner)]
|
||||
#![reexport_test_harness_main = "test_main"]
|
||||
#![deny(missing_docs)]
|
||||
#![deny(warnings)]
|
||||
#![allow(clippy::nonstandard_macro_braces)] // https://github.com/shepmaster/snafu/issues/296
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
#![allow(clippy::enum_variant_names)]
|
||||
|
||||
#[cfg(not(target_arch = "aarch64"))]
|
||||
use architecture_not_supported_sorry;
|
||||
|
||||
/// Architecture-specific code.
|
||||
#[macro_use]
|
||||
pub mod arch;
|
||||
pub use arch::*;
|
||||
mod devices;
|
||||
mod macros;
|
||||
mod mm;
|
||||
mod panic;
|
||||
mod platform;
|
||||
#[cfg(feature = "qemu")]
|
||||
mod qemu;
|
||||
mod sync;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
mod write_to;
|
||||
|
||||
#[cfg(not(test))]
|
||||
use core::panic::PanicInfo;
|
||||
use {
|
||||
crate::platform::rpi3::{
|
||||
display::{Color, DrawError},
|
||||
mailbox::{channel, Mailbox, MailboxOps},
|
||||
vc::VC,
|
||||
},
|
||||
cfg_if::cfg_if,
|
||||
machine::{
|
||||
arch, entry, memory,
|
||||
platform::rpi3::{
|
||||
display::{Color, DrawError},
|
||||
mailbox::{channel, Mailbox, MailboxOps},
|
||||
vc::VC,
|
||||
},
|
||||
println, CONSOLE,
|
||||
},
|
||||
};
|
||||
|
||||
entry!(kmain);
|
||||
|
||||
/// The global console. Output of the kernel print! and println! macros goes here.
|
||||
static CONSOLE: sync::NullLock<devices::Console> = sync::NullLock::new(devices::Console::new());
|
||||
|
||||
/// The global allocator for DMA-able memory. That is, memory which is tagged
|
||||
/// non-cacheable in the page tables.
|
||||
static DMA_ALLOCATOR: sync::NullLock<mm::BumpAllocator> =
|
||||
sync::NullLock::new(mm::BumpAllocator::new(
|
||||
// @todo Init this after we loaded boot memory map
|
||||
memory::map::virt::DMA_HEAP_START as usize,
|
||||
memory::map::virt::DMA_HEAP_END as usize,
|
||||
"Global DMA Allocator",
|
||||
// Try the following arguments instead to see all mailbox operations
|
||||
// fail. It will cause the allocator to use memory that are marked
|
||||
// cacheable and therefore not DMA-safe. The answer from the VideoCore
|
||||
// won't be received by the CPU because it reads an old cached value
|
||||
// that resembles an error case instead.
|
||||
|
||||
// 0x00600000 as usize,
|
||||
// 0x007FFFFF as usize,
|
||||
// "Global Non-DMA Allocator",
|
||||
));
|
||||
#[cfg(not(test))]
|
||||
#[panic_handler]
|
||||
fn panicked(info: &PanicInfo) -> ! {
|
||||
machine::panic::handler(info)
|
||||
}
|
||||
|
||||
fn print_mmu_state_and_features() {
|
||||
memory::mmu::print_features();
|
||||
|
@ -103,7 +68,7 @@ fn init_exception_traps() {
|
|||
|
||||
#[cfg(not(feature = "noserial"))]
|
||||
fn init_uart_serial() {
|
||||
use crate::platform::rpi3::{gpio::GPIO, mini_uart::MiniUart, pl011_uart::PL011Uart};
|
||||
use machine::platform::rpi3::{gpio::GPIO, mini_uart::MiniUart, pl011_uart::PL011Uart};
|
||||
|
||||
let gpio = GPIO::default();
|
||||
let uart = MiniUart::default();
|
||||
|
@ -131,7 +96,7 @@ fn init_uart_serial() {
|
|||
// physical wires (e.g. the Framebuffer), you don't need to do this,
|
||||
// because flush() is anyways called implicitly by replace_with(). This
|
||||
// is just a special case.
|
||||
use crate::devices::console::ConsoleOps;
|
||||
use machine::devices::console::ConsoleOps;
|
||||
CONSOLE.lock(|c| c.flush());
|
||||
|
||||
match uart.prepare(mbox, &gpio) {
|
||||
|
@ -151,7 +116,7 @@ fn init_uart_serial() {
|
|||
#[inline]
|
||||
pub fn kmain() -> ! {
|
||||
#[cfg(feature = "jtag")]
|
||||
jtag::wait_debugger();
|
||||
machine::arch::jtag::wait_debugger();
|
||||
|
||||
init_mmu();
|
||||
init_exception_traps();
|
||||
|
@ -181,7 +146,7 @@ fn command_prompt() {
|
|||
b"uart" => init_uart_serial(),
|
||||
b"disp" => check_display_init(),
|
||||
b"trap" => check_data_abort_trap(),
|
||||
b"map" => arch::memory::print_layout(),
|
||||
b"map" => machine::arch::memory::print_layout(),
|
||||
b"led on" => set_led(true),
|
||||
b"led off" => set_led(false),
|
||||
b"help" => print_help(),
|
||||
|
@ -222,9 +187,9 @@ fn reboot() -> ! {
|
|||
cfg_if! {
|
||||
if #[cfg(feature = "qemu")] {
|
||||
println!("Bye, shutting down QEMU");
|
||||
qemu::semihosting::exit_success()
|
||||
machine::qemu::semihosting::exit_success()
|
||||
} else {
|
||||
use crate::platform::rpi3::power::Power;
|
||||
use machine::platform::rpi3::power::Power;
|
||||
|
||||
println!("Bye, going to reset now");
|
||||
Power::new().reset()
|
||||
|
@ -251,7 +216,7 @@ fn display_graphics() -> Result<(), DrawError> {
|
|||
display.draw_text(50, 50, "Hello there!", Color::rgb(128, 192, 255))?;
|
||||
|
||||
let mut buf = [0u8; 64];
|
||||
let s = write_to::show(&mut buf, format_args!("Display width {}", display.width));
|
||||
let s = machine::write_to::show(&mut buf, format_args!("Display width {}", display.width));
|
||||
|
||||
if s.is_err() {
|
||||
display.draw_text(50, 150, "Error displaying", Color::red())?
|
||||
|
@ -280,7 +245,12 @@ fn check_data_abort_trap() {
|
|||
|
||||
#[cfg(test)]
|
||||
mod main_tests {
|
||||
use super::*;
|
||||
use {super::*, core::panic::PanicInfo};
|
||||
|
||||
#[panic_handler]
|
||||
fn panicked(info: &PanicInfo) -> ! {
|
||||
machine::panic::handler_for_tests(info)
|
||||
}
|
||||
|
||||
#[test_case]
|
||||
fn test_data_abort_trap() {
|
||||
|
|
Loading…
Reference in New Issue