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 GICV32. The Clock is enabled for GIC module.3. ARE is set to 1 in GICD_CTRL, So its in GICV3 mode4. 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 06. 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_EL39. 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-sensitive13. 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