From 9857dfcd7dbe93901c38f5c517d5e561ea98cae4 Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 4 May 2018 18:26:12 +0000 Subject: [PATCH] firmware: add irq::Exception to libboard. --- artiq/firmware/libboard/lib.rs | 2 +- artiq/firmware/libboard/or1k/irq.rs | 84 ++++++++++++++++++++++++++++- artiq/firmware/libboard/or1k/spr.rs | 2 + 3 files changed, 86 insertions(+), 2 deletions(-) diff --git a/artiq/firmware/libboard/lib.rs b/artiq/firmware/libboard/lib.rs index a685f5252..369a38d8c 100644 --- a/artiq/firmware/libboard/lib.rs +++ b/artiq/firmware/libboard/lib.rs @@ -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; diff --git a/artiq/firmware/libboard/or1k/irq.rs b/artiq/firmware/libboard/or1k/irq.rs index ad9c917b9..bc745ae02 100644 --- a/artiq/firmware/libboard/or1k/irq.rs +++ b/artiq/firmware/libboard/or1k/irq.rs @@ -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 for Exception { + type Error = (); + + fn try_from(num: u32) -> Result { + 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 +} diff --git a/artiq/firmware/libboard/or1k/spr.rs b/artiq/firmware/libboard/or1k/spr.rs index 8f011a564..14bb5ae3d 100644 --- a/artiq/firmware/libboard/or1k/spr.rs +++ b/artiq/firmware/libboard/or1k/spr.rs @@ -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") }