ARM Interrupts

Interrupt Configuration for the ARM cortex A9 core

2607

Configuring ARM interrupts

The ARM Cortex A9 core has two external interrupt request ports; one for ‘Fast interrupt requests’ (FIQ) and for normal interrupts (IRQ). When an interrupt is requested on either of these ports, based on the internal configuration of the core, the core may jump to an interrupt handler. This document details the configuration of the core so interrupts can be enabled or disabled.

Current Program Status Register

The Current Program Status Register (CPSR) is a special register in the ARM that configures the processor’s mode as well as enabling or disabling interrupts. It’s bitfields are shown below:

ARM CPSR Register
ARM CPSR Register

For the Purpose of this Document we will only examine the lowest byte. All other fields in the CPSR should remain unmodified.

The diagram shows that bits 7 and 6 are the I and F bits respectively. The I bit is for disabled/enabling IRQ (interrupt request) interrupts and the F bit is for disabling/enabling FIQ (fast interrupt request) interrupts. A 1 written to one of these bits disables the corresponding interrupt. Conversely, a 0 enables the specified interrupt. Additionally, the least significant 5 bits in the CPSR determine which mode the processor is in. Writing 5b11111 to the mode will set the core to System Mode allowing protected resources to be modified. The T bit should also be set to 0 to ensure the processor stays in ARM mode and not thumb mode.

Disabling ARM Interrupts

To modify the CPSR through c code, you need to make use of inline assembly. You’ll need 2 assembly instructions (in addition to operations done with c code). The MRS instruction moves the contents of a special register to a general purpose register. Likewise, the MSR moves a GPR’s value to a special register. The below code modifies the CPSR to put it into system mode with both the FIQ and IRQ disabled.

void disable_arm_interrupts(void)
{
	uint32_t cpsr_val =0;

	asm("mrs %0, cpsr\n" : "=r" (cpsr_val) );	//get current cpsr

	cpsr_val &= ~(0xFF);	//clear lower 8 bits
	cpsr_val |= 0xDF;	//set all bits but the 'T' bit


	asm("msr cpsr, %0\n" : : "r" (cpsr_val));	//writeback modified value

	return;

}

Enabling Interrupts

Conversly, To renable interrupts, just clear the ‘I’ bit in the CPSR.

void enable_arm_interrupts(void)
{

	uint32_t cpsr_val =0;

	asm("mrs %0, cpsr\n" : "=r" (cpsr_val) );	//get current cpsr value

	cpsr_val &= ~(0xFF);	//clear lower 8 bits
	cpsr_val |= 0x5F;	//set all bits but 'T' and 'I' bit


	asm("msr cpsr, %0\n" : : "r" (cpsr_val));	//writeback modified value

	return;

}

After enabling interrupts via the CPSR, the processor will jump to the IRQ vector once it receives a request on the IRQ port. In the Zynq system, interrupt requests are arbitrated through the Generic Interrupt Controller (GIC). First it must be configured before it will generate interrupt requests. Additionally, code for servicing requests needs to be written and registered into the vector table.

Information on configuring the GIC can be found in this document: Configuring the GIC

Information for writing and registering Interrupt handlers can be found here : Interrupt Handlers