GEX core repository.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
gex-core/platform/irq_dispatcher.c

506 lines
13 KiB

//
// Created by MightyPork on 2018/01/14.
//
#include "platform.h"
#include "irq_dispatcher.h"
#include "hw_utils.h"
void * const EXTIS[16] = {
// dumym values for easier debug - those are used instead of periph addresses because EXTIs have no dedicated periph control blocks
(void *const) 0x9000,
(void *const) 0x9001,
(void *const) 0x9002,
(void *const) 0x9003,
(void *const) 0x9004,
(void *const) 0x9005,
(void *const) 0x9006,
(void *const) 0x9007,
(void *const) 0x9008,
(void *const) 0x9009,
(void *const) 0x900A,
(void *const) 0x900B,
(void *const) 0x900C,
(void *const) 0x900D,
(void *const) 0x900E,
(void *const) 0x900F,
};
struct cbslot {
IrqCallback callback;
void *arg;
};
static struct callbacks_ {
struct cbslot exti[16];
struct cbslot usart1;
struct cbslot usart2;
struct cbslot usart3;
#ifdef USART4
struct cbslot usart4;
#endif
#ifdef USART5
struct cbslot usart5;
#endif
struct cbslot dma1_1;
struct cbslot dma1_2;
struct cbslot dma1_3;
struct cbslot dma1_4;
struct cbslot dma1_5;
struct cbslot dma1_6;
struct cbslot dma1_7;
struct cbslot dma1_8;
struct cbslot dma2_1;
struct cbslot dma2_2;
struct cbslot dma2_3;
struct cbslot dma2_4;
struct cbslot dma2_5;
struct cbslot dma2_6;
struct cbslot dma2_7;
struct cbslot dma2_8;
struct cbslot tim2;
struct cbslot tim6;
struct cbslot tim7;
struct cbslot tim14;
struct cbslot tim15;
struct cbslot tim16;
struct cbslot adc1;
struct cbslot tsc;
// XXX add more callbacks here when needed
} callbacks;
void irqd_init(void)
{
memset(&callbacks, 0, sizeof(callbacks));
// TODO move the priorities to some define
// NVIC_EnableIRQ(WWDG_IRQn); /*!< Window WatchDog Interrupt */
// NVIC_EnableIRQ(PVD_VDDIO2_IRQn); /*!< PVD & VDDIO2 Interrupt through EXTI Lines 16 and 31 */
// NVIC_EnableIRQ(RTC_IRQn); /*!< RTC Interrupt through EXTI Lines 17, 19 and 20 */
// NVIC_EnableIRQ(FLASH_IRQn); /*!< FLASH global Interrupt */
// NVIC_EnableIRQ(RCC_CRS_IRQn); /*!< RCC & CRS global Interrupt */
NVIC_EnableIRQ(EXTI0_1_IRQn); /*!< EXTI Line 0 and 1 Interrupt */
NVIC_EnableIRQ(EXTI2_3_IRQn); /*!< EXTI Line 2 and 3 Interrupt */
NVIC_EnableIRQ(EXTI4_15_IRQn); /*!< EXTI Line 4 to 15 Interrupt */
HAL_NVIC_SetPriority(EXTI0_1_IRQn, 2, 0);
HAL_NVIC_SetPriority(EXTI2_3_IRQn, 2, 0);
HAL_NVIC_SetPriority(EXTI4_15_IRQn, 2, 0);
NVIC_EnableIRQ(TSC_IRQn); /*!< Touch Sensing Controller Interrupts */
HAL_NVIC_SetPriority(TSC_IRQn, 2, 0);
NVIC_EnableIRQ(DMA1_Channel1_IRQn); /*!< DMA1 Channel 1 Interrupt */
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); /*!< DMA1 Channel 2 and Channel 3 Interrupt */
NVIC_EnableIRQ(DMA1_Channel4_5_6_7_IRQn); /*!< DMA1 Channel 4 to Channel 7 Interrupt */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 2, 0);
HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 2, 0);
HAL_NVIC_SetPriority(DMA1_Channel4_5_6_7_IRQn, 2, 0);
NVIC_EnableIRQ(ADC1_COMP_IRQn); /*!< ADC1 and COMP interrupts (ADC interrupt combined with EXTI Lines 21 and 22 */
HAL_NVIC_SetPriority(ADC1_COMP_IRQn, 1, 0); // ADC group completion - higher prio than DMA to let it handle the last halfword first
// NVIC_EnableIRQ(TIM1_IRQn); /*!< TIM1 global Interrupt */
NVIC_EnableIRQ(TIM2_IRQn); /*!< TIM2 global Interrupt */
HAL_NVIC_SetPriority(TIM2_IRQn, 2, 0); // Used by FCAP
// NVIC_EnableIRQ(TIM3_IRQn); /*!< TIM3 global Interrupt */
NVIC_EnableIRQ(TIM6_DAC_IRQn); /*!< TIM6 global and DAC channel underrun error Interrupt */
HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 2, 0); // Used for DAC timing
NVIC_EnableIRQ(TIM7_IRQn); /*!< TIM7 global Interrupt */
HAL_NVIC_SetPriority(TIM7_IRQn, 2, 0);// this will be for dac (?)
NVIC_EnableIRQ(TIM14_IRQn); /*used by fcap as a time reference for direct capture */ /*!< TIM14 global Interrupt */
HAL_NVIC_SetPriority(TIM14_IRQn, 2, 0);
NVIC_EnableIRQ(TIM15_IRQn); /*!< TIM15 global Interrupt */
HAL_NVIC_SetPriority(TIM15_IRQn, 2, 0); // Used by ADC
NVIC_EnableIRQ(TIM16_IRQn); /*!< TIM16 global Interrupt */
HAL_NVIC_SetPriority(TIM16_IRQn, 2, 0);
/* Tim17 is used for HAL timebase, because SysTick is used to time FreeRTOS and has the lowest priority. */
/* Tim17's priority is set to 0 in the init routine, which runs early in the startup sequence */
// NVIC_EnableIRQ(TIM17_IRQn); /*!< TIM17 global Interrupt */
// NVIC_EnableIRQ(I2C1_IRQn); /*!< I2C1 Event Interrupt & EXTI Line23 Interrupt (I2C1 wakeup) */
// NVIC_EnableIRQ(I2C2_IRQn); /*!< I2C2 Event Interrupt */
// NVIC_EnableIRQ(SPI1_IRQn); /*!< SPI1 global Interrupt */
// NVIC_EnableIRQ(SPI2_IRQn); /*!< SPI2 global Interrupt */
NVIC_EnableIRQ(USART1_IRQn); /*!< USART1 global Interrupt & EXTI Line25 Interrupt (USART1 wakeup) */
NVIC_EnableIRQ(USART2_IRQn); /*!< USART2 global Interrupt & EXTI Line26 Interrupt (USART2 wakeup) */
NVIC_EnableIRQ(USART3_4_IRQn); /*!< USART3 and USART4 global Interrupt */
HAL_NVIC_SetPriority(USART1_IRQn, 2, 0);
HAL_NVIC_SetPriority(USART2_IRQn, 2, 0);
HAL_NVIC_SetPriority(USART3_4_IRQn, 2, 0);
// NVIC_EnableIRQ(CEC_CAN_IRQn); /*!< CEC and CAN global Interrupts & EXTI Line27 Interrupt */
// NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); /*!< TIM1 Break, Update, Trigger and Commutation Interrupt */ // - handled by hal msp init
// NVIC_EnableIRQ(TIM1_CC_IRQn); /*!< TIM1 Capture Compare Interrupt */
// NVIC_EnableIRQ(USB_IRQn); /*!< USB global Interrupt & EXTI Line18 Interrupt */ // - USB IRQ is handled by the USB library
}
//void Default_Handler(void)
//{
// warn("Missing IRQHandler, ISPR[0]=0x%p", (void*)NVIC->ISPR[0]);
//}
static struct cbslot *get_slot_for_periph(void *periph)
{
struct cbslot *slot = NULL;
// --- USART ---
if (periph == USART1) slot = &callbacks.usart1;
else if (periph == USART2) slot = &callbacks.usart2;
else if (periph == USART3) slot = &callbacks.usart3;
#ifdef USART4
else if (periph == USART4) slot = &callbacks.usart4;
#endif
#ifdef USART5
else if (periph == USART5) slot = &callbacks.usart5;
#endif
else if (periph == TIM2) slot = &callbacks.tim2;
else if (periph == TIM6) slot = &callbacks.tim6;
else if (periph == TIM7) slot = &callbacks.tim7;
else if (periph == TIM14) slot = &callbacks.tim14;
else if (periph == TIM15) slot = &callbacks.tim15;
else if (periph == TIM16) slot = &callbacks.tim16;
// 17 - used by timebase
else if (periph == TSC) slot = &callbacks.tsc;
else if (periph == ADC1) slot = &callbacks.adc1;
else if (periph >= EXTIS[0] && periph <= EXTIS[15]) {
slot = &callbacks.exti[periph - EXTIS[0]];
}
// --- DMA1 ---
else if (periph == DMA1_Channel1) slot = &callbacks.dma1_1;
else if (periph == DMA1_Channel2) slot = &callbacks.dma1_2;
else if (periph == DMA1_Channel3) slot = &callbacks.dma1_3;
else if (periph == DMA1_Channel4) slot = &callbacks.dma1_4;
else if (periph == DMA1_Channel5) slot = &callbacks.dma1_5;
else if (periph == DMA1_Channel6) slot = &callbacks.dma1_6;
else if (periph == DMA1_Channel7) slot = &callbacks.dma1_7;
#ifdef DMA1_Channel8
else if (periph == DMA1_Channel7) slot = &callbacks.dma1_8;
#endif
// --- DMA2 ---
#ifdef DMA2
else if (periph == DMA2_Channel1) slot = &callbacks.dma2_1;
else if (periph == DMA2_Channel2) slot = &callbacks.dma2_2;
else if (periph == DMA2_Channel3) slot = &callbacks.dma2_3;
else if (periph == DMA2_Channel4) slot = &callbacks.dma2_4;
else if (periph == DMA2_Channel5) slot = &callbacks.dma2_5;
#ifdef DMA2_Channel6
else if (periph == DMA2_Channel6) slot = &callbacks.dma2_6;
#endif
#ifdef DMA2_Channel7
else if (periph == DMA2_Channel7) slot = &callbacks.dma2_7;
#endif
#ifdef DMA2_Channel8
else if (periph == DMA2_Channel7) slot = &callbacks.dma2_8;
#endif
#endif
else {
trap("No IRQ cb slot for periph 0x%p", periph);
}
return slot;
}
void irqd_attach(void *periph, IrqCallback callback, void *arg)
{
struct cbslot *slot = get_slot_for_periph(periph);
if (slot->callback != NULL) {
trap("Attach IRQ %p() to %p but %p() already bound", callback, periph, slot->callback);
}
slot->callback = callback;
slot->arg = arg;
}
void* irqd_detach(void *periph, IrqCallback callback)
{
void *oldArg = NULL;
struct cbslot *slot = get_slot_for_periph(periph);
if (slot->callback == callback) {
oldArg = slot->arg;
slot->callback = NULL;
slot->arg = NULL;
return oldArg;
} else {
trap("Detach IRQ %p() from %p but %p() bound instead", callback, periph, slot->callback);
}
}
#define CALL_IRQ_HANDLER(slot) do { if (slot.callback) slot.callback(slot.arg); } while (0)
// ------------ USARTS ------------
void USART1_IRQHandler(void)
{
CALL_IRQ_HANDLER(callbacks.usart1);
}
void USART2_IRQHandler(void)
{
CALL_IRQ_HANDLER(callbacks.usart2);
}
void USART3_4_IRQHandler(void)
{
// we won't check the flags here, both can be pending and it's better to let the handler deal with it
CALL_IRQ_HANDLER(callbacks.usart3);
CALL_IRQ_HANDLER(callbacks.usart4);
}
// ------------ DMA --------------
void DMA1_Channel1_IRQHandler(void)
{
CALL_IRQ_HANDLER(callbacks.dma1_1);
}
void DMA1_Channel2_3_IRQHandler(void)
{
if (LL_DMA_IsActiveFlag_GI2(DMA1)) CALL_IRQ_HANDLER(callbacks.dma1_2);
if (LL_DMA_IsActiveFlag_GI3(DMA1)) CALL_IRQ_HANDLER(callbacks.dma1_3);
}
void DMA1_Channel4_5_6_7_IRQHandler(void)
{
if (LL_DMA_IsActiveFlag_GI4(DMA1)) CALL_IRQ_HANDLER(callbacks.dma1_4);
if (LL_DMA_IsActiveFlag_GI5(DMA1)) CALL_IRQ_HANDLER(callbacks.dma1_5);
if (LL_DMA_IsActiveFlag_GI6(DMA1)) CALL_IRQ_HANDLER(callbacks.dma1_6);
if (LL_DMA_IsActiveFlag_GI7(DMA1)) CALL_IRQ_HANDLER(callbacks.dma1_7);
}
// ------------ EXTI ------------
static void fire_exti_cb(uint8_t start, uint8_t end)
{
for (int i = start; i <= end; i++) {
if (LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINES[i])) {
CALL_IRQ_HANDLER(callbacks.exti[i]);
}
}
}
void EXTI0_1_IRQHandler(void)
{
fire_exti_cb(0, 1);
}
void EXTI2_3_IRQHandler(void)
{
fire_exti_cb(2, 3);
}
void EXTI4_15_IRQHandler(void)
{
fire_exti_cb(4, 15);
}
// ------------ INTERRUPTS -------------
void TIM2_IRQHandler(void)
{
CALL_IRQ_HANDLER(callbacks.tim2);
}
void TIM6_DAC_IRQHandler(void)
{
CALL_IRQ_HANDLER(callbacks.tim6);
}
void TIM7_IRQHandler(void)
{
CALL_IRQ_HANDLER(callbacks.tim7);
}
void TIM14_IRQHandler(void)
{
CALL_IRQ_HANDLER(callbacks.tim14);
}
void TIM15_IRQHandler(void)
{
CALL_IRQ_HANDLER(callbacks.tim15);
}
void TIM16_IRQHandler(void)
{
CALL_IRQ_HANDLER(callbacks.tim16);
}
void ADC1_COMP_IRQHandler(void)
{
CALL_IRQ_HANDLER(callbacks.adc1);
}
void TSC_IRQHandler(void)
{
CALL_IRQ_HANDLER(callbacks.tsc);
}
// other ISRs...
#if 0
void WWDG_IRQHandler(void)
{
//
}
void PVD_VDDIO2_IRQHandler(void)
{
//
}
void RTC_IRQHandler(void)
{
//
}
void FLASH_IRQHandler(void)
{
//
}
void RCC_CRS_IRQHandler(void)
{
//
}
void TSC_IRQHandler(void)
{
//
}
void ADC1_COMP_IRQHandler(void)
{
//
}
void TIM1_BRK_UP_TRG_COM_IRQHandler(void)
{
//
}
void TIM1_CC_IRQHandler(void)
{
//
}
void TIM2_IRQHandler(void)
{
//
}
void TIM3_IRQHandler(void)
{
//
}
// not on F072
void TIM4_IRQHandler(void)
{
//
}
// not on F072
void TIM5_IRQHandler(void)
{
//
}
void TIM6_DAC_IRQHandler(void)
{
//
}
void TIM7_IRQHandler(void)
{
//
}
void TIM8_IRQHandler(void)
{
//
}
void TIM9_IRQHandler(void)
{
//
}
void TIM10_IRQHandler(void)
{
//
}
void TIM11_IRQHandler(void)
{
//
}
void TIM12_IRQHandler(void)
{
//
}
void TIM13_IRQHandler(void)
{
//
}
void TIM14_IRQHandler(void)
{
//
}
void TIM15_IRQHandler(void)
{
//
}
void TIM16_IRQHandler(void)
{
//
}
void TIM17_IRQHandler(void)
{
//
}
void CEC_CAN_IRQHandler(void)
{
//
}
// USB is handled by the USB driver
//void USB_IRQHandler(void)
//{
// //
//}
#endif