I'm having troubles with triggering a software interrupt on Versatile Express board (Cortex-A9).
I managed to set an interrupt pending, but jump to Vector Table does not execute.
#define HAL_READ_UINT32(register, value) (( value ) = *((volatile unsigned int *)( register )))
#define HAL_WRITE_UINT32(register, value) (*((volatile unsigned int *)( register )) = ( value ))
#define PERIPHBASE 0x1e000000
#define CPUBASE ( PERIPHBASE + 0x100 ) // CPU Interface Base Address
#define DISTBASE ( PERIPHBASE + 0x1000 ) // Distributor Base Address
#define ICCICR 0x00 // CPU Interface Control Register (RW)
#define ICCPMR 0x04
//
CPU Interface
Priority Mask Register (RW)
#define ICDDCR 0x000 // Distributor Control Register (RW)
#define ICDISER 0x100
//
Distributor
Interrupt Set Enable Registers (RW)
#define ICDISPR 0x200
//
Distributor
Set Pending Register (RW)
#define ICDIPR
0x400
//
Distributor
Interrupt Priority Register (RW)
#define ICDSGIR 0xF00
//
Distributor
Software Generated Interrupt Register (WO)
int main ()
{
unsigned int tmp;
HAL_WRITE_UINT32( CPUBASE + ICCICR, 0 ); // Disable CPU Interface (it is already disabled, but nevermind)
HAL_WRITE_UINT32( DISTBASE + ICDDCR, 0 ); // Disable Distributor (it is already disabled, but nevermind)
HAL_WRITE_UINT32( DISTBASE + ICDISER, 0x0000ffff ); // Set enable (enable all SGIs)
HAL_WRITE_UINT32( CPUBASE + ICCPMR, 0xff ); // All interrupts whose priority is > 0xff are unmasked
HAL_WRITE_UINT32( DISTBASE + ICDIPR, 0 ); // Set the highest priority
HAL_WRITE_UINT32( DISTBASE + ICDDCR, 1 ); // Enable Distributor
HAL_WRITE_UINT32( CPUBASE + ICCICR, 1 ); // Enable CPU Interface
HAL_READ_UINT32 ( DISTBASE + ICDISPR, tmp); // Is the interrupt pending? => No, it's not
HAL_WRITE_UINT32( DISTBASE + ICDSGIR, 0x02000000); // Generate software interrupt ID=0 to CPU0 (to this, running CPU)
HAL_READ_UINT32 ( DISTBASE + ICDISPR, tmp); // Is the interrupt pending? => Yes, it is
return 0;
}
// ======================================================================================
// File: startup.s
// ======================================================================================
.section INTERRUPT_VECTOR, "x"
.global _Reset
_Reset:
B Reset_Handler /* Reset */
B . /* Undefined */
B . /* SWI */
B . /* Prefetch Abort */
B . /* Data Abort */
B . /* reserved */
B . /* IRQ */
B . /* FIQ */
Reset_Handler:
LDR sp, =stack_top
BL main
B .
// ======================================================================================
// File: test.ld
// ======================================================================================
ENTRY(_Reset)
SECTIONS
{
. = 0x0;
.text : { startup.o(INTERRUPT_VECTOR)
*(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
. = . + 0x10000; /* 4 kB for stack */
stack_top = .;
}
// ======================================================================================
Files are compiled and linked with the following:
From GDB I can see that all the time CPU is in SVC mode (default after reset) and in CSPR register I flag is 0 (interrupt enabled).
Vector table is placed at the address 0x0, but even if that is not correct I expected a jump.
Please, can anyone take a look what am I missing in the configuration of the GIC?