Line 47... |
Line 47... |
* The >private< trap vector look-up table of the XIRQ.
|
* The >private< trap vector look-up table of the XIRQ.
|
**************************************************************************/
|
**************************************************************************/
|
static uint32_t __neorv32_xirq_vector_lut[32] __attribute__((unused)); // trap handler vector table
|
static uint32_t __neorv32_xirq_vector_lut[32] __attribute__((unused)); // trap handler vector table
|
|
|
// private functions
|
// private functions
|
static void __attribute__((aligned(16))) __attribute__((unused)) __neorv32_xirq_core(void);
|
static void __attribute__((aligned(16))) __neorv32_xirq_core(void);
|
static void __attribute__((unused)) __neorv32_xirq_dummy_handler(void);
|
static void __neorv32_xirq_dummy_handler(void);
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Check if external interrupt controller was synthesized.
|
* Check if external interrupt controller was synthesized.
|
*
|
*
|
* @return 0 if XIRQ was not synthesized, 1 if EXTIRQ is available.
|
* @return 0 if XIRQ was not synthesized, 1 if EXTIRQ is available.
|
**************************************************************************/
|
**************************************************************************/
|
int neorv32_xirq_available(void) {
|
int neorv32_xirq_available(void) {
|
|
|
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_IO_XIRQ)) {
|
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_IO_XIRQ)) {
|
return 1;
|
return 1;
|
}
|
}
|
else {
|
else {
|
return 0;
|
return 0;
|
}
|
}
|
Line 76... |
Line 76... |
* handler addresses will be deleted.
|
* handler addresses will be deleted.
|
* @return 0 if success, 1 if error.
|
* @return 0 if success, 1 if error.
|
**************************************************************************/
|
**************************************************************************/
|
int neorv32_xirq_setup(void) {
|
int neorv32_xirq_setup(void) {
|
|
|
XIRQ_IER = 0; // disable all input channels
|
NEORV32_XIRQ.IER = 0; // disable all input channels
|
XIRQ_IPR = 0xffffffff; // clear/ack all pending IRQs
|
NEORV32_XIRQ.IPR = 0; // clear all pending IRQs
|
|
|
int i;
|
int i;
|
for (i=0; i<32; i++) {
|
for (i=0; i<32; i++) {
|
__neorv32_xirq_vector_lut[i] = (uint32_t)(&__neorv32_xirq_dummy_handler);
|
__neorv32_xirq_vector_lut[i] = (uint32_t)(&__neorv32_xirq_dummy_handler);
|
}
|
}
|
|
|
// register XIRQ handler in RTE
|
// register XIRQ handler in NEORV32 RTE
|
return neorv32_rte_exception_install(XIRQ_RTE_ID, __neorv32_xirq_core);
|
return neorv32_rte_exception_install(XIRQ_RTE_ID, __neorv32_xirq_core);
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
Line 122... |
Line 122... |
int i, cnt;
|
int i, cnt;
|
|
|
if (neorv32_xirq_available()) {
|
if (neorv32_xirq_available()) {
|
|
|
neorv32_cpu_irq_disable(XIRQ_FIRQ_ENABLE); // make sure XIRQ cannot fire
|
neorv32_cpu_irq_disable(XIRQ_FIRQ_ENABLE); // make sure XIRQ cannot fire
|
XIRQ_IER = 0xffffffff; // try to set all enable flags
|
NEORV32_XIRQ.IER = 0xffffffff; // try to set all enable flags
|
enable = XIRQ_IER; // read back actually set flags
|
enable = NEORV32_XIRQ.IER; // read back actually set flags
|
|
|
// count set bits in enable
|
// count set bits in enable
|
cnt = 0;
|
cnt = 0;
|
for (i=0; i<32; i++) {
|
for (i=0; i<32; i++) {
|
if (enable & 1) {
|
if (enable & 1) {
|
Line 142... |
Line 142... |
}
|
}
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
|
* Clear pending interrupt.
|
|
*
|
|
* @param[in] ch XIRQ interrupt channel (0..31).
|
|
**************************************************************************/
|
|
void neorv32_xirq_clear_pending(uint8_t ch) {
|
|
|
|
if (ch < 32) { // channel valid?
|
|
NEORV32_XIRQ.IPR = ~(1 << ch);
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Enable IRQ channel.
|
|
*
|
|
* @param[in] ch XIRQ interrupt channel (0..31).
|
|
**************************************************************************/
|
|
void neorv32_xirq_channel_enable(uint8_t ch) {
|
|
|
|
if (ch < 32) { // channel valid?
|
|
NEORV32_XIRQ.IER |= 1 << ch;
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Disable IRQ channel.
|
|
*
|
|
* @param[in] ch XIRQ interrupt channel (0..31).
|
|
**************************************************************************/
|
|
void neorv32_xirq_channel_disable(uint8_t ch) {
|
|
|
|
if (ch < 32) { // channel valid?
|
|
NEORV32_XIRQ.IER &= ~(1 << ch);
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
* Install exception handler function for XIRQ channel.
|
* Install exception handler function for XIRQ channel.
|
*
|
*
|
* @note This will also activate the according XIRQ channel and clear a pending IRQ at this channel.
|
* @note This will also activate the according XIRQ channel and clear a pending IRQ at this channel.
|
*
|
*
|
* @param[in] ch XIRQ interrupt channel (0..31).
|
* @param[in] ch XIRQ interrupt channel (0..31).
|
Line 156... |
Line 195... |
|
|
// channel valid?
|
// channel valid?
|
if (ch < 32) {
|
if (ch < 32) {
|
__neorv32_xirq_vector_lut[ch] = (uint32_t)handler; // install handler
|
__neorv32_xirq_vector_lut[ch] = (uint32_t)handler; // install handler
|
uint32_t mask = 1 << ch;
|
uint32_t mask = 1 << ch;
|
XIRQ_IPR = mask; // clear if pending
|
NEORV32_XIRQ.IPR = ~mask; // clear if pending
|
XIRQ_IER |= mask; // enable channel
|
NEORV32_XIRQ.IER |= mask; // enable channel
|
return 0;
|
return 0;
|
}
|
}
|
return 1;
|
return 1;
|
}
|
}
|
|
|
Line 178... |
Line 217... |
|
|
// channel valid?
|
// channel valid?
|
if (ch < 32) {
|
if (ch < 32) {
|
__neorv32_xirq_vector_lut[ch] = (uint32_t)(&__neorv32_xirq_dummy_handler); // override using dummy handler
|
__neorv32_xirq_vector_lut[ch] = (uint32_t)(&__neorv32_xirq_dummy_handler); // override using dummy handler
|
uint32_t mask = 1 << ch;
|
uint32_t mask = 1 << ch;
|
XIRQ_IER &= ~mask; // disable channel
|
NEORV32_XIRQ.IER &= ~mask; // disable channel
|
XIRQ_IPR = mask; // clear if pending
|
NEORV32_XIRQ.IPR = ~mask; // clear if pending
|
return 0;
|
return 0;
|
}
|
}
|
return 1;
|
return 1;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* This is the actual second-level IRQ handler for the XIRQ. It will call the previously installed handler
|
* This is the actual second-level (F)IRQ handler for the XIRQ. It will
|
* if an XIRQ fires.
|
* call the previously installed handler if an XIRQ fires.
|
*
|
|
* @note This function must no be used by the user.
|
|
**************************************************************************/
|
**************************************************************************/
|
static void __attribute__((aligned(16))) __attribute__((unused)) __neorv32_xirq_core(void) {
|
static void __attribute__((aligned(16))) __neorv32_xirq_core(void) {
|
|
|
register uint32_t src = XIRQ_SCR; // get IRQ source (with highest priority)
|
register uint32_t src = NEORV32_XIRQ.SCR; // get IRQ source (with highest priority)
|
src &= 0x1f;
|
|
|
|
XIRQ_IPR = (uint32_t)(1 << src); // acknowledge pending interrupt
|
uint32_t mask = 1 << src;
|
|
NEORV32_XIRQ.IPR = ~mask; // clear current pending interrupt
|
|
NEORV32_XIRQ.SCR = 0; // acknowledge current interrupt (CPU FIRQ)
|
|
|
// execute handler
|
// execute handler
|
register uint32_t xirq_handler = __neorv32_xirq_vector_lut[src];
|
register uint32_t xirq_handler = __neorv32_xirq_vector_lut[src];
|
void (*handler_pnt)(void);
|
void (*handler_pnt)(void);
|
handler_pnt = (void*)xirq_handler;
|
handler_pnt = (void*)xirq_handler;
|
Line 210... |
Line 248... |
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* XIRQ dummy handler.
|
* XIRQ dummy handler.
|
**************************************************************************/
|
**************************************************************************/
|
static void __attribute__((unused)) __neorv32_xirq_dummy_handler(void) {
|
static void __neorv32_xirq_dummy_handler(void) {
|
|
|
asm volatile ("nop");
|
asm volatile ("nop");
|
}
|
}
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|