summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2021-01-22 01:13:44 +0100
committerVegard Storheil Eriksen <zyp@jvnv.net>2021-01-22 01:13:44 +0100
commit1a38973eb8fd0f889f7c272e9ef183687034d550 (patch)
treea673e3eda50ee3ec1edbaf7534fafdd7073d1b47
parent36efee9187390a52a99919b900b8faaea49be928 (diff)
interrupt: Refactor to be more flexible.
-rw-r--r--interrupt/SConscript29
-rw-r--r--interrupt/default_handlers.cpp.j212
-rw-r--r--interrupt/interrupt.h58
-rw-r--r--interrupt/interrupt_enums.h.j220
-rw-r--r--interrupt/nvic.h52
-rw-r--r--interrupt/vectors_nvic.cpp.j222
-rw-r--r--platforms/cortex-m.yaml24
-rw-r--r--platforms/stm32/f4.yaml185
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