From e586c178073b9a0fee90d5fc8e795d266ebd7b7d Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Tue, 7 Aug 2012 16:50:46 +0200 Subject: Initial import. Most sources are split off from suzumebachi project revision 2fc77d2 as is with some path changes. New build rules introduced. --- interrupt/fault.cpp | 41 +++++++++++ interrupt/interrupt.cpp | 187 ++++++++++++++++++++++++++++++++++++++++++++++++ interrupt/interrupt.h | 151 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 379 insertions(+) create mode 100644 interrupt/fault.cpp create mode 100644 interrupt/interrupt.cpp create mode 100644 interrupt/interrupt.h (limited to 'interrupt') diff --git a/interrupt/fault.cpp b/interrupt/fault.cpp new file mode 100644 index 0000000..016b74b --- /dev/null +++ b/interrupt/fault.cpp @@ -0,0 +1,41 @@ +#include "interrupt.h" +#include +#include + +inline void __attribute__((naked)) switch_context() { + 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"); +} + +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 new file mode 100644 index 0000000..cebfed7 --- /dev/null +++ b/interrupt/interrupt.cpp @@ -0,0 +1,187 @@ +#include "interrupt.h" + +namespace Interrupt { + MFP mf_vectors[16 + NUM_IRQs]; +}; + +void entry(); + +void member_function_interrupt_gate() { + uint32_t interrupt_num; + asm ("mrs %0, ipsr" : "=r" (interrupt_num)); + + Interrupt::mf_vectors[interrupt_num].func_p(Interrupt::mf_vectors[interrupt_num].instance_p); +} + +extern "C" void unused_interrupt() { + member_function_interrupt_gate(); + //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)(); + +vector_t vectors[] __attribute__((section(".vectors"))) = { + (vector_t)0x20004ffc, + 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, + 0, // 60 + 0, // 61 + 0, // 62 + 0, // 63 + 0, // 64 + 0, // 65 + 0, // 66 + 0, // 67 + 0, // 68 + 0, // 69 + 0, // 70 + 0, // 71 + 0, // 72 + 0, // 73 + 0, // 74 + 0, // 75 + 0, // 76 + interrupt<(Interrupt::IRQ)77>, // 77 +}; diff --git a/interrupt/interrupt.h b/interrupt/interrupt.h new file mode 100644 index 0000000..80ccb76 --- /dev/null +++ b/interrupt/interrupt.h @@ -0,0 +1,151 @@ +#ifndef INTERRUPT_H +#define INTERRUPT_H + +#include + +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 { + 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); + } + + inline void set_priority(Exception n, uint8_t priority) { + SCB.SHPR[n - 4] = priority; + } + + inline void set_priority(IRQ n, uint8_t priority) { + NVIC.IPR[n] = priority; + } + + struct MFP { + void (*func_p)(void*); + void* instance_p; + }; + + extern MFP mf_vectors[]; + + template + inline void set_handler(IRQ n, void (T::*f)(), T* i) { + MFP& mfp = mf_vectors[16 + n]; + mfp.func_p = reinterpret_cast(f); + mfp.instance_p = i; + } + + template + inline void enable(IRQ n, void (T::*f)(), T* i) { + set_handler(n, f, i); + enable(n); + } +}; + +template +void interrupt(); + +template +void interrupt(); + +#endif -- cgit v1.2.3