-
Notifications
You must be signed in to change notification settings - Fork 1
feat: Add runtime/interrupt package and update volatile package #27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| package interrupt | ||
|
|
||
| import _ "unsafe" | ||
|
|
||
| // A checkpoint is a setjmp like buffer, that can be used as a flag for | ||
| // interrupts. | ||
| // | ||
| // It can be used as follows: | ||
| // | ||
| // // global var | ||
| // var c Checkpoint | ||
| // | ||
| // // to set up the checkpoint and wait for it | ||
| // if c.Save() { | ||
| // setupInterrupt() | ||
| // for { | ||
| // waitForInterrupt() | ||
| // } | ||
| // } | ||
| // | ||
| // // Inside the interrupt handler: | ||
| // if c.Saved() { | ||
| // c.Jump() | ||
| // } | ||
| type Checkpoint struct { | ||
| jumpSP uintptr | ||
| jumpPC uintptr | ||
| } | ||
|
|
||
| // Save the execution state in the given checkpoint, overwriting a previous | ||
| // saved checkpoint. | ||
| // | ||
| // This function returns twice: once the normal way after saving (returning | ||
| // true) and once after jumping (returning false). | ||
| // | ||
| // This function is a compiler intrinsic, it is not implemented in Go. | ||
| // TODO(zzy): implement Save | ||
| func (c *Checkpoint) Save() bool { | ||
| panic("todo:Checkpoint.Save") | ||
| } | ||
|
|
||
| // Returns whether a jump point was saved (and not erased due to a jump). | ||
| func (c *Checkpoint) Saved() bool { | ||
| return c.jumpPC != 0 | ||
| } | ||
|
|
||
| // Jump to the point where the execution state was saved, and erase the saved | ||
| // jump point. This must *only* be called from inside an interrupt. | ||
| // | ||
| // This method does not return in the conventional way, it resumes execution at | ||
| // the last point a checkpoint was saved. | ||
| func (c *Checkpoint) Jump() { | ||
| if !c.Saved() { | ||
| panic("runtime/interrupt: no checkpoint was saved") | ||
| } | ||
| jumpPC := c.jumpPC | ||
| jumpSP := c.jumpSP | ||
| c.jumpPC = 0 | ||
| c.jumpSP = 0 | ||
| if jumpPC == 0 { | ||
| panic("jumping to 0") | ||
| } | ||
|
Comment on lines
+60
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| checkpointJump(jumpSP, jumpPC) | ||
| } | ||
|
|
||
| //go:linkname checkpointJump __llgo_checkpointJump | ||
| func checkpointJump(jumpSP, jumpPC uintptr) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| // Package interrupt provides access to hardware interrupts. It provides a way | ||
| // to define interrupts and to enable/disable them. | ||
| package interrupt | ||
|
|
||
| import "unsafe" | ||
|
|
||
| // 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. | ||
| // TODO(zzy): implement New | ||
| func New(id int, handler func(Interrupt)) Interrupt { | ||
| panic("todo:interrupt.New") | ||
| } | ||
|
|
||
| // 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 interrupts cannot | ||
| // individually be enabled/disabled, the compiler should create a pseudo-call | ||
| // (like runtime/interrupt.use()) that keeps the interrupt alive. | ||
| type handle struct { | ||
| context unsafe.Pointer | ||
| funcPtr uintptr | ||
| Interrupt | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| //go:build avr | ||
|
|
||
| package interrupt | ||
|
|
||
| import "github.com/goplus/emb/device" | ||
|
|
||
| // State represents the previous global interrupt state. | ||
| type State uint8 | ||
|
|
||
| // Disable disables all interrupts and returns the previous interrupt state. It | ||
| // can be used in a critical section like this: | ||
| // | ||
| // state := interrupt.Disable() | ||
| // // critical section | ||
| // interrupt.Restore(state) | ||
| // | ||
| // Critical sections can be nested. Make sure to call Restore in the same order | ||
| // as you called Disable (this happens naturally with the pattern above). | ||
| func Disable() (state State) { | ||
| // SREG is at I/O address 0x3f. | ||
| return State(device.AsmFull(` | ||
| in {}, 0x3f | ||
| cli | ||
| `, nil)) | ||
| } | ||
|
|
||
| // Restore restores interrupts to what they were before. Give the previous state | ||
| // returned by Disable as a parameter. If interrupts were disabled before | ||
| // calling Disable, this will not re-enable interrupts, allowing for nested | ||
| // critical sections. | ||
| func Restore(state State) { | ||
| // SREG is at I/O address 0x3f. | ||
| device.AsmFull("out 0x3f, {state}", map[string]interface{}{ | ||
| "state": state, | ||
| }) | ||
| } | ||
|
|
||
| // In returns whether the system is currently in an interrupt. | ||
| // | ||
| // Warning: this always returns false on AVR, as there does not appear to be a | ||
| // reliable way to determine whether we're currently running inside an interrupt | ||
| // handler. | ||
| func In() bool { | ||
| return false | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,65 @@ | ||||||
| //go:build cortexm | ||||||
|
|
||||||
| package interrupt | ||||||
|
|
||||||
| import ( | ||||||
| "github.com/goplus/emb/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() { | ||||||
| // Clear the ARM pending bit, an asserting device may still | ||||||
| // trigger the interrupt once enabled. | ||||||
| arm.ClearPendingIRQ(uint32(irq.num)) | ||||||
| arm.EnableIRQ(uint32(irq.num)) | ||||||
| } | ||||||
|
|
||||||
| // Disable disables this interrupt. | ||||||
| func (irq Interrupt) Disable() { | ||||||
| arm.DisableIRQ(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). | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo in documentation
Suggested change
|
||||||
| // | ||||||
| // Examples: 0xff (lowest priority), 0xc0 (low priority), 0x00 (highest possible | ||||||
| // priority). | ||||||
| func (irq Interrupt) SetPriority(priority uint8) { | ||||||
| arm.SetPriority(uint32(irq.num), uint32(priority)) | ||||||
| } | ||||||
|
|
||||||
| // State represents the previous global interrupt state. | ||||||
| type State uintptr | ||||||
|
|
||||||
| // Disable disables all interrupts and returns the previous interrupt state. It | ||||||
| // can be used in a critical section like this: | ||||||
| // | ||||||
| // state := interrupt.Disable() | ||||||
| // // critical section | ||||||
| // interrupt.Restore(state) | ||||||
| // | ||||||
| // Critical sections can be nested. Make sure to call Restore in the same order | ||||||
| // as you called Disable (this happens naturally with the pattern above). | ||||||
| func Disable() (state State) { | ||||||
| return State(arm.DisableInterrupts()) | ||||||
| } | ||||||
|
|
||||||
| // Restore restores interrupts to what they were before. Give the previous state | ||||||
| // returned by Disable as a parameter. If interrupts were disabled before | ||||||
| // calling Disable, this will not re-enable interrupts, allowing for nested | ||||||
| // critical sections. | ||||||
| func Restore(state State) { | ||||||
| arm.EnableInterrupts(uintptr(state)) | ||||||
| } | ||||||
|
|
||||||
| // In returns whether the system is currently in an interrupt. | ||||||
| func In() bool { | ||||||
| // The VECTACTIVE field gives the instruction vector that is currently | ||||||
| // active (in handler mode), or 0 if not in an interrupt. | ||||||
| // Documentation: | ||||||
| // https://developer.arm.com/documentation/dui0497/a/cortex-m0-peripherals/system-control-block/interrupt-control-and-state-register | ||||||
| vectactive := uint8(arm.SCB.ICSR.Get()) | ||||||
| return vectactive != 0 | ||||||
| } | ||||||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documentation: Example code references undefined functions
The example calls
setupInterrupt()andwaitForInterrupt()which are not defined anywhere, making the example non-compilable.Suggestion: Replace with a concrete example using actual interrupt package functions: