mirror of
https://github.com/AmbiML/sparrow-kata-full.git
synced 2025-07-14 14:34:19 +00:00
Merge "Aligns UART API with Rust Read and Write"
GitOrigin-RevId: df407ae4bddb75b1bc43c35062947679c2b10c3a
This commit is contained in:
parent
d6f8c7bced
commit
d70003982c
@ -10,12 +10,10 @@ component DebugConsole {
|
|||||||
control;
|
control;
|
||||||
|
|
||||||
dataport Buf tx_dataport;
|
dataport Buf tx_dataport;
|
||||||
uses dataport_io_inf uart_tx;
|
uses rust_write_inf uart_write;
|
||||||
has mutex tx_mutex;
|
|
||||||
|
|
||||||
dataport Buf rx_dataport;
|
dataport Buf rx_dataport;
|
||||||
uses dataport_io_inf uart_rx;
|
uses rust_read_inf uart_read;
|
||||||
has mutex rx_mutex;
|
|
||||||
|
|
||||||
provides LoggerInterface logger;
|
provides LoggerInterface logger;
|
||||||
uses ProcessControlInterface proc_ctrl;
|
uses ProcessControlInterface proc_ctrl;
|
||||||
|
@ -44,7 +44,7 @@ pub extern "C" fn pre_init() {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn run() -> ! {
|
pub extern "C" fn run() -> ! {
|
||||||
trace!("run");
|
trace!("run");
|
||||||
let mut tx = kata_uart_client::Tx {};
|
let mut tx = kata_uart_client::Tx::new();
|
||||||
let mut rx = kata_uart_client::Rx {};
|
let mut rx = kata_uart_client::Rx::new();
|
||||||
kata_shell::repl(&mut tx, &mut rx);
|
kata_shell::repl(&mut tx, &mut rx);
|
||||||
}
|
}
|
||||||
|
@ -4,19 +4,6 @@ use core::fmt::Write;
|
|||||||
use cstr_core::CStr;
|
use cstr_core::CStr;
|
||||||
use kata_io as io;
|
use kata_io as io;
|
||||||
|
|
||||||
// C interface to external UART driver.
|
|
||||||
extern "C" {
|
|
||||||
static rx_dataport: *mut cty::c_uchar;
|
|
||||||
fn uart_rx_update(n: cty::size_t);
|
|
||||||
fn rx_mutex_lock();
|
|
||||||
fn rx_mutex_unlock();
|
|
||||||
|
|
||||||
static tx_dataport: *mut cty::c_uchar;
|
|
||||||
fn uart_tx_update(n: cty::size_t);
|
|
||||||
fn tx_mutex_lock();
|
|
||||||
fn tx_mutex_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Console logging interface.
|
// Console logging interface.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn logger_log(level: u8, msg: *const cstr_core::c_char) {
|
pub extern "C" fn logger_log(level: u8, msg: *const cstr_core::c_char) {
|
||||||
@ -30,44 +17,83 @@ pub extern "C" fn logger_log(level: u8, msg: *const cstr_core::c_char) {
|
|||||||
};
|
};
|
||||||
if l <= log::max_level() {
|
if l <= log::max_level() {
|
||||||
// TODO(sleffler): is the uart driver ok w/ multiple writers?
|
// TODO(sleffler): is the uart driver ok w/ multiple writers?
|
||||||
let output: &mut dyn io::Write = &mut self::Tx {};
|
let output: &mut dyn io::Write = &mut self::Tx::new();
|
||||||
unsafe {
|
unsafe {
|
||||||
let _ = writeln!(output, "{}", CStr::from_ptr(msg).to_str().unwrap());
|
let _ = writeln!(output, "{}", CStr::from_ptr(msg).to_str().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Rx {}
|
const DATAPORT_SIZE: usize = 4096;
|
||||||
|
|
||||||
|
pub struct Rx {
|
||||||
|
dataport: &'static [u8],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rx {
|
||||||
|
pub fn new() -> Rx {
|
||||||
|
extern "C" {
|
||||||
|
static rx_dataport: *mut cty::c_uchar;
|
||||||
|
}
|
||||||
|
Rx {
|
||||||
|
dataport: unsafe { core::slice::from_raw_parts(rx_dataport, DATAPORT_SIZE) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl io::Read for Rx {
|
impl io::Read for Rx {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
unsafe {
|
extern "C" {
|
||||||
rx_mutex_lock();
|
fn uart_read_read(limit: cty::size_t) -> cty::c_int;
|
||||||
uart_rx_update(buf.len());
|
}
|
||||||
let port = core::slice::from_raw_parts(rx_dataport, buf.len());
|
let n = unsafe { uart_read_read(buf.len()) };
|
||||||
buf.copy_from_slice(&port);
|
if n >= 0 {
|
||||||
rx_mutex_unlock();
|
let s = n as usize;
|
||||||
|
buf[..s].copy_from_slice(&self.dataport[..s]);
|
||||||
|
Ok(s)
|
||||||
|
} else {
|
||||||
|
Err(io::Error)
|
||||||
}
|
}
|
||||||
Ok(buf.len())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Tx {}
|
pub struct Tx {
|
||||||
|
dataport: &'static mut [u8],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tx {
|
||||||
|
pub fn new() -> Tx {
|
||||||
|
extern "C" {
|
||||||
|
static tx_dataport: *mut cty::c_uchar;
|
||||||
|
}
|
||||||
|
Tx {
|
||||||
|
dataport: unsafe { core::slice::from_raw_parts_mut(tx_dataport, DATAPORT_SIZE) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl io::Write for Tx {
|
impl io::Write for Tx {
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
unsafe {
|
extern "C" {
|
||||||
tx_mutex_lock();
|
fn uart_write_write(available: cty::size_t) -> cty::c_int;
|
||||||
let port = core::slice::from_raw_parts_mut(tx_dataport, buf.len());
|
}
|
||||||
port.copy_from_slice(buf);
|
self.dataport[..buf.len()].copy_from_slice(buf);
|
||||||
uart_tx_update(buf.len());
|
let n = unsafe { uart_write_write(buf.len()) };
|
||||||
tx_mutex_unlock();
|
if n >= 0 {
|
||||||
|
Ok(n as usize)
|
||||||
|
} else {
|
||||||
|
Err(io::Error)
|
||||||
}
|
}
|
||||||
Ok(buf.len())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
// Do nothing. This implementation has no internal buffering.
|
extern "C" {
|
||||||
Ok(())
|
fn uart_write_flush() -> cty::c_int;
|
||||||
|
}
|
||||||
|
if unsafe { uart_write_flush() } == 0 {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(io::Error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2017, Data61
|
* CAmkES component accessing an OpenTitan UART.
|
||||||
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
|
|
||||||
* ABN 41 687 119 230.
|
|
||||||
*
|
*
|
||||||
* This software may be distributed and modified according to the terms of
|
* Copyright 2021, Google LLC
|
||||||
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
|
* Apache License 2.0
|
||||||
* See "LICENSE_BSD2.txt" for details.
|
|
||||||
*
|
|
||||||
* @TAG(DATA61_BSD)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import "../../interfaces/RustIO.idl4";
|
||||||
|
|
||||||
component OpenTitanUARTDriver {
|
component OpenTitanUARTDriver {
|
||||||
dataport Buf mmio_region;
|
dataport Buf mmio_region;
|
||||||
|
|
||||||
dataport Buf tx_dataport;
|
dataport Buf tx_dataport;
|
||||||
provides dataport_io_inf tx;
|
provides rust_write_inf write;
|
||||||
consumes Interrupt tx_watermark;
|
consumes Interrupt tx_watermark;
|
||||||
consumes Interrupt tx_empty;
|
consumes Interrupt tx_empty;
|
||||||
has semaphore tx_semaphore;
|
|
||||||
has mutex tx_mutex;
|
has mutex tx_mutex;
|
||||||
|
|
||||||
dataport Buf rx_dataport;
|
dataport Buf rx_dataport;
|
||||||
provides dataport_io_inf rx;
|
provides rust_read_inf read;
|
||||||
consumes Interrupt rx_watermark;
|
consumes Interrupt rx_watermark;
|
||||||
has semaphore rx_semaphore;
|
has semaphore rx_semaphore;
|
||||||
has mutex rx_mutex;
|
has mutex rx_mutex;
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021, Google LLC
|
||||||
|
*
|
||||||
|
* Error codes for the OpenTitanUARTDriver.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Return codes for errors on read() and write().
|
||||||
|
//
|
||||||
|
// Normally these functions return the number of bytes actually read or written,
|
||||||
|
// with 0 indicating the end of the stream. If something goes wrong, the
|
||||||
|
// functions will return one of these negative values.
|
||||||
|
typedef enum UARTDriverError {
|
||||||
|
UARTDriver_AssertionFailed = -1,
|
||||||
|
UARTDriver_OutOfDataportBounds = -2,
|
||||||
|
} uart_driver_error_t;
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "circular_buffer.h"
|
#include "circular_buffer.h"
|
||||||
#include "opentitan/uart.h"
|
#include "opentitan/uart.h"
|
||||||
|
#include "uart_driver_error.h"
|
||||||
|
|
||||||
// Referenced by macros in the generated file opentitan/uart.h.
|
// Referenced by macros in the generated file opentitan/uart.h.
|
||||||
#define UART0_BASE_ADDR (void *)mmio_region
|
#define UART0_BASE_ADDR (void *)mmio_region
|
||||||
@ -46,6 +47,13 @@
|
|||||||
((value & UART_##regname##_##subfield##_MASK) \
|
((value & UART_##regname##_##subfield##_MASK) \
|
||||||
<< UART_##regname##_##subfield##_OFFSET)
|
<< UART_##regname##_##subfield##_OFFSET)
|
||||||
|
|
||||||
|
#define LOCK(lockname) seL4_Assert(lockname##_lock() == 0);
|
||||||
|
#define UNLOCK(lockname) seL4_Assert(lockname##_unlock() == 0);
|
||||||
|
#define ASSERT_OR_RETURN(x) \
|
||||||
|
if (!(bool)(x)) { \
|
||||||
|
return UARTDriver_AssertionFailed; \
|
||||||
|
}
|
||||||
|
|
||||||
// Driver-owned buffer to receive more than the FIFO size before the received
|
// Driver-owned buffer to receive more than the FIFO size before the received
|
||||||
// data is consumed by rx_update.
|
// data is consumed by rx_update.
|
||||||
static circular_buffer rx_buf; // guarded by rx_mutex
|
static circular_buffer rx_buf; // guarded by rx_mutex
|
||||||
@ -84,7 +92,7 @@ static void uart_putchar(char c) {
|
|||||||
// This stops when the transmit FIFO is full or when tx_buf is empty, whichever
|
// This stops when the transmit FIFO is full or when tx_buf is empty, whichever
|
||||||
// comes first.
|
// comes first.
|
||||||
static void fill_tx_fifo() {
|
static void fill_tx_fifo() {
|
||||||
seL4_Assert(tx_mutex_lock() == 0);
|
LOCK(tx_mutex);
|
||||||
while (tx_fifo_level() < UART_FIFO_CAPACITY) {
|
while (tx_fifo_level() < UART_FIFO_CAPACITY) {
|
||||||
char c;
|
char c;
|
||||||
if (!circular_buffer_pop_front(&tx_buf, &c)) {
|
if (!circular_buffer_pop_front(&tx_buf, &c)) {
|
||||||
@ -93,10 +101,7 @@ static void fill_tx_fifo() {
|
|||||||
}
|
}
|
||||||
uart_putchar(c);
|
uart_putchar(c);
|
||||||
}
|
}
|
||||||
if (circular_buffer_remaining(&tx_buf) > 0) {
|
UNLOCK(tx_mutex);
|
||||||
seL4_Assert(tx_semaphore_post() == 0);
|
|
||||||
}
|
|
||||||
seL4_Assert(tx_mutex_unlock() == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CAmkES initialization hook.
|
// CAmkES initialization hook.
|
||||||
@ -157,62 +162,86 @@ void pre_init() {
|
|||||||
BIT(UART_INTR_COMMON_TX_EMPTY));
|
BIT(UART_INTR_COMMON_TX_EMPTY));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the update method of the CAmkES dataport_inf rx.
|
// Implements Rust Read::read().
|
||||||
//
|
//
|
||||||
// Reads a given number of bytes from rx_buf into the CAmkES rx_dataport,
|
// Reads up to a given limit of bytes into the CAmkES rx_dataport, blocking
|
||||||
// blocking the RPC until the entire requested byte count has been read.
|
// until at least one byte is available.
|
||||||
void rx_update(uint32_t num_to_read) {
|
int read_read(size_t limit) {
|
||||||
// TODO(mattharvey): Error return value for num_to_read >
|
if (limit > TX_RX_DATAPORT_CAPACITY) {
|
||||||
// TX_RX_DATAPORT_CAPACITY.
|
return UARTDriver_OutOfDataportBounds;
|
||||||
seL4_Assert(num_to_read <= TX_RX_DATAPORT_CAPACITY);
|
}
|
||||||
|
char *cursor = (char *)rx_dataport;
|
||||||
|
char *const cursor_begin = cursor;
|
||||||
|
char *const cursor_limit = cursor_begin + limit;
|
||||||
|
|
||||||
char *dataport_cursor = (char *)rx_dataport;
|
LOCK(rx_mutex);
|
||||||
char *const dataport_end = dataport_cursor + num_to_read;
|
{
|
||||||
while (dataport_cursor < dataport_end) {
|
|
||||||
seL4_Assert(rx_mutex_lock() == 0);
|
|
||||||
while (circular_buffer_empty(&rx_buf)) {
|
while (circular_buffer_empty(&rx_buf)) {
|
||||||
seL4_Assert(rx_mutex_unlock() == 0);
|
UNLOCK(rx_mutex);
|
||||||
seL4_Assert(rx_semaphore_wait() == 0);
|
seL4_Assert(rx_semaphore_wait() == 0);
|
||||||
seL4_Assert(rx_mutex_lock() == 0);
|
LOCK(rx_mutex);
|
||||||
}
|
}
|
||||||
for (; dataport_cursor < dataport_end; ++dataport_cursor) {
|
while (cursor < cursor_limit) {
|
||||||
if (!circular_buffer_pop_front(&rx_buf, dataport_cursor)) {
|
if (!circular_buffer_pop_front(&rx_buf, cursor)) {
|
||||||
// The buffer is empty.
|
// The buffer is empty.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
++cursor;
|
||||||
}
|
}
|
||||||
seL4_Assert(rx_mutex_unlock() == 0);
|
|
||||||
}
|
}
|
||||||
|
UNLOCK(rx_mutex);
|
||||||
|
|
||||||
|
int num_read = cursor - cursor_begin;
|
||||||
|
ASSERT_OR_RETURN(num_read > 0);
|
||||||
|
return num_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the update method of the CAmkES dataport_inf tx.
|
// Implements Rust Write::write().
|
||||||
//
|
//
|
||||||
// Writes the contents of the CAmkES tx_dataport to the UART, one at a time,
|
// Writes as many bytes from tx_dataport as the hardware will accept, but not
|
||||||
// blocking the RPC until the entire requested number of bytes has been written.
|
// more than the number available (specified by the argument). Returns the
|
||||||
void tx_update(uint32_t num_valid_dataport_bytes) {
|
// number of bytes written or a negative value if there is any error.
|
||||||
// TODO(mattharvey): Error return value for num_valid_dataport_bytes >
|
int write_write(size_t available) {
|
||||||
// TX_RX_DATAPORT_CAPACITY.
|
if (available > TX_RX_DATAPORT_CAPACITY) {
|
||||||
seL4_Assert(num_valid_dataport_bytes <= TX_RX_DATAPORT_CAPACITY);
|
return UARTDriver_OutOfDataportBounds;
|
||||||
|
}
|
||||||
|
const char *cursor = (const char *)tx_dataport;
|
||||||
|
const char *const cursor_begin = cursor;
|
||||||
|
const char *const cursor_limit = cursor_begin + available;
|
||||||
|
|
||||||
const char *dataport_cursor = (const char *)tx_dataport;
|
while (cursor < cursor_limit) {
|
||||||
const char *const dataport_end = dataport_cursor + num_valid_dataport_bytes;
|
LOCK(tx_mutex);
|
||||||
while (dataport_cursor < dataport_end) {
|
{
|
||||||
seL4_Assert(tx_mutex_lock() == 0);
|
if (circular_buffer_remaining(&tx_buf) == 0) {
|
||||||
while (circular_buffer_remaining(&tx_buf) == 0) {
|
|
||||||
seL4_Assert(tx_mutex_unlock() == 0);
|
|
||||||
seL4_Assert(tx_semaphore_wait() == 0);
|
|
||||||
seL4_Assert(tx_mutex_lock() == 0);
|
|
||||||
}
|
|
||||||
for (; dataport_cursor < dataport_end; ++dataport_cursor) {
|
|
||||||
if (!circular_buffer_push_back(&tx_buf, *dataport_cursor)) {
|
|
||||||
// The buffer is full.
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
for (; cursor < cursor_limit; ++cursor) {
|
||||||
|
if (!circular_buffer_push_back(&tx_buf, *cursor)) {
|
||||||
|
// The buffer is full.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
seL4_Assert(tx_mutex_unlock() == 0);
|
UNLOCK(tx_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
fill_tx_fifo();
|
fill_tx_fifo();
|
||||||
|
|
||||||
|
int num_written = cursor - cursor_begin;
|
||||||
|
ASSERT_OR_RETURN(num_written > 0);
|
||||||
|
return num_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements Rust Write::flush().
|
||||||
|
//
|
||||||
|
// Drains tx_buf and TX_FIFO. Returns a negative value if there is any error.
|
||||||
|
int write_flush() {
|
||||||
|
LOCK(tx_mutex);
|
||||||
|
while (circular_buffer_remaining(&tx_buf)) {
|
||||||
|
fill_tx_fifo();
|
||||||
|
}
|
||||||
|
UNLOCK(tx_mutex);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles a tx_watermark interrupt.
|
// Handles a tx_watermark interrupt.
|
||||||
@ -247,7 +276,7 @@ void rx_watermark_handle(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t num_read = 0;
|
uint32_t num_read = 0;
|
||||||
seL4_Assert(rx_mutex_lock() == 0);
|
LOCK(rx_mutex);
|
||||||
while (num_read < num_to_read) {
|
while (num_read < num_to_read) {
|
||||||
if (!circular_buffer_push_back(&rx_buf, uart_getchar())) {
|
if (!circular_buffer_push_back(&rx_buf, uart_getchar())) {
|
||||||
// The buffer is full.
|
// The buffer is full.
|
||||||
@ -255,7 +284,7 @@ void rx_watermark_handle(void) {
|
|||||||
}
|
}
|
||||||
++num_read;
|
++num_read;
|
||||||
}
|
}
|
||||||
seL4_Assert(rx_mutex_unlock() == 0);
|
UNLOCK(rx_mutex);
|
||||||
|
|
||||||
if (num_read > 0) {
|
if (num_read > 0) {
|
||||||
seL4_Assert(rx_semaphore_post() == 0);
|
seL4_Assert(rx_semaphore_post() == 0);
|
||||||
@ -275,14 +304,16 @@ void rx_watermark_handle(void) {
|
|||||||
void tx_empty_handle(void) {
|
void tx_empty_handle(void) {
|
||||||
fill_tx_fifo();
|
fill_tx_fifo();
|
||||||
|
|
||||||
seL4_Assert(tx_mutex_lock() == 0);
|
LOCK(tx_mutex);
|
||||||
if (circular_buffer_empty(&tx_buf)) {
|
{
|
||||||
// Clears INTR_STATE for tx_empty. (INTR_STATE is write-1-to-clear.) We only
|
if (circular_buffer_empty(&tx_buf)) {
|
||||||
// do this if tx_buf is empty, since the TX FIFO might have become empty in
|
// Clears INTR_STATE for tx_empty. (INTR_STATE is write-1-to-clear.) We
|
||||||
// the time from fill_tx_fifo having sent the last character until here. In
|
// only do this if tx_buf is empty, since the TX FIFO might have become
|
||||||
// that case, we want the interrupt to reassert.
|
// empty in the time from fill_tx_fifo having sent the last character
|
||||||
REG(INTR_STATE) = BIT(UART_INTR_STATE_TX_EMPTY);
|
// until here. In that case, we want the interrupt to reassert.
|
||||||
|
REG(INTR_STATE) = BIT(UART_INTR_STATE_TX_EMPTY);
|
||||||
|
}
|
||||||
|
seL4_Assert(tx_empty_acknowledge() == 0);
|
||||||
}
|
}
|
||||||
seL4_Assert(tx_empty_acknowledge() == 0);
|
UNLOCK(tx_mutex);
|
||||||
seL4_Assert(tx_mutex_unlock() == 0);
|
|
||||||
}
|
}
|
||||||
|
38
apps/system/interfaces/RustIO.idl4
Normal file
38
apps/system/interfaces/RustIO.idl4
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* CAmkES backing for Rust Read and Write traits.
|
||||||
|
*
|
||||||
|
* Copyright 2021, Google LLC
|
||||||
|
* Apache License 2.0
|
||||||
|
*
|
||||||
|
* These CAmkES interfaces express the standard Rust read() and write()
|
||||||
|
* signatures, assuming two separate, externally defined, and implicitly
|
||||||
|
* associated dataports for each of read and write.
|
||||||
|
*
|
||||||
|
* It is intended that Rust code be able to use extern "C" declarations
|
||||||
|
* referencing the camkes.h that this will generate as the core of
|
||||||
|
* implementations of the Read and Write traits.
|
||||||
|
*/
|
||||||
|
|
||||||
|
procedure rust_read_inf {
|
||||||
|
// Reads up to limit bytes into the read dataport.
|
||||||
|
//
|
||||||
|
// Returns the number of bytes read or a negative value if there is any
|
||||||
|
// error.
|
||||||
|
int read(in size_t limit);
|
||||||
|
};
|
||||||
|
|
||||||
|
procedure rust_write_inf {
|
||||||
|
// Writes up to a given number of bytes from the write dataport.
|
||||||
|
//
|
||||||
|
// Returns the number of bytes actually written or a negative value if there
|
||||||
|
// is any error. For non-negative return values < available, the caller is
|
||||||
|
// reponsible for retrying with the remaining bytes at the beginning of the
|
||||||
|
// write dataport.
|
||||||
|
int write(in size_t available);
|
||||||
|
|
||||||
|
// Blocks until all bytes so far written have been pushed to the real sink.
|
||||||
|
//
|
||||||
|
// The semantics are the same as Rust's Write::flush. Returns 0 on success
|
||||||
|
// and a negative value if there is any error.
|
||||||
|
int flush();
|
||||||
|
}
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 dataport_io_inf {
|
|
||||||
void update(in size_t n);
|
|
||||||
};
|
|
@ -13,7 +13,6 @@
|
|||||||
import <std_connector.camkes>;
|
import <std_connector.camkes>;
|
||||||
import <global-connectors.camkes>;
|
import <global-connectors.camkes>;
|
||||||
|
|
||||||
import "interfaces/dataport_io.idl4";
|
|
||||||
import "interfaces/VectorCoreInterface.camkes";
|
import "interfaces/VectorCoreInterface.camkes";
|
||||||
import "interfaces/VectorCoreReturnInterface.camkes";
|
import "interfaces/VectorCoreReturnInterface.camkes";
|
||||||
import "components/OpenTitanUARTDriver/OpenTitanUARTDriver.camkes";
|
import "components/OpenTitanUARTDriver/OpenTitanUARTDriver.camkes";
|
||||||
@ -108,12 +107,12 @@ assembly {
|
|||||||
// Connect the DebugConsole to the OpenTitanUARTDriver.
|
// Connect the DebugConsole to the OpenTitanUARTDriver.
|
||||||
connection seL4SharedData tx_channel(
|
connection seL4SharedData tx_channel(
|
||||||
from debug_console.tx_dataport, to uart_driver.tx_dataport);
|
from debug_console.tx_dataport, to uart_driver.tx_dataport);
|
||||||
connection seL4RPCCall tx_call(
|
connection seL4RPCCall write_call(
|
||||||
from debug_console.uart_tx, to uart_driver.tx);
|
from debug_console.uart_write, to uart_driver.write);
|
||||||
connection seL4SharedData rx_channel(
|
connection seL4SharedData rx_channel(
|
||||||
from debug_console.rx_dataport, to uart_driver.rx_dataport);
|
from debug_console.rx_dataport, to uart_driver.rx_dataport);
|
||||||
connection seL4RPCCall rx_call(
|
connection seL4RPCCall read_call(
|
||||||
from debug_console.uart_rx, to uart_driver.rx);
|
from debug_console.uart_read, to uart_driver.read);
|
||||||
|
|
||||||
// Connect the LoggerInterface to each component that needs to log
|
// Connect the LoggerInterface to each component that needs to log
|
||||||
// to the console. Note this allocates a 4KB shared memory region to
|
// to the console. Note this allocates a 4KB shared memory region to
|
||||||
|
Loading…
Reference in New Issue
Block a user