diff options
Diffstat (limited to 'interrupt')
-rw-r--r-- | interrupt/SConscript | 16 | ||||
-rw-r--r-- | interrupt/clic.h | 33 | ||||
-rw-r--r-- | interrupt/dispatch_clic.cpp | 25 | ||||
-rw-r--r-- | interrupt/dispatch_plic.cpp | 8 | ||||
-rw-r--r-- | interrupt/dispatch_riscv.cpp | 24 | ||||
-rw-r--r-- | interrupt/plic.h | 25 | ||||
-rw-r--r-- | interrupt/vectors_clic.cpp.j2 | 23 | ||||
-rw-r--r-- | interrupt/vectors_generic.cpp.j2 | 14 |
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 %} |