By Adam Taylor

In the last blog we looked at sharing data between the Zynq SoC’s two ARM Cortex-A9 MPCore processor. I noted that the approach used could have been improved—made more efficient—had we used software interrupts to communicate between the two cores.

Each ARM Cortex-A9 processor core in the Zynq SoC has 16 software-generated interrupts. Each processor can use these interrupts to interrupt itself, to interrupt the other processor core, or to interrupt both cores. For this example, we will use Core 0 to generate an interrupt that informs Core 1 that there has been an updated LED pattern received.

Using software interrupts is not too different from using hardware interrupts except of course in how we trigger them.

We have 16 software-generated interrupts to choose from so we must define the software interrupt number:

#define SW_INT_ID 0

We need to declare this choice in the code for both of our processor cores or within a shared header file. It would be embarrassing to have one processor core issue one of the 16 software-generated interrupts while the other processor core is waiting for a different one to occur.

The next thing we need to do within Core 1—the core receiving the interrupt—is to connect the software-generated interrupt to the GIC (generic interrupt controller) and then enable the interrupt. We do this within the existing function SetupInterruptSystem.

Connecting the interrupt is achieved by using the function XScuGIC_Connect. This function connects the defined interrupt to the GIC, defines the interrupt service routine, and defines the callback. In this example we have no peripheral instance pointer to act as the callback, as we would with a timer, so we can use the GIC Instance as call back.

Finally, having connected the selected software interrupt to the GIC, we now need to enable the interrupt so that the appropriate processor core will react to the appropriate events as directed by the interrupt.

With the interrupts connected and enabled, the next step is to write the ISR (interrupt service routine). This routine will simply read the OCM (on chip memory) and clear the interrupt to prevent the next interrupt from being masked.

Reading address 0xF8F0010C accesses the interrupt acknowledge register ICCIAR, which clears the interrupt.

In our example, the data read from the OCM is then displayed on the LEDS attached to the GPIO pins driven by the Zynq SoC’s PL (programmable logic). This software mechanism prevents us from missing a value as might have happened with the polled approach used in the previous blog.

Having completed all we need to do within Core 1, we must correctly configure Core 0 to issue the interrupt. We sue the XScuGic_SoftwareIntr function provided within xscugic.h to achieve this. Calling this function issues a software interrupt to the designated core.

XScuGic_SoftwareIntr(<GIC Instance Ptr>, <SW Interrupt ID>, <CPU Mask>)

The GIC Instance Ptr is the same parameter we previously used to configure the interrupt controller. The SW Interrupt ID is the one we previously declared within the macros. The CPU mask in this case is CPU 2, which is corresponds to Core 1 in the Zynq SoC.

When all this was built and the bin file generated as previously explained in the previous AMP Zynq blog post, I achieved a system that worked as I had wanted with interrupts issued by Core 0 and received by Core 1.

As always the code is attached

In a future blog, we will be looking at software interrupts in more detail and how we can interrupt both processor cores simultaneously. However, next week marks the one year anniversary of this blog.

I have planned something a little special.

Please see the previous entries in this MicroZed series by Adam Taylor:

Adam Taylor’s MicroZed Chronicles Part 50: AMP and the Zynq SoC’s OCM (On-Chip Memory)

Adam Taylor’s MicroZed Chronicles Part 49: Using the Zynq SoC’s On-Chip Memory for AMP Communications



Adam Taylor’s MicroZed Chronicles Part 48: Bare-Metal AMP (Asymmetric Multiprocessing)

Adam Taylor’s MicroZed Chronicles Part 47: AMP—Asymmetric Multiprocessing on the Zynq SoC

Adam Taylor’s MicroZed Chronicles Part 46: Using both of the Zynq SoC’s ARM Cortex-A9 Cores

Adam Taylor’s MicroZed Chronicles Part 44: MicroZed Operating Systems—FreeRTOS

Adam Taylor’s MicroZed Chronicles Part 43: XADC Alarms and Interrupts

Adam Taylor’s MicroZed Chronicles MicroZed Part 42: MicroZed Operating Systems Part 4

Adam Taylor’s MicroZed Chronicles MicroZed Part 41: MicroZed Operating Systems Part 3

Adam Taylor’s MicroZed Chronicles MicroZed Part 40: MicroZed Operating Systems Part Two

