This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

GICV3 Interrupt Configuration (i.MX 8M Mini - ARM Cortex A53)

Hi,
We are trying to generate a timer interrupt and configure it.
So that when timer interrupt occurs it should go to the vector table and execute the timer ISR.

What we have Done :

* Generating Timer Interrupt :
1. We are using GPT2(General Purpose Timer - 2) to generate interrupt.
2. The INTID(Interrupt ID) of GPT2 interrupt is 86.
3. First timer is initialized ( clock frequency = 2MHz)
4. Then The Compare value is set to 60,000,000 (i.e 30seconds).
5. Enabling the timer (Now the timer started counting, and we are able verify this by reading the timer counter register.)

* Configuring the Interrupt in GIC:
1. The GIC used is GICV3
2. The Clock is enabled for GIC module.
3. ARE is set to 1 in GICD_CTRL, So its in GICV3 mode
4. All interrupt group are enabled in GICD_CTRL(grp0,grp1,grp1NS)
5. Waking up the GICR by clearing GICR_WAKER.ProcessorSleep to 0 and Polling GICR_WAKER.ChildrenAsleep until it reads 0
6. Enabling the interrupt in PSTATE (CPSR)
7. Setting ICC_SRE_EL3 = 1, so we can access cpu interface registers
8. Enabling all groups (grp0,grp1,grp1NS) in sytem register( cpu interface)
    in ICC_IGRPEN0_EL1,ICC_IGRPEN1_EL1,ICC_IGRPEN1_EL3
9. We are adding (INTID 86) to group0.
10.Routing INTID 86 to 0.0.0.0 (core 0 - current core)
11. Setting INTID 86 to priority to 0 (highest)
12. Set INTID 86 as level-sensitive
13. Enabling the INTID 86.

* What we are seeing:
1. Once timer is enabled,
Before elapsing 30s - The GPT2_SR(0x302e0008) value is 0x0(No compare interrupt)
                                   The GICD_ISPENDR[2](0x38880208) is 0x0 (No pending interrupt)
                                   The GICD_ISACTIVER[2](0x38880308) is 0x0 (No active interrupt)
After elapsing 30s -    The GPT2_SR(0x302e0008) value is 0x1(compare interrupt occurred)
                                   The GICD_ISPENDR[2](0x38880208) is 0x400000 (pending interrupt -INTID 86)
                                   The GICD_ISACTIVER[2](0x38880308) is 0x0 (No active interrupt)
2. The control is still in main ( verified by checking the PC)

* What we are expecting:
1.The interrupt should go to vector table and start executing the ISR.


The code for the same is given below.

Note 1 : INTID86 is SPI(Shared Peripheral Interrupt)

Note 2 : We have kept an infinite for loop in the ISR so that we can verify whether its in ISR by checking PC

Thanks for any suggestions in advance.
Bindu

#if 1

#include "../asm/GICv3_aliases.h"

#define stringify_no_expansion(x) #x
#define stringify(x) stringify_no_expansion(x)

#define GICD_BASE_ADDR 0x38800000
#define GICR_BASE_ADDR 0x38880000
#define GPT_2_BASE_ADDR 0x302E0000

