Keyboard Work - setting up PLIC, UART, Interrupts
This commit is contained in:
parent
4c0a4958a2
commit
50757427be
12 changed files with 295 additions and 68 deletions
|
|
@ -2,7 +2,24 @@
|
|||
#include <stdint.h>
|
||||
#include <drivers/uart.h>
|
||||
#include <syscon/syscon.h>
|
||||
#include "memory.h"
|
||||
#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");
|
||||
}
|
||||
|
||||
void kpanic(const char *reason)
|
||||
{
|
||||
|
|
@ -31,48 +48,74 @@ void kpanic_force()
|
|||
|
||||
void handle_trap()
|
||||
{
|
||||
kprint("\n!!! HARDWARE EXCEPTION DETECTED !!!\n");
|
||||
|
||||
// Read the 'mcause' register to see WHY we trapped
|
||||
unsigned long cause;
|
||||
__asm__ volatile("csrr %0, mcause" : "=r"(cause));
|
||||
|
||||
// fault address (if applicable)
|
||||
uintptr_t mtval;
|
||||
asm volatile("csrr %0, mtval" : "=r"(mtval));
|
||||
// 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;
|
||||
|
||||
switch (cause)
|
||||
if (is_interrupt)
|
||||
{
|
||||
case 0:
|
||||
kprint("Reason: Instruction Address Misaligned\n");
|
||||
break;
|
||||
case 1:
|
||||
kprint("Reason: Instruction Access Fault\n");
|
||||
break;
|
||||
case 2:
|
||||
kprint("Reason: Illegal Instruction\n");
|
||||
break;
|
||||
case 3:
|
||||
kprint("Reason: Breakpoint (ebreak)\n");
|
||||
break;
|
||||
case 4:
|
||||
kprint("Reason: Load Address Misaligned\n");
|
||||
break;
|
||||
case 5:
|
||||
kprint("Reason: Load Access Fault\n");
|
||||
break;
|
||||
case 6:
|
||||
kprint("Reason: Store/AMO Address Misaligned\n");
|
||||
break;
|
||||
case 7:
|
||||
kprint("Reason: Store/AMO Access Fault\n");
|
||||
break;
|
||||
default:
|
||||
kprintf("Reason: Unknown Exception Code %d\n", cause);
|
||||
unsigned long code = cause & 0xfff;
|
||||
handle_interrupt(code);
|
||||
return;
|
||||
}
|
||||
kprintf("Faulting Address (if applicable): %x\n", mtval);
|
||||
else
|
||||
{
|
||||
// fault address (if applicable)
|
||||
uintptr_t mtval;
|
||||
asm volatile("csrr %0, mtval" : "=r"(mtval));
|
||||
|
||||
heap_stats();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
poweroff();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
#ifndef PANIC_H
|
||||
#define PANIC_H
|
||||
|
||||
void kpanic(const char *reason);
|
||||
void interrupt_init();
|
||||
void kpanic(const char *);
|
||||
void kpanic_force();
|
||||
void handle_interrupt(unsigned long code);
|
||||
|
||||
#define KASSERT(cond, msg) \
|
||||
if (!(cond)) \
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <stddef.h>
|
||||
#include <drivers/uart.h>
|
||||
#include <syscon/syscon.h>
|
||||
#include <kernel/plic.h>
|
||||
#include <kernel/interrupts.h>
|
||||
#include <kernel/memory.h>
|
||||
|
||||
|
|
@ -11,9 +12,8 @@ void kmain()
|
|||
kprintf("Hello, from %s!", "SquidgeOS");
|
||||
kputs("----------------------");
|
||||
knewline();
|
||||
plic_init();
|
||||
uart_init();
|
||||
page_init();
|
||||
test_memory_integrity();
|
||||
test_memory_alignment();
|
||||
test_memory_stress();
|
||||
poweroff();
|
||||
interrupt_init();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ extern uint8_t _heap_start[]; // named in the linker script
|
|||
|
||||
void page_init()
|
||||
{
|
||||
kprint("Initialising page allocator.\n");
|
||||
kprint("Initialising page allocator...");
|
||||
uintptr_t start = ((uintptr_t)_heap_start + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
||||
uintptr_t end = 0x88000000; // Default QEMU RAM limit
|
||||
|
||||
|
|
@ -19,6 +19,7 @@ void page_init()
|
|||
{
|
||||
page_free((void *)addr);
|
||||
}
|
||||
kputs("OK");
|
||||
}
|
||||
|
||||
void page_free(void *addr)
|
||||
|
|
|
|||
19
src/kernel/plic.c
Normal file
19
src/kernel/plic.c
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include <stdint.h>
|
||||
#include "kernel/plic.h"
|
||||
|
||||
void plic_init()
|
||||
{
|
||||
int hart = 0;
|
||||
|
||||
// 1. Set the priority of the UART interrupt
|
||||
// We set it to 1. If it's 0 (the default), the interrupt is effectively disabled.
|
||||
*PLIC_PRIORITY(UART_IRQ) = 1;
|
||||
|
||||
// 2. Enable the UART interrupt for Hart 0
|
||||
// This is a bitmask, so we shift 1 by the IRQ number.
|
||||
*PLIC_ENABLE(hart) = (1 << UART_IRQ);
|
||||
|
||||
// 3. Set the priority threshold for Hart 0
|
||||
// We set this to 0 so that ANY interrupt with priority > 0 gets through.
|
||||
*PLIC_THRESHOLD(hart) = 0;
|
||||
}
|
||||
23
src/kernel/plic.h
Normal file
23
src/kernel/plic.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef PLIC_H
|
||||
#define PLIC_H
|
||||
|
||||
#define PLIC_BASE 0x0c000000
|
||||
#define PLIC_CLAIM_COMPLETE 0x0c200004
|
||||
|
||||
// Priorities: 4 bytes per IRQ (IRQ 0 is reserved/null)
|
||||
#define PLIC_PRIORITY(irq) ((volatile uint32_t *)(PLIC_BASE + (irq) * 4))
|
||||
|
||||
// Enables: Each Hart has a 0x80 byte stride for its enable bits
|
||||
// For Hart 0 Machine Mode: 0x0c002000
|
||||
#define PLIC_ENABLE(hart) ((volatile uint32_t *)(PLIC_BASE + 0x2000 + (hart) * 0x80))
|
||||
|
||||
// Threshold and Claim/Complete: Each Hart has a 0x1000 byte stride
|
||||
// For Hart 0 Machine Mode: 0x0c200000 and 0x0c200004
|
||||
#define PLIC_THRESHOLD(hart) ((volatile uint32_t *)(PLIC_BASE + 0x200000 + (hart) * 0x1000))
|
||||
#define PLIC_CLAIM(hart) ((volatile uint32_t *)(PLIC_BASE + 0x200004 + (hart) * 0x1000))
|
||||
|
||||
#define UART_IRQ 10
|
||||
|
||||
void plic_init();
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue