0% found this document useful (0 votes)
29 views5 pages

36 Interrupts-Asm

This document provides instructions for rewriting an interrupt service routine (ISR) for an LED blinking program from C to assembly language. It discusses translating specific C statements to equivalent assembly code, properly saving and restoring registers in the ISR, returning from interrupts using RETI, and setting up the interrupt vector table. Exercises are provided to have the reader implement an interrupt-driven LED blinking program in assembly and analyze the compiled C and assembly code.

Uploaded by

vishnuks
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views5 pages

36 Interrupts-Asm

This document provides instructions for rewriting an interrupt service routine (ISR) for an LED blinking program from C to assembly language. It discusses translating specific C statements to equivalent assembly code, properly saving and restoring registers in the ISR, returning from interrupts using RETI, and setting up the interrupt vector table. Exercises are provided to have the reader implement an interrupt-driven LED blinking program in assembly and analyze the compiled C and assembly code.

Uploaded by

vishnuks
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

Writing an interrupt handler in assembly

language
March 25, 2012

1 Introduction

In this lesson, we learn how to write an interrupt handler in assembly language.


Because we are building on the material presented in a previous lesson on inter-
rupt handling, it is essential that you go through that lesson once again before
continuing.
Many of the ner details of interrupt handling were not visible to you when
you wrote the interrupt service routine in C; writing code in assembler gives
you a complete picture of the interrupt handling mechanism.

2 Objective

The objective of this lesson is to rewrite in assembly language


1 the interrupt
driven LED blinking program written in the previous lesson; here is the C code
of that program:

#include <msp430.h>
#define LED_0 BIT0
__attribute__((interrupt(TIMERA1_VECTOR)))
timer_isr(void)
{
P1OUT ^= LED_0;
TACTL &= ~TAIFG;
}
void main(void)
{
P1OUT = 0;
P1DIR = LED_0;

TACTL = TASSEL_2 | MC_2 | ID_3 | TAIE;


__enable_interrupt();
1 The assembly code will be compiled using naken430asm

1
while(1);
}
The above code congures Timer-A such that it generates an interrupt at a
rate of approximately twice per second. Each time the ISR (interrupt service
routine) is called, it toggles the LED on bit 0 of P1OUT (the RED LED on the
launchpad board); it also clears the interrupt ag (TAIFG) which is bit 0 of the
register TACTL.

3 Rewriting timer_isr

The rst statement of the C function timer_isr is:

P1OUT ^= LED_0;
LED_0 is #dened to BIT0 and BIT0 expands to the constant 1. So, the above
statement is eectively:

P1OUT ^= 1;
One way to translate this is to move (using a byte move, mov.b) P1OUT (whose
memory mapped address is 0x21) to a register (say r15), use xor.b to toggle the
least signicant bit of the register and write the register's value back to P1OUT .
2
The next statement is:

TACTL &= ~TAIFG


The value of TAIFG is 1; so the above statement is:

TACTL &= ~1
The least signicant bit (D0'th bit) of TACTL is the interrupt ag bit, TAIFG
- the above statement clears that bit.
How do you implement this in assembly?
Let us look at the bit pattern for ~1:

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
The constant -2, expressed in two's complement form, has the very same bit
3
pattern . So one method is to rst store the value of TACTL in a register (say
r15) using a word move
4 (mov.w), do a bitwise and with the constant -2 and
5
store back to TACTL . If you refer the device specic data sheet, you will nd
that the address of TACTL is 0x160.
2 Much better: directly do an xor.b to P1OUT. You will note that gcc, with optimizations
enabled, does it like this.
3 You represent -2 in two's complement form by rst writing 2 in binary form, taking ones
complement of all the bits and then adding one to it
4 TACTL is a 16 bit register while P1OUT is 8 bit
5 Or much better: directly do an and.w with TACTL

2
3.1 Saving and restoring registers
An ISR may get invoked any time during the execution of your program. Say
you are modifying a register r15 in your ISR; this will create trouble if the same
register is being used in some other part of your code. So it is always a good
idea to make sure that once the ISR returns, the registers which were modied
in the body of the ISR regain their old values. The easiest way to do this is to
push the registers which are going to be modied within the ISR to the stack
at the beginning of the ISR's body and then pop them out just before returning.

3.2 Returning from the Interrupt Serive Routine


A normal subroutine return is done with the instruction:

ret

But returning from an interrupt service routine is a bit dierent. In order to


understand the dierence, we have to examine how an ISR gets called in the
rst place!
When some external peripheral generates a hardware interrupt, the proces-
sor continues with the execution of the current instruction. Once the current
instruction is executed, control is transferred to the body of the interrupt service
routine (instead of executing the next instruction in the sequence). This control
transfer is very much like a subroutine call in the sense the address of the next
instruction gets pushed onto the stack so that a return statement at the end
of the ISR can once again transfer control back to the portion of the program
whose execution was interrupted.
But there is a key dierence in the way an ISR gets called - after pushing the
value of the Program Counter (R0, the register which holds the address of the
next instruction to be executed), the value of the Status Register (SR, register
R2) is also pushed onto the stack .
6 A ret instruction simply pops the top
element o the stack, assumes it to be the return address and transfers control
to that location. There is another instruction called reti which rst restores
the value of SR by popping it o the stack and then restores the value of PC by
popping the next item o the stack. An Interrupt Service routine should always
end with a reti.
Why is the Status Register also pushed to the stack, besides the return
address? The status register contains many bits which indicate the result of
various arithmetic operations (Zero, Carry, Negative etc). Instructions executed
in the body of the ISR may change the value of these bits
7 - hence it necessary
8
that the value of SR is saved and restored .
6 Note that this happens automatically
7 Besides the Z, C, N bits, the SR also has a bit called GIE, global interrupt enable, which
is cleared by the processor upon entry to the ISR.
8 There are processor architectures where the status register is not autmatically saved dur-
ing execution of an ISR - in such cases, it is your responsibility to add instructions to the
beginning/end of the ISR which will save/restore the status register.

3
4 Rewriting main

4.1 Stopping the watchdog


Writing 0x5a80 to the WDTCTL register (at address 0x120) will stop the watch-
dog.

4.2 Initializing stack pointer, P1DIR and P1OUT


Besides initializing P1DIR (address 0x22) and P1OUT (address 0x21), we need
to initialize the stack pointer to 0x280.

4.3 Conguring TACTL


We do it like this in C:

TACTL = TASSEL_2 | MC_2 | ID_3 | TAIE;


Reading the processor family manual will tell you that the value of the right
hand side pattern is 0x2e2. It is now easy to write an assembly statement which
performs a word move of the constant 0x2e2 to TACTL (address 0x160).

4.4 Enabling interrupts


The msp430 assembly instruction eint enables interrupts.

4.5 Setting up an innite while loop


A simple statement like this:

L1: jmp L1
is sucient.

5 Setting up the interrupt vector

How does the processor nd out the address of the instruction to be executed
when a timer overow interrupt is generated?
MSP430 processors use what is called a vectored interrupts scheme where
for each specic type of hardware interrupt, there is one location in memory
which should hold the address of the rst instruction of the ISR to be executed.
The set of locations which hold the addresses of Interrupt Service Routines is
called an IVT (interrupt vector table). On the MSP430g2231, the vector table is
from 0xe0 to 0x in ash memory. The address of the ISR to handle Timer-A
overow should be at 0xf0.
Let us say we have written the ISR code under the label timer_isr. The
following assembler directives, inserted at the end of the program, will set up
the vectors correctly:

4
org 0xfff0
dw timer_isr

This will result in mspdebug writing the address of the rst instruction under
the label timer_isr to ash memory location 0xf0.
Of course, we also need the following directives:

org 0xfffe
dw main

(assuming that we have a label main under which we have written the instruc-
tions for our main program).
Upon system reset, the processor will read the two byte value at location
0xfe (called the reset vector) and transfers control to that location in memory.
When a timer overow interrupt is generated, the processor reads the 2 bytes
at location 0xf0:0xf1, treats those two bytes as the address of the ISR and
transfers control to the ISR.

6 Exercises

1. Based on the discussion above, write the complete assembly language


program (to be assembled using naken430asm) for interrupt driven LED
blinking. Run the code and verify that it is working properly. Post the
code to your github repo.

2. Compile the original C program with the -S option and read the generated
assembly code. Compile the code once again with -S and -O3 options and
analyse the output.

3. Compile the original C program into an a.out and use msp430-objdump


to analyze it. Verify that location 0xf0 of the interrupt vector table
contains the address of the ISR.

7 Test

There is no test associated with this lesson.

You might also like