Skip to content

Commit

Permalink
soc/software: add irq_attach() / irq_detach()
Browse files Browse the repository at this point in the history
cleaner mechanism for other software to use interrupts

NOTE: uart_isr(void) not changed to uart_isr(int) for compatibility
with cpus that don't implement this interface yet.
  • Loading branch information
Andrew Dennison committed Oct 27, 2023
1 parent 7006b49 commit e0408d3
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 9 deletions.
15 changes: 15 additions & 0 deletions litex/soc/software/include/irq.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once
#include_next<irq.h>

typedef void (*isr_t)(int);

#ifdef __cplusplus
extern "C" {
#endif

extern int irq_attach(unsigned int irq, isr_t isr) __attribute__((weak));
extern int irq_detach(unsigned int irq) __attribute__((weak));

#ifdef __cplusplus
}
#endif
46 changes: 37 additions & 9 deletions litex/soc/software/libbase/isr.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,18 +191,46 @@ void isr(void)
}

#else
void isr(void)
#define NR_IRQ 32
struct irq_table
{
__attribute__((unused)) unsigned int irqs;
void (*isr)(int);
} irq_table[NR_IRQ];

irqs = irq_pending() & irq_getmask();
int irq_attach(unsigned int irq, void (*isr)(int))
{
if (irq >= NR_IRQ) {
printf("Inv irq %d\n", irq);
return -1;
}

#ifdef CSR_UART_BASE
#ifndef UART_POLLING
if(irqs & (1 << UART_INTERRUPT))
uart_isr();
#endif
#endif
unsigned int ie = irq_getie();
irq_setie(0);
irq_table[irq].isr = isr;
irq_setie(ie);
return irq;
}

int irq_detach(unsigned int irq)
{
return irq_attach(irq, NULL);
}

void isr(void)
{
unsigned int irqs = irq_pending() & irq_getmask();

while (irqs)
{
const unsigned int irq = __builtin_ctz(irqs);
if (irq_table[irq].isr)
irq_table[irq].isr(irq);
else {
irq_setmask(irq_getmask() & ~(1<<irq));
printf("\n*** disabled spurious irq %d ***\n", irq);
}
irqs &= irqs - 1; // clear this irq (the first bit set)
}
}
#endif

Expand Down
2 changes: 2 additions & 0 deletions litex/soc/software/libbase/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ void uart_init(void)

uart_ev_pending_write(uart_ev_pending_read());
uart_ev_enable_write(UART_EV_TX | UART_EV_RX);
if (irq_attach)
irq_attach(UART_INTERRUPT, (isr_t)uart_isr);
irq_setmask(irq_getmask() | (1 << UART_INTERRUPT));
}

Expand Down

0 comments on commit e0408d3

Please sign in to comment.