• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Blogs
  2. Verification
  3. ARM Generic Interrupt Controller HOWTO
jasona
jasona

Community Member

Blog Activity
Options
  • Subscribe by email
  • More
  • Cancel
Virtual System Platform
Cortex-A9
System Design and Verification
Cortex-A
howto
ARM Generic Interrupt Controller
SystemC
GIC
ARM
Wadikar
Generic Interrupt Controller

ARM Generic Interrupt Controller HOWTO

22 Jul 2011 • 5 minute read

Way back in 2004, I wrote a book called Co-Verification of Hardware and Software for ARM SoC Design. At that time the world revolved around AHB and the ARM926EJ-S was a popular CPU. All ARM CPUs used two interrupt signals, nIRQ and nFIQ. The nIRQ signal is the normal interrupt request and nFIQ is the fast interrupt request. The bus signals for these two interrupts are active low signals, so driving the signal low indicates an interrupt. The ARM architecture defined exception addresses as shown the table below. 

 

For verification engineers developing diagnostic test software, this was pretty much all you needed to know to understand the how interrupts work. The nIRQ signal could be asserted and the software would jump to the exception vector shown the table. The only variant is if the VINITHI signal is high during reset; then the exception vectors start at 0xFFFF0000 instead of 0x0. There wasn't all that much more to say in the book.

Now we are in 2011, and the ARM926EJ-S is called a "Classic Processor" by ARM and has been replaced in popularity by the Cortex-A9, and more specifically the Cortex-A9 MPCore with 2 or 4 cores. Such multi-core ARM processors use the Generic Interrupt Controller Architecture, also known as GIC. As you can guess the world of interrupts with a GIC is much more complex than it was in the good old days for engineers writing software diagnostic tests.

To help describe the situation, I turned to Praveen Wadikar, an engineer on the Cadence Virtual System Platform team for some insights. Praveen is a member of the modeling team creating models for Virtual Platforms, many of which include ARM Cortex-A series processors in them.

Following is what Praveen had to share on the topic.

Praveen's GIC HOWTO

The ARM GIC is primarily used in the Cortex-A MPCore series processors, but it not specific to any processor. The ARM GIC is part of the ARM processor private bus interface. The GIC is a centralized resource for supporting and managing interrupts in a system that includes at least one processor. GIC architecture splits logically into a Distributor block and one or more CPU Interface blocks. More details about the GIC can be found in the ARM® Generic Interrupt Controller Architecture Specification.

In this short introduction, the security and pre-emption features supported by GIC are not discussed. Instead this focuses on providing a HOWTO introduction to configure the GIC so that an interrupt from a peripheral is detected by GIC and sent to the appropriate processor. This basic setup is frequently needed when developing new Virtual Platform models and running software tests on an ARM CPU to confirm proper operation of the new peripheral model.

Configuration Steps

The first thing to keep in mind is that the GIC is part of ARM private bus and hence the base address is determined by something called peripheral base, the base address of the internal MPCore peripherals. The GIC distributor base address DISTBASE = PERIPHBASE + 0x1000 and CPU interface base is CPUBASE = PERIPHBASE + 0x100.

Note that the GIC works on interrupt IDs and not the physical IRQS lines. Interrupt ID 0 to 15 is usually used for S/W interrupts. In most of the cases the physical line IRQS[0]  will correspond to interrupt ID 32. This is essential because all the enable/disable and other configuration is based on the function ID.

Ensure that the distributor and CPU interface is not enabled (register at offset 0). After reset the distributor and CPU interface are disabled. If the distributor/cpu interface is enabled then the write is not permitted to other registers in distributor or CPU interface respectively

Read the distributor Interrupt Controller Type Register (ICDICTR). The field ITLinesNumber indicates the maximum number of interrupts that the GIC supports. If this field is 0x3 then max interrupts supported is 32(N+1) = 128. i.e. function ID 0 to 127. Ensure that the interrupt line that is connected to GIC falls within function ID 0 to 127 (i.e. physical IRQS line 0 to 96).

Enable the interrupt set enable register (ICDISERn). So if interrupt ID (N) 77 is to be configured then offset of ICDISERn = 0x100 + (4*M), where M = N/32 (integer division).  The bit number of the required Set-enable bit in this register is N MOD 32

Configure Interrupt Processor Targets Registers (ICDIPTRn). This register determines to which processor the interrupt needs to be sent. For interrupt ID N, when DIV and MOD are the integer division and modulo operations:

  • the corresponding ICDIPTR number, M, is given by M = N DIV 4
  • the offset of the required ICDIPTR is (0x800 + (4*M))
  • the byte offset of the required Priority field in this register is N MOD 4, where:
    • byte offset 0 refers to register bits [7:0]
    • byte offset 1 refers to register bits [15:8]
    • byte offset 2 refers to register bits [23:16]
    • byte offset 3 refers to register bits [31:24]

Set Interrupt configuration register ICDICFRn to configure the interrupt to be level sensitive or edge sensitive. Each Interrupt ID has 2 bit field. Bit0 of the bitfield is reserved and Bit1 = 0 => level sensitive. This bit is not programmable for S/W interrupts.

Configure in CPU interface register map, Interrupt Priority Mask Register (ICCPMR). A value of 0xffff means lowest priority. Any priority higher than the value programmed in this register is serviced.

Enable CPU interface and Distributor. This is all that is needed to setup interrupt delivery.

Example to Enable an Interrupt

This example uses Interrupt ID 76 (IRQS[44]) is to be enabled. In this system the PERIPHBASE = 0x2c0c0000, DISTBASE = 0x2c0c1000 and CPUBASE=0x2c0c0100. For ARM models used in Virtual Platforms the PERIPHBASE is set at the start of simulation via a model parameter. It's important this is done correctly or none of the GIC accesses will work correctly.

// Set Interrupt Enable Registers. Offset = 0x100 + dec_to_hex(76/32*4) = 0x108
hw_write(0x2c0c1000 + 0x108, 0xFFFFFFFF);

// Set ICDIPTRn Registers to cpu0. Offset = 0x800 + dec_to_hex(76/4*4) =  0x84c
hw_write(0x2c0c1000 + 0x84C, 0x01010101);

// Set Interrupt Configuration Registers (ICDICFR0) to level sensitive. Offset = 0xC00 + dec_to_hex(76/16 *4) = 0xC10.
hw_write(0x2c0c1000 + 0xC10, 0x0);  

// Priority Mask. Enable interrupts for lowest priority also
hw_write(0x2c0c0100 + 0x4, 0xFFFF);   

// enable signaling of interrupt
hw_write(0x2c0c0100 + 0x0, 0x3);   

// Configure the Distributor Control Register (ICDDCR) to send pending interrupts to cpus
hw_write(0x2c0c1000 + 0x000, 0x1);  

So any peripheral that generates an interrupt and whose interrupt line is connected to IRQS[44] , the GIC will detect and send it to CPU0.

Conclusion

Cool! Thanks, Praveen. Even the simplest case takes some knowledge just to deliver an interrupt to the CPU from a Virtual Platform peripheral model under development. The most difficult part is that if any of the steps are not correct the result is no interrupt and more head scratching.

Virtual System Platform provides good visualization into the GIC registers in Cortex-A series processors. Below is a screenshot showing the register viewer of some of the GIC registers. This allows detailed debugging of such hardware diagnostics to confirm proper operation.When the built-in software debugger is used to step through the code programming the GIC the changed values are highlighted in red.

 

 

We hope this simple HOWTO will help engineers designing hardware tests for peripherals to have an easier time understanding what needs to be done to check that a peripheral is working.

Jason Andrews

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information