diff options
author | Vegard Storheil Eriksen <zyp@jvnv.net> | 2021-01-22 01:13:44 +0100 |
---|---|---|
committer | Vegard Storheil Eriksen <zyp@jvnv.net> | 2021-01-22 01:13:44 +0100 |
commit | 1a38973eb8fd0f889f7c272e9ef183687034d550 (patch) | |
tree | a673e3eda50ee3ec1edbaf7534fafdd7073d1b47 /interrupt | |
parent | 36efee9187390a52a99919b900b8faaea49be928 (diff) |
interrupt: Refactor to be more flexible.
Diffstat (limited to 'interrupt')
-rw-r--r-- | interrupt/SConscript | 29 | ||||
-rw-r--r-- | interrupt/default_handlers.cpp.j2 | 12 | ||||
-rw-r--r-- | interrupt/interrupt.h | 58 | ||||
-rw-r--r-- | interrupt/interrupt_enums.h.j2 | 20 | ||||
-rw-r--r-- | interrupt/nvic.h | 52 | ||||
-rw-r--r-- | interrupt/vectors_nvic.cpp.j2 | 22 |
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 %} }; |