mirror of
https://github.com/AmbiML/sparrow-kata-full.git
synced 2025-04-27 10:31:31 +00:00
Replaces processmanager with a one-app CAmkES assembly for the entire Kata OS
This also adds a skeleton for the DebugConsole CLI taking IO from a UART via some Rust wrapper functions, also defined in this change (kata-uart-client). Change-Id: I56856c14992010483da58c45f6550c0a4c9987b0 GitOrigin-RevId: e1b2d65ed3a7f627a9f7377caa407151fc943864
This commit is contained in:
parent
5007f2c48c
commit
fd2bebb81f
@ -1,26 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.7.2)
|
||||
project(ProcessManager C ASM)
|
||||
|
||||
set(project_dir "${CMAKE_CURRENT_LIST_DIR}/../../")
|
||||
file(GLOB project_modules ${project_dir}/projects/*)
|
||||
list(
|
||||
APPEND
|
||||
CMAKE_MODULE_PATH
|
||||
${project_dir}/kernel
|
||||
${project_dir}/tools/seL4/cmake-tool/helpers/
|
||||
${project_dir}/tools/seL4/elfloader-tool/
|
||||
${project_modules}
|
||||
)
|
||||
set(POLLY_DIR ${project_dir}/tools/polly CACHE INTERNAL "")
|
||||
|
||||
add_executable(ProcessManager src/main.c)
|
||||
|
||||
target_link_libraries(ProcessManager
|
||||
sel4runtime sel4
|
||||
muslc utils sel4muslcsys sel4platsupport sel4utils sel4debug)
|
||||
|
||||
include(rootserver)
|
||||
DeclareRootserver(ProcessManager)
|
||||
|
||||
include(simulation)
|
||||
GenerateSimulateScript()
|
1
CMakeLists.txt
Symbolic link
1
CMakeLists.txt
Symbolic link
@ -0,0 +1 @@
|
||||
../camkes/CMakeLists.txt
|
11
README.md
Normal file
11
README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Kata OS
|
||||
|
||||
This is a CAmkES project that assembles the entire Kata OS. It exists outside
|
||||
the seL4 source trees, since it contains code not intended to go to upstream
|
||||
seL4.
|
||||
|
||||
This uses the [standard CAmkES build system](https://docs.sel4.systems/projects/camkes/manual.html#running-a-simple-example)
|
||||
by symlinking CMakeLists.txt. It also symlinks settings.cmake, and so retains
|
||||
the notion of "apps," which enables the build system to switch which assembly
|
||||
it builds using the CAMKES\_APP CMake cache value. Kata OS just has one app,
|
||||
*system*.
|
37
apps/system/CMakeLists.txt
Normal file
37
apps/system/CMakeLists.txt
Normal file
@ -0,0 +1,37 @@
|
||||
#
|
||||
# Copyright 2018, Data61
|
||||
# Commonwealth Scientific and Industrial Research Organisation (CSIRO)
|
||||
# ABN 41 687 119 230.
|
||||
#
|
||||
# This software may be distributed and modified according to the terms of
|
||||
# the BSD 2-Clause license. Note that NO WARRANTY is provided.
|
||||
# See "LICENSE_BSD2.txt" for details.
|
||||
#
|
||||
# @TAG(DATA61_BSD)
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.7.2)
|
||||
|
||||
project(system)
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/rust.cmake)
|
||||
|
||||
RustAddLibrary(
|
||||
kata_debug_console
|
||||
SOURCE_DIR
|
||||
${CMAKE_CURRENT_LIST_DIR}/components/DebugConsole
|
||||
TARGET
|
||||
"riscv32imc-unknown-none-elf"
|
||||
LIB_FILENAME
|
||||
libkata_debug_console.a
|
||||
)
|
||||
|
||||
DeclareCAmkESComponent(DebugConsole
|
||||
LIBS kata_debug_console
|
||||
)
|
||||
|
||||
DeclareCAmkESComponent(UartDriver
|
||||
SOURCES components/UartDriver/src/driver.c
|
||||
)
|
||||
|
||||
DeclareCAmkESRootserver(system.camkes)
|
17
apps/system/README
Normal file
17
apps/system/README
Normal file
@ -0,0 +1,17 @@
|
||||
<!--
|
||||
Copyright 2017, Data61
|
||||
Commonwealth Scientific and Industrial Research Organisation (CSIRO)
|
||||
ABN 41 687 119 230.
|
||||
|
||||
This software may be distributed and modified according to the terms of
|
||||
the BSD 2-Clause license. Note that NO WARRANTY is provided.
|
||||
See "LICENSE_BSD2.txt" for details.
|
||||
|
||||
@TAG(DATA61_BSD)
|
||||
-->
|
||||
#
|
||||
|
||||
UART driver for KZM.
|
||||
|
||||
This is an example of accessing hardware device memory. The device memory
|
||||
address may vary.
|
49
apps/system/components/DebugConsole/Cargo.lock
generated
Normal file
49
apps/system/components/DebugConsole/Cargo.lock
generated
Normal file
@ -0,0 +1,49 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "cty"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7313c0d620d0cb4dbd9d019e461a4beb501071ff46ec0ab933efb4daa76d73e3"
|
||||
|
||||
[[package]]
|
||||
name = "kata-debug-console"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"kata-shell",
|
||||
"kata-uart-client",
|
||||
"panic-halt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kata-io"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "kata-line-reader"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"kata-io",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kata-shell"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"kata-io",
|
||||
"kata-line-reader",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kata-uart-client"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cty",
|
||||
"kata-io",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "panic-halt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812"
|
9
apps/system/components/DebugConsole/Cargo.toml
Normal file
9
apps/system/components/DebugConsole/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[workspace]
|
||||
|
||||
members = [
|
||||
"kata-debug-console",
|
||||
"kata-io",
|
||||
"kata-line-reader",
|
||||
"kata-shell",
|
||||
"kata-uart-client",
|
||||
]
|
6
apps/system/components/DebugConsole/DebugConsole.camkes
Normal file
6
apps/system/components/DebugConsole/DebugConsole.camkes
Normal file
@ -0,0 +1,6 @@
|
||||
component DebugConsole {
|
||||
control;
|
||||
uses uart_inf uart;
|
||||
dataport Buf tx_dataport;
|
||||
dataport Buf rx_dataport;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "kata-debug-console"
|
||||
version = "0.1.0"
|
||||
authors = ["Matt Harvey <mattharvey@google.com>"]
|
||||
edition = "2018"
|
||||
description = "Kata OS DebugConsole"
|
||||
|
||||
[dependencies]
|
||||
panic-halt = "0.2.0"
|
||||
kata-shell = { path = "../kata-shell" }
|
||||
kata-uart-client = { path = "../kata-uart-client" }
|
||||
|
||||
[lib]
|
||||
name = "kata_debug_console"
|
||||
path = "src/run.rs"
|
||||
crate-type = ["staticlib"]
|
@ -0,0 +1,27 @@
|
||||
//! Kata OS command line interface
|
||||
|
||||
// This brief bootstrap of Rust-in-Kata prototypes a minimal modular design
|
||||
// for the DebugConsole CLI use case.
|
||||
//
|
||||
// * kata_io Read/Write interface (or move to std::, but that requires alloc)
|
||||
// * kata_uart_client implementation of the kata_io interface
|
||||
// * kata_line_reader
|
||||
// * kata_shell
|
||||
// * kata_debug_console main entry point fn run()
|
||||
|
||||
// std:: requires at least an allocator, which Kata does not have yet. For now
|
||||
// the CLI will be implemented with only core::.
|
||||
#![no_std]
|
||||
|
||||
extern crate panic_halt;
|
||||
|
||||
use kata_shell;
|
||||
use kata_uart_client;
|
||||
|
||||
/// Entry point for DebugConsole. Runs the shell with UART IO.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn run() -> ! {
|
||||
let mut tx = kata_uart_client::Tx {};
|
||||
let mut rx = kata_uart_client::Rx {};
|
||||
kata_shell::repl(&mut tx, &mut rx);
|
||||
}
|
5
apps/system/components/DebugConsole/kata-io/Cargo.toml
Normal file
5
apps/system/components/DebugConsole/kata-io/Cargo.toml
Normal file
@ -0,0 +1,5 @@
|
||||
[package]
|
||||
name = "kata-io"
|
||||
version = "0.1.0"
|
||||
authors = ["Matt Harvey <mattharvey@google.com>"]
|
||||
edition = "2018"
|
35
apps/system/components/DebugConsole/kata-io/src/lib.rs
Normal file
35
apps/system/components/DebugConsole/kata-io/src/lib.rs
Normal file
@ -0,0 +1,35 @@
|
||||
#![no_std]
|
||||
|
||||
pub struct Error;
|
||||
|
||||
/// Interface for the CLI to consume bytes.
|
||||
pub trait Read {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error>;
|
||||
}
|
||||
|
||||
/// Interface for the CLI to emit bytes.
|
||||
pub trait Write {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Error>;
|
||||
}
|
||||
|
||||
/// Adapter for writing core::fmt formatted strings.
|
||||
impl core::fmt::Write for dyn Write + '_ {
|
||||
/// Writes the bytes of a &str to the underlying writer.
|
||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
match self.write(s.as_bytes()) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(_) => Err(core::fmt::Error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn Read + '_ {
|
||||
pub fn get_u8(&mut self) -> Result<u8, Error> {
|
||||
let mut buf: [u8; 1] = [0u8];
|
||||
let n_read = self.read(&mut buf)?;
|
||||
match n_read {
|
||||
1usize => Ok(buf[0]),
|
||||
_ => Err(Error),
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "kata-line-reader"
|
||||
version = "0.1.0"
|
||||
authors = ["Matt Harvey <mattharvey@google.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
kata-io = { path = "../kata-io" }
|
@ -0,0 +1,78 @@
|
||||
#![no_std]
|
||||
|
||||
use core::fmt;
|
||||
|
||||
use kata_io as io;
|
||||
|
||||
const LINE_MAX: usize = 128;
|
||||
|
||||
pub enum LineReadError {
|
||||
IO(io::Error),
|
||||
Overflow,
|
||||
Encoding(core::str::Utf8Error),
|
||||
}
|
||||
|
||||
impl From<io::Error> for LineReadError {
|
||||
fn from(err: io::Error) -> LineReadError {
|
||||
LineReadError::IO(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<core::str::Utf8Error> for LineReadError {
|
||||
fn from(err: core::str::Utf8Error) -> LineReadError {
|
||||
LineReadError::Encoding(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for LineReadError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
LineReadError::IO(_) => write!(f, "IO error"),
|
||||
LineReadError::Overflow => write!(f, "line too long"),
|
||||
LineReadError::Encoding(_) => write!(f, "bad character encoding"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LineReader {
|
||||
// Owned by LineReader to facilitate static allocation.
|
||||
buf: [u8; LINE_MAX],
|
||||
}
|
||||
|
||||
impl LineReader {
|
||||
pub fn new() -> LineReader {
|
||||
LineReader {
|
||||
buf: [0u8; LINE_MAX],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_line(
|
||||
&mut self,
|
||||
output: &mut dyn io::Write,
|
||||
input: &mut dyn io::Read,
|
||||
) -> Result<&str, LineReadError> {
|
||||
const DEL: u8 = 127u8;
|
||||
const BACKSPACE: u8 = 8u8;
|
||||
let mut len = 0;
|
||||
while len < self.buf.len() {
|
||||
let mut c = input.get_u8()?;
|
||||
while c == DEL || c == BACKSPACE {
|
||||
if len > 0 {
|
||||
output.write(&[BACKSPACE, b' ', BACKSPACE])?;
|
||||
len -= 1;
|
||||
}
|
||||
c = input.get_u8()?;
|
||||
}
|
||||
if c == b'\r' || c == b'\n' {
|
||||
if len > 0 {
|
||||
output.write(&[b'\n'])?;
|
||||
}
|
||||
return Ok(core::str::from_utf8(&self.buf[0..len])?);
|
||||
}
|
||||
self.buf[len] = c;
|
||||
len += 1;
|
||||
output.write(&[c])?;
|
||||
}
|
||||
Err(LineReadError::Overflow)
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "kata-shell"
|
||||
version = "0.1.0"
|
||||
authors = ["Matt Harvey <mattharvey@google.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
kata-io = { path = "../kata-io" }
|
||||
kata-line-reader = { path = "../kata-line-reader" }
|
127
apps/system/components/DebugConsole/kata-shell/src/lib.rs
Normal file
127
apps/system/components/DebugConsole/kata-shell/src/lib.rs
Normal file
@ -0,0 +1,127 @@
|
||||
#![no_std]
|
||||
|
||||
use core::fmt;
|
||||
use core::fmt::Write;
|
||||
|
||||
use kata_io as io;
|
||||
use kata_line_reader::LineReader;
|
||||
|
||||
/// Error type indicating why a command line is not runnable.
|
||||
enum CommandError {
|
||||
UnknownCommand,
|
||||
BadArgs,
|
||||
Formatter(fmt::Error),
|
||||
}
|
||||
|
||||
impl fmt::Display for CommandError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
CommandError::UnknownCommand => write!(f, "unknown command"),
|
||||
CommandError::BadArgs => write!(f, "invalid arguments"),
|
||||
CommandError::Formatter(e) => write!(f, "{}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<core::num::ParseIntError> for CommandError {
|
||||
fn from(_err: core::num::ParseIntError) -> CommandError {
|
||||
CommandError::BadArgs
|
||||
}
|
||||
}
|
||||
|
||||
impl From<core::num::ParseFloatError> for CommandError {
|
||||
fn from(_err: core::num::ParseFloatError) -> CommandError {
|
||||
CommandError::BadArgs
|
||||
}
|
||||
}
|
||||
|
||||
impl From<fmt::Error> for CommandError {
|
||||
fn from(err: fmt::Error) -> CommandError {
|
||||
CommandError::Formatter(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Read-eval-print loop for the DebugConsole command line interface.
|
||||
pub fn repl(output: &mut dyn io::Write, input: &mut dyn io::Read) -> ! {
|
||||
let mut line_reader = LineReader::new();
|
||||
loop {
|
||||
// The PROMPT is the Hiragana representation of the word "kata."
|
||||
const PROMPT: &str = "かた ";
|
||||
let _ = output.write_str(PROMPT);
|
||||
match line_reader.read_line(output, input) {
|
||||
Ok(cmdline) => dispatch_command(cmdline, output),
|
||||
Err(e) => {
|
||||
let _ = write!(output, "\n{}\n", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs a command line.
|
||||
///
|
||||
/// The line is split on whitespace. The first token is the command; the
|
||||
/// remaining tokens are the arguments.
|
||||
fn dispatch_command(cmdline: &str, output: &mut dyn io::Write) {
|
||||
let mut args = cmdline.split_ascii_whitespace();
|
||||
match args.nth(0) {
|
||||
Some(command) => {
|
||||
// Statically binds command names to implementations fns, which are
|
||||
// defined below.
|
||||
//
|
||||
// Since even the binding is static, it is fine for each command
|
||||
// implementation to use its own preferred signature.
|
||||
let result = match command {
|
||||
"echo" => echo_command(cmdline, output),
|
||||
"add" => add_command(&mut args, output),
|
||||
"clear" => clear_command(output),
|
||||
_ => Err(CommandError::UnknownCommand),
|
||||
};
|
||||
if let Err(e) = result {
|
||||
let _ = write!(output, "{}\n", e);
|
||||
};
|
||||
}
|
||||
None => {
|
||||
let _ = output.write_str("\n");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Implements an "echo" command which writes its arguments to output.
|
||||
fn echo_command(cmdline: &str, output: &mut dyn io::Write) -> Result<(), CommandError> {
|
||||
const COMMAND_LENGTH: usize = 5; // "echo "
|
||||
if cmdline.len() < COMMAND_LENGTH {
|
||||
Ok(())
|
||||
} else {
|
||||
Ok(write!(
|
||||
output,
|
||||
"{}\n",
|
||||
&cmdline[COMMAND_LENGTH..cmdline.len()]
|
||||
)?)
|
||||
}
|
||||
}
|
||||
|
||||
/// Implements a binary float addition command.
|
||||
///
|
||||
/// This is a toy to demonstrate that the CLI can operate on some very basic
|
||||
/// dynamic input and that the Rust runtime provides floating point arithmetic
|
||||
/// on integer-only hardware. It is also a prototype example of "command taking
|
||||
/// arguments." It should be removed once actually useful system control
|
||||
/// commands are implemented and done cribbing from it.
|
||||
fn add_command(
|
||||
args: &mut dyn Iterator<Item = &str>,
|
||||
output: &mut dyn io::Write,
|
||||
) -> Result<(), CommandError> {
|
||||
if let Some(x_str) = args.nth(0) {
|
||||
if let Some(y_str) = args.nth(0) {
|
||||
let x = x_str.parse::<f32>()?;
|
||||
let y = y_str.parse::<f32>()?;
|
||||
return Ok(write!(output, "{}\n", x + y)?);
|
||||
}
|
||||
}
|
||||
Err(CommandError::BadArgs)
|
||||
}
|
||||
|
||||
/// Implements a command that outputs the ANSI "clear console" sequence.
|
||||
fn clear_command(output: &mut dyn io::Write) -> Result<(), CommandError> {
|
||||
Ok(output.write_str("\x1b\x63")?)
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "kata-uart-client"
|
||||
version = "0.1.0"
|
||||
authors = ["Matt Harvey <mattharvey@google.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cty = "0.2.1"
|
||||
kata-io = { path = "../kata-io" }
|
@ -0,0 +1,37 @@
|
||||
#![no_std]
|
||||
|
||||
use kata_io as io;
|
||||
|
||||
// C interface to external UART driver.
|
||||
extern "C" {
|
||||
static rx_dataport: *mut cty::c_char;
|
||||
static tx_dataport: *mut cty::c_char;
|
||||
fn uart_rx(n: cty::size_t);
|
||||
fn uart_tx(n: cty::size_t);
|
||||
}
|
||||
|
||||
pub struct Rx {}
|
||||
|
||||
impl io::Read for Rx {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
|
||||
unsafe {
|
||||
uart_rx(buf.len());
|
||||
let port = core::slice::from_raw_parts(rx_dataport, buf.len());
|
||||
buf.copy_from_slice(&port);
|
||||
}
|
||||
Ok(buf.len())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Tx {}
|
||||
|
||||
impl io::Write for Tx {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
|
||||
unsafe {
|
||||
let port = core::slice::from_raw_parts_mut(tx_dataport, buf.len());
|
||||
port.copy_from_slice(buf);
|
||||
uart_tx(buf.len());
|
||||
}
|
||||
Ok(buf.len())
|
||||
}
|
||||
}
|
21
apps/system/components/UartDriver/UartDriver.camkes
Normal file
21
apps/system/components/UartDriver/UartDriver.camkes
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2017, Data61
|
||||
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
|
||||
* ABN 41 687 119 230.
|
||||
*
|
||||
* This software may be distributed and modified according to the terms of
|
||||
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
|
||||
* See "LICENSE_BSD2.txt" for details.
|
||||
*
|
||||
* @TAG(DATA61_BSD)
|
||||
*/
|
||||
|
||||
component UartDriver {
|
||||
dataport Buf mem;
|
||||
dataport Buf tx_dataport;
|
||||
dataport Buf rx_dataport;
|
||||
|
||||
// consumes Interrupt interrupt;
|
||||
|
||||
provides uart_inf uart;
|
||||
}
|
94
apps/system/components/UartDriver/src/driver.c
Normal file
94
apps/system/components/UartDriver/src/driver.c
Normal file
@ -0,0 +1,94 @@
|
||||
// 16550a UART driver
|
||||
//
|
||||
// Pared down from the xv6 RISC-V source (MIT license).
|
||||
// https://github.com/mit-pdos/xv6-riscv/blob/riscv/kernel/uart.c
|
||||
|
||||
#include <camkes.h>
|
||||
|
||||
#define UART0 (unsigned int)mem
|
||||
|
||||
// the UART control registers are memory-mapped
|
||||
// at address UART0. this macro returns the
|
||||
// address of one of the registers.
|
||||
#define Reg(reg) ((volatile unsigned char *)(UART0 + reg))
|
||||
|
||||
// the UART control registers.
|
||||
// some have different meanings for
|
||||
// read vs write.
|
||||
// see http://byterunner.com/16550.html
|
||||
#define RHR 0 // receive holding register (for input bytes)
|
||||
#define THR 0 // transmit holding register (for output bytes)
|
||||
#define IER 1 // interrupt enable register
|
||||
#define IER_RX_ENABLE (1<<0)
|
||||
#define IER_TX_ENABLE (1<<1)
|
||||
#define FCR 2 // FIFO control register
|
||||
#define FCR_FIFO_ENABLE (1<<0)
|
||||
#define FCR_FIFO_CLEAR (3<<1) // clear the content of the two FIFOs
|
||||
#define ISR 2 // interrupt status register
|
||||
#define LCR 3 // line control register
|
||||
#define LCR_EIGHT_BITS (3<<0)
|
||||
#define LCR_BAUD_LATCH (1<<7) // special mode to set baud rate
|
||||
#define LSR 5 // line status register
|
||||
#define LSR_RX_READY (1<<0) // input is waiting to be read from RHR
|
||||
#define LSR_TX_IDLE (1<<5) // THR can accept another character to send
|
||||
|
||||
#define ReadReg(reg) (*(Reg(reg)))
|
||||
#define WriteReg(reg, v) (*(Reg(reg)) = (v))
|
||||
|
||||
void uart__init()
|
||||
{
|
||||
// disable interrupts (UART from generating, not hart from dispatching)
|
||||
WriteReg(IER, 0x00);
|
||||
|
||||
// special mode to set baud rate.
|
||||
WriteReg(LCR, LCR_BAUD_LATCH);
|
||||
|
||||
// LSB for baud rate of 38.4K.
|
||||
WriteReg(0, 0x03);
|
||||
|
||||
// MSB for baud rate of 38.4K.
|
||||
WriteReg(1, 0x00);
|
||||
|
||||
// leave set-baud mode,
|
||||
// and set word length to 8 bits, no parity.
|
||||
WriteReg(LCR, LCR_EIGHT_BITS);
|
||||
|
||||
// reset and enable FIFOs.
|
||||
WriteReg(FCR, FCR_FIFO_ENABLE | FCR_FIFO_CLEAR);
|
||||
|
||||
// TODO (mattharvey): seL4 is not configured to dispatch UART interrupts to
|
||||
// this driver yet. Until that time, this driver spins to wait. The proper
|
||||
// thing will be to make a Rust embedded_hal implementation for Sparrow.
|
||||
//
|
||||
// enable transmit and receive interrupts.
|
||||
// WriteReg(IER, IER_TX_ENABLE | IER_RX_ENABLE);
|
||||
}
|
||||
|
||||
static int uart_received()
|
||||
{
|
||||
return ReadReg(LSR) & LSR_RX_READY;
|
||||
}
|
||||
|
||||
static int is_transmit_empty() {
|
||||
return ReadReg(LSR) & LSR_TX_IDLE;
|
||||
}
|
||||
|
||||
void uart_rx(size_t n) {
|
||||
char *c = (char*)rx_dataport;
|
||||
// TODO(mattharvey): Error return value for n > PAGE_SIZE
|
||||
for (size_t i = 0; i < n && i < PAGE_SIZE; ++i) {
|
||||
while (!uart_received());
|
||||
*c = ReadReg(RHR);
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
||||
void uart_tx(size_t n) {
|
||||
char *c = (char*)tx_dataport;
|
||||
// TODO(mattharvey): Error return value for n > PAGE_SIZE
|
||||
for (size_t i = 0; i < n && i < PAGE_SIZE; ++i) {
|
||||
while(!is_transmit_empty());
|
||||
WriteReg(THR, *c);
|
||||
++c;
|
||||
}
|
||||
}
|
16
apps/system/interfaces/uart.idl4
Normal file
16
apps/system/interfaces/uart.idl4
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2017, Data61
|
||||
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
|
||||
* ABN 41 687 119 230.
|
||||
*
|
||||
* This software may be distributed and modified according to the terms of
|
||||
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
|
||||
* See "LICENSE_BSD2.txt" for details.
|
||||
*
|
||||
* @TAG(DATA61_BSD)
|
||||
*/
|
||||
|
||||
procedure uart_inf {
|
||||
void rx(in size_t n);
|
||||
void tx(in size_t n);
|
||||
};
|
53
apps/system/rust.cmake
Normal file
53
apps/system/rust.cmake
Normal file
@ -0,0 +1,53 @@
|
||||
#
|
||||
# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.8.2)
|
||||
include_guard(GLOBAL)
|
||||
|
||||
# add_library but for rust libraries. Invokes cargo in the SOURCE_DIR that is provided,
|
||||
# all build output is placed in BUILD_DIR or CMAKE_CURRENT_BINARY_DIR if BUILD_DIR isn't provided.
|
||||
# lib_name: Name of library that is created
|
||||
# SOURCE_DIR: source directory of cargo project
|
||||
# BUILD_DIR: directory for cargo build output
|
||||
# TARGET: custom target to use. See in ../rust_targets/ for list of available targets.
|
||||
# LIB_FILENAME: filename of library created by cargo
|
||||
# DEPENDS: And target or file dependencies that need to be run before cargo
|
||||
function(RustAddLibrary lib_name)
|
||||
cmake_parse_arguments(PARSE_ARGV 1 RUST "" "SOURCE_DIR;BUILD_DIR;TARGET;LIB_FILENAME" "DEPENDS")
|
||||
if(NOT "${RUST_UNPARSED_ARGUMENTS}" STREQUAL "")
|
||||
message(FATAL_ERROR "Unknown arguments to RustAddLibrary ${RUST_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
if("${RUST_SOURCE_DIR}" STREQUAL "")
|
||||
message(FATAL_ERROR "SOURCE_DIR must be set for RustAddLibrary")
|
||||
endif()
|
||||
if("${RUST_LIB_FILENAME}" STREQUAL "")
|
||||
message(FATAL_ERROR "LIB_FILENAME must be set for RustAddLibrary")
|
||||
endif()
|
||||
if("${RUST_BUILD_DIR}" STREQUAL "")
|
||||
set(RUST_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
add_custom_target(
|
||||
${libmain}_custom
|
||||
BYPRODUCTS
|
||||
${RUST_BUILD_DIR}/${RUST_LIB_FILENAME}
|
||||
${USES_TERMINAL_DEBUG}
|
||||
DEPENDS ${RUST_DEPENDS}
|
||||
WORKING_DIRECTORY ${RUST_SOURCE_DIR}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E env cargo +nightly build
|
||||
--target riscv32imc-unknown-none-elf
|
||||
--target-dir ${RUST_BUILD_DIR} -Z unstable-options
|
||||
--out-dir ${RUST_BUILD_DIR}
|
||||
)
|
||||
|
||||
add_library(${lib_name} STATIC IMPORTED GLOBAL)
|
||||
set_property(
|
||||
TARGET ${lib_name}
|
||||
PROPERTY IMPORTED_LOCATION "${RUST_BUILD_DIR}/${RUST_LIB_FILENAME}"
|
||||
)
|
||||
add_dependencies(${lib_name} ${libmain}_custom)
|
||||
endfunction()
|
54
apps/system/system.camkes
Normal file
54
apps/system/system.camkes
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2017, Data61
|
||||
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
|
||||
* ABN 41 687 119 230.
|
||||
*
|
||||
* This software may be distributed and modified according to the terms of
|
||||
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
|
||||
* See "LICENSE_BSD2.txt" for details.
|
||||
*
|
||||
* @TAG(DATA61_BSD)
|
||||
*/
|
||||
|
||||
import <std_connector.camkes>;
|
||||
|
||||
import "interfaces/uart.idl4";
|
||||
import "components/UartDriver/UartDriver.camkes";
|
||||
import "components/DebugConsole/DebugConsole.camkes";
|
||||
|
||||
component UART {
|
||||
hardware;
|
||||
dataport Buf mem;
|
||||
// TODO(mattharvey): Make receives wait on interrupt.
|
||||
// emits Interrupt interrupt;
|
||||
}
|
||||
|
||||
assembly {
|
||||
composition {
|
||||
component UART uart;
|
||||
component UartDriver drv;
|
||||
component DebugConsole debug_console;
|
||||
|
||||
connection seL4HardwareMMIO uart_mem(from drv.mem, to uart.mem);
|
||||
// TODO(mattharvey): Make receives wait on interrupt.
|
||||
// connection seL4HardwareInterrupt uart_interrupt(
|
||||
// from uart.interrupt, to drv.interrupt);
|
||||
connection seL4RPCCall uart_inf(from debug_console.uart, to drv.uart);
|
||||
|
||||
connection seL4SharedData tx_channel(
|
||||
from debug_console.tx_dataport, to drv.tx_dataport);
|
||||
connection seL4SharedData rx_channel(
|
||||
from debug_console.rx_dataport, to drv.rx_dataport);
|
||||
}
|
||||
|
||||
configuration {
|
||||
uart.mem_paddr = 0x10000000;
|
||||
uart.mem_size = 0x1000;
|
||||
// seL4 claims 10 is bigger than irqMax if this is uncommented.
|
||||
// uart.interrupt_irq_number = 10;
|
||||
|
||||
random.ID = 1;
|
||||
|
||||
uart.integrity_label = "drv";
|
||||
}
|
||||
}
|
5
easy-settings.cmake
Normal file
5
easy-settings.cmake
Normal file
@ -0,0 +1,5 @@
|
||||
set(CAMKES_APP "system" CACHE STRING "The one and only CAmkES application in this project")
|
||||
set(SIMULATION ON CACHE BOOL "Whether to build simulate script")
|
||||
set(RELEASE OFF CACHE BOOL "Performance optimized build")
|
||||
set(PLATFORM "spike" CACHE STRING "The one and only seL4 platform for Sparrow")
|
||||
set(KernelSel4Arch "riscv32" CACHE STRING "Specifies 32-bit branch of the seL4 spike platform")
|
60
rust.cmake
Normal file
60
rust.cmake
Normal file
@ -0,0 +1,60 @@
|
||||
# Fork of tools/seL4/cmake-tool/helpers/rust.cmake.
|
||||
#
|
||||
# The differences are that a) xargo has been replaced with cargo +nightly, since
|
||||
# xargo was upstreamed into Rust proper after seL4 created rust.cmake, and b)
|
||||
# the Rust target is hard-coded to riscv32imc-unknown-none-elf to make this
|
||||
# file easier to read.
|
||||
|
||||
#
|
||||
# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.8.2)
|
||||
include_guard(GLOBAL)
|
||||
|
||||
# add_library but for rust libraries. Invokes cargo in the SOURCE_DIR that is provided,
|
||||
# all build output is placed in BUILD_DIR or CMAKE_CURRENT_BINARY_DIR if BUILD_DIR isn't provided.
|
||||
# lib_name: Name of library that is created
|
||||
# SOURCE_DIR: source directory of cargo project
|
||||
# BUILD_DIR: directory for cargo build output
|
||||
# TARGET: custom target to use. See in ../rust_targets/ for list of available targets.
|
||||
# LIB_FILENAME: filename of library created by cargo
|
||||
# DEPENDS: And target or file dependencies that need to be run before cargo
|
||||
function(RustAddLibrary lib_name)
|
||||
cmake_parse_arguments(PARSE_ARGV 1 RUST "" "SOURCE_DIR;BUILD_DIR;TARGET;LIB_FILENAME" "DEPENDS")
|
||||
if(NOT "${RUST_UNPARSED_ARGUMENTS}" STREQUAL "")
|
||||
message(FATAL_ERROR "Unknown arguments to RustAddLibrary ${RUST_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
if("${RUST_SOURCE_DIR}" STREQUAL "")
|
||||
message(FATAL_ERROR "SOURCE_DIR must be set for RustAddLibrary")
|
||||
endif()
|
||||
if("${RUST_LIB_FILENAME}" STREQUAL "")
|
||||
message(FATAL_ERROR "LIB_FILENAME must be set for RustAddLibrary")
|
||||
endif()
|
||||
if("${RUST_BUILD_DIR}" STREQUAL "")
|
||||
set(RUST_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
add_custom_target(
|
||||
${libmain}_custom
|
||||
BYPRODUCTS
|
||||
${RUST_BUILD_DIR}/${RUST_LIB_FILENAME}
|
||||
${USES_TERMINAL_DEBUG}
|
||||
DEPENDS ${RUST_DEPENDS}
|
||||
WORKING_DIRECTORY ${RUST_SOURCE_DIR}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E env cargo +nightly build
|
||||
--target riscv32imc-unknown-none-elf
|
||||
--target-dir ${RUST_BUILD_DIR} -Z unstable-options
|
||||
--out-dir ${RUST_BUILD_DIR}
|
||||
)
|
||||
|
||||
add_library(${lib_name} STATIC IMPORTED GLOBAL)
|
||||
set_property(
|
||||
TARGET ${lib_name}
|
||||
PROPERTY IMPORTED_LOCATION "${RUST_BUILD_DIR}/${RUST_LIB_FILENAME}"
|
||||
)
|
||||
add_dependencies(${lib_name} ${libmain}_custom)
|
||||
endfunction()
|
1
settings.cmake
Symbolic link
1
settings.cmake
Symbolic link
@ -0,0 +1 @@
|
||||
../camkes/settings.cmake
|
Loading…
Reference in New Issue
Block a user