libcortex_a9: added interrupt_handler macro

closes #73
This commit is contained in:
pca006132 2021-01-28 10:58:17 +08:00
parent 7681745282
commit 06c646e61f
5 changed files with 66 additions and 44 deletions

View File

@ -1,6 +1,8 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
#![feature(const_in_array_repeat_expressions)] #![feature(const_in_array_repeat_expressions)]
#![feature(naked_functions)]
#![feature(asm)]
extern crate alloc; extern crate alloc;
@ -33,7 +35,7 @@ use libcortex_a9::{
sync_channel, sync_channel,
regs::{MPIDR, SP}, regs::{MPIDR, SP},
spin_lock_yield, notify_spin_lock, spin_lock_yield, notify_spin_lock,
asm asm, interrupt_handler
}; };
use libregister::{RegisterR, RegisterW}; use libregister::{RegisterR, RegisterW};
use libsupport_zynq::{ use libsupport_zynq::{
@ -53,9 +55,7 @@ extern "C" {
static CORE1_RESTART: AtomicBool = AtomicBool::new(false); static CORE1_RESTART: AtomicBool = AtomicBool::new(false);
#[link_section = ".text.boot"] interrupt_handler!(IRQ, irq, __stack0_start, __stack1_start, {
#[no_mangle]
pub unsafe extern "C" fn IRQ() {
if MPIDR.read().cpu_id() == 1{ if MPIDR.read().cpu_id() == 1{
let mpcore = mpcore::RegisterBlock::mpcore(); let mpcore = mpcore::RegisterBlock::mpcore();
let mut gic = gic::InterruptController::gic(mpcore); let mut gic = gic::InterruptController::gic(mpcore);
@ -73,7 +73,7 @@ pub unsafe extern "C" fn IRQ() {
stdio::drop_uart(); stdio::drop_uart();
println!("IRQ"); println!("IRQ");
loop {} loop {}
} });
pub fn restart_core1() { pub fn restart_core1() {
let mut interrupt_controller = gic::InterruptController::gic(mpcore::RegisterBlock::mpcore()); let mut interrupt_controller = gic::InterruptController::gic(mpcore::RegisterBlock::mpcore());

View File

@ -6,17 +6,17 @@
extern crate alloc; extern crate alloc;
pub mod asm; pub mod asm;
pub mod regs;
pub mod cache; pub mod cache;
mod fpu;
pub mod l2c;
pub mod mmu; pub mod mmu;
pub mod mutex; pub mod mutex;
pub mod sync_channel; pub mod regs;
pub mod semaphore; pub mod semaphore;
pub mod l2c; pub mod sync_channel;
mod uncached; mod uncached;
mod fpu;
pub use uncached::UncachedSlice;
pub use fpu::enable_fpu; pub use fpu::enable_fpu;
pub use uncached::UncachedSlice;
global_asm!(include_str!("exceptions.s")); global_asm!(include_str!("exceptions.s"));
@ -35,3 +35,38 @@ pub fn notify_spin_lock() {
} }
} }
#[macro_export]
/// Interrupt handler, which setup the stack and jump to actual interrupt handler.
/// - `name` is the name of the interrupt, should be the same as the one defined in vector table.
/// - `name2` is the name for the actual handler, should be different from name.
/// - `stack0` is the stack for the interrupt handler when called from core0.
/// - `stack1` is the stack for the interrupt handler when called from core1.
/// - `body` is the body of the actual interrupt handler, should be a normal unsafe rust function
/// body.
///
/// Note that the interrupt handler would use the same stack as normal programs by default, so
/// interrupt handlers should not return to normal program or it may corrupt the stack.
macro_rules! interrupt_handler {
($name:ident, $name2:ident, $stack0:ident, $stack1:ident, $body:block) => {
#[link_section = ".text.boot"]
#[no_mangle]
#[naked]
pub unsafe extern "C" fn $name() -> ! {
asm!(
// setup SP, depending on CPU 0 or 1
"mrc p15, #0, r0, c0, c0, #5",
concat!("movw r1, :lower16:", stringify!($stack0)),
concat!("movt r1, :upper16:", stringify!($stack0)),
"tst r0, #3",
concat!("movwne r1, :lower16:", stringify!($stack1)),
concat!("movtne r1, :upper16:", stringify!($stack1)),
"mov sp, r1",
concat!("bl ", stringify!($name2)),
options(noreturn)
);
}
#[no_mangle]
pub unsafe extern "C" fn $name2() -> ! $body
};
}

View File

@ -1,63 +1,49 @@
use libregister::RegisterR; use libregister::RegisterR;
use libcortex_a9::regs::{DFSR, MPIDR}; use libcortex_a9::{regs::{DFSR, MPIDR}, interrupt_handler};
use libboard_zynq::{println, stdio}; use libboard_zynq::{println, stdio};
#[link_section = ".text.boot"] interrupt_handler!(UndefinedInstruction, undefined_instruction, __stack0_start, __stack1_start, {
#[no_mangle]
pub unsafe extern "C" fn UndefinedInstruction() {
stdio::drop_uart(); stdio::drop_uart();
println!("UndefinedInstruction"); println!("UndefinedInstruction");
loop {} loop {}
} });
#[link_section = ".text.boot"] interrupt_handler!(SoftwareInterrupt, software_interrupt, __stack0_start, __stack1_start, {
#[no_mangle]
pub unsafe extern "C" fn SoftwareInterrupt() {
stdio::drop_uart(); stdio::drop_uart();
println!("SoftwareInterrupt"); println!("SoftwareInterrupt");
loop {} loop {}
} });
#[link_section = ".text.boot"] interrupt_handler!(PrefetchAbort, prefetch_abort, __stack0_start, __stack1_start, {
#[no_mangle]
pub unsafe extern "C" fn PrefetchAbort() {
stdio::drop_uart(); stdio::drop_uart();
println!("PrefetchAbort"); println!("PrefetchAbort");
loop {} loop {}
} });
#[link_section = ".text.boot"] interrupt_handler!(DataAbort, data_abort, __stack0_start, __stack1_start, {
#[no_mangle]
pub unsafe extern "C" fn DataAbort() {
stdio::drop_uart(); stdio::drop_uart();
println!("DataAbort on core {}", MPIDR.read().cpu_id()); println!("DataAbort on core {}", MPIDR.read().cpu_id());
println!("DFSR: {:03X}", DFSR.read()); println!("DFSR: {:03X}", DFSR.read());
loop {} loop {}
} });
#[link_section = ".text.boot"] interrupt_handler!(ReservedException, reserved_exception, __stack0_start, __stack1_start, {
#[no_mangle]
pub unsafe extern "C" fn ReservedException() {
stdio::drop_uart(); stdio::drop_uart();
println!("ReservedException"); println!("ReservedException");
loop {} loop {}
} });
#[link_section = ".text.boot"]
#[no_mangle]
#[cfg(feature = "dummy_irq_handler")] #[cfg(feature = "dummy_irq_handler")]
pub unsafe extern "C" fn IRQ() { interrupt_handler!(IRQ, irq, __stack0_start, __stack1_start, {
stdio::drop_uart(); stdio::drop_uart();
println!("IRQ"); println!("IRQ");
loop {} loop {}
} });
#[link_section = ".text.boot"] interrupt_handler!(FIQ, fiq, __stack0_start, __stack1_start, {
#[no_mangle]
pub unsafe extern "C" fn FIQ() {
stdio::drop_uart(); stdio::drop_uart();
println!("FIQ"); println!("FIQ");
loop {} loop {}
} });

