blob: e89586d2ba94f6dc7e05897b0ff18313527a8d07 [file] [log] [blame]
#![feature(asm,alloc,allocator_api,compiler_builtins_lib,const_fn,global_allocator,lang_items,naked_functions)]
#![no_std]
pub mod syscalls;
pub mod ipc;
pub mod sensors;
pub mod console;
pub mod timer;
pub mod led;
extern crate alloc;
extern crate compiler_builtins;
extern crate linked_list_allocator;
mod lang_items;
use alloc::allocator::{Alloc, Layout, AllocErr};
use core::ptr;
use core::mem::{align_of, size_of};
use linked_list_allocator::{align_up, Heap};
// None-threaded heap wrapper based on `r9` register instead of global variable
struct BaseHeap;
impl BaseHeap {
pub unsafe fn heap(&self) -> &mut Heap {
let heap: &mut Heap;
asm!("mov $0, r9" : "=r"(heap) : : : "volatile");
heap
}
/// Initializes an empty heap
///
/// Returns the end of the heap
///
/// # Unsafety
///
/// This function must be called at most once and must only be used on an
/// empty heap.
#[inline(never)]
pub unsafe fn init(&mut self, heap_size: usize) -> usize {
let heap_bottom = align_up(self as *mut _ as usize + size_of::<Heap>(),
align_of::<Heap>());
self.heap().init(heap_bottom, heap_size);
heap_bottom + heap_size
}
}
unsafe impl<'a> Alloc for &'a BaseHeap {
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
self.heap().allocate_first_fit(layout)
}
unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
self.heap().deallocate(ptr, layout)
}
}
#[global_allocator]
static ALLOCATOR : BaseHeap = BaseHeap;
/// Tock programs' entry point
#[doc(hidden)]
#[no_mangle]
#[naked]
pub extern "C" fn _start(mem_start: usize, _app_heap_break: usize,
_kernel_memory_break: usize) -> ! {
extern "C" {
// NOTE `rustc` forces this signature on us. See `src/lang_items.rs`
fn main(argc: isize, argv: *const *const u8) -> isize;
}
unsafe {
// Setup stack
syscalls::memop(0, mem_start + 1024);
let new_stack = mem_start + 1024;
asm!("mov sp, $0" : : "r"(new_stack) : : "volatile");
syscalls::memop(10, new_stack);
// Setup heap
let new_heap = align_up(new_stack, align_of::<Heap>());
asm!("mov r9, $0" : : "r"(new_heap) : : "volatile");
syscalls::memop(11, new_heap);
let end_of_mem = BaseHeap.init(1024);
syscalls::memop(0, end_of_mem);
// arguments are not used in Tock applications
main(0, ptr::null());
}
loop {
::syscalls::yieldk();
}
}