__attribute__((noreturn)) int main(void)
{
unsigned int flag = 1;

if(flag == 0)
{

/* ****************** interrupt testing ********************* */

/* GIC CONFIGURATION */

*(unsigned int *)0x303845C0UL = 0x3UL; //enable GIC Clock

*(unsigned int *)(GICD_BASE_ADDR + 0x0) = ( (1<<4) | (1<<5) ); // enable affinity routing for secure and non-secure
*(unsigned int *)(GICD_BASE_ADDR + 0x0) = ( 7 | (1<<4) | (1<<5) ); // enable all groups interrupt

/* note : register layout changes here */

*(unsigned int *)(GICR_BASE_ADDR + 0x14) &= ~(1<<1); // ensure GICR_WAKER.ProcessorSleep is off
while( ( (*(unsigned int *)(GICR_BASE_ADDR + 0x14)) & (1<<2) ) != 0x0 ) // wait for children asleep to be cleared
continue;


/* CPU INTERFACE CONFIGURATION */

__asm("MSR DAIFClr, #0xF"); //Enable interrupts in PSTATE

asm("msr "stringify(ICC_SRE_EL3)", %0\n; isb" :: "r" ((unsigned long long int)0x1)); //enable access to CPU interface registers

asm("msr "stringify(ICC_PMR_EL1)", %0\n; isb" :: "r" ((unsigned long long int)0xFF)); //set priority mask to lowest

asm("msr "stringify(ICC_IGRPEN0_EL1)", %0\n; isb" :: "r" ((unsigned long long int)0x1)); //enable GROUP0 Interrupt
asm("msr "stringify(ICC_IGRPEN1_EL1)", %0\n; isb" :: "r" ((unsigned long long int)0x1)); //enable GROUP1 Interrupt
asm("msr "stringify(ICC_IGRPEN1_EL3)", %0\n; isb" :: "r" ((unsigned long long int)0x1)); //enable GROUP1NS Interrupt, note : works only @ EL3


/* CONFIGURE SPI INTERRUPT */
*(unsigned int *)(GICD_BASE_ADDR + 0x88) = 0x0UL; // Add INTID 86 to Group 0
*(unsigned int *)(GICD_BASE_ADDR + 0xD08) = 0x0UL;

*(unsigned long long int *)(GICD_BASE_ADDR + 0x62B0) = 0x0UL; // Route INTID 86 to 0.0.0.0 (this core)
*(unsigned char *)(GICD_BASE_ADDR + 0x0456) = 0x0UL; // Set INTID 86 to priority to 0
*(unsigned int *)(GICD_BASE_ADDR + 0x0C20) = 0x0UL; // Set INTID 86 as level-sensitiv

*(unsigned int *)(GICD_BASE_ADDR + 0x0108) = 0x400000UL; // Enable 86 intid


/* generate timer interrupt */
*(unsigned int*)0x30384110UL = 0x3UL; // enable gpt2 clock

*(unsigned int *)(GPT_2_BASE_ADDR + 0x0) |= (1<<6); //24Mhz clock selected
*(unsigned int *)(GPT_2_BASE_ADDR + 0x0) &= ~(1<<7);
*(unsigned int *)(GPT_2_BASE_ADDR + 0x0) |= (1<<8);

*(unsigned int *)(GPT_2_BASE_ADDR + 0x0) |= (1<<10); //enable 24 Mhz Clock

unsigned int temp = (*(unsigned int *)(GPT_2_BASE_ADDR + 0x4)) & 0xFFF; //presacle by 12 , so clk_freq = 2Mhz
temp |= ((12 << 12) & 0xF000);
*(unsigned int *)(GPT_2_BASE_ADDR + 0x4) = temp;

*(unsigned int *)(GPT_2_BASE_ADDR + 0x0) |= (1<<1); //enable mode is set

*(unsigned int *)(GPT_2_BASE_ADDR + 0x0) |= (1<<9); // select free run mode

/* configure Timer to generate interrupt */

*(unsigned int *)(GPT_2_BASE_ADDR + 0x0) &= ~(1<<20); //Disconnect HW output pin
*(unsigned int *)(GPT_2_BASE_ADDR + 0x0) &= ~(1<<21);
*(unsigned int *)(GPT_2_BASE_ADDR + 0x0) &= ~(1<<22);

*(unsigned int *)(GPT_2_BASE_ADDR + 0x10) = 60000000UL; //30s as match time

*(unsigned int *)(GPT_2_BASE_ADDR + 0xC) |= (1<<0); //enable compare interrupt

*(unsigned int *)(GPT_2_BASE_ADDR + 0x0) |= (1<<0); //enable timer

}

for(;;); //infinite loop
}

#endif