View File

@ -4,7 +4,7 @@ use libregister::{
VolatileCell, VolatileCell,
RegisterR, RegisterW, RegisterRW, RegisterR, RegisterW, RegisterRW,
}; };
use libcortex_a9::{asm, l2c, regs::*, cache, mmu, spin_lock_yield, notify_spin_lock, enable_fpu}; use libcortex_a9::{asm, l2c, regs::*, cache, mmu, spin_lock_yield, notify_spin_lock, enable_fpu, interrupt_handler};
use libboard_zynq::{slcr, mpcore}; use libboard_zynq::{slcr, mpcore};
extern "C" { extern "C" {
@ -18,9 +18,7 @@ extern "C" {
static mut CORE1_ENABLED: VolatileCell<bool> = VolatileCell::new(false); static mut CORE1_ENABLED: VolatileCell<bool> = VolatileCell::new(false);
#[link_section = ".text.boot"] interrupt_handler!(Reset, reset_irq, __stack0_start, __stack1_start, {
#[no_mangle]
pub unsafe extern "C" fn Reset() -> ! {
match MPIDR.read().cpu_id() { match MPIDR.read().cpu_id() {
0 => { 0 => {
SP.write(&mut __stack0_start as *mut _ as u32); SP.write(&mut __stack0_start as *mut _ as u32);
@ -35,7 +33,7 @@ pub unsafe extern "C" fn Reset() -> ! {
} }
_ => unreachable!(), _ => unreachable!(),
} }
} });
#[inline(never)] #[inline(never)]
unsafe extern "C" fn boot_core0() -> ! { unsafe extern "C" fn boot_core0() -> ! {

View File

@ -2,6 +2,8 @@
#![feature(alloc_error_handler)] #![feature(alloc_error_handler)]
#![feature(panic_info_message)] #![feature(panic_info_message)]
#![feature(naked_functions)]
#![feature(asm)]
pub extern crate alloc; pub extern crate alloc;
pub extern crate compiler_builtins; pub extern crate compiler_builtins;
@ -11,3 +13,4 @@ mod abort;
#[cfg(feature = "panic_handler")] #[cfg(feature = "panic_handler")]
mod panic; mod panic;
pub mod ram; pub mod ram;