Simulating an interrupt
Adding an interrupt handler
The application—a brief description
Writing an interrupt handler
Setting up the project
Setting up the simulation environment
Defining a C-SPY setup macro file
Setting C-SPY options
Building the project
Starting the simulator
Specifying a simulated interrupt
Setting an immediate breakpoint
Simulating the interrupt
Executing the application
Using macros for interrupts and breakpoints
In this tutorial an interrupt handler for a serial port is added to the project. The Fibonacci numbers are read from an on-chip communication peripheral device (UART).
This tutorial will show how the compiler interrupt keyword and the #pragma vector directive can be used. The tutorial will also show how to simulate an interrupt, using the features that support interrupts, breakpoints, and macros. Notice that this example does not describe an exact simulation; the purpose is to illustrate a situation where C-SPY® macros, breakpoints, and the interrupt system can be useful to simulate hardware.
This tutorial assumes that you are familiar with the basics of the IAR Embedded Workbench® IDE described in the previous tutorials.
Note that interrupt simulation is possible only when you are using the IAR C-SPY Simulator.
Adding an interrupt handler
This section will demonstrate how to write an interrupt in an easy way. It starts with a brief description of the application used in this project, followed by a description of how to set up the project.
The application—a brief description
The interrupt handler will read values from the serial communication port receive register (UART), RBUF. It will then print the value. The main program enables interrupts and starts printing periods (.) in the foreground process while waiting for interrupts.
Note: In this tutorial, the serial communication port UART and the receive buffer register RBUF are symbolic names. To follow this tutorial and simulate the interrupt in the C-SPY Simulator, you should instead use names that are suitable for your target system. See the Interrupt.c file in the cpuname\tutor directory.
Writing an interrupt handler
The following lines define the interrupt handler used in this tutorial (the complete source code can be found in the file Interrupt.c in project4 supplied in the cpuname\tutor directory):
/* Defines an interrupt handler. */
#pragma vector=UARTR_VECTOR
__interrupt __root void UartReceiveHandler( void )
The #pragma vector directive is used for specifying the interrupt vector address—in this case the interrupt vector for the UART receive interrupt—and the keyword __interrupt is used for directing the compiler to use the calling convention needed for an interrupt function.
Note: In this tutorial, the name of the vector is symbolic. To follow this tutorial and simulate the interrupt in the C-SPY Simulator, you should instead use a name that is suitable for your target system. See the Interrupt.c file in the cpuname\tutor directory.
For detailed information about the extended keywords and pragma directives used in this tutorial, see the IAR C/C++ Compiler Reference Guide.
Setting up the project
1
Add a new project—project4—to the workspace tutorials used in previous tutorials.
2
Add the files Utilities.c and Interrupt.c to it.
3
In the Workspace window, select the project level node and choose Project>Options.
Make sure default factory settings are used in the General Options, C/C++ Compiler, and Linker categories.
Note: Look in the file Interrupt.c to find information about any target-specific settings that might be required.
Next you will set up the simulation environment.
Setting up the simulation environment
The C-SPY interrupt system is based on the cycle counter. You can specify the amount of cycles to pass before C-SPY generates an interrupt.
To simulate the input to UART, values are read from the file InputData.txt, which contains the Fibonacci series. You will set an immediate read breakpoint on the UART receive register, RBUF, and connect a user-defined macro function to it (in this example the Access macro function). The macro reads the Fibonacci values from the text file.
Whenever an interrupt is generated, the interrupt routine reads RBUF and the breakpoint is triggered, the Access macro function is executed and the Fibonacci values are fed into the UART receive register.
The immediate read breakpoint will trigger the break before the processor reads the RBUF register, allowing the macro to store a new value in the register that is immediately read by the instruction.
This section will demonstrate the steps involved in setting up the simulator for simulating a serial port interrupt. The steps involved are:
*
Defining a C-SPY setup file which will open the file InputData.txt and define the Access macro function
*
*
*
*
*
Note: For a simple example of a system timer interrupt simulation, see the C-SPY® Debugging Guide.
Defining a C-SPY setup macro file
In C-SPY, you can define setup macros that will be registered during the C-SPY startup sequence. In this tutorial you will use the C-SPY macro file SetupSimple.mac, available in the cpuname\tutor directory. It is structured as follows:
First the setup macro function execUserSetup is defined, which is automatically executed during C-SPY setup. Thus, it can be used to set up the simulation environment automatically. A message is printed in the Log window to confirm that this macro has been executed:
execUserSetup()
{
__message "execUserSetup() called\n";
Then the file InputData.txt, which contains the Fibonacci series to be fed into UART, is opened:
_fileHandle = __openFile( "$TOOLKIT_DIR$\\tutor\\InputData.txt", "r" );
After that, the macro function Access is defined. It will read the Fibonacci values from the file InputData.txt, and assign them to the receive register address:
Access()
{
__message "Access() called\n";
__var _fibValue;
if( 0 == __readFile( _fileHandle, &_fibValue ) )
{
RBUF = _fibValue;
}
}
You must connect the Access macro to an immediate read breakpoint. However, this will be done at a later stage in this tutorial.
Finally, the file contains two macro functions for managing correct file handling at reset and exit.
For detailed information about macros, see the C-SPY® Debugging Guide.
Next you will specify the macro file and set the other debugger options needed.
Setting C-SPY options
1
To set debugger options, choose Project>Options. In the Debugger category, click the Setup tab.
2
Use the Use macro file browse button to specify the macro file to be used:
SetupSimple.mac
Alternatively, use an argument variable to specify the path:
$TOOLKIT_DIR$\tutor\SetupSimple.mac
For reference information about argument variables, see the IDE Project Management and Building Guide.
3
The C-SPY interrupt system requires some interrupt definitions, provided by the device description files. With the Device description file option you can specify the appropriate file. See the Interrupt.c file in the cpuname\tutor directory for information about which device description file to be used in this tutorial.
4
Select Run to main and click OK. This will ensure that the debug session will start by running to the main function.
The project is now ready to be built.
Building the project
1
Alternatively, click the Make button on the toolbar. The Make command compiles and links those files that have been modified.
Starting the simulator
1
Click the Download and Debug button to start C-SPY and run the project4 project.
The Interrupt.c window is displayed (among other windows). Click in it to make it the active window.
2
Specifying a simulated interrupt
Now you will specify your interrupt to make it simulate an interrupt every 2000 cycles.
1
Choose Simulator>Interrupt Setup to display the Interrupt Setup dialog box. Click New to display the Edit Interrupt dialog box:
Make these settings for your interrupt:
 
The interrupt definition that the simulator uses to be able to simulate the interrupt correctly.
Specifies the first activation moment for the interrupt. The interrupt is activated when the cycle counter has passed this value.
Repeat interval
Specifies probability. 100% specifies that the interrupt will occur at the given frequency. Another percentage might be used for simulating a more random interrupt behavior.
During execution, C-SPY will wait until the cycle counter has passed the activation time. When the current assembler instruction is executed, C-SPY will generate an interrupt which is repeated approximately every 2000 cycles.
2
When you have specified the settings, click OK to close the Edit Interrupt dialog box, and then click OK to close the Interrupt Setup dialog box.
Setting an immediate breakpoint
By defining a macro and connecting it to an immediate breakpoint, you can make the macro simulate the behavior of a hardware device, for instance an I/O port, as in this tutorial. The immediate breakpoint will not halt the execution, only temporarily suspend it to check the conditions and execute any connected macro.
In this example, the input to the UART is simulated by setting an immediate read breakpoint on the RBUF address and connecting the defined Access macro to it. The macro will simulate the input to the UART. These are the steps involved:
1
Choose View>Breakpoints to open the Breakpoints window, right-click to open the context menu, choose New Breakpoint>Immediate to open the Immediate tab.
2
RBUF
During execution, when C-SPY detects a read access from the RBUF address, C-SPY will temporarily suspend the simulation and execute the Access macro. The macro will read a value from the file InputData.txt and write it to RBUF. C-SPY will then resume the simulation by reading the receive buffer value in RBUF.
3
Click OK to close the breakpoints dialog box.
Simulating the interrupt
In this section you will execute your application and simulate the serial port interrupt.
Executing the application
1
In the Interrupt.c source window, step through the application and stop when it reaches the while loop, where the application waits for input.
2
In the Interrupt.c source window, locate the function UartReceiveHandler.
3
Place the insertion point on the ++callCount; statement in this function and set a breakpoint by choosing Edit>Toggle Breakpoint, or click the Toggle Breakpoint button on the toolbar. Alternatively, use the context menu.
If you want to inspect the details of the breakpoint, choose View>Breakpoints.
4
Open the Terminal I/O window and run your application by choosing Debug>Go or clicking the Go button on the toolbar.
The application should stop in the interrupt function.
5
Click Go again to see the next number being printed in the Terminal I/O window.
Because the main program has an upper limit on the Fibonacci value counter, the tutorial application will soon reach the exit label and stop.
The Terminal I/O window will display the Fibonacci series.
Using macros for interrupts and breakpoints
To automate the setting of breakpoints and the procedure of defining interrupts, the system macros __setSimBreak and __orderInterrupt, respectively, can be executed by the setup macro execUserSetup.
The file SetupAdvanced.mac is extended with system macro calls for setting the breakpoint and specifying the interrupt:
simulationSetup()
{...
_interruptID = _  _orderInterrupt( "UARTR_VECTOR", 4000,
2000, 0, 1, 0, 100 );
 
if( -1 == _interruptID )
{
__message "ERROR: failed to order interrupt";
}
 
_breakID = __setSimBreak( "RBUF", "R", "Access()" );
}
If you replace the file SetupSimple.mac, used in the previous tutorial, with the file SetupAdvanced.mac, C-SPY will automatically set the breakpoint and define the interrupt at startup. Thus, you do not need to start the simulation by manually filling in the values in the Interrupts and Breakpoints dialog boxes.
Note: Before you load the file SetupAdvanced.mac you should remove the previously defined breakpoint and interrupt.