29 ARM Instruction and Embedded C
Dr Selvi Ravindran
About the module:
Thismoduleaims to give a detailed introduction on privileged instructions.The interrupt based instructions and program status instructions are critical instructions of the ARM ISA which change the processor mode. The coprocessor instruction is also discussed briefly. We summarise by listing the thumb instructions and embedded C program for ARM chip LPC2148.
Learning Outcomes:
- Able to understand the nuances of ARM instruction. Able to compare ARM and Thumb instructions.
- Should be able to write an arm based embedded C program.
1.1 ARM Instruction set classification
ARM instruction set are classified as Data processing instructions, Control flow instructions(Branch instruction), Data transfer instructions (Load-store instruction, Swap instruction), Software Interrupt instruction, Program status register instruction and Coprocessor instruction. In the following section we will examine the function and syntax of the last three categories.
1.2 Software Interrupt Instruction
Software Interrupt instruction(SWI) causes an interrupt on execution. It is a user-defined instruction.This instruction is used to call the service routines provided by the operating system (OS). The OS executes the Interrupt service routine (ISR)in the privileged mode, referredto as the supervisor mode (SVC). The OS kernel operates in this mode. The privileged mode allows complete access to CPSR which helps the processor to mask the successive interrupts.
The syntax of the interrupt instruction is:SWI{<cond>}<24-bit immediate>
Before executing this instruction the processor saves the address of the next instruction in r14_svc. Saves the CPSR in SPSR_svc.It then enters the supervisor mode and disables IRQs by setting CPSR[4:0] to 100112 and CPSR[7] to 1. Sets the PC to 0x08 and begins executing the instruction from there. The 24-bit immediate value in the SWI does not influence the operation of the instruction but is used to interpretan associated system code or feature. Given below are examples of SWI instruction.
Software interrupt or supervisor call
SWI SW_WriteC ;output r0[7:0]
SWI SW_Exit ;return to monitor program
1.3 Program Status Register (PSR) Instruction
The ARM processor provides two instructions to access thePSR: 1. PSR to general register, 2. General register to PSR. MRS instruction transfers the content from the CPSR or SPSR to a register and the MSR transfers from register to the PSR. Both the instructions basically provide a read and a write instructiononthe PSR. The syntax of MRS instruction is:
MRS{<cond>} Rd,CPSR|SPSR
The CPSR or the current mode SPSR is copied into the destination register. Given below is an example where the 32 bits of PSRare copied into r0 and r3 registers.
MRS r0,CPSR
MRS r3,SPSR
The syntax of MSR instruction is:
MSR{<cond>} CPSR_<field>|SPSR_<field>,#<32-bit immediate>
MSR{<cond>} CPSR_<field>|SPSR_<field>,Rm
The field option in MSR instruction can be one of the four options (bytes) shown in Figure 1.1. These are C– the control field PSR[7:0], X – the extension field PSR[15:8],S – the status field PSR[23:16] and F – the flag field PSR[31:24]. Given below is an example which sets N, Z, C, V flags of the CPSR.
MSR CPSR_f, #&f0000000
1.4 Coprocessor Instruction
The ARM architecture supports 16 coprocessors. The coprocessor instructions are used to extend the ARM instruction set. They add to the computation and control capability of ARM. The instructions for each coprocessor occupy a fixed part of the ARM ISA. If the appropriate coprocessor is not present in the system, an undefined instruction exception occurs.There are three types of coprocessor instructions- data processing, register transfer and memory transfer. Table 1.1 shows the instruction types associated along with the coprocessor mnemonics and explanation.
2 Thumb Execution state
The ARM core has two execution states – ARM and Thumb. In the ARM state, the processor executes ARM instruction set and in the Thumb state the processor executes Thumb instruction set. Switching between the two states can be done using BX instruction. ARM processors always start executing code in ARM state.ARM architecture versions v4T and above define and support the 16-bit Thumb instruction set. Thumb encodes a subset of ARM instructions. It is optimized for higher code density. It has an improved performance for memory constrained systems. In mobile phones and PDAs, there is a tradeoff between the cost and the processing capability. The high code density in thumb gives better performance in such systems. On average, a Thumb implementation of the same code takes around 30% less memory than ARM implementation [1].
2.1 Thumb Registers
Thumb has a restrictive access to the registers. The lower set registers r0 to r7 are fully accessible. The higher set r8 to r12 can be accessed via MOV, ADD and CMP instruction. The r13 to r15 are for special functions as common with ARM state. The r13 is used as the stack pointer; r14 is used as the link register and r15 is used as the program counter. There is no direct access to the CPSR and SPSR registers. We need to move to the ARM state for accessing these registers via MRS and MSR instruction.
2.2 Thumb Instructions
Thumb instruction set has a fewercharacteristics unlike its ARM counterpart:
a) Most Thumb instructions are executed unconditionally.
b) Many Thumb data processing instructions use a 2-address format.
c) Thumb instructions are less regular than ARM, due to dense encoding.
d) Fairly complex instruction formats.
e) Separate shift operations provided, no shifting of second operand.
f) All data processing instructions set condition code bits (no need of ‘S’).
2.2.1 Thumb data processing instruction
As in ARM, the data processing instructions manipulate data within register. The arithmetic instruction, logical instruction, multiply instruction, shift instruction, compare instruction and move instruction – all belong to this category. The syntax of data processing instructions is given below:
<op> Rd, Rm
<op> Rd, Rn, # <imm32>
<op>Rd|Rn, Rm|Rs
<op> Rd, Rn, #<sh 5>
<op> Rd, #<imm 8>
Table 1.2 shows a few data processing operations with their mnemonics and explanation.
The data transfer boundary alignment is same as the datatype size.
2.2.2 Thumb data transfer instruction
Single register load and store instruction transfers signed and unsigned byte, (16-bit) half word and (32-bit) word. The LDR and STR instructions use preindex addressing mode with the offset in the register or as an immediate value. The load/store multiple instruction supportincrement after addressing mode.
The syntax of the instruction is:
LDR/STR{Half word/Byte} Rd, address
Signed operands:
LDR|STR {S} {H|B} Rd, [Rn, Rm]
Table 1.3 shows the data types associated with load/store operations with their mnemonics and explanation.
The data transfer boundary alignment is same as the datatype size.
2.2.3 Thumb Instruction Limitations
Given that Thumb instruction has a compact machine codeword, there are a few features of ARM instructions which have been laid-off. The code space is saved by eliminating the conditional execution of the instructions. This saves the 4 bits space allocated for indicating the condition check in every ARM instruction. Thumb instructions are two address format, which implies that one of the source register is going to act as destination register after completion of the operation. In the register set only the lower registers are used, reducing the bits for addressing. Similarly the constants are limited in size. Lastly, as the inline barrel shifter is not used, the provision of shifting the second operand is not available with Thumb instructions.
3 Embedded C for ARM
The embedded application are generally written in embedded C. This high level language has syntax and semantics of C and has extension to address issues in embedded systems. The C code could be written targeting the Thumb or the ARM instruction.In this section we consider an embedded C example program for LPC 2148 ARM processor. Before explaining the program let us try to understand the basic details of it. LPC2148 is a ARM7TDMI-S microcontroller, referred as Strong ARM given the variety of features it has. It belongs to the ARM 7 family and the revision version of ARMv4T. It includes MMU, and Unifiedcache. It implements a five stage pipeline. The TDMI in its name describes the feature enhancement given to this version. HereTcorrespondsto Thumb instruction set.D: on-chip Debug support, enabling the processor to halt in response to a debug request. It implements a JTAG protocol to debug information between the processor and the test equipment. M: enhanced high performance fast Multiplier which yields a full 64-bit result.I: Embedded ICE is a debug hardware that allows to trace the program. Figure 1.2 shows the pin diagram of LPC 2148. It is a 64 pin chip where most of the pins are multiplexed except a few pins like Vcc, Gnd, XTAL and RESET.
The processor has an on chip memory of: 32KB SRAM. It has a unified Data(D) and Instruction(I) storage. The memory can be accessed as byte, half word, word. It has a 512KB flash memory : D + I storage. It has a Serial built-in JTAG interface. The JTAG uses the UART0 to send and receive debug information. In Application Programming (IAP) capabilities allows the processor to be programmed under the control of firmware.
ARM7TDMI has two I/O Ports: P0 (32 bits)and P1 (16bits) each. All the pins of port P0 are available for I/O, whereas half word of port PI isaccessed as I/O as described in Table 1.4.The port pins are multiplexed. Each pin performs utmost 4 alternate functions. For Ex. P0.8 – àGeneral purpose Input and output (GPIO), Transmitter of Universal Asynchronous Receive and Transmit (UART1), Pulse Width Modulation (PWM4) and Analog and Digital(AD1.1).
To access the port pins, a few control egisters are to beprogrammed. Registers controlling P0 and P1ports are IOPIN, IODIR,IOSEL, IOCLR and IOSEL. The functionalities of these registers are as follows:
IOSEL : selects one function among the four (default function =GPIO). There are three IOSEL registers to select the port pins as shown inTable 1.5(a). Each IOSEL register configures the half word of port pins. Table 1.5(b) shows the bit options of IOSEL for the different multiplexed operations available on its pins. On RESET all pins are configured as GPIO in input mode.Two bits in IOSELX are used for selection among the four functions . Here X = 0, 1 & 2 corresponding to the three different ports selected.
IOPIN: It is a GPIO pin value register. Current state of GPIO port pins can be read from this register irrespective of the port pin direction.
IODIR: GPIO port direction control register. This is used to configure the port direction. Each bit in this register corresponds to the read/ write mode of the port pin. A one in the register bit indicates that the pin is an output pin and a zero means that the pin is an input pin.
IOCLR and IOSET: Clears and sets the port pins by writing ones into the register. Writing one in IOSET register sets the port pin and writing one into IOCLR clear the port pins. Table 1.6 shows the setting of the register for manipulating the port pins.
3.1 Embedded C examples for ARM
This section explores two embedded C programs 1.Blowing a buzzer 2. Toggling an LED. To interface to these simple I/O devices the GPIO registers have to be initialized accordingly. The GPIO related registers are defined in header file ‘lpc214x.h’available in KIEL IDE.In both the programs, the first step is to specify the direction of pin according to the interfaces. Second, Set the IOSET and IOCLR for switching on and off the devices.
3.1.1 Buzzer Program
Table 1.7 shows a buzzer program, where the buzzer is connected to port upper half word pin P1.16. The initialization of IODIR and IOSEL is done as per output pin and GPIO function. Finally a looping function switches on and off the buzzer.
Table 1.7 Buzzer Program
#include <LPC21xx.H> /* LPC21xx definitions */
void delay()
{ long int i=0,j=0; for(i=0;I <=0xfff;i++);
for(j=0;j<=0x4ff;j++);
}
int main()
{ PINSEL0 = 0X00000000; PINSEL1 = 0X00000000; PINSEL2 = 0X00000000;
IO1DIR = 0X00FF0000;
while(1)
{ IO1SET = 0X00010000; // Buzzer On delay();
IO1CLR = 0X00010000; // Buzzer off delay();
}}
3.1.2 LED Toggling Program
Table 1.8 shows a LED toggling program, where the LED is connected to port upper half word pin P1.16. to P1.23. The initialization of IODIR and IOSEL is done as needed for output pin and GPIO function. Finally a looping function switches on and off the LED according to an array of different patterns mentioned in led0[], led1[] and led2[] shifting one by one.
Table 1.8 LED Program
#include <LPC21xx.H> /* LPC21xx definitions */
unsigned int led0[] ={0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff}; unsigned int led1[] ={0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01,0x00}; unsigned int led2[]={0x55,0xaa}; unsigned int i,k;
void delay()
{
int i=0,j=0; for(i=0x00;i<=0xaff;i++)
for(j=0x00;j<=0x2Ff;j++);}
int main(void)
{ PINSEL0 = 0X00000000; PINSEL1 = 0X00000000; PINSEL2 = 0X00000000;
IO0DIR = 0X00000000;
IO1DIR = 0X00FF0000; // 1,6,3,4,8,2,5,7
while(1)
{ for(i=0;i<4;i++) {IO1SET=0X00Ff0000;
delay();
IO1CLR=0X00Ff0000;
delay(); }
for(i=0;i<8;i++)
{ IO1PIN = led0[i] << 16; delay();}
for(i=0;i<8;i++)
{ IO1PIN = led1[i] << 16; delay();} for(k=0;k<=10;k++)
{ for(i=0;i<=1;i++)
4 Summary
In this chapter we discussedsome specialARM and thumb instructions. The ARM7TDMI processor LPC 2148I/O was explained with its interfacing (GPIO) registers. Examplesof ARM embedded C programs for blowing the Buzzer and toggling the LED were discussed.
- 5 References
- www.arm.com
- www.keil.com
- en.wikipedia.org/wiki/ARM_architecture
- Andrew N Sloss, D. Symes, C. Wright, ” Arm system developers guide”, Morgan Kauffman/ Elsevier, 2006.