From 737ced8fa6ab0cfd0e139e0fd9d3a09cb404f4ab Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Mon, 13 Nov 2023 12:07:35 +1100 Subject: [PATCH] soc/software: add irq_attach() / irq_detach() cleaner mechanism for other software to use interrupts --- litex/soc/integration/soc.py | 1 + litex/soc/software/include/irq.h | 15 +++++++++++ litex/soc/software/libbase/isr.c | 45 ++++++++++++++++++++++++------- litex/soc/software/libbase/uart.c | 2 ++ 4 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 litex/soc/software/include/irq.h diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index fee8de48c..d12c27c23 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1320,6 +1320,7 @@ class SoC(LiteXModule, SoCCoreCompat): # SoC IRQ Interconnect --------------------------------------------------------------------- if hasattr(self, "cpu") and hasattr(self.cpu, "interrupt"): + self.add_constant("NR_IRQ", max(self.irq.locs.values()) + 1) for name, loc in sorted(self.irq.locs.items()): if name in self.cpu.interrupts.keys(): continue diff --git a/litex/soc/software/include/irq.h b/litex/soc/software/include/irq.h new file mode 100644 index 000000000..fa7a1411b --- /dev/null +++ b/litex/soc/software/include/irq.h @@ -0,0 +1,15 @@ +#pragma once +#include_next + +typedef void (*isr_t)(void); + +#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 diff --git a/litex/soc/software/libbase/isr.c b/litex/soc/software/libbase/isr.c index ac7a7920c..6c052b2d7 100644 --- a/litex/soc/software/libbase/isr.c +++ b/litex/soc/software/libbase/isr.c @@ -191,18 +191,45 @@ void isr(void) } #else +struct irq_table +{ + isr_t isr; +} irq_table[NR_IRQ]; + +int irq_attach(unsigned int irq, isr_t isr) +{ + if (irq >= NR_IRQ) { + printf("Inv irq %d\n", irq); + return -1; + } + + 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) { - __attribute__((unused)) unsigned int irqs; + unsigned int irqs = irq_pending() & irq_getmask(); - irqs = irq_pending() & irq_getmask(); - -#ifdef CSR_UART_BASE -#ifndef UART_POLLING - if(irqs & (1 << UART_INTERRUPT)) - uart_isr(); -#endif -#endif + while (irqs) + { + const unsigned int irq = __builtin_ctz(irqs); + if (irq < NR_IRQ && irq_table[irq].isr) + irq_table[irq].isr(); + else { + irq_setmask(irq_getmask() & ~(1<