Adam Taylor’s MicroZed Chronicles MicroZed Part 39: MicroZed Operating Systems Part One

Adam Taylor’s MicroZed Chronicles MicroZed Part 38 – Answering a question on Interrupts

Adam Taylor’s MicroZed Chronicles Part 37: Driving Adafruit RGB NeoPixel LED arrays with MicroZed Part 8

Adam Taylor’s MicroZed Chronicles Part 36: Driving Adafruit RGB NeoPixel LED arrays with MicroZed Part 7

Adam Taylor’s MicroZed Chronicles Part 35: Driving Adafruit RGB NeoPixel LED arrays with MicroZed Part 6

Adam Taylor’s MicroZed Chronicles Part 34: Driving Adafruit RGB NeoPixel LED arrays with MicroZed Part 5

Adam Taylor’s MicroZed Chronicles Part 33: Driving Adafruit RGB NeoPixel LED arrays with the Zynq SoC

Adam Taylor’s MicroZed Chronicles Part 32: Driving Adafruit RGB NeoPixel LED arrays

Adam Taylor’s MicroZed Chronicles Part 31: Systems of Modules, Driving RGB NeoPixel LED arrays

Adam Taylor’s MicroZed Chronicles Part 30: The MicroZed I/O Carrier Card

Zynq DMA Part Two – Adam Taylor’s MicroZed Chronicles Part 29

The Zynq PS/PL, Part Eight: Zynq DMA – Adam Taylor’s MicroZed Chronicles Part 28

The Zynq PS/PL, Part Seven: Adam Taylor’s MicroZed Chronicles Part 27

The Zynq PS/PL, Part Six: Adam Taylor’s MicroZed Chronicles Part 26

The Zynq PS/PL, Part Five: Adam Taylor’s MicroZed Chronicles Part 25

The Zynq PS/PL, Part Four: Adam Taylor’s MicroZed Chronicles Part 24

The Zynq PS/PL, Part Three: Adam Taylor’s MicroZed Chronicles Part 23

The Zynq PS/PL, Part Two: Adam Taylor’s MicroZed Chronicles Part 22

The Zynq PS/PL, Part One: Adam Taylor’s MicroZed Chronicles Part 21

Introduction to the Zynq Triple Timer Counter Part Four: Adam Taylor’s MicroZed Chronicles Part 20

Introduction to the Zynq Triple Timer Counter Part Three: Adam Taylor’s MicroZed Chronicles Part 19

Introduction to the Zynq Triple Timer Counter Part Two: Adam Taylor’s MicroZed Chronicles Part 18

Introduction to the Zynq Triple Timer Counter Part One: Adam Taylor’s MicroZed Chronicles Part 17

The Zynq SoC’s Private Watchdog: Adam Taylor’s MicroZed Chronicles Part 16

Implementing the Zynq SoC’s Private Timer: Adam Taylor’s MicroZed Chronicles Part 15

MicroZed Timers, Clocks and Watchdogs: Adam Taylor’s MicroZed Chronicles Part 14

More About MicroZed Interrupts: Adam Taylor’s MicroZed Chronicles Part 13

MicroZed Interrupts: Adam Taylor’s MicroZed Chronicles Part 12

Using the MicroZed Button for Input: Adam Taylor’s MicroZed Chronicles Part 11

Driving the Zynq SoC's GPIO: Adam Taylor’s MicroZed Chronicles Part 10

Meet the Zynq MIO: Adam Taylor’s MicroZed Chronicles Part 9

MicroZed XADC Software: Adam Taylor’s MicroZed Chronicles Part 8

Getting the XADC Running on the MicroZed: Adam Taylor’s MicroZed Chronicles Part 7

A Boot Loader for MicroZed. Adam Taylor’s MicroZed Chronicles, Part 6

Figuring out the MicroZed Boot Loader – Adam Taylor’s MicroZed Chronicles, Part 5

Running your programs on the MicroZed – Adam Taylor’s MicroZed Chronicles, Part 4

Zynq and MicroZed say “Hello World”-- Adam Taylor’s MicroZed Chronicles, Part 3

Adam Taylor’s MicroZed Chronicles: Setting the SW Scene

Bringing up the Avnet MicroZed with Vivado