CS452 - Real-Time Programming - Fall 2009

Lecture 5 - Context Switches on the ARM



What is a task?

  1. A set of instructions
  2. Current state, which is changed by executing instructions

As stated this is just a deterministic finite state machine,

3. But there is also the environment

Two tasks can use the same set of instructions, but

The kernel keeps track of every task's state

The TD normally contains

  1. The task's stack pointer, which points to a private stack, in the memory of the tasks, containing

    all ready to be reloaded whenever the task next runs.

  2. Possibly the return value for when the task is next activated
  3. The task's parent
  4. The task's state
  5. Links to queues on which the task is located

Possible states of the task

  1. Active: running or about to run
  2. Ready: can run if scheduled
  3. Blocked: waiting for something to happen


All the interesting stuff inside done by the kernel is hidden inside getNextRequest.

int getNextRequest( active ) {
  nextRequest = activate( active ); //the active task doesn't change
  return nextRequest;

What's inside activate( active )?

  1. transfer of control to the active task
  2. execution to completion of the active task
  3. transfer of control back to the kernel
  4. getting the request

The hard part to get right is `transfer of control'

How I Get Started Writing a Context Switch

1. Start with a program that calls a function

void func( ) {
  printf( "func: running\n" );

void main( ) {
  printf( "main: beginning\n" );
  func( );
  printf( "main: ending\n" );
  1. Compile and run it.
  2. Compile with the -S flag and look at the assembly code.

2. Find out how to put a PC into an interrupt vector

What is an interrupt vector?

  1. Add to the assembly code a line that puts the address of the first instruction of func( ) into the interrupt vector
  2. Compile the assembly code and run it.

3. Change to calling func() using a software interrupt

  1. Replace the instruction in main that calls func( ) to swin
  2. Replace the bx or mov pc, lr instruction that ends func( ) with mov pc, lr.

4. You have just written a context switch, now you need to dress it up.

  1. Add stuff to main( ) so that it has context
  2. Save the context of main( ) on the stack as the first thing done inside func( )
  3. Restore the context of main( ) from the stack jas the last thing done before the instruction that ends func( ).

5. Add a return value from func( ) and pick it up in main( ).

To go beyond this we need to think about tasks more concretely

What we did here was to replace a function call with a software interrupt. Why bother?

  1. A software interrupt can leap tall barriers at a single bound
  2. A hardware interrupt is very similar to a software interrupt.

Doing It on the ARM

ARM 920T

What is this?

Two modes of labelling

  1. By architecture
    Architecture Instruction








    ARMv1 1 no no no Obsolete
    ARMv2 2 no no no Obsolete
    ARMv3 3 no no no
    ARMv3M 3 no yes no
    ARMv4 4 no yes no
    ARMv4T 4 yes yes no This is the one you use
    ARMv5 5 no yes no Has CLZ
    ARMv5T 5 yes yes no
    ARMv5TE 5 yes yes yes

    Thumb instructions are 16 bit, and accelerated.

  2. By processor core






    ARM7TDMI v4T v1 Most of the ARM7xx processors
    ARM9TDMI v4T v1 ARM[920|922|940]T: 920T is the one we have.
    StrongARM v4 n/a Intel SA-110. Found in the IPAQ.
    ARM9E v5TE v2
    ARM10E v5TE v2
    XScale v5TE v2 Manufactured by Intel. HP versions of IPAQ.


  1. 16 32-bit registers

    partially separate register sets different modes

    link register (lr), program counter (pc) are special, but not very special

  2. Exceptions






    Reset supervisor 0x00
    Undefined instruction undefined 0x04
    Software interrupt supervisor 0x08
    Prefetch abort abort 0x0c
    Data abort abort 0x10
    Ordinary interrupt IRQ 0x18
    Fast interrupt FIQ 0x1c

    1. You are concerned right now with Reset and Software Interrupt.
    2. When the CPU is initializing, it puts
          ldr  pc, [pc, #0x18] ; 0xe590f018

      into addresses 0x00 to 0x1c.

    3. It puts the entry point of RedBoot into addresses 0x20 to 0x3c.
    4. Note endianness of RedBoot output when examining these locations.
  3. Three data types
  4. Program status register
    31 30 29 28 27 7 6 5 4 3 2 1 0
    N Z C V Q Does Not Matter (DNM) I F T M4 M3 M2 M1 M0



General Comments

  1. each instruction is exactly one word
  2. load and store RISC architecture
  3. rich set of addressing modes
  4. allows you to keep any partial computation it makes

Context Switch


Function Call

; In calling code
   bl  <entry point>  ; this treats the pc and lr specially

; In called code
entry point:
   mov     ip, sp
   stmdb   sp!, {fp, ip, lr} ; and usually others, 
                             ; determined by the registers the function uses
   ldmia   sp, {fp, sp, pc} ; and whatever others

Note the role of the link register and stack pointer.

Software Interrupt

; In calling code
   swi  n

; In kernel
kernel entry:
; Change to system mode
; Save user state on user stack
; Return to supervisor mode
   ldr    r4, [lr, #-4]    ; gets the request type
; Retrieve kernel state from kernel stack
; Do kernel work


  1. What is above kernel entry?
  2. If you put swi in a wrapper or stub what happens before and after it?
  3. If the request had arguments, how would you get them into the kernel?

    Hint. How does gcc pass arguments into a function?

  4. It might be important that there are two link registers. Which two link registers? Why?
  5. In practice it isn't important. Why not?


  1. Try this first on paper drawinf the stack, registers, etc after each instruction
  2. Try coding in baby steps, which is usually a good idea in assembly language.
  3. Try reading this.

Return to: