/src/main.rs
#![no_std]
#![no_main]
#![feature(generators, generator_trait)]
#![feature(global_asm)]
#![feature(alloc)]
#![feature(alloc_error_handler)]
#![feature(asm)]
#![feature(const_vec_new)]
#![feature(const_fn)]
#![feature(panic_info_message)]

use cortex_m_rt::{entry, pre_init};
use embedded_hal::watchdog::WatchdogDisable; // REMOVE when embedded-hal watchdog is finalized
use alloc_cortex_m::CortexMHeap;
use r0;

mod util;
mod console;
mod peripherals;
mod timer;
mod mpu;
mod task;
mod svcall;
mod alloc;
mod fault;
mod panic;
mod video;

use peripherals::Peripherals;
use task::Task;
use console::get_global_console;

#[global_allocator]
#[link_section = ".kgbss"]
static ALLOCATOR: CortexMHeap = CortexMHeap::empty();

struct Kernel {
    peripherals: Peripherals,
}

impl Kernel {
    pub fn new() -> Kernel {
        Kernel {
            peripherals: Peripherals::new(),
        }
    }

    pub fn get_peripherals(&mut self) -> &mut Peripherals {
        &mut self.peripherals
    }
}

extern "C" {
    fn shell_main() -> u32;
}

#[allow(dead_code)]
pub struct RustDriverInterfaces {
    console: &'static console::RustConsoleOperations,
    alloc: &'static alloc::RustAllocOperations,
}

#[link_section = ".driver_interfaces"]
pub static RUST_DRIVER_INTERFACES: RustDriverInterfaces = RustDriverInterfaces {
    console: &console::RUST_CONSOLE_OPERATIONS,
    alloc: &alloc::RUST_ALLOC_OPERATIONS,
};

#[allow(dead_code)]
#[repr(C)]
pub struct CDriverInterfaces {
    console: &'static console::CConsoleOperations,
    alloc: &'static alloc::CAllocOperations,
}

#[link_section = ".driver_interfaces"]
pub static C_DRIVER_INTERFACES: CDriverInterfaces = CDriverInterfaces {
    console: &console::C_CONSOLE_OPERATIONS,
    alloc: &alloc::C_ALLOC_OPERATIONS,
};

#[pre_init]
unsafe fn pre_init() {
    extern "C" {
        static mut __skgbss: u32;
        static mut __ekgbss: u32;

        static mut __skgdata: u32;
        static mut __ekgdata: u32;
        static __sikgdata: u32;
    }

    // Initialize KGRAM
    r0::zero_bss(&mut __skgbss, &mut __ekgbss);
    r0::init_data(&mut __skgdata, &mut __ekgdata, &__sikgdata);
}

#[entry]
fn main() -> ! {
    let mut kernel = Kernel::new();

    let peripherals = kernel.get_peripherals();

    peripherals.watchdog.disable();

    get_global_console().write("Kernel initialized!\n");

    let t = Task::default_layout_full(shell_main);
    t.run()
}