diff options
author | Vegard Storheil Eriksen <zyp@jvnv.net> | 2021-01-16 01:25:21 +0100 |
---|---|---|
committer | Vegard Storheil Eriksen <zyp@jvnv.net> | 2021-01-16 01:25:21 +0100 |
commit | 172d694cf7ba582635ac38454bad0f0fdaa14773 (patch) | |
tree | efb0d145ed7fb3eeb44541714568680a6451ab3d /interrupt | |
parent | 9921c9db409ad5b00fe4a43a2459e2fd2de6b0cf (diff) |
interrupt: Generate interrupts from platform spec.
Diffstat (limited to 'interrupt')
-rw-r--r-- | interrupt/SConscript | 18 | ||||
-rw-r--r-- | interrupt/default_handlers.cpp.j2 | 19 | ||||
-rw-r--r-- | interrupt/fault.cpp | 45 | ||||
-rw-r--r-- | interrupt/interrupt.cpp | 159 | ||||
-rw-r--r-- | interrupt/interrupt.h | 87 | ||||
-rw-r--r-- | interrupt/interrupt_enums.h.j2 | 13 | ||||
-rw-r--r-- | interrupt/vectors_nvic.cpp.j2 | 28 |
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 %} +}; |