diff options
-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 | ||||
-rw-r--r-- | platforms/cortex-m.yaml | 24 | ||||
-rw-r--r-- | platforms/stm32/f4.yaml | 185 |
8 files changed, 207 insertions, 195 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 %} }; diff --git a/platforms/cortex-m.yaml b/platforms/cortex-m.yaml index c0aa8bd..a41957a 100644 --- a/platforms/cortex-m.yaml +++ b/platforms/cortex-m.yaml @@ -1,17 +1,21 @@ - match: cpu: cortex-m4f - interrupt_controller: nvic + periph: + nvic: + NVIC: + offset: 0xe000e100 - exception: - 2: NMI - 3: HardFault - 4: MemManage - 5: BusFault - 6: UsageFault - 11: SVCall - 14: PendSV - 15: SysTick + interrupt: + exception: + 2: NMI + 3: HardFault + 4: MemManage + 5: BusFault + 6: UsageFault + 11: SVCall + 14: PendSV + 15: SysTick cflags: - -mcpu=cortex-m4 diff --git a/platforms/stm32/f4.yaml b/platforms/stm32/f4.yaml index c132524..8a632f1 100644 --- a/platforms/stm32/f4.yaml +++ b/platforms/stm32/f4.yaml @@ -34,98 +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 + interrupt: + 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 |