#![feature(naked_functions, asm_const)]
#![no_std]
#[cfg(any(feature = "nezha", feature = "lichee"))]
mod mctl;
#[cfg(any(feature = "nezha", feature = "lichee"))]
pub use mctl::init as dram_init;
use base_address::Static;
pub use d1_rom_rt_macros::entry;
#[cfg(feature = "log")]
use aw_soc::uart::{self, Parity, Serial, StopBits, WordLength};
use aw_soc::{ccu::Clocks, time::U32Ext, Pins, CCU, COM, PLIC, SPI, UART};
use core::arch::asm;
pub struct Parameters {
pub memory_meta: &'static mut Meta,
#[cfg(not(feature = "log"))]
pub gpio: Pins<Static<0x02000000>>,
#[cfg(not(feature = "log"))]
pub uart0: UART<Static<0x02500000>>,
pub spi0: SPI<Static<0x04025000>>,
pub com: COM<Static<0x03102000>>,
pub ccu: CCU<Static<0x02001000>>,
pub plic: PLIC<Static<0x10000000>>,
pub clocks: Clocks,
}
pub struct Handover {}
impl From<Parameters> for Handover {
#[inline]
fn from(src: Parameters) -> Self {
let _ = src;
Handover {}
}
}
#[doc(hidden)]
pub struct Meta {
pub from_flash: bool,
pub see: u32,
pub kernel: u32,
pub dtb: u32,
}
#[link_section = ".head.meta"]
static mut MEMORY_META: Meta = Meta {
from_flash: false,
see: 0,
kernel: 0,
dtb: 0,
};
#[repr(C)]
pub struct EgonHead {
magic: [u8; 8],
pub checksum: u32,
pub length: u32,
_head_size: u32,
fel_script_address: u32,
fel_uenv_length: u32,
dt_name_offset: u32,
dram_size: u32,
boot_media: u32,
string_pool: [u32; 13],
}
#[naked]
#[link_section = ".text.entry"]
unsafe extern "C" fn start() -> ! {
const STACK_SIZE: usize = 1024;
#[link_section = ".bss.uninit"]
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
asm!(
"li t1, 1 << 22",
"csrs 0x7C0, t1",
"li t1, 0x30013",
"csrs 0x7C2, t1",
"csrw mie, zero",
"la sp, {stack}
li t0, {stack_size}
add sp, sp, t0",
"la t1, sbss
la t2, ebss
1: bgeu t1, t2, 1f
sd zero, 0(t1)
addi t1, t1, 8
j 1b
1: ",
"call {main}
1: wfi
j 1b",
stack = sym STACK,
stack_size = const STACK_SIZE,
main = sym wrap_main,
options(noreturn)
)
}
#[rustfmt::skip]
extern "Rust" {
fn main(param: Parameters) -> Handover;
}
fn wrap_main() {
let clocks = Clocks {
psi: 600_000_000.hz(),
apb1: 24_000_000.hz(),
};
let gpio: Pins<Static<0x02000000>> = unsafe { core::mem::transmute(()) };
let ccu: CCU<Static<0x02001000>> = unsafe { CCU::steal_static() };
let uart0: UART<Static<0x02500000>> = unsafe { UART::steal_static() };
let spi0: SPI<Static<0x04025000>> = unsafe { SPI::steal_static() };
let plic: PLIC<Static<0x10000000>> = unsafe { PLIC::steal_static() };
#[cfg(feature = "log")]
let config = uart::Config {
baudrate: 115200.bps(),
wordlength: WordLength::Eight,
parity: Parity::None,
stopbits: StopBits::One,
};
#[cfg(feature = "log")]
let serial = Serial::new(
uart0,
(gpio.pb8.into_function::<6>(), gpio.pb9.into_function::<6>()),
config,
&clocks,
&ccu,
);
let memory_meta = unsafe { &mut MEMORY_META };
let com: COM<Static<0x03102000>> = unsafe { COM::steal_static() };
let params = Parameters {
memory_meta,
#[cfg(not(feature = "log"))]
gpio,
#[cfg(not(feature = "log"))]
uart0,
spi0,
com,
ccu,
plic,
clocks,
};
#[cfg(feature = "log")]
log::set_logger(serial);
let _ = unsafe { main(params) };
}
#[cfg(feature = "log")]
#[doc(hidden)]
pub mod log {
use aw_soc::gpio::{Function, Pin};
use base_address::Static;
use embedded_hal::serial::Write;
use spin::{Mutex, Once};
pub static LOGGER: Once<LockedLogger> = Once::new();
pub type SERIAL = aw_soc::uart::Serial<
Static<0x02500000>,
0,
(
Pin<Static<0x02000000>, 'B', 8, Function<6>>,
Pin<Static<0x02000000>, 'B', 9, Function<6>>,
),
>;
pub struct S(SERIAL);
pub struct LockedLogger {
#[allow(unused)]
pub inner: Mutex<S>,
}
impl ufmt::uWrite for S {
type Error = embedded_hal::serial::ErrorKind;
#[inline]
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
self.0.write(s.as_bytes())?;
self.0.flush()?;
Ok(())
}
}
#[inline]
pub fn set_logger(serial: SERIAL) {
LOGGER.call_once(|| LockedLogger {
inner: Mutex::new(S(serial)),
});
}
}
#[cfg(feature = "log")]
#[doc(hidden)]
pub extern crate ufmt;
#[cfg(feature = "log")]
#[macro_export(local_inner_macros)]
macro_rules! print {
($($arg:tt)*) => ({
pub use $crate::ufmt as ufmt;
let mut logger = $crate::log::LOGGER.wait().inner.lock();
let ans = ufmt::uwrite!(logger, $($arg)*);
drop(logger);
ans
});
}
#[cfg(feature = "log")]
#[macro_export(local_inner_macros)]
macro_rules! println {
() => ($crate::print!("\r\n"));
($fmt: literal $(, $($arg: tt)+)?) => ({
pub use $crate::ufmt as ufmt;
let mut logger = $crate::log::LOGGER.wait().inner.lock();
let ans = ufmt::uwrite!(logger, $fmt $(, $($arg)+)?);
drop(logger);
let _ = $crate::print!("\r\n");
ans
});
}
#[no_mangle]
#[link_section = ".head.egon"]
static EGON_HEAD: EgonHead = EgonHead {
magic: *b"eGON.BT0",
checksum: 0x5F0A6C39, length: 0x8000,
_head_size: 0,
fel_script_address: 0,
fel_uenv_length: 0,
dt_name_offset: 0,
dram_size: 0,
boot_media: 0,
string_pool: [0; 13],
};
core::arch::global_asm! {
".section .text.head",
"head_jump:",
"j {}",
sym start,
}