parent
3c15bd68d3
commit
95951535e4
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,218 @@
|
||||
use core::fmt;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum RiscvException {
|
||||
/// When things are all 0
|
||||
NoException,
|
||||
|
||||
/// 1 0
|
||||
UserSoftwareInterrupt(usize /* mepc */),
|
||||
|
||||
/// 1 1
|
||||
SupervisorSoftwareInterrupt(usize /* mepc */),
|
||||
|
||||
// [reserved]
|
||||
/// 1 3
|
||||
MachineSoftwareInterrupt(usize /* mepc */),
|
||||
|
||||
/// 1 4
|
||||
UserTimerInterrupt(usize /* mepc */),
|
||||
|
||||
/// 1 5
|
||||
SupervisorTimerInterrupt(usize /* mepc */),
|
||||
|
||||
// [reserved]
|
||||
/// 1 7
|
||||
MachineTimerInterrupt(usize /* mepc */),
|
||||
|
||||
/// 1 8
|
||||
UserExternalInterrupt(usize /* mepc */),
|
||||
|
||||
/// 1 9
|
||||
SupervisorExternalInterrupt(usize /* mepc */),
|
||||
|
||||
// [reserved]
|
||||
/// 1 11
|
||||
MachineExternalInterrupt(usize /* mepc */),
|
||||
|
||||
ReservedInterrupt(usize /* unknown cause number */, usize /* mepc */),
|
||||
|
||||
/// 0 0
|
||||
InstructionAddressMisaligned(usize /* mepc */, usize /* target address */),
|
||||
|
||||
/// 0 1
|
||||
InstructionAccessFault(usize /* mepc */, usize /* target address */),
|
||||
|
||||
/// 0 2
|
||||
IllegalInstruction(usize /* mepc */, usize /* instruction value */),
|
||||
|
||||
/// 0 3
|
||||
Breakpoint(usize /* mepc */),
|
||||
|
||||
/// 0 4
|
||||
LoadAddressMisaligned(usize /* mepc */, usize /* target address */),
|
||||
|
||||
/// 0 5
|
||||
LoadAccessFault(usize /* mepc */, usize /* target address */),
|
||||
|
||||
/// 0 6
|
||||
StoreAddressMisaligned(usize /* mepc */, usize /* target address */),
|
||||
|
||||
/// 0 7
|
||||
StoreAccessFault(usize /* mepc */, usize /* target address */),
|
||||
|
||||
/// 0 8
|
||||
CallFromUMode(usize /* mepc */),
|
||||
|
||||
/// 0 9
|
||||
CallFromSMode(usize /* mepc */),
|
||||
|
||||
// [reserved]
|
||||
/// 0 11
|
||||
CallFromMMode(usize /* mepc */),
|
||||
|
||||
/// 0 12
|
||||
InstructionPageFault(usize /* mepc */, usize /* target address */),
|
||||
|
||||
/// 0 13
|
||||
LoadPageFault(usize /* mepc */, usize /* target address */),
|
||||
|
||||
// [reserved]
|
||||
/// 0 15
|
||||
StorePageFault(usize /* mepc */, usize /* target address */),
|
||||
|
||||
ReservedFault(
|
||||
usize, /* unknown cause number */
|
||||
usize, /* mepc */
|
||||
usize, /* mtval */
|
||||
),
|
||||
}
|
||||
|
||||
impl fmt::Display for RiscvException {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
use RiscvException::*;
|
||||
match *self {
|
||||
NoException => write!(f, "No trap"),
|
||||
UserSoftwareInterrupt(epc) => write!(f, "User swi from 0x{:08x}", epc),
|
||||
SupervisorSoftwareInterrupt(epc) => write!(f, "Supervisor swi from 0x{:08x}", epc),
|
||||
// --reserved--
|
||||
MachineSoftwareInterrupt(epc) => write!(f, "Machine swi at 0x{:08x}", epc),
|
||||
UserTimerInterrupt(epc) => write!(f, "User timer interrupt at 0x{:08x}", epc),
|
||||
SupervisorTimerInterrupt(epc) => {
|
||||
write!(f, "Supervisor timer interrupt at 0x{:08x}", epc)
|
||||
}
|
||||
// --reserved--
|
||||
MachineTimerInterrupt(epc) => write!(f, "Machine timer interrupt at 0x{:08x}", epc),
|
||||
UserExternalInterrupt(epc) => write!(f, "User external interrupt at 0x{:08x}", epc),
|
||||
SupervisorExternalInterrupt(epc) => {
|
||||
write!(f, "Machine external interrupt at 0x{:08x}", epc)
|
||||
}
|
||||
// --reserved--
|
||||
MachineExternalInterrupt(epc) => {
|
||||
write!(f, "Supervisor external interrupt at 0x{:08x}", epc)
|
||||
}
|
||||
ReservedInterrupt(code, epc) => {
|
||||
write!(f, "Reserved interrupt 0x{:08x} at 0x{:08x}", code, epc)
|
||||
}
|
||||
|
||||
InstructionAddressMisaligned(epc, mtval) => write!(
|
||||
f,
|
||||
"Misaligned address instruction 0x{:08x} at 0x{:08x}",
|
||||
mtval, epc
|
||||
),
|
||||
InstructionAccessFault(epc, mtval) => write!(
|
||||
f,
|
||||
"Instruction access fault to 0x{:08x} at 0x{:08x}",
|
||||
mtval, epc
|
||||
),
|
||||
IllegalInstruction(epc, mtval) => {
|
||||
write!(f, "Illegal instruction 0x{:08x} at 0x{:08x}", mtval, epc)
|
||||
}
|
||||
Breakpoint(epc) => write!(f, "Breakpoint at 0x{:08x}", epc),
|
||||
LoadAddressMisaligned(epc, mtval) => write!(
|
||||
f,
|
||||
"Misaligned load address of 0x{:08x} at 0x{:08x}",
|
||||
mtval, epc
|
||||
),
|
||||
LoadAccessFault(epc, mtval) => {
|
||||
write!(f, "Load access fault from 0x{:08x} at 0x{:08x}", mtval, epc)
|
||||
}
|
||||
StoreAddressMisaligned(epc, mtval) => write!(
|
||||
f,
|
||||
"Misaligned store address of 0x{:08x} at 0x{:08x}",
|
||||
mtval, epc
|
||||
),
|
||||
StoreAccessFault(epc, mtval) => {
|
||||
write!(f, "Store access fault to 0x{:08x} at 0x{:08x}", mtval, epc)
|
||||
}
|
||||
CallFromUMode(epc) => write!(f, "Call from User mode at 0x{:08x}", epc),
|
||||
CallFromSMode(epc) => write!(f, "Call from Supervisor mode at 0x{:08x}", epc),
|
||||
// --reserved--
|
||||
CallFromMMode(epc) => write!(f, "Call from Machine mode at 0x{:08x}", epc),
|
||||
InstructionPageFault(epc, mtval) => write!(
|
||||
f,
|
||||
"Instruction page fault of 0x{:08x} at 0x{:08x}",
|
||||
mtval, epc
|
||||
),
|
||||
LoadPageFault(epc, mtval) => {
|
||||
write!(f, "Load page fault of 0x{:08x} at 0x{:08x}", mtval, epc)
|
||||
}
|
||||
// --reserved--
|
||||
StorePageFault(epc, mtval) => {
|
||||
write!(f, "Load page fault of 0x{:08x} at 0x{:08x}", mtval, epc)
|
||||
}
|
||||
ReservedFault(code, epc, mtval) => write!(
|
||||
f,
|
||||
"Reserved interrupt 0x{:08x} with cause 0x{:08x} at 0x{:08x}",
|
||||
code, mtval, epc
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RiscvException {
|
||||
pub fn from_regs(mcause: usize, mepc: usize, mtval: usize) -> RiscvException {
|
||||
use RiscvException::*;
|
||||
|
||||
if mepc == 0 && mtval == 0 {
|
||||
return NoException;
|
||||
}
|
||||
|
||||
match mcause {
|
||||
0x80000000 => UserSoftwareInterrupt(mepc),
|
||||
0x80000001 => SupervisorSoftwareInterrupt(mepc),
|
||||
// --reserved--
|
||||
0x80000003 => MachineSoftwareInterrupt(mepc),
|
||||
0x80000004 => UserTimerInterrupt(mepc),
|
||||
0x80000005 => SupervisorTimerInterrupt(mepc),
|
||||
// --reserved--
|
||||
0x80000007 => MachineTimerInterrupt(mepc),
|
||||
0x80000008 => UserExternalInterrupt(mepc),
|
||||
0x80000009 => SupervisorExternalInterrupt(mepc),
|
||||
// --reserved--
|
||||
0x8000000b => MachineExternalInterrupt(mepc),
|
||||
|
||||
0 => InstructionAddressMisaligned(mepc, mtval),
|
||||
1 => InstructionAccessFault(mepc, mtval),
|
||||
2 => IllegalInstruction(mepc, mtval),
|
||||
3 => Breakpoint(mepc),
|
||||
4 => LoadAddressMisaligned(mepc, mtval),
|
||||
5 => LoadAccessFault(mepc, mtval),
|
||||
6 => StoreAddressMisaligned(mepc, mtval),
|
||||
7 => StoreAccessFault(mepc, mtval),
|
||||
8 => CallFromUMode(mepc),
|
||||
9 => CallFromSMode(mepc),
|
||||
// --reserved--
|
||||
11 => CallFromMMode(mepc),
|
||||
12 => InstructionPageFault(mepc, mtval),
|
||||
13 => LoadPageFault(mepc, mtval),
|
||||
// --reserved--
|
||||
15 => StorePageFault(mepc, mtval),
|
||||
x @ 10 | x @ 14 | x @ 16..=0x7fffffff => ReservedFault(x, mepc, mtval),
|
||||
|
||||
x => {
|
||||
ReservedInterrupt(x & 0x7fffffff, mepc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,43 +1,70 @@
|
||||
static mut TIME_MS: u32 = 0;
|
||||
|
||||
pub fn irq(_irq_number: usize) {
|
||||
let timer_base = 0xE0002800 as *mut u8;
|
||||
unsafe {
|
||||
TIME_MS = TIME_MS + 1;
|
||||
timer_base.add(0x3c).write_volatile(1);
|
||||
};
|
||||
}
|
||||
pub struct Timer {
|
||||
|
||||
/// Address of the timer
|
||||
base: *mut u8,
|
||||
|
||||
pub fn get_time() -> u32 {
|
||||
unsafe { TIME_MS }
|
||||
/// Number of clock cycles before the timer fires
|
||||
period: u32,
|
||||
|
||||
/// Current count of the timer, in milliseconds
|
||||
time_ms: u32,
|
||||
}
|
||||
|
||||
pub fn time_init() {
|
||||
let timer_base = 0xE0002800 as *mut u8;
|
||||
let period = 12_000_000 / 1000; // 12 MHz, 1 ms timer
|
||||
unsafe {
|
||||
// Disable, so we can update it
|
||||
timer_base.add(0x20).write_volatile(0);
|
||||
|
||||
// Update "reload" register
|
||||
timer_base.add(0x10).write_volatile((period >> 24) as u8);
|
||||
timer_base.add(0x14).write_volatile((period >> 16) as u8);
|
||||
timer_base.add(0x18).write_volatile((period >> 8) as u8);
|
||||
timer_base.add(0x1c).write_volatile((period >> 0) as u8);
|
||||
|
||||
// Update "load" register
|
||||
timer_base.add(0x00).write_volatile((period >> 24) as u8);
|
||||
timer_base.add(0x04).write_volatile((period >> 16) as u8);
|
||||
timer_base.add(0x08).write_volatile((period >> 8) as u8);
|
||||
timer_base.add(0x0c).write_volatile((period >> 0) as u8);
|
||||
|
||||
// Enable ISR
|
||||
timer_base.add(0x40).write_volatile(1);
|
||||
|
||||
// Set "pending" as well to clear it
|
||||
timer_base.add(0x38).write_volatile(1);
|
||||
|
||||
// Finally, enable it
|
||||
timer_base.add(0x20).write_volatile(1);
|
||||
impl Timer {
|
||||
pub fn new() -> Timer {
|
||||
Timer {
|
||||
base: 0xE0002800 as *mut u8,
|
||||
period: 12_000_000 / 1000, // 12 MHz, 1 ms timer
|
||||
time_ms: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enable(&self) {
|
||||
unsafe {
|
||||
// Disable, so we can update it
|
||||
self.base.add(0x20).write_volatile(0);
|
||||
|
||||
// Update "reload" register
|
||||
self.base.add(0x10).write_volatile((self.period >> 24) as u8);
|
||||
self.base.add(0x14).write_volatile((self.period >> 16) as u8);
|
||||
self.base.add(0x18).write_volatile((self.period >> 8) as u8);
|
||||
self.base.add(0x1c).write_volatile((self.period >> 0) as u8);
|
||||
|
||||
// Update "load" register
|
||||
self.base.add(0x00).write_volatile((self.period >> 24) as u8);
|
||||
self.base.add(0x04).write_volatile((self.period >> 16) as u8);
|
||||
self.base.add(0x08).write_volatile((self.period >> 8) as u8);
|
||||
self.base.add(0x0c).write_volatile((self.period >> 0) as u8);
|
||||
|
||||
// Enable ISR
|
||||
self.base.add(0x40).write_volatile(1);
|
||||
|
||||
// Set "pending" as well to clear it
|
||||
self.base.add(0x38).write_volatile(1);
|
||||
|
||||
// Finally, enable it
|
||||
self.base.add(0x20).write_volatile(1);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn elapsed_ms(&self) -> u32 {
|
||||
return self.time_ms;
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn irq(_irq_number: usize) {
|
||||
// let timer_base = 0xE0002800 as *mut u8;
|
||||
// unsafe {
|
||||
// TIME_MS = TIME_MS + 1;
|
||||
// timer_base.add(0x3c).write_volatile(1);
|
||||
// };
|
||||
// }
|
||||
|
||||
// pub fn get_time() -> u32 {
|
||||
// unsafe { TIME_MS }
|
||||
// }
|
||||
|
||||
// pub fn time_init() {
|
||||
// let timer_base = 0xE0002800 as *mut u8;
|
||||
// let period = 12_000_000 / 1000; // 12 MHz, 1 ms timer
|
||||
// }
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue