From 172d694cf7ba582635ac38454bad0f0fdaa14773 Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Sat, 16 Jan 2021 01:25:21 +0100 Subject: interrupt: Generate interrupts from platform spec. --- interrupt/SConscript | 18 +++++ interrupt/default_handlers.cpp.j2 | 19 +++++ interrupt/fault.cpp | 45 ----------- interrupt/interrupt.cpp | 159 -------------------------------------- interrupt/interrupt.h | 87 ++------------------- interrupt/interrupt_enums.h.j2 | 13 ++++ interrupt/vectors_nvic.cpp.j2 | 28 +++++++ 7 files changed, 85 insertions(+), 284 deletions(-) create mode 100644 interrupt/SConscript create mode 100644 interrupt/default_handlers.cpp.j2 delete mode 100644 interrupt/fault.cpp delete mode 100644 interrupt/interrupt.cpp create mode 100644 interrupt/interrupt_enums.h.j2 create mode 100644 interrupt/vectors_nvic.cpp.j2 (limited to 'interrupt') 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(); + +{% endfor %} + +{% for irq in irqs.values() %} +template<> +[[gnu::weak, gnu::alias("default_blocking_handler")]] +void interrupt(); + +{% 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 -#include - -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() { - switch_context(); -} - -template<> -void interrupt() { - Time::tick(); -} - -template<> void interrupt() { while(1); } -template<> void interrupt() { while(1); } -template<> void interrupt() { while(1); } -template<> void interrupt() { while(1); } -template<> void interrupt() { while(1); } -template<> void interrupt() { 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() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __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, - interrupt, - interrupt, - interrupt, - 0, - 0, - 0, - 0, - interrupt, - 0, - 0, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, -}; 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 +#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 +template void interrupt(); -template +template 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, + {% else %} + 0, + {% endif %} + {% endfor %} + + {% for i in range(irqs | max + 1 if irqs else 0) %} + {% if i in irqs %} + interrupt, + {% else %} + 0, + {% endif %} + {% endfor %} +}; -- cgit v1.2.3