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. --- SConscript | 12 ++- i2c/i2c.cpp | 10 +-- i2c/i2c.h | 4 +- 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 +++++++ platforms/cortex-m.yaml | 12 +++ platforms/stm32/f4.yaml | 93 ++++++++++++++++++++++ 12 files changed, 204 insertions(+), 296 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 diff --git a/SConscript b/SConscript index 7511f19..846a01f 100644 --- a/SConscript +++ b/SConscript @@ -4,10 +4,14 @@ Import('env') Export('env') env.SConscript('ld_scripts/SConscript') -env.SConscript('usb/SConscript') env.Append( - LIB_SOURCES = Glob('*.cpp') + Glob('*/*.cpp'), + LIB_SOURCES = [ + env.SConscript('interrupt/SConscript'), + env.SConscript('usb/SConscript'), + Glob('startup/*.cpp'), + Glob('i2c/*.cpp'), + Glob('os/*.cpp'), + Glob('rcc/*.cpp'), + ], ) - -# vim: syn=python diff --git a/i2c/i2c.cpp b/i2c/i2c.cpp index 36ce972..3039e47 100644 --- a/i2c/i2c.cpp +++ b/i2c/i2c.cpp @@ -4,12 +4,12 @@ #include #if defined(STM32F1) -I2C_t I2C1(0x40005400, 36000000, Interrupt::I2C1_EV, Interrupt::I2C1_ER); -I2C_t I2C2(0x40005800, 36000000, Interrupt::I2C2_EV, Interrupt::I2C2_ER); +I2C_t I2C1(0x40005400, 36000000); +I2C_t I2C2(0x40005800, 36000000); #elif defined(STM32F4) -I2C_t I2C1(0x40005400, 42000000, Interrupt::I2C1_EV, Interrupt::I2C1_ER); -I2C_t I2C2(0x40005800, 42000000, Interrupt::I2C2_EV, Interrupt::I2C2_ER); -//I2C_t I2C3(0x40005c00, 42000000, Interrupt::I2C3_EV, Interrupt::I2C3_ER); +I2C_t I2C1(0x40005400, 42000000); +I2C_t I2C2(0x40005800, 42000000); +//I2C_t I2C3(0x40005c00, 42000000); #endif #if defined(STM32F1) || defined(STM32F4) diff --git a/i2c/i2c.h b/i2c/i2c.h index ed72aa3..a2fde32 100644 --- a/i2c/i2c.h +++ b/i2c/i2c.h @@ -29,10 +29,8 @@ class I2C_t { public: I2C_reg_t& reg; const uint32_t clk; - Interrupt::IRQ irq_ev_n; - Interrupt::IRQ irq_er_n; - I2C_t(uint32_t reg_addr, uint32_t bus_clk, Interrupt::IRQ ev_n, Interrupt::IRQ er_n) : reg(*(I2C_reg_t*)reg_addr), clk(bus_clk), irq_ev_n(ev_n), irq_er_n(er_n) { + I2C_t(uint32_t reg_addr, uint32_t bus_clk) : reg(*(I2C_reg_t*)reg_addr), clk(bus_clk) { reading = writing = 0; } 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 %} +}; diff --git a/platforms/cortex-m.yaml b/platforms/cortex-m.yaml index d1612b2..c0aa8bd 100644 --- a/platforms/cortex-m.yaml +++ b/platforms/cortex-m.yaml @@ -1,6 +1,18 @@ - match: cpu: cortex-m4f + interrupt_controller: nvic + + exception: + 2: NMI + 3: HardFault + 4: MemManage + 5: BusFault + 6: UsageFault + 11: SVCall + 14: PendSV + 15: SysTick + cflags: - -mcpu=cortex-m4 - -mfloat-abi=hard diff --git a/platforms/stm32/f4.yaml b/platforms/stm32/f4.yaml index dccffe9..c132524 100644 --- a/platforms/stm32/f4.yaml +++ b/platforms/stm32/f4.yaml @@ -34,6 +34,99 @@ OTG_HS: offset: 0x40040000 + irq: + 0: WWDG + 1: PVD + 2: TAMP_STAMP + 3: RTC_WKUP + 4: FLASH + 5: RCC + 6: EXTI0 + 7: EXTI1 + 8: EXTI2 + 9: EXTI3 + 10: EXTI4 + 11: DMA1_Stream0 + 12: DMA1_Stream1 + 13: DMA1_Stream2 + 14: DMA1_Stream3 + 15: DMA1_Stream4 + 16: DMA1_Stream5 + 17: DMA1_Stream6 + 18: ADC + 19: CAN1_TX + 20: CAN1_RX0 + 21: CAN1_RX1 + 22: CAN1_SCE + 23: EXTI9_5 + 24: TIM1_BRK_TIM9 + 25: TIM1_UP_TIM10 + 26: TIM1_TRG_COM_TIM11 + 27: TIM1_CC + 28: TIM2 + 29: TIM3 + 30: TIM4 + 31: I2C1_EV + 32: I2C1_ER + 33: I2C2_EV + 34: I2C2_ER + 35: SPI1 + 36: SPI2 + 37: USART1 + 38: USART2 + 39: USART3 + 40: EXTI15_10 + 41: RTC_Alarm + 42: OTG_FS_WKUP + 43: TIM8_BRK_TIM12 + 44: TIM8_UP_TIM13 + 45: TIM8_TRG_COM_TIM14 + 46: TIM8_CC + 47: DMA1_Stream7 + 48: FSMC + 49: SDIO + 50: TIM5 + 51: SPI3 + 52: UART4 + 53: UART5 + 54: TIM6_DAC + 55: TIM7 + 56: DMA2_Stream0 + 57: DMA2_Stream1 + 58: DMA2_Stream2 + 59: DMA2_Stream3 + 60: DMA2_Stream4 + 61: ETH + 62: ETH_WKUP + 63: CAN2_TX + 64: CAN2_RX0 + 65: CAN2_RX1 + 66: CAN2_SCE + 67: OTG_FS + 68: DMA2_Stream5 + 69: DMA2_Stream6 + 70: DMA2_Stream7 + 71: USART6 + 72: I2C3_EV + 73: I2C3_ER + 74: OTG_HS_EP1_OUT + 75: OTG_HS_EP1_IN + 76: OTG_HS_WKUP + 77: OTG_HS + 78: DCMI + 79: CRYP + 80: HASH_RNG + 81: FPU + 82: UART7 + 83: UART8 + 84: SPI4 + 85: SPI5 + 86: SPI6 + 87: SAI1 + 88: LCD_TFT + 89: LCD_TFT_ERR + 90: DMA2D + define: - STM32F4 -- cgit v1.2.3