2026-02-08 22:41:38 +00:00
|
|
|
#include <stddef.h>
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
#include <drivers/uart.h>
|
|
|
|
|
#include <syscon/syscon.h>
|
2026-02-10 01:21:49 +00:00
|
|
|
#include <kernel/plic.h>
|
|
|
|
|
#include <kernel/interrupts.h>
|
|
|
|
|
#include <kernel/memory.h>
|
|
|
|
|
|
|
|
|
|
void interrupt_init()
|
|
|
|
|
{
|
|
|
|
|
kprint("Initialising Interrupts...");
|
|
|
|
|
uint64_t mstatus_val;
|
|
|
|
|
asm volatile("csrr %0, mstatus" : "=r"(mstatus_val));
|
|
|
|
|
mstatus_val |= (1 << MSTATUS_BIT_MIE);
|
|
|
|
|
asm volatile("csrw mstatus, %0" ::"r"(mstatus_val));
|
|
|
|
|
|
|
|
|
|
uint64_t mie_val;
|
|
|
|
|
asm volatile("csrr %0, mie" : "=r"(mie_val));
|
|
|
|
|
mie_val |= (1 << MIE_BIT_MEIE); //|(1 << MIE_BIT_MTIE);
|
|
|
|
|
asm volatile("csrw mie, %0" ::"r"(mie_val));
|
|
|
|
|
kputs("OK");
|
|
|
|
|
}
|
2026-02-08 22:41:38 +00:00
|
|
|
|
2026-02-09 18:55:51 +00:00
|
|
|
void kpanic(const char *reason)
|
|
|
|
|
{
|
2026-02-09 00:37:28 +00:00
|
|
|
kputs("\n!!! PANIC !!!\n");
|
2026-02-09 18:55:51 +00:00
|
|
|
kputs(reason);
|
2026-02-09 00:37:28 +00:00
|
|
|
kputs("\n!!! PANIC !!!\n");
|
2026-02-09 18:55:51 +00:00
|
|
|
poweroff();
|
2026-02-08 22:41:38 +00:00
|
|
|
}
|
|
|
|
|
|
2026-02-09 18:55:51 +00:00
|
|
|
void kpanic_force()
|
|
|
|
|
{
|
2026-02-08 22:41:38 +00:00
|
|
|
kprint("\n!!! FORCE PANIC !!!\n");
|
|
|
|
|
|
|
|
|
|
// 'ebreak' is the standard RISC-V way to trigger a debug trap.
|
|
|
|
|
__asm__ volatile("ebreak");
|
|
|
|
|
|
2026-02-09 00:37:28 +00:00
|
|
|
kprint("Force panic falled. Power off. \n");
|
2026-02-08 22:41:38 +00:00
|
|
|
poweroff();
|
|
|
|
|
|
2026-02-09 00:37:28 +00:00
|
|
|
kprint("Force panic falled. Power off failed. sleep until interupt. \n");
|
2026-02-09 18:55:51 +00:00
|
|
|
while (1)
|
|
|
|
|
{
|
2026-02-08 22:41:38 +00:00
|
|
|
__asm__ volatile("wfi");
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-02-09 02:57:04 +00:00
|
|
|
|
2026-02-09 18:55:51 +00:00
|
|
|
void handle_trap()
|
|
|
|
|
{
|
2026-02-09 02:57:04 +00:00
|
|
|
// Read the 'mcause' register to see WHY we trapped
|
|
|
|
|
unsigned long cause;
|
|
|
|
|
__asm__ volatile("csrr %0, mcause" : "=r"(cause));
|
|
|
|
|
|
2026-02-10 01:21:49 +00:00
|
|
|
// Check if the top bit is 1 (Interrupt) or 0 (Exception)
|
|
|
|
|
// For 64-bit RISC-V, the bit is 63
|
|
|
|
|
int is_interrupt = (cause >> 63) & 1;
|
2026-02-09 03:28:54 +00:00
|
|
|
|
2026-02-10 01:21:49 +00:00
|
|
|
if (is_interrupt)
|
2026-02-09 18:55:51 +00:00
|
|
|
{
|
2026-02-10 01:21:49 +00:00
|
|
|
unsigned long code = cause & 0xfff;
|
|
|
|
|
handle_interrupt(code);
|
|
|
|
|
return;
|
2026-02-09 02:57:04 +00:00
|
|
|
}
|
2026-02-10 01:21:49 +00:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// fault address (if applicable)
|
|
|
|
|
uintptr_t mtval;
|
|
|
|
|
asm volatile("csrr %0, mtval" : "=r"(mtval));
|
2026-02-09 02:57:04 +00:00
|
|
|
|
2026-02-10 01:21:49 +00:00
|
|
|
switch (cause)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
kpanic("Reason: Instruction Address Misaligned\n");
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
kpanic("Reason: Instruction Access Fault\n");
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
kpanic("Reason: Illegal Instruction\n");
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
kpanic("Reason: Breakpoint (ebreak)\n");
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
kpanic("Reason: Load Address Misaligned\n");
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
kpanic("Reason: Load Access Fault\n");
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
kpanic("Reason: Store/AMO Address Misaligned\n");
|
|
|
|
|
break;
|
|
|
|
|
case 7:
|
|
|
|
|
kpanic("Reason: Store/AMO Access Fault\n");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
// kpanic("Reason: Unknown Exception Code %d\n", cause);
|
|
|
|
|
}
|
|
|
|
|
kprintf("Faulting Address (if applicable): %x\n", mtval);
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-02-09 15:06:49 +00:00
|
|
|
|
2026-02-10 01:21:49 +00:00
|
|
|
void handle_interrupt(unsigned long code)
|
|
|
|
|
{
|
|
|
|
|
switch (code)
|
|
|
|
|
{
|
|
|
|
|
case 7:
|
|
|
|
|
break; // timer Interrupt. Ignoring for now.
|
|
|
|
|
case 11:
|
|
|
|
|
volatile uint32_t *claim_reg = (uint32_t *)PLIC_CLAIM_COMPLETE;
|
|
|
|
|
uint32_t irq = *claim_reg;
|
|
|
|
|
if (irq == 10)
|
|
|
|
|
{
|
|
|
|
|
uart_handle_interrupt();
|
|
|
|
|
}
|
|
|
|
|
*claim_reg = irq;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-02-09 02:57:04 +00:00
|
|
|
}
|