summaryrefslogtreecommitdiff
path: root/interrupt
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2021-01-16 01:25:21 +0100
committerVegard Storheil Eriksen <zyp@jvnv.net>2021-01-16 01:25:21 +0100
commit172d694cf7ba582635ac38454bad0f0fdaa14773 (patch)
treeefb0d145ed7fb3eeb44541714568680a6451ab3d /interrupt
parent9921c9db409ad5b00fe4a43a2459e2fd2de6b0cf (diff)
interrupt: Generate interrupts from platform spec.
Diffstat (limited to 'interrupt')
-rw-r--r--interrupt/SConscript18
-rw-r--r--interrupt/default_handlers.cpp.j219
-rw-r--r--interrupt/fault.cpp45
-rw-r--r--interrupt/interrupt.cpp159
-rw-r--r--interrupt/interrupt.h87
-rw-r--r--interrupt/interrupt_enums.h.j213
-rw-r--r--interrupt/vectors_nvic.cpp.j228
7 files changed, 85 insertions, 284 deletions
diff --git a/interrupt/SConscript b/interrupt/SConscript
new file mode 100644
index 0000000..c94bde8
--- /dev/null
+++ b/interrupt/SConscript
@@ -0,0 +1,18 @@
+Import('env')
+
+sources = []
+
+interrupt_controller = env['PLATFORM_SPEC'].get('interrupt_controller')
+
+exceptions = env['PLATFORM_SPEC'].get('exception', {})
+irqs = env['PLATFORM_SPEC'].get('irq', {})
+
+env.Jinja2('interrupt_enums.h', 'interrupt_enums.h.j2', exceptions = exceptions, irqs = irqs),
+
+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),
+ ])
+
+Return('sources')
diff --git a/interrupt/default_handlers.cpp.j2 b/interrupt/default_handlers.cpp.j2
new file mode 100644
index 0000000..cc4c16d
--- /dev/null
+++ b/interrupt/default_handlers.cpp.j2
@@ -0,0 +1,19 @@
+#include "interrupt.h"
+
+extern "C" void default_blocking_handler() {
+ while(1);
+}
+
+{% for exc in exceptions.values() %}
+template<>
+[[gnu::weak, gnu::alias("default_blocking_handler")]]
+void interrupt<Exception::{{ exc }}>();
+
+{% endfor %}
+
+{% for irq in irqs.values() %}
+template<>
+[[gnu::weak, gnu::alias("default_blocking_handler")]]
+void interrupt<IRQ::{{ irq }}>();
+
+{% endfor %}
diff --git a/interrupt/fault.cpp b/interrupt/fault.cpp
deleted file mode 100644
index 0d91c1d..0000000
--- a/interrupt/fault.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#include "interrupt.h"
-#include <os/thread.h>
-#include <os/time.h>
-
-inline void __attribute__((naked)) switch_context() {
- #if ! (defined(STM32F0) || defined(STM32L0)) // TODO: cortex-m0/+ unsupported for now.
-
- asm volatile ("cpsid i");
-
- // Save unsaved registers.
- asm volatile ("push {r4, r5, r6, r7, r8, r9, r10, r11, lr}" ::: "memory");
-
- // Store stack pointer for old thread.
- asm volatile ("str sp, [%0]" :: "r" (&Thread::active_thread->sp));
-
- // Update running thread.
- Thread::active_thread = Thread::active_thread->next;
-
- // Fetch stack pointer for new thread.
- asm volatile ("ldr sp, [%0]" :: "r" (&Thread::active_thread->sp));
-
- asm volatile ("cpsie i");
-
- // Load registers and return.
- asm volatile ("pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}" ::: "memory");
-
- #endif
-}
-
-template<>
-void interrupt<Interrupt::SVCall>() {
- switch_context();
-}
-
-template<>
-void interrupt<Interrupt::SysTick>() {
- Time::tick();
-}
-
-template<> void interrupt<Interrupt::NMI>() { while(1); }
-template<> void interrupt<Interrupt::HardFault>() { while(1); }
-template<> void interrupt<Interrupt::MemManage>() { while(1); }
-template<> void interrupt<Interrupt::BusFault>() { while(1); }
-template<> void interrupt<Interrupt::UsageFault>() { while(1); }
-template<> void interrupt<Interrupt::PendSV>() { while(1); }
diff --git a/interrupt/interrupt.cpp b/interrupt/interrupt.cpp
deleted file mode 100644
index b50c01e..0000000
--- a/interrupt/interrupt.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-#include "interrupt.h"
-
-void entry();
-
-extern "C" void unused_interrupt() {
- //while(1);
-}
-
-template<> void interrupt<Interrupt::NMI>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::HardFault>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::MemManage>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::BusFault>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::UsageFault>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::SVCall>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::PendSV>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::SysTick>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::WWDG>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::PVD>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TAMPER>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::RTC>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::FLASH>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::RCC>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::EXTI0>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::EXTI1>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::EXTI2>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::EXTI3>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::EXTI4>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::DMA1_Channel1>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::DMA1_Channel2>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::DMA1_Channel3>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::DMA1_Channel4>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::DMA1_Channel5>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::DMA1_Channel6>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::DMA1_Channel7>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::ADC1_2>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::USB_HP_CAN_TX>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::USB_LP_CAN_RX0>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::CAN_RX1>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::CAN_SCE>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::EXTI9_5>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TIM1_BRK>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TIM1_UP>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TIM1_TRG_COM>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TIM1_CC>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TIM2>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TIM3>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TIM4>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::I2C1_EV>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::I2C1_ER>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::I2C2_EV>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::I2C2_ER>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::SPI1>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::SPI2>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::USART1>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::USART2>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::USART3>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::EXTI15_10>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::RTCAlarm>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::USBWakeup>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TIM8_BRK>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TIM8_UP>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TIM8_TRG_COM>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TIM8_CC>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::ADC3>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::FSMC>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::SDIO>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TIM5>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::SPI3>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::UART4>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::UART5>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TIM6>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::TIM7>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::DMA2_Channel1>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::DMA2_Channel2>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::DMA2_Channel3>() __attribute__ ((weak, alias ("unused_interrupt")));
-template<> void interrupt<Interrupt::DMA2_Channel4_5>() __attribute__ ((weak, alias ("unused_interrupt")));
-
-typedef void (*vector_t)();
-
-extern uint32_t _ram_end;
-
-vector_t vectors[] __attribute__((section(".vectors"))) = {
- (vector_t)&_ram_end,
- entry,
- interrupt<Interrupt::NMI>,
- interrupt<Interrupt::HardFault>,
- interrupt<Interrupt::MemManage>,
- interrupt<Interrupt::BusFault>,
- interrupt<Interrupt::UsageFault>,
- 0,
- 0,
- 0,
- 0,
- interrupt<Interrupt::SVCall>,
- 0,
- 0,
- interrupt<Interrupt::PendSV>,
- interrupt<Interrupt::SysTick>,
- interrupt<Interrupt::WWDG>,
- interrupt<Interrupt::PVD>,
- interrupt<Interrupt::TAMPER>,
- interrupt<Interrupt::RTC>,
- interrupt<Interrupt::FLASH>,
- interrupt<Interrupt::RCC>,
- interrupt<Interrupt::EXTI0>,
- interrupt<Interrupt::EXTI1>,
- interrupt<Interrupt::EXTI2>,
- interrupt<Interrupt::EXTI3>,
- interrupt<Interrupt::EXTI4>,
- interrupt<Interrupt::DMA1_Channel1>,
- interrupt<Interrupt::DMA1_Channel2>,
- interrupt<Interrupt::DMA1_Channel3>,
- interrupt<Interrupt::DMA1_Channel4>,
- interrupt<Interrupt::DMA1_Channel5>,
- interrupt<Interrupt::DMA1_Channel6>,
- interrupt<Interrupt::DMA1_Channel7>,
- interrupt<Interrupt::ADC1_2>,
- interrupt<Interrupt::USB_HP_CAN_TX>,
- interrupt<Interrupt::USB_LP_CAN_RX0>,
- interrupt<Interrupt::CAN_RX1>,
- interrupt<Interrupt::CAN_SCE>,
- interrupt<Interrupt::EXTI9_5>,
- interrupt<Interrupt::TIM1_BRK>,
- interrupt<Interrupt::TIM1_UP>,
- interrupt<Interrupt::TIM1_TRG_COM>,
- interrupt<Interrupt::TIM1_CC>,
- interrupt<Interrupt::TIM2>,
- interrupt<Interrupt::TIM3>,
- interrupt<Interrupt::TIM4>,
- interrupt<Interrupt::I2C1_EV>,
- interrupt<Interrupt::I2C1_ER>,
- interrupt<Interrupt::I2C2_EV>,
- interrupt<Interrupt::I2C2_ER>,
- interrupt<Interrupt::SPI1>,
- interrupt<Interrupt::SPI2>,
- interrupt<Interrupt::USART1>,
- interrupt<Interrupt::USART2>,
- interrupt<Interrupt::USART3>,
- interrupt<Interrupt::EXTI15_10>,
- interrupt<Interrupt::RTCAlarm>,
- interrupt<Interrupt::USBWakeup>,
- interrupt<Interrupt::TIM8_BRK>,
- interrupt<Interrupt::TIM8_UP>,
- interrupt<Interrupt::TIM8_TRG_COM>,
- interrupt<Interrupt::TIM8_CC>,
- interrupt<Interrupt::ADC3>,
- interrupt<Interrupt::FSMC>,
- interrupt<Interrupt::SDIO>,
- interrupt<Interrupt::TIM5>,
- interrupt<Interrupt::SPI3>,
- interrupt<Interrupt::UART4>,
- interrupt<Interrupt::UART5>,
- interrupt<Interrupt::TIM6>,
- interrupt<Interrupt::TIM7>,
- interrupt<Interrupt::DMA2_Channel1>,
- interrupt<Interrupt::DMA2_Channel2>,
- interrupt<Interrupt::DMA2_Channel3>,
- interrupt<Interrupt::DMA2_Channel4_5>,
-};
diff --git a/interrupt/interrupt.h b/interrupt/interrupt.h
index 0851c87..b87abef 100644
--- a/interrupt/interrupt.h
+++ b/interrupt/interrupt.h
@@ -3,6 +3,8 @@
#include <stdint.h>
+#include "interrupt_enums.h"
+
struct NVIC_t {
volatile uint32_t ISER[32];
volatile uint32_t ICER[32];
@@ -34,98 +36,23 @@ struct SCB_t {
static SCB_t& SCB = *(SCB_t*)0xe000ed00;
namespace Interrupt {
- enum Exception {
- NMI = 2,
- HardFault = 3,
- MemManage = 4,
- BusFault = 5,
- UsageFault = 6,
- SVCall = 11,
- PendSV = 14,
- SysTick = 15
- };
-
- enum IRQ {
- WWDG,
- PVD,
- TAMPER,
- RTC,
- FLASH,
- RCC,
- EXTI0,
- EXTI1,
- EXTI2,
- EXTI3,
- EXTI4,
- DMA1_Channel1,
- DMA1_Channel2,
- DMA1_Channel3,
- DMA1_Channel4,
- DMA1_Channel5,
- DMA1_Channel6,
- DMA1_Channel7,
- ADC1_2,
- USB_HP_CAN_TX,
- USB_LP_CAN_RX0,
- CAN_RX1,
- CAN_SCE,
- EXTI9_5,
- TIM1_BRK,
- TIM1_UP,
- TIM1_TRG_COM,
- TIM1_CC,
- TIM2,
- TIM3,
- TIM4,
- I2C1_EV,
- I2C1_ER,
- I2C2_EV,
- I2C2_ER,
- SPI1,
- SPI2,
- USART1,
- USART2,
- USART3,
- EXTI15_10,
- RTCAlarm,
- USBWakeup,
- TIM8_BRK,
- TIM8_UP,
- TIM8_TRG_COM,
- TIM8_CC,
- ADC3,
- FSMC,
- SDIO,
- TIM5,
- SPI3,
- UART4,
- UART5,
- TIM6,
- TIM7,
- DMA2_Channel1,
- DMA2_Channel2,
- DMA2_Channel3,
- DMA2_Channel4_5,
- NUM_IRQs
- };
-
inline void enable(IRQ n) {
- NVIC.ISER[n >> 5] = 1 << (n & 0x1f);
+ NVIC.ISER[int(n) >> 5] = 1 << (int(n) & 0x1f);
}
inline void set_priority(Exception n, uint8_t priority) {
- SCB.SHPR[n - 4] = priority;
+ SCB.SHPR[int(n) - 4] = priority;
}
inline void set_priority(IRQ n, uint8_t priority) {
- NVIC.IPR[n] = priority;
+ NVIC.IPR[int(n)] = priority;
}
};
-template<Interrupt::Exception>
+template<Exception>
void interrupt();
-template<Interrupt::IRQ>
+template<IRQ>
void interrupt();
#endif
diff --git a/interrupt/interrupt_enums.h.j2 b/interrupt/interrupt_enums.h.j2
new file mode 100644
index 0000000..cc05100
--- /dev/null
+++ b/interrupt/interrupt_enums.h.j2
@@ -0,0 +1,13 @@
+#pragma once
+
+enum class Exception {
+ {% for num, name in exceptions.items() %}
+ {{ name }} = {{ num }},
+ {% endfor %}
+};
+
+enum class IRQ {
+ {% for num, name in irqs.items() %}
+ {{ name }} = {{ num }},
+ {% endfor %}
+};
diff --git a/interrupt/vectors_nvic.cpp.j2 b/interrupt/vectors_nvic.cpp.j2
new file mode 100644
index 0000000..e4293f3
--- /dev/null
+++ b/interrupt/vectors_nvic.cpp.j2
@@ -0,0 +1,28 @@
+#include "interrupt.h"
+
+void entry();
+extern uint32_t _ram_end;
+
+typedef void (*vector_t)();
+
+[[gnu::section(".vectors")]]
+vector_t vectors[] = {
+ (vector_t)&_ram_end,
+ entry,
+
+ {% for i in range(2, 16) %}
+ {% if i in exceptions %}
+ interrupt<Exception::{{ exceptions[i] }}>,
+ {% else %}
+ 0,
+ {% endif %}
+ {% endfor %}
+
+ {% for i in range(irqs | max + 1 if irqs else 0) %}
+ {% if i in irqs %}
+ interrupt<IRQ::{{ irqs[i] }}>,
+ {% else %}
+ 0,
+ {% endif %}
+ {% endfor %}
+};