#![no_std]
#![cfg_attr(not(doc), no_main)]
use core::ptr::{addr_of, addr_of_mut};
use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
use e310_g002::interrupt_service::E310G002DefaultPeripherals;
use kernel::capabilities;
use kernel::component::Component;
use kernel::hil;
use kernel::hil::led::LedLow;
use kernel::platform::chip::Chip;
use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
use kernel::platform::{KernelResources, SyscallDriverLookup};
use kernel::scheduler::cooperative::CooperativeSched;
use kernel::utilities::registers::interfaces::ReadWriteable;
use kernel::Kernel;
use kernel::{create_capability, debug, static_init};
use rv32i::csr;
pub mod io;
pub const NUM_PROCS: usize = 4;
static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
[None; NUM_PROCS];
static mut CHIP: Option<&'static e310_g002::chip::E310x<E310G002DefaultPeripherals>> = None;
static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
None;
const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
capsules_system::process_policies::PanicFaultPolicy {};
#[no_mangle]
#[link_section = ".stack_buffer"]
pub static mut STACK_MEMORY: [u8; 0x900] = [0; 0x900];
struct HiFive1 {
led: &'static capsules_core::led::LedDriver<
'static,
LedLow<'static, sifive::gpio::GpioPin<'static>>,
3,
>,
console: &'static capsules_core::console::Console<'static>,
lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
'static,
capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
>,
alarm: &'static capsules_core::alarm::AlarmDriver<
'static,
VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>,
>,
scheduler: &'static CooperativeSched<'static>,
scheduler_timer: &'static VirtualSchedulerTimer<
VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>,
>,
}
impl SyscallDriverLookup for HiFive1 {
fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
where
F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
{
match driver_num {
capsules_core::led::DRIVER_NUM => f(Some(self.led)),
capsules_core::console::DRIVER_NUM => f(Some(self.console)),
capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
_ => f(None),
}
}
}
impl KernelResources<e310_g002::chip::E310x<'static, E310G002DefaultPeripherals<'static>>>
for HiFive1
{
type SyscallDriverLookup = Self;
type SyscallFilter = ();
type ProcessFault = ();
type Scheduler = CooperativeSched<'static>;
type SchedulerTimer =
VirtualSchedulerTimer<VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>>;
type WatchDog = ();
type ContextSwitchCallback = ();
fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
self
}
fn syscall_filter(&self) -> &Self::SyscallFilter {
&()
}
fn process_fault(&self) -> &Self::ProcessFault {
&()
}
fn scheduler(&self) -> &Self::Scheduler {
self.scheduler
}
fn scheduler_timer(&self) -> &Self::SchedulerTimer {
self.scheduler_timer
}
fn watchdog(&self) -> &Self::WatchDog {
&()
}
fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
&()
}
}
#[inline(never)]
fn load_processes_not_inlined<C: Chip>(board_kernel: &'static Kernel, chip: &'static C) {
extern "C" {
static _sapps: u8;
static _eapps: u8;
static mut _sappmem: u8;
static _eappmem: u8;
}
let app_flash = unsafe {
core::slice::from_raw_parts(
core::ptr::addr_of!(_sapps),
core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
)
};
let app_memory = unsafe {
core::slice::from_raw_parts_mut(
core::ptr::addr_of_mut!(_sappmem),
core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
)
};
let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
kernel::process::load_processes(
board_kernel,
chip,
app_flash,
app_memory,
unsafe { &mut *addr_of_mut!(PROCESSES) },
&FAULT_RESPONSE,
&process_mgmt_cap,
)
.unwrap_or_else(|err| {
debug!("Error loading processes!");
debug!("{:?}", err);
});
}
#[inline(never)]
unsafe fn start() -> (
&'static kernel::Kernel,
HiFive1,
&'static e310_g002::chip::E310x<'static, E310G002DefaultPeripherals<'static>>,
) {
rv32i::configure_trap_handler();
let peripherals = static_init!(
E310G002DefaultPeripherals,
E310G002DefaultPeripherals::new(344_000_000)
);
peripherals.init();
peripherals.e310x.watchdog.disable();
peripherals.e310x.rtc.disable();
peripherals.e310x.pwm0.disable();
peripherals.e310x.pwm1.disable();
peripherals.e310x.pwm2.disable();
peripherals.e310x.uart1.disable();
peripherals
.e310x
.prci
.set_clock_frequency(sifive::prci::ClockFrequency::Freq344Mhz);
let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
kernel::debug::assign_gpios(
Some(&peripherals.e310x.gpio_port[22]), None,
None,
);
let uart_mux = components::console::UartMuxComponent::new(&peripherals.e310x.uart0, 115200)
.finalize(components::uart_mux_component_static!());
let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
LedLow<'static, sifive::gpio::GpioPin>,
LedLow::new(&peripherals.e310x.gpio_port[22]), LedLow::new(&peripherals.e310x.gpio_port[19]), LedLow::new(&peripherals.e310x.gpio_port[21]), ));
peripherals.e310x.uart0.initialize_gpio_pins(
&peripherals.e310x.gpio_port[17],
&peripherals.e310x.gpio_port[16],
);
let hardware_timer = static_init!(
e310_g002::chip::E310xClint,
e310_g002::chip::E310xClint::new(&e310_g002::clint::CLINT_BASE)
);
let mux_alarm = static_init!(
MuxAlarm<'static, e310_g002::chip::E310xClint>,
MuxAlarm::new(hardware_timer)
);
hil::time::Alarm::set_alarm_client(hardware_timer, mux_alarm);
let virtual_alarm_user = static_init!(
VirtualMuxAlarm<'static, e310_g002::chip::E310xClint>,
VirtualMuxAlarm::new(mux_alarm)
);
virtual_alarm_user.setup();
let systick_virtual_alarm = static_init!(
VirtualMuxAlarm<'static, e310_g002::chip::E310xClint>,
VirtualMuxAlarm::new(mux_alarm)
);
systick_virtual_alarm.setup();
let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
let alarm = static_init!(
capsules_core::alarm::AlarmDriver<
'static,
VirtualMuxAlarm<'static, e310_g002::chip::E310xClint>,
>,
capsules_core::alarm::AlarmDriver::new(
virtual_alarm_user,
board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
)
);
hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
let chip = static_init!(
e310_g002::chip::E310x<E310G002DefaultPeripherals>,
e310_g002::chip::E310x::new(peripherals, hardware_timer)
);
CHIP = Some(chip);
let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
.finalize(components::process_printer_text_component_static!());
PROCESS_PRINTER = Some(process_printer);
let process_console = components::process_console::ProcessConsoleComponent::new(
board_kernel,
uart_mux,
mux_alarm,
process_printer,
None,
)
.finalize(components::process_console_component_static!(
e310_g002::chip::E310xClint
));
let _ = process_console.start();
chip.enable_plic_interrupts();
csr::CSR
.mie
.modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET);
csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
let console = components::console::ConsoleComponent::new(
board_kernel,
capsules_core::console::DRIVER_NUM,
uart_mux,
)
.finalize(components::console_component_static!());
const DEBUG_BUFFER_KB: usize = 1;
components::debug_writer::DebugWriterComponent::new(uart_mux)
.finalize(components::debug_writer_component_static!(DEBUG_BUFFER_KB));
let lldb = components::lldb::LowLevelDebugComponent::new(
board_kernel,
capsules_core::low_level_debug::DRIVER_NUM,
uart_mux,
)
.finalize(components::low_level_debug_component_static!());
debug!("HiFive1 initialization complete.");
debug!("Entering main loop.");
let scheduler =
components::sched::cooperative::CooperativeComponent::new(&*addr_of!(PROCESSES))
.finalize(components::cooperative_component_static!(NUM_PROCS));
let scheduler_timer = static_init!(
VirtualSchedulerTimer<VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>>,
VirtualSchedulerTimer::new(systick_virtual_alarm)
);
let hifive1 = HiFive1 {
led,
console,
lldb,
alarm,
scheduler,
scheduler_timer,
};
load_processes_not_inlined(board_kernel, chip);
(board_kernel, hifive1, chip)
}
#[no_mangle]
pub unsafe fn main() {
let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
let (board_kernel, board, chip) = start();
board_kernel.kernel_loop(
&board,
chip,
None::<&kernel::ipc::IPC<0>>,
&main_loop_capability,
);
}