blob: f9fd412689acabab643cdeb2a401a57a9ebd700f [file] [edit]
// Licensed under the Apache-2.0 license
// SPDX-License-Identifier: Apache-2.0
//! Entry point for ASPEED AST10x0 target.
#![no_std]
#![no_main]
use arch_arm_cortex_m::Arch;
#[cfg(feature = "jtag-halt")]
use core::ptr::{self, addr_of};
#[cfg(feature = "jtag-halt")]
/// Enable ARM JTAG pins via SCU pinmux and halt waiting for a debugger.
///
/// # Safety
/// Caller must have exclusive early-boot ownership of SCU MMIO and must have
/// already unlocked SCU write protection (write `0x1688_A8A8` to `SCU000`);
/// otherwise the `SCU41C` pinmux write is silently dropped.
unsafe fn jtag_init() {
// Enable JTAG pins via SCU pinmux - must happen very early
// Scu::steal() is safe here: it's a zero-sized type with no RAM allocation
let scu = unsafe { ast1060_pac::Scu::steal() };
// SCU41C: Multi-function Pin Control - enable ARM JTAG pins
scu.scu41c().modify(|_, w| {
w.enbl_armtmsfn_pin()
.bit(true)
.enbl_armtckfn_pin()
.bit(true)
.enbl_armtrstfn_pin()
.bit(true)
.enbl_armtdifn_pin()
.bit(true)
.enbl_armtdofn_pin()
.bit(true)
});
// Halt here waiting for JTAG debugger
// Break with JTAG and set HALT to 0 to continue
static mut HALT: u32 = 1;
loop {
let val = unsafe { ptr::read_volatile(addr_of!(HALT)) };
if val == 0 {
break;
}
}
}
/// Configure and enable the AST10x0 instruction/data cache.
///
/// Sequence: disable cache, program the cacheable area, invalidate, re-enable.
///
/// # Safety
/// Caller must have exclusive early-boot ownership of SCU MMIO and must have
/// already unlocked SCU write protection.
unsafe fn init_cache() {
// SAFETY: see function-level safety contract.
let scu = unsafe { &*ast1060_pac::Scu::ptr() };
// Disable cache.
scu.scua58().write(|w| unsafe { w.bits(0) });
// Configure cache area.
scu.scua50().write(|w| unsafe { w.bits(0x000f_ffff) });
// Invalidate cache.
scu.scua54().write(|w| unsafe { w.bits(0x8660_0000) });
// Re-enable cache.
scu.scua58().write(|w| unsafe { w.bits(1) });
}
// Pre-kernel hardware initialization
/// Runs before RAM is initialized, before main()
#[cortex_m_rt::pre_init]
unsafe fn pre_init() {
// SAFETY: pre-init has exclusive early-boot ownership of SCU MMIO.
let scu = unsafe { &*ast1060_pac::Scu::ptr() };
// Unlock SCU write-protected registers.
scu.scu000().write(|w| unsafe { w.bits(0x1688_A8A8) });
#[cfg(feature = "jtag-halt")]
jtag_init();
// SAFETY: SCU is unlocked above; pre-init has exclusive ownership.
unsafe { init_cache() };
}
#[unsafe(no_mangle)]
#[allow(non_snake_case)]
pub extern "C" fn pw_assert_HandleFailure() -> ! {
use kernel::Arch as _;
Arch::panic();
}
// ── Interrupt Handler Stubs ──
// These are required by the ast1060-pac's __INTERRUPTS vector table.
macro_rules! default_handler {
($($name:ident),*) => {
$(
#[unsafe(no_mangle)]
pub extern "C" fn $name() {
// Default: infinite loop
loop {}
}
)*
};
}
// Default stub handlers for peripherals not yet implemented
default_handler!(
fmc, gpio, hace,
i2c, i2c1, i2c2, i2c3, i2c4, i2c5, i2c6, i2c7, i2c8, i2c9, i2c10, i2c11, i2c12, i2c13,
i2cfilter,
i3c, i3c1, i3c2, i3c3,
scu, sgpiom,
spi, spi1, spipf1, spipf2, spipf3,
timer1, timer2, timer3, timer4, timer5, timer6, timer7,
uart, uartdma, wdt
);
mod console_backend {
unsafe extern "Rust" {
pub fn console_backend_write_all(buf: &[u8]) -> pw_status::Result<()>;
}
}
#[cortex_m_rt::entry]
fn main() -> ! {
kernel::static_init_state!(static mut INIT_STATE: InitKernelState<Arch>);
#[allow(static_mut_refs)]
unsafe {
// Initialize UART console
let _ = console_backend::console_backend_write_all(b"\r\nHello World!\r\n");
let _ = console_backend::console_backend_write_all(b"ast1060 pigweed fw is running!\r\n");
kernel::main(Arch, &mut INIT_STATE)
};
}