mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-11 22:43:40 +00:00
transform: refactor interrupt lowering
Instead of doing everything in the interrupt lowering pass, generate
some more code in gen-device to declare interrupt handler functions and
do some work in the compiler so that interrupt lowering becomes a lot
simpler.
This has several benefits:
- Overall code is smaller, in particular the interrupt lowering pass.
- The code should be a bit less "magical" and instead a bit easier to
read. In particular, instead of having a magic
runtime.callInterruptHandler (that is fully written by the interrupt
lowering pass), the runtime calls a generated function like
device/sifive.InterruptHandler where this switch already exists in
code.
- Debug information is improved. This can be helpful during actual
debugging but is also useful for other uses of DWARF debug
information.
For an example on debug information improvement, this is what a
backtrace might look like before this commit:
Breakpoint 1, 0x00000b46 in UART0_IRQHandler ()
(gdb) bt
#0 0x00000b46 in UART0_IRQHandler ()
#1 <signal handler called>
[..etc]
Notice that the debugger doesn't see the source code location where it
has stopped.
After this commit, breaking at the same line might look like this:
Breakpoint 1, (*machine.UART).handleInterrupt (arg1=..., uart=<optimized out>) at /home/ayke/src/github.com/tinygo-org/tinygo/src/machine/machine_nrf.go:200
200 uart.Receive(byte(nrf.UART0.RXD.Get()))
(gdb) bt
#0 (*machine.UART).handleInterrupt (arg1=..., uart=<optimized out>) at /home/ayke/src/github.com/tinygo-org/tinygo/src/machine/machine_nrf.go:200
#1 UART0_IRQHandler () at /home/ayke/src/github.com/tinygo-org/tinygo/src/device/nrf/nrf51.go:176
#2 <signal handler called>
[..etc]
By now, the debugger sees an actual source location for UART0_IRQHandler
(in the generated file) and an inlined function.
This commit is contained in:
committed by
Ron Evans
parent
30bbdd5aeb
commit
edcece33ca
@@ -7,6 +7,23 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
IRQ_VBLANK = 0
|
||||
IRQ_HBLANK = 1
|
||||
IRQ_VCOUNT = 2
|
||||
IRQ_TIMER0 = 3
|
||||
IRQ_TIMER1 = 4
|
||||
IRQ_TIMER2 = 5
|
||||
IRQ_TIMER3 = 6
|
||||
IRQ_COM = 7
|
||||
IRQ_DMA0 = 8
|
||||
IRQ_DMA1 = 9
|
||||
IRQ_DMA2 = 10
|
||||
IRQ_DMA3 = 11
|
||||
IRQ_KEYPAD = 12
|
||||
IRQ_GAMEPAK = 13
|
||||
)
|
||||
|
||||
var (
|
||||
regInterruptEnable = (*volatile.Register16)(unsafe.Pointer(uintptr(0x4000200)))
|
||||
regInterruptRequestFlags = (*volatile.Register16)(unsafe.Pointer(uintptr(0x4000202)))
|
||||
@@ -30,10 +47,44 @@ func handleInterrupt() {
|
||||
}
|
||||
}
|
||||
|
||||
// callInterruptHandler is a compiler-generated function that calls the
|
||||
// appropriate interrupt handler for the given interrupt ID.
|
||||
//go:linkname callInterruptHandler runtime.callInterruptHandler
|
||||
func callInterruptHandler(id int)
|
||||
// Pseudo function call that is replaced by the compiler with the actual
|
||||
// functions registered through interrupt.New. If there are none, calls will be
|
||||
// replaced with 'unreachablecalls will be replaced with 'unreachable'.
|
||||
//go:linkname callHandlers runtime/interrupt.callHandlers
|
||||
func callHandlers(num int)
|
||||
|
||||
func callInterruptHandler(id int) {
|
||||
switch id {
|
||||
case IRQ_VBLANK:
|
||||
callHandlers(IRQ_VBLANK)
|
||||
case IRQ_HBLANK:
|
||||
callHandlers(IRQ_HBLANK)
|
||||
case IRQ_VCOUNT:
|
||||
callHandlers(IRQ_VCOUNT)
|
||||
case IRQ_TIMER0:
|
||||
callHandlers(IRQ_TIMER0)
|
||||
case IRQ_TIMER1:
|
||||
callHandlers(IRQ_TIMER1)
|
||||
case IRQ_TIMER2:
|
||||
callHandlers(IRQ_TIMER2)
|
||||
case IRQ_TIMER3:
|
||||
callHandlers(IRQ_TIMER3)
|
||||
case IRQ_COM:
|
||||
callHandlers(IRQ_COM)
|
||||
case IRQ_DMA0:
|
||||
callHandlers(IRQ_DMA0)
|
||||
case IRQ_DMA1:
|
||||
callHandlers(IRQ_DMA1)
|
||||
case IRQ_DMA2:
|
||||
callHandlers(IRQ_DMA2)
|
||||
case IRQ_DMA3:
|
||||
callHandlers(IRQ_DMA3)
|
||||
case IRQ_KEYPAD:
|
||||
callHandlers(IRQ_KEYPAD)
|
||||
case IRQ_GAMEPAK:
|
||||
callHandlers(IRQ_GAMEPAK)
|
||||
}
|
||||
}
|
||||
|
||||
// State represents the previous global interrupt state.
|
||||
type State uint8
|
||||
|
||||
Reference in New Issue
Block a user