all: add compiler support for interrupts

This commit lets the compiler know about interrupts and allows
optimizations to be performed based on that: interrupts are eliminated
when they appear to be unused in a program. This is done with a new
pseudo-call (runtime/interrupt.New) that is treated specially by the
compiler.
This commit is contained in:
Ayke van Laethem
2019-12-15 14:16:22 +01:00
committed by Ron Evans
parent 3729fcfa9e
commit a5ed993f8d
36 changed files with 766 additions and 199 deletions
+38
View File
@@ -0,0 +1,38 @@
// Package interrupt provides access to hardware interrupts. It provides a way
// to define interrupts and to enable/disable them.
package interrupt
// Interrupt provides direct access to hardware interrupts. You can configure
// this interrupt through this interface.
//
// Do not use the zero value of an Interrupt object. Instead, call New to obtain
// an interrupt handle.
type Interrupt struct {
// Make this number unexported so it cannot be set directly. This provides
// some encapsulation.
num int
}
// New is a compiler intrinsic that creates a new Interrupt object. You may call
// it only once, and must pass constant parameters to it. That means that the
// interrupt ID must be a Go constant and that the handler must be a simple
// function: closures are not supported.
func New(id int, handler func(Interrupt)) Interrupt
// Register is used to declare an interrupt. You should not normally call this
// function: it is only for telling the compiler about the mapping between an
// interrupt number and the interrupt handler name.
func Register(id int, handlerName string) int
// handle is used internally, between IR generation and interrupt lowering. The
// frontend will create runtime/interrupt.handle objects, cast them to an int,
// and use that in an Interrupt object. That way the compiler will be able to
// optimize away all interrupt handles that are never used in a program.
// This system only works when interrupts need to be enabled before use and this
// is done only through calling Enable() on this object. If interrups cannot
// individually be enabled/disabled, the compiler should create a pseudo-call
// (like runtime/interrupt.use()) that keeps the interrupt alive.
type handle struct {
handler func(Interrupt)
Interrupt
}
@@ -0,0 +1,23 @@
// +build cortexm
package interrupt
import (
"device/arm"
)
// Enable enables this interrupt. Right after calling this function, the
// interrupt may be invoked if it was already pending.
func (irq Interrupt) Enable() {
arm.EnableIRQ(uint32(irq.num))
}
// SetPriority sets the interrupt priority for this interrupt. A lower number
// means a higher priority. Additionally, most hardware doesn't implement all
// priority bits (only the uppoer bits).
//
// Examples: 0xff (lowest priority), 0xc0 (low priority), 0x00 (highest possible
// priority).
func (irq Interrupt) SetPriority(priority uint8) {
arm.SetPriority(uint32(irq.num), uint32(priority))
}