From 60b0273eda85b9f8418b8660b89f8c0aafa86366 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Thu, 16 May 2024 18:58:16 +0200 Subject: [PATCH] Add baremetal IRQ support --- litex/soc/cores/cpu/vexiiriscv/core.py | 2 +- litex/soc/cores/cpu/vexiiriscv/crt0.S | 85 +++++++++++++++----------- litex/soc/cores/cpu/vexiiriscv/irq.h | 22 +++++-- 3 files changed, 66 insertions(+), 43 deletions(-) diff --git a/litex/soc/cores/cpu/vexiiriscv/core.py b/litex/soc/cores/cpu/vexiiriscv/core.py index 3ccf9441e..359eb4dad 100755 --- a/litex/soc/cores/cpu/vexiiriscv/core.py +++ b/litex/soc/cores/cpu/vexiiriscv/core.py @@ -97,7 +97,7 @@ class VexiiRiscv(CPU): def gcc_flags(self): flags = f" -march={VexiiRiscv.get_arch()} -mabi={VexiiRiscv.get_abi()}" flags += f" -D__VexiiRiscv__" - flags += f" -DUART_POLLING" + flags += f" -D__riscv_plic__" return flags # Reserved Interrupts. diff --git a/litex/soc/cores/cpu/vexiiriscv/crt0.S b/litex/soc/cores/cpu/vexiiriscv/crt0.S index b27df7f47..09007caee 100644 --- a/litex/soc/cores/cpu/vexiiriscv/crt0.S +++ b/litex/soc/cores/cpu/vexiiriscv/crt0.S @@ -12,6 +12,17 @@ #define MSTATUS_FS_DIRTY (3 << 13) #define MSTATUS_FS_MASK (3 << 13) + +#if __riscv_xlen == 64 +#define STORE sd +#define LOAD ld +#define WORD 8 +#else +#define STORE sw +#define LOAD lw +#define WORD 4 +#endif + _start: j crt_init nop @@ -24,41 +35,41 @@ _start: .global trap_entry trap_entry: - sw x1, - 1*4(sp) - sw x5, - 2*4(sp) - sw x6, - 3*4(sp) - sw x7, - 4*4(sp) - sw x10, - 5*4(sp) - sw x11, - 6*4(sp) - sw x12, - 7*4(sp) - sw x13, - 8*4(sp) - sw x14, - 9*4(sp) - sw x15, -10*4(sp) - sw x16, -11*4(sp) - sw x17, -12*4(sp) - sw x28, -13*4(sp) - sw x29, -14*4(sp) - sw x30, -15*4(sp) - sw x31, -16*4(sp) - addi sp,sp,-16*4 + STORE x1, - 1*WORD(sp) + STORE x5, - 2*WORD(sp) + STORE x6, - 3*WORD(sp) + STORE x7, - 4*WORD(sp) + STORE x10, - 5*WORD(sp) + STORE x11, - 6*WORD(sp) + STORE x12, - 7*WORD(sp) + STORE x13, - 8*WORD(sp) + STORE x14, - 9*WORD(sp) + STORE x15, -10*WORD(sp) + STORE x16, -11*WORD(sp) + STORE x17, -12*WORD(sp) + STORE x28, -13*WORD(sp) + STORE x29, -14*WORD(sp) + STORE x30, -15*WORD(sp) + STORE x31, -16*WORD(sp) + addi sp,sp,-16*WORD call isr - lw x1 , 15*4(sp) - lw x5, 14*4(sp) - lw x6, 13*4(sp) - lw x7, 12*4(sp) - lw x10, 11*4(sp) - lw x11, 10*4(sp) - lw x12, 9*4(sp) - lw x13, 8*4(sp) - lw x14, 7*4(sp) - lw x15, 6*4(sp) - lw x16, 5*4(sp) - lw x17, 4*4(sp) - lw x28, 3*4(sp) - lw x29, 2*4(sp) - lw x30, 1*4(sp) - lw x31, 0*4(sp) - addi sp,sp,16*4 + LOAD x1 , 15*WORD(sp) + LOAD x5, 14*WORD(sp) + LOAD x6, 13*WORD(sp) + LOAD x7, 12*WORD(sp) + LOAD x10, 11*WORD(sp) + LOAD x11, 10*WORD(sp) + LOAD x12, 9*WORD(sp) + LOAD x13, 8*WORD(sp) + LOAD x14, 7*WORD(sp) + LOAD x15, 6*WORD(sp) + LOAD x16, 5*WORD(sp) + LOAD x17, 4*WORD(sp) + LOAD x28, 3*WORD(sp) + LOAD x29, 2*WORD(sp) + LOAD x30, 1*WORD(sp) + LOAD x31, 0*WORD(sp) + addi sp,sp,16*WORD mret .text @@ -113,8 +124,10 @@ bss_loop: j bss_loop bss_done: - li a0, 0x880 //880 enable timer + external interrupt sources (until mstatus.MIE is set, they will never trigger an interrupt) - csrw mie,a0 + call plic_init // initialize external interrupt controller + li t0, 0x800 // external interrupt sources only (using LiteX timer); + // NOTE: must still enable mstatus.MIE! + csrw mie,t0 call main infinit_loop: diff --git a/litex/soc/cores/cpu/vexiiriscv/irq.h b/litex/soc/cores/cpu/vexiiriscv/irq.h index 558adc4f1..a29729ba2 100644 --- a/litex/soc/cores/cpu/vexiiriscv/irq.h +++ b/litex/soc/cores/cpu/vexiiriscv/irq.h @@ -9,30 +9,40 @@ extern "C" { #include #include +// VexiiRiscv uses a Platform-Level Interrupt Controller (PLIC) which +// is programmed and queried via a set of MMIO registerss + +#define PLIC_BASE 0xf0c00000L // Base address and per-pin priority array +#define PLIC_PENDING 0xf0c01000L // Bit field matching currently pending pins +#define PLIC_ENABLED 0xf0c02000L // Bit field corresponding to the current mask +#define PLIC_THRSHLD 0xf0e00000L // Per-pin priority must be >= this to trigger +#define PLIC_CLAIM 0xf0e00004L // Claim & completion register address + +#define PLIC_EXT_IRQ_BASE 0 + static inline unsigned int irq_getie(void) { - return 0; + return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; } static inline void irq_setie(unsigned int ie) { - + if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); } static inline unsigned int irq_getmask(void) { - - return 0; + return *((unsigned int *)PLIC_ENABLED) >> PLIC_EXT_IRQ_BASE; } static inline void irq_setmask(unsigned int mask) { - + *((unsigned int *)PLIC_ENABLED) = mask << PLIC_EXT_IRQ_BASE; } static inline unsigned int irq_pending(void) { - return 0; + return *((unsigned int *)PLIC_PENDING) >> PLIC_EXT_IRQ_BASE; } #ifdef __cplusplus