1. Introduction
When using an Intel® SoC FPGA Arm® Cortex®-A9 dual core as an Asymmetric Multi Processing (AMP), you may want to notify both cores of a Shared Peripheral Interrupt (SPI) interrupt.
Many people may think that by setting the target of interrupt notification to both cores in the ICDIPTRn register (see the following document for details), it is possible to notify interrupts to both cores.
Reference:
PrimeCell Generic Interrupt Controller (PL390) Technical Reference Manual
Refer to the "3.2.10 Target Registers (ICDIPTRn)" chapter.
However, even with the above settings, it is not possible to notify interrupts to both cores.
As described in the following document, only one of the cores (or in rare cases, both cores) will be notified.
Reference:
ARM Generic Interrupt Controller Architecture Specification
<Excerpts>
"SPIs using the GIC 1-N model, where the acknowledgement of an interrupt by one processor
removes the pending status of the interrupt on any other targeted processors, see Implications
of the 1-N model on page 3-41." [cited from ARM Generic Interrupt Controller Architecture].
This article provides an example of how to send interrupts to both cores, so you can use it as a reference when sending SPI interrupts to both cores.
Point:
There are three types of interrupts (SGI, PPI, SPI) handled by the interrupt controller (GIC).
The notes in this article are intended for cases where you wish to notify a multicore of an SPI.
- Software Generated Interrupt (SGI): An interrupt that is generated by software control.
- Private Peripheral Interrupt (PPI): Interrupts from peripherals that each core has exclusively.
- Shared Peripheral Interrupt (SPI): Interrupts from peripherals shared between cores.
2. Examples of coping methods
As explained in "1. Introduction" SPI interrupts are basically designed to interrupt only one core.
The most reliable way to get interrupts to both cores is to create two FPGA_IRQxx from the FPGA to the HPS and input them to CPU0 and CPU1 respectively.
The image is as follows.
Figure 1. Preparing two FPGA_IRQs and interrupting both cores
In the above case, two FPGA_IRQxx must be prepared on the hardware side, and RTL must be modified.
Therefore, this article introduces a method to interrupt both cores with a single FPGA_IRQxx.
The solution described here is as follows, One core handles the SPI interrupt routine and issues an SGI to the other core within the interrupt routine.
By doing so, both cores can be interrupted.
The figure is shown below (In this example, core 0 is configured to receive SPI interrupts).
Figure 2. Flow of how to insert interrupts to both cores
3. Code implementation points
The following 3-1 to 3-3 are the key points of the code to implement the countermeasure.
3-1. Set the target of interrupt processing by SPI to one of the cores
The first point, using the alt_int_dist_target_set() API of the HWLib (hardware library) included in the Intel® SoC FPGA Embedded Development Suite (SoC EDS), you can set as follows (In this example, the target is set to core 0).
result_code = alt_int_dist_target_set(ALT_INT_INTERRUPT_TIMER_OSC1_0_IRQ, 1);
For more information about alt_int_dist_target_set(), please refer to the HWLib documentation at the following path in SoC EDS (open index.html in your browser).
\intelFPGA\<version>\embedded\ip\altera\hps\altera_hps\doc\soc_cv_av\index.html
3-2. Registering interrupt handlers to be executed by SGI
As the second point, decide the number of SGI to be used in advance and register the interrupt handler using alt_int_isr_register() of HWLib.
The following is an example of registering an interrupt handler named sample_ictrl_callback_SGI0__OSC1_TMR0() using SGI number 0.
result_code = alt_int_isr_register(ALT_INT_INTERRUPT_SGI0, sample_ictrl_callback_SGI0__OSC1_TMR0, NULL);
For more information on alt_int_isr_register(), please refer to the HWLib documentation.
3-3. Generation of SGI
As the third point, SGI can be generated by HWLib's alt_int_sgi_trigger().
By setting the second argument of alt_int_sgi_trigger() to 1, an interrupt can be notified to a core other than the core executing the code.
In the case of a dual core, there is only one core other than the core executing the code, so the interrupt will necessarily be notified only to the other core.
The following is an example of code that generates an SGI of 0 and signals an interrupt to the other core.
result_code = alt_int_sgi_trigger(ALT_INT_INTERRUPT_SGI0, ALT_INT_SGI_TARGET_ALL_EXCL_SENDER, (alt_int_cpu_target_t)0, true);
The first argument is set to 0 (ALT_INT_INTERRUPT_SGI0) to generate the 0th SGI.
The second argument is set to 1 (ALT_INT_SGI_tARGET_ALL_EXCL_SENDER) to notify the other core of the interrupt.
Please refer to the HWLib documentation for details on alt_int_sgi_trigger().
4. Related information
The following two articles are useful documents for working with the Generic Interrupt Controller (GIC) of the Intel® SoC FPGA HPS.
Reference: Cyclone® V SoC: HPS Register Specification Locations List Sheet - (In Japanese)
For detailed GIC specifications, see Arm® document.
This article introduces URLs of documents related to GIC.
Reference: Techniques for using Arm DS - Register View [2/3] Register Definitions by Yourself
Publish a register definition file for displaying GIC registers in Arm® Development Studio 5 Intel® SoC FPGA Edition (DS-5) debugger.
If you want to check the register values on the debugger GUI, please refer to this article.
5. Conclusion
In this article, we introduced coping methods to notify both cores of a single SPI interrupt.
When using the Intel® SoC FPGA Cortex™-A9 dual-core, you may want to interrupt both cores.
In such cases, we hope you will refer to this document.