elbear_arduino_bsp/cores/arduino/WInterrupts.c

124 lines
3.2 KiB
C

#include <inttypes.h>
#include "mik32_hal_irq.h"
#include "pins_arduino.h"
#include "wiring_digital.h"
#include "WInterrupts.h"
#include "wiring_LL.h"
typedef void (*voidFuncPtr)(void);
// empty irq handler
static void nothing(void)
{
;
}
// enable global interrupts
void interrupts(void)
{
GLOBAL_IRQ_ENABLE();
}
// disable global interrupts
void noInterrupts(void)
{
GLOBAL_IRQ_DISABLE();
}
// we can provide no more than 8 interrupts on gpio at the same time
static volatile voidFuncPtr intFunc[EXTERNAL_INTERRUPTS_QTY] =
{
#if EXTERNAL_INTERRUPTS_QTY > 7
nothing,
#endif
#if EXTERNAL_INTERRUPTS_QTY > 6
nothing,
#endif
#if EXTERNAL_INTERRUPTS_QTY > 5
nothing,
#endif
#if EXTERNAL_INTERRUPTS_QTY > 4
nothing,
#endif
#if EXTERNAL_INTERRUPTS_QTY > 3
nothing,
#endif
#if EXTERNAL_INTERRUPTS_QTY > 2
nothing,
#endif
nothing,
nothing,
};
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)
{
// if the interrupt number does not exceed the total number
if(interruptNum < EXTERNAL_INTERRUPTS_QTY)
{
intFunc[interruptNum] = userFunc; // save pointer to irq handler
// init pin as input without pullups
pinMode(interruptToDigitalPin(interruptNum), INPUT);
// interrupt line initialization
HAL_GPIO_InterruptMode halMode;
if (mode == LOW) halMode = GPIO_INT_MODE_LOW;
else if (mode == HIGH) halMode = GPIO_INT_MODE_HIGH;
else if (mode == CHANGE) halMode = GPIO_INT_MODE_CHANGE;
else if (mode == FALLING) halMode = GPIO_INT_MODE_FALLING;
else if (mode == RISING) halMode = GPIO_INT_MODE_RISING;
else return;
HAL_GPIO_InitInterruptLine(interruptToGpioIntMux(interruptNum), halMode);
// turn on the mask in EPIC
if ((halMode == GPIO_INT_MODE_LOW) || (halMode == GPIO_INT_MODE_HIGH))
// by level
HAL_EPIC_MaskLevelSet(HAL_EPIC_GPIO_IRQ_MASK);
else
// by edge
HAL_EPIC_MaskEdgeSet(HAL_EPIC_GPIO_IRQ_MASK);
}
else
ErrorMsgHandler("attachInterrupt(): incorrect interrupt number\n\r");
}
void detachInterrupt(uint8_t interruptNum)
{
if(interruptNum < EXTERNAL_INTERRUPTS_QTY)
{
// disable the interrupt in line
HAL_GPIO_DeInitInterruptLine(interruptToGpioIntLine(interruptNum));
intFunc[interruptNum] = nothing;
// we don't change anything in the EPIC controller, in case there are still configured lines left
}
}
// disable single interrupt
void disableInterrupt(uint8_t interruptNum)
{
if(interruptNum < EXTERNAL_INTERRUPTS_QTY)
// disable gpio interrupt line
GPIO_IRQ_LINE_DISABLE(interruptToGpioIntLine(interruptNum));
}
// enable single interrupt
void enableInterrupt(uint8_t interruptNum)
{
if(interruptNum < EXTERNAL_INTERRUPTS_QTY)
// enable gpio interrupt line
GPIO_IRQ_LINE_ENABLE(interruptToGpioIntLine(interruptNum));
}
// common gpio interrupt handler
void __attribute__((noinline, section(".ram_text"), optimize("O3"))) gpio_interrupt_handler(void)
{
// go through all the interrupts and call the handler for the triggered line
for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++)
{
if (GPIO_IRQ_LINE_STATE(interruptToGpioIntLine(i)))
intFunc[i]();
}
GPIO_IRQ_CLEAR_ALL();
}