mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-20 04:19:04 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 20883b9fac | |||
| 99b129d366 | |||
| 303acf5ed6 | |||
| 7d1ce24be5 | |||
| 774c86e21b | |||
| 0cabd4de69 | |||
| 56bbc5bf6d | |||
| 0b44d0bcc5 | |||
| 6275b3a8d1 | |||
| 34b50efdcd | |||
| 42088f938e | |||
| c60c36f0a8 | |||
| e3aa13c2a6 | |||
| b0366743cd | |||
| c54bdf8b51 | |||
| 1fd4669bee | |||
| e36dfe58ac |
@@ -342,18 +342,6 @@ commands:
|
|||||||
- /go/pkg/mod
|
- /go/pkg/mod
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test-llvm10-go111:
|
|
||||||
docker:
|
|
||||||
- image: circleci/golang:1.11-buster
|
|
||||||
steps:
|
|
||||||
- test-linux:
|
|
||||||
llvm: "10"
|
|
||||||
test-llvm10-go112:
|
|
||||||
docker:
|
|
||||||
- image: circleci/golang:1.12-buster
|
|
||||||
steps:
|
|
||||||
- test-linux:
|
|
||||||
llvm: "10"
|
|
||||||
test-llvm10-go113:
|
test-llvm10-go113:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/golang:1.13-buster
|
- image: circleci/golang:1.13-buster
|
||||||
@@ -399,8 +387,6 @@ jobs:
|
|||||||
workflows:
|
workflows:
|
||||||
test-all:
|
test-all:
|
||||||
jobs:
|
jobs:
|
||||||
- test-llvm10-go111
|
|
||||||
- test-llvm10-go112
|
|
||||||
- test-llvm10-go113
|
- test-llvm10-go113
|
||||||
- test-llvm10-go114
|
- test-llvm10-go114
|
||||||
- test-llvm11-go115
|
- test-llvm11-go115
|
||||||
|
|||||||
+1
-6
@@ -23,7 +23,7 @@ different guide:
|
|||||||
LLVM, Clang and LLD are quite light on dependencies, requiring only standard
|
LLVM, Clang and LLD are quite light on dependencies, requiring only standard
|
||||||
build tools to be built. Go is of course necessary to build TinyGo itself.
|
build tools to be built. Go is of course necessary to build TinyGo itself.
|
||||||
|
|
||||||
* Go (1.11+)
|
* Go (1.13+)
|
||||||
* Standard build tools (gcc/clang)
|
* Standard build tools (gcc/clang)
|
||||||
* git
|
* git
|
||||||
* CMake
|
* CMake
|
||||||
@@ -43,11 +43,6 @@ You can also store LLVM outside of the TinyGo root directory by setting the
|
|||||||
`LLVM_BUILDDIR`, `CLANG_SRC` and `LLD_SRC` make variables, but that is not
|
`LLVM_BUILDDIR`, `CLANG_SRC` and `LLD_SRC` make variables, but that is not
|
||||||
covered by this guide.
|
covered by this guide.
|
||||||
|
|
||||||
TinyGo uses Go modules, so if you clone TinyGo inside your GOPATH (and are using
|
|
||||||
Go below 1.13), make sure that Go modules are enabled:
|
|
||||||
|
|
||||||
export GO111MODULE=on
|
|
||||||
|
|
||||||
## Build LLVM, Clang, LLD
|
## Build LLVM, Clang, LLD
|
||||||
|
|
||||||
Before starting the build, you may want to set the following environment
|
Before starting the build, you may want to set the following environment
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ See the [getting started instructions](https://tinygo.org/getting-started/) for
|
|||||||
|
|
||||||
You can compile TinyGo programs for microcontrollers, WebAssembly and Linux.
|
You can compile TinyGo programs for microcontrollers, WebAssembly and Linux.
|
||||||
|
|
||||||
The following 53 microcontroller boards are currently supported:
|
The following 55 microcontroller boards are currently supported:
|
||||||
|
|
||||||
* [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
|
* [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
|
||||||
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
|
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
|
||||||
@@ -60,6 +60,7 @@ The following 53 microcontroller boards are currently supported:
|
|||||||
* [Adafruit PyBadge](https://www.adafruit.com/product/4200)
|
* [Adafruit PyBadge](https://www.adafruit.com/product/4200)
|
||||||
* [Adafruit PyGamer](https://www.adafruit.com/product/4242)
|
* [Adafruit PyGamer](https://www.adafruit.com/product/4242)
|
||||||
* [Adafruit PyPortal](https://www.adafruit.com/product/4116)
|
* [Adafruit PyPortal](https://www.adafruit.com/product/4116)
|
||||||
|
* [Adafruit QT Py](https://www.adafruit.com/product/4600)
|
||||||
* [Adafruit Trinket M0](https://www.adafruit.com/product/3500)
|
* [Adafruit Trinket M0](https://www.adafruit.com/product/3500)
|
||||||
* [Arduino Mega 2560](https://store.arduino.cc/arduino-mega-2560-rev3)
|
* [Arduino Mega 2560](https://store.arduino.cc/arduino-mega-2560-rev3)
|
||||||
* [Arduino MKR1000](https://store.arduino.cc/arduino-mkr1000-wifi)
|
* [Arduino MKR1000](https://store.arduino.cc/arduino-mkr1000-wifi)
|
||||||
@@ -87,6 +88,7 @@ The following 53 microcontroller boards are currently supported:
|
|||||||
* [Phytec reel board](https://www.phytec.eu/product-eu/internet-of-things/reelboard/)
|
* [Phytec reel board](https://www.phytec.eu/product-eu/internet-of-things/reelboard/)
|
||||||
* [PineTime DevKit](https://www.pine64.org/pinetime/)
|
* [PineTime DevKit](https://www.pine64.org/pinetime/)
|
||||||
* [PJRC Teensy 3.6](https://www.pjrc.com/store/teensy36.html)
|
* [PJRC Teensy 3.6](https://www.pjrc.com/store/teensy36.html)
|
||||||
|
* [PJRC Teensy 4.0](https://www.pjrc.com/store/teensy40.html)
|
||||||
* [ProductivityOpen P1AM-100](https://facts-engineering.github.io/modules/P1AM-100/P1AM-100.html)
|
* [ProductivityOpen P1AM-100](https://facts-engineering.github.io/modules/P1AM-100/P1AM-100.html)
|
||||||
* [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html)
|
* [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html)
|
||||||
* [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html)
|
* [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html)
|
||||||
|
|||||||
+9
-1
@@ -44,7 +44,7 @@ type BuildResult struct {
|
|||||||
//
|
//
|
||||||
// The error value may be of type *MultiError. Callers will likely want to check
|
// The error value may be of type *MultiError. Callers will likely want to check
|
||||||
// for this case and print such errors individually.
|
// for this case and print such errors individually.
|
||||||
func Build(pkgName, outpath string, config *compileopts.Config, action func(BuildResult) error) error {
|
func Build(pkgName, outpath string, config *compileopts.Config, preAction func() error, action func(BuildResult) error) error {
|
||||||
compilerConfig := &compiler.Config{
|
compilerConfig := &compiler.Config{
|
||||||
Triple: config.Triple(),
|
Triple: config.Triple(),
|
||||||
CPU: config.CPU(),
|
CPU: config.CPU(),
|
||||||
@@ -87,6 +87,14 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
// Makefile target.
|
// Makefile target.
|
||||||
var jobs []*compileJob
|
var jobs []*compileJob
|
||||||
|
|
||||||
|
if preAction != nil {
|
||||||
|
// Add job to preAction.
|
||||||
|
jobs = append(jobs, &compileJob{
|
||||||
|
description: "preAction",
|
||||||
|
run: preAction,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Add job to compile and optimize all Go files at once.
|
// Add job to compile and optimize all Go files at once.
|
||||||
// TODO: parallelize this.
|
// TODO: parallelize this.
|
||||||
var mod llvm.Module
|
var mod llvm.Module
|
||||||
|
|||||||
+2
-2
@@ -25,8 +25,8 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not read version from GOROOT (%v): %v", goroot, err)
|
return nil, fmt.Errorf("could not read version from GOROOT (%v): %v", goroot, err)
|
||||||
}
|
}
|
||||||
if major != 1 || minor < 11 || minor > 16 {
|
if major != 1 || minor < 13 || minor > 16 {
|
||||||
return nil, fmt.Errorf("requires go version 1.11 through 1.16, got go%d.%d", major, minor)
|
return nil, fmt.Errorf("requires go version 1.13 through 1.16, got go%d.%d", major, minor)
|
||||||
}
|
}
|
||||||
clangHeaderPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
|
clangHeaderPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
|
||||||
return &compileopts.Config{
|
return &compileopts.Config{
|
||||||
|
|||||||
+3
-3
@@ -24,7 +24,7 @@ var flagUpdate = flag.Bool("update", false, "Update images based on test output.
|
|||||||
// normalizeResult normalizes Go source code that comes out of tests across
|
// normalizeResult normalizes Go source code that comes out of tests across
|
||||||
// platforms and Go versions.
|
// platforms and Go versions.
|
||||||
func normalizeResult(result string) string {
|
func normalizeResult(result string) string {
|
||||||
actual := strings.Replace(result, "\r\n", "\n", -1)
|
actual := strings.ReplaceAll(result, "\r\n", "\n")
|
||||||
|
|
||||||
// Make sure all functions are wrapped, even those that would otherwise be
|
// Make sure all functions are wrapped, even those that would otherwise be
|
||||||
// single-line functions. This is necessary because Go 1.14 changed the way
|
// single-line functions. This is necessary because Go 1.14 changed the way
|
||||||
@@ -113,7 +113,7 @@ func TestCGo(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not read expected output: %v", err)
|
t.Fatalf("could not read expected output: %v", err)
|
||||||
}
|
}
|
||||||
expected := strings.Replace(string(expectedBytes), "\r\n", "\n", -1)
|
expected := strings.ReplaceAll(string(expectedBytes), "\r\n", "\n")
|
||||||
|
|
||||||
// Check whether the output is as expected.
|
// Check whether the output is as expected.
|
||||||
if expected != actual {
|
if expected != actual {
|
||||||
@@ -154,7 +154,7 @@ func formatDiagnostic(err error) string {
|
|||||||
msg := err.Error()
|
msg := err.Error()
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
// Fix Windows path slashes.
|
// Fix Windows path slashes.
|
||||||
msg = strings.Replace(msg, "testdata\\", "testdata/", -1)
|
msg = strings.ReplaceAll(msg, "testdata\\", "testdata/")
|
||||||
}
|
}
|
||||||
return "// " + msg + "\n"
|
return "// " + msg + "\n"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ func (c *Config) AutomaticStackSize() bool {
|
|||||||
func (c *Config) CFlags() []string {
|
func (c *Config) CFlags() []string {
|
||||||
cflags := append([]string{}, c.Options.CFlags...)
|
cflags := append([]string{}, c.Options.CFlags...)
|
||||||
for _, flag := range c.Target.CFlags {
|
for _, flag := range c.Target.CFlags {
|
||||||
cflags = append(cflags, strings.Replace(flag, "{root}", goenv.Get("TINYGOROOT"), -1))
|
cflags = append(cflags, strings.ReplaceAll(flag, "{root}", goenv.Get("TINYGOROOT")))
|
||||||
}
|
}
|
||||||
if c.Target.Libc == "picolibc" {
|
if c.Target.Libc == "picolibc" {
|
||||||
root := goenv.Get("TINYGOROOT")
|
root := goenv.Get("TINYGOROOT")
|
||||||
@@ -186,7 +186,7 @@ func (c *Config) LDFlags() []string {
|
|||||||
// Merge and adjust LDFlags.
|
// Merge and adjust LDFlags.
|
||||||
ldflags := append([]string{}, c.Options.LDFlags...)
|
ldflags := append([]string{}, c.Options.LDFlags...)
|
||||||
for _, flag := range c.Target.LDFlags {
|
for _, flag := range c.Target.LDFlags {
|
||||||
ldflags = append(ldflags, strings.Replace(flag, "{root}", root, -1))
|
ldflags = append(ldflags, strings.ReplaceAll(flag, "{root}", root))
|
||||||
}
|
}
|
||||||
ldflags = append(ldflags, "-L", root)
|
ldflags = append(ldflags, "-L", root)
|
||||||
if c.Target.LinkerScript != "" {
|
if c.Target.LinkerScript != "" {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module github.com/tinygo-org/tinygo
|
module github.com/tinygo-org/tinygo
|
||||||
|
|
||||||
go 1.11
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2
|
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2
|
||||||
|
|||||||
+21
-2
@@ -142,10 +142,11 @@ func getHomeDir() string {
|
|||||||
// getGoroot returns an appropriate GOROOT from various sources. If it can't be
|
// getGoroot returns an appropriate GOROOT from various sources. If it can't be
|
||||||
// found, it returns an empty string.
|
// found, it returns an empty string.
|
||||||
func getGoroot() string {
|
func getGoroot() string {
|
||||||
|
// An explicitly set GOROOT always has preference.
|
||||||
goroot := os.Getenv("GOROOT")
|
goroot := os.Getenv("GOROOT")
|
||||||
if goroot != "" {
|
if goroot != "" {
|
||||||
// An explicitly set GOROOT always has preference.
|
// Convert to the standard GOROOT being referenced, if it's a TinyGo cache.
|
||||||
return goroot
|
return getStandardGoroot(goroot)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for the location of the 'go' binary and base GOROOT on that.
|
// Check for the location of the 'go' binary and base GOROOT on that.
|
||||||
@@ -195,3 +196,21 @@ func isGoroot(goroot string) bool {
|
|||||||
_, err := os.Stat(filepath.Join(goroot, "src", "runtime", "internal", "sys", "zversion.go"))
|
_, err := os.Stat(filepath.Join(goroot, "src", "runtime", "internal", "sys", "zversion.go"))
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getStandardGoroot returns the physical path to a real, standard Go GOROOT
|
||||||
|
// implied by the given path.
|
||||||
|
// If the given path appears to be a TinyGo cached GOROOT, it returns the path
|
||||||
|
// referenced by symlinks contained in the cache. Otherwise, it returns the
|
||||||
|
// given path as-is.
|
||||||
|
func getStandardGoroot(path string) string {
|
||||||
|
// Check if the "bin" subdirectory of our given GOROOT is a symlink, and then
|
||||||
|
// return the _parent_ directory of its destination.
|
||||||
|
if dest, err := os.Readlink(filepath.Join(path, "bin")); nil == err {
|
||||||
|
// Clean the destination to remove any trailing slashes, so that
|
||||||
|
// filepath.Dir will always return the parent.
|
||||||
|
// (because both "/foo" and "/foo/" are valid symlink destinations,
|
||||||
|
// but filepath.Dir would return "/" and "/foo", respectively)
|
||||||
|
return filepath.Dir(filepath.Clean(dest))
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ import (
|
|||||||
|
|
||||||
// Version of TinyGo.
|
// Version of TinyGo.
|
||||||
// Update this value before release of new version of software.
|
// Update this value before release of new version of software.
|
||||||
const Version = "0.17.0"
|
const Version = "0.18.0-dev"
|
||||||
|
|
||||||
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
||||||
// If the goroot cannot be determined, (0, 0) is returned.
|
// If the goroot cannot be determined, (0, 0) is returned.
|
||||||
|
|||||||
+2
-4
@@ -11,19 +11,17 @@ import (
|
|||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errLiteralToPointer = errors.New("interp: trying to convert literal value to pointer")
|
|
||||||
|
|
||||||
// These errors are expected during normal execution and can be recovered from
|
// These errors are expected during normal execution and can be recovered from
|
||||||
// by running the affected function at runtime instead of compile time.
|
// by running the affected function at runtime instead of compile time.
|
||||||
var (
|
var (
|
||||||
errExpectedPointer = errors.New("interp: trying to use an integer as a pointer (memory-mapped I/O?)")
|
errIntegerAsPointer = errors.New("interp: trying to use an integer as a pointer (memory-mapped I/O?)")
|
||||||
errUnsupportedInst = errors.New("interp: unsupported instruction")
|
errUnsupportedInst = errors.New("interp: unsupported instruction")
|
||||||
errUnsupportedRuntimeInst = errors.New("interp: unsupported instruction (to be emitted at runtime)")
|
errUnsupportedRuntimeInst = errors.New("interp: unsupported instruction (to be emitted at runtime)")
|
||||||
errMapAlreadyCreated = errors.New("interp: map already created")
|
errMapAlreadyCreated = errors.New("interp: map already created")
|
||||||
)
|
)
|
||||||
|
|
||||||
func isRecoverableError(err error) bool {
|
func isRecoverableError(err error) bool {
|
||||||
return err == errExpectedPointer || err == errUnsupportedInst || err == errUnsupportedRuntimeInst || err == errMapAlreadyCreated
|
return err == errIntegerAsPointer || err == errUnsupportedInst || err == errUnsupportedRuntimeInst || err == errMapAlreadyCreated
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrorLine is one line in a traceback. The position may be missing.
|
// ErrorLine is one line in a traceback. The position may be missing.
|
||||||
|
|||||||
+1
-1
@@ -102,7 +102,7 @@ func Run(mod llvm.Module, debug bool) error {
|
|||||||
if callErr != nil {
|
if callErr != nil {
|
||||||
if isRecoverableError(callErr.Err) {
|
if isRecoverableError(callErr.Err) {
|
||||||
if r.debug {
|
if r.debug {
|
||||||
fmt.Fprintln(os.Stderr, "not interpretring", r.pkgName, "because of error:", callErr.Err)
|
fmt.Fprintln(os.Stderr, "not interpreting", r.pkgName, "because of error:", callErr.Error())
|
||||||
}
|
}
|
||||||
mem.revert()
|
mem.revert()
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -550,8 +550,23 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||||||
}
|
}
|
||||||
ptr, err := operands[0].asPointer(r)
|
ptr, err := operands[0].asPointer(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err != errIntegerAsPointer {
|
||||||
return nil, mem, r.errorAt(inst, err)
|
return nil, mem, r.errorAt(inst, err)
|
||||||
}
|
}
|
||||||
|
// GEP on fixed pointer value (for example, memory-mapped I/O).
|
||||||
|
ptrValue := operands[0].Uint() + offset
|
||||||
|
switch operands[0].len(r) {
|
||||||
|
case 8:
|
||||||
|
locals[inst.localIndex] = literalValue{uint64(ptrValue)}
|
||||||
|
case 4:
|
||||||
|
locals[inst.localIndex] = literalValue{uint32(ptrValue)}
|
||||||
|
case 2:
|
||||||
|
locals[inst.localIndex] = literalValue{uint16(ptrValue)}
|
||||||
|
default:
|
||||||
|
panic("pointer operand is not of a known pointer size")
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
ptr = ptr.addOffset(uint32(offset))
|
ptr = ptr.addOffset(uint32(offset))
|
||||||
locals[inst.localIndex] = ptr
|
locals[inst.localIndex] = ptr
|
||||||
if r.debug {
|
if r.debug {
|
||||||
|
|||||||
+2
-2
@@ -348,7 +348,7 @@ func (v literalValue) clone() value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v literalValue) asPointer(r *runner) (pointerValue, error) {
|
func (v literalValue) asPointer(r *runner) (pointerValue, error) {
|
||||||
return pointerValue{}, errLiteralToPointer
|
return pointerValue{}, errIntegerAsPointer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v literalValue) asRawValue(r *runner) rawValue {
|
func (v literalValue) asRawValue(r *runner) rawValue {
|
||||||
@@ -949,7 +949,7 @@ func (v rawValue) clone() value {
|
|||||||
func (v rawValue) asPointer(r *runner) (pointerValue, error) {
|
func (v rawValue) asPointer(r *runner) (pointerValue, error) {
|
||||||
if v.buf[0] <= 255 {
|
if v.buf[0] <= 255 {
|
||||||
// Probably a null pointer or memory-mapped I/O.
|
// Probably a null pointer or memory-mapped I/O.
|
||||||
return pointerValue{}, errExpectedPointer
|
return pointerValue{}, errIntegerAsPointer
|
||||||
}
|
}
|
||||||
return pointerValue{v.buf[0]}, nil
|
return pointerValue{v.buf[0]}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-5
@@ -16,7 +16,6 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/cgo"
|
"github.com/tinygo-org/tinygo/cgo"
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
@@ -110,10 +109,7 @@ func Load(config *compileopts.Config, inputPkgs []string, clangHeaders string, t
|
|||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||||
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
|
os.Exit(exitErr.ExitCode())
|
||||||
os.Exit(status.ExitStatus())
|
|
||||||
}
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("failed to run `go list`: %s", err)
|
return nil, fmt.Errorf("failed to run `go list`: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mattn/go-colorable"
|
"github.com/mattn/go-colorable"
|
||||||
@@ -106,7 +105,7 @@ func Build(pkgName, outpath string, options *compileopts.Options) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.Build(pkgName, outpath, config, func(result builder.BuildResult) error {
|
return builder.Build(pkgName, outpath, config, nil, func(result builder.BuildResult) error {
|
||||||
if err := os.Rename(result.Binary, outpath); err != nil {
|
if err := os.Rename(result.Binary, outpath); err != nil {
|
||||||
// Moving failed. Do a file copy.
|
// Moving failed. Do a file copy.
|
||||||
inf, err := os.Open(result.Binary)
|
inf, err := os.Open(result.Binary)
|
||||||
@@ -142,7 +141,7 @@ func Test(pkgName string, options *compileopts.Options, testCompileOnly bool, ou
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.Build(pkgName, outpath, config, func(result builder.BuildResult) error {
|
return builder.Build(pkgName, outpath, config, nil, func(result builder.BuildResult) error {
|
||||||
if testCompileOnly || outpath != "" {
|
if testCompileOnly || outpath != "" {
|
||||||
// Write test binary to the specified file name.
|
// Write test binary to the specified file name.
|
||||||
if outpath == "" {
|
if outpath == "" {
|
||||||
@@ -166,10 +165,7 @@ func Test(pkgName string, options *compileopts.Options, testCompileOnly bool, ou
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
// Propagate the exit code
|
// Propagate the exit code
|
||||||
if err, ok := err.(*exec.ExitError); ok {
|
if err, ok := err.(*exec.ExitError); ok {
|
||||||
if status, ok := err.Sys().(syscall.WaitStatus); ok {
|
os.Exit(err.ExitCode())
|
||||||
os.Exit(status.ExitStatus())
|
|
||||||
}
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
return &commandError{"failed to run compiled binary", result.Binary, err}
|
return &commandError{"failed to run compiled binary", result.Binary, err}
|
||||||
}
|
}
|
||||||
@@ -241,7 +237,7 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
|||||||
return errors.New("unknown flash method: " + flashMethod)
|
return errors.New("unknown flash method: " + flashMethod)
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.Build(pkgName, fileExt, config, func(result builder.BuildResult) error {
|
return builder.Build(pkgName, fileExt, config, func() error {
|
||||||
// do we need port reset to put MCU into bootloader mode?
|
// do we need port reset to put MCU into bootloader mode?
|
||||||
if config.Target.PortReset == "true" && flashMethod != "openocd" {
|
if config.Target.PortReset == "true" && flashMethod != "openocd" {
|
||||||
if port == "" {
|
if port == "" {
|
||||||
@@ -254,19 +250,21 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
|||||||
|
|
||||||
err := touchSerialPortAt1200bps(port)
|
err := touchSerialPortAt1200bps(port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &commandError{"failed to reset port", result.Binary, err}
|
return &commandError{"failed to reset port", "", err}
|
||||||
}
|
}
|
||||||
// give the target MCU a chance to restart into bootloader
|
// give the target MCU a chance to restart into bootloader
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}, func(result builder.BuildResult) error {
|
||||||
// this flashing method copies the binary data to a Mass Storage Device (msd)
|
// this flashing method copies the binary data to a Mass Storage Device (msd)
|
||||||
switch flashMethod {
|
switch flashMethod {
|
||||||
case "", "command":
|
case "", "command":
|
||||||
// Create the command.
|
// Create the command.
|
||||||
flashCmd := config.Target.FlashCommand
|
flashCmd := config.Target.FlashCommand
|
||||||
fileToken := "{" + fileExt[1:] + "}"
|
fileToken := "{" + fileExt[1:] + "}"
|
||||||
flashCmd = strings.Replace(flashCmd, fileToken, result.Binary, -1)
|
flashCmd = strings.ReplaceAll(flashCmd, fileToken, result.Binary)
|
||||||
|
|
||||||
if port == "" && strings.Contains(flashCmd, "{port}") {
|
if port == "" && strings.Contains(flashCmd, "{port}") {
|
||||||
var err error
|
var err error
|
||||||
@@ -276,7 +274,7 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flashCmd = strings.Replace(flashCmd, "{port}", port, -1)
|
flashCmd = strings.ReplaceAll(flashCmd, "{port}", port)
|
||||||
|
|
||||||
// Execute the command.
|
// Execute the command.
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
@@ -352,7 +350,7 @@ func FlashGDB(pkgName string, ocdOutput bool, options *compileopts.Options) erro
|
|||||||
return errors.New("gdb not configured in the target specification")
|
return errors.New("gdb not configured in the target specification")
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.Build(pkgName, "", config, func(result builder.BuildResult) error {
|
return builder.Build(pkgName, "", config, nil, func(result builder.BuildResult) error {
|
||||||
// Find a good way to run GDB.
|
// Find a good way to run GDB.
|
||||||
gdbInterface, openocdInterface := config.Programmer()
|
gdbInterface, openocdInterface := config.Programmer()
|
||||||
switch gdbInterface {
|
switch gdbInterface {
|
||||||
@@ -516,7 +514,7 @@ func Run(pkgName string, options *compileopts.Options) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.Build(pkgName, ".elf", config, func(result builder.BuildResult) error {
|
return builder.Build(pkgName, ".elf", config, nil, func(result builder.BuildResult) error {
|
||||||
if len(config.Target.Emulator) == 0 {
|
if len(config.Target.Emulator) == 0 {
|
||||||
// Run directly.
|
// Run directly.
|
||||||
cmd := executeCommand(config.Options, result.Binary)
|
cmd := executeCommand(config.Options, result.Binary)
|
||||||
@@ -1080,10 +1078,7 @@ func main() {
|
|||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||||
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
|
os.Exit(exitErr.ExitCode())
|
||||||
os.Exit(status.ExitStatus())
|
|
||||||
}
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
fmt.Fprintln(os.Stderr, "failed to run `go list`:", err)
|
fmt.Fprintln(os.Stderr, "failed to run `go list`:", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|||||||
@@ -0,0 +1,243 @@
|
|||||||
|
// +build grandcentral_m4
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// Digital pins
|
||||||
|
const (
|
||||||
|
// = Pin Alt. Function SERCOM PWM Timer Interrupt
|
||||||
|
// ------ -------------------- -------- ----------- -----------
|
||||||
|
D0 = PB25 // UART1 RX 0[1] EXTI9
|
||||||
|
D1 = PB24 // UART1 TX 0[0] EXTI8
|
||||||
|
D2 = PC18 // TCC0[2] EXTI2
|
||||||
|
D3 = PC19 // TCC0[3] EXTI3
|
||||||
|
D4 = PC20 // TCC0[4] EXTI4
|
||||||
|
D5 = PC21 // TCC0[5] EXTI5
|
||||||
|
D6 = PD20 // TCC1[0] EXTI10
|
||||||
|
D7 = PD21 // TCC1[1] EXTI11
|
||||||
|
D8 = PB18 // TCC1[0] EXTI2
|
||||||
|
D9 = PB02 // TC6[0] EXTI3
|
||||||
|
D10 = PB22 // TC7[0] EXTI6
|
||||||
|
D11 = PB23 // EXTI7
|
||||||
|
D12 = PB00 // TC7[0] EXTI0
|
||||||
|
D13 = PB01 // On-board LED TC7[1] EXTI1
|
||||||
|
D14 = PB16 // UART4 TX, I2S0 SCK 5[0] TC6[0] EXTI0
|
||||||
|
D15 = PB17 // UART4 RX, I2S0 MCK 5[1] EXTI1
|
||||||
|
D16 = PC22 // UART3 TX 1[0] EXTI6
|
||||||
|
D17 = PC23 // UART3 RX 1[1] EXTI6
|
||||||
|
D18 = PB12 // UART2 TX 4[0] TCC3[0] EXTI12
|
||||||
|
D19 = PB13 // UART2 RX 4[1] TCC3[1] EXTI13
|
||||||
|
D20 = PB20 // I2C0 SDA 3[0] EXTI4
|
||||||
|
D21 = PB21 // I2C0 SCL 3[1] EXTI5
|
||||||
|
D22 = PD12 // EXTI7
|
||||||
|
D23 = PA15 // TCC2[1] EXTI15
|
||||||
|
D24 = PC17 // I2C1 SCL 6[1] TCC0[1] EXTI1
|
||||||
|
D25 = PC16 // I2C1 SDA 6[0] TCC0[0] EXTI0
|
||||||
|
D26 = PA12 // PCC DEN1 TC2[0] EXTI12
|
||||||
|
D27 = PA13 // PCC DEN2 TC2[1] EXTI13
|
||||||
|
D28 = PA14 // PCC CLK TCC2[0] EXTI14
|
||||||
|
D29 = PB19 // PCC XCLK EXTI3
|
||||||
|
D30 = PA23 // PCC D7 TC4[1] EXTI7
|
||||||
|
D31 = PA22 // PCC D6, I2S0 SDI TC4[0] EXTI6
|
||||||
|
D32 = PA21 // PCC D5, I2S0 SDO EXTI5
|
||||||
|
D33 = PA20 // PCC D4, I2S0 FS EXTI4
|
||||||
|
D34 = PA19 // PCC D3 TC3[1] EXTI3
|
||||||
|
D35 = PA18 // PCC D2 TC3[0] EXTI2
|
||||||
|
D36 = PA17 // PCC D1 EXTI1
|
||||||
|
D37 = PA16 // PCC D0 EXTI0
|
||||||
|
D38 = PB15 // PCC D9 TCC4[1] EXTI15
|
||||||
|
D39 = PB14 // PCC D8 TCC4[0] EXTI14
|
||||||
|
D40 = PC13 // PCC D11 EXTI13
|
||||||
|
D41 = PC12 // PCC D10 EXTI12
|
||||||
|
D42 = PC15 // PCC D13 EXTI15
|
||||||
|
D43 = PC14 // PCC D12 EXTI14
|
||||||
|
D44 = PC11 // EXTI11
|
||||||
|
D45 = PC10 // EXTI10
|
||||||
|
D46 = PC06 // EXTI6
|
||||||
|
D47 = PC07 // EXTI5
|
||||||
|
D48 = PC04 // EXTI4
|
||||||
|
D49 = PC05 // EXTI5
|
||||||
|
D50 = PD11 // SPI0 SDI 7[3] EXTI11
|
||||||
|
D51 = PD08 // SPI0 SDO 7[0] EXTI8
|
||||||
|
D52 = PD09 // SPI0 SCK 7[1] EXTI9
|
||||||
|
D53 = PD10 // SPI0 CS EXTI10
|
||||||
|
D54 = PB05 // ADC1 (A8) EXTI5
|
||||||
|
D55 = PB06 // ADC1 (A9) EXTI6
|
||||||
|
D56 = PB07 // ADC1 (A10) EXTI7
|
||||||
|
D57 = PB08 // ADC1 (A11) EXTI8
|
||||||
|
D58 = PB09 // ADC1 (A12) EXTI9
|
||||||
|
D59 = PA04 // ADC0 (A13) TC0[0] EXTI4
|
||||||
|
D60 = PA06 // ADC0 (A14) TC1[0] EXTI6
|
||||||
|
D61 = PA07 // ADC0 (A15) TC1[1] EXTI7
|
||||||
|
D62 = PB20 // I2C0 SDA 3[0] TCC1[2] EXTI4
|
||||||
|
D63 = PB21 // I2C0 SCL 3[1] TCC1[3] EXTI5
|
||||||
|
D64 = PD11 // SPI0 SDI 7[3] EXTI6
|
||||||
|
D65 = PD08 // SPI0 SDO 7[0] EXTI3
|
||||||
|
D66 = PD09 // SPI0 SCK 7[1] EXTI4
|
||||||
|
D67 = PA02 // ADC0 (A0), DAC0 EXTI2
|
||||||
|
D68 = PA05 // ADC0 (A1), DAC1 EXTI5
|
||||||
|
D69 = PB03 // ADC0 (A2) TC6[1] EXTI3
|
||||||
|
D70 = PC00 // ADC1 (A3) EXTI0
|
||||||
|
D71 = PC01 // ADC1 (A4) EXTI1
|
||||||
|
D72 = PC02 // ADC1 (A5) EXTI2
|
||||||
|
D73 = PC03 // ADC1 (A6) EXTI3
|
||||||
|
D74 = PB04 // ADC1 (A7) EXTI4
|
||||||
|
D75 = PC31 // UART RX LED
|
||||||
|
D76 = PC30 // UART TX LED
|
||||||
|
D77 = PA27 // USB HOST EN
|
||||||
|
D78 = PA24 // USB DM EXTI8
|
||||||
|
D79 = PA25 // USB DP EXTI9
|
||||||
|
D80 = PB29 // SD/SPI1 SDI 2[3]
|
||||||
|
D81 = PB27 // SD/SPI1 SCK 2[1]
|
||||||
|
D82 = PB26 // SD/SPI1 SDO 2[0]
|
||||||
|
D83 = PB28 // SD/SPI1 CS
|
||||||
|
D84 = PA03 // AREF EXTI3
|
||||||
|
D85 = PA02 // DAC0 EXTI2
|
||||||
|
D86 = PA05 // DAC1 EXTI5
|
||||||
|
D87 = PB01 // On-board LED (D13) TC7[1] EXTI1
|
||||||
|
D88 = PC24 // On-board NeoPixel
|
||||||
|
D89 = PB10 // QSPI SCK EXTI10
|
||||||
|
D90 = PB11 // QSPI CS EXTI11
|
||||||
|
D91 = PA08 // QSPI ID0 EXTI(NMI)
|
||||||
|
D92 = PA09 // QSPI ID1 EXTI9
|
||||||
|
D93 = PA10 // QSPI ID2 EXTI10
|
||||||
|
D94 = PA11 // QSPI ID3 EXTI11
|
||||||
|
D95 = PB31 // SD Detect EXTI15
|
||||||
|
D96 = PB30 // SWO EXTI14
|
||||||
|
)
|
||||||
|
|
||||||
|
// Analog pins
|
||||||
|
const (
|
||||||
|
A0 = D67 // (PA02) ADC0 ch. 0,
|
||||||
|
A1 = D68 // (PA05) ADC0 ch. 5,
|
||||||
|
A2 = D69 // (PB03) ADC0 ch. 15
|
||||||
|
A3 = D70 // (PC00) ADC1 ch. 10
|
||||||
|
A4 = D71 // (PC01) ADC1 ch. 11
|
||||||
|
A5 = D72 // (PC02) ADC1 ch. 4
|
||||||
|
A6 = D73 // (PC03) ADC1 ch. 5
|
||||||
|
A7 = D74 // (PB04) ADC1 ch. 6
|
||||||
|
A8 = D54 // (PB05) ADC1 ch. 7
|
||||||
|
A9 = D55 // (PB06) ADC1 ch. 8
|
||||||
|
A10 = D56 // (PB07) ADC1 ch. 9
|
||||||
|
A11 = D57 // (PB08) ADC1 ch. 0
|
||||||
|
A12 = D58 // (PB09) ADC1 ch. 1
|
||||||
|
A13 = D59 // (PA04) ADC0 ch. 4
|
||||||
|
A14 = D60 // (PA06) ADC0 ch. 6
|
||||||
|
A15 = D61 // (PA07) ADC0 ch. 7
|
||||||
|
|
||||||
|
AREF = D84 // (PA03)
|
||||||
|
)
|
||||||
|
|
||||||
|
// LED pins
|
||||||
|
const (
|
||||||
|
LED_PIN = D13 // (PB01), also on D87
|
||||||
|
UART_RX_LED_PIN = D75 // (PC31)
|
||||||
|
UART_TX_LED_PIN = D76 // (PC30)
|
||||||
|
NEOPIXEL_PIN = D88 // (PC24)
|
||||||
|
|
||||||
|
// aliases used by examples and drivers
|
||||||
|
LED = LED_PIN
|
||||||
|
LED_RX = UART_RX_LED_PIN
|
||||||
|
LED_TX = UART_TX_LED_PIN
|
||||||
|
NEOPIXEL = NEOPIXEL_PIN
|
||||||
|
)
|
||||||
|
|
||||||
|
// UART pins
|
||||||
|
const (
|
||||||
|
UART1_RX_PIN = D0 // (PB25)
|
||||||
|
UART1_TX_PIN = D1 // (PB24)
|
||||||
|
|
||||||
|
UART2_RX_PIN = D19 // (PB13)
|
||||||
|
UART2_TX_PIN = D18 // (PB12)
|
||||||
|
|
||||||
|
UART3_RX_PIN = D17 // (PC23)
|
||||||
|
UART3_TX_PIN = D16 // (PC22)
|
||||||
|
|
||||||
|
UART4_RX_PIN = D15 // (PB17)
|
||||||
|
UART4_TX_PIN = D14 // (PB16)
|
||||||
|
|
||||||
|
UART_RX_PIN = UART1_RX_PIN // default pins
|
||||||
|
UART_TX_PIN = UART1_TX_PIN //
|
||||||
|
)
|
||||||
|
|
||||||
|
// SPI pins
|
||||||
|
const (
|
||||||
|
SPI0_SCK_PIN = D66 // (PD09), also on D52
|
||||||
|
SPI0_SDO_PIN = D65 // (PD08), also on D51
|
||||||
|
SPI0_SDI_PIN = D64 // (PD11), also on D50
|
||||||
|
SPI0_CS_PIN = D53 // (PD10)
|
||||||
|
|
||||||
|
SPI1_SCK_PIN = D81 // (PB27)
|
||||||
|
SPI1_SDO_PIN = D82 // (PB26)
|
||||||
|
SPI1_SDI_PIN = D80 // (PB29)
|
||||||
|
|
||||||
|
SPI_SCK_PIN = SPI0_SCK_PIN // default pins
|
||||||
|
SPI_SDO_PIN = SPI0_SDO_PIN //
|
||||||
|
SPI_SDI_PIN = SPI0_SDI_PIN //
|
||||||
|
SPI_CS_PIN = SPI0_CS_PIN //
|
||||||
|
)
|
||||||
|
|
||||||
|
// I2C pins
|
||||||
|
const (
|
||||||
|
I2C0_SDA_PIN = D62 // (PB20), also on D20
|
||||||
|
I2C0_SCL_PIN = D63 // (PB21), also on D21
|
||||||
|
|
||||||
|
I2C1_SDA_PIN = D25 // (PC16)
|
||||||
|
I2C1_SCL_PIN = D24 // (PC17)
|
||||||
|
|
||||||
|
I2C_SDA_PIN = I2C0_SDA_PIN // default pins
|
||||||
|
I2C_SCL_PIN = I2C0_SCL_PIN //
|
||||||
|
|
||||||
|
SDA_PIN = I2C_SDA_PIN // unconventional pin names
|
||||||
|
SCL_PIN = I2C_SCL_PIN // (required by machine_atsamd51.go)
|
||||||
|
)
|
||||||
|
|
||||||
|
// I2S pins
|
||||||
|
const (
|
||||||
|
I2S0_SCK_PIN = D14 // (PB16)
|
||||||
|
I2S0_MCK_PIN = D15 // (PB17)
|
||||||
|
I2S0_FS_PIN = D33 // (PA20)
|
||||||
|
I2S0_SDO_PIN = D32 // (PA21)
|
||||||
|
I2S0_SDI_PIN = D31 // (PA22)
|
||||||
|
|
||||||
|
I2S_SCK_PIN = I2S0_SCK_PIN // default pins
|
||||||
|
I2S_WS_PIN = I2S0_FS_PIN //
|
||||||
|
I2S_SD_PIN = I2S0_SDO_PIN //
|
||||||
|
)
|
||||||
|
|
||||||
|
// SD card pins
|
||||||
|
const (
|
||||||
|
SD0_SCK_PIN = D81 // (PB27)
|
||||||
|
SD0_SDO_PIN = D82 // (PB26)
|
||||||
|
SD0_SDI_PIN = D80 // (PB29)
|
||||||
|
SD0_CS_PIN = D83 // (PB28)
|
||||||
|
SD0_DET_PIN = D95 // (PB31)
|
||||||
|
|
||||||
|
SDCARD_SCK_PIN = SD0_SCK_PIN // default pins
|
||||||
|
SDCARD_SDO_PIN = SD0_SDO_PIN //
|
||||||
|
SDCARD_SDI_PIN = SD0_SDI_PIN //
|
||||||
|
SDCARD_CS_PIN = SD0_CS_PIN //
|
||||||
|
SDCARD_DET_PIN = SD0_DET_PIN //
|
||||||
|
)
|
||||||
|
|
||||||
|
// Other peripheral constants
|
||||||
|
const (
|
||||||
|
RESET_MAGIC_VALUE = 0xF01669EF // Used to reset into bootloader
|
||||||
|
)
|
||||||
|
|
||||||
|
// USB CDC pins
|
||||||
|
const (
|
||||||
|
USBCDC_HOSTEN_PIN = D77 // (PA27) host enable
|
||||||
|
USBCDC_DM_PIN = D78 // (PA24) D-
|
||||||
|
USBCDC_DP_PIN = D79 // (PA25) D+
|
||||||
|
)
|
||||||
|
|
||||||
|
// USB CDC identifiers
|
||||||
|
const (
|
||||||
|
usb_STRING_PRODUCT = "Adafruit Grand Central M4"
|
||||||
|
usb_STRING_MANUFACTURER = "Adafruit"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
usb_VID uint16 = 0x239A
|
||||||
|
usb_PID uint16 = 0x8031
|
||||||
|
)
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
// +build grandcentral_m4
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/sam"
|
||||||
|
"runtime/interrupt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
UART1.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, UART1.handleInterrupt)
|
||||||
|
UART2.Interrupt = interrupt.New(sam.IRQ_SERCOM4_2, UART2.handleInterrupt)
|
||||||
|
UART3.Interrupt = interrupt.New(sam.IRQ_SERCOM1_2, UART3.handleInterrupt)
|
||||||
|
UART4.Interrupt = interrupt.New(sam.IRQ_SERCOM5_2, UART4.handleInterrupt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UART on the Grand Central M4
|
||||||
|
var (
|
||||||
|
UART1 = UART{
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
Bus: sam.SERCOM0_USART_INT,
|
||||||
|
SERCOM: 0,
|
||||||
|
}
|
||||||
|
UART2 = UART{
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
Bus: sam.SERCOM4_USART_INT,
|
||||||
|
SERCOM: 4,
|
||||||
|
}
|
||||||
|
UART3 = UART{
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
Bus: sam.SERCOM1_USART_INT,
|
||||||
|
SERCOM: 1,
|
||||||
|
}
|
||||||
|
UART4 = UART{
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
Bus: sam.SERCOM5_USART_INT,
|
||||||
|
SERCOM: 5,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// I2C on the Grand Central M4
|
||||||
|
var (
|
||||||
|
I2C0 = I2C{
|
||||||
|
Bus: sam.SERCOM3_I2CM,
|
||||||
|
SERCOM: 3,
|
||||||
|
}
|
||||||
|
I2C1 = I2C{
|
||||||
|
Bus: sam.SERCOM6_I2CM,
|
||||||
|
SERCOM: 6,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// SPI on the Grand Central M4
|
||||||
|
var (
|
||||||
|
SPI0 = SPI{
|
||||||
|
Bus: sam.SERCOM7_SPIM,
|
||||||
|
SERCOM: 7,
|
||||||
|
}
|
||||||
|
SPI1 = SPI{ // SD card
|
||||||
|
Bus: sam.SERCOM2_SPIM,
|
||||||
|
SERCOM: 2,
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -136,9 +136,11 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
UART0 = &UART1 // alias UART0 to UART1
|
||||||
UART1 = UART{
|
UART1 = UART{
|
||||||
Buffer: NewRingBuffer(),
|
|
||||||
Bus: nxp.LPUART6,
|
Bus: nxp.LPUART6,
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
txBuffer: NewRingBuffer(),
|
||||||
muxRX: muxSelect{ // D0 (PA3 [AD_B0_03])
|
muxRX: muxSelect{ // D0 (PA3 [AD_B0_03])
|
||||||
mux: nxp.IOMUXC_LPUART6_RX_SELECT_INPUT_DAISY_GPIO_AD_B0_03_ALT2,
|
mux: nxp.IOMUXC_LPUART6_RX_SELECT_INPUT_DAISY_GPIO_AD_B0_03_ALT2,
|
||||||
sel: &nxp.IOMUXC.LPUART6_RX_SELECT_INPUT,
|
sel: &nxp.IOMUXC.LPUART6_RX_SELECT_INPUT,
|
||||||
@@ -149,8 +151,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
UART2 = UART{
|
UART2 = UART{
|
||||||
Buffer: NewRingBuffer(),
|
|
||||||
Bus: nxp.LPUART4,
|
Bus: nxp.LPUART4,
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
txBuffer: NewRingBuffer(),
|
||||||
muxRX: muxSelect{ // D7 (PB17 [B1_01])
|
muxRX: muxSelect{ // D7 (PB17 [B1_01])
|
||||||
mux: nxp.IOMUXC_LPUART4_RX_SELECT_INPUT_DAISY_GPIO_B1_01_ALT2,
|
mux: nxp.IOMUXC_LPUART4_RX_SELECT_INPUT_DAISY_GPIO_B1_01_ALT2,
|
||||||
sel: &nxp.IOMUXC.LPUART4_RX_SELECT_INPUT,
|
sel: &nxp.IOMUXC.LPUART4_RX_SELECT_INPUT,
|
||||||
@@ -161,8 +164,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
UART3 = UART{
|
UART3 = UART{
|
||||||
Buffer: NewRingBuffer(),
|
|
||||||
Bus: nxp.LPUART2,
|
Bus: nxp.LPUART2,
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
txBuffer: NewRingBuffer(),
|
||||||
muxRX: muxSelect{ // D15 (PA19 [AD_B1_03])
|
muxRX: muxSelect{ // D15 (PA19 [AD_B1_03])
|
||||||
mux: nxp.IOMUXC_LPUART2_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_03_ALT2,
|
mux: nxp.IOMUXC_LPUART2_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_03_ALT2,
|
||||||
sel: &nxp.IOMUXC.LPUART2_RX_SELECT_INPUT,
|
sel: &nxp.IOMUXC.LPUART2_RX_SELECT_INPUT,
|
||||||
@@ -173,8 +177,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
UART4 = UART{
|
UART4 = UART{
|
||||||
Buffer: NewRingBuffer(),
|
|
||||||
Bus: nxp.LPUART3,
|
Bus: nxp.LPUART3,
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
txBuffer: NewRingBuffer(),
|
||||||
muxRX: muxSelect{ // D16 (PA23 [AD_B1_07])
|
muxRX: muxSelect{ // D16 (PA23 [AD_B1_07])
|
||||||
mux: nxp.IOMUXC_LPUART3_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_07_ALT2,
|
mux: nxp.IOMUXC_LPUART3_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_07_ALT2,
|
||||||
sel: &nxp.IOMUXC.LPUART3_RX_SELECT_INPUT,
|
sel: &nxp.IOMUXC.LPUART3_RX_SELECT_INPUT,
|
||||||
@@ -185,8 +190,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
UART5 = UART{
|
UART5 = UART{
|
||||||
Buffer: NewRingBuffer(),
|
|
||||||
Bus: nxp.LPUART8,
|
Bus: nxp.LPUART8,
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
txBuffer: NewRingBuffer(),
|
||||||
muxRX: muxSelect{ // D21 (PA27 [AD_B1_11])
|
muxRX: muxSelect{ // D21 (PA27 [AD_B1_11])
|
||||||
mux: nxp.IOMUXC_LPUART8_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_11_ALT2,
|
mux: nxp.IOMUXC_LPUART8_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_11_ALT2,
|
||||||
sel: &nxp.IOMUXC.LPUART8_RX_SELECT_INPUT,
|
sel: &nxp.IOMUXC.LPUART8_RX_SELECT_INPUT,
|
||||||
@@ -197,15 +203,17 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
UART6 = UART{
|
UART6 = UART{
|
||||||
Buffer: NewRingBuffer(),
|
|
||||||
Bus: nxp.LPUART1,
|
Bus: nxp.LPUART1,
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
txBuffer: NewRingBuffer(),
|
||||||
// LPUART1 not connected via IOMUXC
|
// LPUART1 not connected via IOMUXC
|
||||||
// RX: D24 (PA12 [AD_B0_12])
|
// RX: D24 (PA12 [AD_B0_12])
|
||||||
// TX: D25 (PA13 [AD_B0_13])
|
// TX: D25 (PA13 [AD_B0_13])
|
||||||
}
|
}
|
||||||
UART7 = UART{
|
UART7 = UART{
|
||||||
Buffer: NewRingBuffer(),
|
|
||||||
Bus: nxp.LPUART7,
|
Bus: nxp.LPUART7,
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
txBuffer: NewRingBuffer(),
|
||||||
muxRX: muxSelect{ // D28 (PC18 [EMC_32])
|
muxRX: muxSelect{ // D28 (PC18 [EMC_32])
|
||||||
mux: nxp.IOMUXC_LPUART7_RX_SELECT_INPUT_DAISY_GPIO_EMC_32_ALT2,
|
mux: nxp.IOMUXC_LPUART7_RX_SELECT_INPUT_DAISY_GPIO_EMC_32_ALT2,
|
||||||
sel: &nxp.IOMUXC.LPUART7_RX_SELECT_INPUT,
|
sel: &nxp.IOMUXC.LPUART7_RX_SELECT_INPUT,
|
||||||
|
|||||||
@@ -114,6 +114,12 @@ func (i2c I2C) readByte() byte {
|
|||||||
return byte(avr.TWDR.Get())
|
return byte(avr.TWDR.Get())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UART
|
||||||
|
var (
|
||||||
|
// UART0 is the hardware serial port on the AVR.
|
||||||
|
UART0 = UART{Buffer: NewRingBuffer()}
|
||||||
|
)
|
||||||
|
|
||||||
// UART on the AVR.
|
// UART on the AVR.
|
||||||
type UART struct {
|
type UART struct {
|
||||||
Buffer *RingBuffer
|
Buffer *RingBuffer
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ package machine
|
|||||||
import (
|
import (
|
||||||
"device/arm"
|
"device/arm"
|
||||||
"device/sam"
|
"device/sam"
|
||||||
|
"errors"
|
||||||
"runtime/interrupt"
|
"runtime/interrupt"
|
||||||
"runtime/volatile"
|
"runtime/volatile"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@@ -1469,6 +1470,96 @@ func (spi SPI) Transfer(w byte) (byte, error) {
|
|||||||
return byte(spi.Bus.DATA.Get()), nil
|
return byte(spi.Bus.DATA.Get()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tx handles read/write operation for SPI interface. Since SPI is a syncronous write/read
|
||||||
|
// interface, there must always be the same number of bytes written as bytes read.
|
||||||
|
// The Tx method knows about this, and offers a few different ways of calling it.
|
||||||
|
//
|
||||||
|
// This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer.
|
||||||
|
// Note that the tx and rx buffers must be the same size:
|
||||||
|
//
|
||||||
|
// spi.Tx(tx, rx)
|
||||||
|
//
|
||||||
|
// This form sends the tx buffer, ignoring the result. Useful for sending "commands" that return zeros
|
||||||
|
// until all the bytes in the command packet have been received:
|
||||||
|
//
|
||||||
|
// spi.Tx(tx, nil)
|
||||||
|
//
|
||||||
|
// This form sends zeros, putting the result into the rx buffer. Good for reading a "result packet":
|
||||||
|
//
|
||||||
|
// spi.Tx(nil, rx)
|
||||||
|
//
|
||||||
|
func (spi SPI) Tx(w, r []byte) error {
|
||||||
|
switch {
|
||||||
|
case w == nil:
|
||||||
|
// read only, so write zero and read a result.
|
||||||
|
spi.rx(r)
|
||||||
|
case r == nil:
|
||||||
|
// write only
|
||||||
|
spi.tx(w)
|
||||||
|
|
||||||
|
default:
|
||||||
|
// write/read
|
||||||
|
if len(w) != len(r) {
|
||||||
|
return ErrTxInvalidSliceSize
|
||||||
|
}
|
||||||
|
|
||||||
|
spi.txrx(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (spi SPI) tx(tx []byte) {
|
||||||
|
for i := 0; i < len(tx); i++ {
|
||||||
|
for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_DRE) {
|
||||||
|
}
|
||||||
|
spi.Bus.DATA.Set(uint32(tx[i]))
|
||||||
|
}
|
||||||
|
for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_TXC) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// read to clear RXC register
|
||||||
|
for spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {
|
||||||
|
spi.Bus.DATA.Get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (spi SPI) rx(rx []byte) {
|
||||||
|
spi.Bus.DATA.Set(0)
|
||||||
|
for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_DRE) {
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; i < len(rx); i++ {
|
||||||
|
spi.Bus.DATA.Set(0)
|
||||||
|
for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {
|
||||||
|
}
|
||||||
|
rx[i-1] = byte(spi.Bus.DATA.Get())
|
||||||
|
}
|
||||||
|
for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {
|
||||||
|
}
|
||||||
|
rx[len(rx)-1] = byte(spi.Bus.DATA.Get())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (spi SPI) txrx(tx, rx []byte) {
|
||||||
|
spi.Bus.DATA.Set(uint32(tx[0]))
|
||||||
|
for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_DRE) {
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; i < len(rx); i++ {
|
||||||
|
spi.Bus.DATA.Set(uint32(tx[i]))
|
||||||
|
for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {
|
||||||
|
}
|
||||||
|
rx[i-1] = byte(spi.Bus.DATA.Get())
|
||||||
|
}
|
||||||
|
for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {
|
||||||
|
}
|
||||||
|
rx[len(rx)-1] = byte(spi.Bus.DATA.Get())
|
||||||
|
}
|
||||||
|
|
||||||
// The QSPI peripheral on ATSAMD51 is only available on the following pins
|
// The QSPI peripheral on ATSAMD51 is only available on the following pins
|
||||||
const (
|
const (
|
||||||
QSPI_SCK = PB10
|
QSPI_SCK = PB10
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
// +build sam,atsamd51,atsamd51p20
|
||||||
|
|
||||||
|
// Peripheral abstraction layer for the atsamd51.
|
||||||
|
//
|
||||||
|
// Datasheet:
|
||||||
|
// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
|
||||||
|
//
|
||||||
|
package machine
|
||||||
|
|
||||||
|
import "device/sam"
|
||||||
|
|
||||||
|
const HSRAM_SIZE = 0x00040000
|
||||||
|
|
||||||
|
// InitPWM initializes the PWM interface.
|
||||||
|
func InitPWM() {
|
||||||
|
// turn on timer clocks used for PWM
|
||||||
|
sam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC0_ | sam.MCLK_APBBMASK_TCC1_)
|
||||||
|
sam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC2_ | sam.MCLK_APBCMASK_TCC3_)
|
||||||
|
sam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_TCC4_)
|
||||||
|
|
||||||
|
//use clock generator 0
|
||||||
|
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC0].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) |
|
||||||
|
sam.GCLK_PCHCTRL_CHEN)
|
||||||
|
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC2].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) |
|
||||||
|
sam.GCLK_PCHCTRL_CHEN)
|
||||||
|
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC4].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) |
|
||||||
|
sam.GCLK_PCHCTRL_CHEN)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getTimer returns the timer to be used for PWM on this pin
|
||||||
|
func (pwm PWM) getTimer() *sam.TCC_Type {
|
||||||
|
switch pwm.Pin {
|
||||||
|
case PC18:
|
||||||
|
return sam.TCC0
|
||||||
|
case PC19:
|
||||||
|
return sam.TCC0
|
||||||
|
case PC20:
|
||||||
|
return sam.TCC0
|
||||||
|
case PC21:
|
||||||
|
return sam.TCC0
|
||||||
|
case PD20:
|
||||||
|
return sam.TCC1
|
||||||
|
case PD21:
|
||||||
|
return sam.TCC1
|
||||||
|
case PB18:
|
||||||
|
return sam.TCC1
|
||||||
|
case PB12:
|
||||||
|
return sam.TCC3
|
||||||
|
case PB13:
|
||||||
|
return sam.TCC3
|
||||||
|
case PA15:
|
||||||
|
return sam.TCC2
|
||||||
|
case PC17:
|
||||||
|
return sam.TCC0
|
||||||
|
case PC16:
|
||||||
|
return sam.TCC0
|
||||||
|
case PA14:
|
||||||
|
return sam.TCC2
|
||||||
|
case PB15:
|
||||||
|
return sam.TCC4
|
||||||
|
case PB14:
|
||||||
|
return sam.TCC4
|
||||||
|
case PB20:
|
||||||
|
return sam.TCC1
|
||||||
|
case PB21:
|
||||||
|
return sam.TCC1
|
||||||
|
default:
|
||||||
|
return nil // not supported on this pin
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,23 +2,6 @@
|
|||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
// UART on the AVR is a dummy implementation. UART has not been implemented for ATtiny
|
|
||||||
// devices.
|
|
||||||
type UART struct {
|
|
||||||
Buffer *RingBuffer
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure is a dummy implementation. UART has not been implemented for ATtiny
|
|
||||||
// devices.
|
|
||||||
func (uart UART) Configure(config UARTConfig) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteByte is a dummy implementation. UART has not been implemented for ATtiny
|
|
||||||
// devices.
|
|
||||||
func (uart UART) WriteByte(c byte) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tx is a dummy implementation. I2C has not been implemented for ATtiny
|
// Tx is a dummy implementation. I2C has not been implemented for ATtiny
|
||||||
// devices.
|
// devices.
|
||||||
func (i2c I2C) Tx(addr uint16, w, r []byte) error {
|
func (i2c I2C) Tx(addr uint16, w, r []byte) error {
|
||||||
|
|||||||
@@ -148,9 +148,3 @@ type I2C struct {
|
|||||||
|
|
||||||
// I2C0 is the only I2C interface on most AVRs.
|
// I2C0 is the only I2C interface on most AVRs.
|
||||||
var I2C0 = I2C{}
|
var I2C0 = I2C{}
|
||||||
|
|
||||||
// UART
|
|
||||||
var (
|
|
||||||
// UART0 is the hardware serial port on the AVR.
|
|
||||||
UART0 = UART{Buffer: NewRingBuffer()}
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -174,11 +174,13 @@ func (spi SPI) Transfer(w byte) (byte, error) {
|
|||||||
spi.Bus.TXDATA.Set(uint32(w))
|
spi.Bus.TXDATA.Set(uint32(w))
|
||||||
|
|
||||||
// wait until receive has data
|
// wait until receive has data
|
||||||
for spi.Bus.RXDATA.HasBits(sifive.QSPI_RXDATA_EMPTY) {
|
data := spi.Bus.RXDATA.Get()
|
||||||
|
for data&sifive.QSPI_RXDATA_EMPTY > 0 {
|
||||||
|
data = spi.Bus.RXDATA.Get()
|
||||||
}
|
}
|
||||||
|
|
||||||
// return data
|
// return data
|
||||||
return byte(spi.Bus.RXDATA.Get() & sifive.QSPI_RXDATA_DATA_Msk), nil
|
return byte(data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// I2C on the FE310-G002.
|
// I2C on the FE310-G002.
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ type UART struct {
|
|||||||
Buffer *RingBuffer
|
Buffer *RingBuffer
|
||||||
Interrupt interrupt.Interrupt
|
Interrupt interrupt.Interrupt
|
||||||
|
|
||||||
|
// txBuffer should be allocated globally (such as when UART is created) to
|
||||||
|
// prevent it being reclaimed or cleaned up prematurely.
|
||||||
|
txBuffer *RingBuffer
|
||||||
|
|
||||||
// these hold the input selector ("daisy chain") values that select which pins
|
// these hold the input selector ("daisy chain") values that select which pins
|
||||||
// are connected to the LPUART device, and should be defined where the UART
|
// are connected to the LPUART device, and should be defined where the UART
|
||||||
// instance is declared. see the godoc comments on type muxSelect for more
|
// instance is declared. see the godoc comments on type muxSelect for more
|
||||||
@@ -31,7 +35,6 @@ type UART struct {
|
|||||||
configured bool
|
configured bool
|
||||||
msbFirst bool
|
msbFirst bool
|
||||||
transmitting volatile.Register32
|
transmitting volatile.Register32
|
||||||
txBuffer *RingBuffer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uart *UART) isTransmitting() bool { return uart.transmitting.Get() != 0 }
|
func (uart *UART) isTransmitting() bool { return uart.transmitting.Get() != 0 }
|
||||||
@@ -197,9 +200,6 @@ func (uart *UART) Sync() error {
|
|||||||
|
|
||||||
// WriteByte writes a single byte of data to the UART interface.
|
// WriteByte writes a single byte of data to the UART interface.
|
||||||
func (uart *UART) WriteByte(c byte) error {
|
func (uart *UART) WriteByte(c byte) error {
|
||||||
if nil == uart.txBuffer {
|
|
||||||
uart.txBuffer = NewRingBuffer()
|
|
||||||
}
|
|
||||||
uart.startTransmitting()
|
uart.startTransmitting()
|
||||||
for !uart.txBuffer.Put(c) {
|
for !uart.txBuffer.Put(c) {
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// +build !baremetal sam stm32,!stm32f7x2,!stm32l5x2 fe310 k210 atmega
|
// +build !baremetal atsamd21 stm32,!stm32f7x2,!stm32l5x2 fe310 k210 atmega
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// +build avr esp nrf sam sifive stm32 k210 nxp
|
// +build atmega esp nrf sam sifive stm32 k210 nxp
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -547,8 +547,8 @@ func newUSBSetup(data []byte) usbSetup {
|
|||||||
u.bRequest = uint8(data[1])
|
u.bRequest = uint8(data[1])
|
||||||
u.wValueL = uint8(data[2])
|
u.wValueL = uint8(data[2])
|
||||||
u.wValueH = uint8(data[3])
|
u.wValueH = uint8(data[3])
|
||||||
u.wIndex = uint16(data[4]) | uint16(data[5]<<8)
|
u.wIndex = uint16(data[4]) | (uint16(data[5]) << 8)
|
||||||
u.wLength = uint16(data[6]) | uint16(data[7]<<8)
|
u.wLength = uint16(data[6]) | (uint16(data[7]) << 8)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// Package debug is a dummy package that is not yet implemented.
|
||||||
|
package debug
|
||||||
@@ -4,8 +4,17 @@ package runtime
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"device/avr"
|
"device/avr"
|
||||||
|
"machine"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func initUART() {
|
||||||
|
machine.UART0.Configure(machine.UARTConfig{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func putchar(c byte) {
|
||||||
|
machine.UART0.WriteByte(c)
|
||||||
|
}
|
||||||
|
|
||||||
// Sleep for a given period. The period is defined by the WDT peripheral, and is
|
// Sleep for a given period. The period is defined by the WDT peripheral, and is
|
||||||
// on most chips (at least) 3 bits wide, in powers of two from 16ms to 2s
|
// on most chips (at least) 3 bits wide, in powers of two from 16ms to 2s
|
||||||
// (0=16ms, 1=32ms, 2=64ms...). Note that the WDT is not very accurate: it can
|
// (0=16ms, 1=32ms, 2=64ms...). Note that the WDT is not very accurate: it can
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// +build sam,atsamd51,atsamd51p20
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/sam"
|
||||||
|
)
|
||||||
|
|
||||||
|
func initSERCOMClocks() {
|
||||||
|
// Turn on clock to SERCOM0 for UART0
|
||||||
|
sam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)
|
||||||
|
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |
|
||||||
|
sam.GCLK_PCHCTRL_CHEN)
|
||||||
|
|
||||||
|
// sets the "slow" clock shared by all SERCOM
|
||||||
|
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOMX_SLOW].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |
|
||||||
|
sam.GCLK_PCHCTRL_CHEN)
|
||||||
|
|
||||||
|
// Turn on clock to SERCOM1
|
||||||
|
sam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)
|
||||||
|
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |
|
||||||
|
sam.GCLK_PCHCTRL_CHEN)
|
||||||
|
|
||||||
|
// Turn on clock to SERCOM2
|
||||||
|
sam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)
|
||||||
|
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |
|
||||||
|
sam.GCLK_PCHCTRL_CHEN)
|
||||||
|
|
||||||
|
// Turn on clock to SERCOM3
|
||||||
|
sam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)
|
||||||
|
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |
|
||||||
|
sam.GCLK_PCHCTRL_CHEN)
|
||||||
|
|
||||||
|
// Turn on clock to SERCOM4
|
||||||
|
sam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)
|
||||||
|
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |
|
||||||
|
sam.GCLK_PCHCTRL_CHEN)
|
||||||
|
|
||||||
|
// Turn on clock to SERCOM5
|
||||||
|
sam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)
|
||||||
|
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |
|
||||||
|
sam.GCLK_PCHCTRL_CHEN)
|
||||||
|
|
||||||
|
// Turn on clock to SERCOM6
|
||||||
|
sam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM6_)
|
||||||
|
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM6_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |
|
||||||
|
sam.GCLK_PCHCTRL_CHEN)
|
||||||
|
|
||||||
|
// Turn on clock to SERCOM7
|
||||||
|
sam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM7_)
|
||||||
|
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM7_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |
|
||||||
|
sam.GCLK_PCHCTRL_CHEN)
|
||||||
|
}
|
||||||
@@ -6,6 +6,13 @@ import (
|
|||||||
"device/avr"
|
"device/avr"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func initUART() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func putchar(c byte) {
|
||||||
|
// UART is not supported.
|
||||||
|
}
|
||||||
|
|
||||||
func sleepWDT(period uint8) {
|
func sleepWDT(period uint8) {
|
||||||
// TODO: use the watchdog timer instead of a busy loop.
|
// TODO: use the watchdog timer instead of a busy loop.
|
||||||
for i := 0x45; i != 0; i-- {
|
for i := 0x45; i != 0; i-- {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ package runtime
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"device/avr"
|
"device/avr"
|
||||||
"machine"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -59,14 +58,6 @@ func init() {
|
|||||||
initUART()
|
initUART()
|
||||||
}
|
}
|
||||||
|
|
||||||
func initUART() {
|
|
||||||
machine.UART0.Configure(machine.UARTConfig{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func putchar(c byte) {
|
|
||||||
machine.UART0.WriteByte(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
const asyncScheduler = false
|
const asyncScheduler = false
|
||||||
|
|
||||||
const tickNanos = 1024 * 16384 // roughly 16ms in nanoseconds
|
const tickNanos = 1024 * 16384 // roughly 16ms in nanoseconds
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ type __wasi_iovec_t struct {
|
|||||||
bufLen uint
|
bufLen uint
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:wasm-module wasi_unstable
|
//go:wasm-module wasi_snapshot_preview1
|
||||||
//export fd_write
|
//export fd_write
|
||||||
func fd_write(id uint32, iovs *__wasi_iovec_t, iovs_len uint, nwritten *uint) (errno uint)
|
func fd_write(id uint32, iovs *__wasi_iovec_t, iovs_len uint, nwritten *uint) (errno uint)
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ var (
|
|||||||
u: __wasi_subscription_u_t{
|
u: __wasi_subscription_u_t{
|
||||||
tag: __wasi_eventtype_t_clock,
|
tag: __wasi_eventtype_t_clock,
|
||||||
u: __wasi_subscription_clock_t{
|
u: __wasi_subscription_clock_t{
|
||||||
userData: 0,
|
|
||||||
id: 0,
|
id: 0,
|
||||||
timeout: 0,
|
timeout: 0,
|
||||||
precision: timePrecisionNanoseconds,
|
precision: timePrecisionNanoseconds,
|
||||||
@@ -48,23 +47,23 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func sleepTicks(d timeUnit) {
|
func sleepTicks(d timeUnit) {
|
||||||
sleepTicksSubscription.u.u.timeout = int64(d)
|
sleepTicksSubscription.u.u.timeout = uint64(d)
|
||||||
poll_oneoff(&sleepTicksSubscription, &sleepTicksResult, 1, &sleepTicksNEvents)
|
poll_oneoff(&sleepTicksSubscription, &sleepTicksResult, 1, &sleepTicksNEvents)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ticks() timeUnit {
|
func ticks() timeUnit {
|
||||||
var nano int64
|
var nano uint64
|
||||||
clock_time_get(0, timePrecisionNanoseconds, &nano)
|
clock_time_get(0, timePrecisionNanoseconds, &nano)
|
||||||
return timeUnit(nano)
|
return timeUnit(nano)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementations of wasi_unstable APIs
|
// Implementations of wasi_unstable APIs
|
||||||
|
|
||||||
//go:wasm-module wasi_unstable
|
//go:wasm-module wasi_snapshot_preview1
|
||||||
//export clock_time_get
|
//export clock_time_get
|
||||||
func clock_time_get(clockid uint32, precision uint64, time *int64) (errno uint16)
|
func clock_time_get(clockid uint32, precision uint64, time *uint64) (errno uint16)
|
||||||
|
|
||||||
//go:wasm-module wasi_unstable
|
//go:wasm-module wasi_snapshot_preview1
|
||||||
//export poll_oneoff
|
//export poll_oneoff
|
||||||
func poll_oneoff(in *__wasi_subscription_t, out *__wasi_event_t, nsubscriptions uint32, nevents *uint32) (errno uint16)
|
func poll_oneoff(in *__wasi_subscription_t, out *__wasi_event_t, nsubscriptions uint32, nevents *uint32) (errno uint16)
|
||||||
|
|
||||||
@@ -77,7 +76,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// https://github.com/wasmerio/wasmer/blob/1.0.0-alpha3/lib/wasi/src/syscalls/types.rs#L584-L588
|
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-subscription-record
|
||||||
__wasi_subscription_t struct {
|
__wasi_subscription_t struct {
|
||||||
userData uint64
|
userData uint64
|
||||||
u __wasi_subscription_u_t
|
u __wasi_subscription_u_t
|
||||||
@@ -90,18 +89,17 @@ type (
|
|||||||
u __wasi_subscription_clock_t
|
u __wasi_subscription_clock_t
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/wasmerio/wasmer/blob/1.0.0-alpha3/lib/wasi/src/syscalls/types.rs#L711-L718
|
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-subscription_clock-record
|
||||||
__wasi_subscription_clock_t struct {
|
__wasi_subscription_clock_t struct {
|
||||||
userData uint64
|
|
||||||
id uint32
|
id uint32
|
||||||
timeout int64
|
timeout uint64
|
||||||
precision int64
|
precision uint64
|
||||||
flags uint16
|
flags uint16
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// https://github.com/wasmerio/wasmer/blob/1.0.0-alpha3/lib/wasi/src/syscalls/types.rs#L191-L198
|
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-event-record
|
||||||
__wasi_event_t struct {
|
__wasi_event_t struct {
|
||||||
userData uint64
|
userData uint64
|
||||||
errno uint16
|
errno uint16
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
// +build !go1.12
|
|
||||||
|
|
||||||
package runtime
|
|
||||||
|
|
||||||
import "internal/bytealg"
|
|
||||||
|
|
||||||
// The following functions provide compatibility with Go 1.11.
|
|
||||||
// See the following:
|
|
||||||
// https://github.com/tinygo-org/tinygo/issues/351
|
|
||||||
// https://github.com/golang/go/commit/ad4a58e31501bce5de2aad90a620eaecdc1eecb8
|
|
||||||
|
|
||||||
//go:linkname indexByte strings.IndexByte
|
|
||||||
func indexByte(s string, c byte) int {
|
|
||||||
return bytealg.IndexByteString(s, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:linkname bytesEqual bytes.Equal
|
|
||||||
func bytesEqual(a, b []byte) bool {
|
|
||||||
return bytealg.Equal(a, b)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"inherits": ["cortex-m4"],
|
||||||
|
"build-tags": ["sam", "atsamd51", "atsamd51p20", "atsamd51p20a"],
|
||||||
|
"cflags": [
|
||||||
|
"-Qunused-arguments"
|
||||||
|
],
|
||||||
|
"linkerscript": "targets/atsamd51p20a.ld",
|
||||||
|
"extra-files": [
|
||||||
|
"src/device/sam/atsamd51p20a.s"
|
||||||
|
],
|
||||||
|
"openocd-transport": "swd",
|
||||||
|
"openocd-target": "atsame5x"
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00100000-0x4000 /* First 16KB used by bootloader */
|
||||||
|
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x00040000
|
||||||
|
}
|
||||||
|
|
||||||
|
_stack_size = 4K;
|
||||||
|
|
||||||
|
INCLUDE "targets/arm.ld"
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"inherits": ["atsamd51p20a"],
|
||||||
|
"build-tags": ["grandcentral_m4"],
|
||||||
|
"flash-1200-bps-reset": "true",
|
||||||
|
"flash-method": "msd",
|
||||||
|
"msd-volume-name": "GCM4BOOT",
|
||||||
|
"msd-firmware-name": "firmware.uf2",
|
||||||
|
"openocd-interface": "jlink"
|
||||||
|
}
|
||||||
@@ -247,8 +247,8 @@
|
|||||||
|
|
||||||
const timeOrigin = Date.now() - performance.now();
|
const timeOrigin = Date.now() - performance.now();
|
||||||
this.importObject = {
|
this.importObject = {
|
||||||
wasi_unstable: {
|
wasi_snapshot_preview1: {
|
||||||
// https://github.com/bytecodealliance/wasmtime/blob/master/docs/WASI-api.md#__wasi_fd_write
|
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_write
|
||||||
fd_write: function(fd, iovs_ptr, iovs_len, nwritten_ptr) {
|
fd_write: function(fd, iovs_ptr, iovs_len, nwritten_ptr) {
|
||||||
let nwritten = 0;
|
let nwritten = 0;
|
||||||
if (fd == 1) {
|
if (fd == 1) {
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ type Bitfield struct {
|
|||||||
|
|
||||||
func formatText(text string) string {
|
func formatText(text string) string {
|
||||||
text = regexp.MustCompile(`[ \t\n]+`).ReplaceAllString(text, " ") // Collapse whitespace (like in HTML)
|
text = regexp.MustCompile(`[ \t\n]+`).ReplaceAllString(text, " ") // Collapse whitespace (like in HTML)
|
||||||
text = strings.Replace(text, "\\n ", "\n", -1)
|
text = strings.ReplaceAll(text, "\\n ", "\n")
|
||||||
text = strings.TrimSpace(text)
|
text = strings.TrimSpace(text)
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
@@ -273,9 +273,9 @@ func readSVD(path, sourceURL string) (*Device, error) {
|
|||||||
p.Registers = append(p.Registers, parseRegister(regName, register, baseAddress, "")...)
|
p.Registers = append(p.Registers, parseRegister(regName, register, baseAddress, "")...)
|
||||||
}
|
}
|
||||||
for _, cluster := range periphEl.Clusters {
|
for _, cluster := range periphEl.Clusters {
|
||||||
clusterName := strings.Replace(cluster.Name, "[%s]", "", -1)
|
clusterName := strings.ReplaceAll(cluster.Name, "[%s]", "")
|
||||||
if cluster.DimIndex != nil {
|
if cluster.DimIndex != nil {
|
||||||
clusterName = strings.Replace(clusterName, "%s", "", -1)
|
clusterName = strings.ReplaceAll(clusterName, "%s", "")
|
||||||
}
|
}
|
||||||
clusterPrefix := clusterName + "_"
|
clusterPrefix := clusterName + "_"
|
||||||
clusterOffset, err := strconv.ParseUint(cluster.AddressOffset, 0, 32)
|
clusterOffset, err := strconv.ParseUint(cluster.AddressOffset, 0, 32)
|
||||||
@@ -292,7 +292,7 @@ func readSVD(path, sourceURL string) (*Device, error) {
|
|||||||
}
|
}
|
||||||
// handle sub-clusters of registers
|
// handle sub-clusters of registers
|
||||||
for _, subClusterEl := range cluster.Clusters {
|
for _, subClusterEl := range cluster.Clusters {
|
||||||
subclusterName := strings.Replace(subClusterEl.Name, "[%s]", "", -1)
|
subclusterName := strings.ReplaceAll(subClusterEl.Name, "[%s]", "")
|
||||||
subclusterPrefix := subclusterName + "_"
|
subclusterPrefix := subclusterName + "_"
|
||||||
subclusterOffset, err := strconv.ParseUint(subClusterEl.AddressOffset, 0, 32)
|
subclusterOffset, err := strconv.ParseUint(subClusterEl.AddressOffset, 0, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -414,7 +414,7 @@ func readSVD(path, sourceURL string) (*Device, error) {
|
|||||||
// Properly format the license block, with comments.
|
// Properly format the license block, with comments.
|
||||||
licenseBlock := ""
|
licenseBlock := ""
|
||||||
if text := formatText(device.LicenseText); text != "" {
|
if text := formatText(device.LicenseText); text != "" {
|
||||||
licenseBlock = "// " + strings.Replace(text, "\n", "\n// ", -1)
|
licenseBlock = "// " + strings.ReplaceAll(text, "\n", "\n// ")
|
||||||
licenseBlock = regexp.MustCompile(`\s+\n`).ReplaceAllString(licenseBlock, "\n")
|
licenseBlock = regexp.MustCompile(`\s+\n`).ReplaceAllString(licenseBlock, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -595,7 +595,7 @@ func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPre
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if enumBitSpecifier.MatchString(enumEl.Value) {
|
if enumBitSpecifier.MatchString(enumEl.Value) {
|
||||||
// NXP SVDs use the form #xx1x, #x0xx, etc for values
|
// NXP SVDs use the form #xx1x, #x0xx, etc for values
|
||||||
enumValue, err = strconv.ParseUint(strings.Replace(enumEl.Value[1:], "x", "0", -1), 2, 32)
|
enumValue, err = strconv.ParseUint(strings.ReplaceAll(enumEl.Value[1:], "x", "0"), 2, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -656,7 +656,7 @@ func NewRegister(element *SVDRegister, baseAddress uint64) *Register {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Register) name() string {
|
func (r *Register) name() string {
|
||||||
return strings.Replace(r.element.Name, "[%s]", "", -1)
|
return strings.ReplaceAll(r.element.Name, "[%s]", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Register) description() string {
|
func (r *Register) description() string {
|
||||||
@@ -765,7 +765,7 @@ func parseRegister(groupName string, regEl *SVDRegister, baseAddress uint64, bit
|
|||||||
for i, j := range reg.dimIndex() {
|
for i, j := range reg.dimIndex() {
|
||||||
regAddress := reg.address() + (uint64(i) * dimIncrement)
|
regAddress := reg.address() + (uint64(i) * dimIncrement)
|
||||||
results = append(results, &PeripheralField{
|
results = append(results, &PeripheralField{
|
||||||
Name: strings.ToUpper(strings.Replace(reg.name(), "%s", j, -1)),
|
Name: strings.ToUpper(strings.ReplaceAll(reg.name(), "%s", j)),
|
||||||
Address: regAddress,
|
Address: regAddress,
|
||||||
Description: reg.description(),
|
Description: reg.description(),
|
||||||
Array: -1,
|
Array: -1,
|
||||||
@@ -773,7 +773,7 @@ func parseRegister(groupName string, regEl *SVDRegister, baseAddress uint64, bit
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
// set first result bitfield
|
// set first result bitfield
|
||||||
shortName := strings.ToUpper(strings.Replace(strings.Replace(reg.name(), "_%s", "", -1), "%s", "", -1))
|
shortName := strings.ToUpper(strings.ReplaceAll(strings.ReplaceAll(reg.name(), "_%s", ""), "%s", ""))
|
||||||
results[0].Bitfields = parseBitfields(groupName, shortName, regEl.Fields, bitfieldPrefix)
|
results[0].Bitfields = parseBitfields(groupName, shortName, regEl.Fields, bitfieldPrefix)
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user