Hello
I'm quite a beginner with development of drivers for R52.
I just want, for trials purpose, to write a C interrupt handler (EL1) for some peripheral.
I wrote a very simple "hello world" style and managed to trigger it when my peripheral sends an interruptions to the R52 virtual model.
But now, I would like to know how to clear my interrupt from my C handler, because I do not know which registers must be written and in which order. Could
you please tell me what I have to do to clear my SPI interrupt ?
Best Regards
Frederic
I know you didn't ask about virtualization, but this guide might be useful: Armv8-R virtualizationThe guide includes a description of the GIC and some examples are how it is used.But to try to answer your direct question:On entry to the interrupt handler you'd need to read ICC_IAR0/1 (ICC_IAR0 for FIQs, ICC_IAR1 for IRQs). That acknowledges receipt of the interrupt, returning the INTID to software and updating the interrupt's state in the GIC.Depending on what the interrupt is, you might then need to access the peripheral to clear the interrupt signal. That's going to entirely depend on what the interrupt source is, and whether it's edge or level signalled.
Then, you would write ICC_EOIR0/1 (with the INTID returned earlier) to tell the GIC you'd finishing handling that instance of that interrupt. That updates the interrupt state again, and updates the running priority of the CPU.Note: I'm assuming you have not set EOImode to 1. Otherwise you'd need to write ICC_EOIR0/1 and ICC_DIR.
Hello Martin
many thanks for your quick and clear answer ! I understood. Nevertheless, I have another question: in my C routine, do I not have to clear the register GICD_ICACTIVER (at least, the one matching my INTID) so that I explicitly clean the status of the interrupt ?
Only in-directly.Assuming that you have ICC_CTLR.EOImode=0 (which from memory is the default), then writing ICC_EOIR0/1 will cause the active state of the interrupt to be cleared, which will be reflected in GICx_ICACTIVERn. Now if you write ICC_EOIR0/1 then read GICx_ICACTIVERn, you will need barriers to guarantee the effect of the deactivate has propagated to the GIC. But generally, I wouldn't you to need to do that.If you have ICC_CTLR.EOImode=1, then the equivalent step is performed by writing ICC_DIR
Crystal clear ! many thanks
I have another question : when the interruption active state has been cleared, what happens to the value of the register ICC_IAR ?
When returning from my C interrupt routine, the assembly code tries to check the INTID in this register to check if there is any other pending interrupt ...
Does this mean that if there is no other interrupts, the SPI wire which has been handled comes back to 0 and then INTID value is becoming 0x3FF (spurious INT) ?
A read of ICC_IAR0/1 returns the HPPI (highest priority pending interrupt) if there is one which is signal-able, or Spurious/1023. Only an interrupt which is in the Pending state can be selected as HPPI (and by "Pending" I mean the state as defined in the GIC's state machine).For scenario, what we have to think of which interrupts are in the "Pending" state at what times.Let's say you have a device generating a level-sensitive interrupt. At some point the wire was asserted, the INTID was set as Pending and the INTID became the HPPI. You took the exception and read IAR. When you read IAR, that INTID became Active (or Active + Pending) meaning the GIC can't send more instances of that interrupt. Later, writing EOIR (or DIR) clears the Active state. So the question becomes: is the device still asserting (or asserting again) the interrupt wire into the GIC? If no, the INTID will not be Pending and therefore can't be the HPPI. If yes, then INTID will be Pending and might be selected as HPPI. I say "might" because there could be other interrupts around as well.
This doc is for A-profile, but the concepts are the same:Learn the architecture: Arm Generic Interrupt Controller v3 and v4 Version 3.2There's a longer description of the above with some diagrams.