The startup code used in the GNU project is different in that the Keil Assembler has different directives and naming conventions. However, it is performing the same operations. It is up to the programmer to edit the vector table as discussed in the section on the Keil compiler startup code. The graphical editor allows you to configure the processor stacks and system peripherals in the same way as the Keil compiler startup code.
6.3 Interworking ARM/THUMB Code
The GCC compiler also supports the ARM procedure calling standard and allows interworking between the ARM and THUMB instruction sets. However, unlike the Keil compiler, it is not possible to select individual functions as ARM or THUMB. In the GCC compiler all ARM code must be in one module or modules and the THUMB code must be in separate modules. These modules are compiled as ARM or THUMB as required and then linked together. This process is described in example 3 in this section.
6.4 Accessing Peripherals
The Keil and GNU compilers can use the same include files to access the on-chip SFR registers.
6.5 Interrupt Service Routines
The GCC compiler has a set of non-ANSI extensions which allow functions to be declared as interrupt routines. The general form of the declaration is shown below
void IRQ_Routine (void) __attribute__ ((interrupt("IRQ"))); The following keywords are available to define the exception source required: FIQ,IRQ,SWI,UNDEF.
This function declaration is only required on the function prototype and should not be used on the main body of the function. An interrupt service routine is shown in example 5.
6.5.1 Software Interrupt
There is no real software interrupt support in the GCC compiler. To generate a software interrupt you must use inline Assembler as shown below:
#define SoftwareInterrupt2 asm (" swi #02")
This will place a SWI instruction encoded with the value 2 in your code. Next it is possible to declare a pointer to a CPU register using the non-ANSI register keyword as shown below:
register unsigned * link_ptr asm ("r14");
This allows us to read the contents of the link register when we enter the ISR. When the SWI instruction is executed, the CPU will enter supervisor mode and jump to the SWI vector. The address of the SWI instruction plus four will be stored in the link register. On entry to the software interrupt ISR the following line of code is executed:
temp = *(link_ptr-1) & 0x00FFFFFF;
The address stored in the link register is rolled back by one instruction (word-wide pointer i.e. four bytes) so that it is pointing at the address of the SWI instruction which generated the exception. The top eight bits of the SWI instruction are masked off and bits 0-23 are copied into the temp variable. This in effect loads the number 2 into the temp variable. A switch statement can now be used to run the desired code. This method of handling software interrupts is shown in example 6.
6.6 Inline Functions
Within the GNU compiler functions may be declared as inline functions as follows: inline int fast_function(char param1)
6.7 Exercise 1: Using The Keil Toolset With The GNU Compiler
This example is based on the source code which can be found in: C:\Exercise\Work\EX1 first program
In this first exercise we will spend some time defining a first project, building the code and downloading it into the Simulator for debugging. We will then cover the basic debugging functions of the Keil simulator.
The Keil uVision IDE is designed to support several compilers: the GNU C compiler, the ARM development suite and the Keil ARM compiler. Before compiling, make sure you have the GNU compiler selected. This is done by activating the project workspace, right-clicking and selecting ‘manage components’. In this dialog, select the Folders/extensions tab and make sure the GNU tools box is selected.
Double-click on the Keil UVision3 icon to start the IDE.
In the New Project dialog navigate to your desired project directory.
In the New Project dialog name the project first.uv2 and select Save.
A ‘select new device for target’ dialog will appear. Navigate through the device data base and select the Philips\LPC2129 folder and select OK.
In the project browser highlight the ‘Target1’ root folder and select the local menu by pressing the right mouse button. In this menu select ‘Options for Target’.
In the ‘Target’ tab set the simulation frequency to 12.000 MHz.
In the Linker tab select the linker file flash.ld and tick the “Garbage collection” and do not use “standard startup files” boxes
Note
:
To build the project so it will run within the on-chip RAM of the LPC2100 device, configure the Text start as select the linker file RAM.ldIn the debug tab make sure the “Use Simulator” radio button is active. Also make sure “Load Application at Startup” and “Go till main()” are checked.
Select OK to complete the target options.
In the project browser expand the ‘Target1’ root node to show the Source group 1 folder.
Highlight the ‘Source Group 1’ folder, open the local menu with a right click and select ‘Add Files to group Source Group1’.
Change the ‘Type of file’ filter to ASM and add the file startup.s These are all the source files necessary for the project so select close.
You can view the source code contained in a file by double-clicking on the file name in the project browser window.
Once you have added all the source files the project can be built via the program menu or by the build button on the toolbar.
Once the code is built, you can start the simulator by pressing the debugger button. The use of the simulator and JTAG debugger are detailed in Exercise One in the Tutorial and are the same for the GNU compiler.
6.8 Exercise 2: Startup Code
In this exercise we will configure the compiler startup code to configure the stack for each operating mode of the ARM7. We will also ensure that the interrupts are switched on and that our program is correctly located on the interrupt vector.
Open the project in EX2 Startup\work
Open the file Startup.s and using the graphical editor configure the operating mode stacks as follows:
Compile the code
Start the simulator and when the PC reaches main, examine the contents of each R13 register.
Each stack is allocated a space of 0x80. The user stack is 0x400 bytes so user data will start at 0x40003d80 – 0x400
In this example we will build a very simple program to run in the ARM 32-bit instruction set and call a 16-bit THUMB function and then return to the 32-bit ARM mode.
Open the project in EX3 THUMB code\work
In the files browser select thumb.c open the local menu (right-click) and select “options for thumb.c”
Select the CC tab and in the misc controls add –mthumb or tick the “compile thumb code” box and click OK
In the CC tab tick the “enable APCS option and the “support calls between THUMB and ARM”
Compile and download the code into the debugger
Open the disassembly window and single step through the code using the F11 key
Observe the switch from 32-bit to 16-bit code and the THUMB flag in the CPSR
The processor is running in ARM (32-bit ) mode, the T-bit is clear and the instructions are 4 bytes long. A call to the THUMB function is made which executes a BX instruction forcing the processor into THUMB mode (16-bit). The THUMB bit is set and on entry to the THUMB function a PUSH instruction is used to preserve registers on to the stack.