aboutsummaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2015-06-25 14:08:39 +0200
committerClifford Wolf <clifford@clifford.at>2015-06-25 14:08:39 +0200
commit23b700cf73b7b01b4737db106226bd4220799290 (patch)
tree27a6109332ccf71c4a3b284d05a74d1ab3ac14ed /firmware
parent982e5cc60085236be18a5be35f3747e480ed549f (diff)
downloadpicorv32-23b700cf73b7b01b4737db106226bd4220799290.tar.gz
picorv32-23b700cf73b7b01b4737db106226bd4220799290.zip
Added basic IRQ support
Diffstat (limited to 'firmware')
-rw-r--r--firmware/sieve.c101
-rw-r--r--firmware/start.S163
2 files changed, 263 insertions, 1 deletions
diff --git a/firmware/sieve.c b/firmware/sieve.c
index c3372f4..7f1c82e 100644
--- a/firmware/sieve.c
+++ b/firmware/sieve.c
@@ -18,6 +18,11 @@ static bool bitmap_get(int idx)
return (bitmap[idx/32] & (1 << (idx % 32))) != 0;
}
+static void print_chr(char ch)
+{
+ *((volatile uint32_t*)OUTPORT) = ch;
+}
+
static void print_str(const char *p)
{
while (*p != 0)
@@ -37,6 +42,13 @@ static void print_dec(int val)
}
}
+static void print_hex(unsigned int val)
+{
+ int i;
+ for (i = 32-4; i >= 0; i -= 4)
+ *((volatile uint32_t*)OUTPORT) = "0123456789ABCDEF"[(val >> i) % 16];
+}
+
static void print_prime(int idx, int val)
{
if (idx < 10)
@@ -76,3 +88,92 @@ void sieve()
}
}
+void irq(uint32_t *regs, uint32_t irqnum)
+{
+ static int ext_irq_count = 0;
+ static int timer_irq_count = 0;
+
+ if (irqnum == 0) {
+ ext_irq_count++;
+ // print_str("[EXT-IRQ]");
+ return;
+ }
+
+ if (irqnum == 1) {
+ timer_irq_count++;
+ // print_str("[TIMER-IRQ]");
+ return;
+ }
+
+ if (irqnum == 2)
+ {
+ int i, k;
+ uint32_t pc = regs[0] - 4;
+ uint32_t instr = *(uint32_t*)pc;
+
+ print_str("\n");
+ print_str("------------------------------------------------------------\n");
+
+ if (instr == 0x00100073) {
+ print_str("SBREAK instruction at 0x");
+ print_hex(pc);
+ print_str("\n");
+ } else {
+ print_str("Illegal Instruction at 0x");
+ print_hex(pc);
+ print_str(": 0x");
+ print_hex(instr);
+ print_str("\n");
+ }
+
+ for (i = 0; i < 8; i++)
+ for (k = 0; k < 4; k++)
+ {
+ int r = i + k*8;
+
+ if (r == 0) {
+ print_str("pc ");
+ } else
+ if (r < 10) {
+ print_chr('x');
+ print_chr('0' + r);
+ print_chr(' ');
+ print_chr(' ');
+ } else
+ if (r < 20) {
+ print_chr('x');
+ print_chr('1');
+ print_chr('0' + r - 10);
+ print_chr(' ');
+ } else
+ if (r < 30) {
+ print_chr('x');
+ print_chr('2');
+ print_chr('0' + r - 20);
+ print_chr(' ');
+ } else {
+ print_chr('x');
+ print_chr('3');
+ print_chr('0' + r - 30);
+ print_chr(' ');
+ }
+
+ print_hex(regs[r]);
+ print_str(k == 3 ? "\n" : " ");
+ }
+
+ print_str("------------------------------------------------------------\n");
+
+ print_str("Number of external IRQs counted: ");
+ print_dec(ext_irq_count);
+ print_str("\n");
+
+ print_str("Number of timer IRQs counted: ");
+ print_dec(timer_irq_count);
+ print_str("\n");
+
+ __asm__("sbreak");
+ return;
+ }
+}
+
diff --git a/firmware/start.S b/firmware/start.S
index d9e0b3e..cdb8da0 100644
--- a/firmware/start.S
+++ b/firmware/start.S
@@ -1,13 +1,174 @@
.section .text
- .global start
+ .global irq
.global sieve
.global stats
#define TEST(n) \
.global n; .global n ## _ret; \
+ addi x1, zero, 1000; \
+ custom0 0,1,0,5; /* timer x1 */ \
jal zero,n; n ## _ret:
+reset_vec:
+ custom0 0,0,7,3 // maskirq 7
+ j start
+ nop
+ nop
+
+irq_vec:
+ /* save registers */
+
+ custom0 2,1,0,1 // setq q2, x1
+ custom0 3,2,0,1 // setq q3, x2
+
+ lui x1, %hi(irq_regs)
+ addi x1, x1, %lo(irq_regs)
+
+ custom0 2,0,0,0 // getq x2, q0
+ sw x2, 0*4(x1)
+
+ custom0 2,2,0,0 // getq x2, q2
+ sw x2, 1*4(x1)
+
+ custom0 2,3,0,0 // getq x2, q3
+ sw x2, 2*4(x1)
+
+ sw x3, 3*4(x1)
+ sw x4, 4*4(x1)
+ sw x5, 5*4(x1)
+ sw x6, 6*4(x1)
+ sw x7, 7*4(x1)
+ sw x8, 8*4(x1)
+ sw x9, 9*4(x1)
+ sw x10, 10*4(x1)
+ sw x11, 11*4(x1)
+ sw x12, 12*4(x1)
+ sw x13, 13*4(x1)
+ sw x14, 14*4(x1)
+ sw x15, 15*4(x1)
+ sw x16, 16*4(x1)
+ sw x17, 17*4(x1)
+ sw x18, 18*4(x1)
+ sw x19, 19*4(x1)
+ sw x20, 20*4(x1)
+ sw x21, 21*4(x1)
+ sw x22, 22*4(x1)
+ sw x23, 23*4(x1)
+ sw x24, 24*4(x1)
+ sw x25, 25*4(x1)
+ sw x26, 26*4(x1)
+ sw x27, 27*4(x1)
+ sw x28, 28*4(x1)
+ sw x29, 29*4(x1)
+ sw x30, 30*4(x1)
+ sw x31, 31*4(x1)
+
+ /* call interrupt handler */
+
+ lui sp, %hi(irq_stack_top)
+ addi sp, sp, %lo(irq_stack_top)
+
+ // arg0 = address of regs
+ lui a0, %hi(irq_regs)
+ addi a0, a0, %lo(irq_regs)
+
+ // arg1 = interrupt type
+ custom0 11,1,0,0 // getq x11, q1
+
+ // call to c function
+ jal ra, irq
+
+ /* restore registers */
+
+ lui x1, %hi(irq_regs)
+ addi x1, x1, %lo(irq_regs)
+
+ lw x2, 0*4(x1)
+ custom0 0,2,0,1 // setq q0, x2
+
+ lw x2, 1*4(x1)
+ custom0 1,2,0,1 // setq q1, x2
+
+ lw x2, 2*4(x1)
+ custom0 2,2,0,1 // setq q2, x2
+
+ lw x3, 3*4(x1)
+ lw x4, 4*4(x1)
+ lw x5, 5*4(x1)
+ lw x6, 6*4(x1)
+ lw x7, 7*4(x1)
+ lw x8, 8*4(x1)
+ lw x9, 9*4(x1)
+ lw x10, 10*4(x1)
+ lw x11, 11*4(x1)
+ lw x12, 12*4(x1)
+ lw x13, 13*4(x1)
+ lw x14, 14*4(x1)
+ lw x15, 15*4(x1)
+ lw x16, 16*4(x1)
+ lw x17, 17*4(x1)
+ lw x18, 18*4(x1)
+ lw x19, 19*4(x1)
+ lw x20, 20*4(x1)
+ lw x21, 21*4(x1)
+ lw x22, 22*4(x1)
+ lw x23, 23*4(x1)
+ lw x24, 24*4(x1)
+ lw x25, 25*4(x1)
+ lw x26, 26*4(x1)
+ lw x27, 27*4(x1)
+ lw x28, 28*4(x1)
+ lw x29, 29*4(x1)
+ lw x30, 30*4(x1)
+ lw x31, 31*4(x1)
+
+ custom0 1,1,0,0 // getq x1, q1
+ custom0 2,2,0,0 // getq x2, q2
+
+ custom0 0,0,0,2 // retirq
+
+irq_regs:
+ // registers are saved to this memory region
+ // the program counter is saved as register 0
+ .fill 32,4
+
+irq_stack:
+ .fill 128,4
+irq_stack_top:
+
start:
+ addi x1, zero, 0
+ addi x2, zero, 0
+ addi x3, zero, 0
+ addi x4, zero, 0
+ addi x5, zero, 0
+ addi x6, zero, 0
+ addi x7, zero, 0
+ addi x8, zero, 0
+ addi x9, zero, 0
+ addi x10, zero, 0
+ addi x11, zero, 0
+ addi x12, zero, 0
+ addi x13, zero, 0
+ addi x14, zero, 0
+ addi x15, zero, 0
+ addi x16, zero, 0
+ addi x17, zero, 0
+ addi x18, zero, 0
+ addi x19, zero, 0
+ addi x20, zero, 0
+ addi x21, zero, 0
+ addi x22, zero, 0
+ addi x23, zero, 0
+ addi x24, zero, 0
+ addi x25, zero, 0
+ addi x26, zero, 0
+ addi x27, zero, 0
+ addi x28, zero, 0
+ addi x29, zero, 0
+ addi x30, zero, 0
+ addi x31, zero, 0
+
TEST(lui)
TEST(auipc)
TEST(j)