| // Licensed under the Apache-2.0 license |
| // SPDX-License-Identifier: Apache-2.0 |
| #![no_std] |
| #![no_main] |
| use core::arch::global_asm; |
| |
| use arch_riscv::Arch; |
| use kernel::{self as _}; |
| |
| #[unsafe(no_mangle)] |
| #[allow(non_snake_case)] |
| pub unsafe extern "C" fn pw_assert_HandleFailure() -> ! { |
| use kernel::Arch as _; |
| Arch::panic() |
| } |
| |
| #[riscv_rt::entry] |
| fn main() -> ! { |
| kernel::static_init_state!(static mut INIT_STATE: InitKernelState<Arch>); |
| |
| // SAFETY: `main` is only executed once, so we never generate more than one |
| // `&mut` reference to `INIT_STATE`. |
| #[allow(static_mut_refs)] |
| kernel::main(Arch, unsafe { &mut INIT_STATE }); |
| } |
| |
| pub fn exit(code: u32) -> ! { |
| #[cfg(not(any(feature = "emulator", feature = "fpga")))] |
| let _ = code; |
| |
| #[cfg(feature = "emulator")] |
| unsafe { |
| // SAFETY: writing to this address will cause the emulator to exit. |
| let exitcode = core::ptr::with_exposed_provenance_mut::<u32>(0x1000_2000); |
| exitcode.write_volatile(code); |
| } |
| |
| #[cfg(feature = "fpga")] |
| unsafe { |
| // SAFETY: dbg_fifo_push (0xA401_1014) is the FPGA wrapper's |
| // debug/exit register; writing 0xff/0x01 (valid bit 0x100 set) |
| // signals pass/fail to the host, matching |
| // caliptra-mcu-sw/platforms/fpga/rom/src/io.rs::exit_fpga. |
| let dbg_fifo_push = core::ptr::without_provenance_mut::<u32>(0xA401_1014); |
| let byte: u32 = if code == 0 { 0xff } else { 0x01 }; |
| dbg_fifo_push.write_volatile(byte | 0x100); |
| } |
| loop {} |
| } |
| |
| global_asm!( |
| " |
| .option push |
| .option norvc |
| .option norelax |
| .balign 256 |
| .global _mtvec_table |
| _mtvec_table: |
| j _start_trap /* 0: exception and user software interrupt */ |
| j _start_trap /* 1: supervisor software interrupt */ |
| j _start_trap /* 2: reserved */ |
| j _start_trap /* 3: machine software interrupt */ |
| j _start_trap /* 4: user timer interrupt */ |
| j _start_trap /* 5: supervisor timer interrupt */ |
| j _start_trap /* 6: reserved */ |
| j _start_trap /* 7: machine timer interrupt */ |
| j _start_trap /* 8: user external interrupt */ |
| j _start_trap /* 9: supervisor external interrupt */ |
| j _start_trap /* 10: reserved */ |
| j _start_trap /* 11: machine external interrupt */ |
| j _start_trap /* 12: reserved */ |
| j _start_trap /* 13: reserved */ |
| j _start_trap /* 14: reserved */ |
| j _start_trap /* 15: reserved */ |
| j _start_trap /* 16-30: On Ibex, reserved for 'fast' interrupts */ |
| j _start_trap |
| j _start_trap |
| j _start_trap |
| j _start_trap |
| j _start_trap |
| j _start_trap |
| j _start_trap |
| j _start_trap |
| j _start_trap |
| j _start_trap |
| j _start_trap |
| j _start_trap |
| j _start_trap |
| j _start_trap |
| j _start_trap /* 31: reset vector */ |
| .size _mtvec_table, .-_mtvec_table |
| .option pop |
| " |
| ); |