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]
|
#![no_std]
|
||||||
#![feature(compiler_builtins_lib, asm)]
|
#![feature(compiler_builtins_lib, asm, try_from)]
|
||||||
|
|
||||||
extern crate compiler_builtins;
|
extern crate compiler_builtins;
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
|
|
|
@ -1,9 +1,76 @@
|
||||||
|
use core::{fmt, convert};
|
||||||
|
|
||||||
use super::spr::*;
|
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 {
|
pub fn get_ie() -> bool {
|
||||||
unsafe { mfspr(SPR_SR) & SPR_SR_IEE != 0 }
|
unsafe { mfspr(SPR_SR) & SPR_SR_IEE != 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn set_ie(ie: bool) {
|
pub fn set_ie(ie: bool) {
|
||||||
if ie {
|
if ie {
|
||||||
unsafe { mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE) }
|
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 {
|
pub fn get_mask() -> u32 {
|
||||||
unsafe { mfspr(SPR_PICMR) }
|
unsafe { mfspr(SPR_PICMR) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn set_mask(mask: u32) {
|
pub fn set_mask(mask: u32) {
|
||||||
unsafe { mtspr(SPR_PICMR, mask) }
|
unsafe { mtspr(SPR_PICMR, mask) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pending() -> u32 {
|
#[inline]
|
||||||
|
pub fn pending_mask() -> u32 {
|
||||||
unsafe { mfspr(SPR_PICSR) }
|
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 {
|
pub unsafe fn mfspr(reg: u32) -> u32 {
|
||||||
let value: u32;
|
let value: u32;
|
||||||
asm!("l.mfspr $0, $1, 0" : "=r"(value) : "r"(reg) : : "volatile");
|
asm!("l.mfspr $0, $1, 0" : "=r"(value) : "r"(reg) : : "volatile");
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
pub unsafe fn mtspr(reg: u32, value: u32) {
|
pub unsafe fn mtspr(reg: u32, value: u32) {
|
||||||
asm!("l.mtspr $0, $1, 0" : : "r"(reg), "r"(value) : : "volatile")
|
asm!("l.mtspr $0, $1, 0" : : "r"(reg), "r"(value) : : "volatile")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue