mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-05 15:15:44 +00:00
2002-06-28 Joel Sherrill <joel@OARcorp.com>
* intr_NOTIMES.t: Per PR70 incorporate the posting by Zoltan Kocsi <zoltan@bendor.com.au> explaining a m68k vectoring trick.
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
2002-06-28 Joel Sherrill <joel@OARcorp.com>
|
||||
|
||||
* intr_NOTIMES.t: Per PR70 incorporate the posting by
|
||||
Zoltan Kocsi <zoltan@bendor.com.au> explaining a m68k vectoring trick.
|
||||
|
||||
2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
||||
|
||||
* Makefile.am: Remove AUTOMAKE_OPTIONS.
|
||||
|
||||
@@ -143,6 +143,76 @@ MC68xxx CPU models with separate interrupt stacks:
|
||||
@end html
|
||||
@end ifset
|
||||
|
||||
@section CPU Models Without VBR and RAM at 0
|
||||
|
||||
This is from a post by Zoltan Kocsi <zoltan@bendor.com.au> and is
|
||||
a nice trick in certain situations. In his words:
|
||||
|
||||
I think somebody on this list asked about the interupt vector
|
||||
handling w/o VBR and RAM at 0. The usual trick is
|
||||
to initialise the vector table (except the first 2 two entries, of
|
||||
course) to point to the same location BUT you also add the vector
|
||||
number times 0x1000000 to them. That is, bits 31-24 contain the vector
|
||||
number and 23-0 the address of the common handler.
|
||||
Since the PC is 32 bit wide but the actual address bus is only 24,
|
||||
the top byte will be in the PC but will be ignored when jumping
|
||||
onto your routine.
|
||||
|
||||
Then your common interrupt routine gets this info by loading the PC
|
||||
into some register and based on that info, you can jump to a vector
|
||||
in a vector table pointed by a virtual VBR:
|
||||
|
||||
@example
|
||||
//
|
||||
// Real vector table at 0
|
||||
//
|
||||
|
||||
.long initial_sp
|
||||
.long initial_pc
|
||||
.long myhandler+0x02000000
|
||||
.long myhandler+0x03000000
|
||||
.long myhandler+0x04000000
|
||||
...
|
||||
.long myhandler+0xff000000
|
||||
|
||||
|
||||
//
|
||||
// This handler will jump to the interrupt routine of which
|
||||
// the address is stored at VBR[ vector_no ]
|
||||
// The registers and stackframe will be intact, the interrupt
|
||||
// routine will see exactly what it would see if it was called
|
||||
// directly from the HW vector table at 0.
|
||||
//
|
||||
|
||||
.comm VBR,4,2 // This defines the 'virtual' VBR
|
||||
// From C: extern void *VBR;
|
||||
|
||||
myhandler: // At entry, PC contains the full vector
|
||||
move.l %d0,-(%sp) // Save d0
|
||||
move.l %a0,-(%sp) // Save a0
|
||||
lea 0(%pc),%a0 // Get the value of the PC
|
||||
move.l %a0,%d0 // Copy it to a data reg, d0 is VV??????
|
||||
swap %d0 // Now d0 is ????VV??
|
||||
and.w #0xff00,%d0 // Now d0 is ????VV00 (1)
|
||||
lsr.w #6,%d0 // Now d0.w contains the VBR table offset
|
||||
move.l VBR,%a0 // Get the address from VBR to a0
|
||||
move.l (%a0,%d0.w),%a0 // Fetch the vector
|
||||
move.l 4(%sp),%d0 // Restore d0
|
||||
move.l %a0,4(%sp) // Place target address to the stack
|
||||
move.l (%sp)+,%a0 // Restore a0, target address is on TOS
|
||||
ret // This will jump to the handler and
|
||||
// restore the stack
|
||||
|
||||
(1) If 'myhandler' is guaranteed to be in the first 64K, e.g. just
|
||||
after the vector table then that insn is not needed.
|
||||
|
||||
@end example
|
||||
|
||||
There are probably shorter ways to do this, but it I believe is enough
|
||||
to illustrate the trick. Optimisation is left as an exercise to the
|
||||
reader :-)
|
||||
|
||||
|
||||
@section Interrupt Levels
|
||||
|
||||
Eight levels (0-7) of interrupt priorities are
|
||||
|
||||
Reference in New Issue
Block a user