Download presentation
Presentation is loading. Please wait.
1
Interrupts in Zynq Systems
Cristian Sisterna Universidad Nacional de San Juan Argentina
2
Exception / Interrupt Special condition that requires a processor's immediate attention Abnormal internal event (division by zero, illegal instruction) Exception User-generated SI Software Interrupt Sources of an exception An exception is a special condition that requires a processor's immediate attention. An exception can be raised by an abnormal internal event, such as division by zero or an unimplemented instruction, or by an important external event that has priority over normal program execution. The latter is referred to as a hardware interrupt. Since the book focuses on the I/O interface, our discussion is primarily on hardware interrupt. Important external event that has priority over normal program execution Hardware Interrupt SoC School - C. Sisterna ICTP
3
In Cortex-A9 processor interrupts are handled as exceptions
Cortex A9 - Exceptions In Cortex-A9 processor interrupts are handled as exceptions Each Cortex-A9 processor core accepts two different levels of interrupts nFIQ interrupts from secure sources (serviced first) nIRQ interrupts from either secure sources or non-secure sources ARM Cortex-A9 In the Cortex-A9 processor, interrupts are handled as exceptions. Exceptions in the Cortex-A9 processor cause the program to jump to a pre-determined address that will then perform a jump to the appropriate exception handling routine. This causes the processor to change its operating mode. For example, when an IRQ occurs, the Cortex-A9 processor causes the program to jump to the address 0x (or FFFF0018) that will then perform a jump to the appropriate Interrupt Service Routine (ISR). Unlike other exceptions, when an FIQ interrupt is received, the Cortex-A9 processor jumps to the FIQ handler address where the FIQ service routine is present. This allows the FIQ service routine to be executed immediately when an FIQ occurs. The FIQs are serviced first when multiple interrupts arise. When an FIQ is serviced, IRQs (and FIQs) are disabled. The IRQs will not be serviced until after the FIQ handler exits. The exception vector table contains the addresses for each exception. The exception table is usually located at 0x or 0xFFFF0000. nFIQ nIRQ SoC School - C. Sisterna ICTP
4
Pooling or Hardware Interrupt ?
FIT = ??? PIT = ??? Polling SoC School - C. Sisterna ICTP
5
Interrupt Terminology
Interrupt Service Routine (ISR): ‘C’ code written to answer a specific interrupt. It can be hardware or software interrupt Interrupts Pins: set of pins used as input of hardware interrupts Interrupt Priority: In systems with more tan one source of interrupt, some interrupt have higher priority of attendance than other. Interrupt Vector: code loaded in the bus by the interrupting peripheral that contains the address of the specific ISR Mask Interrupt : interrupt that can be enable or disable by software Non-Maskable Interrupt (NMI): source of interrupt that can not be ignored Interrupt Latency: The time interval from when the interrupt is first asserted to the time the CPU recognizes it. This will depend much upon whether interrupts are disabled, prioritized and what the processor is currently executing FIT = ??? PIT = ??? Regardless of the source, interrupts can also be classified as either maskable or non-maskable. You can safely ignore a maskable interrupt by setting the appropriate bit in an interrupt mask register. But you cannot ignore a non-maskable interrupt, because these are the types typically used for timers and watchdogs Interrupt Response Time: The time interval between the CPU recognizing the interrupt to the time when the first instruction of the interrupt service routine is executed. This is determined by the processor architecture and clock speed SoC School - C. Sisterna ICTP
6
Polling Efficient when events arrives very often
A software routine is used to identify the peripheral requesting service. When the polling technique is used, each peripheral is checked to see if it was the one needing service. Efficient when events arrives very often It requires no special hardware Quick response time (lees overhead) For fast peripherals, polling may simply not be fast enough to satisfy the minimum service requirements It takes CPU time even when there is one peripheral looking for attention; as it needlessly checks the status of all devices all the time priority of the peripherals is determined by the order in the polling loop Polling is like picking up your phone every few seconds to find out whether someone has called you SoC School - C. Sisterna ICTP
7
Hardware Interrupt A special software routine is used to attend an specific peripheral when it rises the need for attention Inefficient when events arrives very often It does requires special hardware Slow response time (more overhead) It does not takes CPU time even when there is no peripheral looking for attention Good for fast peripherals, polling may simply not be fast enough to satisfy the minimum service requirements priority of the peripherals is determined by the hardware Hardware Interrupt is like picking up your phone ONLY when it rings SoC School - C. Sisterna ICTP
8
Polling vs Interrupt Hardware Interrupt Polling Asynchronous
EVENT Asynchronous Synchronous (i.e. you know when to expect it within a small window) Urgent Not urgent (i.e. a slow polling interval has not bad effects) Infrequent Frequent (i.e. majority of your polling cycles create a ‘hit’) Hardware Interrupt Polling SoC School - C. Sisterna ICTP
9
Hardware Interrupt in the Zynq
SoC School - C. Sisterna ICTP
10
Hardware Interrupts A hardware interrupt is an asynchronous signal from hardware, originating either from outside the SoC, from any of the PS peripherals or from the logic implemented in the PL, indicating that a peripheral needs attention Source of Hardware Interrupts in the Zynq: Embedded processor peripheral (FIT, PIT, for example) External bus peripheral (UART, EMAC, for example) External interrupts enter via hardware pin(s) PL block Multiple hardware interrupts can utilize general interrupt controller of the PS FIT = ??? PIT = ??? SoC School - C. Sisterna ICTP
11
Interrupt Types Edge triggered Level triggered Parameter: SENSITIVITY
Rising edge, attribute: EDGE_RISING Falling edge, attribute: EDGE_FALLING Level triggered Parameter: SENSITIVITY High, attribute: LEVEL_HIGH Low, attribute: LEVEL_LOW SoC School - C. Sisterna ICTP
12
How is the Interrupt Flow ? Part 1
Interrupt Handler When an interrupt occurs, the current executing instruction completes Save processor status Copies CPSR into SPSR_irq Stores the return address in LR_irq Change processor status for exception Mode field bits ARM or thumb (T2) state Interrupt disable bits (if appropriate) Sets PC to vector address (either FIQ or IRQ) (This steps are performed automatically by the core) Interrupt Routine Service SoC School - C. Sisterna ICTP
13
How is the Interrupt Flow ? Part 2
Interrupt Handler Executes top-level exception handler The top-level handler branches to the appropriate device handler Return to main application Restore CPSR from SPSR_irq Restore PC from LR_irq When re-enabling interrupts change to system mode (CPS) (Above steps are the responsibility of the software) Interrupt Routine Service SoC School - C. Sisterna ICTP
14
Generic Interrupt Controller (GIC)
SoC School - C. Sisterna ICTP
15
Generic Interrupt Controller (GIC)
Generic Interrupt Controller (PL390) SoC School - C. Sisterna ICTP
16
GIC Block Diagram The GIC collects interrupts from various sources and distributes these interrupts to each of the ARM cores. Each ARM core accepts two different types of interrupts: nFIQ interrupts from secure sources and nIRQ interrupts from either secure or non-secure sources. The interrupt distributor holds the list of pending interrupts for each Cortex-A9 processor. It selects the highest priority interrupt before issuing it to the Cortex-A9 processor interface. Interrupts of equal priority are resolved by selecting the lowest ID. The prioritization logic is physically duplicated to enable the simultaneous selection of the highest priority interrupt for each Cortex-A9 processor. The interrupt distributor holds the central list of interrupts, processors, and activation information and is responsible for triggering software interrupts to processors. SGI and PPI distributor registers are banked to provide a separate copy for each connected processor. Hardware ensures that an interrupt targeted at both Cortex-A9 processors can only be taken by one Cortex-A9 processor at a time. The interrupt distributor transmits to the Cortex-A9 processor interfaces the highest pending interrupt. It receives back the information that the interrupt has been acknowledged and can then change the status of the corresponding interrupt. Only the Cortex-A9 processor that acknowledges the interrupt can end that interrupt. SoC School - C. Sisterna ICTP
17
System Level Block Diagram
7.1.1 Private, Shared and Software Interrupts Each CPU has a set of private peripheral interrupts (PPIs) with private access using banked registers. The PPIs include the global timer, private watchdog timer, private timer, and FIQ/IRQ from the PL. Software generated interrupts (SGIs) are routed to one or both CPUs. The SGIs are generated by writing to the registers in the generic interrupt controller (GIC), refer to section 7.3 Register Overview. The shared peripheral interrupts (SPIs) are generated by the various I/O and memory controllers in the PS and PL. They are routed to either or both CPUs. The SPI interrupts from the PS peripherals are also routed to the PL. 7.1.2 Generic Interrupt Controller (GIC) The generic interrupt controller (GIC) is a centralized resource for managing interrupts sent to the CPUs from the PS and PL. The controller enables, disables, masks, and prioritizes the interrupt sources and sends them to the selected CPU (or CPUs) in a programmed manner as the CPU interface accepts the next interrupt. In addition, the controller supports security extension for implementing a security-aware system. The controller is based on the ARM Generic Interrupt Controller Architecture version 1.0 (GIC v1), non-vectored. The registers are accessed via the CPU private bus for fast read/write response by avoiding temporary blockage or other bottlenecks in the interconnect. The interrupt distributor centralizes all interrupt sources before dispatching the one with the highest priority to the individual CPUs. The GIC ensures that an interrupt targeted to several CPUs can only be taken by one CPU at a time. All interrupt sources are identified by a unique interrupt ID number. All interrupt sources have their own configurable priority and list of targeted CPUs. 7.1.3 Resets and Clocks The interrupt controller is reset by the reset subsystem by writing to the PERI_RST bit of the A9_CPU_RST_CTRL register in the SLCR. The same reset signal also resets the CPU private timers and private watchdog timers (AWDT). Upon reset, all interrupts that are pending or being serviced are ignored. The interrupt controller operates with the CPU_3x2x clock (half the CPU frequency). SoC School - C. Sisterna ICTP
18
Generic Interrupt Controller (GIC)
Each processor has its own configuration space for interrupts Ability to route interrupts to either or both processors Separate mask registers for processors Supports interrupt prioritization Handles up to 16 software-generated interrupts (SGI) Supports 64 shared peripheral interrupts (SPI) starting at ID 32 Processes both level-sensitive interrupts and edge-sensitive interrupts Five private peripheral interrupts (PPI) dedicated for each core (no user- selectable PPI) SoC School - C. Sisterna ICTP
19
Interrupt Flow in the GIC
SoC School - C. Sisterna ICTP
20
System Interrupt in the Zynq
General Interrupt Controller (GIC) Programmable Logic PL0 PL0 – PL 15 Handler USB Handler CAN Handler DMA Handler I2C Handler nnnn Handler SCU Timer Handler CORTEX A9 ... PL15 Interrupt Enabled Devices in the PS ... We should now consider the layout of our processor system, and understand what needs to be done to configure it correctly. We shall start with a block diagram which shows a simplified view of a Zynq device at power-up. Please note the following things, which are all important to the success of this exercise: The Cortex-A9 CPU cores have internal exception handing logic, and this is disabled and initialised at power-up. There is one (standard) interrupt pin on the Cortex-A9 core, and there is a master interrupt handler which the CPU executes when receiving any interrupt request (IRQ). The handler is unassigned. The General Interrupt Controller (GIC) has the ability to manage many interrupt inputs, and has a table which allows interrupt handlers to be assigned to each incoming interrupt. Each interrupt input on the GIC has an enable “switch” that is disabled by default. Each peripheral / interrupt source has an output enable “switch”, that is disabled by default. Master Interrupt Handler Exception Handler Logic IRQ SCU Timer PL PS SoC School - C. Sisterna ICTP
21
Software Generated Interrupts (SGI)
Each CPU can interrupt itself, the other CPU, or both CPUs using a software generated interrupt (SGI) There are 16 software generated interrupts An SGI is generated by writing the SGI interrupt number to the ICDSGIR register and specifying the target CPU(s). All SGIs are edge triggered. There are 16 software generated interrupts An SGI is generated by writing the SGI interrupt number to the ICDSGIR register and specifying the target CPU(s). This write occurs via the CPU's own private bus. Each CPU has its own set of SGI registers to generate one or more of the 16 software generated interrupts. The interrupts are cleared by reading the ICCIAR (Interrupt Acknowledge) register or writing a 1 to the corresponding bits of the ICDICPR (Interrupt Clear-Pending) register. All SGIs are edge triggered. The sensitivity types for SGIs are fixed and cannot be changed; the ICDICFR0 register is read-only, since it specifies the sensitivity types of all the 16 SGIs. SoC School - C. Sisterna ICTP
22
CPU Private Peripheral Interrupts (PPI)
Each CPU connects to a private set of five peripheral interrupts PPI Includes The global timer, private watchdog timer, private timer, and FIQ/IRQ from the PL IRQ IDs reserved, global timer 27, nFIQ 28, private timer 29, watchdog timer 30, nIRQ 31 SoC School - C. Sisterna ICTP
23
Shared Peripheral Interrupts (SPI)
A group of approximately 60 interrupts from various peripherals can be routed to one or both of the CPUs or the PL. The interrupt controller manages the prioritization and reception of these interrupts for the CPUs. Except for IRQ #61 through #68 and #84 through #91, all interrupt sensitivity types are fixed by the requesting sources and cannot be changed. The GIC must be programmed to accommodate this. The boot ROM does not program these registers; therefore the SDK device drivers must program the GIC to accommodate these sensitivity types. For an interrupt of level sensitivity type, the requesting source must provide a mechanism for the interrupt handler to clear the interrupt after the interrupt has been acknowledged. This requirement applies to any IRQF2P[n] (from PL) with a high level sensitivity type. For an interrupt of rising edge sensitivity, the requesting source must provide a pulse wide enough for the GIC to catch. This is normally at least 2 CPU_2x3x periods. This requirement applies to any IRQF2P[n] (from PL) with a rising edge sensitivity type. The ICDICFR2 through ICDICFR5 registers configure the interrupt types of all the SPIs. Each interrupt has a 2-bit field, which specifies sensitivity type and handling model. SoC School - C. Sisterna ICTP
24
Shared Peripheral Interrupts (SPI)
SoC School - C. Sisterna ICTP
25
Connecting Interrupt Source to GIC
The GIC also provides access to the private peripheral interrupts from the programmable logic (PL) Basically a direct connection to the CPU's interrupt input Bypasses the GIC Corex_nFIQ (ID 28) Corex_nIRQ (ID31) SoC School - C. Sisterna ICTP
26
Processing a Harwdware Interrupt
SoC School - C. Sisterna ICTP
27
Detailed Procedure The processor completes the current instruction
The processor disables further interrupts, saves the content of the status register, and saves the content of the program counter, which is the next address of normal program execution The processor transfers execution to the top-level exception handler by loading the program counter with the predetermined exception handler address The exception handler saves the contents of the processor's registers The exception handler determines the cause of the interrupt The exception handler calls the proper ISR according to the cause SoC School - C. Sisterna ICTP
28
Detailed Procedure (cont’)
The ISR clears the associated interrupt condition The ISR performs the designated device-specific function and then returns the control to the exception handler The exception handler restores the contents of the processor's registers and enables future interrupts The exception handler exits by issuing the eret (exception return) instruction The processor executes the eret instruction, which restores the status register and loads the previous saved return address to the program counter The processor resumes the normal program execution from the interrupted point SoC School - C. Sisterna ICTP
29
Interrupt Handling in Cortex-A9 Processor
In order to support interrupts, They must be connected Interrupt signals from on-core peripherals are already connected Interrupt signals from PL must explicitly be connected They must be enable in the Zynq PS They must be enabled in software Use peripheral’s API Interrupt service routine must be developed ‘C’ defined functions and user code SoC School - C. Sisterna ICTP
30
‘C’ Code for Hardware Interrupt
SoC School - C. Sisterna ICTP
31
Pseudo Code for Hardware Interrupt
int main (void) { assign_interrupt_handler(&my_doorbell, front_door_interrupt_handler); while(1) print("I’m watching TV\n\r"); } return(0); void front_door_interrupt_handler (void) print("My pizza has arrived!\n\r"); We have seen from the last exercise that peripheral based timers can be very useful for accurately measuring time, and represent a much more elegant solution than using variable delay loops in software. Although we have cured the problems of inaccuracy, in the previous exercise we are still polling the timer which is an inefficient use of processor time. To cure this inefficiency, we can use interrupts. An interrupt is simply an event which causes the processor to stop what it is doing, make a record of the stage it had reached and the contents of all its internal registers, and then begin work on a new task by executing a different piece of software. The alternate task usually performs a specific function which is related to handling the event which caused the interrupt, and thus we call the alternate piece of software an "interrupt handler". An interrupt handler is written in C code just like any other function, and we then assign the interrupt handler function to the peripheral using some special C functions supplied in the BSP. The Xilinx BSP automates the rest of the flow, and our software will return the processor to the original task once the interrupt handler has executed to completion. People often get confused about interrupts, and don’t always understand why they are helpful in software design. The easiest way to understand interrupts is to liken them to a simple household scenario. Imagine the front door of your house, and imagine you’re sitting inside the house watching TV. How do you know if there is somebody waiting at your door with the pizza that you ordered? One method is that you could routinely get up, walk to the door, and check. If you check very regularly, then you stand a good chance of finding your pizza at the exact moment it arrives, but you’ll spend a lot of wasted time going back and forth, you’ll miss most of your TV show, and your neighbours will think you’re odd. If you check less often then you will waste less of your time, you’ll see more TV, but you might need to be quite lucky in order to get your pizza before it gets cold. This is “polling”; a constant checking process that requires a lot of manual work. All of the same principles apply in The second method is to install a doorbell. When pizza boy arrives, he sends you a signal using a button by the door, and you are notified. You can then stop watching TV, and go to the door only when needed. It takes a bit more time to set up the system in the first place, but ultimately it’s more efficient. This is an interrupt. Again, all of the same principles apply in software. Simple, huh? Here is an example of a piece of code that could write a line of text to the UART when an interrupt was generated. At the moment we will not worry about how or why the interrupt was generated, but simply study it as a textbook example of how the code might appear in C: . Interrupts can be generated by many different peripherals, but for this exercise we will be generating interrupts from the Snoop Control Unit Timer peripheral that we used in the previous exercise. In the last exercise we were operating the timer in polled mode, although the timer peripheral is in fact capable of producing interrupts. The Zynq documentation states that an interrupt is generated by the timer whenever it reaches zero, so we shall use this feature to our advantage. In order to use interrupts, we need to use a few more driver functions to enable the interrupt functionality on the timer, to enable interrupts on the ARM processor, and also to set up the interrupt controller. For the beginner, this process can get a bit scary, but I’ll walk you through it. You’re going to need coffee for this next bit. No really... please get coffee! Let’s look at the software flow for an interrupt. We start in the main part of the code, and then when an interrupt occurs we jump first into a supplied general purpose interrupt handler, and then again into your custom interrupt handler. The supplied interrupt handler does all of the important tasks such as saving the state of the processor, and tidying up any mess that is caused by the interruption. All you have to do is to write the code that you want to execute when the interrupt occurs. SoC School - C. Sisterna ICTP
32
USING INTERRUPTS IN Xilinx SDK
Interrupts are supported and can be implemented on a bare-metal system using the standalone board support package (BSP) within the Xilinx Software Development Kit (SDK). The BSP contains a number of functions that greatly ease this task of creating an interrupt-driven system. They are provided within the following header files: Xparameters.h – This file contains the processor’s address space and the device IDs. Xscugic.h – This file holds the drivers for the configuration and use of the GIC. Xil_exception.h – This file contains exception functions for the Cortex-A9. SoC School - C. Sisterna ICTP
33
Requirements for an Interrupt Routine Service
Requirements for including an interrupt into the application Write a void software function that services the interrupt Use the provided device IP routines to facilitate writing the ISR Clear interrupt Perform the interrupt function Re-enable interrupt upon exit Register the interrupt handler by using an appropriate function Single external interrupt registers with the processor function Multiple external interrupts register with the interrupt controller The call back registration argument is optional SoC School - C. Sisterna ICTP
34
Hardware Interrupt -Example Code
SoC School - C. Sisterna ICTP
35
SCU Timer Interrupt: Detailed Study
The Zynq documentation states that an interrupt is generated by the timer whenever it reaches zero, so we can use this feature to generate a hardware. To configure the ARM processor to be able to answer to an interrupt request from the SCU Timer the following steps have to be implemented: Enable interrupt functionality on the SCU Timer Enable interrupts on the ARM Processor Set up the Interrupt Controller Interrupts can be generated by many different peripherals, but for this exercise we will be generating interrupts from the Snoop Control Unit Timer peripheral that we used in the previous exercise. In the last exercise we were operating the timer in polled mode, although the timer peripheral is in fact capable of producing interrupts. The Zynq documentation states that an interrupt is generated by the timer whenever it reaches zero, so we shall use this feature to our advantage. In order to use interrupts, we need to use a few more driver functions to enable the interrupt functionality on the timer, to enable interrupts on the ARM processor, and also to set up the interrupt controller. For the beginner, this process can get a bit scary, but I’ll walk you through it. You’re going to need coffee for this next bit. No really... please get coffee! SoC School - C. Sisterna ICTP
36
Main Code for the SCU Timer Interrupt – Step 1
In a processor like the ARM Cortex-A9, all interrupts are managed by, and connected via, the general interrupt controller. So our first task is to create instances of the general interrupt controller (GIC) and the timer, and initialise them both. This is done in the same way as before, using the “Lookup_Config” and “CfgInitialize” functions. SoC School - C. Sisterna ICTP
37
Step 2 Next we need to initialize the exception handling features on the ARM processor. This is done using a function call from the “xil_exception.h” header file. SoC School - C. Sisterna ICTP
38
Step 3 When an interrupt occurs, the processor first has to interrogate the interrupt controller to find out which peripheral generated the interrupt. Xilinx provide an interrupt handler to do this automatically, and it is called “XScuGic_InterruptHandler”. When an interrupt occurs, the processor first has to interrogate the interrupt controller to find out which peripheral generated the interrupt. Xilinx provide an interrupt handler to do this automatically, and it is called “XScuGic_InterruptHandler”. To use this supplied handler, we have to assign it to the interrupt controller. The syntax is pretty scary, but it’s the same for all designs so it can just be copied and pasted for every design that you create. The only item that needs to be changed is the name of the GIC instance at the end of the function (in our case “&my_Gic”). SoC School - C. Sisterna ICTP
39
Step 4 We now need to assign our interrupt handler, which will handle interrupts for the timer peripheral. In our case, the handler is called “my_timer_interrupt_handler”. It’s connected to a unique interrupt ID number which is represented by the “XPAR_SCUTIMER_INTR” (“xparameters.h” ). We now need to assign our interrupt handler, which will handle interrupts for the timer peripheral. In our case, the handler is called “my_timer_interrupt_handler”. It’s connected to a unique interrupt ID number which is represented by the “XPAR_SCUTIMER_INTR”. You’ll find a list of these IDs in the “xparameters_ps.h” header file, and they cover all of the peripherals in the PS which generate interrupts. If you were dealing with an interrupt which came from a peripheral in the PL, you’d find a similar list in the “xparameters.h” header file. SoC School - C. Sisterna ICTP
40
Step 5 The next task is to enable the interrupt input for the timer on the interrupt controller. Interrupt controllers are flexible, so you can enable and disable each interrupt to decide what gets through and what doesn’t. The next task is to enable the interrupt input for the timer on the interrupt controller. Interrupt controllers are flexible, so you can enable and disable each interrupt to decide what gets through and what doesn’t. SoC School - C. Sisterna ICTP
41
Next, we need to enable the interrupt output on the timer.
Step 6 Next, we need to enable the interrupt output on the timer. SoC School - C. Sisterna ICTP
42
Step 7 Finally, we need to enable interrupt handling on the ARM processor. Again, this function call can be found in the “xil_exception.h” header file. SoC School - C. Sisterna ICTP
43
Interrupt Steps in the Zynq
General Interrupt Controller (GIC) Programmable Logic PL0 PL0 – PL 15 Handler USB Handler CAN Handler DMA Handler I2C Handler nnnn Handler SCU Timer Handler my_timer_int_hanlder CORTEX A9 ... PL15 Interrupt Enabled Devices in the PS ... We should now consider the layout of our processor system, and understand what needs to be done to configure it correctly. We shall start with a block diagram which shows a simplified view of a Zynq device at power-up. Please note the following things, which are all important to the success of this exercise: The Cortex-A9 CPU cores have internal exception handing logic, and this is disabled and initialised at power-up. There is one (standard) interrupt pin on the Cortex-A9 core, and there is a master interrupt handler which the CPU executes when receiving any interrupt request (IRQ). The handler is unassigned. The General Interrupt Controller (GIC) has the ability to manage many interrupt inputs, and has a table which allows interrupt handlers to be assigned to each incoming interrupt. Each interrupt input on the GIC has an enable “switch” that is disabled by default. Each peripheral / interrupt source has an output enable “switch”, that is disabled by default. 1 Master Interrupt Handler Exception Handler Logic IRQ SCU Timer 2 6 5 4 3 PL PS SoC School - C. Sisterna ICTP
44
IRS - Interrupt Handler - 1
Now we need to write an interrupt handler, which is the function that will be called when the interrupt occurs. We’ve already decided on a name because we used it above; “my_timer_interrupt_handler”. It is considered good programming practice when coding an interrupt handler function to first check to make absolutely sure that the right peripheral has raised the interrupt. Lots of headaches can be created when a software engineer starts making decisions in their code because they believe one interrupt has occurred, when actually it’s a completely different one. This problem is hard to detect because in most cases you have no way of checking which interrupt has occurred. Xilinx has solved this problem by including some clever code in their driver, using something called a “CallBackRef”. We discussed before that there is a supplied interrupt handler which is provided by Xilinx for the interrupt controller, called “XScuGic_InterruptHandler”. This handler is the one that calls our handler, but it also helpfully passes information about the driver instance which is relevant to the peripheral that generated the interrupt. This is the CallBackRef. In practice, this means that from the moment we enter our interrupt handler, the Xilinx drivers have already given us the details of which peripheral generated the interrupt. We can clearly see the “CallBackRef” that is passed into the function, and we can use it to our advantage. Suppose we wanted to control the timer as part of our interrupt handler code? Without the CallBackRef we couldn’t do it, because the original instance of “my_Timer” doesn’t exist in the scope of this function. (We declared it in main() and therefore it cannot be directly used in our interrupt handler because our handler is a different function) SoC School - C. Sisterna ICTP
45
IRS - Interrupt Handler - 2
We can declare a local copy of the “my_Timer” instance, and assign it the information provided by the “CallBackRef” But we can declare a local copy of the “my_Timer” instance, and assign it the information provided by the “CallBackRef The instance “my_Timer_LOCAL” is now an exact copy of the one in our “main” function, and we can control the timer in the same way as we did before. Any changes to “my_Timer_LOCAL” will also apply to the original copy of “my_Timer”, because they are linked together using a pointer. SoC School - C. Sisterna ICTP
46
IRS - Interrupt Handler - 3
we now want to check to make sure that the timer really did generate this interrupt. Returning to our previous comments on good coding practices, we now want to check to make sure that the timer really did generate this interrupt. To do that we can use a standard function from the timer’s header file. All of the functions will work on “my_Timer_LOCAL” in the same way that they did in “main” for the original instance of “my_Timer”, because they are declared as the same data type (“XScuTimer”): SoC School - C. Sisterna ICTP
47
IRS Interrupt Handler - 4
The last task is to clear the interrupt condition in the timer peripheral. If we don’t do this, then the interrupt condition will still be active. The last task is to clear the interrupt condition in the timer peripheral. If we don’t do this, then the interrupt condition will still be active. That means that the moment we exit from our interrupt handler, the processor will jump straight back into it again. The main section of our application would therefore never be executed. Again there is a supplied function call in the timer’s header file to do this, so we need to add it to our interrupt handler : SoC School - C. Sisterna ICTP
48
Interrupt Considerations
SoC School - C. Sisterna ICTP
49
Interrupt Considerations
Interrupts are considered asynchronous events Know the nature of your interrupt Edge or level? How the interrupt is cleared? What happens if another event occurs while the interrupt is asserted? How frequently can the interrupt event occur? Can the system tolerate missing an interrupt? When debugging a system with an interrupt structure, the first milestone is to verify that the interrupt is sensed and the ISR is entered. This can be easily accomplished by setting a breakpoint with the GDB debugger at the first executable statement in the ISR. Often, causes of not seeing an interrupt include: Forgetting to hook up the interrupt port in hardware. Not enabling interrupts to the processor. Not setting the interrupt enable capability on the peripheral (some peripheral registers have multiple bits to set; that is, global enable and channel enable). Not initializing the processor interrupt structure. Forgetting to register the handler. Having a problem of level versus edge, high versus low type interrupts. It is a system design consideration as to whether a system can or will miss interrupts. SoC School - C. Sisterna ICTP
50
ISR Considerations Timing Can the ISR be interrupted? Code portability
What is the latency from the hardware to the ISR? Operating system can aggravate this Are the interrupts prioritized? How long can the ISR be active before affecting other things in the system? Can the ISR be interrupted? If so, code must be written to be reentrant A practice to be avoided Code portability Are operating system hooks needed? SoC School - C. Sisterna ICTP
51
ISR Tips and Tricks Keep the code short and simple; ISRs can be difficult to debug Do not allow other interrupts while in the ISR This is a system design consideration and not a recommended practice The interrupt priority, when using an interrupt controller, is determined by the hardware hookup bit position on the interrupt input bus Time is of the essence! Spend as little time as possible in the ISR Do not perform tasks that can be done in the background Use flags to signal background functions Make use of provided interrupt support functions when using IP drivers Do not forget to enable interrupts when leaving the handler/ISR Make use of the callback argument passed in registration SoC School - C. Sisterna ICTP
52
How to write a Good ISR Keep the interrupt handler code brief (in time) Avoid loops (especially open-ended while statements) Keep the interrupt handler simple Interrupt handlers can be very difficult to debug Disable interrupts as they occur Re-enable the interrupt as you exit the handler Budget your time Interrupts are never implemented for fun—they are required to meet a specified response time Predict how often an interrupt is going to occur and how much time your interrupt handler takes Spending your time in an interrupt handler increases the risk that you may miss another interrupt SoC School - C. Sisterna ICTP
53
ISR: Precautions Despite its simplistic appearance, scheduling with interrupt can be very involved and may complicate the software development. ISRs are the most error-prone portion in embedded software. Since an ISR can be invoked any time during program execution, it is difficult to develop, debug, test, and maintain. ISRs complicate the timing analysis of the main polling loop. We must consider the frequency of occurrence and duration of the ISRs to ensure that normal tasks within the polling loop can be executed in a timely manner. When multiple interrupts are used, an ISR may effect and interfere with other ISRs and the complexity multiplies. To ease the problem, it is good practice to keep ISRs simple and fast. We should use an ISR to perform the most essential functionalities, such as setting event flags, updating counters, sending a message to a queue, etc., and leave the non- critical computation to a task within the main polling loop. This simplifies the ISR development and timing analysis. Despite its simplistic appearance, scheduling with interrupt can be very involved and may complicate the software development. First, ISRs are the most error-prone portion in embedded software. Since an ISR can be invoked any time during program execution, it is difficult to develop, debug, test, and maintain. Second, ISRs complicate the timing analysis of the main polling loop. We must consider the frequency of occurrence and duration of the ISRs to ensure that normal tasks within the polling loop can be executed in a timely manner. When multiple interrupts are used, an ISR may effect and interfere with other ISRs and the complexity multiplies. To ease the problem, it is good practice to keep ISRs simple and fast. We should use an ISR to perform the most essential functionalities, such as setting event flags, updating counters, sending a message to a queue, etc., and leave the non-critical computation to a task within the main polling loop. This simplifies the ISR development and timing analysis. The example in Section follows this principle. The ISR only increments the sys_ms_tick variable and the lecLf lash_v4() function in the main polling loop examines the variable and performs the remaining computation. SoC School - C. Sisterna ICTP
54
Performance The top-level exception handler timing includes three parts Hardware interrupt latency: from the time when an interrupt is asserted to the time when the processor executes the instruction at the exception address. Response time: from the time when an interrupt is asserted to the time when the processor executes the first instruction in the ISR. It includes the time for the exception handler to determine the cause of the interrupt and save the content of register file. Recovery time: the time taken from the last instruction in the ISR to return to normal processing SoC School - C. Sisterna ICTP
55
ISR performance enhancement
Some techniques are: Adjust the buffer size or implement advanced features, such as double buffering. Utilize DMA (direct memory access) controllers to transfer data between memory modules. Implement custom hardware accelerator to perform computation intensive processing. The SoC platform introduces a new dimension of flexibility. We can examine the performance criteria and design complexity and find the best trade-off between software and hardware resources. Keeping ISRs simple and fast is one of the most important design principles in embedded software development. Traditionally, this is done by moving the non-critical computation out of the interrupt context. With the availability of programmable logic, the SoC platform provides an alternative to enhance ISR performance. We can invest additional hardware resource to reduce the software processing time. SoC School - C. Sisterna ICTP
56
Apendix SoC School - C. Sisterna ICTP
57
Cortex A9 – Modes and Registers
Cortex-A9 has seven execution modes Five are exception modes Each mode has its own stack space and different subset of registers System mode will use the user mode registers SoC School - C. Sisterna ICTP
58
Cortex A9 – Modes and Registers
Cortex-A9 has 37 registers Up to 18 visible at any one time Execution modes have some private registers that are banked in when the mode is changed Non-banked registers are shared between modes Each mode can access: A particular set of registers within r0 to r12 registers. These are general-purpose registers. A dedicated r13 register (Stack pointer, sp) and the r14 register (Link Register, lr). The program Counter r15 which will be common to all modes The current program status register r16. The cpsr (r16) register holds the current program status and is shared amongst all modes. When an exception occurs, the contents of cpsr is pushed into the saved program status register (spsr) corresponding to that exception mode. SoC School - C. Sisterna ICTP
59
Application Software for HI
Set a direction control for the AXI GPIO pin as an input pin, which is connected with BTNU push button on the board. The location is fixed via LOC constraint in the user constraint file (UCF) during system creation. Initialize the AXI TIMER module with device ID 0. Associate a timer callback function with AXI timer ISR. This function is called every time the timer interrupt happens. This callback switches on the LED ‘LD9’ on the board and sets the interrupt flag. The main() function uses the interrupt flag to halt execution, wait for timer interrupt to happen, and then restarts the execution. Set the reset value of the timer, which is loaded to the timer during reset and timer starts. Set timer options such as Interrupt mode and Auto Reload mode. Zedboard_refdoc_Vivado_2014-2_cs.pdf SoC School - C. Sisterna ICTP
60
Application Software for HI
Initialize the PS section GPIO. Set the PS section GPIO, channel 0, pin number 7 to the output pin, which is mapped to the MIO pin and physically connected to the LED ‘LD9’ on the board. Set PS Section GPIO channel number 2 pin number 0 to input pin, which is mapped to PL side pin via the EMIO interface and physically connected to the BTNR push button switch. Initialize Snoop control unit Global Interrupt controller. Also, register Timer interrupt routine to interrupt ID '91', register the exceptional handler, and enable the interrupt. Execute a sequence in the loop to select between AXI GPIO or PS GPIO use case via serial terminal. The software accepts your selection from the serial terminal and executes the procedure accordingly. After the selection of the use case via the serial terminal, you must press a push button on the board as per the instruction on terminal. This action switches off the LED ‘LD9’, starts the timer, and tells the function to wait for the Timer interrupt to happen. After the Timer interrupt happens, LED 'LD9'' switches ON and restarts execution. For more details about the API related to device drivers, refer to the Zynq-7000 Software Developers Guide (UG821) linked to in the previous chapter. SoC School - C. Sisterna ICTP
Similar presentations
© 2025 SlidePlayer.com Inc.
All rights reserved.