summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConscript12
-rw-r--r--i2c/i2c.cpp10
-rw-r--r--i2c/i2c.h4
-rw-r--r--interrupt/SConscript18
-rw-r--r--interrupt/default_handlers.cpp.j219
-rw-r--r--interrupt/fault.cpp45
-rw-r--r--interrupt/interrupt.cpp159
-rw-r--r--interrupt/interrupt.h87
-rw-r--r--interrupt/interrupt_enums.h.j213
-rw-r--r--interrupt/vectors_nvic.cpp.j228
-rw-r--r--platforms/cortex-m.yaml12
-rw-r--r--platforms/stm32/f4.yaml93
12 files changed, 204 insertions, 296 deletions
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 <os/thread.h>
#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<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 %}
+};
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