> one more question from me ...
> Simply put, what is the correct way to return from an interrupt (exception)
> on the R3000 ? If I understand it right, I have to do the following:
> - execute the rfe instruction
> - get the address of the interrupted instruction from CP0_EPC
> - jump to that address
You do this in the wrong order. The right way to to it is about:
lw k0,FR_STATUS(sp) # restore the old status register
nop # load delay slot
nop # (cp0 coprocessor hazzard may require
# inserting nops on CPUs < MIPS IV
lw k0,FR_EPC(sp) # where we'll return to
[restore old registers, stack pointer ...]
rfe # delay slot
The trick is that you have to put the rfs instruction in the delay slot of
the jump which jumps to the instruction which was about to be executed when
the code was interrupted.
The order is important because the rfe instruction may put you from kernel
mode to user mode which would make a program counter >= KSEG0 invalid.
> Obviously, I am missing something here. I managed to get a timer interrupt
> 'ticking' on the DS5000/200. In the interrupt routine, I simply print out a
> message and (try to) return. The interrupt rate is currently 2 Hz ...
Should be a bit faster or BogoMIPS won't rock ;-)
> Now, twice a second I get that message on the screen, but the interrupted
> kernel doesn't continue to run. After a while, I get some funny lines on the
> screen (I'm running with a CX video board). This should tell me that the
> pointer has gone crazy or s.th. similiar, I think. Perhaps I also didn't
> initialise CP0 correctly ...
For just doing that you don't need lots of initializations. You should
however have initialized the entire exception handling to at least print
some debugging message for the case unleasant things like address error etc.
> It would be nice if someone could supply me with a short working interrupt
> routine that simply returns whenever it's triggered.
Some of IDT's manuals (see http://www.idt.com/ and ftp.idt.com) contain
examples and explanations. Also a lot of code is available in the MACH
and NetBSD kernels.
About the shortest interrupt routine that works should be:
[Do some "here I am stuff". Integer register haven't been saved,
so only k0/k1 are available ...]
nop # cp0 hazzard
Hope that helps,
Ralf (Loooong time ago I last hacked an R3000 ...)