Skip to content

Commit e86ca20

Browse files
aykevlniaow
authored andcommitted
runtime/interrupt: add cross-chip disable/restore interrupt support
This should cover all supported baremetal targets.
1 parent e2bf7bb commit e86ca20

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// +build avr
2+
3+
package interrupt
4+
5+
import "device"
6+
7+
// State represents the previous global interrupt state.
8+
type State uint8
9+
10+
// Disable disables all interrupts and returns the previous interrupt state. It
11+
// can be used in a critical section like this:
12+
//
13+
// state := interrupt.Disable()
14+
// // critical section
15+
// interrupt.Restore(state)
16+
//
17+
// Critical sections can be nested. Make sure to call Restore in the same order
18+
// as you called Disable (this happens naturally with the pattern above).
19+
func Disable() (state State) {
20+
// SREG is at I/O address 0x3f.
21+
return State(device.AsmFull(`
22+
in {}, 0x3f
23+
cli
24+
`, nil))
25+
}
26+
27+
// Restore restores interrupts to what they were before. Give the previous state
28+
// returned by Disable as a parameter. If interrupts were disabled before
29+
// calling Disable, this will not re-enable interrupts, allowing for nested
30+
// cricital sections.
31+
func Restore(state State) {
32+
// SREG is at I/O address 0x3f.
33+
device.AsmFull("out 0x3f, {state}", map[string]interface{}{
34+
"state": state,
35+
})
36+
}

src/runtime/interrupt/interrupt_cortexm.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,27 @@ func (irq Interrupt) Enable() {
2121
func (irq Interrupt) SetPriority(priority uint8) {
2222
arm.SetPriority(uint32(irq.num), uint32(priority))
2323
}
24+
25+
// State represents the previous global interrupt state.
26+
type State uintptr
27+
28+
// Disable disables all interrupts and returns the previous interrupt state. It
29+
// can be used in a critical section like this:
30+
//
31+
// state := interrupt.Disable()
32+
// // critical section
33+
// interrupt.Restore(state)
34+
//
35+
// Critical sections can be nested. Make sure to call Restore in the same order
36+
// as you called Disable (this happens naturally with the pattern above).
37+
func Disable() (state State) {
38+
return State(arm.DisableInterrupts())
39+
}
40+
41+
// Restore restores interrupts to what they were before. Give the previous state
42+
// returned by Disable as a parameter. If interrupts were disabled before
43+
// calling Disable, this will not re-enable interrupts, allowing for nested
44+
// cricital sections.
45+
func Restore(state State) {
46+
arm.EnableInterrupts(uintptr(state))
47+
}

src/runtime/interrupt/interrupt_gameboyadvance.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,32 @@ func handleInterrupt() {
3434
// appropriate interrupt handler for the given interrupt ID.
3535
//go:linkname callInterruptHandler runtime.callInterruptHandler
3636
func callInterruptHandler(id int)
37+
38+
// State represents the previous global interrupt state.
39+
type State uint8
40+
41+
// Disable disables all interrupts and returns the previous interrupt state. It
42+
// can be used in a critical section like this:
43+
//
44+
// state := interrupt.Disable()
45+
// // critical section
46+
// interrupt.Restore(state)
47+
//
48+
// Critical sections can be nested. Make sure to call Restore in the same order
49+
// as you called Disable (this happens naturally with the pattern above).
50+
func Disable() (state State) {
51+
// Save the previous interrupt state.
52+
state = State(regInterruptMasterEnable.Get())
53+
// Disable all interrupts.
54+
regInterruptMasterEnable.Set(0)
55+
return
56+
}
57+
58+
// Restore restores interrupts to what they were before. Give the previous state
59+
// returned by Disable as a parameter. If interrupts were disabled before
60+
// calling Disable, this will not re-enable interrupts, allowing for nested
61+
// cricital sections.
62+
func Restore(state State) {
63+
// Restore interrupts to the previous state.
64+
regInterruptMasterEnable.Set(uint16(state))
65+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// +build tinygo.riscv
2+
3+
package interrupt
4+
5+
import "device/riscv"
6+
7+
// State represents the previous global interrupt state.
8+
type State uintptr
9+
10+
// Disable disables all interrupts and returns the previous interrupt state. It
11+
// can be used in a critical section like this:
12+
//
13+
// state := interrupt.Disable()
14+
// // critical section
15+
// interrupt.Restore(state)
16+
//
17+
// Critical sections can be nested. Make sure to call Restore in the same order
18+
// as you called Disable (this happens naturally with the pattern above).
19+
func Disable() (state State) {
20+
return State(riscv.DisableInterrupts())
21+
}
22+
23+
// Restore restores interrupts to what they were before. Give the previous state
24+
// returned by Disable as a parameter. If interrupts were disabled before
25+
// calling Disable, this will not re-enable interrupts, allowing for nested
26+
// cricital sections.
27+
func Restore(state State) {
28+
riscv.EnableInterrupts(uintptr(state))
29+
}

0 commit comments

Comments
 (0)