Skip to content

Commit c42f2ea

Browse files
committed
Add software support for PLIC
1 parent 401a13a commit c42f2ea

File tree

8 files changed

+147
-2
lines changed

8 files changed

+147
-2
lines changed

sw/c/common/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
add_library(common OBJECT demo_system.c uart.c timer.c gpio.c pwm.c spi.c crt0.S)
1+
add_library(common OBJECT demo_system.c uart.c timer.c gpio.c pwm.c spi.c plic.c crt0.S)
22
target_include_directories(common INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")

sw/c/common/demo_system.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,36 @@ void set_global_interrupt_enable(uint32_t enable) {
115115
}
116116
}
117117

118+
void verify_core_interrupt_enable(void) {
119+
uint32_t mstatus, mie;
120+
121+
// Read mstatus and mie CSRs
122+
asm volatile("csrr %0, mstatus" : "=r"(mstatus));
123+
asm volatile("csrr %0, mie" : "=r"(mie));
124+
125+
puts("MSTATUS: ");
126+
puthex(mstatus);
127+
putchar('\n');
128+
129+
// Check global interrupt enable (MIE bit in mstatus, bit 3)
130+
if (mstatus & (1 << 3)) {
131+
puts("Global interrupts enabled.\n");
132+
} else {
133+
puts("Global interrupts NOT enabled.\n");
134+
}
135+
136+
puts("MIE: ");
137+
puthex(mie);
138+
putchar('\n');
139+
140+
// Check that external interrupts are enabled
141+
if (mie & (1 << 11)) {
142+
puts("External interrupt (source 11) enabled in MIE.\n");
143+
} else {
144+
puts("External interrupt (source 11) NOT enabled in MIE.\n");
145+
}
146+
}
147+
118148
void simple_exc_handler(void) {
119149
puts("EXCEPTION!!!\n");
120150
puts("============\n");

sw/c/common/demo_system.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
#include "gpio.h"
1212
#include "uart.h"
1313

14-
#define UART_IRQ_NUM 16
14+
// Changed UART_IRQ_NUM from 16 (fast interrupt) to 11 (external interrupt)
15+
// External interrupt is bit 11 in the mie register
16+
#define UART_IRQ_NUM 11
1517
#define UART_IRQ (1 << UART_IRQ_NUM)
1618
#define DEFAULT_UART UART_FROM_BASE_ADDR(UART0_BASE)
1719

@@ -111,4 +113,6 @@ unsigned int get_mtval();
111113
uint32_t get_mcycle(void);
112114
void reset_mcycle(void);
113115

116+
void verify_core_interrupt_enable(void);
117+
114118
#endif

sw/c/common/demo_system_regs.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,21 @@
1919
#define SIM_CTRL_OUT 0x0
2020
#define SIM_CTRL_CTRL 0x8
2121

22+
// Add PLIC definitions
23+
#define PLIC_BASE 0x80005000
24+
25+
// PLIC Register offsets
26+
#define PLIC_PRIORITY_BASE 0x000000
27+
#define PLIC_PENDING_BASE 0x001000
28+
#define PLIC_ENABLE_BASE 0x002000
29+
#define PLIC_THRESHOLD_BASE 0x200000
30+
#define PLIC_CLAIM_BASE 0x200004
31+
32+
// PLIC configuration
33+
#define PLIC_MAX_PRIORITY 7
34+
#define PLIC_PRIORITY_MASK 0x7
35+
36+
// Source IDs
37+
#define PLIC_SOURCE_UART0 0
38+
2239
#endif

sw/c/common/plic.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include "plic.h"
2+
#include "demo_system.h"
3+
#include "dev_access.h"
4+
5+
void plic_init(void) {
6+
// Enable machine external interrupts
7+
enable_interrupts(1 << 11); // Set mie.meie bit
8+
9+
// Set threshold to 0 (allow all priorities)
10+
plic_set_threshold(0);
11+
}
12+
13+
void plic_set_priority(uint32_t source, uint32_t priority) {
14+
uint32_t addr = PLIC_BASE + PLIC_PRIORITY_BASE + (source * 4);
15+
DEV_WRITE(addr, priority & PLIC_PRIORITY_MASK);
16+
}
17+
18+
void plic_enable_interrupt(uint32_t source) {
19+
uint32_t addr = PLIC_BASE + PLIC_ENABLE_BASE;
20+
uint32_t current = DEV_READ(addr);
21+
DEV_WRITE(addr, current | (1 << source));
22+
}
23+
24+
void plic_disable_interrupt(uint32_t source) {
25+
uint32_t addr = PLIC_BASE + PLIC_ENABLE_BASE;
26+
uint32_t current = DEV_READ(addr);
27+
DEV_WRITE(addr, current & ~(1 << source));
28+
}
29+
30+
void plic_set_threshold(uint32_t threshold) {
31+
DEV_WRITE(PLIC_BASE + PLIC_THRESHOLD_BASE, threshold & PLIC_PRIORITY_MASK);
32+
}
33+
34+
uint32_t plic_claim_interrupt(void) {
35+
return DEV_READ(PLIC_BASE + PLIC_CLAIM_BASE);
36+
}
37+
38+
void plic_complete_interrupt(uint32_t source) {
39+
DEV_WRITE(PLIC_BASE + PLIC_CLAIM_BASE, source);
40+
}
41+
42+
void dump_plic_regs(void) {
43+
// Read the pending register from the PLIC.
44+
uint32_t pending = DEV_READ(PLIC_BASE + PLIC_PENDING_BASE);
45+
puts("PLIC pending: ");
46+
puthex(pending);
47+
putchar('\n');
48+
49+
// Read the threshold register from the PLIC.
50+
uint32_t threshold = DEV_READ(PLIC_BASE + PLIC_THRESHOLD_BASE);
51+
puts("PLIC threshold: ");
52+
puthex(threshold);
53+
putchar('\n');
54+
}
55+

sw/c/common/plic.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#ifndef PLIC_H__
2+
#define PLIC_H__
3+
4+
#include <stdint.h>
5+
6+
// Initialize PLIC
7+
void plic_init(void);
8+
9+
// Set priority for an interrupt source
10+
void plic_set_priority(uint32_t source, uint32_t priority);
11+
12+
// Enable/disable interrupt source
13+
void plic_enable_interrupt(uint32_t source);
14+
void plic_disable_interrupt(uint32_t source);
15+
16+
// Set priority threshold
17+
void plic_set_threshold(uint32_t threshold);
18+
19+
// Claim and complete interrupts
20+
uint32_t plic_claim_interrupt(void);
21+
void plic_complete_interrupt(uint32_t source);
22+
23+
// Check register values
24+
void dump_plic_regs(void);
25+
26+
27+
#endif // PLIC_H__

sw/c/common/uart.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "dev_access.h"
99

1010
void uart_enable_rx_int(void) {
11+
// Enable the UART interrupt (now connected to external interrupt)
1112
enable_interrupts(UART_IRQ);
1213
set_global_interrupt_enable(1);
1314
}

sw/c/demo/hello_world/main.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include "gpio.h"
99
#include "pwm.h"
1010
#include "timer.h"
11+
#include "plic.h"
12+
#include "demo_system.h"
1113

1214
#define USE_GPIO_SHIFT_REG 0
1315

@@ -24,9 +26,17 @@ void test_uart_irq_handler(void) {
2426
}
2527

2628
int main(void) {
29+
// Install UART interrupt handler using the updated UART_IRQ_NUM (external interrupt)
2730
install_exception_handler(UART_IRQ_NUM, &test_uart_irq_handler);
2831
uart_enable_rx_int();
2932

33+
// Set UART interrupt priority and enable it in the PLIC
34+
plic_set_priority(11, 1);
35+
plic_enable_interrupt(11);
36+
37+
// Enable global interrupts
38+
set_global_interrupt_enable(1);
39+
3040
// This indicates how often the timer gets updated.
3141
timer_init();
3242
timer_enable(5000000);
@@ -54,6 +64,7 @@ int main(void) {
5464
set_global_interrupt_enable(0);
5565

5666
// Print this to UART (use the screen command to see it).
67+
5768
puts("Hello World! ");
5869
puthex(last_elapsed_time);
5970
puts(" Input Value: ");

0 commit comments

Comments
 (0)