cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
mrbietola
Scholar
Scholar
731 Views
Registered: ‎05-31-2012

Clear Interrupt GIC needed?

Hi all, i'm porting a design from Microblaze Zynq Mpsoc.

I need to disable some interrupts, modify the handler and enable again.

I use to do these operations on Intc controller, i want to figure out the best options with GIC now. This is an example for a VDMA.

XIntc_Disable(VDMA_Interrupt)

XAxiVdma_IntrDisable(VDMA_Interrupt)

XAxiVdma_IntrClear(VDMA_Interrupt)

XIntc_Acknowledge(VDMA_Interrupt)

 

I haven't found an Acknowledge function for GIC. Is this not needed anymore? Should i only disable the interrupt with XScuGic_Disable?

I used to clear the interrupt because with the disable function the interrupt is still hold by the controller even if not fired.

I found people asked for something similar and they get

IntIDFull = XScuGic_CPUReadReg(&ScuGic, XSCUGIC_INT_ACK_OFFSET);
XScuGic_CPUWriteReg(&ScuGic, XSCUGIC_EOI_OFFSET, IntIDFull);

But it's not clear what this code do, i think it clears the most priority pending interrupt, i want to clear only my just disabled interrupts.

Any suggestion?

 

 

 

0 Kudos
10 Replies
derekm_
Voyager
Voyager
721 Views
Registered: ‎01-16-2019

Are you disabling interrupts after the interrupt is triggered? In your handler? What you 're trying to do is a little unclear.

A general answer is that you don't need to disable interrupts in Zynq when an interrupt is being handled. In Arm technology, when an (IRQ) interrupt is being handled, the "I" bit in the CPSR is set, meaning that further interrupts are ignored until you finish handing the current one. (Interrupts are not discarded, they will just be handled in turn.) [Also assumes that you are not using nested interrupts. I'm sure you're not here.]

Generally, in your handler you just need to clear the interrupt and handle the interrupt. When the handler function ends, your system will go back to normal.

0 Kudos
mrbietola
Scholar
Scholar
711 Views
Registered: ‎05-31-2012

@derekm_  thanks for reply,

I want to disable an interrupt (in my example the VDMA), change the handler function (the callback function to be precise) and enable the interrupt again.

I thought the required steps are: 

1)disable interrupt at controller

2)disable interrupt at peripheral(VDMA)

3)clear pending interrupt at peripheral(if any)

4)clear pending interrupt at controller(if any)

5)enable interrupt at peripheral

6)enable interrupt at controller

in this way i have a clear transition and i'm not risking that an old interrupt can be fired

With GIC i don't know how to achieve this since there is no ack function for a certain interrupt source.

Hope it's more clear now

0 Kudos
derekm_
Voyager
Voyager
684 Views
Registered: ‎01-16-2019

Okay, I see what you mean now. I don't know much about that peripheral, so I will just talk about the GIC. First of all, you can find XScuGic_Disconnect() , XScuGic_Connect() , XScuGic_Enable() and XScuGic_Disable() in xscugic.c. That file is in libsrc/scugic_XvX in the BSP. I think the _Disconnect() function will also disable the interrupt, but check through the comments in the file to be sure. If not, just use _Disable() as well.

Then, to clear any pending interrupts for your peripheral in the GIC, you should be able to write to the Clear-Pending register, using a mask for the peripheral interrupt ID. See page 1469 of the Zynq TRM, UG585. Use the XScuGic_DistWriteReg() function for this. The RegOffset is found in xscugic_hw.h, and is XSCUGIC_PENDING_CLR_OFFSET for this register (plus an offset of +4 or +8 depending on your interrupt ID).

Something like the following should work:

XScuGic_Disconnect() // May need XScuGic_Disable() as well
XScuGic_DistWriteReg(*inst,XSCUGIC_PENDING_CLR_OFFSET, YOUR_ID_MASK) // Clear pending interrupts
// Do peripheral specific stuff now
// ...
// ...
XScuGic_Connect()// Connect the new handler
XScuGic_Enable() // Re-enable the interrupt.
 

 

I'm speaking quite generally there, as I've never had to switch a handler dynamically in Zynq, but see how you get on with this. Also let me know your peripheral interrupt ID, if you're unsure of the location in Clear-Pending registers, and I'll tell you what it is.

derekm_
Voyager
Voyager
678 Views
Registered: ‎01-16-2019

Another thing: maybe you need to disable you VDMA interrupt(s) first before running the above sequence. In fact, you might have to experiment a little bit with the overall sequence to ensure there are no race conditions.

0 Kudos
mrbietola
Scholar
Scholar
670 Views
Registered: ‎05-31-2012

Hi @derekm_ ,

yes you understand what i'm trying to do. 

I would like to point out that i'm using RPU GIC for Zynq MPSoc, not Zynq.

The procedure you pointed out makes sense but i would like a Xilinx confirmation since they are not mentioned in the Zynq Mpsoc reference manual.

 

0 Kudos
derekm_
Voyager
Voyager
659 Views
Registered: ‎01-16-2019

Apologies, I missed the MPSoC part! But the RPU in MPSoC uses the same GIC as used in the Zynq-7000, so the instructions should be valid anyway (pending Xilinx confirmation, if that's what you need).

-DerekM

0 Kudos
mrbietola
Scholar
Scholar
652 Views
Registered: ‎05-31-2012

@derekm_  i will tryanyway  your solution

the interrupt is number 142, 141 , 140

so for example if i need the interrupt 142 to be cleared i call the function with

n= 142/32= 4

bit_number= 142 mod 32 = 14

XScuGic_DistWriteReg(*inst,XSCUGIC_PENDING_CLR_OFFSET+(4*n), bit_number) 

 

is it right?

thanks

0 Kudos
derekm_
Voyager
Voyager
634 Views
Registered: ‎01-16-2019

Going by the Zynq GIC (which only has 96 interrupts), I think your calculation is correct. So for ID 142 = 14, you should write 0x0000_2000 to the specific Clear-Pending register. The register is of type write-one-clear (W1C) , so you don't have to do anything else. For all three IDs I guess you can clear all three pending interrupts simultaneously i.e. write 0x0000_3800 (but I'm guessing!).

0 Kudos
mrbietola
Scholar
Scholar
628 Views
Registered: ‎05-31-2012

sorry @derekm_ to bother you, shouldn't be  0x0000_4000  for bit 14?  I think should count from 0  (for example interrupt 128   -> 128 mod 32 = 0 i would write 0x0000_0001)

and for the guessing part, since i'm using these Zynq Mpsoc i have to guess a lot

derekm_
Voyager
Voyager
623 Views
Registered: ‎01-16-2019

Yes, you are correct, apologies for the confusion. 0x0000_4000 for ID 142, 0x0000_2000 for ID 141, and 0x0000_1000 for ID 140.

0 Kudos