summaryrefslogtreecommitdiff
path: root/interrupt
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2021-01-22 01:13:44 +0100
committerVegard Storheil Eriksen <zyp@jvnv.net>2021-01-22 01:13:44 +0100
commit1a38973eb8fd0f889f7c272e9ef183687034d550 (patch)
treea673e3eda50ee3ec1edbaf7534fafdd7073d1b47 /interrupt
parent36efee9187390a52a99919b900b8faaea49be928 (diff)
interrupt: Refactor to be more flexible.
Diffstat (limited to 'interrupt')
-rw-r--r--interrupt/SConscript29
-rw-r--r--interrupt/default_handlers.cpp.j212
-rw-r--r--interrupt/interrupt.h58
-rw-r--r--interrupt/interrupt_enums.h.j220
-rw-r--r--interrupt/nvic.h52
-rw-r--r--interrupt/vectors_nvic.cpp.j222
6 files changed, 100 insertions, 93 deletions
diff --git a/interrupt/SConscript b/interrupt/SConscript
index c94bde8..05cafb9 100644
--- a/interrupt/SConscript
+++ b/interrupt/SConscript
@@ -1,18 +1,33 @@
Import('env')
+headers = []
+instances = []
sources = []
+aliases = {}
-interrupt_controller = env['PLATFORM_SPEC'].get('interrupt_controller')
+interrupts = env['PLATFORM_SPEC'].get('interrupt', {})
-exceptions = env['PLATFORM_SPEC'].get('exception', {})
-irqs = env['PLATFORM_SPEC'].get('irq', {})
+env.Jinja2('interrupt_enums.h', 'interrupt_enums.h.j2', interrupts = interrupts)
+headers.append('interrupt_enums.h')
-env.Jinja2('interrupt_enums.h', 'interrupt_enums.h.j2', exceptions = exceptions, irqs = irqs),
+sources.append(env.Jinja2('default_handlers.cpp', 'default_handlers.cpp.j2', interrupts = interrupts))
+
+periph = env['PLATFORM_SPEC'].get('periph', {})
+
+if 'nvic' in periph:
+ headers.append('nvic.h')
+ for name, data in periph['nvic'].items():
+ instances.append({
+ 'type': 'NVIC_t',
+ 'name': name,
+ 'args': [data['offset']],
+ })
+
+ aliases['SCB'] = 'NVIC.SCB'
+ aliases['interrupt_ctl'] = 'NVIC'
-if interrupt_controller == 'nvic':
sources.extend([
- env.Jinja2('vectors_nvic.cpp', 'vectors_nvic.cpp.j2', exceptions = exceptions, irqs = irqs),
- env.Jinja2('default_handlers.cpp', 'default_handlers.cpp.j2', exceptions = exceptions, irqs = irqs),
+ env.Jinja2('vectors_nvic.cpp', 'vectors_nvic.cpp.j2', interrupts = interrupts),
])
Return('sources')
diff --git a/interrupt/default_handlers.cpp.j2 b/interrupt/default_handlers.cpp.j2
index cc4c16d..a072f7f 100644
--- a/interrupt/default_handlers.cpp.j2
+++ b/interrupt/default_handlers.cpp.j2
@@ -4,16 +4,12 @@ extern "C" void default_blocking_handler() {
while(1);
}
-{% for exc in exceptions.values() %}
+{% for type, entries in interrupts.items() %}
+ {% for name in entries.values() %}
template<>
[[gnu::weak, gnu::alias("default_blocking_handler")]]
-void interrupt<Exception::{{ exc }}>();
+void interrupt::handler<interrupt::{{ type }}::{{ name }}>();
-{% endfor %}
-
-{% for irq in irqs.values() %}
-template<>
-[[gnu::weak, gnu::alias("default_blocking_handler")]]
-void interrupt<IRQ::{{ irq }}>();
+ {% endfor %}
{% endfor %}
diff --git a/interrupt/interrupt.h b/interrupt/interrupt.h
deleted file mode 100644
index b87abef..0000000
--- a/interrupt/interrupt.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef INTERRUPT_H
-#define INTERRUPT_H
-
-#include <stdint.h>
-
-#include "interrupt_enums.h"
-
-struct NVIC_t {
- volatile uint32_t ISER[32];
- volatile uint32_t ICER[32];
- volatile uint32_t ISPR[32];
- volatile uint32_t ICPR[32];
- volatile uint32_t IABR[64];
- volatile uint8_t IPR[2816];
- volatile uint32_t STIR;
-};
-
-static NVIC_t& NVIC = *(NVIC_t*)0xe000e100;
-
-struct SCB_t {
- volatile uint32_t CPUID;
- volatile uint32_t ICSR;
- volatile uint32_t VTOR;
- volatile uint32_t AIRCR;
- volatile uint32_t SCR;
- volatile uint32_t CCR;
- volatile uint8_t SHPR[12];
- volatile uint32_t SHCSR;
- volatile uint32_t CFSR;
- volatile uint32_t HFSR;
- volatile uint32_t DFSR;
- volatile uint32_t MMAR;
- volatile uint32_t BFAR;
-};
-
-static SCB_t& SCB = *(SCB_t*)0xe000ed00;
-
-namespace Interrupt {
- inline void enable(IRQ n) {
- NVIC.ISER[int(n) >> 5] = 1 << (int(n) & 0x1f);
- }
-
- inline void set_priority(Exception n, uint8_t priority) {
- SCB.SHPR[int(n) - 4] = priority;
- }
-
- inline void set_priority(IRQ n, uint8_t priority) {
- NVIC.IPR[int(n)] = priority;
- }
-};
-
-template<Exception>
-void interrupt();
-
-template<IRQ>
-void interrupt();
-
-#endif
diff --git a/interrupt/interrupt_enums.h.j2 b/interrupt/interrupt_enums.h.j2
index cc05100..4d58077 100644
--- a/interrupt/interrupt_enums.h.j2
+++ b/interrupt/interrupt_enums.h.j2
@@ -1,13 +1,17 @@
#pragma once
-enum class Exception {
- {% for num, name in exceptions.items() %}
- {{ name }} = {{ num }},
- {% endfor %}
-};
+namespace interrupt {
+ {% for type, entries in interrupts.items() %}
+ enum class {{ type }} {
+ {% for num, name in entries.items() %}
+ {{ name }} = {{ num }},
+ {% endfor %}
+ };
+
+ template<{{ type }}>
+ void handler();
-enum class IRQ {
- {% for num, name in irqs.items() %}
- {{ name }} = {{ num }},
{% endfor %}
+
+ typedef void (*vector_t)();
};
diff --git a/interrupt/nvic.h b/interrupt/nvic.h
new file mode 100644
index 0000000..b84a8a9
--- /dev/null
+++ b/interrupt/nvic.h
@@ -0,0 +1,52 @@
+#pragma once
+
+#include "interrupt_enums.h"
+
+#include <mmio/mmio.h>
+
+struct NVIC_reg_t {
+ volatile uint32_t ISER[32];
+ volatile uint32_t ICER[32];
+ volatile uint32_t ISPR[32];
+ volatile uint32_t ICPR[32];
+ volatile uint32_t IABR[64];
+ volatile uint8_t IPR[2816];
+ volatile uint32_t STIR;
+};
+
+struct SCB_reg_t {
+ volatile uint32_t CPUID;
+ volatile uint32_t ICSR;
+ volatile uint32_t VTOR;
+ volatile uint32_t AIRCR;
+ volatile uint32_t SCR;
+ volatile uint32_t CCR;
+ volatile uint8_t SHPR[12];
+ volatile uint32_t SHCSR;
+ volatile uint32_t CFSR;
+ volatile uint32_t HFSR;
+ volatile uint32_t DFSR;
+ volatile uint32_t MMAR;
+ volatile uint32_t BFAR;
+};
+
+class NVIC_t : public mmio_ptr<NVIC_reg_t> {
+ public:
+ mmio_ptr<SCB_reg_t> SCB;
+
+ constexpr NVIC_t(uintptr_t offset) :
+ mmio_ptr(offset),
+ SCB(offset + 0xc00) {}
+
+ void enable(interrupt::irq n) const {
+ ptr()->ISER[int(n) >> 5] = 1 << (int(n) & 0x1f);
+ }
+
+ void set_priority(interrupt::exception n, uint8_t priority) const {
+ SCB->SHPR[int(n) - 4] = priority;
+ }
+
+ void set_priority(interrupt::irq n, uint8_t priority) const {
+ ptr()->IPR[int(n)] = priority;
+ }
+};
diff --git a/interrupt/vectors_nvic.cpp.j2 b/interrupt/vectors_nvic.cpp.j2
index e4293f3..962efce 100644
--- a/interrupt/vectors_nvic.cpp.j2
+++ b/interrupt/vectors_nvic.cpp.j2
@@ -1,28 +1,26 @@
#include "interrupt.h"
void entry();
-extern uint32_t _ram_end;
-
-typedef void (*vector_t)();
+extern int _ram_end;
[[gnu::section(".vectors")]]
-vector_t vectors[] = {
- (vector_t)&_ram_end,
+interrupt::vector_t vectors[] = {
+ (interrupt::vector_t)&_ram_end,
entry,
{% for i in range(2, 16) %}
- {% if i in exceptions %}
- interrupt<Exception::{{ exceptions[i] }}>,
+ {% if i in interrupts.exception %}
+ interrupt::handler<interrupt::exception::{{ interrupts.exception[i] }}>,
{% else %}
- 0,
+ 0,
{% endif %}
{% endfor %}
- {% for i in range(irqs | max + 1 if irqs else 0) %}
- {% if i in irqs %}
- interrupt<IRQ::{{ irqs[i] }}>,
+ {% for i in range(interrupts.irq | max + 1 if interrupts.irq else 0) %}
+ {% if i in interrupts.irq %}
+ interrupt::handler<interrupt::irq::{{ interrupts.irq[i] }}>,
{% else %}
- 0,
+ 0,
{% endif %}
{% endfor %}
};