Timer driven interrupts on the PowerPC processor

In order to see the effect that the PowerPC RISC architecture has on interrupt handling, we shall use exactly the same format in this section as for the 68K CISC timer routine.


Developing the "software watchdog"


Developing the main task

The main task is essentially a loop that increments a counter. However, the loop is set up in such a way that can never exit without some external agency. The pseudo code for both the 68K and the PowerPC obviously must be identical as the processors are performing the same task.

global variables counter, semaphore;

main() {
	long inc = 1;

	counter = 0;
	semaphore = 0;
	while (semaphore == 0)
		counter += inc;
}

The solution to this task can be found in the file ppcmain.s. Try to develop your own code before looking.

Note how on a RISC processor you will load an address into a register and then use that register to access a memory location. However, as there are many RISC registers available, it is possible to leave the address in the register for later reuse when storing the modified value to memory. This address register indirect approach is very efficient when multi accesses to memory are necessary.


Understanding the PowerPC timer operation


Developing the interrupt service routine (ISR)

The interrupt task is to check whether the counter value is even. If it is even then set the semaphore variable to 1 and cause the main task to exit. Again try and develop your own solution before looking at the answer in file ppcisr.s.

Note that the "return-from-interrupt" on the PowerPC processor is actually a RFI instruction and not the "RTI" instruction found on many other processors.

Note that there is a possibility that the interrupt service routine will change the semaphore variable, only to have the new value over written by the main task writing the semaphore variable.

Although it is not obvious, the PowerPC return address and the various other pieces of status information are stored in "special registers" SRR0 and SRR1. See HVZ and the PowerPC user manual for details.

As with the 68K processor, the status register on the PowerPC is automatically saved when the interrupt starts. However, unlike the 68K processor, the status register does not include information about the flags. This information is stored in the special register CR. If any compare operations are performed during the ISR, this register must be saved on entry into the ISR and recovered on exit.


Initializing the interrupt, interrupt vector and timer

The startup code for enabling PowerPC interrupts has the following format

	Set-up the stack
	De-activate interrupts to avoid problems while initing

	Clear the semaphore variables
	Set the timer reload variable (how often interrupts occur)
	Set the processor to vector via the low end of memory (0x900)
		when handling timer interrupts

	FIX BECAUSE OF DEMO KIT LIMITATIONS
	Place the start of the ISR routine at the vector address

	Clear the old timer interrupt that occurred since the
		processor resets with the Decrementer register as zero
		and decrementing.

	Activate the interrupts
	Call the main code

Look up any necessary operations and memory locations in the processor's User Manual now you know the format of what is required. Try and develop your own start-up routine before examining my version of the code in file ppcinit.s.


A major DIAB DATA PowerPC demo kit limitation to overcome!

There is one problem that must be overcome when programming the initialization routine. On the 68K processor only the starting address of the ISR is placed at the vector location. On the PowerPC, with fewer interrupt types to handle, all of the ISR, not just its starting address is placed into the interrupt vector memory. Thus we should program on the PowerPC one of the following sets of code

	section ISRspecial		// Place at 0x900
ActualISR: All the ISR routine lives here
	.text
All the other code

or the approach taken by HVZ in their PowerPC interrupt explanation

	section ISRspecial		// Place at 0x900
ActualISR:
	b ISR				// Branch to actual ISR
	.text
All the other code including the ISR lives here

The second approach is only strictly necessary if the ISR is longer than 64 instructions, the amount of memory between the timer interrupt start (0x900) and the start of the next interrupt space (0xA00).

How, with the crippled DIAB DATA PowerPC assembler/linker, can you get the ISR code to be placed at memory location 0x900 and the rest of the code else where? With the full PowerPC kit, you could set up several memory sections as with the 68K demo kit. With the PowerPC demo kit you can't.

Two choices are possible

As you can see from the initialization code ppcinit.s I made use of the second approach. Several interrupts need to be handled at the same time when handling the "virtual device" and the timer in Task 3b.

This self-modifying code approach is not to be taken lightly as it is "highly inadvisable" except under special circumstances. Since the DIAB DATA PowerPC assembler/linker has been crippled in the demo kit, and we don't have to self-modify very much code, this will have to be considered a suitable"special circumstance". With a real embedded processor system, the approach would not work as the program code is placed into "un-self-modificable" ROM.


Some "MAGIC" to get the simulator to run

There are a number of pieces of magic to get the SDS simulator to recognize the timer and correctly respond to the timer interrupts


Customizing the ISR routine

You might want to investigate the following



Last modified: July 22, 1996 01:44 PM by M. Smith.
Copyright -- M. R. Smith