From 15b3d932a4e8e068b824f1b3eabb6d1fcc0de104 Mon Sep 17 00:00:00 2001 From: Robert Szczepanski Date: Tue, 9 Feb 2021 15:29:31 +0100 Subject: [PATCH] gpio: add support for interrupts on GPIOIn --- litex/soc/cores/gpio.py | 46 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/litex/soc/cores/gpio.py b/litex/soc/cores/gpio.py index 3de711dd5..73e0d15c0 100644 --- a/litex/soc/cores/gpio.py +++ b/litex/soc/cores/gpio.py @@ -10,18 +10,62 @@ from migen.genlib.cdc import MultiReg from litex.soc.interconnect.csr import * +from litex.soc.interconnect.csr_eventmanager import * + +from enum import Enum + # Helpers ------------------------------------------------------------------------------------------ def _to_signal(obj): return obj.raw_bits() if isinstance(obj, Record) else obj +class IRQ_Type(Enum): + NO_IRQ = 0 + RISING_EDGE = 1 + FALLING_EDGE = 2 + # GPIO Input --------------------------------------------------------------------------------------- class GPIOIn(Module, AutoCSR): - def __init__(self, pads): + """GPIO Input + + Parameters / Attributes + ----------------------- + pads : Object + GPIO Input pads description. + + irq : list of IRQ_Type (optional) + List containing IRQ types for each pad. It can take values supported by IRQ_Type Enum. + + Example use: + irq = [IRQ_Type.NO_IRQ, IRQ_Type.NO_IRQ, IRQ_Type.FALLING_EDGE, IRQ_Type.RISING_EDGE] + This adds interrupts on pins 2 (falling edge) and 3 (rising edge). + """ + def __init__(self, pads, irq=None): pads = _to_signal(pads) self._in = CSRStatus(len(pads), description="GPIO Input(s) Status.") self.specials += MultiReg(pads, self._in.status) + + if irq: + assert(len(irq) <= len(pads)) + self.submodules.ev = EventManager() + + irq_no = [] + for i, irq_type in enumerate(irq): + assert(irq_type, IRQ_Type) + name = "pin" + str(i) + if irq_type == IRQ_Type.RISING_EDGE: + setattr(self.ev, name, EventSourcePulse()) + irq_no.append(i) + elif irq_type == IRQ_Type.FALLING_EDGE: + setattr(self.ev, name, EventSourceProcess()) + irq_no.append(i) + + self.ev.finalize() + + sources_u = [v for k, v in xdir(self.ev, True) if isinstance(v, (EventSourcePulse, EventSourceProcess))] + for i, source in enumerate(sources_u): + self.comb += source.trigger.eq(pads[irq_no[i]]) # GPIO Output --------------------------------------------------------------------------------------