summaryrefslogtreecommitdiff
path: root/interrupt
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2021-09-15 23:16:11 +0200
committerVegard Storheil Eriksen <zyp@jvnv.net>2021-09-15 23:16:11 +0200
commit968937d0d937487ab301f017c145889fc0e94692 (patch)
treea62e27423fdc515c71624def636b63b12f06cf57 /interrupt
parent9194e871a4590d1118f40ea8dbf1d34e45bc759c (diff)
platforms: Add initial RISC-V/GD32V support.
Diffstat (limited to 'interrupt')
-rw-r--r--interrupt/SConscript16
-rw-r--r--interrupt/clic.h33
-rw-r--r--interrupt/dispatch_clic.cpp25
-rw-r--r--interrupt/dispatch_plic.cpp8
-rw-r--r--interrupt/dispatch_riscv.cpp24
-rw-r--r--interrupt/plic.h25
-rw-r--r--interrupt/vectors_clic.cpp.j223
-rw-r--r--interrupt/vectors_generic.cpp.j214
8 files changed, 168 insertions, 0 deletions
diff --git a/interrupt/SConscript b/interrupt/SConscript
index 2380815..4544785 100644
--- a/interrupt/SConscript
+++ b/interrupt/SConscript
@@ -30,6 +30,22 @@ if 'nvic' in periph:
env.Jinja2('vectors_nvic.cpp', 'vectors_nvic.cpp.j2', interrupts = interrupts),
])
+if 'clic' in periph:
+ headers.append('clic.h')
+ for name, data in periph['clic'].items():
+ instances.append({
+ 'type': 'CLIC_t',
+ 'name': name,
+ 'args': [data['offset']],
+ })
+
+ aliases['interrupt_ctl'] = 'CLIC'
+
+ sources.extend([
+ File('dispatch_clic.cpp'),
+ env.Jinja2('vectors_clic.cpp', 'vectors_clic.cpp.j2', interrupts = interrupts),
+ ])
+
env.Jinja2('interrupt.h', '../templates/periph_instances.h.j2', headers = headers, instances = instances, aliases = aliases)
Return('sources')
diff --git a/interrupt/clic.h b/interrupt/clic.h
new file mode 100644
index 0000000..247aeec
--- /dev/null
+++ b/interrupt/clic.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "interrupt_enums.h"
+
+#include <mmio/mmio.h>
+
+struct CLIC_int_reg_t {
+ volatile uint8_t IP;
+ volatile uint8_t IE;
+ volatile uint8_t ATTR;
+ volatile uint8_t CTL;
+};
+
+struct CLIC_reg_t {
+ volatile uint32_t CFG;
+ volatile uint32_t INFO;
+ uint32_t _reserved[14];
+ volatile uint32_t TRIG[32];
+ uint32_t _reserved2[976];
+ CLIC_int_reg_t INT[4096];
+};
+
+
+class CLIC_t : public mmio_ptr<CLIC_reg_t> {
+ public:
+ void enable(interrupt::irq n) const {
+ ptr()->INT[int(n)].IE = 1;
+ }
+
+ void enable(interrupt::internal n) const {
+ ptr()->INT[int(n)].IE = 1;
+ }
+};
diff --git a/interrupt/dispatch_clic.cpp b/interrupt/dispatch_clic.cpp
new file mode 100644
index 0000000..64e4bfc
--- /dev/null
+++ b/interrupt/dispatch_clic.cpp
@@ -0,0 +1,25 @@
+#include "interrupt.h"
+
+extern interrupt::vector_t vectors_exception[];
+extern interrupt::vector_t vectors_clic[];
+
+[[gnu::interrupt, gnu::aligned(64)]]
+void riscv_interrupt_handler() {
+ uint32_t cause;
+ asm("csrr %0, mcause" : "=r"(cause));
+
+ uint32_t type = cause & 0x80000000;
+ uint32_t code = cause & 0x00000fff;
+
+ if(type) {
+ vectors_clic[code]();
+ } else {
+ vectors_exception[code]();
+ }
+}
+
+[[gnu::constructor(200)]]
+void riscv_interrupt_init() {
+ asm volatile("csrw mtvec, %0" :: "r"(intptr_t(riscv_interrupt_handler) | 3));
+ asm volatile("csrrsi x0, mstatus, (1 << 3)");
+}
diff --git a/interrupt/dispatch_plic.cpp b/interrupt/dispatch_plic.cpp
new file mode 100644
index 0000000..081013d
--- /dev/null
+++ b/interrupt/dispatch_plic.cpp
@@ -0,0 +1,8 @@
+#include "interrupt.h"
+
+extern interrupt::vector_t vectors_irq[];
+
+template<>
+void interrupt::handler<interrupt::internal::MEI>() {
+ while(1) {}
+}
diff --git a/interrupt/dispatch_riscv.cpp b/interrupt/dispatch_riscv.cpp
new file mode 100644
index 0000000..a91e95a
--- /dev/null
+++ b/interrupt/dispatch_riscv.cpp
@@ -0,0 +1,24 @@
+#include "interrupt.h"
+
+extern interrupt::vector_t vectors_exception[];
+extern interrupt::vector_t vectors_internal[];
+
+[[gnu::interrupt]]
+void riscv_interrupt_handler() {
+ uint32_t cause;
+ asm("csrr %0, mcause" : "=r"(cause));
+
+ uint32_t type = cause & 0x80000000;
+ uint32_t code = cause & 0x7fffffff;
+
+ if(type) {
+ vectors_internal[code]();
+ } else {
+ vectors_exception[code]();
+ }
+}
+
+[[gnu::constructor(200)]]
+void riscv_interrupt_init() {
+ asm volatile("csrw mtvec, %0" :: "r"(riscv_interrupt_handler));
+}
diff --git a/interrupt/plic.h b/interrupt/plic.h
new file mode 100644
index 0000000..46ade92
--- /dev/null
+++ b/interrupt/plic.h
@@ -0,0 +1,25 @@
+#pragma once
+
+class PLIC_t {
+ private:
+ struct PLIC_ctx_reg_t {
+ volatile uint32_t THRESHOLD;
+ volatile uint32_t CLAIM;
+ uint32_t _reserved[1022];
+ };
+
+ struct PLIC_reg_t {
+ volatile uint32_t PRIO[1024];
+ volatile uint32_t PEND[32];
+ uint32_t _reserved[992];
+ volatile uint32_t ENABLE[15872][32];
+ uint32_t _reserved2[14336];
+ PLIC_ctx_reg_t CTX[15872];
+ };
+
+ public:
+ PLIC_reg_t& reg;
+
+ PLIC_t(uint32_t reg_addr) :
+ reg(*(PLIC_reg_t*)reg_addr) {}
+};
diff --git a/interrupt/vectors_clic.cpp.j2 b/interrupt/vectors_clic.cpp.j2
new file mode 100644
index 0000000..7f9dd9f
--- /dev/null
+++ b/interrupt/vectors_clic.cpp.j2
@@ -0,0 +1,23 @@
+#include "interrupt.h"
+
+interrupt::vector_t vectors_clic[] = {
+ {% for i in range(interrupts.irq | max + 1 if interrupts.irq else interrupts.internal | max + 1 if interrupts.internal else 0) %}
+ {% if i in interrupts.internal %}
+ interrupt::handler<interrupt::internal::{{ interrupts.internal[i] }}>,
+ {% elif i in interrupts.irq %}
+ interrupt::handler<interrupt::irq::{{ interrupts.irq[i] }}>,
+ {% else %}
+ 0,
+ {% endif %}
+ {% endfor %}
+};
+
+interrupt::vector_t vectors_exception[] = {
+ {% for i in range(interrupts.exception | max + 1 if interrupts.exception else 0) %}
+ {% if i in interrupts.exception %}
+ interrupt::handler<interrupt::exception::{{ interrupts.exception[i] }}>,
+ {% else %}
+ 0,
+ {% endif %}
+ {% endfor %}
+};
diff --git a/interrupt/vectors_generic.cpp.j2 b/interrupt/vectors_generic.cpp.j2
new file mode 100644
index 0000000..26ef05d
--- /dev/null
+++ b/interrupt/vectors_generic.cpp.j2
@@ -0,0 +1,14 @@
+#include "interrupt.h"
+
+{% for type, entries in interrupts.items() %}
+ interrupt::vector_t vectors_{{ type }}[] = {
+ {% for i in range(entries | max + 1 if entries else 0) %}
+ {% if i in entries %}
+ interrupt::handler<interrupt::{{ type }}::{{ entries[i] }}>,
+ {% else %}
+ 0,
+ {% endif %}
+ {% endfor %}
+ };
+
+{% endfor %}