forked from M-Labs/artiq
firmware: add irq::Exception to libboard.
This commit is contained in:
parent
0b4d06c7a9
commit
9857dfcd7d
@ -1,5 +1,5 @@
|
||||
#![no_std]
|
||||
#![feature(compiler_builtins_lib, asm)]
|
||||
#![feature(compiler_builtins_lib, asm, try_from)]
|
||||
|
||||
extern crate compiler_builtins;
|
||||
extern crate byteorder;
|
||||
|
@ -1,9 +1,76 @@
|
||||
use core::{fmt, convert};
|
||||
|
||||
use super::spr::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Exception {
|
||||
Reset = 0x1,
|
||||
BusError = 0x2,
|
||||
DataPageFault = 0x3,
|
||||
InsnPageFault = 0x4,
|
||||
Tick = 0x5,
|
||||
Alignment = 0x6,
|
||||
IllegalInsn = 0x7,
|
||||
Interrupt = 0x8,
|
||||
DtlbMiss = 0x9,
|
||||
ItlbMiss = 0xa,
|
||||
Range = 0xb,
|
||||
Syscall = 0xc,
|
||||
FloatingPoint = 0xd,
|
||||
Trap = 0xe,
|
||||
}
|
||||
|
||||
impl fmt::Display for Exception {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Exception::Reset => write!(f, "reset"),
|
||||
Exception::BusError => write!(f, "bus error"),
|
||||
Exception::DataPageFault => write!(f, "data page fault"),
|
||||
Exception::InsnPageFault => write!(f, "instruction page fault"),
|
||||
Exception::Tick => write!(f, "tick"),
|
||||
Exception::Alignment => write!(f, "alignment"),
|
||||
Exception::IllegalInsn => write!(f, "illegal instruction"),
|
||||
Exception::Interrupt => write!(f, "interrupt"),
|
||||
Exception::DtlbMiss => write!(f, "D-TLB miss"),
|
||||
Exception::ItlbMiss => write!(f, "I-TLB miss"),
|
||||
Exception::Range => write!(f, "range"),
|
||||
Exception::Syscall => write!(f, "system call"),
|
||||
Exception::FloatingPoint => write!(f, "floating point"),
|
||||
Exception::Trap => write!(f, "trap"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl convert::TryFrom<u32> for Exception {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(num: u32) -> Result<Self, Self::Error> {
|
||||
match num {
|
||||
0x1 => Ok(Exception::Reset),
|
||||
0x2 => Ok(Exception::BusError),
|
||||
0x3 => Ok(Exception::DataPageFault),
|
||||
0x4 => Ok(Exception::InsnPageFault),
|
||||
0x5 => Ok(Exception::Tick),
|
||||
0x6 => Ok(Exception::Alignment),
|
||||
0x7 => Ok(Exception::IllegalInsn),
|
||||
0x8 => Ok(Exception::Interrupt),
|
||||
0x9 => Ok(Exception::DtlbMiss),
|
||||
0xa => Ok(Exception::ItlbMiss),
|
||||
0xb => Ok(Exception::Range),
|
||||
0xc => Ok(Exception::Syscall),
|
||||
0xd => Ok(Exception::FloatingPoint),
|
||||
0xe => Ok(Exception::Trap),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_ie() -> bool {
|
||||
unsafe { mfspr(SPR_SR) & SPR_SR_IEE != 0 }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_ie(ie: bool) {
|
||||
if ie {
|
||||
unsafe { mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE) }
|
||||
@ -12,14 +79,29 @@ pub fn set_ie(ie: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_mask() -> u32 {
|
||||
unsafe { mfspr(SPR_PICMR) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_mask(mask: u32) {
|
||||
unsafe { mtspr(SPR_PICMR, mask) }
|
||||
}
|
||||
|
||||
pub fn pending() -> u32 {
|
||||
#[inline]
|
||||
pub fn pending_mask() -> u32 {
|
||||
unsafe { mfspr(SPR_PICSR) }
|
||||
}
|
||||
|
||||
pub fn enable(irq: u32) {
|
||||
set_mask(get_mask() | (1 << irq))
|
||||
}
|
||||
|
||||
pub fn disable(irq: u32) {
|
||||
set_mask(get_mask() & !(1 << irq))
|
||||
}
|
||||
|
||||
pub fn is_pending(irq: u32) -> bool {
|
||||
get_mask() & (1 << irq) != 0
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
#[inline(always)]
|
||||
pub unsafe fn mfspr(reg: u32) -> u32 {
|
||||
let value: u32;
|
||||
asm!("l.mfspr $0, $1, 0" : "=r"(value) : "r"(reg) : : "volatile");
|
||||
value
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn mtspr(reg: u32, value: u32) {
|
||||
asm!("l.mtspr $0, $1, 0" : : "r"(reg), "r"(value) : : "volatile")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user