extern crate alloc;
use core::alloc::{GlobalAlloc, Layout};
use alloc::collections::BTreeMap;
-use crate::console::ConsoleOutput;
use crate::ALLOCATOR;
pub unsafe fn init(start: usize, size: usize) {
let ptr = ALLOCATOR.alloc(layout);
#[cfg(alloc_trace)]
{
- crate::serial_console::get_global_console().write("+");
+ crate::console::get_global_console().write("+");
crate::util::print_hex_padded(ptr as u32, 8);
- crate::serial_console::get_global_console().write(" ");
+ crate::console::get_global_console().write(" ");
}
ptr
}
pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
#[cfg(alloc_trace)]
{
- crate::serial_console::get_global_console().write("-");
+ crate::console::get_global_console().write("-");
crate::util::print_hex_padded(ptr as u32, 8);
- crate::serial_console::get_global_console().write(" ");
+ crate::console::get_global_console().write(" ");
}
ALLOCATOR.dealloc(ptr, layout);
}
pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
#[cfg(alloc_trace)]
{
- crate::serial_console::get_global_console().write("=");
+ crate::console::get_global_console().write("=");
crate::util::print_hex_padded(ptr as u32, 8);
}
let ptr = ALLOCATOR.realloc(ptr, layout, new_size);
#[cfg(alloc_trace)]
{
- crate::serial_console::get_global_console().write("/");
+ crate::console::get_global_console().write("/");
crate::util::print_hex_padded(ptr as u32, 8);
- crate::serial_console::get_global_console().write(" ");
+ crate::console::get_global_console().write(" ");
}
ptr
}
#[alloc_error_handler]
pub fn handle_alloc_error(_layout: Layout) -> ! {
- crate::serial_console::get_global_console().write("OOM!\r\n");
+ crate::console::get_global_console().write("OOM!\r\n");
loop{}
}
-use arraydeque::ArrayDeque;
-use cortex_m::interrupt;
-
-pub trait ConsoleInput {
- fn readb(&mut self) -> Option<u8>;
- fn read(&mut self, buf: &mut [u8]) -> usize;
- fn discard(&mut self);
-}
-
-pub trait ConsoleOutput {
- fn pos(&mut self, x: usize, y: usize);
- fn writeb(&mut self, b: u8);
- fn write<T: AsRef<[u8]>>(&mut self, a: T);
- fn clear(&mut self);
-}
-
-const BUFFER_SIZE: usize = 16;
-
-pub struct Console {
- rb: ArrayDeque<[u8; BUFFER_SIZE], arraydeque::Saturating>,
-}
-
-impl Console {
- pub fn new() -> Console {
- Console {
- rb: ArrayDeque::new(),
- }
- }
-
- pub fn reset(&mut self) {
- interrupt::free(|_| {
- self.rb.clear();
- });
- }
-
- pub fn pushb(&mut self, b: u8) {
- interrupt::free(|_| {
- self.rb.push_back(b).ok();
- });
- }
-}
-
-impl ConsoleInput for Console {
- fn readb(&mut self) -> Option<u8> {
- interrupt::free(|_| {
- self.rb.pop_front()
- })
- }
-
- fn read(&mut self, buf: &mut [u8]) -> usize {
- let len = if buf.len() > self.rb.len() {
- self.rb.len()
- } else {
- buf.len()
- };
-
- for i in 0..len {
- buf[i] = self.readb().unwrap();
- }
-
- len
- }
-
- fn discard(&mut self) {
- self.reset();
- }
-}
-
-pub struct RustConsoleOperations {
- pub readb: fn() -> Option<u8>,
- pub read: fn(&mut [u8]) -> usize,
- pub readline: fn(buf: &mut [u8]) -> usize,
- pub writeb: fn(b: u8),
- pub write: fn(a: &[u8]),
- pub discard: fn(),
- pub pos: fn(x: usize, y: usize),
- pub clear: fn(),
-}
-
-#[repr(C)]
-pub struct CConsoleOperations {
- pub readb: extern "C" fn() -> i32,
- pub read: extern "C" fn(buf: *mut u8, len: usize) -> usize,
- pub readline: extern "C" fn(buf: *mut u8, len: usize) -> usize,
- pub writeb: extern "C" fn(b: u8),
- pub write: extern "C" fn(a: *const u8, len: usize),
- pub discard: extern "C" fn(),
- pub pos: extern "C" fn(x: usize, y: usize),
- pub clear: extern "C" fn(),
-}
+use core::slice;
+
+use crate::console::get_global_console;
+
+pub struct RustConsoleOperations {
+ pub readb: fn() -> Option<u8>,
+ pub read: fn(&mut [u8]) -> usize,
+ pub readline: fn(buf: &mut [u8]) -> usize,
+ pub writeb: fn(b: u8),
+ pub write: fn(a: &[u8]),
+ pub discard: fn(),
+ pub pos: fn(x: usize, y: usize),
+ pub clear: fn(),
+}
+
+#[repr(C)]
+pub struct CConsoleOperations {
+ pub readb: extern "C" fn() -> i32,
+ pub read: extern "C" fn(buf: *mut u8, len: usize) -> usize,
+ pub readline: extern "C" fn(buf: *mut u8, len: usize) -> usize,
+ pub writeb: extern "C" fn(b: u8),
+ pub write: extern "C" fn(a: *const u8, len: usize),
+ pub discard: extern "C" fn(),
+ pub pos: extern "C" fn(x: usize, y: usize),
+ pub clear: extern "C" fn(),
+}
+
+/* Console driver function table */
+
+/* Rust versions */
+fn rust_readb() -> Option<u8> {
+ get_global_console().readb()
+}
+
+fn rust_read(buf: &mut [u8]) -> usize {
+ get_global_console().read(buf)
+}
+
+fn rust_readline(buf: &mut [u8]) -> usize {
+ get_global_console().readline(buf)
+}
+
+fn rust_writeb(b: u8) {
+ get_global_console().writeb(b)
+}
+
+fn rust_write(a: &[u8]) {
+ get_global_console().write(a)
+}
+
+fn rust_discard() {
+ get_global_console().discard()
+}
+
+fn rust_pos(x: usize, y: usize) {
+ get_global_console().pos(x, y)
+}
+
+fn rust_clear() {
+ get_global_console().clear()
+}
+
+pub const RUST_CONSOLE_OPERATIONS: RustConsoleOperations = RustConsoleOperations {
+ readb: rust_readb,
+ read: rust_read,
+ readline: rust_readline,
+ writeb: rust_writeb,
+ write: rust_write,
+ discard: rust_discard,
+ pos: rust_pos,
+ clear: rust_clear,
+};
+
+/* C versions */
+extern "C" fn c_readb() -> i32 {
+ match rust_readb() {
+ Some(b) => b as i32,
+ None => -1,
+ }
+}
+
+extern "C" fn c_read(buf: *mut u8, len: usize) -> usize {
+ if len == 0 {
+ return 0;
+ }
+
+ let buf = unsafe { slice::from_raw_parts_mut(buf, len) };
+ rust_read(buf)
+}
+
+extern "C" fn c_readline(buf: *mut u8, len: usize) -> usize {
+ let buf = unsafe { slice::from_raw_parts_mut(buf, len) };
+ rust_readline(buf)
+}
+
+extern "C" fn c_writeb(b: u8) {
+ rust_writeb(b)
+}
+
+extern "C" fn c_write(a: *const u8, len: usize) {
+ let a = unsafe { slice::from_raw_parts(a, len) };
+ rust_write(a)
+}
+
+extern "C" fn c_discard() {
+ rust_discard()
+}
+
+extern "C" fn c_pos(x: usize, y: usize) {
+ rust_pos(x, y)
+}
+
+extern "C" fn c_clear() {
+ rust_clear()
+}
+
+pub const C_CONSOLE_OPERATIONS: CConsoleOperations = CConsoleOperations {
+ readb: c_readb,
+ read: c_read,
+ readline: c_readline,
+ writeb: c_writeb,
+ write: c_write,
+ discard: c_discard,
+ pos: c_pos,
+ clear: c_clear,
+};
+use core::fmt;
+
+pub mod serial;
+pub mod traits;
+pub mod interfaces;
+
+use crate::console::serial::SerialTerminal;
+
+pub use crate::console::traits::*;
+pub use crate::console::interfaces::*;
+
+#[link_section = ".kgbss"]
+static mut G_CONSOLE: Option<Console> = None;
+
+pub fn get_global_console() -> &'static mut Console {
+ unsafe {
+ core::intrinsics::transmute(&mut G_CONSOLE)
+ }
+}
+
+pub struct Console {
+ terminal: SerialTerminal,
+}
+
+impl Console {
+ pub fn new(terminal: SerialTerminal) -> Console {
+ Console {
+ terminal,
+ }
+ }
+
+ pub fn readb(&mut self) -> Option<u8> {
+ self.terminal.readb()
+ }
+
+ pub fn read(&mut self, buf: &mut [u8]) -> usize {
+ self.terminal.read(buf)
+ }
+
+ pub fn readline(&mut self, buf: &mut [u8]) -> usize {
+ self.terminal.readline(buf)
+ }
+
+ pub fn discard(&mut self) {
+ self.terminal.discard();
+ }
+
+ pub fn pos(&mut self, x: usize, y: usize) {
+ self.terminal.pos(x, y);
+ }
+
+ pub fn writeb(&mut self, b: u8) {
+ self.terminal.writeb(b);
+ }
+
+ pub fn write<T: AsRef<[u8]>>(&mut self, a: T) {
+ self.terminal.write(a);
+ }
+
+ pub fn clear(&mut self) {
+ self.terminal.clear();
+ }
+
+ pub fn handle_interrupt(&mut self) {
+ self.terminal.handle_interrupt();
+ }
+}
+
+impl fmt::Write for Console {
+ fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
+ self.write(s);
+ Ok(())
+ }
+}
+use arraydeque::ArrayDeque;
+use core::fmt;
+use nb::block;
+use embedded_hal::serial::*;
+use atsam3xa::interrupt;
+use cortex_m::interrupt as cm_interrupt;
+
+use crate::console::traits::*;
+use crate::console::get_global_console;
+
+const BUFFER_SIZE: usize = 16;
+
+pub struct SerialTerminal {
+ input_buffer: ArrayDeque<[u8; BUFFER_SIZE], arraydeque::Saturating>,
+ uart: atsam3xa_hal::uart::UART,
+}
+
+impl SerialTerminal {
+ pub fn new(uart: atsam3xa_hal::uart::UART) -> SerialTerminal {
+ SerialTerminal {
+ input_buffer: ArrayDeque::new(),
+ uart,
+ }
+ }
+
+ pub fn handle_interrupt(&mut self) {
+ if let Ok(b) = self.uart.read() {
+ self.input_buffer.push_back(b).ok();
+ }
+ }
+}
+
+impl ConsoleIO for SerialTerminal {
+ fn readb(&mut self) -> Option<u8> {
+ cm_interrupt::free(|_| {
+ self.input_buffer.pop_front()
+ })
+ }
+
+ fn read(&mut self, buf: &mut [u8]) -> usize {
+ let len = if buf.len() > self.input_buffer.len() {
+ self.input_buffer.len()
+ } else {
+ buf.len()
+ };
+
+ for i in 0..len {
+ buf[i] = self.readb().unwrap();
+ }
+
+ len
+ }
+
+ fn readline(&mut self, buf: &mut [u8]) -> usize {
+ let mut c = 0;
+
+ loop {
+ let byte = match self.readb() {
+ Some(b) => b,
+ None => continue,
+ };
+
+ if byte == 0xd {
+ break;
+ } else if byte == 0x8 {
+ if c == 0 {
+ // buffer empty
+ continue;
+ }
+ self.write("\x08 \x08");
+ c -= 1;
+ continue;
+ }
+
+ if c == buf.len() {
+ // Don't overflow the buffer
+ continue;
+ }
+
+ self.writeb(byte);
+ buf[c] = byte;
+ c += 1;
+ }
+
+ c
+ }
+
+ fn discard(&mut self) {
+ cm_interrupt::free(|_| {
+ self.input_buffer.clear();
+ });
+ }
+
+ fn pos(&mut self, x: usize, y: usize) {
+ use core::fmt::Write;
+ assert!(x < 80 && y < 25);
+ write!(self, "\x1b[{};{}H", y, x).ok();
+ }
+
+ fn writeb(&mut self, b: u8) {
+ block!(self.uart.write(b)).ok();
+ }
+
+ fn write<T: AsRef<[u8]>>(&mut self, a: T) {
+ let bytes = a.as_ref();
+ for b in bytes {
+ self.writeb(*b);
+ }
+ }
+
+ fn clear(&mut self) {
+ self.write(&[0x1b, b'[', b'2', b'J', 0x1b, b'[', b'H']);
+ }
+}
+
+impl fmt::Write for SerialTerminal {
+ fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
+ self.write(s);
+ Ok(())
+ }
+}
+
+#[interrupt]
+fn UART() {
+ get_global_console().handle_interrupt();
+}
+pub trait ConsoleIO {
+ // input
+ fn readb(&mut self) -> Option<u8>;
+ fn read(&mut self, buf: &mut [u8]) -> usize;
+ fn readline(&mut self, buf: &mut [u8]) -> usize;
+ fn discard(&mut self);
+
+ // output
+ fn pos(&mut self, x: usize, y: usize);
+ fn writeb(&mut self, b: u8);
+ fn write<T: AsRef<[u8]>>(&mut self, a: T);
+ fn clear(&mut self);
+}
use cortex_m;
use cortex_m_rt::exception;
use cortex_m_rt::ExceptionFrame;
-use crate::serial_console::get_global_console;
-use crate::console::ConsoleOutput;
+use crate::console::get_global_console;
use crate::util::print_hex_padded;
fn print_exception_frame(ef: &ExceptionFrame) {
mod util;
mod console;
-mod serial_console;
mod peripherals;
mod timer;
mod mpu;
mod panic;
mod video;
-use console::ConsoleOutput;
use peripherals::Peripherals;
use task::Task;
+use console::get_global_console;
#[global_allocator]
#[link_section = ".kgbss"]
#[link_section = ".driver_interfaces"]
pub static RUST_DRIVER_INTERFACES: RustDriverInterfaces = RustDriverInterfaces {
- console: &serial_console::RUST_CONSOLE_OPERATIONS,
+ console: &console::RUST_CONSOLE_OPERATIONS,
alloc: &alloc::RUST_ALLOC_OPERATIONS,
};
#[link_section = ".driver_interfaces"]
pub static C_DRIVER_INTERFACES: CDriverInterfaces = CDriverInterfaces {
- console: &serial_console::C_CONSOLE_OPERATIONS,
+ console: &console::C_CONSOLE_OPERATIONS,
alloc: &alloc::C_ALLOC_OPERATIONS,
};
peripherals.watchdog.disable();
- serial_console::get_global_console().write("Kernel initialized!\n");
+ get_global_console().write("Kernel initialized!\n");
let t = Task::default_layout_full(shell_main);
t.run()
extern crate alloc;
use core::panic::PanicInfo;
use core::fmt;
-use crate::serial_console::get_global_console;
-use crate::console::ConsoleOutput;
+use crate::console::get_global_console;
use crate::util::print_dec;
#[panic_handler]
use cortex_m::peripheral::MPU;
use atsam3xa_hal::prelude::*;
-use crate::serial_console::SerialConsole;
+use crate::console::Console;
+use crate::console::serial::SerialTerminal;
use crate::mpu::{self, MemoryRegion, MemoryPermission};
use crate::timer;
use crate::video;
mp.NVIC.enable(atsam3xa::Interrupt::UART);
unsafe { mp.NVIC.set_priority(atsam3xa::Interrupt::UART, 7 << 4) };
uart.enable_interrupts();
- SerialConsole::new(uart);
+ Console::new(SerialTerminal::new(uart));
let watchdog = pp.WDT.constrain();
-use crate::console::*;
-
-use core::slice;
-use core::fmt;
-use nb::block;
-use embedded_hal::serial::*;
-use atsam3xa::interrupt;
-
-#[link_section = ".kgbss"]
-static mut G_CONSOLE: Option<SerialConsole> = None;
-
-pub struct SerialConsole {
- console: Console,
- uart: atsam3xa_hal::uart::UART,
-}
-
-impl SerialConsole {
- pub fn new(uart: atsam3xa_hal::uart::UART) {
- unsafe {
- G_CONSOLE = Some(SerialConsole {
- console: Console::new(),
- uart: uart,
- });
- }
- }
-
- pub fn readline(&mut self, buf: &mut [u8]) -> usize {
- let mut c = 0;
-
- loop {
- let byte = match self.readb() {
- Some(b) => b,
- None => continue,
- };
-
- if byte == 0xd {
- break;
- } else if byte == 0x8 {
- if c == 0 {
- // buffer empty
- continue;
- }
- self.write("\x08 \x08");
- c -= 1;
- continue;
- }
-
- if c == buf.len() {
- // Don't overflow the buffer
- continue;
- }
-
- self.writeb(byte);
- buf[c] = byte;
- c += 1;
- }
-
- c
- }
-
- fn handle_interrupt(&mut self) {
- if let Ok(b) = self.uart.read() {
- self.console.pushb(b);
- }
- }
-}
-
-impl ConsoleOutput for SerialConsole {
- fn pos(&mut self, x: usize, y: usize) {
- }
-
- fn writeb(&mut self, b: u8) {
- block!(self.uart.write(b)).ok();
- }
-
- fn write<T: AsRef<[u8]>>(&mut self, a: T) {
- let bytes = a.as_ref();
- for b in bytes {
- self.writeb(*b);
- }
- }
-
- fn clear(&mut self) {
- self.write(&[0x1b, b'[', b'2', b'J', 0x1b, b'[', b'H']);
- }
-}
-
-impl fmt::Write for SerialConsole {
- fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
- self.write(s);
- Ok(())
- }
-}
-
-impl ConsoleInput for SerialConsole {
- fn readb(&mut self) -> Option<u8> {
- self.console.readb()
- }
-
- fn read(&mut self, buf: &mut [u8]) -> usize {
- self.console.read(buf)
- }
-
- fn discard(&mut self) {
- self.console.discard()
- }
-}
-
-pub fn get_global_console() -> &'static mut SerialConsole {
- unsafe {
- core::intrinsics::transmute(&mut G_CONSOLE)
- }
-}
-
-#[interrupt]
-fn UART() {
- get_global_console().handle_interrupt();
-}
-
-
-/* Console driver function table */
-
-/* Rust versions */
-fn rust_readb() -> Option<u8> {
- get_global_console().readb()
-}
-
-fn rust_read(buf: &mut [u8]) -> usize {
- get_global_console().read(buf)
-}
-
-fn rust_readline(buf: &mut [u8]) -> usize {
- get_global_console().readline(buf)
-}
-
-fn rust_writeb(b: u8) {
- get_global_console().writeb(b)
-}
-
-fn rust_write(a: &[u8]) {
- get_global_console().write(a)
-}
-
-fn rust_discard() {
- get_global_console().discard()
-}
-
-fn rust_pos(x: usize, y: usize) {
- get_global_console().pos(x, y)
-}
-
-fn rust_clear() {
- get_global_console().clear()
-}
-
-pub const RUST_CONSOLE_OPERATIONS: RustConsoleOperations = RustConsoleOperations {
- readb: rust_readb,
- read: rust_read,
- readline: rust_readline,
- writeb: rust_writeb,
- write: rust_write,
- discard: rust_discard,
- pos: rust_pos,
- clear: rust_clear,
-};
-
-/* C versions */
-extern "C" fn c_readb() -> i32 {
- match rust_readb() {
- Some(b) => b as i32,
- None => -1,
- }
-}
-
-extern "C" fn c_read(buf: *mut u8, len: usize) -> usize {
- if len == 0 {
- return 0;
- }
-
- let buf = unsafe { slice::from_raw_parts_mut(buf, len) };
- rust_read(buf)
-}
-
-extern "C" fn c_readline(buf: *mut u8, len: usize) -> usize {
- let buf = unsafe { slice::from_raw_parts_mut(buf, len) };
- rust_readline(buf)
-}
-
-extern "C" fn c_writeb(b: u8) {
- rust_writeb(b)
-}
-
-extern "C" fn c_write(a: *const u8, len: usize) {
- let a = unsafe { slice::from_raw_parts(a, len) };
- rust_write(a)
-}
-
-extern "C" fn c_discard() {
- rust_discard()
-}
-
-extern "C" fn c_pos(x: usize, y: usize) {
- rust_pos(x, y)
-}
-
-extern "C" fn c_clear() {
- rust_clear()
-}
-
-pub const C_CONSOLE_OPERATIONS: CConsoleOperations = CConsoleOperations {
- readb: c_readb,
- read: c_read,
- readline: c_readline,
- writeb: c_writeb,
- write: c_write,
- discard: c_discard,
- pos: c_pos,
- clear: c_clear,
-};
use cortex_m_rt::ExceptionFrame;
-use crate::console::ConsoleOutput;
-use crate::serial_console::get_global_console;
+use crate::console::get_global_console;
use crate::util::{print_dec, print_hex_padded};
global_asm!(r#"
#![allow(dead_code)]
-use crate::serial_console::get_global_console;
-use crate::console::ConsoleOutput;
+use crate::console::get_global_console;
pub fn dec_digit(n: u32) -> u8 {
b'0' + (n % 10) as u8