forked from M-Labs/zynq-rs
parent
7681745282
commit
06c646e61f
@ -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());
|
||||||
|
@ -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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -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 {}
|
||||||
}
|
});
|
||||||
|
@ -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() -> ! {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user