diff --git a/lib/interrupt.c b/lib/interrupt.c new file mode 100644 index 0000000..244f9a4 --- /dev/null +++ b/lib/interrupt.c @@ -0,0 +1,120 @@ +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** BusVoodoo runtime interrupt table + * @file + * @author King Kévin + * @date 2018 + */ +#include "interrupt.h" // own definitions + +vector_table_entry_t interrupt_table[NVIC_IRQ_COUNT] = {0}; + +/** handler intercepting interrupts and running the function provided in the table */ +static void isr_handler(void) +{ + // get current IRQ number + uint8_t irq = 0; + if (NVIC_IABR(0)) { + irq = __builtin_ffs(NVIC_IABR(0))-1; + } else if (NVIC_IABR(1)) { + irq = __builtin_ffs(NVIC_IABR(1))+31; + } else if (NVIC_IABR(2)) { + irq = __builtin_ffs(NVIC_IABR(2))+64; + } else { + while (true); + } + // check if the it's a valid IRQ number + if (irq >= NVIC_IRQ_COUNT) { + while (true); + } + // run user provided ISR + if (interrupt_table[irq]) { + (*(void(*)(void))(interrupt_table[irq]))(); + } else { + while (true); + } +} + +/** use the isr_handler as default ISR + * @note the ISR can still point to other defined function + * @remark from libopencm3/stm32/f1/vector_nvic.c + */ +#pragma weak wwdg_isr = isr_handler +#pragma weak pvd_isr = isr_handler +#pragma weak tamper_isr = isr_handler +#pragma weak rtc_isr = isr_handler +#pragma weak flash_isr = isr_handler +#pragma weak rcc_isr = isr_handler +#pragma weak exti0_isr = isr_handler +#pragma weak exti1_isr = isr_handler +#pragma weak exti2_isr = isr_handler +#pragma weak exti3_isr = isr_handler +#pragma weak exti4_isr = isr_handler +#pragma weak dma1_channel1_isr = isr_handler +#pragma weak dma1_channel2_isr = isr_handler +#pragma weak dma1_channel3_isr = isr_handler +#pragma weak dma1_channel4_isr = isr_handler +#pragma weak dma1_channel5_isr = isr_handler +#pragma weak dma1_channel6_isr = isr_handler +#pragma weak dma1_channel7_isr = isr_handler +#pragma weak adc1_2_isr = isr_handler +#pragma weak usb_hp_can_tx_isr = isr_handler +#pragma weak usb_lp_can_rx0_isr = isr_handler +#pragma weak can_rx1_isr = isr_handler +#pragma weak can_sce_isr = isr_handler +#pragma weak exti9_5_isr = isr_handler +#pragma weak tim1_brk_isr = isr_handler +#pragma weak tim1_up_isr = isr_handler +#pragma weak tim1_trg_com_isr = isr_handler +#pragma weak tim1_cc_isr = isr_handler +#pragma weak tim2_isr = isr_handler +#pragma weak tim3_isr = isr_handler +#pragma weak tim4_isr = isr_handler +#pragma weak i2c1_ev_isr = isr_handler +#pragma weak i2c1_er_isr = isr_handler +#pragma weak i2c2_ev_isr = isr_handler +#pragma weak i2c2_er_isr = isr_handler +#pragma weak spi1_isr = isr_handler +#pragma weak spi2_isr = isr_handler +#pragma weak usart1_isr = isr_handler +#pragma weak usart2_isr = isr_handler +#pragma weak usart3_isr = isr_handler +#pragma weak exti15_10_isr = isr_handler +#pragma weak rtc_alarm_isr = isr_handler +#pragma weak usb_wakeup_isr = isr_handler +#pragma weak tim8_brk_isr = isr_handler +#pragma weak tim8_up_isr = isr_handler +#pragma weak tim8_trg_com_isr = isr_handler +#pragma weak tim8_cc_isr = isr_handler +#pragma weak adc3_isr = isr_handler +#pragma weak fsmc_isr = isr_handler +#pragma weak sdio_isr = isr_handler +#pragma weak tim5_isr = isr_handler +#pragma weak spi3_isr = isr_handler +#pragma weak uart4_isr = isr_handler +#pragma weak uart5_isr = isr_handler +#pragma weak tim6_isr = isr_handler +#pragma weak tim7_isr = isr_handler +#pragma weak dma2_channel1_isr = isr_handler +#pragma weak dma2_channel2_isr = isr_handler +#pragma weak dma2_channel3_isr = isr_handler +#pragma weak dma2_channel4_5_isr = isr_handler +#pragma weak dma2_channel5_isr = isr_handler +#pragma weak eth_isr = isr_handler +#pragma weak eth_wkup_isr = isr_handler +#pragma weak can2_tx_isr = isr_handler +#pragma weak can2_rx0_isr = isr_handler +#pragma weak can2_rx1_isr = isr_handler +#pragma weak can2_sce_isr = isr_handler +#pragma weak otg_fs_isr = isr_handler diff --git a/lib/interrupt.h b/lib/interrupt.h new file mode 100644 index 0000000..c3c40bf --- /dev/null +++ b/lib/interrupt.h @@ -0,0 +1,26 @@ +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** BusVoodoo runtime interrupt table + * @file + * @author King Kévin + * @date 2018 + */ +#pragma once +#include "libopencm3/cm3/nvic.h" +#include "libopencm3/cm3/vector.h" + +/** table of interrupts which can set to user functions + * @note only interrupt using the default handler can be intercepted + */ +extern vector_table_entry_t interrupt_table[NVIC_IRQ_COUNT];