Hello, I am trying to enable interrupt preemption on the second A7 core of the IMX7D inside a baremetal application. I am performing all of this testing before Linux boots.
Currently I am able to enable interrupts on CPU interface 1 in group 1. To accomplish this I am using the following configuration:
GICC_CTLR = 0x2; //enable group 1 in the CPU interface
GICC_CPMR = 0xFF; // Set the priority filter to the lowest priority
GICD_CTLR = 0x2; //Enable group 1 in the distributor
GICC_ABPR = 0; //Set all groups to have different preemption levels
GICC_BRP =0; //Set all groups to have different preemption levels
For each interrupt (I am testing wtih 2)
GICD_GROUPn = 1 (shifted appropriately);// Have the interrupt signal group 1
GICD_ISENABLERn = 1(shifted appropriately); //enable each interrupts
GPC_IMR1_CORE1_A7 = 0(shifted appropriately);// Unmask interrput for A7_1 core
GICD_PRIORITYRn= 0xC0 for interrupt 1 and 0x10 for interrupt 2
GICD_ITARGETSR= 0x2; //Select the second CPU interface to target
Using this configuration I can see both interrupts firing, however neither will preempt the other, as if they were the same priority. Inside the interrupts I check the current priority GICC_RPR and confirm that the running priority matches the priority that I assigned them (0x10 and 0xC0). I also check the highest priority IR GICC_AHPPIR and it has the interrupt number of the other interrupt.
To check for preemption I am toggling a gpio. While inside the interrupt the GPIO is set high. In this figure you can see the red and yellow pulses. The yellow pulses are a timer interrupt that is higher priority than the other. As you can see, the yellow pulses are never high at the same time as red.
Do you know why preemption does not happen?
@benjmcgee
Hello,
I am afraid we do not have detailed description and examples for GIC implementation
under i.MX7, assuming the Linux kernel contains common ARM GIC interrupts handling code.
Customers can refer to Linux codes:
drivers/irqchip/irq-gic.c for i.MX 6/7 SoCs with GIC-400.
Also, bare metal implementation under i.MX6 may be helpful.
Use the i.MX6 Platform SDK for it. In particular - Chapter 4 (Configuring the GIC
Driver) in "iMX6_Firmware_Guide.pdf"
< https://github.com/flit/imx6_platform_sdk/tree/master/doc >
You mentioned about GIC configuring before Linux boot.
Note (if You using system testing under Linux), Linux can reconfigure the GIC.
Regards,
Yuri.
Yuri,
Thanks for the response. That is a useful repository that you pointed me to! I ran the GIC driver contained in the repo. Unfortunately, it behaved the same as my own driver. The driver itself was not intended to support preemption since they are setting the BPR to 7 (with the comment, /*Disable Preemption*/) I of course changed this register to 0 to allow the maximum preemption levels, but preemption still did not occur.
The Linux kernel does not use preemption either.
Are you aware of any test code that enables preemption in the GIC?
Thanks,
Ben
Hi Yuri,
While I don't have it working yet, the missing piece is this:
Enabling interrupts in the core register allows the preemption to occur, but it also results in the application crashing due to stack pointer/link register issues.
I need to write a routine to manage the stack pointers and link registers and switch modes. I tried what was provided with the link and it didn't work so I am looking into it in detail now. If you are aware of any code sample of an ISR that allows preemption without crashing that would be great.
Thanks,
Ben
I have also tried using Group 0 instead of Group 1 and see the same behaviour.
Also,
I am currently using https://developer.arm.com/documentation/ihi0048/latest/ as a reference for the GIC. Is there any NXP IMX7D specific documentation available? If so, perhaps it contains missing needed information.
Thanks,
Ben